github-issue-tower-defence-management 1.144.0 → 1.144.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 +14 -0
- package/bin/adapter/entry-points/console/ui-dist/assets/index-BYoG8oQb.js +82 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js +28 -4
- package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +3 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleDetailPrefetch.test.ts +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleItemDetailData.test.ts +2 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.test.ts +39 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.ts +14 -1
- package/src/adapter/entry-points/console/ui/src/features/console/logic/grouping.test.ts +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.test.ts +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/types.ts +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.test.tsx +42 -1
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.tsx +7 -2
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.test.tsx +7 -0
- package/src/adapter/entry-points/console/ui/src/features/console/testing/fixtures.ts +5 -0
- package/src/adapter/entry-points/console/ui-dist/assets/index-BYoG8oQb.js +82 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/src/domain/usecases/console/GenerateConsoleListsUseCase.test.ts +92 -0
- package/src/domain/usecases/console/GenerateConsoleListsUseCase.ts +52 -4
- package/types/domain/usecases/console/GenerateConsoleListsUseCase.d.ts +3 -0
- package/types/domain/usecases/console/GenerateConsoleListsUseCase.d.ts.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-y6LyqXlu.js +0 -82
- package/src/adapter/entry-points/console/ui-dist/assets/index-y6LyqXlu.js +0 -82
|
@@ -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-BYoG8oQb.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-CKX2ny-z.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -10,6 +10,7 @@ class GenerateConsoleListsUseCase {
|
|
|
10
10
|
const storyOptions = project.story ? project.story.stories : [];
|
|
11
11
|
const storyOrder = storyOptions.map((option) => option.name);
|
|
12
12
|
const statusOptions = project.status.statuses;
|
|
13
|
+
const relatedOpenPullRequestUrlsByIssueUrl = this.buildRelatedOpenPullRequestUrlsByIssueUrl(issues);
|
|
13
14
|
const visibleIssues = issues.filter((issue) => issue.status?.toLowerCase() !==
|
|
14
15
|
WorkflowStatus_1.IN_TMUX_BY_AGENT_STATUS_NAME.toLowerCase());
|
|
15
16
|
const actionableIssues = visibleIssues.filter((issue) => this.isActionable(issue, assigneeLogin));
|
|
@@ -19,7 +20,9 @@ class GenerateConsoleListsUseCase {
|
|
|
19
20
|
statusOptions: this.buildFieldOptions(statusOptions, excludedStatusNames),
|
|
20
21
|
storyOrder,
|
|
21
22
|
storyColors: this.buildStoryColorsObject(storyOptions),
|
|
22
|
-
items: this.sortByStoryOrder(sourceIssues
|
|
23
|
+
items: this.sortByStoryOrder(sourceIssues
|
|
24
|
+
.filter(selector)
|
|
25
|
+
.map((issue) => this.projectItem(issue, relatedOpenPullRequestUrlsByIssueUrl.get(issue.url) ?? [])), storyOrder),
|
|
23
26
|
});
|
|
24
27
|
const buildStatusTab = (selector, excludedStatusNames) => buildStatusTabFromSource(actionableIssues, selector, excludedStatusNames);
|
|
25
28
|
return {
|
|
@@ -51,15 +54,16 @@ class GenerateConsoleListsUseCase {
|
|
|
51
54
|
issue.story.toLowerCase().includes('no story') &&
|
|
52
55
|
issue.status?.toLowerCase() !==
|
|
53
56
|
WorkflowStatus_1.IN_TMUX_BY_AGENT_STATUS_NAME.toLowerCase())
|
|
54
|
-
.map((issue) => this.projectItem(issue)), storyOrder),
|
|
57
|
+
.map((issue) => this.projectItem(issue, relatedOpenPullRequestUrlsByIssueUrl.get(issue.url) ?? [])), storyOrder),
|
|
55
58
|
},
|
|
56
59
|
};
|
|
57
60
|
};
|
|
58
61
|
this.isActionable = (issue, assigneeLogin) => issue.isClosed === false &&
|
|
59
|
-
|
|
62
|
+
this.isOwnedByNobodyElse(issue, assigneeLogin) &&
|
|
60
63
|
issue.dependedIssueUrls.length === 0 &&
|
|
61
64
|
issue.nextActionDate === null &&
|
|
62
65
|
issue.nextActionHour === null;
|
|
66
|
+
this.isOwnedByNobodyElse = (issue, assigneeLogin) => issue.assignees.length === 0 || issue.assignees.includes(assigneeLogin);
|
|
63
67
|
this.workflowBlockerSelector = (workflowBlockerStoryName) => {
|
|
64
68
|
const target = workflowBlockerStoryName?.toLowerCase() ?? '';
|
|
65
69
|
if (target === '') {
|
|
@@ -67,7 +71,26 @@ class GenerateConsoleListsUseCase {
|
|
|
67
71
|
}
|
|
68
72
|
return (issue) => issue.story !== null && issue.story.toLowerCase() === target;
|
|
69
73
|
};
|
|
70
|
-
this.
|
|
74
|
+
this.buildRelatedOpenPullRequestUrlsByIssueUrl = (issues) => {
|
|
75
|
+
const urlsByIssueUrl = new Map();
|
|
76
|
+
for (const issue of issues) {
|
|
77
|
+
if (!issue.isPr || issue.isClosed) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
for (const referencedIssueUrl of issue.closingIssueReferenceUrls) {
|
|
81
|
+
const existing = urlsByIssueUrl.get(referencedIssueUrl);
|
|
82
|
+
if (existing === undefined) {
|
|
83
|
+
urlsByIssueUrl.set(referencedIssueUrl, [issue.url]);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (!existing.includes(issue.url)) {
|
|
87
|
+
existing.push(issue.url);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return urlsByIssueUrl;
|
|
92
|
+
};
|
|
93
|
+
this.projectItem = (issue, relatedOpenPullRequestUrls) => ({
|
|
71
94
|
number: issue.number,
|
|
72
95
|
title: issue.title,
|
|
73
96
|
url: issue.url,
|
|
@@ -83,6 +106,7 @@ class GenerateConsoleListsUseCase {
|
|
|
83
106
|
dependedIssueUrls: issue.dependedIssueUrls,
|
|
84
107
|
labels: issue.labels,
|
|
85
108
|
createdAt: issue.createdAt.toISOString(),
|
|
109
|
+
relatedOpenPullRequestUrls,
|
|
86
110
|
});
|
|
87
111
|
this.buildFieldOptions = (options, excludedLowerCaseNames) => options
|
|
88
112
|
.filter((option) => !excludedLowerCaseNames.includes(option.name.toLowerCase()))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GenerateConsoleListsUseCase.js","sourceRoot":"","sources":["../../../../src/domain/usecases/console/GenerateConsoleListsUseCase.ts"],"names":[],"mappings":";;;AAEA,kEAKuC;
|
|
1
|
+
{"version":3,"file":"GenerateConsoleListsUseCase.js","sourceRoot":"","sources":["../../../../src/domain/usecases/console/GenerateConsoleListsUseCase.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -53,6 +53,7 @@ type ConsoleFixtureListItem = {
|
|
|
53
53
|
dependedIssueUrls: string[];
|
|
54
54
|
labels: string[];
|
|
55
55
|
createdAt: string;
|
|
56
|
+
relatedOpenPullRequestUrls: string[];
|
|
56
57
|
};
|
|
57
58
|
|
|
58
59
|
type ConsoleFixtureFieldOption = {
|
|
@@ -144,6 +145,7 @@ const issueItem = (
|
|
|
144
145
|
projectItemId: `PVTI_lADOABCD1234zg${projectItemSuffix}`,
|
|
145
146
|
itemId: `PVTI_lADOABCD1234zg${projectItemSuffix}`,
|
|
146
147
|
isPr: false,
|
|
148
|
+
relatedOpenPullRequestUrls: [],
|
|
147
149
|
story,
|
|
148
150
|
status: null,
|
|
149
151
|
nextActionDate: null,
|
|
@@ -168,6 +170,7 @@ const pullRequestItem = (
|
|
|
168
170
|
projectItemId: `PVTI_lADOABCD1234zg${projectItemSuffix}`,
|
|
169
171
|
itemId: `PVTI_lADOABCD1234zg${projectItemSuffix}`,
|
|
170
172
|
isPr: true,
|
|
173
|
+
relatedOpenPullRequestUrls: [],
|
|
171
174
|
story,
|
|
172
175
|
status: null,
|
|
173
176
|
nextActionDate: null,
|
|
@@ -21,6 +21,7 @@ const prItem: ConsoleListItem = {
|
|
|
21
21
|
projectItemId: 'PVTI_1',
|
|
22
22
|
itemId: 'PVTI_1',
|
|
23
23
|
isPr: true,
|
|
24
|
+
relatedOpenPullRequestUrls: [],
|
|
24
25
|
story: 'Story',
|
|
25
26
|
status: null,
|
|
26
27
|
nextActionDate: null,
|
|
@@ -33,6 +34,7 @@ const prItem: ConsoleListItem = {
|
|
|
33
34
|
const issueItem: ConsoleListItem = {
|
|
34
35
|
...prItem,
|
|
35
36
|
isPr: false,
|
|
37
|
+
relatedOpenPullRequestUrls: [],
|
|
36
38
|
url: 'https://github.com/o/r/issues/2',
|
|
37
39
|
number: 2,
|
|
38
40
|
};
|
package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.test.ts
CHANGED
|
@@ -41,6 +41,45 @@ describe('useConsoleTabData', () => {
|
|
|
41
41
|
);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
+
it('normalizes relatedOpenPullRequestUrls for a snapshot written before the field existed', async () => {
|
|
45
|
+
const fetchMock = jest.fn(async (url: string) => ({
|
|
46
|
+
ok: true,
|
|
47
|
+
status: 200,
|
|
48
|
+
json: async () => ({
|
|
49
|
+
pjcode: 'umino',
|
|
50
|
+
generatedAt: '2026-06-19T00:00:00.000Z',
|
|
51
|
+
statusOptions: [],
|
|
52
|
+
storyColors: {},
|
|
53
|
+
items: url.includes('/prs/')
|
|
54
|
+
? [
|
|
55
|
+
{ number: 1, itemId: 'PVTI_1', projectItemId: 'PVTI_1' },
|
|
56
|
+
{
|
|
57
|
+
number: 2,
|
|
58
|
+
itemId: 'PVTI_2',
|
|
59
|
+
projectItemId: 'PVTI_2',
|
|
60
|
+
relatedOpenPullRequestUrls: [
|
|
61
|
+
'https://github.com/demo/repo/pull/7',
|
|
62
|
+
9,
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
]
|
|
66
|
+
: [],
|
|
67
|
+
}),
|
|
68
|
+
}));
|
|
69
|
+
global.fetch = fetchMock as unknown as typeof fetch;
|
|
70
|
+
|
|
71
|
+
const { result } = renderHook(() => useConsoleTabData('umino'));
|
|
72
|
+
await waitFor(() => {
|
|
73
|
+
expect(result.current.isLoading).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
expect(
|
|
76
|
+
result.current.snapshots.prs?.items[0].relatedOpenPullRequestUrls,
|
|
77
|
+
).toEqual([]);
|
|
78
|
+
expect(
|
|
79
|
+
result.current.snapshots.prs?.items[1].relatedOpenPullRequestUrls,
|
|
80
|
+
).toEqual(['https://github.com/demo/repo/pull/7']);
|
|
81
|
+
});
|
|
82
|
+
|
|
44
83
|
it('drops an item that disappeared from the snapshot after the refresh interval', async () => {
|
|
45
84
|
jest.useFakeTimers();
|
|
46
85
|
let closed = false;
|
|
@@ -24,11 +24,24 @@ export type ConsoleTabDataState = {
|
|
|
24
24
|
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
25
25
|
value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
26
26
|
|
|
27
|
+
const parseStringArray = (value: unknown): string[] =>
|
|
28
|
+
Array.isArray(value)
|
|
29
|
+
? value.filter((entry): entry is string => typeof entry === 'string')
|
|
30
|
+
: [];
|
|
31
|
+
|
|
27
32
|
const parseItems = (payload: unknown): ConsoleListItem[] => {
|
|
28
33
|
if (!isRecord(payload) || !Array.isArray(payload.items)) {
|
|
29
34
|
return [];
|
|
30
35
|
}
|
|
31
|
-
return payload.items.filter(isRecord)
|
|
36
|
+
return payload.items.filter(isRecord).map(
|
|
37
|
+
(item) =>
|
|
38
|
+
({
|
|
39
|
+
...item,
|
|
40
|
+
relatedOpenPullRequestUrls: parseStringArray(
|
|
41
|
+
item.relatedOpenPullRequestUrls,
|
|
42
|
+
),
|
|
43
|
+
}) as unknown as ConsoleListItem,
|
|
44
|
+
);
|
|
32
45
|
};
|
|
33
46
|
|
|
34
47
|
const parseOptions = (value: unknown): ConsoleFieldOption[] => {
|
|
@@ -26,6 +26,7 @@ const issueItem = consoleListItemsFixture[2];
|
|
|
26
26
|
type CachesOverrides = {
|
|
27
27
|
relatedPrs?: ConsoleRelatedPullRequest[];
|
|
28
28
|
prFiles?: ConsoleChangedFile[];
|
|
29
|
+
relatedPrsNeverResolve?: boolean;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
const buildCaches = (overrides: CachesOverrides = {}): ConsoleCaches => {
|
|
@@ -34,7 +35,10 @@ const buildCaches = (overrides: CachesOverrides = {}): ConsoleCaches => {
|
|
|
34
35
|
fetchComments: async () => [],
|
|
35
36
|
fetchPrFiles: async () => overrides.prFiles ?? [],
|
|
36
37
|
fetchPrCommits: async () => [],
|
|
37
|
-
fetchRelatedPrs: async () =>
|
|
38
|
+
fetchRelatedPrs: async () =>
|
|
39
|
+
overrides.relatedPrsNeverResolve === true
|
|
40
|
+
? new Promise<ConsoleRelatedPullRequest[]>(() => {})
|
|
41
|
+
: (overrides.relatedPrs ?? []),
|
|
38
42
|
fetchIssueState: async () => ({
|
|
39
43
|
state: 'open',
|
|
40
44
|
merged: false,
|
|
@@ -116,6 +120,43 @@ describe('ConsoleItemDetailContainer', () => {
|
|
|
116
120
|
);
|
|
117
121
|
});
|
|
118
122
|
|
|
123
|
+
it('shows Approve for an issue item from the generated related open pull request urls before the related pull requests are fetched', () => {
|
|
124
|
+
const operations = buildOperations();
|
|
125
|
+
const onQueueAction = jest.fn();
|
|
126
|
+
const bakedPullRequestUrl =
|
|
127
|
+
'https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/pull/1372';
|
|
128
|
+
const itemWithBakedPullRequest = {
|
|
129
|
+
...issueItem,
|
|
130
|
+
relatedOpenPullRequestUrls: [bakedPullRequestUrl],
|
|
131
|
+
};
|
|
132
|
+
const { getByText } = render(
|
|
133
|
+
<ConsoleItemDetailContainer
|
|
134
|
+
tab="prs"
|
|
135
|
+
item={itemWithBakedPullRequest}
|
|
136
|
+
caches={buildCaches({ relatedPrsNeverResolve: true })}
|
|
137
|
+
operations={operations}
|
|
138
|
+
statusOptions={consoleStatusOptionsFixture}
|
|
139
|
+
storyOptions={consoleStoryOptionsFixture}
|
|
140
|
+
storyColors={consoleStoryColorsFixture}
|
|
141
|
+
storyName="TDPM Console port"
|
|
142
|
+
overlayStatus={null}
|
|
143
|
+
now={Date.parse('2026-06-19T12:00:00.000Z')}
|
|
144
|
+
onQueueAction={onQueueAction}
|
|
145
|
+
/>,
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
expect(getByText('Approve')).toBeInTheDocument();
|
|
149
|
+
fireEvent.click(getByText('Approve'));
|
|
150
|
+
const input = onQueueAction.mock.calls[0][0];
|
|
151
|
+
input.commit();
|
|
152
|
+
expect(operations.reviewPullRequest).toHaveBeenCalledWith(
|
|
153
|
+
itemWithBakedPullRequest,
|
|
154
|
+
bakedPullRequestUrl,
|
|
155
|
+
'approve',
|
|
156
|
+
[],
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
|
|
119
160
|
it('disables Reject until an inline comment is entered and then commits it as the request-changes review', async () => {
|
|
120
161
|
const operations = buildOperations();
|
|
121
162
|
const onQueueAction = jest.fn();
|
|
@@ -71,7 +71,10 @@ export const ConsoleItemDetailContainer = ({
|
|
|
71
71
|
),
|
|
72
72
|
[caches.state],
|
|
73
73
|
);
|
|
74
|
-
const hasPullRequest =
|
|
74
|
+
const hasPullRequest =
|
|
75
|
+
item.isPr ||
|
|
76
|
+
item.relatedOpenPullRequestUrls.length > 0 ||
|
|
77
|
+
detail.relatedPullRequests.length > 0;
|
|
75
78
|
const [pendingReviewComments, setPendingReviewComments] = useState<
|
|
76
79
|
ConsolePendingReviewComment[]
|
|
77
80
|
>([]);
|
|
@@ -89,7 +92,9 @@ export const ConsoleItemDetailContainer = ({
|
|
|
89
92
|
onReview: (action) => {
|
|
90
93
|
const prUrl = item.isPr
|
|
91
94
|
? item.url
|
|
92
|
-
: (detail.relatedPullRequests[0]?.pullRequest.url ??
|
|
95
|
+
: (detail.relatedPullRequests[0]?.pullRequest.url ??
|
|
96
|
+
item.relatedOpenPullRequestUrls[0] ??
|
|
97
|
+
item.url);
|
|
93
98
|
const reviewComments =
|
|
94
99
|
action === 'request_changes' ? pendingReviewComments : [];
|
|
95
100
|
onQueueAction({
|
|
@@ -37,6 +37,7 @@ const listPayload = (tab: string) => ({
|
|
|
37
37
|
projectItemId: 'PVTI_1',
|
|
38
38
|
itemId: 'PVTI_1',
|
|
39
39
|
isPr: true,
|
|
40
|
+
relatedOpenPullRequestUrls: [],
|
|
40
41
|
story: 'TDPM Console port',
|
|
41
42
|
status: 'Awaiting Quality Check',
|
|
42
43
|
nextActionDate: null,
|
|
@@ -57,6 +58,7 @@ const listPayload = (tab: string) => ({
|
|
|
57
58
|
projectItemId: 'PVTI_2',
|
|
58
59
|
itemId: 'PVTI_2',
|
|
59
60
|
isPr: false,
|
|
61
|
+
relatedOpenPullRequestUrls: [],
|
|
60
62
|
story: 'TDPM Console port',
|
|
61
63
|
status: 'Unread',
|
|
62
64
|
nextActionDate: null,
|
|
@@ -266,6 +268,7 @@ describe('ConsolePage', () => {
|
|
|
266
268
|
projectItemId: 'PVTI_B1',
|
|
267
269
|
itemId: 'PVTI_B1',
|
|
268
270
|
isPr: false,
|
|
271
|
+
relatedOpenPullRequestUrls: [],
|
|
269
272
|
story: 'TDPM Console port',
|
|
270
273
|
status: 'In Progress',
|
|
271
274
|
nextActionDate: null,
|
|
@@ -283,6 +286,7 @@ describe('ConsolePage', () => {
|
|
|
283
286
|
projectItemId: 'PVTI_B2',
|
|
284
287
|
itemId: 'PVTI_B2',
|
|
285
288
|
isPr: false,
|
|
289
|
+
relatedOpenPullRequestUrls: [],
|
|
286
290
|
story: 'TDPM Console port',
|
|
287
291
|
status: 'In Progress',
|
|
288
292
|
nextActionDate: null,
|
|
@@ -348,6 +352,7 @@ describe('ConsolePage', () => {
|
|
|
348
352
|
projectItemId: 'PVTI_B1',
|
|
349
353
|
itemId: 'PVTI_B1',
|
|
350
354
|
isPr: false,
|
|
355
|
+
relatedOpenPullRequestUrls: [],
|
|
351
356
|
story: 'TDPM Console port',
|
|
352
357
|
status: 'In Progress',
|
|
353
358
|
nextActionDate: null,
|
|
@@ -472,6 +477,7 @@ const twoItemPrPayload = () => ({
|
|
|
472
477
|
projectItemId: 'PVTI_1',
|
|
473
478
|
itemId: 'PVTI_1',
|
|
474
479
|
isPr: true,
|
|
480
|
+
relatedOpenPullRequestUrls: [],
|
|
475
481
|
story: 'TDPM Console port',
|
|
476
482
|
status: 'Awaiting Quality Check',
|
|
477
483
|
nextActionDate: null,
|
|
@@ -489,6 +495,7 @@ const twoItemPrPayload = () => ({
|
|
|
489
495
|
projectItemId: 'PVTI_2',
|
|
490
496
|
itemId: 'PVTI_2',
|
|
491
497
|
isPr: true,
|
|
498
|
+
relatedOpenPullRequestUrls: [],
|
|
492
499
|
story: 'TDPM Console port',
|
|
493
500
|
status: 'Awaiting Quality Check',
|
|
494
501
|
nextActionDate: null,
|
|
@@ -56,6 +56,7 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
56
56
|
projectItemId: 'PVTI_lADOABCD1234zgABCD01',
|
|
57
57
|
itemId: 'PVTI_lADOABCD1234zgABCD01',
|
|
58
58
|
isPr: true,
|
|
59
|
+
relatedOpenPullRequestUrls: [],
|
|
59
60
|
story: 'TDPM Console port',
|
|
60
61
|
status: 'Awaiting Quality Check',
|
|
61
62
|
nextActionDate: null,
|
|
@@ -77,6 +78,7 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
77
78
|
projectItemId: 'PVTI_lADOABCD1234zgABCD02',
|
|
78
79
|
itemId: 'PVTI_lADOABCD1234zgABCD02',
|
|
79
80
|
isPr: true,
|
|
81
|
+
relatedOpenPullRequestUrls: [],
|
|
80
82
|
story: 'TDPM Console port',
|
|
81
83
|
status: 'Preparation',
|
|
82
84
|
nextActionDate: null,
|
|
@@ -95,6 +97,7 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
95
97
|
projectItemId: 'PVTI_lADOABCD1234zgABCD03',
|
|
96
98
|
itemId: 'PVTI_lADOABCD1234zgABCD03',
|
|
97
99
|
isPr: false,
|
|
100
|
+
relatedOpenPullRequestUrls: [],
|
|
98
101
|
story: 'TDPM Console port',
|
|
99
102
|
status: 'Todo by human',
|
|
100
103
|
nextActionDate: '2026-06-20T07:00:00.000Z',
|
|
@@ -113,6 +116,7 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
113
116
|
projectItemId: 'PVTI_lADOABCD1234zgABCD04',
|
|
114
117
|
itemId: 'PVTI_lADOABCD1234zgABCD04',
|
|
115
118
|
isPr: false,
|
|
119
|
+
relatedOpenPullRequestUrls: [],
|
|
116
120
|
story: 'regular / workflow improvement',
|
|
117
121
|
status: null,
|
|
118
122
|
nextActionDate: null,
|
|
@@ -131,6 +135,7 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
131
135
|
projectItemId: 'PVTI_lADOABCD1234zgABCD05',
|
|
132
136
|
itemId: 'PVTI_lADOABCD1234zgABCD05',
|
|
133
137
|
isPr: false,
|
|
138
|
+
relatedOpenPullRequestUrls: [],
|
|
134
139
|
story: 'Publish product documentation site',
|
|
135
140
|
status: 'Icebox',
|
|
136
141
|
nextActionDate: null,
|