Job Drawer add "Re-Run" button,

Move Chapter-Drawer to the bottom of the screen (inline with Manga-Drawer)
Format JobState and JobType (with spaces)
This commit is contained in:
2025-06-18 17:51:29 +02:00
parent b4b4479e9b
commit 4c81c571a4
3 changed files with 41 additions and 28 deletions

View File

@ -1,14 +1,15 @@
import React, {ReactElement, useContext, useState} from "react";
import IChapter from "../api/types/IChapter.ts";
import {Box, Chip, Link, Stack, Typography} from "@mui/joy";
import {Box, Chip, Link, Stack, Tooltip, Typography} from "@mui/joy";
import {MangaFromId} from "./Manga.tsx";
import {ChapterContext} from "../api/Contexts/ChapterContext.tsx";
import Drawer from "@mui/joy/Drawer";
import ModalClose from "@mui/joy/ModalClose";
import {Archive} from "@mui/icons-material";
export function ChapterPopupFromId({chapterId, open, setOpen, children}: { chapterId: string | null, open: boolean, setOpen: React.Dispatch<React.SetStateAction<boolean>>, children?: ReactElement<any, any> | ReactElement<any, any>[] | undefined }) {
return (
<Drawer open={open} onClose={() => setOpen(false)}>
<Drawer anchor={"bottom"} open={open} onClose={() => setOpen(false)}>
<ModalClose />
{
chapterId !== null ?
@ -35,13 +36,13 @@ export function ChapterFromId({chapterId, children} : { chapterId: string, child
export function Chapter({chapter, children} : { chapter: IChapter, children?: ReactElement<any, any> | ReactElement<any, any>[] | undefined }){
return (
<Stack direction={"row"}>
<Stack direction={"row"} spacing={5} sx={{paddingTop: "10px"}}>
<MangaFromId mangaId={chapter.parentMangaId} />
<Box>
<Link target={"_blank"} level={"title-lg"} href={chapter.url}>{chapter.title}</Link>
<Typography>Volume <Chip>{chapter.volumeNumber}</Chip></Typography>
<Typography>Chapter <Chip>{chapter.chapterNumber}</Chip></Typography>
<Typography>Title <Chip>{chapter.title}</Chip></Typography>
<Tooltip title={chapter.fullArchiveFilePath} placement={"bottom-start"}><Archive /></Tooltip>
</Box>
{children}
</Stack>

View File

@ -9,11 +9,11 @@ import {
Table,
Typography
} from "@mui/joy";
import {GetJobsInState, GetJobsOfTypeAndWithState, GetJobsWithType} from "../api/Job.tsx";
import {GetJobsInState, GetJobsOfTypeAndWithState, GetJobsWithType, StartJob} from "../api/Job.tsx";
import * as React from "react";
import {useCallback, useContext, useEffect, useState} from "react";
import {ApiUriContext} from "../api/fetchApi.tsx";
import IJob, {JobState, JobType} from "../api/types/Jobs/IJob.ts";
import IJob, {JobState, JobStateToString, JobType, JobTypeToString} from "../api/types/Jobs/IJob.ts";
import ModalClose from "@mui/joy/ModalClose";
import {MangaPopupFromId} from "./MangaPopup.tsx";
import IJobWithMangaId from "../api/types/Jobs/IJobWithMangaId.ts";
@ -86,6 +86,10 @@ export default function JobsDrawer({open, connected, setOpen} : {open: boolean,
setChapterPopupOpen(true);
}
const ReRunJob = useCallback((jobId: string) => {
StartJob(apiUri, jobId, false);
}, [apiUri]);
return (
<Drawer size={"lg"} anchor={"left"} open={open} onClose={() => setOpen(false)}>
<ModalClose />
@ -95,13 +99,13 @@ export default function JobsDrawer({open, connected, setOpen} : {open: boolean,
<Typography>State</Typography>
}>
<Option value={null}>None</Option>
{Object.keys(JobState).map((state) => <Option value={state}>{state}</Option>)}
{Object.keys(JobState).map((state) => <Option value={state}>{JobStateToString(state)}</Option>)}
</Select>
<Select placeholder={"Type"} value={filterType} onChange={handleChangeType} startDecorator={
<Typography>Type</Typography>
}>
<Option value={null}>None</Option>
{Object.keys(JobType).map((type) => <Option value={type}>{type}</Option>)}
{Object.keys(JobType).map((type) => <Option value={type}>{JobTypeToString(type)}</Option>)}
</Select>
<Input type={"number"}
value={page}
@ -111,23 +115,25 @@ export default function JobsDrawer({open, connected, setOpen} : {open: boolean,
endDecorator={<Typography>/{Math.ceil(allJobs.length / pageSize)}</Typography>}/>
</Stack>
<DialogContent>
<Table borderAxis={"xBetween"} stickyHeader>
<Table borderAxis={"bothBetween"} stickyHeader sx={{tableLayout: "auto", width: "100%"}}>
<thead>
<tr>
<th>Type</th>
<th>State</th>
<th>Last Execution</th>
<th>NextExecution</th>
<th>Next Execution</th>
<th></th>
<th>Extra</th>
</tr>
</thead>
<tbody>
{allJobs.slice((page-1)*pageSize, page*pageSize).map((job) => (
<tr key={job.jobId}>
<td>{job.jobType}</td>
<td>{job.state}</td>
<td>{JobTypeToString(job.jobType)}</td>
<td>{JobStateToString(job.state)}</td>
<td>{new Date(job.lastExecution).toLocaleString()}</td>
<td>{new Date(job.nextExecution).toLocaleString()}</td>
<td style={{whiteSpace: "nowrap"}}><Button onClick={() => ReRunJob(job.jobId)}>Re-Run</Button></td>
<td>{ExtraContent(job, OpenMangaPopupDrawer, OpenChapterPopupDrawer)}</td>
</tr>
))}
@ -150,8 +156,7 @@ function ExtraContent(job: IJob, OpenMangaPopupDrawer: (mangaId: string) => void
case JobType.MoveMangaLibraryJob:
return <Button onClick={() => OpenMangaPopupDrawer((job as IJobWithMangaId).mangaId)}>Open Manga</Button>
case JobType.DownloadSingleChapterJob:
case JobType.UpdateSingleChapterDownloadedJob:
return <Button onClick={() => OpenChapterPopupDrawer((job as IJobWithChapterId).chapterId)}>ShowChapter</Button>
return <Button onClick={() => OpenChapterPopupDrawer((job as IJobWithChapterId).chapterId)}>Show Chapter</Button>
default:
return null;
}

View File

@ -16,10 +16,13 @@ export enum JobType {
RetrieveChaptersJob = "RetrieveChaptersJob",
UpdateChaptersDownloadedJob = "UpdateChaptersDownloadedJob",
MoveMangaLibraryJob = "MoveMangaLibraryJob",
UpdateSingleChapterDownloadedJob = "UpdateSingleChapterDownloadedJob",
UpdateCoverJob = "UpdateCoverJob"
}
export function JobTypeToString(job: JobType | string): string {
return job.replace(/([A-Z])/g, ' $1').replace("Job", "").trim();
}
export enum JobState {
FirstExecution = "FirstExecution",
Running = "Running",
@ -27,3 +30,7 @@ export enum JobState {
CompletedWaiting = "CompletedWaiting",
Failed = "Failed"
}
export function JobStateToString(state: JobState | string): string {
return state.replace(/([A-Z])/g, ' $1').trim();
}