solved timeout error via fetch response

This commit is contained in:
Robert Nasarek 2022-08-31 11:03:41 +02:00
parent ba9d9e6abb
commit 1d68336a06
9 changed files with 246 additions and 110 deletions

View file

@ -44,6 +44,7 @@ function createWindow() {
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 400, width: 400,
height: 600, height: 600,
icon: __dirname + '/marvin.ico',
show: false, show: false,
webPreferences: { webPreferences: {
preload: path.join(__dirname, 'preload.js'), preload: path.join(__dirname, 'preload.js'),

BIN
marvin.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View file

@ -1,3 +1,3 @@
{ {
"rootDir": "/home/rbrt/Schreibtisch" "rootDir": "/home/rbrt/Schreibtisch/marvin"
} }

View file

@ -1,5 +1,3 @@
// Modules // Modules
import createReport from 'docx-templates'; import createReport from 'docx-templates';
import fs from 'fs'; import fs from 'fs';
@ -7,23 +5,49 @@ import { mkdir } from 'node:fs/promises';
import path from 'path'; import path from 'path';
import replaceSpecialCharacters from "replace-special-characters"; import replaceSpecialCharacters from "replace-special-characters";
// Components
import ObjektkatalogApi from './ObjektkatalogApi';
//////////////////// ////////////////////
// Main // // Main //
//////////////////// ////////////////////
// Fills the docx template.
export async function fillTemplate(log, objectData) { export async function fillTemplate(log, objectData) {
// Variables
let buffer; let buffer;
let configJson let configJson
// Create docx document.
// Create docx document if there was a response.
if (objectData.httpStatus === 200) { if (objectData.httpStatus === 200) {
let documentInfo;
try { try {
// Load config file.
let ConfigFile = fs.readFileSync('resources/config/config.json') let ConfigFile = fs.readFileSync('resources/config/config.json')
configJson = JSON.parse(ConfigFile) configJson = JSON.parse(ConfigFile)
// Choose the template for selected document type.
switch (objectData.dokumenttyp) {
case 'rp':
documentInfo = {
documentType: 'restaurierungsprotokolle',
templateFile: 'rp-template.docx',
}
break;
case 'lbb':
documentInfo = {
documentType: 'leihgabenbegleitblaetter',
templateFile: 'lbb-template.docx',
}
break;
case 'a':
documentInfo = {
documentType: 'analysen',
templateFile: 'a-template.docx',
}
break;
}
// Read template. // Read template.
const template = fs.readFileSync('resources/templates/rp-template.docx'); const template = fs.readFileSync(path.join('resources/templates/', documentInfo.templateFile));
// Create report. // Create report.
buffer = await createReport({ buffer = await createReport({
template, template,
@ -38,32 +62,40 @@ export async function fillTemplate(log, objectData) {
} }
}); });
} catch (err) { } catch (err) {
// Set error log.
log = { log = {
...log, ...log,
status: 'red', status: 'red',
message: 'Konnte Template nicht erstellen: ' + err, message: 'Konnte Template nicht erstellen: ' + err,
tip: 'Ist das Template vorhanden?', tip: 'Ist das Template vorhanden?',
}; };
return log
} }
const folderPath = path.join(configJson.rootDir, objectData.inventarnummer);
// Create Folder if necessary. // Create folder (if necessary).
const objectPath = path.join(configJson.rootDir, objectData.inventarnummer);
const documentPath = path.join(objectPath, documentInfo.documentType);
const temporaryWorkDirPath = path.join(objectPath, 'werkstatt');
try { try {
const createDir = await mkdir(folderPath, {recursive: true}); const createDocumentPath = await mkdir(documentPath, {recursive: true});
const createTemporaryWorkDirPath = await mkdir(temporaryWorkDirPath, {recursive: true});
} catch (err) { } catch (err) {
// Set error log.
log = { log = {
...log, ...log,
status: 'red', status: 'red',
message: 'Konnte den Pfad nicht erstellen' + err, message: 'Konnte den Pfad nicht erstellen' + err,
tip: 'Bestehen Schreibrechte auf dem Ordner?' tip: 'Bestehen Schreibrechte auf dem Ordner?'
} }
return log
} }
// Write document to disk.
// Write document to disk.
if (buffer) { if (buffer) {
const normCharacterTitle = replaceSpecialCharacters(objectData.titel) const normCharacterTitle = replaceSpecialCharacters(objectData.titel)
const normSpacingTitle = normCharacterTitle.replace(/[^A-Z0-9]+/ig, "_"); const normSpacingTitle = normCharacterTitle.replace(/[^A-Z0-9]+/ig, "_");
const filename = objectData.datum + '_' + normSpacingTitle + '.docx' const filename = objectData.datum + '_' + normSpacingTitle + '.docx'
fs.writeFileSync(path.join(folderPath, filename), buffer) fs.writeFileSync(path.join(documentPath, filename), buffer)
log = { log = {
...log, ...log,
status: 'green', status: 'green',

View file

@ -1,9 +1,11 @@
const {parseString} = require("xml2js"); const {parseString} = require("xml2js");
/* /*
* Sends Object ID to Objektkatalog-API and receives JSON * Properties and functions for communication with Objektkatalog-API.
*/ */
class ObjektkatalogApi { class ObjektkatalogApi {
// Variables
json; json;
raw; raw;
receivedData = { receivedData = {
@ -17,15 +19,33 @@ class ObjektkatalogApi {
materialTechnik: '', materialTechnik: '',
titel: '', titel: '',
}; };
response;
visibility; visibility;
// Get data from objektkatalog.gnm.de.
async getData(objectId) { async getData(objectId) {
if (objectId) { if (objectId) {
const response = await fetch('https://objektkatalog.gnm.de/rest_export/' + objectId); // RESTful GET.
if (response.status === 200) { this.response = await fetch('https://objektkatalog.gnm.de/rest_export/' + objectId).then((response) => {
const responseJson = await response.json(); //extract JSON from the http response if (response.status >= 400 && response.status < 600) {
throw new Error("Bad response from server: " + response.status);
}
return response;
}).then((returnedResponse) => {
// Everything went well.
return returnedResponse
}).catch((error) => {
// Error while fetch.
return {status: 503};
});
switch (this.response.status) {
case 200:
// Parse to json.
const responseJson = await this.response.json(); //extract JSON from the http response
if (responseJson.length !== 0) { if (responseJson.length !== 0) {
// Json with raw data (LIDO inside!)
this.raw = { this.raw = {
eid: responseJson[0]['eid'], eid: responseJson[0]['eid'],
allgemeineBezeichnung: responseJson[0]['fc6392714594e73ddb2fa363815a8fdf'], allgemeineBezeichnung: responseJson[0]['fc6392714594e73ddb2fa363815a8fdf'],
@ -53,8 +73,9 @@ class ObjektkatalogApi {
vitrinentext: responseJson[0]['fe5e3ff18aedf1d25c639dc79fb24ad1'], vitrinentext: responseJson[0]['fe5e3ff18aedf1d25c639dc79fb24ad1'],
zustandsbeschreibung: responseJson[0]['f54b6da6006ea444c33a348b8c4370a8'] zustandsbeschreibung: responseJson[0]['f54b6da6006ea444c33a348b8c4370a8']
} }
break;
} else { } else {
// No JSON // No json, no data form.
this.receivedData = { this.receivedData = {
...this.receivedData, ...this.receivedData,
httpStatus: 404, httpStatus: 404,
@ -62,17 +83,33 @@ class ObjektkatalogApi {
this.visibility = false this.visibility = false
return [this.receivedData, this.visibility] return [this.receivedData, this.visibility]
} }
} else { case 408:
// No response // No response, no data form.
this.receivedData= { this.receivedData = {
...this.receivedData, ...this.receivedData,
httpStatus: 404, httpStatus: 408,
}
this.visibility = false
return [this.receivedData, this.visibility]
case 503:
// Objektkatalog not reachable.
this.receivedData = {
...this.receivedData,
httpStatus: 503,
}
this.visibility = false
return [this.receivedData, this.visibility]
default:
// Any other error
this.receivedData = {
...this.receivedData,
httpStatus: 500,
} }
this.visibility = false this.visibility = false
return [this.receivedData, this.visibility] return [this.receivedData, this.visibility]
} }
} else { } else {
// No ObjectId // No ObjectId, no data form.
this.receivedData = { this.receivedData = {
...this.receivedData, ...this.receivedData,
httpStatus: 500, httpStatus: 500,
@ -84,7 +121,8 @@ class ObjektkatalogApi {
// Datum // Datum
// Default date of today // Default date of today
let today = new Date() let today = new Date()
let todayFormat = today.getFullYear() + '-' + (String(today.getMonth() + 1).padStart(2, '0')) + '-' + String(today.getDate()).padStart(2, '0'); ; let todayFormat = today.getFullYear() + '-' + (String(today.getMonth() + 1).padStart(2, '0')) + '-' + String(today.getDate()).padStart(2, '0');
;
// Inventarnummer // Inventarnummer
let inventarnummer; let inventarnummer;
@ -102,7 +140,7 @@ class ObjektkatalogApi {
titel = 'unbekannt'; titel = 'unbekannt';
} }
// Hersteller // Hersteller (LIDO format!)
let herstellerArray = []; let herstellerArray = [];
let hersteller; let hersteller;
@ -141,7 +179,7 @@ class ObjektkatalogApi {
materialTechnik = 'unbekannt'; materialTechnik = 'unbekannt';
} }
// Maße // Maße (LIDO format!)
let masse; let masse;
if (this.raw.masse.length !== 0) { if (this.raw.masse.length !== 0) {
parseString(this.raw.masse[0].value, (err, result) => { parseString(this.raw.masse[0].value, (err, result) => {
@ -149,7 +187,8 @@ class ObjektkatalogApi {
}) })
} }
this.receivedData ={ // Json with important data.
this.receivedData = {
...this.receivedData, ...this.receivedData,
datum: todayFormat, datum: todayFormat,
titel: titel, titel: titel,

View file

@ -167,6 +167,7 @@ label {
.open { .open {
height: 550px; height: 550px;
overflow: hidden;
} }
p { p {
margin: 0; margin: 0;

View file

@ -41,6 +41,7 @@ export const App = () => {
const [objectData, setObjectData] = useState( const [objectData, setObjectData] = useState(
{ {
datum: '', datum: '',
dokumenttyp: '',
hersteller: '', hersteller: '',
herstellungsdatum: '', herstellungsdatum: '',
herstellungsort: '', herstellungsort: '',
@ -57,64 +58,110 @@ export const App = () => {
); );
// Handler // Handler
// Get userinput from main form, ask Objektkatalog API for Data and fill check up form.
const getDataAndAskForCheckUpClickHandler = async (e) => { const getDataAndAskForCheckUpClickHandler = async (e) => {
// Show loading widget.
setIsLoading(true) setIsLoading(true)
// Prevent page reload. // Prevent page reload.
e.preventDefault() e.preventDefault()
let objectId = ''
objectId = e.target.form.objectId.value
// Get objectId from user input.
// Get objectId and document type from user input.
let objectId = e.target.form.objectId.value
let documentType = e.target.form.documentType.value
// Set object state.
await setObjectData((prevState) => { await setObjectData((prevState) => {
return { return {
...prevState, ...prevState,
inventarnummer: objectId, inventarnummer: objectId,
dokumenttyp: documentType,
} }
} }
) )
if (objectId) { if (objectId) {
// Get object data from objektkatalog.gnm.de // Get object data from objektkatalog.gnm.de.
const [receivedObjectData, receivedVisibility] = await objektkatalogApi.getData(objectId); const [receivedObjectData, receivedVisibility] = await objektkatalogApi.getData(objectId);
if (receivedObjectData.httpStatus !== 200) { // If no response from Objektkatalog.
switch (receivedObjectData.httpStatus) {
// Server not reachable.
case 503:
await setLogState({ await setLogState({
log: { log: {
status: 'red', status: 'red',
message: 'Kein Objekt mit dieser Inventarnummer gefunden!', message: 'Objektkatalog nicht erreichbar!',
code: '', code: '503',
tip: '', tip: 'Sind sie mit dem Internet verbunden und ist der Objektkatalog online?',
}, // with message, code, tip }, // with message, code, tip
logClass: 'active' logClass: 'active'
}) })
await setCheckUpVisibility(false) // Hide Loading
} else { setIsLoading(false)
// Fill and open check up form return;
await setObjectData(receivedObjectData) case 200:
// Fill and open check up form.
await setObjectData(prevState => {
return {
...prevState,
...receivedObjectData
}
})
// Show check up form.
await setCheckUpVisibility(true) await setCheckUpVisibility(true)
// Set success log but hide.
await setLogState({ await setLogState({
log: { log: {
status: '', status: '',
message: '', message: '',
code: '', code: '',
tip: '', tip: '',
}, // with message, code, tip },
logClass: 'inactive' logClass: 'inactive'
}) })
break;
default:
// Set error log state.
await setLogState({
log: {
status: 'red',
message: 'Kein Objekt mit dieser Inventarnummer gefunden!',
code: '',
tip: 'Groß-/Kleinschreibung beachten und keine Leerzeichen verwenden!',
}, // with message, code, tip
logClass: 'active'
})
// Hide Loading
setIsLoading(false)
// Hide check up form.
await setCheckUpVisibility(false)
} }
} else { } else {
// Set error log.
await setLogState({ await setLogState({
log: { log: {
status: 'red', status: 'red',
message: 'Bitte Inventarnummer eingeben!', message: 'Bitte Inventarnummer eingeben!',
code: '', code: '',
tip: '', tip: '',
}, // with message, code, tip },
logClass: 'active' logClass: 'active'
}) })
// Hide check up form.
await setCheckUpVisibility(false) await setCheckUpVisibility(false)
} }
// Hide loading widget.
setIsLoading(false) setIsLoading(false)
} }
// Component with
// * Navigation (Nav) *
// * Main form (this)*
// * Loading widget (LoadingIcon)*
// * Checkup form (DataForm)*
// * Log (Log)*
return ( return (
<div className="App"> <div className="App">
@ -128,10 +175,10 @@ export const App = () => {
<form id={"object-id-form"} className={"flex-wrap"}> <form id={"object-id-form"} className={"flex-wrap"}>
<div className={"center column flex justify-content-space-between "}> <div className={"center column flex justify-content-space-between "}>
<label htmlFor="document-type" className={"center cut v-distance"}>Dokumenttyp:</label> <label htmlFor="document-type" className={"center cut v-distance"}>Dokumenttyp:</label>
<select name="document-type" id="document-type" className={"input-field center cut"}> <select name="documentType" id="document-type" className={"input-field center cut"}>
<option value="restaurierungsprotokoll">Restaurierungsprotokoll</option> <option value="rp">Restaurierungsprotokoll</option>
<option value="leihgabenbegleitblatt">Leihgabenbegleitblatt</option> <option value="lbb">Leihgabenbegleitblatt</option>
<option value="analyse">Analyse</option> <option value="a">Analyse</option>
</select> </select>
</div> </div>
<div className={"center column flex full justify-content-space-between"}> <div className={"center column flex full justify-content-space-between"}>

View file

@ -8,10 +8,17 @@ import React from 'react'
// Main // // Main //
//////////////////// ////////////////////
// Renders check up form and gives the possibility to change received values.
export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState, setLogState}) => { export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState, setLogState}) => {
// Variables
let log; let log;
// Handlers // Handlers
// Change handler response to every keystroke!
// Change date.
const datumChangeHandler = (e) => { const datumChangeHandler = (e) => {
setObjectData((prevState) => { setObjectData((prevState) => {
return { return {
@ -20,7 +27,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
} }
}) })
} }
// Change identifier.
const inventarnummerChangeHandler = (e) => { const inventarnummerChangeHandler = (e) => {
setObjectData((prevState) => { setObjectData((prevState) => {
return { return {
@ -29,7 +36,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
} }
}) })
} }
// Change title.
const titelChangeHandler = (e) => { const titelChangeHandler = (e) => {
setObjectData((prevState) => { setObjectData((prevState) => {
return { return {
@ -39,6 +46,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
}) })
} }
// Change creator.
const herstellerChangeHandler = (e) => { const herstellerChangeHandler = (e) => {
setObjectData((prevState) => { setObjectData((prevState) => {
return { return {
@ -47,7 +55,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
} }
}) })
} }
// Change creation place.
const herstellungsortChangeHandler = (e) => { const herstellungsortChangeHandler = (e) => {
setObjectData((prevState) => { setObjectData((prevState) => {
return { return {
@ -57,6 +65,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
}) })
} }
// Change creation date.
const herstellungsdatumChangeHandler = (e) => { const herstellungsdatumChangeHandler = (e) => {
setObjectData((prevState) => { setObjectData((prevState) => {
return { return {
@ -66,6 +75,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
}) })
} }
// Change material and technic.
const materialTechnikChangeHandler = (e) => { const materialTechnikChangeHandler = (e) => {
setObjectData((prevState) => { setObjectData((prevState) => {
return { return {
@ -75,6 +85,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
}) })
} }
// Change sizes.
const masseChangeHandler = (e) => { const masseChangeHandler = (e) => {
setObjectData((prevState) => { setObjectData((prevState) => {
return { return {
@ -84,6 +95,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
}) })
} }
// Fill the template and save it.
const fillTemplateClickHandler = async (e) => { const fillTemplateClickHandler = async (e) => {
e.preventDefault(); e.preventDefault();
log = await fillTemplate(logState, objectData); log = await fillTemplate(logState, objectData);
@ -94,6 +106,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
}); });
} }
// Renders data form
return (<div className={'checkup ' + (checkUpVisibility ? 'open' : 'closed')}> return (<div className={'checkup ' + (checkUpVisibility ? 'open' : 'closed')}>
<form className={'flex column '}> <form className={'flex column '}>
<div > <div >

View file

@ -42,11 +42,14 @@ module.exports = {
], ],
devtool: 'cheap-source-map', devtool: 'cheap-source-map',
devServer: { devServer: {
static: path.resolve(__dirname, 'dist'), // Tell the server where to serve the content from.
static: {
directory: path.resolve(__dirname, 'dist'),
},
onBeforeSetupMiddleware() { onBeforeSetupMiddleware() {
spawn( spawn(
'electron', 'electron',
['.'], ['--trace-warnings .'],
{ shell: true, env: process.env, stdio: 'inherit' } { shell: true, env: process.env, stdio: 'inherit' }
) )
.on('close', code => process.exit(0)) .on('close', code => process.exit(0))