mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-19 20:37:51 +00:00
upgraded lollmsflow
This commit is contained in:
parent
6a1a2cfb2b
commit
e96ca69f35
@ -145,6 +145,10 @@ class WorkflowVisualizer {
|
||||
this.tempLine = null;
|
||||
this.startSocket = null;
|
||||
|
||||
this.optionsPopup = null;
|
||||
this.setupOptionsPopup();
|
||||
|
||||
|
||||
this.addDefs();
|
||||
this.setupEventListeners();
|
||||
}
|
||||
@ -186,16 +190,21 @@ class WorkflowVisualizer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
drawNode(node) {
|
||||
const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
||||
g.setAttribute("transform", `translate(${node.x}, ${node.y})`);
|
||||
g.setAttribute("data-id", node.id);
|
||||
g.classList.add("node");
|
||||
|
||||
const titleHeight = 30;
|
||||
const buttonHeight = 25;
|
||||
const buttonMargin = 5;
|
||||
const nodeWidth = 160;
|
||||
const nodeHeight = titleHeight + (Object.keys(node.options).length * (buttonHeight + buttonMargin)) + buttonMargin;
|
||||
|
||||
const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||
rect.setAttribute("width", "140");
|
||||
rect.setAttribute("height", this.calculateNodeHeight(node));
|
||||
rect.setAttribute("width", nodeWidth);
|
||||
rect.setAttribute("height", nodeHeight);
|
||||
rect.setAttribute("rx", "5");
|
||||
rect.setAttribute("ry", "5");
|
||||
rect.setAttribute("fill", node.color || "#f0f0f0");
|
||||
@ -204,8 +213,8 @@ class WorkflowVisualizer {
|
||||
g.appendChild(rect);
|
||||
|
||||
const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||||
text.setAttribute("x", "70");
|
||||
text.setAttribute("y", "20");
|
||||
text.setAttribute("x", nodeWidth / 2);
|
||||
text.setAttribute("y", titleHeight / 2 + 5);
|
||||
text.setAttribute("text-anchor", "middle");
|
||||
text.setAttribute("font-family", "Arial, sans-serif");
|
||||
text.setAttribute("font-size", "14");
|
||||
@ -213,15 +222,168 @@ class WorkflowVisualizer {
|
||||
text.textContent = node.name;
|
||||
g.appendChild(text);
|
||||
|
||||
this.drawSockets(g, node.inputs, 'input');
|
||||
this.drawSockets(g, node.outputs, 'output');
|
||||
this.drawOptions(g, node.options);
|
||||
this.drawSockets(g, node.inputs, 'input', nodeHeight);
|
||||
this.drawSockets(g, node.outputs, 'output', nodeHeight);
|
||||
this.drawOptionButtons(g, node, titleHeight, buttonHeight, buttonMargin, nodeWidth);
|
||||
|
||||
g.addEventListener('mousedown', this.onNodeMouseDown.bind(this));
|
||||
this.svg.appendChild(g);
|
||||
this.nodeElements[node.id] = g;
|
||||
}
|
||||
|
||||
drawOptionButtons(nodeGroup, node, titleHeight, buttonHeight, buttonMargin, nodeWidth) {
|
||||
Object.entries(node.options).forEach(([key, option], index) => {
|
||||
const button = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||
button.setAttribute("x", buttonMargin);
|
||||
button.setAttribute("y", titleHeight + index * (buttonHeight + buttonMargin));
|
||||
button.setAttribute("width", nodeWidth - 2 * buttonMargin);
|
||||
button.setAttribute("height", buttonHeight);
|
||||
button.setAttribute("rx", "3");
|
||||
button.setAttribute("ry", "3");
|
||||
button.setAttribute("fill", "#ddd");
|
||||
button.setAttribute("stroke", "#333");
|
||||
button.setAttribute("stroke-width", "1");
|
||||
button.classList.add("option-button");
|
||||
|
||||
const buttonText = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||||
buttonText.setAttribute("x", nodeWidth / 2);
|
||||
buttonText.setAttribute("y", titleHeight + index * (buttonHeight + buttonMargin) + buttonHeight / 2 + 5);
|
||||
buttonText.setAttribute("text-anchor", "middle");
|
||||
buttonText.setAttribute("font-family", "Arial, sans-serif");
|
||||
buttonText.setAttribute("font-size", "12");
|
||||
buttonText.setAttribute("fill", "#333");
|
||||
buttonText.textContent = option.name; // Use the option name (key) instead of index
|
||||
|
||||
button.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
this.showOptionsPopup(node, key, option.name);
|
||||
});
|
||||
|
||||
nodeGroup.appendChild(button);
|
||||
nodeGroup.appendChild(buttonText);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
drawSockets(nodeGroup, sockets, type, nodeHeight) {
|
||||
sockets.forEach((socket, index) => {
|
||||
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
||||
circle.setAttribute("cx", type === 'input' ? "0" : "160");
|
||||
circle.setAttribute("cy", (index + 1) * (nodeHeight / (sockets.length + 1)));
|
||||
circle.setAttribute("r", "6");
|
||||
circle.setAttribute("fill", this.getColorForType(socket.type));
|
||||
circle.setAttribute("stroke", "#333");
|
||||
circle.setAttribute("stroke-width", "2");
|
||||
circle.classList.add("socket", `${type}-socket`);
|
||||
circle.setAttribute("data-node-id", nodeGroup.getAttribute("data-id"));
|
||||
circle.setAttribute("data-socket-index", index);
|
||||
circle.setAttribute("data-socket-type", socket.type);
|
||||
|
||||
this.addSocketListeners(circle, type);
|
||||
nodeGroup.appendChild(circle);
|
||||
});
|
||||
}
|
||||
|
||||
setupOptionsPopup() {
|
||||
this.optionsPopup = document.createElement('div');
|
||||
this.optionsPopup.style.position = 'absolute';
|
||||
this.optionsPopup.style.zIndex = '1000';
|
||||
this.optionsPopup.style.backgroundColor = 'white';
|
||||
this.optionsPopup.style.border = '1px solid #333';
|
||||
this.optionsPopup.style.borderRadius = '5px';
|
||||
this.optionsPopup.style.padding = '10px';
|
||||
this.optionsPopup.style.display = 'none';
|
||||
this.optionsPopup.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
|
||||
document.body.appendChild(this.optionsPopup);
|
||||
|
||||
// Close popup when clicking outside
|
||||
document.addEventListener('click', (event) => {
|
||||
if (!this.optionsPopup.contains(event.target) && !event.target.closest('.option-button')) {
|
||||
this.optionsPopup.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showOptionsPopup(node, optionKey, optionName) {
|
||||
this.optionsPopup.innerHTML = '';
|
||||
|
||||
const title = document.createElement('h3');
|
||||
title.textContent = `${node.name}: ${optionName}`;
|
||||
title.style.marginTop = '0';
|
||||
this.optionsPopup.appendChild(title);
|
||||
|
||||
const option = node.options[optionKey];
|
||||
const optionContainer = document.createElement('div');
|
||||
optionContainer.style.marginBottom = '10px';
|
||||
|
||||
let input;
|
||||
switch (option.type) {
|
||||
case 'checkbox':
|
||||
input = document.createElement('input');
|
||||
input.type = 'checkbox';
|
||||
input.checked = option.value;
|
||||
break;
|
||||
case 'radio':
|
||||
option.options.forEach(optionValue => {
|
||||
const radioInput = document.createElement('input');
|
||||
radioInput.type = 'radio';
|
||||
radioInput.name = optionKey;
|
||||
radioInput.value = optionValue;
|
||||
radioInput.checked = option.value === optionValue;
|
||||
const radioLabel = document.createElement('label');
|
||||
radioLabel.textContent = optionValue;
|
||||
optionContainer.appendChild(radioInput);
|
||||
optionContainer.appendChild(radioLabel);
|
||||
});
|
||||
break;
|
||||
case 'select':
|
||||
input = document.createElement('select');
|
||||
option.options.forEach(optionValue => {
|
||||
const optionElement = document.createElement('option');
|
||||
optionElement.value = optionValue;
|
||||
optionElement.textContent = optionValue;
|
||||
optionElement.selected = option.value === optionValue;
|
||||
input.appendChild(optionElement);
|
||||
});
|
||||
break;
|
||||
case 'file':
|
||||
input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
break;
|
||||
case 'textarea':
|
||||
input = document.createElement('textarea');
|
||||
input.value = option.value;
|
||||
input.rows = 3;
|
||||
break;
|
||||
default:
|
||||
input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
input.value = option.value;
|
||||
}
|
||||
|
||||
if (input) {
|
||||
input.addEventListener('change', (e) => {
|
||||
option.value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
|
||||
});
|
||||
optionContainer.appendChild(input);
|
||||
}
|
||||
|
||||
this.optionsPopup.appendChild(optionContainer);
|
||||
|
||||
const closeButton = document.createElement('button');
|
||||
closeButton.textContent = 'Close';
|
||||
closeButton.style.marginTop = '10px';
|
||||
closeButton.addEventListener('click', () => {
|
||||
this.optionsPopup.style.display = 'none';
|
||||
});
|
||||
this.optionsPopup.appendChild(closeButton);
|
||||
|
||||
const rect = this.svg.getBoundingClientRect();
|
||||
this.optionsPopup.style.left = (rect.left + node.x + 170) + 'px';
|
||||
this.optionsPopup.style.top = (rect.top + node.y) + 'px';
|
||||
this.optionsPopup.style.display = 'block';
|
||||
}
|
||||
|
||||
calculateNodeHeight(node) {
|
||||
const baseHeight = 80;
|
||||
const optionsHeight = Object.keys(node.options).length * 30;
|
||||
|
Loading…
Reference in New Issue
Block a user