This commit addresses several critical stability issues in the notification system spanning the legacy PHP script, the Node.js API, and the Vue frontend.
**Backend / API:**
- **Refactor `notify` script (PHP):** Added `-u` flag to accept a custom filename/ID from the caller. Added filename length sanitization (255 chars) to prevent filesystem errors.
- **Fix ID Mismatch:** The Node API now generates a UUID and passes it to the `notify` script via `-u`. This guarantees that the API, Frontend, and Filesystem all reference the same ID, removing the need for "Risky" notification logic.
- **Fix Counter Bugs:**
- `handleNotificationAdd` no longer ignores duplicate files in the archive.
- `archiveNotification` now checks if a file exists in the archive before moving. If it exists, it simply deletes the unread copy without double-counting.
- `archiveAll` now leverages the robust single-archive logic.
**Frontend (Web):**
- **Fix Infinite Scroll "Drift":**
- Switched `List.vue` to use a **Debounced Refetch** (500ms) for subscription updates instead of manual cache manipulation. This handles rapid-fire events (mass adds) without corruption.
- Increased `pageSize` to `50` to minimize race conditions where new items shift pagination offsets.
- Added **Drift Detection**: If `fetchMore` returns a full page of duplicates (indicating the list has shifted), the component now automatically triggers a full refetch to self-heal.
This change ensures that Nuxt UI notifications respect the display position configured in the legacy webGUI settings.
Backend:
- Added `NotificationSettings` to the GraphQL model.
- Exposed `settings` field on the `Notifications` resolver.
- Implemented `getSettings` in `NotificationsService` to read `notify.position` from the Dynamix store.
Frontend:
- Added `getNotificationSettings` GraphQL query.
- Updated `mount-engine.ts` to fetch settings before mounting.
- Mapped legacy position values (e.g., 'center') to Nuxt UI compatible values (e.g., 'top-center').
Problem this solution addresses:
Basically, when users filtered by alert, warning, or info, results were being paginated first, then filtered by the requested importance, so filtered notifications were not working properly in some (a lot) of cases.
- added a new async generator method to load notifications in batches, enhancing performance and error handling.
- refactored the notification loading logic to utilize the generator, improving readability and maintainability.
- updated filtering logic to streamline the process of matching notifications based on importance and type.
> [!Note] This stubs the unraid-ui/src/components/common/toast. Initially created a shim to convert vue-sonnner toasts to nuxtui. However, since there weren't that many, I just did a clean replacement.
- replace router link with window.location.assign
The `UButton` component attempts to inject the Vue Router instance when the `:to` prop is used. In the standalone component environment (where the router is not installed), this caused a "TypeError: inject(...) is undefined" crash when rendering notifications with links.
This change replaces the `:to` prop with a standard `@click` handler that uses `window.location.assign`, ensuring navigation works correctly without requiring the router context.
- modified vite.config.ts to integrate app configuration into UI setup
- updated app.config.ts to include new button, tabs, and slideover variants for better theming
- cleaned up main.css by removing unused styles and ensuring proper imports
- refactored notification components to streamline structure and improve readability
- replaced Heroicons components with UIcon for better integration
- refactored Sidebar.vue to utilize USlideover and UButton for a cleaner UI
- removed unused imports and styles in main.css for better maintainability
NOTES:
- had to change main.css variables for it to work properly. Need to make sure this doesn't ruin other people's code.
- still needs to be further refactored to align with existing ui variables
commit addresses the following two bugs/issues:
1. infinite network requests
2. make error messages more accurate
bug details:
- when scrolled all the way down in the notification pane (when api is down), unraid infinitely sends network requests.
- must be scrolled all the way to the bottom and stay at the bottom of the pane while the api is down
technical details:
- for infinite loop, added try/catch that sets a canLoadMore flag to false when it encounters an error, preventing infinite loop
- errors now look at non-standard locations as well
impact:
- performance benefits
- more graceful ux on failure
fix context menu trigger area and dropdown styles
implement 'move to folder'
implement 'start / stop' bulk & row actions
implement pause / resume
implement column visibility customization
fix(organizer): over-eager addition of untracked containers to root folder
scaffold docker form service
docker container management prototype
use compacted table as sidebar tree
add drag and drop for re-ordering containers & folders
right click to reame & delete folders
add bottom padding to container to make it easier to drag items to bottom in sidebar
click overview row to open details
track active container in query param
refactor: extract composables
refactor: simplify organizer operations
refactor!: rm intermediate tree resolution of organizers
BREAKING CHANGE: ResolvedOrganizerView -> root is replaced by rootId +
flatEntries.
`root` resolved a tree representation of an organizer, but this required
clients to defined and use their own tree operations, thus increasing
client complexity.
Instead, `flatEntries` is more suitable for client operations and only
requires an initial mapping step on the client for efficiency.
fix: rm extra Root layer in table
map containers to their template files
feat: icon support
fix: container state badge
chore: fix formatting
fix: search filtering
fix: context menu
feat: filtering & bulk actions in compact mode
feat: critical notifications
feat: notifyIfUnique service method
tmp: critical notifications system
fix: nuxt ui portal styling
fix: notifications type check
fix api tests
fix: css
Revert "fix: css"
This reverts commit 234c2e2c65.
add docker constants
flatten css scopes
feat: file modification for replacing docker overview table
feat: navigate to container update page
feat: implement manage settings action
fix: column visibility toggle
fix: move update to a badge + popover
feat: save column visibility preferences across visits
fix: add feature flag to containers file mod
fix: circular dependency in docker service
add a flag to opt out of version check in super.shouldApply in file mods
fix: optimistic column toggle update
refactor: optimistic column toggle
feat: container start & stop order
feat: bulk toggle auto-start
fix: add background style reset, apply to button:hover as well
feat: add ENABLE_NEXT_DOCKER_RELEASE=true to staging environment
chore(api): add dev/notifications to gitignore
feat: container update actions
fix: container update logic
feat: bulk container updates
feat: container sizes
fix: container sizes modla overlay
fix: checkbox alignment
fix: revert color in main css
chore: ignore build output in lint & fix
feat: server-side container ip
add docker feature flag to .env.production
fix: container port duplication
feat: multi-value copyable badges
feat: make lanIpPorts a list, not a csv
feat: visit button
feat: include indexed search fields in filter input title
feat: sync userprefs.cfg for rollback compat
feat: port conflicts
refactor: port conflict frontend stuff
feat: update all containers bulk action
feat: docker logs
fix: use container name instead of id in 'view logs' modal
make webgui iframable
feat: re-add compact mode
manage settings > compact view
fix styles
feat: container stats
refactor: docker autostart service
refactor: docker log, event, and port services
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes v4.29.2
* **New Features**
* Added iframe mode support with UI adjustments for embedded deployments
* Introduced modal portal system with dark mode integration
* **Bug Fixes**
* Fixed log line deduplication sync issue in Docker log viewer to
prevent orphaned entries
* **Improvements**
* Enhanced table header rendering for consistent behavior and resizing
* Improved notification subscription handling for better stability
* Optimized log viewer initialization behavior
* Simplified organizer API parameter handling
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Pujit Mehrotra <pujit@lime-technology.com>
Previously, api plugins could only be installed as `peerDependencies` in
the api. This change allows them to be listed as `dependencies` as well.
This makes plugin loading (eg loading Connect) more robust.
Tests:
- [x] Re-logging on 7.3.0-beta.0.5
- Replaced BrandLoading with BrandButton in UpdateOs component for
better user interaction.
- Updated test cases to reflect changes in rendering logic, ensuring the
account button is displayed when no reboot is pending.
- Added functionality to navigate to account update when the button is
clicked.
- Introduced WEBGUI_REDIRECT URL for handling update installations in
the store logic.
Raised by [MitchellThompkins](https://github.com/MitchellThompkins) in
#1848
- Documents how to use Docker to build a local Connect plugin
- Local Plugin flow will now build workspace packages before proceeding
with plugin infra + build
- Removes recommendation to run `pnpm build:watch` from root, as this
race conditions and build cache issues.
- Makes `pnpm dev` from root parallel, preventing servers from blocking
each other.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Updated development workflow documentation to emphasize Docker-based
plugin builds
* Restructured development modes into three workflows: local Docker
builds, direct deployment, and development servers
* Updated build and deployment instructions
* **Chores**
* Modified dev script for parallel execution
* Refactored build scripts with improved dependency handling
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#1848
## Background
The `build:dev` script is used for the `unraid:deploy` workflow, and it
implicitly triggered the `predev` script to build the `unraid-ui`
package as needed.
`web` builds depend on `unraid-ui`. In the past, `unraid-ui` was built
during `pnpm install` via a `prepare` step in its `package.json`.
However, this approach doesn't ensure that `web` builds correctly; stale
`unraid-ui` builds could cause false-positives.
So, instead of doing that, we call `predev` from `prebuild`, ensuring
that both local builds and the `unraid:deploy` workflow lazily get the
correct build of `unraid-ui`.
## Summary
Introduces a new Vue-based Docker container management interface
replacing the legacy webgui table.
### Container Management
- Start, stop, pause, resume, and remove containers via GraphQL
mutations
- Bulk actions for managing multiple containers at once
- Container update detection with one-click updates
- Real-time container statistics (CPU, memory, I/O)
### Organization & Navigation
- Folder-based container organization with drag-and-drop support
- Accessible reordering via keyboard controls
- Customizable column visibility with persistent preferences
- Column resizing and reordering
- Filtering and search across container properties
### Auto-start Configuration
- Dedicated autostart view with delay configuration
- Drag-and-drop reordering of start/stop sequences
### Logs & Console
- Integrated log viewer with filtering and download
- Persistent console sessions with shell selection
- Slideover panel for quick access
### Networking
- Port conflict detection and alerts
- Tailscale integration for container networking status
- LAN IP and port information display
### Additional Features
- Orphaned container detection and cleanup
- Template mapping management
- Critical notifications system
- WebUI visit links with Tailscale support
<sub>PR Summary by Claude Opus 4.5</sub>
`myservers.cfg` no longer gets written to or read (except for migration
purposes), so it'd be better to read from the new values instead of
continuing to use the old ones @elibosley @Squidly271 .
unless i'm missing something! see #1805
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Switches to a centralized remote-access configuration with a legacy
fallback and richer client-side handling.
* Optional GraphQL submission path for applying remote settings when
available.
* **Bug Fixes**
* Normalized boolean and port handling to prevent incorrect values
reaching the UI.
* Improved error handling and UI state restoration during save/apply
flows.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
On errors, a `console.error` message should be emitted from the browser
console, tagged `[ReplaceCheck.check]`.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added retry capability for license eligibility checks with a
contextual "Retry" button that appears in error states.
* **Bug Fixes**
* Fixed license status initialization to correctly default to ready
state.
* Enhanced error messaging with specific messages for different failure
scenarios (missing credentials, access denied, server errors).
* Improved status display handling to prevent potential runtime errors.
* **Localization**
* Added "Retry" text translation.
* **Tests**
* Updated and added tests for reset functionality and error handling.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Updated the total startup budget, bootstrap reserved time, and maximum
operation timeout values to enhance API startup reliability. The total
startup budget is now set to 30 seconds, with 20 seconds reserved for
bootstrap and a maximum operation timeout of 5 seconds.
## Summary
Fixes the `estimatedRuntime` field in the UPS GraphQL query to return
values in **seconds** as documented, instead of **minutes**.
## Problem
The `TIMELEFT` value from `apcupsd` is returned in minutes (e.g., `6.0`
for 6 minutes), but the GraphQL schema documentation states:
> Estimated runtime remaining on battery power. **Unit: seconds**.
Example: 3600 means 1 hour of runtime remaining
Currently, the API returns `6` (minutes) instead of `360` (seconds).
## Solution
Convert the `TIMELEFT` value from minutes to seconds by multiplying by
60:
```typescript
// Before
estimatedRuntime: parseInt(upsData.TIMELEFT || '3600', 10),
// After
estimatedRuntime: Math.round(parseFloat(upsData.TIMELEFT || '60') * 60),
```
## Testing
1. Query `upsDevices` before the fix → `estimatedRuntime: 6` (incorrect
- minutes)
2. Query `upsDevices` after the fix → `estimatedRuntime: 360` (correct -
seconds)
Tested on Unraid server with APC UPS connected via apcupsd.
## Related Issues
Fixes#1821
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Corrected UPS battery runtime calculation to interpret provider
TIMELEFT as minutes, convert to seconds, and use a sensible default when
missing—improves displayed battery runtime accuracy.
* **Tests**
* Updated UPS test fixtures to match the minute-based TIMELEFT format
used by the UPS provider.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Necessary for "clean" upgrades to api orchestration (eg changing how the
api is daemonized).
Prior to this, `rc.unraid-api start` would also restart a running api,
which sufficed for application updates, but is insufficient for
orchestration updates.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved update reliability by ensuring services are properly stopped
before system modifications occur.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
…on and pnpm-lock.yaml
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a standalone redirect page that shows "Redirecting..." and
navigates automatically.
* **Improvements**
* Redirect preserves hash callback data, validates targets, and logs the
computed redirect.
* Purchase callback origin changed to a different account host.
* Date/time formatting now tolerates missing or empty server formats
with safe fallbacks.
* Redirect page included in backup/restore.
* **Tests**
* Added tests covering date/time formatting fallbacks.
* **Chores**
* Dependency @unraid/shared-callbacks upgraded.
* Removed multiple demo/debug pages and related test UIs.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Added PHP logic to determine if the current theme is dark and set a
CSS variable accordingly.
- Introduced a new function to retrieve the dark mode state from the CSS
variable in JavaScript.
- Updated the theme store to initialize dark mode based on the CSS
variable, ensuring consistent theme application across the application.
This improves user experience by ensuring the correct theme is applied
based on user preferences.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Server-persisted theme mutation and client action to fetch/apply
themes
* **Improvements**
* Safer theme parsing and multi-source initialization (CSS var, storage,
cookie, server)
* Robust dark-mode detection and propagation across document, modals and
teleport containers
* Responsive banner/header gradient handling with tunable CSS variables
and fallbacks
* **Tests**
* Expanded tests for theme flows, dark-mode detection, banner gradients
and manifest robustness
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | major | `v5` -> `v6` |
---
### Release Notes
<details>
<summary>actions/checkout (actions/checkout)</summary>
### [`v6`](https://redirect.github.com/actions/checkout/compare/v5...v6)
[Compare
Source](https://redirect.github.com/actions/checkout/compare/v5...v6)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | major | `v5` -> `v6` |
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | major | `v4` -> `v6` |
---
### Release Notes
<details>
<summary>actions/setup-node (actions/setup-node)</summary>
###
[`v6`](https://redirect.github.com/actions/setup-node/compare/v5...v6)
[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v5...v6)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
|
[github/codeql-action](https://redirect.github.com/github/codeql-action)
| action | major | `v3` -> `v4` |
---
### Release Notes
<details>
<summary>github/codeql-action (github/codeql-action)</summary>
###
[`v4`](https://redirect.github.com/github/codeql-action/compare/v3...v4)
[Compare
Source](https://redirect.github.com/github/codeql-action/compare/v3...v4)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
## Summary
- ensure the API release build copies nodemon.json into the packaged
artifacts so nodemon-managed deployments have the config available
## Testing
- pnpm --filter @unraid/api lint:fix
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_e_691e1f4bde3483238726478f6fb2d52a)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Switch to Nodemon for process management and updated CLI to use it.
* Added boot-time diagnostic logging and direct log-file writing.
* New per-package CPU telemetry and topology exposure.
* **Bug Fixes**
* More reliable process health detection and lifecycle handling.
* Improved log handling and startup robustness.
* **Chores**
* Removed PM2-related components and tests; migrated to Nodemon.
* Consolidated pub/sub channel usage and bumped internal version.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Pujit Mehrotra <pujit@lime-technology.com>
## Summary
- guard build number generation to the main repository and allow
failures without stopping the workflow
- add a fallback build number derived from the GitHub run number when
the tag-based number cannot be created
## Testing
- not run (workflow-only change)
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_e_693894fb808c8323a3ee51e47fe5d772)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Improved build pipeline reliability with enhanced fallback mechanisms
to ensure consistent artifact generation.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->