github-issue-tower-defence-management 1.168.1 → 1.168.2
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 +7 -0
- package/bin/adapter/entry-points/console/ui-dist/assets/index-DL4JeBCA.js +86 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemList.stories.tsx +1 -1
- package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemList.test.tsx +1 -1
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.test.ts +22 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.ts +2 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/grouping.test.ts +47 -3
- package/src/adapter/entry-points/console/ui/src/features/console/logic/grouping.ts +17 -2
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +4 -2
- package/src/adapter/entry-points/console/ui-dist/assets/index-DL4JeBCA.js +86 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-DkAuY63u.js +0 -86
- package/src/adapter/entry-points/console/ui-dist/assets/index-DkAuY63u.js +0 -86
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>TDPM Console</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-DL4JeBCA.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-U8I8ESZj.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@ type Story = StoryObj<typeof ConsoleItemList>;
|
|
|
18
18
|
|
|
19
19
|
export const WithStoryGroups: Story = {
|
|
20
20
|
args: {
|
|
21
|
-
rows: buildConsoleListRows(consoleListItemsFixture, {}),
|
|
21
|
+
rows: buildConsoleListRows(consoleListItemsFixture, {}, []),
|
|
22
22
|
storyColors: consoleStoryColorsFixture,
|
|
23
23
|
activeItemId: null,
|
|
24
24
|
isLoading: false,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from '../../testing/fixtures';
|
|
7
7
|
import { ConsoleItemList } from './ConsoleItemList';
|
|
8
8
|
|
|
9
|
-
const rows = buildConsoleListRows(consoleListItemsFixture, {});
|
|
9
|
+
const rows = buildConsoleListRows(consoleListItemsFixture, {}, []);
|
|
10
10
|
const now = Date.parse('2026-06-19T12:00:00.000Z');
|
|
11
11
|
|
|
12
12
|
describe('ConsoleItemList', () => {
|
package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.test.ts
CHANGED
|
@@ -225,6 +225,28 @@ describe('useConsoleTabData', () => {
|
|
|
225
225
|
).toBe(true);
|
|
226
226
|
});
|
|
227
227
|
|
|
228
|
+
it('parses storyOrder from the snapshot payload', async () => {
|
|
229
|
+
const fetchMock = jest.fn(async (url: string) => ({
|
|
230
|
+
ok: true,
|
|
231
|
+
status: 200,
|
|
232
|
+
json: async () => ({
|
|
233
|
+
pjcode: 'acme',
|
|
234
|
+
generatedAt: '2026-06-19T00:00:00.000Z',
|
|
235
|
+
statusOptions: [],
|
|
236
|
+
storyColors: {},
|
|
237
|
+
storyOrder: url.includes('/prs/') ? ['Alpha', 'Beta'] : [],
|
|
238
|
+
items: [],
|
|
239
|
+
}),
|
|
240
|
+
}));
|
|
241
|
+
global.fetch = fetchMock as unknown as typeof fetch;
|
|
242
|
+
|
|
243
|
+
const { result } = renderHook(() => useConsoleTabData('acme'));
|
|
244
|
+
await waitFor(() => {
|
|
245
|
+
expect(result.current.isLoading).toBe(false);
|
|
246
|
+
});
|
|
247
|
+
expect(result.current.snapshots.prs?.storyOrder).toEqual(['Alpha', 'Beta']);
|
|
248
|
+
});
|
|
249
|
+
|
|
228
250
|
it('reports an error and fetches nothing when no pjcode is in the URL', async () => {
|
|
229
251
|
const fetchMock = jest.fn();
|
|
230
252
|
global.fetch = fetchMock as unknown as typeof fetch;
|
|
@@ -17,6 +17,7 @@ export type ConsoleTabSnapshot = {
|
|
|
17
17
|
stories: ConsoleStoryEntry[];
|
|
18
18
|
defaultNameWithOwner: string | null;
|
|
19
19
|
fromCache: boolean;
|
|
20
|
+
storyOrder: string[];
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
export type ConsoleTabDataState = {
|
|
@@ -81,6 +82,7 @@ const parseSnapshotData = (
|
|
|
81
82
|
isRecord(payload) && typeof payload.defaultNameWithOwner === 'string'
|
|
82
83
|
? payload.defaultNameWithOwner
|
|
83
84
|
: null,
|
|
85
|
+
storyOrder: isRecord(payload) ? parseStringArray(payload.storyOrder) : [],
|
|
84
86
|
});
|
|
85
87
|
|
|
86
88
|
const emptySnapshots = (): Record<
|
|
@@ -69,14 +69,58 @@ describe('resolveItemStory', () => {
|
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
describe('buildConsoleListRows', () => {
|
|
72
|
-
it('
|
|
72
|
+
it('sorts items by storyOrder before grouping', () => {
|
|
73
|
+
const items = [
|
|
74
|
+
item({ number: 1, story: 'Beta' }),
|
|
75
|
+
item({ number: 2, story: 'Alpha' }),
|
|
76
|
+
item({ number: 3, story: 'Beta' }),
|
|
77
|
+
];
|
|
78
|
+
const rows = buildConsoleListRows(items, {}, ['Alpha', 'Beta']);
|
|
79
|
+
expect(rows.map((row) => row.kind)).toEqual([
|
|
80
|
+
'group-header',
|
|
81
|
+
'item',
|
|
82
|
+
'group-header',
|
|
83
|
+
'item',
|
|
84
|
+
'item',
|
|
85
|
+
]);
|
|
86
|
+
const firstHeader = rows[0];
|
|
87
|
+
expect(firstHeader.kind === 'group-header' && firstHeader.story).toBe(
|
|
88
|
+
'Alpha',
|
|
89
|
+
);
|
|
90
|
+
const secondHeader = rows[2];
|
|
91
|
+
expect(secondHeader.kind === 'group-header' && secondHeader.story).toBe(
|
|
92
|
+
'Beta',
|
|
93
|
+
);
|
|
94
|
+
expect(secondHeader.kind === 'group-header' && secondHeader.count).toBe(2);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('sorts by overlay-resolved story when storyOrder is provided', () => {
|
|
98
|
+
const overlay: ConsoleOverlay = {
|
|
99
|
+
PVTI_1: {
|
|
100
|
+
ts: 1,
|
|
101
|
+
mode: 'triage',
|
|
102
|
+
story: { name: 'Alpha', color: 'BLUE' },
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
const items = [
|
|
106
|
+
item({ number: 1, story: 'Beta' }),
|
|
107
|
+
item({ number: 2, story: 'Beta' }),
|
|
108
|
+
];
|
|
109
|
+
const rows = buildConsoleListRows(items, overlay, ['Alpha', 'Beta']);
|
|
110
|
+
const firstHeader = rows[0];
|
|
111
|
+
expect(firstHeader.kind === 'group-header' && firstHeader.story).toBe(
|
|
112
|
+
'Alpha',
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('keeps original relative order when storyOrder is empty', () => {
|
|
73
117
|
const items = [
|
|
74
118
|
item({ number: 1, story: 'Alpha' }),
|
|
75
119
|
item({ number: 2, story: 'Alpha' }),
|
|
76
120
|
item({ number: 3, story: 'Beta' }),
|
|
77
121
|
item({ number: 4, story: 'Alpha' }),
|
|
78
122
|
];
|
|
79
|
-
const rows = buildConsoleListRows(items, {});
|
|
123
|
+
const rows = buildConsoleListRows(items, {}, []);
|
|
80
124
|
expect(rows.map((row) => row.kind)).toEqual([
|
|
81
125
|
'group-header',
|
|
82
126
|
'item',
|
|
@@ -91,6 +135,6 @@ describe('buildConsoleListRows', () => {
|
|
|
91
135
|
});
|
|
92
136
|
|
|
93
137
|
it('returns no rows for an empty list', () => {
|
|
94
|
-
expect(buildConsoleListRows([], {})).toEqual([]);
|
|
138
|
+
expect(buildConsoleListRows([], {}, [])).toEqual([]);
|
|
95
139
|
});
|
|
96
140
|
});
|
|
@@ -51,19 +51,34 @@ export type ConsoleItemSummary = {
|
|
|
51
51
|
|
|
52
52
|
export type ConsoleListRow = ConsoleListGroupRow | ConsoleItemSummary;
|
|
53
53
|
|
|
54
|
+
const UNKNOWN_STORY_SORT_INDEX = 999999;
|
|
55
|
+
|
|
54
56
|
export const buildConsoleListRows = (
|
|
55
57
|
items: ConsoleListItem[],
|
|
56
58
|
overlay: ConsoleOverlay,
|
|
59
|
+
storyOrder: string[],
|
|
57
60
|
): ConsoleListRow[] => {
|
|
61
|
+
const indexByStory = new Map(storyOrder.map((name, index) => [name, index]));
|
|
62
|
+
const sorted =
|
|
63
|
+
storyOrder.length === 0
|
|
64
|
+
? items
|
|
65
|
+
: [...items].sort((a, b) => {
|
|
66
|
+
const storyA = resolveItemStory(a, overlay);
|
|
67
|
+
const storyB = resolveItemStory(b, overlay);
|
|
68
|
+
const indexA = indexByStory.get(storyA) ?? UNKNOWN_STORY_SORT_INDEX;
|
|
69
|
+
const indexB = indexByStory.get(storyB) ?? UNKNOWN_STORY_SORT_INDEX;
|
|
70
|
+
return indexA - indexB;
|
|
71
|
+
});
|
|
72
|
+
|
|
58
73
|
const storyCounts = new Map<string, number>();
|
|
59
|
-
for (const item of
|
|
74
|
+
for (const item of sorted) {
|
|
60
75
|
const story = resolveItemStory(item, overlay);
|
|
61
76
|
storyCounts.set(story, (storyCounts.get(story) ?? 0) + 1);
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
const rows: ConsoleListRow[] = [];
|
|
65
80
|
let previousStory: string | null = null;
|
|
66
|
-
for (const item of
|
|
81
|
+
for (const item of sorted) {
|
|
67
82
|
const story = resolveItemStory(item, overlay);
|
|
68
83
|
if (story !== previousStory) {
|
|
69
84
|
rows.push({
|
|
@@ -117,9 +117,11 @@ export const ConsolePage = () => {
|
|
|
117
117
|
[pendingItems],
|
|
118
118
|
);
|
|
119
119
|
|
|
120
|
+
const storyOrder = activeSnapshot?.storyOrder ?? [];
|
|
121
|
+
|
|
120
122
|
const rows = useMemo(
|
|
121
|
-
() => buildConsoleListRows(pendingItems, overlayState.overlay),
|
|
122
|
-
[pendingItems, overlayState.overlay],
|
|
123
|
+
() => buildConsoleListRows(pendingItems, overlayState.overlay, storyOrder),
|
|
124
|
+
[pendingItems, overlayState.overlay, storyOrder],
|
|
123
125
|
);
|
|
124
126
|
|
|
125
127
|
const storyColors = activeSnapshot?.storyColors ?? {};
|