@@ -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
|
||||
|
||||
+1
-1
@@ -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"]
|
||||
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
Reference in New Issue
Block a user