1786 lines
67 KiB
JavaScript
1786 lines
67 KiB
JavaScript
import { app } from '../../scripts/app.js'
|
|
import { api } from '../../scripts/api.js';
|
|
import { ComfyDialog } from "../../scripts/ui/dialog.js";
|
|
import { $el } from "../../scripts/ui.js";
|
|
|
|
var container = null;
|
|
var lockCanvas = null;
|
|
var isMaster = false;
|
|
var selectedItem = null;
|
|
var lockTimeout = 30000; // 30 seconds
|
|
var lockInterval = 2000; // 2 seconds
|
|
var errorMessage = 'An error occurred, please try again later.';
|
|
|
|
let dialogCreateTemplateInstance = null;
|
|
let dialogModalBlank = null;
|
|
let dialogModalRelease = null;
|
|
let dialogEditTemplateInstance= null;
|
|
|
|
|
|
export async function handleRestartButton() {
|
|
|
|
var dialog = new ModalConfirmDialog(app, 'Do you want to RESTART the ComfyUI?', async () => {
|
|
try {
|
|
const response = await api.fetchApi("/restart");
|
|
const result = await response.json();
|
|
if (response.result) {
|
|
alert(result.message);
|
|
} else {
|
|
alert(result.message);
|
|
}
|
|
} catch (exception) {
|
|
console.error('Restart error:', exception);
|
|
alert(errorMessage);
|
|
}
|
|
});
|
|
dialog.show();
|
|
}
|
|
|
|
export async function handleResetButton() {
|
|
|
|
var dialog = new ModalConfirmDialog(app, 'Do you want to RESET the local environment?', async () => {
|
|
try {
|
|
var target = {};
|
|
const response = await api.fetchApi("/restore", {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
const result = await response.json();
|
|
if (response.result) {
|
|
alert(result.message);
|
|
} else {
|
|
alert(result.message);
|
|
}
|
|
} catch (exception) {
|
|
console.error('Reset error:', exception);
|
|
alert(errorMessage);
|
|
}
|
|
});
|
|
dialog.show();
|
|
}
|
|
|
|
// export async function changeOnAWS(disableAWS, checkbox) {
|
|
// var target
|
|
// var isChecked = checkbox.checked;
|
|
// if (disableAWS === false) {
|
|
// var dialog = new ModalConfirmDialog(app, 'Do you want to DISABLE cloud prompt?', async () => {
|
|
// try {
|
|
// target = { 'DISABLE_AWS_PROXY': "True" }
|
|
// const response = await api.fetchApi("/change_env", {
|
|
// method: 'POST',
|
|
// headers: { 'Content-Type': 'application/json' },
|
|
// body: JSON.stringify(target)
|
|
// });
|
|
// } catch (exception) {
|
|
// }
|
|
// checkbox.checked = false;
|
|
// });
|
|
// dialog.show();
|
|
// } else {
|
|
// var dialog = new ModalConfirmDialog(app, 'Do you want to ENABLE cloud prompt?', async () => {
|
|
// try {
|
|
// target = { 'DISABLE_AWS_PROXY': "False" }
|
|
// const response = await api.fetchApi("/change_env", {
|
|
// method: 'POST',
|
|
// headers: { 'Content-Type': 'application/json' },
|
|
// body: JSON.stringify(target)
|
|
// });
|
|
// } catch (exception) {
|
|
// }
|
|
// checkbox.checked = true;
|
|
// });
|
|
// dialog.show();
|
|
// }
|
|
// checkbox.checked = !isChecked;
|
|
// return disableAWS;
|
|
// }
|
|
|
|
function alert(message) {
|
|
var messageDialog = new ModalMessageDialog(app, message);
|
|
messageDialog.show();
|
|
}
|
|
|
|
function createButton(text, onClick) {
|
|
const button = document.createElement('button');
|
|
button.textContent = text;
|
|
button.style.padding = '4px 12px';
|
|
button.style.borderRadius = '4px';
|
|
button.style.border = 'none';
|
|
button.style.backgroundColor = '#232f3e';
|
|
button.style.color = '#fff';
|
|
button.style.fontWeight = '600';
|
|
button.style.cursor = 'pointer';
|
|
button.style.transition = 'background-color 0.3s ease';
|
|
button.style.width = '90%';
|
|
button.style.marginTop = '4px';
|
|
button.style.whiteSpace = 'nowrap';
|
|
button.style.overflow = 'hidden';
|
|
button.style.textOverflow = 'ellipsis';
|
|
button.style.fontSize = '14px';
|
|
|
|
// Add hover effect
|
|
button.addEventListener('mouseenter', () => {
|
|
button.style.backgroundColor = '#cbd3da';
|
|
});
|
|
|
|
button.addEventListener('mouseleave', () => {
|
|
button.style.backgroundColor = '#232f3e';
|
|
});
|
|
|
|
button.addEventListener('click', onClick);
|
|
return button;
|
|
}
|
|
|
|
// prompt on aws
|
|
function createSageMakerOption(labelText, name, checked, onChange) {
|
|
const container = document.createElement('div');
|
|
container.style.display = 'flex';
|
|
container.style.alignItems = 'center';
|
|
container.style.marginTop = '5px';
|
|
container.style.marginLeft = '10px';
|
|
container.style.width = '90%';
|
|
|
|
const label = document.createElement('label');
|
|
label.textContent = labelText;
|
|
label.style.fontWeight = '700';
|
|
label.style.marginRight = '10px';
|
|
label.style.fontSize = '14px';
|
|
label.style.color = '#212529';
|
|
|
|
const checkbox = document.createElement('input');
|
|
checkbox.type = 'checkbox';
|
|
checkbox.name = name;
|
|
checkbox.checked = checked;
|
|
checkbox.style.padding = '5px 10px';
|
|
checkbox.style.borderRadius = '4px';
|
|
checkbox.style.border = '1px solid #949494';
|
|
checkbox.style.backgroundColor = '#ffffff';
|
|
checkbox.style.color = '#212529';
|
|
checkbox.style.fontSize = '14px';
|
|
checkbox.addEventListener('change', onChange);
|
|
|
|
container.appendChild(label);
|
|
container.appendChild(checkbox);
|
|
|
|
return container;
|
|
}
|
|
|
|
// config panel
|
|
function createConfigPanel() {
|
|
const div = document.createElement('div');
|
|
div.style.border = '1px solid #d9d9d9';
|
|
div.style.width = '100%';
|
|
div.style.position = 'relative';
|
|
div.style.paddingTop = '10px';
|
|
div.style.paddingBottom = '10px';
|
|
div.style.marginTop = '20px';
|
|
div.style.borderRadius = '4px';
|
|
div.style.backgroundColor = '#ffffff';
|
|
|
|
const label = document.createElement('label');
|
|
label.textContent = 'AWS Config';
|
|
label.style.position = 'absolute';
|
|
label.style.borderRadius = '4px';
|
|
|
|
label.style.top = '-8px';
|
|
label.style.left = '32px';
|
|
label.style.backgroundColor = '#ffffff';
|
|
label.style.padding = '4px 4px 0px 4px';
|
|
label.style.fontSize = '14px';
|
|
label.style.fontWeight = '700';
|
|
label.style.color = '#212529';
|
|
|
|
// Add the icon
|
|
const icon = document.createElement('span');
|
|
icon.innerHTML = '❐';
|
|
icon.style.marginLeft = '8px';
|
|
icon.style.cursor = 'pointer';
|
|
icon.setAttribute('alt', 'Move Panel');
|
|
icon.setAttribute('title', 'Move Panel');
|
|
icon.addEventListener('click', () => toggleConfigPanelPosition(div));
|
|
label.appendChild(icon);
|
|
|
|
div.appendChild(label);
|
|
|
|
return div;
|
|
}
|
|
|
|
// move the config
|
|
function toggleConfigPanelPosition(div) {
|
|
const menu = document.getElementsByClassName('comfy-menu')[0];
|
|
const menuRect = menu.getBoundingClientRect();
|
|
const moveTop = menuRect.top - div.getBoundingClientRect().top + 12;
|
|
const moveLeft = 0 - menuRect.width + 4;
|
|
|
|
// Add transition styles
|
|
div.style.transition = 'transform 0.1s ease-in-out';
|
|
|
|
if (div.style.transform === '') {
|
|
div.style.transform = `translate(${moveLeft}px, ${moveTop}px)`;
|
|
} else {
|
|
div.style.transform = '';
|
|
}
|
|
}
|
|
|
|
|
|
// function createWorkflowList() {
|
|
// const outerContainer = document.createElement('div');
|
|
// outerContainer.style.display = 'flex';
|
|
// outerContainer.style.flexDirection = 'column';
|
|
// outerContainer.style.height = '160px';
|
|
// outerContainer.style.marginTop = '8px';
|
|
// outerContainer.style.marginLeft = '8px';
|
|
// outerContainer.style.width = '90%';
|
|
//
|
|
// const toolbarContainer = createToolbar();
|
|
//
|
|
// container = document.createElement('div');
|
|
// container.style.height = '100%';
|
|
// container.style.overflow = 'auto';
|
|
// container.style.border = '1px solid #949494';
|
|
// container.style.position = 'relative';
|
|
//
|
|
// // Add the background text
|
|
// const backgroundText = document.createElement('div');
|
|
// backgroundText.textContent = 'Please create workflow';
|
|
// backgroundText.style.position = 'absolute';
|
|
// backgroundText.style.top = '50%';
|
|
// backgroundText.style.left = '50%';
|
|
// backgroundText.style.transform = 'translate(-50%, -50%)';
|
|
// backgroundText.style.color = '#949494';
|
|
// backgroundText.style.fontSize = '16px';
|
|
// backgroundText.style.fontWeight = '600';
|
|
// backgroundText.style.pointerEvents = 'none';
|
|
// container.appendChild(backgroundText);
|
|
//
|
|
// outerContainer.appendChild(toolbarContainer);
|
|
// outerContainer.appendChild(container);
|
|
//
|
|
// return outerContainer;
|
|
// }
|
|
|
|
function createTemplateList() {
|
|
const outerContainer = document.createElement('div');
|
|
outerContainer.style.display = 'flex';
|
|
outerContainer.style.flexDirection = 'column';
|
|
outerContainer.style.height = '160px';
|
|
outerContainer.style.marginTop = '8px';
|
|
outerContainer.style.marginLeft = '8px';
|
|
outerContainer.style.width = '90%';
|
|
|
|
const title = document.createElement('div');
|
|
title.textContent = 'Template List';
|
|
title.style.fontSize = '14px';
|
|
title.style.fontWeight = 'bold';
|
|
title.style.color = '#333';
|
|
title.style.marginBottom = '0px';
|
|
title.style.backgroundColor = '#f0f0f0';
|
|
title.style.borderRadius = '4px';
|
|
outerContainer.appendChild(title);
|
|
|
|
const toolbarContainer = createTemplateToolbar();
|
|
toolbarContainer.style.marginTop = '0';
|
|
|
|
container = document.createElement('div');
|
|
container.style.height = '100%';
|
|
container.style.overflow = 'auto';
|
|
container.style.border = '1px solid #949494';
|
|
container.style.position = 'relative';
|
|
|
|
// Add the background text
|
|
const backgroundText = document.createElement('div');
|
|
backgroundText.textContent = 'Please create template';
|
|
backgroundText.style.position = 'absolute';
|
|
backgroundText.style.top = '50%';
|
|
backgroundText.style.left = '50%';
|
|
backgroundText.style.transform = 'translate(-50%, -50%)';
|
|
backgroundText.style.color = '#949494';
|
|
backgroundText.style.fontSize = '16px';
|
|
backgroundText.style.fontWeight = '600';
|
|
backgroundText.style.pointerEvents = 'none';
|
|
container.appendChild(backgroundText);
|
|
|
|
outerContainer.appendChild(toolbarContainer);
|
|
outerContainer.appendChild(container);
|
|
|
|
return outerContainer;
|
|
}
|
|
|
|
// function createToolbar() {
|
|
// const toolbarContainer = document.createElement('div');
|
|
// toolbarContainer.style.display = 'flex';
|
|
// toolbarContainer.style.justifyContent = 'space-between';
|
|
// toolbarContainer.style.backgroundColor = '#232f3e';
|
|
// toolbarContainer.style.padding = '3px';
|
|
// toolbarContainer.style.position = 'sticky';
|
|
// toolbarContainer.style.top = '0';
|
|
// toolbarContainer.style.zIndex = '1';
|
|
// if (isMaster) {
|
|
// toolbarContainer.appendChild(createToolbarButton('✚', handleCreateButton, 'Create New Workflow', isMaster));
|
|
// }
|
|
// toolbarContainer.appendChild(createButtonSeparator());
|
|
// toolbarContainer.appendChild(createToolbarButton('↻', handleLoadButton, 'Reload Workflow', true));
|
|
// toolbarContainer.appendChild(createButtonSeparator());
|
|
// toolbarContainer.appendChild(createToolbarButton('✓', handleChangeButton, 'Change Workflow', true));
|
|
// toolbarContainer.appendChild(createButtonSeparator());
|
|
// if (isMaster) {
|
|
// toolbarContainer.appendChild(createToolbarButton('✕', handleDeleteButton, 'Remove Workflow', isMaster));
|
|
// }
|
|
//
|
|
// return toolbarContainer;
|
|
// }
|
|
|
|
|
|
function createTemplateToolbar() {
|
|
const toolbarContainer = document.createElement('div');
|
|
toolbarContainer.style.display = 'flex';
|
|
toolbarContainer.style.justifyContent = 'space-between';
|
|
toolbarContainer.style.backgroundColor = '#232f3e';
|
|
toolbarContainer.style.padding = '3px';
|
|
toolbarContainer.style.position = 'sticky';
|
|
toolbarContainer.style.top = '0';
|
|
toolbarContainer.style.zIndex = '1';
|
|
if (isMaster) {
|
|
toolbarContainer.appendChild(createToolbarButton('✚', handleCreateTemplateButton, 'Create', isMaster));
|
|
}
|
|
toolbarContainer.appendChild(createButtonSeparator());
|
|
toolbarContainer.appendChild(createToolbarButton('↻', handleLoadTemplateButton, 'Refresh', true));
|
|
toolbarContainer.appendChild(createButtonSeparator());
|
|
toolbarContainer.appendChild(createToolbarButton('✓', handleChangeTemplateButton, 'Confirm to Switch', true));
|
|
toolbarContainer.appendChild(createButtonSeparator());
|
|
if (isMaster) {
|
|
toolbarContainer.appendChild(createToolbarButton('✎', handleEditTemplateButton, 'Edit', isMaster));
|
|
toolbarContainer.appendChild(createToolbarButton('✕', handleDeleteTemplateButton, 'Delete', isMaster));
|
|
}
|
|
|
|
return toolbarContainer;
|
|
}
|
|
|
|
|
|
function handleCreateTemplateButton() {
|
|
if (!dialogCreateTemplateInstance) {
|
|
dialogCreateTemplateInstance = new ModalTemplateDialog(app);
|
|
}
|
|
dialogCreateTemplateInstance.populateWorkflowSelectField();
|
|
dialogCreateTemplateInstance.clear();
|
|
dialogCreateTemplateInstance.show();
|
|
}
|
|
|
|
|
|
function handleEditTemplateButton() {
|
|
if (selectedItem) {
|
|
if (!dialogEditTemplateInstance) {
|
|
dialogEditTemplateInstance = new ModalEditTemplateDialog(app, selectedItem);
|
|
}
|
|
dialogEditTemplateInstance.populateWorkflowSelectField();
|
|
dialogEditTemplateInstance.clear(selectedItem);
|
|
dialogEditTemplateInstance.show();
|
|
} else {
|
|
alert('Please select a template in the list');
|
|
}
|
|
}
|
|
|
|
function handleCreateButton() {
|
|
if(!dialogModalRelease){
|
|
dialogModalRelease = new ModalEndpointReleaseDialog(app);
|
|
}
|
|
dialogModalRelease.clear();
|
|
dialogModalRelease.show();
|
|
}
|
|
|
|
|
|
async function handleLoadTemplateButton() {
|
|
// Clear the container
|
|
container.innerHTML = '';
|
|
|
|
// Add a loading indicator
|
|
const loadingIndicator = document.createElement('div');
|
|
loadingIndicator.textContent = 'Loading...';
|
|
loadingIndicator.style.textAlign = 'center';
|
|
loadingIndicator.style.padding = '20px';
|
|
container.appendChild(loadingIndicator);
|
|
|
|
try {
|
|
const response = await api.fetchApi("/schemas");
|
|
console.log(response);
|
|
const data = await response.json();
|
|
// Clear the loading indicator
|
|
container.innerHTML = '';
|
|
data.data.schemas.forEach(template => {
|
|
const itemContainer = createTemplateItem(template, () => {
|
|
if (selectedItem) {
|
|
selectedItem.style.backgroundColor = '#f8f9fa';
|
|
}
|
|
itemContainer.style.backgroundColor = '#cbd3da';
|
|
selectedItem = itemContainer;
|
|
});
|
|
container.appendChild(itemContainer);
|
|
});
|
|
} catch (error) {
|
|
// Clear the loading indicator
|
|
container.innerHTML = '';
|
|
|
|
// Display an error message
|
|
const errorMessage = document.createElement('div');
|
|
errorMessage.textContent = 'Loading error, please try again later.';
|
|
errorMessage.style.textAlign = 'center';
|
|
errorMessage.style.padding = '20px';
|
|
container.appendChild(errorMessage);
|
|
|
|
console.error('Loading error:', error);
|
|
}
|
|
}
|
|
|
|
async function handleLoadButton() {
|
|
// Clear the container
|
|
container.innerHTML = '';
|
|
|
|
// Add a loading indicator
|
|
const loadingIndicator = document.createElement('div');
|
|
loadingIndicator.textContent = 'Loading...';
|
|
loadingIndicator.style.textAlign = 'center';
|
|
loadingIndicator.style.padding = '20px';
|
|
container.appendChild(loadingIndicator);
|
|
|
|
try {
|
|
const response = await api.fetchApi("/workflows");
|
|
console.log(response);
|
|
const data = await response.json();
|
|
// Clear the loading indicator
|
|
container.innerHTML = '';
|
|
data.data.workflows.forEach(workflow => {
|
|
if (workflow.status == 'Enabled') {
|
|
const itemContainer = createWorkflowItem(workflow, () => {
|
|
if (selectedItem) {
|
|
selectedItem.style.backgroundColor = '#f8f9fa';
|
|
}
|
|
itemContainer.style.backgroundColor = '#cbd3da';
|
|
selectedItem = itemContainer;
|
|
});
|
|
container.appendChild(itemContainer);
|
|
}
|
|
});
|
|
} catch (error) {
|
|
// Clear the loading indicator
|
|
container.innerHTML = '';
|
|
|
|
// Display an error message
|
|
const errorMessage = document.createElement('div');
|
|
errorMessage.textContent = 'Loading error, please try again later.';
|
|
errorMessage.style.textAlign = 'center';
|
|
errorMessage.style.padding = '20px';
|
|
container.appendChild(errorMessage);
|
|
|
|
console.error('Loading error:', error);
|
|
}
|
|
}
|
|
|
|
async function handleChangeTemplateButton() {
|
|
if (selectedItem) {
|
|
var dialog = new ModalConfirmDialog(app, 'Do you want to CHANGE template to "' + selectedItem.firstChild.firstChild.textContent + '" ?', async () => {
|
|
try {
|
|
const template_name = selectedItem.firstChild.firstChild.textContent
|
|
handleLockScreen();
|
|
const templateValue = selectedItem.firstChild.firstChild.value || 'default';
|
|
var target = {
|
|
'name': templateValue
|
|
};
|
|
await handleLoadTemplateJson(selectedItem.firstChild.firstChild.dataset.payload);
|
|
const response = await api.fetchApi("/workflows", {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
const result = await response.json();
|
|
handleUnlockScreen();
|
|
localStorage.setItem("in_use_template", template_name);
|
|
alert(result.message);
|
|
} catch (exception) {
|
|
console.error('Change error:', exception);
|
|
alert(errorMessage);
|
|
}
|
|
});
|
|
dialog.show();
|
|
} else {
|
|
alert('Please select a template in the list');
|
|
}
|
|
}
|
|
|
|
async function handleChangeButton() {
|
|
if (selectedItem) {
|
|
var dialog = new ModalConfirmDialog(app, 'Do you want to CHANGE workflow to "' + selectedItem.firstChild.firstChild.textContent + '" ?', async () => {
|
|
try {
|
|
handleLockScreen();
|
|
var target = {
|
|
'name': selectedItem.firstChild.firstChild.textContent
|
|
};
|
|
|
|
await handleLoadJson(selectedItem.firstChild.firstChild.textContent);
|
|
const response = await api.fetchApi("/workflows", {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
const result = await response.json();
|
|
handleUnlockScreen();
|
|
alert(result.message);
|
|
} catch (exception) {
|
|
console.error('Change error:', exception);
|
|
alert(errorMessage);
|
|
}
|
|
});
|
|
dialog.show();
|
|
} else {
|
|
alert('Please select a workflow in the list');
|
|
}
|
|
}
|
|
|
|
|
|
async function handleDeleteTemplateButton() {
|
|
if (selectedItem) {
|
|
var dialog = new ModalConfirmDialog(app, 'Do you want to DELETE the template?', async () => {
|
|
try {
|
|
var target = {
|
|
'schema_name_list': [selectedItem.firstChild.firstChild.textContent]
|
|
};
|
|
const response = await api.fetchApi("/schemas", {
|
|
method: 'DELETE',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
const result = await response.json();
|
|
if (result.result) {
|
|
selectedItem.remove();
|
|
selectedItem = null;
|
|
} else {
|
|
handleUnlockScreen();
|
|
alert(result.message);
|
|
}
|
|
} catch (exception) {
|
|
console.error('Delete error:', exception);
|
|
alert(errorMessage);
|
|
}
|
|
});
|
|
dialog.show();
|
|
|
|
} else {
|
|
alert('Please select a template in the list');
|
|
}
|
|
}
|
|
|
|
async function handleDeleteButton() {
|
|
if (selectedItem) {
|
|
var dialog = new ModalConfirmDialog(app, 'Do you want to DELETE the workflow?', async () => {
|
|
try {
|
|
var target = {
|
|
'name': selectedItem.firstChild.firstChild.textContent
|
|
};
|
|
const response = await api.fetchApi("/workflows", {
|
|
method: 'DELETE',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
const result = await response.json();
|
|
if (result.result) {
|
|
selectedItem.remove();
|
|
selectedItem = null;
|
|
} else {
|
|
handleUnlockScreen();
|
|
alert(result.message);
|
|
}
|
|
} catch (exception) {
|
|
console.error('Delete error:', exception);
|
|
alert(errorMessage);
|
|
}
|
|
});
|
|
dialog.show();
|
|
|
|
} else {
|
|
alert('Please select a workflow in the list');
|
|
}
|
|
|
|
}
|
|
|
|
function createToolbarButton(icon, onClick, altText, enabled) {
|
|
const button = document.createElement('button');
|
|
button.innerHTML = icon;
|
|
button.style.padding = '6px 12px';
|
|
button.style.borderRadius = '4px';
|
|
button.style.border = 'none';
|
|
button.style.backgroundColor = '#232f3e';
|
|
button.style.color = '#fff';
|
|
button.style.fontWeight = '600';
|
|
button.style.cursor = 'pointer';
|
|
button.style.transition = 'background-color 0.3s ease';
|
|
button.style.width = '30px';
|
|
button.style.display = 'flex';
|
|
button.style.justifyContent = 'center';
|
|
button.style.alignItems = 'center';
|
|
button.style.fontSize = '14px';
|
|
button.setAttribute('alt', altText);
|
|
button.setAttribute('title', altText);
|
|
button.disabled = !enabled;
|
|
|
|
if (enabled) {
|
|
// Add hover effect
|
|
button.addEventListener('mouseenter', () => {
|
|
button.style.backgroundColor = '#cbd3da';
|
|
});
|
|
|
|
button.addEventListener('mouseleave', () => {
|
|
button.style.backgroundColor = '#232f3e';
|
|
});
|
|
|
|
button.addEventListener('click', onClick);
|
|
}
|
|
return button;
|
|
}
|
|
|
|
|
|
function createButtonSeparator() {
|
|
const buttonSeparator = document.createElement('div');
|
|
buttonSeparator.style.width = '1px';
|
|
buttonSeparator.style.height = '24px';
|
|
buttonSeparator.style.backgroundColor = '#949494';
|
|
return buttonSeparator;
|
|
}
|
|
|
|
function createTemplateItem(template, onClick) {
|
|
const itemContainer = document.createElement('div');
|
|
itemContainer.style.display = 'flex';
|
|
itemContainer.style.alignItems = 'flex-start';
|
|
itemContainer.style.justifyContent = 'space-between';
|
|
itemContainer.style.padding = '2px';
|
|
itemContainer.style.paddingLeft = '4px';
|
|
itemContainer.style.borderBottom = '1px solid #949494';
|
|
itemContainer.style.backgroundColor = '#f8f9fa';
|
|
itemContainer.style.position = 'relative';
|
|
itemContainer.addEventListener('click', onClick);
|
|
|
|
const labelContainer = document.createElement('div');
|
|
labelContainer.style.display = 'flex';
|
|
labelContainer.style.flexDirection = 'column';
|
|
labelContainer.style.alignItems = 'flex-start';
|
|
labelContainer.style.zIndex = '1';
|
|
labelContainer.setAttribute('alt', template.payload);
|
|
labelContainer.setAttribute('title', template.payload);
|
|
|
|
const nameLabel = document.createElement('span');
|
|
nameLabel.textContent = `${template.name}`;
|
|
nameLabel.value = `${template.workflow}`;
|
|
nameLabel.dataset.payload = `${template.payload}`;
|
|
nameLabel.style.display = 'flex';
|
|
nameLabel.style.alignItems = 'center';
|
|
const in_use_template = localStorage.getItem("in_use_template");
|
|
if (in_use_template === `${template.name}` ) {
|
|
nameLabel.style.fontWeight = '600';
|
|
try {
|
|
var target = {
|
|
'clientId': api.initialClientId ?? api.clientId,
|
|
'releaseVersion': `${template.workflow}` || 'default'
|
|
};
|
|
const response = api.fetchApi("/map_release", {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
} catch (error) {
|
|
console.error('Error checking lock status:', error);
|
|
}
|
|
const greenBall = document.createElement('div');
|
|
greenBall.style.width = '8px';
|
|
greenBall.style.height = '8px';
|
|
greenBall.style.borderRadius = '50%';
|
|
greenBall.style.backgroundColor = 'green';
|
|
greenBall.style.marginRight = '4px';
|
|
nameLabel.insertBefore(greenBall, nameLabel.firstChild);
|
|
nameLabel.click()
|
|
} else {
|
|
nameLabel.style.fontWeight = '200';
|
|
}
|
|
nameLabel.style.color = '#212529';
|
|
nameLabel.style.marginBottom = '2px';
|
|
|
|
const sizeLabel = document.createElement('span');
|
|
sizeLabel.textContent = template.workflow ? `${template.workflow} ` : "unbind";
|
|
sizeLabel.style.fontWeight = '300';
|
|
sizeLabel.style.color = template.workflow ? '#6c757d' : '#FFA07A';
|
|
sizeLabel.style.fontSize = '12px';
|
|
sizeLabel.style.marginBottom = '2px';
|
|
|
|
labelContainer.appendChild(nameLabel);
|
|
labelContainer.appendChild(sizeLabel);
|
|
itemContainer.appendChild(labelContainer);
|
|
return itemContainer;
|
|
}
|
|
|
|
function createWorkflowItem(workflow, onClick) {
|
|
const itemContainer = document.createElement('div');
|
|
itemContainer.style.display = 'flex';
|
|
itemContainer.style.alignItems = 'flex-start';
|
|
itemContainer.style.justifyContent = 'space-between';
|
|
itemContainer.style.padding = '2px';
|
|
itemContainer.style.paddingLeft = '4px';
|
|
itemContainer.style.borderBottom = '1px solid #949494';
|
|
itemContainer.style.backgroundColor = '#f8f9fa';
|
|
itemContainer.style.position = 'relative';
|
|
itemContainer.addEventListener('click', onClick);
|
|
|
|
const labelContainer = document.createElement('div');
|
|
labelContainer.style.display = 'flex';
|
|
labelContainer.style.flexDirection = 'column';
|
|
labelContainer.style.alignItems = 'flex-start';
|
|
labelContainer.style.zIndex = '1';
|
|
labelContainer.setAttribute('alt', workflow.payload_json);
|
|
labelContainer.setAttribute('title', workflow.payload_json);
|
|
|
|
const nameLabel = document.createElement('span');
|
|
nameLabel.textContent = `${workflow.name}`;
|
|
nameLabel.style.display = 'flex';
|
|
nameLabel.style.alignItems = 'center';
|
|
if (workflow.in_use) {
|
|
nameLabel.style.fontWeight = '600';
|
|
try {
|
|
var target = {
|
|
'clientId': api.initialClientId ?? api.clientId,
|
|
'releaseVersion': `${workflow.name}`
|
|
};
|
|
const response = api.fetchApi("/map_release", {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
} catch (error) {
|
|
console.error('Error checking lock status:', error);
|
|
}
|
|
const greenBall = document.createElement('div');
|
|
greenBall.style.width = '8px';
|
|
greenBall.style.height = '8px';
|
|
greenBall.style.borderRadius = '50%';
|
|
greenBall.style.backgroundColor = 'green';
|
|
greenBall.style.marginRight = '4px';
|
|
nameLabel.insertBefore(greenBall, nameLabel.firstChild);
|
|
} else {
|
|
nameLabel.style.fontWeight = '200';
|
|
}
|
|
nameLabel.style.color = '#212529';
|
|
nameLabel.style.marginBottom = '2px';
|
|
|
|
const sizeLabel = document.createElement('span');
|
|
sizeLabel.textContent = workflow.size ? `${workflow.size} GB` : "unknow";
|
|
sizeLabel.style.fontWeight = '300';
|
|
sizeLabel.style.color = '#6c757d';
|
|
sizeLabel.style.fontSize = '12px';
|
|
sizeLabel.style.marginBottom = '2px';
|
|
|
|
// const createTimeLabel = document.createElement('span');
|
|
// const createTime = new Date(workflow.create_time);
|
|
// const formattedCreateTime = `${createTime.toISOString().slice(0, 19).replace('T', ' ')}`;
|
|
// createTimeLabel.textContent = formattedCreateTime;
|
|
// createTimeLabel.style.fontWeight = '300';
|
|
// createTimeLabel.style.color = '#6c757d';
|
|
// createTimeLabel.style.fontSize = '12px';
|
|
// createTimeLabel.style.marginBottom = '2px';
|
|
|
|
|
|
labelContainer.appendChild(nameLabel);
|
|
labelContainer.appendChild(sizeLabel);
|
|
// labelContainer.appendChild(createTimeLabel);
|
|
itemContainer.appendChild(labelContainer);
|
|
return itemContainer;
|
|
}
|
|
|
|
async function handlePromptChange(event) {
|
|
console.log(`Checkbox ${event.target.checked ? 'checked' : 'unchecked'}`);
|
|
// Handle checkbox change
|
|
// changeOnAWS(event.target.checked, event.target);
|
|
var disableAWS = event.target.checked
|
|
var checkbox = event.target
|
|
var target
|
|
var isChecked = checkbox.checked;
|
|
if (disableAWS === false) {
|
|
var dialog = new ModalConfirmDialog(app, 'Do you want to DISABLE cloud prompt?', async () => {
|
|
try {
|
|
target = { 'DISABLE_AWS_PROXY': "True" }
|
|
const response = await api.fetchApi("/change_env", {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
} catch (exception) {
|
|
}
|
|
checkbox.checked = false;
|
|
});
|
|
dialog.show();
|
|
} else {
|
|
var dialog = new ModalConfirmDialog(app, 'Do you want to ENABLE cloud prompt?', async () => {
|
|
try {
|
|
target = { 'DISABLE_AWS_PROXY': "False" }
|
|
const response = await api.fetchApi("/change_env", {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
} catch (exception) {
|
|
}
|
|
checkbox.checked = true;
|
|
});
|
|
dialog.show();
|
|
}
|
|
checkbox.checked = !isChecked;
|
|
return disableAWS;
|
|
|
|
}
|
|
|
|
async function handleLoadJson(templateId){
|
|
try {
|
|
const response = await api.fetchApi(`/get_env_template/${templateId}`);
|
|
console.log(response);
|
|
if (response.ok) {
|
|
const promptJson =await response.json();
|
|
if (!promptJson){
|
|
console.info("load default json")
|
|
return
|
|
}
|
|
let jsonContent;
|
|
if (typeof promptJson === 'object') {
|
|
const jsonString = JSON.stringify(promptJson);
|
|
jsonContent = JSON.parse(jsonString);
|
|
} else {
|
|
jsonContent = JSON.parse(promptJson);
|
|
}
|
|
if (jsonContent?.workflow) {
|
|
const workflowJsonString = JSON.stringify(jsonContent.workflow);
|
|
const workflowContent = JSON.parse(workflowJsonString);
|
|
console.log(workflowContent)
|
|
await app.loadGraphData(workflowContent);
|
|
console.log("finished loadGraphData")
|
|
} else {
|
|
console.error(jsonContent);
|
|
console.error("Invalid JSON: missing 'workflow' property when loadGraphData.");
|
|
}
|
|
}else {
|
|
console.info('Loading json none: load default');
|
|
}
|
|
return true
|
|
} catch (error) {
|
|
console.error('Loading error:', error);
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function handleLoadTemplateJson(promptJson){
|
|
try {
|
|
if (!promptJson){
|
|
console.info("load default json")
|
|
return
|
|
}
|
|
let jsonContent;
|
|
if (typeof promptJson === 'object') {
|
|
const jsonString = JSON.stringify(promptJson);
|
|
jsonContent = JSON.parse(jsonString);
|
|
} else {
|
|
jsonContent = JSON.parse(promptJson);
|
|
}
|
|
if (jsonContent?.workflow) {
|
|
const workflowJsonString = JSON.stringify(jsonContent.workflow);
|
|
const workflowContent = JSON.parse(workflowJsonString);
|
|
console.log(workflowContent)
|
|
await app.loadGraphData(workflowContent);
|
|
console.log("finished loadGraphData")
|
|
} else {
|
|
console.error(jsonContent);
|
|
console.error("Invalid JSON: missing 'workflow' property when loadGraphData.");
|
|
}
|
|
return true
|
|
} catch (error) {
|
|
console.error('Loading error:', error);
|
|
return false
|
|
}
|
|
}
|
|
|
|
|
|
const awsConfigPanel = {
|
|
name: 'awsConfigPanel',
|
|
async setup(app) {
|
|
const check_response = await api.fetchApi("/check_is_master");
|
|
const check_data = await check_response.json();
|
|
isMaster = check_data.master;
|
|
const widgetsContainer = createConfigPanel();
|
|
if (isMaster) {
|
|
const response = await api.fetchApi("/get_env_new/DISABLE_AWS_PROXY");
|
|
const data = await response.json();
|
|
|
|
const checkboxSageMaker = createSageMakerOption('Prompt on AWS', 'options', data.env ? data.env.toUpperCase() === 'FALSE' : false, handlePromptChange);
|
|
widgetsContainer.appendChild(checkboxSageMaker);
|
|
}
|
|
|
|
const scrollList = createTemplateList();
|
|
widgetsContainer.appendChild(scrollList);
|
|
|
|
if (isMaster) {
|
|
const syncButton = createButton('New Environment', handleCreateButton);
|
|
widgetsContainer.appendChild(syncButton);
|
|
}
|
|
|
|
const restartButton = createButton('Restart ComfyUI', handleRestartButton);
|
|
widgetsContainer.appendChild(restartButton);
|
|
|
|
if (isMaster) {
|
|
const restoreButton = createButton('Reset to default', handleResetButton);
|
|
widgetsContainer.appendChild(restoreButton);
|
|
}
|
|
|
|
app.ui.menuContainer.appendChild(widgetsContainer);
|
|
// handleLoadButton();
|
|
dialogCreateTemplateInstance = new ModalTemplateDialog(app);
|
|
dialogCreateTemplateInstance.populateWorkflowSelectField();
|
|
handleLoadTemplateButton();
|
|
}
|
|
}
|
|
|
|
app.registerExtension(awsConfigPanel);
|
|
|
|
function handleLockScreen(message) {
|
|
if (lockCanvas == null) {
|
|
if (!dialogModalBlank){
|
|
lockCanvas = new ModalBlankDialog(app, message ? message : "Create processing...");
|
|
}else {
|
|
dialogModalBlank.reset_msg(message)
|
|
lockCanvas = dialogModalBlank
|
|
}
|
|
}
|
|
lockCanvas.show();
|
|
localStorage.setItem("ui_lock_status", "locked");
|
|
}
|
|
|
|
function handleUnlockScreen() {
|
|
if (lockCanvas != null) {
|
|
lockCanvas.close();
|
|
localStorage.setItem("ui_lock_status", "unlocked");
|
|
}
|
|
}
|
|
|
|
api.addEventListener("ui_lock", ({ detail }) => {
|
|
console.log(detail);
|
|
if (detail.lock) {
|
|
handleLockScreen();
|
|
}
|
|
});
|
|
|
|
// Close ui_lock listener
|
|
api.addEventListener("ui_lock", ({ detail }) => {
|
|
if (!detail.lock) {
|
|
handleUnlockScreen();
|
|
}
|
|
});
|
|
|
|
// Restore ui_lock status on page load
|
|
// window.addEventListener("load", () => {
|
|
// const uiLockStatus = localStorage.getItem("ui_lock_status");
|
|
// if (uiLockStatus === "locked") {
|
|
// handleLockScreen();
|
|
// }
|
|
// });
|
|
|
|
(async function checkLockStatus() {
|
|
try {
|
|
const response = await api.fetchApi("/lock");
|
|
const data = await response.json();
|
|
// fixed cannot lock screen
|
|
if (data.lock) {
|
|
handleLockScreen();
|
|
} else {
|
|
handleUnlockScreen();
|
|
}
|
|
} catch (error) {
|
|
}
|
|
|
|
// Call the function again after 'lockInterval' seconds
|
|
setTimeout(checkLockStatus, lockInterval);
|
|
})();
|
|
|
|
// Blank modal dialog, show a close button after 10 seconds
|
|
export class ModalBlankDialog extends ComfyDialog {
|
|
constructor(app, message) {
|
|
super();
|
|
this.app = app;
|
|
this.settingsValues = {};
|
|
this.settingsLookup = {};
|
|
this.element = $el(
|
|
"dialog",
|
|
{
|
|
id: "comfy-settings-dialog-blank",
|
|
parent: document.body,
|
|
style: { width: "33%" , border: 0, padding:0}
|
|
},
|
|
[
|
|
$el("table.comfy-modal-content.comfy-table", [
|
|
$el(
|
|
"caption",
|
|
{
|
|
id: "black_model_msg",
|
|
textContent: message
|
|
},
|
|
),
|
|
$el(
|
|
"tr",
|
|
{
|
|
style: { display: "none" },
|
|
},
|
|
[$el("th"), $el("th", { style: { width: "23%" } })]
|
|
),
|
|
]),
|
|
$el(
|
|
"div",
|
|
{
|
|
id: "close-button",
|
|
style: {
|
|
position: "fixed",
|
|
top: "10px",
|
|
right: "10px",
|
|
display: "none",
|
|
},
|
|
},
|
|
[
|
|
$el("button", {
|
|
textContent: "X",
|
|
onclick: () => this.element.close(),
|
|
}),
|
|
]
|
|
),
|
|
]
|
|
);
|
|
|
|
setTimeout(() => {
|
|
document.getElementById("close-button").style.display = "block";
|
|
}, lockTimeout);
|
|
}
|
|
|
|
show() {
|
|
this.element.showModal();
|
|
}
|
|
|
|
reset_msg(message){
|
|
document.getElementById("black_model_msg").textContent = message;
|
|
}
|
|
|
|
close() {
|
|
this.element.close();
|
|
}
|
|
}
|
|
|
|
// input field dialog
|
|
export class ModalEndpointReleaseDialog extends ComfyDialog {
|
|
|
|
constructor(app) {
|
|
super();
|
|
this.app = app;
|
|
this.settingsValues = {};
|
|
this.settingsLookup = {};
|
|
this.element = $el(
|
|
"dialog",
|
|
{
|
|
id: "comfy-settings-dialog-release",
|
|
parent: document.body,
|
|
style: { width: "40%" , border: 0, padding:0}
|
|
},
|
|
[
|
|
$el("table.comfy-modal-content.comfy-table", [
|
|
$el(
|
|
"caption",
|
|
{ textContent: "Release Environment", style: { border: "0" } },
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("th", { textContent: "Environment Name", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("input", {
|
|
type: "text",
|
|
id: "release-input-field",
|
|
style: { width: "100%", border: "0" },
|
|
value: "",
|
|
})
|
|
])
|
|
]
|
|
),
|
|
$el(
|
|
"caption",
|
|
{ textContent: "Endpoint Config", style: { border: "0" } },
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("th", { textContent: "Instance Type", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("select", {
|
|
id: "select-instance-field",
|
|
style: { width: "100%", border: "0" },
|
|
}, [
|
|
$el("option", { value: "ml.g5.2xlarge", textContent: "ml.g5.2xlarge" }),
|
|
$el("option", { value: "ml.g5.4xlarge", textContent: "ml.g5.4xlarge" }),
|
|
$el("option", { value: "ml.g5.8xlarge", textContent: "ml.g5.8xlarge" }),
|
|
$el("option", { value: "ml.g5.12xlarge", textContent: "ml.g5.12xlarge" }),
|
|
$el("option", { value: "ml.g5.24xlarge", textContent: "ml.g5.24xlarge" }),
|
|
$el("option", { value: "ml.g4dn.4xlarge", textContent: "ml.g4dn.4xlarge" }),
|
|
$el("option", { value: "ml.g4dn.8xlarge", textContent: "ml.g4dn.8xlarge" }),
|
|
$el("option", { value: "ml.g4dn.12xlarge", textContent: "ml.g4dn.12xlarge" }),
|
|
$el("option", { value: "ml.p4d.24xlarge", textContent: "ml.p4d.24xlarge" }),
|
|
$el("option", { value: "ml.g6.xlarge", textContent: "ml.g6.xlarge" }),
|
|
$el("option", { value: "ml.g6.2xlarge", textContent: "ml.g6.2xlarge" }),
|
|
$el("option", { value: "ml.g6.4xlarge", textContent: "ml.g6.4xlarge" }),
|
|
$el("option", { value: "ml.g6.8xlarge", textContent: "ml.g6.8xlarge" }),
|
|
$el("option", { value: "ml.g6.12xlarge", textContent: "ml.g6.12xlarge" }),
|
|
$el("option", { value: "ml.g6.16xlarge", textContent: "ml.g6.16xlarge" }),
|
|
$el("option", { value: "ml.g6.24xlarge", textContent: "ml.g6.24xlarge" }),
|
|
$el("option", { value: "ml.g6.48xlarge", textContent: "ml.g6.48xlarge" }),
|
|
])
|
|
]),
|
|
$el("th", { textContent: "Auto-Scale", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("select", {
|
|
id: "select-scale-field",
|
|
style: { width: "100%", border: "0" },
|
|
onchange: async () => {
|
|
const scaleSelectField = document.getElementById("select-scale-field");
|
|
const minMaxCountRow = document.getElementById("min-max-count");
|
|
minMaxCountRow.hidden = scaleSelectField.value !== 'true';
|
|
}
|
|
}, [
|
|
$el("option", { value: true, textContent: "true" }),
|
|
$el("option", { value: false, textContent: "false" }),
|
|
])
|
|
]),
|
|
$el("th", { textContent: "Init Count", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("input", {
|
|
type: "text",
|
|
id: "init-count-input-field",
|
|
style: { width: "100%", border: "0" },
|
|
value: "",
|
|
})
|
|
]),
|
|
]
|
|
),
|
|
$el(
|
|
"tr",
|
|
{
|
|
id: "min-max-count",
|
|
hidden: true
|
|
},
|
|
[
|
|
$el("th", { textContent: "Min-count", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("input", {
|
|
type: "text",
|
|
id: "min-input-field",
|
|
style: { width: "100%", border: "0" },
|
|
value: "",
|
|
})
|
|
]),
|
|
$el("th", { textContent: "Max-Count", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("input", {
|
|
type: "text",
|
|
id: "max-input-field",
|
|
style: { width: "100%", border: "0" },
|
|
value: "",
|
|
})
|
|
])
|
|
]
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("td", { colspan: 3, style: { textAlign: "center", border: "0" } }, [
|
|
$el("button", {
|
|
id: "release-ok-button",
|
|
textContent: "OK",
|
|
style: { marginRight: "10px", width: "60px" },
|
|
onclick: async () => {
|
|
const workflowNameInputField = document.getElementById("release-input-field");
|
|
const initCountInputField = document.getElementById("init-count-input-field");
|
|
const instanceTypeSelectField = document.getElementById("select-instance-field");
|
|
const scaleSelectField = document.getElementById("select-scale-field");
|
|
const minInputField = document.getElementById("min-input-field");
|
|
const maxInputField = document.getElementById("max-input-field");
|
|
await this.releaseEndpointWorkflow(workflowNameInputField.value, initCountInputField.value, instanceTypeSelectField.value, scaleSelectField.value, minInputField.value, maxInputField.value);
|
|
}
|
|
}),
|
|
$el("button", {
|
|
id: "release-cancel-button",
|
|
textContent: "Cancel",
|
|
style: { marginRight: "10px", width: "60px" },
|
|
onclick: () => this.handleCancelClick(),
|
|
}),
|
|
$el("span", {
|
|
id: "release-validate-span",
|
|
textContent: "",
|
|
style: { marginRight: "10px", color: "red" }
|
|
}),
|
|
]),
|
|
]
|
|
),
|
|
]),
|
|
]
|
|
);
|
|
}
|
|
|
|
show() {
|
|
this.textElement.replaceChildren(
|
|
$el(
|
|
"tr",
|
|
{
|
|
style: { display: "none" },
|
|
},
|
|
[$el("th"), $el("th", { style: { width: "50%" } })]
|
|
)
|
|
);
|
|
this.element.showModal();
|
|
}
|
|
|
|
clear(){
|
|
document.getElementById("release-input-field").value = '';
|
|
document.getElementById("init-count-input-field").value = '';
|
|
document.getElementById("select-instance-field").value = '';
|
|
document.getElementById("select-scale-field").value = '';
|
|
document.getElementById("min-input-field").value = '';
|
|
document.getElementById("max-input-field").value = '';
|
|
document.getElementById("release-validate-span").textContent = '';
|
|
}
|
|
|
|
async releaseEndpointWorkflow(workflowName, initCount, instanceType, autoScale, minCount, maxCount) {
|
|
// validate names
|
|
if (workflowName.length > 40) {
|
|
document.getElementById("release-validate-span").textContent = 'The environment name cannot exceed 40 characters.';
|
|
return;
|
|
}
|
|
|
|
// Check if the input value contains only English letters, numbers, and underscores
|
|
const nameRegex = /^[a-zA-Z0-9_]+$/;
|
|
if (!nameRegex.test(workflowName)) {
|
|
document.getElementById("release-validate-span").textContent = 'The environment name must only contain letters, numbers, and underscores.';
|
|
return;
|
|
}
|
|
|
|
// Validate initCount
|
|
if (!initCount || isNaN(initCount) || Number(initCount) < 0) {
|
|
document.getElementById("release-validate-span").textContent = 'Initial count must be a non-negative number.';
|
|
return;
|
|
}
|
|
|
|
// Validate minCount and maxCount if autoScale is true
|
|
if (autoScale === true) {
|
|
if (!minCount || isNaN(minCount) || Number(minCount) < 0) {
|
|
document.getElementById("release-validate-span").textContent = 'Min count must be a non-negative number.';
|
|
return;
|
|
}
|
|
if (!maxCount || isNaN(maxCount) || Number(maxCount) < 0) {
|
|
document.getElementById("release-validate-span").textContent = 'Max count must be a non-negative number.';
|
|
return;
|
|
}
|
|
}
|
|
|
|
// this.element.close();
|
|
handleLockScreen("Creating...");
|
|
try {
|
|
let payloadJson =await app.graphToPrompt()
|
|
console.log(payloadJson)
|
|
|
|
minCount = minCount || "1";
|
|
maxCount = maxCount || "1";
|
|
|
|
var target = {
|
|
'name': workflowName,
|
|
'payload_json': payloadJson,
|
|
'initCount': initCount,
|
|
'instanceType': instanceType,
|
|
'autoScale': autoScale,
|
|
'minCount': minCount,
|
|
'maxCount': maxCount,
|
|
};
|
|
const response = await api.fetchApi("/release", {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
const result = await response.json();
|
|
if (!result.result) {
|
|
handleUnlockScreen();
|
|
document.getElementById("release-validate-span").textContent = result.message;
|
|
} else {
|
|
this.element.close();
|
|
}
|
|
} catch (exception) {
|
|
console.error('Create error:', exception);
|
|
handleUnlockScreen();
|
|
document.getElementById("release-validate-span").textContent = errorMessage;
|
|
}
|
|
}
|
|
|
|
handleCancelClick() {
|
|
this.element.close();
|
|
}
|
|
}
|
|
|
|
// var newTemplateName = '';
|
|
export class ModalTemplateDialog extends ComfyDialog{
|
|
constructor(app) {
|
|
super();
|
|
this.app = app;
|
|
this.settingsValues = {};
|
|
this.settingsLookup = {};
|
|
this.element = $el(
|
|
"dialog",
|
|
{
|
|
id: "comfy-settings-dialog-temp",
|
|
parent: document.body,
|
|
style: { width: "40%" , border: 0, padding:0}
|
|
},
|
|
[
|
|
$el("table.comfy-modal-content.comfy-table", [
|
|
$el(
|
|
"caption",
|
|
{ textContent: "Create Template", style: { border: "0" } },
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("th", { textContent: "Template Name", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("input", {
|
|
type: "text",
|
|
id: "input-template_field",
|
|
style: { width: "100%", border: "0" },
|
|
value: "",
|
|
})
|
|
]),
|
|
$el("th", { textContent: "Environment Name", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("select", {
|
|
id: "select-workflow_field",
|
|
style: { width: "100%", border: "0" },
|
|
})
|
|
]),
|
|
]
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("td", { colspan: 3, style: { textAlign: "center", border: "0" } }, [
|
|
$el("button", {
|
|
id: "ok-button",
|
|
textContent: "OK",
|
|
style: { marginRight: "10px", width: "60px" },
|
|
onclick: async () => {
|
|
const tempInputField = document.getElementById("input-template_field");
|
|
const workflowInputField = document.getElementById("select-workflow_field");
|
|
console.log(tempInputField)
|
|
console.log(workflowInputField)
|
|
await this.createTemplate(tempInputField.value, workflowInputField.value);
|
|
}
|
|
}),
|
|
$el("button", {
|
|
id: "cancel-button",
|
|
textContent: "Cancel",
|
|
style: { marginRight: "10px", width: "60px" },
|
|
onclick: () => this.handleCancelClick(),
|
|
}),
|
|
$el("span", {
|
|
id: "template-release-validate",
|
|
textContent: "",
|
|
style: { marginRight: "10px", color: "red" }
|
|
}),
|
|
]),
|
|
]
|
|
),
|
|
]),
|
|
]
|
|
);
|
|
}
|
|
|
|
show() {
|
|
this.textElement.replaceChildren(
|
|
$el(
|
|
"tr",
|
|
{
|
|
style: { display: "none" },
|
|
},
|
|
[$el("th"), $el("th", { style: { width: "33%" } })]
|
|
)
|
|
);
|
|
this.element.showModal();
|
|
}
|
|
|
|
clear() {
|
|
document.getElementById("input-template_field").value='';
|
|
document.getElementById("select-workflow_field").value = 'default';
|
|
document.getElementById("template-release-validate").textContent = '';
|
|
|
|
}
|
|
|
|
populateWorkflowSelectField() {
|
|
api.fetchApi("/workflows", {
|
|
method: 'GET',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.data && Array.isArray(data.data.workflows)) {
|
|
const workflowSelectField = document.getElementById("select-workflow_field");
|
|
workflowSelectField.innerHTML = '';
|
|
data.data.workflows.forEach(workflow => {
|
|
if (workflow.status === 'Enabled') {
|
|
const option = document.createElement('option');
|
|
option.value = workflow.name;
|
|
option.textContent = `${workflow.name}(${workflow.size})`;
|
|
workflowSelectField.appendChild(option);
|
|
}
|
|
});
|
|
} else {
|
|
console.error('Failed to fetch workflow names:', data.message);
|
|
}
|
|
})
|
|
.catch(exception => {
|
|
console.error('Error fetching workflow names:', exception);
|
|
});
|
|
}
|
|
|
|
|
|
async createTemplate(templateName, workflowName) {
|
|
// validate names
|
|
if (templateName.length > 40) {
|
|
document.getElementById("template-release-validate").textContent = 'The template name cannot exceed 40 characters.';
|
|
return;
|
|
}
|
|
|
|
// Check if the input value contains only English letters, numbers, and underscores
|
|
const nameRegex = /^[a-zA-Z0-9_]+$/;
|
|
if (!nameRegex.test(templateName)) {
|
|
document.getElementById("template-release-validate").textContent = 'The template name must only contain letters, numbers, and underscores.';
|
|
return;
|
|
}
|
|
|
|
// this.element.close();
|
|
handleLockScreen("Creating...");
|
|
try {
|
|
let payloadJson =await app.graphToPrompt()
|
|
if (typeof payloadJson === 'object') {
|
|
payloadJson = JSON.stringify(payloadJson);
|
|
}
|
|
console.log(payloadJson)
|
|
var target = {
|
|
'name': templateName,
|
|
'payload': payloadJson,
|
|
'workflow': workflowName
|
|
};
|
|
const response = await api.fetchApi("/schemas", {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
const result = await response.json();
|
|
if (!result.result) {
|
|
handleUnlockScreen();
|
|
document.getElementById("template-release-validate").textContent = result.message;
|
|
} else {
|
|
this.element.close();
|
|
}
|
|
} catch (exception) {
|
|
console.error('Create error:', exception);
|
|
handleUnlockScreen();
|
|
document.getElementById("template-release-validate").textContent = errorMessage;
|
|
}
|
|
}
|
|
|
|
handleCancelClick() {
|
|
this.element.close();
|
|
}
|
|
}
|
|
|
|
export class ModalEditTemplateDialog extends ComfyDialog{
|
|
constructor(app, selectedItem) {
|
|
super();
|
|
this.app = app;
|
|
this.settingsValues = {};
|
|
this.settingsLookup = {};
|
|
this.selectedItem = selectedItem;
|
|
this.element = $el(
|
|
"dialog",
|
|
{
|
|
id: "comfy-settings-dialog-edit",
|
|
parent: document.body,
|
|
style: { width: "50%" , border: 0, padding:0}
|
|
},
|
|
[
|
|
$el("table.comfy-modal-content.comfy-table", [
|
|
$el(
|
|
"caption",
|
|
{ textContent: "Edit Template", style: { border: "0" } },
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("th", { textContent: "Template Name", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("input", {
|
|
type: "text",
|
|
id: "edit-template_field",
|
|
style: { width: "100%", border: "0" },
|
|
value: selectedItem.firstChild.firstChild.textContent,
|
|
disabled: true,
|
|
})
|
|
]),
|
|
$el("th", { textContent: "Workflow Name", style: { border: "0" } }),
|
|
$el("td", [
|
|
$el("select", {
|
|
id: "edit-workflow_field",
|
|
style: { width: "100%", border: "0" },
|
|
})
|
|
]),
|
|
]
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("td", { colspan: 3, style: { textAlign: "center", border: "0" } }, [
|
|
$el("button", {
|
|
id: "edit-ok-button",
|
|
textContent: "OK",
|
|
style: { marginRight: "10px", width: "60px" },
|
|
onclick: async () => {
|
|
const tempEditField = document.getElementById("edit-template_field");
|
|
const workflowEditField = document.getElementById("edit-workflow_field");
|
|
console.log(tempEditField)
|
|
console.log(workflowEditField)
|
|
await this.editTemplate(tempEditField.value, workflowEditField.value);
|
|
}
|
|
}),
|
|
$el("button", {
|
|
id: "edit-cancel-button",
|
|
textContent: "Cancel",
|
|
style: { marginRight: "10px", width: "60px" },
|
|
onclick: () => this.handleCancelClick(),
|
|
}),
|
|
$el("span", {
|
|
id: "edit-release-validate",
|
|
textContent: "",
|
|
style: { marginRight: "10px", color: "red" }
|
|
}),
|
|
]),
|
|
]
|
|
),
|
|
]),
|
|
]
|
|
);
|
|
}
|
|
|
|
show() {
|
|
this.textElement.replaceChildren(
|
|
$el(
|
|
"tr",
|
|
{
|
|
style: { display: "none" },
|
|
},
|
|
[$el("th"), $el("th", { style: { width: "33%" } })]
|
|
)
|
|
);
|
|
this.element.showModal();
|
|
}
|
|
|
|
clear(selectedItem) {
|
|
document.getElementById("edit-template_field").value = selectedItem.firstChild.firstChild.textContent;
|
|
document.getElementById("edit-workflow_field").value = 'default';
|
|
document.getElementById("edit-release-validate").textContent = '';
|
|
}
|
|
|
|
populateWorkflowSelectField() {
|
|
api.fetchApi("/workflows", {
|
|
method: 'GET',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.data && Array.isArray(data.data.workflows)) {
|
|
const workflowSelectField = document.getElementById("edit-workflow_field");
|
|
workflowSelectField.innerHTML = '';
|
|
data.data.workflows.forEach(workflow => {
|
|
if (workflow.status === 'Enabled') {
|
|
const option = document.createElement('option');
|
|
option.value = workflow.name;
|
|
option.textContent = `${workflow.name}(${workflow.size})`;
|
|
workflowSelectField.appendChild(option);
|
|
}
|
|
});
|
|
} else {
|
|
console.error('Failed to fetch workflow names:', data.message);
|
|
}
|
|
})
|
|
.catch(exception => {
|
|
console.error('Error fetching workflow names:', exception);
|
|
});
|
|
}
|
|
|
|
|
|
async editTemplate(templateName, workflowName) {
|
|
|
|
// this.element.close();
|
|
handleLockScreen("Updating...");
|
|
try {
|
|
let payloadJson =await app.graphToPrompt()
|
|
if (typeof payloadJson === 'object') {
|
|
payloadJson = JSON.stringify(payloadJson);
|
|
}
|
|
console.log(payloadJson)
|
|
var target = {
|
|
'name': templateName,
|
|
'payload': payloadJson,
|
|
'workflow': workflowName
|
|
};
|
|
const response = await api.fetchApi("/schemas", {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(target)
|
|
});
|
|
const result = await response.json();
|
|
if (!result.result) {
|
|
handleUnlockScreen();
|
|
document.getElementById("edit-release-validate").textContent = result.message;
|
|
} else {
|
|
this.element.close();
|
|
}
|
|
} catch (exception) {
|
|
console.error('Update error:', exception);
|
|
handleUnlockScreen();
|
|
document.getElementById("edit-release-validate").textContent = errorMessage;
|
|
}
|
|
}
|
|
|
|
handleCancelClick() {
|
|
this.element.close();
|
|
}
|
|
}
|
|
|
|
export class ModalConfirmDialog extends ComfyDialog {
|
|
constructor(app, message, callback) {
|
|
super();
|
|
this.app = app;
|
|
this.message = message;
|
|
this.callback = callback;
|
|
this.settingsValues = {};
|
|
this.settingsLookup = {};
|
|
this.element = $el(
|
|
"dialog",
|
|
{
|
|
id: "comfy-settings-dialog-confirm",
|
|
parent: document.body,
|
|
style: { width: "33%" , border: 0, padding:0}
|
|
},
|
|
[
|
|
$el("table.comfy-modal-content.comfy-table", [
|
|
$el(
|
|
"caption",
|
|
{ textContent: "AWS Config", style: { border: "0" } },
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("td", { colspan: 2, style: { textAlign: "center", border: "0" } }, [
|
|
$el("p", { textContent: this.message, style: { textAlign: "center" } }),
|
|
]),
|
|
]
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("td", { colspan: 2, style: { textAlign: "center", border: "0" } }, [
|
|
$el("button", {
|
|
id: "ok-button",
|
|
textContent: "Yes",
|
|
style: { marginRight: "10px", width: "40px" },
|
|
onclick: () => this.handleYesClick(),
|
|
}),
|
|
$el("button", {
|
|
id: "cancel-button",
|
|
textContent: "No",
|
|
style: { marginRight: "10px", width: "40px" },
|
|
onclick: () => this.handleNoClick(),
|
|
}),
|
|
]),
|
|
]
|
|
),
|
|
]),
|
|
]
|
|
);
|
|
}
|
|
|
|
show() {
|
|
this.element.showModal();
|
|
}
|
|
|
|
handleYesClick() {
|
|
this.callback();
|
|
this.element.close();
|
|
}
|
|
|
|
handleNoClick() {
|
|
this.element.close();
|
|
}
|
|
}
|
|
|
|
export class ModalMessageDialog extends ComfyDialog {
|
|
constructor(app, message) {
|
|
super();
|
|
this.app = app;
|
|
this.message = message;
|
|
this.settingsValues = {};
|
|
this.settingsLookup = {};
|
|
this.element = $el(
|
|
"dialog",
|
|
{
|
|
id: "comfy-settings-dialog-msg",
|
|
parent: document.body,
|
|
style: { width: "33%" , border: 0, padding:0}
|
|
},
|
|
[
|
|
$el("table.comfy-modal-content.comfy-table", [
|
|
$el(
|
|
"caption",
|
|
{ textContent: "AWS Config", style: { border: "0" } },
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("td", { colspan: 2, style: { textAlign: "center", border: "0" } }, [
|
|
$el("p", { textContent: this.message, style: { textAlign: "center" } }),
|
|
]),
|
|
]
|
|
),
|
|
$el(
|
|
"tr",
|
|
[
|
|
$el("td", { colspan: 2, style: { textAlign: "center" } }, [
|
|
$el("button", {
|
|
id: "ok-button",
|
|
textContent: "OK",
|
|
onclick: () => this.handleOkClick(),
|
|
}),
|
|
]),
|
|
]
|
|
),
|
|
]),
|
|
]
|
|
);
|
|
}
|
|
|
|
show() {
|
|
this.element.showModal();
|
|
}
|
|
|
|
handleOkClick() {
|
|
this.element.close();
|
|
}
|
|
}
|