Skip to content

Commit

Permalink
Merge branch 'templates-export-import' of https://github.com/jn-jairo…
Browse files Browse the repository at this point in the history
  • Loading branch information
comfyanonymous committed Oct 21, 2023
2 parents 77c8933 + 484bfe4 commit 8d50f08
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 26 deletions.
148 changes: 123 additions & 25 deletions web/extensions/core/nodeTemplates.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ class ManageTemplates extends ComfyDialog {
super();
this.element.classList.add("comfy-manage-templates");
this.templates = this.load();

this.importInput = $el("input", {
type: "file",
accept: ".json",
multiple: true,
style: {display: "none"},
parent: document.body,
onchange: () => this.importAll(),
});
}

createButtons() {
Expand All @@ -34,6 +43,22 @@ class ManageTemplates extends ComfyDialog {
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;
}

Expand Down Expand Up @@ -69,6 +94,52 @@ class ManageTemplates extends ComfyDialog {
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 list of template names + delete button
super.show(
Expand Down Expand Up @@ -97,19 +168,48 @@ class ManageTemplates extends ComfyDialog {
}),
]
),
$el("button", {
textContent: "Delete",
style: {
fontSize: "12px",
color: "red",
fontWeight: "normal",
},
onclick: (e) => {
nameInput.value = "";
e.target.style.display = "none";
e.target.previousElementSibling.style.display = "none";
},
}),
$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", {
textContent: "Delete",
style: {
fontSize: "12px",
color: "red",
fontWeight: "normal",
},
onclick: (e) => {
nameInput.value = "";
e.target.parentElement.style.display = "none";
e.target.parentElement.previousElementSibling.style.display = "none";
},
}),
]
),
];
})
)
Expand Down Expand Up @@ -164,19 +264,17 @@ app.registerExtension({
},
}));

if (subItems.length) {
subItems.push(null, {
content: "Manage",
callback: () => manage.show(),
});
subItems.push(null, {
content: "Manage",
callback: () => manage.show(),
});

options.push({
content: "Node Templates",
submenu: {
options: subItems,
},
});
}
options.push({
content: "Node Templates",
submenu: {
options: subItems,
},
});

return options;
};
Expand Down
44 changes: 43 additions & 1 deletion web/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
* @param {*} graphData A serialized graph object
Expand Down Expand Up @@ -1756,7 +1793,12 @@ export class ComfyApp {
} else if (file.type === "application/json" || file.name?.endsWith(".json")) {
const reader = new FileReader();
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);
} else if (file.name?.endsWith(".latent") || file.name?.endsWith(".safetensors")) {
Expand Down

0 comments on commit 8d50f08

Please sign in to comment.