Browse Source

Merge branch 'templates-export-import' of https://github.com/jn-jairo/ComfyUI

pull/1814/head
comfyanonymous 1 year ago
parent
commit
8d50f0890d
  1. 106
      web/extensions/core/nodeTemplates.js
  2. 44
      web/scripts/app.js

106
web/extensions/core/nodeTemplates.js

@ -22,6 +22,15 @@ class ManageTemplates extends ComfyDialog {
super(); super();
this.element.classList.add("comfy-manage-templates"); this.element.classList.add("comfy-manage-templates");
this.templates = this.load(); this.templates = this.load();
this.importInput = $el("input", {
type: "file",
accept: ".json",
multiple: true,
style: {display: "none"},
parent: document.body,
onchange: () => this.importAll(),
});
} }
createButtons() { createButtons() {
@ -34,6 +43,22 @@ class ManageTemplates extends ComfyDialog {
onclick: () => this.save(), onclick: () => this.save(),
}) })
); );
btns.unshift(
$el("button", {
type: "button",
textContent: "Export",
onclick: () => this.exportAll(),
})
);
btns.unshift(
$el("button", {
type: "button",
textContent: "Import",
onclick: () => {
this.importInput.click();
},
})
);
return btns; return btns;
} }
@ -69,6 +94,52 @@ class ManageTemplates extends ComfyDialog {
localStorage.setItem(id, JSON.stringify(this.templates)); localStorage.setItem(id, JSON.stringify(this.templates));
} }
async importAll() {
for (const file of this.importInput.files) {
if (file.type === "application/json" || file.name.endsWith(".json")) {
const reader = new FileReader();
reader.onload = async () => {
var importFile = JSON.parse(reader.result);
if (importFile && importFile?.templates) {
for (const template of importFile.templates) {
if (template?.name && template?.data) {
this.templates.push(template);
}
}
this.store();
}
};
await reader.readAsText(file);
}
}
this.importInput.value = null;
this.close();
}
exportAll() {
if (this.templates.length == 0) {
alert("No templates to export.");
return;
}
const json = JSON.stringify({templates: this.templates}, null, 2); // convert the data to a JSON string
const blob = new Blob([json], {type: "application/json"});
const url = URL.createObjectURL(blob);
const a = $el("a", {
href: url,
download: "node_templates.json",
style: {display: "none"},
parent: document.body,
});
a.click();
setTimeout(function () {
a.remove();
window.URL.revokeObjectURL(url);
}, 0);
}
show() { show() {
// Show list of template names + delete button // Show list of template names + delete button
super.show( super.show(
@ -97,6 +168,33 @@ class ManageTemplates extends ComfyDialog {
}), }),
] ]
), ),
$el(
"div",
{},
[
$el("button", {
textContent: "Export",
style: {
fontSize: "12px",
fontWeight: "normal",
},
onclick: (e) => {
const json = JSON.stringify({templates: [t]}, null, 2); // convert the data to a JSON string
const blob = new Blob([json], {type: "application/json"});
const url = URL.createObjectURL(blob);
const a = $el("a", {
href: url,
download: (nameInput.value || t.name) + ".json",
style: {display: "none"},
parent: document.body,
});
a.click();
setTimeout(function () {
a.remove();
window.URL.revokeObjectURL(url);
}, 0);
},
}),
$el("button", { $el("button", {
textContent: "Delete", textContent: "Delete",
style: { style: {
@ -106,10 +204,12 @@ class ManageTemplates extends ComfyDialog {
}, },
onclick: (e) => { onclick: (e) => {
nameInput.value = ""; nameInput.value = "";
e.target.style.display = "none"; e.target.parentElement.style.display = "none";
e.target.previousElementSibling.style.display = "none"; e.target.parentElement.previousElementSibling.style.display = "none";
}, },
}), }),
]
),
]; ];
}) })
) )
@ -164,7 +264,6 @@ app.registerExtension({
}, },
})); }));
if (subItems.length) {
subItems.push(null, { subItems.push(null, {
content: "Manage", content: "Manage",
callback: () => manage.show(), callback: () => manage.show(),
@ -176,7 +275,6 @@ app.registerExtension({
options: subItems, options: subItems,
}, },
}); });
}
return options; return options;
}; };

44
web/scripts/app.js

@ -1416,6 +1416,43 @@ export class ComfyApp {
} }
} }
loadTemplateData(templateData) {
if (!templateData?.templates) {
return;
}
const old = localStorage.getItem("litegrapheditor_clipboard");
var maxY, nodeBottom, node;
for (const template of templateData.templates) {
if (!template?.data) {
continue;
}
localStorage.setItem("litegrapheditor_clipboard", template.data);
app.canvas.pasteFromClipboard();
// Move mouse position down to paste the next template below
maxY = false;
for (const i in app.canvas.selected_nodes) {
node = app.canvas.selected_nodes[i];
nodeBottom = node.pos[1] + node.size[1];
if (maxY === false || nodeBottom > maxY) {
maxY = nodeBottom;
}
}
app.canvas.graph_mouse[1] = maxY + 50;
}
localStorage.setItem("litegrapheditor_clipboard", old);
}
/** /**
* Populates the graph with the specified workflow data * Populates the graph with the specified workflow data
* @param {*} graphData A serialized graph object * @param {*} graphData A serialized graph object
@ -1756,7 +1793,12 @@ export class ComfyApp {
} else if (file.type === "application/json" || file.name?.endsWith(".json")) { } else if (file.type === "application/json" || file.name?.endsWith(".json")) {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = () => { reader.onload = () => {
this.loadGraphData(JSON.parse(reader.result)); var jsonContent = JSON.parse(reader.result);
if (jsonContent?.templates) {
this.loadTemplateData(jsonContent);
} else {
this.loadGraphData(jsonContent);
}
}; };
reader.readAsText(file); reader.readAsText(file);
} else if (file.name?.endsWith(".latent") || file.name?.endsWith(".safetensors")) { } else if (file.name?.endsWith(".latent") || file.name?.endsWith(".safetensors")) {

Loading…
Cancel
Save