Login.tsx only read the return path from router state, which a hard
cross-document navigation (a child app bouncing the whole shell here
on session expiry) can never carry — so re-authenticating always
landed on the Dashboard instead of back in whatever app you were
using. Login.tsx now also accepts a ?from= query param for that case.
Also wired up AuthGate's inactivity auto-logout timer, which was
defined (getInactivityMs) but never actually called — so the
per-device timeout configurable in Admin Settings had no effect.
Disabled for installed PWAs as intended.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Admin clicks 'Auth secret', re-enters their password, and sees CENTRAL_AUTH_SECRET
with a copy button. Secret auto-clears after 60 seconds.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On every iframe load, mirror its current path to the portal URL hash
(e.g. /app/cashup#/reports). On mount, initialSrc reads that hash and
restores the correct page after a refresh. Hash is cleared when
switching apps so it doesn't bleed across slugs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
If a different user logs into a child app while the portal tab is open,
the portal cookie changes but the in-memory user state goes stale. Now
AuthGate re-fetches /api/auth/me on visibilitychange and focus events,
updating state only when the user identity actually changes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Displays a gold badge next to the latest commit hash when the backend
returns a commitsBehind count greater than zero.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Backup Directory field in the Nextcloud integration card gains a
Browse button that opens an inline panel with: breadcrumb navigation,
scrollable directory list, and a Select button to pick the current path.
Falls back to manual text entry.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backups tab shows last-run status, expandable run history with per-item
breakdown (db/vol, size, status), and a Run Now trigger button.
Settings Nextcloud card gains a Backup Directory field.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Portal sidebar was rendering nothing for the history app entry because
History was missing from the Lucide icon map.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Maintenance (Wrench) and Reports (BarChart2) icons were missing from
the hardcoded iconMap, causing those app tiles to show no icon.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When an app is open, the sidebar collapses to a 44px strip with a
chevron button. Clicking it opens the full sidebar as a fixed overlay
with a backdrop that closes on click. Also closes automatically when
the user interacts with / navigates within the iframe (window blur).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire /admin/settings route and sidebar link; proxy /settings/api/ to the
new settings service at 10.10.10.116. Admin can configure integration
credentials and manage Newbook room ordering from the portal.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sidebar now renders uncategorised apps flat and categorised apps in
collapsible accordion sections; active category stays expanded. Dashboard
groups tiles under category section headings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>