@orchestrator-ui/orchestrator-ui-components 7.6.0 → 7.7.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/.turbo/turbo-build.log +7 -7
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +8 -8
- package/CHANGELOG.md +19 -0
- package/dist/index.d.ts +63 -45
- package/dist/index.js +767 -639
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/WfoBadges/WfoEngineStatusBadge/WfoEngineStatusBadge.tsx +3 -1
- package/src/components/WfoBadges/WfoWebsocketStatusBadge/WfoWebsocketStatusBadge.tsx +9 -3
- package/src/components/WfoSubscription/WfoSubscriptionGeneralSections/WfoSubscriptionDetailSection.tsx +34 -3
- package/src/components/WfoTitleWithWebsocketBadge/WfoTitleWithWebsocketBadge.tsx +3 -2
- package/src/components/WfoWorkflowSteps/WfoStep/WfoStep.tsx +68 -38
- package/src/components/WfoWorkflowSteps/WfoStep/useStepDetailOverride.ts +9 -0
- package/src/components/WfoWorkflowSteps/WfoWorkflowStepList/WfoStepListHeader.tsx +0 -1
- package/src/configuration/version.ts +1 -1
- package/src/messages/en-GB.json +2 -0
- package/src/messages/nl-NL.json +2 -0
- package/src/pages/metadata/WfoScheduleTaskFormPage.tsx +153 -35
- package/src/rtk/endpoints/forms.ts +1 -1
- package/src/rtk/endpoints/metadata/scheduledTasks.ts +9 -17
- package/src/rtk/endpoints/streamMessages.ts +10 -23
- package/src/rtk/slices/orchestratorComponentOverride.ts +5 -1
- package/src/utils/compareVersions.ts +1 -1
package/package.json
CHANGED
|
@@ -13,10 +13,12 @@ export const WfoEngineStatusBadge = () => {
|
|
|
13
13
|
const { data } = useGetEngineStatusQuery();
|
|
14
14
|
const { engineStatus } = data || {};
|
|
15
15
|
const { useWebSockets } = useGetOrchestratorConfig();
|
|
16
|
+
|
|
17
|
+
const { orchestratorWebsocketUrl } = useGetOrchestratorConfig();
|
|
16
18
|
const [websocketTrigger, { isUninitialized }] = useLazyStreamMessagesQuery();
|
|
17
19
|
|
|
18
20
|
if (useWebSockets && isUninitialized) {
|
|
19
|
-
websocketTrigger();
|
|
21
|
+
websocketTrigger(orchestratorWebsocketUrl);
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
const engineStatusText: string = engineStatus ? `Engine is ${engineStatus}` : 'Engine status is unavailable';
|
|
@@ -6,7 +6,7 @@ import { useTranslations } from 'next-intl';
|
|
|
6
6
|
import { EuiToolTip } from '@elastic/eui';
|
|
7
7
|
|
|
8
8
|
import { WfoHeaderBadge } from '@/components';
|
|
9
|
-
import { useWithOrchestratorTheme } from '@/hooks';
|
|
9
|
+
import { useGetOrchestratorConfig, useWithOrchestratorTheme } from '@/hooks';
|
|
10
10
|
import { useOrchestratorTheme } from '@/hooks/useOrchestratorTheme';
|
|
11
11
|
import { WfoBoltFill, WfoBoltSlashFill } from '@/icons';
|
|
12
12
|
import { orchestratorApi } from '@/rtk';
|
|
@@ -15,16 +15,22 @@ import { useStreamMessagesQuery } from '@/rtk/endpoints/streamMessages';
|
|
|
15
15
|
import { getStyles } from './styles';
|
|
16
16
|
|
|
17
17
|
interface WfoWebsocketStatusBadgeProps {
|
|
18
|
+
wsUrl?: string;
|
|
18
19
|
hideWhenConnected?: boolean;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
export const WfoWebsocketStatusBadge: FC<WfoWebsocketStatusBadgeProps> = ({
|
|
22
|
+
export const WfoWebsocketStatusBadge: FC<WfoWebsocketStatusBadgeProps> = ({
|
|
23
|
+
hideWhenConnected = false,
|
|
24
|
+
wsUrl = undefined,
|
|
25
|
+
}) => {
|
|
22
26
|
const dispatch = useDispatch();
|
|
23
27
|
const { connectedStyle, disconnectedStyle } = useWithOrchestratorTheme(getStyles);
|
|
24
28
|
|
|
25
29
|
const t = useTranslations('main');
|
|
26
30
|
const { theme } = useOrchestratorTheme();
|
|
27
|
-
|
|
31
|
+
|
|
32
|
+
const { orchestratorWebsocketUrl } = useGetOrchestratorConfig();
|
|
33
|
+
const { data: websocketConnected } = useStreamMessagesQuery(wsUrl || orchestratorWebsocketUrl);
|
|
28
34
|
|
|
29
35
|
const showBadge = !(websocketConnected && hideWhenConnected);
|
|
30
36
|
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
import { useTranslations } from 'next-intl';
|
|
4
|
+
import Link from 'next/link';
|
|
4
5
|
|
|
5
6
|
import {
|
|
7
|
+
PATH_TASKS,
|
|
6
8
|
SubscriptionKeyValueBlock,
|
|
7
9
|
WfoCustomerDescriptionsField,
|
|
8
10
|
WfoInSyncField,
|
|
9
11
|
WfoSubscriptionDetailNoteEdit,
|
|
10
12
|
WfoSubscriptionStatusBadge,
|
|
11
13
|
} from '@/components';
|
|
12
|
-
import { SubscriptionDetail } from '@/types';
|
|
14
|
+
import { SubscriptionDetail, WorkflowTarget } from '@/types';
|
|
13
15
|
import { formatDate } from '@/utils';
|
|
14
16
|
|
|
15
17
|
interface WfoSubscriptionDetailSectionProps {
|
|
@@ -19,8 +21,17 @@ interface WfoSubscriptionDetailSectionProps {
|
|
|
19
21
|
export const WfoSubscriptionDetailSection = ({ subscriptionDetail }: WfoSubscriptionDetailSectionProps) => {
|
|
20
22
|
const t = useTranslations('subscriptions.detail');
|
|
21
23
|
|
|
22
|
-
const {
|
|
23
|
-
|
|
24
|
+
const {
|
|
25
|
+
subscriptionId,
|
|
26
|
+
product,
|
|
27
|
+
description,
|
|
28
|
+
startDate,
|
|
29
|
+
endDate,
|
|
30
|
+
status,
|
|
31
|
+
customer,
|
|
32
|
+
customerDescriptions,
|
|
33
|
+
processes,
|
|
34
|
+
} = subscriptionDetail;
|
|
24
35
|
|
|
25
36
|
const subscriptionDetailBlockData = [
|
|
26
37
|
{
|
|
@@ -52,6 +63,26 @@ export const WfoSubscriptionDetailSection = ({ subscriptionDetail }: WfoSubscrip
|
|
|
52
63
|
key: t('insync'),
|
|
53
64
|
value: <WfoInSyncField subscriptionDetail={subscriptionDetail} />,
|
|
54
65
|
},
|
|
66
|
+
{
|
|
67
|
+
key: t('lastRunValidation'),
|
|
68
|
+
value: (() => {
|
|
69
|
+
const lastValidate = processes?.page
|
|
70
|
+
?.filter((process) => process.workflowTarget.toLowerCase() === WorkflowTarget.VALIDATE.toLowerCase())
|
|
71
|
+
.slice(-1)[0];
|
|
72
|
+
|
|
73
|
+
if (!lastValidate) {
|
|
74
|
+
return t('noValidateWorkflows');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const processUrl = `${PATH_TASKS}/${lastValidate.processId}`;
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<Link href={processUrl}>
|
|
81
|
+
{lastValidate.lastStatus} ({formatDate(lastValidate.startedAt)})
|
|
82
|
+
</Link>
|
|
83
|
+
);
|
|
84
|
+
})(),
|
|
85
|
+
},
|
|
55
86
|
{
|
|
56
87
|
key: t('customer'),
|
|
57
88
|
value: subscriptionDetail && subscriptionDetail.customer ? `${customer?.fullname}` : '-',
|
|
@@ -7,15 +7,16 @@ import { useGetOrchestratorConfig } from '@/hooks';
|
|
|
7
7
|
|
|
8
8
|
interface WfoTitleWithWebsocketBadgeProps {
|
|
9
9
|
title: string;
|
|
10
|
+
wsUrl?: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
export const WfoTitleWithWebsocketBadge = ({ title }: WfoTitleWithWebsocketBadgeProps) => {
|
|
13
|
+
export const WfoTitleWithWebsocketBadge = ({ title, wsUrl = undefined }: WfoTitleWithWebsocketBadgeProps) => {
|
|
13
14
|
const { useWebSockets } = useGetOrchestratorConfig();
|
|
14
15
|
|
|
15
16
|
const pageTitle =
|
|
16
17
|
useWebSockets ?
|
|
17
18
|
<>
|
|
18
|
-
{title} <WfoWebsocketStatusBadge />
|
|
19
|
+
{title} <WfoWebsocketStatusBadge wsUrl={wsUrl} />
|
|
19
20
|
</>
|
|
20
21
|
: title;
|
|
21
22
|
|
|
@@ -17,6 +17,7 @@ import { getStepContent } from '../stepListUtils';
|
|
|
17
17
|
import { getWorkflowStepsStyles } from '../styles';
|
|
18
18
|
import { CodeView, WfoCodeViewSelector } from './WfoCodeViewSelector';
|
|
19
19
|
import { WfoStepForm } from './WfoStepForm';
|
|
20
|
+
import { useStepDetailOverride } from './useStepDetailOverride';
|
|
20
21
|
|
|
21
22
|
export interface WfoStepProps {
|
|
22
23
|
stepListItem: StepListItem;
|
|
@@ -58,6 +59,7 @@ export const WfoStep = React.forwardRef(
|
|
|
58
59
|
stepRowStyle,
|
|
59
60
|
getStepToggleExpandStyle,
|
|
60
61
|
} = useWithOrchestratorTheme(getWorkflowStepsStyles);
|
|
62
|
+
const { overrideStepDetail } = useStepDetailOverride();
|
|
61
63
|
const t = useTranslations('processes.steps');
|
|
62
64
|
const hasHtmlMail = Object.prototype.hasOwnProperty.call(step?.stateDelta || {}, 'confirmation_mail');
|
|
63
65
|
|
|
@@ -98,62 +100,90 @@ export const WfoStep = React.forwardRef(
|
|
|
98
100
|
);
|
|
99
101
|
};
|
|
100
102
|
|
|
101
|
-
const
|
|
102
|
-
(newCodeView:
|
|
103
|
-
setCodeView(newCodeView
|
|
103
|
+
const handleCodeViewChange = useCallback(
|
|
104
|
+
(newCodeView: CodeView) => {
|
|
105
|
+
setCodeView(newCodeView);
|
|
104
106
|
},
|
|
105
107
|
[setCodeView],
|
|
106
108
|
);
|
|
107
109
|
|
|
110
|
+
const shouldExpand: boolean = isExpanded && hasStepContent;
|
|
111
|
+
|
|
108
112
|
return (
|
|
109
113
|
<div ref={ref}>
|
|
110
114
|
<EuiPanel>
|
|
111
115
|
<EuiFlexGroup css={getStepHeaderStyle(hasStepContent)} onClick={() => hasStepContent && onToggleStepDetail()}>
|
|
112
116
|
<WfoStepStatusIcon stepStatus={step.status} isStartStep={isStartStep} />
|
|
113
117
|
|
|
114
|
-
<
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
<EuiFlexGroup direction="column" gutterSize="none">
|
|
119
|
+
<EuiFlexItem css={{ flexDirection: 'row' }}>
|
|
120
|
+
<EuiFlexItem grow={0}>
|
|
121
|
+
<EuiText css={stepListContentBoldTextStyle}>{step.name}</EuiText>
|
|
122
|
+
<EuiText>
|
|
123
|
+
{step.status} {step.completed && `- ${formatDate(step.completed)}`}
|
|
124
|
+
</EuiText>
|
|
125
|
+
</EuiFlexItem>
|
|
120
126
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
<EuiFlexGroup css={stepRowStyle}>
|
|
128
|
+
{step.completed && !userInputForm && !hasHtmlMail && (
|
|
129
|
+
<>
|
|
130
|
+
{isExpanded && (
|
|
131
|
+
<WfoCodeViewSelector codeView={codeView} handleCodeViewChange={handleCodeViewChange} />
|
|
132
|
+
)}
|
|
133
|
+
<EuiFlexItem grow={0} css={stepHeaderRightStyle}>
|
|
134
|
+
<EuiText css={stepDurationStyle}>{t('duration')}</EuiText>
|
|
135
|
+
<EuiText size="m">{calculateTimeDifference(startedAt, completedAt)}</EuiText>
|
|
136
|
+
</EuiFlexItem>
|
|
137
|
+
<EuiFlexItem grow={0} css={getStepToggleExpandStyle(hasStepContent)}>
|
|
138
|
+
{(isExpanded && <WfoChevronUp color={theme.colors.textParagraph} />) || (
|
|
139
|
+
<WfoChevronDown color={theme.colors.textParagraph} />
|
|
140
|
+
)}
|
|
141
|
+
</EuiFlexItem>
|
|
142
|
+
</>
|
|
143
|
+
)}
|
|
144
|
+
</EuiFlexGroup>
|
|
145
|
+
</EuiFlexItem>
|
|
146
|
+
<EuiFlexItem>
|
|
147
|
+
{overrideStepDetail?.stepHeader && <overrideStepDetail.stepHeader step={step} />}
|
|
148
|
+
</EuiFlexItem>
|
|
136
149
|
</EuiFlexGroup>
|
|
137
150
|
</EuiFlexGroup>
|
|
138
|
-
{
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
151
|
+
{shouldExpand && !hasHtmlMail && (
|
|
152
|
+
<EuiFlexGroup direction="column" gutterSize="none">
|
|
153
|
+
<EuiFlexItem>
|
|
154
|
+
{codeView === CodeView.TABLE ?
|
|
155
|
+
<WfoTableCodeBlock stepState={stepContent} />
|
|
156
|
+
: codeView === CodeView.RAW ?
|
|
157
|
+
<WfoJsonCodeBlock data={stepContent} />
|
|
158
|
+
: <WfoMonacoCodeBlock data={stepContent} />}
|
|
159
|
+
</EuiFlexItem>
|
|
160
|
+
<EuiFlexItem grow={1}>
|
|
161
|
+
{!(step.status === StepStatus.SUSPEND && userInputForm) && overrideStepDetail?.stepBody && (
|
|
162
|
+
<overrideStepDetail.stepBody step={step} />
|
|
163
|
+
)}
|
|
164
|
+
</EuiFlexItem>
|
|
165
|
+
</EuiFlexGroup>
|
|
166
|
+
)}
|
|
167
|
+
{step.status === StepStatus.SUSPEND && userInputForm && (
|
|
168
|
+
<EuiFlexGroup direction="column" gutterSize="none">
|
|
169
|
+
<EuiFlexItem grow={1}>
|
|
170
|
+
<WfoStepForm
|
|
171
|
+
userInputForm={userInputForm}
|
|
172
|
+
isTask={isTask}
|
|
173
|
+
processId={processId ?? ''}
|
|
174
|
+
userPermissions={userPermissions}
|
|
175
|
+
/>
|
|
176
|
+
</EuiFlexItem>
|
|
177
|
+
<EuiFlexItem grow={1}>
|
|
178
|
+
{overrideStepDetail?.stepBody && <overrideStepDetail.stepBody step={step} />}
|
|
179
|
+
</EuiFlexItem>
|
|
180
|
+
</EuiFlexGroup>
|
|
181
|
+
)}
|
|
144
182
|
{isExpanded && hasHtmlMail && (
|
|
145
183
|
<div css={stepEmailContainerStyle}>
|
|
146
184
|
{displayMailConfirmation(step.stateDelta.confirmation_mail as EmailState)}
|
|
147
185
|
</div>
|
|
148
186
|
)}
|
|
149
|
-
{step.status === StepStatus.SUSPEND && userInputForm && (
|
|
150
|
-
<WfoStepForm
|
|
151
|
-
userInputForm={userInputForm}
|
|
152
|
-
isTask={isTask}
|
|
153
|
-
processId={processId ?? ''}
|
|
154
|
-
userPermissions={userPermissions}
|
|
155
|
-
/>
|
|
156
|
-
)}
|
|
157
187
|
</EuiPanel>
|
|
158
188
|
</div>
|
|
159
189
|
);
|
|
@@ -69,7 +69,6 @@ export const WfoStepListHeader: FC<WfoStepListHeaderProps> = ({
|
|
|
69
69
|
<EuiText css={stepListContentBoldTextStyle}>{t(isTask ? 'taskSteps' : 'workflowSteps')}</EuiText>
|
|
70
70
|
{!showRaw && <WfoTextAnchor text={allDetailToggleText} onClick={onToggleAllDetailsIsOpen} />}
|
|
71
71
|
</EuiFlexGroup>
|
|
72
|
-
|
|
73
72
|
{/* Right side: view options */}
|
|
74
73
|
<EuiFlexGroup justifyContent="flexEnd" direction="row" css={stepListOptionsContainerStyle} gutterSize="s">
|
|
75
74
|
{showTracebackButton && (
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const ORCHESTRATOR_UI_LIBRARY_VERSION = '7.
|
|
1
|
+
export const ORCHESTRATOR_UI_LIBRARY_VERSION = '7.7.1';
|
package/src/messages/en-GB.json
CHANGED
|
@@ -390,6 +390,8 @@
|
|
|
390
390
|
"subscriptionId": "Subscription ID",
|
|
391
391
|
"description": "Description",
|
|
392
392
|
"startDate": "Start date",
|
|
393
|
+
"lastRunValidation": "Most recent validate",
|
|
394
|
+
"noValidateWorkflows": "No validate workflows have been run recently",
|
|
393
395
|
"insync": "In sync",
|
|
394
396
|
"customer": "Customer",
|
|
395
397
|
"customerUuid": "Customer UUID",
|
package/src/messages/nl-NL.json
CHANGED
|
@@ -389,6 +389,8 @@
|
|
|
389
389
|
"subscriptionId": "Subscription ID",
|
|
390
390
|
"description": "Beschrijving",
|
|
391
391
|
"startDate": "Startdatum",
|
|
392
|
+
"lastRunValidation": "Meest recente validate",
|
|
393
|
+
"noValidateWorkflows": "Er zijn recentelijk geen validate workflows uitgevoerd",
|
|
392
394
|
"insync": "In sync",
|
|
393
395
|
"customer": "Klant",
|
|
394
396
|
"customerUuid": "Klant UUID",
|
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useCallback, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import _ from 'lodash';
|
|
4
4
|
import { useTranslations } from 'next-intl';
|
|
5
5
|
import { useRouter } from 'next/router';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from '
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
PydanticFormDefinitionResponse,
|
|
15
|
-
PydanticFormSuccessResponse,
|
|
16
|
-
RawJsonProperties,
|
|
17
|
-
} from 'pydantic-forms';
|
|
18
|
-
|
|
19
|
-
import { Footer, PATH_METADATA_SCHEDULED_TASKS, WfoContentHeader, WfoLoading } from '@/components';
|
|
6
|
+
import { PydanticForm } from 'pydantic-forms';
|
|
7
|
+
import type { PydanticFormApiProvider } from 'pydantic-forms';
|
|
8
|
+
import { PydanticFormApiResponseType, PydanticFormFieldFormat, PydanticFormFieldType } from 'pydantic-forms';
|
|
9
|
+
import type { PydanticFormDefinitionResponse, PydanticFormSuccessResponse, RawJsonProperties } from 'pydantic-forms';
|
|
10
|
+
|
|
11
|
+
import { PATH_METADATA_SCHEDULED_TASKS } from '@/components';
|
|
12
|
+
import { WfoContentHeader, WfoLoading } from '@/components';
|
|
13
|
+
import { Footer } from '@/components/WfoPydanticForm/Footer';
|
|
20
14
|
import { NUMBER_OF_ITEMS_REPRESENTING_ALL_ITEMS } from '@/configuration';
|
|
21
|
-
import {
|
|
22
|
-
import
|
|
23
|
-
import {
|
|
24
|
-
|
|
15
|
+
import { useShowToastMessage } from '@/hooks';
|
|
16
|
+
import { useGetPydanticFormsConfig } from '@/hooks/useGetPydanticFormsConfig';
|
|
17
|
+
import {
|
|
18
|
+
HttpStatus,
|
|
19
|
+
ScheduledTaskPostPayload,
|
|
20
|
+
isFetchBaseQueryError,
|
|
21
|
+
isRecord,
|
|
22
|
+
useCreateScheduledTaskMutation,
|
|
23
|
+
} from '@/rtk';
|
|
24
|
+
import type { CronKwargs } from '@/rtk';
|
|
25
|
+
import { useGetTasksQuery } from '@/rtk';
|
|
26
|
+
import { useStartFormMutation } from '@/rtk/endpoints/forms';
|
|
27
|
+
import { useGetVersionsQuery } from '@/rtk/endpoints/versions';
|
|
28
|
+
import { ToastTypes } from '@/types';
|
|
29
|
+
import { Intervals, TaskDefinition, TaskType } from '@/types';
|
|
30
|
+
import { compareVersions } from '@/utils/compareVersions';
|
|
25
31
|
|
|
26
32
|
type CreateScheduleFormStep1 = {
|
|
27
33
|
workflowId: TaskDefinition['workflowId'];
|
|
@@ -50,7 +56,8 @@ type CreateScheduleFormStep2 =
|
|
|
50
56
|
|
|
51
57
|
type CreateScheduleFormInput = [CreateScheduleFormStep1, CreateScheduleFormStep2];
|
|
52
58
|
|
|
53
|
-
|
|
59
|
+
// TODO: remove after 5.0.0 releases and rename WfoScheduleTaskFormPageBackend to WfoScheduleTaskFormPage
|
|
60
|
+
export const WfoScheduleTaskFormPageHardCoded = () => {
|
|
54
61
|
const t = useTranslations('metadata.scheduleTaskForm');
|
|
55
62
|
const { showToastMessage } = useShowToastMessage();
|
|
56
63
|
|
|
@@ -256,13 +263,15 @@ export const WfoScheduleTaskFormPage = () => {
|
|
|
256
263
|
|
|
257
264
|
if (userInputStep1.taskType === TaskType.DATE) {
|
|
258
265
|
return {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
266
|
+
scheduled_type: 'create',
|
|
267
|
+
workflow_id: task.workflowId,
|
|
268
|
+
workflow_name: task.name,
|
|
269
|
+
name: task.description,
|
|
270
|
+
trigger: userInputStep1.taskType,
|
|
271
|
+
trigger_kwargs: {
|
|
264
272
|
run_date: startDate,
|
|
265
273
|
},
|
|
274
|
+
user_inputs: [],
|
|
266
275
|
};
|
|
267
276
|
} else if (userInputStep1.taskType === TaskType.INTERVAL) {
|
|
268
277
|
const step2Input = userInputStep2 as CreateScheduleFormStep2Interval;
|
|
@@ -273,24 +282,28 @@ export const WfoScheduleTaskFormPage = () => {
|
|
|
273
282
|
}
|
|
274
283
|
|
|
275
284
|
return {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
285
|
+
scheduled_type: 'create',
|
|
286
|
+
workflow_id: task.workflowId,
|
|
287
|
+
workflow_name: task.name,
|
|
288
|
+
name: task.description,
|
|
289
|
+
trigger: userInputStep1.taskType,
|
|
290
|
+
trigger_kwargs: {
|
|
281
291
|
start_date: startDate,
|
|
282
292
|
...intervalArg,
|
|
283
293
|
},
|
|
294
|
+
user_inputs: [],
|
|
284
295
|
};
|
|
285
296
|
} else if (userInputStep1.taskType === TaskType.CRON) {
|
|
286
297
|
const step2Input = userInputStep2 as CreateScheduleFormStep2Cron;
|
|
287
298
|
// minute hour day month weekday
|
|
288
299
|
return {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
300
|
+
scheduled_type: 'create',
|
|
301
|
+
workflow_id: task.workflowId,
|
|
302
|
+
workflow_name: task.name,
|
|
303
|
+
name: task.description,
|
|
304
|
+
trigger: userInputStep1.taskType,
|
|
305
|
+
trigger_kwargs: getCronKwargs(step2Input.cron, startDate),
|
|
306
|
+
user_inputs: [],
|
|
294
307
|
};
|
|
295
308
|
}
|
|
296
309
|
throw new Error('Unknown or missing task type');
|
|
@@ -420,3 +433,108 @@ export const WfoScheduleTaskFormPage = () => {
|
|
|
420
433
|
</>
|
|
421
434
|
);
|
|
422
435
|
};
|
|
436
|
+
|
|
437
|
+
const START_SCHEDULE_PAYLOAD = {};
|
|
438
|
+
|
|
439
|
+
export const WfoScheduleTaskFormPageBackend = () => {
|
|
440
|
+
const { showToastMessage } = useShowToastMessage();
|
|
441
|
+
|
|
442
|
+
const generateFormId = useMemo(() => {
|
|
443
|
+
return `${JSON.stringify(START_SCHEDULE_PAYLOAD)}`;
|
|
444
|
+
}, []);
|
|
445
|
+
|
|
446
|
+
const [startForm] = useStartFormMutation();
|
|
447
|
+
const [createScheduledTask, mutationState] = useCreateScheduledTaskMutation();
|
|
448
|
+
const router = useRouter();
|
|
449
|
+
|
|
450
|
+
const onSuccess = useCallback(
|
|
451
|
+
async (_fieldValues: object, req: object) => {
|
|
452
|
+
const request = req as {
|
|
453
|
+
status: HttpStatus;
|
|
454
|
+
data: ScheduledTaskPostPayload;
|
|
455
|
+
};
|
|
456
|
+
if (request?.data?.workflow_id) {
|
|
457
|
+
const resp = await createScheduledTask(request.data);
|
|
458
|
+
if (!resp?.error) {
|
|
459
|
+
router.replace(PATH_METADATA_SCHEDULED_TASKS);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
[router, createScheduledTask],
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
const getPydanticFormProvider = useCallback(() => {
|
|
467
|
+
const pydanticFormProvider: PydanticFormApiProvider = async ({ requestBody = [], formKey }) => {
|
|
468
|
+
const userInputs =
|
|
469
|
+
_.isEmpty(START_SCHEDULE_PAYLOAD) ? [...requestBody] : [{ ...START_SCHEDULE_PAYLOAD }, ...requestBody];
|
|
470
|
+
|
|
471
|
+
const response = startForm({
|
|
472
|
+
formKey,
|
|
473
|
+
userInputs,
|
|
474
|
+
});
|
|
475
|
+
return response
|
|
476
|
+
.then(({ error, data }) => {
|
|
477
|
+
return new Promise<Record<string, unknown>>((resolve) => {
|
|
478
|
+
if (isFetchBaseQueryError(error) && isRecord(error.data)) {
|
|
479
|
+
if (error.status === HttpStatus.FormNotComplete) {
|
|
480
|
+
resolve(error.data);
|
|
481
|
+
} else if (error.status === HttpStatus.BadRequest) {
|
|
482
|
+
resolve({
|
|
483
|
+
...error.data,
|
|
484
|
+
status: error.status,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
} else if (data) {
|
|
488
|
+
resolve({
|
|
489
|
+
data,
|
|
490
|
+
status: HttpStatus.Created,
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
resolve({});
|
|
495
|
+
});
|
|
496
|
+
})
|
|
497
|
+
.catch((error) => {
|
|
498
|
+
return new Promise<Record<string, object>>((resolve, reject) => {
|
|
499
|
+
if (error.status === HttpStatus.FormNotComplete) {
|
|
500
|
+
resolve(error.data);
|
|
501
|
+
}
|
|
502
|
+
reject(error);
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
return pydanticFormProvider;
|
|
508
|
+
}, [startForm]);
|
|
509
|
+
|
|
510
|
+
const config = useGetPydanticFormsConfig(getPydanticFormProvider, (props) => <Footer {...props} />);
|
|
511
|
+
|
|
512
|
+
const handleCancel = useCallback(() => {
|
|
513
|
+
const pfBasePath = PATH_METADATA_SCHEDULED_TASKS;
|
|
514
|
+
router.replace(pfBasePath);
|
|
515
|
+
}, [router]);
|
|
516
|
+
|
|
517
|
+
if (mutationState.isError) {
|
|
518
|
+
showToastMessage(ToastTypes.ERROR, '', 'Error while saving scheduled task');
|
|
519
|
+
console.error('Error saving scheduled task', mutationState);
|
|
520
|
+
return undefined;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
return (
|
|
524
|
+
<PydanticForm
|
|
525
|
+
formKey="configure_schedule"
|
|
526
|
+
formId={generateFormId}
|
|
527
|
+
onSuccess={onSuccess}
|
|
528
|
+
onCancel={handleCancel}
|
|
529
|
+
config={config}
|
|
530
|
+
/>
|
|
531
|
+
);
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
export const WfoScheduleTaskFormPage = () => {
|
|
535
|
+
const { data } = useGetVersionsQuery();
|
|
536
|
+
const coreVersion = data?.version.applicationVersions[0].split(' ')[1] ?? '';
|
|
537
|
+
|
|
538
|
+
const isCompatible = compareVersions(coreVersion, '5.0.0a7') !== -1;
|
|
539
|
+
return isCompatible ? <WfoScheduleTaskFormPageBackend /> : <WfoScheduleTaskFormPageHardCoded />;
|
|
540
|
+
};
|
|
@@ -2,7 +2,7 @@ import { BaseQueryTypes, orchestratorApi } from '@/rtk';
|
|
|
2
2
|
|
|
3
3
|
const PROCESS_ENDPOINT = 'processes';
|
|
4
4
|
const RESUME_ENDPOINT = 'resume';
|
|
5
|
-
const FORMS_ENDPOINT = '
|
|
5
|
+
const FORMS_ENDPOINT = 'forms/'; // It is still being used by example-wfo-ui
|
|
6
6
|
|
|
7
7
|
const formsApi = orchestratorApi.injectEndpoints({
|
|
8
8
|
endpoints: (build) => ({
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
GraphqlQueryVariables,
|
|
8
8
|
ScheduledTaskDefinition,
|
|
9
9
|
ScheduledTasksDefinitionsResult,
|
|
10
|
-
TaskType,
|
|
11
10
|
} from '@/types';
|
|
12
11
|
|
|
13
12
|
export const scheduledTasks = `
|
|
@@ -41,7 +40,7 @@ export type ScheduledTasksResponse = {
|
|
|
41
40
|
schedules: ScheduledTaskDefinition[];
|
|
42
41
|
} & BaseGraphQlResult;
|
|
43
42
|
|
|
44
|
-
/*
|
|
43
|
+
/*
|
|
45
44
|
https://apscheduler.readthedocs.io/en/3.x/modules/triggers/interval.html#module-apscheduler.triggers.interval
|
|
46
45
|
Possible parameters:
|
|
47
46
|
weeks (int) – number of weeks to wait
|
|
@@ -105,11 +104,13 @@ export type CronKwargs = {
|
|
|
105
104
|
type Kwargs = DateKwargs | InterValKwargs | CronKwargs;
|
|
106
105
|
|
|
107
106
|
export type ScheduledTaskPostPayload = {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
107
|
+
workflow_id: string;
|
|
108
|
+
workflow_name: string;
|
|
109
|
+
name: string;
|
|
110
|
+
trigger: string;
|
|
111
|
+
trigger_kwargs: Kwargs;
|
|
112
|
+
scheduled_type: string;
|
|
113
|
+
user_inputs: object[];
|
|
113
114
|
};
|
|
114
115
|
|
|
115
116
|
const scheduledTasksApi = orchestratorApi.injectEndpoints({
|
|
@@ -149,22 +150,13 @@ const scheduledTasksApi = orchestratorApi.injectEndpoints({
|
|
|
149
150
|
}),
|
|
150
151
|
createScheduledTask: builder.mutation<unknown, ScheduledTaskPostPayload>({
|
|
151
152
|
query: (payload) => {
|
|
152
|
-
const scheduleTaskPayload = {
|
|
153
|
-
scheduled_type: 'create',
|
|
154
|
-
name: payload.workflowDescription,
|
|
155
|
-
workflow_name: payload.workflowName,
|
|
156
|
-
workflow_id: payload.workflowId,
|
|
157
|
-
trigger: payload.type,
|
|
158
|
-
trigger_kwargs: payload.kwargs,
|
|
159
|
-
};
|
|
160
|
-
|
|
161
153
|
return {
|
|
162
154
|
url: METADATA_SCHEDULES_ENDPOINT,
|
|
163
155
|
method: 'POST',
|
|
164
156
|
headers: {
|
|
165
157
|
'Content-Type': 'application/json',
|
|
166
158
|
},
|
|
167
|
-
body:
|
|
159
|
+
body: payload,
|
|
168
160
|
};
|
|
169
161
|
},
|
|
170
162
|
extraOptions: {
|