#361 · Every timeline list on the dashboard and profiles searches, sorts and pages (#337)
- timeline-app
- pull request
Closes #337 Every timeline list on the dashboard and on profiles can now be searched by words and tag, sorted and paged, each in its own query parameters so a search in one list leaves the others alone. ## What changed - **`platform/lib/timeline-lists.js`** (new, works on the server and in the browser): each list's parameters and options. | List | Parameters | | --- | --- | | Explore timelines (and `/?owner=…`) | `search`, `tag`, `sort`, `page` (+ `owner`) | | Your timelines | `mineSearch`, `mineTag`, `mineSort`, `mineVisibility`, `minePage` | | Your favorites | `favoriteSearch`, `favoriteTag`, `favoriteSort`, `favoriteVisibility`, `favoritePage` | | Drafts in this browser | `draftSearch`, `draftTag`, `draftSort`, `draftPage` | | Profile: public timelines / favorites | `search`… / `favoriteSearch`… | It reads each list's state from the address safely (`readList`), writes back only what differs from the defaults (`listQuery`, `pageQuery`), and builds links that change one list and keep the rest (`listHref`). It also searches browser drafts in the browser (`searchDrafts`): words, `"phrases"` and `-exclusions` over title, description and tags, with relevance, alphabetical, most-moments and recently-changed orders. - **`timeline-search.jsx`**: a general per-list form. It has words, tag, sort, and visibility on your own lists. The other lists' state goes in hidden fields, so a search without JavaScript keeps them too. - **`timeline-list.jsx`**: tag chips filter their own list from page one, the pager keeps the other lists' state, and the list shows its own empty and no-match messages and correct singular/plural counts. The card markup is unchanged here; #338 reworks it. - **`app/page.jsx`**, **`profile.jsx`**, **`browser-drafts.jsx`**: every list gets the form and pager. Your own lists search private timelines too. Profile sections get ids (`profile-timelines`, `profile-favorites`). - **Server**: `searchTimelines` takes a `visibility` filter (`''`, `public`, `private`) and a new `updated` (recently changed) sort. `server/openapi/collaboration.mjs` documents both. - **Drafts**: the drafts list in the browser now records each draft's description and tags (`src/draft-store.ts`, `src/app.ts`), so they can be searched. - **Docs**: `docs/guide.md` (what each list searches by), `docs/browsing.md` (new "Searching the lists" section with the parameters), `docs/architecture.md`. ## Tests - `test/timeline-lists.test.mjs` (new): parameter names never clash on a page, sorts match the server's `SEARCH_SORTS`, state is made safe, links keep other lists' state, plus draft search, phrases, exclusions, paging and status lines. - `test/collaboration.test.mjs`: the `visibility` and `updated` inputs, and the visibility parameter in the SQL. - `test/next-postgres.mjs`: against PostgreSQL, the account's list by words, tag and visibility (private found, public excluded and the reverse); favorites by words, visibility and tag; a profile's two lists each on their own; the owner-filtered explore list; tag links and hidden form fields that carry the other lists' state. - Results: `npm test` (339 pass), `npm run typecheck`, `npx prettier --check` on changed files, `npm run test:platform:postgres`, and `npm run test:platform` with `PLATFORM_BROWSER_TEST=1` in chromium (Playwright container) all pass. The browser-side drafts search is covered by unit tests. #338 adds a live browser test.