Give the Admin tab sub-sections of its own
Administration was one scrolling page with three cards on it: the teams, the people, and the settings. There was no way to link somebody to the settings, no way back to the top of the user list but scrolling, and the poll loop refetched all three endpoints every tick however little of the page you were looking at. Each is now a route -- /admin/teams, /admin/users, /admin/settings -- reached from a strip across the top, with /admin an overview that says how many of each there are. The three cards themselves are untouched; they are simply rendered one at a time, so a tab fetches only what it shows. The Users page is the exception and fetches the teams too, since its invite form has to offer a team to invite somebody into. The strip is ordinary links rather than chips. Chips filter what a page already shows, here and in the queue, and these four go somewhere: the browser's Back walks them, a reload lands where you were, and the click is intercepted by the same handler every other link in the app uses. The current one is marked with aria-current="page", the convention the tab bar has used since it existed, so the state lives on the attribute and not in a class. admin.js owns the table of the four routes, because it also builds the strip that links to them; app.js parses against that table rather than keeping a second list to drift from it. Adding a fifth sub-section is one line. The bottom tab bar still has six items.56b8191made it count-agnostic when Admin arriving pushed it past four, and the note there records that six at 420px already leaves 55-65px each -- so the sub-sections went inside the Admin page rather than beside it. A person's page keeps its own route at /admin/users/{id}; its back link now returns to the user list rather than to the top of everything. Nobody has looked at this in a browser, the same caveatac9af8ecarried. What is checked is the wiring: the module graph evaluates at every admin URL, all four tabs render against live server responses with one aria-current each and the fetches the table above describes, the non-administrator branch still refuses without fetching, and the server serves index.html for each new path so a reload survives. The strip's appearance at phone and desktop width is not checked. Claude-Session: https://claude.ai/code/session_01RHPj4ggeFdEjKKfm4SHbD7
This commit is contained in:
@@ -92,14 +92,17 @@ the server refuses their writes anyway. Somebody in more than one team picks
|
||||
between them at the top.
|
||||
|
||||
The **Admin** tab appears only for a system administrator, and holds what
|
||||
belongs to the whole server rather than to one team: every team, every user, and
|
||||
the settings that used to be environment variables. Adding somebody is minting
|
||||
them an invite link into a team, rather than creating a bare account: the person
|
||||
who accepts it picks their own password, so one never passes through an
|
||||
administrator, and the link carries the team, so they land somewhere with a
|
||||
belongs to the whole server rather than to one team. It has three sub-sections,
|
||||
each with a URL of its own and a strip across the top to move between them:
|
||||
every team (`/admin/teams`), every user (`/admin/users`), and the settings that
|
||||
used to be environment variables (`/admin/settings`). `/admin` itself is an
|
||||
overview — how many of each, and what each section is for. Adding somebody is
|
||||
minting them an invite link into a team, rather than creating a bare account:
|
||||
the person who accepts it picks their own password, so one never passes through
|
||||
an administrator, and the link carries the team, so they land somewhere with a
|
||||
queue in it.
|
||||
|
||||
A name in that list opens **that person's page**, at `/admin/users/{id}`: their
|
||||
A name in the user list opens **that person's page**, at `/admin/users/{id}`: their
|
||||
email and when they joined, where their notifications go, whether they are an
|
||||
administrator, whether the account is disabled, the teams they are in with their
|
||||
role in each, a password field for a first or forgotten one, and deletion. It is
|
||||
|
||||
Reference in New Issue
Block a user