github-issue-tower-defence-management 2.18.0 → 2.19.1
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/README.md +1 -1
- package/bin/adapter/entry-points/console/consoleOperationApi.js +12 -1
- package/bin/adapter/entry-points/console/consoleOperationApi.js.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/{index-CfqusL5j.js → index-BYDbK1Fj.js} +31 -31
- package/bin/adapter/entry-points/console/ui-dist/assets/{index-DshIymWu.css → index-KyQISRuQ.css} +1 -1
- package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/bin/adapter/entry-points/console/webServer.js +2 -0
- package/bin/adapter/entry-points/console/webServer.js.map +1 -1
- package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +41 -0
- package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
- package/bin/domain/usecases/OauthTokenSelectUseCase.js +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/consoleOperationApi.test.ts +30 -0
- package/src/adapter/entry-points/console/consoleOperationApi.ts +14 -0
- package/src/adapter/entry-points/console/ui/e2e/consoleScenario.spec.ts +31 -0
- package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +12 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.stories.tsx +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleDangerousActions.stories.tsx +14 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleDangerousActions.test.tsx +40 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleDangerousActions.tsx +37 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOperationMenu.stories.tsx +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOperationMenu.test.tsx +15 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOperationMenu.tsx +4 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOperations.ts +11 -0
- package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.ts +19 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/actionToast.ts +9 -1
- package/src/adapter/entry-points/console/ui/src/features/console/logic/operations.ts +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.test.tsx +67 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.tsx +7 -0
- package/src/adapter/entry-points/console/ui/src/index.css +6 -0
- package/src/adapter/entry-points/console/ui-dist/assets/{index-CfqusL5j.js → index-BYDbK1Fj.js} +31 -31
- package/src/adapter/entry-points/console/ui-dist/assets/{index-DshIymWu.css → index-KyQISRuQ.css} +1 -1
- package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/src/adapter/entry-points/console/webServer.ts +3 -0
- package/src/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.test.ts +1 -1
- package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +150 -0
- package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +70 -0
- package/src/domain/usecases/OauthTokenSelectUseCase.test.ts +21 -10
- package/src/domain/usecases/OauthTokenSelectUseCase.ts +1 -1
- package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +1 -0
- package/types/adapter/entry-points/console/consoleOperationApi.d.ts +1 -0
- package/types/adapter/entry-points/console/consoleOperationApi.d.ts.map +1 -1
- package/types/adapter/entry-points/console/webServer.d.ts.map +1 -1
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +1 -0
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
- package/types/domain/usecases/OauthTokenSelectUseCase.d.ts +1 -1
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +1 -0
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
|
@@ -14,6 +14,7 @@ const handlers: ConsoleOperationHandlers = {
|
|
|
14
14
|
onSetInTmuxByHuman: jest.fn(),
|
|
15
15
|
onClose: jest.fn(),
|
|
16
16
|
onOkAndAwaitingWorkspace: jest.fn(),
|
|
17
|
+
onDeleteAllComments: jest.fn(),
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
const prItem = consoleListItemsFixture[0];
|
|
@@ -141,4 +142,18 @@ describe('ConsoleOperationMenu', () => {
|
|
|
141
142
|
);
|
|
142
143
|
expect(getByText('Reject')).not.toBeDisabled();
|
|
143
144
|
});
|
|
145
|
+
|
|
146
|
+
it('renders the dangerous actions toggle on all tabs', () => {
|
|
147
|
+
const { getByText } = render(
|
|
148
|
+
<ConsoleOperationMenu
|
|
149
|
+
tab="prs"
|
|
150
|
+
item={prItem}
|
|
151
|
+
hasPullRequest
|
|
152
|
+
rejectEnabled={false}
|
|
153
|
+
statusOptions={consoleStatusOptionsFixture}
|
|
154
|
+
handlers={handlers}
|
|
155
|
+
/>,
|
|
156
|
+
);
|
|
157
|
+
expect(getByText('⚠')).toBeInTheDocument();
|
|
158
|
+
});
|
|
144
159
|
});
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
ConsoleTabName,
|
|
9
9
|
} from '../../logic/types';
|
|
10
10
|
import { ConsoleCloseActions } from './ConsoleCloseActions';
|
|
11
|
+
import { ConsoleDangerousActions } from './ConsoleDangerousActions';
|
|
11
12
|
import { ConsoleNextActionDateActions } from './ConsoleNextActionDateActions';
|
|
12
13
|
import { ConsolePullRequestReviewActions } from './ConsolePullRequestReviewActions';
|
|
13
14
|
import { ConsoleStatusActions } from './ConsoleStatusActions';
|
|
@@ -30,6 +31,9 @@ export const ConsoleOperationMenu = ({
|
|
|
30
31
|
}: ConsoleOperationBarProps) => {
|
|
31
32
|
return (
|
|
32
33
|
<div className="console-operation-bar">
|
|
34
|
+
<ConsoleDangerousActions
|
|
35
|
+
onDeleteAllComments={handlers.onDeleteAllComments}
|
|
36
|
+
/>
|
|
33
37
|
{hasPullRequest && (
|
|
34
38
|
<ConsolePullRequestReviewActions
|
|
35
39
|
onReview={handlers.onReview}
|
package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOperations.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
encodeAttachmentContent,
|
|
8
8
|
postConsoleAttachment,
|
|
9
9
|
postConsoleComment,
|
|
10
|
+
postConsoleDeleteAllComments,
|
|
10
11
|
postConsoleOperation,
|
|
11
12
|
postConsoleReviewComment,
|
|
12
13
|
} from '../lib/consoleApi';
|
|
@@ -74,6 +75,7 @@ export type ConsoleOperationsApi = {
|
|
|
74
75
|
side: ConsoleReviewCommentSide,
|
|
75
76
|
body: string,
|
|
76
77
|
) => Promise<void>;
|
|
78
|
+
deleteAllComments: (item: ConsoleListItem) => Promise<void>;
|
|
77
79
|
};
|
|
78
80
|
|
|
79
81
|
export const reviewRequest = (
|
|
@@ -391,6 +393,14 @@ export const useConsoleOperations = (
|
|
|
391
393
|
[pjcode],
|
|
392
394
|
);
|
|
393
395
|
|
|
396
|
+
const deleteAllComments = useCallback(
|
|
397
|
+
async (item: ConsoleListItem) => {
|
|
398
|
+
await postConsoleDeleteAllComments({ issueUrl: item.url });
|
|
399
|
+
invalidateItemContent(item);
|
|
400
|
+
},
|
|
401
|
+
[invalidateItemContent],
|
|
402
|
+
);
|
|
403
|
+
|
|
394
404
|
return {
|
|
395
405
|
reviewPullRequest,
|
|
396
406
|
setNextActionDate,
|
|
@@ -402,5 +412,6 @@ export const useConsoleOperations = (
|
|
|
402
412
|
addComment,
|
|
403
413
|
uploadAttachment,
|
|
404
414
|
addInlineReviewComment,
|
|
415
|
+
deleteAllComments,
|
|
405
416
|
};
|
|
406
417
|
};
|
|
@@ -482,6 +482,25 @@ export const postConsoleReorderStory = async (
|
|
|
482
482
|
}
|
|
483
483
|
};
|
|
484
484
|
|
|
485
|
+
export const DELETE_ALL_COMMENTS_OPERATION_PATH = '/api/deleteallcomments';
|
|
486
|
+
|
|
487
|
+
export type ConsoleDeleteAllCommentsRequest = {
|
|
488
|
+
issueUrl: string;
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
export const postConsoleDeleteAllComments = async (
|
|
492
|
+
request: ConsoleDeleteAllCommentsRequest,
|
|
493
|
+
): Promise<void> => {
|
|
494
|
+
const response = await fetch(DELETE_ALL_COMMENTS_OPERATION_PATH, {
|
|
495
|
+
method: 'POST',
|
|
496
|
+
headers: { 'Content-Type': 'application/json' },
|
|
497
|
+
body: JSON.stringify(request),
|
|
498
|
+
});
|
|
499
|
+
if (!response.ok) {
|
|
500
|
+
throw new Error(await readOperationErrorReason(response));
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
|
|
485
504
|
export type ProjectListResponse = {
|
|
486
505
|
pjcodes: string[];
|
|
487
506
|
workflowImprovementIssueUrl: string | null;
|
|
@@ -21,7 +21,8 @@ export type ConsoleActionKind =
|
|
|
21
21
|
| { type: 'set_status'; optionName: string }
|
|
22
22
|
| { type: 'set_in_tmux_by_human'; optionName: string }
|
|
23
23
|
| { type: 'close'; action: ConsoleCloseAction }
|
|
24
|
-
| { type: 'ok_and_awaiting_workspace' }
|
|
24
|
+
| { type: 'ok_and_awaiting_workspace' }
|
|
25
|
+
| { type: 'delete_all_comments' };
|
|
25
26
|
|
|
26
27
|
export const ACTION_TOAST_DELAY_MS = 5000;
|
|
27
28
|
|
|
@@ -67,6 +68,8 @@ export const actionToastMessage = (
|
|
|
67
68
|
return 'ok → Awaiting Workspace';
|
|
68
69
|
case 'close':
|
|
69
70
|
return kind.action === 'close' ? 'Closed' : 'Closed as not planned';
|
|
71
|
+
case 'delete_all_comments':
|
|
72
|
+
return 'Deleted all comments';
|
|
70
73
|
}
|
|
71
74
|
};
|
|
72
75
|
|
|
@@ -94,6 +97,8 @@ export const actionToastColor = (
|
|
|
94
97
|
return 'blue';
|
|
95
98
|
case 'close':
|
|
96
99
|
return 'red';
|
|
100
|
+
case 'delete_all_comments':
|
|
101
|
+
return 'red';
|
|
97
102
|
}
|
|
98
103
|
};
|
|
99
104
|
|
|
@@ -104,6 +109,9 @@ export const actionAdvances = (
|
|
|
104
109
|
if (kind.type === 'next_action_date') {
|
|
105
110
|
return isManualTriageTab(tab);
|
|
106
111
|
}
|
|
112
|
+
if (kind.type === 'delete_all_comments') {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
107
115
|
return true;
|
|
108
116
|
};
|
|
109
117
|
|
|
@@ -43,6 +43,7 @@ export type ConsoleOperationHandlers = {
|
|
|
43
43
|
onSetInTmuxByHuman: (option: ConsoleFieldOption) => void;
|
|
44
44
|
onClose: (action: ConsoleCloseAction) => void;
|
|
45
45
|
onOkAndAwaitingWorkspace: (option: ConsoleFieldOption) => void;
|
|
46
|
+
onDeleteAllComments: () => void;
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
export const IN_TMUX_BY_HUMAN_NAME = 'In Tmux by human';
|
|
@@ -82,6 +82,7 @@ const buildOperations = (): ConsoleOperationsApi => ({
|
|
|
82
82
|
})),
|
|
83
83
|
uploadAttachment: jest.fn(async () => ''),
|
|
84
84
|
addInlineReviewComment: jest.fn(async () => {}),
|
|
85
|
+
deleteAllComments: jest.fn(async () => {}),
|
|
85
86
|
});
|
|
86
87
|
|
|
87
88
|
const findCommentsPanelToggle = (container: HTMLElement): HTMLElement => {
|
|
@@ -559,4 +560,70 @@ describe('ConsoleItemDetailContainer', () => {
|
|
|
559
560
|
]);
|
|
560
561
|
expect(reviewCall?.[3][0].body).not.toBe('');
|
|
561
562
|
});
|
|
563
|
+
|
|
564
|
+
it('routes delete-all-comments through onQueueAction with the correct kind and commit', async () => {
|
|
565
|
+
const operations = buildOperations();
|
|
566
|
+
const onQueueAction = jest.fn();
|
|
567
|
+
const { getByText } = render(
|
|
568
|
+
<ConsoleItemDetailContainer
|
|
569
|
+
tab="todo-by-agent"
|
|
570
|
+
item={issueItem}
|
|
571
|
+
caches={buildCaches()}
|
|
572
|
+
operations={operations}
|
|
573
|
+
statusOptions={consoleStatusOptionsFixture}
|
|
574
|
+
storyColors={consoleStoryColorsFixture}
|
|
575
|
+
storyName="TDPM Console port"
|
|
576
|
+
overlayStatus={null}
|
|
577
|
+
now={Date.parse('2026-06-19T12:00:00.000Z')}
|
|
578
|
+
onQueueAction={onQueueAction}
|
|
579
|
+
/>,
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
await waitFor(() => {
|
|
583
|
+
expect(getByText('⚠')).toBeInTheDocument();
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
fireEvent.click(getByText('⚠'));
|
|
587
|
+
fireEvent.click(getByText('Delete All Comments'));
|
|
588
|
+
|
|
589
|
+
expect(onQueueAction).toHaveBeenCalledTimes(1);
|
|
590
|
+
const input = onQueueAction.mock.calls[0][0];
|
|
591
|
+
expect(input.kind).toEqual({ type: 'delete_all_comments' });
|
|
592
|
+
expect(input.item).toBe(issueItem);
|
|
593
|
+
expect(operations.deleteAllComments).not.toHaveBeenCalled();
|
|
594
|
+
|
|
595
|
+
await input.commit();
|
|
596
|
+
expect(operations.deleteAllComments).toHaveBeenCalledWith(issueItem);
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
it('surfaces errors from deleteAllComments via the queue rather than swallowing them', async () => {
|
|
600
|
+
const operations = buildOperations();
|
|
601
|
+
const error = new Error('GitHub API failure');
|
|
602
|
+
(operations.deleteAllComments as jest.Mock).mockRejectedValue(error);
|
|
603
|
+
const onQueueAction = jest.fn();
|
|
604
|
+
const { getByText } = render(
|
|
605
|
+
<ConsoleItemDetailContainer
|
|
606
|
+
tab="todo-by-agent"
|
|
607
|
+
item={issueItem}
|
|
608
|
+
caches={buildCaches()}
|
|
609
|
+
operations={operations}
|
|
610
|
+
statusOptions={consoleStatusOptionsFixture}
|
|
611
|
+
storyColors={consoleStoryColorsFixture}
|
|
612
|
+
storyName="TDPM Console port"
|
|
613
|
+
overlayStatus={null}
|
|
614
|
+
now={Date.parse('2026-06-19T12:00:00.000Z')}
|
|
615
|
+
onQueueAction={onQueueAction}
|
|
616
|
+
/>,
|
|
617
|
+
);
|
|
618
|
+
|
|
619
|
+
await waitFor(() => {
|
|
620
|
+
expect(getByText('⚠')).toBeInTheDocument();
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
fireEvent.click(getByText('⚠'));
|
|
624
|
+
fireEvent.click(getByText('Delete All Comments'));
|
|
625
|
+
|
|
626
|
+
const input = onQueueAction.mock.calls[0][0];
|
|
627
|
+
await expect(input.commit()).rejects.toThrow('GitHub API failure');
|
|
628
|
+
});
|
|
562
629
|
});
|
|
@@ -262,6 +262,13 @@ export const ConsoleItemDetailContainer = ({
|
|
|
262
262
|
commit: () => operations.okAndMoveToAwaitingWorkspace(item, option),
|
|
263
263
|
});
|
|
264
264
|
},
|
|
265
|
+
onDeleteAllComments: () => {
|
|
266
|
+
onQueueAction({
|
|
267
|
+
kind: { type: 'delete_all_comments' },
|
|
268
|
+
item,
|
|
269
|
+
commit: () => operations.deleteAllComments(item),
|
|
270
|
+
});
|
|
271
|
+
},
|
|
265
272
|
};
|
|
266
273
|
|
|
267
274
|
const awaitingWorkspaceOption =
|
|
@@ -1133,6 +1133,12 @@ body {
|
|
|
1133
1133
|
color: #79c0ff;
|
|
1134
1134
|
}
|
|
1135
1135
|
|
|
1136
|
+
.console-op-button-danger {
|
|
1137
|
+
background: #3a1518;
|
|
1138
|
+
border-color: #f85149;
|
|
1139
|
+
color: #f85149;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1136
1142
|
.console-pr-section {
|
|
1137
1143
|
border: 1px solid #30363d;
|
|
1138
1144
|
border-radius: 8px;
|