diff --git a/web/apps/web/src/components/app/export-dialog/index.tsx b/web/apps/web/src/components/app/export-dialog/index.tsx index 2add1a91..7e360177 100644 --- a/web/apps/web/src/components/app/export-dialog/index.tsx +++ b/web/apps/web/src/components/app/export-dialog/index.tsx @@ -198,7 +198,7 @@ export const ExportDialog = ({ id, name, children }: ExportDialogProps) => { {key.toLocaleUpperCase()} -
+
{Object.values(item).map(v => ( {v as string} diff --git a/web/apps/web/src/components/workflow/import-modal/index.tsx b/web/apps/web/src/components/workflow/import-modal/index.tsx index 519eae8d..80bd9290 100644 --- a/web/apps/web/src/components/workflow/import-modal/index.tsx +++ b/web/apps/web/src/components/workflow/import-modal/index.tsx @@ -9,25 +9,46 @@ import { DialogTitle, Separator, Heading, + AlertDialog, + AlertDialogContent, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogPortal, + Text, } from '@shellagent/ui'; -import { useRequest } from 'ahooks'; +import { useBoolean, useRequest } from 'ahooks'; import { useState, useEffect } from 'react'; import { toast } from 'react-toastify'; +import { ChevronDownIcon } from '@heroicons/react/16/solid'; +import { + ExclamationTriangleIcon, + XMarkIcon, +} from '@heroicons/react/24/outline'; import FileUploader from '@/components/common/uploader'; import { APIFetch } from '@/services/base'; import { importFormComfyUI } from '@/services/workflow'; import { useWorkflowStore } from '@/stores/workflow/workflow-provider'; +import { cn } from '@/utils/cn'; +import { isEmpty } from 'lodash-es'; const ImportModal: React.FC<{ open: boolean; onOpenChange: (open: boolean) => void; }> = ({ open, onOpenChange }) => { + const [openTips, setOpenTips] = useBoolean(false); + const [isExpand, isExpandAction] = useBoolean(false); const [fileUrl, setFileUrl] = useState(); const [workflow, setWorkflow] = useState(); - const { importWorkflow } = useWorkflowStore(state => ({ - importWorkflow: state.importWorkflow, - })); + const { existedInfo, importWorkflow, setExistedInfo } = useWorkflowStore( + state => ({ + existedInfo: state.existedInfo, + setExistedInfo: state.setExistedInfo, + importWorkflow: state.importWorkflow, + }), + ); useEffect(() => { if (fileUrl) { @@ -58,6 +79,18 @@ const ImportModal: React.FC<{ workflow: result.data, comfyui: request?.[0]?.data, }); + setExistedInfo({ + undefined_widgets: result.undefined_widgets, + non_existed_models: result.non_existed_models, + }); + if ( + !isEmpty(result.undefined_widgets) || + !isEmpty(result.non_existed_models) + ) { + setTimeout(() => { + setOpenTips.setTrue(); + }, 1000); + } toast.success(`Import Success!`, { position: 'top-center', autoClose: 1000, @@ -108,45 +141,141 @@ const ImportModal: React.FC<{ } }; + const onCloseTips = () => { + setOpenTips.setFalse(); + }; + return ( - - onOpenChange(false)} autoFocus={false}> - - - Import from ComfyUI - - - - - - - - - - - - - + <> + + onOpenChange(false)} autoFocus={false}> + + + Import from ComfyUI + + + + + + + + + + + + + + + + + + +
+ + + +
+ +
+
+
+
+ + Warning + + The following items are missing. +
+ Replace it with installed models/widgets, or contact us to add + it to the standard environment. +
+
isExpandAction.toggle()}> + + {isExpand ? 'Show Less' : 'View Detail'} + + +
+
+ {!isEmpty(existedInfo.non_existed_models) ? ( +
+ + Models + +
+ {existedInfo.non_existed_models?.map(v => ( + + {v as string} + + ))} +
+
+ ) : null} + {!isEmpty(existedInfo.undefined_widgets) ? ( +
+ {!isEmpty(existedInfo.non_existed_models) ? ( + + ) : null} + + Widgets + +
+ {existedInfo.undefined_widgets?.map(v => ( + + {v as string} + + ))} +
+
+ ) : null} +
+
+ + + +
+
+
+ ); }; diff --git a/web/apps/web/src/services/workflow/type.ts b/web/apps/web/src/services/workflow/type.ts index a853ef20..d94b7d9a 100644 --- a/web/apps/web/src/services/workflow/type.ts +++ b/web/apps/web/src/services/workflow/type.ts @@ -142,9 +142,14 @@ export type ComfyUIRequest = { data: object; }; +export type ExistedInfo = { + undefined_widgets?: Array; + non_existed_models?: Array; +} + export type ComfyuiResponse = { success?: boolean; data?: Workflow; error_message?: string; error_message_detail?: string; -}; +} & ExistedInfo; diff --git a/web/apps/web/src/stores/workflow/workflow-store.tsx b/web/apps/web/src/stores/workflow/workflow-store.tsx index 0e170bd5..acadba80 100644 --- a/web/apps/web/src/stores/workflow/workflow-store.tsx +++ b/web/apps/web/src/stores/workflow/workflow-store.tsx @@ -29,6 +29,7 @@ import { GetWidgetListResponse, RunWorkflowResponse, EventStatusEnum, + ExistedInfo, } from '@/services/workflow/type'; import { genNodeData, @@ -64,6 +65,7 @@ export type WorkflowState = { }; resetData: Record; reloadSchemaMap: Record; + existedInfo: ExistedInfo; }; export type WorkflowAction = { @@ -81,6 +83,7 @@ export type WorkflowAction = { setNodeData: (params: { id: NodeId; data: TValues }) => void; setFlowInstance: (instance: ReactFlowInstance) => void; getWidgetList: (params: GetWidgetListRequest) => void; + setExistedInfo: (params: ExistedInfo) => void; getWidgetSchema: ( params: GetWidgetSchemaRequest & { id?: string }, reload?: boolean, @@ -134,6 +137,7 @@ export const initState: WorkflowState = { resetData: {}, // reload reloadSchemaMap: {}, + existedInfo: {}, }; export const createWorkflowStore = () => { @@ -526,6 +530,13 @@ export const createWorkflowStore = () => { }), ); }, + setExistedInfo(params) { + set( + produce(state => { + state.existedInfo = params; + }), + ); + }, })), ); };