@orchestrator-ui/orchestrator-ui-components 1.13.2 → 1.14.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 +10 -10
- package/CHANGELOG.md +6 -0
- package/dist/index.d.ts +1027 -1024
- package/dist/index.js +486 -507
- package/package.json +1 -1
- package/src/components/WfoForms/CreateForm.tsx +15 -13
- package/src/components/WfoForms/UserInputForm.tsx +24 -26
- package/src/components/WfoForms/UserInputFormWizard.tsx +3 -5
- package/src/components/WfoForms/index.ts +0 -1
- package/src/components/WfoWorkflowSteps/WfoStep/WfoStepForm.tsx +10 -8
- package/src/pages/processes/WfoStartProcessPage.tsx +28 -26
- package/src/rtk/api.ts +2 -1
- package/src/rtk/endpoints/forms.ts +64 -0
- package/src/types/forms.ts +16 -0
- package/src/components/WfoForms/UserInputFormWizardDeprecated.tsx +0 -125
package/package.json
CHANGED
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
16
16
|
|
|
17
|
+
import { UserInputFormWizard } from '@/components';
|
|
18
|
+
import { handlePromiseErrorWithCallback } from '@/rtk';
|
|
19
|
+
import { useStartFormMutation } from '@/rtk/endpoints/forms';
|
|
17
20
|
import { Form, FormNotCompleteResponse } from '@/types/forms';
|
|
18
21
|
|
|
19
|
-
import UserInputFormWizardDeprecated from './UserInputFormWizardDeprecated';
|
|
20
|
-
import { useAxiosApiClient } from './useAxiosApiClient';
|
|
21
|
-
|
|
22
22
|
interface IProps {
|
|
23
23
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
24
24
|
preselectedInput?: unknown;
|
|
@@ -31,20 +31,22 @@ export function CreateForm(props: IProps) {
|
|
|
31
31
|
const { preselectedInput, formKey, handleSubmit, handleCancel } = props;
|
|
32
32
|
const [form, setForm] = useState<Form>({});
|
|
33
33
|
const { stepUserInput, hasNext } = form;
|
|
34
|
-
const
|
|
34
|
+
const [startForm] = useStartFormMutation();
|
|
35
35
|
|
|
36
36
|
const submit = useCallback(
|
|
37
37
|
(userInputs: object[]) => {
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
return startForm({ formKey, userInputs })
|
|
39
|
+
.unwrap()
|
|
40
|
+
.then((form) => {
|
|
41
|
+
handleSubmit(form);
|
|
42
|
+
});
|
|
41
43
|
},
|
|
42
|
-
[formKey, handleSubmit,
|
|
44
|
+
[formKey, handleSubmit, startForm],
|
|
43
45
|
);
|
|
44
46
|
|
|
45
47
|
useEffect(() => {
|
|
46
|
-
if (formKey
|
|
47
|
-
|
|
48
|
+
if (formKey) {
|
|
49
|
+
handlePromiseErrorWithCallback<FormNotCompleteResponse>(
|
|
48
50
|
submit([]),
|
|
49
51
|
510,
|
|
50
52
|
(json) => {
|
|
@@ -55,14 +57,14 @@ export function CreateForm(props: IProps) {
|
|
|
55
57
|
},
|
|
56
58
|
);
|
|
57
59
|
}
|
|
58
|
-
}, [formKey, submit, preselectedInput
|
|
60
|
+
}, [formKey, submit, preselectedInput]);
|
|
59
61
|
|
|
60
62
|
return (
|
|
61
63
|
<div>
|
|
62
64
|
{stepUserInput && (
|
|
63
|
-
<
|
|
65
|
+
<UserInputFormWizard
|
|
64
66
|
stepUserInput={stepUserInput}
|
|
65
|
-
|
|
67
|
+
stepSubmit={submit}
|
|
66
68
|
cancel={handleCancel}
|
|
67
69
|
hasNext={hasNext ?? false}
|
|
68
70
|
isTask={false}
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import React, { useContext, useState } from 'react';
|
|
18
18
|
|
|
19
|
-
import axios from 'axios';
|
|
20
19
|
import invariant from 'invariant';
|
|
21
20
|
import { JSONSchema6 } from 'json-schema';
|
|
22
21
|
import cloneDeep from 'lodash/cloneDeep';
|
|
@@ -37,7 +36,7 @@ import {
|
|
|
37
36
|
import { ConfirmDialogActions, ConfirmationDialogContext } from '@/contexts';
|
|
38
37
|
import { useOrchestratorTheme } from '@/hooks';
|
|
39
38
|
import { WfoPlayFill } from '@/icons';
|
|
40
|
-
import { ValidationError } from '@/types/forms';
|
|
39
|
+
import { FormValidationError, ValidationError } from '@/types/forms';
|
|
41
40
|
|
|
42
41
|
import { autoFieldFunction } from './AutoFieldLoader';
|
|
43
42
|
import AutoFields from './AutoFields';
|
|
@@ -440,31 +439,30 @@ function UserInputForm({
|
|
|
440
439
|
return null;
|
|
441
440
|
} catch (error: unknown) {
|
|
442
441
|
setProcessing(false);
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
)
|
|
465
|
-
}
|
|
442
|
+
if (typeof error === 'object' && error !== null) {
|
|
443
|
+
const validationError = error as FormValidationError;
|
|
444
|
+
if (validationError?.status === 400) {
|
|
445
|
+
const json = validationError.data;
|
|
446
|
+
setNrOfValidationErrors(json.validation_errors.length);
|
|
447
|
+
setRootErrors(
|
|
448
|
+
json.validation_errors
|
|
449
|
+
.filter(
|
|
450
|
+
(e: ValidationError) =>
|
|
451
|
+
e.loc[0] === '__root__',
|
|
452
|
+
)
|
|
453
|
+
.map((e: ValidationError) => e.msg),
|
|
454
|
+
);
|
|
455
|
+
throw Object.assign(new Error(), {
|
|
456
|
+
details: json.validation_errors.map(
|
|
457
|
+
(e: ValidationError) => ({
|
|
458
|
+
message: e.msg,
|
|
459
|
+
params: e.ctx || {},
|
|
460
|
+
dataPath: '.' + e.loc.join('.'),
|
|
461
|
+
}),
|
|
462
|
+
),
|
|
463
|
+
});
|
|
464
|
+
}
|
|
466
465
|
}
|
|
467
|
-
|
|
468
466
|
// Let the error escape so it can be caught by our own onerror handler instead of being silenced by uniforms
|
|
469
467
|
setTimeout(() => {
|
|
470
468
|
throw error;
|
|
@@ -44,14 +44,14 @@ function stop(e: React.SyntheticEvent) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
export
|
|
47
|
+
export const UserInputFormWizard = ({
|
|
48
48
|
hasNext = false,
|
|
49
49
|
stepUserInput,
|
|
50
50
|
stepSubmit,
|
|
51
51
|
cancel,
|
|
52
52
|
isTask,
|
|
53
53
|
isResuming = false,
|
|
54
|
-
}: UserInputFormWizardProps) {
|
|
54
|
+
}: UserInputFormWizardProps) => {
|
|
55
55
|
const router = useRouter();
|
|
56
56
|
const [forms, setForms] = useState<Form[]>([
|
|
57
57
|
{ form: stepUserInput, hasNext: hasNext },
|
|
@@ -118,6 +118,4 @@ export function UserInputFormWizard({
|
|
|
118
118
|
isResuming={isResuming}
|
|
119
119
|
/>
|
|
120
120
|
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export default UserInputFormWizard;
|
|
121
|
+
};
|
|
@@ -2,9 +2,9 @@ import React, { useState } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { EuiFlexItem } from '@elastic/eui';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { useAxiosApiClient } from '@/components/WfoForms/useAxiosApiClient';
|
|
5
|
+
import { UserInputFormWizard, WfoLoading } from '@/components';
|
|
7
6
|
import { useOrchestratorTheme } from '@/hooks';
|
|
7
|
+
import { useResumeProcessMutation } from '@/rtk/endpoints/forms';
|
|
8
8
|
import { InputForm } from '@/types/forms';
|
|
9
9
|
|
|
10
10
|
interface WfoStepFormProps {
|
|
@@ -20,24 +20,26 @@ export const WfoStepForm = ({
|
|
|
20
20
|
}: WfoStepFormProps) => {
|
|
21
21
|
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
|
22
22
|
const { theme } = useOrchestratorTheme();
|
|
23
|
-
const
|
|
23
|
+
const [resumeProcess] = useResumeProcessMutation();
|
|
24
24
|
|
|
25
25
|
const submitForm = (processInput: object[]) => {
|
|
26
26
|
if (!processId) {
|
|
27
27
|
return Promise.reject();
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
return
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
return resumeProcess({ processId, userInputs: processInput }).then(
|
|
31
|
+
() => {
|
|
32
|
+
setIsProcessing(true);
|
|
33
|
+
},
|
|
34
|
+
);
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
return (
|
|
36
38
|
<EuiFlexItem css={{ margin: theme.size.m }}>
|
|
37
39
|
{(isProcessing && <WfoLoading />) || (
|
|
38
|
-
<
|
|
40
|
+
<UserInputFormWizard
|
|
39
41
|
stepUserInput={userInputForm}
|
|
40
|
-
|
|
42
|
+
stepSubmit={submitForm}
|
|
41
43
|
hasNext={false}
|
|
42
44
|
isTask={isTask}
|
|
43
45
|
isResuming={true}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import { AxiosError } from 'axios';
|
|
4
3
|
import { JSONSchema6 } from 'json-schema';
|
|
5
4
|
import { useTranslations } from 'next-intl';
|
|
6
5
|
import { useRouter } from 'next/router';
|
|
@@ -13,13 +12,18 @@ import {
|
|
|
13
12
|
EuiText,
|
|
14
13
|
} from '@elastic/eui';
|
|
15
14
|
|
|
16
|
-
import { PATH_TASKS, WfoError, WfoLoading } from '@/components';
|
|
17
|
-
import {
|
|
15
|
+
import { PATH_TASKS, PATH_WORKFLOWS, WfoError, WfoLoading } from '@/components';
|
|
16
|
+
import { UserInputFormWizard } from '@/components/WfoForms/UserInputFormWizard';
|
|
18
17
|
import { useAxiosApiClient } from '@/components/WfoForms/useAxiosApiClient';
|
|
19
18
|
import { WfoStepStatusIcon } from '@/components/WfoWorkflowSteps';
|
|
20
19
|
import { getStyles } from '@/components/WfoWorkflowSteps/styles';
|
|
21
20
|
import { useOrchestratorTheme } from '@/hooks';
|
|
22
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
HttpStatus,
|
|
23
|
+
handlePromiseErrorWithCallback,
|
|
24
|
+
useGetTimeLineItemsQuery,
|
|
25
|
+
} from '@/rtk';
|
|
26
|
+
import { useStartProcessMutation } from '@/rtk/endpoints/forms';
|
|
23
27
|
import {
|
|
24
28
|
EngineStatus,
|
|
25
29
|
ProcessDetail,
|
|
@@ -28,7 +32,6 @@ import {
|
|
|
28
32
|
} from '@/types';
|
|
29
33
|
import { FormNotCompleteResponse } from '@/types/forms';
|
|
30
34
|
|
|
31
|
-
import UserInputFormWizardDeprecated from '../../components/WfoForms/UserInputFormWizardDeprecated';
|
|
32
35
|
import { WfoProcessDetail } from './WfoProcessDetail';
|
|
33
36
|
|
|
34
37
|
type StartCreateWorkflowPayload = {
|
|
@@ -86,6 +89,8 @@ export const WfoStartProcessPage = ({
|
|
|
86
89
|
const [form, setForm] = useState<UserInputForm>({});
|
|
87
90
|
const { productId, subscriptionId } = router.query as StartProcessPageQuery;
|
|
88
91
|
|
|
92
|
+
const [startProcess] = useStartProcessMutation();
|
|
93
|
+
|
|
89
94
|
const startProcessPayload = useMemo(
|
|
90
95
|
() => getInitialProcessPayload({ productId, subscriptionId }),
|
|
91
96
|
[productId, subscriptionId],
|
|
@@ -110,17 +115,15 @@ export const WfoStartProcessPage = ({
|
|
|
110
115
|
|
|
111
116
|
const submit = useCallback(
|
|
112
117
|
(processInput: object[]) => {
|
|
113
|
-
const startProcessPromise =
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
startProcessPayload
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
)
|
|
118
|
+
const startProcessPromise = startProcess({
|
|
119
|
+
workflowName: processName,
|
|
120
|
+
userInputs: startProcessPayload
|
|
121
|
+
? [startProcessPayload, ...processInput]
|
|
122
|
+
: [...processInput],
|
|
123
|
+
})
|
|
124
|
+
.unwrap()
|
|
120
125
|
.then(
|
|
121
|
-
|
|
122
|
-
(result) => {
|
|
123
|
-
const process = result as { id: string };
|
|
126
|
+
(process) => {
|
|
124
127
|
if (process.id) {
|
|
125
128
|
const basePath = isTask
|
|
126
129
|
? PATH_TASKS
|
|
@@ -133,13 +136,12 @@ export const WfoStartProcessPage = ({
|
|
|
133
136
|
throw e;
|
|
134
137
|
},
|
|
135
138
|
)
|
|
136
|
-
.catch((error
|
|
137
|
-
if (error?.
|
|
138
|
-
if (error?.
|
|
139
|
+
.catch((error) => {
|
|
140
|
+
if (error?.status !== HttpStatus.FormNotComplete) {
|
|
141
|
+
if (error?.status === HttpStatus.BadRequest) {
|
|
139
142
|
// Rethrow the error so userInputForm can catch it and display validation errors
|
|
140
143
|
throw error;
|
|
141
144
|
}
|
|
142
|
-
|
|
143
145
|
console.error(error);
|
|
144
146
|
setHasError(true);
|
|
145
147
|
} else {
|
|
@@ -149,9 +151,9 @@ export const WfoStartProcessPage = ({
|
|
|
149
151
|
|
|
150
152
|
// Catch a 503: Service unavailable error indicating the engine is down. This rethrows other errors
|
|
151
153
|
// if it's not 503 so we can catch the special 510 error in the catchErrorStatus call in the useEffect hook
|
|
152
|
-
return
|
|
154
|
+
return handlePromiseErrorWithCallback<EngineStatus>(
|
|
153
155
|
startProcessPromise,
|
|
154
|
-
|
|
156
|
+
HttpStatus.ServiceUnavailable,
|
|
155
157
|
(json) => {
|
|
156
158
|
// TODO: Use the toastMessage hook to display an engine down error message
|
|
157
159
|
console.error('engine down!!!', json);
|
|
@@ -159,7 +161,7 @@ export const WfoStartProcessPage = ({
|
|
|
159
161
|
},
|
|
160
162
|
);
|
|
161
163
|
},
|
|
162
|
-
[
|
|
164
|
+
[startProcess, processName, startProcessPayload, isTask, router],
|
|
163
165
|
);
|
|
164
166
|
|
|
165
167
|
useEffect(() => {
|
|
@@ -171,9 +173,9 @@ export const WfoStartProcessPage = ({
|
|
|
171
173
|
});
|
|
172
174
|
};
|
|
173
175
|
|
|
174
|
-
|
|
176
|
+
handlePromiseErrorWithCallback<FormNotCompleteResponse>(
|
|
175
177
|
submit([]),
|
|
176
|
-
|
|
178
|
+
HttpStatus.FormNotComplete,
|
|
177
179
|
clientResultCallback,
|
|
178
180
|
);
|
|
179
181
|
}
|
|
@@ -215,9 +217,9 @@ export const WfoStartProcessPage = ({
|
|
|
215
217
|
<EuiHorizontalRule />
|
|
216
218
|
{(hasError && <WfoError />) ||
|
|
217
219
|
(stepUserInput && (
|
|
218
|
-
<
|
|
220
|
+
<UserInputFormWizard
|
|
219
221
|
stepUserInput={stepUserInput}
|
|
220
|
-
|
|
222
|
+
stepSubmit={submit}
|
|
221
223
|
cancel={() =>
|
|
222
224
|
router.push(
|
|
223
225
|
isTask ? PATH_TASKS : PATH_WORKFLOWS,
|
package/src/rtk/api.ts
CHANGED
|
@@ -25,6 +25,7 @@ export enum HttpStatus {
|
|
|
25
25
|
FormNotComplete = 510,
|
|
26
26
|
BadGateway = 502,
|
|
27
27
|
BadRequest = 400,
|
|
28
|
+
ServiceUnavailable = 503,
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
type ExtraOptions = {
|
|
@@ -42,7 +43,7 @@ export const prepareHeaders = async (headers: Headers) => {
|
|
|
42
43
|
|
|
43
44
|
export const handlePromiseErrorWithCallback = <T>(
|
|
44
45
|
promise: Promise<unknown>,
|
|
45
|
-
status:
|
|
46
|
+
status: HttpStatus,
|
|
46
47
|
callbackAction: (json: T) => void,
|
|
47
48
|
) => {
|
|
48
49
|
return promise.catch((err) => {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { BaseQueryTypes, orchestratorApi } from '@/rtk';
|
|
2
|
+
|
|
3
|
+
const PROCESS_ENDPOINT = 'processes';
|
|
4
|
+
const RESUME_ENDPOINT = 'resume';
|
|
5
|
+
const FORMS_ENDPOINT = 'surf/forms/'; // It is still being used by example-wfo-ui
|
|
6
|
+
|
|
7
|
+
const formsApi = orchestratorApi.injectEndpoints({
|
|
8
|
+
endpoints: (build) => ({
|
|
9
|
+
startProcess: build.mutation<
|
|
10
|
+
{ id: string },
|
|
11
|
+
{ workflowName: string; userInputs: object[] }
|
|
12
|
+
>({
|
|
13
|
+
query: ({ workflowName, userInputs }) => ({
|
|
14
|
+
url: `${PROCESS_ENDPOINT}/${workflowName}`,
|
|
15
|
+
method: 'POST',
|
|
16
|
+
body: JSON.stringify(userInputs),
|
|
17
|
+
headers: {
|
|
18
|
+
'Content-Type': 'application/json',
|
|
19
|
+
},
|
|
20
|
+
}),
|
|
21
|
+
extraOptions: {
|
|
22
|
+
baseQueryType: BaseQueryTypes.fetch,
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
resumeProcess: build.mutation<
|
|
26
|
+
void,
|
|
27
|
+
{ processId: string; userInputs: object[] }
|
|
28
|
+
>({
|
|
29
|
+
query: ({ processId, userInputs }) => ({
|
|
30
|
+
url: `${PROCESS_ENDPOINT}/${processId}/${RESUME_ENDPOINT}`,
|
|
31
|
+
method: 'PUT',
|
|
32
|
+
body: JSON.stringify(userInputs),
|
|
33
|
+
headers: {
|
|
34
|
+
'Content-Type': 'application/json',
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
extraOptions: {
|
|
38
|
+
baseQueryType: BaseQueryTypes.fetch,
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
startForm: build.mutation<
|
|
42
|
+
void,
|
|
43
|
+
{ formKey: string; userInputs: object[] }
|
|
44
|
+
>({
|
|
45
|
+
query: ({ formKey, userInputs }) => ({
|
|
46
|
+
url: `${FORMS_ENDPOINT}${formKey}`,
|
|
47
|
+
method: 'POST',
|
|
48
|
+
body: JSON.stringify(userInputs),
|
|
49
|
+
headers: {
|
|
50
|
+
'Content-Type': 'application/json',
|
|
51
|
+
},
|
|
52
|
+
}),
|
|
53
|
+
extraOptions: {
|
|
54
|
+
baseQueryType: BaseQueryTypes.fetch,
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
57
|
+
}),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export const {
|
|
61
|
+
useStartProcessMutation,
|
|
62
|
+
useResumeProcessMutation,
|
|
63
|
+
useStartFormMutation,
|
|
64
|
+
} = formsApi;
|
package/src/types/forms.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { Ref } from 'react';
|
|
|
3
3
|
import { JSONSchema6 } from 'json-schema';
|
|
4
4
|
import { HTMLFieldProps } from 'uniforms';
|
|
5
5
|
|
|
6
|
+
import { HttpStatus } from '@/rtk';
|
|
7
|
+
|
|
6
8
|
export interface ValidationError {
|
|
7
9
|
input_type: string;
|
|
8
10
|
loc: (string | number)[];
|
|
@@ -38,3 +40,17 @@ export type FieldProps<
|
|
|
38
40
|
description?: string;
|
|
39
41
|
} & Extra
|
|
40
42
|
>;
|
|
43
|
+
|
|
44
|
+
type ValidationErrorData = {
|
|
45
|
+
detail: string;
|
|
46
|
+
status: HttpStatus;
|
|
47
|
+
title: string;
|
|
48
|
+
traceback: string;
|
|
49
|
+
type: string;
|
|
50
|
+
validation_errors: [];
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type FormValidationError = {
|
|
54
|
+
data: ValidationErrorData;
|
|
55
|
+
status: HttpStatus;
|
|
56
|
+
};
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2019-2023 SURF.
|
|
3
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License.
|
|
5
|
-
* You may obtain a copy of the License at
|
|
6
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
*
|
|
8
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
* See the License for the specific language governing permissions and
|
|
12
|
-
* limitations under the License.
|
|
13
|
-
*
|
|
14
|
-
*/
|
|
15
|
-
import React, { useEffect, useState } from 'react';
|
|
16
|
-
|
|
17
|
-
import { useRouter } from 'next/router';
|
|
18
|
-
import hash from 'object-hash';
|
|
19
|
-
|
|
20
|
-
import { ConfirmDialogActions } from '@/contexts';
|
|
21
|
-
import { FormNotCompleteResponse, InputForm } from '@/types/forms';
|
|
22
|
-
|
|
23
|
-
import UserInputForm from './UserInputForm';
|
|
24
|
-
import { useAxiosApiClient } from './useAxiosApiClient';
|
|
25
|
-
|
|
26
|
-
interface Form {
|
|
27
|
-
form: InputForm;
|
|
28
|
-
hasNext?: boolean;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
interface UserInputFormWizardProps {
|
|
32
|
-
stepUserInput: InputForm;
|
|
33
|
-
validSubmit: (processInput: object[]) => Promise<unknown>;
|
|
34
|
-
cancel?: () => void;
|
|
35
|
-
isTask: boolean;
|
|
36
|
-
hasNext?: boolean;
|
|
37
|
-
isResuming?: boolean;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function stop(e: React.SyntheticEvent) {
|
|
41
|
-
if (e !== undefined && e !== null) {
|
|
42
|
-
e.preventDefault();
|
|
43
|
-
e.stopPropagation();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function UserInputFormWizardDeprecated({
|
|
48
|
-
hasNext = false,
|
|
49
|
-
stepUserInput,
|
|
50
|
-
validSubmit,
|
|
51
|
-
cancel,
|
|
52
|
-
isTask,
|
|
53
|
-
isResuming = false,
|
|
54
|
-
}: UserInputFormWizardProps) {
|
|
55
|
-
const router = useRouter();
|
|
56
|
-
const apiClient = useAxiosApiClient();
|
|
57
|
-
const [forms, setForms] = useState<Form[]>([
|
|
58
|
-
{ form: stepUserInput, hasNext: hasNext },
|
|
59
|
-
]);
|
|
60
|
-
const [userInputs, setUserInputs] = useState<object[]>([]);
|
|
61
|
-
|
|
62
|
-
useEffect(() => {
|
|
63
|
-
setForms([{ form: stepUserInput, hasNext: hasNext }]);
|
|
64
|
-
}, [hasNext, stepUserInput]);
|
|
65
|
-
|
|
66
|
-
const previous: ConfirmDialogActions['closeConfirmDialog'] = (e) => {
|
|
67
|
-
if (e) {
|
|
68
|
-
stop(e);
|
|
69
|
-
}
|
|
70
|
-
const current = forms.pop();
|
|
71
|
-
setForms(forms.filter((item) => item !== current));
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const submit = (currentFormData: object) => {
|
|
75
|
-
const newUserInputs = userInputs.slice(0, forms.length - 1);
|
|
76
|
-
newUserInputs.push(currentFormData);
|
|
77
|
-
|
|
78
|
-
const result = validSubmit(newUserInputs);
|
|
79
|
-
return apiClient.catchErrorStatus<FormNotCompleteResponse>(
|
|
80
|
-
result,
|
|
81
|
-
510,
|
|
82
|
-
(json) => {
|
|
83
|
-
window.scrollTo(0, 0);
|
|
84
|
-
setForms([
|
|
85
|
-
...forms,
|
|
86
|
-
{ form: json.form, hasNext: json.hasNext },
|
|
87
|
-
]);
|
|
88
|
-
setUserInputs(newUserInputs);
|
|
89
|
-
},
|
|
90
|
-
);
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const currentForm = forms[forms.length - 1];
|
|
94
|
-
const currentUserInput = userInputs[forms.length - 1];
|
|
95
|
-
if (!currentForm || !currentForm.form.properties) {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/* Generate a key based on input widget names that results in a new
|
|
100
|
-
* clean instance + rerender of UserInputForm if the form changes. Without this, state of previous,
|
|
101
|
-
* wizard step can cause wrong/weird default values for forms inputs.
|
|
102
|
-
*
|
|
103
|
-
* Note: to ensure a new form for multiple form wizard steps with exactly the same fields and labels on
|
|
104
|
-
* the form the hash is calculated on the form object itself + length, which generates a unique hash as it
|
|
105
|
-
* has a changing ".length" attribute.
|
|
106
|
-
* */
|
|
107
|
-
const key = hash.sha1({ form: currentForm.form, length: forms.length });
|
|
108
|
-
return (
|
|
109
|
-
<UserInputForm
|
|
110
|
-
key={key}
|
|
111
|
-
router={router}
|
|
112
|
-
stepUserInput={currentForm.form}
|
|
113
|
-
validSubmit={submit}
|
|
114
|
-
previous={previous}
|
|
115
|
-
hasNext={currentForm.hasNext}
|
|
116
|
-
hasPrev={forms.length > 1}
|
|
117
|
-
cancel={cancel}
|
|
118
|
-
userInput={currentUserInput}
|
|
119
|
-
isTask={isTask}
|
|
120
|
-
isResuming={isResuming}
|
|
121
|
-
/>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export default UserInputFormWizardDeprecated;
|