diff --git a/main.js b/main.js index 8915834..39d7562 100644 --- a/main.js +++ b/main.js @@ -30,8 +30,8 @@ if (process.platform === 'win32') { // Functions -async function handleFileOpen() { - const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, {properties: ['openDirectory']}) + async function handleFileOpen() { + const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, {properties: ['openDirectory']}) if (canceled) { return } else { diff --git a/package.json b/package.json index 6d7f786..f3e0ec7 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "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", "package": "npm run build", - "postpackage": "electron-packager ./ --out=./builds" + "postpackage": "electron-packager ./ --out=./builds --overwrite" }, "dependencies": { "@emotion/react": "^11.10.0", @@ -49,7 +49,9 @@ "react": "^18.2.0", "react-async-devtools": "^10.0.1", "react-dom": "^18.2.0", + "react-loader-spinner": "^5.3.3", "react-router-dom": "^6.3.0", + "replace-special-characters": "^1.2.6", "write-json-file": "^5.0.0", "xml-parse-from-string": "^1.0.1", "xml2js": "^0.4.23" @@ -58,6 +60,7 @@ "@babel/core": "^7.18.10", "@babel/preset-env": "^7.18.10", "@babel/preset-react": "^7.18.6", + "@electron-forge/plugin-webpack": "^6.0.0-beta.65", "babel-loader": "^8.2.5", "cross-env": "^7.0.3", "css-loader": "^6.7.1", diff --git a/resources/config/config.json b/resources/config/config.json new file mode 100644 index 0000000..b0b532a --- /dev/null +++ b/resources/config/config.json @@ -0,0 +1,3 @@ +{ + "rootDir": "/home/rbrt/Schreibtisch/marvin" +} \ No newline at end of file diff --git a/src/assets/templates/lbb-template.docx b/resources/templates/lbb-template.docx similarity index 100% rename from src/assets/templates/lbb-template.docx rename to resources/templates/lbb-template.docx diff --git a/src/assets/templates/rp-template.docx b/resources/templates/rp-template.docx similarity index 100% rename from src/assets/templates/rp-template.docx rename to resources/templates/rp-template.docx diff --git a/src/DocxInserter.js b/src/DocxInserter.js index a86b0dd..3b2a505 100644 --- a/src/DocxInserter.js +++ b/src/DocxInserter.js @@ -1,11 +1,12 @@ // Config -import config from './config/config.json' +import config from '/resources/config/config.json' // 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"; // Components import ObjektkatalogApi from './ObjektkatalogApi'; @@ -20,7 +21,7 @@ export async function fillTemplate(log, objectData) { if (objectData.httpStatus === 200) { try { // Read template. - const template = fs.readFileSync('src/assets/templates/rp-template.docx'); + const template = fs.readFileSync('resources/templates/rp-template.docx'); // Create report. buffer = await createReport({ template, @@ -57,8 +58,10 @@ export async function fillTemplate(log, objectData) { // Write document to disk. if (buffer) { - console.log(objectData) - fs.writeFileSync(path.join(folderPath, objectData.titel), buffer) + const normCharacterTitle = replaceSpecialCharacters(objectData.titel) + const normSpacingTitle = normCharacterTitle.replace(/[^A-Z0-9]+/ig, "_"); + const filename = objectData.datum + '_' + normSpacingTitle + '.docx' + fs.writeFileSync(path.join(folderPath, filename), buffer) log = { ...log, status: 'green', diff --git a/src/ObjektkatalogApi.js b/src/ObjektkatalogApi.js index 98beea7..041f348 100644 --- a/src/ObjektkatalogApi.js +++ b/src/ObjektkatalogApi.js @@ -5,8 +5,21 @@ const {parseString} = require("xml2js"); */ class ObjektkatalogApi { json; - short; raw; + receivedData = { + datum: '', + hersteller: '', + herstellungsdatum: '', + herstellungsort: '', + httpStatus: 500, + inventarnummer: '', + masse: '', + materialTechnik: '', + titel: '', + }; + + visibility; + async getData(objectId) { if (objectId) { const response = await fetch('https://objektkatalog.gnm.de/rest_export/' + objectId); @@ -41,15 +54,38 @@ class ObjektkatalogApi { zustandsbeschreibung: responseJson[0]['f54b6da6006ea444c33a348b8c4370a8'] } } else { - return {httpStatus: 404}; + // No JSON + this.receivedData = { + ...this.receivedData, + httpStatus: 404, + } + this.visibility = false + return [this.receivedData, this.visibility] } } else { - return {httpStatus: response.status}; + // No response + this.receivedData= { + ...this.receivedData, + httpStatus: 404, + } + this.visibility = false + return [this.receivedData, this.visibility] } } else { - return {httpStatus: 400} + // No ObjectId + this.receivedData = { + ...this.receivedData, + httpStatus: 500, + } + this.visibility = false + return [this.receivedData, this.visibility] } + // Datum + // Default date of today + let today = new Date() + let todayFormat = today.getFullYear() + '-' + (String(today.getMonth() + 1).padStart(2, '0')) + '-' + String(today.getDate()).padStart(2, '0'); ; + // Inventarnummer let inventarnummer; if (this.raw.inventarnummer.length !== 0) { @@ -113,19 +149,22 @@ class ObjektkatalogApi { }) } - return this.short = { - inventarnummer: inventarnummer, - titel: titel, - hersteller: hersteller, - herstellungsort: herstellungsort, - herstellungsdatum: herstellungsdatum, - materialTechnik: materialTechnik, - masse: masse, - httpStatus: 200, - } - - + this.receivedData ={ + ...this.receivedData, + datum: todayFormat, + titel: titel, + hersteller: hersteller, + herstellungsort: herstellungsort, + herstellungsdatum: herstellungsdatum, + inventarnummer: inventarnummer, + materialTechnik: materialTechnik, + masse: masse, + httpStatus: 200, + } + this.visibility = true + return [this.receivedData, this.visibility] } } + module.exports = ObjektkatalogApi; diff --git a/src/actions/getData.js b/src/actions/getData.js deleted file mode 100644 index 5d04706..0000000 --- a/src/actions/getData.js +++ /dev/null @@ -1,7 +0,0 @@ -import GnmObject from "../ObjektkatalogApi"; - -/* - * - */ - - diff --git a/src/assets/css/styles.css b/src/assets/css/styles.css index 820c2de..b1a380a 100644 --- a/src/assets/css/styles.css +++ b/src/assets/css/styles.css @@ -1,4 +1,4 @@ -@import url('https://fonts.googleapis.com/css?family=Roboto'); +@import url('https://fonts.googleapis.com/css?family=Open+Sans'); a { color: #d5d5d5; @@ -9,10 +9,10 @@ a { } body { - background-color: #00152E ; + background-color: white ; color: #d5d5d5; - font-family: 'Roboto', regular, serif; - font-size: larger; + font-family: 'Open Sans', sans-serif; + font-size: 1rem; } @@ -26,7 +26,8 @@ body { } .closed{ - height: 0; + height: 0px; + overflow: hidden; position: relative; } @@ -47,13 +48,13 @@ div { } .edit-button { - background-color: #d5d5d5; - font-family: roboto, sans-serif; + background-color: #e30f27; + color: #d5d5d5; + font-family: "Open Sans", sans-serif; font-size: 1rem; - border-radius: 0 0.4rem 0.4rem 0; border: unset; padding: 0 4px; - height: 1.1rem; + height: 1.5rem; } .edit-input { @@ -64,6 +65,12 @@ div { display: flex; } +.flex-center { + display: flex; + justify-content: center; + align-items: center; +} + .flex-full { flex: 1 } @@ -88,21 +95,23 @@ input { border-top: none; border-right: none; border-left: none; - border-bottom: 2px solid darkred; + border-bottom: 2px solid #e30f27; border-radius: 3px; } input[type="date"]::-webkit-calendar-picker-indicator { - color: #d5d5d5; + color: black; width: 20px; height: 20px; border-width: thin; - filter: invert(1); } + + input:focus { background-color: #d5d5d5; color: #00152E; + font-size: .9rem; } input.edit-input:not(:disabled) { @@ -112,9 +121,9 @@ input.edit-input:not(:disabled) { .input-field { - background-color: #00152E ; - color: #d5d5d5; - font-size: medium; + background-color: #f2f2f2 ; + color: black; + font-size: .9rem; font-family: roboto, sans-serif; } @@ -130,19 +139,34 @@ input.edit-input:not(:disabled) { label { padding-right: 5px; + color: #464646; +} +.loading-icon-canvas { + position: absolute; + height: 98%; + width: 98%; + left: 0%; + top: 0%; + background-color: #555555; + opacity: .5; } +.loading-icon .log { font-size: 0.75em; height: 5em; } + +.nav-icon svg { + fill: black; +} .no-overflow { overflow: hidden; height: inherit; } .open { - height: 700px; + height: 500px; } p { margin: 0; @@ -157,7 +181,8 @@ p { } .red { - background-color: crimson; + background-color: #e30f27; + color: white; } .round-box { @@ -172,12 +197,12 @@ select { } .send-button { - font-family: roboto, sans-serif; + background-color: #e30f27; + color: white; + font-family: "Open Sans", sans-serif; font-size: 1rem; - border-radius: 0.4rem; border: unset; - background-color: darkred; - color: #d5d5d5; + } .scroll-y { @@ -191,6 +216,18 @@ select { font-size: .85rem; } +.settings-div { + background-color: #d5d5d5; + color: black; + width: 300px; + border-top: none; + border-right: none; + border-left: none; + border-bottom: 0.125rem solid #e30019; + border-radius: 0.1875rem; + overflow-x: scroll; + white-space:nowrap; +} .sticky-edit { display: flex; @@ -198,7 +235,7 @@ select { } textarea, textarea:focus, input:focus{ outline: none; - font-size: medium; + font-size: .9rem; ; } @@ -215,6 +252,32 @@ textarea.select-folder-field, textarea.select-folder-field:focus, input.select-f margin-bottom: 0.25em; } +/* width */ +::-webkit-scrollbar { + width: 10px; + height: 5px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: #f1f1f1; + +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #888; + width: 10px; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #555; +} + + .yellow{ background-color: goldenrod; } + + diff --git a/src/components/App.js b/src/components/App.js index 5b0b2b5..7597b7c 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -3,13 +3,16 @@ import {DataForm} from "./DataForm"; import {Log} from "./Log" import SettingsIcon from '@mui/icons-material/Settings'; +// Modules +import ObjektkatalogApi from "../ObjektkatalogApi"; + // React -import { Link } from "react-router-dom"; +import {NavLink} from "react-router-dom"; import React, {useState} from 'react' // CSS import '../assets/css/styles.css' -import ObjektkatalogApi from "../ObjektkatalogApi"; +import {LoadingIcon} from "./LoadingIcon"; //////////////////// @@ -18,34 +21,34 @@ import ObjektkatalogApi from "../ObjektkatalogApi"; export const App = () => { + // Variables + const objektkatalogApi = new ObjektkatalogApi(); // States - /* Initialize state of the log. - * log: variables fpr logging message. - * logClass: for visibility of log
{logState.log.message}
diff --git a/src/config/config.json b/src/config/config.json deleted file mode 100644 index f62e2f6..0000000 --- a/src/config/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "rootDir": "/home/rbrt/Dokumente/marvin" -} \ No newline at end of file diff --git a/src/routes/settings.js b/src/routes/settings.js index f101a63..578df00 100644 --- a/src/routes/settings.js +++ b/src/routes/settings.js @@ -1,15 +1,18 @@ -import config from '../config/config.json' +// Config +import configImport from '/resources/config/config.json' + +// Components +import {Log} from "../components/Log"; // Icons import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; -import EditIcon from '@mui/icons-material/Edit'; - -// Modules -const {writeFile} = require('fs'); // React import React, {useState} from "react"; -import {Link} from "react-router-dom"; +import {NavLink} from "react-router-dom"; +import {Input} from "../components/Input"; +import EditIcon from "@mui/icons-material/Edit"; +import {writeFile} from "fs"; //////////////////// @@ -17,54 +20,62 @@ import {Link} from "react-router-dom"; //////////////////// export default function Settings() { - let rootDir; - const [disableButton, setDisableButton] = useState(true) + // States + const [config, setConfig] = useState( + configImport + ) - async function selectFolderHandler() { - return rootDir = await window.openFile(); + const [restart, setRestart] = useState( + false + ) + //Functions + async function selectFolderHandler(e) { + e.preventDefault() + const rootDirFromWindow = await window.openFile(); + setConfig((prevState) => { + return { + ...prevState, + rootDir: rootDirFromWindow + } + }) + const saveResult = await saveInputClickHandler(rootDirFromWindow) } - - // Handler - function saveInputClickHandler(rootDir) { - if (rootDir) { - config.rootDir = rootDir - writeFile('src/config/config.json', JSON.stringify(config, null, 2), (error) => { - if (error) { - console.log('An error has occurred ', error); - return; + async function saveInputClickHandler(rootDirFromWindow) { + let config2Safe = { + rootDir: rootDirFromWindow + } + if (rootDirFromWindow) { + let message; + await writeFile('resources/config/config.json', JSON.stringify(config2Safe, null, 2), (err) => { + if (err) { + message = err; + } else { + message = 'saved file' } - console.log('Data written successfully to disk'); - }); + return message + }) + setRestart(true) } } + return (