Skip to content

Commit

Permalink
added add all button to scan models (#5811)
Browse files Browse the repository at this point in the history
## What type of PR is this? (check all applicable)

- [ ] Refactor
- [X] Feature
- [ ] Bug Fix
- [ ] Optimization
- [ ] Documentation Update
- [ ] Community Node Submission


## Have you discussed this change with the InvokeAI team?
- [X] Yes
- [ ] No, because:

      
## Have you updated all relevant documentation?
- [ ] Yes
- [ ] No


## Description


## Related Tickets & Documents

<!--
For pull requests that relate or close an issue, please include them
below. 

For example having the text: "closes #1234" would connect the current
pull
request to issue 1234.  And when we merge the pull request, Github will
automatically close the issue.
-->

- Related Issue #
- Closes #

## QA Instructions, Screenshots, Recordings

<!-- 
Please provide steps on how to test changes, any hardware or 
software specifications as well as any other pertinent information. 
-->

## Merge Plan

<!--
A merge plan describes how this PR should be handled after it is
approved.

Example merge plans:
- "This PR can be merged when approved"
- "This must be squash-merged when approved"
- "DO NOT MERGE - I will rebase and tidy commits before merging"
- "#dev-chat on discord needs to be advised of this change when it is
merged"

A merge plan is particularly important for large PRs or PRs that touch
the
database in any way.
-->

## Added/updated tests?

- [ ] Yes
- [ ] No : _please replace this line with details on why tests
      have not been included_

## [optional] Are there any post deployment tasks we need to perform?
  • Loading branch information
chainchompa committed Feb 27, 2024
2 parents 18af534 + 110b0bc commit 4418c11
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 26 deletions.
1 change: 1 addition & 0 deletions invokeai/frontend/web/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@
},
"modelManager": {
"active": "active",
"addAll": "Add All",
"addCheckpointModel": "Add Checkpoint / Safetensor Model",
"addDifference": "Add Difference",
"addDiffuserModel": "Add Diffusers",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Box, Button, Flex, Text } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
import { addToast } from 'features/system/store/systemSlice';
import { makeToast } from 'features/system/util/makeToast';
import { t } from 'i18next';
Expand Down Expand Up @@ -57,9 +58,11 @@ export const ImportQueue = () => {
</Button>
</Flex>
<Box mt={3} layerStyle="first" p={3} borderRadius="base" w="full" h="full">
<Flex flexDir="column-reverse" gap="2">
{data?.map((model) => <ImportQueueItem key={model.id} model={model} />)}
</Flex>
<ScrollableContent>
<Flex flexDir="column-reverse" gap="2">
{data?.map((model) => <ImportQueueItem key={model.id} model={model} />)}
</Flex>
</ScrollableContent>
</Box>
</Flex>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const ImportQueueItem = (props: ModelListItemProps) => {
</Box>

<Box minW="20px">
{(model.status === 'downloading' || model.status === 'waiting') && (
{(model.status === 'downloading' || model.status === 'waiting' || model.status === 'running') && (
<IconButton
isRound={true}
size="xs"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import { Divider, Flex, Heading, IconButton, Input, InputGroup, InputRightElement } from '@invoke-ai/ui-library';
import {
Button,
Divider,
Flex,
Heading,
IconButton,
Input,
InputGroup,
InputRightElement,
} from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
import { addToast } from 'features/system/store/systemSlice';
import { makeToast } from 'features/system/util/makeToast';
import type { ChangeEventHandler } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PiXBold } from 'react-icons/pi';
import type { ScanFolderResponse } from 'services/api/endpoints/models';
import { type ScanFolderResponse, useInstallModelMutation } from 'services/api/endpoints/models';

import { ScanModelResultItem } from './ScanModelResultItem';

Expand All @@ -15,6 +27,9 @@ type ScanModelResultsProps = {
export const ScanModelsResults = ({ results }: ScanModelResultsProps) => {
const { t } = useTranslation();
const [searchTerm, setSearchTerm] = useState('');
const dispatch = useAppDispatch();

const [installModel] = useInstallModelMutation();

const filteredResults = useMemo(() => {
return results.filter((result) => {
Expand All @@ -31,6 +46,38 @@ export const ScanModelsResults = ({ results }: ScanModelResultsProps) => {
setSearchTerm('');
}, []);

const handleAddAll = useCallback(() => {
for (const result of filteredResults) {
if (result.is_installed) {
continue;
}
installModel({ source: result.path })
.unwrap()
.then((_) => {
dispatch(
addToast(
makeToast({
title: t('toast.modelAddedSimple'),
status: 'success',
})
)
);
})
.catch((error) => {
if (error) {
dispatch(
addToast(
makeToast({
title: `${error.data.detail} `,
status: 'error',
})
)
);
}
});
}
}, [installModel, filteredResults, dispatch, t]);

return (
<>
<Divider mt={4} />
Expand All @@ -39,27 +86,32 @@ export const ScanModelsResults = ({ results }: ScanModelResultsProps) => {
<Heading fontSize="md" as="h4">
{t('modelManager.scanResults')}
</Heading>
<InputGroup maxW="300px" size="xs">
<Input
placeholder={t('modelManager.search')}
value={searchTerm}
data-testid="board-search-input"
onChange={handleSearch}
size="xs"
/>
<Flex alignItems="center" gap="4">
<Button onClick={handleAddAll} isDisabled={filteredResults.length === 0}>
{t('modelManager.addAll')}
</Button>
<InputGroup maxW="300px" size="xs">
<Input
placeholder={t('modelManager.search')}
value={searchTerm}
data-testid="board-search-input"
onChange={handleSearch}
size="xs"
/>

{searchTerm && (
<InputRightElement h="full" pe={2}>
<IconButton
size="sm"
variant="link"
aria-label={t('boards.clearSearch')}
icon={<PiXBold />}
onClick={clearSearch}
/>
</InputRightElement>
)}
</InputGroup>
{searchTerm && (
<InputRightElement h="full" pe={2}>
<IconButton
size="sm"
variant="link"
aria-label={t('boards.clearSearch')}
icon={<PiXBold />}
onClick={clearSearch}
/>
</InputRightElement>
)}
</InputGroup>
</Flex>
</Flex>
<Flex height="100%" layerStyle="third" borderRadius="base" p={4} mt={4} mb={4}>
<ScrollableContent>
Expand Down

0 comments on commit 4418c11

Please sign in to comment.