diff --git a/web/bun.lockb b/web/bun.lockb index 704c778..3e3f367 100755 Binary files a/web/bun.lockb and b/web/bun.lockb differ diff --git a/web/package.json b/web/package.json index 22d78c6..262e558 100644 --- a/web/package.json +++ b/web/package.json @@ -56,6 +56,7 @@ "react-use-websocket": "^4.5.0", "shikiji": "^0.9.3", "sonner": "^1.2.4", + "swr": "^2.2.4", "tailwind-merge": "^2.1.0", "tailwindcss-animate": "^1.0.7", "uuid": "^9.0.1", diff --git a/web/src/app/workflows/[workflow_id]/page.tsx b/web/src/app/workflows/[workflow_id]/page.tsx index b026a4e..16d3218 100644 --- a/web/src/app/workflows/[workflow_id]/page.tsx +++ b/web/src/app/workflows/[workflow_id]/page.tsx @@ -8,6 +8,7 @@ import { MachineSelect, RunWorkflowButton, VersionSelect, + ViewWorkflowDetailsButton, } from "@/components/VersionSelect"; import { Card, @@ -47,6 +48,7 @@ export default async function Page({ + diff --git a/web/src/components/VersionSelect.tsx b/web/src/components/VersionSelect.tsx index 99888f7..54aa702 100644 --- a/web/src/components/VersionSelect.tsx +++ b/web/src/components/VersionSelect.tsx @@ -3,6 +3,7 @@ import { callServerPromise } from "./callServerPromise"; import { LoadingIcon } from "@/components/LoadingIcon"; import AutoForm, { AutoFormSubmit } from "@/components/ui/auto-form"; +import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, @@ -27,15 +28,25 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import type { workflowAPINodeType } from "@/db/schema"; import { getInputsFromWorkflow } from "@/lib/getInputsFromWorkflow"; import { createRun } from "@/server/createRun"; import { createDeployments } from "@/server/curdDeploments"; import type { getMachines } from "@/server/curdMachine"; import type { findFirstTableWithVersion } from "@/server/findFirstTableWithVersion"; -import { Copy, MoreVertical, Play } from "lucide-react"; +import { Copy, ExternalLink, Info, MoreVertical, Play } from "lucide-react"; import { parseAsInteger, useQueryState } from "next-usequerystate"; import { useMemo, useState } from "react"; import { toast } from "sonner"; +import useSWR from "swr"; import { z } from "zod"; export function VersionSelect({ @@ -329,3 +340,157 @@ export function getWorkflowVersionFromVersionIndex( return workflow_version; } + +export default async function fetcher( + input: RequestInfo, + init?: RequestInit +): Promise { + const res = await fetch(input, init); + return res.json(); +} + +export function ViewWorkflowDetailsButton({ + workflow, +}: { + workflow: Awaited>; +}) { + const [version] = useQueryState("version", { + defaultValue: workflow?.versions[0].version ?? 1, + ...parseAsInteger, + }); + const [isLoading, setIsLoading] = useState(false); + + const [open, setOpen] = useState(false); + + const { + data, + error, + isLoading: isNodesIndexLoading, + } = useSWR( + "https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/extension-node-map.json", + fetcher + ); + + const groupedByAuxName = useMemo(() => { + if (!data) return null; + + console.log(data); + + const workflow_version = getWorkflowVersionFromVersionIndex( + workflow, + version + ); + + const api = workflow_version?.workflow_api; + + if (!api) return null; + + const crossCheckedApi = Object.entries(api) + .map(([_, value]) => { + const classType = value.class_type; + const classTypeData = Object.entries(data).find(([_, nodeArray]) => + nodeArray[0].includes(classType) + ); + return classTypeData ? { node: value, classTypeData } : null; + }) + .filter((item) => item !== null); + + console.log(crossCheckedApi); + + const groupedByAuxName = crossCheckedApi.reduce( + (acc, data) => { + if (!data) return acc; + + const { node, classTypeData } = data; + const auxName = classTypeData[1][1].title_aux; + console.log(auxName); + if (!acc[auxName]) { + acc[auxName] = { + url: classTypeData[0], + node: [], + }; + } + acc[auxName].node.push(node); + return acc; + }, + {} as Record< + string, + { + node: z.infer[]; + url: string; + } + > + ); + + console.log(groupedByAuxName); + + return groupedByAuxName; + }, [version, data]); + + return ( + + + + + + + Workflow Details + + View your custom nodes, models, external files used in this workflow + + + +
+ + + + File + Output + + + + {groupedByAuxName && + Object.entries(groupedByAuxName).map(([key, group]) => { + // const filePath + return ( + + + + {key} + + + + + {group.node.map((x) => ( + + {x.class_type} + + ))} + + + ); + })} + +
+
+ +
+ +
+ {/* */} + {/*
{view}
*/} +
+
+ ); +} diff --git a/web/src/db/schema.ts b/web/src/db/schema.ts index d237818..f4b1dc2 100644 --- a/web/src/db/schema.ts +++ b/web/src/db/schema.ts @@ -51,12 +51,12 @@ export const workflowType = z.any(); // ), // }); -export const workflowAPIType = z.record( - z.object({ - inputs: z.record(z.any()), - class_type: z.string().optional(), - }) -); +export const workflowAPINodeType = z.object({ + inputs: z.record(z.any()), + class_type: z.string().optional(), +}); + +export const workflowAPIType = z.record(workflowAPINodeType); export const workflowVersionTable = dbSchema.table("workflow_versions", { workflow_id: uuid("workflow_id")