[Frontend] Add a wiki search box and fix inconsistent, silently-truncating sidebar pagination #396

Closed
opened 2026-08-25 20:42:31 +00:00 by claude-bot · 2 comments
Contributor

Impact: MEDIUM

Found in the August 2026 session lifecycle review (#319).

What the user experiences

There is no search box anywhere in the wiki — the only way to find an entry is to browse the category tree by hand. Worse, the sidebar that provides that browse tree is implemented twice, and the two implementations disagree: CampaignStoryline's sidebar paginates properly ("Load more (X of Y)"), while WikiArticle's sidebar uses an unpaginated fetch that silently truncates at the backend's default page size of 200. A campaign with more than 200 wiki entries will see an incomplete category tree from WikiArticle with no indication that entries are missing.

Evidence

  • Grep for search in webapp/frontend/src/pages/CampaignStoryline.jsx and webapp/frontend/src/pages/WikiArticle.jsx returns no results — there is no search box anywhere in the wiki.
  • webapp/frontend/src/pages/CampaignStoryline.jsx:136,170-183 — paginates the sidebar with "Load more (X of Y)".
  • webapp/frontend/src/pages/WikiArticle.jsx:1331 — uses the unpaginated fetchLoreEntries, silently truncating at the backend default of 200 (webapp/frontend/src/api/campaigns.js:170).

Why it matters for a hosted product

A campaign that grows past 200 wiki entries — plausible for a long-running hosted game — silently loses part of its own category tree on one of two pages showing the same data, with nothing telling the GM that entries are missing.

Proposed fix

Add a search box to the wiki, covering entry titles at minimum. Unify WikiArticle's sidebar to use the same paginated fetchLoreEntries call CampaignStoryline already uses correctly, so the two pages show a consistent, complete category tree regardless of entry count. This is the audit's P24 and the sidebar-pagination finding from §9.6.

Acceptance criteria

  • The wiki has a search box that finds entries by title (and body, if feasible) from at least one entry point.
  • WikiArticle's sidebar uses the same paginated fetch CampaignStoryline uses, so both show the same complete entry list regardless of campaign size.
  • A campaign with more than 200 wiki entries shows all of them in both sidebars, not a silently truncated subset.
**Impact: MEDIUM** Found in the August 2026 session lifecycle review (#319). ## What the user experiences There is no search box anywhere in the wiki — the only way to find an entry is to browse the category tree by hand. Worse, the sidebar that provides that browse tree is implemented twice, and the two implementations disagree: `CampaignStoryline`'s sidebar paginates properly ("Load more (X of Y)"), while `WikiArticle`'s sidebar uses an unpaginated fetch that silently truncates at the backend's default page size of 200. A campaign with more than 200 wiki entries will see an incomplete category tree from `WikiArticle` with no indication that entries are missing. ## Evidence - Grep for `search` in `webapp/frontend/src/pages/CampaignStoryline.jsx` and `webapp/frontend/src/pages/WikiArticle.jsx` returns no results — there is no search box anywhere in the wiki. - `webapp/frontend/src/pages/CampaignStoryline.jsx:136,170-183` — paginates the sidebar with "Load more (X of Y)". - `webapp/frontend/src/pages/WikiArticle.jsx:1331` — uses the unpaginated `fetchLoreEntries`, silently truncating at the backend default of 200 (`webapp/frontend/src/api/campaigns.js:170`). ## Why it matters for a hosted product A campaign that grows past 200 wiki entries — plausible for a long-running hosted game — silently loses part of its own category tree on one of two pages showing the same data, with nothing telling the GM that entries are missing. ## Proposed fix Add a search box to the wiki, covering entry titles at minimum. Unify `WikiArticle`'s sidebar to use the same paginated `fetchLoreEntries` call `CampaignStoryline` already uses correctly, so the two pages show a consistent, complete category tree regardless of entry count. This is the audit's P24 and the sidebar-pagination finding from §9.6. ## Acceptance criteria - [ ] The wiki has a search box that finds entries by title (and body, if feasible) from at least one entry point. - [ ] `WikiArticle`'s sidebar uses the same paginated fetch `CampaignStoryline` uses, so both show the same complete entry list regardless of campaign size. - [ ] A campaign with more than 200 wiki entries shows all of them in both sidebars, not a silently truncated subset.
Author
Contributor

Picking this up as v4.3.0 phase 6 (#514), last on the wiki lane. A search box reachable from the wiki home and the article sidebar (titles at minimum, via a small additive query parameter on the list endpoint if the backend has none), and the article sidebar moves onto the same paginated fetch the wiki home uses, so a campaign past 200 entries sees all of them on both pages.

Picking this up as v4.3.0 phase 6 (#514), last on the wiki lane. A search box reachable from the wiki home and the article sidebar (titles at minimum, via a small additive query parameter on the list endpoint if the backend has none), and the article sidebar moves onto the same paginated fetch the wiki home uses, so a campaign past 200 entries sees all of them on both pages.
Author
Contributor

Done in PR #527 (auto-merging on green); ships with v4.3.0.

No backend change was needed. The plan offered a q parameter as a fallback if the list endpoint had no search; it already has ?search=, implemented in lore_service.list_lore_entries, covering title, body, aliases and the viewer-visible structured fields, with existing tests. Adding q would have been a second name for the same behaviour, so the search is a pure frontend addition.

New WikiSearch component: debounced 200 ms, two-character minimum, server-side (a client-side filter could only ever find what the rail had already loaded, and the backend's search reaches the body and aliases too). One box per page, where that page navigates from: the main column on the wiki home, so it is reachable below md, and the rail on the article page, which has no other nav surface.

WikiArticle's rail was on the unpaginated fetchLoreEntries, capped at 200, so a long-running campaign's rail simply ended with nothing saying so. It now uses the same paginated fetch and "Load more (X of Y)" as the wiki home, which also widens the entry set behind [[wiki links]] and the relationship picker.

Results are titles only: an entry-type chip would have been a fourth copy of the TYPE_LABELS map that already lives in WikiArticle, CampaignStoryline, WikiProposals and CampaignDetail. Extracting that taxonomy into one module is a sensible small follow-up for the release-readiness pass.

7 new tests; the lane's frontend suite ends at 616 passed.

Done in PR #527 (auto-merging on green); ships with v4.3.0. No backend change was needed. The plan offered a `q` parameter as a fallback if the list endpoint had no search; it already has `?search=`, implemented in `lore_service.list_lore_entries`, covering title, body, aliases and the viewer-visible structured fields, with existing tests. Adding `q` would have been a second name for the same behaviour, so the search is a pure frontend addition. New `WikiSearch` component: debounced 200 ms, two-character minimum, server-side (a client-side filter could only ever find what the rail had already loaded, and the backend's search reaches the body and aliases too). One box per page, where that page navigates from: the main column on the wiki home, so it is reachable below `md`, and the rail on the article page, which has no other nav surface. `WikiArticle`'s rail was on the unpaginated `fetchLoreEntries`, capped at 200, so a long-running campaign's rail simply ended with nothing saying so. It now uses the same paginated fetch and "Load more (X of Y)" as the wiki home, which also widens the entry set behind `[[wiki links]]` and the relationship picker. Results are titles only: an entry-type chip would have been a fourth copy of the `TYPE_LABELS` map that already lives in `WikiArticle`, `CampaignStoryline`, `WikiProposals` and `CampaignDetail`. Extracting that taxonomy into one module is a sensible small follow-up for the release-readiness pass. 7 new tests; the lane's frontend suite ends at 616 passed.
Sign in to join this conversation.
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
rbrooks/Quest-Board#396
No description provided.