Skip to content

Add the desk as the landing page with the six queues - #2568

Merged
pournasserian merged 2 commits into
v2from
2562-desk-queues
Oct 19, 2026
Merged

pournasserian merged 2 commits into
v2from
2562-desk-queues

Conversation

@pournasserian

Copy link
Copy Markdown
Member

Closes #2562

What

The first slice of F-DSK (#2422): the desk is the landing page after sign-in (DSK-01) and shows the six queues with their counts (DSK-02).

  • Core read side (FluentCMS.Core.ChangeSets):
    • IChangeSetLists, separate from IChangeSetDirectory. ListAsync(ChangeSetListQuery) returns one page of ChangeSetSummary and the total, and CountAsync returns only the total.
    • ChangeSetListQuery names the states, an optional EnteredSince, newest or oldest first, an offset and a limit (1 to 200). A bad window fails with offset_invalid or limit_invalid, and no states with list_states_missing.
    • ChangeSetSummary has the id, rationale, initiator, state, item count, the set it reverts, OpenedAt and StateSince.
  • Core desk (FluentCMS.Core.Desk): DeskQueue and IDeskQueues, which define each queue once, for this screen and for the agents' desk tools in a later slice.
  • Infrastructure: ChangeSetLists in its own file. ChangeSetDirectory is untouched.
  • Admin: Desk.razor at / replaces the placeholder home page.
    • A queue navigation with counts, where each queue is a URL (/?queue=checks-failed&page=2) and the current one has aria-current="page".
    • The list shows, for a set: its rationale, initiator badge, item count, a Revert badge and the time it entered its state.
    • For a stale fact: the entity type and short id, the field, Expired or Unverified, since when, and whether the published version or the latest draft holds it.
    • Pages of 50 with previous and next links. An empty queue and a page past the end each say so.
    • Until the set view lands, a set links to its audit history and a fact to its entity's history.
    • The header gets a Desk link.

Why

Choices worth a look:

  • Times from the audit log, not new columns. Every transition appends an event whose subject is the set, so the open event is when the set was opened and the last move event is when it entered its state. Other events about a set, such as a refused agent move, are left out. This needs no migration and leaves ChangeSetDirectory to its lane. The query is SQL because EF Core will not compare or order a DateTimeOffset on SQLite. AuditReader and AgentActivity already rely on stored UTC text sorting in time order.
  • Static server rendering. The queues are reads, and a queue and page as a URL can be bookmarked and shared. This follows /agents and /users. The set view's diff will be an interactive island when it needs progressive rendering.
  • Seven days for "recently". The epic gives no window. Seven days keeps the count meaningful, and DeskQueues.RecentWithin is the one place to change it.
  • Awaiting me. The page says on the queue that it lists every set awaiting review until approvals exist.
  • Not in this PR: the set view, review actions, keyboard batch review, notification counts in the header, security events and the desk tools for agents. Those are the next slices of F-DSK: Review desk as the home screen #2422.

Tests

Unit:

  • DeskQueuesTests: each change set queue selects its state, window and order. The counts cover all six queues. Stale facts are paged in their order. A failed fact read fails the counts. Stale facts is not a queue of change sets.
  • bUnit DeskTests:
    • The six queue links have their counts, and awaiting me is current with its note.
    • A set row has its rationale, history link, initiator, item count, time and revert badge.
    • The queue and page come from the address, and an unknown queue or page falls back to the first.
    • Previous and next links appear only where they lead somewhere.
    • An empty queue, a page past the end and a refused read are each reported.
    • A stale fact row has its reason, entity link and holders.
    • Only logical utilities are used.

Integration, each on SQLite and PostgreSQL:

  • Every queue lists its sets in its order and counts them, with sets in all eight states. A published set older than seven days is left out, and a revert set awaiting review names the set it reverts.
  • A page returns its window and the total, newest first included. The time window counts and lists the same sets, whatever the offset of the time given, and a refused agent move does not change when a set entered its state.
  • The stale facts queue lists expired before unverified facts, longest stale first, and pages them.
  • Reading every queue appends no event.

Integration, host:

  • An anonymous request for the desk goes to sign-in with its return URL.
  • Signing in lands on / with the six queues and their counts, and the sets awaiting review are listed. A queue with nothing in it says so.
  • The desk renders with dir="rtl".

dotnet build -warnaserror and the full suite pass locally against a postgres:17 container as well as SQLite. No new package and no new project reference.

Checklist

  • Linked to an issue a maintainer has confirmed
  • Targets v2
  • Tests or docs updated where behaviour changed
  • No tool-generated co-author trailers or footers

@pournasserian pournasserian added this to the M1 Governance core milestone Oct 19, 2026
@pournasserian pournasserian added type:feature New capability v2 FluentCMS v2 (v2 branch) area:desk labels Oct 19, 2026
@pournasserian
pournasserian merged commit 5221a84 into v2 Oct 19, 2026
2 checks passed
@pournasserian
pournasserian deleted the 2562-desk-queues branch October 19, 2026 04:01
pournasserian added a commit that referenced this pull request Oct 19, 2026
… page (#2647)

Closes #2631

## What

A Low finding from the independent review of #2568 (F-DSK, #2422). A
`page` that didn't parse, such as `abc` or `99999999999`, answered an
empty 500 on the desk and on `/security`.

- The desk and the security view read `page` as text and parse it with
`int.TryParse`. A value that doesn't parse shows the first page, as 0
and negative values already did.

## Why

- **Text, not `int?`.** Blazor throws while binding a query value that
doesn't parse, before the page can fall back. Reading text keeps the
fallback in the page.

## Tests

- bUnit: `page=abc`, `page=99999999999` and an empty `page` show the
first page on both views.
- Host: the same addresses answer 200 on both views.

`dotnet build -warnaserror`, the unit and bUnit suite and the desk host
tests pass locally. No new package and no new project reference.

## Checklist

- [x] Linked to an issue a maintainer has confirmed
- [x] Targets `v2`
- [x] Tests or docs updated where behaviour changed
- [x] No tool-generated co-author trailers or footers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:feature New capability v2 FluentCMS v2 (v2 branch)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Desk shell: the desk as the landing page with the six queues

1 participant