diff --git a/.gitignore b/.gitignore index 2a8f3c9..a6fc37f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Build folder and files # ########################## builds/ +installers/ # Development folders and files # ################################# diff --git a/electron-builder.json b/electron-builder.json new file mode 100644 index 0000000..6c17fbf --- /dev/null +++ b/electron-builder.json @@ -0,0 +1,32 @@ +{ + "appId": "org.nasarek.marvin", + "win": { + "target": "NSIS", + "icon": "marvin256x256.ico" + }, + "nsis": { + "oneClick": false, + "installerIcon": "marvin256x256.ico", + "uninstallerIcon": "marvin256x256.ico", + "allowToChangeInstallationDirectory": true + }, + "linux": { + "target": "deb", + "category": "Utility", + "icon": "marvin256x256.png" + }, + "files": [ + "*.js", + "**/*", + "./dist/bundle.css", + "./dist/index.html", + "./dist/main.js", + "./dist/main.js.LICENSE.txt", + "node_modules" + ], + "extraResources": [{ + "from": "resources/files", + "to": "files" + } + ] +} diff --git a/main.js b/main.js index 1429c87..d2b5099 100644 --- a/main.js +++ b/main.js @@ -142,6 +142,16 @@ let mainMenu = Menu.buildFromTemplate( ] ) +const RESOURCES_PATH = app.isPackaged + ? path.join(process.resourcesPath, 'assets') + : path.join(__dirname, '../../assets'); + +console.log(process.resourcesPath); +console.log(__dirname); + +const getAssetPath = (paths) => { + return path.join(RESOURCES_PATH, paths); +}; function createWindow(dimensions) { if (dev !== true) { @@ -255,5 +265,3 @@ app.on('activate', () => { } }) - -// IPC-Channel handling diff --git a/marvin256x256.png b/marvin256x256.png new file mode 100644 index 0000000..1c861b8 Binary files /dev/null and b/marvin256x256.png differ diff --git a/package.json b/package.json index 3fe99d2..ed4e429 100644 --- a/package.json +++ b/package.json @@ -33,25 +33,9 @@ "prod": "cross-env NODE_ENV=production webpack --mode production --config webpack.build.config.js && electron --noDevServer .", "start": "cross-env NODE_ENV=development webpack serve --hot --host 0.0.0.0 --config=./webpack.dev.config.js --mode development", "build": "cross-env NODE_ENV=production webpack --config webpack.build.config.js --mode production", - "installer": "electron-builder", + "pack:installer": "electron-builder build -lw", "package": "npm run build", - "postpackage": "electron-packager ./ --ignore 'resources/files' --out=./builds --asar --overwrite --platform win32,linux --icon marvin.ico --extra-resource 'resources/files'" - }, - "build": { - "appId": "marvin", - "win": { - "target": [ - "nsis" - ], - "icon": "marvin256x256.ico" - }, - "nsis": { - "oneClick": false, - "installerIcon": "marvin.ico", - "uninstallerIcon": "marvin.ico", - "uninstallDisplayName": "Marvin-Uninstaller", - "allowToChangeInstallationDirectory": true - } + "postpackage": "electron-packager ./ --ignore \"(resources|builds|installer)\" --out=./builds --overwrite --platform win32,linux --icon marvin.ico --extra-resource 'resources/files'" }, "dependencies": { "@emotion/react": "^11.10.0", @@ -60,10 +44,12 @@ "@mui/material": "^5.10.2", "about-window": "^1.15.2", "docx-templates": "^4.9.2", + "image-resize-compress": "^1.0.8", "postcss": "^8.4.16", "react": "^18.2.0", "react-async-devtools": "^10.0.1", "react-dom": "^18.2.0", + "react-image-gallery": "^1.2.9", "react-loader-spinner": "^5.3.3", "react-router-dom": "^6.3.0", "replace-special-characters": "^1.2.6", @@ -91,6 +77,7 @@ "postcss-nested": "^5.0.6", "postcss-preset-env": "^7.8.0", "postcss-pxtorem": "^6.0.0", + "source-map-support": "^0.5.21", "style-loader": "^3.3.1", "webpack": "^5.74.0", "webpack-cli": "^4.10.0", diff --git a/resources/files/config/config.json b/resources/files/config/config.json deleted file mode 100644 index 4ca2d73..0000000 --- a/resources/files/config/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "rootDir": "C:\\Users\\Robert\\Desktop\\marvin" -} \ No newline at end of file diff --git a/src/DocCreator.js b/src/DocCreator.js new file mode 100644 index 0000000..8c64deb --- /dev/null +++ b/src/DocCreator.js @@ -0,0 +1,478 @@ +// Modules +import createReport from 'docx-templates'; +import fs, {writeFile} from 'fs'; +import {mkdir} from 'node:fs/promises'; +import path from 'path'; +import replaceSpecialCharacters from "replace-special-characters"; + +import {parseString, Builder} from 'xml2js'; + + +//////////////////// +// Main // +//////////////////// + +class DocCreator { + constructor(log, objectData) { + + // Assign Log. + this.log = log; + + // Assign general object data. + this.objectData = objectData; + + // Get DateTime. + this.today = new Date(); + + // Get config file and parse to json. + this.configFile = fs.readFileSync('/resources/files/config/config.json') + this.configJson = JSON.parse(this.configFile.toString()) + + // Choose the template for selected document type. + switch (objectData.dokumenttyp) { + case 'rp': + this.documentInfo = { + documentType: 'restaurierungsprotokolle', docTypeAbbr: 'rp', templateFile: 'rp-template.docx', + } + break; + case 'lbb': + this.documentInfo = { + documentType: 'leihgabenbegleitblaetter', docTypeAbbr: 'lbb', templateFile: 'lbb-template.docx', + } + break; + case 'a': + this.documentInfo = { + documentType: 'analysen', docTypeAbbr: 'a', templateFile: 'a-template.docx', + } + break; + } + + // ObjectId normalisation. + const normCharacterObjectId = replaceSpecialCharacters(objectData.inventarnummer); + this.normObjectId = normCharacterObjectId.replace("__", "_"); + + // Title normalisation + const replaceEszettTitle = objectData.titel.replace("ß", "-ss-"); + let replaceUmlauteTitle = replaceEszettTitle.replace(/[^Ä]+/ig, "Ae"); + replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^ä]+/ig, "ae"); + replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^Ö]+/ig, "Oe"); + replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^ö]+/ig, "oe"); + replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^Ü]+/ig, "Ue"); + replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^ü]+/ig, "ue"); + const normCharacterTitle = replaceSpecialCharacters(replaceUmlauteTitle); + const normSingleSpaceTitle = normCharacterTitle.replace("__", "_"); + const normSpacingTitle = normSingleSpaceTitle.replace(/[^A-Z0-9\-]+/ig, "_"); + this.normTitle = normSpacingTitle.slice(0, 50); + + const folderName = this.normObjectId + '__' + this.normTitle + this.objectPath = path.join(this.configJson.rootDir, folderName); + this.documentPath = path.join(this.objectPath, this.documentInfo.documentType, objectData.datum); + this.filename = this.normObjectId + '__' + this.normTitle + '__' + this.objectData.datum + '__' + this.objectData.dokumenttyp; + this.filenameWithExtension = this.filename + '.docx' + this.temporaryWorkDirPath = path.join(this.objectPath, 'werkstatt'); + + + } + +// Fills the docx template. + async fillTemplate() { + // Variables + let buffer; + let configJson + + // Create docx document if there was a response. + if (this.objectData.httpStatus === 200) { + try { + // Read template. + const template = fs.readFileSync(path.join('/resources/files/templates/', this.documentInfo.templateFile)); + + // Create report. + buffer = await createReport({ + template, data: { + inventarnummer: this.objectData.inventarnummer ? this.objectData.inventarnummer : 'unbekannt', + titel: this.objectData.titel ? this.objectData.titel : 'unbekannt', + hersteller: this.objectData.hersteller ? this.objectData.hersteller : 'unbekannt', + herstellungsort: this.objectData.herstellungsort ? this.objectData.herstellungsort : 'unbekannt', + herstellungsdatum: this.objectData.herstellungsdatum ? this.objectData.herstellungsdatum : 'unbekannt', + materialTechnik: this.objectData.materialTechnik ? this.objectData.materialTechnik : 'unbekannt', + masse: this.objectData.masse ? this.objectData.masse : 'unbekannt' + } + }); + } catch (err) { + // Set error log. + this.log = { + ...this.log, + status: 'red', + message: 'Konnte Template nicht erstellen: ' + err, + tip: 'Ist das Template vorhanden?', + }; + return this.log + } + + try { + const createDocumentPath = await mkdir(this.documentPath, {recursive: true}); + const createTemporaryWorkDirPath = await mkdir(this.temporaryWorkDirPath, {recursive: true}); + } catch (err) { + // Set error log. + this.log = { + ...this.log, + status: 'red', + message: 'Konnte den Pfad nicht erstellen' + err, + tip: 'Bestehen Schreibrechte auf dem Ordner?' + } + return this.log + } + + // Write document to disk. + if (buffer) { + fs.writeFileSync(path.join(this.documentPath, this.filenameWithExtension), buffer) + this.log = { + ...this.log, status: 'green', message: 'Dokument erstellt', + }; + } + + } else { + this.log = { + status: 'red', + message: 'Fehler bei der Kommunikation mit dem Objektkatalog', + code: this.objectData.httpStatus, + tip: 'Ist die Inventarnummer richtig?', + }; + } + return this.log; + } + + async createMetsMods() { + + const metsModsString = ` + + + + + ${process.env.REACT_APP_NAME} v${process.env.REACT_APP_VERSION} + + + + + + + + + + + + + + + + + + + + + + + + + + ${this.objectData.inventarnummer} + + + ${this.objectData.titel} + + + ${this.objectData.herstellungsdatum} + + ${this.objectData.herstellungsort} + + + + + cre + + ${this.objectData.herstellungsort} + ${this.objectData.herstellungsort} + + + + ${this.objectData.masse} + + + + + + + ` + + const metModsJson = { + 'mets:mets': { + $: { + 'xmlns:mets': "http://www.loc.gov/METS/", + 'xmlns:xlink': "http://www.w3.org/1999/xlink", + 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance", + 'xsi:schemaLocation': "info:lc/xmlns/premis-v2 http://www.loc.gov/standards/premis/v2/premis-v2-0.xsd " + + "http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-6.xsd " + + "http://www.loc.gov/METS/ http://www.loc.gov/standards/mets/version17/mets.v1-7.xsd " + + "http://www.loc.gov/mix/v10 http://www.loc.gov/standards/mix/mix10/mix10.xsd" + }, + 'mets:metsHdr': { + $: { + // Creation date of the mets/mods xml. + 'createDate': this.today // Should be w3ctdf format: YYYY-MM-DDThh:mm:ssTZD + }, + 'mets:agent': { + // App, which created the xml document + $: { + 'type': 'other', + 'otherType': 'software', + 'role': 'creator' + }, + 'mets:name': { + // App name and version + _: `${process.env.REACT_APP_NAME} v${process.env.REACT_APP_VERSION}` + } + } + }, + 'mets:fileSec': { + 'mets:fielGrp': { + $: { + // Documenttype + 'use': `${this.documentInfo.documentType}` + }, + 'mets:file': { + // Phyical file + $: { + 'id': `file__${this.filename}`, + 'mimeType': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + }, + 'mets:FLocat': { + // Physical location - here in same folder + $: { + 'locType': 'other', + 'otherLocType': 'file', + 'xlink:href': `${this.filenameWithExtension}` + } + } + } + } + }, + 'mets:structMap': [ + { // These are solo documents only, this may be inappropriate. + $: { + // Physical structure. + 'type': 'physical' + }, + 'mets:div': { + $: { + // Documenttype and id. + 'type': `${this.documentInfo.docTypeAbbr}`, + // since we have only one document, id and dmdid are static. + 'id': `phys_00`, + 'dmdid': 'dmdphys_00' + }, + 'mets:fptr': { + $: { + // File id from above + 'fileId': `file__${this.filename}` + } + } + } + }, + { // These are solo documents only, this may be inappropriate. + $: { + // Physical structure. + 'type': 'logical' + }, + 'mets:div': { + $: { + // Documenttype and id. + 'type': `${this.documentInfo.docTypeAbbr}`, + // since we have only one document, id and dmdid are static. + 'id': `phys_00`, + 'dmdid': 'dmdphys_00' + }, + 'mets:fptr': { + $: { + // File id from above + 'fileId': `file__${this.filename}` + } + } + } + }], + 'mets:dmdSec': + { + $: { + // Since we have only one document, dmdlog is static + 'id': + `dmdlog_00` + } + , + 'mets:mdWrap': + { + $: { + 'mdType': + 'mods' + } + , + 'mets:xmlData': + { + 'mods:mods': + { + // Object properties as found at https://objektkatalog.gnm.de. + $: { + 'xmlns:mods': + 'http://www.loc.gov/mods/v3' + } + , + 'mods:recordInfo': + { + 'mods:recordIdentifier': + { + // ObjectId. + $: { + 'source': + 'https://objektkatalag.gnm.de' + } + , + _: `${this.objectData.inventarnummer}` + } + } + , + 'mods:titleInfo': + { + // Title. + 'mods:title': + { + _: `${this.objectData.titel}` + } + } + , + 'mods:originInfo': + { + // Creation date. + 'mods_dateIssued': + { + $: { + 'encoding': + 'w3cdtf', // W3C Date and Time, should be YYYY-MM-DDThh:mm:ssTZD + 'keyDate': + 'yes' + } + , + _: `${this.objectData.herstellungsdatum}` + } + , + 'mods:place': + { + // Creation place + 'mods:placeTerm': + { + $: { + 'type': + 'text' + } + , + _: `${this.objectData.herstellungsort}` + } + } + } + , + 'mods:name': + { + // Creator. + $: { + 'type': + 'personal' + } + , + 'mods:role': + { + 'mods:roleTerm': + { + $: { + 'authority': + 'marcrelator', + 'type': + 'code' + } + , + _: 'cre' + } + } + , + 'mods:namePart': + { + _: this.objectData.hersteller + } + , + 'mods:displayForm': + { + _: this.objectData.hersteller + } + } + , + 'mods:physicalDescription': + { + 'mods:form': + { + $: { + 'type': + 'Material and Technique', + 'lang': + 'de' + } + } + , + 'mods:extent': + { + _: `${this.objectData.masse}` + } + } + } + } + } + } + } + } + + let metModsXml + parseString(metsModsString, {trim: true}, + function (err, result) { + metModsXml = result; + } + ); + console.log(metModsXml, 'from string'); + + const builder = new Builder() + metModsXml = builder.buildObject(metModsJson); + console.log(metModsXml, 'from Json') + + const fileName = `.metsMods__${this.normObjectId}__${this.normTitle}.xml` + fs.writeFileSync(path.join(this.documentPath,fileName),metModsXml.toString(), + function (err) { + if (err) { + console.log(err); + } else { + console.log("The file was saved!"); + } + } + ) + return true; + } +} + +export {DocCreator}; diff --git a/src/DocxInserter.js b/src/DocxInserter.js deleted file mode 100644 index c20e80f..0000000 --- a/src/DocxInserter.js +++ /dev/null @@ -1,116 +0,0 @@ -// Modules -import createReport from 'docx-templates'; -import fs from 'fs'; -import { mkdir } from 'node:fs/promises'; -import path from 'path'; -import replaceSpecialCharacters from "replace-special-characters"; - - -//////////////////// -// Main // -//////////////////// - -// Fills the docx template. -export async function fillTemplate(log, objectData) { - // Variables - let buffer; - let configJson - - // Create docx document if there was a response. - if (objectData.httpStatus === 200) { - let documentInfo; - try { - // Load config file. - let ConfigFile = fs.readFileSync('resources/files/config/config.json') - 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. - const template = fs.readFileSync(path.join('resources/files/templates/', documentInfo.templateFile)); - - // Create report. - buffer = await createReport({ - template, - data: { - inventarnummer: objectData.inventarnummer ? objectData.inventarnummer : 'unbekannt' , - titel: objectData.titel ? objectData.titel : 'unbekannt', - hersteller: objectData.hersteller ? objectData.hersteller : 'unbekannt', - herstellungsort: objectData.herstellungsort ? objectData.herstellungsort : 'unbekannt', - herstellungsdatum: objectData.herstellungsdatum ? objectData.herstellungsdatum : 'unbekannt', - materialTechnik: objectData.materialTechnik ? objectData.materialTechnik : 'unbekannt' , - masse: objectData.masse ? objectData.masse : 'unbekannt' - } - }); - } catch (err) { - // Set error log. - log = { - ...log, - status: 'red', - message: 'Konnte Template nicht erstellen: ' + err, - tip: 'Ist das Template vorhanden?', - }; - return log - } - - // 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 { - const createDocumentPath = await mkdir(documentPath, {recursive: true}); - const createTemporaryWorkDirPath = await mkdir(temporaryWorkDirPath, {recursive: true}); - } catch (err) { - // Set error log. - log = { - ...log, - status: 'red', - message: 'Konnte den Pfad nicht erstellen' + err, - tip: 'Bestehen Schreibrechte auf dem Ordner?' - } - return log - } - - // Write document to disk. - if (buffer) { - const normCharacterObjectId = replaceSpecialCharacters(objectData.inventarnummer) - const normCharacterTitle = replaceSpecialCharacters(objectData.titel) - const normSpacingTitle = normCharacterTitle.replace(/[^A-Z0-9]+/ig, "_"); - const filename = objectData.datum + '_' + normCharacterObjectId + '_' + normSpacingTitle + '.docx' - fs.writeFileSync(path.join(documentPath, filename), buffer) - log = { - ...log, - status: 'green', - message: 'Dokument erstellt', - }; - } - - } else { - log = { - status: 'red', - message: 'Fehler bei der Kommunikation mit dem Objektkatalog', - code: objectData.httpStatus, - tip: 'Ist die Inventarnummer richtig?', - }; - } - return log; -} diff --git a/src/Image.js b/src/Image.js new file mode 100644 index 0000000..bcdb8bc --- /dev/null +++ b/src/Image.js @@ -0,0 +1,30 @@ +import {blobToURL, fromURL} from "image-resize-compress"; + +class Image { + constructor(originalUri, originalHeight = '300px', originalWidth = '200px', loading = 'lazy') { + this.original = originalUri; + this.originalHeight = originalHeight; + this.originalWidth = originalWidth; + this.loading = loading; + + (async () => { + this.thumbnail = await this.convert2Thumbnail(this.original) + })(); + } + convert2Thumbnail = async (sourceUrl) => { + // quality value for webp and jpeg formats. + const quality = 80; + // output width. 0 will keep its original width and 'auto' will calculate its scale from height. + const width = 100; + // output height. 0 will keep its original height and 'auto' will calculate its scale from width. + const height = 'auto'; + // file format: png, jpeg, bmp, gif, webp. If null, original format will be used. + const format = 'webp'; + // note only the sourceUrl argument is required + let blob = await fromURL(sourceUrl, quality, width, height, format); + return await blobToURL(blob); + }; + +} + +export {Image}; diff --git a/src/ObjektkatalogApi.js b/src/ObjektkatalogApi.js index 424f497..041d6f4 100644 --- a/src/ObjektkatalogApi.js +++ b/src/ObjektkatalogApi.js @@ -18,12 +18,14 @@ class ObjektkatalogApi { masse: '', materialTechnik: '', titel: '', + wisskiUri: '', }; response; visibility; // Get data from objektkatalog.gnm.de. + async getData(objectId) { if (objectId) { // RESTful GET. @@ -50,6 +52,7 @@ class ObjektkatalogApi { eid: responseJson[0]['eid'], allgemeineBezeichnung: responseJson[0]['fc6392714594e73ddb2fa363815a8fdf'], beschreibung: responseJson[0]['f81f557caccf45074edfb65ff077011f'], + bilder: responseJson[0]['f41dae62df47283958f605716d141ebf'], darstellung: responseJson[0]['f217e1053b1e29411d4b00f3b1e1d52b'], erwerbsmethode: responseJson[0]['fa4aa035d411275cd36a2fbb5c159a2c'], fruehstes: responseJson[0]['ff4a178095c895a12fce6320c04ba0b0'], @@ -71,6 +74,7 @@ class ObjektkatalogApi { titel: responseJson[0]['f2049b2456b20f8fd80f714e154f1d47'], unterbringung: responseJson[0]['f15265e39237868a568ee63453492b17'], vitrinentext: responseJson[0]['fe5e3ff18aedf1d25c639dc79fb24ad1'], + wisskiUri: responseJson[0]['wisski_uri'][0]['value'], zustandsbeschreibung: responseJson[0]['f54b6da6006ea444c33a348b8c4370a8'] } break; @@ -118,6 +122,16 @@ class ObjektkatalogApi { return [this.receivedData, this.visibility] } + // Bilder + let bilder =[]; + if (this.raw.bilder.length !== 0) { + for (const bildIndex in this.raw.bilder) { + bilder.push(this.raw.bilder[bildIndex].url) + } + } else { + this.bilder = null; + } + // Datum // Default date of today let today = new Date() @@ -187,9 +201,11 @@ class ObjektkatalogApi { }) } + // Json with important data. this.receivedData = { ...this.receivedData, + bilder: bilder, datum: todayFormat, titel: titel, hersteller: hersteller, @@ -198,6 +214,7 @@ class ObjektkatalogApi { inventarnummer: inventarnummer, materialTechnik: materialTechnik, masse: masse, + wisskiUri: this.raw.wisskiUri, httpStatus: 200, } this.visibility = true diff --git a/src/assets/config/config.json b/src/assets/config/config.json new file mode 100644 index 0000000..99bebb3 --- /dev/null +++ b/src/assets/config/config.json @@ -0,0 +1,3 @@ +{ + "rootDir": "/home/rbrt/Schreibtisch/boehler" +} \ No newline at end of file diff --git a/src/assets/css/styles.css b/src/assets/css/styles.css index 81b89ad..d23db39 100644 --- a/src/assets/css/styles.css +++ b/src/assets/css/styles.css @@ -1,4 +1,7 @@ + + /* Imports */ @import url('https://fonts.googleapis.com/css?family=Open+Sans'); +@import "react-image-gallery/styles/css/image-gallery.css"; a { color: #d5d5d5; @@ -23,6 +26,10 @@ body { .checkup { transition: height 1s; height: 0; + display: flex; + justify-content: center; + align-items: center; + gap: 1rem; } .closed{ @@ -43,10 +50,6 @@ body { max-width: max-content; } -div { - padding: 0.5em; -} - .edit-button { background-color: #e30f27; color: #d5d5d5; @@ -55,6 +58,7 @@ div { border: unset; padding: 0 4px; height: 1.5rem; + border-radius: 0 .1875rem .1875rem 0; } .edit-input { @@ -87,6 +91,23 @@ div { background-color: darkgreen; } +h3 { + color: #464646; +} + +.image-gallery { + flex: .5 .5 50%; +} + +.image-gallery-thumbnails-container { + display: flex; + justify-content: center; +} + +.image-gallery-slide-wrapper { + margin-bottom: .5rem; +} + .inactive { display: none; } @@ -129,6 +150,10 @@ input.edit-input:not(:disabled) { font-family: "Open Sans", sans-serif; } + .justify-content-center { + display: flex; + justify-content: center; + } .justify-content-end { @@ -168,13 +193,16 @@ label { } .open { - height: 610px; + height: 100%; overflow: hidden; } p { margin: 0; } +.pd-05rem { + padding: .5rem; +} .position-absolute { position: absolute; } @@ -223,15 +251,15 @@ select { } .settings-div { - background-color: #d5d5d5; + background-color: #f2f2f2; color: black; - width: 300px; + width: 388px; border-top: none; border-right: none; border-left: none; border-bottom: 0.125rem solid #e30019; - border-radius: 0.1875rem; - overflow-x: scroll; + border-radius: .1875rem 0 0 .1875rem; + overflow-x: auto; white-space:nowrap; } @@ -256,10 +284,13 @@ textarea.select-folder-field, textarea.select-folder-field:focus, input.select-f } .v-distance { - margin-top: 0.25em; - margin-bottom: 0.25em; + margin-top: 0.25rem; + margin-bottom: 0.25rem; } +.bottom-distance { + margin-bottom: 1rem; +} /* width */ ::-webkit-scrollbar { width: 5px; diff --git a/resources/files/images/marvin16x16.png b/src/assets/images/marvin16x16.png similarity index 100% rename from resources/files/images/marvin16x16.png rename to src/assets/images/marvin16x16.png diff --git a/resources/files/templates/a-template.docx b/src/assets/templates/a-template.docx similarity index 100% rename from resources/files/templates/a-template.docx rename to src/assets/templates/a-template.docx diff --git a/resources/files/templates/lbb-template.docx b/src/assets/templates/lbb-template.docx similarity index 100% rename from resources/files/templates/lbb-template.docx rename to src/assets/templates/lbb-template.docx diff --git a/resources/files/templates/rp-template.docx b/src/assets/templates/rp-template.docx similarity index 100% rename from resources/files/templates/rp-template.docx rename to src/assets/templates/rp-template.docx diff --git a/src/components/App.js b/src/components/App.js index b643a31..42f5c48 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,6 +1,13 @@ // Components import {DataForm} from "./DataForm"; import {Log} from "./Log" + + +// CSS +import '../assets/css/styles.css' +import {LoadingIcon} from "./LoadingIcon"; + +// Icons import SettingsIcon from '@mui/icons-material/Settings'; // Modules @@ -10,10 +17,6 @@ import ObjektkatalogApi from "../ObjektkatalogApi"; import {NavLink} from "react-router-dom"; import React, {useState} from 'react' -// CSS -import '../assets/css/styles.css' -import {LoadingIcon} from "./LoadingIcon"; - //////////////////// // Main // @@ -91,8 +94,21 @@ export const App = () => { await setLogState({ log: { status: 'red', - message: 'Objektkatalog nicht erreichbar!', + message: 'Objektkatalog kann sich nicht um die Anfrage kümmern!', code: '503', + tip: 'Vielleicht hat der Katalog gerade sehr viele Zugriffe, probieren Sie es später noch einmal.', + }, // with message, code, tip + logClass: 'active' + }) + // Hide Loading + setIsLoading(false) + return; + case 404: + await setLogState({ + log: { + status: 'red', + message: 'Objektkatalog nicht erreichbar!', + code: '404', tip: 'Sind sie mit dem Internet verbunden und ist der Objektkatalog online?', }, // with message, code, tip logClass: 'active' @@ -170,34 +186,38 @@ export const App = () => { -
-
-
-
- - -
-
- - -
+
+

Marvin

+
+
+ +
+ + +
+
+ + +
- + - -
- + +
+ + +
{ logState={logState} setLogState={setLogState} /> +