diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index a458563fd5..406df71e06 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -701,6 +701,7 @@ "availableModels": "Available Models", "baseModel": "Base Model", "cached": "cached", + "cancel": "Cancel", "cannotUseSpaces": "Cannot Use Spaces", "checkpointFolder": "Checkpoint Folder", "checkpointModels": "Checkpoints", @@ -743,6 +744,7 @@ "heightValidationMsg": "Default height of your model.", "ignoreMismatch": "Ignore Mismatches Between Selected Models", "importModels": "Import Models", + "importQueue": "Import Queue", "inpainting": "v1 Inpainting", "interpolationType": "Interpolation Type", "inverseSigmoid": "Inverse Sigmoid", @@ -796,6 +798,7 @@ "pickModelType": "Pick Model Type", "predictionType": "Prediction Type (for Stable Diffusion 2.x Models and occasional Stable Diffusion 1.x Models)", "quickAdd": "Quick Add", + "removeFromQueue": "Remove From Queue", "repo_id": "Repo ID", "repoIDValidationMsg": "Online repository of your model", "safetensorModels": "SafeTensors", diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ImportModels.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ImportModels.tsx index 2325fcf7dc..14ed0c6848 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ImportModels.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ImportModels.tsx @@ -1,10 +1,85 @@ -import { Box } from '@invoke-ai/ui-library'; +import { Button, Box, Flex, FormControl, FormLabel, Heading, Input, Text, Divider } from '@invoke-ai/ui-library'; +import { t } from 'i18next'; +import { CSSProperties } from 'react'; +import { useImportMainModelsMutation } from '../../../services/api/endpoints/models'; +import { useForm } from '@mantine/form'; +import { useAppDispatch } from 'app/store/storeHooks'; +import { addToast } from 'features/system/store/systemSlice'; +import { makeToast } from 'features/system/util/makeToast'; +import { ImportQueue } from './ImportQueue'; + +const formStyles: CSSProperties = { + width: '100%', +}; + +type ExtendedImportModelConfig = { + location: string; +}; -//jenn's workspace export const ImportModels = () => { + const dispatch = useAppDispatch(); + + const [importMainModel, { isLoading }] = useImportMainModelsMutation(); + + const addModelForm = useForm({ + initialValues: { + location: '', + }, + }); + + console.log('addModelForm', addModelForm.values.location) + + const handleAddModelSubmit = (values: ExtendedImportModelConfig) => { + importMainModel({ source: values.location, config: undefined }) + .unwrap() + .then((_) => { + dispatch( + addToast( + makeToast({ + title: t('toast.modelAddedSimple'), + status: 'success', + }) + ) + ); + addModelForm.reset(); + }) + .catch((error) => { + if (error) { + dispatch( + addToast( + makeToast({ + title: `${error.data.detail} `, + status: 'error', + }) + ) + ); + } + }); + }; + return ( - - Import Models + + + Add Model + + +
handleAddModelSubmit(v))} style={formStyles}> + + + + {t('modelManager.modelLocation')} + + + + + +
+ + {t('modelManager.importQueue')} + +
); }; diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ImportQueue.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ImportQueue.tsx new file mode 100644 index 0000000000..4a0407ff1a --- /dev/null +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ImportQueue.tsx @@ -0,0 +1,85 @@ +import { + Button, + Box, + Flex, + FormControl, + FormLabel, + Heading, + IconButton, + Input, + InputGroup, + InputRightElement, + Progress, + Text, +} from '@invoke-ai/ui-library'; +import { t } from 'i18next'; +import { useMemo } from 'react'; +import { useGetModelImportsQuery } from '../../../services/api/endpoints/models'; +import { useAppDispatch } from 'app/store/storeHooks'; +import { addToast } from 'features/system/store/systemSlice'; +import { makeToast } from 'features/system/util/makeToast'; +import { PiXBold } from 'react-icons/pi'; + +export const ImportQueue = () => { + const dispatch = useAppDispatch(); + + // start with this data then pull from sockets (idk how to do that yet, also might not even use this and just use socket) + const { data } = useGetModelImportsQuery(); + + const progressValues = useMemo(() => { + if (!data) { + return []; + } + const values = []; + for (let i = 0; i < data.length; i++) { + let value; + if (data[i] && data[i]?.bytes && data[i]?.total_bytes) { + value = (data[i]?.bytes / data[i]?.total_bytes) * 100; + } + values.push(value || undefined); + } + return values; + }, [data]); + + return ( + + + {data?.map((model, i) => ( + + + {model.source.repo_id} + + + {model.status} + {model.status === 'completed' ? ( + } + // onClick={handleRemove} + /> + ) : ( + } + // onClick={handleCancel} + colorScheme="error" + /> + )} + + ))} + + + ); +};