diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelEdit.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelEdit.tsx index 70d0596cd8..4528733c4f 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelEdit.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelEdit.tsx @@ -1,6 +1,6 @@ import { skipToken } from '@reduxjs/toolkit/query'; import { useAppDispatch, useAppSelector } from '../../../../app/store/storeHooks'; -import { useGetModelQuery } from '../../../../services/api/endpoints/models'; +import { useGetModelQuery, useUpdateModelsMutation } from '../../../../services/api/endpoints/models'; import { Flex, Text, Heading, Button, Input, FormControl, FormLabel, Textarea } from '@invoke-ai/ui-library'; import { useCallback, useMemo } from 'react'; import { @@ -16,19 +16,26 @@ import { } from '../../../../services/api/types'; import { setSelectedModelMode } from '../../store/modelManagerV2Slice'; import BaseModelSelect from './Fields/BaseModelSelect'; -import { useForm } from 'react-hook-form'; +import { SubmitHandler, useForm } from 'react-hook-form'; import ModelTypeSelect from './Fields/ModelTypeSelect'; import ModelVariantSelect from './Fields/ModelVariantSelect'; import RepoVariantSelect from './Fields/RepoVariantSelect'; import PredictionTypeSelect from './Fields/PredictionTypeSelect'; import BooleanSelect from './Fields/BooleanSelect'; import ModelFormatSelect from './Fields/ModelFormatSelect'; +import { useTranslation } from 'react-i18next'; +import { addToast } from '../../../system/store/systemSlice'; +import { makeToast } from '../../../system/util/makeToast'; export const ModelEdit = () => { const dispatch = useAppDispatch(); const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey); const { data, isLoading } = useGetModelQuery(selectedModelKey ?? skipToken); + const [updateModel, { isLoading: isSubmitting }] = useUpdateModelsMutation(); + + const { t } = useTranslation(); + const modelData = useMemo(() => { if (!data) { return null; @@ -75,6 +82,46 @@ export const ModelEdit = () => { mode: 'onChange', }); + const onSubmit = useCallback>( + (values) => { + if (!modelData?.key) { + return; + } + + const responseBody = { + key: modelData.key, + body: values, + }; + + updateModel(responseBody) + .unwrap() + .then((payload) => { + reset(payload as AnyModelConfig, { keepDefaultValues: true }); + dispatch(setSelectedModelMode('view')); + dispatch( + addToast( + makeToast({ + title: t('modelManager.modelUpdated'), + status: 'success', + }) + ) + ); + }) + .catch((_) => { + reset(); + dispatch( + addToast( + makeToast({ + title: t('modelManager.modelUpdateFailed'), + status: 'error', + }) + ) + ); + }); + }, + [dispatch, modelData?.key, reset, t, updateModel] + ); + const handleClickCancel = useCallback(() => { dispatch(setSelectedModelMode('view')); }, [dispatch]); @@ -88,109 +135,111 @@ export const ModelEdit = () => { } return ( - - value.trim().length > 3 || 'Must be at least 3 characters', - })} - size="lg" - /> - - - +
+ + value.trim().length > 3 || 'Must be at least 3 characters', + })} + size="lg" + /> + + + + - - - - - Description -