Skip to content

Settings fixes from a full UI test pass - #228

Open
Brandon-Haney wants to merge 6 commits into
StudioNirin:mainfrom
Brandon-Haney:pr/settings-ui-fixes
Open

Brandon-Haney wants to merge 6 commits into
StudioNirin:mainfrom
Brandon-Haney:pr/settings-ui-fixes

Conversation

@Brandon-Haney

Copy link
Copy Markdown
Collaborator

I went through every Settings tab on a test build, changing each setting, saving, reloading and checking what was stored. These are the problems that turned up. Each one has tests that fail without the fix.

Import / Export (the important one)

Importing a backup that was exported with "Include sensitive data" unticked wrote its placeholders over the real values, even in Merge mode. The Plex token went blank (so the app dropped back to the Setup wizard), the login password hash became [REDACTED], and user tokens, the webhook and the Sonarr/Radarr keys were cleared. That kind of export is meant for sharing, so importing one now keeps this installation's Plex connection, login, users and keys and only applies the other settings. Validate says so before you import. New exports carry a marker, and older ones are recognised by their placeholders.

Also in this area:

Cache

Size fields accepted anything. banana saved fine and the engine then treated it as "no limit". A negative value like -5GB was read as a huge percentage and would stop caching altogether. Bad values are now refused with a message naming the field, and the size parser never returns a negative.

Schedule

An invalid cron expression saved as successful, then the job couldn't be created, so the schedule showed Enabled but never ran. It's now refused with the reason.

Users

  • Every save stored the owner account as skipped for OnDeck and Watchlist, because its toggles are disabled and disabled checkboxes aren't submitted. Caching always includes the owner anyway, but the settings file was wrong.
  • A failed Sync replaced the users table with the error message. The table now stays, with the error above it.

Libraries (custom mappings)

  • Delete on a Custom Mapping did nothing. It targeted an element from the old Paths page.
  • Adding the first custom mapping saved it but didn't show it.
  • Cards address mappings by list position, which shifts after any delete. A card left on screen could edit or delete the wrong mapping. The section now re-renders after Add and Delete, and the server refuses a stale card.

Integrations

  • The add form never cleared after adding an instance. The page's security policy blocks hx-on handlers, so a small listener in app.js does it now. A test keeps hx-on out of templates.
  • The "No Sonarr/Radarr instances configured" message stayed after adding one.

Everywhere

  • If setup became incomplete while a page was open, the status pill's background check pulled the whole Setup page into the pill, on top of the current page. It now redirects the whole page, the same way an expired login already does.
  • Confirm prompts used the browser's own confirm() box. They now use a themed dialog in the app's style, with a red button and focus on Cancel for destructive actions.
  • Badge icons were 24px instead of 12px, because .badge i never applied once Lucide swaps the <i> for an <svg>. That also made a text-only badge sit lower than an icon badge next to it, e.g. "OnDeck" beside "Returns when watched" on Recently Added.

Testing

  1. Settings → Import/Export: untick "Include sensitive data", download, then Import that file in Merge mode. Plex should stay connected and login should still work.
  2. Settings → Cache: enter banana as Cache Limit and save. It's refused and nothing changes.
  3. Settings → Schedule: choose Cron, enter 99 * * * and save. It's refused.
  4. Settings → Libraries: add a custom mapping, edit it, then delete it.
  5. Settings → Integrations: add an instance. The form clears and the placeholder goes.
  6. Recently Added: the OnDeck badge sits level with the status badge.

hx-confirm and the settings import prompt showed the browser's own
confirm() box. app.js now handles htmx:confirm with a shared modal in the
app's theme (data-confirm-title, data-confirm-label, red confirm button for
destructive actions, Escape/backdrop cancel, focus kept in the dialog).
Also styles .modal-close, which the existing modals use.
htmx compiles hx-on handlers with Function(), and the Content-Security-Policy
has no 'unsafe-eval', so the Integrations add form never cleared after adding
an instance (EvalError in the console). A delegated htmx:afterRequest listener
in app.js now resets forms marked data-reset-on-success, skipping responses
retargeted to an error alert. Test keeps hx-on out of templates.
Delete targeted #path-mappings, which only existed on the retired Paths page,
so htmx dropped the request. Add targeted #orphan-mappings, which was only
rendered once a custom mapping existed, so the first one saved without
appearing. The Custom Mappings section is now always present and Add/Delete
re-render it, keeping every card's index current.

Cards address a mapping by list index, which shifts when any mapping is
deleted (including Remove on a library card). Cards now send the paths they
were rendered with and the server refuses a stale edit or delete rather than
acting on whichever mapping sits at that index; a library save that removes a
mapping also refreshes the custom cards out-of-band. Errors show in the page
alert area.
Import/Export: importing an export made without sensitive data, even in
Merge mode, wrote its placeholders over the real values, so the Plex token
went blank (the app fell back to Setup), the login password hash became
"[REDACTED]" and user, webhook and Sonarr/Radarr keys were cleared. Such a
file is now marked (older ones are recognised by their placeholders) and
importing it keeps the current Plex connection, login, API key, users and
Sonarr/Radarr keys. The redacted export also leaked the API key and user
usernames. Validate no longer flags 24 real settings as unknown or "75%" as
an invalid cache limit; a key-coverage test keeps the list current.

Cache: an unreadable size ("banana") saved with a success message and was
then read as "no limit"; a negative one ("-5GB") parsed as a percentage of
billions and stopped caching. Sizes are validated on save and
parse_size_bytes() never returns a negative.

Schedule: an invalid cron expression saved with "success", then failed when
the job was created, leaving a schedule shown as Enabled that never ran. It
is now refused with the reason. The Validate preview inserts the message as
text.

Users: every save wrote skip_ondeck/skip_watchlist = True for the admin,
because its toggles are rendered disabled and never submitted. A failed Sync
replaced the users table with the error; the table now stays under it.

Integrations: Add appended the new card beside the "none configured"
placeholder; it now re-renders the list. "Settings merged with successfully"
reads "merged successfully".
When setup became incomplete while a page was open, the banner's htmx poll
was redirected to /setup, the browser followed it, and htmx swapped the
whole Setup page into the status pill on top of the current page. HTMX
requests now get HX-Redirect so the page navigates, as auth_middleware
already does for an expired login.
Lucide renders <svg>, so .badge i never applied and badge icons were 24px.
An icon badge was taller than a text-only one beside it, and with baseline
alignment the text-only badge sat lower (Recently Added: 'Returns when
watched' + 'OnDeck'). Size .badge svg at the intended 12px and align badges
by the middle.

Also reload the settings/api routers in two test modules when an earlier
module bound them to a mocked web.config, so they pass in any order.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant