Add Workers Drawer

This commit is contained in:
2025-09-01 21:50:38 +02:00
parent 2019a11e93
commit 7c1d9125ba
4 changed files with 166 additions and 43 deletions

View File

@@ -13,6 +13,7 @@ import {
} from "./apiClient/data-contracts.ts"; } from "./apiClient/data-contracts.ts";
import Search from "./Components/Search.tsx"; import Search from "./Components/Search.tsx";
import { Typography } from "@mui/joy"; import { Typography } from "@mui/joy";
import Workers from "./Components/WorkerModal/Workers.tsx";
export const MangaConnectorContext = createContext<MangaConnector[]>([]); export const MangaConnectorContext = createContext<MangaConnector[]>([]);
export const MangaContext = createContext<Manga[]>([]); export const MangaContext = createContext<Manga[]>([]);
@@ -43,7 +44,7 @@ export default function App() {
if (response.ok) setFileLibraries(response.data); if (response.ok) setFileLibraries(response.data);
}); });
Api.queryMangaDownloadingList().then((response) => { Api.mangaDownloadingList().then((response) => {
if (response.ok) setManga(response.data); if (response.ok) setManga(response.data);
}); });
}, []); }, []);
@@ -67,6 +68,7 @@ export default function App() {
<Sheet className={"app"}> <Sheet className={"app"}>
<Header> <Header>
<Settings setApiUri={setApiUri} /> <Settings setApiUri={setApiUri} />
<Workers />
</Header> </Header>
<Sheet className={"app-content"}> <Sheet className={"app-content"}>
<MangaList mangas={manga}> <MangaList mangas={manga}>

View File

@@ -0,0 +1,72 @@
import { Dispatch, ReactNode, useContext, useState } from "react";
import Drawer from "@mui/joy/Drawer";
import { Button, Option, Select, Table } from "@mui/joy";
import { BaseWorker } from "../../apiClient/data-contracts.ts";
import ModalClose from "@mui/joy/ModalClose";
import { ApiContext } from "../../apiClient/ApiContext.tsx";
export default function (): ReactNode {
const [open, setOpen] = useState(false);
const [workers, setWorkers] = useState<BaseWorker[]>([]);
const Api = useContext(ApiContext);
Api.workerList().then((response) => {
if (response.ok) {
setWorkers(response.data);
}
});
return (
<>
<Button onClick={() => setOpen(true)}>Workers</Button>
<WorkerDrawer open={open} setOpen={setOpen} workers={workers} />
</>
);
}
function WorkerDrawer({
open,
setOpen,
workers,
}: {
open: boolean;
setOpen: Dispatch<boolean>;
workers: BaseWorker[];
}): ReactNode {
return (
<Drawer open={open} onClose={() => setOpen(false)} size={"lg"}>
<ModalClose />
<Table
borderAxis="bothBetween"
size="md"
stickyFooter={false}
stickyHeader
>
<thead>
<tr>
<th>Key</th>
<th>Can run</th>
<th>Missing dependencies</th>
</tr>
</thead>
<tbody>
{workers.map((worker) => {
return (
<tr>
<td>{worker.key}</td>
<td>{worker.allDependenciesFulfilled ? "yes" : "no"}</td>
<td>
<Select placeholder={"Missing dependencies"}>
{worker.missingDependencies?.map((worker) => {
return <Option value={worker.key}>{worker.key}</Option>;
})}
</Select>
</td>
</tr>
);
})}
</tbody>
</Table>
</Drawer>
);
}

View File

@@ -227,12 +227,42 @@ export class V2<
* @request GET:/v2/Manga * @request GET:/v2/Manga
*/ */
mangaList = (params: RequestParams = {}) => mangaList = (params: RequestParams = {}) =>
this.request<string[], any>({ this.request<Manga[], any>({
path: `/v2/Manga`, path: `/v2/Manga`,
method: "GET", method: "GET",
format: "json", format: "json",
...params, ...params,
}); });
/**
* No description
*
* @tags Manga
* @name MangaKeysList
* @summary Returns all cached API.Schema.MangaContext.Manga.Keys
* @request GET:/v2/Manga/Keys
*/
mangaKeysList = (params: RequestParams = {}) =>
this.request<string[], any>({
path: `/v2/Manga/Keys`,
method: "GET",
format: "json",
...params,
});
/**
* No description
*
* @tags Manga
* @name MangaDownloadingList
* @summary Returns all API.Schema.MangaContext.Manga that are being downloaded from at least one API.MangaConnectors.MangaConnector
* @request GET:/v2/Manga/Downloading
*/
mangaDownloadingList = (params: RequestParams = {}) =>
this.request<Manga[], any>({
path: `/v2/Manga/Downloading`,
method: "GET",
format: "json",
...params,
});
/** /**
* No description * No description
* *
@@ -863,27 +893,12 @@ export class V2<
format: "json", format: "json",
...params, ...params,
}); });
/**
* No description
*
* @tags Query
* @name QueryMangaDownloadingList
* @summary Returns all API.Schema.MangaContext.Manga that are being downloaded from at least one API.MangaConnectors.MangaConnector
* @request GET:/v2/Query/Manga/Downloading
*/
queryMangaDownloadingList = (params: RequestParams = {}) =>
this.request<Manga[], any>({
path: `/v2/Query/Manga/Downloading`,
method: "GET",
format: "json",
...params,
});
/** /**
* No description * No description
* *
* @tags Query * @tags Query
* @name QueryMangaSimilarNameList * @name QueryMangaSimilarNameList
* @summary Returns API.Schema.MangaContext.Manga with names similar to API.Schema.MangaContext.Manga (identified by MangaId * @summary Returns API.Schema.MangaContext.Manga with names similar to API.Schema.MangaContext.Manga (identified by MangaId)
* @request GET:/v2/Query/Manga/{MangaId}/SimilarName * @request GET:/v2/Query/Manga/{MangaId}/SimilarName
*/ */
queryMangaSimilarNameList = (mangaId: string, params: RequestParams = {}) => queryMangaSimilarNameList = (mangaId: string, params: RequestParams = {}) =>
@@ -1283,11 +1298,11 @@ export class V2<
* *
* @tags Worker * @tags Worker
* @name WorkerList * @name WorkerList
* @summary Returns all API.Workers.BaseWorker.Keys * @summary Returns all API.Workers.BaseWorker
* @request GET:/v2/Worker * @request GET:/v2/Worker
*/ */
workerList = (params: RequestParams = {}) => workerList = (params: RequestParams = {}) =>
this.request<string[], any>({ this.request<BaseWorker[], any>({
path: `/v2/Worker`, path: `/v2/Worker`,
method: "GET", method: "GET",
format: "json", format: "json",
@@ -1297,16 +1312,14 @@ export class V2<
* No description * No description
* *
* @tags Worker * @tags Worker
* @name WorkerWithIDsCreate * @name WorkerKeysList
* @summary Returns API.Workers.BaseWorker with requested WorkerIds * @summary Returns all API.Workers.BaseWorker.Keys
* @request POST:/v2/Worker/WithIDs * @request GET:/v2/Worker/Keys
*/ */
workerWithIDsCreate = (data: string[], params: RequestParams = {}) => workerKeysList = (params: RequestParams = {}) =>
this.request<BaseWorker[], any>({ this.request<string[], any>({
path: `/v2/Worker/WithIDs`, path: `/v2/Worker/Keys`,
method: "POST", method: "GET",
body: data,
type: ContentType.Json,
format: "json", format: "json",
...params, ...params,
}); });

View File

@@ -52,7 +52,11 @@ export interface AltTitle {
* @maxLength 256 * @maxLength 256
*/ */
title: string; title: string;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface Author { export interface Author {
@@ -61,20 +65,24 @@ export interface Author {
* @maxLength 128 * @maxLength 128
*/ */
authorName: string; authorName: string;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface BaseWorker { export interface BaseWorker {
/** Workers this Worker depends on being completed before running. */ /** Workers this Worker depends on being completed before running. */
dependsOn?: BaseWorker[] | null; dependsOn?: BaseWorker[] | null;
/** Dependencies and dependencies of dependencies. See also API.Workers.BaseWorker.DependsOn. */
allDependencies?: BaseWorker[] | null;
/** API.Workers.BaseWorker.AllDependencies and Self. */
dependenciesAndSelf?: BaseWorker[] | null;
/** API.Workers.BaseWorker.DependsOn where API.Workers.WorkerExecutionState is less than Completed. */ /** API.Workers.BaseWorker.DependsOn where API.Workers.WorkerExecutionState is less than Completed. */
missingDependencies?: BaseWorker[] | null; missingDependencies?: BaseWorker[] | null;
allDependenciesFulfilled?: boolean; allDependenciesFulfilled?: boolean;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface Chapter { export interface Chapter {
@@ -103,7 +111,11 @@ export interface Chapter {
fileName: string; fileName: string;
downloaded: boolean; downloaded: boolean;
fullArchiveFilePath?: string | null; fullArchiveFilePath?: string | null;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface ChapterMangaConnectorId { export interface ChapterMangaConnectorId {
@@ -129,7 +141,11 @@ export interface ChapterMangaConnectorId {
*/ */
websiteUrl?: string | null; websiteUrl?: string | null;
useForDownload?: boolean; useForDownload?: boolean;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface FileLibrary { export interface FileLibrary {
@@ -143,7 +159,11 @@ export interface FileLibrary {
* @maxLength 512 * @maxLength 512
*/ */
libraryName: string; libraryName: string;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface GotifyRecord { export interface GotifyRecord {
@@ -167,7 +187,11 @@ export interface LibraryConnector {
* @maxLength 256 * @maxLength 256
*/ */
auth: string; auth: string;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface Link { export interface Link {
@@ -182,7 +206,11 @@ export interface Link {
* @maxLength 2048 * @maxLength 2048
*/ */
linkUrl: string; linkUrl: string;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface Manga { export interface Manga {
@@ -220,7 +248,11 @@ export interface Manga {
chapterIds?: string[] | null; chapterIds?: string[] | null;
idsOnMangaConnectors?: Record<string, string>; idsOnMangaConnectors?: Record<string, string>;
mangaConnectorIdsIds?: string[] | null; mangaConnectorIdsIds?: string[] | null;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface MangaConnector { export interface MangaConnector {
@@ -270,7 +302,11 @@ export interface MangaMangaConnectorId {
*/ */
websiteUrl?: string | null; websiteUrl?: string | null;
useForDownload?: boolean; useForDownload?: boolean;
key?: string | null; /**
* @minLength 16
* @maxLength 64
*/
key: string;
} }
export interface MangaTag { export interface MangaTag {