add support for multi col row to ui

This commit is contained in:
hiddify
2024-09-30 23:16:24 +02:00
parent bc958e1177
commit 8545e2cb18
4 changed files with 152 additions and 153 deletions

View File

@@ -73,7 +73,6 @@
</div> </div>
</div> </div>
<script src="https://unpkg.com/ansi_up@5.0.0/ansi_up.js"></script> <script src="https://unpkg.com/ansi_up@5.0.0/ansi_up.js"></script>
<script src="https://unpkg.com/google-protobuf@3.20.1/dist/google-protobuf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/protobufjs@7.X.X/dist/protobuf.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/protobufjs@7.X.X/dist/protobuf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.bundle.min.js" integrity="sha512-7Pi/otdlbbCR+LnW+F7PwFcSDJOuUJB3OxtEHbg4vSMvzvJjde4Po1v4BR9Gdc9aXNUNFVUY+SK51wWT8WF0Gg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.bundle.min.js" integrity="sha512-7Pi/otdlbbCR+LnW+F7PwFcSDJOuUJB3OxtEHbg4vSMvzvJjde4Po1v4BR9Gdc9aXNUNFVUY+SK51wWT8WF0Gg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

View File

@@ -686,12 +686,12 @@ const extension = require("./extension_grpc_web_pb.js");
const { renderForm } = require('./formRenderer.js'); const { renderForm } = require('./formRenderer.js');
const { listExtensions } = require('./extensionList.js'); const { listExtensions } = require('./extensionList.js');
var currentExtensionId=undefined; var currentExtensionId = undefined;
function openExtensionPage(extensionId) { function openExtensionPage(extensionId) {
currentExtensionId=extensionId; currentExtensionId = extensionId;
$("#extension-list-container").hide(); $("#extension-list-container").hide();
$("#extension-page-container").show(); $("#extension-page-container").show();
$("#connection-page").hide(); $("#connection-page").hide();
connect() connect()
} }
@@ -700,42 +700,45 @@ function connect() {
request.setExtensionId(currentExtensionId); request.setExtensionId(currentExtensionId);
const stream = extensionClient.connect(request, {}); const stream = extensionClient.connect(request, {});
stream.on('data', (response) => { stream.on('data', (response) => {
console.log('Receving ',response); console.log('Receving ', response);
if (response.getExtensionId() === currentExtensionId) { if (response.getExtensionId() === currentExtensionId) {
ui=JSON.parse(response.getJsonUi()) ui = JSON.parse(response.getJsonUi())
if(response.getType()== proto.hiddifyrpc.ExtensionResponseType.SHOW_DIALOG) { if (response.getType() == proto.hiddifyrpc.ExtensionResponseType.SHOW_DIALOG) {
renderForm(ui, "dialog",handleSubmitButtonClick,handleCancelButtonClick,undefined); renderForm(ui, "dialog", handleSubmitButtonClick, undefined);
}else{ } else {
renderForm(ui, "",handleSubmitButtonClick,handleCancelButtonClick,handleStopButtonClick); renderForm(ui, "", handleSubmitButtonClick, handleStopButtonClick);
} }
} }
}); });
stream.on('error', (err) => { stream.on('error', (err) => {
console.error('Error opening extension page:', err); console.error('Error opening extension page:', err);
// openExtensionPage(extensionId); // openExtensionPage(extensionId);
}); });
stream.on('end', () => { stream.on('end', () => {
console.log('Stream ended'); console.log('Stream ended');
setTimeout(connect, 1000); setTimeout(connect, 1000);
}); });
} }
async function handleSubmitButtonClick(event) { async function handleSubmitButtonClick(event, button) {
event.preventDefault(); event.preventDefault();
bootstrap.Modal.getOrCreateInstance("#extension-dialog").hide(); bootstrap.Modal.getOrCreateInstance("#extension-dialog").hide();
const formData = new FormData(event.target.closest('form')); const request = new extension.SendExtensionDataRequest();
const request = new extension.ExtensionRequest(); request.setButton(button);
const datamap=request.getDataMap() if (event.type != 'hidden.bs.modal') {
formData.forEach((value, key) => { const formData = new FormData(event.target.closest('form'));
datamap.set(key,value); const datamap = request.getDataMap()
}); formData.forEach((value, key) => {
datamap.set(key, value);
});
}
request.setExtensionId(currentExtensionId); request.setExtensionId(currentExtensionId);
try { try {
@@ -746,26 +749,12 @@ async function handleSubmitButtonClick(event) {
} }
} }
async function handleCancelButtonClick(event) {
event.preventDefault();
const request = new extension.ExtensionRequest();
request.setExtensionId(currentExtensionId);
try {
bootstrap.Modal.getOrCreateInstance("#extension-dialog").hide();
await extensionClient.cancel(request, {});
console.log('Extension cancelled successfully.');
} catch (err) {
console.error('Error cancelling extension:', err);
}
}
async function handleStopButtonClick(event) { async function handleStopButtonClick(event) {
event.preventDefault(); event.preventDefault();
const request = new extension.ExtensionRequest(); const request = new extension.ExtensionRequest();
request.setExtensionId(currentExtensionId); request.setExtensionId(currentExtensionId);
bootstrap.Modal.getOrCreateInstance("#extension-dialog").hide();
try { try {
await extensionClient.stop(request, {}); await extensionClient.stop(request, {});
console.log('Extension stopped successfully.'); console.log('Extension stopped successfully.');
@@ -2762,7 +2751,7 @@ const ansi_up = new AnsiUp({
}); });
function renderForm(json, dialog, submitAction, cancelAction, stopAction) { function renderForm(json, dialog, submitAction, stopAction) {
const container = document.getElementById(`extension-page-container${dialog}`); const container = document.getElementById(`extension-page-container${dialog}`);
const formId = `dynamicForm${json.id}${dialog}`; const formId = `dynamicForm${json.id}${dialog}`;
@@ -2778,37 +2767,26 @@ function renderForm(json, dialog, submitAction, cancelAction, stopAction) {
document.getElementById("modalLabel").textContent = json.title; document.getElementById("modalLabel").textContent = json.title;
} else { } else {
const titleElement = createTitleElement(json); const titleElement = createTitleElement(json);
if (stopAction != undefined) {
const stopButton = document.createElement('button');
stopButton.textContent = "Back";
stopButton.classList.add('btn', 'btn-danger');
stopButton.addEventListener('click', stopAction);
form.appendChild(stopButton);
}
form.appendChild(titleElement); form.appendChild(titleElement);
} }
addElementsToForm(form, json); addElementsToForm(form, json,submitAction);
const buttonGroup = createButtonGroup(json, submitAction, cancelAction);
if (dialog === "dialog") { if (dialog === "dialog") {
document.getElementById("modal-footer").innerHTML = ''; document.getElementById("modal-footer").innerHTML = '';
document.getElementById("modal-footer").appendChild(buttonGroup); // if ($(form.lastChild).find("button").length > 0) {
// document.getElementById("modal-footer").appendChild(form.lastChild);
// }
const extensionDialog = document.getElementById("extension-dialog"); const extensionDialog = document.getElementById("extension-dialog");
const dialog = bootstrap.Modal.getOrCreateInstance(extensionDialog); const dialog = bootstrap.Modal.getOrCreateInstance(extensionDialog);
dialog.show(); dialog.show();
extensionDialog.addEventListener("hidden.bs.modal", (e)=>submitAction(e,"CloseDialog"));
extensionDialog.addEventListener("hidden.bs.modal", cancelAction);
// const dialog = bootstrap.Modal.getOrCreateInstance("#extension-dialog");
// dialog.show()
// dialog.on("hidden.bs.modal", () => {
// cancelAction()
// })
} else {
form.appendChild(buttonGroup);
} }
} }
function addElementsToForm(form, json) { function addElementsToForm(form, json,submitAction) {
@@ -2817,8 +2795,14 @@ function addElementsToForm(form, json) {
form.appendChild(description); form.appendChild(description);
if (json.fields) { if (json.fields) {
json.fields.forEach(field => { json.fields.forEach(field => {
const formGroup = createFormGroup(field); div=document.createElement("div")
form.appendChild(formGroup); div.classList.add("row")
form.appendChild(div)
for (let i = 0; i < field.length; i++) {
const formGroup = createFormGroup(field[i], submitAction);
formGroup.classList.add("col")
div.appendChild(formGroup);
}
}); });
} }
@@ -2831,19 +2815,35 @@ function createTitleElement(json) {
return title; return title;
} }
function createFormGroup(field) { function createFormGroup(field, submitAction) {
const formGroup = document.createElement('div'); const formGroup = document.createElement('div');
formGroup.classList.add('mb-3'); formGroup.classList.add('mb-3');
if (field.type == "Button") {
const button = document.createElement('button');
button.textContent = field.label;
button.name=field.key
button.classList.add('btn');
if (field.key == "Submit") {
button.classList.add('btn-primary');
} else if (field.key == "Cancel") {
button.classList.add('btn-secondary');
}else{
button.classList.add('btn', 'btn-outline-secondary');
}
button.addEventListener('click', (e) => submitAction(e,field.key));
formGroup.appendChild(button);
} else {
if (field.label && !field.labelHidden) {
const label = document.createElement('label');
label.textContent = field.label;
label.setAttribute('for', field.key);
formGroup.appendChild(label);
}
if (field.label && !field.labelHidden) { const input = createInputElement(field);
const label = document.createElement('label'); formGroup.appendChild(input);
label.textContent = field.label;
label.setAttribute('for', field.key);
formGroup.appendChild(label);
} }
const input = createInputElement(field);
formGroup.appendChild(input);
return formGroup; return formGroup;
} }
@@ -2956,18 +2956,18 @@ function createButtonGroup(json, submitAction, cancelAction) {
buttonGroup.classList.add('btn-group'); buttonGroup.classList.add('btn-group');
json.buttons.forEach(buttonText => { json.buttons.forEach(buttonText => {
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.classList.add('btn',"btn-default"); btn.classList.add('btn', "btn-default");
buttonGroup.appendChild(btn); buttonGroup.appendChild(btn);
btn.textContent = buttonText btn.textContent = buttonText
if (buttonText=="Cancel") { if (buttonText == "Cancel") {
btn.classList.add( 'btn-secondary'); btn.classList.add('btn-secondary');
btn.addEventListener('click', cancelAction); btn.addEventListener('click', cancelAction);
}else{ } else {
if (buttonText=="Submit"||buttonText=="Ok") if (buttonText == "Submit" || buttonText == "Ok")
btn.classList.add('btn-primary'); btn.classList.add('btn-primary');
btn.addEventListener('click', submitAction); btn.addEventListener('click', submitAction);
} }
}) })

View File

@@ -3,12 +3,12 @@ const extension = require("./extension_grpc_web_pb.js");
const { renderForm } = require('./formRenderer.js'); const { renderForm } = require('./formRenderer.js');
const { listExtensions } = require('./extensionList.js'); const { listExtensions } = require('./extensionList.js');
var currentExtensionId=undefined; var currentExtensionId = undefined;
function openExtensionPage(extensionId) { function openExtensionPage(extensionId) {
currentExtensionId=extensionId; currentExtensionId = extensionId;
$("#extension-list-container").hide(); $("#extension-list-container").hide();
$("#extension-page-container").show(); $("#extension-page-container").show();
$("#connection-page").hide(); $("#connection-page").hide();
connect() connect()
} }
@@ -17,42 +17,45 @@ function connect() {
request.setExtensionId(currentExtensionId); request.setExtensionId(currentExtensionId);
const stream = extensionClient.connect(request, {}); const stream = extensionClient.connect(request, {});
stream.on('data', (response) => { stream.on('data', (response) => {
console.log('Receving ',response); console.log('Receving ', response);
if (response.getExtensionId() === currentExtensionId) { if (response.getExtensionId() === currentExtensionId) {
ui=JSON.parse(response.getJsonUi()) ui = JSON.parse(response.getJsonUi())
if(response.getType()== proto.hiddifyrpc.ExtensionResponseType.SHOW_DIALOG) { if (response.getType() == proto.hiddifyrpc.ExtensionResponseType.SHOW_DIALOG) {
renderForm(ui, "dialog",handleSubmitButtonClick,handleCancelButtonClick,undefined); renderForm(ui, "dialog", handleSubmitButtonClick, undefined);
}else{ } else {
renderForm(ui, "",handleSubmitButtonClick,handleCancelButtonClick,handleStopButtonClick); renderForm(ui, "", handleSubmitButtonClick, handleStopButtonClick);
} }
} }
}); });
stream.on('error', (err) => { stream.on('error', (err) => {
console.error('Error opening extension page:', err); console.error('Error opening extension page:', err);
// openExtensionPage(extensionId); // openExtensionPage(extensionId);
}); });
stream.on('end', () => { stream.on('end', () => {
console.log('Stream ended'); console.log('Stream ended');
setTimeout(connect, 1000); setTimeout(connect, 1000);
}); });
} }
async function handleSubmitButtonClick(event) { async function handleSubmitButtonClick(event, button) {
event.preventDefault(); event.preventDefault();
bootstrap.Modal.getOrCreateInstance("#extension-dialog").hide(); bootstrap.Modal.getOrCreateInstance("#extension-dialog").hide();
const formData = new FormData(event.target.closest('form')); const request = new extension.SendExtensionDataRequest();
const request = new extension.ExtensionRequest(); request.setButton(button);
const datamap=request.getDataMap() if (event.type != 'hidden.bs.modal') {
formData.forEach((value, key) => { const formData = new FormData(event.target.closest('form'));
datamap.set(key,value); const datamap = request.getDataMap()
}); formData.forEach((value, key) => {
datamap.set(key, value);
});
}
request.setExtensionId(currentExtensionId); request.setExtensionId(currentExtensionId);
try { try {
@@ -63,26 +66,12 @@ async function handleSubmitButtonClick(event) {
} }
} }
async function handleCancelButtonClick(event) {
event.preventDefault();
const request = new extension.ExtensionRequest();
request.setExtensionId(currentExtensionId);
try {
bootstrap.Modal.getOrCreateInstance("#extension-dialog").hide();
await extensionClient.cancel(request, {});
console.log('Extension cancelled successfully.');
} catch (err) {
console.error('Error cancelling extension:', err);
}
}
async function handleStopButtonClick(event) { async function handleStopButtonClick(event) {
event.preventDefault(); event.preventDefault();
const request = new extension.ExtensionRequest(); const request = new extension.ExtensionRequest();
request.setExtensionId(currentExtensionId); request.setExtensionId(currentExtensionId);
bootstrap.Modal.getOrCreateInstance("#extension-dialog").hide();
try { try {
await extensionClient.stop(request, {}); await extensionClient.stop(request, {});
console.log('Extension stopped successfully.'); console.log('Extension stopped successfully.');

View File

@@ -5,7 +5,7 @@ const ansi_up = new AnsiUp({
}); });
function renderForm(json, dialog, submitAction, cancelAction, stopAction) { function renderForm(json, dialog, submitAction, stopAction) {
const container = document.getElementById(`extension-page-container${dialog}`); const container = document.getElementById(`extension-page-container${dialog}`);
const formId = `dynamicForm${json.id}${dialog}`; const formId = `dynamicForm${json.id}${dialog}`;
@@ -21,37 +21,26 @@ function renderForm(json, dialog, submitAction, cancelAction, stopAction) {
document.getElementById("modalLabel").textContent = json.title; document.getElementById("modalLabel").textContent = json.title;
} else { } else {
const titleElement = createTitleElement(json); const titleElement = createTitleElement(json);
if (stopAction != undefined) {
const stopButton = document.createElement('button');
stopButton.textContent = "Back";
stopButton.classList.add('btn', 'btn-danger');
stopButton.addEventListener('click', stopAction);
form.appendChild(stopButton);
}
form.appendChild(titleElement); form.appendChild(titleElement);
} }
addElementsToForm(form, json); addElementsToForm(form, json,submitAction);
const buttonGroup = createButtonGroup(json, submitAction, cancelAction);
if (dialog === "dialog") { if (dialog === "dialog") {
document.getElementById("modal-footer").innerHTML = ''; document.getElementById("modal-footer").innerHTML = '';
document.getElementById("modal-footer").appendChild(buttonGroup); // if ($(form.lastChild).find("button").length > 0) {
// document.getElementById("modal-footer").appendChild(form.lastChild);
// }
const extensionDialog = document.getElementById("extension-dialog"); const extensionDialog = document.getElementById("extension-dialog");
const dialog = bootstrap.Modal.getOrCreateInstance(extensionDialog); const dialog = bootstrap.Modal.getOrCreateInstance(extensionDialog);
dialog.show(); dialog.show();
extensionDialog.addEventListener("hidden.bs.modal", (e)=>submitAction(e,"CloseDialog"));
extensionDialog.addEventListener("hidden.bs.modal", cancelAction);
// const dialog = bootstrap.Modal.getOrCreateInstance("#extension-dialog");
// dialog.show()
// dialog.on("hidden.bs.modal", () => {
// cancelAction()
// })
} else {
form.appendChild(buttonGroup);
} }
} }
function addElementsToForm(form, json) { function addElementsToForm(form, json,submitAction) {
@@ -60,8 +49,14 @@ function addElementsToForm(form, json) {
form.appendChild(description); form.appendChild(description);
if (json.fields) { if (json.fields) {
json.fields.forEach(field => { json.fields.forEach(field => {
const formGroup = createFormGroup(field); div=document.createElement("div")
form.appendChild(formGroup); div.classList.add("row")
form.appendChild(div)
for (let i = 0; i < field.length; i++) {
const formGroup = createFormGroup(field[i], submitAction);
formGroup.classList.add("col")
div.appendChild(formGroup);
}
}); });
} }
@@ -74,19 +69,35 @@ function createTitleElement(json) {
return title; return title;
} }
function createFormGroup(field) { function createFormGroup(field, submitAction) {
const formGroup = document.createElement('div'); const formGroup = document.createElement('div');
formGroup.classList.add('mb-3'); formGroup.classList.add('mb-3');
if (field.type == "Button") {
const button = document.createElement('button');
button.textContent = field.label;
button.name=field.key
button.classList.add('btn');
if (field.key == "Submit") {
button.classList.add('btn-primary');
} else if (field.key == "Cancel") {
button.classList.add('btn-secondary');
}else{
button.classList.add('btn', 'btn-outline-secondary');
}
button.addEventListener('click', (e) => submitAction(e,field.key));
formGroup.appendChild(button);
} else {
if (field.label && !field.labelHidden) {
const label = document.createElement('label');
label.textContent = field.label;
label.setAttribute('for', field.key);
formGroup.appendChild(label);
}
if (field.label && !field.labelHidden) { const input = createInputElement(field);
const label = document.createElement('label'); formGroup.appendChild(input);
label.textContent = field.label;
label.setAttribute('for', field.key);
formGroup.appendChild(label);
} }
const input = createInputElement(field);
formGroup.appendChild(input);
return formGroup; return formGroup;
} }
@@ -199,18 +210,18 @@ function createButtonGroup(json, submitAction, cancelAction) {
buttonGroup.classList.add('btn-group'); buttonGroup.classList.add('btn-group');
json.buttons.forEach(buttonText => { json.buttons.forEach(buttonText => {
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.classList.add('btn',"btn-default"); btn.classList.add('btn', "btn-default");
buttonGroup.appendChild(btn); buttonGroup.appendChild(btn);
btn.textContent = buttonText btn.textContent = buttonText
if (buttonText=="Cancel") { if (buttonText == "Cancel") {
btn.classList.add( 'btn-secondary'); btn.classList.add('btn-secondary');
btn.addEventListener('click', cancelAction); btn.addEventListener('click', cancelAction);
}else{ } else {
if (buttonText=="Submit"||buttonText=="Ok") if (buttonText == "Submit" || buttonText == "Ok")
btn.classList.add('btn-primary'); btn.classList.add('btn-primary');
btn.addEventListener('click', submitAction); btn.addEventListener('click', submitAction);
} }
}) })