@orchestrator-ui/orchestrator-ui-components 1.24.0 → 1.26.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 +4 -4
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +7 -7
- package/CHANGELOG.md +24 -0
- package/dist/index.d.ts +16 -13
- package/dist/index.js +1600 -1520
- package/package.json +1 -1
- package/src/components/WfoBadges/WfoWebsocketStatusBadge/WfoWebsocketStatusBadge.tsx +1 -1
- package/src/components/WfoForms/formFields/utils.spec.ts +24 -6
- package/src/components/WfoKeyValueTable/styles.ts +0 -1
- package/src/components/WfoSettingsModal/WfoSettingsModal.tsx +28 -22
- package/src/components/WfoSubscription/WfoInUseByRelations.tsx +1 -1
- package/src/components/WfoSubscription/WfoRelatedSubscriptions.tsx +2 -1
- package/src/components/WfoSubscription/WfoSubscriptionDetailTree.tsx +4 -24
- package/src/components/WfoSubscription/WfoSubscriptionProductBlock/WfoProductBlockKeyValueRow.tsx +2 -3
- package/src/components/WfoSubscription/WfoSubscriptionProductBlock/WfoSubscriptionProductBlock.tsx +93 -36
- package/src/components/WfoSubscription/WfoSubscriptionProductBlock/styles.ts +16 -10
- package/src/components/WfoTable/WfoTableSettingsModal/WfoTableSettingsModal.tsx +5 -2
- package/src/components/WfoTable/WfoTableWithFilter/WfoTableWithFilter.tsx +4 -4
- package/src/components/WfoTree/treeUtils.spec.ts +20 -4
- package/src/components/WfoWorkflowSteps/WfoStep/WfoStepForm.tsx +20 -6
- package/src/messages/en-GB.json +5 -1
- package/src/messages/nl-NL.json +5 -1
- package/src/pages/processes/WfoProcessDetailPage.tsx +23 -70
- package/src/pages/processes/WfoStartProcessPage.tsx +30 -3
- package/src/rtk/api.ts +2 -2
- package/src/rtk/endpoints/processDetail.ts +15 -4
- package/src/rtk/endpoints/processList.ts +1 -1
- package/src/rtk/endpoints/streamMessages.ts +25 -10
- package/src/rtk/endpoints/subscriptionDetail.ts +4 -1
- package/src/types/types.ts +1 -1
- package/src/utils/date.ts +3 -1
|
@@ -5,7 +5,6 @@ describe('getWfoTreeNodeDepth', () => {
|
|
|
5
5
|
const field: FieldValue = { field: 'test', value: 'test' };
|
|
6
6
|
const sampleTree: TreeBlock = {
|
|
7
7
|
id: 1,
|
|
8
|
-
ownerSubscriptionId: 'subscription-1',
|
|
9
8
|
subscriptionInstanceId: 'subscription-1',
|
|
10
9
|
parent: null,
|
|
11
10
|
icon: 'folder',
|
|
@@ -14,10 +13,13 @@ describe('getWfoTreeNodeDepth', () => {
|
|
|
14
13
|
productBlockInstanceValues: [field],
|
|
15
14
|
inUseByRelations: [],
|
|
16
15
|
isOutsideCurrentSubscription: false,
|
|
16
|
+
subscription: {
|
|
17
|
+
subscriptionId: 'subscription-1',
|
|
18
|
+
description: 'Subscription 1',
|
|
19
|
+
},
|
|
17
20
|
children: [
|
|
18
21
|
{
|
|
19
22
|
id: 2,
|
|
20
|
-
ownerSubscriptionId: 'subscription-2',
|
|
21
23
|
subscriptionInstanceId: 'subscription-2',
|
|
22
24
|
parent: 1,
|
|
23
25
|
icon: 'file',
|
|
@@ -27,10 +29,13 @@ describe('getWfoTreeNodeDepth', () => {
|
|
|
27
29
|
inUseByRelations: [],
|
|
28
30
|
children: [],
|
|
29
31
|
isOutsideCurrentSubscription: false,
|
|
32
|
+
subscription: {
|
|
33
|
+
subscriptionId: 'subscription-2',
|
|
34
|
+
description: 'Subscription 2',
|
|
35
|
+
},
|
|
30
36
|
},
|
|
31
37
|
{
|
|
32
38
|
id: 3,
|
|
33
|
-
ownerSubscriptionId: 'subscription-3',
|
|
34
39
|
subscriptionInstanceId: 'subscription-3',
|
|
35
40
|
parent: 1,
|
|
36
41
|
icon: 'file',
|
|
@@ -39,10 +44,13 @@ describe('getWfoTreeNodeDepth', () => {
|
|
|
39
44
|
productBlockInstanceValues: [field],
|
|
40
45
|
inUseByRelations: [],
|
|
41
46
|
isOutsideCurrentSubscription: false,
|
|
47
|
+
subscription: {
|
|
48
|
+
subscriptionId: 'subscription-3',
|
|
49
|
+
description: 'Subscription 3',
|
|
50
|
+
},
|
|
42
51
|
children: [
|
|
43
52
|
{
|
|
44
53
|
id: 4,
|
|
45
|
-
ownerSubscriptionId: 'subscription-4',
|
|
46
54
|
subscriptionInstanceId: 'subscription-4',
|
|
47
55
|
parent: 3,
|
|
48
56
|
icon: 'file',
|
|
@@ -52,6 +60,10 @@ describe('getWfoTreeNodeDepth', () => {
|
|
|
52
60
|
inUseByRelations: [],
|
|
53
61
|
children: [],
|
|
54
62
|
isOutsideCurrentSubscription: false,
|
|
63
|
+
subscription: {
|
|
64
|
+
subscriptionId: 'subscription-4',
|
|
65
|
+
description: 'Subscription 4',
|
|
66
|
+
},
|
|
55
67
|
},
|
|
56
68
|
],
|
|
57
69
|
},
|
|
@@ -96,6 +108,10 @@ describe('getWfoTreeNodeDepth', () => {
|
|
|
96
108
|
inUseByRelations: [],
|
|
97
109
|
children: [],
|
|
98
110
|
isOutsideCurrentSubscription: false,
|
|
111
|
+
subscription: {
|
|
112
|
+
subscriptionId: 'subscription-1',
|
|
113
|
+
description: 'Subscription 1',
|
|
114
|
+
},
|
|
99
115
|
};
|
|
100
116
|
|
|
101
117
|
expect(() =>
|
|
@@ -2,8 +2,9 @@ import React, { useState } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { EuiFlexItem } from '@elastic/eui';
|
|
4
4
|
|
|
5
|
-
import { UserInputFormWizard, WfoLoading } from '@/components';
|
|
5
|
+
import { UserInputFormWizard, WfoError, WfoLoading } from '@/components';
|
|
6
6
|
import { useOrchestratorTheme } from '@/hooks';
|
|
7
|
+
import { HttpStatus } from '@/rtk';
|
|
7
8
|
import { useResumeProcessMutation } from '@/rtk/endpoints/forms';
|
|
8
9
|
import { InputForm } from '@/types/forms';
|
|
9
10
|
|
|
@@ -19,6 +20,7 @@ export const WfoStepForm = ({
|
|
|
19
20
|
processId,
|
|
20
21
|
}: WfoStepFormProps) => {
|
|
21
22
|
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
|
23
|
+
const [hasError, setHasError] = useState<boolean>(false);
|
|
22
24
|
const { theme } = useOrchestratorTheme();
|
|
23
25
|
const [resumeProcess] = useResumeProcessMutation();
|
|
24
26
|
|
|
@@ -27,16 +29,28 @@ export const WfoStepForm = ({
|
|
|
27
29
|
return Promise.reject();
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
return resumeProcess({ processId, userInputs: processInput })
|
|
31
|
-
()
|
|
32
|
+
return resumeProcess({ processId, userInputs: processInput })
|
|
33
|
+
.unwrap()
|
|
34
|
+
.then(() => {
|
|
32
35
|
setIsProcessing(true);
|
|
33
|
-
}
|
|
34
|
-
|
|
36
|
+
})
|
|
37
|
+
.catch((error) => {
|
|
38
|
+
if (error?.status !== HttpStatus.FormNotComplete) {
|
|
39
|
+
if (error?.status === HttpStatus.BadRequest) {
|
|
40
|
+
// Rethrow the error so userInputForm can catch it and display validation errors
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
console.error(error);
|
|
44
|
+
setHasError(true);
|
|
45
|
+
} else {
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
35
49
|
};
|
|
36
50
|
|
|
37
51
|
return (
|
|
38
52
|
<EuiFlexItem css={{ margin: theme.size.m }}>
|
|
39
|
-
{(isProcessing && <WfoLoading />) || (
|
|
53
|
+
{(hasError && <WfoError />) || (isProcessing && <WfoLoading />) || (
|
|
40
54
|
<UserInputFormWizard
|
|
41
55
|
stepUserInput={userInputForm}
|
|
42
56
|
stepSubmit={submitForm}
|
package/src/messages/en-GB.json
CHANGED
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
"darkMode": "Dark mode",
|
|
18
18
|
"lightMode": "Light mode",
|
|
19
19
|
"websocketConnected": "The websocket is connected",
|
|
20
|
-
"websocketDisconnected": "The websocket is disconnected, click the icon or refresh the page"
|
|
20
|
+
"websocketDisconnected": "The websocket is disconnected, click the icon or refresh the page",
|
|
21
|
+
"resetToDefault": "Reset to default",
|
|
22
|
+
"savePreferences": "Save preferences",
|
|
23
|
+
"numberOfRows": "Number of rows",
|
|
24
|
+
"tableSettings": "Table settings"
|
|
21
25
|
},
|
|
22
26
|
"common": {
|
|
23
27
|
"product": "Product",
|
package/src/messages/nl-NL.json
CHANGED
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
"darkMode": "Dark mode",
|
|
18
18
|
"lightMode": "Light mode",
|
|
19
19
|
"websocketConnected": "De websocket is actief",
|
|
20
|
-
"websocketDisconnected": "De websocket verbinding is verbroken, klik op het icoon of ververs de pagina."
|
|
20
|
+
"websocketDisconnected": "De websocket verbinding is verbroken, klik op het icoon of ververs de pagina.",
|
|
21
|
+
"resetToDefault": "Reset naar standaard",
|
|
22
|
+
"savePreferences": "Voorkeuren opslaan",
|
|
23
|
+
"numberOfRows": "Aantal rijen",
|
|
24
|
+
"tableSettings": "Tabel instellingen"
|
|
21
25
|
},
|
|
22
26
|
"common": {
|
|
23
27
|
"product": "Produkt",
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
3
|
-
import { TimelineItem, WfoError, WfoLoading } from '@/components';
|
|
4
|
-
import { useGetProcessDetailQuery } from '@/rtk/endpoints/processDetail';
|
|
1
|
+
import React, { useRef } from 'react';
|
|
5
2
|
|
|
6
3
|
import {
|
|
4
|
+
TimelineItem,
|
|
5
|
+
WfoError,
|
|
6
|
+
WfoLoading,
|
|
7
7
|
WfoStepListRef,
|
|
8
8
|
WfoWorkflowStepList,
|
|
9
|
-
} from '
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Step,
|
|
15
|
-
} from '../../types';
|
|
16
|
-
import { getProductNamesFromProcess } from '../../utils';
|
|
9
|
+
} from '@/components';
|
|
10
|
+
import { useGetProcessDetailQuery } from '@/rtk/endpoints/processDetail';
|
|
11
|
+
import { Step } from '@/types';
|
|
12
|
+
import { getProductNamesFromProcess } from '@/utils';
|
|
13
|
+
|
|
17
14
|
import { WfoProcessDetail } from './WfoProcessDetail';
|
|
18
15
|
import {
|
|
19
16
|
convertStepsToGroupedSteps,
|
|
@@ -24,69 +21,25 @@ export type GroupedStep = {
|
|
|
24
21
|
steps: Step[];
|
|
25
22
|
};
|
|
26
23
|
|
|
27
|
-
const PROCESS_DETAIL_DEFAULT_REFETCH_INTERVAL = 3000;
|
|
28
|
-
|
|
29
24
|
interface WfoProcessDetailPageProps {
|
|
30
25
|
processId: string;
|
|
31
|
-
processDetailRefetchInterval?: number;
|
|
32
26
|
}
|
|
33
27
|
|
|
34
28
|
export const WfoProcessDetailPage = ({
|
|
35
29
|
processId,
|
|
36
|
-
processDetailRefetchInterval = PROCESS_DETAIL_DEFAULT_REFETCH_INTERVAL,
|
|
37
30
|
}: WfoProcessDetailPageProps) => {
|
|
38
31
|
const stepListRef = useRef<WfoStepListRef>(null);
|
|
39
|
-
const [fetchInterval, setFetchInterval] = useState<number | undefined>();
|
|
40
|
-
const [process, setProcess] = useState<ProcessDetail | undefined>();
|
|
41
|
-
|
|
42
|
-
const { data, isLoading, isError } = useGetProcessDetailQuery(
|
|
43
|
-
{ processId },
|
|
44
|
-
{ pollingInterval: fetchInterval },
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
if (isError) {
|
|
48
|
-
if (fetchInterval) {
|
|
49
|
-
setFetchInterval(undefined);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
const process = data?.processes[0];
|
|
55
|
-
// We need to cast here because the backend might return the string in upperCase and
|
|
56
|
-
// toLowerCase() will converts the value type to string
|
|
57
|
-
const lastStatus =
|
|
58
|
-
process?.lastStatus.toLocaleLowerCase() as ProcessStatus;
|
|
59
|
-
|
|
60
|
-
const isInProgress = !(
|
|
61
|
-
lastStatus && ProcessDoneStatuses.includes(lastStatus)
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
setFetchInterval(
|
|
65
|
-
isInProgress ? processDetailRefetchInterval : undefined,
|
|
66
|
-
);
|
|
67
|
-
}, [data, processDetailRefetchInterval]);
|
|
68
|
-
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
const fetchedProcessDetails = data?.processes[0];
|
|
71
|
-
|
|
72
|
-
if (!process) {
|
|
73
|
-
setProcess(fetchedProcessDetails);
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
32
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
setProcess(fetchedProcessDetails);
|
|
82
|
-
}
|
|
83
|
-
}, [data, process]);
|
|
33
|
+
const { data, isLoading, isError } = useGetProcessDetailQuery({
|
|
34
|
+
processId,
|
|
35
|
+
});
|
|
36
|
+
const processDetail = data?.processes[0];
|
|
84
37
|
|
|
85
|
-
const steps =
|
|
38
|
+
const steps = processDetail?.steps ?? [];
|
|
86
39
|
|
|
87
|
-
const productNames = getProductNamesFromProcess(
|
|
88
|
-
const pageTitle =
|
|
89
|
-
const isTask =
|
|
40
|
+
const productNames = getProductNamesFromProcess(processDetail);
|
|
41
|
+
const pageTitle = processDetail?.workflowName || '';
|
|
42
|
+
const isTask = processDetail?.isTask ?? false;
|
|
90
43
|
const groupedSteps: GroupedStep[] = convertStepsToGroupedSteps(steps);
|
|
91
44
|
const timelineItems: TimelineItem[] =
|
|
92
45
|
mapGroupedStepsToTimelineItems(groupedSteps);
|
|
@@ -96,7 +49,7 @@ export const WfoProcessDetailPage = ({
|
|
|
96
49
|
pageTitle={pageTitle}
|
|
97
50
|
productNames={productNames}
|
|
98
51
|
buttonsAreDisabled={isLoading || isError}
|
|
99
|
-
processDetail={
|
|
52
|
+
processDetail={processDetail}
|
|
100
53
|
timelineItems={timelineItems}
|
|
101
54
|
onTimelineItemClick={(id: string) =>
|
|
102
55
|
stepListRef.current?.scrollToStep(id)
|
|
@@ -106,16 +59,16 @@ export const WfoProcessDetailPage = ({
|
|
|
106
59
|
>
|
|
107
60
|
{(isError && <WfoError />) ||
|
|
108
61
|
(isLoading && <WfoLoading />) ||
|
|
109
|
-
(
|
|
62
|
+
(processDetail !== undefined && (
|
|
110
63
|
<WfoWorkflowStepList
|
|
111
64
|
ref={stepListRef}
|
|
112
|
-
processId={
|
|
65
|
+
processId={processDetail.processId}
|
|
113
66
|
steps={groupedSteps.flatMap(
|
|
114
67
|
(groupedStep) => groupedStep.steps,
|
|
115
68
|
)}
|
|
116
|
-
traceBack={
|
|
117
|
-
userInputForm={
|
|
118
|
-
startedAt={
|
|
69
|
+
traceBack={processDetail.traceback}
|
|
70
|
+
userInputForm={processDetail.form}
|
|
71
|
+
startedAt={processDetail.startedAt}
|
|
119
72
|
isTask={isTask}
|
|
120
73
|
/>
|
|
121
74
|
)) || <h1>Invalid processId</h1>}
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
handlePromiseErrorWithCallback,
|
|
23
23
|
useGetTimeLineItemsQuery,
|
|
24
24
|
} from '@/rtk';
|
|
25
|
+
import { useGetSubscriptionDetailQuery } from '@/rtk';
|
|
25
26
|
import { useStartProcessMutation } from '@/rtk/endpoints/forms';
|
|
26
27
|
import {
|
|
27
28
|
EngineStatus,
|
|
@@ -87,6 +88,17 @@ export const WfoStartProcessPage = ({
|
|
|
87
88
|
const [form, setForm] = useState<UserInputForm>({});
|
|
88
89
|
const { productId, subscriptionId } = router.query as StartProcessPageQuery;
|
|
89
90
|
|
|
91
|
+
const {
|
|
92
|
+
data: subscriptionDetail,
|
|
93
|
+
isLoading: isLoadingSubscriptionDetail,
|
|
94
|
+
isError: isErrorSubscriptionDetail,
|
|
95
|
+
} = useGetSubscriptionDetailQuery(
|
|
96
|
+
{
|
|
97
|
+
subscriptionId: subscriptionId || '',
|
|
98
|
+
},
|
|
99
|
+
{ skip: !subscriptionId },
|
|
100
|
+
);
|
|
101
|
+
|
|
90
102
|
const [startProcess] = useStartProcessMutation();
|
|
91
103
|
|
|
92
104
|
const startProcessPayload = useMemo(
|
|
@@ -101,10 +113,13 @@ export const WfoStartProcessPage = ({
|
|
|
101
113
|
|
|
102
114
|
const {
|
|
103
115
|
data: timeLineItems = [],
|
|
104
|
-
isError,
|
|
105
|
-
isLoading,
|
|
116
|
+
isError: isErrorTimeLineItems,
|
|
117
|
+
isLoading: isLoadingTimeLineItems,
|
|
106
118
|
} = useGetTimeLineItemsQuery(processName);
|
|
107
119
|
|
|
120
|
+
const isLoading = isLoadingSubscriptionDetail || isLoadingTimeLineItems;
|
|
121
|
+
const isError = isErrorSubscriptionDetail || isErrorTimeLineItems;
|
|
122
|
+
|
|
108
123
|
if (isError) {
|
|
109
124
|
if (!hasError) {
|
|
110
125
|
setHasError(true);
|
|
@@ -126,7 +141,7 @@ export const WfoStartProcessPage = ({
|
|
|
126
141
|
const basePath = isTask
|
|
127
142
|
? PATH_TASKS
|
|
128
143
|
: PATH_WORKFLOWS;
|
|
129
|
-
router.
|
|
144
|
+
router.replace(`${basePath}/${process.id}`);
|
|
130
145
|
}
|
|
131
146
|
},
|
|
132
147
|
// Reject handler
|
|
@@ -186,6 +201,18 @@ export const WfoStartProcessPage = ({
|
|
|
186
201
|
lastStep: StepStatus.FORM,
|
|
187
202
|
workflowName: processName,
|
|
188
203
|
createdBy: '-',
|
|
204
|
+
subscriptions: subscriptionDetail && {
|
|
205
|
+
page: [
|
|
206
|
+
{
|
|
207
|
+
product: {
|
|
208
|
+
name: subscriptionDetail.subscription.product.name,
|
|
209
|
+
},
|
|
210
|
+
description: subscriptionDetail.subscription.description,
|
|
211
|
+
subscriptionId:
|
|
212
|
+
subscriptionDetail.subscription.subscriptionId,
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
},
|
|
189
216
|
};
|
|
190
217
|
|
|
191
218
|
return (
|
package/src/rtk/api.ts
CHANGED
|
@@ -16,7 +16,7 @@ export enum BaseQueryTypes {
|
|
|
16
16
|
export enum CacheTags {
|
|
17
17
|
engineStatus = 'engineStatus',
|
|
18
18
|
cacheNames = 'cacheNames',
|
|
19
|
-
|
|
19
|
+
processes = 'processes',
|
|
20
20
|
processListSummary = 'processListSummary',
|
|
21
21
|
subscription = 'subscription',
|
|
22
22
|
subscriptionList = 'subscriptionList',
|
|
@@ -108,7 +108,7 @@ export const orchestratorApi = createApi({
|
|
|
108
108
|
tagTypes: [
|
|
109
109
|
CacheTags.engineStatus,
|
|
110
110
|
CacheTags.cacheNames,
|
|
111
|
-
CacheTags.
|
|
111
|
+
CacheTags.processes,
|
|
112
112
|
CacheTags.processListSummary,
|
|
113
113
|
CacheTags.subscriptionList,
|
|
114
114
|
CacheTags.subscription,
|
|
@@ -86,6 +86,17 @@ const processDetailApi = orchestratorApi.injectEndpoints({
|
|
|
86
86
|
processes,
|
|
87
87
|
};
|
|
88
88
|
},
|
|
89
|
+
providesTags: (result, error, queryArguments) => {
|
|
90
|
+
if (!error && result) {
|
|
91
|
+
return [
|
|
92
|
+
{
|
|
93
|
+
type: CacheTags.processes,
|
|
94
|
+
id: queryArguments.processId,
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
return [];
|
|
99
|
+
},
|
|
89
100
|
}),
|
|
90
101
|
getRawProcessDetail: builder.query<
|
|
91
102
|
ProcessDetailResultRaw,
|
|
@@ -111,7 +122,7 @@ const processDetailApi = orchestratorApi.injectEndpoints({
|
|
|
111
122
|
extraOptions: {
|
|
112
123
|
baseQueryType: BaseQueryTypes.fetch,
|
|
113
124
|
},
|
|
114
|
-
invalidatesTags: [CacheTags.
|
|
125
|
+
invalidatesTags: [CacheTags.processes],
|
|
115
126
|
}),
|
|
116
127
|
retryProcess: builder.mutation<void, { processId: string }>({
|
|
117
128
|
query: ({ processId }) => ({
|
|
@@ -126,7 +137,7 @@ const processDetailApi = orchestratorApi.injectEndpoints({
|
|
|
126
137
|
extraOptions: {
|
|
127
138
|
baseQueryType: BaseQueryTypes.fetch,
|
|
128
139
|
},
|
|
129
|
-
invalidatesTags: [CacheTags.
|
|
140
|
+
invalidatesTags: [CacheTags.processes],
|
|
130
141
|
}),
|
|
131
142
|
deleteProcess: builder.mutation<void, { processId: string }>({
|
|
132
143
|
query: ({ processId }) => ({
|
|
@@ -137,7 +148,7 @@ const processDetailApi = orchestratorApi.injectEndpoints({
|
|
|
137
148
|
extraOptions: {
|
|
138
149
|
baseQueryType: BaseQueryTypes.fetch,
|
|
139
150
|
},
|
|
140
|
-
invalidatesTags: [CacheTags.
|
|
151
|
+
invalidatesTags: [CacheTags.processes],
|
|
141
152
|
}),
|
|
142
153
|
abortProcess: builder.mutation<void, { processId: string }>({
|
|
143
154
|
query: ({ processId }) => ({
|
|
@@ -148,7 +159,7 @@ const processDetailApi = orchestratorApi.injectEndpoints({
|
|
|
148
159
|
extraOptions: {
|
|
149
160
|
baseQueryType: BaseQueryTypes.fetch,
|
|
150
161
|
},
|
|
151
|
-
invalidatesTags: [CacheTags.
|
|
162
|
+
invalidatesTags: [CacheTags.processes],
|
|
152
163
|
}),
|
|
153
164
|
}),
|
|
154
165
|
});
|
|
@@ -27,6 +27,8 @@ type WebSocketMessage = {
|
|
|
27
27
|
value: string[] | string;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
type CacheInvalidationTag = CacheTags | { type: CacheTags; id: string };
|
|
31
|
+
|
|
30
32
|
enum MessageTypes {
|
|
31
33
|
invalidateCache = 'invalidateCache',
|
|
32
34
|
}
|
|
@@ -66,17 +68,25 @@ const streamMessagesApi = orchestratorApi.injectEndpoints({
|
|
|
66
68
|
updateCachedData(() => false);
|
|
67
69
|
};
|
|
68
70
|
|
|
69
|
-
const invalidateTag = (
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
const invalidateTag = (cacheTag: CacheTags, id?: string) => {
|
|
72
|
+
if (validCacheTags.includes(cacheTag)) {
|
|
73
|
+
// If we receive an object with cacheTag and id we both invalidate the cache key and the cache key with the id
|
|
74
|
+
// invalidating both the general and specific caches
|
|
75
|
+
const cacheTags: CacheInvalidationTag[] = [cacheTag];
|
|
76
|
+
|
|
77
|
+
if (id) {
|
|
78
|
+
cacheTags.push({
|
|
79
|
+
type: cacheTag,
|
|
80
|
+
id,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
const cacheInvalidationAction =
|
|
73
|
-
orchestratorApi.util.invalidateTags(
|
|
74
|
-
tagToInvalidate,
|
|
75
|
-
]);
|
|
85
|
+
orchestratorApi.util.invalidateTags(cacheTags);
|
|
76
86
|
dispatch(cacheInvalidationAction);
|
|
77
87
|
} else {
|
|
78
88
|
console.error(
|
|
79
|
-
`Trying to invalidate a cache entry with an unknown tag: ${
|
|
89
|
+
`Trying to invalidate a cache entry with an unknown tag: ${cacheTag}`,
|
|
80
90
|
);
|
|
81
91
|
}
|
|
82
92
|
};
|
|
@@ -88,9 +98,14 @@ const streamMessagesApi = orchestratorApi.injectEndpoints({
|
|
|
88
98
|
const messageValue = message.value;
|
|
89
99
|
|
|
90
100
|
if (typeof messageValue === 'string') {
|
|
91
|
-
invalidateTag(messageValue);
|
|
92
|
-
} else if (
|
|
93
|
-
|
|
101
|
+
invalidateTag(messageValue as CacheTags);
|
|
102
|
+
} else if (
|
|
103
|
+
Array.isArray(messageValue) &&
|
|
104
|
+
messageValue.length === 2
|
|
105
|
+
) {
|
|
106
|
+
const [tag, id] = messageValue;
|
|
107
|
+
const cacheTag = tag as CacheTags;
|
|
108
|
+
invalidateTag(cacheTag, id);
|
|
94
109
|
} else {
|
|
95
110
|
console.error(
|
|
96
111
|
'invalid message value type',
|
package/src/types/types.ts
CHANGED
|
@@ -39,11 +39,11 @@ export type InUseByRelation = {
|
|
|
39
39
|
|
|
40
40
|
export type ProductBlockInstance = {
|
|
41
41
|
id: number;
|
|
42
|
-
ownerSubscriptionId: string;
|
|
43
42
|
subscriptionInstanceId: string;
|
|
44
43
|
parent: Nullable<number>;
|
|
45
44
|
productBlockInstanceValues: FieldValue[];
|
|
46
45
|
inUseByRelations: InUseByRelation[];
|
|
46
|
+
subscription: Pick<Subscription, 'subscriptionId' | 'description'>;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
export interface ResourceTypeDefinition {
|
package/src/utils/date.ts
CHANGED
|
@@ -2,7 +2,9 @@ import { Locale } from '../types/types';
|
|
|
2
2
|
|
|
3
3
|
export const getCurrentBrowserLocale = () => window.navigator.language;
|
|
4
4
|
|
|
5
|
-
export const parseDate = (
|
|
5
|
+
export const parseDate = (
|
|
6
|
+
date: string | null | undefined | number,
|
|
7
|
+
): Date | null => {
|
|
6
8
|
if (date === null || date === undefined || date === '') {
|
|
7
9
|
return null;
|
|
8
10
|
}
|