feat: options to clone the workflow
This commit is contained in:
		
							parent
							
								
									20635612bb
								
							
						
					
					
						commit
						56eb91d102
					
				@ -1,3 +1,5 @@
 | 
			
		||||
MODAL_TOKEN_ID=
 | 
			
		||||
MODAL_TOKEN_SECRET=
 | 
			
		||||
 | 
			
		||||
# On production set to False
 | 
			
		||||
DEPLOY_TEST_FLAG=True
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
import { createNewWorkflow } from "../../../../server/createNewWorkflow";
 | 
			
		||||
import { parseJWT } from "../../../../server/parseJWT";
 | 
			
		||||
import { db } from "@/db/db";
 | 
			
		||||
import {
 | 
			
		||||
  snapshotType,
 | 
			
		||||
  workflowAPIType,
 | 
			
		||||
  workflowTable,
 | 
			
		||||
  workflowType,
 | 
			
		||||
  workflowVersionTable,
 | 
			
		||||
} from "@/db/schema";
 | 
			
		||||
@ -76,29 +76,44 @@ export async function POST(request: Request) {
 | 
			
		||||
  try {
 | 
			
		||||
    if ((!workflow_id || workflow_id.length == 0) && workflow_name) {
 | 
			
		||||
      // Create a new parent workflow
 | 
			
		||||
      const workflow_parent = await db
 | 
			
		||||
        .insert(workflowTable)
 | 
			
		||||
        .values({
 | 
			
		||||
          user_id,
 | 
			
		||||
          name: workflow_name,
 | 
			
		||||
      const { workflow_id: _workflow_id, version: _version } =
 | 
			
		||||
        await createNewWorkflow({
 | 
			
		||||
          user_id: user_id,
 | 
			
		||||
          org_id: org_id,
 | 
			
		||||
        })
 | 
			
		||||
        .returning();
 | 
			
		||||
          workflow_name: workflow_name,
 | 
			
		||||
          workflowData: {
 | 
			
		||||
            workflow,
 | 
			
		||||
            workflow_api,
 | 
			
		||||
            snapshot,
 | 
			
		||||
          },
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
      workflow_id = workflow_parent[0].id;
 | 
			
		||||
      workflow_id = _workflow_id;
 | 
			
		||||
      version = _version;
 | 
			
		||||
 | 
			
		||||
      // Create a new version
 | 
			
		||||
      const data = await db
 | 
			
		||||
        .insert(workflowVersionTable)
 | 
			
		||||
        .values({
 | 
			
		||||
          workflow_id: workflow_id,
 | 
			
		||||
          workflow,
 | 
			
		||||
          workflow_api,
 | 
			
		||||
          version: 1,
 | 
			
		||||
          snapshot: snapshot,
 | 
			
		||||
        })
 | 
			
		||||
        .returning();
 | 
			
		||||
      version = data[0].version;
 | 
			
		||||
      // const workflow_parent = await db
 | 
			
		||||
      //   .insert(workflowTable)
 | 
			
		||||
      //   .values({
 | 
			
		||||
      //     user_id,
 | 
			
		||||
      //     name: workflow_name,
 | 
			
		||||
      //     org_id: org_id,
 | 
			
		||||
      //   })
 | 
			
		||||
      //   .returning();
 | 
			
		||||
 | 
			
		||||
      // workflow_id = workflow_parent[0].id;
 | 
			
		||||
 | 
			
		||||
      // // Create a new version
 | 
			
		||||
      // const data = await db
 | 
			
		||||
      //   .insert(workflowVersionTable)
 | 
			
		||||
      //   .values({
 | 
			
		||||
      //     workflow_id: workflow_id,
 | 
			
		||||
      //     workflow,
 | 
			
		||||
      //     workflow_api,
 | 
			
		||||
      //     version: 1,
 | 
			
		||||
      //     snapshot: snapshot,
 | 
			
		||||
      //   })
 | 
			
		||||
      //   .returning();
 | 
			
		||||
      // version = data[0].version;
 | 
			
		||||
    } else if (workflow_id) {
 | 
			
		||||
      // Case 2 update workflow
 | 
			
		||||
      const data = await db
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,9 @@
 | 
			
		||||
import { ButtonAction } from "@/components/ButtonActionLoader";
 | 
			
		||||
import {
 | 
			
		||||
  PublicRunOutputs,
 | 
			
		||||
  RunWorkflowInline,
 | 
			
		||||
} from "@/components/VersionSelect";
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
import {
 | 
			
		||||
  Card,
 | 
			
		||||
  CardContent,
 | 
			
		||||
@ -14,7 +16,7 @@ import { usersTable } from "@/db/schema";
 | 
			
		||||
import { getInputsFromWorkflow } from "@/lib/getInputsFromWorkflow";
 | 
			
		||||
import { getRelativeTime } from "@/lib/getRelativeTime";
 | 
			
		||||
import { setInitialUserData } from "@/lib/setInitialUserData";
 | 
			
		||||
import { findSharedDeployment } from "@/server/curdDeploments";
 | 
			
		||||
import { cloneWorkflow, findSharedDeployment } from "@/server/curdDeploments";
 | 
			
		||||
import { auth, clerkClient } from "@clerk/nextjs/server";
 | 
			
		||||
import { eq } from "drizzle-orm";
 | 
			
		||||
import { redirect } from "next/navigation";
 | 
			
		||||
@ -55,10 +57,19 @@ export default async function Page({
 | 
			
		||||
    <div className="mt-4 w-full grid grid-rows-[1fr,1fr] lg:grid-cols-[minmax(auto,500px),1fr] gap-4 max-h-[calc(100dvh-100px)]">
 | 
			
		||||
      <Card className="w-full h-fit mt-4">
 | 
			
		||||
        <CardHeader>
 | 
			
		||||
          <CardTitle>
 | 
			
		||||
            {userName}
 | 
			
		||||
            {" / "}
 | 
			
		||||
            {sharedDeployment.workflow.name}
 | 
			
		||||
          <CardTitle className="flex justify-between items-center">
 | 
			
		||||
            <div>
 | 
			
		||||
              {userName}
 | 
			
		||||
              {" / "}
 | 
			
		||||
              {sharedDeployment.workflow.name}
 | 
			
		||||
            </div>
 | 
			
		||||
            <Button asChild className="gap-2" variant="outline" type="submit">
 | 
			
		||||
              <ButtonAction
 | 
			
		||||
                action={cloneWorkflow.bind(null, sharedDeployment.id)}
 | 
			
		||||
              >
 | 
			
		||||
                Clone
 | 
			
		||||
              </ButtonAction>
 | 
			
		||||
            </Button>
 | 
			
		||||
          </CardTitle>
 | 
			
		||||
          <CardDescription suppressHydrationWarning={true}>
 | 
			
		||||
            {getRelativeTime(sharedDeployment?.updated_at)}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								web/src/server/createNewWorkflow.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								web/src/server/createNewWorkflow.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
import { db } from "@/db/db";
 | 
			
		||||
import type { WorkflowVersionType } from "@/db/schema";
 | 
			
		||||
import { workflowTable, workflowVersionTable } from "@/db/schema";
 | 
			
		||||
 | 
			
		||||
export async function createNewWorkflow({
 | 
			
		||||
  workflow_name,
 | 
			
		||||
  user_id,
 | 
			
		||||
  org_id,
 | 
			
		||||
  workflowData,
 | 
			
		||||
}: {
 | 
			
		||||
  workflow_name: string;
 | 
			
		||||
  user_id: string;
 | 
			
		||||
  org_id?: string;
 | 
			
		||||
  workflowData: Pick<
 | 
			
		||||
    WorkflowVersionType,
 | 
			
		||||
    "workflow" | "workflow_api" | "snapshot"
 | 
			
		||||
  >;
 | 
			
		||||
}) {
 | 
			
		||||
  // Create a new parent workflow
 | 
			
		||||
  const workflow_parent = await db
 | 
			
		||||
    .insert(workflowTable)
 | 
			
		||||
    .values({
 | 
			
		||||
      user_id,
 | 
			
		||||
      name: workflow_name,
 | 
			
		||||
      org_id: org_id,
 | 
			
		||||
    })
 | 
			
		||||
    .returning();
 | 
			
		||||
 | 
			
		||||
  const workflow_id = workflow_parent[0].id;
 | 
			
		||||
 | 
			
		||||
  // Create a new version
 | 
			
		||||
  const data = await db
 | 
			
		||||
    .insert(workflowVersionTable)
 | 
			
		||||
    .values({
 | 
			
		||||
      workflow_id: workflow_id,
 | 
			
		||||
      version: 1,
 | 
			
		||||
      ...workflowData,
 | 
			
		||||
    })
 | 
			
		||||
    .returning();
 | 
			
		||||
  const version = data[0].version;
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    workflow_id,
 | 
			
		||||
    version,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@ -3,10 +3,12 @@
 | 
			
		||||
import { db } from "@/db/db";
 | 
			
		||||
import type { DeploymentType } from "@/db/schema";
 | 
			
		||||
import { deploymentsTable, workflowTable } from "@/db/schema";
 | 
			
		||||
import { createNewWorkflow } from "@/server/createNewWorkflow";
 | 
			
		||||
import { withServerPromise } from "@/server/withServerPromise";
 | 
			
		||||
import { auth } from "@clerk/nextjs";
 | 
			
		||||
import { and, eq, isNull } from "drizzle-orm";
 | 
			
		||||
import { revalidatePath } from "next/cache";
 | 
			
		||||
import { redirect } from "next/navigation";
 | 
			
		||||
import "server-only";
 | 
			
		||||
 | 
			
		||||
export async function createDeployments(
 | 
			
		||||
@ -18,6 +20,10 @@ export async function createDeployments(
 | 
			
		||||
  const { userId } = auth();
 | 
			
		||||
  if (!userId) throw new Error("No user id");
 | 
			
		||||
 | 
			
		||||
  if (!machine_id) {
 | 
			
		||||
    throw new Error("No machine id provided");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Same environment and same workflow
 | 
			
		||||
  const existingDeployment = await db.query.deploymentsTable.findFirst({
 | 
			
		||||
    where: and(
 | 
			
		||||
@ -108,7 +114,6 @@ export async function findSharedDeployment(workflow_id: string) {
 | 
			
		||||
 | 
			
		||||
export const removePublicShareDeployment = withServerPromise(
 | 
			
		||||
  async (deployment_id: string) => {
 | 
			
		||||
    // throw new Error("Not implemented");
 | 
			
		||||
    await db
 | 
			
		||||
      .delete(deploymentsTable)
 | 
			
		||||
      .where(
 | 
			
		||||
@ -119,3 +124,41 @@ export const removePublicShareDeployment = withServerPromise(
 | 
			
		||||
      );
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const cloneWorkflow = withServerPromise(
 | 
			
		||||
  async (deployment_id: string) => {
 | 
			
		||||
    const deployment = await db.query.deploymentsTable.findFirst({
 | 
			
		||||
      where: and(
 | 
			
		||||
        eq(deploymentsTable.environment, "public-share"),
 | 
			
		||||
        eq(deploymentsTable.id, deployment_id)
 | 
			
		||||
      ),
 | 
			
		||||
      with: {
 | 
			
		||||
        version: true,
 | 
			
		||||
        workflow: true,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (!deployment) throw new Error("No deployment found");
 | 
			
		||||
 | 
			
		||||
    const { userId, orgId } = auth();
 | 
			
		||||
 | 
			
		||||
    if (!userId) throw new Error("No user id");
 | 
			
		||||
 | 
			
		||||
    await createNewWorkflow({
 | 
			
		||||
      user_id: userId,
 | 
			
		||||
      org_id: orgId,
 | 
			
		||||
      workflow_name: `${deployment.workflow.name} (Cloned)`,
 | 
			
		||||
      workflowData: {
 | 
			
		||||
        workflow: deployment.version.workflow,
 | 
			
		||||
        workflow_api: deployment?.version.workflow_api,
 | 
			
		||||
        snapshot: deployment?.version.snapshot,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    redirect(`/workflows/${deployment.workflow.id}`);
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      message: "Successfully cloned workflow",
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user