Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 15 additions & 29 deletions ui/src/demo/handlers/newsList.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,23 @@
import { http, HttpResponse } from 'msw'
import { demoNewsArticles } from '../fixtures/news'
import type { NewsListResponse } from '../../api/types'

/**
* News demo handler — seeded articles for the showcase.
* News demo handler.
*
* (Previously also mocked the legacy /api/notifications/history feed; the
* NotificationsStore surface was removed, so only the news list remains.
* The `/api/news/collector` config endpoint is mocked separately in
* news.ts.)
* `/api/news` returns `NewsListResponse = { items, count, lookback }` per
* ui/src/api/types.ts — NOT { articles, hasMore }. NewsPage does
* `setArticles(res.items)`; the wrong shape leaves articles=undefined and
* crashes the page on `[...articles].reverse()` in render.
*/

const DEMO_ARTICLES = [
{
id: 'demo-news-1',
title: 'Fed holds rates steady; dot plot signals one cut in 2025',
source: 'Reuters',
url: 'https://example.com/news/fed-holds',
publishedAt: new Date(Date.now() - 1000 * 60 * 60 * 2).toISOString(),
summary: 'The Federal Reserve kept its benchmark rate unchanged...',
tickers: ['SPY', 'TLT'],
},
{
id: 'demo-news-2',
title: 'NVIDIA unveils next-gen Blackwell Ultra accelerators',
source: 'Bloomberg',
url: 'https://example.com/news/nvidia-blackwell',
publishedAt: new Date(Date.now() - 1000 * 60 * 60 * 6).toISOString(),
summary: 'NVIDIA announced its Blackwell Ultra line...',
tickers: ['NVDA'],
},
]

export const newsListHandlers = [
http.get('/api/news', () => {
return HttpResponse.json({ articles: DEMO_ARTICLES, hasMore: false })
http.get('/api/news', ({ request }) => {
const lookback = new URL(request.url).searchParams.get('lookback') ?? '24h'
const body: NewsListResponse = {
items: demoNewsArticles,
count: demoNewsArticles.length,
lookback,
}
return HttpResponse.json(body)
}),
]
6 changes: 5 additions & 1 deletion ui/src/tabs/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,11 @@ export const useWorkspace = create<WorkspaceStore>()(
// TabStrip call getView() on a missing kind and crash on rehydrate;
// bumping the version drops stale persisted state (no migrate fn —
// schema bump clears, per this store's loud-fail contract).
version: 4,
// v5: the demo `/api/news` handler shape mismatch poisoned any
// session that had a news tab open — NewsPage's `[...articles]`
// throws when res.items is undefined, and the rehydrate replays
// that tab open on every reload. Bump clears the loop.
version: 5,
// Persist only the data shape — actions are recreated by the store factory.
partialize: (state) => ({
tabs: state.tabs,
Expand Down
Loading