github-issue-tower-defence-management 1.91.1 → 1.91.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.test.ts +29 -1
- package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.ts +6 -6
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.test.ts +68 -46
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.ts +5 -58
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.test.tsx +55 -1
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +2 -10
- package/src/adapter/entry-points/console/ui-dist/assets/{index-PtVrAcBb.js → index-Cn4xr5-h.js} +20 -20
- package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [1.91.3](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.91.2...v1.91.3) (2026-06-21)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **console:** anchor read API paths at server root so per-project routes load detail content ([#879](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/879)) ([789e4a1](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/789e4a1da0ec087e061f051de08af7d30e3735ef))
|
|
7
|
+
|
|
8
|
+
## [1.91.2](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.91.1...v1.91.2) (2026-06-20)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **console:** apply processed-item overlay to all tab badges so a zeroed tab stays zero ([#871](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/871)) ([4eda1ab](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/4eda1ab29cce54969c5fcc2b8a5ff838013978f7)), closes [#868](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/868)
|
|
14
|
+
|
|
1
15
|
## [1.91.1](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.91.0...v1.91.1) (2026-06-20)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
|
@@ -20,10 +20,38 @@ describe('createConsoleApiClient', () => {
|
|
|
20
20
|
const body = await client.fetchItemBody('https://github.com/o/r/issues/1');
|
|
21
21
|
expect(body).toBe('# Title');
|
|
22
22
|
const requested = fetchMock.mock.calls[0][0] as string;
|
|
23
|
-
expect(requested).toContain('
|
|
23
|
+
expect(requested).toContain('/api/itembody?url=');
|
|
24
24
|
expect(requested).toContain('&k=token');
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
+
it('anchors every read endpoint at the server root regardless of route', async () => {
|
|
28
|
+
const readers: ((url: string) => Promise<unknown>)[] = [];
|
|
29
|
+
const client = createConsoleApiClient(appendToken);
|
|
30
|
+
readers.push((url) => client.fetchItemBody(url));
|
|
31
|
+
readers.push((url) => client.fetchComments(url));
|
|
32
|
+
readers.push((url) => client.fetchPrFiles(url));
|
|
33
|
+
readers.push((url) => client.fetchPrCommits(url));
|
|
34
|
+
readers.push((url) => client.fetchRelatedPrs(url));
|
|
35
|
+
readers.push((url) => client.fetchIssueState(url));
|
|
36
|
+
const expectedPaths = [
|
|
37
|
+
'/api/itembody',
|
|
38
|
+
'/api/comments',
|
|
39
|
+
'/api/prfiles',
|
|
40
|
+
'/api/prcommits',
|
|
41
|
+
'/api/relatedprs',
|
|
42
|
+
'/api/issuetitle',
|
|
43
|
+
];
|
|
44
|
+
for (let index = 0; index < readers.length; index += 1) {
|
|
45
|
+
const fetchMock = mockFetchOnce({});
|
|
46
|
+
await readers[index]('https://github.com/o/r/issues/1');
|
|
47
|
+
const requested = fetchMock.mock.calls[0][0] as string;
|
|
48
|
+
expect(requested.startsWith(expectedPaths[index])).toBe(true);
|
|
49
|
+
expect(requested.startsWith('/api/')).toBe(true);
|
|
50
|
+
expect(requested.startsWith('./')).toBe(false);
|
|
51
|
+
expect(requested.startsWith('/projects')).toBe(false);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
27
55
|
it('parses comments', async () => {
|
|
28
56
|
mockFetchOnce({
|
|
29
57
|
comments: [
|
|
@@ -156,19 +156,19 @@ export const createConsoleApiClient = (
|
|
|
156
156
|
appendToken: AppendToken,
|
|
157
157
|
): ConsoleApiClient => ({
|
|
158
158
|
fetchItemBody: async (url) => {
|
|
159
|
-
const payload = await requestJson(appendToken, '
|
|
159
|
+
const payload = await requestJson(appendToken, '/api/itembody', url);
|
|
160
160
|
return isRecord(payload) ? getString(payload.body) : '';
|
|
161
161
|
},
|
|
162
162
|
fetchComments: async (url) =>
|
|
163
|
-
parseComments(await requestJson(appendToken, '
|
|
163
|
+
parseComments(await requestJson(appendToken, '/api/comments', url)),
|
|
164
164
|
fetchPrFiles: async (url) =>
|
|
165
|
-
parseFiles(await requestJson(appendToken, '
|
|
165
|
+
parseFiles(await requestJson(appendToken, '/api/prfiles', url)),
|
|
166
166
|
fetchPrCommits: async (url) =>
|
|
167
|
-
parseCommits(await requestJson(appendToken, '
|
|
167
|
+
parseCommits(await requestJson(appendToken, '/api/prcommits', url)),
|
|
168
168
|
fetchRelatedPrs: async (url) =>
|
|
169
|
-
parseRelatedPrs(await requestJson(appendToken, '
|
|
169
|
+
parseRelatedPrs(await requestJson(appendToken, '/api/relatedprs', url)),
|
|
170
170
|
fetchIssueState: async (url) =>
|
|
171
|
-
parseState(await requestJson(appendToken, '
|
|
171
|
+
parseState(await requestJson(appendToken, '/api/issuetitle', url)),
|
|
172
172
|
});
|
|
173
173
|
|
|
174
174
|
export const postConsoleOperation = async (
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
countPendingItems,
|
|
3
3
|
filterPendingItems,
|
|
4
|
-
|
|
5
|
-
isOverlayEntryActedForMode,
|
|
6
|
-
isOverlayEntryExpiredForMode,
|
|
4
|
+
isOverlayEntryActed,
|
|
7
5
|
overlayKeyForItem,
|
|
8
6
|
overlayStorageKey,
|
|
9
|
-
parseGeneratedAtMs,
|
|
10
7
|
writeOverlayEntry,
|
|
11
8
|
} from './overlay';
|
|
12
9
|
import type { ConsoleListItem, ConsoleOverlay } from './types';
|
|
@@ -34,68 +31,71 @@ describe('overlay helpers', () => {
|
|
|
34
31
|
expect(overlayKeyForItem(item(5))).toBe('PVTI_5');
|
|
35
32
|
});
|
|
36
33
|
|
|
37
|
-
it('
|
|
38
|
-
expect(
|
|
39
|
-
Date.parse('2026-06-10T00:00:00.000Z'),
|
|
40
|
-
);
|
|
41
|
-
expect(parseGeneratedAtMs('not-a-date')).toBe(0);
|
|
34
|
+
it('falls back to the itemId when the projectItemId is empty', () => {
|
|
35
|
+
expect(overlayKeyForItem({ ...item(5), projectItemId: '' })).toBe('PVTI_5');
|
|
42
36
|
});
|
|
43
37
|
});
|
|
44
38
|
|
|
45
|
-
describe('
|
|
46
|
-
it('
|
|
47
|
-
expect(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
200,
|
|
51
|
-
'prs',
|
|
52
|
-
),
|
|
53
|
-
).toBe(true);
|
|
39
|
+
describe('isOverlayEntryActed', () => {
|
|
40
|
+
it('treats a done entry as acted', () => {
|
|
41
|
+
expect(isOverlayEntryActed({ ts: 100, mode: 'prs', done: true })).toBe(
|
|
42
|
+
true,
|
|
43
|
+
);
|
|
54
44
|
});
|
|
55
45
|
|
|
56
|
-
it('
|
|
57
|
-
expect(
|
|
58
|
-
isOverlayEntryExpiredForMode(
|
|
59
|
-
{ ts: 100, mode: 'triage', done: true },
|
|
60
|
-
200,
|
|
61
|
-
'prs',
|
|
62
|
-
),
|
|
63
|
-
).toBe(false);
|
|
46
|
+
it('treats a missing entry as not acted', () => {
|
|
47
|
+
expect(isOverlayEntryActed(undefined)).toBe(false);
|
|
64
48
|
});
|
|
65
49
|
|
|
66
|
-
it('
|
|
50
|
+
it('treats an entry without done as not acted', () => {
|
|
67
51
|
expect(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
'
|
|
72
|
-
),
|
|
52
|
+
isOverlayEntryActed({
|
|
53
|
+
ts: 100,
|
|
54
|
+
mode: 'prs',
|
|
55
|
+
story: { name: 'Story', color: 'BLUE' },
|
|
56
|
+
}),
|
|
73
57
|
).toBe(false);
|
|
74
58
|
});
|
|
59
|
+
|
|
60
|
+
it('treats a done entry as acted regardless of the mode it was written in', () => {
|
|
61
|
+
expect(isOverlayEntryActed({ ts: 100, mode: 'triage', done: true })).toBe(
|
|
62
|
+
true,
|
|
63
|
+
);
|
|
64
|
+
});
|
|
75
65
|
});
|
|
76
66
|
|
|
77
67
|
describe('counts driven to zero do not revive on tab switch', () => {
|
|
78
|
-
it('keeps a done item subtracted in
|
|
68
|
+
it('keeps a done item subtracted in the tab it was processed in', () => {
|
|
79
69
|
const overlay: ConsoleOverlay = {
|
|
80
70
|
PVTI_1: { ts: 500, mode: 'prs', done: true },
|
|
81
71
|
};
|
|
82
|
-
|
|
83
|
-
expect(countPendingItems([item(1)], overlay, generatedAtMs, 'prs')).toBe(0);
|
|
72
|
+
expect(countPendingItems([item(1)], overlay)).toBe(0);
|
|
84
73
|
});
|
|
85
74
|
|
|
86
|
-
it('
|
|
75
|
+
it('keeps a done item subtracted from every tab regardless of its mode', () => {
|
|
87
76
|
const overlay: ConsoleOverlay = {
|
|
88
77
|
PVTI_1: { ts: 100, mode: 'triage', done: true },
|
|
89
78
|
};
|
|
90
|
-
expect(
|
|
91
|
-
|
|
79
|
+
expect(countPendingItems([item(1)], overlay)).toBe(0);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('does not revive a done item even when an entry was processed before the snapshot it still appears in', () => {
|
|
83
|
+
const overlay: ConsoleOverlay = {
|
|
84
|
+
PVTI_1: { ts: 100, mode: 'prs', done: true },
|
|
85
|
+
};
|
|
86
|
+
expect(countPendingItems([item(1)], overlay)).toBe(0);
|
|
92
87
|
});
|
|
93
88
|
|
|
94
|
-
it('
|
|
89
|
+
it('does not revive a done item when it appears in a tab other than the one it was processed in', () => {
|
|
95
90
|
const overlay: ConsoleOverlay = {
|
|
96
91
|
PVTI_1: { ts: 100, mode: 'prs', done: true },
|
|
97
92
|
};
|
|
98
|
-
expect(countPendingItems([item(1)], overlay
|
|
93
|
+
expect(countPendingItems([item(1)], overlay)).toBe(0);
|
|
94
|
+
expect(filterPendingItems([item(1)], overlay)).toEqual([]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('counts an item that has no done entry', () => {
|
|
98
|
+
expect(countPendingItems([item(1)], {})).toBe(1);
|
|
99
99
|
});
|
|
100
100
|
});
|
|
101
101
|
|
|
@@ -104,21 +104,43 @@ describe('filterPendingItems', () => {
|
|
|
104
104
|
const overlay: ConsoleOverlay = {
|
|
105
105
|
PVTI_1: { ts: 500, mode: 'prs', done: true },
|
|
106
106
|
};
|
|
107
|
-
const result = filterPendingItems([item(1), item(2)], overlay
|
|
107
|
+
const result = filterPendingItems([item(1), item(2)], overlay);
|
|
108
108
|
expect(result.map((entry) => entry.number)).toEqual([2]);
|
|
109
109
|
});
|
|
110
|
-
});
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
it('returns null for an expired entry', () => {
|
|
111
|
+
it('keeps the badge count and the filtered list consistent', () => {
|
|
114
112
|
const overlay: ConsoleOverlay = {
|
|
115
|
-
PVTI_1: { ts:
|
|
113
|
+
PVTI_1: { ts: 500, mode: 'prs', done: true },
|
|
116
114
|
};
|
|
117
|
-
|
|
115
|
+
const items = [item(1), item(2)];
|
|
116
|
+
expect(countPendingItems(items, overlay)).toBe(
|
|
117
|
+
filterPendingItems(items, overlay).length,
|
|
118
|
+
);
|
|
118
119
|
});
|
|
120
|
+
});
|
|
119
121
|
|
|
122
|
+
describe('writeOverlayEntry', () => {
|
|
120
123
|
it('stamps the timestamp and mode on write', () => {
|
|
121
124
|
const next = writeOverlayEntry({}, 'PVTI_1', { done: true }, 'prs', 1234);
|
|
122
125
|
expect(next.PVTI_1).toEqual({ done: true, ts: 1234, mode: 'prs' });
|
|
123
126
|
});
|
|
127
|
+
|
|
128
|
+
it('merges a patch into an existing entry while refreshing ts and mode', () => {
|
|
129
|
+
const overlay: ConsoleOverlay = {
|
|
130
|
+
PVTI_1: { ts: 100, mode: 'prs', done: true },
|
|
131
|
+
};
|
|
132
|
+
const next = writeOverlayEntry(
|
|
133
|
+
overlay,
|
|
134
|
+
'PVTI_1',
|
|
135
|
+
{ story: { name: 'New Story', color: 'GREEN' } },
|
|
136
|
+
'triage',
|
|
137
|
+
999,
|
|
138
|
+
);
|
|
139
|
+
expect(next.PVTI_1).toEqual({
|
|
140
|
+
done: true,
|
|
141
|
+
story: { name: 'New Story', color: 'GREEN' },
|
|
142
|
+
ts: 999,
|
|
143
|
+
mode: 'triage',
|
|
144
|
+
});
|
|
145
|
+
});
|
|
124
146
|
});
|
|
@@ -11,76 +11,23 @@ export const overlayStorageKey = (pjcode: string): string =>
|
|
|
11
11
|
export const overlayKeyForItem = (item: ConsoleListItem): string =>
|
|
12
12
|
item.projectItemId !== '' ? item.projectItemId : item.itemId;
|
|
13
13
|
|
|
14
|
-
export const
|
|
15
|
-
const parsed = Date.parse(generatedAt);
|
|
16
|
-
return Number.isNaN(parsed) ? 0 : parsed;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const isOverlayEntryExpiredForMode = (
|
|
20
|
-
entry: ConsoleOverlayEntry,
|
|
21
|
-
generatedAtMs: number,
|
|
22
|
-
mode: ConsoleTabName,
|
|
23
|
-
): boolean =>
|
|
24
|
-
entry.ts > 0 &&
|
|
25
|
-
generatedAtMs > 0 &&
|
|
26
|
-
entry.mode === mode &&
|
|
27
|
-
entry.ts < generatedAtMs;
|
|
28
|
-
|
|
29
|
-
export const getOverlayEntry = (
|
|
30
|
-
overlay: ConsoleOverlay,
|
|
31
|
-
item: ConsoleListItem,
|
|
32
|
-
generatedAtMs: number,
|
|
33
|
-
mode: ConsoleTabName,
|
|
34
|
-
): ConsoleOverlayEntry | null => {
|
|
35
|
-
const entry = overlay[overlayKeyForItem(item)];
|
|
36
|
-
if (entry === undefined) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
if (isOverlayEntryExpiredForMode(entry, generatedAtMs, mode)) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
return entry;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const isOverlayEntryActedForMode = (
|
|
14
|
+
export const isOverlayEntryActed = (
|
|
46
15
|
entry: ConsoleOverlayEntry | undefined,
|
|
47
|
-
|
|
48
|
-
mode: ConsoleTabName,
|
|
49
|
-
): boolean => {
|
|
50
|
-
if (entry === undefined || entry.done !== true) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
return !isOverlayEntryExpiredForMode(entry, generatedAtMs, mode);
|
|
54
|
-
};
|
|
16
|
+
): boolean => entry !== undefined && entry.done === true;
|
|
55
17
|
|
|
56
18
|
export const countPendingItems = (
|
|
57
19
|
items: ConsoleListItem[],
|
|
58
20
|
overlay: ConsoleOverlay,
|
|
59
|
-
generatedAtMs: number,
|
|
60
|
-
mode: ConsoleTabName,
|
|
61
21
|
): number =>
|
|
62
|
-
items.filter(
|
|
63
|
-
|
|
64
|
-
!isOverlayEntryActedForMode(
|
|
65
|
-
overlay[overlayKeyForItem(item)],
|
|
66
|
-
generatedAtMs,
|
|
67
|
-
mode,
|
|
68
|
-
),
|
|
69
|
-
).length;
|
|
22
|
+
items.filter((item) => !isOverlayEntryActed(overlay[overlayKeyForItem(item)]))
|
|
23
|
+
.length;
|
|
70
24
|
|
|
71
25
|
export const filterPendingItems = (
|
|
72
26
|
items: ConsoleListItem[],
|
|
73
27
|
overlay: ConsoleOverlay,
|
|
74
|
-
generatedAtMs: number,
|
|
75
|
-
mode: ConsoleTabName,
|
|
76
28
|
): ConsoleListItem[] =>
|
|
77
29
|
items.filter(
|
|
78
|
-
(item) =>
|
|
79
|
-
!isOverlayEntryActedForMode(
|
|
80
|
-
overlay[overlayKeyForItem(item)],
|
|
81
|
-
generatedAtMs,
|
|
82
|
-
mode,
|
|
83
|
-
),
|
|
30
|
+
(item) => !isOverlayEntryActed(overlay[overlayKeyForItem(item)]),
|
|
84
31
|
);
|
|
85
32
|
|
|
86
33
|
export const writeOverlayEntry = (
|
|
@@ -28,7 +28,23 @@ const listPayload = (tab: string) => ({
|
|
|
28
28
|
createdAt: '2026-06-17T00:00:00.000Z',
|
|
29
29
|
},
|
|
30
30
|
]
|
|
31
|
-
:
|
|
31
|
+
: tab === 'unread'
|
|
32
|
+
? [
|
|
33
|
+
{
|
|
34
|
+
number: 866,
|
|
35
|
+
title: 'Notify finished issue preparation',
|
|
36
|
+
url: 'https://github.com/o/r/issues/866',
|
|
37
|
+
repo: 'o/r',
|
|
38
|
+
nameWithOwner: 'o/r',
|
|
39
|
+
projectItemId: 'PVTI_2',
|
|
40
|
+
itemId: 'PVTI_2',
|
|
41
|
+
isPr: false,
|
|
42
|
+
story: 'TDPM Console port',
|
|
43
|
+
labels: [],
|
|
44
|
+
createdAt: '2026-06-18T00:00:00.000Z',
|
|
45
|
+
},
|
|
46
|
+
]
|
|
47
|
+
: [],
|
|
32
48
|
});
|
|
33
49
|
|
|
34
50
|
const installFetch = (): void => {
|
|
@@ -71,4 +87,42 @@ describe('ConsolePage', () => {
|
|
|
71
87
|
expect(await findByText('← Back to list')).toBeInTheDocument();
|
|
72
88
|
expect(getByText('Approve')).toBeInTheDocument();
|
|
73
89
|
});
|
|
90
|
+
|
|
91
|
+
it('keeps a tab driven to zero at zero and does not revive its badge after switching tabs', async () => {
|
|
92
|
+
const { getByText, queryByText, findByText } = render(<ConsolePage />);
|
|
93
|
+
await waitFor(() => {
|
|
94
|
+
expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
|
|
95
|
+
});
|
|
96
|
+
expect(
|
|
97
|
+
getByText('Awaiting Quality Check')
|
|
98
|
+
.closest('button')
|
|
99
|
+
?.querySelector('.console-tab-badge')?.textContent,
|
|
100
|
+
).toBe('1');
|
|
101
|
+
|
|
102
|
+
fireEvent.click(getByText('Add serveConsole subcommand'));
|
|
103
|
+
expect(await findByText('← Back to list')).toBeInTheDocument();
|
|
104
|
+
fireEvent.click(getByText('Approve'));
|
|
105
|
+
|
|
106
|
+
await waitFor(() => {
|
|
107
|
+
expect(
|
|
108
|
+
getByText('Awaiting Quality Check')
|
|
109
|
+
.closest('button')
|
|
110
|
+
?.querySelector('.console-tab-badge')?.textContent,
|
|
111
|
+
).toBe('0');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
fireEvent.click(getByText('Unread'));
|
|
115
|
+
await waitFor(() => {
|
|
116
|
+
expect(
|
|
117
|
+
getByText('Notify finished issue preparation'),
|
|
118
|
+
).toBeInTheDocument();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const prsTabButton = queryByText('Awaiting Quality Check')?.closest(
|
|
122
|
+
'button',
|
|
123
|
+
);
|
|
124
|
+
const prsBadge =
|
|
125
|
+
prsTabButton?.querySelector('.console-tab-badge')?.textContent ?? '0';
|
|
126
|
+
expect(prsBadge).toBe('0');
|
|
127
|
+
});
|
|
74
128
|
});
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
countPendingItems,
|
|
13
13
|
filterPendingItems,
|
|
14
14
|
overlayKeyForItem,
|
|
15
|
-
parseGeneratedAtMs,
|
|
16
15
|
} from '../logic/overlay';
|
|
17
16
|
import type {
|
|
18
17
|
ConsoleListItem,
|
|
@@ -57,8 +56,6 @@ export const ConsolePage = () => {
|
|
|
57
56
|
result[tab.name] = countPendingItems(
|
|
58
57
|
snapshot.items,
|
|
59
58
|
overlayState.overlay,
|
|
60
|
-
parseGeneratedAtMs(snapshot.generatedAt),
|
|
61
|
-
tab.name,
|
|
62
59
|
);
|
|
63
60
|
}
|
|
64
61
|
return result;
|
|
@@ -69,13 +66,8 @@ export const ConsolePage = () => {
|
|
|
69
66
|
if (activeSnapshot === null) {
|
|
70
67
|
return [];
|
|
71
68
|
}
|
|
72
|
-
return filterPendingItems(
|
|
73
|
-
|
|
74
|
-
overlayState.overlay,
|
|
75
|
-
parseGeneratedAtMs(activeSnapshot.generatedAt),
|
|
76
|
-
activeTab,
|
|
77
|
-
);
|
|
78
|
-
}, [activeSnapshot, overlayState.overlay, activeTab]);
|
|
69
|
+
return filterPendingItems(activeSnapshot.items, overlayState.overlay);
|
|
70
|
+
}, [activeSnapshot, overlayState.overlay]);
|
|
79
71
|
|
|
80
72
|
const rows = useMemo(
|
|
81
73
|
() => buildConsoleListRows(pendingItems, overlayState.overlay),
|