diff --git a/src/renderer/routes/test_sequencer_panel/components/TestSequencerInfo.tsx b/src/renderer/routes/test_sequencer_panel/components/TestSequencerInfo.tsx index 2d19d1d58..db272620c 100644 --- a/src/renderer/routes/test_sequencer_panel/components/TestSequencerInfo.tsx +++ b/src/renderer/routes/test_sequencer_panel/components/TestSequencerInfo.tsx @@ -11,10 +11,10 @@ import SequencerKeyboardShortcuts from "@/renderer/routes/test_sequencer_panel/S import { ControlButton } from "./ControlButton"; import { DesignBar } from "./DesignBar"; import { useDisplayedSequenceState } from "@/renderer/hooks/useTestSequencerState"; -import { TestSequencerProjectModal } from "./modals/TestSequencerProjectModal"; import { ImportTestModal } from "./modals/ImportTestModal"; import { ErrorModal } from "./modals/ErrorModal"; import { RenameTestModal } from "./modals/RenameTestModal"; +import { CreateSequenceModal } from "./modals/CreateSequenceModal"; const TestSequencerView = () => { const { backendGlobalState } = useDisplayedSequenceState(); @@ -40,7 +40,7 @@ const TestSequencerView = () => { }} className="overflow-y-auto" > - + diff --git a/src/renderer/routes/test_sequencer_panel/components/modals/CreateSequenceModal.tsx b/src/renderer/routes/test_sequencer_panel/components/modals/CreateSequenceModal.tsx new file mode 100644 index 000000000..7dca49ea4 --- /dev/null +++ b/src/renderer/routes/test_sequencer_panel/components/modals/CreateSequenceModal.tsx @@ -0,0 +1,175 @@ +import { Dialog, DialogContent } from "@/renderer/components/ui/dialog"; +import { Button } from "@/renderer/components/ui/button"; +import { useState } from "react"; +import { Input } from "@/renderer/components/ui/input"; +import { useDisplayedSequenceState } from "@/renderer/hooks/useTestSequencerState"; +import { useCreateSequence } from "@/renderer/hooks/useTestSequencerProject"; +import { InterpreterType } from "@/renderer/types/test-sequencer"; +import { PathInput } from "@/renderer/components/ui/path-input"; +import { useSequencerModalStore } from "@/renderer/stores/modal"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/renderer/components/ui/form"; + +const formSchema = z.object({ + name: z + .string() + .min(1) + .max(50) + .regex(/\S/, { + message: "The sequence name should not contain white spaces", + }) + .transform((val) => val.trim()), + description: z.string().max(100), + projectPath: z.string().min(1).regex(/\S/, { + message: "The project path should not contain white spaces", + }), +}); + +export const CreateSequenceModal = () => { + const { isCreateProjectModalOpen, setIsCreateProjectModalOpen } = + useSequencerModalStore(); + const { elems } = useDisplayedSequenceState(); + const handleCreate = useCreateSequence(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [interpreterPath, setInterpreterPath] = useState(""); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [type, setType] = useState("flojoy"); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + name: "", + description: "", + projectPath: "", + }, + }); + + function handleSubmit(values: z.infer) { + handleCreate( + { + name: values.name, + description: values.description, + elems: elems, + projectPath: values.projectPath, + interpreter: { + type: type, + path: interpreterPath === "" ? null : interpreterPath, + requirementsPath: "flojoy_requirements.txt", + }, + }, + setIsCreateProjectModalOpen, + ); + } + + return ( + + + New Sequence + + + ( + + Sequence Name + + + + + + )} + /> + ( + + Description + + + + + + )} + /> + ( + + Project Root Directory + + + + + + )} + /> + { + // + // + // {setType(e)}}> + // + // + // + // + // + // Interpreter + // { availableInterpreter.map((interpreter) => ( + // + // { interpreter.charAt(0).toUpperCase() + interpreter.slice(1) } + // + // ))} + // + // + // + // + // {setInterpreterPath(event.target.value)}} + // /> + // + } + + New Sequence + + + + + + ); +}; diff --git a/src/renderer/routes/test_sequencer_panel/components/modals/TestSequencerProjectModal.tsx b/src/renderer/routes/test_sequencer_panel/components/modals/TestSequencerProjectModal.tsx deleted file mode 100644 index dd2677180..000000000 --- a/src/renderer/routes/test_sequencer_panel/components/modals/TestSequencerProjectModal.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { Dialog, DialogContent } from "@/renderer/components/ui/dialog"; -import { Button } from "@/renderer/components/ui/button"; -import { useState } from "react"; -import { Input } from "@/renderer/components/ui/input"; -import { useDisplayedSequenceState } from "@/renderer/hooks/useTestSequencerState"; -import { useCreateSequence } from "@/renderer/hooks/useTestSequencerProject"; -import { InterpreterType } from "@/renderer/types/test-sequencer"; -import { PathInput } from "@/renderer/components/ui/path-input"; -import { useSequencerModalStore } from "@/renderer/stores/modal"; - -export const TestSequencerProjectModal = () => { - const { isCreateProjectModalOpen, setIsCreateProjectModalOpen } = - useSequencerModalStore(); - const { elems } = useDisplayedSequenceState(); - const handleCreate = useCreateSequence(); - const [name, setName] = useState(""); - const [description, setDescription] = useState(""); - const [projectDirPath, setProjectDirPath] = useState(""); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [interpreterPath, setInterpreterPath] = useState(""); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [type, setType] = useState("flojoy"); - - function handleSubmit() { - handleCreate( - { - name: name, - description: description, - elems: elems, - projectPath: projectDirPath, - interpreter: { - type: type, - path: interpreterPath === "" ? null : interpreterPath, - requirementsPath: "flojoy_requirements.txt", - }, - }, - setIsCreateProjectModalOpen, - ); - } - - return ( - - - - New Sequence - - { - setName(e.target.value); - }} - /> - { - setDescription(e.target.value); - }} - /> - { - setProjectDirPath(event.target.value); - }} - pickerType="directory" - allowDirectoryCreation={true} - /> - { - // - // - // {setType(e)}}> - // - // - // - // - // - // Interpreter - // { availableInterpreter.map((interpreter) => ( - // - // { interpreter.charAt(0).toUpperCase() + interpreter.slice(1) } - // - // ))} - // - // - // - // - // {setInterpreterPath(event.target.value)}} - // /> - // - } - handleSubmit()} - > - New Sequence - - - - ); -};