Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0952e0fb3 |
@@ -179,6 +179,8 @@ and skips row 2. Each prompt triggers a separate pass through the downstream gra
|
||||
- **Scanning stops at the first empty prompt cell**, so anything below a gap is ignored.
|
||||
- **The sheet is re-read on every run**, so edits you make in the browser are picked up
|
||||
automatically. Add rows or clear status cells and just hit Run again.
|
||||
- **Refresh sheet** is optional — it reports how many prompts are pending without running
|
||||
the graph.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -157,7 +157,8 @@ all. Write `done` next to a prompt in the sheet and the next run skips it; clear
|
||||
the cell and it gets queued again. Scanning stops at the first empty prompt cell.
|
||||
|
||||
The sheet is re-read fresh on every run, so edits you make in the browser are
|
||||
picked up automatically — there is nothing to refresh by hand.
|
||||
always picked up. **Refresh sheet** is optional — it reports how many prompts
|
||||
are pending without having to run the graph.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
@@ -197,3 +198,30 @@ picked up automatically — there is nothing to refresh by hand.
|
||||
|
||||
NODE_CLASS_MAPPINGS = {"SFGoogleSheetPromptQueue": SFGoogleSheetPromptQueue}
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {"SFGoogleSheetPromptQueue": "SF Google Sheet Prompt Queue"}
|
||||
|
||||
|
||||
# --- Server route backing the node's Refresh button ---------------------------
|
||||
|
||||
try:
|
||||
from aiohttp import web
|
||||
from server import PromptServer
|
||||
|
||||
@PromptServer.instance.routes.post("/sf_gsheet/preview")
|
||||
async def _preview(request):
|
||||
body = await request.json()
|
||||
try:
|
||||
rows = fetch_rows(body.get("url", ""), body.get("sheet_gid", "0"))
|
||||
pending, total = scan_rows(
|
||||
rows,
|
||||
col_letter_to_index(body.get("prompt_col", "A")),
|
||||
col_letter_to_index(body.get("status_col", "B")),
|
||||
bool(body.get("skip_first_row", True)),
|
||||
)
|
||||
return web.json_response(
|
||||
{"ok": True, "total": total, "pending": len(pending)}
|
||||
)
|
||||
except Exception as e:
|
||||
return web.json_response({"ok": False, "error": str(e)})
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-sf-nodes"
|
||||
description = "Custom nodes for ComfyUI including LLM Chat with support for Claude, Gemini, and OpenAI models, WaveSpeed AI image/video generation, VertexAI integration, and workflow utilities"
|
||||
version = "1.0.9"
|
||||
version = "1.0.10"
|
||||
license = { file = "LICENSE" }
|
||||
dependencies = [
|
||||
"requests>=2.31.0",
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* SF Google Sheet Prompt Queue — adds a Refresh button that re-reads the sheet
|
||||
* and reports how many prompts are still waiting to run.
|
||||
*/
|
||||
|
||||
import { app } from "../../../scripts/app.js";
|
||||
import { api } from "../../../scripts/api.js";
|
||||
|
||||
const NODE_NAME = "SFGoogleSheetPromptQueue";
|
||||
|
||||
function widgetValue(node, name, fallback) {
|
||||
const widget = node.widgets?.find((w) => w.name === name);
|
||||
return widget ? widget.value : fallback;
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: "Stillfront.GoogleSheetPromptQueue",
|
||||
|
||||
async beforeRegisterNodeDef(nodeType, nodeData) {
|
||||
if (nodeData.name !== NODE_NAME) {
|
||||
return;
|
||||
}
|
||||
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const result = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined;
|
||||
const node = this;
|
||||
|
||||
const status = node.addWidget("text", "", "Press Refresh to read the sheet", () => {});
|
||||
status.disabled = true;
|
||||
status.serialize = false;
|
||||
|
||||
const setStatus = (text) => {
|
||||
status.value = text;
|
||||
node.setDirtyCanvas(true, false);
|
||||
};
|
||||
|
||||
const refreshButton = node.addWidget("button", "Refresh sheet", null, async () => {
|
||||
setStatus("Reading sheet…");
|
||||
try {
|
||||
const response = await api.fetchApi("/sf_gsheet/preview", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
url: widgetValue(node, "url", ""),
|
||||
sheet_gid: widgetValue(node, "sheet_gid", "0"),
|
||||
prompt_col: widgetValue(node, "prompt_col", "A"),
|
||||
status_col: widgetValue(node, "status_col", "B"),
|
||||
skip_first_row: widgetValue(node, "skip_first_row", true),
|
||||
}),
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.ok) {
|
||||
setStatus(`Error: ${data.error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const cap = widgetValue(node, "max_rows", 10);
|
||||
const willSend = Math.min(data.pending, cap);
|
||||
setStatus(
|
||||
data.pending === 0
|
||||
? `Nothing pending — all ${data.total} prompt(s) marked`
|
||||
: `${data.pending} pending of ${data.total} — next run sends ${willSend}`
|
||||
);
|
||||
} catch (e) {
|
||||
setStatus("Could not reach ComfyUI server");
|
||||
}
|
||||
});
|
||||
refreshButton.serialize = false;
|
||||
|
||||
return result;
|
||||
};
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user