(ui) update so that default list does not sort

This commit is contained in:
Mary Hipp
2024-10-08 15:36:18 -04:00
committed by psychedelicious
parent a28cabdf97
commit ed88b096f3
3 changed files with 90 additions and 101 deletions

View File

@@ -1,19 +1,55 @@
import { Button, Collapse, Flex, Icon, Text } from '@invoke-ai/ui-library';
import { Button, Collapse, Flex, Icon, Spinner, Text } from '@invoke-ai/ui-library';
import { EMPTY_ARRAY } from 'app/store/constants';
import { useAppSelector } from 'app/store/storeHooks';
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
import { useCategorySections } from 'features/nodes/hooks/useCategorySections';
import { selectWorkflowSearchTerm } from 'features/nodes/store/workflowSlice';
import {
selectWorkflowOrderBy,
selectWorkflowOrderDirection,
selectWorkflowSearchTerm,
} from 'features/nodes/store/workflowSlice';
import type { WorkflowCategory } from 'features/nodes/types/workflow';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { PiCaretDownBold } from 'react-icons/pi';
import type { WorkflowRecordListItemDTO } from 'services/api/types';
import { useListWorkflowsQuery } from 'services/api/endpoints/workflows';
import { WorkflowListItem } from './WorkflowListItem';
export const WorkflowList = ({ title, data }: { title: string; data: WorkflowRecordListItemDTO[] }) => {
const { t } = useTranslation();
export const WorkflowList = ({ category }: { category: WorkflowCategory }) => {
const searchTerm = useAppSelector(selectWorkflowSearchTerm);
const orderBy = useAppSelector(selectWorkflowOrderBy);
const direction = useAppSelector(selectWorkflowOrderDirection);
const { t } = useTranslation();
const { isOpen, onToggle } = useCategorySections(title);
const queryArg = useMemo<Parameters<typeof useListWorkflowsQuery>[0]>(() => {
if (category !== 'default') {
return {
order_by: orderBy,
direction,
category: category,
};
}
return {
order_by: 'name' as const,
direction: 'ASC' as const,
category: category,
};
}, [category, direction, orderBy]);
const { data, isLoading } = useListWorkflowsQuery(queryArg, {
selectFromResult: ({ data, isLoading }) => {
const filteredData =
data?.items.filter((workflow) => workflow.name.toLowerCase().includes(searchTerm.toLowerCase())) || EMPTY_ARRAY;
return {
data: filteredData,
isLoading,
};
},
});
const { isOpen, onToggle } = useCategorySections(category);
return (
<Flex flexDir="column">
@@ -21,12 +57,16 @@ export const WorkflowList = ({ title, data }: { title: string; data: WorkflowRec
<Flex gap={2} alignItems="center">
<Icon boxSize={4} as={PiCaretDownBold} transform={isOpen ? undefined : 'rotate(-90deg)'} fill="base.500" />
<Text fontSize="sm" fontWeight="semibold" userSelect="none" color="base.500">
{title}
{t(`workflows.${category}Workflows`)}
</Text>
</Flex>
</Button>
<Collapse in={isOpen}>
{data.length ? (
{isLoading ? (
<Flex alignItems="center" justifyContent="center" p={20}>
<Spinner />
</Flex>
) : data.length ? (
data.map((workflow) => <WorkflowListItem workflow={workflow} key={workflow.workflow_id} />)
) : (
<IAINoContentFallback

View File

@@ -1,88 +1,28 @@
import { Flex, Spinner } from '@invoke-ai/ui-library';
import { Flex } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { EMPTY_ARRAY } from 'app/store/constants';
import { $workflowCategories } from 'app/store/nanostores/workflowCategories';
import { useAppSelector } from 'app/store/storeHooks';
import {
selectWorkflowOrderBy,
selectWorkflowOrderDirection,
selectWorkflowSearchTerm,
} from 'features/nodes/store/workflowSlice';
import UploadWorkflowButton from 'features/workflowLibrary/components/UploadWorkflowButton';
import { useTranslation } from 'react-i18next';
import { useListWorkflowsQuery } from 'services/api/endpoints/workflows';
import type { WorkflowRecordListItemDTO } from 'services/api/types';
import { WorkflowList } from './WorkflowList';
import WorkflowSearch from './WorkflowSearch';
import { WorkflowSortControl } from './WorkflowSortControl';
export const WorkflowListMenu = () => {
const searchTerm = useAppSelector(selectWorkflowSearchTerm);
const orderBy = useAppSelector(selectWorkflowOrderBy);
const direction = useAppSelector(selectWorkflowOrderDirection);
const { t } = useTranslation();
const { data, isLoading } = useListWorkflowsQuery(
{ order_by: orderBy, direction },
{
selectFromResult: ({ data, isLoading }) => {
const filteredData =
data?.items.filter((workflow) => workflow.name.toLowerCase().includes(searchTerm.toLowerCase())) ||
EMPTY_ARRAY;
const groupedData = filteredData.reduce(
(
acc: {
default: WorkflowRecordListItemDTO[];
project: WorkflowRecordListItemDTO[];
user: WorkflowRecordListItemDTO[];
},
workflow
) => {
if (workflow.category === 'default') {
acc.default.push(workflow);
} else if (workflow.category === 'project') {
acc.project.push(workflow);
} else {
acc.user.push(workflow);
}
return acc;
},
{ default: [], project: [], user: [] }
);
return {
data: groupedData,
isLoading,
};
},
}
);
const workflowCategories = useStore($workflowCategories);
return (
<Flex flexDir="column" gap={2} padding={3} layerStyle="second" borderRadius="base">
<Flex alignItems="center" gap={2} w="full" justifyContent="space-between">
<WorkflowSearch />
<Flex>
<WorkflowSortControl />
<UploadWorkflowButton />
</Flex>
<WorkflowSortControl />
<UploadWorkflowButton />
</Flex>
{isLoading ? (
<Flex alignItems="center" justifyContent="center" p={20}>
<Spinner />
</Flex>
) : (
<>
{workflowCategories.map((category) => (
<WorkflowList key={category} title={t(`workflows.${category}Workflows`)} data={data[category]} />
))}
</>
)}
{workflowCategories.map((category) => (
<WorkflowList key={category} category={category} />
))}
</Flex>
);
};

View File

@@ -10,6 +10,7 @@ import {
PopoverContent,
PopoverTrigger,
Tooltip,
useDisclosure,
} from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { $projectId } from 'app/store/nanostores/projectId';
@@ -91,31 +92,39 @@ export const WorkflowSortControl = () => {
[direction, DIRECTION_OPTIONS]
);
const { isOpen, onToggle, onClose } = useDisclosure();
return (
<Popover>
<PopoverTrigger>
<Tooltip label={`Sorting by ${valueOrderBy?.label} ${valueDirection?.label}`}>
<IconButton
aria-label="Sort Workflow Librar"
icon={direction === 'ASC' ? <PiSortAscendingBold /> : <PiSortDescendingBold />}
variant="ghost"
/>
</Tooltip>
</PopoverTrigger>
<PopoverContent>
<PopoverBody>
<Flex flexDir="column" gap={4}>
<FormControl orientation="horizontal" gap={1}>
<FormLabel>{t('common.orderBy')}</FormLabel>
<Combobox value={valueOrderBy} options={orderByOptions} onChange={onChangeOrderBy} />
</FormControl>
<FormControl orientation="horizontal" gap={1}>
<FormLabel>{t('common.direction')}</FormLabel>
<Combobox value={valueDirection} options={DIRECTION_OPTIONS} onChange={onChangeDirection} />
</FormControl>
</Flex>
</PopoverBody>
</PopoverContent>
</Popover>
<>
<Tooltip label={`Sorting by ${valueOrderBy?.label} ${valueDirection?.label}`}>
<IconButton
aria-label="Sort Workflow Librar"
icon={direction === 'ASC' ? <PiSortAscendingBold /> : <PiSortDescendingBold />}
variant="ghost"
onClick={onToggle}
/>
</Tooltip>
<Popover placement="bottom" isOpen={isOpen} onClose={onClose} returnFocusOnClose={false} closeOnBlur={false}>
<PopoverTrigger>
<Flex></Flex>
</PopoverTrigger>
<PopoverContent>
<PopoverBody>
<Flex flexDir="column" gap={4}>
<FormControl orientation="horizontal" gap={1}>
<FormLabel>{t('common.orderBy')}</FormLabel>
<Combobox value={valueOrderBy} options={orderByOptions} onChange={onChangeOrderBy} />
</FormControl>
<FormControl orientation="horizontal" gap={1}>
<FormLabel>{t('common.direction')}</FormLabel>
<Combobox value={valueDirection} options={DIRECTION_OPTIONS} onChange={onChangeDirection} />
</FormControl>
</Flex>
</PopoverBody>
</PopoverContent>
</Popover>
</>
);
};