diff --git a/web/bun.lockb b/web/bun.lockb index c4349f9..ce68861 100755 Binary files a/web/bun.lockb and b/web/bun.lockb differ diff --git a/web/package.json b/web/package.json index e2a0046..81e9548 100644 --- a/web/package.json +++ b/web/package.json @@ -47,6 +47,7 @@ "@sindresorhus/slugify": "^2.2.1", "@tailwindcss/typography": "^0.5.10", "@tanstack/react-table": "^8.10.7", + "@tanstack/react-virtual": "beta", "@types/jsonwebtoken": "^9.0.5", "@types/react-highlight-words": "^0.16.7", "@types/swagger-ui-react": "^4.18.3", diff --git a/web/src/components/InsertModal.tsx b/web/src/components/InsertModal.tsx index 209433c..f9385b2 100644 --- a/web/src/components/InsertModal.tsx +++ b/web/src/components/InsertModal.tsx @@ -17,6 +17,7 @@ import { TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; +import { cn } from "@/lib/utils"; import * as React from "react"; import { useState } from "react"; import type { UnknownKeysParam, ZodObject, ZodRawShape, z } from "zod"; @@ -30,6 +31,7 @@ export function InsertModal< disabled?: boolean; title: string; description: string; + dialogClassName?: string; serverAction: (data: z.infer) => Promise; formSchema: Z; fieldConfig?: FieldConfig>; @@ -70,7 +72,7 @@ export function InsertModal< )} {/* */} - + {props.title} {props.description} @@ -108,6 +110,7 @@ export function UpdateModal< setOpen: (open: boolean) => void; title: string; description: string; + dialogClassName?: string; data: z.infer; serverAction: ( data: z.infer & { @@ -130,7 +133,7 @@ export function UpdateModal< {/* {props.title} */} - + {props.title} {props.description} diff --git a/web/src/components/MachineList.tsx b/web/src/components/MachineList.tsx index c9fc68e..d513185 100644 --- a/web/src/components/MachineList.tsx +++ b/web/src/components/MachineList.tsx @@ -214,6 +214,7 @@ export const columns: ColumnDef[] = [ {machine.type === "comfy-deploy-serverless" ? (
machine.type === "comfy-deploy-serverless" )} diff --git a/web/src/components/VersionSelect.tsx b/web/src/components/VersionSelect.tsx index 3ba2dd9..860ac99 100644 --- a/web/src/components/VersionSelect.tsx +++ b/web/src/components/VersionSelect.tsx @@ -1,6 +1,7 @@ "use client"; import { callServerPromise } from "./callServerPromise"; +import fetcher from "./fetcher"; import { LoadingIcon } from "@/components/LoadingIcon"; import AutoForm, { AutoFormSubmit } from "@/components/ui/auto-form"; import { Badge } from "@/components/ui/badge"; @@ -361,14 +362,6 @@ 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, }: { diff --git a/web/src/components/custom-form/ModelPickerView.tsx b/web/src/components/custom-form/ModelPickerView.tsx index 5c1abe8..79d22aa 100644 --- a/web/src/components/custom-form/ModelPickerView.tsx +++ b/web/src/components/custom-form/ModelPickerView.tsx @@ -112,7 +112,7 @@ export function ModelPickerView({ - + No framework found. @@ -144,7 +144,7 @@ export function ModelPickerView({ {field.value && ( - +
               {JSON.stringify(field.value, null, 2)}
diff --git a/web/src/components/custom-form/SnapshotPickerView.tsx b/web/src/components/custom-form/SnapshotPickerView.tsx
index 675393c..31bf534 100644
--- a/web/src/components/custom-form/SnapshotPickerView.tsx
+++ b/web/src/components/custom-form/SnapshotPickerView.tsx
@@ -1,6 +1,7 @@
 "use client";
 
 import type { AutoFormInputComponentProps } from "../ui/auto-form/types";
+import fetcher from "@/components/fetcher";
 import { Button } from "@/components/ui/button";
 import {
   Command,
@@ -8,6 +9,7 @@ import {
   CommandGroup,
   CommandInput,
   CommandItem,
+  CommandList,
 } from "@/components/ui/command";
 import {
   Popover,
@@ -19,9 +21,30 @@ import { cn } from "@/lib/utils";
 import { findAllDeployments } from "@/server/curdDeploments";
 import { Check, ChevronsUpDown } from "lucide-react";
 import * as React from "react";
+import useSWR from "swr";
 
 export function SnapshotPickerView({
   field,
+}: Pick) {
+  return (
+    
+ + + {field.value && ( + +
+
+              {JSON.stringify(field.value, null, 2)}
+            
+
+
+ )} +
+ ); +} + +function SnapshotPresetPicker({ + field, }: Pick) { const [open, setOpen] = React.useState(false); const [selected, setSelected] = React.useState(null); @@ -59,67 +82,168 @@ export function SnapshotPickerView({ }, []); function findItem(value: string) { - // console.log(frameworks); - return frameworks?.find((item) => item.id === value); } return ( -
- - - - - - - - No framework found. - - {frameworks?.map((framework) => ( - { - setSelected(currentValue); - const json = - frameworks?.find((item) => item.id === currentValue) - ?.value ?? null; - field.onChange(json ? JSON.parse(json) : null); - setOpen(false); - }} - > - {framework.label} - - - ))} - - - - - {field.value && ( - -
-
-              {JSON.stringify(field.value, null, 2)}
-            
-
-
- )} -
+ + + + + + + + No framework found. + + {frameworks?.map((framework) => ( + { + setSelected(currentValue); + const json = + frameworks?.find((item) => item.id === currentValue) + ?.value ?? null; + field.onChange(json ? JSON.parse(json) : null); + setOpen(false); + }} + > + {framework.label} + + + ))} + + + + + ); +} + +type CustomNodeList = { + custom_nodes: { + author: string; + title: string; + reference: string; + files: string[]; + install_type: string; + description: string; + }[]; +}; + +function CustomNodesSelector({ + field, +}: Pick) { + const [open, setOpen] = React.useState(false); + + const customNodeList = + field.value.git_custom_nodes ?? + ({} as Record< + string, + { + hash: string; + disabled: boolean; + } + >); + + const { data, error, isLoading } = useSWR( + "https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json", + fetcher + ); + + const keys = React.useMemo( + () => Object.keys(customNodeList), + [customNodeList, data] + ); + + function findItem(value: string) { + // console.log(keys, value.toLowerCase()); + const included = keys.includes(value.toLowerCase()); + return included; + } + + return ( + + + + + + + + No custom nodes found. + + + {data && + data.custom_nodes?.map((framework, index) => ( + { + let nodeList: Record< + string, + { + hash: string; + disabled: boolean; + } + >; + const x = customNodeList; + + if (x[currentValue]) { + const newNodeList = { ...x }; + delete newNodeList[currentValue]; + nodeList = newNodeList; + } else { + nodeList = { + [currentValue]: { + hash: "latest", + disabled: false, + }, + ...x, + }; + } + field.onChange({ + ...field.value, + git_custom_nodes: nodeList, + }); + }} + > + {framework.title} + + + ))} + + + + + ); } diff --git a/web/src/components/fetcher.tsx b/web/src/components/fetcher.tsx new file mode 100644 index 0000000..a0e4a0b --- /dev/null +++ b/web/src/components/fetcher.tsx @@ -0,0 +1,9 @@ +"use client"; + +export default async function fetcher( + input: RequestInfo, + init?: RequestInit +): Promise { + const res = await fetch(input, init); + return res.json(); +}