From 21e76f9ad75c5f8c1bcf01cf5ed0024b93f85cd0 Mon Sep 17 00:00:00 2001
From: Aditya Choudhari <48932219+adityachoudhari26@users.noreply.github.com>
Date: Sun, 1 Dec 2024 00:07:17 -0800
Subject: [PATCH] fix: Settings page runbooks (#242)
---
.../runbooks/EditRunbookDialog.tsx | 144 ++--------------
.../[systemSlug]/runbooks/EditRunbookForm.tsx | 160 ++++++++++++++++++
.../runbooks/[runbookId]/RunbookNavBar.tsx | 29 ++--
.../runbooks/[runbookId]/layout.tsx | 2 +-
.../[runbookId]/settings/EditRunbook.tsx | 49 ++++++
.../runbooks/[runbookId]/settings/page.tsx | 32 ++++
packages/api/src/router/runbook.ts | 5 +-
7 files changed, 277 insertions(+), 144 deletions(-)
create mode 100644 apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/EditRunbookForm.tsx
create mode 100644 apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/settings/EditRunbook.tsx
create mode 100644 apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/settings/page.tsx
diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/EditRunbookDialog.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/EditRunbookDialog.tsx
index 3f59b10c..29f884ac 100644
--- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/EditRunbookDialog.tsx
+++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/EditRunbookDialog.tsx
@@ -7,7 +7,6 @@ import { useRouter } from "next/navigation";
import { z } from "zod";
import { createRunbookVariable } from "@ctrlplane/db/schema";
-import { Button } from "@ctrlplane/ui/button";
import {
Dialog,
DialogContent,
@@ -15,23 +14,11 @@ import {
DialogTitle,
DialogTrigger,
} from "@ctrlplane/ui/dialog";
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
- FormRootError,
- useForm,
-} from "@ctrlplane/ui/form";
-import { Input } from "@ctrlplane/ui/input";
-import { Textarea } from "@ctrlplane/ui/textarea";
+import { useForm } from "@ctrlplane/ui/form";
-import { JobAgentConfig } from "~/components/form/job-agent/JobAgentConfig";
-import { JobAgentSelector } from "~/components/form/job-agent/JobAgentSelector";
+import type { EditRunbookFormSchema } from "./EditRunbookForm";
import { api } from "~/trpc/react";
-import { RunbookVariablesEditor } from "./create/RunbookVariableEditor";
+import { EditRunbookForm } from "./EditRunbookForm";
const updateRunbookSchema = z.object({
name: z.string().min(1),
@@ -60,12 +47,12 @@ export const EditRunbookDialog: React.FC<{
});
const router = useRouter();
- const onSubmit = form.handleSubmit(async (data) =>
+
+ const onSubmit = (data: EditRunbookFormSchema) =>
update
.mutateAsync({ id: runbook.id, data })
.then(() => router.refresh())
- .then(() => setOpen(false)),
- );
+ .then(() => setOpen(false));
const jobAgentId = form.watch("jobAgentId");
const jobAgent = jobAgents.find((j) => j.id === jobAgentId);
@@ -76,118 +63,13 @@ export const EditRunbookDialog: React.FC<{
Edit Runbook
-
-
+
);
diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/EditRunbookForm.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/EditRunbookForm.tsx
new file mode 100644
index 00000000..da6f13b3
--- /dev/null
+++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/EditRunbookForm.tsx
@@ -0,0 +1,160 @@
+"use client";
+
+import type { UseFormReturn } from "react-hook-form";
+import { z } from "zod";
+
+import * as SCHEMA from "@ctrlplane/db/schema";
+import { Button } from "@ctrlplane/ui/button";
+import {
+ Form,
+ FormControl,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+ FormRootError,
+} from "@ctrlplane/ui/form";
+import { Input } from "@ctrlplane/ui/input";
+import { Textarea } from "@ctrlplane/ui/textarea";
+
+import { JobAgentConfig } from "~/components/form/job-agent/JobAgentConfig";
+import { JobAgentSelector } from "~/components/form/job-agent/JobAgentSelector";
+import { RunbookVariablesEditor } from "./create/RunbookVariableEditor";
+
+export const updateRunbookSchema = z.object({
+ name: z.string().min(1),
+ description: z.string(),
+ variables: z.array(SCHEMA.createRunbookVariable),
+ jobAgentId: z.string().uuid({ message: "Must be a valid job agent ID" }),
+ jobAgentConfig: z.record(z.any()),
+});
+
+export type EditRunbookFormSchema = z.infer;
+
+export type EditRunbookFormProps = {
+ form: UseFormReturn;
+ jobAgents: SCHEMA.JobAgent[];
+ jobAgent?: SCHEMA.JobAgent;
+ workspace: SCHEMA.Workspace;
+ onSubmit: (data: EditRunbookFormSchema) => void;
+};
+
+export const EditRunbookForm: React.FC = ({
+ form,
+ jobAgents,
+ jobAgent,
+ workspace,
+ onSubmit,
+}) => (
+
+
+);
diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/RunbookNavBar.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/RunbookNavBar.tsx
index e01b758d..8ee5d1c7 100644
--- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/RunbookNavBar.tsx
+++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/RunbookNavBar.tsx
@@ -1,5 +1,6 @@
"use client";
+import type { RouterOutputs } from "@ctrlplane/api";
import type React from "react";
import Link from "next/link";
import { useParams, usePathname } from "next/navigation";
@@ -18,9 +19,13 @@ import { nFormatter } from "../../_components/nFormatter";
type RunbookNavBarProps = {
totalJobs: number;
+ runbook: NonNullable;
};
-export const RunbookNavBar: React.FC = ({ totalJobs }) => {
+export const RunbookNavBar: React.FC = ({
+ totalJobs,
+ runbook,
+}) => {
const { workspaceSlug, systemSlug, runbookId } = useParams<{
workspaceSlug: string;
systemSlug: string;
@@ -56,16 +61,18 @@ export const RunbookNavBar: React.FC = ({ totalJobs }) => {
-
-
-
- Settings
-
-
-
+ {runbook.runhooks.length === 0 && (
+
+
+
+ Settings
+
+
+
+ )}
diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/layout.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/layout.tsx
index 5be37414..2b30d87c 100644
--- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/layout.tsx
+++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/layout.tsx
@@ -43,7 +43,7 @@ export default async function RunbookLayout({
-
+
{children}
diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/settings/EditRunbook.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/settings/EditRunbook.tsx
new file mode 100644
index 00000000..fb0afe14
--- /dev/null
+++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/settings/EditRunbook.tsx
@@ -0,0 +1,49 @@
+"use client";
+
+import type { RouterOutputs } from "@ctrlplane/api";
+import type * as SCHEMA from "@ctrlplane/db/schema";
+import { useRouter } from "next/navigation";
+
+import { useForm } from "@ctrlplane/ui/form";
+
+import type { EditRunbookFormSchema } from "../../EditRunbookForm";
+import { api } from "~/trpc/react";
+import { EditRunbookForm, updateRunbookSchema } from "../../EditRunbookForm";
+
+type EditRunbookProps = {
+ runbook: NonNullable
;
+ jobAgents: SCHEMA.JobAgent[];
+ jobAgent: SCHEMA.JobAgent;
+ workspace: SCHEMA.Workspace;
+};
+
+export const EditRunbook: React.FC = ({
+ runbook,
+ jobAgents,
+ jobAgent,
+ workspace,
+}) => {
+ const defaultValues = {
+ ...runbook,
+ description: runbook.description ?? "",
+ jobAgentId: jobAgent.id,
+ jobAgentConfig: jobAgent.config,
+ };
+
+ const form = useForm({ schema: updateRunbookSchema, defaultValues });
+ const update = api.runbook.update.useMutation();
+ const router = useRouter();
+
+ const onSubmit = (data: EditRunbookFormSchema) =>
+ update.mutateAsync({ id: runbook.id, data }).then(() => router.refresh());
+
+ return (
+
+ );
+};
diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/settings/page.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/settings/page.tsx
new file mode 100644
index 00000000..4ae70ef1
--- /dev/null
+++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/runbooks/[runbookId]/settings/page.tsx
@@ -0,0 +1,32 @@
+import { notFound } from "next/navigation";
+
+import { api } from "~/trpc/server";
+import { EditRunbook } from "./EditRunbook";
+
+export default async function RunbookSettingsPage({
+ params,
+}: {
+ params: { workspaceSlug: string; runbookId: string };
+}) {
+ const workspace = await api.workspace.bySlug(params.workspaceSlug);
+ if (workspace == null) return notFound();
+ const jobAgents = await api.job.agent.byWorkspaceId(workspace.id);
+ const runbook = await api.runbook.byId(params.runbookId);
+ if (runbook == null) return notFound();
+
+ const jobAgent = jobAgents.find((ja) => ja.id === runbook.jobAgentId);
+ if (jobAgent == null) return notFound();
+
+ return (
+
+ );
+}
diff --git a/packages/api/src/router/runbook.ts b/packages/api/src/router/runbook.ts
index bdb4906f..1a70e8cc 100644
--- a/packages/api/src/router/runbook.ts
+++ b/packages/api/src/router/runbook.ts
@@ -21,7 +21,10 @@ export const runbookRouter = createTRPCRouter({
}),
})
.query(({ ctx, input }) =>
- ctx.db.query.runbook.findFirst({ where: eq(SCHEMA.runbook.id, input) }),
+ ctx.db.query.runbook.findFirst({
+ where: eq(SCHEMA.runbook.id, input),
+ with: { variables: true, runhooks: true },
+ }),
),
trigger: protectedProcedure