Commit Graph
7 Commits
Author SHA1 Message Date
Steven RYDELL 503cae465f feat(roles): add Enabled/Disabled Permissions count columns
New SCHEMA-DEVIATION: role-permission-count-columns — the Roles list
only shows Description, so seeing how broad or restrictive a role is
required opening it and counting permissions by hand.

Generalized DynamicList's existing alias-count handling (previously
hardcoded to the single `aliasCount` -> `aliases` mapping) into
COUNT_COLUMN_SOURCES, a table of synthetic "*Count" column names to the
real set/objectList property they count. account-alias-count-column
now runs through the same generic path with no behavior change;
role-permission-count-columns (enabledPermissionCount/
disabledPermissionCount -> enabledPermissions/disabledPermissions) is
the second consumer, added with zero new DynamicList.tsx branching.

Verified against the live dev server: correct counts for both seeded
custom roles (Support Agent: 3/0, Read-only Auditor: 1/0) and the
built-in roles (System Administrator: 452/0, User: 244/0, etc.).
Confirmed no regression on Accounts' existing Aliases column/sort.
2026-08-01 22:23:48 +02:00
Steven RYDELL 9cd21a2d34 feat(mailing-lists): add Aliases count column
Same account-alias-count-column deviation already used on Accounts and
Groups, extended to x:MailingList: adds a synthetic aliasCount column
and lets DynamicList's existing generic column-name-driven handling
resolve/render it — no changes needed there, the mechanism was already
list-agnostic.

Verified in the running dev server: the column renders 0 with no
aliases set on either seeded mailing list.
2026-08-01 22:19:35 +02:00
Steven RYDELL 93b10c3ed1 refactor(sort): make client-side column sorting generic, not view-hardcoded
Previous commit hardcoded which lists (viewName === 'x:Account/User' /
'x:Account/Group') and columns (a fixed accessor map) got client-side
sort. Moved the "which columns" decision into the schema itself instead:

- New ClientSortableColumn type in schemaDeviationTypes.ts (intersection
  with the official Column type, same pattern as ClientOnlyFilterEnum —
  src/types/schema.ts stays untouched).
- withAccountListColumns tags Email Address, Full Name, quotaUsage, and
  aliasCount with clientSortable: true when it builds the Accounts/
  Groups column lists — the deviation-specific knowledge lives where the
  columns themselves are defined.
- DynamicList reads that flag generically (clientSortableColumns, a
  useMemo over resolved.list.columns) with no viewName check at all.
  getClientSortValue() replaces the old per-list accessor map: real
  columns compare their own property directly, only the two synthetic
  columns need a value override.

Net effect for Accounts/Groups is unchanged (verified: sort indicators
still only on Email/Full Name/Usage/Aliases, ascending/descending still
works). Any other list can now opt into the same client-sort mechanism
by tagging a column clientSortable, without touching DynamicList.tsx.
2026-08-01 20:32:04 +02:00
Steven RYDELL 518ec4059a feat(accounts): add client-side column sorting to Accounts and Groups
Verified against a live server: x:Account/query rejects sort on every
property tried, including real ones like emailAddress, with
unsupportedSort — the schema's empty list.sort is accurate, this is a
systemic server gap, not something specific to this fork's synthetic
columns.

Added client-side sorting (SCHEMA-DEVIATION: account-client-sort) for
Email Address, Full Name, Usage/Quota, and Aliases on both lists,
reusing the fetch-all-then-sort-locally mechanism already established
for mailbox-client-hierarchy-sort: clicking a sortable header switches
that one query to an unpaginated fetch, sorts the results in memory by
the appropriate accessor (numeric for Usage/Aliases, string compare
otherwise), then paginates client-side. Role isn't included (not a
sortable scalar). Normal server-paginated lists are unaffected — this
only activates when a client-sortable column is actually clicked.

Verified end-to-end: sort indicators appear only on the intended
columns, clicking Email Address/Aliases correctly reorders rows and
toggles ascending/descending, Groups behaves the same as Accounts.
2026-08-01 20:23:42 +02:00
Steven RYDELL 3241dea5e4 feat(accounts): add Aliases count column to Accounts and Groups
Same pattern as the existing quotaUsage deviation: neither list's
schema exposes an alias count as a column, only the full `aliases`
objectList on the detail view. Added a synthetic `aliasCount` column
(SCHEMA-DEVIATION: account-alias-count-column, documented in
SCHEMA_DEVIATIONS.md) that DynamicList resolves by fetching the real
`aliases` property and counting its entries.

Verified against a live test server: adding a real alias to an
account correctly bumps its Aliases count from 0 to 1 in the list.
2026-08-01 20:18:01 +02:00
Steven RYDELL 0aa92c394c feat(accounts): add Usage/Quota column to Groups, show unlimited as ∞
Groups have real usedDiskQuota/quotas fields, same as Users, but the
Groups list schema doesn't expose usage as a column any more than the
Accounts list did — extend the existing account-quota-usage-column
deviation to x:Account/Group too (SCHEMA_DEVIATIONS.md updated).

The isAccountsList gate that resolved/rendered quotaUsage was hardcoded
to viewName === 'x:Account/User', so it silently no-oped for Groups.
Replaced with hasQuotaUsageColumn, derived from whether the resolved
list's own columns include the synthetic quotaUsage column — works for
any list withAccountListColumns patches, not just a hardcoded pair of
view names.

Also: "Unlimited" (no quota configured) now renders as "∞" instead of
the word, matching the size formatting style used elsewhere in the
column.
2026-08-01 20:02:10 +02:00
Steven RYDELL 101b24b361 fix(schema): track client-side schema deviations, restore schema.ts fidelity
src/types/schema.ts had drifted from the official schema contract: a
`clientOnly` field had been added to `FilterEnum` to support client-side
log filtering. Restored it to match upstream exactly and moved the
deviation-only type into a new intersection type in
src/lib/schemaDeviationTypes.ts instead.

Audited the codebase for every place the UI does something the official
schema doesn't support and tagged each with `// SCHEMA-DEVIATION: <id>`,
documented in the new SCHEMA_DEVIATIONS.md registry (what, why, and the
ideal server-side fix):

- log-client-filters: Level/Event filters on Log Entries, applied
  client-side because x:Log/query rejects them as JMAP filters.
- account-quota-usage-column: synthetic quotaUsage column on the
  Accounts list.
- mailbox-client-hierarchy-sort: full-fetch + client-side sort to
  reconstruct mailbox parent/child hierarchy.
- webapp-enabled-column-fallback: synthetic "Enabled" column label for
  x:Application when the schema list doesn't define one.

Other viewName/objectName special cases (x:OtpAuth, x:Expression,
x:Rate, x:Action, x:Trace, CustomComponent/*) were checked against
upstream and are pre-existing architecture, not fork deviations.
2026-08-01 17:54:08 +02:00