add: node focusing function
This commit is contained in:
		
							parent
							
								
									01e323b7e2
								
							
						
					
					
						commit
						369c1456a9
					
				@ -24,7 +24,10 @@ function dispatchAPIEventData(data) {
 | 
				
			|||||||
            message += "\n" + nodeError.class_type + ":";
 | 
					            message += "\n" + nodeError.class_type + ":";
 | 
				
			||||||
            for (const errorReason of nodeError.errors) {
 | 
					            for (const errorReason of nodeError.errors) {
 | 
				
			||||||
                message +=
 | 
					                message +=
 | 
				
			||||||
          "\n    - " + errorReason.message + ": " + errorReason.details;
 | 
					                    "\n    - " +
 | 
				
			||||||
 | 
					                    errorReason.message +
 | 
				
			||||||
 | 
					                    ": " +
 | 
				
			||||||
 | 
					                    errorReason.details;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -44,32 +47,38 @@ function dispatchAPIEventData(data) {
 | 
				
			|||||||
                // window.name = this.clientId; // use window name so it isnt reused when duplicating tabs
 | 
					                // window.name = this.clientId; // use window name so it isnt reused when duplicating tabs
 | 
				
			||||||
                // sessionStorage.setItem("clientId", this.clientId); // store in session storage so duplicate tab can load correct workflow
 | 
					                // sessionStorage.setItem("clientId", this.clientId); // store in session storage so duplicate tab can load correct workflow
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
      api.dispatchEvent(new CustomEvent("status", { detail: msg.data.status }));
 | 
					            api.dispatchEvent(
 | 
				
			||||||
 | 
					                new CustomEvent("status", { detail: msg.data.status })
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case "progress":
 | 
					        case "progress":
 | 
				
			||||||
      api.dispatchEvent(new CustomEvent("progress", { detail: msg.data }));
 | 
					            api.dispatchEvent(
 | 
				
			||||||
 | 
					                new CustomEvent("progress", { detail: msg.data })
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case "executing":
 | 
					        case "executing":
 | 
				
			||||||
            api.dispatchEvent(
 | 
					            api.dispatchEvent(
 | 
				
			||||||
        new CustomEvent("executing", { detail: msg.data.node }),
 | 
					                new CustomEvent("executing", { detail: msg.data.node })
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case "executed":
 | 
					        case "executed":
 | 
				
			||||||
      api.dispatchEvent(new CustomEvent("executed", { detail: msg.data }));
 | 
					            api.dispatchEvent(
 | 
				
			||||||
 | 
					                new CustomEvent("executed", { detail: msg.data })
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case "execution_start":
 | 
					        case "execution_start":
 | 
				
			||||||
            api.dispatchEvent(
 | 
					            api.dispatchEvent(
 | 
				
			||||||
        new CustomEvent("execution_start", { detail: msg.data }),
 | 
					                new CustomEvent("execution_start", { detail: msg.data })
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case "execution_error":
 | 
					        case "execution_error":
 | 
				
			||||||
            api.dispatchEvent(
 | 
					            api.dispatchEvent(
 | 
				
			||||||
        new CustomEvent("execution_error", { detail: msg.data }),
 | 
					                new CustomEvent("execution_error", { detail: msg.data })
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case "execution_cached":
 | 
					        case "execution_cached":
 | 
				
			||||||
            api.dispatchEvent(
 | 
					            api.dispatchEvent(
 | 
				
			||||||
        new CustomEvent("execution_cached", { detail: msg.data }),
 | 
					                new CustomEvent("execution_cached", { detail: msg.data })
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
@ -143,11 +152,13 @@ const ext = {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!workflow_version_id) {
 | 
					        if (!workflow_version_id) {
 | 
				
			||||||
      console.error("No workflow_version_id provided in query parameters.");
 | 
					            console.error(
 | 
				
			||||||
 | 
					                "No workflow_version_id provided in query parameters."
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            loadingDialog.showLoading(
 | 
					            loadingDialog.showLoading(
 | 
				
			||||||
                "Loading workflow from " + org_display,
 | 
					                "Loading workflow from " + org_display,
 | 
				
			||||||
        "Please wait...",
 | 
					                "Please wait..."
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            fetch(endpoint + "/api/workflow-version/" + workflow_version_id, {
 | 
					            fetch(endpoint + "/api/workflow-version/" + workflow_version_id, {
 | 
				
			||||||
                method: "GET",
 | 
					                method: "GET",
 | 
				
			||||||
@ -160,7 +171,10 @@ const ext = {
 | 
				
			|||||||
                    const data = await res.json();
 | 
					                    const data = await res.json();
 | 
				
			||||||
                    const { workflow, workflow_id, error } = data;
 | 
					                    const { workflow, workflow_id, error } = data;
 | 
				
			||||||
                    if (error) {
 | 
					                    if (error) {
 | 
				
			||||||
            infoDialog.showMessage("Unable to load this workflow", error);
 | 
					                        infoDialog.showMessage(
 | 
				
			||||||
 | 
					                            "Unable to load this workflow",
 | 
				
			||||||
 | 
					                            error
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
                        return;
 | 
					                        return;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -183,7 +197,7 @@ const ext = {
 | 
				
			|||||||
                    window.history.replaceState(
 | 
					                    window.history.replaceState(
 | 
				
			||||||
                        {},
 | 
					                        {},
 | 
				
			||||||
                        document.title,
 | 
					                        document.title,
 | 
				
			||||||
            window.location.pathname,
 | 
					                        window.location.pathname
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -206,22 +220,37 @@ const ext = {
 | 
				
			|||||||
                ComfyWidgets.STRING(
 | 
					                ComfyWidgets.STRING(
 | 
				
			||||||
                    this,
 | 
					                    this,
 | 
				
			||||||
                    "workflow_name",
 | 
					                    "workflow_name",
 | 
				
			||||||
          ["", { default: this.properties.workflow_name, multiline: false }],
 | 
					                    [
 | 
				
			||||||
          app,
 | 
					                        "",
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            default: this.properties.workflow_name,
 | 
				
			||||||
 | 
					                            multiline: false,
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                    app
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                ComfyWidgets.STRING(
 | 
					                ComfyWidgets.STRING(
 | 
				
			||||||
                    this,
 | 
					                    this,
 | 
				
			||||||
                    "workflow_id",
 | 
					                    "workflow_id",
 | 
				
			||||||
          ["", { default: this.properties.workflow_id, multiline: false }],
 | 
					                    [
 | 
				
			||||||
          app,
 | 
					                        "",
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            default: this.properties.workflow_id,
 | 
				
			||||||
 | 
					                            multiline: false,
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                    app
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                ComfyWidgets.STRING(
 | 
					                ComfyWidgets.STRING(
 | 
				
			||||||
                    this,
 | 
					                    this,
 | 
				
			||||||
                    "version",
 | 
					                    "version",
 | 
				
			||||||
          ["", { default: this.properties.version, multiline: false }],
 | 
					                    [
 | 
				
			||||||
          app,
 | 
					                        "",
 | 
				
			||||||
 | 
					                        { default: this.properties.version, multiline: false },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                    app
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // this.widgets.forEach((w) => {
 | 
					                // this.widgets.forEach((w) => {
 | 
				
			||||||
@ -248,7 +277,7 @@ const ext = {
 | 
				
			|||||||
                title_mode: LiteGraph.NORMAL_TITLE,
 | 
					                title_mode: LiteGraph.NORMAL_TITLE,
 | 
				
			||||||
                title: "Comfy Deploy",
 | 
					                title: "Comfy Deploy",
 | 
				
			||||||
                collapsable: true,
 | 
					                collapsable: true,
 | 
				
			||||||
      }),
 | 
					            })
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ComfyDeploy.category = "deploy";
 | 
					        ComfyDeploy.category = "deploy";
 | 
				
			||||||
@ -281,7 +310,9 @@ const ext = {
 | 
				
			|||||||
                    if (typeof api.handlePromptGenerated === "function") {
 | 
					                    if (typeof api.handlePromptGenerated === "function") {
 | 
				
			||||||
                        api.handlePromptGenerated(prompt);
 | 
					                        api.handlePromptGenerated(prompt);
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
            console.warn("api.handlePromptGenerated is not a function");
 | 
					                        console.warn(
 | 
				
			||||||
 | 
					                            "api.handlePromptGenerated is not a function"
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    sendEventToCD("cd_plugin_onQueuePrompt", prompt);
 | 
					                    sendEventToCD("cd_plugin_onQueuePrompt", prompt);
 | 
				
			||||||
                } else if (message.type === "get_prompt") {
 | 
					                } else if (message.type === "get_prompt") {
 | 
				
			||||||
@ -305,6 +336,72 @@ const ext = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    app.graph.add(node);
 | 
					                    app.graph.add(node);
 | 
				
			||||||
                    app.graph.afterChange();
 | 
					                    app.graph.afterChange();
 | 
				
			||||||
 | 
					                } else if (message.type === "zoom_to_node") {
 | 
				
			||||||
 | 
					                    const nodeId = message.data.nodeId;
 | 
				
			||||||
 | 
					                    const position = message.data.position;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    const node = app.graph.getNodeById(nodeId);
 | 
				
			||||||
 | 
					                    if (!node) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    const canvas = app.canvas;
 | 
				
			||||||
 | 
					                    const targetScale = 1;
 | 
				
			||||||
 | 
					                    const targetOffsetX =
 | 
				
			||||||
 | 
					                        canvas.canvas.width / 4 -
 | 
				
			||||||
 | 
					                        position[0] -
 | 
				
			||||||
 | 
					                        node.size[0] / 2;
 | 
				
			||||||
 | 
					                    const targetOffsetY =
 | 
				
			||||||
 | 
					                        canvas.canvas.height / 4 -
 | 
				
			||||||
 | 
					                        position[1] -
 | 
				
			||||||
 | 
					                        node.size[1] / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    const startScale = canvas.ds.scale;
 | 
				
			||||||
 | 
					                    const startOffsetX = canvas.ds.offset[0];
 | 
				
			||||||
 | 
					                    const startOffsetY = canvas.ds.offset[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    const duration = 400; // Animation duration in milliseconds
 | 
				
			||||||
 | 
					                    const startTime = Date.now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    function easeOutCubic(t) {
 | 
				
			||||||
 | 
					                        return 1 - Math.pow(1 - t, 3);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    function lerp(start, end, t) {
 | 
				
			||||||
 | 
					                        return start * (1 - t) + end * t;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    function animate() {
 | 
				
			||||||
 | 
					                        const currentTime = Date.now();
 | 
				
			||||||
 | 
					                        const elapsedTime = currentTime - startTime;
 | 
				
			||||||
 | 
					                        const t = Math.min(elapsedTime / duration, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        const easedT = easeOutCubic(t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        const currentScale = lerp(
 | 
				
			||||||
 | 
					                            startScale,
 | 
				
			||||||
 | 
					                            targetScale,
 | 
				
			||||||
 | 
					                            easedT
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                        const currentOffsetX = lerp(
 | 
				
			||||||
 | 
					                            startOffsetX,
 | 
				
			||||||
 | 
					                            targetOffsetX,
 | 
				
			||||||
 | 
					                            easedT
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                        const currentOffsetY = lerp(
 | 
				
			||||||
 | 
					                            startOffsetY,
 | 
				
			||||||
 | 
					                            targetOffsetY,
 | 
				
			||||||
 | 
					                            easedT
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        canvas.setZoom(currentScale);
 | 
				
			||||||
 | 
					                        canvas.ds.offset = [currentOffsetX, currentOffsetY];
 | 
				
			||||||
 | 
					                        canvas.draw(true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (t < 1) {
 | 
				
			||||||
 | 
					                            requestAnimationFrame(animate);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    animate();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                // else if (message.type === "refresh") {
 | 
					                // else if (message.type === "refresh") {
 | 
				
			||||||
                //   sendEventToCD("cd_plugin_onRefresh");
 | 
					                //   sendEventToCD("cd_plugin_onRefresh");
 | 
				
			||||||
@ -345,7 +442,7 @@ const ext = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function showError(title, message) {
 | 
					function showError(title, message) {
 | 
				
			||||||
    infoDialog.show(
 | 
					    infoDialog.show(
 | 
				
			||||||
    `<h3 style="margin: 0px; color: red;">${title}</h3><br><span>${message}</span> `,
 | 
					        `<h3 style="margin: 0px; color: red;">${title}</h3><br><span>${message}</span> `
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -379,11 +476,14 @@ function createDynamicUIHtml(data) {
 | 
				
			|||||||
    Object.values(data.custom_nodes).forEach((node) => {
 | 
					    Object.values(data.custom_nodes).forEach((node) => {
 | 
				
			||||||
        html += `
 | 
					        html += `
 | 
				
			||||||
          <div style="border-bottom: 1px solid #e2e8f0; padding-top: 16px;">
 | 
					          <div style="border-bottom: 1px solid #e2e8f0; padding-top: 16px;">
 | 
				
			||||||
              <a href="${node.url
 | 
					              <a href="${
 | 
				
			||||||
      }" target="_blank" style="font-size: 18px; font-weight: semibold; color: white; text-decoration: none;">${node.name
 | 
					                  node.url
 | 
				
			||||||
 | 
					              }" target="_blank" style="font-size: 18px; font-weight: semibold; color: white; text-decoration: none;">${
 | 
				
			||||||
 | 
					            node.name
 | 
				
			||||||
        }</a>
 | 
					        }</a>
 | 
				
			||||||
              <p style="font-size: 14px; color: #4b5563;">${node.hash}</p>
 | 
					              <p style="font-size: 14px; color: #4b5563;">${node.hash}</p>
 | 
				
			||||||
              ${node.warning
 | 
					              ${
 | 
				
			||||||
 | 
					                  node.warning
 | 
				
			||||||
                      ? `<p style="font-size: 14px; color: #d69e2e;">${node.warning}</p>`
 | 
					                      ? `<p style="font-size: 14px; color: #d69e2e;">${node.warning}</p>`
 | 
				
			||||||
                      : ""
 | 
					                      : ""
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
@ -400,7 +500,8 @@ function createDynamicUIHtml(data) {
 | 
				
			|||||||
    Object.entries(data.models).forEach(([section, items]) => {
 | 
					    Object.entries(data.models).forEach(([section, items]) => {
 | 
				
			||||||
        html += `
 | 
					        html += `
 | 
				
			||||||
    <div style="border-bottom: 1px solid #e2e8f0; padding-top: 8px; padding-bottom: 8px;">
 | 
					    <div style="border-bottom: 1px solid #e2e8f0; padding-top: 8px; padding-bottom: 8px;">
 | 
				
			||||||
        <h3 style="font-size: 18px; font-weight: semibold; margin-bottom: 8px;">${section.charAt(0).toUpperCase() + section.slice(1)
 | 
					        <h3 style="font-size: 18px; font-weight: semibold; margin-bottom: 8px;">${
 | 
				
			||||||
 | 
					            section.charAt(0).toUpperCase() + section.slice(1)
 | 
				
			||||||
        }</h3>`;
 | 
					        }</h3>`;
 | 
				
			||||||
        items.forEach((item) => {
 | 
					        items.forEach((item) => {
 | 
				
			||||||
            html += `<p style="font-size: 14px; color: ${textColor};">${item.name}</p>`;
 | 
					            html += `<p style="font-size: 14px; color: ${textColor};">${item.name}</p>`;
 | 
				
			||||||
@ -417,7 +518,8 @@ function createDynamicUIHtml(data) {
 | 
				
			|||||||
    Object.entries(data.files).forEach(([section, items]) => {
 | 
					    Object.entries(data.files).forEach(([section, items]) => {
 | 
				
			||||||
        html += `
 | 
					        html += `
 | 
				
			||||||
    <div style="border-bottom: 1px solid #e2e8f0; padding-top: 8px; padding-bottom: 8px;">
 | 
					    <div style="border-bottom: 1px solid #e2e8f0; padding-top: 8px; padding-bottom: 8px;">
 | 
				
			||||||
        <h3 style="font-size: 18px; font-weight: semibold; margin-bottom: 8px;">${section.charAt(0).toUpperCase() + section.slice(1)
 | 
					        <h3 style="font-size: 18px; font-weight: semibold; margin-bottom: 8px;">${
 | 
				
			||||||
 | 
					            section.charAt(0).toUpperCase() + section.slice(1)
 | 
				
			||||||
        }</h3>`;
 | 
					        }</h3>`;
 | 
				
			||||||
        items.forEach((item) => {
 | 
					        items.forEach((item) => {
 | 
				
			||||||
            html += `<p style="font-size: 14px; color: ${textColor};">${item.name}</p>`;
 | 
					            html += `<p style="font-size: 14px; color: ${textColor};">${item.name}</p>`;
 | 
				
			||||||
@ -448,7 +550,7 @@ async function deployWorkflow() {
 | 
				
			|||||||
    if (deployMeta.length == 0) {
 | 
					    if (deployMeta.length == 0) {
 | 
				
			||||||
        const text = await inputDialog.input(
 | 
					        const text = await inputDialog.input(
 | 
				
			||||||
            "Create your deployment",
 | 
					            "Create your deployment",
 | 
				
			||||||
      "Workflow name",
 | 
					            "Workflow name"
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        if (!text) return;
 | 
					        if (!text) return;
 | 
				
			||||||
        console.log(text);
 | 
					        console.log(text);
 | 
				
			||||||
@ -489,7 +591,7 @@ async function deployWorkflow() {
 | 
				
			|||||||
    <input id="reuse-hash" type="checkbox" checked>Reuse hash from last version</input>
 | 
					    <input id="reuse-hash" type="checkbox" checked>Reuse hash from last version</input>
 | 
				
			||||||
    </label>
 | 
					    </label>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    `,
 | 
					    `
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    if (!ok) return;
 | 
					    if (!ok) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -508,7 +610,7 @@ async function deployWorkflow() {
 | 
				
			|||||||
    if (!snapshot) {
 | 
					    if (!snapshot) {
 | 
				
			||||||
        showError(
 | 
					        showError(
 | 
				
			||||||
            "Error when deploying",
 | 
					            "Error when deploying",
 | 
				
			||||||
      "Unable to generate snapshot, please install ComfyUI Manager",
 | 
					            "Unable to generate snapshot, please install ComfyUI Manager"
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -529,7 +631,7 @@ async function deployWorkflow() {
 | 
				
			|||||||
                    "Content-Type": "application/json",
 | 
					                    "Content-Type": "application/json",
 | 
				
			||||||
                    Authorization: "Bearer " + apiKey,
 | 
					                    Authorization: "Bearer " + apiKey,
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
      },
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
            .then((x) => x.json())
 | 
					            .then((x) => x.json())
 | 
				
			||||||
            .catch(() => {
 | 
					            .catch(() => {
 | 
				
			||||||
@ -548,7 +650,7 @@ async function deployWorkflow() {
 | 
				
			|||||||
                // Match previous hash for models
 | 
					                // Match previous hash for models
 | 
				
			||||||
                if (reuseHash && existing_workflow?.dependencies?.models) {
 | 
					                if (reuseHash && existing_workflow?.dependencies?.models) {
 | 
				
			||||||
                    const previousModelHash = Object.entries(
 | 
					                    const previousModelHash = Object.entries(
 | 
				
			||||||
            existing_workflow?.dependencies?.models,
 | 
					                        existing_workflow?.dependencies?.models
 | 
				
			||||||
                    ).flatMap(([key, value]) => {
 | 
					                    ).flatMap(([key, value]) => {
 | 
				
			||||||
                        return Object.values(value).map((x) => ({
 | 
					                        return Object.values(value).map((x) => ({
 | 
				
			||||||
                            ...x,
 | 
					                            ...x,
 | 
				
			||||||
@ -570,7 +672,9 @@ async function deployWorkflow() {
 | 
				
			|||||||
                console.log(file);
 | 
					                console.log(file);
 | 
				
			||||||
                loadingDialog.showLoading("Generating hash", file);
 | 
					                loadingDialog.showLoading("Generating hash", file);
 | 
				
			||||||
                const hash = await fetch(
 | 
					                const hash = await fetch(
 | 
				
			||||||
          `/comfyui-deploy/get-file-hash?file_path=${encodeURIComponent(file)}`,
 | 
					                    `/comfyui-deploy/get-file-hash?file_path=${encodeURIComponent(
 | 
				
			||||||
 | 
					                        file
 | 
				
			||||||
 | 
					                    )}`
 | 
				
			||||||
                ).then((x) => x.json());
 | 
					                ).then((x) => x.json());
 | 
				
			||||||
                loadingDialog.showLoading("Generating hash", file);
 | 
					                loadingDialog.showLoading("Generating hash", file);
 | 
				
			||||||
                console.log(hash);
 | 
					                console.log(hash);
 | 
				
			||||||
@ -580,18 +684,24 @@ async function deployWorkflow() {
 | 
				
			|||||||
                console.log("Uploading ", file);
 | 
					                console.log("Uploading ", file);
 | 
				
			||||||
                loadingDialog.showLoading("Uploading file", file);
 | 
					                loadingDialog.showLoading("Uploading file", file);
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
          const { download_url } = await fetch(`/comfyui-deploy/upload-file`, {
 | 
					                    const { download_url } = await fetch(
 | 
				
			||||||
 | 
					                        `/comfyui-deploy/upload-file`,
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
                            method: "POST",
 | 
					                            method: "POST",
 | 
				
			||||||
                            body: JSON.stringify({
 | 
					                            body: JSON.stringify({
 | 
				
			||||||
                                file_path: file,
 | 
					                                file_path: file,
 | 
				
			||||||
                                token: apiKey,
 | 
					                                token: apiKey,
 | 
				
			||||||
                                url: endpoint + "/api/upload-url",
 | 
					                                url: endpoint + "/api/upload-url",
 | 
				
			||||||
                            }),
 | 
					                            }),
 | 
				
			||||||
          })
 | 
					                        }
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                        .then((x) => x.json())
 | 
					                        .then((x) => x.json())
 | 
				
			||||||
                        .catch(() => {
 | 
					                        .catch(() => {
 | 
				
			||||||
                            loadingDialog.close();
 | 
					                            loadingDialog.close();
 | 
				
			||||||
              confirmDialog.confirm("Error", "Unable to upload file " + file);
 | 
					                            confirmDialog.confirm(
 | 
				
			||||||
 | 
					                                "Error",
 | 
				
			||||||
 | 
					                                "Unable to upload file " + file
 | 
				
			||||||
 | 
					                            );
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    loadingDialog.showLoading("Uploaded file", file);
 | 
					                    loadingDialog.showLoading("Uploaded file", file);
 | 
				
			||||||
                    console.log(download_url);
 | 
					                    console.log(download_url);
 | 
				
			||||||
@ -628,8 +738,8 @@ async function deployWorkflow() {
 | 
				
			|||||||
      <iframe 
 | 
					      <iframe 
 | 
				
			||||||
      style="z-index: 10; min-width: 600px; max-width: 1024px; min-height: 600px; border: none; background-color: transparent;"
 | 
					      style="z-index: 10; min-width: 600px; max-width: 1024px; min-height: 600px; border: none; background-color: transparent;"
 | 
				
			||||||
      src="https://www.comfydeploy.com/dependency-graph?deps=${encodeURIComponent(
 | 
					      src="https://www.comfydeploy.com/dependency-graph?deps=${encodeURIComponent(
 | 
				
			||||||
        JSON.stringify(deps),
 | 
					          JSON.stringify(deps)
 | 
				
			||||||
      )}" />`,
 | 
					      )}" />`
 | 
				
			||||||
            // createDynamicUIHtml(deps),
 | 
					            // createDynamicUIHtml(deps),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        if (!depsOk) return;
 | 
					        if (!depsOk) return;
 | 
				
			||||||
@ -690,7 +800,7 @@ async function deployWorkflow() {
 | 
				
			|||||||
        graph.change();
 | 
					        graph.change();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        infoDialog.show(
 | 
					        infoDialog.show(
 | 
				
			||||||
      `<span style="color:green;">Deployed successfully!</span>  <a style="color:white;" target="_blank" href=${endpoint}/workflows/${data.workflow_id}>-> View here</a> <br/> <br/> Workflow ID: ${data.workflow_id} <br/> Workflow Name: ${workflow_name} <br/> Workflow Version: ${data.version} <br/>`,
 | 
					            `<span style="color:green;">Deployed successfully!</span>  <a style="color:white;" target="_blank" href=${endpoint}/workflows/${data.workflow_id}>-> View here</a> <br/> <br/> Workflow ID: ${data.workflow_id} <br/> Workflow Name: ${workflow_name} <br/> Workflow Version: ${data.version} <br/>`
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        setTimeout(() => {
 | 
					        setTimeout(() => {
 | 
				
			||||||
@ -841,9 +951,11 @@ export class LoadingDialog extends ComfyDialog {
 | 
				
			|||||||
    showLoading(title, message) {
 | 
					    showLoading(title, message) {
 | 
				
			||||||
        this.show(`
 | 
					        this.show(`
 | 
				
			||||||
      <div style="width: 400px; display: flex; gap: 18px; flex-direction: column; overflow: unset">
 | 
					      <div style="width: 400px; display: flex; gap: 18px; flex-direction: column; overflow: unset">
 | 
				
			||||||
        <h3 style="margin: 0px; display: flex; align-items: center; justify-content: center; gap: 12px;">${title} ${this.loadingIcon
 | 
					        <h3 style="margin: 0px; display: flex; align-items: center; justify-content: center; gap: 12px;">${title} ${
 | 
				
			||||||
 | 
					            this.loadingIcon
 | 
				
			||||||
        }</h3>
 | 
					        }</h3>
 | 
				
			||||||
          ${message
 | 
					          ${
 | 
				
			||||||
 | 
					              message
 | 
				
			||||||
                  ? `<label style="max-width: 100%; white-space: pre-wrap; word-wrap: break-word;">${message}</label>`
 | 
					                  ? `<label style="max-width: 100%; white-space: pre-wrap; word-wrap: break-word;">${message}</label>`
 | 
				
			||||||
                  : ""
 | 
					                  : ""
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -885,17 +997,22 @@ export class InputDialog extends InfoDialog {
 | 
				
			|||||||
                        type: "button",
 | 
					                        type: "button",
 | 
				
			||||||
                        textContent: "Save",
 | 
					                        textContent: "Save",
 | 
				
			||||||
                        onclick: () => {
 | 
					                        onclick: () => {
 | 
				
			||||||
              const input = this.textElement.querySelector("#input").value;
 | 
					                            const input =
 | 
				
			||||||
 | 
					                                this.textElement.querySelector("#input").value;
 | 
				
			||||||
                            if (input.trim() === "") {
 | 
					                            if (input.trim() === "") {
 | 
				
			||||||
                showError("Input validation", "Input cannot be empty");
 | 
					                                showError(
 | 
				
			||||||
 | 
					                                    "Input validation",
 | 
				
			||||||
 | 
					                                    "Input cannot be empty"
 | 
				
			||||||
 | 
					                                );
 | 
				
			||||||
                            } else {
 | 
					                            } else {
 | 
				
			||||||
                                this.callback?.(input);
 | 
					                                this.callback?.(input);
 | 
				
			||||||
                                this.close();
 | 
					                                this.close();
 | 
				
			||||||
                this.textElement.querySelector("#input").value = "";
 | 
					                                this.textElement.querySelector("#input").value =
 | 
				
			||||||
 | 
					                                    "";
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
        ],
 | 
					                ]
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -956,7 +1073,7 @@ export class ConfirmDialog extends InfoDialog {
 | 
				
			|||||||
                            this.close();
 | 
					                            this.close();
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
        ],
 | 
					                ]
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1013,7 +1130,7 @@ function getData(environment) {
 | 
				
			|||||||
function saveData(data) {
 | 
					function saveData(data) {
 | 
				
			||||||
    localStorage.setItem(
 | 
					    localStorage.setItem(
 | 
				
			||||||
        "comfy_deploy_env_data_" + data.environment,
 | 
					        "comfy_deploy_env_data_" + data.environment,
 | 
				
			||||||
    JSON.stringify(data),
 | 
					        JSON.stringify(data)
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1028,7 +1145,9 @@ export class ConfigDialog extends ComfyDialog {
 | 
				
			|||||||
        this.element.style.paddingBottom = "20px";
 | 
					        this.element.style.paddingBottom = "20px";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.container = document.createElement("div");
 | 
					        this.container = document.createElement("div");
 | 
				
			||||||
    this.element.querySelector(".comfy-modal-content").prepend(this.container);
 | 
					        this.element
 | 
				
			||||||
 | 
					            .querySelector(".comfy-modal-content")
 | 
				
			||||||
 | 
					            .prepend(this.container);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    createButtons() {
 | 
					    createButtons() {
 | 
				
			||||||
@ -1062,7 +1181,7 @@ export class ConfigDialog extends ComfyDialog {
 | 
				
			|||||||
                            this.close();
 | 
					                            this.close();
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
        ],
 | 
					                ]
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1074,7 +1193,8 @@ export class ConfigDialog extends ComfyDialog {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    save(api_key, displayName) {
 | 
					    save(api_key, displayName) {
 | 
				
			||||||
    const deployOption = this.container.querySelector("#deployOption").value;
 | 
					        const deployOption =
 | 
				
			||||||
 | 
					            this.container.querySelector("#deployOption").value;
 | 
				
			||||||
        localStorage.setItem("comfy_deploy_env", deployOption);
 | 
					        localStorage.setItem("comfy_deploy_env", deployOption);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const endpoint = this.container.querySelector("#endpoint").value;
 | 
					        const endpoint = this.container.querySelector("#endpoint").value;
 | 
				
			||||||
@ -1106,22 +1226,32 @@ export class ConfigDialog extends ComfyDialog {
 | 
				
			|||||||
    <h3 style="margin: 0px;">Comfy Deploy Config</h3>
 | 
					    <h3 style="margin: 0px;">Comfy Deploy Config</h3>
 | 
				
			||||||
    <label style="color: white; width: 100%;">
 | 
					    <label style="color: white; width: 100%;">
 | 
				
			||||||
      <select id="deployOption" style="margin: 8px 0px; width: 100%; height:30px; box-sizing: border-box;" >
 | 
					      <select id="deployOption" style="margin: 8px 0px; width: 100%; height:30px; box-sizing: border-box;" >
 | 
				
			||||||
        <option value="cloud" ${data.environment === "cloud" ? "selected" : ""}>Cloud</option>
 | 
					        <option value="cloud" ${
 | 
				
			||||||
        <option value="local" ${data.environment === "local" ? "selected" : ""}>Local</option>
 | 
					            data.environment === "cloud" ? "selected" : ""
 | 
				
			||||||
 | 
					        }>Cloud</option>
 | 
				
			||||||
 | 
					        <option value="local" ${
 | 
				
			||||||
 | 
					            data.environment === "local" ? "selected" : ""
 | 
				
			||||||
 | 
					        }>Local</option>
 | 
				
			||||||
      </select>
 | 
					      </select>
 | 
				
			||||||
    </label>
 | 
					    </label>
 | 
				
			||||||
      <label style="color: white; width: 100%;">
 | 
					      <label style="color: white; width: 100%;">
 | 
				
			||||||
        Endpoint:
 | 
					        Endpoint:
 | 
				
			||||||
        <input id="endpoint" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;" type="text" value="${data.endpoint
 | 
					        <input id="endpoint" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;" type="text" value="${
 | 
				
			||||||
 | 
					            data.endpoint
 | 
				
			||||||
        }">
 | 
					        }">
 | 
				
			||||||
      </label>
 | 
					      </label>
 | 
				
			||||||
      <div style="color: white;">
 | 
					      <div style="color: white;">
 | 
				
			||||||
        API Key: User / Org <button style="font-size: 18px;">${data.displayName ?? ""
 | 
					        API Key: User / Org <button style="font-size: 18px;">${
 | 
				
			||||||
 | 
					            data.displayName ?? ""
 | 
				
			||||||
        }</button>
 | 
					        }</button>
 | 
				
			||||||
        <input id="apiKey" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;" type="password" value="${data.apiKey
 | 
					        <input id="apiKey" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;" type="password" value="${
 | 
				
			||||||
 | 
					            data.apiKey
 | 
				
			||||||
        }">
 | 
					        }">
 | 
				
			||||||
        <button id="loginButton" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;">
 | 
					        <button id="loginButton" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;">
 | 
				
			||||||
          ${data.apiKey ? "Re-login with ComfyDeploy" : "Login with ComfyDeploy"
 | 
					          ${
 | 
				
			||||||
 | 
					              data.apiKey
 | 
				
			||||||
 | 
					                  ? "Re-login with ComfyDeploy"
 | 
				
			||||||
 | 
					                  : "Login with ComfyDeploy"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
@ -1142,7 +1272,7 @@ export class ConfigDialog extends ComfyDialog {
 | 
				
			|||||||
                clearInterval(poll);
 | 
					                clearInterval(poll);
 | 
				
			||||||
                infoDialog.showMessage(
 | 
					                infoDialog.showMessage(
 | 
				
			||||||
                    "Timeout",
 | 
					                    "Timeout",
 | 
				
			||||||
          "Wait too long for the response, please try re-login",
 | 
					                    "Wait too long for the response, please try re-login"
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            }, 30000); // Stop polling after 30 seconds
 | 
					            }, 30000); // Stop polling after 30 seconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1153,14 +1283,15 @@ export class ConfigDialog extends ComfyDialog {
 | 
				
			|||||||
                        if (json.api_key) {
 | 
					                        if (json.api_key) {
 | 
				
			||||||
                            this.save(json.api_key, json.name);
 | 
					                            this.save(json.api_key, json.name);
 | 
				
			||||||
                            this.close();
 | 
					                            this.close();
 | 
				
			||||||
              this.container.querySelector("#apiKey").value = json.api_key;
 | 
					                            this.container.querySelector("#apiKey").value =
 | 
				
			||||||
 | 
					                                json.api_key;
 | 
				
			||||||
                            // infoDialog.show();
 | 
					                            // infoDialog.show();
 | 
				
			||||||
                            clearInterval(this.poll);
 | 
					                            clearInterval(this.poll);
 | 
				
			||||||
                            clearTimeout(this.timeout);
 | 
					                            clearTimeout(this.timeout);
 | 
				
			||||||
                            // Refresh dialog
 | 
					                            // Refresh dialog
 | 
				
			||||||
                            const a = await confirmDialog.confirm(
 | 
					                            const a = await confirmDialog.confirm(
 | 
				
			||||||
                                "Authenticated",
 | 
					                                "Authenticated",
 | 
				
			||||||
                `<div>You will be able to upload workflow to <button style="font-size: 18px; width: fit;">${json.name}</button></div>`,
 | 
					                                `<div>You will be able to upload workflow to <button style="font-size: 18px; width: fit;">${json.name}</button></div>`
 | 
				
			||||||
                            );
 | 
					                            );
 | 
				
			||||||
                            configDialog.show();
 | 
					                            configDialog.show();
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user