mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
add video_count and asset_count to boards UI
This commit is contained in:
committed by
Mary Hipp Rogers
parent
d4378d9f2a
commit
e36490c2ec
@@ -61,6 +61,8 @@
|
||||
"imagesWithCount_other": "{{count}} images",
|
||||
"assetsWithCount_one": "{{count}} asset",
|
||||
"assetsWithCount_other": "{{count}} assets",
|
||||
"videosWithCount_one": "{{count}} video",
|
||||
"videosWithCount_other": "{{count}} videos",
|
||||
"updateBoardError": "Error updating board"
|
||||
},
|
||||
"accordions": {
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
import { Flex, Image, Text } from '@invoke-ai/ui-library';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGetBoardAssetsTotalQuery, useGetBoardImagesTotalQuery } from 'services/api/endpoints/boards';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import type { BoardDTO } from 'services/api/types';
|
||||
|
||||
type Props = {
|
||||
board: BoardDTO | null;
|
||||
boardCounts: {
|
||||
image_count: number;
|
||||
asset_count: number;
|
||||
video_count: number;
|
||||
};
|
||||
};
|
||||
|
||||
export const BoardTooltip = ({ board }: Props) => {
|
||||
export const BoardTooltip = ({ board, boardCounts }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { imagesTotal } = useGetBoardImagesTotalQuery(board?.board_id || 'none', {
|
||||
selectFromResult: ({ data }) => {
|
||||
return { imagesTotal: data?.total ?? 0 };
|
||||
},
|
||||
});
|
||||
const { assetsTotal } = useGetBoardAssetsTotalQuery(board?.board_id || 'none', {
|
||||
selectFromResult: ({ data }) => {
|
||||
return { assetsTotal: data?.total ?? 0 };
|
||||
},
|
||||
});
|
||||
|
||||
const { currentData: coverImage } = useGetImageDTOQuery(board?.cover_image_name ?? skipToken);
|
||||
|
||||
return (
|
||||
@@ -39,8 +34,10 @@ export const BoardTooltip = ({ board }: Props) => {
|
||||
<Flex flexDir="column" alignItems="center">
|
||||
{board && <Text fontWeight="semibold">{board.board_name}</Text>}
|
||||
<Text noOfLines={1}>
|
||||
{t('boards.imagesWithCount', { count: imagesTotal })}, {t('boards.assetsWithCount', { count: assetsTotal })}
|
||||
{t('boards.imagesWithCount', { count: boardCounts.image_count })},{' '}
|
||||
{t('boards.assetsWithCount', { count: boardCounts.asset_count })}
|
||||
</Text>
|
||||
<Text noOfLines={1}>{t('boards.videosWithCount', { count: boardCounts.video_count })}</Text>
|
||||
{board?.archived && <Text>({t('boards.archived')})</Text>}
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
@@ -50,11 +50,26 @@ const GalleryBoard = ({ board, isSelected }: GalleryBoardProps) => {
|
||||
[board.board_id]
|
||||
);
|
||||
|
||||
const boardCounts = useMemo(
|
||||
() => ({
|
||||
image_count: board.image_count,
|
||||
asset_count: board.asset_count,
|
||||
video_count: board.video_count,
|
||||
}),
|
||||
[board]
|
||||
);
|
||||
|
||||
return (
|
||||
<Box position="relative" w="full" h={12}>
|
||||
<BoardContextMenu board={board}>
|
||||
{(ref) => (
|
||||
<Tooltip label={<BoardTooltip board={board} />} openDelay={1000} placement="left" closeOnScroll p={2}>
|
||||
<Tooltip
|
||||
label={<BoardTooltip board={board} boardCounts={boardCounts} />}
|
||||
openDelay={1000}
|
||||
placement="right"
|
||||
closeOnScroll
|
||||
p={2}
|
||||
>
|
||||
<Flex
|
||||
ref={ref}
|
||||
onClick={onClick}
|
||||
@@ -71,12 +86,16 @@ const GalleryBoard = ({ board, isSelected }: GalleryBoardProps) => {
|
||||
h="full"
|
||||
>
|
||||
<CoverImage board={board} />
|
||||
<Flex w="full">
|
||||
<Flex flex={1}>
|
||||
<BoardEditableTitle board={board} isSelected={isSelected} />
|
||||
</Flex>
|
||||
{autoAddBoardId === board.board_id && <AutoAddBadge />}
|
||||
{board.archived && <Icon as={PiArchiveBold} fill="base.300" />}
|
||||
<Text variant="subtext">{board.image_count}</Text>
|
||||
<Flex justifyContent="flex-end">
|
||||
<Text variant="subtext">
|
||||
{board.image_count} | {board.asset_count} | {board.video_count}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@@ -15,7 +15,11 @@ import {
|
||||
import { autoAddBoardIdChanged, boardIdSelected } from 'features/gallery/store/gallerySlice';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGetBoardImagesTotalQuery } from 'services/api/endpoints/boards';
|
||||
import {
|
||||
useGetBoardAssetsTotalQuery,
|
||||
useGetBoardImagesTotalQuery,
|
||||
useGetBoardVideosTotalQuery,
|
||||
} from 'services/api/endpoints/boards';
|
||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||
|
||||
interface Props {
|
||||
@@ -33,6 +37,16 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
|
||||
return { imagesTotal: data?.total ?? 0 };
|
||||
},
|
||||
});
|
||||
const { assetsTotal } = useGetBoardAssetsTotalQuery('none', {
|
||||
selectFromResult: ({ data }) => {
|
||||
return { assetsTotal: data?.total ?? 0 };
|
||||
},
|
||||
});
|
||||
const { videoTotal } = useGetBoardVideosTotalQuery('none', {
|
||||
selectFromResult: ({ data }) => {
|
||||
return { videoTotal: data?.total ?? 0 };
|
||||
},
|
||||
});
|
||||
const autoAddBoardId = useAppSelector(selectAutoAddBoardId);
|
||||
const autoAssignBoardOnClick = useAppSelector(selectAutoAssignBoardOnClick);
|
||||
const boardSearchText = useAppSelector(selectBoardSearchText);
|
||||
@@ -56,7 +70,17 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
|
||||
<Box position="relative" w="full" h={12}>
|
||||
<NoBoardBoardContextMenu>
|
||||
{(ref) => (
|
||||
<Tooltip label={<BoardTooltip board={null} />} openDelay={1000} placement="left" closeOnScroll>
|
||||
<Tooltip
|
||||
label={
|
||||
<BoardTooltip
|
||||
board={null}
|
||||
boardCounts={{ image_count: imagesTotal, asset_count: assetsTotal, video_count: videoTotal }}
|
||||
/>
|
||||
}
|
||||
openDelay={1000}
|
||||
placement="right"
|
||||
closeOnScroll
|
||||
>
|
||||
<Flex
|
||||
ref={ref}
|
||||
onClick={handleSelectBoard}
|
||||
@@ -92,7 +116,9 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
|
||||
{boardName}
|
||||
</Text>
|
||||
{autoAddBoardId === 'none' && <AutoAddBadge />}
|
||||
<Text variant="subtext">{imagesTotal}</Text>
|
||||
<Text variant="subtext">
|
||||
{imagesTotal} | {assetsTotal} | {videoTotal}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@@ -3,6 +3,7 @@ import queryString from 'query-string';
|
||||
import type {
|
||||
BoardDTO,
|
||||
CreateBoardArg,
|
||||
GetVideoIdsResult,
|
||||
ImageCategory,
|
||||
ListBoardsArgs,
|
||||
OffsetPaginatedResults_ImageDTO_,
|
||||
@@ -12,6 +13,7 @@ import { getListImagesUrl } from 'services/api/util';
|
||||
|
||||
import type { ApiTagDescription } from '..';
|
||||
import { api, buildV1Url, LIST_TAG } from '..';
|
||||
import { buildVideosUrl } from './videos';
|
||||
|
||||
/**
|
||||
* Builds an endpoint URL for the boards router
|
||||
@@ -95,6 +97,17 @@ export const boardsApi = api.injectEndpoints({
|
||||
},
|
||||
}),
|
||||
|
||||
getBoardVideosTotal: build.query<{ total: number }, string | undefined>({
|
||||
query: (board_id) => ({
|
||||
url: buildVideosUrl('ids', { board_id: board_id ?? 'none' }),
|
||||
method: 'GET',
|
||||
}),
|
||||
providesTags: (result, error, arg) => [{ type: 'BoardVideosTotal', id: arg ?? 'none' }, 'FetchOnReconnect'],
|
||||
transformResponse: (response: GetVideoIdsResult) => {
|
||||
return { total: response.total_count };
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* Boards Mutations
|
||||
*/
|
||||
@@ -132,6 +145,7 @@ export const {
|
||||
useListAllBoardsQuery,
|
||||
useGetBoardImagesTotalQuery,
|
||||
useGetBoardAssetsTotalQuery,
|
||||
useGetBoardVideosTotalQuery,
|
||||
useCreateBoardMutation,
|
||||
useUpdateBoardMutation,
|
||||
useListAllImageNamesForBoardQuery,
|
||||
|
||||
@@ -18,7 +18,7 @@ import { api, buildV1Url, LIST_TAG } from '..';
|
||||
* buildVideosUrl('some-path')
|
||||
* // '/api/v1/videos/some-path'
|
||||
*/
|
||||
const buildVideosUrl = (path: string = '', query?: Parameters<typeof buildV1Url>[1]) =>
|
||||
export const buildVideosUrl = (path: string = '', query?: Parameters<typeof buildV1Url>[1]) =>
|
||||
buildV1Url(`videos/${path}`, query);
|
||||
|
||||
const buildBoardVideosUrl = (path: string = '') => buildV1Url(`board_videos/${path}`);
|
||||
|
||||
@@ -19,6 +19,7 @@ const tagTypes = [
|
||||
'Board',
|
||||
'BoardImagesTotal',
|
||||
'BoardAssetsTotal',
|
||||
'BoardVideosTotal',
|
||||
'HFTokenStatus',
|
||||
'Image',
|
||||
'ImageNameList',
|
||||
|
||||
@@ -2781,6 +2781,11 @@ export type components = {
|
||||
* @description The number of images in the board.
|
||||
*/
|
||||
image_count: number;
|
||||
/**
|
||||
* Asset Count
|
||||
* @description The number of assets in the board.
|
||||
*/
|
||||
asset_count: number;
|
||||
/**
|
||||
* Video Count
|
||||
* @description The number of videos in the board.
|
||||
|
||||
Reference in New Issue
Block a user