diff --git a/invokeai/frontend/web/src/app/contexts/AddImageToBoardContext.tsx b/invokeai/frontend/web/src/app/contexts/AddImageToBoardContext.tsx
index cf541dca01..da3dcb2239 100644
--- a/invokeai/frontend/web/src/app/contexts/AddImageToBoardContext.tsx
+++ b/invokeai/frontend/web/src/app/contexts/AddImageToBoardContext.tsx
@@ -1,23 +1,7 @@
import { useDisclosure } from '@chakra-ui/react';
-import { createSelector } from '@reduxjs/toolkit';
-import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
-import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
-import { requestedImageDeletion } from 'features/gallery/store/actions';
-import { systemSelector } from 'features/system/store/systemSelectors';
-import {
- PropsWithChildren,
- createContext,
- useCallback,
- useEffect,
- useState,
-} from 'react';
+import { useAppDispatch } from 'app/store/storeHooks';
+import { PropsWithChildren, createContext, useCallback, useState } from 'react';
import { ImageDTO } from 'services/api';
-import { RootState } from 'app/store/store';
-import { canvasSelector } from 'features/canvas/store/canvasSelectors';
-import { controlNetSelector } from 'features/controlNet/store/controlNetSlice';
-import { nodesSelecter } from 'features/nodes/store/nodesSlice';
-import { generationSelector } from 'features/parameters/store/generationSelectors';
-import { some } from 'lodash-es';
import { imageAddedToBoard } from '../../services/thunks/board';
export type ImageUsage = {
@@ -27,48 +11,6 @@ export type ImageUsage = {
isControlNetImage: boolean;
};
-export const selectImageUsage = createSelector(
- [
- generationSelector,
- canvasSelector,
- nodesSelecter,
- controlNetSelector,
- (state: RootState, image_name?: string) => image_name,
- ],
- (generation, canvas, nodes, controlNet, image_name) => {
- const isInitialImage = generation.initialImage?.image_name === image_name;
-
- const isCanvasImage = canvas.layerState.objects.some(
- (obj) => obj.kind === 'image' && obj.image.image_name === image_name
- );
-
- const isNodesImage = nodes.nodes.some((node) => {
- return some(
- node.data.inputs,
- (input) =>
- input.type === 'image' && input.value?.image_name === image_name
- );
- });
-
- const isControlNetImage = some(
- controlNet.controlNets,
- (c) =>
- c.controlImage?.image_name === image_name ||
- c.processedControlImage?.image_name === image_name
- );
-
- const imageUsage: ImageUsage = {
- isInitialImage,
- isCanvasImage,
- isNodesImage,
- isControlNetImage,
- };
-
- return imageUsage;
- },
- defaultSelectorOptions
-);
-
type AddImageToBoardContextValue = {
/**
* Whether the move image dialog is open.
diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList.tsx
index 9e7d1ab960..1f84d3be0e 100644
--- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList.tsx
@@ -1,4 +1,13 @@
-import { Box, Grid, Input, Spacer } from '@chakra-ui/react';
+import {
+ Box,
+ Divider,
+ Grid,
+ Input,
+ InputGroup,
+ InputRightElement,
+ Spacer,
+ useDisclosure,
+} from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
@@ -14,19 +23,25 @@ import AddBoardButton from './AddBoardButton';
import AllImagesBoard from './AllImagesBoard';
import { searchBoardsSelector } from '../../store/boardSelectors';
import { useSelector } from 'react-redux';
+import IAICollapse from '../../../../common/components/IAICollapse';
+import { CloseIcon } from '@chakra-ui/icons';
const selector = createSelector(
[selectBoardsAll, boardsSelector],
(boards, boardsState) => {
- return { boards, selectedBoardId: boardsState.selectedBoardId };
+ const selectedBoard = boards.find(
+ (board) => board.board_id === boardsState.selectedBoardId
+ );
+ return { selectedBoard, searchText: boardsState.searchText };
},
defaultSelectorOptions
);
const BoardsList = () => {
const dispatch = useAppDispatch();
- const { selectedBoardId } = useAppSelector(selector);
+ const { selectedBoard, searchText } = useAppSelector(selector);
const filteredBoards = useSelector(searchBoardsSelector);
+ const { isOpen, onToggle } = useDisclosure();
const [searchMode, setSearchMode] = useState(false);
@@ -34,52 +49,68 @@ const BoardsList = () => {
setSearchMode(searchTerm.length > 0);
dispatch(setBoardSearchText(searchTerm));
};
+ const clearBoardSearch = () => {
+ setSearchMode(false);
+ dispatch(setBoardSearchText(''));
+ };
return (
-
-
- {
- handleBoardSearch(e.target.value);
+
+ <>
+
+
+ {
+ handleBoardSearch(e.target.value);
+ }}
+ />
+ {searchText && searchText.length && (
+
+
+
+ )}
+
+
+
-
-
- {!searchMode && (
- <>
-
-
- >
- )}
- {filteredBoards.map((board) => (
-
- ))}
-
-
+ >
+
+ {!searchMode && (
+ <>
+
+
+ >
+ )}
+ {filteredBoards.map((board) => (
+
+ ))}
+
+
+ >
+
);
};
diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/HoverableBoard.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/HoverableBoard.tsx
index d368d4ab0b..6fd6ac41be 100644
--- a/invokeai/frontend/web/src/features/gallery/components/Boards/HoverableBoard.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/Boards/HoverableBoard.tsx
@@ -4,19 +4,34 @@ import {
EditableInput,
EditablePreview,
Flex,
- Icon,
- Image,
MenuItem,
MenuList,
} from '@chakra-ui/react';
-import { useAppDispatch } from 'app/store/storeHooks';
+
+import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { memo, useCallback } from 'react';
-import { FaFolder, FaTrash } from 'react-icons/fa';
+import { FaTrash } from 'react-icons/fa';
import { ContextMenu } from 'chakra-ui-contextmenu';
-import { BoardDTO } from 'services/api';
+import { BoardDTO, ImageDTO } from 'services/api';
import { IAIImageFallback } from 'common/components/IAIImageFallback';
import { boardIdSelected } from 'features/gallery/store/boardSlice';
-import { boardDeleted, boardUpdated } from '../../../../services/thunks/board';
+import {
+ boardDeleted,
+ boardUpdated,
+ imageAddedToBoard,
+} from '../../../../services/thunks/board';
+import { selectImagesAll } from '../../store/imagesSlice';
+import IAIDndImage from '../../../../common/components/IAIDndImage';
+import { defaultSelectorOptions } from '../../../../app/store/util/defaultMemoizeOptions';
+import { createSelector } from '@reduxjs/toolkit';
+
+const selector = createSelector(
+ [selectImagesAll],
+ (images) => {
+ return { images };
+ },
+ defaultSelectorOptions
+);
interface HoverableBoardProps {
board: BoardDTO;
@@ -25,6 +40,7 @@ interface HoverableBoardProps {
const HoverableBoard = memo(({ board, isSelected }: HoverableBoardProps) => {
const dispatch = useAppDispatch();
+ const { images } = useAppSelector(selector);
const { board_name, board_id, cover_image_url } = board;
@@ -45,6 +61,23 @@ const HoverableBoard = memo(({ board, isSelected }: HoverableBoardProps) => {
);
};
+ const handleDrop = useCallback(
+ (droppedImage: ImageDTO) => {
+ if (droppedImage.board_id === board_id) {
+ return;
+ }
+ dispatch(
+ imageAddedToBoard({
+ requestBody: {
+ board_id,
+ image_name: droppedImage.image_name,
+ },
+ })
+ );
+ },
+ [board_id, dispatch]
+ );
+
return (
@@ -91,19 +124,12 @@ const HoverableBoard = memo(({ board, isSelected }: HoverableBoardProps) => {
overflow: 'hidden',
}}
>
- {cover_image_url ? (
- }
- sx={{}}
- />
- ) : (
-
- )}
+ }
+ isUploadDisabled={true}
+ />
{
const boards = useSelector(selectBoardsAll);
- const [selectedBoard, setSelectedBoard] = useState(null);
-
const { isOpen, onClose, handleAddToBoard, image } = useContext(
AddImageToBoardContext
);
+ const [selectedBoard, setSelectedBoard] = useState();
const cancelRef = useRef(null);
@@ -50,10 +49,12 @@ const UpdateImageBoardModal = () => {
-
- Moving this image to a board will remove it from its existing
- board.
-
+ {currentBoard && (
+
+ Moving this image from{' '}
+ {currentBoard.board_name} to
+
+ )}
setSelectedBoard(v)}
diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx
index 647477ce39..c1c414ad8b 100644
--- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx
@@ -240,39 +240,10 @@ const ImageGalleryContent = () => {
icon={}
/>
- {selectedBoard && (
-
- {selectedBoard.board_name}
-
- )}
+
+ {selectedBoard ? selectedBoard.board_name : 'All Images'}
+
- {/* }
- />
- }
- >
-
- setNewBoardName(e.target.value)}
- />
-
- Create
-
-
- */}