feat(kb): show the measured duration on the article #488

Merged
longjacksonle merged 2 commits from feat/PMS-732-article-measured-duration into main 2026-08-06 21:52:25 +02:00

Final slice of the client-request frontend, after #485, #486 and #487. The article that documents a procedure now shows how long that procedure has actually been taking.

Adds a Measured duration card at the top of the KB article's right rail, above version history, reading GET /kb/articles/{id}/measured-duration (mokosh-server #499).

What it shows

The typical per-request figure, the sample it was drawn from, and the window it covers. Rendered through fmt_duration, so it honours the user's stored h:mm or decimal preference like every other duration in the app.

Details worth reviewing

Three states, kept distinct on purpose.

  • A measurement shows the average alongside its sample size, so a confident-looking number is never detached from how much evidence sits behind it.
  • No data says so plainly and explains what would make it appear, rather than rendering 0h. Zero minutes would be a measurement ("these take no time"); the absence of one is not the same claim, and the server is careful to send null rather than zero for exactly this reason.
  • A failed fetch says the load failed rather than reusing the no-data copy. Saying "no time measured yet" about something we did not manage to look at would be a false statement rather than an absent one.

The period is always rendered. The server defaults this endpoint to a trailing 90 days, deliberately unlike the calendar-month accounting /reports/request-types uses, because an estimate needs a sample. Showing the window keeps the two numbers from looking like they disagree when a reader sees both.

It measures the request type, not the category. The server joins through form_submissions, so ad-hoc tickets carrying the same article are excluded. Nothing to do here beyond not undoing it, but it is why the figure is trustworthy as an estimate.

Verification

cargo check --target wasm32-unknown-unknown, cargo fmt --all --check, cargo test (261 passed, 0 failed), and both guard scripts.

The two pre-existing clippy failures in src/pages/projects.rs and src/pages/time.rs are unchanged and unrelated (flagged on #485, #486 and #487).

Loop status

With this merged, the whole client-request loop is reachable from the UI: define a form, send a client the link, they fill it in, it becomes a ticket carrying the procedure, time is tracked against it, and the measured duration comes back to the article for the next person.

Final slice of the client-request frontend, after #485, #486 and #487. The article that documents a procedure now shows how long that procedure has actually been taking. Adds a **Measured duration** card at the top of the KB article's right rail, above version history, reading `GET /kb/articles/{id}/measured-duration` (mokosh-server #499). ## What it shows The typical per-request figure, the sample it was drawn from, and the window it covers. Rendered through `fmt_duration`, so it honours the user's stored h:mm or decimal preference like every other duration in the app. ## Details worth reviewing **Three states, kept distinct on purpose.** - A measurement shows the average alongside its sample size, so a confident-looking number is never detached from how much evidence sits behind it. - No data says so plainly and explains what would make it appear, rather than rendering `0h`. Zero minutes would be a measurement ("these take no time"); the absence of one is not the same claim, and the server is careful to send null rather than zero for exactly this reason. - A failed fetch says the load failed rather than reusing the no-data copy. Saying "no time measured yet" about something we did not manage to look at would be a false statement rather than an absent one. **The period is always rendered.** The server defaults this endpoint to a trailing 90 days, deliberately unlike the calendar-month accounting `/reports/request-types` uses, because an estimate needs a sample. Showing the window keeps the two numbers from looking like they disagree when a reader sees both. **It measures the request type, not the category.** The server joins through `form_submissions`, so ad-hoc tickets carrying the same article are excluded. Nothing to do here beyond not undoing it, but it is why the figure is trustworthy as an estimate. ## Verification `cargo check --target wasm32-unknown-unknown`, `cargo fmt --all --check`, `cargo test` (261 passed, 0 failed), and both guard scripts. The two pre-existing clippy failures in `src/pages/projects.rs` and `src/pages/time.rs` are unchanged and unrelated (flagged on #485, #486 and #487). ## Loop status With this merged, the whole client-request loop is reachable from the UI: define a form, send a client the link, they fill it in, it becomes a ticket carrying the procedure, time is tracked against it, and the measured duration comes back to the article for the next person.
Mirrors the shape `GET /kb/articles/{id}/measured-duration` returns.

Every measurement field is `Option` and they move together, matching the server: an article no request type has tracked time against reports null, not zero. Zero minutes would be a measurement ("these take no time"), and rendering that as a confident estimate is worse than the hand-written guess this is meant to replace.

`from` and `to` are always present, so a rendered figure can never be ambiguous about what window it measured.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011myibMMwyb6za3GVWJGkiX
feat(kb): show the measured duration on the article
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 1m36s
Create release / Create release from merged PR (pull_request) Has been skipped
4641b0fd5e
Closes the client-request loop: the person about to perform a change reads how long it has actually been taking instead of a hand-written guess.

Sits at the top of the article's right rail, above version history, because it is the number they came for. Renders through `fmt_duration`, so it honours the user's stored h:mm or decimal preference like every other duration in the app, and states the window it covers because the server's default is a trailing 90 days rather than a calendar month.

Three states, kept distinct on purpose. A measurement shows the typical per-request figure with the sample it was drawn from, so a confident-looking number is never detached from how much evidence is behind it. No data says so plainly and explains what would make it appear. A failed fetch says the load failed rather than reusing the no-data copy, because claiming "no time measured yet" about something we did not manage to look at would be a false statement rather than an absent one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011myibMMwyb6za3GVWJGkiX
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-08-06 21:51:38 +02:00
longjacksonle deleted branch feat/PMS-732-article-measured-duration 2026-08-06 21:52:25 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-apps!488
No description provided.