mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-06-20 01:48:21 +02: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 React, { useEffect, useRef } from "react";
|
||||||
|
|
||||||
import { useImageCreate } from "../../../stores/imageCreateStore";
|
import { useImageCreate } from "../../../stores/imageCreateStore";
|
||||||
import { useImageQueue } from "../../../stores/imageQueueStore";
|
import {
|
||||||
|
QueueStatus,
|
||||||
|
useRequestQueue
|
||||||
|
} from "../../../stores/requestQueueStore";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FetchingStates,
|
FetchingStates,
|
||||||
useImageFetching
|
useImageFetching
|
||||||
@ -42,10 +46,10 @@ export default function MakeButton() {
|
|||||||
|
|
||||||
const isSoundEnabled = useImageCreate((state) => state.isSoundEnabled());
|
const isSoundEnabled = useImageCreate((state) => state.isSoundEnabled());
|
||||||
|
|
||||||
const addNewImage = useImageQueue((state) => state.addNewImage);
|
const addtoQueue = useRequestQueue((state) => state.addtoQueue);
|
||||||
const hasQueue = useImageQueue((state) => state.hasQueuedImages());
|
const hasQueue = useRequestQueue((state) => state.hasPendingQueue());
|
||||||
const removeFirstInQueue = useImageQueue((state) => state.removeFirstInQueue);
|
const { id, options } = useRequestQueue((state) => state.firstInQueue());
|
||||||
const { id, options } = useImageQueue((state) => state.firstInQueue());
|
const updateQueueStatus = useRequestQueue((state) => state.updateStatus);
|
||||||
|
|
||||||
const status = useImageFetching((state) => state.status);
|
const status = useImageFetching((state) => state.status);
|
||||||
const setStatus = useImageFetching((state) => state.setStatus);
|
const setStatus = useImageFetching((state) => state.setStatus);
|
||||||
@ -64,7 +68,11 @@ export default function MakeButton() {
|
|||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(jsonStr);
|
const parsed = JSON.parse(jsonStr);
|
||||||
const { status, request, output: outputs } = parsed as ImageReturnType;
|
const { status, request, output: outputs } = parsed as ImageReturnType;
|
||||||
|
|
||||||
|
|
||||||
if (status === 'succeeded') {
|
if (status === 'succeeded') {
|
||||||
|
|
||||||
|
updateQueueStatus(id, QueueStatus.complete);
|
||||||
outputs.forEach((output: any, index: number) => {
|
outputs.forEach((output: any, index: number) => {
|
||||||
|
|
||||||
const { data, seed } = output as ImageOutput;
|
const { data, seed } = output as ImageOutput;
|
||||||
@ -79,10 +87,12 @@ export default function MakeButton() {
|
|||||||
|
|
||||||
else {
|
else {
|
||||||
console.warn(`Unexpected status: ${status}`);
|
console.warn(`Unexpected status: ${status}`);
|
||||||
|
updateQueueStatus(id, QueueStatus.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
updateQueueStatus(id, QueueStatus.error);
|
||||||
console.log("Error HACKING JSON: ", e)
|
console.log("Error HACKING JSON: ", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,7 +153,7 @@ export default function MakeButton() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log('EXPECTED PARSE ERRROR')
|
// console.log('EXPECTED PARSE ERRROR')
|
||||||
finalJSON += jsonStr;
|
finalJSON += jsonStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,8 +162,8 @@ export default function MakeButton() {
|
|||||||
|
|
||||||
const startStream = async (id: string, req: ImageRequest) => {
|
const startStream = async (id: string, req: ImageRequest) => {
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
updateQueueStatus(id, QueueStatus.processing);
|
||||||
resetForFetching();
|
resetForFetching();
|
||||||
const res = await doMakeImage(req);
|
const res = await doMakeImage(req);
|
||||||
const reader = res.body?.getReader();
|
const reader = res.body?.getReader();
|
||||||
@ -164,6 +174,7 @@ export default function MakeButton() {
|
|||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('TOP LINE STREAM ERROR')
|
console.log('TOP LINE STREAM ERROR')
|
||||||
|
updateQueueStatus(id, QueueStatus.error);
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +212,7 @@ export default function MakeButton() {
|
|||||||
seed = useRandomSeed();
|
seed = useRandomSeed();
|
||||||
}
|
}
|
||||||
// add the request to the queue
|
// add the request to the queue
|
||||||
addNewImage(uuidv4(), {
|
addtoQueue(uuidv4(), {
|
||||||
...req,
|
...req,
|
||||||
// updated the number of images to make
|
// updated the number of images to make
|
||||||
num_outputs: num,
|
num_outputs: num,
|
||||||
@ -224,7 +235,7 @@ export default function MakeButton() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const makeImages = async (options: ImageRequest) => {
|
const makeImages = async (options: ImageRequest) => {
|
||||||
removeFirstInQueue();
|
// removeFirstInQueue();
|
||||||
await startStream(id ?? "", options);
|
await startStream(id ?? "", options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,6 +249,7 @@ export default function MakeButton() {
|
|||||||
console.log('req is undefined');
|
console.log('req is undefined');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
makeImages(options).catch((e) => {
|
makeImages(options).catch((e) => {
|
||||||
console.log('HAS QUEUE ERROR');
|
console.log('HAS QUEUE ERROR');
|
||||||
console.log(e);
|
console.log(e);
|
@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { useImageCreate } from "../../../../../stores/imageCreateStore";
|
import { useImageCreate } from "../../../../../stores/imageCreateStore";
|
||||||
import ModifierTag from "../../../../atoms/modifierTag";
|
import ModifierTag from "../../../../molecules/modifierTag";
|
||||||
|
|
||||||
export default function ActiveTags() {
|
export default function ActiveTags() {
|
||||||
const selectedtags = useImageCreate((state) => state.selectedTags());
|
const selectedtags = useImageCreate((state) => state.selectedTags());
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import MakeButton from "../../../../atoms/makeButton";
|
import MakeButton from "../../../../molecules/makeButton";
|
||||||
import StopButton from "../../../../atoms/stopButton";
|
// import StopButton from "../../../../molecules/stopButton";
|
||||||
import ClearQueue from "../../../../atoms/clearQueue";
|
// import ClearQueue from "../../../../molecules/clearQueue";
|
||||||
|
|
||||||
|
import ShowQueue from "../showQueue";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
StopContainer
|
StopContainer
|
||||||
@ -12,10 +14,11 @@ export default function CreationActions() {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<MakeButton></MakeButton>
|
<MakeButton></MakeButton>
|
||||||
<div className={StopContainer}>
|
<ShowQueue></ShowQueue>
|
||||||
|
{/* <div className={StopContainer}>
|
||||||
<StopButton></StopButton>
|
<StopButton></StopButton>
|
||||||
<ClearQueue></ClearQueue>
|
<ClearQueue></ClearQueue>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -37,12 +37,6 @@ export default function BasicCreation() {
|
|||||||
|
|
||||||
<CreationActions></CreationActions>
|
<CreationActions></CreationActions>
|
||||||
|
|
||||||
{/* <MakeButton></MakeButton>
|
|
||||||
<div>
|
|
||||||
<StopButton></StopButton>
|
|
||||||
<ClearQueue></ClearQueue>
|
|
||||||
</div> */}
|
|
||||||
|
|
||||||
<SeedImage></SeedImage>
|
<SeedImage></SeedImage>
|
||||||
<ActiveTags></ActiveTags>
|
<ActiveTags></ActiveTags>
|
||||||
</div>
|
</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 { style } from "@vanilla-extract/css";
|
||||||
|
import { PanelBox } from "../../../styles/shared.css";
|
||||||
export const CreationPaneMain = style({
|
export const CreationPaneMain = style({
|
||||||
position: "relative",
|
position: "relative",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
padding: "0 10px",
|
padding: "0 10px",
|
||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
|
overflowX: "hidden",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const InpaintingSlider = style({
|
export const InpaintingSlider = style({
|
||||||
@ -16,10 +17,11 @@ export const InpaintingSlider = style({
|
|||||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const QueueSlider = style({
|
export const QueueSlider = style([PanelBox, {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: "10px",
|
top: "10px",
|
||||||
left: "400px",
|
left: "400px",
|
||||||
zIndex: 1,
|
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 { ModifierObject, useImageCreate } from "../../../../stores/imageCreateStore";
|
||||||
import { useCreateUI } from "../creationPanelUIStore";
|
import { useCreateUI } from "../creationPanelUIStore";
|
||||||
|
|
||||||
import ModifierTag from "../../../atoms/modifierTag";
|
import ModifierTag from "../../../molecules/modifierTag";
|
||||||
|
|
||||||
interface ModifierListProps {
|
interface ModifierListProps {
|
||||||
category: string;
|
category: string;
|
||||||
|
@ -11,7 +11,7 @@ import QueueDisplay from "../queueDisplay";
|
|||||||
// import { useImageCreate } from "@stores/imageCreateStore.ts";
|
// import { useImageCreate } from "@stores/imageCreateStore.ts";
|
||||||
|
|
||||||
import { useImageCreate } from "../../../stores/imageCreateStore";
|
import { useImageCreate } from "../../../stores/imageCreateStore";
|
||||||
import { useImageQueue } from "../../../stores/imageQueueStore";
|
import { useRequestQueue } from "../../../stores/requestQueueStore";
|
||||||
|
|
||||||
import { useCreateUI } from "./creationPanelUIStore";
|
import { useCreateUI } from "./creationPanelUIStore";
|
||||||
|
|
||||||
@ -24,12 +24,11 @@ import {
|
|||||||
} from "./creationPanel.css";
|
} from "./creationPanel.css";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default function CreationPanel() {
|
export default function CreationPanel() {
|
||||||
const isInPaintingMode = useImageCreate((state) => state.isInpainting);
|
const isInPaintingMode = useImageCreate((state) => state.isInpainting);
|
||||||
|
|
||||||
const showQueue = useCreateUI((state) => state.showQueue);
|
const showQueue = useCreateUI((state) => state.showQueue);
|
||||||
const hasQueue = useImageQueue((state) => state.hasQueuedImages());
|
const hasQueue = useRequestQueue((state) => state.hasAnyQueue());
|
||||||
|
|
||||||
// console.log('hasQueue', hasQueue);
|
// console.log('hasQueue', hasQueue);
|
||||||
console.log('showQueue', showQueue);
|
console.log('showQueue', showQueue);
|
||||||
@ -48,7 +47,7 @@ export default function CreationPanel() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(showQueue) && (
|
{(showQueue && hasQueue) && (
|
||||||
<div className={QueueSlider}>
|
<div className={QueueSlider}>
|
||||||
<QueueDisplay></QueueDisplay>
|
<QueueDisplay></QueueDisplay>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,24 +1,45 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { ImageRequest } from "../../../api";
|
||||||
|
|
||||||
import { useImageQueue } from "../../../stores/imageQueueStore";
|
import { QueuedRequest, useRequestQueue } from "../../../stores/requestQueueStore";
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
QueueDisplayMain
|
QueueDisplayMain,
|
||||||
|
QueueListButtons,
|
||||||
|
CompleteButtton,
|
||||||
|
ErrorButton
|
||||||
} from "./queueDisplay.css";
|
} from "./queueDisplay.css";
|
||||||
|
|
||||||
|
|
||||||
|
import ClearQueue from "../../molecules/clearQueue";
|
||||||
import QueueItem from "./queueItem";
|
import QueueItem from "./queueItem";
|
||||||
|
|
||||||
|
|
||||||
export default function QueueDisplay() {
|
export default function QueueDisplay() {
|
||||||
|
|
||||||
const images = useImageQueue((state) => state.images);
|
const requests: QueuedRequest[] = useRequestQueue((state) => state.requests);
|
||||||
console.log('images', images);
|
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 (
|
return (
|
||||||
<div className={QueueDisplayMain}>
|
<div className={QueueDisplayMain}>
|
||||||
{images.map((image) => {
|
<ClearQueue />
|
||||||
return <QueueItem key={image.id} info={image}></QueueItem>;
|
<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>
|
</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({
|
export const QueueDisplayMain = style({
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
width: '400px',
|
width: '400px',
|
||||||
height: '100%',
|
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 React from "react";
|
||||||
|
|
||||||
import {
|
|
||||||
QueueItemMain
|
|
||||||
} from "./queueItem.css";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ImageRequest
|
ImageRequest
|
||||||
} from '../../../../api'
|
} 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 {
|
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 {
|
const {
|
||||||
id,
|
id,
|
||||||
@ -23,16 +40,64 @@ export default function QueueItem({ info }: QueueItemProps) {
|
|||||||
seed,
|
seed,
|
||||||
sampler,
|
sampler,
|
||||||
},
|
},
|
||||||
// status,
|
status,
|
||||||
} = info;
|
} = 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 (
|
return (
|
||||||
<div className={QueueItemMain}>
|
<div className={[QueueItemMain, status].join(' ')}>
|
||||||
<div>{id}</div>
|
{/* @ts-expect-error */}
|
||||||
|
<div>{status}</div>
|
||||||
<div>{prompt}</div>
|
<div>{prompt}</div>
|
||||||
<div>{seed}</div>
|
<div>{seed}</div>
|
||||||
<div>{sampler}</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>
|
</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({
|
export const QueueItemMain = style({
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
padding: "0.5rem",
|
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;
|
setStartTime: () => void;
|
||||||
setNowTime: () => void;
|
setNowTime: () => void;
|
||||||
resetForFetching: () => void;
|
resetForFetching: () => void;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useImageFetching = create<ImageFetchingState>((set) => ({
|
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…
x
Reference in New Issue
Block a user