before restructering project
This commit is contained in:
parent
99adc9c445
commit
9605a5b972
22 changed files with 733 additions and 210 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,6 +1,7 @@
|
||||||
# Build folder and files #
|
# Build folder and files #
|
||||||
##########################
|
##########################
|
||||||
builds/
|
builds/
|
||||||
|
installers/
|
||||||
|
|
||||||
# Development folders and files #
|
# Development folders and files #
|
||||||
#################################
|
#################################
|
||||||
|
|
|
||||||
32
electron-builder.json
Normal file
32
electron-builder.json
Normal file
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
12
main.js
12
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) {
|
function createWindow(dimensions) {
|
||||||
if (dev !== true) {
|
if (dev !== true) {
|
||||||
|
|
@ -255,5 +265,3 @@ app.on('activate', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// IPC-Channel handling
|
|
||||||
|
|
|
||||||
BIN
marvin256x256.png
Normal file
BIN
marvin256x256.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
23
package.json
23
package.json
|
|
@ -33,25 +33,9 @@
|
||||||
"prod": "cross-env NODE_ENV=production webpack --mode production --config webpack.build.config.js && electron --noDevServer .",
|
"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",
|
"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",
|
"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",
|
"package": "npm run build",
|
||||||
"postpackage": "electron-packager ./ --ignore 'resources/files' --out=./builds --asar --overwrite --platform win32,linux --icon marvin.ico --extra-resource 'resources/files'"
|
"postpackage": "electron-packager ./ --ignore \"(resources|builds|installer)\" --out=./builds --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
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.10.0",
|
"@emotion/react": "^11.10.0",
|
||||||
|
|
@ -60,10 +44,12 @@
|
||||||
"@mui/material": "^5.10.2",
|
"@mui/material": "^5.10.2",
|
||||||
"about-window": "^1.15.2",
|
"about-window": "^1.15.2",
|
||||||
"docx-templates": "^4.9.2",
|
"docx-templates": "^4.9.2",
|
||||||
|
"image-resize-compress": "^1.0.8",
|
||||||
"postcss": "^8.4.16",
|
"postcss": "^8.4.16",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-async-devtools": "^10.0.1",
|
"react-async-devtools": "^10.0.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-image-gallery": "^1.2.9",
|
||||||
"react-loader-spinner": "^5.3.3",
|
"react-loader-spinner": "^5.3.3",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"replace-special-characters": "^1.2.6",
|
"replace-special-characters": "^1.2.6",
|
||||||
|
|
@ -91,6 +77,7 @@
|
||||||
"postcss-nested": "^5.0.6",
|
"postcss-nested": "^5.0.6",
|
||||||
"postcss-preset-env": "^7.8.0",
|
"postcss-preset-env": "^7.8.0",
|
||||||
"postcss-pxtorem": "^6.0.0",
|
"postcss-pxtorem": "^6.0.0",
|
||||||
|
"source-map-support": "^0.5.21",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"webpack": "^5.74.0",
|
"webpack": "^5.74.0",
|
||||||
"webpack-cli": "^4.10.0",
|
"webpack-cli": "^4.10.0",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"rootDir": "C:\\Users\\Robert\\Desktop\\marvin"
|
|
||||||
}
|
|
||||||
478
src/DocCreator.js
Normal file
478
src/DocCreator.js
Normal file
|
|
@ -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 = `
|
||||||
|
<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 createDate="${this.today}">
|
||||||
|
<mets:agent
|
||||||
|
type="other"
|
||||||
|
otherType="software"
|
||||||
|
role="creator">
|
||||||
|
<mets:name>
|
||||||
|
${process.env.REACT_APP_NAME} v${process.env.REACT_APP_VERSION}
|
||||||
|
</mets:name>
|
||||||
|
</mets:agent>
|
||||||
|
</mets:metsHdr>
|
||||||
|
<mets:fileSec>
|
||||||
|
<mets:fileGrp use="${this.documentInfo.documentType}">
|
||||||
|
<mets:file id="file__${this.filename}" mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document">
|
||||||
|
<mets:FLocat locType="other" otherLocType="file" xlink:href="${this.filenameWithExtension}"/>
|
||||||
|
</mets:file>
|
||||||
|
</mets:fileGrp>
|
||||||
|
</mets:fileSec>
|
||||||
|
<mets:structMap type="physical">
|
||||||
|
<mets:div type="${this.documentInfo.docTypeAbbr}" id="phys_00" dmdid="dmdphys_00">
|
||||||
|
<mets:fptr fileId="file__${this.filename}"/>
|
||||||
|
</mets:div>
|
||||||
|
</mets:structMap>
|
||||||
|
<mets:structMap type="logical">
|
||||||
|
<mets:div type="${this.documentInfo.docTypeAbbr}" id="phys_00">
|
||||||
|
<mets:fptr fileId="file__${this.filename}"/>
|
||||||
|
</mets:div>
|
||||||
|
</mets:structMap>
|
||||||
|
<mets:dmdSec id="dmdlog_00">
|
||||||
|
<mets:mdWrap mdType="mods">
|
||||||
|
<mets:xmlData>
|
||||||
|
<mods:mods xmlns:mods="http://www.loc.gov/mods/v3">
|
||||||
|
<mods:recordInfo>
|
||||||
|
<mods:recordIdentifier source="https://objektkatalag.gnm.de">${this.objectData.inventarnummer}</mods:recordIdentifier>
|
||||||
|
</mods:recordInfo>
|
||||||
|
<mods:titleInfo>
|
||||||
|
<mods:title>${this.objectData.titel}</mods:title>
|
||||||
|
</mods:titleInfo>
|
||||||
|
<mods:originInfo>
|
||||||
|
<mods_dateIssued encoding="w3cdtf" keyDate="yes">${this.objectData.herstellungsdatum}</mods_dateIssued>
|
||||||
|
<mods:place>
|
||||||
|
<mods:placeTerm type="text">${this.objectData.herstellungsort}</mods:placeTerm>
|
||||||
|
</mods:place>
|
||||||
|
</mods:originInfo>
|
||||||
|
<mods:name type="personal">
|
||||||
|
<mods:role>
|
||||||
|
<mods:roleTerm authority="marcrelator" type="code">cre</mods:roleTerm>
|
||||||
|
</mods:role>
|
||||||
|
<mods:namePart>${this.objectData.herstellungsort}</mods:namePart>
|
||||||
|
<mods:displayForm>${this.objectData.herstellungsort}</mods:displayForm>
|
||||||
|
</mods:name>
|
||||||
|
<mods:physicalDescription>
|
||||||
|
<mods:form type="Material and Technique" lang="de"/>
|
||||||
|
<mods:extent>${this.objectData.masse}</mods:extent>
|
||||||
|
</mods:physicalDescription>
|
||||||
|
</mods:mods>
|
||||||
|
</mets:xmlData>
|
||||||
|
</mets:mdWrap>
|
||||||
|
</mets:dmdSec>
|
||||||
|
</mets:mets>
|
||||||
|
`
|
||||||
|
|
||||||
|
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};
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
30
src/Image.js
Normal file
30
src/Image.js
Normal file
|
|
@ -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};
|
||||||
|
|
@ -18,12 +18,14 @@ class ObjektkatalogApi {
|
||||||
masse: '',
|
masse: '',
|
||||||
materialTechnik: '',
|
materialTechnik: '',
|
||||||
titel: '',
|
titel: '',
|
||||||
|
wisskiUri: '',
|
||||||
};
|
};
|
||||||
response;
|
response;
|
||||||
visibility;
|
visibility;
|
||||||
|
|
||||||
|
|
||||||
// Get data from objektkatalog.gnm.de.
|
// Get data from objektkatalog.gnm.de.
|
||||||
|
|
||||||
async getData(objectId) {
|
async getData(objectId) {
|
||||||
if (objectId) {
|
if (objectId) {
|
||||||
// RESTful GET.
|
// RESTful GET.
|
||||||
|
|
@ -50,6 +52,7 @@ class ObjektkatalogApi {
|
||||||
eid: responseJson[0]['eid'],
|
eid: responseJson[0]['eid'],
|
||||||
allgemeineBezeichnung: responseJson[0]['fc6392714594e73ddb2fa363815a8fdf'],
|
allgemeineBezeichnung: responseJson[0]['fc6392714594e73ddb2fa363815a8fdf'],
|
||||||
beschreibung: responseJson[0]['f81f557caccf45074edfb65ff077011f'],
|
beschreibung: responseJson[0]['f81f557caccf45074edfb65ff077011f'],
|
||||||
|
bilder: responseJson[0]['f41dae62df47283958f605716d141ebf'],
|
||||||
darstellung: responseJson[0]['f217e1053b1e29411d4b00f3b1e1d52b'],
|
darstellung: responseJson[0]['f217e1053b1e29411d4b00f3b1e1d52b'],
|
||||||
erwerbsmethode: responseJson[0]['fa4aa035d411275cd36a2fbb5c159a2c'],
|
erwerbsmethode: responseJson[0]['fa4aa035d411275cd36a2fbb5c159a2c'],
|
||||||
fruehstes: responseJson[0]['ff4a178095c895a12fce6320c04ba0b0'],
|
fruehstes: responseJson[0]['ff4a178095c895a12fce6320c04ba0b0'],
|
||||||
|
|
@ -71,6 +74,7 @@ class ObjektkatalogApi {
|
||||||
titel: responseJson[0]['f2049b2456b20f8fd80f714e154f1d47'],
|
titel: responseJson[0]['f2049b2456b20f8fd80f714e154f1d47'],
|
||||||
unterbringung: responseJson[0]['f15265e39237868a568ee63453492b17'],
|
unterbringung: responseJson[0]['f15265e39237868a568ee63453492b17'],
|
||||||
vitrinentext: responseJson[0]['fe5e3ff18aedf1d25c639dc79fb24ad1'],
|
vitrinentext: responseJson[0]['fe5e3ff18aedf1d25c639dc79fb24ad1'],
|
||||||
|
wisskiUri: responseJson[0]['wisski_uri'][0]['value'],
|
||||||
zustandsbeschreibung: responseJson[0]['f54b6da6006ea444c33a348b8c4370a8']
|
zustandsbeschreibung: responseJson[0]['f54b6da6006ea444c33a348b8c4370a8']
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -118,6 +122,16 @@ class ObjektkatalogApi {
|
||||||
return [this.receivedData, this.visibility]
|
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
|
// Datum
|
||||||
// Default date of today
|
// Default date of today
|
||||||
let today = new Date()
|
let today = new Date()
|
||||||
|
|
@ -187,9 +201,11 @@ class ObjektkatalogApi {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Json with important data.
|
// Json with important data.
|
||||||
this.receivedData = {
|
this.receivedData = {
|
||||||
...this.receivedData,
|
...this.receivedData,
|
||||||
|
bilder: bilder,
|
||||||
datum: todayFormat,
|
datum: todayFormat,
|
||||||
titel: titel,
|
titel: titel,
|
||||||
hersteller: hersteller,
|
hersteller: hersteller,
|
||||||
|
|
@ -198,6 +214,7 @@ class ObjektkatalogApi {
|
||||||
inventarnummer: inventarnummer,
|
inventarnummer: inventarnummer,
|
||||||
materialTechnik: materialTechnik,
|
materialTechnik: materialTechnik,
|
||||||
masse: masse,
|
masse: masse,
|
||||||
|
wisskiUri: this.raw.wisskiUri,
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
}
|
}
|
||||||
this.visibility = true
|
this.visibility = true
|
||||||
|
|
|
||||||
3
src/assets/config/config.json
Normal file
3
src/assets/config/config.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"rootDir": "/home/rbrt/Schreibtisch/boehler"
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
|
|
||||||
|
/* Imports */
|
||||||
@import url('https://fonts.googleapis.com/css?family=Open+Sans');
|
@import url('https://fonts.googleapis.com/css?family=Open+Sans');
|
||||||
|
@import "react-image-gallery/styles/css/image-gallery.css";
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #d5d5d5;
|
color: #d5d5d5;
|
||||||
|
|
@ -23,6 +26,10 @@ body {
|
||||||
.checkup {
|
.checkup {
|
||||||
transition: height 1s;
|
transition: height 1s;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.closed{
|
.closed{
|
||||||
|
|
@ -43,10 +50,6 @@ body {
|
||||||
max-width: max-content;
|
max-width: max-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
div {
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edit-button {
|
.edit-button {
|
||||||
background-color: #e30f27;
|
background-color: #e30f27;
|
||||||
color: #d5d5d5;
|
color: #d5d5d5;
|
||||||
|
|
@ -55,6 +58,7 @@ div {
|
||||||
border: unset;
|
border: unset;
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
|
border-radius: 0 .1875rem .1875rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-input {
|
.edit-input {
|
||||||
|
|
@ -87,6 +91,23 @@ div {
|
||||||
background-color: darkgreen;
|
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 {
|
.inactive {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
@ -129,6 +150,10 @@ input.edit-input:not(:disabled) {
|
||||||
font-family: "Open Sans", sans-serif;
|
font-family: "Open Sans", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.justify-content-center {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.justify-content-end {
|
.justify-content-end {
|
||||||
|
|
@ -168,13 +193,16 @@ label {
|
||||||
}
|
}
|
||||||
|
|
||||||
.open {
|
.open {
|
||||||
height: 610px;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pd-05rem {
|
||||||
|
padding: .5rem;
|
||||||
|
}
|
||||||
.position-absolute {
|
.position-absolute {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
@ -223,15 +251,15 @@ select {
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-div {
|
.settings-div {
|
||||||
background-color: #d5d5d5;
|
background-color: #f2f2f2;
|
||||||
color: black;
|
color: black;
|
||||||
width: 300px;
|
width: 388px;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
border-left: none;
|
border-left: none;
|
||||||
border-bottom: 0.125rem solid #e30019;
|
border-bottom: 0.125rem solid #e30019;
|
||||||
border-radius: 0.1875rem;
|
border-radius: .1875rem 0 0 .1875rem;
|
||||||
overflow-x: scroll;
|
overflow-x: auto;
|
||||||
white-space:nowrap;
|
white-space:nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -256,10 +284,13 @@ textarea.select-folder-field, textarea.select-folder-field:focus, input.select-f
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-distance {
|
.v-distance {
|
||||||
margin-top: 0.25em;
|
margin-top: 0.25rem;
|
||||||
margin-bottom: 0.25em;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bottom-distance {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
/* width */
|
/* width */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 5px;
|
width: 5px;
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 434 B After Width: | Height: | Size: 434 B |
|
|
@ -1,6 +1,13 @@
|
||||||
// Components
|
// Components
|
||||||
import {DataForm} from "./DataForm";
|
import {DataForm} from "./DataForm";
|
||||||
import {Log} from "./Log"
|
import {Log} from "./Log"
|
||||||
|
|
||||||
|
|
||||||
|
// CSS
|
||||||
|
import '../assets/css/styles.css'
|
||||||
|
import {LoadingIcon} from "./LoadingIcon";
|
||||||
|
|
||||||
|
// Icons
|
||||||
import SettingsIcon from '@mui/icons-material/Settings';
|
import SettingsIcon from '@mui/icons-material/Settings';
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
|
|
@ -10,10 +17,6 @@ import ObjektkatalogApi from "../ObjektkatalogApi";
|
||||||
import {NavLink} from "react-router-dom";
|
import {NavLink} from "react-router-dom";
|
||||||
import React, {useState} from 'react'
|
import React, {useState} from 'react'
|
||||||
|
|
||||||
// CSS
|
|
||||||
import '../assets/css/styles.css'
|
|
||||||
import {LoadingIcon} from "./LoadingIcon";
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
// Main //
|
// Main //
|
||||||
|
|
@ -91,8 +94,21 @@ export const App = () => {
|
||||||
await setLogState({
|
await setLogState({
|
||||||
log: {
|
log: {
|
||||||
status: 'red',
|
status: 'red',
|
||||||
message: 'Objektkatalog nicht erreichbar!',
|
message: 'Objektkatalog kann sich nicht um die Anfrage kümmern!',
|
||||||
code: '503',
|
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?',
|
tip: 'Sind sie mit dem Internet verbunden und ist der Objektkatalog online?',
|
||||||
}, // with message, code, tip
|
}, // with message, code, tip
|
||||||
logClass: 'active'
|
logClass: 'active'
|
||||||
|
|
@ -170,7 +186,9 @@ export const App = () => {
|
||||||
<NavLink className={'nav-icon'} to="/settings"><SettingsIcon/></NavLink>
|
<NavLink className={'nav-icon'} to="/settings"><SettingsIcon/></NavLink>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main className={"bottom-distance"}>
|
||||||
|
<h3 className={"flex-center"}>Marvin</h3>
|
||||||
|
<section>
|
||||||
<div className={"container"}>
|
<div className={"container"}>
|
||||||
<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 "}>
|
||||||
|
|
@ -198,6 +216,8 @@ export const App = () => {
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<LoadingIcon isLoading={isLoading}/>
|
<LoadingIcon isLoading={isLoading}/>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
<DataForm
|
<DataForm
|
||||||
checkUpVisibility={checkUpVisibility}
|
checkUpVisibility={checkUpVisibility}
|
||||||
objectData={objectData}
|
objectData={objectData}
|
||||||
|
|
@ -205,6 +225,7 @@ export const App = () => {
|
||||||
logState={logState}
|
logState={logState}
|
||||||
setLogState={setLogState}
|
setLogState={setLogState}
|
||||||
/>
|
/>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
{/* We give state and state setter of the parent as params to the child components, so that child events can change parent states */}
|
{/* We give state and state setter of the parent as params to the child components, so that child events can change parent states */}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
// Components
|
||||||
|
import {Galary} from './Galary'
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
import {fillTemplate} from "../DocxInserter";
|
import {DocCreator} from "../DocCreator";
|
||||||
|
|
||||||
// React
|
// React
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
@ -98,7 +101,10 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
|
||||||
// Fill the template and save it.
|
// Fill the template and save it.
|
||||||
const fillTemplateClickHandler = async (e) => {
|
const fillTemplateClickHandler = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
log = await fillTemplate(logState, objectData);
|
const docCreator = new DocCreator(logState, objectData)
|
||||||
|
log = await docCreator.fillTemplate();
|
||||||
|
const metsMods = await docCreator.createMetsMods();
|
||||||
|
|
||||||
// Set new state of log div with message and visibility class
|
// Set new state of log div with message and visibility class
|
||||||
setLogState({
|
setLogState({
|
||||||
log: log,
|
log: log,
|
||||||
|
|
@ -107,8 +113,11 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renders data form
|
// Renders data form
|
||||||
return (<div className={'checkup ' + (checkUpVisibility ? 'open' : 'closed')}>
|
return (
|
||||||
<form className={'flex column '}>
|
<div className={'checkup ' + (checkUpVisibility ? 'open' : 'closed')}>
|
||||||
|
<form className={'flex column pd-05rem'}>
|
||||||
|
<Galary objectData={objectData}/>
|
||||||
|
<div>
|
||||||
<div >
|
<div >
|
||||||
<label htmlFor={'template-datum'} >Datum</label>
|
<label htmlFor={'template-datum'} >Datum</label>
|
||||||
<input
|
<input
|
||||||
|
|
@ -198,6 +207,7 @@ export const DataForm = ({checkUpVisibility, objectData, setObjectData, logState
|
||||||
onChange={masseChangeHandler}
|
onChange={masseChangeHandler}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
type={"submit"}
|
type={"submit"}
|
||||||
className={'send-button center top-distance'}
|
className={'send-button center top-distance'}
|
||||||
|
|
|
||||||
22
src/components/Galary.js
Normal file
22
src/components/Galary.js
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {Image} from "../Image";
|
||||||
|
import ImageGallery from 'react-image-gallery';
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
// Main //
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
export const Galary = ({objectData}) => {
|
||||||
|
let images =[];
|
||||||
|
if (objectData.bilder) {
|
||||||
|
for (const imageIndex in objectData.bilder) {
|
||||||
|
images.push(new Image(objectData.bilder[imageIndex]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ImageGallery items={images} showFullscreenButton={false} showPlayButton={false} showThumbnails={false} disableKeyDown={true}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Galary;
|
||||||
|
|
@ -15,7 +15,7 @@ export const Log = ({logState, setLogState}) => {
|
||||||
logClass: 'inactive'});
|
logClass: 'inactive'});
|
||||||
}
|
}
|
||||||
|
|
||||||
const classes = 'round-box flex ' + logState.log.status + ' ' + logState.logClass
|
const classes = 'round-box flex pd-05rem ' + logState.log.status + ' ' + logState.logClass
|
||||||
if (logState.log.code) {
|
if (logState.log.code) {
|
||||||
code = ' Code: ' + logState.log.code
|
code = ' Code: ' + logState.log.code
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -29,10 +29,10 @@ export const Log = ({logState, setLogState}) => {
|
||||||
return (
|
return (
|
||||||
<div className={'log '}>
|
<div className={'log '}>
|
||||||
<div id={'log-content'} className={classes}>
|
<div id={'log-content'} className={classes}>
|
||||||
<div>
|
<div className={"log-close-button"}>
|
||||||
<button onClick={closeLog}>x</button>
|
<button onClick={closeLog}>x</button>
|
||||||
</div>
|
</div>
|
||||||
<div className={'scroll-y flex-full'} style={{maxHeight: 4 + 'em'}}>
|
<div className={'scroll-y flex-full pd-05rem'} style={{maxHeight: 4 + 'em'}}>
|
||||||
<p>{logState.log.message}</p>
|
<p>{logState.log.message}</p>
|
||||||
<p>{code}</p>
|
<p>{code}</p>
|
||||||
<p>{tip}</p>
|
<p>{tip}</p>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// Config
|
// Modules
|
||||||
import configImport from '/resources/files/config/config.json'
|
import path from "path";
|
||||||
|
|
||||||
// Components
|
// Config
|
||||||
import {Log} from "../components/Log";
|
import configImport from '/src/assets/config/config.json'
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
|
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
|
||||||
|
|
@ -48,8 +48,9 @@ export default function Settings() {
|
||||||
rootDir: rootDirFromWindow
|
rootDir: rootDirFromWindow
|
||||||
}
|
}
|
||||||
if (rootDirFromWindow) {
|
if (rootDirFromWindow) {
|
||||||
|
console.log(__dirname);
|
||||||
let message;
|
let message;
|
||||||
await writeFile('resources/files/config/config.json', JSON.stringify(config2Safe, null, 2), (err) => {
|
await writeFile('/resources/files/config/config.json', JSON.stringify(config2Safe, null, 2), (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
message = err;
|
message = err;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -68,11 +69,13 @@ export default function Settings() {
|
||||||
<NavLink className={'nav-icon'} to="/"><ArrowBackIosIcon/></NavLink>
|
<NavLink className={'nav-icon'} to="/"><ArrowBackIosIcon/></NavLink>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<form onSubmit={selectFolderHandler}>
|
<section className={"flex-center column"}>
|
||||||
<label htmlFor={"output-root"}>
|
<h3>Einstellungen</h3>
|
||||||
|
<form onSubmit={selectFolderHandler} className={"pd-05rem"}>
|
||||||
|
<label className={"center cut v-distance"} htmlFor={"output-root"}>
|
||||||
Hauptverzeichnis
|
Hauptverzeichnis
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10 d-flex align-items-center flex sticky-edit">
|
<div className="align-items-center flex">
|
||||||
<Input config={config} setConfig={setConfig}/>
|
<Input config={config} setConfig={setConfig}/>
|
||||||
<button type="submit" className="edit-button text-end">
|
<button type="submit" className="edit-button text-end">
|
||||||
<i className="fas fa-edit d-block">
|
<i className="fas fa-edit d-block">
|
||||||
|
|
@ -81,6 +84,7 @@ export default function Settings() {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
|
|
@ -12,25 +12,23 @@ module.exports = {
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'postcss-loader' }],
|
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'postcss-loader' }],
|
||||||
include: defaultInclude
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.jsx?$/,
|
test: /\.jsx?$/,
|
||||||
use: [{ loader: 'babel-loader' }],
|
use: [{ loader: 'babel-loader' }],
|
||||||
include: defaultInclude
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(jpe?g|png|gif)$/,
|
test: /\.(jpe?g|png|gif)$/,
|
||||||
use: [{ loader: 'file-loader?name=img/[name]__[hash:base64:5].[ext]' }],
|
use: [{ loader: 'file-loader?name=img/[name]__[hash:base64:5].[ext]' }],
|
||||||
include: defaultInclude
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(eot|svg|ttf|woff|woff2)$/,
|
test: /\.(eot|svg|ttf|woff|woff2)$/,
|
||||||
use: [{ loader: 'file-loader?name=font/[name]__[hash:base64:5].[ext]' }],
|
use: [{ loader: 'file-loader?name=font/[name]__[hash:base64:5].[ext]' }],
|
||||||
include: defaultInclude
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
target: 'electron-renderer',
|
target: 'electron-renderer',
|
||||||
plugins: [
|
plugins: [
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue