diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/CreateDeployment.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/CreateDeployment.tsx index 09716b54e..64a3645c9 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/CreateDeployment.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/CreateDeployment.tsx @@ -2,10 +2,10 @@ import React, { useState } from "react"; import { useParams, useRouter } from "next/navigation"; +import { IconLoader2 } from "@tabler/icons-react"; import slugify from "slugify"; -import { z } from "zod"; -import { deploymentSchema } from "@ctrlplane/db/schema"; +import * as SCHEMA from "@ctrlplane/db/schema"; import { Button } from "@ctrlplane/ui/button"; import { Dialog, @@ -37,10 +37,10 @@ import { } from "@ctrlplane/ui/select"; import { Textarea } from "@ctrlplane/ui/textarea"; +import { JobAgentConfig } from "~/components/form/job-agent/JobAgentConfig"; +import { JobAgentSelector } from "~/components/form/job-agent/JobAgentSelector"; import { api } from "~/trpc/react"; -const deploymentForm = z.object(deploymentSchema.omit({ id: true }).shape); - export const CreateDeploymentDialog: React.FC<{ children?: React.ReactNode; systemId?: string; @@ -48,18 +48,24 @@ export const CreateDeploymentDialog: React.FC<{ }> = ({ children, onSuccess, ...props }) => { const [open, setOpen] = useState(false); const { workspaceSlug } = useParams<{ workspaceSlug: string }>(); - const workspace = api.workspace.bySlug.useQuery(workspaceSlug); - const systems = api.system.list.useQuery( - { workspaceId: workspace.data?.id ?? "" }, - { enabled: workspace.isSuccess }, + const { data: workspace, ...workspaceQ } = + api.workspace.bySlug.useQuery(workspaceSlug); + const { data: systems, ...systemsQ } = api.system.list.useQuery( + { workspaceId: workspace?.id ?? "" }, + { enabled: workspace != null }, ); const createDeployment = api.deployment.create.useMutation(); const router = useRouter(); + const { data: jobAgentsResult, ...jobAgentsQ } = + api.job.agent.byWorkspaceId.useQuery(workspace?.id ?? "", { + enabled: workspace != null, + }); + const jobAgents = jobAgentsResult ?? []; const form = useForm({ - schema: deploymentForm, + schema: SCHEMA.createDeployment, defaultValues: { - systemId: props.systemId ?? systems.data?.items[0]?.id, + systemId: props.systemId ?? systems?.items[0]?.id, name: "", slug: "", description: "", @@ -70,38 +76,41 @@ export const CreateDeploymentDialog: React.FC<{ const { handleSubmit, watch, setValue, setError } = form; + const selectedJobAgentId = watch("jobAgentId"); + const selectedJobAgent = jobAgents.find( + (agent) => agent.id === selectedJobAgentId, + ); + watch((data, { name: fieldName }) => { if (fieldName === "name") setValue("slug", slugify(data.name ?? "", { lower: true })); }); const onSubmit = handleSubmit(async (deployment) => { - const systemSlug = systems.data?.items.find( - (system) => system.id === form.getValues("systemId"), + const systemSlug = systems?.items.find( + (system) => system.id === deployment.systemId, )?.slug; await createDeployment - .mutateAsync( - deployment as { - systemId: string; - name: string; - slug: string; - description: string; - }, + .mutateAsync(deployment) + .then( + () => + systemSlug != null && + router.push( + `/${workspaceSlug}/systems/${systemSlug}/deployments/${deployment.slug}`, + ), ) - .then(() => { - router.push( - `/${workspaceSlug}/systems/${systemSlug}/deployments/${deployment.slug}`, - ); - setOpen(false); - onSuccess?.(); - }) - .catch(() => { + .then(() => setOpen(false)) + .then(() => onSuccess?.()) + .catch(() => setError("root", { message: "Deployment with this slug already exists", - }); - }); + }), + ); }); + const loading = + workspaceQ.isLoading || systemsQ.isLoading || jobAgentsQ.isLoading; + return ( {children} @@ -116,98 +125,154 @@ export const CreateDeploymentDialog: React.FC<{ - ( - - System - - - - - - )} - /> - ( - - Name - - - - - - )} - /> - ( - - Slug - - - - - - )} - /> - ( - - Description - -