- One tree for projects and workflows; clicking goes to the open tab and keeps unsaved changes. - Every save goes to ComfyUI's folder and, for projects with their own folder, to that folder too. - Save button, File menu entries and Ctrl+S in the panel; rename inline, undo, collapse all. - Drag and drop with a tip: no key moves within a project, Ctrl also adds, Shift moves exclusively; drop on the canvas to open. Shift works whether pressed before or during the drag. - Migrates 1.0.x data, including custom roots, without touching the original folders. - Moves are all-or-nothing, deletes never enter linked folders, unusable names are refused, Git never touches ComfyUI's repository, and jobs stay private with --multi-user. - Tested on Windows and Linux with real ComfyUI, on Edge, Chromium and Firefox. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
166 lines
7.7 KiB
HTML
166 lines
7.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Bone-Studio Workflow Manager</title>
|
|
<link rel="stylesheet" href="styles.css" />
|
|
</head>
|
|
<body>
|
|
<header class="topbar">
|
|
<a class="brand" href="https://bone-studio.com" target="_blank" rel="noopener noreferrer"
|
|
data-i18n-title="brand_link_title" title="Go to bone-studio.com">
|
|
<svg class="brand-logo" viewBox="0 0 256 256" role="img" aria-label="Bone-Studio Workflow Manager">
|
|
<circle cx="128" cy="128" r="124" fill="#AC1F23" />
|
|
<text x="128" y="150" text-anchor="middle"
|
|
font-family="Jost, 'Century Gothic', 'Arial Rounded MT Bold', Arial, sans-serif"
|
|
font-weight="700" font-size="62" letter-spacing="-1" fill="#FAF0DC">BS-WM</text>
|
|
</svg>
|
|
</a>
|
|
<nav class="tabs">
|
|
<button class="tab active" data-view="library" data-i18n="tab_library">Library</button>
|
|
<button class="tab" data-view="git" data-i18n="tab_git">Git</button>
|
|
<button class="tab" data-view="settings" data-i18n="tab_settings">Settings</button>
|
|
</nav>
|
|
<div class="header-right">
|
|
<button id="help-btn" class="help-btn" aria-label="Help" data-i18n-title="help_tooltip" title="Help">?</button>
|
|
<div class="lang-toggle" role="group" aria-label="Language" data-i18n-aria="aria_language">
|
|
<button class="lang-btn" data-lang="en">EN</button>
|
|
<button class="lang-btn" data-lang="es">ES</button>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Workflow activo y guardado -->
|
|
<div id="savebar" class="savebar">
|
|
<div class="sb-info">
|
|
<div class="sb-name"><span id="sb-mod" class="mod-dot hidden"></span><span id="sb-name"></span></div>
|
|
<div id="sb-target" class="sb-target"></div>
|
|
</div>
|
|
<button id="sb-save" class="btn primary" data-i18n="btn_save">Save</button>
|
|
<button id="sb-save-project" class="btn" data-i18n="btn_save_project" data-i18n-title="btn_save_project_tip">To project…</button>
|
|
</div>
|
|
|
|
<div id="status" class="status" role="status"></div>
|
|
|
|
<!-- ============ VIEW: LIBRARY ============ -->
|
|
<section id="view-library" class="view lib active">
|
|
<div class="lib-tools">
|
|
<input id="search" type="search" class="grow" data-i18n-ph="ph_search" placeholder="Search workflows…" />
|
|
<button id="btn-collapse" class="btn icon" data-i18n-title="btn_collapse" aria-label="Collapse all"></button>
|
|
<button id="btn-refresh" class="btn icon" data-i18n-title="btn_refresh" aria-label="Refresh">⟳</button>
|
|
</div>
|
|
<div id="tree" class="tree" tabindex="0" role="tree"></div>
|
|
<div id="selbar" class="selbar hidden">
|
|
<span id="sel-count" class="grow"></span>
|
|
<button id="sel-move" class="btn small" data-i18n="ctx_move">Move to…</button>
|
|
<button id="sel-export" class="btn small" data-i18n="ctx_export">Export</button>
|
|
<button id="sel-delete" class="btn small danger" data-i18n="ctx_delete">Delete</button>
|
|
<button id="sel-clear" class="btn small icon" data-i18n-title="btn_clear_selection" aria-label="Clear selection">✕</button>
|
|
</div>
|
|
<div id="exports" class="exports"></div>
|
|
</section>
|
|
|
|
<!-- ============ VIEW: GIT ============ -->
|
|
<section id="view-git" class="view">
|
|
<div id="git-banner" class="banner"></div>
|
|
<div id="git-body">
|
|
<label class="field">
|
|
<span data-i18n="lbl_git_project">Project</span>
|
|
<select id="git-project"></select>
|
|
</label>
|
|
<div id="git-info" class="kv-list"></div>
|
|
<div id="git-status" class="status"></div>
|
|
|
|
<div id="git-actions" class="panel">
|
|
<button id="git-init" class="btn small" data-i18n="btn_git_init">Create repository</button>
|
|
<div id="git-repo-actions">
|
|
<div class="row">
|
|
<input id="git-commit-msg" type="text" class="grow" data-i18n-ph="ph_commit" placeholder="What changed?" />
|
|
<button id="git-commit" class="btn small primary" data-i18n="btn_git_commit">Commit</button>
|
|
</div>
|
|
<div class="row">
|
|
<button id="git-pull" class="btn small" data-i18n="btn_git_pull">Pull</button>
|
|
<button id="git-push" class="btn small" data-i18n="btn_git_push">Push</button>
|
|
</div>
|
|
<div class="row">
|
|
<input id="git-remote-url" type="text" class="grow" data-i18n-ph="ph_remote" placeholder="Remote URL (https://… or git@…)" />
|
|
<button id="git-remote" class="btn small" data-i18n="btn_git_remote">Set remote</button>
|
|
<button id="git-gh" class="btn small" data-i18n="btn_git_gh">Create on GitHub</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<h3><span data-i18n="h_changes">Pending changes</span> <span id="git-changes-sum" class="muted"></span></h3>
|
|
<div id="git-changes" class="changes"></div>
|
|
</div>
|
|
<div class="panel">
|
|
<h3 data-i18n="h_history">History</h3>
|
|
<div id="git-log" class="changes"></div>
|
|
</div>
|
|
<div id="git-jobs-panel" class="panel hidden">
|
|
<h3 class="row"><span class="grow" data-i18n="h_git_jobs">Git operations</span>
|
|
<button id="git-clear" class="btn small" data-i18n="btn_clear_finished">Clear finished</button></h3>
|
|
<div id="git-jobs"></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ============ VIEW: SETTINGS ============ -->
|
|
<section id="view-settings" class="view">
|
|
<div class="panel">
|
|
<h3 data-i18n="h_view_options">View</h3>
|
|
<label class="field inline"><input id="s-show-linked" type="checkbox" /><span data-i18n="lbl_show_linked">Also list project workflows under "Workflows"</span></label>
|
|
</div>
|
|
<div class="panel">
|
|
<h3 data-i18n="h_storage">Where workflows are saved</h3>
|
|
<p class="muted" data-i18n="storage_desc">Always in ComfyUI's workflows folder. If the project has its own folder, a copy is kept there too.</p>
|
|
<div class="kv"><b id="s-root"></b></div>
|
|
</div>
|
|
<div class="panel">
|
|
<h3 data-i18n="h_db">Projects database</h3>
|
|
<p class="muted" data-i18n="db_desc">A single JSON file. Export it as a backup; import it to restore or merge.</p>
|
|
<div class="kv"><b id="s-db-path"></b></div>
|
|
<div class="row">
|
|
<button id="s-db-export" class="btn small" data-i18n="btn_db_export">Export</button>
|
|
<button id="s-db-import" class="btn small" data-i18n="btn_db_import">Import…</button>
|
|
<label class="field inline"><input id="s-db-merge" type="checkbox" /><span data-i18n="lbl_merge">Merge with current</span></label>
|
|
</div>
|
|
<div id="s-db-status" class="status"></div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Help / documentation -->
|
|
<div id="help-modal" class="modal hidden">
|
|
<div class="modal-card help-card">
|
|
<div class="help-head">
|
|
<div id="help-title" class="modal-title"></div>
|
|
<button id="help-close" class="btn small icon" aria-label="Close" data-i18n-aria="aria_close">✕</button>
|
|
</div>
|
|
<div id="help-body" class="help-body"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Generic modal dialog -->
|
|
<div id="modal" class="modal hidden">
|
|
<form id="modal-form" class="modal-card">
|
|
<div id="modal-title" class="modal-title"></div>
|
|
<div id="modal-body" class="modal-body"></div>
|
|
<div class="modal-actions">
|
|
<button id="modal-cancel" type="button" class="btn" data-i18n="btn_cancel">Cancel</button>
|
|
<button id="modal-ok" type="submit" class="btn primary" data-i18n="btn_accept">Accept</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Tip mientras se arrastra -->
|
|
<div id="drag-tip" class="drag-tip hidden" role="status"></div>
|
|
|
|
<!-- Hidden file input for imports -->
|
|
<input id="file-input" type="file" accept=".json,application/json" style="display:none" multiple />
|
|
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|