feat: Initial port of Model Manager to new tab

This commit is contained in:
blessedcoolant 2023-06-26 23:09:16 +12:00 committed by psychedelicious
parent 9e35643911
commit 2ad5a4ea46
16 changed files with 149 additions and 131 deletions

View File

@ -1,93 +0,0 @@
import {
Flex,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
useDisclosure,
} from '@chakra-ui/react';
import { cloneElement } from 'react';
import { RootState } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import { useTranslation } from 'react-i18next';
import type { ReactElement } from 'react';
import { useListModelsQuery } from 'services/api/endpoints/models';
import CheckpointModelEdit from './CheckpointModelEdit';
import DiffusersModelEdit from './DiffusersModelEdit';
import ModelList from './ModelList';
type ModelManagerModalProps = {
children: ReactElement;
};
export default function ModelManagerModal({
children,
}: ModelManagerModalProps) {
const {
isOpen: isModelManagerModalOpen,
onOpen: onModelManagerModalOpen,
onClose: onModelManagerModalClose,
} = useDisclosure();
const { data: pipelineModels } = useListModelsQuery({
model_type: 'pipeline',
});
const openModel = useAppSelector(
(state: RootState) => state.system.openModel
);
const { t } = useTranslation();
const renderModelEditTabs = () => {
if (!openModel || !pipelineModels) return;
if (pipelineModels['entities'][openModel]['model_format'] === 'diffusers') {
return (
<DiffusersModelEdit
modelToEdit={openModel}
retrievedModel={pipelineModels['entities'][openModel]}
/>
);
} else {
return (
<CheckpointModelEdit
modelToEdit={openModel}
retrievedModel={pipelineModels['entities'][openModel]}
/>
);
}
};
return (
<>
{cloneElement(children, {
onClick: onModelManagerModalOpen,
})}
<Modal
isOpen={isModelManagerModalOpen}
onClose={onModelManagerModalClose}
size="full"
>
<ModalOverlay />
<ModalContent>
<ModalCloseButton />
<ModalHeader>{t('modelManager.modelManager')}</ModalHeader>
<ModalBody>
<Flex width="100%" columnGap={8}>
<ModelList />
{renderModelEditTabs()}
</Flex>
</ModalBody>
<ModalFooter />
</ModalContent>
</Modal>
</>
);
}

View File

@ -5,21 +5,18 @@ import StatusIndicator from './StatusIndicator';
import { Link } from '@chakra-ui/react';
import IAIIconButton from 'common/components/IAIIconButton';
import { useTranslation } from 'react-i18next';
import { FaBug, FaCube, FaDiscord, FaGithub, FaKeyboard } from 'react-icons/fa';
import { FaBug, FaDiscord, FaGithub, FaKeyboard } from 'react-icons/fa';
import { MdSettings } from 'react-icons/md';
import { useFeatureStatus } from '../hooks/useFeatureStatus';
import ColorModeButton from './ColorModeButton';
import HotkeysModal from './HotkeysModal/HotkeysModal';
import InvokeAILogoComponent from './InvokeAILogoComponent';
import LanguagePicker from './LanguagePicker';
import ModelManagerModal from './ModelManager/ModelManagerModal';
import SettingsModal from './SettingsModal/SettingsModal';
import { useFeatureStatus } from '../hooks/useFeatureStatus';
import ColorModeButton from './ColorModeButton';
const SiteHeader = () => {
const { t } = useTranslation();
const isModelManagerEnabled =
useFeatureStatus('modelManager').isFeatureEnabled;
const isLocalizationEnabled =
useFeatureStatus('localization').isFeatureEnabled;
const isBugLinkEnabled = useFeatureStatus('bugLink').isFeatureEnabled;
@ -37,20 +34,6 @@ const SiteHeader = () => {
<Spacer />
<StatusIndicator />
{isModelManagerEnabled && (
<ModelManagerModal>
<IAIIconButton
aria-label={t('modelManager.modelManager')}
tooltip={t('modelManager.modelManager')}
size="sm"
variant="link"
data-variant="link"
fontSize={20}
icon={<FaCube />}
/>
</ModelManagerModal>
)}
<HotkeysModal>
<IAIIconButton
aria-label={t('common.hotkeysLabel')}

View File

@ -1,7 +1,81 @@
import { memo } from 'react';
import { Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/react';
import i18n from 'i18n';
import { ReactNode, memo } from 'react';
import AddModelsPanel from './subpanels/AddModelsPanel';
import MergeModelsPanel from './subpanels/MergeModelsPanel';
import ModelManagerPanel from './subpanels/ModelManagerPanel';
type ModelManagerTabName = 'modelmanager' | 'add_models' | 'merge_models';
type ModelManagerTabInfo = {
id: ModelManagerTabName;
label: string;
content: ReactNode;
};
const modelManagerTabs: ModelManagerTabInfo[] = [
{
id: 'modelmanager',
label: i18n.t('modelManager.modelManager'),
content: <ModelManagerPanel />,
},
{
id: 'add_models',
label: i18n.t('modelManager.addModel'),
content: <AddModelsPanel />,
},
{
id: 'merge_models',
label: i18n.t('modelManager.mergeModels'),
content: <MergeModelsPanel />,
},
];
const ModelManagerTab = () => {
return 'Model Manager';
const renderTabsList = () => {
const modelManagerTabListsToRender: ReactNode[] = [];
modelManagerTabs.forEach((modelManagerTab) => {
modelManagerTabListsToRender.push(
<Tab key={modelManagerTab.id}>{modelManagerTab.label}</Tab>
);
});
return (
<TabList
sx={{
w: '100%',
color: 'base.200',
flexDirection: 'row',
borderBottomWidth: 2,
borderColor: 'accent.700',
}}
>
{modelManagerTabListsToRender}
</TabList>
);
};
const renderTabPanels = () => {
const modelManagerTabPanelsToRender: ReactNode[] = [];
modelManagerTabs.forEach((modelManagerTab) => {
modelManagerTabPanelsToRender.push(
<TabPanel key={modelManagerTab.id}>{modelManagerTab.content}</TabPanel>
);
});
return <TabPanels sx={{ p: 2 }}>{modelManagerTabPanelsToRender}</TabPanels>;
};
return (
<Tabs
isLazy
variant="invokeAI"
sx={{ w: 'full', h: 'full', p: 2, gap: 4, flexDirection: 'column' }}
>
{renderTabsList()}
{renderTabPanels()}
</Tabs>
);
};
export default memo(ModelManagerTab);

View File

@ -0,0 +1,10 @@
import { Flex } from '@chakra-ui/react';
import AddModel from 'features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AddModel';
export default function AddModelsPanel() {
return (
<Flex>
<AddModel />
</Flex>
);
}

View File

@ -10,13 +10,11 @@ import {
} from '@chakra-ui/react';
import IAIButton from 'common/components/IAIButton';
import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
import IAIInput from 'common/components/IAIInput';
import IAINumberInput from 'common/components/IAINumberInput';
import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
import React from 'react';
import SearchModels from './SearchModels';
// import { addNewModel } from 'app/socketio/actions';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
@ -24,12 +22,13 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { Field, Formik } from 'formik';
import { useTranslation } from 'react-i18next';
import type { InvokeModelConfigProps } from 'app/types/invokeai';
import type { RootState } from 'app/store/store';
import { setAddNewModelUIOption } from 'features/ui/store/uiSlice';
import type { FieldInputProps, FormikProps } from 'formik';
import type { InvokeModelConfigProps } from 'app/types/invokeai';
import IAIForm from 'common/components/IAIForm';
import { IAIFormItemWrapper } from 'common/components/IAIForms/IAIFormItemWrapper';
import { setAddNewModelUIOption } from 'features/ui/store/uiSlice';
import type { FieldInputProps, FormikProps } from 'formik';
import SearchModels from './SearchModels';
const MIN_MODEL_SIZE = 64;
const MAX_MODEL_SIZE = 2048;

View File

@ -0,0 +1,10 @@
import { Flex } from '@chakra-ui/react';
import MergeModels from 'features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel/MergeModels';
export default function MergeModelsPanel() {
return (
<Flex>
<MergeModels />
</Flex>
);
}

View File

@ -0,0 +1,44 @@
import { Flex } from '@chakra-ui/react';
import { RootState } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import { useListModelsQuery } from 'services/api/endpoints/models';
import CheckpointModelEdit from './ModelManagerPanel/CheckpointModelEdit';
import DiffusersModelEdit from './ModelManagerPanel/DiffusersModelEdit';
import ModelList from './ModelManagerPanel/ModelList';
export default function ModelManagerPanel() {
const { data: pipelineModels } = useListModelsQuery({
model_type: 'pipeline',
});
const openModel = useAppSelector(
(state: RootState) => state.system.openModel
);
const renderModelEditTabs = () => {
if (!openModel || !pipelineModels) return;
if (pipelineModels['entities'][openModel]['model_format'] === 'diffusers') {
return (
<DiffusersModelEdit
modelToEdit={openModel}
retrievedModel={pipelineModels['entities'][openModel]}
/>
);
} else {
return (
<CheckpointModelEdit
modelToEdit={openModel}
retrievedModel={pipelineModels['entities'][openModel]}
/>
);
}
};
return (
<Flex width="100%" columnGap={8}>
<ModelList />
{renderModelEditTabs()}
</Flex>
);
}

View File

@ -1,9 +1,7 @@
import { Box, Flex, Heading, Spacer, Spinner, Text } from '@chakra-ui/react';
import { Box, Flex, Spinner, Text } from '@chakra-ui/react';
import IAIButton from 'common/components/IAIButton';
import IAIInput from 'common/components/IAIInput';
import AddModel from './AddModel';
import MergeModels from './MergeModels';
import ModelListItem from './ModelListItem';
import { useTranslation } from 'react-i18next';
@ -185,13 +183,6 @@ const ModelList = () => {
return (
<Flex flexDirection="column" rowGap={4} width="50%" minWidth="50%">
<Flex justifyContent="space-between" alignItems="center" gap={2}>
<Heading size="md">{t('modelManager.availableModels')}</Heading>
<Spacer />
<AddModel />
<MergeModels />
</Flex>
<IAIInput
onChange={handleSearchFilter}
label={t('modelManager.search')}