From 99407c899fff64501d4391337de33009276fda15 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Tue, 5 Mar 2024 19:04:13 +1100 Subject: [PATCH] feat(ui): update UI to use new model config backend - Update all queries - Remove Advanced Add - Removed un-editable, internal-only model attributes from model edit UI (e.g. format, repo variant, model type) - Update model tags so the list refreshes when a model installs - Rename some queries, components, variables, types to match backend - Fix divide-by-zero in install queue --- .../listeners/setDefaultSettings.ts | 6 +- .../listeners/socketio/socketModelInstall.ts | 8 +- .../AddModelPanel/AdvancedImport.tsx | 228 -- ...{SimpleImport.tsx => InstallModelForm.tsx} | 2 +- .../ModelInstallQueue.tsx} | 25 +- .../ModelInstallQueueBadge.tsx} | 13 +- .../ModelInstallQueueItem.tsx} | 59 +- .../ScanFolderForm.tsx} | 14 +- .../ScanFolderResultItem.tsx} | 0 .../ScanFolderResults.tsx} | 2 +- .../{ImportModels.tsx => InstallModels.tsx} | 17 +- .../ModelManagerPanel/ModelTypeFilter.tsx | 2 +- .../modelManagerV2/subpanels/ModelPane.tsx | 4 +- .../subpanels/ModelPanel/DefaultSettings.tsx | 4 +- .../DefaultSettings/DefaultSettingsForm.tsx | 8 +- .../ModelPanel/Fields/BaseModelSelect.tsx | 12 +- .../ModelPanel/Fields/BooleanSelect.tsx | 27 - .../ModelPanel/Fields/ModelFormatSelect.tsx | 47 - .../ModelPanel/Fields/ModelTypeSelect.tsx | 32 - .../ModelPanel/Fields/ModelVariantSelect.tsx | 12 +- .../Fields/PredictionTypeSelect.tsx | 12 +- .../ModelPanel/Fields/RepoVariantSelect.tsx | 27 - .../ModelPanel/Metadata/ModelMetadata.tsx | 6 +- .../subpanels/ModelPanel/ModelConvert.tsx | 4 +- .../subpanels/ModelPanel/ModelEdit.tsx | 165 +- .../subpanels/ModelPanel/ModelView.tsx | 33 +- .../web/src/services/api/endpoints/models.ts | 179 +- .../frontend/web/src/services/api/index.ts | 2 +- .../frontend/web/src/services/api/schema.ts | 1858 +++++++---------- .../frontend/web/src/services/api/types.ts | 9 +- 30 files changed, 993 insertions(+), 1824 deletions(-) delete mode 100644 invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/AdvancedImport.tsx rename invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/{SimpleImport.tsx => InstallModelForm.tsx} (98%) rename invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/{ImportQueue/ImportQueue.tsx => ModelInstallQueue/ModelInstallQueue.tsx} (67%) rename invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/{ImportQueue/ImportQueueBadge.tsx => ModelInstallQueue/ModelInstallQueueBadge.tsx} (76%) rename invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/{ImportQueue/ImportQueueItem.tsx => ModelInstallQueue/ModelInstallQueueItem.tsx} (60%) rename invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/{ScanModels/ScanModelsForm.tsx => ScanFolder/ScanFolderForm.tsx} (76%) rename invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/{ScanModels/ScanModelResultItem.tsx => ScanFolder/ScanFolderResultItem.tsx} (100%) rename invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/{ScanModels/ScanModelsResults.tsx => ScanFolder/ScanFolderResults.tsx} (98%) rename invokeai/frontend/web/src/features/modelManagerV2/subpanels/{ImportModels.tsx => InstallModels.tsx} (66%) delete mode 100644 invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/Fields/BooleanSelect.tsx delete mode 100644 invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/Fields/ModelFormatSelect.tsx delete mode 100644 invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/Fields/ModelTypeSelect.tsx delete mode 100644 invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/Fields/RepoVariantSelect.tsx diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts index cd4c574be4..da7cf6b6fe 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts @@ -34,13 +34,13 @@ export const addSetDefaultSettingsListener = (startAppListening: AppStartListeni return; } - const metadata = await dispatch(modelsApi.endpoints.getModelMetadata.initiate(currentModel.key)).unwrap(); + const modelConfig = await dispatch(modelsApi.endpoints.getModelConfig.initiate(currentModel.key)).unwrap(); - if (!metadata || !metadata.default_settings) { + if (!modelConfig || !modelConfig.default_settings) { return; } - const { vae, vae_precision, cfg_scale, cfg_rescale_multiplier, steps, scheduler } = metadata.default_settings; + const { vae, vae_precision, cfg_scale, cfg_rescale_multiplier, steps, scheduler } = modelConfig.default_settings; if (vae) { // we store this as "default" within default settings diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelInstall.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelInstall.ts index 9faedc64d7..59c88bf2a8 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelInstall.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelInstall.ts @@ -14,7 +14,7 @@ export const addModelInstallEventListener = (startAppListening: AppStartListenin const { bytes, total_bytes, id } = action.payload.data; dispatch( - modelsApi.util.updateQueryData('getModelImports', undefined, (draft) => { + modelsApi.util.updateQueryData('listModelInstalls', undefined, (draft) => { const modelImport = draft.find((m) => m.id === id); if (modelImport) { modelImport.bytes = bytes; @@ -33,7 +33,7 @@ export const addModelInstallEventListener = (startAppListening: AppStartListenin const { id } = action.payload.data; dispatch( - modelsApi.util.updateQueryData('getModelImports', undefined, (draft) => { + modelsApi.util.updateQueryData('listModelInstalls', undefined, (draft) => { const modelImport = draft.find((m) => m.id === id); if (modelImport) { modelImport.status = 'completed'; @@ -41,7 +41,7 @@ export const addModelInstallEventListener = (startAppListening: AppStartListenin return draft; }) ); - dispatch(api.util.invalidateTags([{ type: 'ModelConfig' }])); + dispatch(api.util.invalidateTags(['Model'])); }, }); @@ -51,7 +51,7 @@ export const addModelInstallEventListener = (startAppListening: AppStartListenin const { id, error, error_type } = action.payload.data; dispatch( - modelsApi.util.updateQueryData('getModelImports', undefined, (draft) => { + modelsApi.util.updateQueryData('listModelInstalls', undefined, (draft) => { const modelImport = draft.find((m) => m.id === id); if (modelImport) { modelImport.status = 'error'; diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/AdvancedImport.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/AdvancedImport.tsx deleted file mode 100644 index 56abf7b09a..0000000000 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/AddModelPanel/AdvancedImport.tsx +++ /dev/null @@ -1,228 +0,0 @@ -import { Button, Flex, FormControl, FormErrorMessage, FormLabel, Input, Text, Textarea } from '@invoke-ai/ui-library'; -import { useAppDispatch } from 'app/store/storeHooks'; -import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent'; -import BaseModelSelect from 'features/modelManagerV2/subpanels/ModelPanel/Fields/BaseModelSelect'; -import BooleanSelect from 'features/modelManagerV2/subpanels/ModelPanel/Fields/BooleanSelect'; -import ModelFormatSelect from 'features/modelManagerV2/subpanels/ModelPanel/Fields/ModelFormatSelect'; -import ModelTypeSelect from 'features/modelManagerV2/subpanels/ModelPanel/Fields/ModelTypeSelect'; -import ModelVariantSelect from 'features/modelManagerV2/subpanels/ModelPanel/Fields/ModelVariantSelect'; -import PredictionTypeSelect from 'features/modelManagerV2/subpanels/ModelPanel/Fields/PredictionTypeSelect'; -import RepoVariantSelect from 'features/modelManagerV2/subpanels/ModelPanel/Fields/RepoVariantSelect'; -import { addToast } from 'features/system/store/systemSlice'; -import { makeToast } from 'features/system/util/makeToast'; -import { isNil, omitBy } from 'lodash-es'; -import { useCallback, useEffect } from 'react'; -import type { SubmitHandler } from 'react-hook-form'; -import { useForm } from 'react-hook-form'; -import { useTranslation } from 'react-i18next'; -import { useInstallModelMutation } from 'services/api/endpoints/models'; -import type { AnyModelConfig } from 'services/api/types'; - -export const AdvancedImport = () => { - const dispatch = useAppDispatch(); - - const [installModel] = useInstallModelMutation(); - - const { t } = useTranslation(); - - const { - register, - handleSubmit, - control, - formState: { errors }, - setValue, - resetField, - reset, - watch, - } = useForm({ - defaultValues: { - name: '', - base: 'sd-1', - type: 'main', - path: '', - description: '', - format: 'diffusers', - vae: '', - variant: 'normal', - }, - mode: 'onChange', - }); - - const onSubmit = useCallback>( - (values) => { - installModel({ - source: values.path, - config: omitBy(values, isNil), - }) - .unwrap() - .then((_) => { - dispatch( - addToast( - makeToast({ - title: t('modelManager.modelAdded', { - modelName: values.name, - }), - status: 'success', - }) - ) - ); - reset(); - }) - .catch((error) => { - if (error) { - dispatch( - addToast( - makeToast({ - title: t('toast.modelAddFailed'), - status: 'error', - }) - ) - ); - } - }); - }, - [installModel, dispatch, t, reset] - ); - - const watchedModelType = watch('type'); - const watchedModelFormat = watch('format'); - - useEffect(() => { - if (watchedModelType === 'main') { - setValue('format', 'diffusers'); - setValue('repo_variant', ''); - setValue('variant', 'normal'); - } - if (watchedModelType === 'lora') { - setValue('format', 'lycoris'); - } else if (watchedModelType === 'embedding') { - setValue('format', 'embedding_file'); - } else if (watchedModelType === 'ip_adapter') { - setValue('format', 'invokeai'); - } else { - setValue('format', 'diffusers'); - } - resetField('upcast_attention'); - resetField('ztsnr_training'); - resetField('vae'); - resetField('config'); - resetField('prediction_type'); - resetField('image_encoder_model_id'); - }, [watchedModelType, resetField, setValue]); - - return ( - -
- - - - {t('modelManager.modelType')} - control={control} name="type" /> - - - {t('modelManager.advancedImportInfo')} - - - - - - - {t('modelManager.name')} - value.trim().length >= 3 || 'Must be at least 3 characters', - })} - /> - {errors.name?.message && {errors.name?.message}} - - - - - - {t('modelManager.description')} -