mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-07 02:21:23 +00:00
implemented dismiss jobs endpoint (#585)
Co-authored-by: Victor <victor@storyteller.ai>
This commit is contained in:
1 parent
5be986bf7b
commit
c326cad2cc
13 files changed
+408
-117
No files matched your search
@@ -0,0 +1,17 @@
|
||||
import MakeRequest from "../MakeRequest";
|
||||
|
||||
export interface DismissFinishedJobsRequest {}
|
||||
|
||||
export interface DismissFinishedJobsResponse {
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
export const DismissFinishedJobs = MakeRequest<
|
||||
string,
|
||||
DismissFinishedJobsRequest,
|
||||
DismissFinishedJobsResponse,
|
||||
{}
|
||||
>({
|
||||
method: "POST",
|
||||
routingFunction: (jobToken: string) => `/v1/jobs/session/dismiss_finished`,
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import React from "react";
|
||||
import { a, useTransition } from "@react-spring/web";
|
||||
import { basicTransition } from "resources";
|
||||
import { Button, Spinner } from "components/common";
|
||||
import { FetchStatus } from "@storyteller/components/src/api/_common/SharedFetchTypes";
|
||||
import { faTrash } from "@fortawesome/pro-solid-svg-icons";
|
||||
|
||||
interface Props {
|
||||
clearJobs?: () => void;
|
||||
clearJobsStatus?: FetchStatus;
|
||||
someJobsAreDone?: boolean;
|
||||
}
|
||||
|
||||
export default function JobsClearButton({
|
||||
clearJobs,
|
||||
clearJobsStatus,
|
||||
someJobsAreDone,
|
||||
}: Props) {
|
||||
const transitions = useTransition(
|
||||
// index || 0,
|
||||
someJobsAreDone ? clearJobsStatus || 0 : 0,
|
||||
basicTransition({})
|
||||
);
|
||||
return (
|
||||
<div
|
||||
{...{
|
||||
className: "fy-clear-jobs-input",
|
||||
}}
|
||||
>
|
||||
{transitions(
|
||||
(style: any, index) =>
|
||||
[
|
||||
<></>,
|
||||
<a.div {...{ className: "fy-clear-jobs-frame", style }}>
|
||||
<Button
|
||||
{...{
|
||||
icon: faTrash,
|
||||
onClick: clearJobs,
|
||||
tooltip: "Clear completed jobs",
|
||||
variant: "secondary",
|
||||
square: true,
|
||||
}}
|
||||
/>
|
||||
</a.div>,
|
||||
<a.div {...{ className: "fy-clear-jobs-frame", style }}>
|
||||
<Spinner />
|
||||
</a.div>,
|
||||
][index]
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./JobsClearButton";
|
||||
@@ -19,6 +19,7 @@ import FileLabel from "./FileLabel";
|
||||
import ImageInput from "./ImageInput";
|
||||
import Input from "./Input";
|
||||
import InputSeed from "./InputSeed";
|
||||
import JobsClearButton from "./JobsClearButton";
|
||||
import JobQueueTicker from "./JobQueueTicker";
|
||||
import Label from "./Label";
|
||||
import LikeButton from "./LikeButton";
|
||||
@@ -83,6 +84,7 @@ export {
|
||||
ImageInput,
|
||||
Input,
|
||||
InputSeed,
|
||||
JobsClearButton,
|
||||
JobQueueTicker,
|
||||
Label,
|
||||
LikeButton,
|
||||
|
||||
+189
-82
@@ -1,19 +1,57 @@
|
||||
@import "scss/colours.scss";
|
||||
@import "scss/site-refresh.scss";
|
||||
|
||||
$primary-transparent: rgba($primary,.75);
|
||||
$primary-transparent: rgba($primary, 0.75);
|
||||
|
||||
.fy-inference-jobs-list {
|
||||
overflow: hidden;
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
h3 {
|
||||
height: 1em;
|
||||
margin-bottom: 0;
|
||||
// display: inline;
|
||||
// background-color: green;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fy-clear-jobs-input {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 3rem;
|
||||
right: 0;
|
||||
|
||||
.fy-clear-jobs-frame {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
// top: 50%;
|
||||
// transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.fy-inference-jobs-list-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 2.25rem fit-content(100px) minmax(0, 1fr) minmax(min-content, 1fr);
|
||||
grid-template-columns: 2.25rem fit-content(100px) minmax(0, 1fr) minmax(
|
||||
min-content,
|
||||
1fr
|
||||
);
|
||||
gap: 1rem 0;
|
||||
|
||||
.work-indicator {
|
||||
margin-right: -.5rem; // offset for svg gap
|
||||
margin-right: -0.5rem; // offset for svg gap
|
||||
}
|
||||
|
||||
h6 {
|
||||
@@ -24,8 +62,9 @@ $primary-transparent: rgba($primary,.75);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.fy-inference-job-hover-on, .fy-inference-job-hover-off {
|
||||
padding: .5rem;
|
||||
.fy-inference-job-hover-on,
|
||||
.fy-inference-job-hover-off {
|
||||
padding: 0.5rem;
|
||||
|
||||
// &:first-of-type { }
|
||||
}
|
||||
@@ -39,25 +78,31 @@ $primary-transparent: rgba($primary,.75);
|
||||
}
|
||||
|
||||
.fy-inference-job-indicator {
|
||||
border-radius: .5rem 0 0 .5rem;
|
||||
margin-left: -.5rem;
|
||||
border-radius: 0.5rem 0 0 0.5rem;
|
||||
margin-left: -0.5rem;
|
||||
padding-right: 0;
|
||||
}
|
||||
.fy-inference-job-action-frame { border-radius: 0 .5rem .5rem 0 }
|
||||
}
|
||||
.fy-inference-job-action-frame {
|
||||
border-radius: 0 0.5rem 0.5rem 0;
|
||||
}
|
||||
|
||||
.fy-inference-job-subtitle, .fy-inference-job-subtitle-success, .job-info-label {
|
||||
font-size: .875rem;
|
||||
.fy-inference-job-subtitle,
|
||||
.fy-inference-job-subtitle-success,
|
||||
.job-info-label {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
height: 1.125em;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.fy-inference-job-subtitle, .job-info-label {
|
||||
opacity: .6;
|
||||
.fy-inference-job-subtitle,
|
||||
.job-info-label {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.fy-inference-job-subtitle, .fy-inference-job-subtitle-success {
|
||||
.fy-inference-job-subtitle,
|
||||
.fy-inference-job-subtitle-success {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -82,14 +127,14 @@ $primary-transparent: rgba($primary,.75);
|
||||
}
|
||||
|
||||
.fy-inference-job-action-frame {
|
||||
margin-right: -.5rem;
|
||||
margin-right: -0.5rem;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
// width: fit-content;
|
||||
// background: rgba(#0f0, .1);
|
||||
|
||||
.fy-inference-job-action, .fy-inference-job-action-success {
|
||||
|
||||
.fy-inference-job-action,
|
||||
.fy-inference-job-action-success {
|
||||
@include medium-svg;
|
||||
|
||||
cursor: pointer;
|
||||
@@ -98,39 +143,46 @@ $primary-transparent: rgba($primary,.75);
|
||||
// padding-left: .75rem;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
border-radius: .5rem;
|
||||
border-radius: 0.5rem;
|
||||
// line-height: 1em;
|
||||
margin: auto 0 auto auto;
|
||||
|
||||
}
|
||||
|
||||
.job-status-complete-success {
|
||||
|
||||
&:hover { background-color: $panel-inner; }
|
||||
.job-status-complete-success {
|
||||
&:hover {
|
||||
background-color: $panel-inner;
|
||||
}
|
||||
}
|
||||
|
||||
.fy-inference-job-action-success {
|
||||
background-color: $primary-transparent;
|
||||
&:hover { background-color: lighten($primary, 5%); }
|
||||
&:hover {
|
||||
background-color: lighten($primary, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
.fy-inference-job-action, .job-stop-confirm, .job-stop-cancel {
|
||||
.fy-inference-job-action,
|
||||
.job-stop-confirm,
|
||||
.job-stop-cancel {
|
||||
cursor: pointer;
|
||||
background-color: $secondary;
|
||||
&:hover { background-color: $secondary-light; }
|
||||
&:hover {
|
||||
background-color: $secondary-light;
|
||||
}
|
||||
}
|
||||
.fy-slide-wrapper {
|
||||
justify-content: flex-end;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: .5rem;
|
||||
padding-right: 0.5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.job-stop-confirm, .job-stop-cancel {
|
||||
border-radius: .5rem;
|
||||
margin-left: .5rem;
|
||||
padding: .625rem 1rem;;
|
||||
.job-stop-confirm,
|
||||
.job-stop-cancel {
|
||||
border-radius: 0.5rem;
|
||||
margin-left: 0.5rem;
|
||||
padding: 0.625rem 1rem;
|
||||
line-height: 1em;
|
||||
// height: 2.25rem;
|
||||
}
|
||||
@@ -138,10 +190,10 @@ $primary-transparent: rgba($primary,.75);
|
||||
}
|
||||
|
||||
.fy-job-queue-ticker {
|
||||
border-radius: .5rem;
|
||||
margin-bottom: 1rem;
|
||||
// padding:1rem;
|
||||
background-color: rgba(0, 0, 0, .25);
|
||||
border-radius: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
// padding:1rem;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
@@ -152,52 +204,101 @@ $primary-transparent: rgba($primary,.75);
|
||||
h6 {
|
||||
display: inline;
|
||||
margin-bottom: 0;
|
||||
opacity: .66;
|
||||
opacity: 0.66;
|
||||
padding: 1rem;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
|
||||
@keyframes tictictic {
|
||||
00.0% { transform: rotate(0deg); }
|
||||
04.2% { transform: rotate(15deg); }
|
||||
08.3% { transform: rotate(30deg); }
|
||||
12.5% { transform: rotate(45deg); }
|
||||
16.7% { transform: rotate(60deg); }
|
||||
20.8% { transform: rotate(75deg); }
|
||||
25.0% { transform: rotate(90deg); }
|
||||
29.2% { transform: rotate(105deg); }
|
||||
33.3% { transform: rotate(120deg); }
|
||||
37.5% { transform: rotate(135deg); }
|
||||
41.7% { transform: rotate(150deg); }
|
||||
45.8% { transform: rotate(165deg); }
|
||||
50.0% { transform: rotate(180deg); }
|
||||
54.2% { transform: rotate(195deg); }
|
||||
58.3% { transform: rotate(210deg); }
|
||||
62.5% { transform: rotate(225deg); }
|
||||
66.7% { transform: rotate(240deg); }
|
||||
70.8% { transform: rotate(255deg); }
|
||||
75.0% { transform: rotate(270deg); }
|
||||
79.2% { transform: rotate(285deg); }
|
||||
83.3% { transform: rotate(300deg); }
|
||||
87.5% { transform: rotate(315deg); }
|
||||
91.7% { transform: rotate(330deg); }
|
||||
95.8% { transform: rotate(345deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
00.0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
04.2% {
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
08.3% {
|
||||
transform: rotate(30deg);
|
||||
}
|
||||
12.5% {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
16.7% {
|
||||
transform: rotate(60deg);
|
||||
}
|
||||
20.8% {
|
||||
transform: rotate(75deg);
|
||||
}
|
||||
25.0% {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
29.2% {
|
||||
transform: rotate(105deg);
|
||||
}
|
||||
33.3% {
|
||||
transform: rotate(120deg);
|
||||
}
|
||||
37.5% {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
41.7% {
|
||||
transform: rotate(150deg);
|
||||
}
|
||||
45.8% {
|
||||
transform: rotate(165deg);
|
||||
}
|
||||
50.0% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
54.2% {
|
||||
transform: rotate(195deg);
|
||||
}
|
||||
58.3% {
|
||||
transform: rotate(210deg);
|
||||
}
|
||||
62.5% {
|
||||
transform: rotate(225deg);
|
||||
}
|
||||
66.7% {
|
||||
transform: rotate(240deg);
|
||||
}
|
||||
70.8% {
|
||||
transform: rotate(255deg);
|
||||
}
|
||||
75.0% {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
79.2% {
|
||||
transform: rotate(285deg);
|
||||
}
|
||||
83.3% {
|
||||
transform: rotate(300deg);
|
||||
}
|
||||
87.5% {
|
||||
transform: rotate(315deg);
|
||||
}
|
||||
91.7% {
|
||||
transform: rotate(330deg);
|
||||
}
|
||||
95.8% {
|
||||
transform: rotate(345deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.job-cta-clock {
|
||||
height: 2.625rem;
|
||||
width: 2.625rem;
|
||||
fill: none;
|
||||
margin-left: .25rem;
|
||||
animation: tictictic 15s cubic-bezier(1,.14,.27,1.51) infinite;
|
||||
margin-left: 0.25rem;
|
||||
animation: tictictic 15s cubic-bezier(1, 0.14, 0.27, 1.51) infinite;
|
||||
|
||||
.clock-circle {
|
||||
fill: $primary;
|
||||
}
|
||||
.mask-circle {
|
||||
fill: #fff;
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
line {
|
||||
@@ -213,11 +314,10 @@ $primary-transparent: rgba($primary,.75);
|
||||
padding: 0 1rem 1rem;
|
||||
grid-auto-flow: column;
|
||||
grid-auto-columns: minmax(0, 1fr);
|
||||
gap: .5rem;
|
||||
gap: 0.5rem;
|
||||
|
||||
|
||||
* {
|
||||
display: flex;
|
||||
* {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -226,8 +326,8 @@ $primary-transparent: rgba($primary,.75);
|
||||
max-width: 5rem;
|
||||
// background-color: greenyellow;
|
||||
// white-space: nowrap;
|
||||
font-size: .75rem;
|
||||
opacity: .5;
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.5;
|
||||
line-height: 1.25em;
|
||||
}
|
||||
}
|
||||
@@ -241,33 +341,41 @@ $primary-transparent: rgba($primary,.75);
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
overflow: hidden;
|
||||
transition: background-color .5s cubic-bezier(0.45, 0, 0.55, 1);
|
||||
background-color: rgba($primary,.45);
|
||||
border-radius: 0 .5rem 0 .5rem;
|
||||
transition: background-color 0.5s cubic-bezier(0.45, 0, 0.55, 1);
|
||||
background-color: rgba($primary, 0.45);
|
||||
border-radius: 0 0.5rem 0 0.5rem;
|
||||
line-height: 1em;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba($primary,.25);
|
||||
background-color: rgba($primary, 0.25);
|
||||
}
|
||||
|
||||
.cta-membership-gradient {
|
||||
background: linear-gradient(90deg, rgba($primary,.0) 0%, rgba($primary,.85) 100%);
|
||||
padding: .5rem;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba($primary, 0) 0%,
|
||||
rgba($primary, 0.85) 100%
|
||||
);
|
||||
padding: 0.5rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
color: rgba(#fff,.80);
|
||||
color: rgba(#fff, 0.8);
|
||||
align-items: center;
|
||||
|
||||
.job-cta-message {
|
||||
line-height: 1.25em;
|
||||
margin: 0 .5rem 0 .75rem;
|
||||
&:hover { color: rgba(#fff,.80); }
|
||||
margin: 0 0.5rem 0 0.75rem;
|
||||
&:hover {
|
||||
color: rgba(#fff, 0.8);
|
||||
}
|
||||
span {
|
||||
color: rgba(#fff,.90);
|
||||
color: rgba(#fff, 0.9);
|
||||
font-weight: bolder;
|
||||
text-decoration: underline;
|
||||
text-shadow: $primary 0 0 6px;
|
||||
&:hover { color: #fff; }
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,4 +387,3 @@ $primary-transparent: rgba($primary,.75);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,15 @@ import {
|
||||
FrontendInferenceJobType,
|
||||
InferenceJob,
|
||||
} from "@storyteller/components/src/jobs/InferenceJob";
|
||||
// import { useTransition } from "@react-spring/web";
|
||||
import JobItem from "./JobItem";
|
||||
import { useInferenceJobs, useLocalize, useSession } from "hooks";
|
||||
import "./InferenceJobsList.scss";
|
||||
import { Button, Panel, JobQueueTicker } from "components/common";
|
||||
import {
|
||||
JobsClearButton,
|
||||
Button,
|
||||
Panel,
|
||||
JobQueueTicker,
|
||||
} from "components/common";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faClipboardList } from "@fortawesome/pro-solid-svg-icons";
|
||||
|
||||
@@ -45,19 +49,46 @@ export default function InferenceJobsList({
|
||||
const { sessionSubscriptions } = useSession();
|
||||
const hasPaidFeatures = sessionSubscriptions?.hasPaidFeatures();
|
||||
const {
|
||||
clearJobs,
|
||||
clearJobsStatus,
|
||||
inferenceJobs = [],
|
||||
inferenceJobsByCategory,
|
||||
jobStatusDescription,
|
||||
someJobsAreDone,
|
||||
} = useInferenceJobs();
|
||||
const { t } = useLocalize("InferenceJobs");
|
||||
|
||||
const selectedJobs =
|
||||
jobType === undefined || jobType === AllInferenceJobs.All
|
||||
? inferenceJobs
|
||||
: inferenceJobsByCategory.get(jobType);
|
||||
|
||||
// const { index, ticker } = useInterval({
|
||||
// debug: "YES",
|
||||
// end: 2,
|
||||
// interval: 1000,
|
||||
// });
|
||||
|
||||
const jobContent = (
|
||||
<>
|
||||
{showHeader && <h3 className="fw-semibold mb-3">{t("core.heading")}</h3>}
|
||||
{showHeader && (
|
||||
<header>
|
||||
<h3 className="fw-semibold">{t("core.heading")}</h3>
|
||||
<div
|
||||
{...{
|
||||
className: "fy-clear-jobs-input",
|
||||
}}
|
||||
>
|
||||
<JobsClearButton
|
||||
{...{
|
||||
clearJobs,
|
||||
clearJobsStatus,
|
||||
someJobsAreDone,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
)}
|
||||
{showJobQueue && <JobQueueTicker {...{ hasPaidFeatures }} />}
|
||||
<div {...{ className: "fy-inference-jobs-list-grid" }}>
|
||||
{selectedJobs &&
|
||||
@@ -82,8 +113,9 @@ export default function InferenceJobsList({
|
||||
<h4 className="fw-semibold mb-1">{t("core.noJobsTitle")}</h4>
|
||||
<p className="opacity-75 mb-2">{t("core.noJobsSubtitle")}</p>
|
||||
</div>
|
||||
|
||||
<Button label={t("core.exploreBtn")} to="/explore" />
|
||||
<div>
|
||||
<Button label={t("core.exploreBtn")} to="/explore" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
||||
+28
-14
@@ -1,10 +1,10 @@
|
||||
import React, { useState } from "react"; // useState
|
||||
import InferenceJobsList from "components/layout/InferenceJobsList";
|
||||
import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
|
||||
import { TempSelect as Select } from "components/common";
|
||||
import { TempSelect as Select, JobsClearButton } from "components/common";
|
||||
import { enumToKeyArr } from "resources";
|
||||
import ModalHeader from "../ModalHeader";
|
||||
import { useLocalize, useSession } from "hooks";
|
||||
import { useInferenceJobs, useLocalize, useSession } from "hooks";
|
||||
|
||||
interface Props {
|
||||
handleClose?: any;
|
||||
@@ -19,14 +19,16 @@ export default function InferenceJobsModal({
|
||||
...rest
|
||||
}: Props) {
|
||||
const { canAccessStudio } = useSession();
|
||||
const { clearJobs, clearJobsStatus, someJobsAreDone } = useInferenceJobs();
|
||||
const presetFilter = enumToKeyArr(FrontendInferenceJobType)[inJobType];
|
||||
const [jobType,jobTypeSet] = useState(inJobType > -1 ? presetFilter : "All");
|
||||
const [jobType, jobTypeSet] = useState(inJobType > -1 ? presetFilter : "All");
|
||||
const typeObj = ["All", ...Object.values(FrontendInferenceJobType)];
|
||||
const options = typeObj.filter(val => isNaN(Number(val)))
|
||||
.map((value) => {
|
||||
if (typeof value === "string") return { value, label: value }
|
||||
return { label: "", value: "" };
|
||||
});
|
||||
const options = typeObj
|
||||
.filter(val => isNaN(Number(val)))
|
||||
.map(value => {
|
||||
if (typeof value === "string") return { value, label: value };
|
||||
return { label: "", value: "" };
|
||||
});
|
||||
const { t } = useLocalize("InferenceJobs");
|
||||
const selectedType = typeObj.indexOf(jobType) - 1;
|
||||
const failures = (fail = "") => {
|
||||
@@ -38,22 +40,34 @@ export default function InferenceJobsModal({
|
||||
|
||||
return (
|
||||
<>
|
||||
{ showModalHeader && <ModalHeader {...{ handleClose, title: t("core.jobsTitle") }} /> }
|
||||
{ canAccessStudio() &&
|
||||
<Select {...{ onChange: ({ target }: { target: any }) => jobTypeSet(target.value), options, value: jobType }} />
|
||||
}
|
||||
{showModalHeader && (
|
||||
<ModalHeader {...{ handleClose, title: t("core.jobsTitle") }}>
|
||||
<JobsClearButton
|
||||
{...{ clearJobs, clearJobsStatus, someJobsAreDone }}
|
||||
/>
|
||||
</ModalHeader>
|
||||
)}
|
||||
{canAccessStudio() && (
|
||||
<Select
|
||||
{...{
|
||||
onChange: ({ target }: { target: any }) => jobTypeSet(target.value),
|
||||
options,
|
||||
value: jobType,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<InferenceJobsList
|
||||
{...{
|
||||
failures,
|
||||
onSelect: () => {
|
||||
if (handleClose) handleClose();
|
||||
},
|
||||
...selectedType > -1 ? { jobType: selectedType } : {},
|
||||
...(selectedType > -1 ? { jobType: selectedType } : {}),
|
||||
showHeader: false,
|
||||
showJobQueue: true,
|
||||
showNoJobs: true,
|
||||
panel: false,
|
||||
...rest
|
||||
...rest,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
.fy-media-browser-tools {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: auto 0 auto auto;
|
||||
gap: 1rem;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -11,11 +12,15 @@
|
||||
margin: auto 0 auto auto;
|
||||
}
|
||||
|
||||
.fy-temp-select { margin-bottom: 0 }
|
||||
.fy-temp-select {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.fy-media-browser-header{
|
||||
h3 { margin-bottom: 0 }
|
||||
.fy-media-browser-header {
|
||||
h3 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
> * {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -28,7 +33,6 @@
|
||||
@include close-parent;
|
||||
}
|
||||
|
||||
|
||||
.fy-media-browser-list {
|
||||
flex-grow: 1;
|
||||
overflow-y: scroll;
|
||||
@@ -38,4 +42,4 @@
|
||||
|
||||
.fy-media-browser-footer {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,26 @@ interface Props {
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export default function ModalHeader({ children, handleClose, onSearchChange = () => {}, search, title }: Props) {
|
||||
export default function ModalHeader({
|
||||
children,
|
||||
handleClose,
|
||||
onSearchChange = () => {},
|
||||
search,
|
||||
title,
|
||||
}: Props) {
|
||||
return (
|
||||
<header {...{ className: "fy-media-browser-header" }}>
|
||||
<div {...{ className: "fy-media-browser-tools" }}>
|
||||
{ search !== undefined ? <Input autoFocus {...{ onChange: onSearchChange, value: search }}/> :
|
||||
title && <h3 className="fw-semibold">{ title }</h3> }
|
||||
{ handleClose && (
|
||||
{search !== undefined ? (
|
||||
<Input autoFocus {...{ onChange: onSearchChange, value: search }} />
|
||||
) : (
|
||||
title && <h3 className="fw-semibold">{title}</h3>
|
||||
)}
|
||||
|
||||
{children && (
|
||||
<div {...{ className: "fy-media-browser-tools" }}>{children}</div>
|
||||
)}
|
||||
{handleClose && (
|
||||
<Icon
|
||||
{...{
|
||||
className: "icon-close-button",
|
||||
@@ -27,9 +40,6 @@ export default function ModalHeader({ children, handleClose, onSearchChange = ()
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{children && (
|
||||
<div {...{ className: "fy-media-browser-tools" }}>{children}</div>
|
||||
)}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
+11
-2
@@ -21,8 +21,14 @@ export default function CoreServicesProvider({
|
||||
querySubscriptions,
|
||||
state,
|
||||
}: Props) {
|
||||
const { byCategory, enqueueInferenceJob, inferenceJobs } =
|
||||
useInferenceJobsPolling({ sessionWrapper: state.sessionWrapper });
|
||||
const {
|
||||
byCategory,
|
||||
clearJobs,
|
||||
clearJobsStatus,
|
||||
enqueueInferenceJob,
|
||||
inferenceJobs,
|
||||
someJobsAreDone,
|
||||
} = useInferenceJobsPolling({ sessionWrapper: state.sessionWrapper });
|
||||
|
||||
const sessionProps = {
|
||||
querySession: querySession,
|
||||
@@ -34,7 +40,10 @@ export default function CoreServicesProvider({
|
||||
const inferenceJobsProps = {
|
||||
enqueue: enqueueInferenceJob,
|
||||
byCategory,
|
||||
clearJobs,
|
||||
clearJobsStatus,
|
||||
inferenceJobs,
|
||||
someJobsAreDone,
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
+4
@@ -3,13 +3,17 @@ import {
|
||||
BaseQueueObject,
|
||||
GetQueuesResponse,
|
||||
} from "@storyteller/components/src/api/stats/queues/GetQueues";
|
||||
import { FetchStatus } from "@storyteller/components/src/api/_common/SharedFetchTypes";
|
||||
import { useQueuePoll } from "hooks";
|
||||
|
||||
interface InferenceJobsContextType {
|
||||
inferenceJobs?: any;
|
||||
byCategory?: any;
|
||||
clearJobs?: () => void;
|
||||
clearJobsStatus?: FetchStatus;
|
||||
enqueue?: any;
|
||||
queueStats: GetQueuesResponse;
|
||||
someJobsAreDone?: boolean;
|
||||
}
|
||||
|
||||
export const InferenceJobsContext = createContext<InferenceJobsContextType>({
|
||||
|
||||
@@ -6,14 +6,23 @@ import { useModal } from "hooks";
|
||||
import { InferenceJobsModal } from "components/modals";
|
||||
|
||||
export default function useInferenceJobs(debug = false) {
|
||||
const { byCategory, enqueue, inferenceJobs, queueStats } =
|
||||
useContext(InferenceJobsContext);
|
||||
const {
|
||||
byCategory,
|
||||
clearJobs,
|
||||
clearJobsStatus,
|
||||
enqueue,
|
||||
inferenceJobs,
|
||||
queueStats,
|
||||
someJobsAreDone,
|
||||
} = useContext(InferenceJobsContext);
|
||||
|
||||
const { open } = useModal();
|
||||
const openJobListModal = (jobType?: FrontendInferenceJobType) =>
|
||||
open({ component: InferenceJobsModal, props: { jobType } });
|
||||
|
||||
return {
|
||||
clearJobs,
|
||||
clearJobsStatus,
|
||||
enqueue: (
|
||||
jobToken: string,
|
||||
jobTypeOverride?: FrontendInferenceJobType,
|
||||
@@ -30,5 +39,6 @@ export default function useInferenceJobs(debug = false) {
|
||||
jobStatusDescription: (jobState: JobState) =>
|
||||
Object.keys(JobState).filter(key => isNaN(Number(key)))[jobState],
|
||||
queueStats,
|
||||
someJobsAreDone,
|
||||
};
|
||||
}
|
||||
@@ -13,6 +13,11 @@ import {
|
||||
GetJobStatus,
|
||||
GetJobStatusResponse,
|
||||
} from "@storyteller/components/src/api/model_inference/GetJobStatus";
|
||||
import {
|
||||
DismissFinishedJobs,
|
||||
DismissFinishedJobsResponse,
|
||||
} from "@storyteller/components/src/api/jobs/DismissFinishedJobs";
|
||||
import { FetchStatus } from "@storyteller/components/src/api/_common/SharedFetchTypes";
|
||||
import { useInterval } from "hooks";
|
||||
|
||||
export type CategoryMap = Map<FrontendInferenceJobType, InferenceJob[]>;
|
||||
@@ -64,6 +69,8 @@ export default function useInferenceJobsPolling({
|
||||
const [byCategory, byCategorySet] = useState(newJobCategoryMap());
|
||||
const [initialized, initializedSet] = useState(false);
|
||||
|
||||
const [clearJobsStatus, clearJobsStatusSet] = useState(FetchStatus.ready);
|
||||
|
||||
// this boolean when set to true starts a useInterval loop, when false it runs clearInterval on that loop
|
||||
// this is to prevent memory leaks, and to update params provided to useInterval's onTick event.
|
||||
const [keepAlive, keepAliveSet] = useState(!!user);
|
||||
@@ -171,6 +178,25 @@ export default function useInferenceJobsPolling({
|
||||
keepAliveSet(true);
|
||||
};
|
||||
|
||||
const clearJobs = () => {
|
||||
keepAliveSet(false);
|
||||
if (clearJobsStatus === FetchStatus.ready) {
|
||||
clearJobsStatusSet(FetchStatus.in_progress);
|
||||
DismissFinishedJobs("", {}).then((res: DismissFinishedJobsResponse) => {
|
||||
if (res.success) {
|
||||
onTick({ eventProps: { inferenceJobs: [] } });
|
||||
keepAliveSet(true);
|
||||
clearJobsStatusSet(FetchStatus.ready);
|
||||
console.log("🗑️ Finish jobs cleared");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const someJobsAreDone =
|
||||
!!inferenceJobs &&
|
||||
inferenceJobs.some(job => !jobStateCanChange(job.jobState));
|
||||
|
||||
useInterval({
|
||||
eventProps: { inferenceJobs },
|
||||
interval,
|
||||
@@ -180,8 +206,11 @@ export default function useInferenceJobsPolling({
|
||||
|
||||
return {
|
||||
byCategory,
|
||||
clearJobs,
|
||||
clearJobsStatus,
|
||||
inferenceJobsByCategory: byCategory,
|
||||
enqueueInferenceJob,
|
||||
inferenceJobs,
|
||||
someJobsAreDone,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user