mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
basic scan working and renders results
This commit is contained in:
parent
a022aaf258
commit
5b66baa3ec
@ -7,7 +7,7 @@ import { useCallback, useMemo } from 'react';
|
|||||||
import { RiSparklingFill } from 'react-icons/ri';
|
import { RiSparklingFill } from 'react-icons/ri';
|
||||||
import { useGetModelImportsQuery, usePruneModelImportsMutation } from 'services/api/endpoints/models';
|
import { useGetModelImportsQuery, usePruneModelImportsMutation } from 'services/api/endpoints/models';
|
||||||
|
|
||||||
import { ImportQueueModel } from '../ImportQueueModel';
|
import { ImportQueueModel } from './ImportQueueModel';
|
||||||
|
|
||||||
export const ImportQueue = () => {
|
export const ImportQueue = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
import { ScanModelsForm } from './ScanModelsForm';
|
||||||
|
|
||||||
|
export const ScanModels = () => {
|
||||||
|
return <ScanModelsForm />;
|
||||||
|
};
|
@ -0,0 +1,54 @@
|
|||||||
|
import { Flex, FormControl, FormLabel, Input, Button, FormErrorMessage, Divider } from '@invoke-ai/ui-library';
|
||||||
|
import { ChangeEventHandler, useCallback, useState } from 'react';
|
||||||
|
import { useLazyScanModelsQuery } from '../../../../../services/api/endpoints/models';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { ScanModelsResults } from './ScanModelsResults';
|
||||||
|
|
||||||
|
export const ScanModelsForm = () => {
|
||||||
|
const [scanPath, setScanPath] = useState('');
|
||||||
|
const [errorMessage, setErrorMessage] = useState('');
|
||||||
|
const [results, setResults] = useState<string[] | undefined>();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const [_scanModels, { isLoading }] = useLazyScanModelsQuery();
|
||||||
|
|
||||||
|
const handleSubmitScan = useCallback(async () => {
|
||||||
|
_scanModels({ scan_path: scanPath })
|
||||||
|
.unwrap()
|
||||||
|
.then((result) => {
|
||||||
|
setResults(result);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (error) {
|
||||||
|
setErrorMessage(error.data.detail);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [scanPath]);
|
||||||
|
|
||||||
|
const handleSetScanPath: ChangeEventHandler<HTMLInputElement> = useCallback((e) => {
|
||||||
|
setScanPath(e.target.value);
|
||||||
|
setErrorMessage('');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormControl isInvalid={!!errorMessage.length} w="full">
|
||||||
|
<Flex flexDir="column" w="full">
|
||||||
|
<Flex gap={2} alignItems="flex-end" justifyContent="space-between">
|
||||||
|
<Flex direction="column" w="full">
|
||||||
|
<FormLabel>{t('common.folder')}</FormLabel>
|
||||||
|
<Input value={scanPath} onChange={handleSetScanPath} />
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Button onClick={handleSubmitScan} isLoading={isLoading} isDisabled={scanPath.length === 0}>
|
||||||
|
{t('modelManager.scanFolder')}
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
{!!errorMessage.length && <FormErrorMessage>{errorMessage}</FormErrorMessage>}
|
||||||
|
</Flex>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
{results && <ScanModelsResults results={results} />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,77 @@
|
|||||||
|
import {
|
||||||
|
Text,
|
||||||
|
Flex,
|
||||||
|
Heading,
|
||||||
|
IconButton,
|
||||||
|
Input,
|
||||||
|
InputGroup,
|
||||||
|
InputRightElement,
|
||||||
|
Divider,
|
||||||
|
Box,
|
||||||
|
} from '@invoke-ai/ui-library';
|
||||||
|
import { t } from 'i18next';
|
||||||
|
import { ChangeEventHandler, useCallback, useMemo, useState } from 'react';
|
||||||
|
import { PiXBold } from 'react-icons/pi';
|
||||||
|
|
||||||
|
export const ScanModelsResults = ({ results }: { results: string[] }) => {
|
||||||
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
|
const [filteredResults, setFilteredResults] = useState(results);
|
||||||
|
|
||||||
|
const handleSearch: ChangeEventHandler<HTMLInputElement> = useCallback(
|
||||||
|
(e) => {
|
||||||
|
setSearchTerm(e.target.value);
|
||||||
|
setFilteredResults(
|
||||||
|
results.filter((result) => {
|
||||||
|
const modelName = result.split('\\').slice(-1)[0];
|
||||||
|
return modelName?.includes(e.target.value);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[results]
|
||||||
|
);
|
||||||
|
|
||||||
|
const clearSearch = useCallback(() => {
|
||||||
|
setSearchTerm('');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Divider mt={4} />
|
||||||
|
<Flex flexDir="column" gap={2} mt={4}>
|
||||||
|
<Flex justifyContent="space-between" alignItems="center" mb={4}>
|
||||||
|
<Heading fontSize="md" as="h4">
|
||||||
|
Scan Results
|
||||||
|
</Heading>
|
||||||
|
<InputGroup maxW="300px" size="xs">
|
||||||
|
<Input
|
||||||
|
placeholder={t('modelManager.search')}
|
||||||
|
value={searchTerm || ''}
|
||||||
|
data-testid="board-search-input"
|
||||||
|
onChange={handleSearch}
|
||||||
|
size="xs"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{!!searchTerm?.length && (
|
||||||
|
<InputRightElement h="full" pe={2}>
|
||||||
|
<IconButton
|
||||||
|
size="sm"
|
||||||
|
variant="link"
|
||||||
|
aria-label={t('boards.clearSearch')}
|
||||||
|
icon={<PiXBold />}
|
||||||
|
onClick={clearSearch}
|
||||||
|
/>
|
||||||
|
</InputRightElement>
|
||||||
|
)}
|
||||||
|
</InputGroup>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
{filteredResults.map((result) => (
|
||||||
|
<Flex key={result} fontSize="sm" flexDir="column">
|
||||||
|
<Text fontWeight="semibold">{result.split('\\').slice(-1)[0]}</Text>
|
||||||
|
<Text variant="subtext">{result}</Text>
|
||||||
|
</Flex>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -2,6 +2,7 @@ import { Box, Divider, Heading, Tab, TabList, TabPanel, TabPanels, Tabs } from '
|
|||||||
|
|
||||||
import { ImportQueue } from './AddModelPanel/ImportQueue';
|
import { ImportQueue } from './AddModelPanel/ImportQueue';
|
||||||
import { SimpleImport } from './AddModelPanel/SimpleImport';
|
import { SimpleImport } from './AddModelPanel/SimpleImport';
|
||||||
|
import { ScanModels } from './AddModelPanel/ScanModels/ScanModels';
|
||||||
|
|
||||||
export const ImportModels = () => {
|
export const ImportModels = () => {
|
||||||
return (
|
return (
|
||||||
@ -9,7 +10,7 @@ export const ImportModels = () => {
|
|||||||
<Box w="full" p={4}>
|
<Box w="full" p={4}>
|
||||||
<Heading fontSize="xl">Add Model</Heading>
|
<Heading fontSize="xl">Add Model</Heading>
|
||||||
</Box>
|
</Box>
|
||||||
<Box layerStyle="second" borderRadius="base" w="full" h="100vh">
|
<Box layerStyle="second" borderRadius="base" w="full">
|
||||||
<Tabs variant="collapse">
|
<Tabs variant="collapse">
|
||||||
<TabList>
|
<TabList>
|
||||||
<Tab>Simple</Tab>
|
<Tab>Simple</Tab>
|
||||||
@ -21,7 +22,9 @@ export const ImportModels = () => {
|
|||||||
<SimpleImport />
|
<SimpleImport />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>Advanced Import Placeholder</TabPanel>
|
<TabPanel>Advanced Import Placeholder</TabPanel>
|
||||||
<TabPanel>Scan Models Placeholder</TabPanel>
|
<TabPanel>
|
||||||
|
<ScanModels />
|
||||||
|
</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
@ -349,6 +349,7 @@ export const {
|
|||||||
useMergeMainModelsMutation,
|
useMergeMainModelsMutation,
|
||||||
useSyncModelsMutation,
|
useSyncModelsMutation,
|
||||||
useScanModelsQuery,
|
useScanModelsQuery,
|
||||||
|
useLazyScanModelsQuery,
|
||||||
useGetCheckpointConfigsQuery,
|
useGetCheckpointConfigsQuery,
|
||||||
useGetModelImportsQuery,
|
useGetModelImportsQuery,
|
||||||
useGetModelMetadataQuery,
|
useGetModelMetadataQuery,
|
||||||
|
Loading…
Reference in New Issue
Block a user