Varaverk: arrange mode, folder management, rsync standalone, layout fixes
Scheduler UI: - Arrange mode: drag scripts between orchs and reorder within arrays; right panel shows unassigned script pool; Save Arrangement commits to master.conf - + Folder: named collapsible subfolders for Custom Scripts stored in schedule.json - Rsync children: hide Run/Dry Run/Log/location when orch is ON; show standalone location + cron controls when orch is OFF; cron only fires when both filled - Non-conf-managed children (transcode): toggles now show enabled when orch is on - Right panel height sync: fix ResizeObserver feedback loop via align-self:flex-start on left panel and left.offsetHeight in vvFitRight - How do I use this: updated to cover arrange, folders, rsync standalone, transcode New API endpoints: - board.php, clearlock.php, movescript.php, rawconf.php, readscript.php - reorderarray.php, rsync_standalone.php, savefolders.php run.php / dryrun.php: accept optional --location= arg for standalone rsync calls
This commit is contained in:
@@ -98,21 +98,47 @@
|
||||
|
||||
/* Two-panel layout */
|
||||
#vv-sched-layout { display: flex; gap: 16px; align-items: stretch; }
|
||||
#vv-sched-left { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
|
||||
#vv-sched-left { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-self: flex-start; }
|
||||
#vv-sched-cards { flex: 1; }
|
||||
#vv-sched-right { display: none; flex: 1 1 0; min-width: 0; flex-direction: column; }
|
||||
#vv-sched-right.vv-panel-visible { display: flex; }
|
||||
.vv-log-card { flex: 1; display: flex; flex-direction: column; padding-bottom: 0; }
|
||||
.vv-log-right-pre { max-height: none; overflow-y: auto; }
|
||||
|
||||
/* Mobile: stack vertically, right panel full-width below cards */
|
||||
@media (max-width: 880px) {
|
||||
/* Scheduler stacked layout (narrow viewport) */
|
||||
@media (max-width: 900px) {
|
||||
#vv-sched-layout { flex-direction: column; align-items: stretch; }
|
||||
#vv-sched-left { flex: none; width: 100%; }
|
||||
#vv-sched-right { flex-direction: column; width: 100%; }
|
||||
.vv-log-right-pre { min-height: 260px; max-height: 340px; }
|
||||
}
|
||||
|
||||
/* Plugin settings row (Advanced mode) */
|
||||
.vv-nb-settings { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
||||
padding: 5px 10px; background: #101010; border-bottom: 1px solid #1a1a1a; }
|
||||
|
||||
/* Monitor responsive — 4-column grid at medium width */
|
||||
@media (max-width: 1024px) {
|
||||
#vv-monitor { grid-template-columns: repeat(4, 1fr) !important; }
|
||||
#vv-docker { grid-column: span 4 !important; }
|
||||
}
|
||||
|
||||
/* Phone layout — scheduler row/actions fixes + monitor single-column */
|
||||
@media (max-width: 600px) {
|
||||
/* Allow action buttons to wrap rather than overflow the card */
|
||||
.vv-job-actions { flex-wrap: wrap; padding-left: 0; }
|
||||
/* Kill the inline margin-left:auto that pushes Advanced off-screen */
|
||||
.vv-advanced-toggle { margin-left: 0 !important; width: auto !important; }
|
||||
/* Let the cron input flex rather than hold a fixed 110px */
|
||||
.vv-cron { flex: 1 1 80px; width: auto; min-width: 80px; }
|
||||
/* Slightly tighter label on narrow screens */
|
||||
.vv-job-label { font-size: 14px; }
|
||||
|
||||
/* Monitor single-column */
|
||||
#vv-monitor { grid-template-columns: 1fr !important; }
|
||||
#vv-monitor > .vv-card { grid-column: 1 / -1 !important; }
|
||||
}
|
||||
|
||||
/* Shared footer (Save Schedule left, info right) — same min-height so log card ends level with script cards */
|
||||
.vv-sched-footer { display: flex; align-items: center; gap: 10px;
|
||||
margin-top: 12px; padding: 10px 0; border-top: 1px solid #333;
|
||||
@@ -173,6 +199,17 @@
|
||||
border: 1px solid #333; border-radius: 4px; padding: 10px 12px; resize: none;
|
||||
line-height: 1.5; scroll-behavior: auto; tab-size: 2; width: 100%; box-sizing: border-box; }
|
||||
|
||||
/* Syntax-highlighted conf editor overlay */
|
||||
#vv-editor-wrap { position: relative; display: block; }
|
||||
#vv-hl-overlay { display: none; position: absolute; top: 1px; left: 1px; right: 1px; bottom: 1px;
|
||||
margin: 0; padding: 10px 12px; box-sizing: border-box;
|
||||
font-family: monospace; font-size: 12px; line-height: 1.5; tab-size: 2;
|
||||
white-space: pre-wrap; word-break: break-all; overflow: hidden;
|
||||
pointer-events: none; user-select: none;
|
||||
background: #0d0d0d; border: none; border-radius: 3px; }
|
||||
.vv-editor-hl #vv-hl-overlay { display: block; }
|
||||
.vv-editor-hl #vv-editor-body { color: transparent; caret-color: #ddd; background: transparent; }
|
||||
|
||||
/* Suggestions panel — accordion */
|
||||
#vv-suggestions { overflow-y: auto; }
|
||||
.vv-sug-block { border-bottom: 1px solid #1e1e1e; }
|
||||
@@ -210,6 +247,150 @@
|
||||
.vv-info-divider { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: #444;
|
||||
padding: 10px 12px 4px; border-top: 1px solid #2a2a2a; margin-top: 2px; }
|
||||
|
||||
/* How do I use this — pinned at top of suggestions panel */
|
||||
#vv-how-to-use {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 3;
|
||||
background: #1e1e1e;
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
|
||||
/* Board blocks — Next Runs, Errors, Locks, Partner, Disabled */
|
||||
.vv-board-placeholder { color: #555; font-size: 11px; padding: 3px 0; }
|
||||
|
||||
.vv-hdr-badge { display: inline-block; padding: 1px 7px; border-radius: 10px;
|
||||
font-size: 10px; font-weight: bold; flex-shrink: 0; }
|
||||
.vv-hdr-badge-red { background: #7f0000; color: #ef9a9a; }
|
||||
.vv-hdr-badge-orange { background: #5d2000; color: #ffcc80; }
|
||||
.vv-hdr-badge-gray { background: #2a2a2a; color: #aaa; }
|
||||
|
||||
/* Next Runs */
|
||||
.vv-nextrun-list { display: flex; flex-direction: column; }
|
||||
.vv-nextrun-row { display: flex; align-items: center; gap: 8px; padding: 4px 0;
|
||||
border-bottom: 1px solid #1a1a1a; font-size: 12px; }
|
||||
.vv-nextrun-row:last-child { border-bottom: none; }
|
||||
.vv-nr-label { color: #ccc; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.vv-nr-cron { color: #555; font-family: monospace; font-size: 10px; flex-shrink: 0; }
|
||||
.vv-nr-in { color: #4caf50; font-size: 11px; white-space: nowrap; flex-shrink: 0; }
|
||||
.vv-nr-at { color: #666; font-size: 11px; white-space: nowrap; flex-shrink: 0; }
|
||||
|
||||
/* Errors */
|
||||
.vv-errors-list { display: flex; flex-direction: column; gap: 1px; }
|
||||
.vv-err-row { padding: 5px 0; border-bottom: 1px solid #1a1a1a; }
|
||||
.vv-err-row:last-child { border-bottom: none; }
|
||||
.vv-err-top { display: flex; align-items: baseline; gap: 8px; margin-bottom: 2px; }
|
||||
.vv-err-script { color: #e07070; font-size: 11px; font-weight: bold; }
|
||||
.vv-err-age { color: #555; font-size: 10px; }
|
||||
.vv-err-line { color: #888; font-size: 11px; word-break: break-all; line-height: 1.4; }
|
||||
|
||||
/* Locks */
|
||||
.vv-locks-list { display: flex; flex-direction: column; }
|
||||
.vv-lock-row { display: flex; align-items: center; gap: 8px; padding: 4px 0;
|
||||
border-bottom: 1px solid #1a1a1a; font-size: 12px; }
|
||||
.vv-lock-row:last-child { border-bottom: none; }
|
||||
.vv-lk-name { color: #e8a87c; flex: 1; }
|
||||
.vv-lk-age { color: #777; font-size: 11px; white-space: nowrap; }
|
||||
.vv-lock-clear { font-size: 11px !important; padding: 1px 7px !important;
|
||||
border-color: #b71c1c !important; color: #ef9a9a !important; }
|
||||
.vv-lock-clear:hover { background: #7f0000 !important; color: #fff !important; }
|
||||
|
||||
/* Partner */
|
||||
.vv-partner-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 12px; }
|
||||
.vv-partner-name { color: #ccc; }
|
||||
.vv-partner-detail { color: #666; font-size: 11px; }
|
||||
.vv-partner-down { color: #f44336 !important; }
|
||||
|
||||
/* Disabled scripts */
|
||||
.vv-disabled-list { display: flex; flex-direction: column; gap: 1px; }
|
||||
.vv-disabled-row { display: flex; align-items: center; gap: 8px; padding: 3px 0;
|
||||
border-bottom: 1px solid #1a1a1a; font-size: 12px; }
|
||||
.vv-disabled-row:last-child { border-bottom: none; }
|
||||
.vv-disabled-name { color: #888; flex: 1; }
|
||||
.vv-disabled-grp { color: #444; font-size: 10px; font-family: monospace; white-space: nowrap; }
|
||||
|
||||
/* Notification board */
|
||||
.vv-nb-board { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
||||
padding: 7px 10px; background: #141414; border-bottom: 1px solid #222;
|
||||
font-size: 12px; min-height: 34px; }
|
||||
.vv-nb-stat { color: #aaa; }
|
||||
.vv-nb-sep { color: #444; }
|
||||
.vv-nb-running { color: #f0a040; }
|
||||
.vv-nb-conf-btns { display: flex; gap: 6px; margin-left: auto; }
|
||||
.vv-nb-conf-btn { font-size: 11px; font-family: monospace; }
|
||||
|
||||
/* Advanced mode button */
|
||||
.vv-adv-mode-btn { border: 1px solid #555; color: #999; transition: background 0.15s, color 0.15s, border-color 0.15s; }
|
||||
.vv-adv-mode-btn:hover { border-color: #888; color: #fff; }
|
||||
.vv-adv-mode-btn.vv-adv-mode-on { background: #1565c0; border-color: #1565c0; color: #fff; }
|
||||
|
||||
/* Script browser in suggestions panel */
|
||||
.vv-sb-desc { font-size: 12px; color: #888; margin: 4px 0 6px; line-height: 1.5; }
|
||||
.vv-sb-child-desc { margin-left: 16px; }
|
||||
.vv-sb-hdr { font-family: monospace; font-size: 11px; color: #666; white-space: pre-wrap;
|
||||
word-break: break-word; background: none; border: none; margin: 4px 0 8px;
|
||||
padding: 0; line-height: 1.5; border-left: 2px solid #222; padding-left: 8px; }
|
||||
.vv-sb-full { font-family: monospace; font-size: 11px; color: #888; white-space: pre-wrap;
|
||||
word-break: break-word; background: #0a0a0a; border: 1px solid #222;
|
||||
border-radius: 3px; margin: 6px 0 8px; padding: 8px 10px; line-height: 1.5;
|
||||
max-height: 480px; overflow-y: auto; }
|
||||
.vv-sb-child-block { border-top: 1px solid #1a1a1a; margin-top: 8px; padding-top: 8px; }
|
||||
.vv-sb-child-name { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; flex-wrap: wrap; }
|
||||
|
||||
/* README content display */
|
||||
.vv-readme-body { font-family: monospace; font-size: 11px; color: #777; white-space: pre-wrap;
|
||||
word-break: break-word; background: none; border: none; margin: 0;
|
||||
padding: 0 4px; line-height: 1.6; }
|
||||
|
||||
/* Script browser tree rows */
|
||||
#vv-sb-tree { padding: 0; }
|
||||
.vv-sb-entry { }
|
||||
.vv-sb-row { display: flex; align-items: center; gap: 6px; padding: 5px 6px;
|
||||
cursor: pointer; border-radius: 3px; user-select: none; }
|
||||
.vv-sb-row:hover { background: rgba(255,255,255,0.04); }
|
||||
.vv-sb-selected { background: rgba(100,149,237,0.12) !important; outline: 1px solid #3a5a8a; }
|
||||
.vv-sb-orch-row { border-bottom: 1px solid #1c1c1c; }
|
||||
.vv-sb-child-row { padding-left: 2px; }
|
||||
.vv-sb-expand { width: 14px; flex-shrink: 0; color: #555; font-size: 10px; text-align: center; }
|
||||
.vv-sb-expand:hover { color: #aaa; }
|
||||
.vv-sb-leaf { cursor: default; pointer-events: none; }
|
||||
.vv-sb-name { flex: 1; font-size: 13px; color: #b0c4d0; min-width: 0;
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.vv-sb-orch-row .vv-sb-name { font-weight: bold; color: #9ab; }
|
||||
.vv-sb-children { padding-left: 10px; }
|
||||
.vv-sb-child-indent { width: 14px; flex-shrink: 0; color: #333; font-size: 11px;
|
||||
text-align: center; pointer-events: none; }
|
||||
.vv-sb-badge { flex-shrink: 0; font-size: 11px; }
|
||||
.vv-sb-cron { color: #555; background: #111; border: 1px solid #222;
|
||||
padding: 0 4px; border-radius: 2px; font-size: 10px;
|
||||
font-family: monospace; flex-shrink: 0; }
|
||||
.vv-sb-status { font-size: 10px; flex-shrink: 0; }
|
||||
|
||||
/* Script info content area */
|
||||
.vv-si-hdr { font-family: monospace; font-size: 12px; color: #4d894d; white-space: pre-wrap;
|
||||
word-break: break-word; background: none; border: none; margin: 0;
|
||||
padding: 8px 12px; line-height: 1.6; }
|
||||
.vv-si-src { font-family: monospace; font-size: 11px; white-space: pre-wrap;
|
||||
word-break: break-word; background: none; border: none; margin: 0;
|
||||
padding: 8px 12px; line-height: 1.5; }
|
||||
|
||||
/* Syntax highlight tokens — dark theme (VSCode-inspired) */
|
||||
.vv-hl-sep { color: #2d2d2d; }
|
||||
.vv-hl-shebang { color: #4a4a4a; }
|
||||
.vv-hl-hash { color: #4a7340; }
|
||||
.vv-hl-comment { color: #6a9955; }
|
||||
.vv-hl-section { color: #9cdcfe; font-weight: bold; letter-spacing: 0.04em; }
|
||||
.vv-hl-key { color: #9cdcfe; }
|
||||
.vv-hl-value { color: #ce9178; }
|
||||
.vv-hl-cron { color: #d7ba7d; font-weight: bold; }
|
||||
.vv-hl-text { color: #4d894d; }
|
||||
.vv-hl-keyword { color: #569cd6; }
|
||||
.vv-hl-builtin { color: #4ec9b0; }
|
||||
.vv-hl-string { color: #ce9178; }
|
||||
.vv-hl-var { color: #d7ba7d; }
|
||||
.vv-hl-number { color: #b5cea8; }
|
||||
.vv-hl-op { color: #808080; }
|
||||
|
||||
/* Log panel */
|
||||
.vv-log-panel { margin-top: 10px; border-top: 1px solid #333; padding-top: 8px; }
|
||||
.vv-log-toolbar { display: flex; justify-content: space-between; align-items: center;
|
||||
@@ -288,3 +469,63 @@
|
||||
/* Live var substitution colours */
|
||||
code.vv-live-var { color: #4caf50; background: #0d1f0d; }
|
||||
code.vv-unknown-var { color: #ff9800; background: #1f130d; }
|
||||
|
||||
/* ── Arrange mode ─────────────────────────────────────────────────────────── */
|
||||
.vv-drag-handle { cursor: grab; color: #555; font-size: 14px; padding: 0 5px 0 0; user-select: none; flex-shrink: 0; }
|
||||
.vv-drag-handle:hover { color: #888; }
|
||||
.vv-drag-ghost { opacity: 0.35; }
|
||||
.vv-drop-line { height: 2px; background: #4caf50; border-radius: 2px; margin: 2px 0; pointer-events: none; }
|
||||
.vv-arrange-active .vv-children { min-height: 28px; border: 1px dashed #2a2a2a; border-radius: 4px;
|
||||
padding: 4px 2px; transition: border-color 0.12s, background 0.12s; }
|
||||
.vv-arrange-active .vv-children.vv-drop-target { border-color: #4caf50; background: rgba(76,175,80,0.07); }
|
||||
.vv-arrange-btn-active { background: #1a3a1e !important; color: #4caf50 !important; border-color: #2d5c33 !important; }
|
||||
.vv-arrange-save-btn { background: #1a3a1e; border-color: #2d5c33; color: #4caf50; }
|
||||
.vv-arrange-save-btn:hover { background: #22502a; }
|
||||
|
||||
/* ── Arrange workspace panel ─────────────────────────────────────────────── */
|
||||
.vv-arrange-ws-hdr { font-size: 11px; font-weight: bold; color: #888; text-transform: uppercase;
|
||||
letter-spacing: 0.6px; margin-bottom: 8px; display: flex; align-items: center; gap: 8px; }
|
||||
#vv-pending-badge { background: #ff9800; color: #000; font-size: 10px; padding: 1px 7px;
|
||||
border-radius: 10px; font-weight: bold; }
|
||||
.vv-arrange-pending-hdr { font-size: 10px; color: #555; text-transform: uppercase; letter-spacing: 0.5px;
|
||||
margin-bottom: 5px; }
|
||||
.vv-pending-row { display: flex; align-items: center; gap: 8px; padding: 3px 0;
|
||||
font-size: 11px; border-bottom: 1px solid #1e1e1e; }
|
||||
.vv-pending-script { color: #ddd; font-weight: 500; }
|
||||
.vv-pending-arrow { color: #555; font-size: 10px; }
|
||||
.vv-library-zone { border: 1px dashed #2a2a2a; border-radius: 4px; padding: 6px;
|
||||
min-height: 60px; transition: border-color 0.12s, background 0.12s; }
|
||||
.vv-library-zone.vv-drop-target { border-color: #c62828; background: rgba(198,40,40,0.07); }
|
||||
.vv-arrange-drop-hint { font-size: 10px; color: #444; text-align: center; padding: 2px 0 7px; }
|
||||
.vv-lib-card { background: #1c1c1c; border: 1px solid #2e2e2e; border-radius: 3px;
|
||||
padding: 4px 8px; margin-bottom: 4px; cursor: grab; display: flex;
|
||||
align-items: center; justify-content: space-between; gap: 8px; }
|
||||
.vv-lib-card:hover { border-color: #444; }
|
||||
.vv-lib-card.vv-drag-ghost { opacity: 0.35; }
|
||||
.vv-lib-card-name { font-size: 16px; color: #ccc; font-weight: bold; }
|
||||
.vv-lib-card-path { font-size: 10px; color: #444; font-family: monospace; }
|
||||
|
||||
/* ── Custom script folders ────────────────────────────────────────────────── */
|
||||
.vv-folder-group { margin-bottom: 1px; }
|
||||
.vv-folder-row { display: flex; align-items: center; gap: 6px; padding: 3px 6px;
|
||||
cursor: pointer; border-radius: 3px; color: #888; font-size: 12px; user-select: none; }
|
||||
.vv-folder-row:hover { background: #1e1e1e; }
|
||||
.vv-folder-chevron { font-size: 10px; color: #555; width: 10px; flex-shrink: 0; }
|
||||
.vv-folder-name { flex: 1; font-weight: 500; color: #aaa; }
|
||||
.vv-folder-count { font-size: 10px; color: #555; background: #1c1c1c;
|
||||
padding: 0 5px; border-radius: 8px; border: 1px solid #2a2a2a; }
|
||||
.vv-folder-children { padding-left: 12px; min-height: 4px; }
|
||||
.vv-folder-children.vv-drop-target { background: rgba(76,175,80,0.07); border-radius: 4px;
|
||||
outline: 1px dashed #3a6a3e; }
|
||||
.vv-folder-new-row { display: flex; align-items: center; gap: 6px; padding: 4px 6px; }
|
||||
.vv-new-folder-btn { background: #1c1e1c; border-color: #2e3a2e; color: #6a9e6a; }
|
||||
.vv-new-folder-btn:hover { background: #222e22; }
|
||||
|
||||
/* ── Rsync standalone controls ────────────────────────────────────────────── */
|
||||
.vv-rsync-location { width: 120px; flex-shrink: 1; min-width: 60px; font-size: 11px; font-family: monospace;
|
||||
background: #111; border: 1px solid #333; color: #aaa;
|
||||
padding: 2px 6px; border-radius: 3px; }
|
||||
.vv-rsync-location:focus { border-color: #555; outline: none; }
|
||||
.vv-rsync-location::placeholder { color: #444; }
|
||||
.vv-rsync-save-btn { background: #1a2e1a; border-color: #2a4a2a; color: #6aaa6a; }
|
||||
.vv-rsync-save-btn:hover { background: #22382a; }
|
||||
|
||||
Reference in New Issue
Block a user