Skip to content

Commit

Permalink
[UI v2] feat: Starts AutomationsActionSelect component (#16599)
Browse files Browse the repository at this point in the history
  • Loading branch information
devinvillarosa authored Jan 3, 2025
1 parent eb083ba commit 858eec5
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";
import { useState } from "react";
import {
type AutomationActions,
AutomationsActionSelect,
} from "./automations-action-select";

const meta = {
title: "Components/Automations/Wizard/AutomationsActionSelect",
component: AutomationsActionSelect,
args: { onValueChange: fn() },
render: function ComponentExmaple() {
const [action, setAction] = useState<AutomationActions>();
return <AutomationsActionSelect onValueChange={setAction} value={action} />;
},
} satisfies Meta<typeof AutomationsActionSelect>;

export default meta;

export const story: StoryObj = { name: "AutomationsActionSelect" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { expect, test, vi } from "vitest";

import { AutomationsActionSelect } from "./automations-action-select";

test("AutomationsActionSelect can select an option", async () => {
/**
* 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();

const user = userEvent.setup();

// ------------ Setup
const mockOnValueChangeFn = vi.fn();

render(<AutomationsActionSelect onValueChange={mockOnValueChangeFn} />);

// ------------ Act
await user.click(screen.getByLabelText("Action Type"));
await user.click(screen.getByRole("option", { name: "Resume a flow run" }));

// ------------ Assert
expect(screen.getByText("Resume a flow run")).toBeVisible();
expect(mockOnValueChangeFn).toBeCalledWith("resume-flow-run");
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";

const AUTOMATION_ACTION_TYPES = {
"cancel-flow-run": "Cancel a flow run",
"suspend-flow-run": "Suspend a flow run",
"resume-flow-run": "Resume a flow run",
"change-flow-run-state": "Change flow run's state",
"run-deployment": "Run a deployment",
"pause-deployment": "Pause a deployment",
"resume-deployment": "Resume a deployment",
"pause-work-queue": "Pause a work queue",
"resume-work-queue": "Resume a work queue",
"pause-work-pool": "Pause a work pool",
"resume-work-pool": "Resume a work pool",
"pause-automation": "Pause an automation",
"resume-automation": "Resume an automation",
"send-notification": "Send a notification",
"do-nothing": "Do nothing",
} as const;

export type AutomationActions = keyof typeof AUTOMATION_ACTION_TYPES;

type AutomationsActionSelectSelectProps = {
onValueChange: (value: AutomationActions) => void;
value?: AutomationActions;
};

export const AutomationsActionSelect = ({
onValueChange,
value,
}: AutomationsActionSelectSelectProps) => {
return (
<div className="row flex-col gap-4">
<div>
<Label htmlFor="automations-action-select">Action Type</Label>
<Select value={value} onValueChange={onValueChange}>
<SelectTrigger id="automations-action-select">
<SelectValue placeholder="Select action" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Actions</SelectLabel>
{Object.keys(AUTOMATION_ACTION_TYPES)
.filter((key) => (key as AutomationActions) !== "do-nothing")
.map((key) => (
<SelectItem key={key} value={key}>
{AUTOMATION_ACTION_TYPES[key as AutomationActions]}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</div>
<AdditionalActionFields actionType={value} />
</div>
);
};

type AdditionalActionFieldsProps = {
actionType?: AutomationActions;
};
const AdditionalActionFields = ({
actionType,
}: AdditionalActionFieldsProps) => {
switch (actionType) {
case "change-flow-run-state":
return <div>TODO Flow Run state</div>;
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":
case "do-nothing":
default:
return null;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export {
AutomationsActionSelect,
type AutomationActions,
} from "./automations-action-select";

0 comments on commit 858eec5

Please sign in to comment.