@orchestrator-ui/orchestrator-ui-components 8.8.2 → 8.9.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 +7 -7
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +16 -15
- package/CHANGELOG.md +11 -0
- package/dist/index.d.ts +43 -21
- package/dist/index.js +2151 -2048
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/WfoBadges/WfoProductStatusBadge/WfoProductStatusBadge.tsx +2 -5
- package/src/components/WfoStartButton/WfoStartButtonComboBox.tsx +6 -11
- package/src/components/WfoStartButton/WfoStartWorkflowComboBox.tsx +1 -1
- package/src/components/WfoSubscription/WfoSubscriptionActions/WfoSubscriptionActions.tsx +6 -16
- package/src/components/WfoSubscription/utils/utils.spec.ts +57 -0
- package/src/components/WfoSubscription/utils/utils.ts +15 -0
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoSearchHelpModal.tsx +59 -0
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoStructuredSearchTable.tsx +3 -17
- package/src/configuration/version.ts +1 -1
- package/src/messages/en-GB.json +19 -0
- package/src/messages/nl-NL.json +20 -1
- package/src/rtk/endpoints/metadata/productBlocks.ts +9 -1
- package/src/rtk/endpoints/metadata/products.ts +5 -2
- package/src/rtk/endpoints/startOptions.ts +4 -3
- package/src/types/types.ts +3 -3
- package/src/utils/getProductLifecycleStatus.spec.ts +26 -0
- package/src/utils/getProductLifecycleStatus.ts +13 -0
- package/src/utils/index.ts +1 -0
package/package.json
CHANGED
|
@@ -8,16 +8,13 @@ export type WfoProductStatusBadgeProps = {
|
|
|
8
8
|
status: ProductLifecycleStatus;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
const normalizedStatus = (status: ProductLifecycleStatus): string => status.toLowerCase().replace(/_/g, ' ');
|
|
12
|
-
|
|
13
11
|
export const WfoProductStatusBadge: FC<WfoProductStatusBadgeProps> = ({ status }) => {
|
|
14
12
|
const { theme, toSecondaryColor } = useOrchestratorTheme();
|
|
15
13
|
|
|
16
|
-
const productLifeCycleStatus = normalizedStatus(status);
|
|
17
14
|
const getBadgeColorFromStatus = () => {
|
|
18
15
|
const { primary, borderBaseSubdued, textPrimary, textParagraph, success, textSuccess } = theme.colors;
|
|
19
16
|
|
|
20
|
-
switch (
|
|
17
|
+
switch (status) {
|
|
21
18
|
case ProductLifecycleStatus.ACTIVE:
|
|
22
19
|
return {
|
|
23
20
|
badgeColor: toSecondaryColor(success),
|
|
@@ -41,7 +38,7 @@ export const WfoProductStatusBadge: FC<WfoProductStatusBadgeProps> = ({ status }
|
|
|
41
38
|
|
|
42
39
|
return (
|
|
43
40
|
<WfoBadge textColor={textColor} color={badgeColor}>
|
|
44
|
-
{
|
|
41
|
+
{status}
|
|
45
42
|
</WfoBadge>
|
|
46
43
|
);
|
|
47
44
|
};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import { capitalize } from 'lodash';
|
|
4
|
-
|
|
5
3
|
import { EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiPopover, EuiSelectable, EuiSpacer } from '@elastic/eui';
|
|
6
4
|
|
|
7
5
|
import { useGetOrchestratorConfig, useOrchestratorTheme, useWithOrchestratorTheme } from '@/hooks';
|
|
8
6
|
import { WfoChevronDown, WfoPlusCircleFill } from '@/icons';
|
|
9
7
|
import { ProductLifecycleStatus, StartComboBoxOption } from '@/types';
|
|
8
|
+
import { getProductLifecycleStatus } from '@/utils';
|
|
10
9
|
|
|
11
10
|
import { getStyles } from './styles';
|
|
12
11
|
|
|
@@ -16,12 +15,8 @@ export type WfoStartButtonComboBoxProps = {
|
|
|
16
15
|
onOptionChange: (selectedOption: StartComboBoxOption) => void;
|
|
17
16
|
isProcess: boolean;
|
|
18
17
|
className?: string;
|
|
19
|
-
selectedProductStatus?: ProductLifecycleStatus
|
|
20
|
-
setSelectedProductStatus?: (status: ProductLifecycleStatus
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const formatProductStatusLabel = (productStatus: string) => {
|
|
24
|
-
return capitalize(productStatus.replace(/_/g, ' '));
|
|
18
|
+
selectedProductStatus?: ProductLifecycleStatus;
|
|
19
|
+
setSelectedProductStatus?: (status: ProductLifecycleStatus) => void;
|
|
25
20
|
};
|
|
26
21
|
|
|
27
22
|
export const WfoStartButtonComboBox = ({
|
|
@@ -67,7 +62,7 @@ export const WfoStartButtonComboBox = ({
|
|
|
67
62
|
iconType={() => <WfoChevronDown height={18} width={18} color="currentColor" />}
|
|
68
63
|
onClick={() => setFilterPopoverOpen((v) => !v)}
|
|
69
64
|
>
|
|
70
|
-
<b>{
|
|
65
|
+
<b>{selectedProductStatus ?? ProductLifecycleStatus.ACTIVE}</b>
|
|
71
66
|
</EuiButtonEmpty>
|
|
72
67
|
}
|
|
73
68
|
isOpen={isFilterPopoverOpen}
|
|
@@ -80,11 +75,11 @@ export const WfoStartButtonComboBox = ({
|
|
|
80
75
|
key={productStatus}
|
|
81
76
|
size="xs"
|
|
82
77
|
onClick={() => {
|
|
83
|
-
setSelectedProductStatus(productStatus
|
|
78
|
+
setSelectedProductStatus(getProductLifecycleStatus(productStatus));
|
|
84
79
|
setFilterPopoverOpen(false);
|
|
85
80
|
}}
|
|
86
81
|
>
|
|
87
|
-
{
|
|
82
|
+
{productStatus ?? ProductLifecycleStatus.ACTIVE}
|
|
88
83
|
</EuiButtonEmpty>
|
|
89
84
|
</div>
|
|
90
85
|
))}
|
|
@@ -14,7 +14,7 @@ export const WfoStartWorkflowButtonComboBox = () => {
|
|
|
14
14
|
const router = useRouter();
|
|
15
15
|
const t = useTranslations('common');
|
|
16
16
|
const { isEngineRunningNow } = useCheckEngineStatus();
|
|
17
|
-
const [selectedProductStatus, setSelectedProductStatus] = React.useState<ProductLifecycleStatus
|
|
17
|
+
const [selectedProductStatus, setSelectedProductStatus] = React.useState<ProductLifecycleStatus>(
|
|
18
18
|
ProductLifecycleStatus.ACTIVE,
|
|
19
19
|
);
|
|
20
20
|
|
|
@@ -12,13 +12,14 @@ import {
|
|
|
12
12
|
WfoInSyncField,
|
|
13
13
|
WfoPopover,
|
|
14
14
|
} from '@/components';
|
|
15
|
+
import { getActionItemsByTarget } from '@/components/WfoSubscription';
|
|
15
16
|
import { WfoSubscriptionActionsMenuItem } from '@/components/WfoSubscription/WfoSubscriptionActions/WfoSubscriptionActionsMenuItem';
|
|
16
17
|
import { useActiveProcess } from '@/components/WfoSubscription/WfoSubscriptionActions/utils';
|
|
17
18
|
import { PolicyResource } from '@/configuration/policy-resources';
|
|
18
19
|
import { useOrchestratorTheme, usePolicy } from '@/hooks';
|
|
19
20
|
import { WfoDotsHorizontal } from '@/icons/WfoDotsHorizontal';
|
|
20
21
|
import { useGetSubscriptionActionsQuery, useGetSubscriptionDetailQuery, useStartProcessMutation } from '@/rtk';
|
|
21
|
-
import {
|
|
22
|
+
import { WorkflowTarget } from '@/types';
|
|
22
23
|
|
|
23
24
|
type MenuBlockProps = {
|
|
24
25
|
title: string;
|
|
@@ -129,21 +130,10 @@ export const WfoSubscriptionActions: FC<WfoSubscriptionActionsProps> = ({
|
|
|
129
130
|
}
|
|
130
131
|
};
|
|
131
132
|
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const actionsByTarget = subscriptionActions as unknown as
|
|
137
|
-
| Record<string, SubscriptionAction[] | undefined>
|
|
138
|
-
| undefined;
|
|
139
|
-
|
|
140
|
-
return actionsByTarget?.[workflowTarget] ?? actionsByTarget?.[workflowTarget.toLowerCase()] ?? [];
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const validateActionItems = getActionItems(WorkflowTarget.VALIDATE);
|
|
144
|
-
const reconcileActionItems = getActionItems(WorkflowTarget.RECONCILE);
|
|
145
|
-
const modifyActionItems = getActionItems(WorkflowTarget.MODIFY);
|
|
146
|
-
const terminateActionItems = getActionItems(WorkflowTarget.TERMINATE);
|
|
133
|
+
const validateActionItems = getActionItemsByTarget(WorkflowTarget.VALIDATE, subscriptionActions);
|
|
134
|
+
const reconcileActionItems = getActionItemsByTarget(WorkflowTarget.RECONCILE, subscriptionActions);
|
|
135
|
+
const modifyActionItems = getActionItemsByTarget(WorkflowTarget.MODIFY, subscriptionActions);
|
|
136
|
+
const terminateActionItems = getActionItemsByTarget(WorkflowTarget.TERMINATE, subscriptionActions);
|
|
147
137
|
|
|
148
138
|
const compactItems = (
|
|
149
139
|
<>
|
|
@@ -5,11 +5,13 @@ import {
|
|
|
5
5
|
ProcessStatus,
|
|
6
6
|
ProductBlockInstance,
|
|
7
7
|
SubscriptionAction,
|
|
8
|
+
SubscriptionActions,
|
|
8
9
|
SubscriptionDetailProcess,
|
|
9
10
|
WorkflowTarget,
|
|
10
11
|
} from '../../../types';
|
|
11
12
|
import {
|
|
12
13
|
flattenSubscriptionActionProps,
|
|
14
|
+
getActionItemsByTarget,
|
|
13
15
|
getFieldFromProductBlockInstanceValues,
|
|
14
16
|
getLastUncompletedProcess,
|
|
15
17
|
getLatestTaskDate,
|
|
@@ -470,6 +472,61 @@ describe('mapProductBlockInstancesToEuiSelectableOptions', () => {
|
|
|
470
472
|
});
|
|
471
473
|
});
|
|
472
474
|
|
|
475
|
+
describe('getActionItemsByTarget', () => {
|
|
476
|
+
const modifyAction: SubscriptionAction = {
|
|
477
|
+
name: 'modify_note',
|
|
478
|
+
description: 'Modify note',
|
|
479
|
+
};
|
|
480
|
+
const terminateAction: SubscriptionAction = {
|
|
481
|
+
name: 'terminate',
|
|
482
|
+
description: 'Terminate subscription',
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
const subscriptionActions: SubscriptionActions = {
|
|
486
|
+
[WorkflowTarget.MODIFY]: [modifyAction],
|
|
487
|
+
[WorkflowTarget.TERMINATE]: [terminateAction],
|
|
488
|
+
[WorkflowTarget.SYSTEM]: [],
|
|
489
|
+
[WorkflowTarget.VALIDATE]: [],
|
|
490
|
+
[WorkflowTarget.RECONCILE]: [],
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
it('returns actions for the given target with uppercase keys', () => {
|
|
494
|
+
expect(getActionItemsByTarget(WorkflowTarget.MODIFY, subscriptionActions)).toEqual([modifyAction]);
|
|
495
|
+
expect(getActionItemsByTarget(WorkflowTarget.TERMINATE, subscriptionActions)).toEqual([terminateAction]);
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
it('falls back to lowercase keys returned by core versions 5.2 and lower', () => {
|
|
499
|
+
const lowercaseActions = {
|
|
500
|
+
modify: [modifyAction],
|
|
501
|
+
terminate: [terminateAction],
|
|
502
|
+
} as unknown as SubscriptionActions;
|
|
503
|
+
|
|
504
|
+
expect(getActionItemsByTarget(WorkflowTarget.MODIFY, lowercaseActions)).toEqual([modifyAction]);
|
|
505
|
+
expect(getActionItemsByTarget(WorkflowTarget.TERMINATE, lowercaseActions)).toEqual([terminateAction]);
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
it('prefers the uppercase key when both casings are present', () => {
|
|
509
|
+
const mixedActions = {
|
|
510
|
+
[WorkflowTarget.MODIFY]: [modifyAction],
|
|
511
|
+
modify: [terminateAction],
|
|
512
|
+
} as unknown as SubscriptionActions;
|
|
513
|
+
|
|
514
|
+
expect(getActionItemsByTarget(WorkflowTarget.MODIFY, mixedActions)).toEqual([modifyAction]);
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
it('returns an empty array when the target is missing in either casing', () => {
|
|
518
|
+
const actionsWithoutValidate = {
|
|
519
|
+
[WorkflowTarget.MODIFY]: [modifyAction],
|
|
520
|
+
} as unknown as SubscriptionActions;
|
|
521
|
+
|
|
522
|
+
expect(getActionItemsByTarget(WorkflowTarget.VALIDATE, actionsWithoutValidate)).toEqual([]);
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
it('returns an empty array when subscriptionActions is undefined', () => {
|
|
526
|
+
expect(getActionItemsByTarget(WorkflowTarget.MODIFY, undefined)).toEqual([]);
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
|
|
473
530
|
describe('parseErrorDetail', () => {
|
|
474
531
|
it('parses a single UUID inside brackets', () => {
|
|
475
532
|
const input = "Subscription 123 has still failed processes with id's: ['11111111-1111-1111-1111-111111111111']";
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
ProductBlockInstance,
|
|
10
10
|
SortOrder,
|
|
11
11
|
SubscriptionAction,
|
|
12
|
+
SubscriptionActions,
|
|
12
13
|
SubscriptionDetailProcess,
|
|
13
14
|
SubscriptionRelation,
|
|
14
15
|
WorkflowTarget,
|
|
@@ -189,3 +190,17 @@ export const mapProductBlockInstancesToEuiSelectableOptions = (
|
|
|
189
190
|
},
|
|
190
191
|
}));
|
|
191
192
|
};
|
|
193
|
+
|
|
194
|
+
export const getActionItemsByTarget = (
|
|
195
|
+
workflowTarget: WorkflowTarget,
|
|
196
|
+
subscriptionActions?: SubscriptionActions,
|
|
197
|
+
): SubscriptionAction[] => {
|
|
198
|
+
// https://github.com/workfloworchestrator/orchestrator-core/issues/1820 will align the WorkflowTarget enum and make it
|
|
199
|
+
// uppercase. We support both for now. The lowercase keys are deliberately not part of the
|
|
200
|
+
// SubscriptionActions type, so the fallback is a runtime-only check behind a cast.
|
|
201
|
+
const actionsByTarget = subscriptionActions as unknown as
|
|
202
|
+
| Record<string, SubscriptionAction[] | undefined>
|
|
203
|
+
| undefined;
|
|
204
|
+
|
|
205
|
+
return actionsByTarget?.[workflowTarget] ?? actionsByTarget?.[workflowTarget.toLowerCase()] ?? [];
|
|
206
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { useTranslations } from 'next-intl';
|
|
4
|
+
|
|
5
|
+
import { EuiText } from '@elastic/eui';
|
|
6
|
+
|
|
7
|
+
import { WfoInformationModal } from '@/components';
|
|
8
|
+
|
|
9
|
+
export type WfoSearchHelpModalProps = {
|
|
10
|
+
onClose: () => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const WfoSearchHelpModal = ({ onClose }: WfoSearchHelpModalProps) => {
|
|
14
|
+
const t = useTranslations('search.page');
|
|
15
|
+
const tCommon = useTranslations('common');
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<WfoInformationModal title={t('help.title')} onClose={onClose}>
|
|
19
|
+
<EuiText size="s">
|
|
20
|
+
<p>
|
|
21
|
+
<strong>{t('help.searchFieldTitle')}</strong> - {t('help.searchFieldDescription')}
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<h4>{t('help.filterTitle')}</h4>
|
|
25
|
+
<p>{t('help.filterIntro')}</p>
|
|
26
|
+
<ul>
|
|
27
|
+
<li>
|
|
28
|
+
<strong>{t('addRule')}</strong> - {t('help.addRuleDescription')}
|
|
29
|
+
</li>
|
|
30
|
+
<li>
|
|
31
|
+
<strong>{t('addGroup')}</strong> - {t('help.addGroupDescription')}
|
|
32
|
+
</li>
|
|
33
|
+
</ul>
|
|
34
|
+
|
|
35
|
+
<h4>{t('help.quickFilterTitle')}</h4>
|
|
36
|
+
<p>{t('help.quickFilterDescription')}</p>
|
|
37
|
+
|
|
38
|
+
<h4>{t('help.matchingRowTitle')}</h4>
|
|
39
|
+
<p>{t('help.matchingRowDescription')}</p>
|
|
40
|
+
|
|
41
|
+
<h4>{t('help.tableSettingsTitle')}</h4>
|
|
42
|
+
<ul>
|
|
43
|
+
<li>
|
|
44
|
+
<strong>{tCommon('showMatchDetails')}</strong> - {t('help.showMatchDetailsDescription')}
|
|
45
|
+
</li>
|
|
46
|
+
<li>
|
|
47
|
+
<strong>{tCommon('retrieval')}</strong> - {t('help.retrievalDescription')}
|
|
48
|
+
</li>
|
|
49
|
+
<li>
|
|
50
|
+
<strong>{tCommon('export')}</strong> - {t('help.exportDescription')}
|
|
51
|
+
</li>
|
|
52
|
+
<li>
|
|
53
|
+
<strong>{t('help.advancedNestedSearchLabel')}</strong> - {t('help.advancedNestedSearchDescription')}
|
|
54
|
+
</li>
|
|
55
|
+
</ul>
|
|
56
|
+
</EuiText>
|
|
57
|
+
</WfoInformationModal>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
@@ -3,16 +3,7 @@ import type { RuleGroupType } from 'react-querybuilder';
|
|
|
3
3
|
|
|
4
4
|
import { useTranslations } from 'next-intl';
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
EuiButton,
|
|
8
|
-
EuiFlexGroup,
|
|
9
|
-
EuiFlexItem,
|
|
10
|
-
EuiFormRow,
|
|
11
|
-
EuiSelect,
|
|
12
|
-
EuiSpacer,
|
|
13
|
-
EuiSwitch,
|
|
14
|
-
EuiText,
|
|
15
|
-
} from '@elastic/eui';
|
|
6
|
+
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSelect, EuiSpacer, EuiSwitch } from '@elastic/eui';
|
|
16
7
|
|
|
17
8
|
import {
|
|
18
9
|
DEFAULT_PAGE_SIZE,
|
|
@@ -45,6 +36,7 @@ import { getDefaultTableConfig } from '@/utils';
|
|
|
45
36
|
import { ColumnType, WfoTable, WfoTableProps } from '../WfoTable';
|
|
46
37
|
import { WfoFilterBuilder } from './WfoFilterBuilder';
|
|
47
38
|
import { WfoSearchFieldWithActions } from './WfoSearchFieldWithActions';
|
|
39
|
+
import { WfoSearchHelpModal } from './WfoSearchHelpModal';
|
|
48
40
|
import { getWfoStructuredSearchTableStyles } from './styles';
|
|
49
41
|
import { buildColumnFilter } from './utils';
|
|
50
42
|
|
|
@@ -380,13 +372,7 @@ export const WfoStructuredSearchTable = <T extends object>({
|
|
|
380
372
|
/>
|
|
381
373
|
)}
|
|
382
374
|
|
|
383
|
-
{showInformationModal && (
|
|
384
|
-
<WfoInformationModal title={t('searchModalTitle')} onClose={() => setShowInformationModal(false)}>
|
|
385
|
-
<EuiText>
|
|
386
|
-
<p>TODO: Info about searching</p>
|
|
387
|
-
</EuiText>
|
|
388
|
-
</WfoInformationModal>
|
|
389
|
-
)}
|
|
375
|
+
{showInformationModal && <WfoSearchHelpModal onClose={() => setShowInformationModal(false)} />}
|
|
390
376
|
|
|
391
377
|
{rowDetailData && (
|
|
392
378
|
<WfoInformationModal title={'TODO: Information modal title'} onClose={() => setRowDetailModalData(undefined)}>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const ORCHESTRATOR_UI_LIBRARY_VERSION = '8.
|
|
1
|
+
export const ORCHESTRATOR_UI_LIBRARY_VERSION = '8.9.0';
|
package/src/messages/en-GB.json
CHANGED
|
@@ -339,6 +339,25 @@
|
|
|
339
339
|
"fromDate": "From date",
|
|
340
340
|
"fromNumber": "From",
|
|
341
341
|
"groupLabel": "Group",
|
|
342
|
+
"help": {
|
|
343
|
+
"addGroupDescription": "adds a new group with two rules inside. A group has its own AND/OR choice.",
|
|
344
|
+
"addRuleDescription": "adds a new rule to the current group. A rule consists of a field, an operator and a value.",
|
|
345
|
+
"advancedNestedSearchDescription": "when enabled, the field dropdown in the filter also offers the full nested paths. When disabled, only the paths that match the table columns are shown.",
|
|
346
|
+
"advancedNestedSearchLabel": "Advanced nested search",
|
|
347
|
+
"exportDescription": "downloads a CSV file with only the rows that match the current filter.",
|
|
348
|
+
"filterIntro": "Use 'Create a filter' to build a structured filter out of rules.",
|
|
349
|
+
"filterTitle": "Filter rules and grouping",
|
|
350
|
+
"matchingRowDescription": "Hover over a row to reveal an extra row with information about the matched item: the fields that matched the search text and the confidence of the match.",
|
|
351
|
+
"matchingRowTitle": "Matching row",
|
|
352
|
+
"quickFilterDescription": "You can also click a column header and enter a value there - this adds a new rule for that column to the filter.",
|
|
353
|
+
"quickFilterTitle": "Quick filter from a column header",
|
|
354
|
+
"retrievalDescription": "choose how results are retrieved: Auto, Fuzzy, Semantic or Hybrid.",
|
|
355
|
+
"searchFieldDescription": "Searches across all available fields - no filter applied.",
|
|
356
|
+
"searchFieldTitle": "Default Search box behavior",
|
|
357
|
+
"showMatchDetailsDescription": "always show the matching rows instead of only on hover.",
|
|
358
|
+
"tableSettingsTitle": "Table settings (gear button)",
|
|
359
|
+
"title": "How search works"
|
|
360
|
+
},
|
|
342
361
|
"hideFilters": "Hide filters",
|
|
343
362
|
"loadingSearchResults": "Loading search results...",
|
|
344
363
|
"maxNestingDepth": "Maximum nesting depth reached",
|
package/src/messages/nl-NL.json
CHANGED
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"metadataProductblocks": "Product blocks",
|
|
65
65
|
"metadataProducts": "Products",
|
|
66
66
|
"metadataResourceTypes": "Resource types",
|
|
67
|
-
"metadataScheduledTasks": "
|
|
67
|
+
"metadataScheduledTasks": "Geplande taken",
|
|
68
68
|
"metadataTasks": "Taken",
|
|
69
69
|
"metadataWorkflows": "Workflows",
|
|
70
70
|
"minimumOrchestratorCoreVersion": "Minimale versie van orchestrator-core",
|
|
@@ -339,6 +339,25 @@
|
|
|
339
339
|
"fromDate": "Vanaf datum",
|
|
340
340
|
"fromNumber": "Van",
|
|
341
341
|
"groupLabel": "Groep",
|
|
342
|
+
"help": {
|
|
343
|
+
"addGroupDescription": "voegt een nieuwe groep toe met daarin twee regels. Een groep heeft een eigen AND/OR-keuze.",
|
|
344
|
+
"addRuleDescription": "voegt een nieuwe regel toe aan de huidige groep. Een regel bestaat uit een veld, een operator en een waarde.",
|
|
345
|
+
"advancedNestedSearchDescription": "indien ingeschakeld biedt de veldkeuzelijst in het filter ook de volledige geneste paden. Indien uitgeschakeld worden alleen de paden getoond die overeenkomen met de tabelkolommen.",
|
|
346
|
+
"advancedNestedSearchLabel": "Geavanceerd genest zoeken",
|
|
347
|
+
"exportDescription": "downloadt een CSV-bestand met alleen de rijen die voldoen aan het huidige filter.",
|
|
348
|
+
"filterIntro": "Bouw met 'Filter' een gestructureerd filter op uit regels.",
|
|
349
|
+
"filterTitle": "Filterregels en groepen",
|
|
350
|
+
"matchingRowDescription": "Beweeg de muis over een rij om een extra rij te tonen met informatie over het gevonden item: de velden die overeenkomen met de zoektekst en de betrouwbaarheid van de match.",
|
|
351
|
+
"matchingRowTitle": "Matching rij",
|
|
352
|
+
"quickFilterDescription": "Je kunt ook op een tabel header klikken en daar een waarde invoeren - dit voegt een nieuwe regel voor die kolom aan het filter toe.",
|
|
353
|
+
"quickFilterTitle": "Snel filteren via een tabel header",
|
|
354
|
+
"retrievalDescription": "kies hoe resultaten worden opgehaald: Auto, Fuzzy, Semantic of Hybride.",
|
|
355
|
+
"searchFieldDescription": "Doorzoekt alle beschikbare velden - geen filter toegepast.",
|
|
356
|
+
"searchFieldTitle": "Standaardgedrag van het zoekveld",
|
|
357
|
+
"showMatchDetailsDescription": "toon de matching rijen altijd in plaats van alleen bij hover.",
|
|
358
|
+
"tableSettingsTitle": "Tabelinstellingen (tandwielknop)",
|
|
359
|
+
"title": "Hoe zoeken werkt"
|
|
360
|
+
},
|
|
342
361
|
"hideFilters": "Verberg filters",
|
|
343
362
|
"loadingSearchResults": "Zoekresultaten laden...",
|
|
344
363
|
"maxNestingDepth": "Maximale nesting-diepte bereikt",
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
ProductBlockDefinition,
|
|
8
8
|
ProductBlockDefinitionsResult,
|
|
9
9
|
} from '@/types';
|
|
10
|
+
import { getProductLifecycleStatus } from '@/utils';
|
|
10
11
|
|
|
11
12
|
export const productBlocksQuery = `
|
|
12
13
|
query MetadataProductBlocks(
|
|
@@ -69,7 +70,14 @@ const productBlocksApi = orchestratorApi.injectEndpoints({
|
|
|
69
70
|
variables,
|
|
70
71
|
}),
|
|
71
72
|
transformResponse: (response: ProductBlockDefinitionsResult): ProductBlocksResponse => {
|
|
72
|
-
const productBlocks = response.productBlocks.page || []
|
|
73
|
+
const productBlocks = (response.productBlocks.page || []).map((productBlock) => ({
|
|
74
|
+
...productBlock,
|
|
75
|
+
status: getProductLifecycleStatus(productBlock.status),
|
|
76
|
+
dependsOn: productBlock.dependsOn.map((dependsOnBlock) => ({
|
|
77
|
+
...dependsOnBlock,
|
|
78
|
+
status: getProductLifecycleStatus(dependsOnBlock.status),
|
|
79
|
+
})),
|
|
80
|
+
}));
|
|
73
81
|
const pageInfo = response.productBlocks.pageInfo || {};
|
|
74
82
|
|
|
75
83
|
return {
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
ProductDefinition,
|
|
10
10
|
ProductDefinitionsResult,
|
|
11
11
|
} from '@/types';
|
|
12
|
-
import { getCacheTag } from '@/utils';
|
|
12
|
+
import { getCacheTag, getProductLifecycleStatus } from '@/utils';
|
|
13
13
|
|
|
14
14
|
export const products = `
|
|
15
15
|
query MetadataProducts(
|
|
@@ -61,7 +61,10 @@ const productsApi = orchestratorApi.injectEndpoints({
|
|
|
61
61
|
variables,
|
|
62
62
|
}),
|
|
63
63
|
transformResponse: (response: ProductDefinitionsResult): ProductsResponse => {
|
|
64
|
-
const products = response.products.page || []
|
|
64
|
+
const products = (response.products.page || []).map((product) => ({
|
|
65
|
+
...product,
|
|
66
|
+
status: getProductLifecycleStatus(product.status),
|
|
67
|
+
}));
|
|
65
68
|
const pageInfo = response.products.pageInfo || {};
|
|
66
69
|
|
|
67
70
|
return {
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
WorkflowDefinition,
|
|
6
6
|
WorkflowTarget,
|
|
7
7
|
} from '@/types';
|
|
8
|
+
import { getProductLifecycleStatus } from '@/utils';
|
|
8
9
|
|
|
9
10
|
import { orchestratorApi } from '../api';
|
|
10
11
|
|
|
@@ -68,18 +69,18 @@ type TaskOptionsResult = StartOptionsResult<TaskOption>;
|
|
|
68
69
|
|
|
69
70
|
const startButtonOptionsApi = orchestratorApi.injectEndpoints({
|
|
70
71
|
endpoints: (build) => ({
|
|
71
|
-
getWorkflowOptions: build.query<StartOptionsResponse<WorkflowOption>, ProductLifecycleStatus
|
|
72
|
+
getWorkflowOptions: build.query<StartOptionsResponse<WorkflowOption>, ProductLifecycleStatus>({
|
|
72
73
|
query: () => ({
|
|
73
74
|
document: workflowOptionsQuery,
|
|
74
75
|
}),
|
|
75
76
|
transformResponse: (response: WorkflowOptionsResult | undefined, _, productStatus) => {
|
|
76
|
-
const statusToMatch =
|
|
77
|
+
const statusToMatch = productStatus ?? ProductLifecycleStatus.ACTIVE;
|
|
77
78
|
const startOptions: WorkflowOption[] = [];
|
|
78
79
|
const workflows = response?.workflows?.page || [];
|
|
79
80
|
workflows.forEach((workflow) => {
|
|
80
81
|
const workflowName = workflow.name;
|
|
81
82
|
workflow.products
|
|
82
|
-
.filter((product) => product.status
|
|
83
|
+
.filter((product) => getProductLifecycleStatus(product.status) === statusToMatch)
|
|
83
84
|
.forEach((product) => {
|
|
84
85
|
startOptions.push({
|
|
85
86
|
workflowName,
|
package/src/types/types.ts
CHANGED
|
@@ -83,9 +83,9 @@ export interface ProductBlockDefinition {
|
|
|
83
83
|
|
|
84
84
|
export enum ProductLifecycleStatus {
|
|
85
85
|
ACTIVE = 'active',
|
|
86
|
-
PRE_PRODUCTION = '
|
|
87
|
-
PHASE_OUT = '
|
|
88
|
-
END_OF_LIFE = '
|
|
86
|
+
PRE_PRODUCTION = 'pre production',
|
|
87
|
+
PHASE_OUT = 'phase out',
|
|
88
|
+
END_OF_LIFE = 'end of life',
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
export enum BadgeType {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ProductLifecycleStatus } from '@/types';
|
|
2
|
+
|
|
3
|
+
import { getProductLifecycleStatus } from './getProductLifecycleStatus';
|
|
4
|
+
|
|
5
|
+
describe('getProductLifecycleStatus()', () => {
|
|
6
|
+
it('converts an uppercase GraphQL key to its ProductLifecycleStatus value', () => {
|
|
7
|
+
expect(getProductLifecycleStatus('ACTIVE')).toBe(ProductLifecycleStatus.ACTIVE);
|
|
8
|
+
expect(getProductLifecycleStatus('PRE_PRODUCTION')).toBe(ProductLifecycleStatus.PRE_PRODUCTION);
|
|
9
|
+
expect(getProductLifecycleStatus('PHASE_OUT')).toBe(ProductLifecycleStatus.PHASE_OUT);
|
|
10
|
+
expect(getProductLifecycleStatus('END_OF_LIFE')).toBe(ProductLifecycleStatus.END_OF_LIFE);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('converts a lowercase key to its ProductLifecycleStatus value', () => {
|
|
14
|
+
expect(getProductLifecycleStatus('pre_production')).toBe(ProductLifecycleStatus.PRE_PRODUCTION);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('converts a mixed case key to its ProductLifecycleStatus value', () => {
|
|
18
|
+
expect(getProductLifecycleStatus('Phase_Out')).toBe(ProductLifecycleStatus.PHASE_OUT);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('returns undefined for a status that does not match any ProductLifecycleStatus key', () => {
|
|
22
|
+
expect(getProductLifecycleStatus('not_a_status')).toBeUndefined();
|
|
23
|
+
expect(getProductLifecycleStatus('')).toBeUndefined();
|
|
24
|
+
expect(getProductLifecycleStatus('active_pending')).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ProductLifecycleStatus } from '@/types';
|
|
2
|
+
|
|
3
|
+
const productStatusAsString = Object.values(ProductLifecycleStatus) as string[];
|
|
4
|
+
|
|
5
|
+
export const getProductLifecycleStatus = (rawStatus: string): ProductLifecycleStatus => {
|
|
6
|
+
const trimmed = rawStatus.trim();
|
|
7
|
+
if (productStatusAsString.includes(trimmed)) {
|
|
8
|
+
return trimmed as ProductLifecycleStatus;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const normalizedKey = trimmed.replace(/\s+/g, '_').toUpperCase();
|
|
12
|
+
return ProductLifecycleStatus[normalizedKey as keyof typeof ProductLifecycleStatus];
|
|
13
|
+
};
|
package/src/utils/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from './getDefaultTableConfig';
|
|
|
6
6
|
export * from './getEnvironmentVariables';
|
|
7
7
|
export * from './getObjectKeys';
|
|
8
8
|
export * from './getQueryUrl';
|
|
9
|
+
export * from './getProductLifecycleStatus';
|
|
9
10
|
export * from './getProductNamesFromProcess';
|
|
10
11
|
export * from './getQueryVariablesForExport';
|
|
11
12
|
export * from './getStatusBadgeColor';
|