feat(task-tray): backgroundable running ops + corrected modal buttons [OS-461]#2669
feat(task-tray): backgroundable running ops + corrected modal buttons [OS-461]#2669elibosley wants to merge 31 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🔧 PR Test Plugin AvailableA test plugin has been generated for this PR that includes the modified files. Version: 📥 Installation Instructions:Install via Unraid Web UI:
Alternative: Direct Download
|
d54a2d6 to
9d016d8
Compare
Apply robot review feedback for the backend task queue: - TaskQueue.php: escape the full bash -c payload with escapeshellarg() to close a single-quote shell-injection vector while preserving multi-arg word splitting; serialize create->launch per type with flock to keep the one-running-task-per-type invariant under concurrent requests. - nchan/tasks: require numeric pid before the /proc liveness check; recover queued-only tasks so the daemon never sleeps with pending work; match _ERROR_ as a discrete RS-delimited record (read tail in PHP). - TaskCommand.php: validate pid is numeric before kill. - BodyInlineJS.php: escape task.title in the swal title and task ids in the tray onclick handlers. - HeadInlineJS.php: surface a createTask() failure via .fail(). - default-base.css: add min-width:0 so .op-title ellipsizes reliably. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The foreground task modal drove its single button off an inverted per-type
`button` flag. For docker/vmaction (default button=0) this hid the Close
button for the entire running phase AND left the confirm button disabled,
which surfaced SweetAlert's `.la-ball-fall` loader (the "bouncing green
dots") with no way to background the operation.
Drive the modal by task status instead, uniformly for all types:
- running -> a top-corner minimize control backgrounds the task (it keeps
running under the daemon and stays in the tray); no disabled
button, so the bouncing-dots loader never appears. The
spinning title icon remains the in-progress indicator.
- done/err -> a single primary "Dismiss" button that fires the reload
callback and clears the task from the tray.
Esc while running now backgrounds (instead of deleting) since the
done-callback checks live status. No caller passes the `button` flag, so
no real behavior contract changes; `task.button` is now inert (follow-up:
drop it from the task record + open* signatures).
Stacked on the backend task queue (#2665).
OS-461
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The foreground task modal is a 90vw centered, rounded card — on phones that reads as a cramped "circular" blob. On <=767px take it fullscreen (flush, no radius), pin the title at top, let the log fill and scroll, and keep the corner minimize + bottom Dismiss reachable. Scoped to `.nchan` so ordinary confirm/warning dialogs keep their dialog look. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per design review: the top-corner control is now a persistent "close this window" present in every state, rather than vanishing when the task finishes. While running it reads as minimize (fa-window-minimize, task keeps running); once finished it swaps to a plain close (fa-times, task stays in the tray). Removal stays the separate primary Dismiss action — mirroring the tray tile's Show + Dismiss split: close-and-keep (corner) vs dismiss-and-remove (button). OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The control was colored with --text-color at 60% opacity, but the modal is a dark surface (.sweet-alert bg = --black), so on the default theme it was dark-on-dark and easy to miss. Make it a light, bordered circular button with a brand-orange hover, bump the hit area (and again on mobile for touch), and use a cleaner fa-minus for the running/minimize glyph (fa-times stays for close). OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Align the foreground task modal with the Unraid notifications sidebar: dock it to the right as a full-height sheet (full-width on mobile), shrink the header and move the status onto a muted subline, put the log in a card, and give it a brand-orange primary Dismiss button. Critically, all colors now come from theme tokens (--dynamix-sweet-alert-*, --alt-text-color, --shade-bg-color, --border-color, --brand-orange) instead of hardcoded light values, so it adapts correctly across white / azure / black / gray. (azure/white override the sweet-alert tokens to a LIGHT surface, which is why the previous hardcoded-white close icon was invisible.) OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bump the docked sheet to 46rem (max 95vw) and pin min/height to 100dvh + top/bottom:0 so it always fills the available height. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pull the desktop form back from a full-height right sidebar to a compact, centered card — a transient progress log shouldn't take over the screen, and a familiar centered modal is lower-risk for the docker/plugin update flow. All the substance stays: smaller header + muted status subline, themed log card, brand-orange Dismiss, minimize/close semantics, theme-token colors, and mobile fullscreen. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sparent) SweetAlert sets background-color:transparent inline on the confirm button (default confirmButtonColor), which beat the CSS class and left the orange Dismiss button white-on-white. Override bg/color/border with !important. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…carousel The scroll-to-top/bottom buttons and the task tray both sit bottom-right at the same z-index, so the buttons covered the task tiles. Raise the tray above them and, when the tray has tasks, move the buttons clear (bottom-left on desktop, lifted above the tray on mobile) via the #opTray sibling selector. On mobile the tray is now a full-width horizontal scroll-snap carousel — one task tile at a time, swipe between them — instead of a bottom-right stack. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…swap) The corner control flipped from minimize (-) while running to a close (x) when done, but that 'x' still only minimized (kept the task in the tray) while the Dismiss button was the real remove. Confusing. Keep the corner as a single, consistent minimize in every state; Dismiss remains the close-and-remove. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… screens - Close: fade the modal out with .nchan still applied, then strip the class after (~350ms) via a shared nchanCloseModal(). Removing .nchan while visible snapped it back to the default swal look for a frame (the flash). Guard with pointer-events:none and a reopen check. - Width: bump max-width 42rem -> 60rem so it's as wide as it used to be on large screens (still 90vw on smaller ones). OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…button) The Dismiss button was centered (swal's .sa-confirm-button-container centers it) in a tall footer (margin-top + a hidden loader reserving space). Make it a full-width button in a slim footer: deliberate, less vertical space, consistent desktop/mobile. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SweetAlert adds padding-bottom:40px when no buttons are shown (the running
state has no footer button), and that selector outspecified .nchan { padding:0 }.
Override it with a matching higher-specificity rule.
OS-461
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… placement) Switch from full-width to a compact bottom-right Dismiss - lighter, more dialog-like. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…was centering) .sa-button-container is itself a flex container with justify-content:center, and the inner confirm-container is only button-width, so right-aligning the inner one did nothing. Right-align the outer container instead. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The log sat in its own bordered, filled box inside the modal that already has a header divider and footer divider - a box-in-a-box. Make the log a plain region framed by the dividers (header / body / footer). OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ty strip) The running modal has no Dismiss button, but the footer container still rendered its top border + padding as an empty bottom bar. Hide it when no confirm button. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…85vh The log used flex:1 1 auto and stretched the modal full height, leaving a big empty gap for short logs. Use flex:0 1 auto so the modal hugs its content and only grows/scrolls once the log exceeds the 85vh cap. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…title Move the In Progress/Finished/Error status out of the title subline into a distinct, colored state section between the title and the log: blue while running, green when finished, red on error (with an icon). openDone/openError recolor it. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e strip - height: the swal @media(max-width:1200px){height:95vh} forced the modal tall, pooling empty space below the footer. Set .nchan height:auto so it sizes to content (capped at 85vh, scrolls beyond). Dismiss now sits at the real bottom. - state strip: drop the dated pale-color banner for a subtle translucent tint + colored icon + theme (--text-color) text, readable on light and dark. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per feedback: a stable button beats a modal that grows and shifts as the log streams. Fixed height 34rem (capped at 85vh on short screens); the log fills and scrolls in place, footer pinned to the bottom. Mobile stays fullscreen. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The modal opens running with showConfirmButton:false (data-has-confirm-button= false), and the footer is hidden by CSS keyed on that attribute. openDone/openError showed the button but never flipped the attribute, so the footer stayed hidden until the modal was reopened. Set data-has-confirm-button=true on completion. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ning Minimizing the progress modal during a plugin update left the row's Update button visible and clickable (stale) - you could start a duplicate update. Drive the button off the live task queue: while a running/queued plugins task targets a plugin, its update/install button shows 'Upgrading' and is disabled. Survives modal minimize, list reloads and page reloads via a window.onTaskListChanged hook fired from onTaskListUpdate. Also align the in-progress modal status line with the new state strip. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…task queue) Replace the client-side string-matching/busy-toggle with a single source of truth: make_link() now renders 'Upgrading'/'Installing' (disabled) when the task queue has a running/queued task for that .plg (plugin_task_busy via task_list, precise token match). The Plugins page just triggers a cheap status-cell refresh (loadlist(null,1), no network re-check) when the active plugin-task set changes. Correct on every render path - page load, reload, completion - and generalizes better than the per-page client logic. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…s rendering The tabbed content renderer (generateContent) Markdown-processes a page body unless the header sets Markdown="false". Plugins.page lacked it (unlike the script-heavy Docker/VM pages), so its inline <script> got Markdown-mangled (<script> wrapped in <p>, * -> <em>, < -> <), initlist() never ran and the table rendered empty. Add the flag like the other script pages. Unrelated to the Upgrading change (diff confirmed) - a latent page-header bug exposed by the tabbed renderer. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The mobile carousel tiles and their action icons were small and hard to tap. Give tiles more padding + a min-height and make the action icons proper ~48px touch targets (inline-flex, min-width/height, larger glyph). OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hard to tell the mobile tray was swipeable. Make each tile 85% width so the neighbour peeks in (a swipe cue), end-align the snap, and scroll the carousel to the newest task on render instead of starting on the leftmost 'Clear finished' header. OS-461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the horizontal swipe carousel on mobile with the iOS/Android grouped-notification pattern. When multiple background operations are active the tray collapses to the newest card with the rest peeking behind it (faux stacked edges + a count badge); tapping it expands the full vertical list so all operations can be viewed and cleared at once. A collapse chevron returns to the single card. Desktop is unchanged (always a full vertical stack). The carousel scroll-snap/scrollLeft behaviour and its default-to-newest hack are removed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The mobile stacked tray (larger card + peeking edges + count badge) sits higher than the old carousel, so raise the scroll-to-top/bottom buttons from 6rem to 7.5rem to keep them clear of it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
33a9007 to
31b24c4
Compare
…lds #2669, OS-461) Squash of feat/task-modal-buttons (PR #2669, 31 iteration commits) into the consolidated task-queue PR. Adds backgroundable running operations with a corrected modal button set, drives the plugin "Upgrading" button state from the server-side task queue, and a round of task-modal/tray styling (state strip, dismiss placement, mobile grouped-notification carousel). Touches only the tray/modal UI (BodyInlineJS, HeadInlineJS, default-base.css) and the Plugins page (Plugins.page, PluginHelpers.php); no changes to the core queue/daemon files. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
Fixes the foreground task modal's behavior and gives it a compact, theme-aware restyle. The behavioral issues were rooted in one place — the modal drove a single button off an inverted per-type
buttonflag inforegroundTask(), which for docker/vmaction hid the close button for the whole running phase (can't background) and left the confirm button[disabled], surfacing SweetAlert'sla-ball-fallloader (the "bouncing dots").Behavior
Show+Dismiss.Look
max-width: 42rem,max-height: 85vh, log scrolls inside.1.6rem, left-aligned) with the status on a muted subline.--dynamix-sweet-alert-*,--shade-bg-color,--alt-text-color,--border-color,--brand-orange), so it adapts across white / azure / black / gray. (Notably, azure/white override the sweet-alert tokens to a light surface — the earlier hardcoded-white close icon was invisible there; it now uses the modal's own text-color token.)Files
BodyInlineJS.php— status-drivenforegroundTask();minimizeForegroundTask().HeadInlineJS.php—openDone/openErrorswap the corner control for the Dismiss primary.default-base.css— centered-card restyle + theme tokens + mobile fullscreen.Notes
buttonflag, so no behavior contract changes;task.buttonis now inert (follow-up: drop it from the record +open*signatures).php -lclean;swal/swal.close()are globals in the bundled SweetAlert v1.Closes OS-461