2025-04-01 04:13:50 +02:00

156 lines
6.3 KiB
TypeScript

import React, {useEffect, useState} from 'react';
import Footer from "./modules/Footer";
import Search from "./modules/Search";
import Header from "./modules/Header";
import MonitorJobsList from "./modules/MonitorJobsList";
import './styles/index.css'
import {useCookies} from "react-cookie";
import Loader from "./modules/Loader";
import IFrontendSettings from "./modules/types/IFrontendSettings";
import {LoadFrontendSettings} from "./modules/api/FrontendSettings";
export default function App(){
const [, setCookie] = useCookies(['apiUri', 'jobInterval']);
const [connected, setConnected] = React.useState(false);
const [showSearch, setShowSearch] = React.useState(false);
const [frontendSettings, setFrontendSettings] = useState<IFrontendSettings>(LoadFrontendSettings());
const [updateInterval, setUpdateInterval] = React.useState<number | undefined>(undefined);
const checkConnectedInterval = 1000;
useEffect(() => {
setCookie('apiUri', frontendSettings.apiUri);
setCookie('jobInterval', frontendSettings.jobInterval);
updateConnected(frontendSettings.apiUri, connected, setConnected);
}, [frontendSettings]);
useEffect(() => {
if(updateInterval === undefined){
setUpdateInterval(setInterval(() => {
updateConnected(frontendSettings.apiUri, connected, setConnected);
}, checkConnectedInterval));
}else{
clearInterval(updateInterval);
setUpdateInterval(undefined);
}
}, [connected]);
return(<div>
<Header apiUri={frontendSettings.apiUri} backendConnected={connected} settings={frontendSettings} setFrontendSettings={setFrontendSettings} />
{connected
? <>
{showSearch
? <>
<Search apiUri={frontendSettings.apiUri} jobInterval={frontendSettings.jobInterval} closeSearch={() => setShowSearch(false)} />
<hr/>
</>
: <></>}
<MonitorJobsList apiUri={frontendSettings.apiUri} onStartSearch={() => setShowSearch(true)} connectedToBackend={connected} checkConnectedInterval={checkConnectedInterval} />
</>
: <>
<h1>No connection to the Backend.</h1>
<h3>Check the Settings ApiUri.</h3>
<Loader loading={true} />
</>}
<Footer apiUri={frontendSettings.apiUri} connectedToBackend={connected} checkConnectedInterval={checkConnectedInterval} />
</div>)
}
export function getData(uri: string) : Promise<object> {
return makeRequest("GET", uri, null) as Promise<object>;
}
export function postData(uri: string, content: object | string | number | boolean) : Promise<object> {
return makeRequest("POST", uri, content) as Promise<object>;
}
export function deleteData(uri: string) : Promise<void> {
return makeRequest("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 putData(uri: string, content: object | string | number | boolean) : Promise<object> {
return makeRequest("PUT", uri, content) as Promise<object>;
}
let currentlyRequestedEndpoints: string[] = [];
function makeRequest(method: string, uri: string, content: object | string | number | null | boolean) : Promise<object | void> {
const id = method + uri;
if(currentlyRequestedEndpoints.find(x => x == id) != undefined)
return Promise.reject(`Already requested: ${method} ${uri}`);
currentlyRequestedEndpoints.push(id);
return fetch(uri,
{
method: method,
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: content ? JSON.stringify(content) : null
})
.then(function(response){
if(!response.ok){
if(response.status === 503){
let retryHeaderVal = response.headers.get("Retry-After");
let seconds = 10;
if(!retryHeaderVal){
return response.text().then(text => {
seconds = parseInt(text);
return new Promise(resolve => setTimeout(resolve, seconds * 1000))
.then(() => {
return makeRequest(method, uri, content);
});
});
}else {
seconds = parseInt(retryHeaderVal);
return new Promise(resolve => setTimeout(resolve, seconds * 1000))
.then(() => {
return makeRequest(method, uri, content);
});
}
}else
throw new Error(response.statusText);
}
let json = response.json();
return json.then((json) => json).catch(() => null);
})
.catch(function(err : Error){
console.error(`Error ${method}ing Data ${uri}\n${err}`);
return Promise.reject();
}).finally(() => currentlyRequestedEndpoints.splice(currentlyRequestedEndpoints.indexOf(id), 1));
}
export function isValidUri(uri: string) : boolean{
try {
new URL(uri);
return true;
} catch (err) {
return false;
}
}
const updateConnected = (apiUri: string, connected: boolean, setConnected: (c: boolean) => void) => {
checkConnection(apiUri)
.then(res => {
if(connected != res)
setConnected(res);
})
.catch(() => setConnected(false));
}
export const checkConnection = async (apiUri: string): Promise<boolean> =>{
return fetch(`${apiUri}/swagger/v2/swagger.json`,
{
method: 'GET',
})
.then((response) => {
if(!(response.ok && response.status == 200))
return false;
return response.json().then((json) => (json as {openapi:string}).openapi.match("[0-9]+(?:\.[0-9]+)+")?true:false).catch(() => false);
})
.catch(() => {
return Promise.reject();
});
}