mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
stubbing out change board functionality
This commit is contained in:
committed by
Mary Hipp Rogers
parent
a918198d4f
commit
67042e6dec
38
invokeai/app/api/routers/board_videos.py
Normal file
38
invokeai/app/api/routers/board_videos.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from fastapi import Body, HTTPException
|
||||
from fastapi.routing import APIRouter
|
||||
|
||||
from invokeai.app.services.videos_common import AddVideosToBoardResult, RemoveVideosFromBoardResult
|
||||
|
||||
board_videos_router = APIRouter(prefix="/v1/board_videos", tags=["boards"])
|
||||
|
||||
@board_videos_router.post(
|
||||
"/batch",
|
||||
operation_id="add_videos_to_board",
|
||||
responses={
|
||||
201: {"description": "Videos were added to board successfully"},
|
||||
},
|
||||
status_code=201,
|
||||
response_model=AddVideosToBoardResult,
|
||||
)
|
||||
async def add_videos_to_board(
|
||||
board_id: str = Body(description="The id of the board to add to"),
|
||||
video_ids: list[str] = Body(description="The ids of the videos to add", embed=True),
|
||||
) -> AddVideosToBoardResult:
|
||||
"""Adds a list of videos to a board"""
|
||||
raise HTTPException(status_code=501, detail="Not implemented")
|
||||
|
||||
|
||||
@board_videos_router.post(
|
||||
"/batch/delete",
|
||||
operation_id="remove_videos_from_board",
|
||||
responses={
|
||||
201: {"description": "Videos were removed from board successfully"},
|
||||
},
|
||||
status_code=201,
|
||||
response_model=RemoveVideosFromBoardResult,
|
||||
)
|
||||
async def remove_videos_from_board(
|
||||
video_ids: list[str] = Body(description="The ids of the videos to remove", embed=True),
|
||||
) -> RemoveVideosFromBoardResult:
|
||||
"""Removes a list of videos from their board, if they had one"""
|
||||
raise HTTPException(status_code=501, detail="Not implemented")
|
||||
@@ -20,6 +20,7 @@ from invokeai.app.api.routers import (
|
||||
board_images,
|
||||
boards,
|
||||
client_state,
|
||||
board_videos,
|
||||
download_queue,
|
||||
images,
|
||||
model_manager,
|
||||
@@ -129,6 +130,7 @@ app.include_router(images.images_router, prefix="/api")
|
||||
app.include_router(videos.videos_router, prefix="/api")
|
||||
app.include_router(boards.boards_router, prefix="/api")
|
||||
app.include_router(board_images.board_images_router, prefix="/api")
|
||||
app.include_router(board_videos.board_videos_router, prefix="/api")
|
||||
app.include_router(model_relationships.model_relationships_router, prefix="/api")
|
||||
app.include_router(app_info.app_router, prefix="/api")
|
||||
app.include_router(session_queue.session_queue_router, prefix="/api")
|
||||
|
||||
@@ -5,14 +5,15 @@ import { imageDownloaded } from 'features/gallery/store/actions';
|
||||
import { toast } from 'features/toast/toast';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ImageDTO, VideoDTO } from 'services/api/types';
|
||||
|
||||
export const useDownloadImage = () => {
|
||||
export const useDownloadItem = (itemDTO: ImageDTO | VideoDTO) => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const authToken = useStore($authToken);
|
||||
|
||||
const downloadImage = useCallback(
|
||||
async (image_url: string, image_name: string) => {
|
||||
const downloadItem = useCallback(
|
||||
async (item_url: string, item_id: string) => {
|
||||
try {
|
||||
const requestOpts = authToken
|
||||
? {
|
||||
@@ -21,7 +22,7 @@ export const useDownloadImage = () => {
|
||||
},
|
||||
}
|
||||
: {};
|
||||
const blob = await fetch(image_url, requestOpts).then((resp) => resp.blob());
|
||||
const blob = await fetch(item_url, requestOpts).then((resp) => resp.blob());
|
||||
if (!blob) {
|
||||
throw new Error('Unable to create Blob');
|
||||
}
|
||||
@@ -30,7 +31,7 @@ export const useDownloadImage = () => {
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none';
|
||||
a.href = url;
|
||||
a.download = image_name;
|
||||
a.download = item_id;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
@@ -47,5 +48,5 @@ export const useDownloadImage = () => {
|
||||
[t, dispatch, authToken]
|
||||
);
|
||||
|
||||
return { downloadImage };
|
||||
return { downloadItem };
|
||||
};
|
||||
|
||||
@@ -4,11 +4,13 @@ import { useItemDTOContext } from 'features/gallery/contexts/ItemDTOContext';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiTrashSimpleBold } from 'react-icons/pi';
|
||||
import { useDeleteVideosMutation } from 'services/api/endpoints/videos';
|
||||
import { isImageDTO } from 'services/api/types';
|
||||
|
||||
export const ContextMenuItemDelete = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const deleteImageModal = useDeleteImageModalApi();
|
||||
const [deleteVideos] = useDeleteVideosMutation();
|
||||
const itemDTO = useItemDTOContext();
|
||||
|
||||
const onClick = useCallback(async () => {
|
||||
@@ -16,12 +18,13 @@ export const ContextMenuItemDelete = memo(() => {
|
||||
if (isImageDTO(itemDTO)) {
|
||||
await deleteImageModal.delete([itemDTO.image_name]);
|
||||
} else {
|
||||
// await deleteVideoModal.delete([itemDTO.video_id]);
|
||||
// TODO: Add confirm on delete and video usage functionality
|
||||
await deleteVideos({ video_ids: [itemDTO.video_id] });
|
||||
}
|
||||
} catch {
|
||||
// noop;
|
||||
}
|
||||
}, [deleteImageModal, itemDTO]);
|
||||
}, [deleteImageModal, deleteVideos, itemDTO]);
|
||||
|
||||
return (
|
||||
<IconMenuItem
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IconMenuItem } from 'common/components/IconMenuItem';
|
||||
import { useDownloadImage } from 'common/hooks/useDownloadImage';
|
||||
import { useDownloadItem } from 'common/hooks/useDownloadImage';
|
||||
import { useItemDTOContext } from 'features/gallery/contexts/ItemDTOContext';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -9,15 +9,15 @@ import { isImageDTO } from 'services/api/types';
|
||||
export const ContextMenuItemDownload = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const itemDTO = useItemDTOContext();
|
||||
const { downloadImage } = useDownloadImage();
|
||||
const { downloadItem } = useDownloadItem(itemDTO);
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
if (isImageDTO(itemDTO)) {
|
||||
downloadImage(itemDTO.image_url, itemDTO.image_name);
|
||||
downloadItem(itemDTO.image_url, itemDTO.image_name);
|
||||
} else {
|
||||
// downloadVideo(itemDTO.video_url, itemDTO.video_id);
|
||||
downloadItem(itemDTO.video_url, itemDTO.video_id);
|
||||
}
|
||||
}, [downloadImage, itemDTO]);
|
||||
}, [downloadItem, itemDTO]);
|
||||
|
||||
return (
|
||||
<IconMenuItem
|
||||
|
||||
@@ -16,7 +16,7 @@ export const ContextMenuItemOpenInNewTab = memo(() => {
|
||||
window.open(itemDTO.image_url, '_blank');
|
||||
dispatch(imageOpenedInNewTab());
|
||||
} else {
|
||||
// TODO: Implement video open in new tab
|
||||
window.open(itemDTO.video_url, '_blank');
|
||||
}
|
||||
}, [itemDTO, dispatch]);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import stableHash from 'stable-hash';
|
||||
import type { Param0 } from 'tsafe';
|
||||
|
||||
import { api, buildV1Url, LIST_TAG } from '..';
|
||||
import { getTagsToInvalidateForBoardAffectingMutation, getTagsToInvalidateForVideoMutation } from '../util/tagInvalidation';
|
||||
import { getTagsToInvalidateForBoardAffectingMutation, getTagsToInvalidateForImageMutation, getTagsToInvalidateForVideoMutation } from '../util/tagInvalidation';
|
||||
|
||||
/**
|
||||
* Builds an endpoint URL for the videos router
|
||||
@@ -19,6 +19,8 @@ import { getTagsToInvalidateForBoardAffectingMutation, getTagsToInvalidateForVid
|
||||
const buildVideosUrl = (path: string = '', query?: Parameters<typeof buildV1Url>[1]) =>
|
||||
buildV1Url(`videos/${path}`, query);
|
||||
|
||||
const buildBoardVideosUrl = (path: string = '') => buildV1Url(`board_videos/${path}`);
|
||||
|
||||
export const videosApi = api.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
/**
|
||||
@@ -150,6 +152,44 @@ export const videosApi = api.injectEndpoints({
|
||||
];
|
||||
},
|
||||
}),
|
||||
addVideosToBoard: build.mutation<
|
||||
paths['/api/v1/board_videos/batch']['post']['responses']['201']['content']['application/json'],
|
||||
paths['/api/v1/board_videos/batch']['post']['requestBody']['content']['application/json']
|
||||
>({
|
||||
query: (body) => ({
|
||||
url: buildBoardVideosUrl('batch'),
|
||||
method: 'POST',
|
||||
body,
|
||||
}),
|
||||
invalidatesTags: (result) => {
|
||||
if (!result) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
...getTagsToInvalidateForVideoMutation(result.added_videos),
|
||||
...getTagsToInvalidateForBoardAffectingMutation(result.affected_boards),
|
||||
];
|
||||
},
|
||||
}),
|
||||
removeVideosFromBoard: build.mutation<
|
||||
paths['/api/v1/board_videos/batch/delete']['post']['responses']['201']['content']['application/json'],
|
||||
paths['/api/v1/board_videos/batch/delete']['post']['requestBody']['content']['application/json']
|
||||
>({
|
||||
query: (body) => ({
|
||||
url: buildBoardVideosUrl('batch/delete'),
|
||||
method: 'POST',
|
||||
body,
|
||||
}),
|
||||
invalidatesTags: (result) => {
|
||||
if (!result) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
...getTagsToInvalidateForVideoMutation(result.removed_videos),
|
||||
...getTagsToInvalidateForBoardAffectingMutation(result.affected_boards),
|
||||
];
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -160,6 +200,8 @@ export const {
|
||||
useStarVideosMutation,
|
||||
useUnstarVideosMutation,
|
||||
useDeleteVideosMutation,
|
||||
useAddVideosToBoardMutation,
|
||||
useRemoveVideosFromBoardMutation,
|
||||
} = videosApi;
|
||||
|
||||
|
||||
|
||||
@@ -1083,6 +1083,46 @@ export type paths = {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/board_videos/batch": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/**
|
||||
* Add Videos To Board
|
||||
* @description Adds a list of videos to a board
|
||||
*/
|
||||
post: operations["add_videos_to_board"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/board_videos/batch/delete": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/**
|
||||
* Remove Videos From Board
|
||||
* @description Removes a list of videos from their board, if they had one
|
||||
*/
|
||||
post: operations["remove_videos_from_board"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/model_relationships/i/{model_key}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -2087,6 +2127,19 @@ export type components = {
|
||||
*/
|
||||
type: "add";
|
||||
};
|
||||
/** AddVideosToBoardResult */
|
||||
AddVideosToBoardResult: {
|
||||
/**
|
||||
* Affected Boards
|
||||
* @description The ids of boards affected by the delete operation
|
||||
*/
|
||||
affected_boards: string[];
|
||||
/**
|
||||
* Added Videos
|
||||
* @description The video ids that were added to the board
|
||||
*/
|
||||
added_videos: string[];
|
||||
};
|
||||
/**
|
||||
* Alpha Mask to Tensor
|
||||
* @description Convert a mask image to a tensor. Opaque regions are 1 and transparent regions are 0.
|
||||
@@ -2772,6 +2825,19 @@ export type components = {
|
||||
*/
|
||||
image_names: string[];
|
||||
};
|
||||
/** Body_add_videos_to_board */
|
||||
Body_add_videos_to_board: {
|
||||
/**
|
||||
* Board Id
|
||||
* @description The id of the board to add to
|
||||
*/
|
||||
board_id: string;
|
||||
/**
|
||||
* Video Ids
|
||||
* @description The ids of the videos to add
|
||||
*/
|
||||
video_ids: string[];
|
||||
};
|
||||
/** Body_cancel_by_batch_ids */
|
||||
Body_cancel_by_batch_ids: {
|
||||
/**
|
||||
@@ -2957,6 +3023,14 @@ export type components = {
|
||||
*/
|
||||
image_names: string[];
|
||||
};
|
||||
/** Body_remove_videos_from_board */
|
||||
Body_remove_videos_from_board: {
|
||||
/**
|
||||
* Video Ids
|
||||
* @description The ids of the videos to remove
|
||||
*/
|
||||
video_ids: string[];
|
||||
};
|
||||
/** Body_set_workflow_thumbnail */
|
||||
Body_set_workflow_thumbnail: {
|
||||
/**
|
||||
@@ -18385,6 +18459,19 @@ export type components = {
|
||||
*/
|
||||
removed_images: string[];
|
||||
};
|
||||
/** RemoveVideosFromBoardResult */
|
||||
RemoveVideosFromBoardResult: {
|
||||
/**
|
||||
* Affected Boards
|
||||
* @description The ids of boards affected by the delete operation
|
||||
*/
|
||||
affected_boards: string[];
|
||||
/**
|
||||
* Removed Videos
|
||||
* @description The video ids that were removed from their board
|
||||
*/
|
||||
removed_videos: string[];
|
||||
};
|
||||
/**
|
||||
* Resize Latents
|
||||
* @description Resizes latents to explicit width/height (in pixels). Provided dimensions are floor-divided by 8.
|
||||
@@ -25148,6 +25235,72 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
add_videos_to_board: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["Body_add_videos_to_board"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Videos were added to board successfully */
|
||||
201: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["AddVideosToBoardResult"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
remove_videos_from_board: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["Body_remove_videos_from_board"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Videos were removed from board successfully */
|
||||
201: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["RemoveVideosFromBoardResult"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
get_related_models: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
Reference in New Issue
Block a user