-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[UI v2] feat: Adds component for change-flow-run-state option (#16611)
Co-authored-by: Alex Streed <desertaxle@users.noreply.github.com>
- Loading branch information
1 parent
b8a7988
commit e067622
Showing
18 changed files
with
514 additions
and
169 deletions.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
...d/action-step/action-change-flow-run-state-fields/action-change-flow-run-state-fields.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { ActionChangeFlowRunStateMessageField } from "./action-change-flow-run-state-message-field"; | ||
import { ActionChangeFlowRunStateNameField } from "./action-change-flow-run-state-name-field"; | ||
import { ActionChangeFlowRunStateStateField } from "./action-change-flow-run-state-state-field"; | ||
|
||
export const ActionChangeFlowRunStateFields = () => ( | ||
<div> | ||
<ActionChangeFlowRunStateStateField /> | ||
<ActionChangeFlowRunStateNameField /> | ||
<ActionChangeFlowRunStateMessageField /> | ||
</div> | ||
); |
31 changes: 31 additions & 0 deletions
31
...n-step/action-change-flow-run-state-fields/action-change-flow-run-state-message-field.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { | ||
FormControl, | ||
FormField, | ||
FormItem, | ||
FormLabel, | ||
FormMessage, | ||
} from "@/components/ui/form"; | ||
import { Textarea } from "@/components/ui/textarea"; | ||
import { useFormContext } from "react-hook-form"; | ||
|
||
export const ActionChangeFlowRunStateMessageField = () => { | ||
const form = useFormContext(); | ||
return ( | ||
<FormField | ||
control={form.control} | ||
name="message" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Message</FormLabel> | ||
<FormControl> | ||
<Textarea | ||
{...field} | ||
placeholder="State changed by Automation <id>" | ||
/> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
); | ||
}; |
35 changes: 35 additions & 0 deletions
35
...tion-step/action-change-flow-run-state-fields/action-change-flow-run-state-name-field.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { ActionsSchema } from "@/components/automations/automations-wizard/action-step/action-type-schemas"; | ||
import { | ||
FormControl, | ||
FormField, | ||
FormItem, | ||
FormLabel, | ||
FormMessage, | ||
} from "@/components/ui/form"; | ||
import { Input } from "@/components/ui/input"; | ||
import { useFormContext, useWatch } from "react-hook-form"; | ||
import { FLOW_STATES, FlowStates } from "./flow-states"; | ||
|
||
export const ActionChangeFlowRunStateNameField = () => { | ||
const form = useFormContext(); | ||
const stateField = useWatch<ActionsSchema>({ name: "state" }) as FlowStates; | ||
return ( | ||
<FormField | ||
control={form.control} | ||
name="name" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Name</FormLabel> | ||
<FormControl> | ||
<Input | ||
type="text" | ||
{...field} | ||
placeholder={FLOW_STATES[stateField]} | ||
/> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
); | ||
}; |
51 changes: 51 additions & 0 deletions
51
...ion-step/action-change-flow-run-state-fields/action-change-flow-run-state-state-field.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { | ||
FormControl, | ||
FormField, | ||
FormItem, | ||
FormLabel, | ||
FormMessage, | ||
} from "@/components/ui/form"; | ||
import { | ||
Select, | ||
SelectContent, | ||
SelectGroup, | ||
SelectItem, | ||
SelectLabel, | ||
SelectTrigger, | ||
SelectValue, | ||
} from "@/components/ui/select"; | ||
import { useFormContext } from "react-hook-form"; | ||
import { FLOW_STATES, type FlowStates } from "./flow-states"; | ||
|
||
export const ActionChangeFlowRunStateStateField = () => { | ||
const form = useFormContext(); | ||
return ( | ||
<FormField | ||
control={form.control} | ||
name="state" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>State</FormLabel> | ||
<FormControl> | ||
<Select {...field} onValueChange={field.onChange}> | ||
<SelectTrigger aria-label="select state"> | ||
<SelectValue placeholder="Select state" /> | ||
</SelectTrigger> | ||
<SelectContent> | ||
<SelectGroup> | ||
<SelectLabel>Actions</SelectLabel> | ||
{Object.keys(FLOW_STATES).map((key) => ( | ||
<SelectItem key={key} value={key}> | ||
{FLOW_STATES[key as FlowStates]} | ||
</SelectItem> | ||
))} | ||
</SelectGroup> | ||
</SelectContent> | ||
</Select> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
); | ||
}; |
17 changes: 17 additions & 0 deletions
17
...mations/automations-wizard/action-step/action-change-flow-run-state-fields/flow-states.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { components } from "@/api/prefect"; | ||
|
||
export const FLOW_STATES = { | ||
COMPLETED: "Completed", | ||
RUNNING: "Running", | ||
SCHEDULED: "Scheduled", | ||
PENDING: "Pending", | ||
FAILED: "Failed", | ||
CANCELLED: "Cancelled", | ||
CANCELLING: "Cancelling", | ||
CRASHED: "Crashed", | ||
PAUSED: "Paused", | ||
} as const satisfies Record< | ||
components["schemas"]["StateType"], | ||
Capitalize<Lowercase<components["schemas"]["StateType"]>> | ||
>; | ||
export type FlowStates = keyof typeof FLOW_STATES; |
1 change: 1 addition & 0 deletions
1
...s/automations/automations-wizard/action-step/action-change-flow-run-state-fields/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { ActionChangeFlowRunStateFields } from "./action-change-flow-run-state-fields"; |
14 changes: 14 additions & 0 deletions
14
ui-v2/src/components/automations/automations-wizard/action-step/action-step.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
import { fn } from "@storybook/test"; | ||
import { ActionStep } from "./action-step"; | ||
|
||
const meta = { | ||
title: "Components/Automations/Wizard/ActionStep", | ||
component: ActionStep, | ||
args: { onSubmit: fn() }, | ||
} satisfies Meta; | ||
|
||
export default meta; | ||
|
||
export const story: StoryObj = { name: "ActionStep" }; |
72 changes: 72 additions & 0 deletions
72
ui-v2/src/components/automations/automations-wizard/action-step/action-step.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { ActionStep } from "./action-step"; | ||
|
||
import { render, screen } from "@testing-library/react"; | ||
import userEvent from "@testing-library/user-event"; | ||
import { beforeAll, describe, expect, it, vi } from "vitest"; | ||
|
||
describe("ActionStep", () => { | ||
beforeAll(() => { | ||
/** | ||
* JSDOM doesn't implement PointerEvent so we need to mock our own implementation | ||
* Default to mouse left click interaction | ||
* https://github.com/radix-ui/primitives/issues/1822 | ||
* https://github.com/jsdom/jsdom/pull/2666 | ||
*/ | ||
class MockPointerEvent extends Event { | ||
button: number; | ||
ctrlKey: boolean; | ||
pointerType: string; | ||
|
||
constructor(type: string, props: PointerEventInit) { | ||
super(type, props); | ||
this.button = props.button || 0; | ||
this.ctrlKey = props.ctrlKey || false; | ||
this.pointerType = props.pointerType || "mouse"; | ||
} | ||
} | ||
window.PointerEvent = MockPointerEvent as never; | ||
window.HTMLElement.prototype.scrollIntoView = vi.fn(); | ||
window.HTMLElement.prototype.releasePointerCapture = vi.fn(); | ||
window.HTMLElement.prototype.hasPointerCapture = vi.fn(); | ||
}); | ||
|
||
it("able to select a basic action", async () => { | ||
const user = userEvent.setup(); | ||
|
||
// ------------ Setup | ||
const mockOnSubmitFn = vi.fn(); | ||
render(<ActionStep onSubmit={mockOnSubmitFn} />); | ||
|
||
// ------------ Act | ||
await user.click(screen.getByRole("combobox", { name: /select action/i })); | ||
await user.click(screen.getByRole("option", { name: "Cancel a flow run" })); | ||
|
||
// ------------ Assert | ||
expect(screen.getAllByText("Cancel a flow run")).toBeTruthy(); | ||
}); | ||
|
||
it("able to configure change flow run's state action", async () => { | ||
const user = userEvent.setup(); | ||
|
||
// ------------ Setup | ||
const mockOnSubmitFn = vi.fn(); | ||
render(<ActionStep onSubmit={mockOnSubmitFn} />); | ||
|
||
// ------------ Act | ||
await user.click(screen.getByRole("combobox", { name: /select action/i })); | ||
await user.click( | ||
screen.getByRole("option", { name: "Change flow run's state" }), | ||
); | ||
|
||
await user.click(screen.getByRole("combobox", { name: /select state/i })); | ||
await user.click(screen.getByRole("option", { name: "Failed" })); | ||
await user.type(screen.getByPlaceholderText("Failed"), "test name"); | ||
await user.type(screen.getByLabelText("Message"), "test message"); | ||
|
||
// ------------ Assert | ||
expect(screen.getAllByText("Change flow run's state")).toBeTruthy(); | ||
expect(screen.getAllByText("Failed")).toBeTruthy(); | ||
expect(screen.getByLabelText("Name")).toHaveValue("test name"); | ||
expect(screen.getByLabelText("Message")).toHaveValue("test message"); | ||
}); | ||
}); |
42 changes: 42 additions & 0 deletions
42
ui-v2/src/components/automations/automations-wizard/action-step/action-step.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { Button } from "@/components/ui/button"; | ||
import { Form, FormMessage } from "@/components/ui/form"; | ||
import { zodResolver } from "@hookform/resolvers/zod"; | ||
import { useEffect } from "react"; | ||
import { useForm } from "react-hook-form"; | ||
import { z } from "zod"; | ||
|
||
import { ActionTypeAdditionalFields } from "./action-type-additional-fields"; | ||
import { ActionsSchema } from "./action-type-schemas"; | ||
import { ActionTypeSelect } from "./action-type-select"; | ||
|
||
type ActionStepProps = { | ||
onSubmit: (schema: ActionsSchema) => void; | ||
}; | ||
|
||
export const ActionStep = ({ onSubmit }: ActionStepProps) => { | ||
const form = useForm<z.infer<typeof ActionsSchema>>({ | ||
resolver: zodResolver(ActionsSchema), | ||
}); | ||
|
||
// Reset form when changing action type | ||
const watchType = form.watch("type"); | ||
useEffect(() => { | ||
const currentActionType = form.getValues("type"); | ||
form.reset(); | ||
form.setValue("type", currentActionType); | ||
}, [form, watchType]); | ||
|
||
return ( | ||
<Form {...form}> | ||
<form onSubmit={(e) => void form.handleSubmit(onSubmit)(e)}> | ||
<ActionTypeSelect /> | ||
<ActionTypeAdditionalFields actionType={watchType} /> | ||
<FormMessage>{form.formState.errors.root?.message}</FormMessage> | ||
{/** nb: This button will change once we integrate it with the full wizard */} | ||
<Button className="mt-2" type="submit"> | ||
Validate | ||
</Button> | ||
</form> | ||
</Form> | ||
); | ||
}; |
35 changes: 35 additions & 0 deletions
35
...c/components/automations/automations-wizard/action-step/action-type-additional-fields.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { ActionChangeFlowRunStateFields } from "./action-change-flow-run-state-fields"; | ||
import type { ActionsSchema } from "./action-type-schemas"; | ||
|
||
type ActionTypeAdditionalFieldsProps = { | ||
actionType: ActionsSchema["type"]; | ||
}; | ||
|
||
export const ActionTypeAdditionalFields = ({ | ||
actionType, | ||
}: ActionTypeAdditionalFieldsProps) => { | ||
switch (actionType) { | ||
case "change-flow-run-state": | ||
return <ActionChangeFlowRunStateFields />; | ||
case "run-deployment": | ||
case "pause-deployment": | ||
case "resume-deployment": | ||
return <div>TODO Deployment</div>; | ||
case "pause-work-queue": | ||
case "resume-work-queue": | ||
return <div>TODO Work Queue</div>; | ||
case "pause-work-pool": | ||
case "resume-work-pool": | ||
return <div>TODO Work pool</div>; | ||
case "pause-automation": | ||
case "resume-automation": | ||
return <div>TODO Automation</div>; | ||
case "send-notification": | ||
return <div>TODO send notification</div>; | ||
case "cancel-flow-run": | ||
case "suspend-flow-run": | ||
case "resume-flow-run": | ||
default: | ||
return null; | ||
} | ||
}; |
Oops, something went wrong.