From 8d44363d495245c81d1ddfefbdf64643c25ff4e4 Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Fri, 11 Oct 2024 13:52:52 -0400 Subject: [PATCH] (ui): update boards list queries to only use sort params for list, and make sure archived boards are included in most places we are searching --- .../changeBoardModal/components/ChangeBoardModal.tsx | 4 +--- .../src/features/gallery/store/gallerySelectors.ts | 6 ++++++ .../web/src/features/gallery/store/gallerySlice.ts | 12 +++++++++++- .../frontend/web/src/features/gallery/store/types.ts | 4 +++- .../fields/inputs/BoardFieldInputComponent.tsx | 6 ++---- .../web/src/services/api/hooks/accessChecks.ts | 5 ++--- .../web/src/services/api/hooks/useBoardName.ts | 5 +---- invokeai/frontend/web/src/services/api/schema.ts | 10 ++++++++++ invokeai/frontend/web/src/services/api/types.ts | 2 ++ 9 files changed, 38 insertions(+), 16 deletions(-) diff --git a/invokeai/frontend/web/src/features/changeBoardModal/components/ChangeBoardModal.tsx b/invokeai/frontend/web/src/features/changeBoardModal/components/ChangeBoardModal.tsx index 6c6b55f7ac..0900b99d2b 100644 --- a/invokeai/frontend/web/src/features/changeBoardModal/components/ChangeBoardModal.tsx +++ b/invokeai/frontend/web/src/features/changeBoardModal/components/ChangeBoardModal.tsx @@ -9,7 +9,6 @@ import { isModalOpenChanged, selectChangeBoardModalSlice, } from 'features/changeBoardModal/store/slice'; -import { selectListBoardsQueryArgs } from 'features/gallery/store/gallerySelectors'; import { memo, useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useListAllBoardsQuery } from 'services/api/endpoints/boards'; @@ -29,8 +28,7 @@ const ChangeBoardModal = () => { useAssertSingleton('ChangeBoardModal'); const dispatch = useAppDispatch(); const [selectedBoard, setSelectedBoard] = useState(); - const queryArgs = useAppSelector(selectListBoardsQueryArgs); - const { data: boards, isFetching } = useListAllBoardsQuery(queryArgs); + const { data: boards, isFetching } = useListAllBoardsQuery({include_archived: true}); const isModalOpen = useAppSelector(selectIsModalOpen); const imagesToChange = useAppSelector(selectImagesToChange); const [addImagesToBoard] = useAddImagesToBoardMutation(); diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts index c7b4daa92c..4f4e9f7322 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts @@ -32,6 +32,8 @@ export const selectListImagesQueryArgs = createMemoizedSelector( export const selectListBoardsQueryArgs = createMemoizedSelector( selectGallerySlice, (gallery): ListBoardsArgs => ({ + order_by: gallery.boardsListOrderBy, + direction: gallery.boardsListOrderDir, include_archived: gallery.shouldShowArchivedBoards ? true : undefined, }) ); @@ -44,6 +46,10 @@ export const selectAutoAssignBoardOnClick = createSelector( ); export const selectBoardSearchText = createSelector(selectGallerySlice, (gallery) => gallery.boardSearchText); export const selectSearchTerm = createSelector(selectGallerySlice, (gallery) => gallery.searchTerm); +export const selectBoardsListOrderBy = createSelector(selectGallerySlice, (gallery) => gallery.boardsListOrderBy); +export const selectBoardsListOrderDir = createSelector(selectGallerySlice, (gallery) => gallery.boardsListOrderDir); + + export const selectSelectionCount = createSelector(selectGallerySlice, (gallery) => gallery.selection.length); export const selectHasMultipleImagesSelected = createSelector(selectSelectionCount, (count) => count > 1); export const selectGalleryImageMinimumWidth = createSelector( diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index 267757a600..c4f40ba55b 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -2,7 +2,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; import type { PersistConfig, RootState } from 'app/store/store'; import { isEqual, uniqBy } from 'lodash-es'; -import type { ImageDTO } from 'services/api/types'; +import type { BoardRecordOrderBy, ImageDTO } from 'services/api/types'; import type { BoardId, ComparisonMode, GalleryState, GalleryView, OrderDir } from './types'; @@ -25,6 +25,8 @@ const initialGalleryState: GalleryState = { comparisonMode: 'slider', comparisonFit: 'fill', shouldShowArchivedBoards: false, + boardsListOrderBy: 'created_at', + boardsListOrderDir: "DESC", }; export const gallerySlice = createSlice({ @@ -161,6 +163,12 @@ export const gallerySlice = createSlice({ state.searchTerm = action.payload; state.offset = 0; }, + boardsListOrderByChanged: (state, action: PayloadAction) => { + state.boardsListOrderBy = action.payload; + }, + boardsListOrderDirChanged: (state, action: PayloadAction) => { + state.boardsListOrderDir = action.payload; + }, }, }); @@ -186,6 +194,8 @@ export const { starredFirstChanged, shouldShowArchivedBoardsChanged, searchTermChanged, + boardsListOrderByChanged, + boardsListOrderDirChanged } = gallerySlice.actions; export const selectGallerySlice = (state: RootState) => state.gallery; diff --git a/invokeai/frontend/web/src/features/gallery/store/types.ts b/invokeai/frontend/web/src/features/gallery/store/types.ts index 48bbc8b7be..89c3ca7bda 100644 --- a/invokeai/frontend/web/src/features/gallery/store/types.ts +++ b/invokeai/frontend/web/src/features/gallery/store/types.ts @@ -1,4 +1,4 @@ -import type { ImageCategory, ImageDTO } from 'services/api/types'; +import type { BoardRecordOrderBy, ImageCategory, ImageDTO } from 'services/api/types'; export const IMAGE_CATEGORIES: ImageCategory[] = ['general']; export const ASSETS_CATEGORIES: ImageCategory[] = ['control', 'mask', 'user', 'other']; @@ -28,4 +28,6 @@ export type GalleryState = { comparisonMode: ComparisonMode; comparisonFit: ComparisonFit; shouldShowArchivedBoards: boolean; + boardsListOrderBy: BoardRecordOrderBy, + boardsListOrderDir: OrderDir }; diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/inputs/BoardFieldInputComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/inputs/BoardFieldInputComponent.tsx index aabcfa4b38..96ec88468d 100644 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/inputs/BoardFieldInputComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/inputs/BoardFieldInputComponent.tsx @@ -1,7 +1,6 @@ import type { ComboboxOnChange, ComboboxOption } from '@invoke-ai/ui-library'; import { Combobox, FormControl } from '@invoke-ai/ui-library'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { selectListBoardsQueryArgs } from 'features/gallery/store/gallerySelectors'; +import { useAppDispatch } from 'app/store/storeHooks'; import { fieldBoardValueChanged } from 'features/nodes/store/nodesSlice'; import type { BoardFieldInputInstance, BoardFieldInputTemplate } from 'features/nodes/types/field'; import { memo, useCallback, useMemo } from 'react'; @@ -14,8 +13,7 @@ const BoardFieldInputComponent = (props: FieldComponentProps { const options: ComboboxOption[] = [ { diff --git a/invokeai/frontend/web/src/services/api/hooks/accessChecks.ts b/invokeai/frontend/web/src/services/api/hooks/accessChecks.ts index 864d537ef2..ebf75c1eda 100644 --- a/invokeai/frontend/web/src/services/api/hooks/accessChecks.ts +++ b/invokeai/frontend/web/src/services/api/hooks/accessChecks.ts @@ -44,10 +44,9 @@ export const checkImageAccess = async (name: string): Promise => { * @returns A promise that resolves to true if the client has access, else false. */ export const checkBoardAccess = async (id: string): Promise => { - const { dispatch, getState } = getStore(); + const { dispatch } = getStore(); try { - const queryArgs = selectListBoardsQueryArgs(getState()); - const req = dispatch(boardsApi.endpoints.listAllBoards.initiate(queryArgs)); + const req = dispatch(boardsApi.endpoints.listAllBoards.initiate({include_archived: true})); req.unsubscribe(); const result = await req.unwrap(); return result.some((b) => b.board_id === id); diff --git a/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts b/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts index c2501d50e3..2cc72d1b3a 100644 --- a/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts +++ b/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts @@ -1,12 +1,9 @@ -import { useAppSelector } from 'app/store/storeHooks'; -import { selectListBoardsQueryArgs } from 'features/gallery/store/gallerySelectors'; import type { BoardId } from 'features/gallery/store/types'; import { t } from 'i18next'; import { useListAllBoardsQuery } from 'services/api/endpoints/boards'; export const useBoardName = (board_id: BoardId) => { - const queryArgs = useAppSelector(selectListBoardsQueryArgs); - const { boardName } = useListAllBoardsQuery(queryArgs, { + const { boardName } = useListAllBoardsQuery({include_archived: true}, { selectFromResult: ({ data }) => { const selectedBoard = data?.find((b) => b.board_id === board_id); const boardName = selectedBoard?.board_name || t('boards.uncategorized'); diff --git a/invokeai/frontend/web/src/services/api/schema.ts b/invokeai/frontend/web/src/services/api/schema.ts index 2053723271..0680b0609d 100644 --- a/invokeai/frontend/web/src/services/api/schema.ts +++ b/invokeai/frontend/web/src/services/api/schema.ts @@ -2033,6 +2033,12 @@ export type components = { */ board_id: string; }; + /** + * BoardRecordOrderBy + * @description The order by options for board records + * @enum {string} + */ + BoardRecordOrderBy: "created_at" | "board_name"; /** Body_add_image_to_board */ Body_add_image_to_board: { /** @@ -18884,6 +18890,10 @@ export interface operations { list_boards: { parameters: { query?: { + /** @description The attribute to order by */ + order_by?: components["schemas"]["BoardRecordOrderBy"]; + /** @description The direction to order by */ + direction?: components["schemas"]["SQLiteDirection"]; /** @description Whether to list all boards */ all?: boolean | null; /** @description The page offset */ diff --git a/invokeai/frontend/web/src/services/api/types.ts b/invokeai/frontend/web/src/services/api/types.ts index 7f3329c7c9..9f87ce2f40 100644 --- a/invokeai/frontend/web/src/services/api/types.ts +++ b/invokeai/frontend/web/src/services/api/types.ts @@ -241,3 +241,5 @@ export type PostUploadAction = | RGIPAdapterImagePostUploadAction | UpscaleInitialImageAction | ReplaceLayerWithImagePostUploadAction; + +export type BoardRecordOrderBy = S["BoardRecordOrderBy"]