github-issue-tower-defence-management 1.151.0 → 1.151.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 +15 -0
- package/bin/adapter/entry-points/console/consoleDoneStore.js +19 -1
- package/bin/adapter/entry-points/console/consoleDoneStore.js.map +1 -1
- package/bin/adapter/entry-points/console/consoleOperationApi.js +17 -5
- package/bin/adapter/entry-points/console/consoleOperationApi.js.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-CY96HROQ.js +83 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +14 -15
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js +2 -10
- package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js.map +1 -1
- package/bin/adapter/repositories/TranscriptOwnerCallStatusProvider.js +16 -5
- package/bin/adapter/repositories/TranscriptOwnerCallStatusProvider.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/consoleDoneStore.test.ts +21 -0
- package/src/adapter/entry-points/console/consoleDoneStore.ts +25 -0
- package/src/adapter/entry-points/console/consoleOperationApi.test.ts +58 -7
- package/src/adapter/entry-points/console/consoleOperationApi.ts +43 -6
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.test.ts +79 -1
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.ts +20 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.test.tsx +42 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +6 -2
- package/src/adapter/entry-points/console/ui-dist/assets/index-CY96HROQ.js +83 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +26 -28
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.test.ts +36 -3
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts +3 -22
- package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.singleScan.test.ts +88 -0
- package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.ts +22 -11
- package/types/adapter/entry-points/console/consoleDoneStore.d.ts +3 -0
- package/types/adapter/entry-points/console/consoleDoneStore.d.ts.map +1 -1
- package/types/adapter/entry-points/console/consoleOperationApi.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts +2 -2
- package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts.map +1 -1
- package/types/adapter/repositories/TranscriptOwnerCallStatusProvider.d.ts +2 -0
- package/types/adapter/repositories/TranscriptOwnerCallStatusProvider.d.ts.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-UQt5L756.js +0 -83
- package/src/adapter/entry-points/console/ui-dist/assets/index-UQt5L756.js +0 -83
|
@@ -4,10 +4,15 @@ import {
|
|
|
4
4
|
isOverlayEntryActed,
|
|
5
5
|
overlayEntriesActedSinceSnapshot,
|
|
6
6
|
overlayKeyForItem,
|
|
7
|
+
overlayStatusSinceSnapshot,
|
|
7
8
|
overlayStorageKey,
|
|
8
9
|
writeOverlayEntry,
|
|
9
10
|
} from './overlay';
|
|
10
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
ConsoleListItem,
|
|
13
|
+
ConsoleOverlay,
|
|
14
|
+
ConsoleOverlayStatus,
|
|
15
|
+
} from './types';
|
|
11
16
|
|
|
12
17
|
const item = (number: number): ConsoleListItem => ({
|
|
13
18
|
number,
|
|
@@ -230,3 +235,76 @@ describe('writeOverlayEntry', () => {
|
|
|
230
235
|
});
|
|
231
236
|
});
|
|
232
237
|
});
|
|
238
|
+
|
|
239
|
+
describe('overlayStatusSinceSnapshot', () => {
|
|
240
|
+
const snapshotGeneratedAt = '2026-08-13T21:52:01.000Z';
|
|
241
|
+
const snapshotEpochMs = Date.parse(snapshotGeneratedAt);
|
|
242
|
+
const inTmuxByHuman: ConsoleOverlayStatus = {
|
|
243
|
+
name: 'In Tmux by human',
|
|
244
|
+
color: 'RED',
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const overlayWithStatusAt = (epochMs: number): ConsoleOverlay => ({
|
|
248
|
+
[overlayKeyForItem(item(1))]: {
|
|
249
|
+
status: inTmuxByHuman,
|
|
250
|
+
ts: epochMs,
|
|
251
|
+
mode: 'todo-by-human',
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('shows a status the owner set after the snapshot was generated', () => {
|
|
256
|
+
expect(
|
|
257
|
+
overlayStatusSinceSnapshot(
|
|
258
|
+
overlayWithStatusAt(snapshotEpochMs + 1000),
|
|
259
|
+
item(1),
|
|
260
|
+
snapshotGeneratedAt,
|
|
261
|
+
),
|
|
262
|
+
).toEqual(inTmuxByHuman);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('drops a status the snapshot already superseded', () => {
|
|
266
|
+
expect(
|
|
267
|
+
overlayStatusSinceSnapshot(
|
|
268
|
+
overlayWithStatusAt(snapshotEpochMs - 1000),
|
|
269
|
+
item(1),
|
|
270
|
+
snapshotGeneratedAt,
|
|
271
|
+
),
|
|
272
|
+
).toBeNull();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('drops every status when the snapshot time is unusable', () => {
|
|
276
|
+
expect(
|
|
277
|
+
overlayStatusSinceSnapshot(
|
|
278
|
+
overlayWithStatusAt(snapshotEpochMs + 1000),
|
|
279
|
+
item(1),
|
|
280
|
+
null,
|
|
281
|
+
),
|
|
282
|
+
).toBeNull();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('shows a status set at the exact moment the snapshot was generated', () => {
|
|
286
|
+
expect(
|
|
287
|
+
overlayStatusSinceSnapshot(
|
|
288
|
+
overlayWithStatusAt(snapshotEpochMs),
|
|
289
|
+
item(1),
|
|
290
|
+
snapshotGeneratedAt,
|
|
291
|
+
),
|
|
292
|
+
).toEqual(inTmuxByHuman);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('drops every status when the snapshot time cannot be parsed', () => {
|
|
296
|
+
expect(
|
|
297
|
+
overlayStatusSinceSnapshot(
|
|
298
|
+
overlayWithStatusAt(snapshotEpochMs + 1000),
|
|
299
|
+
item(1),
|
|
300
|
+
'not a timestamp',
|
|
301
|
+
),
|
|
302
|
+
).toBeNull();
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('returns null when the item has no overlay entry', () => {
|
|
306
|
+
expect(
|
|
307
|
+
overlayStatusSinceSnapshot({}, item(1), snapshotGeneratedAt),
|
|
308
|
+
).toBeNull();
|
|
309
|
+
});
|
|
310
|
+
});
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
ConsoleListItem,
|
|
3
3
|
ConsoleOverlay,
|
|
4
4
|
ConsoleOverlayEntry,
|
|
5
|
+
ConsoleOverlayStatus,
|
|
5
6
|
ConsoleTabName,
|
|
6
7
|
} from './types';
|
|
7
8
|
|
|
@@ -47,6 +48,25 @@ export const overlayEntriesActedSinceSnapshot = (
|
|
|
47
48
|
return acted;
|
|
48
49
|
};
|
|
49
50
|
|
|
51
|
+
export const overlayStatusSinceSnapshot = (
|
|
52
|
+
overlay: ConsoleOverlay,
|
|
53
|
+
item: ConsoleListItem,
|
|
54
|
+
snapshotGeneratedAt: string | null,
|
|
55
|
+
): ConsoleOverlayStatus | null => {
|
|
56
|
+
if (snapshotGeneratedAt === null) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const snapshotGeneratedAtMs = Date.parse(snapshotGeneratedAt);
|
|
60
|
+
if (Number.isNaN(snapshotGeneratedAtMs)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const entry = overlay[overlayKeyForItem(item)];
|
|
64
|
+
if (entry === undefined || entry.ts < snapshotGeneratedAtMs) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return entry.status ?? null;
|
|
68
|
+
};
|
|
69
|
+
|
|
50
70
|
export const writeOverlayEntry = (
|
|
51
71
|
overlay: ConsoleOverlay,
|
|
52
72
|
key: string,
|
|
@@ -106,6 +106,48 @@ describe('ConsolePage', () => {
|
|
|
106
106
|
).toContain('TDPM Console port');
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
+
it('keeps a status the snapshot already superseded out of the detail header', async () => {
|
|
110
|
+
localStorage.setItem(
|
|
111
|
+
'pv_overlay_acme',
|
|
112
|
+
JSON.stringify({
|
|
113
|
+
PVTI_1: {
|
|
114
|
+
status: { name: 'In Tmux by human', color: 'RED' },
|
|
115
|
+
ts: Date.parse('2026-06-18T00:00:00.000Z'),
|
|
116
|
+
mode: 'prs',
|
|
117
|
+
},
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
const { getByText, findByText, container } = render(<ConsolePage />);
|
|
121
|
+
await waitFor(() => {
|
|
122
|
+
expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
|
|
123
|
+
});
|
|
124
|
+
fireEvent.click(getByText('Add serveConsole subcommand'));
|
|
125
|
+
expect(await findByText('Approve')).toBeInTheDocument();
|
|
126
|
+
expect(container.querySelector('.console-detail-status-chip')).toBeNull();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('shows a status the owner set after the snapshot was generated in the detail header', async () => {
|
|
130
|
+
localStorage.setItem(
|
|
131
|
+
'pv_overlay_acme',
|
|
132
|
+
JSON.stringify({
|
|
133
|
+
PVTI_1: {
|
|
134
|
+
status: { name: 'In Tmux by human', color: 'RED' },
|
|
135
|
+
ts: Date.parse('2026-06-19T00:10:00.000Z'),
|
|
136
|
+
mode: 'prs',
|
|
137
|
+
},
|
|
138
|
+
}),
|
|
139
|
+
);
|
|
140
|
+
const { getByText, findByText, container } = render(<ConsolePage />);
|
|
141
|
+
await waitFor(() => {
|
|
142
|
+
expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
|
|
143
|
+
});
|
|
144
|
+
fireEvent.click(getByText('Add serveConsole subcommand'));
|
|
145
|
+
expect(await findByText('Approve')).toBeInTheDocument();
|
|
146
|
+
expect(
|
|
147
|
+
container.querySelector('.console-detail-status-chip')?.textContent,
|
|
148
|
+
).toBe('In Tmux by human');
|
|
149
|
+
});
|
|
150
|
+
|
|
109
151
|
it('opens the detail view when an item is selected', async () => {
|
|
110
152
|
const { getByText, findByText } = render(<ConsolePage />);
|
|
111
153
|
await waitFor(() => {
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
filterPendingItems,
|
|
31
31
|
overlayEntriesActedSinceSnapshot,
|
|
32
32
|
overlayKeyForItem,
|
|
33
|
+
overlayStatusSinceSnapshot,
|
|
33
34
|
} from '../logic/overlay';
|
|
34
35
|
import type { ConsoleSwipeDirection } from '../logic/swipe';
|
|
35
36
|
import { findNextNonEmptyTabToRight } from '../logic/tabAdvance';
|
|
@@ -164,8 +165,11 @@ export const ConsolePage = () => {
|
|
|
164
165
|
if (selectedItem === null) {
|
|
165
166
|
return null;
|
|
166
167
|
}
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
return overlayStatusSinceSnapshot(
|
|
169
|
+
overlayState.overlay,
|
|
170
|
+
selectedItem,
|
|
171
|
+
snapshots[activeTab]?.generatedAt ?? null,
|
|
172
|
+
);
|
|
169
173
|
})();
|
|
170
174
|
|
|
171
175
|
const storyNameForSelected =
|