From 809a4de1e8829538d49ce685771b510923eb1307 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Sun, 31 Aug 2025 01:57:02 -0700 Subject: [PATCH 01/10] Workflows --- .../workflows/[workflowId]/page.tsx | 104 +++++ .../projects/[projectId]/workflows/page.tsx | 355 ++++++++++++++++++ .../[projectId]/workflows/workflow-list.tsx | 160 ++++++++ packages/stack-shared/src/config/schema.ts | 27 +- 4 files changed, 643 insertions(+), 3 deletions(-) create mode 100644 apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/workflows/[workflowId]/page.tsx create mode 100644 apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/workflows/page.tsx create mode 100644 apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/workflows/workflow-list.tsx diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/workflows/[workflowId]/page.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/workflows/[workflowId]/page.tsx new file mode 100644 index 0000000000..885058b240 --- /dev/null +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/workflows/[workflowId]/page.tsx @@ -0,0 +1,104 @@ +"use client"; + +import { useRouter } from "@/components/router"; +import { Button, Card, CardContent, CardHeader, CardTitle, toast } from "@stackframe/stack-ui"; +import { ArrowLeft, Save } from "lucide-react"; +import { useParams } from "next/navigation"; +import { useEffect, useState } from "react"; +import { PageLayout } from "../../page-layout"; +import { useAdminApp } from "../../use-admin-app"; + +export default function WorkflowDetailPage() { + const params = useParams(); + const router = useRouter(); + const workflowId = params.workflowId as string; + const projectId = params.projectId as string; + + const stackAdminApp = useAdminApp(); + const project = stackAdminApp.useProject(); + const config = project.useConfig(); + + const availableWorkflows = config.workflows.availableWorkflows; + const workflow = workflowId in availableWorkflows ? availableWorkflows[workflowId] : undefined; + const [workflowContent, setWorkflowContent] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + useEffect(() => { + if (workflow && workflow.tsSource) { + setWorkflowContent(workflow.tsSource); + } + }, [workflow]); + + const handleSave = async () => { + setIsLoading(true); + try { + await project.updateConfig({ + [`workflows.availableWorkflows.${workflowId}.tsSource`]: workflowContent + }); + toast({ title: "Workflow saved successfully" }); + } catch (error) { + toast({ title: "Failed to save workflow", variant: "destructive" }); + } finally { + setIsLoading(false); + } + }; + + const handleBack = () => { + router.push(`/projects/${projectId}/workflows`); + }; + + if (workflow === undefined) { + return ( + +
+

The workflow {JSON.stringify(workflowId)} was not found.

+ +
+
+ ); + } + + return ( + + + + + } + > +
+ + + Workflow Definition +

+ {workflow.enabled ? "This workflow is enabled" : "This workflow is disabled"} +

+
+ +
+