From 448227c2185d7fe22105f891104722301a8bd9b7 Mon Sep 17 00:00:00 2001 From: Vito Sansevero Date: Tue, 9 Dec 2025 14:11:32 -0800 Subject: [PATCH 1/3] feat(prompt_manager): add top bar button for UI access --- web/prompt_manager.js | 163 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/web/prompt_manager.js b/web/prompt_manager.js index eb35cf7..83f2053 100644 --- a/web/prompt_manager.js +++ b/web/prompt_manager.js @@ -2,9 +2,172 @@ import { app } from "../../scripts/app.js"; +// ============================================================================ +// Top Bar Button Integration (similar to rgthree-comfy approach) +// ============================================================================ + +let pmButtonGroup = null; + +/** + * Create a DOM element with optional attributes and children + * @param {string} tag - HTML tag name + * @param {Object} attrs - Attributes and properties + * @returns {HTMLElement} + */ +function $el(tag, attrs = {}) { + const element = document.createElement(tag); + + for (const [key, value] of Object.entries(attrs)) { + if (key === "children") { + if (Array.isArray(value)) { + value.forEach(child => child && element.appendChild(child)); + } else if (value) { + element.appendChild(value); + } + } else if (key === "child") { + if (value) element.appendChild(value); + } else if (key === "text") { + element.textContent = value; + } else if (key === "html") { + element.innerHTML = value; + } else if (key === "style" && typeof value === "object") { + Object.assign(element.style, value); + } else if (key === "classList") { + element.className = value; + } else if (key.startsWith("on") && typeof value === "function") { + element.addEventListener(key.slice(2).toLowerCase(), value); + } else { + element.setAttribute(key, value); + } + } + + return element; +} + +/** + * Add PromptManager button to the top bar + */ +function addPMTopBarButton() { + // Remove existing button group if present + if (pmButtonGroup?.parentElement) { + pmButtonGroup.parentElement.removeChild(pmButtonGroup); + pmButtonGroup = null; + } + + // Check if app.menu exists (new frontend) + if (!app.menu?.settingsGroup?.element) { + console.log("[PromptManager] New frontend menu not found, trying legacy approach"); + addPMTopBarButtonLegacy(); + return; + } + + // Create button group container + pmButtonGroup = $el("div", { + classList: "comfyui-button-group promptmanager-top-button-group", + style: { + display: "flex", + gap: "4px", + marginRight: "8px", + } + }); + + // Create PM button + const pmButton = $el("button", { + classList: "comfyui-button comfyui-menu-mobile-collapse primary", + title: "PromptManager - Open Admin Dashboard", + style: { + display: "flex", + alignItems: "center", + justifyContent: "center", + padding: "4px 10px", + background: "#14b8a6", + color: "white", + border: "none", + borderRadius: "4px", + fontWeight: "bold", + fontSize: "12px", + cursor: "pointer", + transition: "background 0.2s", + }, + onclick: () => { + window.open("/prompt_manager/admin", "_blank"); + }, + onmouseenter: (e) => { e.target.style.background = "#0d9488"; }, + onmouseleave: (e) => { e.target.style.background = "#14b8a6"; }, + text: "PM" + }); + + pmButtonGroup.appendChild(pmButton); + + // Insert before the settings group + app.menu.settingsGroup.element.before(pmButtonGroup); + console.log("[PromptManager] Top bar button added (new frontend)"); +} + +/** + * Legacy approach for older ComfyUI versions + */ +function addPMTopBarButtonLegacy() { + // Try multiple selectors for different ComfyUI versions + const topBar = document.querySelector(".comfyui-menu") || + document.querySelector(".comfy-menu") || + document.querySelector("#comfy-main-menu"); + + if (!topBar) { + // Retry after a short delay if UI not loaded yet + setTimeout(addPMTopBarButtonLegacy, 500); + return; + } + + // Check if button already exists + if (document.getElementById("pm-toolbar-btn")) { + return; + } + + const btn = document.createElement("button"); + btn.id = "pm-toolbar-btn"; + btn.innerText = "PM"; + btn.title = "Open PromptManager Admin Dashboard"; + + // Teal button styling + btn.style.cssText = ` + margin-left: 8px; + padding: 4px 12px; + background: #14b8a6; + color: white; + border: none; + border-radius: 6px; + font-weight: bold; + font-size: 12px; + cursor: pointer; + transition: background 0.2s; + `; + + btn.onmouseenter = () => btn.style.background = "#0d9488"; + btn.onmouseleave = () => btn.style.background = "#14b8a6"; + + btn.onclick = () => { + window.open("/prompt_manager/admin", "_blank"); + }; + + topBar.appendChild(btn); + console.log("[PromptManager] Toolbar button added (legacy frontend)"); +} + +// ============================================================================ +// Extension Registration +// ============================================================================ + app.registerExtension({ name: "PromptManager.UI", + async setup() { + // Add the top bar button after a short delay to ensure UI is ready + setTimeout(() => { + addPMTopBarButton(); + }, 100); + }, + async beforeRegisterNodeDef(nodeType, nodeData, app) { if (nodeData.name === "PromptManager" || nodeData.name === "PromptManagerText") { console.log(`[PromptManager] Patching node type for custom UI: ${nodeData.name}`); From eb75978da41f8d5ca73bf40390fe2205bd43fc3f Mon Sep 17 00:00:00 2001 From: Vito Sansevero Date: Tue, 9 Dec 2025 14:13:37 -0800 Subject: [PATCH 2/3] docs: Update README with v3.0.26 changelog --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index ec365ce..1f619e9 100644 --- a/README.md +++ b/README.md @@ -824,6 +824,13 @@ MIT License - see LICENSE file for details. ## Changelog +### v3.0.26 (Top Bar Button) + +- **🔘 Top Bar PM Button**: Added a "PM" button to the ComfyUI top bar for quick access to the admin dashboard +- **🚀 No Node Required**: Open PromptManager without having to add the node to your workflow first +- **🎨 Teal Button Design**: Distinctive teal-colored button positioned before the settings gear +- **🔄 Frontend Compatibility**: Works with both new ComfyUI frontend (v1.3.1+) and legacy versions + ### v3.0.25 (Film Strip & QoL Improvements) - **🎞️ Film Strip Preview**: Backported from V2 - thumbnail strip under each prompt showing linked images From 33a66da2f1edc49919fd19f947a786b9e24b162c Mon Sep 17 00:00:00 2001 From: Vito Sansevero Date: Tue, 9 Dec 2025 14:13:44 -0800 Subject: [PATCH 3/3] chore: bump version to 3.0.26 in pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bace6fe..6a1f82d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "promptmanager" description = "A powerful ComfyUI custom node that extends the standard text encoder with persistent prompt storage, advanced search capabilities, and an automatic image gallery system using SQLite." -version = "3.0.25" +version = "3.0.26" license = {file = "LICENSE"} dependencies = ["# Core dependencies for PromptManager", "# Note: Most dependencies are already included with ComfyUI", "# Already included with Python standard library:", "# - sqlite3", "# - hashlib", "# - json", "# - datetime", "# - os", "# - typing", "# - threading", "# - uuid", "# Required for gallery functionality:", "watchdog>=2.1.0 # For file system monitoring", "Pillow>=8.0.0 # For image metadata extraction (usually included with ComfyUI)", "# Optional dependencies for enhanced search functionality:", "# fuzzywuzzy[speedup]>=0.18.0 # For fuzzy string matching (optional)", "# sqlalchemy>=1.4.0 # For advanced ORM features (optional)", "# Development dependencies (optional):", "# pytest>=6.0.0 # For running tests", "# black>=22.0.0 # For code formatting", "# flake8>=4.0.0 # For linting", "# mypy>=0.910 # For type checking"]