feat(web): add workflow inputs code template
This commit is contained in:
		
							parent
							
								
									c2d67da7db
								
							
						
					
					
						commit
						91b8c4d702
					
				@ -9,6 +9,7 @@ import {
 | 
			
		||||
} from "@/components/ui/dialog";
 | 
			
		||||
import { TableCell, TableRow } from "@/components/ui/table";
 | 
			
		||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
 | 
			
		||||
import { getInputsFromWorkflow } from "@/lib/getInputsFromWorkflow";
 | 
			
		||||
import { getRelativeTime } from "@/lib/getRelativeTime";
 | 
			
		||||
import type { findAllDeployments } from "@/server/findAllRuns";
 | 
			
		||||
import { headers } from "next/headers";
 | 
			
		||||
@ -29,28 +30,29 @@ curl --request GET \
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
const jsTemplate = `
 | 
			
		||||
fetch('<URL>', {
 | 
			
		||||
const { run_id } = await fetch('<URL>', {
 | 
			
		||||
  method: 'POST',
 | 
			
		||||
  headers: {'Content-Type': 'application/json'},
 | 
			
		||||
  headers: {
 | 
			
		||||
    'Content-Type': 'application/json',
 | 
			
		||||
    'Authorization': 'Bearer ' + process.env.COMFY_DEPLOY_API_KEY,
 | 
			
		||||
  },
 | 
			
		||||
  body: JSON.stringify({
 | 
			
		||||
    deployment_id: '<ID>',
 | 
			
		||||
    inputs: {}
 | 
			
		||||
  }),
 | 
			
		||||
})
 | 
			
		||||
  .then(response => response.json())
 | 
			
		||||
  .then(response => console.log(response))
 | 
			
		||||
  .catch(err => console.error(err));
 | 
			
		||||
}).then(response => response.json())
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
const jsTemplate_checkStatus = `
 | 
			
		||||
const run_id = '<RUN_ID>';
 | 
			
		||||
 | 
			
		||||
fetch('<URL>?run_id=' + run_id, {
 | 
			
		||||
const output = fetch('<URL>?run_id=' + run_id, {
 | 
			
		||||
  method: 'GET',
 | 
			
		||||
  headers: {'Content-Type': 'application/json'},
 | 
			
		||||
})
 | 
			
		||||
  .then(response => response.json())
 | 
			
		||||
  .then(response => console.log(response))
 | 
			
		||||
  .catch(err => console.error(err));
 | 
			
		||||
  headers: {
 | 
			
		||||
    'Content-Type': 'application/json',
 | 
			
		||||
    'Authorization': 'Bearer ' + process.env.COMFY_DEPLOY_API_KEY,
 | 
			
		||||
  },
 | 
			
		||||
}).then(response => response.json())
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
export function DeploymentDisplay({
 | 
			
		||||
@ -63,6 +65,8 @@ export function DeploymentDisplay({
 | 
			
		||||
  const protocol = headersList.get("x-forwarded-proto") || "";
 | 
			
		||||
  const domain = `${protocol}://${host}`;
 | 
			
		||||
 | 
			
		||||
  const workflowInput = getInputsFromWorkflow(deployment.version);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Dialog>
 | 
			
		||||
      <DialogTrigger asChild className="appearance-none hover:cursor-pointer">
 | 
			
		||||
@ -79,7 +83,7 @@ export function DeploymentDisplay({
 | 
			
		||||
          </TableCell>
 | 
			
		||||
        </TableRow>
 | 
			
		||||
      </DialogTrigger>
 | 
			
		||||
      <DialogContent className="max-w-xl">
 | 
			
		||||
      <DialogContent className="max-w-2xl">
 | 
			
		||||
        <DialogHeader>
 | 
			
		||||
          <DialogTitle className="capitalize">
 | 
			
		||||
            {deployment.environment} Deployment
 | 
			
		||||
@ -95,7 +99,7 @@ export function DeploymentDisplay({
 | 
			
		||||
            Trigger the workflow
 | 
			
		||||
            <CodeBlock
 | 
			
		||||
              lang="js"
 | 
			
		||||
              code={formatCode(jsTemplate, deployment, domain)}
 | 
			
		||||
              code={formatCode(jsTemplate, deployment, domain, workflowInput)}
 | 
			
		||||
            />
 | 
			
		||||
            Check the status of the run, and retrieve the outputs
 | 
			
		||||
            <CodeBlock
 | 
			
		||||
@ -122,8 +126,32 @@ export function DeploymentDisplay({
 | 
			
		||||
function formatCode(
 | 
			
		||||
  codeTemplate: string,
 | 
			
		||||
  deployment: Awaited<ReturnType<typeof findAllDeployments>>[0],
 | 
			
		||||
  domain: string
 | 
			
		||||
  domain: string,
 | 
			
		||||
  inputs?: ReturnType<typeof getInputsFromWorkflow>
 | 
			
		||||
) {
 | 
			
		||||
  if (inputs && inputs.length > 0) {
 | 
			
		||||
    codeTemplate = codeTemplate.replace(
 | 
			
		||||
      "inputs: {}",
 | 
			
		||||
      `inputs: ${JSON.stringify(
 | 
			
		||||
        Object.fromEntries(
 | 
			
		||||
          inputs.map((x) => {
 | 
			
		||||
            return [x?.input_id, ""];
 | 
			
		||||
          })
 | 
			
		||||
        ),
 | 
			
		||||
        null,
 | 
			
		||||
        2
 | 
			
		||||
      )
 | 
			
		||||
        .split("\n")
 | 
			
		||||
        .map((line, index) => (index === 0 ? line : `    ${line}`)) // Add two spaces indentation except for the first line
 | 
			
		||||
        .join("\n")}`
 | 
			
		||||
    );
 | 
			
		||||
  } else {
 | 
			
		||||
    codeTemplate = codeTemplate.replace(
 | 
			
		||||
      `
 | 
			
		||||
    inputs: {}`,
 | 
			
		||||
      ""
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
  return codeTemplate
 | 
			
		||||
    .replace("<URL>", `${domain ?? "http://localhost:3000"}/api/run`)
 | 
			
		||||
    .replace("<ID>", deployment.id);
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
"use client";
 | 
			
		||||
 | 
			
		||||
import { getInputsFromWorkflow } from "../lib/getInputsFromWorkflow";
 | 
			
		||||
import { callServerPromise } from "./callServerPromise";
 | 
			
		||||
import { customInputNodes } from "./customInputNodes";
 | 
			
		||||
import { LoadingIcon } from "@/components/LoadingIcon";
 | 
			
		||||
import { Badge } from "@/components/ui/badge";
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
@ -206,10 +208,16 @@ export function CreateDeploymentButton({
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const customInputNodes: Record<string, string> = {
 | 
			
		||||
  ComfyUIDeployExternalText: "string",
 | 
			
		||||
  ComfyUIDeployExternalImage: "string - (public image url)",
 | 
			
		||||
};
 | 
			
		||||
export function getWorkflowVersionFromVersionIndex(
 | 
			
		||||
  workflow: Awaited<ReturnType<typeof findFirstTableWithVersion>>,
 | 
			
		||||
  version: number
 | 
			
		||||
) {
 | 
			
		||||
  const workflow_version = workflow?.versions.find(
 | 
			
		||||
    (x) => x.version === version
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return workflow_version;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function VersionDetails({
 | 
			
		||||
  workflow,
 | 
			
		||||
@ -220,22 +228,23 @@ export function VersionDetails({
 | 
			
		||||
    defaultValue: workflow?.versions[0].version ?? 1,
 | 
			
		||||
    ...parseAsInteger,
 | 
			
		||||
  });
 | 
			
		||||
  const workflow_version = workflow?.versions.find(
 | 
			
		||||
    (x) => x.version === version
 | 
			
		||||
  const workflow_version = getWorkflowVersionFromVersionIndex(
 | 
			
		||||
    workflow,
 | 
			
		||||
    version
 | 
			
		||||
  );
 | 
			
		||||
  const inputs = getInputsFromWorkflow(workflow_version);
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="mt-4">
 | 
			
		||||
      Workflow Details
 | 
			
		||||
      <div className="border rounded-lg p-2">
 | 
			
		||||
        {workflow_version?.workflow_api && (
 | 
			
		||||
        {inputs && (
 | 
			
		||||
          <div className="flex flex-col gap-2">
 | 
			
		||||
            {Object.entries(workflow_version.workflow_api).map(
 | 
			
		||||
              ([key, value]) => {
 | 
			
		||||
            {inputs.map((value) => {
 | 
			
		||||
              if (!value.class_type) return <> </>;
 | 
			
		||||
              const nodeType = customInputNodes[value.class_type];
 | 
			
		||||
              if (nodeType) {
 | 
			
		||||
                  const input_id = value.inputs.input_id;
 | 
			
		||||
                  const defaultValue = value.inputs.default_value;
 | 
			
		||||
                const input_id = value.input_id;
 | 
			
		||||
                const defaultValue = value.default_value;
 | 
			
		||||
                return (
 | 
			
		||||
                  <div key={input_id}>
 | 
			
		||||
                    <Tooltip>
 | 
			
		||||
@ -244,7 +253,7 @@ export function VersionDetails({
 | 
			
		||||
                          <div>
 | 
			
		||||
                            {input_id}
 | 
			
		||||
                            {" : "}
 | 
			
		||||
                              {nodeType}
 | 
			
		||||
                            <span className="text-orange-500">{nodeType}</span>
 | 
			
		||||
                          </div>
 | 
			
		||||
                        </Badge>
 | 
			
		||||
                        {/* {nodeType}{" "} */}
 | 
			
		||||
@ -258,8 +267,7 @@ export function VersionDetails({
 | 
			
		||||
                );
 | 
			
		||||
              }
 | 
			
		||||
              return <></>;
 | 
			
		||||
              }
 | 
			
		||||
            )}
 | 
			
		||||
            })}
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								web/src/components/customInputNodes.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								web/src/components/customInputNodes.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
export const customInputNodes: Record<string, string> = {
 | 
			
		||||
  ComfyUIDeployExternalText: "string",
 | 
			
		||||
  ComfyUIDeployExternalImage: "string - (public image url)",
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										24
									
								
								web/src/lib/getInputsFromWorkflow.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								web/src/lib/getInputsFromWorkflow.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
import type { getWorkflowVersionFromVersionIndex } from "../components/VersionSelect";
 | 
			
		||||
import { customInputNodes } from "@/components/customInputNodes";
 | 
			
		||||
 | 
			
		||||
export function getInputsFromWorkflow(
 | 
			
		||||
  workflow_version: ReturnType<typeof getWorkflowVersionFromVersionIndex>
 | 
			
		||||
) {
 | 
			
		||||
  if (!workflow_version || !workflow_version.workflow_api) return null;
 | 
			
		||||
  return Object.entries(workflow_version.workflow_api)
 | 
			
		||||
    .map(([_, value]) => {
 | 
			
		||||
      if (!value.class_type) return undefined;
 | 
			
		||||
      const nodeType = customInputNodes[value.class_type];
 | 
			
		||||
      if (nodeType) {
 | 
			
		||||
        const input_id = value.inputs.input_id as string;
 | 
			
		||||
        const default_value = value.inputs.default_value as string;
 | 
			
		||||
        return {
 | 
			
		||||
          class_type: value.class_type,
 | 
			
		||||
          input_id,
 | 
			
		||||
          default_value,
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
      return undefined;
 | 
			
		||||
    })
 | 
			
		||||
    .filter((item) => item !== undefined);
 | 
			
		||||
}
 | 
			
		||||
@ -8,7 +8,7 @@ export async function findAllRuns(workflow_id: string) {
 | 
			
		||||
    orderBy: desc(workflowRunsTable.created_at),
 | 
			
		||||
    limit: 10,
 | 
			
		||||
    extras: {
 | 
			
		||||
      "number": sql<number>`row_number() over (order by created_at)`.as("number"),
 | 
			
		||||
      number: sql<number>`row_number() over (order by created_at)`.as("number"),
 | 
			
		||||
    },
 | 
			
		||||
    with: {
 | 
			
		||||
      machine: {
 | 
			
		||||
@ -36,11 +36,7 @@ export async function findAllDeployments(workflow_id: string) {
 | 
			
		||||
          name: true,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      version: {
 | 
			
		||||
        columns: {
 | 
			
		||||
      version: true,
 | 
			
		||||
    },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user