The UI was uneven: the home page looked finished, but app pages used three
different display typefaces, the anonymize flow changed frame between steps,
and the dashboard, explorer and admin screens each had their own controls,
status colours and edge-case handling.
Make every screen follow one system: shared page header, grid, buttons,
filters and status colours; a repository picker and step trail on anonymize;
a "What reviewers will see" preview of the actual reviewer page; consistent
file headers and viewers for every file type; truthful admin charts and
tables. Fold the accumulated override blocks back into style.css (22%
smaller, no visual change).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Go to line: themed popover under the file toolbar (line or line:column,
range check) instead of Ace's unthemed prompt
- Code selection: no per-box outline, so multi-line selections no longer
overlap at the joins; single-line matches keep an inset outline
- My work: copy-link is an icon button (URL in the tooltip); phone cards
drop the URL row and truncate long names
- Date fields: drop WebKit's native button styling so they fit their column
- Submit bar: the checkout note gets its own line under the button
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Admin errors: filters stack on phones (tabs, search, Sort and Group,
refresh) instead of squeezing into one row
- Admin overview: Summary / Performance / Cache views, kept in the URL
hash; charts take the full width on phones
- Phone menu: aligned rows with icons, neutral fill for the current page,
account links inline, no duplicate Sign in
- My work: removed and expired projects get a labelled badge, a muted
"Link offline" in place of the copy link, and an inline Enable/Extend
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Viewer: full-height app bar with a Help menu, search + ZIP sidebar, one
toolbar for README and code, reading mode with a scroll-tracking outline,
docked find for Markdown and code, and redaction slots (a blank stone slot
holding the term number) in prose, headings, code, the tree and the path.
Landing and FAQ: live redaction demo, serif display headings, teal accent.
Author screens: My work table with copy/open/edit actions, a usage meter,
a single-container New anonymization flow with a sticky submit bar, themed
form controls, and consistent GitHub connection cards.
Admin: underline tabs, severity-first errors chart and list, error tiles
that filter (older pages load until matches appear), queue and overview
health states, and shared toolbar heights and borders.
Fixes: guarded localStorage access, failed README images render a
placeholder, phone hover states no longer stick, and UI tests updated for
the new copy and markup.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dashboard showed the anonymize date under "Expired", a dash in the
Expires column for 54 of 60 rows, raw status codes such as
branch_not_found, and a chip reading "REMOVED" that actually meant
"removed items are hidden". Muted text sat at 3.5:1 contrast, keyboard
focus was invisible, numbers were left-aligned, and a legacy record
without an identifier rendered as an empty link to /pr/undefined/.
This rewrites the dashboard template and controller and tightens the
theme tokens:
- Status sub-line is labelled ("anonymized on Sep 6, 2026"); Expires
shows Never, the date, or "Expired on <date>".
- Conference folded into the name cell as a tag; Views right-aligned;
every column header is a keyboard-sortable button with aria-sort.
- Sort/Status buttons show their state; chips read "Hiding Removed";
result count and Clear filters; empty state with a way out.
- Status filter covers Ready, In progress, Error, Expired, Removed.
Stuck downloads say so; codes map to sentences; statuses to labels.
- Lists load in parallel and merge once behind a skeleton; broken
records are flagged instead of linking nowhere.
- Actions menu: View, View page, Edit, Force update, divider, Remove,
all as buttons rather than href="#" anchors.
- Theme: warm dark canvas, muted text >= 4.5:1 in both modes, semantic
status tokens, 11/13/14/16px type scale, mono only for identifiers,
6px/10px/pill radii, :focus-visible ring, quota bars in ink until a
limit is near, unlimited shown as such.
- Mobile: no 9px text, filter row wraps in two lines, meta on one line.
Adds scripts/dev-mock.js to serve the dashboard with fixture data and
test/dashboard-ui.test.js covering the filters, template invariants and
token contrast.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The Conference cell is a grid item with the default min-width:auto,
so a long unbroken URL forces the grid track wider than its
minmax(140px, 1fr) size and bleeds visually into the Status column.
Clip it with overflow:hidden/ellipsis and expose the full value via
a title attribute.
* fix: dashboard menu clickability + expiration date UX
Dashboard actions menu:
- Inactive (expired/removed) rows dimmed via their cells instead of the
row, so `opacity` no longer creates a stacking context that trapped the
actions dropdown beneath later rows and made its items unclickable.
- Add an "Extend 6 months" menu item for expired repos/PRs/gists.
Expiration form (anonymize):
- Fix the "After , the content will be removed." blank date: guard the
helper text and add min/max validation feedback so an invalid pick no
longer nulls the model into a broken sentence.
- Add a `min` (today) so past dates can no longer be selected, and
compute min/max from local date parts (not UTC) to avoid a timezone
off-by-one in the native picker.
- Default expiration is now 6 months (single source of truth, removing a
latent double-offset bug); max stays at 1 year.
- Block submitting a missing/out-of-range expiration date.
Backend:
- New POST /:id/extend endpoint for repos, PRs and gists that pushes the
expiration +6 months and re-anonymizes so expired items come back
online, mirroring the refresh flow. Shared extendExpirationDate helper.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: add frontend translation for invalid_status error code
The new /extend endpoints throw an "invalid_status" AnonymousError, which
the error-code coverage test requires to have a locale entry.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The Remove action in the dashboard dropdown was gated on
status == 'ready', so expired repos showed no way to be removed and
stuck on the front page. The backend DELETE route already accepts any
non-'removed' status, so widen the ng-show to include 'expired' and
'error'.
Fixes#463.