@orchestrator-ui/orchestrator-ui-components 0.11.0 → 0.12.0
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/.turbo/turbo-build.log +5 -5
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +10 -10
- package/CHANGELOG.md +14 -0
- package/dist/index.d.ts +144 -83
- package/dist/index.js +714 -539
- package/package.json +1 -1
- package/src/api/index.ts +12 -18
- package/src/components/WfoAuth/WfoPageUnauthorized.tsx +8 -0
- package/src/components/WfoAuth/WfoPolicyRenderPageFallback.tsx +19 -0
- package/src/components/WfoAuth/index.ts +2 -0
- package/src/components/WfoForms/CreateForm.tsx +1 -1
- package/src/components/WfoForms/index.ts +1 -1
- package/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx +36 -3
- package/src/components/WfoSubscription/WfoSubscriptionActions.tsx +65 -44
- package/src/configuration/index.ts +2 -0
- package/src/configuration/policy-resources.ts +19 -0
- package/src/hooks/useQueryWithFetch.ts +7 -2
- package/src/index.ts +6 -5
- package/src/messages/en-GB.json +6 -0
- package/src/messages/nl-NL.json +6 -0
- package/src/pages/processes/WfoProcessDetail.tsx +89 -71
- package/src/pages/startPage/WfoStartPage.tsx +48 -0
- package/src/pages/tasks/WfoTasksListPage.tsx +20 -8
- package/src/types/index.ts +1 -0
- package/src/utils/string.spec.ts +37 -1
- package/src/utils/strings.ts +9 -0
|
@@ -17,14 +17,17 @@ import {
|
|
|
17
17
|
PATH_TASKS,
|
|
18
18
|
PATH_WORKFLOWS,
|
|
19
19
|
TimelineItem,
|
|
20
|
+
WfoIsAllowedToRender,
|
|
20
21
|
WfoLoading,
|
|
21
22
|
WfoTimeline,
|
|
22
23
|
} from '@/components';
|
|
24
|
+
import { PolicyResource } from '@/configuration/policy-resources';
|
|
23
25
|
import { ConfirmationDialogContext } from '@/contexts';
|
|
24
26
|
import {
|
|
25
27
|
useCheckEngineStatus,
|
|
26
28
|
useMutateProcess,
|
|
27
29
|
useOrchestratorTheme,
|
|
30
|
+
usePolicy,
|
|
28
31
|
} from '@/hooks';
|
|
29
32
|
import { WfoRefresh, WfoXCircleFill } from '@/icons';
|
|
30
33
|
import { ProcessDetail, ProcessStatus } from '@/types';
|
|
@@ -101,6 +104,7 @@ export const WfoProcessDetail = ({
|
|
|
101
104
|
const { deleteProcess, abortProcess, retryProcess } = useMutateProcess();
|
|
102
105
|
const router = useRouter();
|
|
103
106
|
const { isEngineRunningNow } = useCheckEngineStatus();
|
|
107
|
+
const { isAllowed } = usePolicy();
|
|
104
108
|
|
|
105
109
|
const listIncludesStatus = (
|
|
106
110
|
processStatusesForDisabledState: ProcessStatus[],
|
|
@@ -195,55 +199,65 @@ export const WfoProcessDetail = ({
|
|
|
195
199
|
css={{ flexGrow: 0 }}
|
|
196
200
|
gutterSize="s"
|
|
197
201
|
>
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
iconType={() => (
|
|
201
|
-
<WfoRefresh
|
|
202
|
-
color={
|
|
203
|
-
retryButtonIsDisabled
|
|
204
|
-
? theme.colors.subduedText
|
|
205
|
-
: theme.colors.link
|
|
206
|
-
}
|
|
207
|
-
/>
|
|
208
|
-
)}
|
|
209
|
-
isDisabled={retryButtonIsDisabled}
|
|
202
|
+
<WfoIsAllowedToRender
|
|
203
|
+
resource={PolicyResource.PROCESS_RETRY}
|
|
210
204
|
>
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
205
|
+
<EuiButton
|
|
206
|
+
onClick={handleActionButtonClick(retryAction)}
|
|
207
|
+
iconType={() => (
|
|
208
|
+
<WfoRefresh
|
|
209
|
+
color={
|
|
210
|
+
retryButtonIsDisabled
|
|
211
|
+
? theme.colors.subduedText
|
|
212
|
+
: theme.colors.link
|
|
213
|
+
}
|
|
214
|
+
/>
|
|
215
|
+
)}
|
|
216
|
+
isDisabled={retryButtonIsDisabled}
|
|
217
|
+
>
|
|
218
|
+
{t('retry')}
|
|
219
|
+
</EuiButton>
|
|
220
|
+
</WfoIsAllowedToRender>
|
|
221
|
+
<WfoIsAllowedToRender
|
|
222
|
+
resource={PolicyResource.PROCESS_ABORT}
|
|
226
223
|
>
|
|
227
|
-
{t('abort')}
|
|
228
|
-
</EuiButton>
|
|
229
|
-
{processDetail && processIsTask && (
|
|
230
224
|
<EuiButton
|
|
231
|
-
onClick={handleActionButtonClick(
|
|
225
|
+
onClick={handleActionButtonClick(abortAction)}
|
|
232
226
|
iconType={() => (
|
|
233
227
|
<WfoXCircleFill
|
|
234
228
|
color={
|
|
235
|
-
|
|
229
|
+
abortButtonIsDisabled
|
|
236
230
|
? theme.colors.subduedText
|
|
237
231
|
: theme.colors.danger
|
|
238
232
|
}
|
|
239
233
|
/>
|
|
240
234
|
)}
|
|
241
235
|
color="danger"
|
|
242
|
-
isDisabled={
|
|
236
|
+
isDisabled={abortButtonIsDisabled}
|
|
243
237
|
>
|
|
244
|
-
{t('
|
|
238
|
+
{t('abort')}
|
|
245
239
|
</EuiButton>
|
|
246
|
-
|
|
240
|
+
</WfoIsAllowedToRender>
|
|
241
|
+
{processDetail &&
|
|
242
|
+
processIsTask &&
|
|
243
|
+
isAllowed(PolicyResource.PROCESS_DELETE) && (
|
|
244
|
+
<EuiButton
|
|
245
|
+
onClick={handleActionButtonClick(deleteAction)}
|
|
246
|
+
iconType={() => (
|
|
247
|
+
<WfoXCircleFill
|
|
248
|
+
color={
|
|
249
|
+
deleteButtonIsDisabled
|
|
250
|
+
? theme.colors.subduedText
|
|
251
|
+
: theme.colors.danger
|
|
252
|
+
}
|
|
253
|
+
/>
|
|
254
|
+
)}
|
|
255
|
+
color="danger"
|
|
256
|
+
isDisabled={deleteButtonIsDisabled}
|
|
257
|
+
>
|
|
258
|
+
{t('delete')}
|
|
259
|
+
</EuiButton>
|
|
260
|
+
)}
|
|
247
261
|
</EuiFlexGroup>
|
|
248
262
|
</EuiFlexGroup>
|
|
249
263
|
<EuiSpacer />
|
|
@@ -295,47 +309,51 @@ export const WfoProcessDetail = ({
|
|
|
295
309
|
: ''
|
|
296
310
|
}
|
|
297
311
|
/>
|
|
298
|
-
{process &&
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
>
|
|
307
|
-
<EuiText size="xs">
|
|
308
|
-
{t('relatedSubscriptions')}
|
|
309
|
-
</EuiText>
|
|
310
|
-
<EuiText
|
|
312
|
+
{process &&
|
|
313
|
+
isAllowed(
|
|
314
|
+
PolicyResource.PROCESS_RELATED_SUBSCRIPTIONS,
|
|
315
|
+
) &&
|
|
316
|
+
processDetail.subscriptions && (
|
|
317
|
+
<EuiFlexGroup
|
|
318
|
+
gutterSize="xs"
|
|
319
|
+
direction="column"
|
|
311
320
|
css={{
|
|
312
321
|
flex: 1,
|
|
313
|
-
whiteSpace: 'nowrap',
|
|
314
322
|
overflow: 'hidden',
|
|
315
|
-
textOverflow: 'ellipsis',
|
|
316
|
-
fontSize: theme.size.m,
|
|
317
323
|
}}
|
|
318
324
|
>
|
|
319
|
-
<
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
325
|
+
<EuiText size="xs">
|
|
326
|
+
{t('relatedSubscriptions')}
|
|
327
|
+
</EuiText>
|
|
328
|
+
<EuiText
|
|
329
|
+
css={{
|
|
330
|
+
flex: 1,
|
|
331
|
+
whiteSpace: 'nowrap',
|
|
332
|
+
overflow: 'hidden',
|
|
333
|
+
textOverflow: 'ellipsis',
|
|
334
|
+
fontSize: theme.size.m,
|
|
335
|
+
}}
|
|
336
|
+
>
|
|
337
|
+
<WfoProcessListSubscriptionsCell
|
|
338
|
+
subscriptions={
|
|
339
|
+
(process &&
|
|
340
|
+
processDetail?.subscriptions?.page.map(
|
|
341
|
+
(subscription) => ({
|
|
342
|
+
subscriptionId:
|
|
343
|
+
subscription.subscriptionId,
|
|
344
|
+
description:
|
|
345
|
+
subscription.description,
|
|
346
|
+
}),
|
|
347
|
+
)) ||
|
|
348
|
+
[]
|
|
349
|
+
}
|
|
350
|
+
renderDirection={
|
|
351
|
+
RenderDirection.VERTICAL
|
|
352
|
+
}
|
|
353
|
+
/>
|
|
354
|
+
</EuiText>
|
|
355
|
+
</EuiFlexGroup>
|
|
356
|
+
)}
|
|
339
357
|
</EuiFlexGroup>
|
|
340
358
|
))}
|
|
341
359
|
</EuiPanel>
|
|
@@ -36,6 +36,14 @@ export const WfoStartPage = () => {
|
|
|
36
36
|
subscriptionsListSummaryQueryVariables,
|
|
37
37
|
['subscriptions', 'startPage'],
|
|
38
38
|
);
|
|
39
|
+
const {
|
|
40
|
+
data: outOfSyncSubscriptionsSummaryResult,
|
|
41
|
+
isLoading: outOfSyncsubscriptionsSummaryIsFetching,
|
|
42
|
+
} = useQueryWithGraphql(
|
|
43
|
+
getSubscriptionsListSummaryGraphQlQuery(),
|
|
44
|
+
outOfSyncSubscriptionsListSummaryQueryVariables,
|
|
45
|
+
['subscriptions', 'startPage'],
|
|
46
|
+
);
|
|
39
47
|
const {
|
|
40
48
|
data: processesSummaryResult,
|
|
41
49
|
isLoading: processesSummaryIsFetching,
|
|
@@ -82,6 +90,28 @@ export const WfoStartPage = () => {
|
|
|
82
90
|
isLoading: subscriptionsSummaryIsFetching,
|
|
83
91
|
};
|
|
84
92
|
|
|
93
|
+
const latestOutOfSyncSubscriptionsSummaryCard: SummaryCard = {
|
|
94
|
+
headerTitle: t('outOfSyncSubscriptions.headerTitle'),
|
|
95
|
+
headerValue:
|
|
96
|
+
outOfSyncSubscriptionsSummaryResult?.subscriptions.pageInfo
|
|
97
|
+
.totalItems ?? 0,
|
|
98
|
+
headerStatus: SummaryCardStatus.Error,
|
|
99
|
+
listTitle: t('outOfSyncSubscriptions.listTitle'),
|
|
100
|
+
listItems:
|
|
101
|
+
outOfSyncSubscriptionsSummaryResult?.subscriptions.page.map(
|
|
102
|
+
(subscription) => ({
|
|
103
|
+
title: subscription.description,
|
|
104
|
+
value: formatDate(subscription.startDate),
|
|
105
|
+
url: `${PATH_SUBSCRIPTIONS}/${subscription.subscriptionId}`,
|
|
106
|
+
}),
|
|
107
|
+
) ?? [],
|
|
108
|
+
button: {
|
|
109
|
+
name: t('outOfSyncSubscriptions.buttonText'),
|
|
110
|
+
url: `${PATH_SUBSCRIPTIONS}?activeTab=ALL&sortBy=field-startDate_order-ASC&queryString=status%3A%28provisioning%7Cactive%29+insync%3Afalse`,
|
|
111
|
+
},
|
|
112
|
+
isLoading: outOfSyncsubscriptionsSummaryIsFetching,
|
|
113
|
+
};
|
|
114
|
+
|
|
85
115
|
const latestWorkflowsSummaryCard: SummaryCard = {
|
|
86
116
|
headerTitle: t('activeWorkflows.headerTitle'),
|
|
87
117
|
headerValue: processesSummaryResult?.processes.pageInfo.totalItems ?? 0,
|
|
@@ -155,6 +185,7 @@ export const WfoStartPage = () => {
|
|
|
155
185
|
<WfoSummaryCards
|
|
156
186
|
summaryCards={[
|
|
157
187
|
failedTasksSummaryCard,
|
|
188
|
+
latestOutOfSyncSubscriptionsSummaryCard,
|
|
158
189
|
latestWorkflowsSummaryCard,
|
|
159
190
|
latestActiveSubscriptionsSummaryCard,
|
|
160
191
|
productsSummaryCard,
|
|
@@ -180,6 +211,23 @@ const subscriptionsListSummaryQueryVariables: GraphqlQueryVariables<Subscription
|
|
|
180
211
|
],
|
|
181
212
|
};
|
|
182
213
|
|
|
214
|
+
const outOfSyncSubscriptionsListSummaryQueryVariables: GraphqlQueryVariables<Subscription> =
|
|
215
|
+
{
|
|
216
|
+
first: 5,
|
|
217
|
+
after: 0,
|
|
218
|
+
sortBy: {
|
|
219
|
+
field: 'startDate',
|
|
220
|
+
order: SortOrder.ASC,
|
|
221
|
+
},
|
|
222
|
+
query: 'insync:false',
|
|
223
|
+
filterBy: [
|
|
224
|
+
{
|
|
225
|
+
field: 'status',
|
|
226
|
+
value: 'Active-Provisioning',
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
};
|
|
230
|
+
|
|
183
231
|
const processListSummaryQueryVariables: GraphqlQueryVariables<Process> = {
|
|
184
232
|
first: 5,
|
|
185
233
|
after: 0,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
DEFAULT_PAGE_SIZE,
|
|
20
20
|
StoredTableConfig,
|
|
21
21
|
WfoFilterTabs,
|
|
22
|
+
WfoIsAllowedToRender,
|
|
22
23
|
WfoStartTaskButtonComboBox,
|
|
23
24
|
WfoTableColumns,
|
|
24
25
|
} from '@/components';
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
ProcessListItem,
|
|
28
29
|
WfoProcessesList,
|
|
29
30
|
} from '@/components/WfoProcessList/WfoProcessesList';
|
|
31
|
+
import { PolicyResource } from '@/configuration/policy-resources';
|
|
30
32
|
import { ConfirmationDialogContext } from '@/contexts';
|
|
31
33
|
import {
|
|
32
34
|
useCheckEngineStatus,
|
|
@@ -150,15 +152,25 @@ export const WfoTasksListPage = () => {
|
|
|
150
152
|
<EuiFlexItem>
|
|
151
153
|
<EuiFlexGroup justifyContent="flexEnd">
|
|
152
154
|
{' '}
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
iconType={() => (
|
|
156
|
-
<WfoRefresh color={theme.colors.primaryText} />
|
|
157
|
-
)}
|
|
155
|
+
<WfoIsAllowedToRender
|
|
156
|
+
resource={PolicyResource.TASKS_RETRY_ALL}
|
|
158
157
|
>
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
<EuiButton
|
|
159
|
+
onClick={handleRerunAllButtonClick}
|
|
160
|
+
iconType={() => (
|
|
161
|
+
<WfoRefresh
|
|
162
|
+
color={theme.colors.primaryText}
|
|
163
|
+
/>
|
|
164
|
+
)}
|
|
165
|
+
>
|
|
166
|
+
{t('rerunAll')}
|
|
167
|
+
</EuiButton>
|
|
168
|
+
</WfoIsAllowedToRender>
|
|
169
|
+
<WfoIsAllowedToRender
|
|
170
|
+
resource={PolicyResource.TASKS_CREATE}
|
|
171
|
+
>
|
|
172
|
+
<WfoStartTaskButtonComboBox />
|
|
173
|
+
</WfoIsAllowedToRender>
|
|
162
174
|
</EuiFlexGroup>
|
|
163
175
|
</EuiFlexItem>
|
|
164
176
|
</EuiFlexGroup>
|
package/src/types/index.ts
CHANGED
package/src/utils/string.spec.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
camelToHuman,
|
|
3
|
+
removeSuffix,
|
|
4
|
+
snakeToHuman,
|
|
5
|
+
snakeToKebab,
|
|
6
|
+
upperCaseFirstChar,
|
|
7
|
+
} from './strings';
|
|
2
8
|
|
|
3
9
|
describe('upperCaseFirstChar()', () => {
|
|
4
10
|
it("Doesn't crash on an empty string but returns empty string", () => {
|
|
@@ -68,3 +74,33 @@ describe('camelToHuman()', () => {
|
|
|
68
74
|
expect(result).toEqual('A Quick Brown Fox');
|
|
69
75
|
});
|
|
70
76
|
});
|
|
77
|
+
|
|
78
|
+
describe('snakeToHuman()', () => {
|
|
79
|
+
it('Returns an empty string when input is an empty string', () => {
|
|
80
|
+
const result = snakeToHuman('');
|
|
81
|
+
expect(result).toEqual('');
|
|
82
|
+
});
|
|
83
|
+
it('Returns two words from a single underscore snake case word', () => {
|
|
84
|
+
const result = snakeToHuman('hello_world');
|
|
85
|
+
expect(result).toEqual('hello world');
|
|
86
|
+
});
|
|
87
|
+
it('Returns multiple words from a multiple underscore snake case word', () => {
|
|
88
|
+
const result = snakeToHuman('quick_brown_fox');
|
|
89
|
+
expect(result).toEqual('quick brown fox');
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('snakeToKebab()', () => {
|
|
94
|
+
it('Returns an empty string when input is an empty string', () => {
|
|
95
|
+
const result = snakeToKebab('');
|
|
96
|
+
expect(result).toEqual('');
|
|
97
|
+
});
|
|
98
|
+
it('Returns kebab case word from a single underscore snake case word', () => {
|
|
99
|
+
const result = snakeToKebab('hello_world');
|
|
100
|
+
expect(result).toEqual('hello-world');
|
|
101
|
+
});
|
|
102
|
+
it('Returns kebab case word from a multiple underscore snake case word', () => {
|
|
103
|
+
const result = snakeToKebab('quick_brown_fox');
|
|
104
|
+
expect(result).toEqual('quick-brown-fox');
|
|
105
|
+
});
|
|
106
|
+
});
|
package/src/utils/strings.ts
CHANGED
|
@@ -13,3 +13,12 @@ export const camelToHuman = (value: string): string => {
|
|
|
13
13
|
const result = value.replace(/([A-Z])/g, ' $1').trimStart();
|
|
14
14
|
return result.charAt(0).toUpperCase() + result.slice(1);
|
|
15
15
|
};
|
|
16
|
+
|
|
17
|
+
export const snakeToHuman = (value: string): string => {
|
|
18
|
+
const result = value.replace(/_/g, ' ');
|
|
19
|
+
return result.charAt(0) + result.slice(1);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const snakeToKebab = (value: string): string => {
|
|
23
|
+
return value.replace(/_/g, '-');
|
|
24
|
+
};
|