diff --git a/.erb/configs/webpack.paths.ts b/.erb/configs/webpack.paths.ts new file mode 100644 index 0000000..78a0faa --- /dev/null +++ b/.erb/configs/webpack.paths.ts @@ -0,0 +1,29 @@ +const path = require('path'); + +const rootPath = path.resolve(__dirname, '../..'); + +const srcPath = path.resolve(rootPath, 'src'); +const srcMainPath = path.resolve(srcPath, 'main'); +const srcRendererPath = path.resolve(srcPath, 'renderer'); + +const appPackagePath = path.resolve(rootPath, 'package.json'); +const appNodeModulesPath = path.resolve(rootPath, 'node_modules'); + +const distPath = path.resolve(rootPath, 'dist'); +const distMainPath = path.resolve(distPath, 'main'); +const distRendererPath = path.resolve(distPath, 'renderer'); + +const buildPath = path.resolve(rootPath, 'build'); + +export default { + rootPath, + srcPath, + srcMainPath, + srcRendererPath, + appPackagePath, + appNodeModulesPath, + distPath, + distMainPath, + distRendererPath, + buildPath, +}; diff --git a/main.js b/main.js index d2b5099..9331189 100644 --- a/main.js +++ b/main.js @@ -3,14 +3,19 @@ // Import parts of electron to use const {app, BrowserWindow, dialog, ipcMain, Menu, screen, Tray} = require('electron') const openAboutWindow = require('about-window').default -const path = require('path') -const url = require('url') +const path = require('path'); +const fs = require('fs'); +const url = require('url'); // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let mainWindow, tray; let devBrowserProperties = {}; +const ASSET_PATH = app.isPackaged + ? path.resolve(process.resourcesPath, 'app/src/assets') + : path.resolve(__dirname, 'src/assets'); + let trayMenu = Menu.buildFromTemplate([ { label: 'Öffnen', @@ -27,8 +32,10 @@ let trayMenu = Menu.buildFromTemplate([ } ]) + const RESSOURCE_PATH= fs.existsSync(ASSET_PATH) ? ASSET_PATH : 'resources/files' ; + function createTray() { - tray = new Tray('./resources/files/images/marvin16x16.png'); + tray = new Tray(path.resolve(RESSOURCE_PATH, 'images/marvin16x16.png')); tray.setToolTip('Marvin') tray.setContextMenu(trayMenu); tray.on('click', function() { @@ -60,12 +67,18 @@ if (process.platform === 'win32') { async function handleFileOpen() { const {canceled, filePaths} = await dialog.showOpenDialog(mainWindow, {properties: ['openDirectory']}) if (canceled) { - return + return false } else { return filePaths[0] } } +// Constants + +const getAssetPath = async (assetPath) => { + return path.resolve(ASSET_PATH, assetPath); +}; + // Build main menu from file. let mainMenu = Menu.buildFromTemplate( [ @@ -142,22 +155,11 @@ 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) { devBrowserProperties = { fullscreenable: false, - resizable: false, + resizable: true, } } @@ -173,7 +175,7 @@ function createWindow(dimensions) { y: 0, width: appWidth, height: appHeight, - icon: __dirname + '/marvin.ico', + icon: path.resolve(RESSOURCE_PATH, 'images/marvin.ico'), show: false, webPreferences: { preload: path.join(__dirname, 'preload.js'), @@ -221,11 +223,13 @@ function createWindow(dimensions) { .catch(err => console.log('Error loading React DevTools: ', err)) mainWindow.webContents.openDevTools() } + mainWindow.webContents.openDevTools() }) mainWindow.on('close', function (e) { if(mainWindow.isMinimized()) { app.quit() + app.quit() } else { e.preventDefault() mainWindow.minimize(); @@ -235,6 +239,7 @@ function createWindow(dimensions) { mainWindow.on('closed', function () { mainWindow = null; }) + } // This method will be called when Electron has finished @@ -242,6 +247,10 @@ function createWindow(dimensions) { // Some APIs can only be used after this event occurs. app.on('ready', () => { ipcMain.handle('dialog:openFile', handleFileOpen) + ipcMain.handle('assetPath:getAssetPath', async (event, assetPath) => { + return await getAssetPath(assetPath) + }) + const display = screen.getPrimaryDisplay(); const dimensions = display.size; createWindow(dimensions); diff --git a/package.json b/package.json index ed4e429..242e438 100644 --- a/package.json +++ b/package.json @@ -33,9 +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", - "pack:installer": "electron-builder build -lw", + "pack:installer": "electron-builder build -l", "package": "npm run build", - "postpackage": "electron-packager ./ --ignore \"(resources|builds|installer)\" --out=./builds --overwrite --platform win32,linux --icon marvin.ico --extra-resource 'resources/files'" + "postpackage": "electron-packager ./ --ignore \"(resources|builds|installer)\" --out=./builds --overwrite --platform linux --icon marvin.ico" }, "dependencies": { "@emotion/react": "^11.10.0", diff --git a/src/DocCreator.js b/src/DocCreator.js index 8c64deb..a636a0d 100644 --- a/src/DocCreator.js +++ b/src/DocCreator.js @@ -1,11 +1,11 @@ // 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'; +import {FileLoader} from "./FileLoader"; //////////////////// @@ -24,9 +24,11 @@ class DocCreator { // Get DateTime. this.today = new Date(); + // FileLoader + this.fileLoader = new FileLoader() + // Get config file and parse to json. - this.configFile = fs.readFileSync('/resources/files/config/config.json') - this.configJson = JSON.parse(this.configFile.toString()) + this.configFile = this.fileLoader.getConfigFile() // Choose the template for selected document type. switch (objectData.dokumenttyp) { @@ -53,19 +55,21 @@ class DocCreator { // 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"); + let replaceUmlauteTitle = replaceEszettTitle.replace("Ä", "Ae"); + replaceUmlauteTitle = replaceUmlauteTitle.replace("ä", "ae"); + replaceUmlauteTitle = replaceUmlauteTitle.replace("Ö", "Oe"); + replaceUmlauteTitle = replaceUmlauteTitle.replace("ö", "oe"); + replaceUmlauteTitle = replaceUmlauteTitle.replace("Ü", "Ue"); + replaceUmlauteTitle = replaceUmlauteTitle.replace("ü", "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.objectPath = path.join(this.configFile.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' @@ -78,13 +82,12 @@ class DocCreator { 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)); + const template = fs.readFileSync(path.resolve(this.fileLoader.getTemplateDir(), this.documentInfo.templateFile)); // Create report. buffer = await createReport({ @@ -110,8 +113,8 @@ class DocCreator { } try { - const createDocumentPath = await mkdir(this.documentPath, {recursive: true}); - const createTemporaryWorkDirPath = await mkdir(this.temporaryWorkDirPath, {recursive: true}); + await mkdir(this.documentPath, {recursive: true}); + await mkdir(this.temporaryWorkDirPath, {recursive: true}); } catch (err) { // Set error log. this.log = { @@ -148,15 +151,7 @@ class DocCreator { + > { if (objectId) { // Get object data from objektkatalog.gnm.de. - const [receivedObjectData, receivedVisibility] = await objektkatalogApi.getData(objectId); + const receivedObjectData = await objektkatalogApi.getData(objectId); // If no response from Objektkatalog. switch (receivedObjectData.httpStatus) { // Server not reachable. diff --git a/src/components/Input.js b/src/components/Input.js index cf31f57..fecff3f 100644 --- a/src/components/Input.js +++ b/src/components/Input.js @@ -1,6 +1,6 @@ import React from "react"; -export const Input = ({config}) => { +export const Input = ({configFile}) => { return ( - {config.rootDir} ) + {configFile.rootDir} ) } diff --git a/src/routes/settings.js b/src/routes/settings.js index 7b35001..6f5c787 100644 --- a/src/routes/settings.js +++ b/src/routes/settings.js @@ -1,8 +1,9 @@ // Modules -import path from "path"; +import {FileLoader} from "../FileLoader"; -// Config -import configImport from '/src/assets/config/config.json' +// Electron +const electron = window.require('electron'); +const ipcRenderer = electron.ipcRenderer; // Icons import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; @@ -20,37 +21,43 @@ import {writeFile} from "fs"; //////////////////// export default function Settings() { - // States - const [config, setConfig] = useState( - configImport - ) + const fileLoader = new FileLoader() + const initialConfig = fileLoader.getConfigFile() + console.log(initialConfig) + const getConfigPath = async (path) => { + return await ipcRenderer.invoke('assetPath:getAssetPath', path) + } +// States + const [configFile, setConfigFile] = useState( + initialConfig + ) const [restart, setRestart] = useState( false ) - //Functions +//Functions async function selectFolderHandler(e) { e.preventDefault() const rootDirFromWindow = await window.openFile(); - setConfig((prevState) => { + setConfigFile((prevState) => { return { ...prevState, rootDir: rootDirFromWindow } }) - const saveResult = await saveInputClickHandler(rootDirFromWindow) + await saveInputClickHandler(rootDirFromWindow) } - // Handler +// Handler async function saveInputClickHandler(rootDirFromWindow) { let config2Safe = { rootDir: rootDirFromWindow } if (rootDirFromWindow) { - console.log(__dirname); let message; - await writeFile('/resources/files/config/config.json', JSON.stringify(config2Safe, null, 2), (err) => { + const configPath = await getConfigPath('config/config.json') + await writeFile(configPath, JSON.stringify(config2Safe, null, 2), (err) => { if (err) { message = err; } else { @@ -59,6 +66,7 @@ export default function Settings() { return message }) setRestart(true) + return restart; } } @@ -76,7 +84,7 @@ export default function Settings() { Hauptverzeichnis
- +