mirror of
https://github.com/C9Glax/tranga-website.git
synced 2025-05-20 05:03:02 +02:00
fetchApi dont throw rejected promises
This commit is contained in:
parent
a0d15e08a7
commit
f391ace9b2
@ -5,7 +5,7 @@ import {
|
||||
CardContent, CardCover,
|
||||
Link,
|
||||
} from "@mui/joy";
|
||||
import IManga, {DefaultManga} from "../api/types/IManga.ts";
|
||||
import IManga from "../api/types/IManga.ts";
|
||||
import {CSSProperties, ReactElement, useCallback, useContext, useEffect, useRef, useState} from "react";
|
||||
import {GetMangaById, GetMangaCoverImageUrl} from "../api/Manga.tsx";
|
||||
import {ApiUriContext, getData} from "../api/fetchApi.tsx";
|
||||
@ -16,7 +16,7 @@ import IMangaConnector from "../api/types/IMangaConnector.ts";
|
||||
import {GetConnector} from "../api/MangaConnector.tsx";
|
||||
|
||||
export function MangaFromId({mangaId, children} : { mangaId: string, children?: ReactElement<any, any> | ReactElement<any, any>[] | undefined }){
|
||||
const [manga, setManga] = useState(DefaultManga);
|
||||
const [manga, setManga] = useState<IManga>();
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const apiUri = useContext(ApiUriContext);
|
||||
@ -32,7 +32,7 @@ export function MangaFromId({mangaId, children} : { mangaId: string, children?:
|
||||
|
||||
return (
|
||||
<>
|
||||
{loading ? <></> : <Manga manga={manga} children={children} /> }
|
||||
{loading || manga === undefined ? <></> : <Manga manga={manga} children={children} /> }
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -35,21 +35,23 @@ export default function MangaList({connected, children}: {connected: boolean, ch
|
||||
const timerRef = React.useRef<ReturnType<typeof setInterval>>(undefined);
|
||||
const updateTimer = () => {
|
||||
if(!connected){
|
||||
console.debug("Clear timer");
|
||||
clearTimeout(timerRef.current);
|
||||
return;
|
||||
}else{
|
||||
console.debug("Add timer");
|
||||
if(timerRef.current === undefined) {
|
||||
console.log("Added timer!");
|
||||
getJobList();
|
||||
timerRef.current = setInterval(() => {
|
||||
getJobList();
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(
|
||||
<Stack direction="row" spacing={1} flexWrap={"wrap"}>
|
||||
{children}
|
||||
{jobList.map((job) => (
|
||||
{jobList?.map((job) => (
|
||||
<MangaFromId key={job.mangaId} mangaId={job.mangaId}>
|
||||
<Button color={"danger"} endDecorator={<Remove />} onClick={() => deleteJob(job.jobId)}>Delete</Button>
|
||||
</MangaFromId>
|
||||
|
@ -35,7 +35,7 @@ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Disp
|
||||
const [step, setStep] = useState<number>(1);
|
||||
|
||||
const apiUri = useContext(ApiUriContext);
|
||||
const [mangaConnectors, setMangaConnectors] = useState<IMangaConnector[]>([]);
|
||||
const [mangaConnectors, setMangaConnectors] = useState<IMangaConnector[]>();
|
||||
const [mangaConnectorsLoading, setMangaConnectorsLoading] = useState<boolean>(true);
|
||||
const [selectedMangaConnector, setSelectedMangaConnector] = useState<IMangaConnector>();
|
||||
|
||||
@ -83,7 +83,7 @@ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Disp
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ListItemDecorator>
|
||||
<Avatar size="sm" src={mangaConnectors.find((o) => o.name === option.value)?.iconUrl} />
|
||||
<Avatar size="sm" src={mangaConnectors?.find((o) => o.name === option.value)?.iconUrl} />
|
||||
</ListItemDecorator>
|
||||
{option.label}
|
||||
</React.Fragment>
|
||||
@ -101,13 +101,13 @@ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Disp
|
||||
<ModalClose />
|
||||
<Stepper orientation={"vertical"} sx={{ height: '100%', width: "calc(100% - 80px)", margin:"40px"}}>
|
||||
<Step indicator={
|
||||
<StepIndicator variant={step==1?"solid":"outlined"} color={mangaConnectors.length < 1 ? "danger" : "primary"}>
|
||||
<StepIndicator variant={step==1?"solid":"outlined"} color={mangaConnectors?.length??0 < 1 ? "danger" : "primary"}>
|
||||
1
|
||||
</StepIndicator>}>
|
||||
<Skeleton loading={mangaConnectorsLoading}>
|
||||
<Select
|
||||
color={mangaConnectors.length < 1 ? "danger" : "neutral"}
|
||||
disabled={mangaConnectorsLoading || resultsLoading || mangaConnectors.length < 1}
|
||||
color={mangaConnectors?.length??0 < 1 ? "danger" : "neutral"}
|
||||
disabled={mangaConnectorsLoading || resultsLoading || mangaConnectors?.length == null || mangaConnectors.length < 1}
|
||||
placeholder={"Select Connector"}
|
||||
slotProps={{
|
||||
listbox: {
|
||||
@ -120,9 +120,9 @@ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Disp
|
||||
renderValue={renderValue}
|
||||
onChange={(_e, newValue) => {
|
||||
setStep(2);
|
||||
setSelectedMangaConnector(mangaConnectors.find((o) => o.name === newValue));
|
||||
setSelectedMangaConnector(mangaConnectors?.find((o) => o.name === newValue));
|
||||
}}
|
||||
endDecorator={<Chip size={"sm"} color={mangaConnectors.length < 1 ? "danger" : "primary"}>{mangaConnectors.length}</Chip>}>
|
||||
endDecorator={<Chip size={"sm"} color={mangaConnectors?.length??0 < 1 ? "danger" : "primary"}>{mangaConnectors?.length}</Chip>}>
|
||||
{mangaConnectors?.map((connector: IMangaConnector) => ConnectorOption(connector))}
|
||||
</Select>
|
||||
</Skeleton>
|
||||
|
@ -0,0 +1,4 @@
|
||||
import {createContext} from "react";
|
||||
import IMangaConnector from "../types/IMangaConnector.ts";
|
||||
|
||||
export const MangaConnectorContext = createContext<IMangaConnector[]>([]);
|
@ -88,10 +88,10 @@ export const CreateUpdateAllMetadataJob = async (apiUri: string) : Promise<strin
|
||||
return await putData(`${apiUri}/v2/Job/UpdateAllMetadataJob`, {}) as Promise<string[]>;
|
||||
}
|
||||
|
||||
export const StartJob = async (apiUri: string, jobId: string) : Promise<object> => {
|
||||
export const StartJob = async (apiUri: string, jobId: string) : Promise<object | undefined> => {
|
||||
return await postData(`${apiUri}/v2/Job/${jobId}/Start`, {});
|
||||
}
|
||||
|
||||
export const StopJob = async (apiUri: string, jobId: string) : Promise<object> => {
|
||||
export const StopJob = async (apiUri: string, jobId: string) : Promise<object | undefined> => {
|
||||
return await postData(`${apiUri}/v2/Job/${jobId}/Stop`, {});
|
||||
}
|
@ -18,14 +18,14 @@ export const DeleteLibrary = async (apiUri: string, libraryId: string) : Promis
|
||||
return await deleteData(`${apiUri}/v2/LocalLibraries/${libraryId}`);
|
||||
}
|
||||
|
||||
export const ChangeLibraryPath = async (apiUri: string, libraryId: string, newPath: string) : Promise<object> => {
|
||||
export const ChangeLibraryPath = async (apiUri: string, libraryId: string, newPath: string) : Promise<object | undefined> => {
|
||||
return await patchData(`${apiUri}/v2/LocalLibraries/${libraryId}/ChangeBasePath`, newPath);
|
||||
}
|
||||
|
||||
export const ChangeLibraryName = async (apiUri: string, libraryId: string, newName: string) : Promise<object> => {
|
||||
export const ChangeLibraryName = async (apiUri: string, libraryId: string, newName: string) : Promise<object | undefined> => {
|
||||
return await patchData(`${apiUri}/v2/LocalLibraries/${libraryId}/ChangeName`, newName);
|
||||
}
|
||||
|
||||
export const UpdateLibrary = async (apiUri: string, libraryId: string, record: INewLibraryRecord) : Promise<object> => {
|
||||
export const UpdateLibrary = async (apiUri: string, libraryId: string, record: INewLibraryRecord) : Promise<object | undefined> => {
|
||||
return await patchData(`${apiUri}/v2/LocalLibraries/${libraryId}`, record);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import {deleteData, getData, patchData, postData} from './fetchApi.tsx';
|
||||
import IManga from "./types/IManga.ts";
|
||||
import IManga, {DefaultManga} from "./types/IManga.ts";
|
||||
import IChapter from "./types/IChapter.ts";
|
||||
|
||||
export const GetAllManga = async (apiUri: string) : Promise<IManga[]> => {
|
||||
@ -15,63 +15,83 @@ export const GetMangaWithIds = async (apiUri: string, mangaIds: string[]) : Prom
|
||||
export const GetMangaById = async (apiUri: string, mangaId: string) : Promise<IManga> => {
|
||||
if(mangaId === undefined || mangaId === null || mangaId.length < 1)
|
||||
return Promise.reject("mangaId was not provided");
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return Promise.reject("Default Manga was requested");
|
||||
return await getData(`${apiUri}/v2/Manga/${mangaId}`) as Promise<IManga>;
|
||||
}
|
||||
|
||||
export const DeleteManga = async (apiUri: string, mangaId: string) : Promise<void> => {
|
||||
if(mangaId === undefined || mangaId === null || mangaId.length < 1)
|
||||
return Promise.reject("mangaId was not provided");
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return Promise.reject("Default Manga was requested");
|
||||
return await deleteData(`${apiUri}/v2/Manga/${mangaId}`);
|
||||
}
|
||||
|
||||
export const GetMangaCoverImageUrl = (apiUri: string, mangaId: string, ref: HTMLImageElement | undefined | null) : string => {
|
||||
if(ref == null || ref == undefined)
|
||||
return `${apiUri}/v2/Manga/${mangaId}/Cover?width=64&height=64`;
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return "/blahaj.png";
|
||||
return `${apiUri}/v2/Manga/${mangaId}/Cover?width=${ref.clientWidth}&height=${ref.clientHeight}`;
|
||||
}
|
||||
|
||||
export const GetChapters = async (apiUri: string, mangaId: string) : Promise<IChapter[]> => {
|
||||
if(mangaId === undefined || mangaId === null || mangaId.length < 1)
|
||||
return Promise.reject("mangaId was not provided");
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return Promise.reject("Default Manga was requested");
|
||||
return await getData(`${apiUri}/v2/Manga/${mangaId}/Chapters`) as Promise<IChapter[]>;
|
||||
}
|
||||
|
||||
export const GetDownloadedChapters = async (apiUri: string, mangaId: string) : Promise<IChapter[]> => {
|
||||
if(mangaId === undefined || mangaId === null || mangaId.length < 1)
|
||||
return Promise.reject("mangaId was not provided");
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return Promise.reject("Default Manga was requested");
|
||||
return await getData(`${apiUri}/v2/Manga/${mangaId}/Chapters/Downloaded`) as Promise<IChapter[]>;
|
||||
}
|
||||
|
||||
export const GetNotDownloadedChapters = async (apiUri: string, mangaId: string) : Promise<IChapter[]> => {
|
||||
if(mangaId === undefined || mangaId === null || mangaId.length < 1)
|
||||
return Promise.reject("mangaId was not provided");
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return Promise.reject("Default Manga was requested");
|
||||
return await getData(`${apiUri}/v2/Manga/${mangaId}/Chapters/NotDownloaded`) as Promise<IChapter[]>;
|
||||
}
|
||||
|
||||
export const GetLatestChapterAvailable = async (apiUri: string, mangaId: string) : Promise<IChapter> => {
|
||||
if(mangaId === undefined || mangaId === null || mangaId.length < 1)
|
||||
return Promise.reject("mangaId was not provided");
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return Promise.reject("Default Manga was requested");
|
||||
return await getData(`${apiUri}/v2/Manga/${mangaId}/Chapter/LatestAvailable`) as Promise<IChapter>;
|
||||
}
|
||||
|
||||
export const GetLatestChapterDownloaded = async (apiUri: string, mangaId: string) : Promise<IChapter> => {
|
||||
if(mangaId === undefined || mangaId === null || mangaId.length < 1)
|
||||
return Promise.reject("mangaId was not provided");
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return Promise.reject("Default Manga was requested");
|
||||
return await getData(`${apiUri}/v2/Manga/${mangaId}/Chapter/LatestDownloaded`) as Promise<IChapter>;
|
||||
}
|
||||
|
||||
export const SetIgnoreThreshold = async (apiUri: string, mangaId: string, chapterThreshold: number) : Promise<object> => {
|
||||
export const SetIgnoreThreshold = async (apiUri: string, mangaId: string, chapterThreshold: number) : Promise<object | undefined> => {
|
||||
if(mangaId === undefined || mangaId === null || mangaId.length < 1)
|
||||
return Promise.reject("mangaId was not provided");
|
||||
if(chapterThreshold === undefined || chapterThreshold === null)
|
||||
return Promise.reject("chapterThreshold was not provided");
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return Promise.reject("Default Manga was requested");
|
||||
return await patchData(`${apiUri}/v2/Manga/${mangaId}/IgnoreChaptersBefore`, chapterThreshold);
|
||||
}
|
||||
|
||||
export const MoveFolder = async (apiUri: string, mangaId: string, newPath: string) : Promise<object> => {
|
||||
export const MoveFolder = async (apiUri: string, mangaId: string, newPath: string) : Promise<object | undefined> => {
|
||||
if(mangaId === undefined || mangaId === null || mangaId.length < 1)
|
||||
return Promise.reject("mangaId was not provided");
|
||||
if(newPath === undefined || newPath === null || newPath.length < 1)
|
||||
return Promise.reject("newPath was not provided");
|
||||
if(mangaId === DefaultManga.mangaId)
|
||||
return Promise.reject("Default Manga was requested");
|
||||
return await postData(`${apiUri}/v2/Manga/{MangaId}/MoveFolder`, {newPath});
|
||||
}
|
@ -17,7 +17,7 @@ export const GetDisabledConnectors = async (apiUri: string) : Promise<IMangaCon
|
||||
return await getData(`${apiUri}/v2/MangaConnector/disabled`) as Promise<IMangaConnector[]>
|
||||
}
|
||||
|
||||
export const SetConnectorEnabled = async (apiUri: string, connectorName: string, enabled: boolean) : Promise<object> => {
|
||||
export const SetConnectorEnabled = async (apiUri: string, connectorName: string, enabled: boolean) : Promise<object | undefined> => {
|
||||
if(connectorName === undefined || connectorName === null || connectorName.length < 1)
|
||||
return Promise.reject("connectorName was not provided");
|
||||
if(enabled === undefined || enabled === null)
|
||||
|
@ -2,24 +2,33 @@ import {createContext} from "react";
|
||||
|
||||
export const ApiUriContext = createContext<string>("");
|
||||
|
||||
export function getData(uri: string) : Promise<object> {
|
||||
return makeRequest("GET", uri, null) as Promise<object>;
|
||||
export function getData(uri: string) : Promise<object | undefined> {
|
||||
return makeRequestWrapper("GET", uri, null);
|
||||
}
|
||||
|
||||
export function postData(uri: string, content: object | string | number | boolean) : Promise<object> {
|
||||
return makeRequest("POST", uri, content) as Promise<object>;
|
||||
export function postData(uri: string, content: object | string | number | boolean) : Promise<object | undefined> {
|
||||
return makeRequestWrapper("POST", uri, content);
|
||||
}
|
||||
|
||||
export function deleteData(uri: string) : Promise<void> {
|
||||
return makeRequest("DELETE", uri, null) as Promise<void>;
|
||||
return makeRequestWrapper("DELETE", uri, null) as Promise<void>;
|
||||
}
|
||||
|
||||
export function patchData(uri: string, content: object | string | number | boolean) : Promise<object> {
|
||||
return makeRequest("patch", uri, content) as Promise<object>;
|
||||
export function patchData(uri: string, content: object | string | number | boolean) : Promise<object | undefined> {
|
||||
return makeRequestWrapper("patch", uri, content);
|
||||
}
|
||||
|
||||
export function putData(uri: string, content: object | string | number | boolean) : Promise<object> {
|
||||
return makeRequest("PUT", uri, content) as Promise<object>;
|
||||
export function putData(uri: string, content: object | string | number | boolean) : Promise<object | undefined> {
|
||||
return makeRequestWrapper("PUT", uri, content);
|
||||
}
|
||||
|
||||
function makeRequestWrapper(method: string, uri: string, content: object | string | number | null | boolean) : Promise<object | undefined>{
|
||||
return makeRequest(method, uri, content)
|
||||
.then((result) => result as Promise<object>)
|
||||
.catch((e) => {
|
||||
console.warn(e);
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
}
|
||||
|
||||
let currentlyRequestedEndpoints: string[] = [];
|
||||
|
@ -1,5 +1,5 @@
|
||||
import IJob from "./IJob";
|
||||
import IJobWithMangaId from "./IJobWithMangaId.ts";
|
||||
|
||||
export default interface IDownloadAvailableChaptersJob extends IJobWithMangaId {
|
||||
|
||||
export default interface IDownloadAvailableChaptersJob extends IJob {
|
||||
mangaId: string;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import IJob from "./IJob";
|
||||
import IJobWithMangaId from "./IJobWithMangaId.ts";
|
||||
|
||||
export default interface IDownloadMangaCoverJob extends IJobWithMangaId {
|
||||
|
||||
export default interface IDownloadMangaCoverJob extends IJob {
|
||||
mangaId: string;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import IJob from "./IJob";
|
||||
import IJobWithChapterId from "./IJobWithChapterId.tsx";
|
||||
|
||||
export default interface IDownloadSingleChapterJob extends IJobWithChapterId {
|
||||
|
||||
export default interface IDownloadSingleChapterJob extends IJob {
|
||||
chapterId: string;
|
||||
}
|
@ -18,7 +18,8 @@ export enum JobType {
|
||||
RetrieveChaptersJob = "RetrieveChaptersJob",
|
||||
UpdateChaptersDownloadedJob = "UpdateChaptersDownloadedJob",
|
||||
MoveMangaLibraryJob = "MoveMangaLibraryJob",
|
||||
UpdateSingleChapterDownloadedJob = "UpdateSingleChapterDownloadedJob"
|
||||
UpdateSingleChapterDownloadedJob = "UpdateSingleChapterDownloadedJob",
|
||||
UpdateCoverJob = "UpdateCoverJob"
|
||||
}
|
||||
|
||||
export enum JobState {
|
||||
|
5
tranga-website/src/api/types/Jobs/IJobWithChapterId.tsx
Normal file
5
tranga-website/src/api/types/Jobs/IJobWithChapterId.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import IJob from "./IJob.ts";
|
||||
|
||||
export default interface IJobWithChapterId extends IJob {
|
||||
chapterId: string;
|
||||
}
|
5
tranga-website/src/api/types/Jobs/IJobWithMangaId.ts
Normal file
5
tranga-website/src/api/types/Jobs/IJobWithMangaId.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import IJob from "./IJob.ts";
|
||||
|
||||
export default interface IJobWithMangaId extends IJob {
|
||||
mangaId: string;
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import IJob from "./IJob";
|
||||
import IJobWithMangaId from "./IJobWithMangaId.ts";
|
||||
|
||||
export default interface IMoveMangaLibraryJob extends IJob {
|
||||
MangaId: string;
|
||||
export default interface IMoveMangaLibraryJob extends IJobWithMangaId {
|
||||
ToLibraryId: string;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import IJob from "./IJob";
|
||||
import IJobWithMangaId from "./IJobWithMangaId.ts";
|
||||
|
||||
export default interface IRetrieveChaptersJob extends IJobWithMangaId {
|
||||
|
||||
export default interface IRetrieveChaptersJob extends IJob {
|
||||
mangaId: string;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import IJobWithMangaId from "./IJobWithMangaId.ts";
|
||||
|
||||
export default interface IUpdateChaptersDownloadedJob extends IJobWithMangaId {
|
||||
|
||||
}
|
5
tranga-website/src/api/types/Jobs/IUpdateCoverJob.ts
Normal file
5
tranga-website/src/api/types/Jobs/IUpdateCoverJob.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import IJobWithMangaId from "./IJobWithMangaId.ts";
|
||||
|
||||
export default interface IUpdateCoverJob extends IJobWithMangaId {
|
||||
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
import IJob from "./IJob";
|
||||
|
||||
export default interface IUpdateFilesDownloadedJob extends IJob {
|
||||
mangaId: string;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
import IJob from "./IJob";
|
||||
|
||||
export default interface IUpdateMetadataJob extends IJob {
|
||||
mangaId: string;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import IJobWithChapterId from "./IJobWithChapterId.tsx";
|
||||
|
||||
export default interface IUpdateChaptersDownloadedJob extends IJobWithChapterId {
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user