diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowLibrary/WorkflowLibrarySideNav.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowLibrary/WorkflowLibrarySideNav.tsx index 690d22d181..6262be6d44 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowLibrary/WorkflowLibrarySideNav.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowLibrary/WorkflowLibrarySideNav.tsx @@ -27,7 +27,7 @@ import { import { NewWorkflowButton } from 'features/workflowLibrary/components/NewWorkflowButton'; import { UploadWorkflowButton } from 'features/workflowLibrary/components/UploadWorkflowButton'; import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; -import { memo, useCallback, useMemo } from 'react'; +import { memo, useCallback, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { PiArrowCounterClockwiseBold, PiUsersBold } from 'react-icons/pi'; import { useDispatch } from 'react-redux'; @@ -43,6 +43,8 @@ export const WorkflowLibrarySideNav = () => { dispatch(workflowLibraryTagsReset()); }, [dispatch]); + useEffect(() => {}, [selectedTags, dispatch]); + return ( @@ -121,7 +123,7 @@ const useCountForIndividualTag = (tag: string) => { const queryArg = useMemo( () => ({ - tags: allTags, + tags: allTags.map((tag) => tag.label), categories: ['default'], }) satisfies Parameters[0], [allTags] @@ -146,7 +148,7 @@ const useCountForTagCategory = (tagCategory: WorkflowTagCategory) => { const queryArg = useMemo( () => ({ - tags: allTags, + tags: allTags.map((tag) => tag.label), categories: ['default'], // We only allow filtering by tag for default workflows }) satisfies Parameters[0], [allTags] @@ -159,7 +161,7 @@ const useCountForTagCategory = (tagCategory: WorkflowTagCategory) => { return { count: 0 }; } return { - count: tagCategory.tags.reduce((acc, tag) => acc + (data[tag] ?? 0), 0), + count: tagCategory.tags.reduce((acc, tag) => acc + (data[tag.label] ?? 0), 0), }; }, }) satisfies Parameters[1], @@ -197,6 +199,15 @@ WorkflowLibraryViewButton.displayName = 'NavButton'; const TagCategory = memo(({ tagCategory }: { tagCategory: WorkflowTagCategory }) => { const { t } = useTranslation(); const count = useCountForTagCategory(tagCategory); + const dispatch = useAppDispatch(); + + useEffect(() => { + for (const tag of tagCategory.tags) { + if (tag.selected) { + dispatch(workflowLibraryTagToggled(tag.label)); + } + } + }, [count, tagCategory.tags, dispatch]); if (count === 0) { return null; @@ -209,7 +220,7 @@ const TagCategory = memo(({ tagCategory }: { tagCategory: WorkflowTagCategory }) {tagCategory.tags.map((tag) => ( - + ))} diff --git a/invokeai/frontend/web/src/features/nodes/store/workflowLibrarySlice.ts b/invokeai/frontend/web/src/features/nodes/store/workflowLibrarySlice.ts index d4b8f8b201..d10b0bfb04 100644 --- a/invokeai/frontend/web/src/features/nodes/store/workflowLibrarySlice.ts +++ b/invokeai/frontend/web/src/features/nodes/store/workflowLibrarySlice.ts @@ -92,12 +92,21 @@ export const selectWorkflowLibraryView = createWorkflowLibrarySelector(({ view } export const DEFAULT_WORKFLOW_LIBRARY_CATEGORIES = ['user', 'default'] satisfies WorkflowCategory[]; export const $workflowLibraryCategoriesOptions = atom(DEFAULT_WORKFLOW_LIBRARY_CATEGORIES); -export type WorkflowTagCategory = { categoryTKey: string; tags: string[] }; +export type WorkflowTagCategory = { categoryTKey: string; tags: Array<{ label: string; selected?: boolean }> }; export const DEFAULT_WORKFLOW_LIBRARY_TAG_CATEGORIES: WorkflowTagCategory[] = [ - { categoryTKey: 'Industry', tags: ['Architecture', 'Fashion', 'Game Dev', 'Food'] }, - { categoryTKey: 'Common Tasks', tags: ['Upscaling', 'Text to Image', 'Image to Image'] }, - { categoryTKey: 'Model Architecture', tags: ['SD1.5', 'SDXL', 'SD3.5', 'FLUX'] }, - { categoryTKey: 'Tech Showcase', tags: ['Control', 'Reference Image'] }, + { + categoryTKey: 'Industry', + tags: [{ label: 'Architecture' }, { label: 'Fashion' }, { label: 'Game Dev' }, { label: 'Food' }], + }, + { + categoryTKey: 'Common Tasks', + tags: [{ label: 'Upscaling' }, { label: 'Text to Image' }, { label: 'Image to Image' }], + }, + { + categoryTKey: 'Model Architecture', + tags: [{ label: 'SD1.5' }, { label: 'SDXL' }, { label: 'SD3.5' }, { label: 'FLUX' }], + }, + { categoryTKey: 'Tech Showcase', tags: [{ label: 'Control' }, { label: 'Reference Image' }] }, ]; export const $workflowLibraryTagCategoriesOptions = atom( DEFAULT_WORKFLOW_LIBRARY_TAG_CATEGORIES