Skip to content

Commit e539823

Browse files
authored
Update workflow action types (#886)
* update workflow action tyoes * remove unnessesary as Control<ResetWorkflowFormData>
1 parent 301fb64 commit e539823

File tree

9 files changed

+130
-117
lines changed

9 files changed

+130
-117
lines changed

src/views/workflow-actions/__fixtures__/workflow-actions-config.tsx

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import { type TerminateWorkflowResponse } from '@/route-handlers/terminate-workf
88
import { type WorkflowAction } from '../workflow-actions.types';
99

1010
export const mockResetActionConfig: WorkflowAction<
11+
ResetWorkflowResponse,
1112
{ testField: string },
12-
{ transformed: string },
13-
ResetWorkflowResponse
13+
{ transformed: string }
1414
> = {
1515
id: 'reset',
1616
label: 'Mock reset',
@@ -21,6 +21,7 @@ export const mockResetActionConfig: WorkflowAction<
2121
text: 'Mock docs link',
2222
href: 'https://mock.docs.link',
2323
},
24+
withForm: true,
2425
form: ({ control, fieldErrors }) => (
2526
<div data-testid="mock-form">
2627
<input
@@ -44,52 +45,54 @@ export const mockResetActionConfig: WorkflowAction<
4445
`Mock reset notification (Run ID: ${result.runId})`,
4546
};
4647

47-
const mockCancelActionConfig: WorkflowAction<any, any, CancelWorkflowResponse> =
48-
{
49-
id: 'cancel',
50-
label: 'Mock cancel',
51-
subtitle: 'Mock cancel a workflow execution',
52-
modal: {
53-
text: 'Mock modal text to cancel a workflow execution',
54-
docsLink: {
55-
text: 'Mock docs link',
56-
href: 'https://mock.docs.link',
57-
},
58-
},
59-
icon: MdHighlightOff,
60-
getRunnableStatus: () => 'RUNNABLE',
61-
apiRoute: 'cancel',
62-
renderSuccessMessage: () => 'Mock cancel notification',
63-
};
64-
65-
const mockTerminateActionConfig: WorkflowAction<
66-
any,
67-
any,
68-
TerminateWorkflowResponse
48+
export const mockCancelActionConfig: WorkflowAction<
49+
CancelWorkflowResponse,
50+
undefined,
51+
undefined
6952
> = {
70-
id: 'terminate',
71-
label: 'Mock terminate',
72-
subtitle: 'Mock terminate a workflow execution',
53+
id: 'cancel',
54+
label: 'Mock cancel',
55+
subtitle: 'Mock cancel a workflow execution',
7356
modal: {
74-
text: 'Mock modal text to terminate a workflow execution',
57+
text: 'Mock modal text to cancel a workflow execution',
7558
docsLink: {
7659
text: 'Mock docs link',
7760
href: 'https://mock.docs.link',
7861
},
62+
withForm: false,
7963
},
80-
icon: MdPowerSettingsNew,
64+
icon: MdHighlightOff,
8165
getRunnableStatus: () => 'RUNNABLE',
82-
apiRoute: 'terminate',
83-
renderSuccessMessage: () => 'Mock terminate notification',
66+
apiRoute: 'cancel',
67+
renderSuccessMessage: () => 'Mock cancel notification',
8468
};
8569

70+
export const mockTerminateActionConfig: WorkflowAction<TerminateWorkflowResponse> =
71+
{
72+
id: 'terminate',
73+
label: 'Mock terminate',
74+
subtitle: 'Mock terminate a workflow execution',
75+
modal: {
76+
text: 'Mock modal text to terminate a workflow execution',
77+
docsLink: {
78+
text: 'Mock docs link',
79+
href: 'https://mock.docs.link',
80+
},
81+
withForm: false,
82+
},
83+
icon: MdPowerSettingsNew,
84+
getRunnableStatus: () => 'RUNNABLE',
85+
apiRoute: 'terminate',
86+
renderSuccessMessage: () => 'Mock terminate notification',
87+
};
88+
8689
export const mockWorkflowActionsConfig: [
87-
WorkflowAction<any, any, CancelWorkflowResponse>,
88-
WorkflowAction<any, any, TerminateWorkflowResponse>,
90+
WorkflowAction<CancelWorkflowResponse>,
91+
WorkflowAction<TerminateWorkflowResponse>,
8992
WorkflowAction<
93+
ResetWorkflowResponse,
9094
{ testField: string },
91-
{ transformed: string },
92-
ResetWorkflowResponse
95+
{ transformed: string }
9396
>,
9497
] = [
9598
mockCancelActionConfig,

src/views/workflow-actions/config/workflow-actions.config.ts

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,7 @@ import {
2222
} from '../workflow-action-reset-form/workflow-action-reset-form.types';
2323
import { type WorkflowAction } from '../workflow-actions.types';
2424

25-
const cancelWorkflowActionConfig: WorkflowAction<
26-
any,
27-
any,
28-
CancelWorkflowResponse
29-
> = {
25+
const cancelWorkflowActionConfig: WorkflowAction<CancelWorkflowResponse> = {
3026
id: 'cancel',
3127
label: 'Cancel',
3228
subtitle: 'Cancel a workflow execution',
@@ -36,6 +32,7 @@ const cancelWorkflowActionConfig: WorkflowAction<
3632
text: 'Read more about cancelling workflows',
3733
href: 'https://cadenceworkflow.io/docs/cli#signal-cancel-terminate-workflow',
3834
},
35+
withForm: false,
3936
},
4037
icon: MdHighlightOff,
4138
getRunnableStatus: (workflow) =>
@@ -48,37 +45,31 @@ const cancelWorkflowActionConfig: WorkflowAction<
4845
renderSuccessMessage: () => 'Workflow cancellation has been requested.',
4946
};
5047

51-
const terminateWorkflowActionConfig: WorkflowAction<
52-
any,
53-
any,
54-
TerminateWorkflowResponse
55-
> = {
56-
id: 'terminate',
57-
label: 'Terminate',
58-
subtitle: 'Terminate a workflow execution',
59-
modal: {
60-
text: 'Terminates a running workflow immediately. Please terminate a workflow only if you know what you are doing.',
61-
docsLink: {
62-
text: 'Read more about terminating workflows',
63-
href: 'https://cadenceworkflow.io/docs/cli#signal-cancel-terminate-workflow',
48+
const terminateWorkflowActionConfig: WorkflowAction<TerminateWorkflowResponse> =
49+
{
50+
id: 'terminate',
51+
label: 'Terminate',
52+
subtitle: 'Terminate a workflow execution',
53+
modal: {
54+
text: 'Terminates a running workflow immediately. Please terminate a workflow only if you know what you are doing.',
55+
docsLink: {
56+
text: 'Read more about terminating workflows',
57+
href: 'https://cadenceworkflow.io/docs/cli#signal-cancel-terminate-workflow',
58+
},
59+
withForm: false,
6460
},
65-
},
66-
icon: MdPowerSettingsNew,
67-
getRunnableStatus: (workflow) =>
68-
getWorkflowIsCompleted(
69-
workflow.workflowExecutionInfo?.closeEvent?.attributes ?? ''
70-
)
71-
? 'NOT_RUNNABLE_WORKFLOW_CLOSED'
72-
: 'RUNNABLE',
73-
apiRoute: 'terminate',
74-
renderSuccessMessage: () => 'Workflow has been terminated.',
75-
};
61+
icon: MdPowerSettingsNew,
62+
getRunnableStatus: (workflow) =>
63+
getWorkflowIsCompleted(
64+
workflow.workflowExecutionInfo?.closeEvent?.attributes ?? ''
65+
)
66+
? 'NOT_RUNNABLE_WORKFLOW_CLOSED'
67+
: 'RUNNABLE',
68+
apiRoute: 'terminate',
69+
renderSuccessMessage: () => 'Workflow has been terminated.',
70+
};
7671

77-
const restartWorkflowActionConfig: WorkflowAction<
78-
any,
79-
any,
80-
RestartWorkflowResponse
81-
> = {
72+
const restartWorkflowActionConfig: WorkflowAction<RestartWorkflowResponse> = {
8273
id: 'restart',
8374
label: 'Restart',
8475
subtitle: 'Restart a workflow execution',
@@ -87,6 +78,7 @@ const restartWorkflowActionConfig: WorkflowAction<
8778
'Restarts a workflow by creating a new execution with a fresh Run ID while using the existing input. If the previous execution is still running, it will be terminated.',
8879
'What differentiates Restart from Reset is that the restarted workflow is not aware of the previous workflow execution.',
8980
],
81+
withForm: false,
9082
},
9183
icon: MdOutlineRestartAlt,
9284
getRunnableStatus: () => 'RUNNABLE',
@@ -99,9 +91,9 @@ const restartWorkflowActionConfig: WorkflowAction<
9991
};
10092

10193
export const resetWorkflowActionConfig: WorkflowAction<
94+
ResetWorkflowResponse,
10295
ResetWorkflowFormData,
103-
ResetWorkflowSubmissionData,
104-
ResetWorkflowResponse
96+
ResetWorkflowSubmissionData
10597
> = {
10698
id: 'reset',
10799
label: 'Reset',
@@ -114,6 +106,7 @@ export const resetWorkflowActionConfig: WorkflowAction<
114106
text: 'Read more about resetting workflows',
115107
href: 'https://cadenceworkflow.io/docs/cli#workflow-reset',
116108
},
109+
withForm: true,
117110
form: WorkflowActionResetForm,
118111
formSchema: resetWorkflowFormSchema,
119112
transformFormDataToSubmission: (v) => v,
@@ -133,6 +126,6 @@ const workflowActionsConfig = [
133126
terminateWorkflowActionConfig,
134127
restartWorkflowActionConfig,
135128
resetWorkflowActionConfig,
136-
] as const;
129+
] as const satisfies WorkflowAction<any, any, any>[];
137130

138131
export default workflowActionsConfig;

src/views/workflow-actions/workflow-action-reset-form/__tests__/workflow-action-reset-form.test.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22

3-
import { type FieldErrors, useForm, type Control } from 'react-hook-form';
3+
import { type FieldErrors, useForm } from 'react-hook-form';
44

55
import { render, screen, userEvent } from '@/test-utils/rtl';
66

@@ -82,9 +82,13 @@ function TestWrapper({ formErrors, formData }: TestProps) {
8282

8383
return (
8484
<WorkflowActionResetForm
85-
control={methods.control as Control<ResetWorkflowFormData>}
85+
control={methods.control}
8686
fieldErrors={formErrors}
8787
formData={formData}
88+
cluster="test-cluster"
89+
domain="test-domain"
90+
workflowId="test-workflow-id"
91+
runId="test-run-id"
8892
/>
8993
);
9094
}

src/views/workflow-actions/workflow-actions-modal-content/__tests__/workflow-actions-modal-content.test.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import { type CancelWorkflowResponse } from '@/route-handlers/cancel-workflow/ca
66
import { type ResetWorkflowResponse } from '@/route-handlers/reset-workflow/reset-workflow.types';
77
import { mockWorkflowDetailsParams } from '@/views/workflow-page/__fixtures__/workflow-details-params';
88

9-
import { mockWorkflowActionsConfig } from '../../__fixtures__/workflow-actions-config';
9+
import {
10+
mockCancelActionConfig,
11+
mockWorkflowActionsConfig,
12+
} from '../../__fixtures__/workflow-actions-config';
1013
import { type WorkflowAction } from '../../workflow-actions.types';
1114
import WorkflowActionsModalContent from '../workflow-actions-modal-content';
1215

@@ -85,8 +88,9 @@ describe(WorkflowActionsModalContent.name, () => {
8588

8689
it('renders array text correctly in modal content', () => {
8790
const cancelAction = {
88-
...mockWorkflowActionsConfig[0],
91+
...mockCancelActionConfig,
8992
modal: {
93+
...mockCancelActionConfig.modal,
9094
text: ['First line of array text', 'Second line of array text'],
9195
},
9296
};

src/views/workflow-actions/workflow-actions-modal-content/workflow-actions-modal-content.tsx

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ import { Banner, HIERARCHY, KIND as BANNER_KIND } from 'baseui/banner';
44
import { KIND as BUTTON_KIND, SIZE } from 'baseui/button';
55
import { ModalButton } from 'baseui/modal';
66
import { useSnackbar } from 'baseui/snackbar';
7-
import {
8-
type FieldValues,
9-
useForm,
10-
type DefaultValues,
11-
type Control,
12-
} from 'react-hook-form';
7+
import { type DefaultValues, type FieldValues, useForm } from 'react-hook-form';
138
import { MdCheckCircle, MdErrorOutline, MdOpenInNew } from 'react-icons/md';
149

1510
import request from '@/utils/request';
@@ -21,28 +16,31 @@ import { overrides, styled } from './workflow-actions-modal-content.styles';
2116
import { type Props } from './workflow-actions-modal-content.types';
2217

2318
export default function WorkflowActionsModalContent<
24-
FormData extends FieldValues,
25-
SubmissionData,
2619
Result,
20+
FormData,
21+
SubmissionData,
2722
>({
2823
action,
2924
params,
3025
onCloseModal,
3126
initialFormValues,
32-
}: Props<FormData, SubmissionData, Result>) {
27+
}: Props<Result, FormData, SubmissionData>) {
3328
const queryClient = useQueryClient();
3429
const { enqueue, dequeue } = useSnackbar();
3530

31+
// useForm doesn't accept form data that is not a FieldValues (e.g. undefined)
32+
type OptionalFormData = FormData extends FieldValues ? FormData : any;
33+
3634
const {
3735
handleSubmit,
3836
formState: { errors: validationErrors, isSubmitting },
3937
control,
4038
watch,
41-
} = useForm<FormData>({
39+
} = useForm<OptionalFormData>({
4240
resolver: action.modal.formSchema
4341
? zodResolver(action.modal.formSchema)
4442
: undefined,
45-
defaultValues: initialFormValues,
43+
defaultValues: initialFormValues as DefaultValues<OptionalFormData>,
4644
});
4745

4846
const { mutate, isPending, error } = useMutation<
@@ -87,12 +85,11 @@ export default function WorkflowActionsModalContent<
8785
);
8886

8987
const onSubmit = (data: FormData) => {
90-
const { transformFormDataToSubmission } = action.modal;
91-
const transform = transformFormDataToSubmission || (() => undefined);
92-
9388
mutate({
9489
...params,
95-
submissionData: transform(data),
90+
submissionData: action.modal.withForm
91+
? action.modal.transformFormDataToSubmission(data)
92+
: (undefined as SubmissionData),
9693
});
9794
};
9895

@@ -121,11 +118,15 @@ export default function WorkflowActionsModalContent<
121118
<MdOpenInNew />
122119
</styled.Link>
123120
)}
124-
{Form && (
121+
{action.modal.withForm && Form && (
125122
<Form
126123
formData={watch()}
127124
fieldErrors={validationErrors}
128-
control={control as Control<FieldValues>}
125+
control={control}
126+
cluster={params.cluster}
127+
domain={params.domain}
128+
workflowId={params.workflowId}
129+
runId={params.runId}
129130
/>
130131
)}
131132
{error && (
@@ -143,7 +144,7 @@ export default function WorkflowActionsModalContent<
143144
</styled.ModalBody>
144145
<styled.ModalFooter>
145146
<ModalButton
146-
autoFocus={!action.modal.form}
147+
autoFocus={!action.modal.withForm}
147148
size={SIZE.compact}
148149
type="button"
149150
kind={BUTTON_KIND.secondary}

src/views/workflow-actions/workflow-actions-modal-content/workflow-actions-modal-content.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import {
55
type WorkflowActionInputParams,
66
} from '../workflow-actions.types';
77

8-
export type Props<FormData, SubmissionData, Result> = {
9-
action: WorkflowAction<FormData, SubmissionData, Result>;
8+
export type Props<Result, FormData, SubmissionData> = {
9+
action: WorkflowAction<Result, FormData, SubmissionData>;
1010
params: WorkflowActionInputParams;
1111
onCloseModal: () => void;
1212
initialFormValues?: DefaultValues<FormData>;

0 commit comments

Comments
 (0)