Files
CosmicLaca-ComfyUI_Primere_…/front_end/primere_promptsaver.js
T

304 lines
13 KiB
JavaScript

import { app } from "/scripts/app.js";
import { api } from "/scripts/api.js";
import { applyPrimereButtonStyle, showToast } from "./frontend_helper.js";
let PrompteventListenerInit = false;
const validClasses = ['PrimerePrompt'];
let PositivePrompt = '';
let NegativePrompt = '';
let SubPath = '';
let Model = 'None';
let Orientation = 'None';
let PromptData = {};
function isVisible(element) {
return !!(element && element.offsetParent !== null);
}
function setVisible(element, visible) {
if (element) {
element.style.display = visible ? '' : 'none';
}
}
function appendOption(selectElement, value, text, selected = false) {
if (!selectElement) {
return;
}
const option = document.createElement('option');
option.value = value;
option.textContent = text;
option.selected = selected;
selectElement.appendChild(option);
}
app.registerExtension({
name: "Primere.PromptSaver",
async beforeRegisterNodeDef(nodeType, nodeData, app) { // 0
if (validClasses.includes(nodeData.name)) {
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function () {
onNodeCreated ? onNodeCreated.apply(this, []) : undefined;
PrimerePromptSaverWidget.apply(this, [this, 'PrimerePromptSaver']);
}
}
},
});
async function PrimerePromptSaverWidget(node, inputName) {
if (inputName == 'PrimerePromptSaver') {
node.name = inputName;
const widget = {
type: "preview_saver_widget",
name: `w${inputName}`,
callback: () => {
},
};
const saveBtn = node.addWidget("button", '💾 Save prompt to file...', null, () => {
node.PromptSaver = new PromptSaver(node);
});
applyPrimereButtonStyle(saveBtn);
LoadedNode = node;
return {widget: widget};
}
}
class PromptSaver {
constructor(node) {
if (PrompteventListenerInit == false) {
PromptModalHandler();
}
function PromptModalHandler() {
PrompteventListenerInit = true;
PromptData['replace'] = 0;
document.body.addEventListener('click', async function (event) {
const promptmodal = document.getElementById("primere_promptsaver_modal");
if (!promptmodal) {
return;
}
if (event.target.closest('div#primere_promptsaver_modal button.promptmodal-closer')) {
promptmodal.setAttribute('style', 'display: none; width: 30%; height: 60%;');
return;
}
if (!event.target.closest('div#primere_promptsaver_modal button.prompt_saver_button')) {
return;
}
PromptData['prompt'] = promptmodal.querySelector('textarea[name="positive_prompt"]')?.value ?? '';
PromptData['negative_prompt'] = promptmodal.querySelector('textarea[name="negative_prompt"]')?.value ?? '';
PromptData['preferred_model'] = promptmodal.querySelector('input[name="model"]')?.value ?? '';
PromptData['preferred_orientation'] = promptmodal.querySelector('input[name="orientation"]')?.value ?? '';
const promptNameInput = promptmodal.querySelector('input#prompt_name');
const promptNameSelect = promptmodal.querySelector('select#name');
const promptPathInput = promptmodal.querySelector('input#prompt_path');
const promptPathSelect = promptmodal.querySelector('select#preferred_subpath');
if (isVisible(promptNameInput)) {
PromptData['replace'] = 0;
PromptData['name'] = promptNameInput?.value ?? '';
const promptNameLower = PromptData['name'].toLowerCase();
const optionExists = Array.from(promptNameSelect?.options ?? []).some((option) => option.value.toLowerCase() === promptNameLower);
if (optionExists && PromptData['name'].length > 0) {
if (confirm('The [' + PromptData['name'] + '] prompt already exist. Replace existing prompt by this name?')) {
PromptData['replace'] = 1;
} else {
return false;
}
}
} else {
PromptData['replace'] = 1;
PromptData['name'] = promptNameSelect?.value ?? '';
}
if (isVisible(promptPathInput)) {
PromptData['preferred_subpath'] = promptPathInput?.value ?? '';
} else {
PromptData['preferred_subpath'] = promptPathSelect?.value ?? '';
}
if (PromptData['prompt'].length < 3 || PromptData['name'].length < 1) {
showToast('error', 'Required data missing...');
return false;
}
const isSaved = await savePromptData('stylecsv', 'styles', 'csv', JSON.stringify(PromptData));
if (isSaved == false) {
showToast('error', 'Cannot save new prompt to CSV file.');
} else {
showToast('success', 'New prompt: [' + PromptData['name'] + '] added to CSV file.');
promptmodal.setAttribute('style', 'display: none; width: 30%; height: 60%;');
}
});
document.body.addEventListener('change', function (event) {
const promptmodal = document.getElementById("primere_promptsaver_modal");
if (!promptmodal) {
return;
}
const nameSelect = event.target.closest('div#primere_promptsaver_modal select#name');
if (nameSelect) {
const promptNameInput = promptmodal.querySelector('input#prompt_name');
const replaceWarning = promptmodal.querySelector('span.prompt_replace_warning');
if (nameSelect.value == '') {
setVisible(promptNameInput, true);
setVisible(replaceWarning, false);
} else {
setVisible(promptNameInput, false);
if (promptNameInput) {
promptNameInput.value = '';
}
setVisible(replaceWarning, true);
}
return;
}
const subpathSelect = event.target.closest('div#primere_promptsaver_modal select#preferred_subpath');
if (subpathSelect) {
const promptPathInput = promptmodal.querySelector('input#prompt_path');
if (subpathSelect.value == '') {
setVisible(promptPathInput, true);
} else {
setVisible(promptPathInput, false);
if (promptPathInput) {
promptPathInput.value = '';
}
}
}
});
}
for (var px = 0; px < node.widgets.length; ++px) {
if (node.widgets[px].name == 'positive_prompt') {
PositivePrompt = node.widgets[px].value;
}
if (node.widgets[px].name == 'negative_prompt') {
NegativePrompt = node.widgets[px].value;
}
if (node.widgets[px].name == 'subpath') {
SubPath = node.widgets[px].value;
}
if (node.widgets[px].name == 'model') {
Model = node.widgets[px].value;
}
if (node.widgets[px].name == 'orientation') {
Orientation = node.widgets[px].value;
}
}
if (PositivePrompt.length < 3) {
showToast('error', '⛔ Positive prompt required...');
return false;
}
setup_promptsaver_modal();
}
}
async function setup_promptsaver_modal() {
var container = null;
var modal = null;
modal = document.getElementById("primere_promptsaver_modal");
if (!modal) {
modal = document.createElement("div");
modal.classList.add("comfy-modal");
modal.setAttribute("id", "primere_promptsaver_modal");
modal.innerHTML = '<div class="promptmodal_header"><div class="prompt_modal_title">Save prompt to external file</div></div>';
let container = document.createElement("div");
container.classList.add("primere-promptsaver-modal-content", "prompt-container");
modal.appendChild(container);
document.body.appendChild(modal);
} else {
const modalTitle = document.querySelector('div#primere_promptsaver_modal div.promptmodal_header .prompt_modal_title');
if (modalTitle) {
modalTitle.textContent = '💾 Save prompt to file...';
}
}
var PromptData = await getPromptData('stylecsv', 'styles', 'csv', ['name', 'preferred_subpath']);
container = modal.getElementsByClassName("prompt-container")[0];
container.innerHTML = "<p></p><label>Prompt name:</label><select name='name' id='name'>";
const promptNameSelect = container.querySelector('select#name');
appendOption(promptNameSelect, '', 'Add new name');
for (const item of PromptData['name']) {
appendOption(promptNameSelect, item, item);
}
container.innerHTML += "<input type='text' name='prompt_name' id='prompt_name' value='' placeholder='Enter new prompt name'>";
container.innerHTML += "<span class='prompt_replace_warning'>This setting will replace the existing prompt by selected name!</span>";
setVisible(container.querySelector('span.prompt_replace_warning'), false);
var category_match = false;
container.innerHTML += "<label>Prompt category (subpath):</label><select name='preferred_subpath' id='preferred_subpath'>";
const promptSubpathSelect = container.querySelector('select#preferred_subpath');
appendOption(promptSubpathSelect, '', 'Add new category');
for (const item of PromptData['preferred_subpath']) {
if (SubPath == item) {
category_match = true;
appendOption(promptSubpathSelect, item, item, true);
} else {
appendOption(promptSubpathSelect, item, item);
}
}
if (category_match == true) {
container.innerHTML += "<input type='text' name='prompt_path' id='prompt_path' value='' placeholder='Enter new prompt category (subpath)'>";
setVisible(container.querySelector('input#prompt_path'), false);
} else {
container.innerHTML += "<input type='text' name='prompt_path' id='prompt_path' value='" + SubPath + "' placeholder='Enter new prompt category (subpath)'>";
}
container.innerHTML += "<label>Positive prompt:</label><textarea name='positive_prompt' rows=4 cols=50>" + PositivePrompt + "</textarea>";
container.innerHTML += "<label>Negative prompt:</label><textarea name='negative_prompt' rows=4 cols=50>" + NegativePrompt + "</textarea>";
container.innerHTML += "<label>Preferred Model:</label><input type='text' name='model' value='" + Model + "' readonly='readonly'>";
container.innerHTML += "<label>Preferred Orientation:</label><input type='text' name='orientation' value='" + Orientation + "' readonly='readonly'>";
container.innerHTML += '<button type="button" class="promptmodal-closer">Close without save</button>';
container.innerHTML += "<button type='button' class='prompt_saver_button'>Save prompt to external CSV file</button>";
modal.setAttribute('style', 'display: block; width: 30%; height: 60%;');
}
// ************************* getPromptData PromptDataResponse
function getPromptData(folder, name, type, keys) {
return new Promise((resolve, reject) => {
api.addEventListener("PromptDataResponse", (event) => resolve(event.detail), true);
postPromptDataList(folder, name, type, keys);
});
}
function postPromptDataList(folder, name, type, keys) {
const body = new FormData();
body.append('folder', folder);
body.append('name', name);
body.append('type', type);
body.append('keys', keys);
api.fetchApi("/primere_prompt_data", {method: "POST", body,});
}
// ************************* savePromptData PromptDataSaveResponse
function savePromptData(folder, name, type, data) {
return new Promise((resolve, reject) => {
api.addEventListener("PromptDataSaveResponse", (event) => resolve(event.detail), true);
postPromptSave(folder, name, type, data);
});
}
function postPromptSave(folder, name, type, data) {
const body = new FormData();
body.append('folder', folder);
body.append('name', name);
body.append('type', type);
body.append('promptdata', data);
api.fetchApi("/primere_prompt_saver", {method: "POST", body,});
}