1.3.0
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
# noEmbryo Nodes
|
||||
A diverse set of nodes for ComfyUI.
|
||||
- [PromptTermList (1-6)](#prompttermlist-1-6)
|
||||
- [Json Prompt Loader](#json-prompt-loader)
|
||||
- [Resolution Scale](#resolution-scale)
|
||||
- [Regex Text Chopper](#regex-text-chopper)
|
||||
- [Auto Save Workflow](#auto-save-workflow)
|
||||
- [PromptTermList (1-6)](#prompttermlist-1-6)
|
||||
|
||||
You can access them through "Add node > noEmbryo" submenu.
|
||||
|
||||
@@ -11,46 +12,41 @@ You can access them through "Add node > noEmbryo" submenu.
|
||||
[![License: MIT][MIT]](LICENSE)
|
||||
|
||||
---
|
||||
## PromptTermList (1-6)
|
||||
These are some nodes that help with the creation of Prompts inside [ComfyUI](https://github.com/comfyanonymous/ComfyUI).
|
||||
## Json Prompt Loader
|
||||

|
||||
|
||||
A node that can load a `.json` file with `item:prompt` pairs and outputs the selected item's prompt, while combining it with a custom prompt.
|
||||
It can load `.json` files from any directory, not just the node's directory.
|
||||
For the custom text integration, there is a variable (can be specified by the user), that can be used in the item's prompt text to insert the custom text anywhere in the body of the prompt.
|
||||
|
||||

|
||||
|
||||
<!-- <p align="center">
|
||||
<a href="https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/Screen2.png">
|
||||
<img src="https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/Screen2.png" height="180"></a>
|
||||
</p> -->
|
||||
|
||||
### Usage
|
||||
Every one of the 6 nodes have a different `json` file that stores its Prompt Terms in "label"/"value" pairs.
|
||||
The "label" part is what we see at the node's dropdown menu, and the "value" part is what it produces at its `Term` output when we run a generation job.
|
||||
|
||||
These `json` files are located inside the `TermLists` directory, in the node's folder.
|
||||
There are two ways to add a new term.
|
||||
- From within ComfyUI:
|
||||
- Connect a text box to the node's `text` input.
|
||||
- Write the "label"/"value" part in the box using the following format:
|
||||
```
|
||||
label=Descriptive text
|
||||
value=masterpiece, artful and cozy
|
||||
```
|
||||
- Enable the `store_input` switch.
|
||||
- Run a generation job.
|
||||
- Refresh the page.
|
||||
- Manually:
|
||||
- Just open the `json` file and add/remove/change entries.
|
||||
|
||||
Ofcourse we must be very careful with this, to keep the `json` format of labels/values (with the appropriate commas), otherwise the file will not be parsed.
|
||||
|
||||
This `text` input is also useful if we want to manually add something *after* our term, or as the *only* term if we select the `None` label of the dropdown.
|
||||
The `strength` value is changing the impact of the term by using the parenthesis format like this: `(a great term:1.3)`
|
||||
|
||||
We can delete a term by sending an empty value to the `text` input like this:
|
||||
```
|
||||
label=The label to be deleted
|
||||
value=
|
||||
```
|
||||
- **UI controls**
|
||||
- **json_path** is the path to the `.json` file.
|
||||
It can be an absolute path of your hard drive, or a relative path to the ComfyUI's installation directory.
|
||||
- **selected_item** selects one of the `.json` file's items (prompts).
|
||||
- **variable** is the variable that will be used to insert the custom text into the item's prompt text.
|
||||
- **custom_text** is the custom text that will be inserted into the item's prompt text.
|
||||
- **Advanced Usage**
|
||||

|
||||
- **Adding new items**
|
||||
To add a new item, we have to write it in the `custom_text` input, using the following format:
|
||||
```
|
||||
item=The prompt's title/keyword
|
||||
value=The prompt's text, including our variable
|
||||
```
|
||||
- **Updating items**
|
||||
To update an item, we use the same method, just write the specific item we want to update.
|
||||
```
|
||||
item=An existing title/keyword
|
||||
value=The new prompt's text, including our variable
|
||||
```
|
||||
- **Deleting items**
|
||||
To delete an item, we use the same format, but we just leave the `value` empty.
|
||||
```
|
||||
item=An existing title/keyword
|
||||
value=
|
||||
```
|
||||
All of these methods will update the `.json` file, and the node will output a message about the success or failure of the operation.
|
||||
We can also load an empty `.json`file and use this method to populate it.
|
||||
---
|
||||
## Resolution Scale
|
||||

|
||||
@@ -77,6 +73,46 @@ This node can save the current workflow to a `.json` file, every time a generati
|
||||
- **status** outputs a text with the status of the saving process (the path of the saved file, or an error message).
|
||||
- **✳️trigger** is a dummy output that's used to trigger the saving process, even if nothing is connected to the node.
|
||||
|
||||
---
|
||||
## PromptTermList 1-6
|
||||
|
||||
<u>**The PromptTermList nodes are now obsolete, and can mostly be replaced by the [Json Prompt Loader](#json-prompt-loader) node.
|
||||
I won't remove them for compatibility reasons, but I would recommend using the [JsonPromptLoader](#json-prompt-loader) node instead.**</u>
|
||||
|
||||

|
||||
These are some nodes that help with the creation of Prompts inside [ComfyUI](https://github.com/comfyanonymous/ComfyUI).
|
||||
|
||||
### Usage
|
||||
|
||||
Every one of these 6 nodes have a different `json` file that stores its Prompt Terms in "label"/"value" pairs.
|
||||
The "label" part is what we see at the node's dropdown menu, and the "value" part is what it produces at its `Term` output when we run a generation job.
|
||||
|
||||
These `json` files are located inside the `TermLists` directory, in the node's folder.
|
||||
There are two ways to add a new term.
|
||||
- From within ComfyUI:
|
||||
- Connect a text box to the node's `text` input.
|
||||
- Write the "label"/"value" part in the box using the following format:
|
||||
```
|
||||
label=Descriptive text
|
||||
value=masterpiece, artful and cozy
|
||||
```
|
||||
- Enable the `store_input` switch.
|
||||
- Run a generation job.
|
||||
- Refresh the page.
|
||||
- Manually:
|
||||
- Just open the `json` file and add/remove/change entries.
|
||||
|
||||
Ofcourse we must be very careful with this, to keep the `json` format of labels/values (with the appropriate commas), otherwise the file will not be parsed.
|
||||
|
||||
This `text` input is also useful if we want to manually add something *after* our term, or as the *only* term if we select the `None` label of the dropdown.
|
||||
The `strength` value is changing the impact of the term by using the parenthesis format like this: `(a great term:1.3)`
|
||||
|
||||
We can delete a term by sending an empty value to the `text` input like this:
|
||||
```
|
||||
label=The label to be deleted
|
||||
value=
|
||||
```
|
||||
|
||||
---
|
||||
## Installation
|
||||
* Use the ComfyUI Manager
|
||||
@@ -85,6 +121,6 @@ This node can save the current workflow to a `.json` file, every time a generati
|
||||
* git clone https://github.com/noembryo/ComfyUI-noEmbryo.git
|
||||
* Restart ComfyUI
|
||||
|
||||
|
||||
---
|
||||
[Python]:https://img.shields.io/badge/Made%20with-Python-1f425f.svg
|
||||
[MIT]:https://img.shields.io/badge/License-MIT-green.svg
|
||||
|
||||
+41
-6
@@ -10,18 +10,23 @@ import os
|
||||
import io
|
||||
from os.path import isfile, join, isdir
|
||||
import importlib
|
||||
from .nodes import LISTS_PATH, __author__, __version__
|
||||
from aiohttp import web
|
||||
from server import PromptServer
|
||||
|
||||
from .nodes import LISTS_PATH, JsonPromptLoader, __author__, __version__
|
||||
|
||||
print(f"### Loading: {__author__} nodes v{__version__}")
|
||||
|
||||
WEB_DIRECTORY = "./web/js"
|
||||
|
||||
NODE_CLASS_MAPPINGS = {}
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||
|
||||
node_list = [
|
||||
"nodes",
|
||||
# "load_image_from_dir",
|
||||
]
|
||||
|
||||
NODE_CLASS_MAPPINGS = {}
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||
|
||||
for module_name in node_list:
|
||||
imported_module = importlib.import_module(".{}".format(module_name), __name__)
|
||||
|
||||
@@ -35,9 +40,39 @@ for i in range(6): # create TermList1-6 if not exists
|
||||
file_name = join(LISTS_PATH, "TermList{}.json".format(i + 1))
|
||||
if not isfile(file_name):
|
||||
with io.open(file_name, "w+", encoding="utf-8", newline="\n") as f:
|
||||
# noinspection PyTypeChecker
|
||||
json.dump({"None": ""}, f, indent=4)
|
||||
|
||||
WEB_DIRECTORY = "./web"
|
||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS",
|
||||
"WEB_DIRECTORY",
|
||||
"WEB_DIRECTORY", "setup",
|
||||
]
|
||||
|
||||
# Add custom route for JSON loading
|
||||
try:
|
||||
@PromptServer.instance.routes.get('/noembryo/get_json')
|
||||
async def get_json(request):
|
||||
path = request.query.get('path', '')
|
||||
if path:
|
||||
try:
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
JsonPromptLoader.load_data(path) # Update Python data
|
||||
return web.json_response(data)
|
||||
except Exception as e:
|
||||
return web.json_response({"error": str(e)})
|
||||
return web.json_response({})
|
||||
except ImportError:
|
||||
pass # Server not available
|
||||
|
||||
# def setup():
|
||||
# @PromptServer.instance.routes.get('/noembryo/get_json')
|
||||
# async def get_json(request):
|
||||
# path = request.query.get('path', '')
|
||||
# if path:
|
||||
# try:
|
||||
# with open(path, 'r', encoding='utf-8') as f:
|
||||
# data = json.load(f)
|
||||
# return web.json_response(data)
|
||||
# except Exception as e:
|
||||
# return web.json_response({"error": str(e)})
|
||||
# return web.json_response({})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import os, re, io
|
||||
import json
|
||||
from os.path import realpath, join, dirname, isabs
|
||||
from os.path import realpath, join, dirname, isabs, splitext, basename
|
||||
from datetime import datetime
|
||||
import folder_paths
|
||||
|
||||
@@ -12,12 +12,133 @@ MANIFEST = {"name": "noEmbryo Nodes",
|
||||
"license": "MIT",
|
||||
}
|
||||
__author__ = "noEmbryo"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.3.0"
|
||||
|
||||
# LISTS_PATH = realpath("./custom_nodes/ComfyUI-noEmbryo/TermLists/")
|
||||
LISTS_PATH = join(dirname(realpath(__file__)), "TermLists")
|
||||
|
||||
|
||||
class JsonPromptLoader:
|
||||
data = {}
|
||||
data_labels = ["None"]
|
||||
json_path = ""
|
||||
|
||||
def __init__(self):
|
||||
super(JsonPromptLoader, self).__init__()
|
||||
self.name = type(self).__name__
|
||||
|
||||
@classmethod
|
||||
def load_data(cls, json_path):
|
||||
cls.json_path = ""
|
||||
if not splitext(json_path)[1].lower() == ".json":
|
||||
return
|
||||
if json_path:
|
||||
try:
|
||||
with io.open(json_path, mode="r", encoding="utf-8") as f:
|
||||
cls.data.clear()
|
||||
cls.data["None"] = ""
|
||||
cls.data.update(json.load(f))
|
||||
cls.data_labels[:] = list(cls.data.keys())
|
||||
cls.json_path = json_path
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
cls.data.clear()
|
||||
cls.data.update({})
|
||||
cls.data_labels[:] = ["None"]
|
||||
if os.stat(json_path).st_size == 0: # empty json files
|
||||
cls.json_path = json_path
|
||||
else: # no path given
|
||||
cls.data.clear()
|
||||
cls.data.update({})
|
||||
cls.data_labels[:] = ["None"]
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {"required": {"json_path": ("STRING", {"default": "",
|
||||
"tooltip": "Path to a JSON file with "
|
||||
"`item`:`prompt` pairs"}),
|
||||
"selected_item": (cls.data_labels, cls.data), # Options will be updated by JS
|
||||
"variable": ("STRING", {"default": "{subject}",
|
||||
"tooltip": "If this variable exists in the selected item's prompt,\n"
|
||||
"it will be replaced with the custom_prompt text"}),
|
||||
"custom_prompt": ("STRING", {"multiline": True, "default": "",
|
||||
"tooltip": "Text to replace the variable in the selected prompt.\n"
|
||||
"You can also use it to save a new item or update an existing one.\n"
|
||||
"To do that you should use the following format:\n"
|
||||
"item=... ...\n"
|
||||
"value=.... .... ...\n"
|
||||
"To delete an existing item, use an empty value:\n"
|
||||
"item=... ...\n"
|
||||
"value="}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("Prompt",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "noEmbryo"
|
||||
|
||||
def run(self, json_path, selected_item, variable, custom_prompt):
|
||||
self.load_data(json_path)
|
||||
if custom_prompt:
|
||||
message = self.edit_data(custom_prompt)
|
||||
if message: # if the custom_prompt was saved successfully
|
||||
return (message,)
|
||||
if selected_item in self.data and selected_item != "None":
|
||||
prompt = self.data[selected_item]
|
||||
# if variable and "{" + variable + "}" in prompt:
|
||||
if variable and variable in prompt:
|
||||
prompt = prompt.replace(variable, custom_prompt)
|
||||
# prompt = prompt.replace("{" + variable + "}", custom_prompt)
|
||||
elif custom_prompt:
|
||||
prompt += " " + custom_prompt
|
||||
else:
|
||||
prompt = custom_prompt
|
||||
return (prompt,)
|
||||
|
||||
def edit_data(self, text):
|
||||
""" Parses the json values from the custom_prompt and changes the json file
|
||||
|
||||
:type text: str
|
||||
:param text: The custom_prompt text
|
||||
"""
|
||||
lines = text.splitlines()
|
||||
if len(lines) >= 2:
|
||||
if all((lines[0].startswith("item="), lines[1].startswith("value="))):
|
||||
if not self.json_path:
|
||||
return False
|
||||
item = lines[0][5:]
|
||||
lines_txt = "\n".join(lines[1:])
|
||||
value = lines_txt[6:]
|
||||
filename = basename(self.json_path)
|
||||
if item == "None": # cannot change None
|
||||
msg = f'{filename}: The item "{item}" cannot be changed!'
|
||||
return msg
|
||||
if not value: # delete item
|
||||
if item in self.data:
|
||||
del self.data[item]
|
||||
msg = f'{filename}: The item "{item}" was deleted!'
|
||||
self.save_json_file()
|
||||
else:
|
||||
msg = f'{filename}: The item "{item}" does not exist!'
|
||||
else: # save/update item
|
||||
if item in self.data:
|
||||
msg = f'{filename}: The item "{item}" is updated!'
|
||||
else:
|
||||
msg = f'{filename}: The item "{item}" is added!'
|
||||
self.data[item] = value
|
||||
self.save_json_file()
|
||||
return msg
|
||||
return False
|
||||
|
||||
def save_json_file(self):
|
||||
with io.open(self.json_path, mode="w", encoding="utf-8") as f:
|
||||
data = self.data.copy()
|
||||
if "None" in data:
|
||||
del data["None"]
|
||||
# noinspection PyTypeChecker
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
|
||||
class PromptTermList:
|
||||
idx = 0
|
||||
data = {"None": ""}
|
||||
@@ -50,7 +171,7 @@ class PromptTermList:
|
||||
cls.load_data_from_json(list_path)
|
||||
term_list = [i[0] for i in cls.data_labels]
|
||||
# noinspection SqlNoDataSourceInspection,SqlResolve
|
||||
return {"required": {"terms": (term_list,{"tooltip": "Select a term from the "
|
||||
return {"required": {"terms": (term_list,{"tooltip": "Choose a term from the "
|
||||
"TermList with the "
|
||||
"corresponding number"}), },
|
||||
"optional": {"text": ("STRING", {"forceInput": True,
|
||||
@@ -115,7 +236,8 @@ class PromptTermList:
|
||||
self.data[label] = value
|
||||
with io.open(join(LISTS_PATH, "TermList{}.json".format(self.idx)), mode="w",
|
||||
encoding="utf-8") as f:
|
||||
json.dump(self.data, f, indent=4)
|
||||
# noinspection PyTypeChecker
|
||||
json.dump(self.data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("Term",)
|
||||
@@ -340,6 +462,7 @@ class AutoSaveWorkflow:
|
||||
|
||||
# Save workflow to JSON
|
||||
with open(save_path, "w", encoding="utf-8") as f:
|
||||
# noinspection PyTypeChecker
|
||||
json.dump(workflow_data, f, indent=4)
|
||||
|
||||
status = f"Workflow saved to: {save_path}"
|
||||
@@ -349,27 +472,26 @@ class AutoSaveWorkflow:
|
||||
return (status,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {"PromptTermList1": PromptTermList1,
|
||||
NODE_CLASS_MAPPINGS = {f"JsonPromptLoader -{__author__}": JsonPromptLoader,
|
||||
f"Resolution Scale -{__author__}": ResolutionScale,
|
||||
f"Regex Text Chopper -{__author__}": RegExTextChopper,
|
||||
f"Auto Save Workflow -{__author__}": AutoSaveWorkflow,
|
||||
"PromptTermList1": PromptTermList1,
|
||||
"PromptTermList2": PromptTermList2,
|
||||
"PromptTermList3": PromptTermList3,
|
||||
"PromptTermList4": PromptTermList4,
|
||||
"PromptTermList5": PromptTermList5,
|
||||
"PromptTermList6": PromptTermList6,
|
||||
f"Resolution Scale /{__author__}": ResolutionScale,
|
||||
f"Regex Text Chopper /{__author__}": RegExTextChopper,
|
||||
f"Auto Save Workflow /{__author__}": AutoSaveWorkflow
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {"PromptTermList1": f"PromptTermList 1 /{__author__}",
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {f"JsonPromptLoader -{__author__}": f"Json Prompt Loader /{__author__}",
|
||||
f"Resolution Scale -{__author__}": f"Resolution Scale /{__author__}",
|
||||
f"Regex Text Chopper -{__author__}": f"Regex Text Chopper /{__author__}",
|
||||
f"Auto Save Workflow -{__author__}": f"Auto Save Workflow /{__author__}",
|
||||
"PromptTermList1": f"PromptTermList 1 /{__author__}",
|
||||
"PromptTermList2": f"PromptTermList 2 /{__author__}",
|
||||
"PromptTermList3": f"PromptTermList 3 /{__author__}",
|
||||
"PromptTermList4": f"PromptTermList 4 /{__author__}",
|
||||
"PromptTermList5": f"PromptTermList 5 /{__author__}",
|
||||
"PromptTermList6": f"PromptTermList 6 /{__author__}",
|
||||
f"Resolution Scale /{__author__}":
|
||||
f"Resolution Scale /{__author__}",
|
||||
f"Regex Text Chopper /{__author__}":
|
||||
f"Regex Text Chopper /{__author__}",
|
||||
f"Auto Save Workflow /{__author__}":
|
||||
f"Auto Save Workflow /{__author__}",
|
||||
}
|
||||
|
||||
+5
-4
@@ -1,13 +1,14 @@
|
||||
[project]
|
||||
name = "comfyui-noembryo"
|
||||
name = "noEmbryo"
|
||||
description = """
|
||||
A collection of nodes for ComyUI.
|
||||
* "PromptTermList (1-6)" nodes to help with the creation of Prompts.
|
||||
* "JsonPromptLoader" is a node that enhances a propt using a .json file with `item:prompt` pairs.
|
||||
* "Resolution Scale" is a node that resizes an image using pixels or scale factor.
|
||||
* "Regex Text Chopper" is a node that cuts text based on regex.
|
||||
* "Auto Save Workflow" can save the current workflow to a .json file automatically.
|
||||
* "PromptTermList (1-6)" nodes to help with the creation of Prompts.
|
||||
"""
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
license = {text = "MIT License"}
|
||||
|
||||
[project.urls]
|
||||
@@ -16,5 +17,5 @@ Repository = "https://github.com/noembryo/ComfyUI-noEmbryo"
|
||||
|
||||
[tool.comfy]
|
||||
PublisherId = "noembryo"
|
||||
DisplayName = "ComfyUI-noEmbryo"
|
||||
DisplayName = "noEmbryo"
|
||||
Icon = "https://iili.io/JmSdmAJ.png"
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import { ComfyApp, app } from "../../scripts/app.js";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Comfy.noEmbryo",
|
||||
|
||||
nodeCreated(node, app) {
|
||||
console.log("nodeCreated", node.comfyClass);
|
||||
|
||||
// if(node.comfyClass === "LoadImage From Dir /noEmbryo") {
|
||||
//
|
||||
// // async function listAllFiles(dirHandle) {
|
||||
// // const files = [];
|
||||
// // for await (let [name, handle] of dirHandle) {
|
||||
// // const {kind} = handle;
|
||||
// // {
|
||||
// // files.push({name, handle, kind});
|
||||
// // }
|
||||
// // }
|
||||
// // return files;
|
||||
// // }
|
||||
// //
|
||||
// // async function onClickHandler(e) {
|
||||
// // try {
|
||||
// // const directoryHandle = await window.showDirectoryPicker()
|
||||
// // console.log(directoryHandle)
|
||||
// // const data = await listAllFiles(directoryHandle);
|
||||
// // // console.log('files', files);
|
||||
// // return data;
|
||||
// // }catch(e) {
|
||||
// // console.log(e);
|
||||
// // }
|
||||
// // }
|
||||
//
|
||||
// let path_i = 0;
|
||||
// let images_i = 1;
|
||||
// node._value = "None";
|
||||
//
|
||||
// Object.defineProperty(node.widgets[path_i], "value", {
|
||||
// set: (value) => {
|
||||
// const stackTrace = new Error().stack;
|
||||
// if(stackTrace.includes('inner_value_change')) {
|
||||
// if(value !== "") {
|
||||
// console.log(node.widgets[images_i])
|
||||
// let values = node.widgets[images_i].options.values;
|
||||
// console.log(values)
|
||||
// node.widgets[images_i].value = values[1];
|
||||
// // if(node.widgets_values) {
|
||||
// // node.widgets_values[images_i] = node.widgets[path_i].value;
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// node._value = value;
|
||||
// },
|
||||
// get: () => {
|
||||
// return node._value;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
if(node.comfyClass === "JsonPromptLoader -noEmbryo") {
|
||||
console.log('Setting up JsonPromptLoader');
|
||||
let json_path_i = 0;
|
||||
let selected_title_i = 1;
|
||||
const originalCallback = node.widgets[json_path_i].callback;
|
||||
node.widgets[json_path_i].callback = async (value) => {
|
||||
// console.log('Callback called with path:', value);
|
||||
if(originalCallback) originalCallback(value);
|
||||
if(value) {
|
||||
try {
|
||||
const url = '/noembryo/get_json?path=' + encodeURIComponent(value);
|
||||
// console.log('Fetching:', url);
|
||||
const response = await fetch(url);
|
||||
// console.log('Response status:', response.status);
|
||||
const data = await response.json();
|
||||
// console.log('Data:', data);
|
||||
if(data.error) {
|
||||
console.log('Error:', data.error);
|
||||
node.widgets[selected_title_i].options.values = ["None"];
|
||||
node.widgets[selected_title_i].value = "None";
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
} else {
|
||||
const titles = ["None", ...Object.keys(data)];
|
||||
// console.log('Titles:', titles);
|
||||
node.widgets[selected_title_i].options.values = titles;
|
||||
const currentValue = node.widgets[selected_title_i].value;
|
||||
if (titles.includes(currentValue)) {
|
||||
node.widgets[selected_title_i].value = currentValue;
|
||||
} else {
|
||||
node.widgets[selected_title_i].value = "None";
|
||||
}
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Error loading JSON:', e);
|
||||
node.widgets[selected_title_i].options.values = ["None"];
|
||||
node.widgets[selected_title_i].value = "None";
|
||||
}
|
||||
} else {
|
||||
node.widgets[selected_title_i].options.values = ["None"];
|
||||
node.widgets[selected_title_i].value = "None";
|
||||
}
|
||||
};
|
||||
// Trigger callback if path is already set (e.g., from loaded workflow)
|
||||
setTimeout(() => {
|
||||
if(node.widgets[json_path_i].value) {
|
||||
node.widgets[json_path_i].callback(node.widgets[json_path_i].value);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user