mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-03-04 10:11:23 +01:00
decent queue display
This commit is contained in:
parent
fd2961ecb9
commit
129839ce21
@ -1,41 +0,0 @@
|
||||
import React from "react";
|
||||
import { doStopImage } from "../../../api";
|
||||
import { useImageQueue } from "../../../stores/imageQueueStore";
|
||||
import { BrandedButton } from "../../../styles/shared.css";
|
||||
|
||||
import { useCreateUI } from "../../../components/organisms/creationPanel/creationPanelUIStore";
|
||||
|
||||
export default function ClearQueue() {
|
||||
|
||||
const hasQueue = useImageQueue((state) => state.hasQueuedImages());
|
||||
const clearQueue = useImageQueue((state) => state.clearQueue);
|
||||
|
||||
const showQueue = useCreateUI((state) => state.showQueue);
|
||||
const toggleQueue = useCreateUI((state) => state.toggleQueue);
|
||||
|
||||
|
||||
const stopAll = async () => {
|
||||
console.log("stopAll");
|
||||
try {
|
||||
clearQueue();
|
||||
const res = await doStopImage();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<button className={BrandedButton} disabled={!hasQueue} onClick={() => void stopAll()}>Clear Queue</button>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={showQueue}
|
||||
onChange={() => toggleQueue()}
|
||||
>
|
||||
</input>
|
||||
Display
|
||||
</label>
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import React from "react";
|
||||
import { doStopImage } from "../../../api";
|
||||
import { useRequestQueue } from "../../../stores/requestQueueStore";
|
||||
import { BrandedButton } from "../../../styles/shared.css";
|
||||
|
||||
export default function ClearQueue() {
|
||||
|
||||
const hasQueue = useRequestQueue((state) => state.hasPendingQueue());
|
||||
const clearQueue = useRequestQueue((state) => state.clearQueue);
|
||||
|
||||
const stopAll = async () => {
|
||||
try {
|
||||
clearQueue();
|
||||
const res = await doStopImage();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<button className={BrandedButton} disabled={!hasQueue} onClick={() => void stopAll()}>
|
||||
Stop ALL
|
||||
</button>
|
||||
);
|
||||
}
|
@ -2,7 +2,11 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
|
||||
import { useImageCreate } from "../../../stores/imageCreateStore";
|
||||
import { useImageQueue } from "../../../stores/imageQueueStore";
|
||||
import {
|
||||
QueueStatus,
|
||||
useRequestQueue
|
||||
} from "../../../stores/requestQueueStore";
|
||||
|
||||
import {
|
||||
FetchingStates,
|
||||
useImageFetching
|
||||
@ -42,10 +46,10 @@ export default function MakeButton() {
|
||||
|
||||
const isSoundEnabled = useImageCreate((state) => state.isSoundEnabled());
|
||||
|
||||
const addNewImage = useImageQueue((state) => state.addNewImage);
|
||||
const hasQueue = useImageQueue((state) => state.hasQueuedImages());
|
||||
const removeFirstInQueue = useImageQueue((state) => state.removeFirstInQueue);
|
||||
const { id, options } = useImageQueue((state) => state.firstInQueue());
|
||||
const addtoQueue = useRequestQueue((state) => state.addtoQueue);
|
||||
const hasQueue = useRequestQueue((state) => state.hasPendingQueue());
|
||||
const { id, options } = useRequestQueue((state) => state.firstInQueue());
|
||||
const updateQueueStatus = useRequestQueue((state) => state.updateStatus);
|
||||
|
||||
const status = useImageFetching((state) => state.status);
|
||||
const setStatus = useImageFetching((state) => state.setStatus);
|
||||
@ -64,7 +68,11 @@ export default function MakeButton() {
|
||||
try {
|
||||
const parsed = JSON.parse(jsonStr);
|
||||
const { status, request, output: outputs } = parsed as ImageReturnType;
|
||||
|
||||
|
||||
if (status === 'succeeded') {
|
||||
|
||||
updateQueueStatus(id, QueueStatus.complete);
|
||||
outputs.forEach((output: any, index: number) => {
|
||||
|
||||
const { data, seed } = output as ImageOutput;
|
||||
@ -79,10 +87,12 @@ export default function MakeButton() {
|
||||
|
||||
else {
|
||||
console.warn(`Unexpected status: ${status}`);
|
||||
updateQueueStatus(id, QueueStatus.error);
|
||||
}
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
updateQueueStatus(id, QueueStatus.error);
|
||||
console.log("Error HACKING JSON: ", e)
|
||||
}
|
||||
}
|
||||
@ -143,7 +153,7 @@ export default function MakeButton() {
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.log('EXPECTED PARSE ERRROR')
|
||||
// console.log('EXPECTED PARSE ERRROR')
|
||||
finalJSON += jsonStr;
|
||||
}
|
||||
|
||||
@ -152,8 +162,8 @@ export default function MakeButton() {
|
||||
|
||||
const startStream = async (id: string, req: ImageRequest) => {
|
||||
|
||||
|
||||
try {
|
||||
updateQueueStatus(id, QueueStatus.processing);
|
||||
resetForFetching();
|
||||
const res = await doMakeImage(req);
|
||||
const reader = res.body?.getReader();
|
||||
@ -164,6 +174,7 @@ export default function MakeButton() {
|
||||
|
||||
} catch (e) {
|
||||
console.log('TOP LINE STREAM ERROR')
|
||||
updateQueueStatus(id, QueueStatus.error);
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
@ -201,7 +212,7 @@ export default function MakeButton() {
|
||||
seed = useRandomSeed();
|
||||
}
|
||||
// add the request to the queue
|
||||
addNewImage(uuidv4(), {
|
||||
addtoQueue(uuidv4(), {
|
||||
...req,
|
||||
// updated the number of images to make
|
||||
num_outputs: num,
|
||||
@ -224,7 +235,7 @@ export default function MakeButton() {
|
||||
|
||||
useEffect(() => {
|
||||
const makeImages = async (options: ImageRequest) => {
|
||||
removeFirstInQueue();
|
||||
// removeFirstInQueue();
|
||||
await startStream(id ?? "", options);
|
||||
}
|
||||
|
||||
@ -238,6 +249,7 @@ export default function MakeButton() {
|
||||
console.log('req is undefined');
|
||||
return;
|
||||
}
|
||||
|
||||
makeImages(options).catch((e) => {
|
||||
console.log('HAS QUEUE ERROR');
|
||||
console.log(e);
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
import { useImageCreate } from "../../../../../stores/imageCreateStore";
|
||||
import ModifierTag from "../../../../atoms/modifierTag";
|
||||
import ModifierTag from "../../../../molecules/modifierTag";
|
||||
|
||||
export default function ActiveTags() {
|
||||
const selectedtags = useImageCreate((state) => state.selectedTags());
|
||||
|
@ -1,8 +1,10 @@
|
||||
import React from "react";
|
||||
|
||||
import MakeButton from "../../../../atoms/makeButton";
|
||||
import StopButton from "../../../../atoms/stopButton";
|
||||
import ClearQueue from "../../../../atoms/clearQueue";
|
||||
import MakeButton from "../../../../molecules/makeButton";
|
||||
// import StopButton from "../../../../molecules/stopButton";
|
||||
// import ClearQueue from "../../../../molecules/clearQueue";
|
||||
|
||||
import ShowQueue from "../showQueue";
|
||||
|
||||
import {
|
||||
StopContainer
|
||||
@ -12,10 +14,11 @@ export default function CreationActions() {
|
||||
return (
|
||||
<div>
|
||||
<MakeButton></MakeButton>
|
||||
<div className={StopContainer}>
|
||||
<ShowQueue></ShowQueue>
|
||||
{/* <div className={StopContainer}>
|
||||
<StopButton></StopButton>
|
||||
<ClearQueue></ClearQueue>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -37,12 +37,6 @@ export default function BasicCreation() {
|
||||
|
||||
<CreationActions></CreationActions>
|
||||
|
||||
{/* <MakeButton></MakeButton>
|
||||
<div>
|
||||
<StopButton></StopButton>
|
||||
<ClearQueue></ClearQueue>
|
||||
</div> */}
|
||||
|
||||
<SeedImage></SeedImage>
|
||||
<ActiveTags></ActiveTags>
|
||||
</div>
|
||||
|
@ -0,0 +1,21 @@
|
||||
import React from "react";
|
||||
|
||||
import { useCreateUI } from "../../creationPanelUIStore";
|
||||
|
||||
export default function ShowQueue() {
|
||||
|
||||
const showQueue = useCreateUI((state) => state.showQueue);
|
||||
const toggleQueue = useCreateUI((state) => state.toggleQueue);
|
||||
|
||||
return (
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={showQueue}
|
||||
onChange={() => toggleQueue()}
|
||||
>
|
||||
</input>
|
||||
Display
|
||||
</label>
|
||||
);
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
import { style } from "@vanilla-extract/css";
|
||||
|
||||
import { PanelBox } from "../../../styles/shared.css";
|
||||
export const CreationPaneMain = style({
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
padding: "0 10px",
|
||||
overflowY: "auto",
|
||||
overflowX: "hidden",
|
||||
});
|
||||
|
||||
export const InpaintingSlider = style({
|
||||
@ -16,10 +17,11 @@ export const InpaintingSlider = style({
|
||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||
});
|
||||
|
||||
export const QueueSlider = style({
|
||||
export const QueueSlider = style([PanelBox, {
|
||||
position: "absolute",
|
||||
top: "10px",
|
||||
left: "400px",
|
||||
zIndex: 1,
|
||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||
});
|
||||
maxHeight: "90%",
|
||||
overflowY: "auto",
|
||||
}]);
|
@ -15,7 +15,7 @@ import {
|
||||
import { ModifierObject, useImageCreate } from "../../../../stores/imageCreateStore";
|
||||
import { useCreateUI } from "../creationPanelUIStore";
|
||||
|
||||
import ModifierTag from "../../../atoms/modifierTag";
|
||||
import ModifierTag from "../../../molecules/modifierTag";
|
||||
|
||||
interface ModifierListProps {
|
||||
category: string;
|
||||
|
@ -11,7 +11,7 @@ import QueueDisplay from "../queueDisplay";
|
||||
// import { useImageCreate } from "@stores/imageCreateStore.ts";
|
||||
|
||||
import { useImageCreate } from "../../../stores/imageCreateStore";
|
||||
import { useImageQueue } from "../../../stores/imageQueueStore";
|
||||
import { useRequestQueue } from "../../../stores/requestQueueStore";
|
||||
|
||||
import { useCreateUI } from "./creationPanelUIStore";
|
||||
|
||||
@ -24,12 +24,11 @@ import {
|
||||
} from "./creationPanel.css";
|
||||
|
||||
|
||||
|
||||
export default function CreationPanel() {
|
||||
const isInPaintingMode = useImageCreate((state) => state.isInpainting);
|
||||
|
||||
const showQueue = useCreateUI((state) => state.showQueue);
|
||||
const hasQueue = useImageQueue((state) => state.hasQueuedImages());
|
||||
const hasQueue = useRequestQueue((state) => state.hasAnyQueue());
|
||||
|
||||
// console.log('hasQueue', hasQueue);
|
||||
console.log('showQueue', showQueue);
|
||||
@ -48,7 +47,7 @@ export default function CreationPanel() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(showQueue) && (
|
||||
{(showQueue && hasQueue) && (
|
||||
<div className={QueueSlider}>
|
||||
<QueueDisplay></QueueDisplay>
|
||||
</div>
|
||||
|
@ -1,24 +1,45 @@
|
||||
import React from "react";
|
||||
import { ImageRequest } from "../../../api";
|
||||
|
||||
import { useImageQueue } from "../../../stores/imageQueueStore";
|
||||
|
||||
import { QueuedRequest, useRequestQueue } from "../../../stores/requestQueueStore";
|
||||
|
||||
import {
|
||||
QueueDisplayMain
|
||||
QueueDisplayMain,
|
||||
QueueListButtons,
|
||||
CompleteButtton,
|
||||
ErrorButton
|
||||
} from "./queueDisplay.css";
|
||||
|
||||
|
||||
import ClearQueue from "../../molecules/clearQueue";
|
||||
import QueueItem from "./queueItem";
|
||||
|
||||
|
||||
export default function QueueDisplay() {
|
||||
|
||||
const images = useImageQueue((state) => state.images);
|
||||
console.log('images', images);
|
||||
const requests: QueuedRequest[] = useRequestQueue((state) => state.requests);
|
||||
const removeCompleted = useRequestQueue((state) => state.removeCompleted);
|
||||
const removeErrored = useRequestQueue((state) => state.removeErrored);
|
||||
|
||||
const clearCompleted = () => {
|
||||
console.log('clear completed');
|
||||
removeCompleted();
|
||||
}
|
||||
|
||||
const clearErrored = () => {
|
||||
console.log('clear errored');
|
||||
removeErrored();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={QueueDisplayMain}>
|
||||
{images.map((image) => {
|
||||
return <QueueItem key={image.id} info={image}></QueueItem>;
|
||||
<ClearQueue />
|
||||
<div className={QueueListButtons}>
|
||||
<button className={CompleteButtton} onClick={clearCompleted}>Clear Completed</button>
|
||||
<button className={ErrorButton} onClick={clearErrored}>Clear Errored</button>
|
||||
</div>
|
||||
{requests.map((request) => {
|
||||
return <QueueItem key={request.id} request={request}></QueueItem>;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
|
@ -1,10 +1,39 @@
|
||||
import { style } from "@vanilla-extract/css";
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
|
||||
import { BrandedButton } from "../../../styles/shared.css";
|
||||
|
||||
import { vars } from "../../../styles/theme/index.css";
|
||||
|
||||
export const QueueDisplayMain = style({
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: '400px',
|
||||
height: '100%',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
|
||||
});
|
||||
|
||||
export const QueueListButtons = style({
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: vars.spacing.medium,
|
||||
marginTop: vars.spacing.medium,
|
||||
});
|
||||
|
||||
globalStyle(`${QueueListButtons} button`, {
|
||||
flexGrow: 1,
|
||||
});
|
||||
|
||||
globalStyle(`${QueueListButtons} button:first-child`, {
|
||||
marginRight: vars.spacing.medium,
|
||||
});
|
||||
|
||||
|
||||
// TODO these should be a button recipe?
|
||||
export const CompleteButtton = style([BrandedButton, {
|
||||
|
||||
}]);
|
||||
|
||||
export const ErrorButton = style([BrandedButton, {
|
||||
|
||||
}]);
|
@ -1,20 +1,37 @@
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
QueueItemMain
|
||||
} from "./queueItem.css";
|
||||
|
||||
import {
|
||||
ImageRequest
|
||||
} from '../../../../api'
|
||||
|
||||
import { QueueStatus, QueuedRequest, useRequestQueue } from '../../../../stores/requestQueueStore';
|
||||
|
||||
import StopButton from '../../../molecules/stopButton';
|
||||
|
||||
import {
|
||||
QueueItemMain,
|
||||
QueueButtons,
|
||||
CompleteButtton,
|
||||
PauseButton,
|
||||
ResumeButton,
|
||||
CancelButton,
|
||||
RetryButton,
|
||||
SendToTopButton,
|
||||
} from "./queueItem.css";
|
||||
|
||||
|
||||
interface QueueItemProps {
|
||||
info: ImageRequest
|
||||
request: QueuedRequest;
|
||||
}
|
||||
|
||||
export default function QueueItem({ info }: QueueItemProps) {
|
||||
export default function QueueItem({ request }: QueueItemProps) {
|
||||
|
||||
console.log('info', info);
|
||||
// console.log('info', info);
|
||||
// console.log('status', status);
|
||||
|
||||
const removeItem = useRequestQueue((state) => state.removeItem);
|
||||
const updateStatus = useRequestQueue((state) => state.updateStatus);
|
||||
const sendPendingToTop = useRequestQueue((state) => state.sendPendingToTop);
|
||||
|
||||
const {
|
||||
id,
|
||||
@ -23,16 +40,64 @@ export default function QueueItem({ info }: QueueItemProps) {
|
||||
seed,
|
||||
sampler,
|
||||
},
|
||||
// status,
|
||||
} = info;
|
||||
status,
|
||||
} = request;
|
||||
|
||||
const removeFromQueue = () => {
|
||||
console.log('remove from queue');
|
||||
removeItem(id);
|
||||
}
|
||||
|
||||
const pauseItem = () => {
|
||||
console.log('pause item');
|
||||
updateStatus(id, QueueStatus.paused);
|
||||
}
|
||||
|
||||
const retryRequest = () => {
|
||||
console.log('retry request');
|
||||
updateStatus(id, QueueStatus.pending);
|
||||
}
|
||||
|
||||
const sendToTop = () => {
|
||||
console.log('send to top');
|
||||
sendPendingToTop(id);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={QueueItemMain}>
|
||||
<div>{id}</div>
|
||||
<div className={[QueueItemMain, status].join(' ')}>
|
||||
{/* @ts-expect-error */}
|
||||
<div>{status}</div>
|
||||
<div>{prompt}</div>
|
||||
<div>{seed}</div>
|
||||
<div>{sampler}</div>
|
||||
|
||||
<div className={QueueButtons}>
|
||||
|
||||
{status === QueueStatus.processing && (
|
||||
<StopButton></StopButton>
|
||||
)}
|
||||
|
||||
{status === QueueStatus.complete && (
|
||||
<button className={CompleteButtton} onClick={removeFromQueue}>Clear</button>
|
||||
)}
|
||||
|
||||
{status === QueueStatus.pending && (
|
||||
<>
|
||||
<button className={CancelButton} onClick={removeFromQueue}>Remove</button>
|
||||
<button className={PauseButton} onClick={pauseItem}>Pause</button>
|
||||
<button className={SendToTopButton} onClick={sendToTop}>Send to top</button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{status === QueueStatus.paused && (
|
||||
<button className={ResumeButton} onClick={retryRequest}>Resume</button>
|
||||
)}
|
||||
|
||||
{status === QueueStatus.error && (
|
||||
<button className={RetryButton} onClick={retryRequest}>Retry</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,9 +1,68 @@
|
||||
import { style } from "@vanilla-extract/css";
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
|
||||
|
||||
import { vars } from "../../../../styles/theme/index.css";
|
||||
|
||||
import { BrandedButton } from "../../../../styles/shared.css";
|
||||
|
||||
import { QueueStatus } from "../../../../stores/requestQueueStore";
|
||||
|
||||
export const QueueItemMain = style({
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
padding: "0.5rem",
|
||||
});
|
||||
});
|
||||
|
||||
globalStyle(`${QueueItemMain}.${QueueStatus.processing}`, {
|
||||
backgroundColor: vars.colors.warning,
|
||||
});
|
||||
|
||||
globalStyle(`${QueueItemMain}.${QueueStatus.pending}`, {
|
||||
backgroundColor: vars.colors.backgroundDark,
|
||||
});
|
||||
|
||||
globalStyle(`${QueueItemMain}.${QueueStatus.paused}`, {
|
||||
backgroundColor: vars.colors.backgroundAlt,
|
||||
});
|
||||
|
||||
globalStyle(`${QueueItemMain}.${QueueStatus.complete}`, {
|
||||
backgroundColor: vars.colors.success,
|
||||
});
|
||||
|
||||
globalStyle(`${QueueItemMain}.${QueueStatus.error}`, {
|
||||
backgroundColor: vars.colors.error,
|
||||
});
|
||||
|
||||
export const QueueButtons = style({
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
});
|
||||
|
||||
|
||||
// TODO these should be a button recipe?
|
||||
export const CompleteButtton = style([BrandedButton, {
|
||||
|
||||
}]);
|
||||
|
||||
export const PauseButton = style([BrandedButton, {
|
||||
|
||||
}]);
|
||||
|
||||
export const ResumeButton = style([BrandedButton, {
|
||||
|
||||
}]);
|
||||
|
||||
export const CancelButton = style([BrandedButton, {
|
||||
|
||||
}]);
|
||||
|
||||
export const RetryButton = style([BrandedButton, {
|
||||
|
||||
}]);
|
||||
|
||||
export const SendToTopButton = style([BrandedButton, {
|
||||
|
||||
}]);
|
||||
|
@ -27,7 +27,6 @@ interface ImageFetchingState {
|
||||
setStartTime: () => void;
|
||||
setNowTime: () => void;
|
||||
resetForFetching: () => void;
|
||||
|
||||
}
|
||||
|
||||
export const useImageFetching = create<ImageFetchingState>((set) => ({
|
||||
|
@ -1,78 +0,0 @@
|
||||
import create from "zustand";
|
||||
import produce from "immer";
|
||||
import { useRandomSeed } from "../utils";
|
||||
|
||||
import { ImageRequest } from "../api";
|
||||
|
||||
interface QueueItem {
|
||||
id?: string;
|
||||
options?: ImageRequest;
|
||||
status?: "pending" | "complete" | "error";
|
||||
}
|
||||
|
||||
interface ImageQueueState {
|
||||
images: QueueItem[];
|
||||
completedImageIds: string[];
|
||||
addNewImage: (id: string, imgRec: ImageRequest) => void;
|
||||
hasQueuedImages: () => boolean;
|
||||
firstInQueue: () => QueueItem;
|
||||
removeFirstInQueue: () => void;
|
||||
clearQueue: () => void;
|
||||
clearCachedIds: () => void;
|
||||
}
|
||||
|
||||
export const useImageQueue = create<ImageQueueState>((set, get) => ({
|
||||
images: [],
|
||||
completedImageIds: [],
|
||||
// use produce to make sure we don't mutate state
|
||||
addNewImage: (id: string, imgRec: ImageRequest) => {
|
||||
set(
|
||||
produce((state) => {
|
||||
const item: QueueItem = { id, options: imgRec, status: "pending" };
|
||||
state.images.push(item);
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
hasQueuedImages: () => {
|
||||
return get().images.length > 0;
|
||||
},
|
||||
|
||||
firstInQueue: () => {
|
||||
const { images } = get();
|
||||
if (images.length > 0) {
|
||||
return images[0];
|
||||
}
|
||||
// // cast an empty object to QueueItem
|
||||
const empty: QueueItem = {};
|
||||
return empty;
|
||||
|
||||
},
|
||||
|
||||
removeFirstInQueue: () => {
|
||||
set(
|
||||
produce((state) => {
|
||||
const image = state.images.shift();
|
||||
if (void 0 !== image) {
|
||||
state.completedImageIds.push(image.id);
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
clearQueue: () => {
|
||||
set(
|
||||
produce((state) => {
|
||||
state.images = [];
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
clearCachedIds: () => {
|
||||
set(
|
||||
produce((state) => {
|
||||
state.completedImageIds = [];
|
||||
})
|
||||
);
|
||||
},
|
||||
}));
|
143
ui/frontend/build_src/src/stores/requestQueueStore.ts
Normal file
143
ui/frontend/build_src/src/stores/requestQueueStore.ts
Normal file
@ -0,0 +1,143 @@
|
||||
import create from "zustand";
|
||||
import produce from "immer";
|
||||
|
||||
import { ImageRequest } from "../api";
|
||||
|
||||
export enum QueueStatus {
|
||||
pending = "pending",
|
||||
processing = "processing",
|
||||
complete = "complete",
|
||||
paused = "paused",
|
||||
error = "error",
|
||||
}
|
||||
|
||||
export interface QueuedRequest {
|
||||
id: string;
|
||||
options: ImageRequest;
|
||||
status: QueueStatus[keyof QueueStatus];
|
||||
//"pending" | "processing" | "complete" | "error";
|
||||
}
|
||||
|
||||
interface RequestQueueState {
|
||||
requests: QueuedRequest[];
|
||||
addtoQueue: (id: string, imgRec: ImageRequest) => void;
|
||||
pendingRequests: () => QueuedRequest[];
|
||||
hasPendingQueue: () => boolean;
|
||||
hasAnyQueue: () => boolean;
|
||||
firstInQueue: () => QueuedRequest;
|
||||
updateStatus: (id: string, status: QueueStatus[keyof QueueStatus]) => void;
|
||||
sendPendingToTop: (id: string) => void;
|
||||
removeItem: (id: string) => void;
|
||||
removeCompleted: () => void;
|
||||
removeErrored: () => void;
|
||||
clearQueue: () => void;
|
||||
|
||||
}
|
||||
|
||||
export const useRequestQueue = create<RequestQueueState>((set, get) => ({
|
||||
requests: [],
|
||||
// use produce to make sure we don't mutate state
|
||||
addtoQueue: (id: string, imgRec: ImageRequest) => {
|
||||
set(
|
||||
produce((state) => {
|
||||
const item: QueuedRequest = { id, options: imgRec, status: QueueStatus.pending };
|
||||
state.requests.push(item);
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
pendingRequests: () => {
|
||||
return get().requests.filter((item) => item.status === QueueStatus.pending);
|
||||
},
|
||||
|
||||
hasPendingQueue: () => {
|
||||
return get().pendingRequests().length > 0;
|
||||
},
|
||||
|
||||
hasAnyQueue: () => {
|
||||
return get().requests.length > 0;
|
||||
},
|
||||
|
||||
firstInQueue: () => {
|
||||
const pending = get().pendingRequests()[0];
|
||||
|
||||
if (pending === undefined) {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const temp: QueuedRequest = { id: "", options: ({} as ImageRequest), status: QueueStatus.pending };
|
||||
return temp;
|
||||
}
|
||||
return pending;
|
||||
},
|
||||
|
||||
updateStatus: (id: string, status: QueueStatus[keyof QueueStatus]) => {
|
||||
set(
|
||||
produce((state) => {
|
||||
const item = state.requests.find((item: QueuedRequest) => item.id === id);
|
||||
if (void 0 !== item) {
|
||||
item.status = status;
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
sendPendingToTop: (id: string) => {
|
||||
set(
|
||||
produce((state) => {
|
||||
const item = state.requests.find((item: QueuedRequest) => item.id === id);
|
||||
if (void 0 !== item) {
|
||||
const index = state.requests.indexOf(item);
|
||||
// insert infront of the pending requests
|
||||
const pending = get().pendingRequests();
|
||||
const pendingIndex = state.requests.indexOf(pending[0]);
|
||||
console.log()
|
||||
state.requests.splice(index, 1);
|
||||
state.requests.splice(pendingIndex, 0, item);
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
removeItem: (id: string) => {
|
||||
set(
|
||||
produce((state) => {
|
||||
const index = state.requests.findIndex((item: QueuedRequest) => item.id === id);
|
||||
if (index > -1) {
|
||||
state.requests.splice(index, 1);
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
removeCompleted: () => {
|
||||
set(
|
||||
produce((state) => {
|
||||
const completed = state.requests.filter((item: QueuedRequest) => item.status === QueueStatus.complete);
|
||||
completed.forEach((item: QueuedRequest) => {
|
||||
const index = state.requests.indexOf(item);
|
||||
state.requests.splice(index, 1);
|
||||
});
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
removeErrored: () => {
|
||||
set(
|
||||
produce((state) => {
|
||||
const errored = state.requests.filter((item: QueuedRequest) => item.status === QueueStatus.error);
|
||||
errored.forEach((item: QueuedRequest) => {
|
||||
const index = state.requests.indexOf(item);
|
||||
state.requests.splice(index, 1);
|
||||
});
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
clearQueue: () => {
|
||||
set(
|
||||
produce((state) => {
|
||||
state.requests = [];
|
||||
})
|
||||
);
|
||||
},
|
||||
}));
|
Loading…
Reference in New Issue
Block a user