diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-16 08:18:42 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-16 08:18:42 -0800 |
| commit | de741fa9c5491787ab1e55dcb8b361a598fc945a (patch) | |
| tree | bd5d3cd3014193ba853f1f0a85a9dffddd194320 | |
| parent | 795d48fe18c38422fe63ffa900c26405e395ade2 (diff) | |
| download | neko-de741fa9c5491787ab1e55dcb8b361a598fc945a.tar.gz neko-de741fa9c5491787ab1e55dcb8b361a598fc945a.tar.bz2 neko-de741fa9c5491787ab1e55dcb8b361a598fc945a.zip | |
Implement settings toggle logic and refactor sidebar navigation
- Close NK-s8nytj: Settings page close behavior
- Update frontend-vanilla/src/main.ts to toggle settings/filter navigation
- Add tests in frontend-vanilla/src/main.test.ts for navigation logic
- Created NK-gxvegm for feed/tag settings behavior
- Created NK-f64ocp for routing logic refactor
| -rw-r--r-- | .thicket/tickets.jsonl | 7 | ||||
| -rw-r--r-- | frontend-vanilla/src/main.test.ts | 27 | ||||
| -rw-r--r-- | frontend-vanilla/src/main.ts | 14 |
3 files changed, 45 insertions, 3 deletions
diff --git a/.thicket/tickets.jsonl b/.thicket/tickets.jsonl index e17f556..b99cc2c 100644 --- a/.thicket/tickets.jsonl +++ b/.thicket/tickets.jsonl @@ -15,6 +15,7 @@ {"id":"NK-3om7x2","title":"Implement Feed Items View","description":"Create a component to display items for a selected feed. Fetch items from /api/stream?feed_id=...","type":"","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T05:59:46.161356437Z","updated":"2026-02-13T14:55:14.795643835Z"} {"id":"NK-4juza2","title":"v2 ui - collapsible feed list","description":"In the left side navigation list of feeds, the feeds should be hidden by default. The word \"feeds\" should be a toggle to show/hide the list, with a triangle that indicates state.","type":"feature","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T02:48:25.194856022Z","updated":"2026-02-14T03:16:19.259726648Z"} {"id":"NK-4jy0t2","title":"Implement Mocked-API UI Tests","description":"Configure Playwright to intercept /api/ requests and return mock JSON. This decouples UI testing from the backend, reducing VM crash risk and enabling fast UI iteration.","type":"task","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-15T16:23:32.209848684Z","updated":"2026-02-15T21:47:24.97680381Z"} +{"id":"NK-4p3s91","title":"Page title \"frontend-vanilla\" should be \"neko\"","description":"Frontend-vanilla is like, an internal thing. The app should just show up at \"neko\" in browser title bar.","type":"task","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-16T16:18:00.411259747Z","updated":"2026-02-16T16:18:00.411259747Z"} {"id":"NK-4y484t","title":"last item behavior on mobile","description":"I think there's a bug where if the last item on screen on mobile isn't \"big\" enough it won't trigger loading more items, but not sure. please verify the behavior.","type":"bug","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-15T16:46:38.025288816Z","updated":"2026-02-15T16:50:36.390669216Z"} {"id":"NK-4yjicm","title":"Create api/reader package and middleware","description":"","type":"task","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-15T00:21:45.866133071Z","updated":"2026-02-15T00:44:41.290163192Z"} {"id":"NK-59kbij","title":"Implement Frontend Logout","description":"Add logout button to dashboard header. Call /api/logout (need to create this potentially?). Redirect to /login","type":"","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T14:58:18.343464645Z","updated":"2026-02-13T15:01:33.783216589Z"} @@ -62,6 +63,7 @@ {"id":"NK-edahin","title":"v3: cut \"FILTERS\" text","description":"there's no header needed above unread/read/starred, just cut that please","type":"task","status":"open","priority":1,"labels":null,"assignee":"","created":"2026-02-16T15:48:13.470233363Z","updated":"2026-02-16T15:48:13.470233363Z"} {"id":"NK-ek0cox","title":"Implement Item Interactions","description":"Add ability to toggle read/unread and star/unstar status for items. Use PUT /item/:id","type":"","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T14:55:14.825454967Z","updated":"2026-02-13T14:58:18.307521003Z"} {"id":"NK-exyau3","title":"check coverage again","description":"check test coverage again and see if more tests are needed","type":"task","status":"closed","priority":3,"labels":null,"assignee":"","created":"2026-02-15T00:07:39.320521992Z","updated":"2026-02-15T05:31:22.48357749Z"} +{"id":"NK-f64ocp","title":"Refactor routing logic for consistent settings exit","description":"Instead of checking 'if currentRoute.path == /settings' in every click handler, maybe centralize this logic in the router or a helper function to ensure consistent behavior when navigating away from settings.","type":"cleanup","status":"open","priority":4,"labels":null,"assignee":"","created":"2026-02-16T16:17:36.299928698Z","updated":"2026-02-16T16:17:36.299928698Z"} {"id":"NK-fkc119","title":"setup github ci","description":"Maybe it'd be nice to have github run the tests. Is that a thing we can try to setup","type":"feature","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T03:16:32.574415787Z","updated":"2026-02-14T03:23:01.837550873Z"} {"id":"NK-fm15vq","title":"UI: Improve accessibility for star icon","description":"The new star button should have proper aria-labels and potentially better focus states for screen readers.","type":"task","status":"closed","priority":3,"labels":null,"assignee":"","created":"2026-02-13T20:27:36.768034045Z","updated":"2026-02-13T20:27:36.768034045Z"} {"id":"NK-fnaohu","title":"UI Styling: Dark Mode Support","description":"","type":"","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T18:05:19.59504351Z","updated":"2026-02-13T18:11:46.326064329Z"} @@ -77,6 +79,7 @@ {"id":"NK-gjymiw","title":"FEEDS in sidebar needs to be more clearly a collapsible thing","description":"FEEDS in the sidebar needs a caret (\u003e that turns to V) or something similar to make it clear it's a toggle collapsible list thing","type":"feature","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T23:54:20.355824171Z","updated":"2026-02-15T00:06:02.456524674Z"} {"id":"NK-gnxc6e","title":"Feed list collapsed by default","description":"The list of feeds on the left side should be collapsed by default, with a little control to extend it.","type":"feature","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T00:58:15.661695308Z","updated":"2026-02-14T01:29:12.82081713Z"} {"id":"NK-gqkh96","title":"Remaining test coverage gaps","description":"Cross-package test coverage is at 81.2%. The remaining untested functions are: GetFullContent (goose HTTP extraction), indexHandler/serveBoxedFile (rice.MustFindBox), Serve (starts HTTP server), main, util.init. To reach 90%, consider: (1) refactoring GetFullContent to accept an interface for HTTP fetching, (2) refactoring Serve to extract route setup into a testable function, (3) mocking rice.MustFindBox, (4) using feeds from https://trenchant.org/feeds.txt as static test fixtures for integration tests.","type":"cleanup","status":"closed","priority":3,"labels":null,"assignee":"","created":"2026-02-13T03:54:30.298141982Z","updated":"2026-02-14T02:44:05.399097286Z"} +{"id":"NK-gxvegm","title":"Settings page toggle behavior for feeds and tags","description":"Currently only 'filters' and 'settings' link toggle away from settings page. We should probably implement similar behavior if clicking on a feed or tag while on the settings page (it currently might work by accident due to direct navigation, but we should verify).","type":"task","status":"open","priority":4,"labels":null,"assignee":"","created":"2026-02-16T16:17:21.4431998Z","updated":"2026-02-16T16:17:21.4431998Z"} {"id":"NK-hidz4w","title":"Add Local Git Hooks","description":"Create a script/make target to install a pre-push hook that runs 'make check'. This enforces quality gates locally, keeping the CI clean.","type":"task","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-15T16:23:36.906173277Z","updated":"2026-02-15T17:25:28.129358055Z"} {"id":"NK-hj6f9p","title":"Investigate E2E Tag View flakiness","description":"The E2E test for /v2/tag/Tech was temporarily disabled because it was timing out/failing. Investigate if it's a race condition or a routing issue.","type":"bug","status":"closed","priority":4,"labels":null,"assignee":"","created":"2026-02-15T01:04:54.404114014Z","updated":"2026-02-15T19:14:17.974207248Z"} {"id":"NK-hspao2","title":"Vanilla JS: Implement Test Infrastructure","description":"Setup testing infrastructure for vanilla JS prototype to ensure 80% coverage. Refactor app.js for testability and add unit tests.","type":"task","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T05:13:11.587767054Z","updated":"2026-02-14T05:13:11.587767054Z"} @@ -131,7 +134,7 @@ {"id":"NK-rn4nzp","title":"font themes","description":"in the v2 ui, let's offer a few different font stacks the user can switch through. primarily this should just change font-face, maybe size, but don't worry about colors or anything right now.\n\nthe current default (helvetica neue, palatino)\na fancy all serif stack\na no-nonsense modern san-serif stack\na terminal inspired fixed width stack","type":"feature","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-14T17:10:02.185477382Z","updated":"2026-02-14T18:12:30.253145852Z"} {"id":"NK-rohuiq","title":"titles changing on read state and hover","description":"Titles are changing on read state from blue to grey. They should just stay blue all the time.\n\nTitles are getting underlined on hover. They should have no underline regardless of hover state.","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T03:36:26.36373162Z","updated":"2026-02-14T03:37:50.73870586Z"} {"id":"NK-s2g59a","title":"change scroll mark-as-read criteria","description":"Currently items are marked as read immediately when 50% visible. This might be annoying if users are scrolling fast. We change it 100% viewable, ie the bottom has scrolled into view.","type":"bug","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-16T15:37:40.617999342Z","updated":"2026-02-16T15:37:40.617999342Z"} -{"id":"NK-s8nytj","title":"v3: close settings","description":"when settings page is shown, clicking settings again should close it and go back to the \"unread items\" state\n\nsimilarly, clicking \"unread\" or \"all\" or \"starred\" should close settings and take you to those.","type":"bug","status":"open","priority":1,"labels":null,"assignee":"","created":"2026-02-16T15:40:59.195773828Z","updated":"2026-02-16T15:40:59.195773828Z"} +{"id":"NK-s8nytj","title":"v3: close settings","description":"when settings page is shown, clicking settings again should close it and go back to the \"unread items\" state\n\nsimilarly, clicking \"unread\" or \"all\" or \"starred\" should close settings and take you to those.","type":"bug","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-16T15:40:59.195773828Z","updated":"2026-02-16T16:17:20.080233097Z"} {"id":"NK-sdxq5p","title":"update documentation based on all the recent changes","description":"update README.md based on what's been changed given all the CLs and tickets recently","type":"task","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-15T00:07:09.08704631Z","updated":"2026-02-15T00:24:50.622207852Z"} {"id":"NK-shpyxh","title":"add search to new ui","description":"","type":"epic","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T19:29:44.251257089Z","updated":"2026-02-14T01:02:58.547025683Z"} {"id":"NK-sk6pym","title":"fix docker-compose","description":"bug when trying to build in docker -- we may want to add an automated test for this later (though it may be hard since we're building in a vm to nest these)\n\n--\u003e 668e2e2c4b44\n[2/3] STEP 3/9: WORKDIR /app\n--\u003e b42c7c265b7f\n[2/3] STEP 4/9: COPY go.mod go.sum ./\n--\u003e 093e4d9b623e\n[2/3] STEP 5/9: RUN go mod download\n--\u003e 208c8aaac5eb\n[2/3] STEP 6/9: COPY . .\n--\u003e 7c44260c3ac0\n[2/3] STEP 7/9: COPY --from=frontend-builder /app/frontend/dist ./frontend/dist\n--\u003e 09749e6660e1\n[2/3] STEP 8/9: RUN rice -i ./web embed-go\n2026/02/14 17:34:13 no calls to rice.FindBox() found\n--\u003e cdc88c64da36\n[2/3] STEP 9/9: RUN go build -o neko .\nno Go files in /app\nError: building at STEP \"RUN go build -o neko .\": while running runtime: exit status 1","type":"bug","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T17:38:05.696339994Z","updated":"2026-02-14T18:06:42.659012133Z"} @@ -159,6 +162,7 @@ {"id":"NK-zt4e32","title":"Implement Frontend Feed List","description":"Create feed list view in new frontend. Fetch feeds from API.","type":"task","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T05:44:01.58866298Z","updated":"2026-02-13T05:59:46.132148641Z"} {"id":"NK-zvt8hi","title":"neko button always must be visible","description":"once you hide the sidebar with the nekoo button, there's no way to unhide it in the v2 ui after the recent changes","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T17:58:18.468707709Z","updated":"2026-02-14T18:00:05.356506442Z"} {"id":"NK-d06p20m","from_ticket_id":"NK-mpb1e1","to_ticket_id":"NK-aiaza3","type":"created_from","created":"2026-02-14T23:43:56.535481378Z"} +{"id":"NK-d07q72v","from_ticket_id":"NK-f64ocp","to_ticket_id":"NK-s8nytj","type":"created_from","created":"2026-02-16T16:17:36.347178621Z"} {"id":"NK-d0ghccy","from_ticket_id":"NK-ric1zs","to_ticket_id":"NK-1phdpf","type":"created_from","created":"2026-02-13T04:26:55.875394997Z"} {"id":"NK-d0lgaab","from_ticket_id":"NK-sne5ox","to_ticket_id":"NK-0ppv3f","type":"created_from","created":"2026-02-13T15:05:23.289745853Z"} {"id":"NK-d1q1e8a","from_ticket_id":"NK-wjnczv","to_ticket_id":"NK-chns2b","type":"created_from","created":"2026-02-14T05:13:23.323181359Z"} @@ -171,6 +175,7 @@ {"id":"NK-d7tr9po","from_ticket_id":"NK-8d1uzw","to_ticket_id":"NK-3g1ouf","type":"created_from","created":"2026-02-15T02:24:06.423302632Z"} {"id":"NK-d7zgu6w","from_ticket_id":"NK-fm15vq","to_ticket_id":"NK-ymf1jb","type":"created_from","created":"2026-02-13T20:27:36.795511524Z"} {"id":"NK-d86tgcs","from_ticket_id":"NK-ed1iah","to_ticket_id":"NK-1phdpf","type":"created_from","created":"2026-02-13T04:26:55.917754798Z"} +{"id":"NK-db0jm5a","from_ticket_id":"NK-gxvegm","to_ticket_id":"NK-s8nytj","type":"created_from","created":"2026-02-16T16:17:21.472303923Z"} {"id":"NK-dda9zfr","from_ticket_id":"NK-lrew5z","to_ticket_id":"NK-mwf9q2","type":"created_from","created":"2026-02-13T18:04:57.273164732Z"} {"id":"NK-de65jjz","from_ticket_id":"NK-p0nfoi","to_ticket_id":"NK-r8rs7m","type":"created_from","created":"2026-02-15T16:49:31.043201298Z"} {"id":"NK-dew7hvb","from_ticket_id":"NK-tw0nga","to_ticket_id":"NK-59kbij","type":"created_from","created":"2026-02-13T15:01:33.825547908Z"} diff --git a/frontend-vanilla/src/main.test.ts b/frontend-vanilla/src/main.test.ts index a8b6969..d397a5e 100644 --- a/frontend-vanilla/src/main.test.ts +++ b/frontend-vanilla/src/main.test.ts @@ -293,4 +293,31 @@ describe('main application logic', () => { body: expect.stringContaining('"read":true') })); }); + + it('should close settings and return to home when clicking settings again', () => { + renderLayout(); + const settingsLink = document.querySelector('[data-nav="settings"]') as HTMLElement; + expect(settingsLink).not.toBeNull(); + + const getCurrentRouteSpy = vi.spyOn(router, 'getCurrentRoute').mockReturnValue({ path: '/settings', params: {}, query: new URLSearchParams() }); + const navigateSpy = vi.spyOn(router, 'navigate'); + + settingsLink.click(); + + expect(navigateSpy).toHaveBeenCalledWith('/', expect.any(Object)); + getCurrentRouteSpy.mockRestore(); + }); + + it('should navigate to home with filter when clicking filter from settings', () => { + renderLayout(); + const getCurrentRouteSpy = vi.spyOn(router, 'getCurrentRoute').mockReturnValue({ path: '/settings', params: {}, query: new URLSearchParams() }); + const navigateSpy = vi.spyOn(router, 'navigate'); + + const filterLink = document.querySelector('a[data-nav="filter"][data-value="starred"]') as HTMLElement; + expect(filterLink).not.toBeNull(); + filterLink.click(); + + expect(navigateSpy).toHaveBeenCalledWith('/', expect.objectContaining({ filter: 'starred' })); + getCurrentRouteSpy.mockRestore(); + }); }); diff --git a/frontend-vanilla/src/main.ts b/frontend-vanilla/src/main.ts index b167a18..c22dd26 100644 --- a/frontend-vanilla/src/main.ts +++ b/frontend-vanilla/src/main.ts @@ -114,7 +114,12 @@ export function attachLayoutListeners() { if (navType === 'filter') { e.preventDefault(); const filter = link.getAttribute('data-value') as FilterType; - router.updateQuery({ filter }); + const currentRoute = router.getCurrentRoute(); + if (currentRoute.path === '/settings') { + router.navigate('/', { ...currentQuery, filter }); + } else { + router.updateQuery({ filter }); + } } else if (navType === 'tag') { e.preventDefault(); const tag = link.getAttribute('data-value')!; @@ -129,7 +134,12 @@ export function attachLayoutListeners() { } } else if (navType === 'settings') { e.preventDefault(); - router.navigate('/settings', currentQuery); + const currentRoute = router.getCurrentRoute(); + if (currentRoute.path === '/settings') { + router.navigate('/', currentQuery); + } else { + router.navigate('/settings', currentQuery); + } } // Auto-close sidebar on mobile after clicking a link |
