The exact issuance and expiry times in the device rows' hover titles were
rendered in UTC, which reads as wrong to anyone not living there.
- Mark the dates with a <time> element carrying the absolute (UTC) timestamp,
rather than a custom data attribute whose name claimed to hold local time
- Rewrite those titles in the browser's own zone, keeping the server's UTC
rendering as the fallback for when JavaScript is unavailable
- Only convert values that carry an explicit offset, so a date-only <time> is
not read as UTC midnight and shifted onto the previous day
- Give the revoke button a little more room from the device name and dates
Part of #254
Revoking a device redirected away from the storage dashboard, which closed the
details modal and reloaded the page. Refreshing the affected parts instead
keeps the modal open and shows the change where it happened.
- Extract the card and the modal's access list into their own components, so
either can be re-rendered without touching the modal's open state, and share
the group summaries between the components
- Derive the app's DOM ids from its client_id (the grouping key) and the device
row ids from the authorization, through one helper used by both the templates
and the controller
- Revoke one of several devices as a Turbo Stream: remove the row and refresh
the card behind the modal and the access list
- Revoke an app's last device with a redirect, so the dashboard re-renders
itself and grouping, sorting and the empty state stay in one place
- Fade the removed row out, deferring Turbo's own removal until the animation
has ended
Part of #254
* Show sats instead of BTC on donation page
* Use number delimiters on both donation page and wallet page
* Refactor donation page CSS into Tailwind directives
The production build was purging input[type=text] styles, because it
couldn't find it in the Rails templates. Change config, so it only
purges utility classes.