diff --git a/ui/frontend/build_src/src/components/atoms/clearQueue/index.tsx b/ui/frontend/build_src/src/components/atoms/clearQueue/index.tsx
deleted file mode 100644
index 1818672d..00000000
--- a/ui/frontend/build_src/src/components/atoms/clearQueue/index.tsx
+++ /dev/null
@@ -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 (
- <>
-
-
- >
- );
-}
\ No newline at end of file
diff --git a/ui/frontend/build_src/src/components/molecules/clearQueue/index.tsx b/ui/frontend/build_src/src/components/molecules/clearQueue/index.tsx
new file mode 100644
index 00000000..77a0479e
--- /dev/null
+++ b/ui/frontend/build_src/src/components/molecules/clearQueue/index.tsx
@@ -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 (
+
+ );
+}
\ No newline at end of file
diff --git a/ui/frontend/build_src/src/components/atoms/makeButton/index.tsx b/ui/frontend/build_src/src/components/molecules/makeButton/index.tsx
similarity index 90%
rename from ui/frontend/build_src/src/components/atoms/makeButton/index.tsx
rename to ui/frontend/build_src/src/components/molecules/makeButton/index.tsx
index caf5d295..d0364947 100644
--- a/ui/frontend/build_src/src/components/atoms/makeButton/index.tsx
+++ b/ui/frontend/build_src/src/components/molecules/makeButton/index.tsx
@@ -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);
diff --git a/ui/frontend/build_src/src/components/atoms/makeButton/makeButton.css.ts b/ui/frontend/build_src/src/components/molecules/makeButton/makeButton.css.ts
similarity index 100%
rename from ui/frontend/build_src/src/components/atoms/makeButton/makeButton.css.ts
rename to ui/frontend/build_src/src/components/molecules/makeButton/makeButton.css.ts
diff --git a/ui/frontend/build_src/src/components/atoms/modifierTag/index.tsx b/ui/frontend/build_src/src/components/molecules/modifierTag/index.tsx
similarity index 100%
rename from ui/frontend/build_src/src/components/atoms/modifierTag/index.tsx
rename to ui/frontend/build_src/src/components/molecules/modifierTag/index.tsx
diff --git a/ui/frontend/build_src/src/components/atoms/modifierTag/modifierTags.css.ts b/ui/frontend/build_src/src/components/molecules/modifierTag/modifierTags.css.ts
similarity index 100%
rename from ui/frontend/build_src/src/components/atoms/modifierTag/modifierTags.css.ts
rename to ui/frontend/build_src/src/components/molecules/modifierTag/modifierTags.css.ts
diff --git a/ui/frontend/build_src/src/components/atoms/stopButton/index.tsx b/ui/frontend/build_src/src/components/molecules/stopButton/index.tsx
similarity index 100%
rename from ui/frontend/build_src/src/components/atoms/stopButton/index.tsx
rename to ui/frontend/build_src/src/components/molecules/stopButton/index.tsx
diff --git a/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/activeTags/index.tsx b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/activeTags/index.tsx
index 57b0fd60..6789c4fd 100644
--- a/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/activeTags/index.tsx
+++ b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/activeTags/index.tsx
@@ -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());
diff --git a/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/creationActions/index.tsx b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/creationActions/index.tsx
index 8fb3cf16..dda996b9 100644
--- a/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/creationActions/index.tsx
+++ b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/creationActions/index.tsx
@@ -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 (
);
}
\ No newline at end of file
diff --git a/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/index.tsx b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/index.tsx
index b4097453..63a154ac 100644
--- a/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/index.tsx
+++ b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/index.tsx
@@ -37,12 +37,6 @@ export default function BasicCreation() {
- {/*
-
-
-
-
*/}
-
diff --git a/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/showQueue/index.tsx b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/showQueue/index.tsx
new file mode 100644
index 00000000..cae54ce5
--- /dev/null
+++ b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/showQueue/index.tsx
@@ -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 (
+
+ );
+}
\ No newline at end of file
diff --git a/ui/frontend/build_src/src/components/organisms/creationPanel/creationPanel.css.ts b/ui/frontend/build_src/src/components/organisms/creationPanel/creationPanel.css.ts
index 5ac371c0..b8495f5e 100644
--- a/ui/frontend/build_src/src/components/organisms/creationPanel/creationPanel.css.ts
+++ b/ui/frontend/build_src/src/components/organisms/creationPanel/creationPanel.css.ts
@@ -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)",
-});
\ No newline at end of file
+ maxHeight: "90%",
+ overflowY: "auto",
+}]);
\ No newline at end of file
diff --git a/ui/frontend/build_src/src/components/organisms/creationPanel/imageModifiers/index.tsx b/ui/frontend/build_src/src/components/organisms/creationPanel/imageModifiers/index.tsx
index a0cc296b..c9343d58 100644
--- a/ui/frontend/build_src/src/components/organisms/creationPanel/imageModifiers/index.tsx
+++ b/ui/frontend/build_src/src/components/organisms/creationPanel/imageModifiers/index.tsx
@@ -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;
diff --git a/ui/frontend/build_src/src/components/organisms/creationPanel/index.tsx b/ui/frontend/build_src/src/components/organisms/creationPanel/index.tsx
index 141e0001..ec7a0e13 100644
--- a/ui/frontend/build_src/src/components/organisms/creationPanel/index.tsx
+++ b/ui/frontend/build_src/src/components/organisms/creationPanel/index.tsx
@@ -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() {
)}
- {(showQueue) && (
+ {(showQueue && hasQueue) && (
diff --git a/ui/frontend/build_src/src/components/organisms/queueDisplay/index.tsx b/ui/frontend/build_src/src/components/organisms/queueDisplay/index.tsx
index 46e0cc82..b0ed115a 100644
--- a/ui/frontend/build_src/src/components/organisms/queueDisplay/index.tsx
+++ b/ui/frontend/build_src/src/components/organisms/queueDisplay/index.tsx
@@ -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 (
- {images.map((image) => {
- return
;
+
+
+
+
+
+ {requests.map((request) => {
+ return
;
})}
);
diff --git a/ui/frontend/build_src/src/components/organisms/queueDisplay/queueDisplay.css.ts b/ui/frontend/build_src/src/components/organisms/queueDisplay/queueDisplay.css.ts
index f2d6d204..c052afb4 100644
--- a/ui/frontend/build_src/src/components/organisms/queueDisplay/queueDisplay.css.ts
+++ b/ui/frontend/build_src/src/components/organisms/queueDisplay/queueDisplay.css.ts
@@ -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, {
+
+}]);
\ No newline at end of file
diff --git a/ui/frontend/build_src/src/components/organisms/queueDisplay/queueItem/index.tsx b/ui/frontend/build_src/src/components/organisms/queueDisplay/queueItem/index.tsx
index 15d95508..289c5f7f 100644
--- a/ui/frontend/build_src/src/components/organisms/queueDisplay/queueItem/index.tsx
+++ b/ui/frontend/build_src/src/components/organisms/queueDisplay/queueItem/index.tsx
@@ -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 (
-
-
{id}
+
+ {/* @ts-expect-error */}
+
{status}
{prompt}
{seed}
{sampler}
+
+
+ {status === QueueStatus.processing && (
+
+ )}
+
+ {status === QueueStatus.complete && (
+
+ )}
+
+ {status === QueueStatus.pending && (
+ <>
+
+
+
+ >
+ )}
+
+ {status === QueueStatus.paused && (
+
+ )}
+
+ {status === QueueStatus.error && (
+
+ )}
+
+
);
}
\ No newline at end of file
diff --git a/ui/frontend/build_src/src/components/organisms/queueDisplay/queueItem/queueItem.css.ts b/ui/frontend/build_src/src/components/organisms/queueDisplay/queueItem/queueItem.css.ts
index 6fd48e1c..c51c57f8 100644
--- a/ui/frontend/build_src/src/components/organisms/queueDisplay/queueItem/queueItem.css.ts
+++ b/ui/frontend/build_src/src/components/organisms/queueDisplay/queueItem/queueItem.css.ts
@@ -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",
-});
\ No newline at end of file
+});
+
+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, {
+
+}]);
diff --git a/ui/frontend/build_src/src/stores/imageFetchingStore.ts b/ui/frontend/build_src/src/stores/imageFetchingStore.ts
index 7fc1c9d6..42391a31 100644
--- a/ui/frontend/build_src/src/stores/imageFetchingStore.ts
+++ b/ui/frontend/build_src/src/stores/imageFetchingStore.ts
@@ -27,7 +27,6 @@ interface ImageFetchingState {
setStartTime: () => void;
setNowTime: () => void;
resetForFetching: () => void;
-
}
export const useImageFetching = create
((set) => ({
diff --git a/ui/frontend/build_src/src/stores/imageQueueStore.ts b/ui/frontend/build_src/src/stores/imageQueueStore.ts
deleted file mode 100644
index a3ef7e21..00000000
--- a/ui/frontend/build_src/src/stores/imageQueueStore.ts
+++ /dev/null
@@ -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((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 = [];
- })
- );
- },
-}));
diff --git a/ui/frontend/build_src/src/stores/requestQueueStore.ts b/ui/frontend/build_src/src/stores/requestQueueStore.ts
new file mode 100644
index 00000000..75de334a
--- /dev/null
+++ b/ui/frontend/build_src/src/stores/requestQueueStore.ts
@@ -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((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 = [];
+ })
+ );
+ },
+}));