From 19a45fb7eaa3682665c901c2565afb90b63217c4 Mon Sep 17 00:00:00 2001 From: Christoph Reiter <reiter.christoph@gmail.com> Date: Thu, 3 Feb 2022 17:19:37 +0100 Subject: [PATCH] Re-format while code base --- .eslintrc.json | 4 +- .renovaterc.json | 20 +- app-template/app.manifest.json | 107 ++- app-template/topic.metadata.json | 40 +- app.config.js | 12 +- assets/manifest.json | 107 ++- i18next-scanner.config.js | 12 +- karma.conf.js | 50 +- package.json | 154 ++-- rollup.config.js | 357 +++++----- src/activity.js | 2 +- src/base-element.js | 21 +- src/dbp-official-signature-pdf-upload.js | 508 +++++++++----- ...fficial-signature-pdf-upload.metadata.json | 34 +- src/dbp-pdf-annotation-view.js | 199 ++++-- src/dbp-pdf-preview.js | 416 ++++++----- src/dbp-qualified-signature-pdf-upload.js | 663 +++++++++++------- ...alified-signature-pdf-upload.metadata.json | 32 +- src/dbp-signature-lit-element.js | 127 ++-- src/dbp-signature-verification-full.js | 372 ++++++---- ...-signature-verification-full.metadata.json | 32 +- src/dbp-signature-verification.js | 49 +- src/dbp-signature-verification.metadata.json | 32 +- src/dbp-signature.js | 4 +- src/ext-sign-iframe.js | 48 +- src/i18n.js | 2 +- src/i18n/de/translation.json | 278 ++++---- src/i18n/en/translation.json | 278 ++++---- src/signature-entry.js | 3 +- src/styles.js | 65 +- src/textswitch.js | 55 +- src/utils.js | 80 ++- test/unit.js | 76 +- 33 files changed, 2431 insertions(+), 1808 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index e541fba..c30e287 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -14,11 +14,11 @@ "sourceType": "module" }, "rules": { - "no-unused-vars": ["error", { "args": "none" }], + "no-unused-vars": ["error", {"args": "none"}], "semi": [2, "always"], "jsdoc/require-jsdoc": 0, "jsdoc/require-param-description": 0, "jsdoc/require-returns": 0, "jsdoc/require-param-type": 0 } -} \ No newline at end of file +} diff --git a/.renovaterc.json b/.renovaterc.json index 2fb8654..2425a87 100644 --- a/.renovaterc.json +++ b/.renovaterc.json @@ -1,13 +1,9 @@ { - "extends": [ - "config:base", - "group:allNonMajor", - "schedule:weekly" - ], - "ignorePresets": [":prHourlyLimit2"], - "rangeStrategy": "update-lockfile", - "composer": { - "enabled": false - }, - "cloneSubmodules": true -} \ No newline at end of file + "extends": ["config:base", "group:allNonMajor", "schedule:weekly"], + "ignorePresets": [":prHourlyLimit2"], + "rangeStrategy": "update-lockfile", + "composer": { + "enabled": false + }, + "cloneSubmodules": true +} diff --git a/app-template/app.manifest.json b/app-template/app.manifest.json index e9e4eb8..b8aaf36 100644 --- a/app-template/app.manifest.json +++ b/app-template/app.manifest.json @@ -1,56 +1,55 @@ { - "short_name": "esign", - "name": "Electronic Signature Service", - "start_url": "./", - "icons": [ - { - "src": "images/icon-72x72.png", - "sizes": "72x72", - "type": "image/png" - }, - { - "src": "images/icon-96x96.png", - "sizes": "96x96", - "type": "image/png" - }, - { - "src": "images/icon-128x128.png", - "sizes": "128x128", - "type": "image/png" - }, - { - "src": "images/icon-144x144.png", - "sizes": "144x144", - "type": "image/png" - }, - { - "src": "images/icon-152x152.png", - "sizes": "152x152", - "type": "image/png" - }, - { - "src": "images/icon-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "images/icon-384x384.png", - "sizes": "384x384", - "type": "image/png" - }, - { - "src": "images/icon-256x256.png", - "sizes": "256x256", - "type": "image/png" - }, - { - "src": "images/icon-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "background_color": "#FEFEFE", - "display": "standalone", - "theme_color": "#FFFFFF" + "short_name": "esign", + "name": "Electronic Signature Service", + "start_url": "./", + "icons": [ + { + "src": "images/icon-72x72.png", + "sizes": "72x72", + "type": "image/png" + }, + { + "src": "images/icon-96x96.png", + "sizes": "96x96", + "type": "image/png" + }, + { + "src": "images/icon-128x128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "images/icon-144x144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "images/icon-152x152.png", + "sizes": "152x152", + "type": "image/png" + }, + { + "src": "images/icon-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "images/icon-384x384.png", + "sizes": "384x384", + "type": "image/png" + }, + { + "src": "images/icon-256x256.png", + "sizes": "256x256", + "type": "image/png" + }, + { + "src": "images/icon-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "background_color": "#FEFEFE", + "display": "standalone", + "theme_color": "#FFFFFF" } - diff --git a/app-template/topic.metadata.json b/app-template/topic.metadata.json index 45aee4f..013b68e 100644 --- a/app-template/topic.metadata.json +++ b/app-template/topic.metadata.json @@ -1,21 +1,21 @@ { - "name": { - "de": "Elektronisches Signaturservice", - "en": "Electronic Signatures" - }, - "short_name": { - "de": "Elektronisches Signaturservice", - "en": "Electronic Signatures" - }, - "description": { - "de": "Mit dieser Applikation können Sie PDF-Dokumente signieren", - "en": "With this application you can sign PDF documents" - }, - "routing_name": "signature", - "activities": [ - {"path": "/app/dbp-qualified-signature-pdf-upload.metadata.json"}, - {"path": "/app/dbp-signature-verification.metadata.json"}, - {"path": "/app/dbp-official-signature-pdf-upload.metadata.json"} - ], - "attributes": [] -} \ No newline at end of file + "name": { + "de": "Elektronisches Signaturservice", + "en": "Electronic Signatures" + }, + "short_name": { + "de": "Elektronisches Signaturservice", + "en": "Electronic Signatures" + }, + "description": { + "de": "Mit dieser Applikation können Sie PDF-Dokumente signieren", + "en": "With this application you can sign PDF documents" + }, + "routing_name": "signature", + "activities": [ + {"path": "/app/dbp-qualified-signature-pdf-upload.metadata.json"}, + {"path": "/app/dbp-signature-verification.metadata.json"}, + {"path": "/app/dbp-official-signature-pdf-upload.metadata.json"} + ], + "attributes": [] +} diff --git a/app.config.js b/app.config.js index 843b6b7..309a55d 100644 --- a/app.config.js +++ b/app.config.js @@ -11,7 +11,7 @@ export default { nextcloudName: 'TU Graz cloud', pdfAsQualifiedlySigningServer: 'https://sig-dev.tugraz.at', hiddenActivities: ['dbp-signature-verification-full'], - enableAnnotations: true + enableAnnotations: true, }, bs: { basePath: '/dist/', @@ -25,7 +25,7 @@ export default { nextcloudName: 'TU Graz cloud', pdfAsQualifiedlySigningServer: 'https://sig-dev.tugraz.at', hiddenActivities: [], - enableAnnotations: true + enableAnnotations: true, }, development: { basePath: '/apps/signature/', @@ -39,7 +39,7 @@ export default { nextcloudName: 'TU Graz cloud', pdfAsQualifiedlySigningServer: 'https://sig-dev.tugraz.at', hiddenActivities: ['dbp-signature-verification-full'], - enableAnnotations: true + enableAnnotations: true, }, demo: { basePath: '/apps/signature/', @@ -53,7 +53,7 @@ export default { nextcloudName: 'TU Graz cloud', pdfAsQualifiedlySigningServer: 'https://sig-demo.tugraz.at', hiddenActivities: ['dbp-signature-verification-full'], - enableAnnotations: true + enableAnnotations: true, }, production: { basePath: '/', @@ -67,6 +67,6 @@ export default { nextcloudName: 'TU Graz cloud', pdfAsQualifiedlySigningServer: 'https://sig.tugraz.at', hiddenActivities: ['dbp-signature-verification-full'], - enableAnnotations: false + enableAnnotations: false, }, -}; \ No newline at end of file +}; diff --git a/assets/manifest.json b/assets/manifest.json index 28b62f1..67847a7 100644 --- a/assets/manifest.json +++ b/assets/manifest.json @@ -1,56 +1,55 @@ { - "short_name": "TU Graz esign", - "name": "TU Graz Electronic Signature Service", - "start_url": "./", - "icons": [ - { - "src": "local/@dbp-topics/signature/icon-72x72.png", - "sizes": "72x72", - "type": "image/png" - }, - { - "src": "local/@dbp-topics/signature/icon-96x96.png", - "sizes": "96x96", - "type": "image/png" - }, - { - "src": "local/@dbp-topics/signature/icon-128x128.png", - "sizes": "128x128", - "type": "image/png" - }, - { - "src": "local/@dbp-topics/signature/icon-144x144.png", - "sizes": "144x144", - "type": "image/png" - }, - { - "src": "local/@dbp-topics/signature/icon-152x152.png", - "sizes": "152x152", - "type": "image/png" - }, - { - "src": "local/@dbp-topics/signature/icon-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "local/@dbp-topics/signature/icon-384x384.png", - "sizes": "384x384", - "type": "image/png" - }, - { - "src": "local/@dbp-topics/signature/icon-256x256.png", - "sizes": "256x256", - "type": "image/png" - }, - { - "src": "local/@dbp-topics/signature/icon-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "background_color": "#FEFEFE", - "display": "standalone", - "theme_color": "#FFFFFF" + "short_name": "TU Graz esign", + "name": "TU Graz Electronic Signature Service", + "start_url": "./", + "icons": [ + { + "src": "local/@dbp-topics/signature/icon-72x72.png", + "sizes": "72x72", + "type": "image/png" + }, + { + "src": "local/@dbp-topics/signature/icon-96x96.png", + "sizes": "96x96", + "type": "image/png" + }, + { + "src": "local/@dbp-topics/signature/icon-128x128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "local/@dbp-topics/signature/icon-144x144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "local/@dbp-topics/signature/icon-152x152.png", + "sizes": "152x152", + "type": "image/png" + }, + { + "src": "local/@dbp-topics/signature/icon-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "local/@dbp-topics/signature/icon-384x384.png", + "sizes": "384x384", + "type": "image/png" + }, + { + "src": "local/@dbp-topics/signature/icon-256x256.png", + "sizes": "256x256", + "type": "image/png" + }, + { + "src": "local/@dbp-topics/signature/icon-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "background_color": "#FEFEFE", + "display": "standalone", + "theme_color": "#FFFFFF" } - diff --git a/i18next-scanner.config.js b/i18next-scanner.config.js index d2338d3..895a82a 100644 --- a/i18next-scanner.config.js +++ b/i18next-scanner.config.js @@ -1,18 +1,16 @@ module.exports = { - input: [ - 'src/**/*.js', - ], + input: ['src/**/*.js'], output: './', options: { debug: false, removeUnusedKeys: true, - lngs: ['en','de'], + lngs: ['en', 'de'], func: { - list: ['i18n.t', '_i18n.t'] + list: ['i18n.t', '_i18n.t'], }, resource: { loadPath: 'src/i18n/{{lng}}/{{ns}}.json', - savePath: 'src/i18n/{{lng}}/{{ns}}.json' + savePath: 'src/i18n/{{lng}}/{{ns}}.json', }, }, -} +}; diff --git a/karma.conf.js b/karma.conf.js index 69fe685..4d47ec4 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,25 +1,25 @@ -module.exports = function(config) { - config.set({ - basePath: 'dist', - frameworks: ['mocha'], - client: { - mocha: { - ui: 'tdd', - }, - }, - files: [ - {pattern: './*.js', included: true, watched: true, served: true, type: 'module'}, - {pattern: './**/*', included: false, watched: true, served: true}, - ], - autoWatch: true, - browsers: ['ChromiumHeadlessNoSandbox', 'FirefoxHeadless'], - customLaunchers: { - ChromiumHeadlessNoSandbox: { - base: 'ChromiumHeadless', - flags: ['--no-sandbox'] - } - }, - singleRun: false, - logLevel: config.LOG_ERROR - }); -} +module.exports = function (config) { + config.set({ + basePath: 'dist', + frameworks: ['mocha'], + client: { + mocha: { + ui: 'tdd', + }, + }, + files: [ + {pattern: './*.js', included: true, watched: true, served: true, type: 'module'}, + {pattern: './**/*', included: false, watched: true, served: true}, + ], + autoWatch: true, + browsers: ['ChromiumHeadlessNoSandbox', 'FirefoxHeadless'], + customLaunchers: { + ChromiumHeadlessNoSandbox: { + base: 'ChromiumHeadless', + flags: ['--no-sandbox'], + }, + }, + singleRun: false, + logLevel: config.LOG_ERROR, + }); +}; diff --git a/package.json b/package.json index aa8954d..b85d528 100644 --- a/package.json +++ b/package.json @@ -1,79 +1,79 @@ { - "name": "@dbp-topics/signature", - "internalName": "dbp-signature", - "version": "1.0.26", - "main": "src/dbp-signature.js", - "license": "LGPL-2.1-or-later", - "repository": { - "type": "git", - "url": "https://gitlab.tugraz.at/dbp/esign/signature.git" - }, - "private": true, - "workspaces": [ - "vendor/toolkit/packages/*" - ], - "devDependencies": { - "@babel/core": "^7.10.3", - "@babel/preset-env": "^7.10.3", - "@rollup/plugin-babel": "^5.0.4", - "@rollup/plugin-commonjs": "^21.0.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^13.0.0", - "@rollup/plugin-url": "^6.0.0", - "can-npm-publish": "^1.3.3", - "chai": "^4.2.0", - "eslint": "^8.0.1", - "eslint-plugin-jsdoc": "^37.0.0", - "glob": "^7.1.6", - "i18next-scanner": "^3.0.0", - "karma": "^6.0.0", - "karma-chrome-launcher": "^3.1.0", - "karma-firefox-launcher": "^2.1.0", - "karma-mocha": "^2.0.1", - "mocha": "^9.0.0", - "prettier": "^2.5.1", - "rollup": "^2.18.1", - "rollup-plugin-copy": "^3.3.0", - "rollup-plugin-delete": "^2.0.0", - "rollup-plugin-emit-ejs": "^3.1.0", - "rollup-plugin-license": "^2.1.0", - "rollup-plugin-serve": "^1.0.1", - "rollup-plugin-terser": "^7.0.2", - "selfsigned": "^2.0.0" - }, - "dependencies": { - "@dbp-toolkit/app-shell": "^0.2.0", - "@dbp-toolkit/auth": "^0.2.0", - "@dbp-toolkit/common": "^0.2.0", - "@dbp-toolkit/file-handling": "^0.2.0", - "@dbp-toolkit/font-source-sans-pro": "^0.2.0", - "@dbp-toolkit/language-select": "^0.2.0", - "@dbp-toolkit/notification": "^0.2.0", - "@dbp-toolkit/organization-select": "^0.2.0", - "@dbp-toolkit/person-profile": "^0.2.0", - "@digital-blueprint/annotpdf": "^1.0.13-a", - "@open-wc/scoped-elements": "^2.0.0", - "fabric": "^4.2.0", - "file-saver": "^2.0.2", - "i18next": "^21.4.2", - "jszip": "^3.5.0", - "lit": "^2.0.0", - "pdfjs-dist": "^2.12.313", - "universal-router": "^9.0.1" - }, - "scripts": { - "format": "yarn run format:eslint && yarn run format:prettier", - "format:eslint": "eslint \"**/*.{js,ts}\" --fix", - "format:prettier": "prettier \"**/*.{js,json,ts}\" --write", - "build": "rollup -c", - "i18next": "i18next-scanner", - "watch": "rollup -c --watch", - "watch-local": "yarn run watch", - "watch-full": "rollup -c --watch --environment FORCE_FULL", - "watch-bs": "rollup -c --watch --environment APP_ENV:bs", - "test": "rollup -c --environment APP_ENV:test && karma start --singleRun", - "test-full": "rollup -c --environment FORCE_FULL,APP_ENV:test && karma start --singleRun", - "lint": "eslint .", - "publish": "sed -i 's/\"private\": true/\"private\": false/' package.json && can-npm-publish --verbose 2>&1 && npm publish --access public 2>&1; sed -i 's/\"private\": false/\"private\": true/' package.json" - } + "name": "@dbp-topics/signature", + "internalName": "dbp-signature", + "version": "1.0.26", + "main": "src/dbp-signature.js", + "license": "LGPL-2.1-or-later", + "repository": { + "type": "git", + "url": "https://gitlab.tugraz.at/dbp/esign/signature.git" + }, + "private": true, + "workspaces": [ + "vendor/toolkit/packages/*" + ], + "devDependencies": { + "@babel/core": "^7.10.3", + "@babel/preset-env": "^7.10.3", + "@rollup/plugin-babel": "^5.0.4", + "@rollup/plugin-commonjs": "^21.0.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^13.0.0", + "@rollup/plugin-url": "^6.0.0", + "can-npm-publish": "^1.3.3", + "chai": "^4.2.0", + "eslint": "^8.0.1", + "eslint-plugin-jsdoc": "^37.0.0", + "glob": "^7.1.6", + "i18next-scanner": "^3.0.0", + "karma": "^6.0.0", + "karma-chrome-launcher": "^3.1.0", + "karma-firefox-launcher": "^2.1.0", + "karma-mocha": "^2.0.1", + "mocha": "^9.0.0", + "prettier": "^2.5.1", + "rollup": "^2.18.1", + "rollup-plugin-copy": "^3.3.0", + "rollup-plugin-delete": "^2.0.0", + "rollup-plugin-emit-ejs": "^3.1.0", + "rollup-plugin-license": "^2.1.0", + "rollup-plugin-serve": "^1.0.1", + "rollup-plugin-terser": "^7.0.2", + "selfsigned": "^2.0.0" + }, + "dependencies": { + "@dbp-toolkit/app-shell": "^0.2.0", + "@dbp-toolkit/auth": "^0.2.0", + "@dbp-toolkit/common": "^0.2.0", + "@dbp-toolkit/file-handling": "^0.2.0", + "@dbp-toolkit/font-source-sans-pro": "^0.2.0", + "@dbp-toolkit/language-select": "^0.2.0", + "@dbp-toolkit/notification": "^0.2.0", + "@dbp-toolkit/organization-select": "^0.2.0", + "@dbp-toolkit/person-profile": "^0.2.0", + "@digital-blueprint/annotpdf": "^1.0.13-a", + "@open-wc/scoped-elements": "^2.0.0", + "fabric": "^4.2.0", + "file-saver": "^2.0.2", + "i18next": "^21.4.2", + "jszip": "^3.5.0", + "lit": "^2.0.0", + "pdfjs-dist": "^2.12.313", + "universal-router": "^9.0.1" + }, + "scripts": { + "format": "yarn run format:eslint && yarn run format:prettier", + "format:eslint": "eslint \"**/*.{js,ts}\" --fix", + "format:prettier": "prettier \"**/*.{js,json,ts}\" --write", + "build": "rollup -c", + "i18next": "i18next-scanner", + "watch": "rollup -c --watch", + "watch-local": "yarn run watch", + "watch-full": "rollup -c --watch --environment FORCE_FULL", + "watch-bs": "rollup -c --watch --environment APP_ENV:bs", + "test": "rollup -c --environment APP_ENV:test && karma start --singleRun", + "test-full": "rollup -c --environment FORCE_FULL,APP_ENV:test && karma start --singleRun", + "lint": "eslint .", + "publish": "sed -i 's/\"private\": true/\"private\": false/' package.json && can-npm-publish --verbose 2>&1 && npm publish --access public 2>&1; sed -i 's/\"private\": false/\"private\": true/' package.json" + } } diff --git a/rollup.config.js b/rollup.config.js index ceb158f..aea6a62 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -4,27 +4,32 @@ import glob from 'glob'; import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import copy from 'rollup-plugin-copy'; -import {terser} from "rollup-plugin-terser"; +import {terser} from 'rollup-plugin-terser'; import json from '@rollup/plugin-json'; import serve from 'rollup-plugin-serve'; -import urlPlugin from "@rollup/plugin-url"; +import urlPlugin from '@rollup/plugin-url'; import license from 'rollup-plugin-license'; import del from 'rollup-plugin-delete'; -import emitEJS from 'rollup-plugin-emit-ejs' +import emitEJS from 'rollup-plugin-emit-ejs'; import {getBabelOutputPlugin} from '@rollup/plugin-babel'; import appConfig from './app.config.js'; -import {getPackagePath, getBuildInfo, generateTLSConfig, getDistPath} from './vendor/toolkit/rollup.utils.js'; +import { + getPackagePath, + getBuildInfo, + generateTLSConfig, + getDistPath, +} from './vendor/toolkit/rollup.utils.js'; const pkg = require('./package.json'); -const appEnv = (typeof process.env.APP_ENV !== 'undefined') ? process.env.APP_ENV : 'local'; +const appEnv = typeof process.env.APP_ENV !== 'undefined' ? process.env.APP_ENV : 'local'; const watch = process.env.ROLLUP_WATCH === 'true'; -const buildFull = (!watch && appEnv !== 'test') || (process.env.FORCE_FULL !== undefined); +const buildFull = (!watch && appEnv !== 'test') || process.env.FORCE_FULL !== undefined; let useTerser = buildFull; let useBabel = buildFull; let checkLicenses = buildFull; let useHTTPS = false; -console.log("APP_ENV: " + appEnv); +console.log('APP_ENV: ' + appEnv); let config; if (appEnv in appConfig) { @@ -64,167 +69,205 @@ if (watch) { } function getOrigin(url) { - if (url) - return new URL(url).origin; + if (url) return new URL(url).origin; return ''; } config.CSP = `default-src 'self' 'unsafe-eval' 'unsafe-inline' \ -${getOrigin(config.matomoUrl)} ${getOrigin(config.keyCloakBaseURL)} ${getOrigin(config.entryPointURL)} \ +${getOrigin(config.matomoUrl)} ${getOrigin(config.keyCloakBaseURL)} ${getOrigin( + config.entryPointURL +)} \ httpbin.org ${getOrigin(config.nextcloudBaseURL)} www.handy-signatur.at \ ${getOrigin(config.pdfAsQualifiedlySigningServer)}; \ img-src * blob: data:; font-src 'self' data:`; export default (async () => { - let privatePath = await getDistPath(pkg.name) + let privatePath = await getDistPath(pkg.name); return { - input: (appEnv != 'test') ? [ - 'src/' + pkg.internalName + '.js', - 'src/dbp-official-signature-pdf-upload.js', - 'src/dbp-qualified-signature-pdf-upload.js', - 'src/dbp-signature-verification.js', - 'src/dbp-signature-verification-full.js', - ] : glob.sync('test/**/*.js'), - output: { - dir: 'dist', - entryFileNames: '[name].js', - chunkFileNames: 'shared/[name].[hash].[format].js', - format: 'esm', - sourcemap: true - }, - preserveEntrySignatures: false, - // external: ['zlib', 'http', 'fs', 'https', 'url'], - onwarn: function (warning, warn) { - // ignore chai warnings - if (warning.code === 'CIRCULAR_DEPENDENCY' && warning.message.includes('/chai/')) { - return; - } - // keycloak bundled code uses eval - if (warning.code === 'EVAL') { - return; - } - warn(warning); - }, - plugins: [ - del({ - targets: 'dist/*' - }), - emitEJS({ - src: 'assets', - include: ['**/*.ejs', '**/.*.ejs'], - data: { - getUrl: (p) => { - return url.resolve(config.basePath, p); - }, - getPrivateUrl: (p) => { - return url.resolve(`${config.basePath}${privatePath}/`, p); - }, - isVisible: (name) => { - return !config.hiddenActivities.includes(name); - }, - name: pkg.internalName, - entryPointURL: config.entryPointURL, - nextcloudWebAppPasswordURL: config.nextcloudWebAppPasswordURL, - nextcloudWebDavURL: config.nextcloudWebDavURL, - nextcloudBaseURL: config.nextcloudBaseURL, - nextcloudFileURL: config.nextcloudFileURL, - nextcloudName: config.nextcloudName, - keyCloakBaseURL: config.keyCloakBaseURL, - keyCloakClientId: config.keyCloakClientId, - keyCloakRealm: config.keyCloakRealm, - CSP: config.CSP, - matomoUrl: config.matomoUrl, - matomoSiteId: config.matomoSiteId, - buildInfo: getBuildInfo(appEnv), - enableAnnotations: config.enableAnnotations, - } - }), - resolve({ - // ignore node_modules from vendored packages - moduleDirectories: [path.join(process.cwd(), 'node_modules')], - browser: true, - preferBuiltins: true - }), - checkLicenses && license({ - banner: { - commentStyle: 'ignored', - content: ` + input: + appEnv != 'test' + ? [ + 'src/' + pkg.internalName + '.js', + 'src/dbp-official-signature-pdf-upload.js', + 'src/dbp-qualified-signature-pdf-upload.js', + 'src/dbp-signature-verification.js', + 'src/dbp-signature-verification-full.js', + ] + : glob.sync('test/**/*.js'), + output: { + dir: 'dist', + entryFileNames: '[name].js', + chunkFileNames: 'shared/[name].[hash].[format].js', + format: 'esm', + sourcemap: true, + }, + preserveEntrySignatures: false, + // external: ['zlib', 'http', 'fs', 'https', 'url'], + onwarn: function (warning, warn) { + // ignore chai warnings + if (warning.code === 'CIRCULAR_DEPENDENCY' && warning.message.includes('/chai/')) { + return; + } + // keycloak bundled code uses eval + if (warning.code === 'EVAL') { + return; + } + warn(warning); + }, + plugins: [ + del({ + targets: 'dist/*', + }), + emitEJS({ + src: 'assets', + include: ['**/*.ejs', '**/.*.ejs'], + data: { + getUrl: (p) => { + return url.resolve(config.basePath, p); + }, + getPrivateUrl: (p) => { + return url.resolve(`${config.basePath}${privatePath}/`, p); + }, + isVisible: (name) => { + return !config.hiddenActivities.includes(name); + }, + name: pkg.internalName, + entryPointURL: config.entryPointURL, + nextcloudWebAppPasswordURL: config.nextcloudWebAppPasswordURL, + nextcloudWebDavURL: config.nextcloudWebDavURL, + nextcloudBaseURL: config.nextcloudBaseURL, + nextcloudFileURL: config.nextcloudFileURL, + nextcloudName: config.nextcloudName, + keyCloakBaseURL: config.keyCloakBaseURL, + keyCloakClientId: config.keyCloakClientId, + keyCloakRealm: config.keyCloakRealm, + CSP: config.CSP, + matomoUrl: config.matomoUrl, + matomoSiteId: config.matomoSiteId, + buildInfo: getBuildInfo(appEnv), + enableAnnotations: config.enableAnnotations, + }, + }), + resolve({ + // ignore node_modules from vendored packages + moduleDirectories: [path.join(process.cwd(), 'node_modules')], + browser: true, + preferBuiltins: true, + }), + checkLicenses && + license({ + banner: { + commentStyle: 'ignored', + content: ` License: <%= pkg.license %> Dependencies: <% _.forEach(dependencies, function (dependency) { if (dependency.name) { %> <%= dependency.name %>: <%= dependency.license %><% }}) %> -`}, - thirdParty: { - allow: { - test: '(MIT OR BSD-3-Clause OR Apache-2.0 OR LGPL-2.1-or-later)', - failOnUnlicensed: true, - failOnViolation: true, - }, - }, - }), - commonjs({ - include: 'node_modules/**', - }), - json(), - urlPlugin({ - limit: 0, - include: [ - await getPackagePath('select2', '**/*.css'), - ], - emitFiles: true, - fileName: 'shared/[name].[hash][extname]' - }), - copy({ - targets: [ - {src: 'assets/*-placeholder.png', dest: 'dist/' + await getDistPath(pkg.name)}, - {src: 'assets/*.css', dest: 'dist/' + await getDistPath(pkg.name)}, - {src: 'assets/*.ico', dest: 'dist/' + await getDistPath(pkg.name)}, - {src: 'src/*.metadata.json', dest: 'dist'}, - {src: 'assets/*.svg', dest: 'dist/' + await getDistPath(pkg.name)}, - {src: 'assets/htaccess-shared', dest: 'dist/shared/', rename: '.htaccess'}, - {src: 'assets/icon-*.png', dest: 'dist/' + await getDistPath(pkg.name)}, - {src: 'assets/apple-*.png', dest: 'dist/' + await getDistPath(pkg.name)}, - {src: 'assets/safari-*.svg', dest: 'dist/' + await getDistPath(pkg.name)}, - {src: 'assets/images/*', dest: 'dist/images'}, - {src: 'assets/manifest.json', dest: 'dist', rename: pkg.internalName + '.manifest.json'}, - {src: 'assets/silent-check-sso.html', dest:'dist'}, - {src: 'assets/dbp-signature-maintenance.html', dest:'dist'}, - { - src: await getPackagePath('pdfjs-dist', 'legacy/build/pdf.worker.js'), - dest: 'dist/' + await getDistPath(pkg.name, 'pdfjs') - }, - {src: await getPackagePath('pdfjs-dist', 'cmaps/*'), dest: 'dist/' + await getDistPath(pkg.name, 'pdfjs')}, // do we want all map files? - {src: await getPackagePath('@dbp-toolkit/font-source-sans-pro', 'files/*'), dest: 'dist/' + await getDistPath(pkg.name, 'fonts/source-sans-pro')}, - {src: await getPackagePath('@dbp-toolkit/common', 'src/spinner.js'), dest: 'dist/' + await getDistPath(pkg.name)}, - {src: await getPackagePath('@dbp-toolkit/common', 'misc/browser-check.js'), dest: 'dist/' + await getDistPath(pkg.name)}, - {src: await getPackagePath('@dbp-toolkit/common', 'assets/icons/*.svg'), dest: 'dist/' + await getDistPath('@dbp-toolkit/common', 'icons')}, - {src: await getPackagePath('tabulator-tables', 'dist/css'), dest: 'dist/' + await getDistPath('@dbp-toolkit/file-handling', 'tabulator-tables')}, - ], - }), - useBabel && getBabelOutputPlugin({ - compact: false, - presets: [[ - '@babel/preset-env', { - loose: true, - shippedProposals: true, - bugfixes: true, - modules: false, - targets: { - esmodules: true - } - } - ]], - }), - useTerser ? terser() : false, - watch ? serve({ - contentBase: '.', - host: '127.0.0.1', - port: 8001, - historyApiFallback: config.basePath + pkg.internalName + '.html', - https: useHTTPS ? await generateTLSConfig() : false, - headers: { - 'Content-Security-Policy': config.CSP - }, - }) : false - ] -};})(); \ No newline at end of file +`, + }, + thirdParty: { + allow: { + test: '(MIT OR BSD-3-Clause OR Apache-2.0 OR LGPL-2.1-or-later)', + failOnUnlicensed: true, + failOnViolation: true, + }, + }, + }), + commonjs({ + include: 'node_modules/**', + }), + json(), + urlPlugin({ + limit: 0, + include: [await getPackagePath('select2', '**/*.css')], + emitFiles: true, + fileName: 'shared/[name].[hash][extname]', + }), + copy({ + targets: [ + { + src: 'assets/*-placeholder.png', + dest: 'dist/' + (await getDistPath(pkg.name)), + }, + {src: 'assets/*.css', dest: 'dist/' + (await getDistPath(pkg.name))}, + {src: 'assets/*.ico', dest: 'dist/' + (await getDistPath(pkg.name))}, + {src: 'src/*.metadata.json', dest: 'dist'}, + {src: 'assets/*.svg', dest: 'dist/' + (await getDistPath(pkg.name))}, + {src: 'assets/htaccess-shared', dest: 'dist/shared/', rename: '.htaccess'}, + {src: 'assets/icon-*.png', dest: 'dist/' + (await getDistPath(pkg.name))}, + {src: 'assets/apple-*.png', dest: 'dist/' + (await getDistPath(pkg.name))}, + {src: 'assets/safari-*.svg', dest: 'dist/' + (await getDistPath(pkg.name))}, + {src: 'assets/images/*', dest: 'dist/images'}, + { + src: 'assets/manifest.json', + dest: 'dist', + rename: pkg.internalName + '.manifest.json', + }, + {src: 'assets/silent-check-sso.html', dest: 'dist'}, + {src: 'assets/dbp-signature-maintenance.html', dest: 'dist'}, + { + src: await getPackagePath('pdfjs-dist', 'legacy/build/pdf.worker.js'), + dest: 'dist/' + (await getDistPath(pkg.name, 'pdfjs')), + }, + { + src: await getPackagePath('pdfjs-dist', 'cmaps/*'), + dest: 'dist/' + (await getDistPath(pkg.name, 'pdfjs')), + }, // do we want all map files? + { + src: await getPackagePath('@dbp-toolkit/font-source-sans-pro', 'files/*'), + dest: 'dist/' + (await getDistPath(pkg.name, 'fonts/source-sans-pro')), + }, + { + src: await getPackagePath('@dbp-toolkit/common', 'src/spinner.js'), + dest: 'dist/' + (await getDistPath(pkg.name)), + }, + { + src: await getPackagePath('@dbp-toolkit/common', 'misc/browser-check.js'), + dest: 'dist/' + (await getDistPath(pkg.name)), + }, + { + src: await getPackagePath('@dbp-toolkit/common', 'assets/icons/*.svg'), + dest: 'dist/' + (await getDistPath('@dbp-toolkit/common', 'icons')), + }, + { + src: await getPackagePath('tabulator-tables', 'dist/css'), + dest: + 'dist/' + + (await getDistPath('@dbp-toolkit/file-handling', 'tabulator-tables')), + }, + ], + }), + useBabel && + getBabelOutputPlugin({ + compact: false, + presets: [ + [ + '@babel/preset-env', + { + loose: true, + shippedProposals: true, + bugfixes: true, + modules: false, + targets: { + esmodules: true, + }, + }, + ], + ], + }), + useTerser ? terser() : false, + watch + ? serve({ + contentBase: '.', + host: '127.0.0.1', + port: 8001, + historyApiFallback: config.basePath + pkg.internalName + '.html', + https: useHTTPS ? await generateTLSConfig() : false, + headers: { + 'Content-Security-Policy': config.CSP, + }, + }) + : false, + ], + }; +})(); diff --git a/src/activity.js b/src/activity.js index b661ce5..9b3900c 100644 --- a/src/activity.js +++ b/src/activity.js @@ -12,4 +12,4 @@ export class Activity { let desc = this._data['description']; return desc[lang] ?? desc['en']; } -} \ No newline at end of file +} diff --git a/src/base-element.js b/src/base-element.js index 487063c..e30d172 100644 --- a/src/base-element.js +++ b/src/base-element.js @@ -9,16 +9,22 @@ export class BaseLitElement extends DBPLitElement { static get properties() { return { ...super.properties, - auth: { type: Object }, + auth: {type: Object}, }; } _(selector) { - return this.shadowRoot === null ? this.querySelector(selector) : this.shadowRoot.querySelector(selector); + return this.shadowRoot === null + ? this.querySelector(selector) + : this.shadowRoot.querySelector(selector); } _hasSignaturePermissions(roleName) { - return (this.auth.person && Array.isArray(this.auth.person.roles) && this.auth.person.roles.indexOf(roleName) !== -1); + return ( + this.auth.person && + Array.isArray(this.auth.person.roles) && + this.auth.person.roles.indexOf(roleName) !== -1 + ); } _updateAuth() { @@ -34,7 +40,7 @@ export class BaseLitElement extends DBPLitElement { update(changedProperties) { changedProperties.forEach((oldValue, propName) => { switch (propName) { - case "auth": + case 'auth': this._updateAuth(); break; } @@ -51,12 +57,11 @@ export class BaseLitElement extends DBPLitElement { } isLoggedIn() { - return (this.auth.person !== undefined && this.auth.person !== null); + return this.auth.person !== undefined && this.auth.person !== null; } isLoading() { - if (this._loginStatus === "logged-out") - return false; - return (!this.isLoggedIn() && this.auth.token !== undefined); + if (this._loginStatus === 'logged-out') return false; + return !this.isLoggedIn() && this.auth.token !== undefined; } } diff --git a/src/dbp-official-signature-pdf-upload.js b/src/dbp-official-signature-pdf-upload.js index e534994..f55b018 100644 --- a/src/dbp-official-signature-pdf-upload.js +++ b/src/dbp-official-signature-pdf-upload.js @@ -2,23 +2,23 @@ import {createInstance} from './i18n.js'; import {humanFileSize} from '@dbp-toolkit/common/i18next.js'; import {css, html} from 'lit'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; -import DBPSignatureLitElement from "./dbp-signature-lit-element"; -import {PdfPreview} from "./dbp-pdf-preview"; +import DBPSignatureLitElement from './dbp-signature-lit-element'; +import {PdfPreview} from './dbp-pdf-preview'; import * as commonUtils from '@dbp-toolkit/common/utils'; import * as utils from './utils'; import {Button, Icon, MiniSpinner} from '@dbp-toolkit/common'; import * as commonStyles from '@dbp-toolkit/common/styles'; import {classMap} from 'lit/directives/class-map.js'; import {FileSource} from '@dbp-toolkit/file-handling'; -import JSONLD from "@dbp-toolkit/common/jsonld"; +import JSONLD from '@dbp-toolkit/common/jsonld'; import {TextSwitch} from './textswitch.js'; -import {FileSink} from "@dbp-toolkit/file-handling"; +import {FileSink} from '@dbp-toolkit/file-handling'; import {name as pkgName} from './../package.json'; import {send as notify} from '@dbp-toolkit/common/notification'; -import {OrganizationSelect} from "@dbp-toolkit/organization-select"; +import {OrganizationSelect} from '@dbp-toolkit/organization-select'; import metadata from './dbp-official-signature-pdf-upload.metadata.json'; import {Activity} from './activity.js'; -import {PdfAnnotationView} from "./dbp-pdf-annotation-view"; +import {PdfAnnotationView} from './dbp-pdf-annotation-view'; import * as SignatureStyles from './styles'; class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElement) { @@ -27,21 +27,21 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem this._i18n = createInstance(); this.lang = this._i18n.language; this.entryPointUrl = ''; - this.nextcloudWebAppPasswordURL = ""; - this.nextcloudWebDavURL = ""; - this.nextcloudName = ""; - this.nextcloudFileURL = ""; - this.nextcloudAuthInfo = ""; + this.nextcloudWebAppPasswordURL = ''; + this.nextcloudWebDavURL = ''; + this.nextcloudName = ''; + this.nextcloudFileURL = ''; + this.nextcloudAuthInfo = ''; this.signedFiles = []; this.signedFilesCount = 0; this.signedFilesToDownload = 0; this.errorFiles = []; this.errorFilesCount = 0; - this.uploadStatusFileName = ""; - this.uploadStatusText = ""; + this.uploadStatusFileName = ''; + this.uploadStatusText = ''; this.currentFile = {}; - this.currentFileName = ""; - this.currentFilePlacementMode = ""; + this.currentFileName = ''; + this.currentFilePlacementMode = ''; this.currentFileSignaturePlacement = {}; this.signingProcessEnabled = false; this.signingProcessActive = false; @@ -60,65 +60,67 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem this.isAnnotationViewVisible = false; this.addAnnotationInProgress = false; this.activity = new Activity(metadata); - this.fileHandlingEnabledTargets = "local"; + this.fileHandlingEnabledTargets = 'local'; } static get scopedElements() { return { - 'dbp-icon': Icon, - 'dbp-file-source': FileSource, - 'dbp-file-sink': FileSink, - 'dbp-pdf-preview': PdfPreview, - 'dbp-mini-spinner': MiniSpinner, - 'dbp-button': Button, - 'dbp-textswitch': TextSwitch, - 'dbp-organization-select': OrganizationSelect, - 'dbp-pdf-annotation-view': PdfAnnotationView, + 'dbp-icon': Icon, + 'dbp-file-source': FileSource, + 'dbp-file-sink': FileSink, + 'dbp-pdf-preview': PdfPreview, + 'dbp-mini-spinner': MiniSpinner, + 'dbp-button': Button, + 'dbp-textswitch': TextSwitch, + 'dbp-organization-select': OrganizationSelect, + 'dbp-pdf-annotation-view': PdfAnnotationView, }; } static get properties() { return { ...super.properties, - lang: { type: String }, - entryPointUrl: { type: String, attribute: 'entry-point-url' }, - nextcloudWebAppPasswordURL: { type: String, attribute: 'nextcloud-web-app-password-url' }, - nextcloudWebDavURL: { type: String, attribute: 'nextcloud-webdav-url' }, - nextcloudName: { type: String, attribute: 'nextcloud-name' }, - nextcloudFileURL: { type: String, attribute: 'nextcloud-file-url' }, + lang: {type: String}, + entryPointUrl: {type: String, attribute: 'entry-point-url'}, + nextcloudWebAppPasswordURL: {type: String, attribute: 'nextcloud-web-app-password-url'}, + nextcloudWebDavURL: {type: String, attribute: 'nextcloud-webdav-url'}, + nextcloudName: {type: String, attribute: 'nextcloud-name'}, + nextcloudFileURL: {type: String, attribute: 'nextcloud-file-url'}, nextcloudAuthInfo: {type: String, attribute: 'nextcloud-auth-info'}, - signedFiles: { type: Array, attribute: false }, - signedFilesCount: { type: Number, attribute: false }, - signedFilesToDownload: { type: Number, attribute: false }, - queuedFilesCount: { type: Number, attribute: false }, - errorFiles: { type: Array, attribute: false }, - errorFilesCount: { type: Number, attribute: false }, - uploadInProgress: { type: Boolean, attribute: false }, - uploadStatusFileName: { type: String, attribute: false }, - uploadStatusText: { type: String, attribute: false }, - signingProcessEnabled: { type: Boolean, attribute: false }, - signingProcessActive: { type: Boolean, attribute: false }, - queueBlockEnabled: { type: Boolean, attribute: false }, - currentFile: { type: Object, attribute: false }, - currentFileName: { type: String, attribute: false }, - signaturePlacementInProgress: { type: Boolean, attribute: false }, - withSigBlock: { type: Boolean, attribute: false }, - isSignaturePlacement: { type: Boolean, attribute: false }, - allowAnnotating: { type: Boolean, attribute: 'allow-annotating' }, - isAnnotationViewVisible: { type: Boolean, attribute: false }, - queuedFilesAnnotations: { type: Array, attribute: false }, - queuedFilesAnnotationsCount: { type: Number, attribute: false }, - addAnnotationInProgress: { type: Boolean, attribute: false }, - queuedFilesAnnotationModes: { type: Array, attribute: false }, - queuedFilesAnnotationSaved: { type: Array, attribute: false }, - fileHandlingEnabledTargets: { type: String, attribute: 'file-handling-enabled-targets' }, + signedFiles: {type: Array, attribute: false}, + signedFilesCount: {type: Number, attribute: false}, + signedFilesToDownload: {type: Number, attribute: false}, + queuedFilesCount: {type: Number, attribute: false}, + errorFiles: {type: Array, attribute: false}, + errorFilesCount: {type: Number, attribute: false}, + uploadInProgress: {type: Boolean, attribute: false}, + uploadStatusFileName: {type: String, attribute: false}, + uploadStatusText: {type: String, attribute: false}, + signingProcessEnabled: {type: Boolean, attribute: false}, + signingProcessActive: {type: Boolean, attribute: false}, + queueBlockEnabled: {type: Boolean, attribute: false}, + currentFile: {type: Object, attribute: false}, + currentFileName: {type: String, attribute: false}, + signaturePlacementInProgress: {type: Boolean, attribute: false}, + withSigBlock: {type: Boolean, attribute: false}, + isSignaturePlacement: {type: Boolean, attribute: false}, + allowAnnotating: {type: Boolean, attribute: 'allow-annotating'}, + isAnnotationViewVisible: {type: Boolean, attribute: false}, + queuedFilesAnnotations: {type: Array, attribute: false}, + queuedFilesAnnotationsCount: {type: Number, attribute: false}, + addAnnotationInProgress: {type: Boolean, attribute: false}, + queuedFilesAnnotationModes: {type: Array, attribute: false}, + queuedFilesAnnotationSaved: {type: Array, attribute: false}, + fileHandlingEnabledTargets: {type: String, attribute: 'file-handling-enabled-targets'}, }; } connectedCallback() { super.connectedCallback(); // needs to be called in a function to get the variable scope of "this" - setInterval(() => { this.handleQueuedFiles(); }, 1000); + setInterval(() => { + this.handleQueuedFiles(); + }, 1000); } async queueFile(file) { @@ -151,9 +153,9 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem if (this.queuedFilesNeedsPlacement.get(key) && !isManual) { // Some have a signature but are not "manual", stop everything notify({ - "body": i18n.t('error-manual-positioning-missing'), - "type": "danger", - "timeout": 5, + body: i18n.t('error-manual-positioning-missing'), + type: 'danger', + timeout: 5, }); this.signingProcessEnabled = false; this.signingProcessActive = false; @@ -174,7 +176,7 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem let params = {}; // prepare parameters to tell PDF-AS where and how the signature should be placed - if (this.queuedFilesPlacementModes[key] === "manual") { + if (this.queuedFilesPlacementModes[key] === 'manual') { const data = this.queuedFilesSignaturePlacements[key]; if (data !== undefined) { params = utils.fabricjs2pdfasPosition(data); @@ -194,9 +196,6 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem this.uploadInProgress = false; } - - - /** * Decides if the "beforeunload" event needs to be canceled * @@ -228,7 +227,6 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem event.returnValue = ''; } - addToErrorFiles(file) { this.endSigningProcessIfQueueEmpty(); @@ -238,7 +236,10 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem this.errorFilesCount++; this.sendSetPropertyEvent('analytics-event', { - 'category': 'officiallySigning', 'action': 'SigningFailed', 'name': file.json["hydra:description"]}); + category: 'officiallySigning', + action: 'SigningFailed', + name: file.json['hydra:description'], + }); } /** @@ -247,7 +248,7 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem onFileUploadFinished(data) { if (data.status !== 201) { this.addToErrorFiles(data); - } else if (data.json["@type"] === "http://schema.org/MediaObject" ) { + } else if (data.json['@type'] === 'http://schema.org/MediaObject') { // this doesn't seem to trigger an update() execution this.signedFiles.push(data.json); // this triggers the correct update() execution @@ -256,23 +257,28 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem this.currentFileName = entryPoint.name; this.endSigningProcessIfQueueEmpty(); this.sendSetPropertyEvent('analytics-event', { - 'category': 'OfficialSigning', 'action': 'DocumentSigned', 'name': data.json.contentSize}); + category: 'OfficialSigning', + action: 'DocumentSigned', + name: data.json.contentSize, + }); } } update(changedProperties) { changedProperties.forEach((oldValue, propName) => { switch (propName) { - case "lang": + case 'lang': this._i18n.changeLanguage(this.lang); break; - case "entryPointUrl": + case 'entryPointUrl': JSONLD.getInstance(this.entryPointUrl).then((jsonld) => { let apiUrlBase; try { - apiUrlBase = jsonld.getApiUrlForEntityName("EsignAdvancedlySignedDocument"); + apiUrlBase = jsonld.getApiUrlForEntityName( + 'EsignAdvancedlySignedDocument' + ); } catch (error) { - apiUrlBase = jsonld.getApiUrlForEntityName("AdvancedlySignedDocument"); + apiUrlBase = jsonld.getApiUrlForEntityName('AdvancedlySignedDocument'); } this.fileSourceUrl = apiUrlBase; }); @@ -290,7 +296,7 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem } async stopSigningProcess() { - console.log("stop"); + console.log('stop'); this.signingProcessEnabled = false; this.signingProcessActive = false; @@ -303,8 +309,6 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem } } - - static get styles() { // language=css return css` @@ -334,44 +338,67 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem results.push(html` <div class="file-block"> <div class="header"> - <span class="filename"><strong>${file.name}</strong> (${humanFileSize(file.size)})</span> - <button class="button close" + <span class="filename"> + <strong>${file.name}</strong> + (${humanFileSize(file.size)}) + </span> + <button + class="button close" ?disabled="${this.signingProcessEnabled}" title="${i18n.t('official-pdf-upload.remove-queued-file-button-title')}" - @click="${() => { this.takeFileFromQueue(id); }}"> - <dbp-icon name="trash"></dbp-icon></button> + @click="${() => { + this.takeFileFromQueue(id); + }}"> + <dbp-icon name="trash"></dbp-icon> + </button> </div> <div class="bottom-line"> <div></div> - <button class="button" + <button + class="button" ?disabled="${this.signingProcessEnabled}" - @click="${() => { this.showPreview(id); }}">${i18n.t('official-pdf-upload.show-preview')}</button> + @click="${() => { + this.showPreview(id); + }}"> + ${i18n.t('official-pdf-upload.show-preview')} + </button> <span class="headline">${i18n.t('official-pdf-upload.positioning')}:</span> - <dbp-textswitch name1="auto" + <dbp-textswitch + name1="auto" name2="manual" - name="${this.queuedFilesPlacementModes[id] || "auto"}" - class="${classMap({'placement-missing': placementMissing, 'switch': true})}" + name="${this.queuedFilesPlacementModes[id] || 'auto'}" + class="${classMap({ + 'placement-missing': placementMissing, + switch: true, + })}" value1="${i18n.t('official-pdf-upload.positioning-automatic')}" value2="${i18n.t('official-pdf-upload.positioning-manual')}" ?disabled="${this.signingProcessEnabled}" - @change=${ (e) => this.queuePlacementSwitch(id, e.target.name) }></dbp-textswitch> - <span class="headline ${classMap({hidden: !this.allowAnnotating})}">${i18n.t('official-pdf-upload.annotation')}:</span> + @change=${(e) => + this.queuePlacementSwitch(id, e.target.name)}></dbp-textswitch> + <span class="headline ${classMap({hidden: !this.allowAnnotating})}"> + ${i18n.t('official-pdf-upload.annotation')}: + </span> <div class="${classMap({hidden: !this.allowAnnotating})}"> - <dbp-textswitch id="annotation-switch" + <dbp-textswitch + id="annotation-switch" name1="no-text" name2="text-selected" - name="${this.queuedFilesAnnotationModes[id] || "no-text"}" - class="${classMap({'switch': true})}" + name="${this.queuedFilesAnnotationModes[id] || 'no-text'}" + class="${classMap({switch: true})}" value1="${i18n.t('official-pdf-upload.annotation-no')}" value2="${i18n.t('official-pdf-upload.annotation-yes')}" ?disabled="${this.signingProcessEnabled}" - @change=${ (e) => this.showAnnotationView(id, e.target.name) }></dbp-textswitch> + @change=${(e) => + this.showAnnotationView(id, e.target.name)}></dbp-textswitch> </div> </div> <div class="error-line"> - ${ placementMissing ? html` - ${i18n.t('label-manual-positioning-missing')} - ` : '' } + ${placementMissing + ? html` + ${i18n.t('label-manual-positioning-missing')} + ` + : ''} </div> </div> `); @@ -396,11 +423,18 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem results.push(html` <div class="file-block" id="file-block-${id}"> <div class="header"> - <span class="filename"><span class="bold-filename">${file.name}</span> (${humanFileSize(file.contentSize)})</span> - <button class="button close" + <span class="filename"> + <span class="bold-filename">${file.name}</span> + (${humanFileSize(file.contentSize)}) + </span> + <button + class="button close" title="${i18n.t('official-pdf-upload.download-file-button-title')}" - @click="${() => { this.downloadFileClickHandler(file, 'file-block-' + id); }}"> - <dbp-icon name="download"></dbp-icon></button> + @click="${() => { + this.downloadFileClickHandler(file, 'file-block-' + id); + }}"> + <dbp-icon name="download"></dbp-icon> + </button> </div> </div> `); @@ -429,19 +463,33 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem results.push(html` <div class="file-block error"> <div class="header"> - <span class="filename"><strong>${data.file.name}</strong> (${humanFileSize(data.file.size)})</span> + <span class="filename"> + <strong>${data.file.name}</strong> + (${humanFileSize(data.file.size)}) + </span> <div class="buttons"> - <button class="button" - title="${i18n.t('official-pdf-upload.re-upload-file-button-title')}" - @click="${() => {this.fileQueueingClickHandler(data.file, id);}}"><dbp-icon name="reload"></dbp-icon></button> - <button class="button" - title="${i18n.t('official-pdf-upload.remove-failed-file-button-title')}" - @click="${() => { this.takeFailedFileFromQueue(id); }}"> - <dbp-icon name="trash"></dbp-icon></button> + <button + class="button" + title="${i18n.t('official-pdf-upload.re-upload-file-button-title')}" + @click="${() => { + this.fileQueueingClickHandler(data.file, id); + }}"> + <dbp-icon name="reload"></dbp-icon> + </button> + <button + class="button" + title="${i18n.t( + 'official-pdf-upload.remove-failed-file-button-title' + )}" + @click="${() => { + this.takeFailedFileFromQueue(id); + }}"> + <dbp-icon name="trash"></dbp-icon> + </button> </div> </div> <div class="bottom-line"> - <strong class="error">${data.json["hydra:description"]}</strong> + <strong class="error">${data.json['hydra:description']}</strong> </div> </div> `); @@ -455,24 +503,29 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem } render() { - const placeholderUrl = commonUtils.getAssetURL(pkgName, 'official-signature-placeholder.png'); + const placeholderUrl = commonUtils.getAssetURL( + pkgName, + 'official-signature-placeholder.png' + ); const i18n = this._i18n; return html` - <div class="${classMap({hidden: !this.isLoggedIn() || !this.hasSignaturePermissions() || this.isLoading()})}"> + <div + class="${classMap({ + hidden: + !this.isLoggedIn() || !this.hasSignaturePermissions() || this.isLoading(), + })}"> <div class="field"> <h2>${this.activity.getName(this.lang)}</h2> - <p class="subheadline"> - ${this.activity.getDescription(this.lang)} - </p> + <p class="subheadline">${this.activity.getDescription(this.lang)}</p> <div class="control"> - - <p> - ${i18n.t('official-pdf-upload.upload-text')} - </p> - <button @click="${() => { this._("#file-source").setAttribute("dialog-open", ""); }}" - ?disabled="${this.signingProcessActive}" - class="button is-primary"> + <p>${i18n.t('official-pdf-upload.upload-text')}</p> + <button + @click="${() => { + this._('#file-source').setAttribute('dialog-open', ''); + }}" + ?disabled="${this.signingProcessActive}" + class="button is-primary"> ${i18n.t('official-pdf-upload.upload-button-label')} </button> <dbp-file-source @@ -492,132 +545,200 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem text="${i18n.t('official-pdf-upload.upload-area-text')}" button-label="${i18n.t('official-pdf-upload.upload-button-label')}" @dbp-file-source-file-selected="${this.onFileSelected}" - @dbp-file-source-switched="${this.onFileSourceSwitch}" - ></dbp-file-source> + @dbp-file-source-switched="${this + .onFileSourceSwitch}"></dbp-file-source> </div> </div> <div id="grid-container"> <div class="left-container"> - <div class="files-block field ${classMap({hidden: !this.queueBlockEnabled})}"> + <div + class="files-block field ${classMap({ + hidden: !this.queueBlockEnabled, + })}"> <!-- Queued files headline and queueing spinner --> - <h3 class="${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <h3 + class="${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${i18n.t('official-pdf-upload.queued-files-label')} </h3> <!-- Buttons to start/stop signing process and clear queue --> <div class="control field"> - <button @click="${this.clearQueuedFiles}" - ?disabled="${this.queuedFilesCount === 0 || this.signingProcessActive || this.isUserInterfaceDisabled()}" - class="button ${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <button + @click="${this.clearQueuedFiles}" + ?disabled="${this.queuedFilesCount === 0 || + this.signingProcessActive || + this.isUserInterfaceDisabled()}" + class="button ${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${i18n.t('official-pdf-upload.clear-all')} </button> - <button @click="${() => { this.signingProcessEnabled = true; this.signingProcessActive = true; }}" - ?disabled="${this.queuedFilesCount === 0}" - class="button is-right is-primary ${classMap( - { - "is-disabled": this.isUserInterfaceDisabled(), - hidden: this.signingProcessActive - })}"> + <button + @click="${() => { + this.signingProcessEnabled = true; + this.signingProcessActive = true; + }}" + ?disabled="${this.queuedFilesCount === 0}" + class="button is-right is-primary ${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + hidden: this.signingProcessActive, + })}"> ${i18n.t('official-pdf-upload.start-signing-process-button')} </button> <!-- --> - <button @click="${this.stopSigningProcess}" - id="cancel-signing-process" - class="button is-right ${classMap({hidden: !this.signingProcessActive})}"> + <button + @click="${this.stopSigningProcess}" + id="cancel-signing-process" + class="button is-right ${classMap({ + hidden: !this.signingProcessActive, + })}"> ${i18n.t('official-pdf-upload.stop-signing-process-button')} </button> <!-- --> </div> <!-- List of queued files --> - <div class="control file-list ${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="control file-list ${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${this.getQueuedFilesHtml()} </div> <!-- Text "queue empty" --> - <div class="empty-queue control ${classMap({hidden: this.queuedFilesCount !== 0, "is-disabled": this.isUserInterfaceDisabled()})}"> - ${i18n.t('official-pdf-upload.queued-files-empty1')}<br /> + <div + class="empty-queue control ${classMap({ + hidden: this.queuedFilesCount !== 0, + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> + ${i18n.t('official-pdf-upload.queued-files-empty1')} + <br /> ${i18n.t('official-pdf-upload.queued-files-empty2')} </div> </div> <!-- List of signed PDFs --> - <div class="files-block field ${classMap({hidden: this.signedFilesCount === 0, "is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="files-block field ${classMap({ + hidden: this.signedFilesCount === 0, + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> <h3>${i18n.t('official-pdf-upload.signed-files-label')}</h3> <!-- Button to download all signed PDFs --> <div class="field ${classMap({hidden: this.signedFilesCount === 0})}"> <div class="control"> - <button @click="${this.clearSignedFiles}" - class="button"> + <button @click="${this.clearSignedFiles}" class="button"> ${i18n.t('official-pdf-upload.clear-all')} </button> - <dbp-button id="zip-download-button" - value="${i18n.t('official-pdf-upload.download-zip-button')}" - title="${i18n.t('official-pdf-upload.download-zip-button-tooltip')}" - class="is-right" - @click="${this.zipDownloadClickHandler}" - type="is-primary"></dbp-button> + <dbp-button + id="zip-download-button" + value="${i18n.t('official-pdf-upload.download-zip-button')}" + title="${i18n.t( + 'official-pdf-upload.download-zip-button-tooltip' + )}" + class="is-right" + @click="${this.zipDownloadClickHandler}" + type="is-primary"></dbp-button> </div> </div> - <div class="control"> - ${this.getSignedFilesHtml()} - </div> + <div class="control">${this.getSignedFilesHtml()}</div> </div> <!-- List of errored files --> - <div class="files-block error-files field ${classMap({hidden: this.errorFilesCount === 0, "is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="files-block error-files field ${classMap({ + hidden: this.errorFilesCount === 0, + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> <h3>${i18n.t('official-pdf-upload.error-files-label')}</h3> <!-- Button to upload errored files again --> <div class="field ${classMap({hidden: this.errorFilesCount === 0})}"> <div class="control"> - <button @click="${this.clearErrorFiles}" - class="button"> + <button @click="${this.clearErrorFiles}" class="button"> ${i18n.t('official-pdf-upload.clear-all')} </button> - <dbp-button id="re-upload-all-button" - ?disabled="${this.uploadInProgress}" - value="${i18n.t('official-pdf-upload.re-upload-all-button')}" - title="${i18n.t('official-pdf-upload.re-upload-all-button-title')}" - class="is-right" - @click="${this.reUploadAllClickHandler}" - type="is-primary"></dbp-button> + <dbp-button + id="re-upload-all-button" + ?disabled="${this.uploadInProgress}" + value="${i18n.t( + 'official-pdf-upload.re-upload-all-button' + )}" + title="${i18n.t( + 'official-pdf-upload.re-upload-all-button-title' + )}" + class="is-right" + @click="${this.reUploadAllClickHandler}" + type="is-primary"></dbp-button> </div> </div> - <div class="control"> - ${this.getErrorFilesHtml()} - </div> + <div class="control">${this.getErrorFilesHtml()}</div> </div> </div> <div class="right-container"> <!-- PDF preview --> - <div id="pdf-preview" class="field ${classMap({hidden: !this.signaturePlacementInProgress})}"> - <h3>${this.withSigBlock ? i18n.t('official-pdf-upload.signature-placement-label') : i18n.t('official-pdf-upload.preview-label')}</h3> + <div + id="pdf-preview" + class="field ${classMap({hidden: !this.signaturePlacementInProgress})}"> + <h3> + ${this.withSigBlock + ? i18n.t('official-pdf-upload.signature-placement-label') + : i18n.t('official-pdf-upload.preview-label')} + </h3> <div class="box-header"> <div class="filename"> - <strong>${this.currentFile.name}</strong> (${humanFileSize(this.currentFile !== undefined ? this.currentFile.size : 0)}) + <strong>${this.currentFile.name}</strong> + (${humanFileSize( + this.currentFile !== undefined ? this.currentFile.size : 0 + )}) </div> - <button class="button is-cancel" - @click="${this.hidePDF}"><dbp-icon name="close"></dbp-icon></button> + <button class="button is-cancel" @click="${this.hidePDF}"> + <dbp-icon name="close"></dbp-icon> + </button> </div> - <dbp-pdf-preview lang="${this.lang}" - allow-signature-rotation - signature-placeholder-image-src="${placeholderUrl}" - signature-width="162" - signature-height="28" - @dbp-pdf-preview-accept="${this.storePDFData}" - @dbp-pdf-preview-cancel="${this.hidePDF}"></dbp-pdf-preview> + <dbp-pdf-preview + lang="${this.lang}" + allow-signature-rotation + signature-placeholder-image-src="${placeholderUrl}" + signature-width="162" + signature-height="28" + @dbp-pdf-preview-accept="${this.storePDFData}" + @dbp-pdf-preview-cancel="${this.hidePDF}"></dbp-pdf-preview> </div> <!-- Annotation view --> - <div id="annotation-view" class="field ${classMap({hidden: !this.isAnnotationViewVisible || !this.allowAnnotating})}"> + <div + id="annotation-view" + class="field ${classMap({ + hidden: !this.isAnnotationViewVisible || !this.allowAnnotating, + })}"> <h2>${i18n.t('official-pdf-upload.annotation-view-label')}</h2> <div class="box-header"> <div class="filename"> - <strong>${this.currentFile.file !== undefined ? this.currentFile.file.name : ''}</strong> (${humanFileSize(this.currentFile.file !== undefined ? this.currentFile.file.size : 0)}) + <strong> + ${this.currentFile.file !== undefined + ? this.currentFile.file.name + : ''} + </strong> + (${humanFileSize( + this.currentFile.file !== undefined + ? this.currentFile.file.size + : 0 + )}) </div> - <button class="button is-cancel annotation" - @click="${this.hideAnnotationView}"><dbp-icon name="close" id="close-icon"></dbp-icon></button> + <button + class="button is-cancel annotation" + @click="${this.hideAnnotationView}"> + <dbp-icon name="close" id="close-icon"></dbp-icon> + </button> </div> - <dbp-pdf-annotation-view lang="${this.lang}" - @dbp-pdf-annotations-save="${this.processAnnotationEvent}" - @dbp-pdf-annotations-cancel="${this.processAnnotationCancelEvent}"></dbp-pdf-annotation-view> + <dbp-pdf-annotation-view + lang="${this.lang}" + @dbp-pdf-annotations-save="${this.processAnnotationEvent}" + @dbp-pdf-annotations-cancel="${this + .processAnnotationCancelEvent}"></dbp-pdf-annotation-view> </div> <!-- File upload progress --> - <div id="upload-progress" class="field notification is-info ${classMap({hidden: !this.uploadInProgress})}"> + <div + id="upload-progress" + class="field notification is-info ${classMap({ + hidden: !this.uploadInProgress, + })}"> <dbp-mini-spinner></dbp-mini-spinner> <strong>${this.uploadStatusFileName}</strong> ${this.uploadStatusText} @@ -625,17 +746,27 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem </div> </div> </div> - <div class="notification is-warning ${classMap({hidden: this.isLoggedIn() || this.isLoading()})}"> + <div + class="notification is-warning ${classMap({ + hidden: this.isLoggedIn() || this.isLoading(), + })}"> ${i18n.t('error-login-message')} </div> - <div class="notification is-danger ${classMap({hidden: this.hasSignaturePermissions() || !this.isLoggedIn() || this.isLoading()})}"> + <div + class="notification is-danger ${classMap({ + hidden: + this.hasSignaturePermissions() || !this.isLoggedIn() || this.isLoading(), + })}"> ${i18n.t('error-permission-message')} </div> <div class="${classMap({hidden: !this.isLoading()})}"> <dbp-mini-spinner></dbp-mini-spinner> </div> - <dbp-file-sink id="file-sink" - context="${i18n.t('qualified-pdf-upload.save-field-label', {count: this.signedFilesToDownload})}" + <dbp-file-sink + id="file-sink" + context="${i18n.t('qualified-pdf-upload.save-field-label', { + count: this.signedFilesToDownload, + })}" filename="signed-documents.zip" subscribe="initial-file-handling-state:initial-file-handling-state,clipboard-files:clipboard-files" enabled-targets="${this.fileHandlingEnabledTargets}" @@ -643,8 +774,7 @@ class OfficialSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElem nextcloud-web-dav-url="${this.nextcloudWebDavURL}" nextcloud-name="${this.nextcloudName}" nextcloud-file-url="${this.nextcloudFileURL}" - lang="${this.lang}" - ></dbp-file-sink> + lang="${this.lang}"></dbp-file-sink> `; } } diff --git a/src/dbp-official-signature-pdf-upload.metadata.json b/src/dbp-official-signature-pdf-upload.metadata.json index 70d177e..af84d67 100644 --- a/src/dbp-official-signature-pdf-upload.metadata.json +++ b/src/dbp-official-signature-pdf-upload.metadata.json @@ -1,19 +1,19 @@ { - "element": "dbp-official-signature-pdf-upload", - "module_src": "dbp-official-signature-pdf-upload.js", - "routing_name": "official-pdf-upload", - "name": { - "de": "Dokumente amtssignieren", - "en": "Officially sign documents" - }, - "short_name": { - "de": "Dokumente amtssignieren", - "en": "Officially sign documents" - }, - "description": { - "de": "Erlaubt das Hochladen von PDF-Dokumenten, um sie mit einer Amtssignatur zu versehen", - "en": "Allows upload of PDF-documents to officially sign them" - }, - "subscribe": "lang,entry-point-url,nextcloud-web-app-password-url,nextcloud-webdav-url,nextcloud-name,nextcloud-auth-info,nextcloud-file-url,auth,allow-annotating,file-handling-enabled-targets", - "required_roles": ["ROLE_SCOPE_OFFICIAL-SIGNATURE"] + "element": "dbp-official-signature-pdf-upload", + "module_src": "dbp-official-signature-pdf-upload.js", + "routing_name": "official-pdf-upload", + "name": { + "de": "Dokumente amtssignieren", + "en": "Officially sign documents" + }, + "short_name": { + "de": "Dokumente amtssignieren", + "en": "Officially sign documents" + }, + "description": { + "de": "Erlaubt das Hochladen von PDF-Dokumenten, um sie mit einer Amtssignatur zu versehen", + "en": "Allows upload of PDF-documents to officially sign them" + }, + "subscribe": "lang,entry-point-url,nextcloud-web-app-password-url,nextcloud-webdav-url,nextcloud-name,nextcloud-auth-info,nextcloud-file-url,auth,allow-annotating,file-handling-enabled-targets", + "required_roles": ["ROLE_SCOPE_OFFICIAL-SIGNATURE"] } diff --git a/src/dbp-pdf-annotation-view.js b/src/dbp-pdf-annotation-view.js index 93e55bb..edc199a 100644 --- a/src/dbp-pdf-annotation-view.js +++ b/src/dbp-pdf-annotation-view.js @@ -4,8 +4,8 @@ import {classMap} from 'lit/directives/class-map.js'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import DBPLitElement from '@dbp-toolkit/common/dbp-lit-element'; import {MiniSpinner, Icon} from '@dbp-toolkit/common'; -import {OrganizationSelect} from "@dbp-toolkit/organization-select"; -import { send } from '@dbp-toolkit/common/notification'; +import {OrganizationSelect} from '@dbp-toolkit/organization-select'; +import {send} from '@dbp-toolkit/common/notification'; import * as commonStyles from '@dbp-toolkit/common/styles'; import * as utils from './utils'; @@ -38,24 +38,24 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { static get properties() { return { ...super.properties, - lang: { type: String }, - key: { type: Number }, - isTextHidden: { type: Boolean, attribute: false }, - isSelected: { type: Boolean, attribute: false }, - annotationRows: { type: Array, attribute: false }, - queuedFilesAnnotationsCount: { type: Number, attribute: false }, + lang: {type: String}, + key: {type: Number}, + isTextHidden: {type: Boolean, attribute: false}, + isSelected: {type: Boolean, attribute: false}, + annotationRows: {type: Array, attribute: false}, + queuedFilesAnnotationsCount: {type: Number, attribute: false}, }; } update(changedProperties) { changedProperties.forEach((oldValue, propName) => { switch (propName) { - case "lang": + case 'lang': this._i18n.changeLanguage(this.lang); break; } }); - + super.update(changedProperties); } @@ -67,7 +67,7 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { } /** - * Deletes all fields and restore introduction text + * Deletes all fields and restore introduction text */ deleteAll() { this.annotationRows = []; @@ -77,8 +77,11 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { sendCancelEvent() { console.log('cancel event called'); - const event = new CustomEvent("dbp-pdf-annotations-cancel", - { "detail": {}, bubbles: true, composed: true }); + const event = new CustomEvent('dbp-pdf-annotations-cancel', { + detail: {}, + bubbles: true, + composed: true, + }); this.dispatchEvent(event); } @@ -90,12 +93,16 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { if (annotationTypeData['hasOrganization']) { let organization = annotation.organizationValue; - if (typeof organization === 'undefined' || organization === null || organization === '') { + if ( + typeof organization === 'undefined' || + organization === null || + organization === '' + ) { send({ - "summary": i18n.t('annotation-view.empty-organization-title'), - "body": i18n.t('annotation-view.empty-organization-message'), - "type": "danger", - "timeout": 5, + summary: i18n.t('annotation-view.empty-organization-title'), + body: i18n.t('annotation-view.empty-organization-message'), + type: 'danger', + timeout: 5, }); return false; } @@ -103,10 +110,12 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { if (annotation['value'] === null || annotation['value'] === '') { send({ - "summary": i18n.t('annotation-view.empty-annotation-title', {annotationType: annotationTypeData.name[this.lang]}), - "body": i18n.t('annotation-view.empty-annotation-message'), - "type": "danger", - "timeout": 5, + summary: i18n.t('annotation-view.empty-annotation-title', { + annotationType: annotationTypeData.name[this.lang], + }), + body: i18n.t('annotation-view.empty-annotation-message'), + type: 'danger', + timeout: 5, }); return false; } @@ -114,12 +123,15 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { const pattern = new RegExp('[A-Za-z0-9ÄäÖöÜüß*\\/?! &@()=+_-]*'); let matchResult = annotation['value'].match(pattern); - if (matchResult[0] === undefined || annotation['value'].length !== matchResult[0].length) { + if ( + matchResult[0] === undefined || + annotation['value'].length !== matchResult[0].length + ) { send({ - "summary": i18n.t('annotation-view.invalid-annotation-text-title'), - "body": i18n.t('annotation-view.invalid-annotation-text-message'), - "type": "danger", - "timeout": 5, + summary: i18n.t('annotation-view.invalid-annotation-text-title'), + body: i18n.t('annotation-view.invalid-annotation-text-message'), + type: 'danger', + timeout: 5, }); return false; } @@ -134,13 +146,16 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { if (!this.validateValues()) { return; } - + const data = { - "key": this.key, - "annotationRows": this.annotationRows, + key: this.key, + annotationRows: this.annotationRows, }; - const event = new CustomEvent("dbp-pdf-annotations-save", - { "detail": data, bubbles: true, composed: true }); + const event = new CustomEvent('dbp-pdf-annotations-save', { + detail: data, + bubbles: true, + composed: true, + }); this.dispatchEvent(event); if (this.annotationRows.length === 0) { @@ -160,7 +175,7 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { let e = this._('#additional-select'); let type = e?.options[e?.selectedIndex]?.value; - this.annotationRows.push({'annotationType': type, 'value': ''}); + this.annotationRows.push({annotationType: type, value: ''}); // we just need this so the UI will update this.queuedFilesAnnotationsCount++; @@ -193,7 +208,7 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { // delete this.annotationRows[id]; //length of array doesn't change this.annotationRows.splice(id, 1); - if(this.annotationRows.length === 0) { + if (this.annotationRows.length === 0) { this.isTextHidden = false; this.sendCancelEvent(); } @@ -218,10 +233,10 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { div.annotation-block { display: grid; - row-gap: .3em; + row-gap: 0.3em; align-items: center; - + margin-left: 2px; margin-right: 2px; } @@ -233,7 +248,7 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { .border { border-top: var(--dbp-border-dark); - padding-bottom: .5em; + padding-bottom: 0.5em; } .border-wrapper { border: var(--dbp-border-dark); @@ -260,7 +275,7 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { } .delete-elements .button { - margin-left: .5em; + margin-left: 0.5em; } select:not(.select) { @@ -314,9 +329,7 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { } /* Handling for small displays (like mobile devices) */ - @media only screen - and (orientation: portrait) - and (max-width: 768px) { + @media only screen and (orientation: portrait) and (max-width: 768px) { .nav-buttons { flex-direction: column; } @@ -326,7 +339,6 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { grid-template-columns: auto 42px; column-gap: 3px; } - } `; } @@ -337,43 +349,64 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { * @returns {*[]} Array of html templates */ getAnnotationsHtml() { - const i18n = this._i18n; - const annotations = this.annotationRows || []; - const ids = Object.keys(annotations); - let results = []; + const i18n = this._i18n; + const annotations = this.annotationRows || []; + const ids = Object.keys(annotations); + let results = []; - ids.forEach((id) => { + ids.forEach((id) => { const data = this.annotationRows[id] || []; const annotationTypeData = utils.getAnnotationTypes(data.annotationType); const name = annotationTypeData.name[this.lang]; results.push(html` - <div class="${classMap({'with-organization': annotationTypeData.hasOrganization, 'annotation-block': true})}"> + <div + class="${classMap({ + 'with-organization': annotationTypeData.hasOrganization, + 'annotation-block': true, + })}"> <div class="inner-grid"> <label><strong>${name}</strong></label> - <button class="button close" - title="${i18n.t('annotation-view.remove-field')}" - @click="${() => { this.removeAnnotation(id); } }"> - <dbp-icon name="trash"></dbp-icon></button> + <button + class="button close" + title="${i18n.t('annotation-view.remove-field')}" + @click="${() => { + this.removeAnnotation(id); + }}"> + <dbp-icon name="trash"></dbp-icon> + </button> </div> - <dbp-organization-select subscribe="lang:lang,entry-point-url:entry-point-url,auth:auth" - class="${classMap({hidden: !annotationTypeData.hasOrganization})}" - value="${data.organizationValue}" - @change=${e => { - this.updateAnnotation(id, 'organizationValue', e.target.value); - this.updateAnnotation(id, 'organizationNumber', JSON.parse(e.target.getAttribute("data-object")).alternateName); - }}></dbp-organization-select> - - <input type="text" .value="${data.value}" class="input" pattern="[A-Za-z0-9ÄäÖöÜüß\*\\/! &@()=+_-]*" - placeholder="${annotationTypeData.hasOrganization ? i18n.t('annotation-view.businessnumber-placeholder') : i18n.t('annotation-view.intended-use-placeholder')}" - @change=${e => { this.updateAnnotation(id, 'value', e.target.value); }}> + <dbp-organization-select + subscribe="lang:lang,entry-point-url:entry-point-url,auth:auth" + class="${classMap({hidden: !annotationTypeData.hasOrganization})}" + value="${data.organizationValue}" + @change=${(e) => { + this.updateAnnotation(id, 'organizationValue', e.target.value); + this.updateAnnotation( + id, + 'organizationNumber', + JSON.parse(e.target.getAttribute('data-object')).alternateName + ); + }}></dbp-organization-select> + + <input + type="text" + .value="${data.value}" + class="input" + pattern="[A-Za-z0-9ÄäÖöÜüß*\\/! &@()=+_-]*" + placeholder="${annotationTypeData.hasOrganization + ? i18n.t('annotation-view.businessnumber-placeholder') + : i18n.t('annotation-view.intended-use-placeholder')}" + @change=${(e) => { + this.updateAnnotation(id, 'value', e.target.value); + }} /> </div> `); - }); + }); - return results; - } + return results; + } render() { const i18n = this._i18n; @@ -383,22 +416,30 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { <div class="nav-buttons"> <div class="add-elements"> - <select id="additional-select" @change="${() => { this.isSelected = true; } }"> + <select id="additional-select" @change="${() => { + this.isSelected = true; + }}"> ${utils.getAnnotationTypeSelectOptionsHtml('', this.lang)} - <option value="" disabled selected>${i18n.t('annotation-view.insert-field')}</option> + <option value="" disabled selected>${i18n.t( + 'annotation-view.insert-field' + )}</option> </select> <button class="button" title="${i18n.t('annotation-view.insert-field')}" - @click="${() => { this.addAnnotation(); } }" - ?disabled="${ !this.isSelected }"> + @click="${() => { + this.addAnnotation(); + }}" + ?disabled="${!this.isSelected}"> <dbp-icon name="checkmark-circle"></dbp-icon></button> </button> </div> <button class="button is-primary" title="${i18n.t('annotation-view.save-all-button-title')}" - @click="${() => { this.saveAll(); } }" - ?disabled="${ this.annotationRows.length === 0 }"> + @click="${() => { + this.saveAll(); + }}" + ?disabled="${this.annotationRows.length === 0}"> ${i18n.t('annotation-view.save-all-button-text')} </button> </div> @@ -408,16 +449,22 @@ export class PdfAnnotationView extends ScopedElementsMixin(DBPLitElement) { </div> <div id="fields-wrapper"> <div id="inside-fields"> - <div class="text ${classMap({hidden: this.isTextHidden || this.annotationRows.length > 0})}"> + <div class="text ${classMap({ + hidden: this.isTextHidden || this.annotationRows.length > 0, + })}"> <p>${i18n.t('annotation-view.introduction')}</p> </div> ${this.getAnnotationsHtml()} </div> <div class="delete-elements"> - <button class="button ${classMap({hidden: !this.isTextHidden && this.annotationRows.length === 0})}" + <button class="button ${classMap({ + hidden: !this.isTextHidden && this.annotationRows.length === 0, + })}" title="${i18n.t('annotation-view.delete-all-button-title')}" - @click="${() => { this.deleteAll(); } }" - ?disabled="${ this.annotationRows.length === 0 }"> + @click="${() => { + this.deleteAll(); + }}" + ?disabled="${this.annotationRows.length === 0}"> ${i18n.t('annotation-view.delete-all-button-text')} </button> </div> diff --git a/src/dbp-pdf-preview.js b/src/dbp-pdf-preview.js index 3efaf70..cc6e8b6 100644 --- a/src/dbp-pdf-preview.js +++ b/src/dbp-pdf-preview.js @@ -5,7 +5,7 @@ import {live} from 'lit/directives/live.js'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import DBPLitElement from '@dbp-toolkit/common/dbp-lit-element'; import {MiniSpinner, Icon} from '@dbp-toolkit/common'; -import * as commonUtils from "@dbp-toolkit/common/utils"; +import * as commonUtils from '@dbp-toolkit/common/utils'; import * as commonStyles from '@dbp-toolkit/common/styles'; import pdfjs from 'pdfjs-dist/legacy/build/pdf.js'; import {name as pkgName} from './../package.json'; @@ -54,25 +54,25 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { static get properties() { return { ...super.properties, - lang: { type: String }, - currentPage: { type: Number, attribute: false }, - totalPages: { type: Number, attribute: false }, - isShowPage: { type: Boolean, attribute: false }, - isPageRenderingInProgress: { type: Boolean, attribute: false }, - isPageLoaded: { type: Boolean, attribute: false }, - showErrorMessage: { type: Boolean, attribute: false }, - isShowPlacement: { type: Boolean, attribute: false }, - placeholder: { type: String, attribute: 'signature-placeholder-image-src' }, - signature_width: { type: Number, attribute: 'signature-width' }, - signature_height: { type: Number, attribute: 'signature-height' }, - allowSignatureRotation: { type: Boolean, attribute: 'allow-signature-rotation' }, + lang: {type: String}, + currentPage: {type: Number, attribute: false}, + totalPages: {type: Number, attribute: false}, + isShowPage: {type: Boolean, attribute: false}, + isPageRenderingInProgress: {type: Boolean, attribute: false}, + isPageLoaded: {type: Boolean, attribute: false}, + showErrorMessage: {type: Boolean, attribute: false}, + isShowPlacement: {type: Boolean, attribute: false}, + placeholder: {type: String, attribute: 'signature-placeholder-image-src'}, + signature_width: {type: Number, attribute: 'signature-width'}, + signature_height: {type: Number, attribute: 'signature-height'}, + allowSignatureRotation: {type: Boolean, attribute: 'allow-signature-rotation'}, }; } update(changedProperties) { changedProperties.forEach((oldValue, propName) => { switch (propName) { - case "lang": + case 'lang': this._i18n.changeLanguage(this.lang); break; } @@ -92,12 +92,15 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { } window.removeEventListener('resize', this._onWindowResize); super.disconnectedCallback(); - } + } connectedCallback() { super.connectedCallback(); const that = this; - pdfjs.GlobalWorkerOptions.workerSrc = commonUtils.getAssetURL(pkgName, 'pdfjs/pdf.worker.js'); + pdfjs.GlobalWorkerOptions.workerSrc = commonUtils.getAssetURL( + pkgName, + 'pdfjs/pdf.worker.js' + ); window.addEventListener('resize', this._onWindowResize); @@ -119,9 +122,14 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { }); // add signature image - fabric.Image.fromURL(this.placeholder, function(image) { + fabric.Image.fromURL(this.placeholder, function (image) { // add a red border around the signature placeholder - image.set({stroke: "#e4154b", strokeWidth: that.border_width, strokeUniform: true, centeredRotation: true}); + image.set({ + stroke: '#e4154b', + strokeWidth: that.border_width, + strokeUniform: true, + centeredRotation: true, + }); // disable controls, we currently don't want resizing and do rotation with a button image.hasControls = false; @@ -131,12 +139,12 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { }); this.fabricCanvas.on({ - 'object:moving': function(e) { - e.target.opacity = 0.5; + 'object:moving': function (e) { + e.target.opacity = 0.5; + }, + 'object:modified': function (e) { + e.target.opacity = 1; }, - 'object:modified': function(e) { - e.target.opacity = 1; - } }); // this.fabricCanvas.on("object:moved", function(opt){ console.log(opt); }); @@ -169,10 +177,24 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { } // bottom-right corner - if (obj.getBoundingRect().top + obj.getBoundingRect().height > obj.canvas.height || - obj.getBoundingRect().left + obj.getBoundingRect().width > obj.canvas.width) { - obj.top = Math.min(obj.top, obj.canvas.height - obj.getBoundingRect().height + obj.top - obj.getBoundingRect().top); - obj.left = Math.min(obj.left, obj.canvas.width - obj.getBoundingRect().width + obj.left - obj.getBoundingRect().left); + if ( + obj.getBoundingRect().top + obj.getBoundingRect().height > obj.canvas.height || + obj.getBoundingRect().left + obj.getBoundingRect().width > obj.canvas.width + ) { + obj.top = Math.min( + obj.top, + obj.canvas.height - + obj.getBoundingRect().height + + obj.top - + obj.getBoundingRect().top + ); + obj.left = Math.min( + obj.left, + obj.canvas.width - + obj.getBoundingRect().width + + obj.left - + obj.getBoundingRect().left + ); } } @@ -200,20 +222,20 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { // move signature if placementData was set if (item !== undefined) { - if (placementData["scaleX"] !== undefined) { - item.set("scaleX", placementData["scaleX"] * this.canvasToPdfScale); + if (placementData['scaleX'] !== undefined) { + item.set('scaleX', placementData['scaleX'] * this.canvasToPdfScale); } - if (placementData["scaleY"] !== undefined) { - item.set("scaleY", placementData["scaleY"] * this.canvasToPdfScale); + if (placementData['scaleY'] !== undefined) { + item.set('scaleY', placementData['scaleY'] * this.canvasToPdfScale); } - if (placementData["left"] !== undefined) { - item.set("left", placementData["left"] * this.canvasToPdfScale); + if (placementData['left'] !== undefined) { + item.set('left', placementData['left'] * this.canvasToPdfScale); } - if (placementData["top"] !== undefined) { - item.set("top", placementData["top"] * this.canvasToPdfScale); + if (placementData['top'] !== undefined) { + item.set('top', placementData['top'] * this.canvasToPdfScale); } - if (placementData["angle"] !== undefined) { - item.set("angle", placementData["angle"]); + if (placementData['angle'] !== undefined) { + item.set('angle', placementData['angle']); } } @@ -237,7 +259,7 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { // show the first page // if the placementData has no values we want to initialize the signature position - await this.showPage(page, placementData["scaleX"] === undefined); + await this.showPage(page, placementData['scaleX'] === undefined); this.isPageLoaded = true; @@ -269,7 +291,7 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { // get handle of page await this.pdfDoc.getPage(pageNumber).then(async (page) => { // original width of the pdf page at scale 1 - const originalViewport = page.getViewport({ scale: 1 }); + const originalViewport = page.getViewport({scale: 1}); this.currentPageOriginalHeight = originalViewport.height; // set the canvas width to the width of the container (minus the borders) @@ -280,23 +302,23 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { const oldScale = this.canvasToPdfScale; this.canvasToPdfScale = this.canvas.width / originalViewport.width; - console.log("this.canvasToPdfScale: " + this.canvasToPdfScale); + console.log('this.canvasToPdfScale: ' + this.canvasToPdfScale); // get viewport to render the page at required scale - const viewport = page.getViewport({ scale: this.canvasToPdfScale }); + const viewport = page.getViewport({scale: this.canvasToPdfScale}); // set canvas height same as viewport height this.fabricCanvas.setHeight(viewport.height); this.canvas.height = viewport.height; // setting page loader height for smooth experience - this._("#page-loader").style.height = this.canvas.height + 'px'; - this._("#page-loader").style.lineHeight = this.canvas.height + 'px'; + this._('#page-loader').style.height = this.canvas.height + 'px'; + this._('#page-loader').style.lineHeight = this.canvas.height + 'px'; // page is rendered on <canvas> element const render_context = { canvasContext: this.canvas.getContext('2d'), - viewport: viewport + viewport: viewport, }; let signature = this.getSignatureRect(); @@ -315,8 +337,12 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { }; const sigSize = signature.getOriginalSize(); - const scaleX = (this.canvas.width / sigSize.width) * (sigSizeMM.width / documentSizeMM.width); - const scaleY = (this.canvas.height / sigSize.height) * (sigSizeMM.height / documentSizeMM.height); + const scaleX = + (this.canvas.width / sigSize.width) * + (sigSizeMM.width / documentSizeMM.width); + const scaleY = + (this.canvas.height / sigSize.height) * + (sigSizeMM.height / documentSizeMM.height); const offsetTop = sigPosMM.top * pointsPerMM; const offsetLeft = sigPosMM.left * pointsPerMM; @@ -326,17 +352,17 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { angle: 0, top: offsetTop, left: offsetLeft, - lockUniScaling: true // lock aspect ratio when resizing + lockUniScaling: true, // lock aspect ratio when resizing }); } else { // adapt signature scale to new scale const scaleAdapt = this.canvasToPdfScale / oldScale; signature.set({ - scaleX: signature.get("scaleX") * scaleAdapt, - scaleY: signature.get("scaleY") * scaleAdapt, - left: signature.get("left") * scaleAdapt, - top: signature.get("top") * scaleAdapt + scaleX: signature.get('scaleX') * scaleAdapt, + scaleY: signature.get('scaleY') * scaleAdapt, + left: signature.get('left') * scaleAdapt, + top: signature.get('top') * scaleAdapt, }); signature.setCoords(); @@ -344,66 +370,77 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { // render the page contents in the canvas try { - await page.render(render_context).promise.then(() => { - console.log('Page rendered'); - that.isPageRenderingInProgress = false; - - return page.getAnnotations(); - }).then(function(annotationData) { - // remove all child nodes - that.annotationLayer.innerHTML = ''; - // update size - that.annotationLayer.style.height = that.canvas.height + 'px'; - that.annotationLayer.style.width = that.canvas.width + 'px'; - - // create all supported annotations - annotationData.forEach((annotation) => { - const subtype = annotation.subtype; - let text = ''; - switch (subtype) { - case 'Text': - case 'FreeText': - // Annotations by Adobe Acrobat already have an appearance that can be viewed by pdf.js - if (annotation.hasAppearance) { - return; - } - - text = annotation.contents; - break; - case 'Widget': - // Annotations by Adobe Acrobat already have an appearance that can be viewed by pdf.js - if (annotation.hasAppearance) { + await page + .render(render_context) + .promise.then(() => { + console.log('Page rendered'); + that.isPageRenderingInProgress = false; + + return page.getAnnotations(); + }) + .then(function (annotationData) { + // remove all child nodes + that.annotationLayer.innerHTML = ''; + // update size + that.annotationLayer.style.height = that.canvas.height + 'px'; + that.annotationLayer.style.width = that.canvas.width + 'px'; + + // create all supported annotations + annotationData.forEach((annotation) => { + const subtype = annotation.subtype; + let text = ''; + switch (subtype) { + case 'Text': + case 'FreeText': + // Annotations by Adobe Acrobat already have an appearance that can be viewed by pdf.js + if (annotation.hasAppearance) { + return; + } + + text = annotation.contents; + break; + case 'Widget': + // Annotations by Adobe Acrobat already have an appearance that can be viewed by pdf.js + if (annotation.hasAppearance) { + return; + } + + text = annotation.alternativeText; + break; + default: + // we don't support other types return; - } - - text = annotation.alternativeText; - break; - default: - // we don't support other types - return; - } - - const annotationDiv = document.createElement("div"); - const annotationDivInner = document.createElement("div"); - annotationDiv.className = 'annotation annotation-' + subtype; - annotationDiv.style.left = (annotation.rect[0] * that.canvasToPdfScale) + 'px'; - annotationDiv.style.bottom = (annotation.rect[1] * that.canvasToPdfScale) + 'px'; - annotationDiv.style.width = ((annotation.rect[2] - annotation.rect[0]) * that.canvasToPdfScale) + 'px'; - annotationDiv.style.height = ((annotation.rect[3] - annotation.rect[1]) * that.canvasToPdfScale) + 'px'; - annotationDivInner.innerText = text === '' ? subtype : text; - - annotationDiv.appendChild(annotationDivInner); - that.annotationLayer.appendChild(annotationDiv); + } + + const annotationDiv = document.createElement('div'); + const annotationDivInner = document.createElement('div'); + annotationDiv.className = 'annotation annotation-' + subtype; + annotationDiv.style.left = + annotation.rect[0] * that.canvasToPdfScale + 'px'; + annotationDiv.style.bottom = + annotation.rect[1] * that.canvasToPdfScale + 'px'; + annotationDiv.style.width = + (annotation.rect[2] - annotation.rect[0]) * + that.canvasToPdfScale + + 'px'; + annotationDiv.style.height = + (annotation.rect[3] - annotation.rect[1]) * + that.canvasToPdfScale + + 'px'; + annotationDivInner.innerText = text === '' ? subtype : text; + + annotationDiv.appendChild(annotationDivInner); + that.annotationLayer.appendChild(annotationDiv); + }); + + // console.log("annotationData render", annotationData); }); - - // console.log("annotationData render", annotationData); - }); - } catch(error) { + } catch (error) { console.error(error.message); that.isPageRenderingInProgress = false; } }); - } catch(error) { + } catch (error) { console.error(error.message); that.isPageRenderingInProgress = false; } @@ -411,13 +448,13 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { sendAcceptEvent() { const item = this.getSignatureRect(); - let left = item.get("left"); - let top = item.get("top"); - const angle = item.get("angle"); + let left = item.get('left'); + let top = item.get('top'); + const angle = item.get('angle'); // fabricjs includes the stroke in the image position // and we have to remove it - const border_offset = (this.border_width / 2); + const border_offset = this.border_width / 2; if (angle === 0) { left += border_offset; top += border_offset; @@ -433,24 +470,30 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { } const data = { - "currentPage": this.currentPage, - "scaleX": item.get("scaleX") / this.canvasToPdfScale, - "scaleY": item.get("scaleY") / this.canvasToPdfScale, - "width": item.get("width") * item.get("scaleX") / this.canvasToPdfScale, - "height": item.get("height") * item.get("scaleY") / this.canvasToPdfScale, - "left": left / this.canvasToPdfScale, - "top": top / this.canvasToPdfScale, - "bottom": this.currentPageOriginalHeight - (top / this.canvasToPdfScale), - "angle": item.get("angle") + currentPage: this.currentPage, + scaleX: item.get('scaleX') / this.canvasToPdfScale, + scaleY: item.get('scaleY') / this.canvasToPdfScale, + width: (item.get('width') * item.get('scaleX')) / this.canvasToPdfScale, + height: (item.get('height') * item.get('scaleY')) / this.canvasToPdfScale, + left: left / this.canvasToPdfScale, + top: top / this.canvasToPdfScale, + bottom: this.currentPageOriginalHeight - top / this.canvasToPdfScale, + angle: item.get('angle'), }; - const event = new CustomEvent("dbp-pdf-preview-accept", - { "detail": data, bubbles: true, composed: true }); + const event = new CustomEvent('dbp-pdf-preview-accept', { + detail: data, + bubbles: true, + composed: true, + }); this.dispatchEvent(event); } sendCancelEvent() { - const event = new CustomEvent("dbp-pdf-preview-cancel", - { "detail": {}, bubbles: true, composed: true }); + const event = new CustomEvent('dbp-pdf-preview-cancel', { + detail: {}, + bubbles: true, + composed: true, + }); this.dispatchEvent(event); } @@ -459,7 +502,7 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { */ async rotateSignature() { let signature = this.getSignatureRect(); - let angle = (signature.get("angle") + 90) % 360; + let angle = (signature.get('angle') + 90) % 360; signature.rotate(angle); signature.setCoords(); this.enforceCanvasBoundaries(signature); @@ -474,12 +517,12 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { ${commonStyles.getGeneralCSS()} ${commonStyles.getButtonCSS()} - #pdf-meta input[type=number]{ + #pdf-meta input[type=number] { max-width: 50px; } #page-loader { - display:flex; + display: flex; align-items: center; justify-content: center; } @@ -546,7 +589,7 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { margin: 2px; } - input[type=number] { + input[type='number'] { border: var(--dbp-border-dark); padding: 0 0.3em; } @@ -561,15 +604,16 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { .button.is-cancel { color: var(--dbp-danger-dark); } - - .error-message{ + + .error-message { text-align: center; border: 1px solid black; border-top: 0px; padding: 15px; } - - #canvas-wrapper canvas#fabric-canvas, #canvas-wrapper canvas.upper-canvas{ + + #canvas-wrapper canvas#fabric-canvas, + #canvas-wrapper canvas.upper-canvas { border: unset; } `; @@ -580,66 +624,114 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { const i18n = this._i18n; return html` - -<!-- + <!-- <form> <input type="file" name="pdf" id="upload-pdf-input"> </form> --> <div id="pdf-main-container" class="${classMap({hidden: !this.isShowPage})}"> - <dbp-mini-spinner class="${classMap({hidden: this.isPageLoaded || this.showErrorMessage})}"></dbp-mini-spinner> - <div class="error-message ${classMap({hidden: !this.showErrorMessage || this.isPageLoaded})}"> + <dbp-mini-spinner + class="${classMap({ + hidden: this.isPageLoaded || this.showErrorMessage, + })}"></dbp-mini-spinner> + <div + class="error-message ${classMap({ + hidden: !this.showErrorMessage || this.isPageLoaded, + })}"> ${i18n.t('pdf-preview.error-message')} </div> <div class="${classMap({hidden: !this.isPageLoaded})}"> <div id="pdf-meta"> <div class="buttons ${classMap({hidden: !this.isPageLoaded})}"> - <button class="button ${classMap({hidden: !this.isShowPlacement || isRotationHidden})}" - title="${i18n.t('pdf-preview.rotate-signature')}" - @click="${() => { this.rotateSignature(); } }" - ?disabled="${this.isPageRenderingInProgress}">⟳ ${i18n.t('pdf-preview.rotate')}</button> + <button + class="button ${classMap({ + hidden: !this.isShowPlacement || isRotationHidden, + })}" + title="${i18n.t('pdf-preview.rotate-signature')}" + @click="${() => { + this.rotateSignature(); + }}" + ?disabled="${this.isPageRenderingInProgress}"> + ⟳ ${i18n.t('pdf-preview.rotate')} + </button> <div class="nav-buttons"> - <button class="button" - title="${i18n.t('pdf-preview.first-page')}" - @click="${async () => { await this.showPage(1); } }" - ?disabled="${this.isPageRenderingInProgress || this.currentPage === 1}"> + <button + class="button" + title="${i18n.t('pdf-preview.first-page')}" + @click="${async () => { + await this.showPage(1); + }}" + ?disabled="${this.isPageRenderingInProgress || + this.currentPage === 1}"> <dbp-icon name="angle-double-left"></dbp-icon> </button> - <button class="button" - title="${i18n.t('pdf-preview.previous-page')}" - @click="${async () => { if (this.currentPage > 1) await this.showPage(--this.currentPage); } }" - ?disabled="${this.isPageRenderingInProgress || this.currentPage === 1}"> + <button + class="button" + title="${i18n.t('pdf-preview.previous-page')}" + @click="${async () => { + if (this.currentPage > 1) + await this.showPage(--this.currentPage); + }}" + ?disabled="${this.isPageRenderingInProgress || + this.currentPage === 1}"> <dbp-icon name="chevron-left"></dbp-icon> </button> - <input type="number" + <input + type="number" min="1" max="${this.totalPages}" @input="${this.onPageNumberChanged}" - .value="${live(this.currentPage)}"> - <div class="page-info">${i18n.t('pdf-preview.page-count', {totalPages: this.totalPages, })}</div> - <button class="button" - title="${i18n.t('pdf-preview.next-page')}" - @click="${async () => { if (this.currentPage < this.totalPages) await this.showPage(++this.currentPage); } }" - ?disabled="${this.isPageRenderingInProgress || this.currentPage === this.totalPages}"> + .value="${live(this.currentPage)}" /> + <div class="page-info"> + ${i18n.t('pdf-preview.page-count', { + totalPages: this.totalPages, + })} + </div> + <button + class="button" + title="${i18n.t('pdf-preview.next-page')}" + @click="${async () => { + if (this.currentPage < this.totalPages) + await this.showPage(++this.currentPage); + }}" + ?disabled="${this.isPageRenderingInProgress || + this.currentPage === this.totalPages}"> <dbp-icon name="chevron-right"></dbp-icon> </button> - <button class="button" - title="${i18n.t('pdf-preview.last-page')}" - @click="${async () => { await this.showPage(this.totalPages); } }" - ?disabled="${this.isPageRenderingInProgress || this.currentPage === this.totalPages}"> + <button + class="button" + title="${i18n.t('pdf-preview.last-page')}" + @click="${async () => { + await this.showPage(this.totalPages); + }}" + ?disabled="${this.isPageRenderingInProgress || + this.currentPage === this.totalPages}"> <dbp-icon name="angle-double-right"></dbp-icon> </button> </div> - <button class="button is-primary ${classMap({hidden: !this.isShowPlacement})}" - @click="${() => { this.sendAcceptEvent(); } }">${i18n.t('pdf-preview.continue')}</button> + <button + class="button is-primary ${classMap({ + hidden: !this.isShowPlacement, + })}" + @click="${() => { + this.sendAcceptEvent(); + }}"> + ${i18n.t('pdf-preview.continue')} + </button> </div> </div> - <div id="canvas-wrapper" class="${classMap({hidden: this.isPageRenderingInProgress})}"> + <div + id="canvas-wrapper" + class="${classMap({hidden: this.isPageRenderingInProgress})}"> <canvas id="pdf-canvas"></canvas> <div id="annotation-layer"></div> - <canvas id="fabric-canvas" class="${classMap({hidden: !this.isShowPlacement})}"></canvas> + <canvas + id="fabric-canvas" + class="${classMap({hidden: !this.isShowPlacement})}"></canvas> + </div> + <div class="${classMap({hidden: !this.isPageRenderingInProgress})}"> + <dbp-mini-spinner id="page-loader"></dbp-mini-spinner> </div> - <div class="${classMap({hidden: !this.isPageRenderingInProgress})}"><dbp-mini-spinner id="page-loader"></dbp-mini-spinner></div> </div> </div> `; diff --git a/src/dbp-qualified-signature-pdf-upload.js b/src/dbp-qualified-signature-pdf-upload.js index 4272d63..025c649 100644 --- a/src/dbp-qualified-signature-pdf-upload.js +++ b/src/dbp-qualified-signature-pdf-upload.js @@ -2,23 +2,23 @@ import {createInstance} from './i18n.js'; import {humanFileSize} from '@dbp-toolkit/common/i18next.js'; import {css, html} from 'lit'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; -import DBPSignatureLitElement from "./dbp-signature-lit-element"; -import {PdfPreview} from "./dbp-pdf-preview"; +import DBPSignatureLitElement from './dbp-signature-lit-element'; +import {PdfPreview} from './dbp-pdf-preview'; import * as commonUtils from '@dbp-toolkit/common/utils'; import * as utils from './utils'; import {Button, Icon, MiniSpinner} from '@dbp-toolkit/common'; import * as commonStyles from '@dbp-toolkit/common/styles'; import {classMap} from 'lit/directives/class-map.js'; import {FileSource} from '@dbp-toolkit/file-handling'; -import JSONLD from "@dbp-toolkit/common/jsonld"; +import JSONLD from '@dbp-toolkit/common/jsonld'; import {TextSwitch} from './textswitch.js'; -import {FileSink} from "@dbp-toolkit/file-handling"; +import {FileSink} from '@dbp-toolkit/file-handling'; import {name as pkgName} from './../package.json'; import {send as notify} from '@dbp-toolkit/common/notification'; import metadata from './dbp-qualified-signature-pdf-upload.metadata.json'; import {Activity} from './activity.js'; -import {PdfAnnotationView} from "./dbp-pdf-annotation-view"; -import { ExternalSignIFrame } from './ext-sign-iframe.js'; +import {PdfAnnotationView} from './dbp-pdf-annotation-view'; +import {ExternalSignIFrame} from './ext-sign-iframe.js'; import * as SignatureStyles from './styles'; class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitElement) { @@ -27,22 +27,22 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle this._i18n = createInstance(); this.lang = this._i18n.language; this.entryPointUrl = ''; - this.nextcloudWebAppPasswordURL = ""; - this.nextcloudWebDavURL = ""; - this.nextcloudName = ""; - this.nextcloudFileURL = ""; - this.nextcloudAuthInfo = ""; + this.nextcloudWebAppPasswordURL = ''; + this.nextcloudWebDavURL = ''; + this.nextcloudName = ''; + this.nextcloudFileURL = ''; + this.nextcloudAuthInfo = ''; this.externalAuthInProgress = false; this.signedFiles = []; this.signedFilesCount = 0; this.signedFilesToDownload = 0; this.errorFiles = []; this.errorFilesCount = 0; - this.uploadStatusFileName = ""; - this.uploadStatusText = ""; + this.uploadStatusFileName = ''; + this.uploadStatusText = ''; this.currentFile = {}; - this.currentFileName = ""; - this.currentFilePlacementMode = ""; + this.currentFileName = ''; + this.currentFilePlacementMode = ''; this.currentFileSignaturePlacement = {}; this.signingProcessEnabled = false; this.signingProcessActive = false; @@ -61,67 +61,69 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle this.isAnnotationViewVisible = false; this.addAnnotationInProgress = false; this.activity = new Activity(metadata); - this.fileHandlingEnabledTargets = "local"; + this.fileHandlingEnabledTargets = 'local'; this._onReceiveBeforeUnload = this.onReceiveBeforeUnload.bind(this); } static get scopedElements() { return { - 'dbp-icon': Icon, - 'dbp-file-source': FileSource, - 'dbp-file-sink': FileSink, - 'dbp-pdf-preview': PdfPreview, - 'dbp-mini-spinner': MiniSpinner, - 'dbp-button': Button, - 'dbp-textswitch': TextSwitch, - 'dbp-pdf-annotation-view': PdfAnnotationView, - 'external-sign-iframe': ExternalSignIFrame, + 'dbp-icon': Icon, + 'dbp-file-source': FileSource, + 'dbp-file-sink': FileSink, + 'dbp-pdf-preview': PdfPreview, + 'dbp-mini-spinner': MiniSpinner, + 'dbp-button': Button, + 'dbp-textswitch': TextSwitch, + 'dbp-pdf-annotation-view': PdfAnnotationView, + 'external-sign-iframe': ExternalSignIFrame, }; } static get properties() { return { ...super.properties, - lang: { type: String }, - entryPointUrl: { type: String, attribute: 'entry-point-url' }, - nextcloudWebAppPasswordURL: { type: String, attribute: 'nextcloud-web-app-password-url' }, - nextcloudWebDavURL: { type: String, attribute: 'nextcloud-webdav-url' }, - nextcloudName: { type: String, attribute: 'nextcloud-name' }, - nextcloudFileURL: { type: String, attribute: 'nextcloud-file-url' }, + lang: {type: String}, + entryPointUrl: {type: String, attribute: 'entry-point-url'}, + nextcloudWebAppPasswordURL: {type: String, attribute: 'nextcloud-web-app-password-url'}, + nextcloudWebDavURL: {type: String, attribute: 'nextcloud-webdav-url'}, + nextcloudName: {type: String, attribute: 'nextcloud-name'}, + nextcloudFileURL: {type: String, attribute: 'nextcloud-file-url'}, nextcloudAuthInfo: {type: String, attribute: 'nextcloud-auth-info'}, - signedFiles: { type: Array, attribute: false }, - signedFilesCount: { type: Number, attribute: false }, - signedFilesToDownload: { type: Number, attribute: false }, - queuedFilesCount: { type: Number, attribute: false }, - errorFiles: { type: Array, attribute: false }, - errorFilesCount: { type: Number, attribute: false }, - uploadInProgress: { type: Boolean, attribute: false }, - uploadStatusFileName: { type: String, attribute: false }, - uploadStatusText: { type: String, attribute: false }, - externalAuthInProgress: { type: Boolean, attribute: false }, - signingProcessEnabled: { type: Boolean, attribute: false }, - signingProcessActive: { type: Boolean, attribute: false }, - queueBlockEnabled: { type: Boolean, attribute: false }, - currentFile: { type: Object, attribute: false }, - currentFileName: { type: String, attribute: false }, - signaturePlacementInProgress: { type: Boolean, attribute: false }, - withSigBlock: { type: Boolean, attribute: false }, - isSignaturePlacement: { type: Boolean, attribute: false }, - allowAnnotating: { type: Boolean, attribute: 'allow-annotating' }, - isAnnotationViewVisible: { type: Boolean, attribute: false }, - queuedFilesAnnotations: { type: Array, attribute: false }, - queuedFilesAnnotationsCount: { type: Number, attribute: false }, - addAnnotationInProgress: { type: Boolean, attribute: false }, - queuedFilesAnnotationModes: { type: Array, attribute: false }, - queuedFilesAnnotationSaved: { type: Array, attribute: false }, - fileHandlingEnabledTargets: {type: String, attribute: 'file-handling-enabled-targets'} + signedFiles: {type: Array, attribute: false}, + signedFilesCount: {type: Number, attribute: false}, + signedFilesToDownload: {type: Number, attribute: false}, + queuedFilesCount: {type: Number, attribute: false}, + errorFiles: {type: Array, attribute: false}, + errorFilesCount: {type: Number, attribute: false}, + uploadInProgress: {type: Boolean, attribute: false}, + uploadStatusFileName: {type: String, attribute: false}, + uploadStatusText: {type: String, attribute: false}, + externalAuthInProgress: {type: Boolean, attribute: false}, + signingProcessEnabled: {type: Boolean, attribute: false}, + signingProcessActive: {type: Boolean, attribute: false}, + queueBlockEnabled: {type: Boolean, attribute: false}, + currentFile: {type: Object, attribute: false}, + currentFileName: {type: String, attribute: false}, + signaturePlacementInProgress: {type: Boolean, attribute: false}, + withSigBlock: {type: Boolean, attribute: false}, + isSignaturePlacement: {type: Boolean, attribute: false}, + allowAnnotating: {type: Boolean, attribute: 'allow-annotating'}, + isAnnotationViewVisible: {type: Boolean, attribute: false}, + queuedFilesAnnotations: {type: Array, attribute: false}, + queuedFilesAnnotationsCount: {type: Number, attribute: false}, + addAnnotationInProgress: {type: Boolean, attribute: false}, + queuedFilesAnnotationModes: {type: Array, attribute: false}, + queuedFilesAnnotationSaved: {type: Array, attribute: false}, + fileHandlingEnabledTargets: {type: String, attribute: 'file-handling-enabled-targets'}, }; } connectedCallback() { super.connectedCallback(); // needs to be called in a function to get the variable scope of "this" - setInterval(() => { this.handleQueuedFiles(); }, 1000); + setInterval(() => { + this.handleQueuedFiles(); + }, 1000); // we want to be able to cancel the leaving of the page window.addEventListener('beforeunload', this._onReceiveBeforeUnload); @@ -154,7 +156,12 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle return; } - if (!this.signingProcessEnabled || this.externalAuthInProgress || this.uploadInProgress || this.addAnnotationInProgress) { + if ( + !this.signingProcessEnabled || + this.externalAuthInProgress || + this.uploadInProgress || + this.addAnnotationInProgress + ) { return; } this.signaturePlacementInProgress = false; @@ -165,9 +172,9 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle if (this.queuedFilesNeedsPlacement.get(key) && !isManual) { // Some have a signature but are not "manual", stop everything notify({ - "body": i18n.t('error-manual-positioning-missing'), - "type": "danger", - "timeout": 5, + body: i18n.t('error-manual-positioning-missing'), + type: 'danger', + timeout: 5, }); this.signingProcessEnabled = false; this.signingProcessActive = false; @@ -188,7 +195,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle let params = {}; // prepare parameters to tell PDF-AS where and how the signature should be placed - if (this.queuedFilesPlacementModes[key] === "manual") { + if (this.queuedFilesPlacementModes[key] === 'manual') { const data = this.queuedFilesSignaturePlacements[key]; if (data !== undefined) { params = utils.fabricjs2pdfasPosition(data); @@ -208,11 +215,6 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle this.uploadInProgress = false; } - - - - - /** * Decides if the "beforeunload" event needs to be canceled * @@ -254,18 +256,15 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle let errorParsed = error; // Common Error Messages fpr pdf-as: https://www.buergerkarte.at/konzept/securitylayer/spezifikation/20140114/errorcodes/errorcodes.html // SecurityLayer Error: [6000] Unklassifizierter Abbruch durch den Bürger. - if (error.includes('SecurityLayer Error: [6001]')) - { + if (error.includes('SecurityLayer Error: [6001]')) { errorParsed = i18n.t('error-cancel-message'); } // SecurityLayer Error: [6001] Abbruch durch den Bürger über die Benutzerschnittstelle. - else if (error.includes('SecurityLayer Error: [6000]')) - { + else if (error.includes('SecurityLayer Error: [6000]')) { errorParsed = i18n.t('error-cancel-message'); } // SecurityLayer Error: [6002] Abbruch auf Grund mangelnder Rechte zur Befehlsausführung. - else if (error.includes('SecurityLayer Error: [6002]')) - { + else if (error.includes('SecurityLayer Error: [6002]')) { errorParsed = i18n.t('error-rights-message'); } return errorParsed; @@ -275,74 +274,84 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle const sessionId = event.detail.id; // check if sessionId is valid - if ((typeof sessionId !== 'string') || (sessionId.length < 15)) { + if (typeof sessionId !== 'string' || sessionId.length < 15) { return; } - console.log("Got iframe message for sessionId " + sessionId); + console.log('Got iframe message for sessionId ' + sessionId); const that = this; // get correct file name - const fileName = this.currentFileName === "" ? "mydoc.pdf" : this.currentFileName; + const fileName = this.currentFileName === '' ? 'mydoc.pdf' : this.currentFileName; // fetch pdf from api gateway with sessionId - JSONLD.getInstance(this.entryPointUrl).then((jsonld) => { - let apiUrlBase; - try { - apiUrlBase = jsonld.getApiUrlForEntityName("EsignQualifiedlySignedDocument"); - } catch (error) { - apiUrlBase = jsonld.getApiUrlForEntityName("QualifiedlySignedDocument"); - } - - const apiUrl = apiUrlBase + '/' + encodeURIComponent(sessionId) + '?fileName=' + - encodeURIComponent(fileName); - - fetch(apiUrl, { - headers: { - 'Content-Type': 'application/ld+json', - 'Authorization': 'Bearer ' + that.auth.token, - }, - }) - .then(result => { - // hide iframe - that.externalAuthInProgress = false; - this._("#iframe").reset(); - this.endSigningProcessIfQueueEmpty(); - - if (!result.ok) throw result; - - return result.json(); + JSONLD.getInstance(this.entryPointUrl).then( + (jsonld) => { + let apiUrlBase; + try { + apiUrlBase = jsonld.getApiUrlForEntityName('EsignQualifiedlySignedDocument'); + } catch (error) { + apiUrlBase = jsonld.getApiUrlForEntityName('QualifiedlySignedDocument'); + } + + const apiUrl = + apiUrlBase + + '/' + + encodeURIComponent(sessionId) + + '?fileName=' + + encodeURIComponent(fileName); + + fetch(apiUrl, { + headers: { + 'Content-Type': 'application/ld+json', + Authorization: 'Bearer ' + that.auth.token, + }, }) - .then((document) => { - // this doesn't seem to trigger an update() execution - that.signedFiles.push(document); - // this triggers the correct update() execution - that.signedFilesCount++; - - this.sendSetPropertyEvent('analytics-event', { - 'category': 'QualifiedlySigning', 'action': 'DocumentSigned', 'name': document.contentSize}); - }).catch(error => { - let file = this.currentFile; - // let's override the json to inject an error message - file.json = {"hydra:description" : "Download failed!"}; - - this.addToErrorFiles(file); - }); - }, {}, that.lang); + .then((result) => { + // hide iframe + that.externalAuthInProgress = false; + this._('#iframe').reset(); + this.endSigningProcessIfQueueEmpty(); + + if (!result.ok) throw result; + + return result.json(); + }) + .then((document) => { + // this doesn't seem to trigger an update() execution + that.signedFiles.push(document); + // this triggers the correct update() execution + that.signedFilesCount++; + + this.sendSetPropertyEvent('analytics-event', { + category: 'QualifiedlySigning', + action: 'DocumentSigned', + name: document.contentSize, + }); + }) + .catch((error) => { + let file = this.currentFile; + // let's override the json to inject an error message + file.json = {'hydra:description': 'Download failed!'}; + + this.addToErrorFiles(file); + }); + }, + {}, + that.lang + ); } - _onIFrameError(event) { let error = event.detail.message; let file = this.currentFile; - file.json = {"hydra:description" : this.parseError(error)}; + file.json = {'hydra:description': this.parseError(error)}; this.addToErrorFiles(file); - this._("#iframe").reset(); + this._('#iframe').reset(); this.externalAuthInProgress = false; this.endSigningProcessIfQueueEmpty(); } - addToErrorFiles(file) { this.endSigningProcessIfQueueEmpty(); @@ -352,7 +361,10 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle this.errorFilesCount++; this.sendSetPropertyEvent('analytics-event', { - 'category': 'QualifiedlySigning', 'action': 'SigningFailed', 'name': file.json["hydra:description"]}); + category: 'QualifiedlySigning', + action: 'SigningFailed', + name: file.json['hydra:description'], + }); } /** @@ -361,7 +373,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle onFileUploadFinished(data) { if (data.status !== 201) { this.addToErrorFiles(data); - } else if (data.json["@type"] === "http://schema.org/EntryPoint" ) { + } else if (data.json['@type'] === 'http://schema.org/EntryPoint') { // after the "real" upload we immediately start with the 2FA process // show the iframe and lock processing @@ -374,7 +386,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle this.currentFile = data; // we want to load the redirect url in the iframe - let iframe = this._("#iframe"); + let iframe = this._('#iframe'); iframe.setUrl(entryPoint.url); } } @@ -382,18 +394,20 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle update(changedProperties) { changedProperties.forEach((oldValue, propName) => { switch (propName) { - case "lang": + case 'lang': this._i18n.changeLanguage(this.lang); break; - case "entryPointUrl": + case 'entryPointUrl': JSONLD.getInstance(this.entryPointUrl).then((jsonld) => { let apiUrlBase; try { - apiUrlBase = jsonld.getApiUrlForEntityName("EsignQualifiedSigningRequest"); + apiUrlBase = jsonld.getApiUrlForEntityName( + 'EsignQualifiedSigningRequest' + ); } catch (error) { - apiUrlBase = jsonld.getApiUrlForEntityName("QualifiedSigningRequest"); + apiUrlBase = jsonld.getApiUrlForEntityName('QualifiedSigningRequest'); } - this.fileSourceUrl = apiUrlBase ; + this.fileSourceUrl = apiUrlBase; }); break; } @@ -408,7 +422,6 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle super.clearQueuedFiles(); } - static get styles() { // language=css return css` @@ -454,44 +467,69 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle results.push(html` <div class="file-block"> <div class="header"> - <span class="filename"><strong>${file.name}</strong> (${humanFileSize(file.size)})</span> - <button class="button close" + <span class="filename"> + <strong>${file.name}</strong> + (${humanFileSize(file.size)}) + </span> + <button + class="button close" ?disabled="${this.signingProcessEnabled}" - title="${i18n.t('qualified-pdf-upload.remove-queued-file-button-title')}" - @click="${() => { this.takeFileFromQueue(id); }}"> - <dbp-icon name="trash"></dbp-icon></button> + title="${i18n.t( + 'qualified-pdf-upload.remove-queued-file-button-title' + )}" + @click="${() => { + this.takeFileFromQueue(id); + }}"> + <dbp-icon name="trash"></dbp-icon> + </button> </div> <div class="bottom-line"> <div></div> - <button class="button" + <button + class="button" ?disabled="${this.signingProcessEnabled}" - @click="${() => { this.showPreview(id); }}">${i18n.t('qualified-pdf-upload.show-preview')}</button> + @click="${() => { + this.showPreview(id); + }}"> + ${i18n.t('qualified-pdf-upload.show-preview')} + </button> <span class="headline">${i18n.t('qualified-pdf-upload.positioning')}:</span> - <dbp-textswitch name1="auto" + <dbp-textswitch + name1="auto" name2="manual" - name="${this.queuedFilesPlacementModes[id] || "auto"}" - class="${classMap({'placement-missing': placementMissing, 'switch': true})}" + name="${this.queuedFilesPlacementModes[id] || 'auto'}" + class="${classMap({ + 'placement-missing': placementMissing, + switch: true, + })}" value1="${i18n.t('qualified-pdf-upload.positioning-automatic')}" value2="${i18n.t('qualified-pdf-upload.positioning-manual')}" ?disabled="${this.signingProcessEnabled}" - @change=${ (e) => this.queuePlacementSwitch(id, e.target.name) }></dbp-textswitch> - <span class="headline ${classMap({hidden: !this.allowAnnotating})}">${i18n.t('qualified-pdf-upload.annotation')}:</span> + @change=${(e) => + this.queuePlacementSwitch(id, e.target.name)}></dbp-textswitch> + <span class="headline ${classMap({hidden: !this.allowAnnotating})}"> + ${i18n.t('qualified-pdf-upload.annotation')}: + </span> <div class="${classMap({hidden: !this.allowAnnotating})}"> - <dbp-textswitch id="annotation-switch" + <dbp-textswitch + id="annotation-switch" name1="no-text" name2="text-selected" - name="${this.queuedFilesAnnotationModes[id] || "no-text"}" - class="${classMap({'switch': true})}" + name="${this.queuedFilesAnnotationModes[id] || 'no-text'}" + class="${classMap({switch: true})}" value1="${i18n.t('qualified-pdf-upload.annotation-no')}" value2="${i18n.t('qualified-pdf-upload.annotation-yes')}" ?disabled="${this.signingProcessEnabled}" - @change=${ (e) => this.showAnnotationView(id, e.target.name) }></dbp-textswitch> + @change=${(e) => + this.showAnnotationView(id, e.target.name)}></dbp-textswitch> </div> </div> <div class="error-line"> - ${ placementMissing ? html` - ${i18n.t('label-manual-positioning-missing')} - ` : '' } + ${placementMissing + ? html` + ${i18n.t('label-manual-positioning-missing')} + ` + : ''} </div> </div> `); @@ -516,11 +554,18 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle results.push(html` <div class="file-block" id="file-block-${id}"> <div class="header"> - <span class="filename"><span class="bold-filename">${file.name}</span> (${humanFileSize(file.contentSize)})</span> - <button class="button close" + <span class="filename"> + <span class="bold-filename">${file.name}</span> + (${humanFileSize(file.contentSize)}) + </span> + <button + class="button close" title="${i18n.t('qualified-pdf-upload.download-file-button-title')}" - @click="${() => { this.downloadFileClickHandler(file, 'file-block-' + id); }}"> - <dbp-icon name="download"></dbp-icon></button> + @click="${() => { + this.downloadFileClickHandler(file, 'file-block-' + id); + }}"> + <dbp-icon name="download"></dbp-icon> + </button> </div> </div> `); @@ -549,19 +594,35 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle results.push(html` <div class="file-block error"> <div class="header"> - <span class="filename"><strong>${data.file.name}</strong> (${humanFileSize(data.file.size)})</span> + <span class="filename"> + <strong>${data.file.name}</strong> + (${humanFileSize(data.file.size)}) + </span> <div class="buttons"> - <button class="button" - title="${i18n.t('qualified-pdf-upload.re-upload-file-button-title')}" - @click="${() => {this.fileQueueingClickHandler(data.file, id);}}"><dbp-icon name="reload"></dbp-icon></button> - <button class="button" - title="${i18n.t('qualified-pdf-upload.remove-failed-file-button-title')}" - @click="${() => { this.takeFailedFileFromQueue(id); }}"> - <dbp-icon name="trash"></dbp-icon></button> + <button + class="button" + title="${i18n.t( + 'qualified-pdf-upload.re-upload-file-button-title' + )}" + @click="${() => { + this.fileQueueingClickHandler(data.file, id); + }}"> + <dbp-icon name="reload"></dbp-icon> + </button> + <button + class="button" + title="${i18n.t( + 'qualified-pdf-upload.remove-failed-file-button-title' + )}" + @click="${() => { + this.takeFailedFileFromQueue(id); + }}"> + <dbp-icon name="trash"></dbp-icon> + </button> </div> </div> <div class="bottom-line"> - <strong class="error">${data.json["hydra:description"]}</strong> + <strong class="error">${data.json['hydra:description']}</strong> </div> </div> `); @@ -579,7 +640,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle return; } - this._("#iframe").reset(); + this._('#iframe').reset(); this.signingProcessEnabled = false; this.externalAuthInProgress = false; this.signingProcessActive = false; @@ -594,24 +655,29 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle } render() { - const placeholderUrl = commonUtils.getAssetURL(pkgName, 'qualified-signature-placeholder.png'); + const placeholderUrl = commonUtils.getAssetURL( + pkgName, + 'qualified-signature-placeholder.png' + ); const i18n = this._i18n; return html` - <div class="${classMap({hidden: !this.isLoggedIn() || !this.hasSignaturePermissions() || this.isLoading()})}"> - <div class="field ${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="${classMap({ + hidden: + !this.isLoggedIn() || !this.hasSignaturePermissions() || this.isLoading(), + })}"> + <div class="field ${classMap({'is-disabled': this.isUserInterfaceDisabled()})}"> <h2>${this.activity.getName(this.lang)}</h2> - <p class="subheadline"> - ${this.activity.getDescription(this.lang)} - </p> + <p class="subheadline">${this.activity.getDescription(this.lang)}</p> <div class="control"> - - <p> - ${i18n.t('qualified-pdf-upload.upload-text')} - </p> - <button @click="${() => { this._("#file-source").setAttribute("dialog-open", ""); }}" - ?disabled="${this.signingProcessActive}" - class="button is-primary"> + <p>${i18n.t('qualified-pdf-upload.upload-text')}</p> + <button + @click="${() => { + this._('#file-source').setAttribute('dialog-open', ''); + }}" + ?disabled="${this.signingProcessActive}" + class="button is-primary"> ${i18n.t('qualified-pdf-upload.upload-button-label')} </button> <dbp-file-source @@ -631,165 +697,261 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle text="${i18n.t('qualified-pdf-upload.upload-area-text')}" button-label="${i18n.t('qualified-pdf-upload.upload-button-label')}" @dbp-file-source-file-selected="${this.onFileSelected}" - @dbp-file-source-switched="${this.onFileSourceSwitch}" - ></dbp-file-source> + @dbp-file-source-switched="${this + .onFileSourceSwitch}"></dbp-file-source> </div> </div> <div id="grid-container"> <div class="left-container"> - <div class="files-block field ${classMap({hidden: !this.queueBlockEnabled})}"> + <div + class="files-block field ${classMap({ + hidden: !this.queueBlockEnabled, + })}"> <!-- Queued files headline and queueing spinner --> - <h3 class="${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <h3 + class="${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${i18n.t('qualified-pdf-upload.queued-files-label')} </h3> <!-- Buttons to start/stop signing process and clear queue --> <div class="control field"> - <button @click="${this.clearQueuedFiles}" - ?disabled="${this.queuedFilesCount === 0 || this.signingProcessActive || this.isUserInterfaceDisabled()}" - class="button ${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <button + @click="${this.clearQueuedFiles}" + ?disabled="${this.queuedFilesCount === 0 || + this.signingProcessActive || + this.isUserInterfaceDisabled()}" + class="button ${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${i18n.t('qualified-pdf-upload.clear-all')} </button> - <button @click="${() => { this.signingProcessEnabled = true; this.signingProcessActive = true; }}" - ?disabled="${this.queuedFilesCount === 0}" - class="button is-right is-primary ${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <button + @click="${() => { + this.signingProcessEnabled = true; + this.signingProcessActive = true; + }}" + ?disabled="${this.queuedFilesCount === 0}" + class="button is-right is-primary ${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${i18n.t('qualified-pdf-upload.start-signing-process-button')} </button> <!-- <button @click="${this.stopSigningProcess}" ?disabled="${this.uploadInProgress}" id="cancel-signing-process" - class="button is-right ${classMap({hidden: !this.signingProcessActive})}"> + class="button is-right ${classMap({ + hidden: !this.signingProcessActive, + })}"> ${i18n.t('qualified-pdf-upload.stop-signing-process-button')} </button> --> </div> <!-- List of queued files --> - <div class="control file-list ${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="control file-list ${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${this.getQueuedFilesHtml()} </div> <!-- Text "queue empty" --> - <div class="empty-queue control ${classMap({hidden: this.queuedFilesCount !== 0, "is-disabled": this.isUserInterfaceDisabled()})}"> - ${i18n.t('qualified-pdf-upload.queued-files-empty1')}<br /> + <div + class="empty-queue control ${classMap({ + hidden: this.queuedFilesCount !== 0, + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> + ${i18n.t('qualified-pdf-upload.queued-files-empty1')} + <br /> ${i18n.t('qualified-pdf-upload.queued-files-empty2')} </div> </div> <!-- List of signed PDFs --> - <div class="files-block field ${classMap({hidden: this.signedFilesCount === 0, "is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="files-block field ${classMap({ + hidden: this.signedFilesCount === 0, + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> <h3>${i18n.t('qualified-pdf-upload.signed-files-label')}</h3> <!-- Button to download all signed PDFs --> <div class="field ${classMap({hidden: this.signedFilesCount === 0})}"> <div class="control"> - <button @click="${this.clearSignedFiles}" - class="button"> + <button @click="${this.clearSignedFiles}" class="button"> ${i18n.t('qualified-pdf-upload.clear-all')} </button> - <dbp-button id="zip-download-button" - value="${i18n.t('qualified-pdf-upload.download-zip-button')}" - title="${i18n.t('qualified-pdf-upload.download-zip-button-tooltip')}" - class="is-right" - @click="${this.zipDownloadClickHandler}" - type="is-primary"></dbp-button> + <dbp-button + id="zip-download-button" + value="${i18n.t( + 'qualified-pdf-upload.download-zip-button' + )}" + title="${i18n.t( + 'qualified-pdf-upload.download-zip-button-tooltip' + )}" + class="is-right" + @click="${this.zipDownloadClickHandler}" + type="is-primary"></dbp-button> </div> </div> - <div class="control"> - ${this.getSignedFilesHtml()} - </div> + <div class="control">${this.getSignedFilesHtml()}</div> </div> <!-- List of errored files --> - <div class="files-block error-files field ${classMap({hidden: this.errorFilesCount === 0, "is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="files-block error-files field ${classMap({ + hidden: this.errorFilesCount === 0, + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> <h3>${i18n.t('qualified-pdf-upload.error-files-label')}</h3> <!-- Button to upload errored files again --> <div class="field ${classMap({hidden: this.errorFilesCount === 0})}"> <div class="control"> - <button @click="${this.clearErrorFiles}" - class="button"> + <button @click="${this.clearErrorFiles}" class="button"> ${i18n.t('qualified-pdf-upload.clear-all')} </button> - <dbp-button id="re-upload-all-button" - ?disabled="${this.uploadInProgress}" - value="${i18n.t('qualified-pdf-upload.re-upload-all-button')}" - title="${i18n.t('qualified-pdf-upload.re-upload-all-button-title')}" - class="is-right" - @click="${this.reUploadAllClickHandler}" - type="is-primary"></dbp-button> + <dbp-button + id="re-upload-all-button" + ?disabled="${this.uploadInProgress}" + value="${i18n.t( + 'qualified-pdf-upload.re-upload-all-button' + )}" + title="${i18n.t( + 'qualified-pdf-upload.re-upload-all-button-title' + )}" + class="is-right" + @click="${this.reUploadAllClickHandler}" + type="is-primary"></dbp-button> </div> </div> - <div class="control"> - ${this.getErrorFilesHtml()} - </div> + <div class="control">${this.getErrorFilesHtml()}</div> </div> </div> <div class="right-container"> <!-- PDF preview --> - <div id="pdf-preview" class="field ${classMap({hidden: !this.signaturePlacementInProgress})}"> - <h3>${this.withSigBlock ? i18n.t('qualified-pdf-upload.signature-placement-label') : i18n.t('qualified-pdf-upload.preview-label')}</h3> + <div + id="pdf-preview" + class="field ${classMap({hidden: !this.signaturePlacementInProgress})}"> + <h3> + ${this.withSigBlock + ? i18n.t('qualified-pdf-upload.signature-placement-label') + : i18n.t('qualified-pdf-upload.preview-label')} + </h3> <div class="box-header"> <div class="filename"> - <strong>${this.currentFile.name}</strong> (${humanFileSize(this.currentFile !== undefined ? this.currentFile.size : 0)}) + <strong>${this.currentFile.name}</strong> + (${humanFileSize( + this.currentFile !== undefined ? this.currentFile.size : 0 + )}) </div> - <button class="button is-cancel" - @click="${this.hidePDF}"><dbp-icon name="close"></dbp-icon></button> + <button class="button is-cancel" @click="${this.hidePDF}"> + <dbp-icon name="close"></dbp-icon> + </button> </div> - <dbp-pdf-preview lang="${this.lang}" - allow-signature-rotation - signature-placeholder-image-src="${placeholderUrl}" - signature-width="80" - signature-height="29" - @dbp-pdf-preview-accept="${this.storePDFData}" - @dbp-pdf-preview-cancel="${this.hidePDF}"></dbp-pdf-preview> + <dbp-pdf-preview + lang="${this.lang}" + allow-signature-rotation + signature-placeholder-image-src="${placeholderUrl}" + signature-width="80" + signature-height="29" + @dbp-pdf-preview-accept="${this.storePDFData}" + @dbp-pdf-preview-cancel="${this.hidePDF}"></dbp-pdf-preview> </div> <!-- Annotation view --> - <div id="annotation-view" class="field ${classMap({hidden: !this.isAnnotationViewVisible || !this.allowAnnotating})}"> + <div + id="annotation-view" + class="field ${classMap({ + hidden: !this.isAnnotationViewVisible || !this.allowAnnotating, + })}"> <h2>${i18n.t('qualified-pdf-upload.annotation-view-label')}</h2> <div class="box-header"> <div class="filename"> - <strong>${this.currentFile.file !== undefined ? this.currentFile.file.name : ''}</strong> (${humanFileSize(this.currentFile.file !== undefined ? this.currentFile.file.size : 0)}) + <strong> + ${this.currentFile.file !== undefined + ? this.currentFile.file.name + : ''} + </strong> + (${humanFileSize( + this.currentFile.file !== undefined + ? this.currentFile.file.size + : 0 + )}) </div> - <button class="button is-cancel annotation" - @click="${this.hideAnnotationView}"><dbp-icon name="close" id="close-icon"></dbp-icon></button> + <button + class="button is-cancel annotation" + @click="${this.hideAnnotationView}"> + <dbp-icon name="close" id="close-icon"></dbp-icon> + </button> </div> - <dbp-pdf-annotation-view lang="${this.lang}" - @dbp-pdf-annotations-save="${this.processAnnotationEvent}" - @dbp-pdf-annotations-cancel="${this.processAnnotationCancelEvent}"></dbp-pdf-annotation-view> + <dbp-pdf-annotation-view + lang="${this.lang}" + @dbp-pdf-annotations-save="${this.processAnnotationEvent}" + @dbp-pdf-annotations-cancel="${this + .processAnnotationCancelEvent}"></dbp-pdf-annotation-view> </div> <!-- File upload progress --> - <div id="upload-progress" class="field notification is-info ${classMap({hidden: !this.uploadInProgress})}"> + <div + id="upload-progress" + class="field notification is-info ${classMap({ + hidden: !this.uploadInProgress, + })}"> <dbp-mini-spinner></dbp-mini-spinner> <strong>${this.uploadStatusFileName}</strong> ${this.uploadStatusText} </div> <!-- External auth --> - <div id="external-auth" class="files-block field ${classMap({hidden: !this.externalAuthInProgress})}"> + <div + id="external-auth" + class="files-block field ${classMap({ + hidden: !this.externalAuthInProgress, + })}"> <h3>${i18n.t('qualified-pdf-upload.current-signing-process-label')}</h3> <div class="box"> <div class="box-header"> <div class="filename"> - <strong>${this.currentFileName}</strong> (${humanFileSize(this.currentFile.file !== undefined ? this.currentFile.file.size : 0)}) + <strong>${this.currentFileName}</strong> + (${humanFileSize( + this.currentFile.file !== undefined + ? this.currentFile.file.size + : 0 + )}) </div> - <button class="button is-cancel" - title="${i18n.t('qualified-pdf-upload.stop-signing-process-button')}" - @click="${this.stopSigningProcess}"><dbp-icon name="close"></dbp-icon></button> + <button + class="button is-cancel" + title="${i18n.t( + 'qualified-pdf-upload.stop-signing-process-button' + )}" + @click="${this.stopSigningProcess}"> + <dbp-icon name="close"></dbp-icon> + </button> </div> - <external-sign-iframe id="iframe" + <external-sign-iframe + id="iframe" @signature-error="${this._onIFrameError}" - @signature-done="${this._onIFrameDone}" - ></external-sign-iframe> + @signature-done="${this._onIFrameDone}"></external-sign-iframe> </div> </div> </div> </div> </div> - <div class="notification is-warning ${classMap({hidden: this.isLoggedIn() || this.isLoading()})}"> + <div + class="notification is-warning ${classMap({ + hidden: this.isLoggedIn() || this.isLoading(), + })}"> ${i18n.t('error-login-message')} </div> - <div class="notification is-danger ${classMap({hidden: this.hasSignaturePermissions() || !this.isLoggedIn() || this.isLoading()})}"> + <div + class="notification is-danger ${classMap({ + hidden: + this.hasSignaturePermissions() || !this.isLoggedIn() || this.isLoading(), + })}"> ${i18n.t('error-permission-message')} </div> <div class="${classMap({hidden: !this.isLoading()})}"> <dbp-mini-spinner></dbp-mini-spinner> </div> - <dbp-file-sink id="file-sink" - context="${i18n.t('qualified-pdf-upload.save-field-label', {count: this.signedFilesToDownload})}" + <dbp-file-sink + id="file-sink" + context="${i18n.t('qualified-pdf-upload.save-field-label', { + count: this.signedFilesToDownload, + })}" filename="signed-documents.zip" subscribe="initial-file-handling-state:initial-file-handling-state" enabled-targets="${this.fileHandlingEnabledTargets}" @@ -797,8 +959,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle nextcloud-web-dav-url="${this.nextcloudWebDavURL}" nextcloud-name="${this.nextcloudName}" nextcloud-file-url="${this.nextcloudFileURL}" - lang="${this.lang}" - ></dbp-file-sink> + lang="${this.lang}"></dbp-file-sink> `; } } diff --git a/src/dbp-qualified-signature-pdf-upload.metadata.json b/src/dbp-qualified-signature-pdf-upload.metadata.json index 8ce6b81..72b2eef 100644 --- a/src/dbp-qualified-signature-pdf-upload.metadata.json +++ b/src/dbp-qualified-signature-pdf-upload.metadata.json @@ -1,18 +1,18 @@ { - "element": "dbp-qualified-signature-pdf-upload", - "module_src": "dbp-qualified-signature-pdf-upload.js", - "routing_name": "qualified-pdf-upload", - "name": { - "de": "Dokument persönlich signieren", - "en": "Personally sign document" - }, - "short_name": { - "de": "Dokument persönlich signieren", - "en": "Personally sign document" - }, - "description": { - "de": "Erlaubt das Hochladen von PDF-Dokumenten, um sie mit einer persönlichen elektronischen Signatur zu versehen", - "en": "Allows upload of PDF-documents to personally sign them" - }, - "subscribe": "lang,entry-point-url,nextcloud-web-app-password-url,nextcloud-webdav-url,nextcloud-name,nextcloud-auth-info,nextcloud-file-url,file-handling-enabled-targets,auth,allow-annotating" + "element": "dbp-qualified-signature-pdf-upload", + "module_src": "dbp-qualified-signature-pdf-upload.js", + "routing_name": "qualified-pdf-upload", + "name": { + "de": "Dokument persönlich signieren", + "en": "Personally sign document" + }, + "short_name": { + "de": "Dokument persönlich signieren", + "en": "Personally sign document" + }, + "description": { + "de": "Erlaubt das Hochladen von PDF-Dokumenten, um sie mit einer persönlichen elektronischen Signatur zu versehen", + "en": "Allows upload of PDF-documents to personally sign them" + }, + "subscribe": "lang,entry-point-url,nextcloud-web-app-password-url,nextcloud-webdav-url,nextcloud-name,nextcloud-auth-info,nextcloud-file-url,file-handling-enabled-targets,auth,allow-annotating" } diff --git a/src/dbp-signature-lit-element.js b/src/dbp-signature-lit-element.js index 8c17d12..cd0bf33 100644 --- a/src/dbp-signature-lit-element.js +++ b/src/dbp-signature-lit-element.js @@ -1,8 +1,8 @@ -import * as utils from "./utils"; -import * as commonUtils from "@dbp-toolkit/common/utils"; +import * as utils from './utils'; +import * as commonUtils from '@dbp-toolkit/common/utils'; import {BaseLitElement} from './base-element.js'; import {SignatureEntry} from './signature-entry.js'; -import {getPDFSignatureCount} from "./utils"; +import {getPDFSignatureCount} from './utils'; export default class DBPSignatureLitElement extends BaseLitElement { constructor() { @@ -14,7 +14,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { this._queueKey = 0; // will be set in function update - this.fileSourceUrl = ""; + this.fileSourceUrl = ''; this.fileSource = ''; this.nextcloudDefaultDir = ''; @@ -53,11 +53,10 @@ export default class DBPSignatureLitElement extends BaseLitElement { } /** - * @param {*} key - * @param {*} name + * @param {*} key + * @param {*} name */ async showAnnotationView(key, name) { - this.queuedFilesAnnotationModes[key] = name; console.log(name); @@ -90,8 +89,8 @@ export default class DBPSignatureLitElement extends BaseLitElement { } /** - * - * @param {*} event + * + * @param {*} event */ processAnnotationEvent(event) { let annotationDetails = event.detail; @@ -102,13 +101,13 @@ export default class DBPSignatureLitElement extends BaseLitElement { this.isAnnotationViewVisible = false; this.addAnnotationInProgress = false; - this.queuedFilesAnnotationModes[this.currentPreviewQueueKey] = "text-selected"; + this.queuedFilesAnnotationModes[this.currentPreviewQueueKey] = 'text-selected'; this.queuedFilesAnnotationSaved[this.currentPreviewQueueKey] = true; } /** - * - * @param {*} event + * + * @param {*} event */ processAnnotationCancelEvent(event) { let key = this.currentPreviewQueueKey; @@ -117,7 +116,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { this.queuedFilesAnnotations[key] = undefined; this.disableAnnotationsForKey(key); - this.queuedFilesAnnotationModes[this.currentPreviewQueueKey] = "no-text"; + this.queuedFilesAnnotationModes[this.currentPreviewQueueKey] = 'no-text'; this.queuedFilesAnnotationSaved[this.currentPreviewQueueKey] = false; } @@ -127,10 +126,13 @@ export default class DBPSignatureLitElement extends BaseLitElement { hideAnnotationView() { console.log('hide view - x click'); - if (this.queuedFilesAnnotationSaved[this.currentPreviewQueueKey] !== undefined && this.queuedFilesAnnotationSaved[this.currentPreviewQueueKey]) { - this.queuedFilesAnnotationModes[this.currentPreviewQueueKey] = "text-selected"; + if ( + this.queuedFilesAnnotationSaved[this.currentPreviewQueueKey] !== undefined && + this.queuedFilesAnnotationSaved[this.currentPreviewQueueKey] + ) { + this.queuedFilesAnnotationModes[this.currentPreviewQueueKey] = 'text-selected'; } else { - this.queuedFilesAnnotationModes[this.currentPreviewQueueKey] = "no-text"; + this.queuedFilesAnnotationModes[this.currentPreviewQueueKey] = 'no-text'; } this.isAnnotationViewVisible = false; this.addAnnotationInProgress = false; @@ -151,7 +153,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { const activityNameEN = this.activity.getName('en'); await commonUtils.asyncObjectForEach(annotations, async (annotation) => { - console.log("annotation", annotation); + console.log('annotation', annotation); const annotationType = (annotation.annotationType || '').trim(); const organizationNumber = (annotation.organizationNumber || '').trim(); @@ -164,8 +166,16 @@ export default class DBPSignatureLitElement extends BaseLitElement { const annotationTypeData = utils.getAnnotationTypes(annotationType); pdfFactory = await utils.addKeyValuePdfAnnotationsToAnnotationFactory( - pdfFactory, activityNameDE, activityNameEN, this.auth['user-full-name'], annotationType, - annotationTypeData.name.de, annotationTypeData.name.en, organizationNumber, value); + pdfFactory, + activityNameDE, + activityNameEN, + this.auth['user-full-name'], + annotationType, + annotationTypeData.name.de, + annotationTypeData.name.en, + organizationNumber, + value + ); }); // output the AnnotationFactory as File again @@ -287,17 +297,21 @@ export default class DBPSignatureLitElement extends BaseLitElement { // add annotations if (annotations.length > 0) { file = await this.addAnnotationsToFile(file, annotations); - console.log("uploadFile file", file); + console.log('uploadFile file', file); // Also send annotations to the server so they get included in the signature block let userText = []; for (let annotation of annotations) { const annotationTypeData = utils.getAnnotationTypes(annotation['annotationType']); - const organizationNumberText = annotation['organizationNumber'] ? ` (${annotation['organizationNumber']})` : ''; + const organizationNumberText = annotation['organizationNumber'] + ? ` (${annotation['organizationNumber']})` + : ''; userText.push({ - 'description': `${annotationTypeData.name.de || ''} / ${annotationTypeData.name.en || ''}`, - 'value': annotation['value'] + organizationNumberText + description: `${annotationTypeData.name.de || ''} / ${ + annotationTypeData.name.en || '' + }`, + value: annotation['value'] + organizationNumberText, }); } formData.append('user_text', JSON.stringify(userText)); @@ -309,14 +323,13 @@ export default class DBPSignatureLitElement extends BaseLitElement { formData.append(key, params[key]); } - // I got a 60s timeout in Google Chrome and found no way to increase that await fetch(url, { method: 'POST', headers: { - 'Authorization': 'Bearer ' + this.auth.token, + Authorization: 'Bearer ' + this.auth.token, }, - body: formData + body: formData, }) .then((response) => { /* Done. Inform the user */ @@ -337,10 +350,10 @@ export default class DBPSignatureLitElement extends BaseLitElement { return; } - let data = { + let data = { fileName: file.name, status: response.status, - json: {"hydra:description": ""} + json: {'hydra:description': ''}, }; try { @@ -356,8 +369,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { this.onFileUploadFinished(data); } - onFileSourceSwitch(event) - { + onFileSourceSwitch(event) { if (event.detail.source) { this.fileSource = event.detail.source; } @@ -376,15 +388,19 @@ export default class DBPSignatureLitElement extends BaseLitElement { // add all signed pdf-files this.signedFiles.forEach((file) => { const arr = utils.convertDataURIToBinary(file.contentUrl); - const binaryFile = new File([arr], file.name, { type: utils.getDataURIContentType(file.contentUrl) }); + const binaryFile = new File([arr], file.name, { + type: utils.getDataURIContentType(file.contentUrl), + }); files.push(binaryFile); }); this.signedFilesToDownload = files.length; - this._("#file-sink").files = files; - this._("#zip-download-button").stop(); + this._('#file-sink').files = files; + this._('#zip-download-button').stop(); // mark downloaded files buttons - const spans = this.shadowRoot.querySelectorAll('.file-block > div.header > span.filename > span.bold-filename'); - spans.forEach(span => { + const spans = this.shadowRoot.querySelectorAll( + '.file-block > div.header > span.filename > span.bold-filename' + ); + spans.forEach((span) => { span.classList.remove('bold-filename'); }); } @@ -393,7 +409,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { * @param data */ onFileUploadFinished(data) { - console.log("Override me"); + console.log('Override me'); } /** @@ -405,12 +421,16 @@ export default class DBPSignatureLitElement extends BaseLitElement { async downloadFileClickHandler(file, id) { let files = []; const arr = utils.convertDataURIToBinary(file.contentUrl); - const binaryFile = new File([arr], file.name, { type: utils.getDataURIContentType(file.contentUrl) }); + const binaryFile = new File([arr], file.name, { + type: utils.getDataURIContentType(file.contentUrl), + }); files.push(binaryFile); this.signedFilesToDownload = files.length; - this._("#file-sink").files = files; + this._('#file-sink').files = files; // mark downloaded files button - const span = this.shadowRoot.querySelector('#' + id + ' > div.header > span.filename > span.bold-filename'); + const span = this.shadowRoot.querySelector( + '#' + id + ' > div.header > span.filename > span.bold-filename' + ); if (span) { span.classList.remove('bold-filename'); } @@ -420,8 +440,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { let entry = this.queuedFiles[id]; let sigCount = await getPDFSignatureCount(entry.file); this.queuedFilesNeedsPlacement.delete(id); - if (sigCount > 0) - this.queuedFilesNeedsPlacement.set(id, true); + if (sigCount > 0) this.queuedFilesNeedsPlacement.set(id, true); } storePDFData(event) { @@ -442,7 +461,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { hidePDF(event) { // reset placement mode to "auto" if no placement was confirmed previously if (this.queuedFilesSignaturePlacements[this.currentPreviewQueueKey] === undefined) { - this.queuedFilesPlacementModes[this.currentPreviewQueueKey] = "auto"; + this.queuedFilesPlacementModes[this.currentPreviewQueueKey] = 'auto'; } this.signaturePlacementInProgress = false; } @@ -451,7 +470,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { this.queuedFilesPlacementModes[key] = name; console.log(name); - if (name === "manual") { + if (name === 'manual') { this.showPreview(key, true); } else if (this.currentPreviewQueueKey === key) { this.signaturePlacementInProgress = false; @@ -472,8 +491,6 @@ export default class DBPSignatureLitElement extends BaseLitElement { this.queueFile(ev.detail.file); } - - /** * Re-Upload all failed files */ @@ -489,7 +506,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { await this.fileQueueingClickHandler(file.file, id); }); - that._("#re-upload-all-button").stop(); + that._('#re-upload-all-button').stop(); } /** @@ -509,7 +526,7 @@ export default class DBPSignatureLitElement extends BaseLitElement { * @param key * @param withSigBlock */ - async showPreview(key, withSigBlock=false) { + async showPreview(key, withSigBlock = false) { if (this.signingProcessEnabled) { return; } @@ -521,18 +538,18 @@ export default class DBPSignatureLitElement extends BaseLitElement { // start signature placement process this.signaturePlacementInProgress = true; this.withSigBlock = withSigBlock; - const previewTag = this.getScopedTagName("dbp-pdf-preview"); + const previewTag = this.getScopedTagName('dbp-pdf-preview'); await this._(previewTag).showPDF( entry.file, withSigBlock, //this.queuedFilesPlacementModes[key] === "manual", - this.queuedFilesSignaturePlacements[key]); + this.queuedFilesSignaturePlacements[key] + ); } onLanguageChanged(e) { this.lang = e.detail.lang; } - /** * Takes a failed file off of the queue * @@ -544,7 +561,6 @@ export default class DBPSignatureLitElement extends BaseLitElement { return file; } - clearSignedFiles() { this.signedFiles = []; this.signedFilesCount = 0; @@ -556,8 +572,11 @@ export default class DBPSignatureLitElement extends BaseLitElement { } isUserInterfaceDisabled() { - return this.signaturePlacementInProgress || this.externalAuthInProgress || this.uploadInProgress || this.addAnnotationInProgress; + return ( + this.signaturePlacementInProgress || + this.externalAuthInProgress || + this.uploadInProgress || + this.addAnnotationInProgress + ); } - - } diff --git a/src/dbp-signature-verification-full.js b/src/dbp-signature-verification-full.js index 2c6dfc4..5621995 100644 --- a/src/dbp-signature-verification-full.js +++ b/src/dbp-signature-verification-full.js @@ -2,14 +2,14 @@ import {createInstance} from './i18n.js'; import {humanFileSize} from '@dbp-toolkit/common/i18next.js'; import {css, html} from 'lit'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; -import DBPSignatureLitElement from "./dbp-signature-lit-element"; -import {PdfPreview} from "./dbp-pdf-preview"; +import DBPSignatureLitElement from './dbp-signature-lit-element'; +import {PdfPreview} from './dbp-pdf-preview'; import * as commonUtils from '@dbp-toolkit/common/utils'; import {Icon, MiniSpinner, Button} from '@dbp-toolkit/common'; import * as commonStyles from '@dbp-toolkit/common/styles'; import {classMap} from 'lit/directives/class-map.js'; import {FileSource} from '@dbp-toolkit/file-handling'; -import JSONLD from "@dbp-toolkit/common/jsonld"; +import JSONLD from '@dbp-toolkit/common/jsonld'; import {name as pkgName} from './../package.json'; import metadata from './dbp-signature-verification-full.metadata.json'; import {Activity} from './activity.js'; @@ -21,29 +21,29 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme this._i18n = createInstance(); this.lang = this._i18n.language; this.entryPointUrl = ''; - this.nextcloudWebAppPasswordURL = ""; - this.nextcloudWebDavURL = ""; - this.nextcloudName = ""; - this.nextcloudFileURL = ""; + this.nextcloudWebAppPasswordURL = ''; + this.nextcloudWebDavURL = ''; + this.nextcloudName = ''; + this.nextcloudFileURL = ''; this.verifiedFiles = []; this.verifiedFilesCount = 0; this.errorFiles = []; this.errorFilesCount = 0; - this.uploadStatusFileName = ""; - this.uploadStatusText = ""; + this.uploadStatusFileName = ''; + this.uploadStatusText = ''; this.currentFile = {}; - this.currentFileName = ""; - this.currentFilePlacementMode = ""; + this.currentFileName = ''; + this.currentFilePlacementMode = ''; this.currentFileSignaturePlacement = {}; this.verificationProcessEnabled = false; this.verificationProcessActive = false; this.previewInProgress = false; this.currentPreviewQueueKey = ''; - this.fileHandlingEnabledTargets="local"; + this.fileHandlingEnabledTargets = 'local'; // will be set in function update - this.verificationUrl = ""; + this.verificationUrl = ''; } static get scopedElements() { @@ -59,35 +59,37 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme static get properties() { return { ...super.properties, - lang: { type: String }, - entryPointUrl: { type: String, attribute: 'entry-point-url' }, - nextcloudWebAppPasswordURL: { type: String, attribute: 'nextcloud-web-app-password-url' }, - nextcloudWebDavURL: { type: String, attribute: 'nextcloud-webdav-url' }, - nextcloudName: { type: String, attribute: 'nextcloud-name' }, - nextcloudFileURL: { type: String, attribute: 'nextcloud-file-url' }, - verifiedFiles: { type: Array, attribute: false }, - verifiedFilesCount: { type: Number, attribute: false }, - queuedFilesCount: { type: Number, attribute: false }, - errorFiles: { type: Array, attribute: false }, - errorFilesCount: { type: Number, attribute: false }, - uploadInProgress: { type: Boolean, attribute: false }, - uploadStatusFileName: { type: String, attribute: false }, - uploadStatusText: { type: String, attribute: false }, - verificationProcessEnabled: { type: Boolean, attribute: false }, - verificationProcessActive: { type: Boolean, attribute: false }, - queueBlockEnabled: { type: Boolean, attribute: false }, - currentFile: { type: Object, attribute: false }, - currentFileName: { type: String, attribute: false }, - previewInProgress: { type: Boolean, attribute: false }, - isSignaturePlacement: { type: Boolean, attribute: false }, - fileHandlingEnabledTargets: { type: String, attribute: 'file-handling-enabled-targets'} + lang: {type: String}, + entryPointUrl: {type: String, attribute: 'entry-point-url'}, + nextcloudWebAppPasswordURL: {type: String, attribute: 'nextcloud-web-app-password-url'}, + nextcloudWebDavURL: {type: String, attribute: 'nextcloud-webdav-url'}, + nextcloudName: {type: String, attribute: 'nextcloud-name'}, + nextcloudFileURL: {type: String, attribute: 'nextcloud-file-url'}, + verifiedFiles: {type: Array, attribute: false}, + verifiedFilesCount: {type: Number, attribute: false}, + queuedFilesCount: {type: Number, attribute: false}, + errorFiles: {type: Array, attribute: false}, + errorFilesCount: {type: Number, attribute: false}, + uploadInProgress: {type: Boolean, attribute: false}, + uploadStatusFileName: {type: String, attribute: false}, + uploadStatusText: {type: String, attribute: false}, + verificationProcessEnabled: {type: Boolean, attribute: false}, + verificationProcessActive: {type: Boolean, attribute: false}, + queueBlockEnabled: {type: Boolean, attribute: false}, + currentFile: {type: Object, attribute: false}, + currentFileName: {type: String, attribute: false}, + previewInProgress: {type: Boolean, attribute: false}, + isSignaturePlacement: {type: Boolean, attribute: false}, + fileHandlingEnabledTargets: {type: String, attribute: 'file-handling-enabled-targets'}, }; } connectedCallback() { super.connectedCallback(); // needs to be called in a function to get the variable scope of "this" - setInterval(() => { this.handleQueuedFiles(); }, 1000); + setInterval(() => { + this.handleQueuedFiles(); + }, 1000); } /** @@ -174,7 +176,7 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme * @param ev */ onFileSelected(ev) { - console.log("File was selected: ev", ev); + console.log('File was selected: ev', ev); this.queueFile(ev.detail.file); } @@ -187,7 +189,10 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme this.errorFilesCount++; this.sendSetPropertyEvent('analytics-event', { - 'category': 'officiallyVerification', 'action': 'VerificationFailed', 'name': file.json["hydra:description"]}); + category: 'officiallyVerification', + action: 'VerificationFailed', + name: file.json['hydra:description'], + }); } /** @@ -196,7 +201,9 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme onFileUploadFinished(data) { if (data.status !== 201) { this.addToErrorFiles(data); - } else if (data.json["@type"] === "https://schema.tugraz.at/ElectronicSignatureVerificationReport" ) { + } else if ( + data.json['@type'] === 'https://schema.tugraz.at/ElectronicSignatureVerificationReport' + ) { // this doesn't seem to trigger an update() execution this.verifiedFiles.push(data.json); // this triggers the correct update() execution @@ -210,16 +217,20 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme update(changedProperties) { changedProperties.forEach((oldValue, propName) => { switch (propName) { - case "lang": + case 'lang': this._i18n.changeLanguage(this.lang); break; - case "entryPointUrl": + case 'entryPointUrl': JSONLD.getInstance(this.entryPointUrl).then((jsonld) => { let apiUrlBase; try { - apiUrlBase = jsonld.getApiUrlForEntityName("EsignElectronicSignatureVerificationReport"); + apiUrlBase = jsonld.getApiUrlForEntityName( + 'EsignElectronicSignatureVerificationReport' + ); } catch (error) { - apiUrlBase = jsonld.getApiUrlForEntityName("ElectronicSignatureVerificationReport"); + apiUrlBase = jsonld.getApiUrlForEntityName( + 'ElectronicSignatureVerificationReport' + ); } this.fileSourceUrl = apiUrlBase; }); @@ -251,7 +262,7 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme await this.fileQueueingClickHandler(file.file, id); }); - that._("#re-upload-all-button").stop(); + that._('#re-upload-all-button').stop(); } /** @@ -281,7 +292,7 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme console.log(file); // start signature placement process this.previewInProgress = true; - const previewTag = this.getScopedTagName("dbp-pdf-preview"); + const previewTag = this.getScopedTagName('dbp-pdf-preview'); await this._(previewTag).showPDF(file); } @@ -336,7 +347,6 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme grid-gap: 10px; margin-top: 10px; } - `; } @@ -356,18 +366,32 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme results.push(html` <div class="file-block"> <div class="header"> - <span class="filename"><strong>${file.name}</strong> (${humanFileSize(file.size)})</span> - <button class="button close" + <span class="filename"> + <strong>${file.name}</strong> + (${humanFileSize(file.size)}) + </span> + <button + class="button close" ?disabled="${this.verificationProcessEnabled}" - title="${i18n.t('signature-verification.remove-queued-file-button-title')}" - @click="${() => { this.takeFileFromQueue(id); }}"> - <dbp-icon name="trash"></dbp-icon></button> + title="${i18n.t( + 'signature-verification.remove-queued-file-button-title' + )}" + @click="${() => { + this.takeFileFromQueue(id); + }}"> + <dbp-icon name="trash"></dbp-icon> + </button> </div> <div class="bottom-line"> <div></div> - <button class="button" + <button + class="button" ?disabled="${this.verificationProcessEnabled}" - @click="${() => { this.showPreview(id); }}">${i18n.t('signature-verification.show-preview')}</button> + @click="${() => { + this.showPreview(id); + }}"> + ${i18n.t('signature-verification.show-preview')} + </button> </div> </div> `); @@ -388,11 +412,11 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme ids.forEach((id) => { const report = this.verifiedFiles[id]; - console.log("report", report); + console.log('report', report); let signatures = []; report.signatures.forEach((signature) => { - console.log("signature", signature); + console.log('signature', signature); signatures.push(html` <tr> @@ -400,7 +424,12 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme <td>${signature.familyName}</td> <td>${signature.nationality}</td> <td>${signature.serialNumber}</td> - <td class="${classMap({"verification-ok": signature.valueMessage === "OK"})}">${signature.valueMessage}</td> + <td + class="${classMap({ + 'verification-ok': signature.valueMessage === 'OK', + })}"> + ${signature.valueMessage} + </td> </tr> `); }); @@ -418,9 +447,7 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme <th>${i18n.t('signature-verification.serial-number')}</th> <th>${i18n.t('signature-verification.value-message')}</th> </thead> - <tbody> - ${signatures} - </tbody> + <tbody>${signatures}</tbody> </table> <div class="${classMap({hidden: signatures.length !== 0})}"> ${i18n.t('signature-verification.no-signatures-found')} @@ -452,19 +479,35 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme results.push(html` <div class="file-block error"> <div class="header"> - <span class="filename"><strong>${data.file.name}</strong> (${humanFileSize(data.file.size)})</span> + <span class="filename"> + <strong>${data.file.name}</strong> + (${humanFileSize(data.file.size)}) + </span> <div class="buttons"> - <button class="button" - title="${i18n.t('signature-verification.re-upload-file-button-title')}" - @click="${() => {this.fileQueueingClickHandler(data.file, id);}}"><dbp-icon name="reload"></dbp-icon></button> - <button class="button" - title="${i18n.t('signature-verification.remove-failed-file-button-title')}" - @click="${() => { this.takeFailedFileFromQueue(id); }}"> - <dbp-icon name="trash"></dbp-icon></button> + <button + class="button" + title="${i18n.t( + 'signature-verification.re-upload-file-button-title' + )}" + @click="${() => { + this.fileQueueingClickHandler(data.file, id); + }}"> + <dbp-icon name="reload"></dbp-icon> + </button> + <button + class="button" + title="${i18n.t( + 'signature-verification.remove-failed-file-button-title' + )}" + @click="${() => { + this.takeFailedFileFromQueue(id); + }}"> + <dbp-icon name="trash"></dbp-icon> + </button> </div> </div> <div class="bottom-line"> - <strong class="error">${data.json["hydra:description"]}</strong> + <strong class="error">${data.json['hydra:description']}</strong> </div> </div> `); @@ -479,24 +522,29 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme render() { const i18n = this._i18n; - const placeholderUrl = commonUtils.getAssetURL(pkgName, 'official-signature-placeholder.png'); + const placeholderUrl = commonUtils.getAssetURL( + pkgName, + 'official-signature-placeholder.png' + ); const activity = new Activity(metadata); return html` - <div class="${classMap({hidden: !this.isLoggedIn() || !this.hasSignaturePermissions() || this.isLoading()})}"> + <div + class="${classMap({ + hidden: + !this.isLoggedIn() || !this.hasSignaturePermissions() || this.isLoading(), + })}"> <div class="field"> <h2>${activity.getName(this.lang)}</h2> - <p class="subheadline"> - ${activity.getDescription(this.lang)} - </p> + <p class="subheadline">${activity.getDescription(this.lang)}</p> <div class="control"> - - <p> - ${i18n.t('signature-verification.upload-text')} - </p> - <button @click="${() => { this._("#file-source").setAttribute("dialog-open", ""); }}" - ?disabled="${this.signingProcessActive}" - class="button is-primary"> + <p>${i18n.t('signature-verification.upload-text')}</p> + <button + @click="${() => { + this._('#file-source').setAttribute('dialog-open', ''); + }}" + ?disabled="${this.signingProcessActive}" + class="button is-primary"> ${i18n.t('signature-verification.upload-button-label')} </button> <dbp-file-source @@ -514,96 +562,142 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme text="${i18n.t('signature-verification.upload-area-text')}" button-label="${i18n.t('signature-verification.upload-button-label')}" @dbp-file-source-file-selected="${this.onFileSelected}" - @dbp-file-source-switched="${this.onFileSourceSwitch}" - ></dbp-file-source> + @dbp-file-source-switched="${this + .onFileSourceSwitch}"></dbp-file-source> </div> </div> <div id="grid-container"> <div class="left-container"> - <div class="files-block field ${classMap({hidden: !this.queueBlockEnabled})}"> + <div + class="files-block field ${classMap({ + hidden: !this.queueBlockEnabled, + })}"> <!-- Queued files headline and queueing spinner --> - <h3 class="${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <h3 + class="${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${i18n.t('signature-verification.queued-files-label')} </h3> <!-- Buttons to start/stop verification process and clear queue --> <div class="control field"> - <button @click="${this.clearQueuedFiles}" - ?disabled="${this.queuedFilesCount === 0 || this.verificationProcessActive || this.isUserInterfaceDisabled()}" - class="button ${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <button + @click="${this.clearQueuedFiles}" + ?disabled="${this.queuedFilesCount === 0 || + this.verificationProcessActive || + this.isUserInterfaceDisabled()}" + class="button ${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${i18n.t('signature-verification.clear-all')} </button> - <button @click="${() => { this.verificationProcessEnabled = true; this.verificationProcessActive = true; }}" - ?disabled="${this.queuedFilesCount === 0}" - class="button is-right is-primary ${classMap( - { - "is-disabled": this.isUserInterfaceDisabled(), - hidden: this.verificationProcessActive - })}"> - ${i18n.t('signature-verification.start-verification-process-button')} + <button + @click="${() => { + this.verificationProcessEnabled = true; + this.verificationProcessActive = true; + }}" + ?disabled="${this.queuedFilesCount === 0}" + class="button is-right is-primary ${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + hidden: this.verificationProcessActive, + })}"> + ${i18n.t( + 'signature-verification.start-verification-process-button' + )} </button> <!-- --> - <button @click="${this.stopVerificationProcess}" - ?disabled="${this.uploadInProgress}" - id="cancel-verification-process" - class="button is-right ${classMap({hidden: !this.verificationProcessActive})}"> - ${i18n.t('signature-verification.stop-verification-process-button')} + <button + @click="${this.stopVerificationProcess}" + ?disabled="${this.uploadInProgress}" + id="cancel-verification-process" + class="button is-right ${classMap({ + hidden: !this.verificationProcessActive, + })}"> + ${i18n.t( + 'signature-verification.stop-verification-process-button' + )} </button> <!-- --> </div> <!-- List of queued files --> - <div class="control file-list ${classMap({"is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="control file-list ${classMap({ + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> ${this.getQueuedFilesHtml()} </div> <!-- Text "queue empty" --> - <div class="empty-queue control ${classMap({hidden: this.queuedFilesCount !== 0, "is-disabled": this.isUserInterfaceDisabled()})}"> - ${i18n.t('signature-verification.queued-files-empty1')}<br /> + <div + class="empty-queue control ${classMap({ + hidden: this.queuedFilesCount !== 0, + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> + ${i18n.t('signature-verification.queued-files-empty1')} + <br /> ${i18n.t('signature-verification.queued-files-empty2')} </div> </div> <!-- List of errored files --> - <div class="files-block error-files field ${classMap({hidden: this.errorFilesCount === 0, "is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="files-block error-files field ${classMap({ + hidden: this.errorFilesCount === 0, + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> <h3>${i18n.t('signature-verification.error-files-label')}</h3> <!-- Button to upload errored files again --> <div class="field ${classMap({hidden: this.errorFilesCount === 0})}"> <div class="control"> - <button @click="${this.clearErrorFiles}" - class="button"> + <button @click="${this.clearErrorFiles}" class="button"> ${i18n.t('signature-verification.clear-all')} </button> - <dbp-button id="re-upload-all-button" - ?disabled="${this.uploadInProgress}" - value="${i18n.t('signature-verification.re-upload-all-button')}" - title="${i18n.t('signature-verification.re-upload-all-button-title')}" - class="is-right" - @click="${this.reUploadAllClickHandler}" - type="is-primary"></dbp-button> + <dbp-button + id="re-upload-all-button" + ?disabled="${this.uploadInProgress}" + value="${i18n.t( + 'signature-verification.re-upload-all-button' + )}" + title="${i18n.t( + 'signature-verification.re-upload-all-button-title' + )}" + class="is-right" + @click="${this.reUploadAllClickHandler}" + type="is-primary"></dbp-button> </div> </div> - <div class="control"> - ${this.getErrorFilesHtml()} - </div> + <div class="control">${this.getErrorFilesHtml()}</div> </div> </div> <div class="right-container"> <!-- PDF preview --> - <div id="pdf-preview" class="field ${classMap({hidden: !this.previewInProgress})}"> + <div + id="pdf-preview" + class="field ${classMap({hidden: !this.previewInProgress})}"> <h2>${i18n.t('signature-verification.preview-label')}</h2> <div class="box-header"> <div class="filename"> - <strong>${this.currentFile.name}</strong> (${humanFileSize(this.currentFile !== undefined ? this.currentFile.size : 0)}) + <strong>${this.currentFile.name}</strong> + (${humanFileSize( + this.currentFile !== undefined ? this.currentFile.size : 0 + )}) </div> - <button class="button is-cancel" - @click="${this.hidePDF}"><dbp-icon name="close"></dbp-icon></button> + <button class="button is-cancel" @click="${this.hidePDF}"> + <dbp-icon name="close"></dbp-icon> + </button> </div> - <dbp-pdf-preview lang="${this.lang}" - allow-signature-rotation - signature-placeholder-image-src="${placeholderUrl}" - signature-width="146" - signature-height="42" - @dbp-pdf-preview-cancel="${this.hidePDF}"></dbp-pdf-preview> + <dbp-pdf-preview + lang="${this.lang}" + allow-signature-rotation + signature-placeholder-image-src="${placeholderUrl}" + signature-width="146" + signature-height="42" + @dbp-pdf-preview-cancel="${this.hidePDF}"></dbp-pdf-preview> </div> <!-- File upload progress --> - <div id="upload-progress" class="field notification is-info ${classMap({hidden: !this.uploadInProgress})}"> + <div + id="upload-progress" + class="field notification is-info ${classMap({ + hidden: !this.uploadInProgress, + })}"> <dbp-mini-spinner></dbp-mini-spinner> <strong>${this.uploadStatusFileName}</strong> ${this.uploadStatusText} @@ -611,26 +705,34 @@ class SignatureVerificationFull extends ScopedElementsMixin(DBPSignatureLitEleme </div> </div> <!-- List of verified PDFs --> - <div class="verified-files files-block field ${classMap({hidden: this.verifiedFilesCount === 0, "is-disabled": this.isUserInterfaceDisabled()})}"> + <div + class="verified-files files-block field ${classMap({ + hidden: this.verifiedFilesCount === 0, + 'is-disabled': this.isUserInterfaceDisabled(), + })}"> <h3>${i18n.t('signature-verification.verified-files-label')}</h3> <!-- Button to clear verified PDFs --> <div class="field ${classMap({hidden: this.verifiedFilesCount === 0})}"> <div class="control"> - <button @click="${this.clearVerifiedFiles}" - class="button"> + <button @click="${this.clearVerifiedFiles}" class="button"> ${i18n.t('signature-verification.clear-all')} </button> </div> </div> - <div class="control"> - ${this.getVerifiedFilesHtml()} - </div> + <div class="control">${this.getVerifiedFilesHtml()}</div> </div> </div> - <div class="notification is-warning ${classMap({hidden: this.isLoggedIn() || this.isLoading()})}"> + <div + class="notification is-warning ${classMap({ + hidden: this.isLoggedIn() || this.isLoading(), + })}"> ${i18n.t('error-login-message')} </div> - <div class="notification is-danger ${classMap({hidden: this.hasSignaturePermissions() || !this.isLoggedIn() || this.isLoading()})}"> + <div + class="notification is-danger ${classMap({ + hidden: + this.hasSignaturePermissions() || !this.isLoggedIn() || this.isLoading(), + })}"> ${i18n.t('error-permission-message')} </div> <div class="${classMap({hidden: !this.isLoading()})}"> diff --git a/src/dbp-signature-verification-full.metadata.json b/src/dbp-signature-verification-full.metadata.json index 3e5a5f0..62c1cff 100644 --- a/src/dbp-signature-verification-full.metadata.json +++ b/src/dbp-signature-verification-full.metadata.json @@ -1,18 +1,18 @@ { - "element": "dbp-signature-verification-full", - "module_src": "dbp-signature-verification-full.js", - "routing_name": "signature-verification-full", - "name": { - "de": "Signierte Dokumente verifizieren", - "en": "Verify signed documents" - }, - "short_name": { - "de": "Signierte Dokumente verifizieren", - "en": "Verify signed documents" - }, - "description": { - "de": "Erlaubt das Verifizieren von signierten PDF-Dokumenten", - "en": "Allows verification of signed PDF-documents" - }, - "subscribe": "lang,entry-point-url,nextcloud-web-app-password-url,nextcloud-webdav-url,nextcloud-name,nextcloud-file-url,file-handling-enabled-targets,auth" + "element": "dbp-signature-verification-full", + "module_src": "dbp-signature-verification-full.js", + "routing_name": "signature-verification-full", + "name": { + "de": "Signierte Dokumente verifizieren", + "en": "Verify signed documents" + }, + "short_name": { + "de": "Signierte Dokumente verifizieren", + "en": "Verify signed documents" + }, + "description": { + "de": "Erlaubt das Verifizieren von signierten PDF-Dokumenten", + "en": "Allows verification of signed PDF-documents" + }, + "subscribe": "lang,entry-point-url,nextcloud-web-app-password-url,nextcloud-webdav-url,nextcloud-name,nextcloud-file-url,file-handling-enabled-targets,auth" } diff --git a/src/dbp-signature-verification.js b/src/dbp-signature-verification.js index 0c2bcb9..d69b5b8 100644 --- a/src/dbp-signature-verification.js +++ b/src/dbp-signature-verification.js @@ -1,13 +1,12 @@ import {createInstance} from './i18n.js'; import {css, html} from 'lit'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; -import DBPSignatureLitElement from "./dbp-signature-lit-element"; +import DBPSignatureLitElement from './dbp-signature-lit-element'; import * as commonUtils from '@dbp-toolkit/common/utils'; import * as commonStyles from '@dbp-toolkit/common/styles'; import metadata from './dbp-signature-verification.metadata.json'; import {Activity} from './activity.js'; - class SignatureVerification extends ScopedElementsMixin(DBPSignatureLitElement) { constructor() { super(); @@ -16,20 +15,20 @@ class SignatureVerification extends ScopedElementsMixin(DBPSignatureLitElement) } static get scopedElements() { - return { }; + return {}; } static get properties() { return { ...super.properties, - lang: { type: String }, + lang: {type: String}, }; } update(changedProperties) { changedProperties.forEach((oldValue, propName) => { switch (propName) { - case "lang": + case 'lang': this._i18n.changeLanguage(this.lang); break; } @@ -59,18 +58,18 @@ class SignatureVerification extends ScopedElementsMixin(DBPSignatureLitElement) margin-bottom: 0px; } - .int-link-internal{ + .int-link-internal { transition: background-color 0.15s, color 0.15s; border-bottom: var(--dbp-border-dark); } - - .int-link-internal:hover{ + + .int-link-internal:hover { background-color: var(--dbp-hover-base); color: var(--dbp-hover-text); } - - .int-link-internal:after{ - content: "\\00a0\\00a0\\00a0"; + + .int-link-internal:after { + content: '\\00a0\\00a0\\00a0'; background-image: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3Ardf%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%228.6836mm%22%20width%3D%225.2043mm%22%20version%3D%221.1%22%20xmlns%3Acc%3D%22http%3A%2F%2Fcreativecommons.org%2Fns%23%22%20xmlns%3Adc%3D%22http%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2F%22%20viewBox%3D%220%200%2018.440707%2030.768605%22%3E%3Cg%20transform%3D%22translate(-382.21%20-336.98)%22%3E%3Cpath%20style%3D%22stroke-linejoin%3Around%3Bstroke%3A%23000%3Bstroke-linecap%3Around%3Bstroke-miterlimit%3A10%3Bstroke-width%3A2%3Bfill%3Anone%22%20d%3D%22m383.22%20366.74%2016.43-14.38-16.43-14.37%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E'); background-size: 73%; background-repeat: no-repeat; @@ -80,9 +79,9 @@ class SignatureVerification extends ScopedElementsMixin(DBPSignatureLitElement) animation: 0.15s linkIconOut; font-size: 103%; } - - .int-link-internal:hover::after{ - content: "\\00a0\\00a0\\00a0"; + + .int-link-internal:hover::after { + content: '\\00a0\\00a0\\00a0'; background-image: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3Ardf%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%228.6836mm%22%20width%3D%225.2043mm%22%20version%3D%221.1%22%20xmlns%3Acc%3D%22http%3A%2F%2Fcreativecommons.org%2Fns%23%22%20xmlns%3Adc%3D%22http%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2F%22%20viewBox%3D%220%200%2018.440707%2030.768605%22%3E%3Cg%20transform%3D%22translate(-382.21%20-336.98)%22%3E%3Cpath%20style%3D%22stroke-linejoin%3Around%3Bstroke%3A%23FFF%3Bstroke-linecap%3Around%3Bstroke-miterlimit%3A10%3Bstroke-width%3A2%3Bfill%3Anone%22%20d%3D%22m383.22%20366.74%2016.43-14.38-16.43-14.37%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E'); background-size: 73%; background-repeat: no-repeat; @@ -93,7 +92,7 @@ class SignatureVerification extends ScopedElementsMixin(DBPSignatureLitElement) font-size: 103%; } - .subheadline{ + .subheadline { font-style: italic; padding-left: 2em; margin-top: -1px; @@ -108,16 +107,16 @@ class SignatureVerification extends ScopedElementsMixin(DBPSignatureLitElement) const activity = new Activity(metadata); return html` <h2>${activity.getName(this.lang)}</h2> - <p class="subheadline"> - ${activity.getDescription(this.lang)} - </p> - <p> - ${i18n.t('signature-verification-extern.description-text')} - </p> - <a target="_blank" rel="noopener" class="int-link-internal" href="https://www.signaturpruefung.gv.at">${i18n.t('signature-verification-extern.link-label')}</a> - <p> - ${i18n.t('signature-verification-extern.adobe-reader-text')} - </p> + <p class="subheadline">${activity.getDescription(this.lang)}</p> + <p>${i18n.t('signature-verification-extern.description-text')}</p> + <a + target="_blank" + rel="noopener" + class="int-link-internal" + href="https://www.signaturpruefung.gv.at"> + ${i18n.t('signature-verification-extern.link-label')} + </a> + <p>${i18n.t('signature-verification-extern.adobe-reader-text')}</p> <slot name="additional-information"></slot> `; } diff --git a/src/dbp-signature-verification.metadata.json b/src/dbp-signature-verification.metadata.json index 8a688b4..d8110dc 100644 --- a/src/dbp-signature-verification.metadata.json +++ b/src/dbp-signature-verification.metadata.json @@ -1,18 +1,18 @@ { - "element": "dbp-signature-verification", - "module_src": "dbp-signature-verification.js", - "routing_name": "signature-verification", - "name": { - "de": "Signierte Dokumente verifizieren", - "en": "Verify signed documents" - }, - "short_name": { - "de": "Signierte Dokumente verifizieren", - "en": "Verify signed documents" - }, - "description": { - "de": "Erlaubt das Verifizieren von signierten PDF-Dokumenten", - "en": "Allows verification of signed PDF-documents" - }, - "subscribe": "lang,entry-point-url,auth,html-overrides" + "element": "dbp-signature-verification", + "module_src": "dbp-signature-verification.js", + "routing_name": "signature-verification", + "name": { + "de": "Signierte Dokumente verifizieren", + "en": "Verify signed documents" + }, + "short_name": { + "de": "Signierte Dokumente verifizieren", + "en": "Verify signed documents" + }, + "description": { + "de": "Erlaubt das Verifizieren von signierten PDF-Dokumenten", + "en": "Allows verification of signed PDF-documents" + }, + "subscribe": "lang,entry-point-url,auth,html-overrides" } diff --git a/src/dbp-signature.js b/src/dbp-signature.js index d8e83b1..8166105 100644 --- a/src/dbp-signature.js +++ b/src/dbp-signature.js @@ -1,7 +1,7 @@ import {AppShell} from '@dbp-toolkit/app-shell'; import * as commonUtils from '@dbp-toolkit/common/utils'; -import {Translated} from "@dbp-toolkit/common/src/translated"; -import {TUGrazLogo} from "@dbp-toolkit/app-shell/src/tugraz-logo"; +import {Translated} from '@dbp-toolkit/common/src/translated'; +import {TUGrazLogo} from '@dbp-toolkit/app-shell/src/tugraz-logo'; commonUtils.defineCustomElement('dbp-signature', AppShell); commonUtils.defineCustomElement('dbp-translated', Translated); diff --git a/src/ext-sign-iframe.js b/src/ext-sign-iframe.js index b760134..a8bb341 100644 --- a/src/ext-sign-iframe.js +++ b/src/ext-sign-iframe.js @@ -5,13 +5,12 @@ import {ScopedElementsMixin} from '@open-wc/scoped-elements'; /** * Set the URL via setUrl(), reset via reset(). - * + * * Emits two custom events: * signature-error with a "message" * signature-done with an "id" */ export class ExternalSignIFrame extends ScopedElementsMixin(LitElement) { - constructor() { super(); this._loading = false; @@ -20,13 +19,13 @@ export class ExternalSignIFrame extends ScopedElementsMixin(LitElement) { static get scopedElements() { return { - 'dbp-mini-spinner': MiniSpinner, + 'dbp-mini-spinner': MiniSpinner, }; } static get properties() { return { - _loading: { type: Boolean, attribute: false }, + _loading: {type: Boolean, attribute: false}, }; } @@ -47,28 +46,32 @@ export class ExternalSignIFrame extends ScopedElementsMixin(LitElement) { if (data.cause) { error = `${error}: ${data.cause}`; } - this.dispatchEvent(new CustomEvent('signature-error', { - detail: { - message: error, - } - })); + this.dispatchEvent( + new CustomEvent('signature-error', { + detail: { + message: error, + }, + }) + ); } else if (data.type === 'pdf-as-callback') { - this.dispatchEvent(new CustomEvent('signature-done', { - detail: { - id: data.sessionId, - } - })); + this.dispatchEvent( + new CustomEvent('signature-done', { + detail: { + id: data.sessionId, + }, + }) + ); } } setUrl(url) { - let iframe = this.renderRoot.querySelector("#iframe"); + let iframe = this.renderRoot.querySelector('#iframe'); this._loading = true; iframe.src = url; } reset() { - this.setUrl("about:blank"); + this.setUrl('about:blank'); } static get styles() { @@ -93,18 +96,23 @@ export class ExternalSignIFrame extends ScopedElementsMixin(LitElement) { } render() { - let onDone = (event) => { this._loading = false; }; return html` - ${ this._loading ? html`<dbp-mini-spinner></dbp-mini-spinner>` : html`` } + ${this._loading + ? html` + <dbp-mini-spinner></dbp-mini-spinner> + ` + : html``} <!-- "scrolling" is deprecated, but still seem to help --> - <iframe id="iframe" class=${classMap({hidden: this._loading})} + <iframe + id="iframe" + class=${classMap({hidden: this._loading})} @load="${onDone}" @error="${onDone}" scrolling="no"></iframe> `; } -} \ No newline at end of file +} diff --git a/src/i18n.js b/src/i18n.js index 975c199..0c6fedc 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -5,4 +5,4 @@ import en from './i18n/en/translation.json'; export function createInstance() { return _createInstance({en: en, de: de}, 'de', 'en'); -} \ No newline at end of file +} diff --git a/src/i18n/de/translation.json b/src/i18n/de/translation.json index 74465c5..0f4772c 100644 --- a/src/i18n/de/translation.json +++ b/src/i18n/de/translation.json @@ -1,141 +1,141 @@ { - "official-pdf-upload": { - "upload-text": "Die Amtssignatur des \"Elektronische Signaturservice\" ist eine Applikation, mit der Sie PDF-Dateien mit einer elektronischen Amtssignatur versehen können.", - "upload-area-text": "Sie können in diesem Bereich PDF-Dokumente mit einer Maximalgröße von bis zu 32MB pro Dokument per Drag & Drop oder per Direktauswahl hochladen. Die PDF-Dokumente dürfen sich auch in ZIP-Dateien befinden.", - "queued-files-label": "Dokumente in der Warteschlange", - "queued-files-empty1": "Kein Dokument in der Warteschlange", - "queued-files-empty2": "Sie können jetzt ein neues Dokument hochladen", - "remove-failed-file-button-title": "Fehlgeschlagenes Dokument entfernen", - "remove-queued-file-button-title": "Dokument aus der Warteschlange entfernen", - "clear-all": "Alle entfernen", - "start-signing-process-button": "Signatur starten", - "stop-signing-process-button": "Unterbrechen", - "show-preview": "Dokument anzeigen", - "positioning-automatic": "Auto", - "positioning-manual": "Manuell", - "preview-label": "Dokumentenansicht", - "signed-files-label": "Signierte Dokumente", - "download-zip-button": "Alle speichern unter", - "download-zip-button-tooltip": "Alle signierten Dokumente speichern", - "upload-button-label": "PDF-Dokumente auswählen", - "download-file-button-title": "Signiertes PDF Dokument speichern", - "error-files-label": "Fehlgeschlagene Dokumente", - "re-upload-file-button-title": "Erneut in die Warteschlange stellen", - "upload-status-file-text": "({{fileSize}}) wird hochgeladen und verarbeitet...", - "re-upload-all-button": "Alle wiederholen", - "re-upload-all-button-title": "Alle fehlgeschlagen Signaturvorgänge erneut in die Warteschlange stellen", - "signature-placement-label": "Signatur platzieren", - "positioning": "Positionierung", - "confirm-page-leave": "Sind Sie sicher, dass Sie die Seite verlassen wollen? Es stehen signierte Dokumente zum Download bereit.", - "file-picker-context": "PDF-Dokumente zum Signieren auswählen (max. 32 MB pro Datei)", - "annotation": "Anmerkungen", - "annotation-no": "Nein", - "annotation-yes": "Ja", - "annotation-view-label": "Anmerkungen zu Dokument hinzufügen" - }, - "qualified-pdf-upload": { - "save-field-label": "{{count}} Datei speichern", - "save-field-label_plural": "{{count}} Dateien speichern", - "upload-text": "Das \"Elektronische Signaturservice\" ist eine Applikation, mit der Sie PDF-Dateien mit einer persönlichen, elektronischen (qualifizierten) Signatur versehen können. Eine qualifizierte Signatur ist Ihre persönliche Unterschrift im Internet und der eigenhändigen Unterschrift rechtlich gleichgestellt.", - "upload-area-text": "Sie können in diesem Bereich PDF-Dokumente mit einer Maximalgröße von bis zu 32MB pro Dokument per Drag & Drop oder per Direktauswahl hochladen. Die PDF-Dokumente dürfen sich auch in ZIP-Dateien befinden.", - "current-signing-process-label": "Aktueller Signaturprozess", - "queued-files-label": "Dokumente in der Warteschlange", - "queued-files-empty1": "Kein Dokument in der Warteschlange", - "queued-files-empty2": "Sie können jetzt ein neues Dokument hochladen", - "remove-failed-file-button-title": "Fehlgeschlagenes Dokument entfernen", - "remove-queued-file-button-title": "Dokument aus der Warteschlange entfernen", - "clear-all": "Alle entfernen", - "start-signing-process-button": "Signatur starten", - "stop-signing-process-button": "Unterbrechen", - "show-preview": "Dokument anzeigen", - "positioning-automatic": "Auto", - "positioning-manual": "Manuell", - "preview-label": "Dokumentenansicht", - "signed-files-label": "Signierte Dokumente", - "download-zip-button": "Alle speichern unter", - "download-zip-button-tooltip": "Alle signierten Dokumente speichern", - "upload-button-label": "PDF-Dokumente auswählen", - "download-file-button-title": "Signiertes PDF Dokument speichern", - "error-files-label": "Fehlgeschlagene Dokumente", - "re-upload-file-button-title": "Erneut in die Warteschlange stellen", - "upload-status-file-text": "({{fileSize}}) wird hochgeladen und verarbeitet...", - "re-upload-all-button": "Alle wiederholen", - "re-upload-all-button-title": "Alle fehlgeschlagen Signaturvorgänge erneut in die Warteschlange stellen", - "signature-placement-label": "Signatur platzieren", - "positioning": "Positionierung", - "confirm-page-leave": "Sind Sie sicher, dass Sie die Seite verlassen wollen? Es stehen signierte Dokumente zum Download bereit.", - "file-picker-context": "PDF-Dokumente zum Signieren auswählen (max. 32 MB pro Datei)", - "annotation": "Anmerkungen", - "annotation-no": "Nein", - "annotation-yes": "Ja", - "annotation-view-label": "Anmerkungen zu Dokument hinzufügen" - }, - "signature-verification": { - "upload-text": "Sie können in diesem Bereich PDF-Dokumente mit einer Maximalgröße von bis zu 32MB pro Dokument hochladen. Die PDF-Dokumente dürfen sich auch in ZIP-Dateien befinden.", - "upload-area-text": "Sie können in diesem Bereich PDF-Dokumente mit einer Maximalgröße von bis zu 32MB pro Dokument per Drag & Drop oder per Direktauswahl hochladen. Die PDF-Dokumente dürfen sich auch in ZIP-Dateien befinden.", - "queued-files-label": "Dokumente in der Warteschlange", - "queued-files-empty1": "Kein Dokument in der Warteschlange", - "queued-files-empty2": "Sie können jetzt ein neues Dokument hochladen", - "remove-failed-file-button-title": "Fehlgeschlagenes Dokument entfernen", - "remove-queued-file-button-title": "Dokument aus der Warteschlange entfernen", - "clear-all": "Alle entfernen", - "start-verification-process-button": "Verifikation starten", - "stop-verification-process-button": "Verifikation unterbrechen", - "show-preview": "Dokument anzeigen", - "preview-label": "Dokumentenansicht", - "verified-files-label": "Verifizierte Dokumente", - "upload-button-label": "PDF-Dokumente auswählen", - "error-files-label": "Fehlgeschlagene Dokumente", - "re-upload-file-button-title": "Erneut in die Warteschlange stellen", - "upload-status-file-text": "({{fileSize}}) wird hochgeladen und verifiziert...", - "re-upload-all-button": "Alle wiederholen", - "re-upload-all-button-title": "Alle fehlgeschlagenen Verifikationsprozesse erneut in die Warteschlange stellen", - "given-name": "Vorname", - "last-name": "Nachname", - "nationality": "Nationalität", - "serial-number": "Seriennummer", - "value-message": "Überprüfung", - "no-signatures-found": "Es wurden keine Signaturen gefunden.", - "confirm-page-leave": "Sind Sie sicher, dass Sie die Seite verlassen wollen? Es stehen signierte Dokumente zum Download bereit.", - "file-picker-context": "PDF-Dokumente zum Verifizieren auswählen (max. 32 MB pro Datei)" - }, - "signature-verification-extern": { - "description-text": "Um eine PDF-Signatur auf ihre Gültigkeit zu überprüfen, benutzen Sie bitte das Verifikationsservice der Rundfunk und Telekom Regulierungs-GmbH. Mit diesem Verifikationsservice können Sie überprüfen, ob das Dokument eine valide Signatur enthält.", - "link-label": "Zum RTR Verifikationsservice wechseln", - "adobe-reader-text": "Des Weiteren besteht auch die Möglichkeit, das Dokument lokal mit dem Adobe Reader zu überprüfen." - }, - "pdf-preview": { - "first-page": "Erste Seite", - "previous-page": "Vorherige Seite", - "next-page": "Nächste Seite", - "last-page": "Letzte Seite", - "page-count": "von {{totalPages}}", - "rotate-signature": "Signatur im Uhrzeigersinn rotieren", - "rotate": "Signatur rotieren", - "continue": "Platzierung bestätigen", - "error-message": "Fehler: Dieses Dokument ist beschädigt." - }, - "annotation-view": { - "delete-all-button-text": "Alle entfernen", - "delete-all-button-title": "Alle entfernen", - "save-all-button-text": "Für Dokument übernehmen", - "save-all-button-title": "Für Dokument übernehmen", - "insert-field": "Neues Feld einfügen", - "remove-field": "Feld löschen", - "businessnumber-placeholder": "Fügen Sie hier die Geschäftszahl ein (z.B. 247/1/2020-S)", - "intended-use-placeholder": "Fügen Sie hier den gewünschten Text ein", - "introduction": "In diesem Bereich können Sie zusätzlichen Text definieren, der in der Signatur enthalten sein soll. Klicken Sie dafür auf \"Neues Feld einfügen\" und wählen Sie das gewünschte Feld aus. Klicken Sie dann auf das \"+\" um das Feld einzufügen und den gewünschten Text einzugeben.", - "empty-annotation-title": "{{annotationType}} ist leer!", - "empty-annotation-message": "Bitte tragen Sie einen Wert für die gewählte Anmerkung ein.", - "empty-organization-title": "Organisation wurde nicht ausgewählt!", - "empty-organization-message": "Bitte wählen Sie Ihre Organisation aus, bevor Sie die gewählte Anmerkung übernehmen.", - "invalid-annotation-text-title": "Ungültiger Eingabewert!", - "invalid-annotation-text-message": "Sie haben ein oder mehrere ungültige Zeichen eingegeben. Zulässige Sonderzeichen sind: \\/ !=+-_*&()" - }, - "error-permission-message": "Sie müssen das Recht auf Amtssignaturen besitzen um diese Funktion nutzen zu können!", - "error-login-message": "Sie müssen angemeldet sein um diese Funktion nutzen zu können!", - "error-cancel-message": "Der Signaturprozess wurde manuell abgebrochen.", - "error-rights-message": "Abbruch auf Grund mangelnder Rechte Ihres Accounts.", - "label-manual-positioning-missing": "Bestehende Signatur vorhanden, bitte wählen Sie ihre Positionierung manuell.", - "error-manual-positioning-missing": "Ein oder mehrere Signaturen in der Warteschlange müssen manuell positioniert werden." + "official-pdf-upload": { + "upload-text": "Die Amtssignatur des \"Elektronische Signaturservice\" ist eine Applikation, mit der Sie PDF-Dateien mit einer elektronischen Amtssignatur versehen können.", + "upload-area-text": "Sie können in diesem Bereich PDF-Dokumente mit einer Maximalgröße von bis zu 32MB pro Dokument per Drag & Drop oder per Direktauswahl hochladen. Die PDF-Dokumente dürfen sich auch in ZIP-Dateien befinden.", + "queued-files-label": "Dokumente in der Warteschlange", + "queued-files-empty1": "Kein Dokument in der Warteschlange", + "queued-files-empty2": "Sie können jetzt ein neues Dokument hochladen", + "remove-failed-file-button-title": "Fehlgeschlagenes Dokument entfernen", + "remove-queued-file-button-title": "Dokument aus der Warteschlange entfernen", + "clear-all": "Alle entfernen", + "start-signing-process-button": "Signatur starten", + "stop-signing-process-button": "Unterbrechen", + "show-preview": "Dokument anzeigen", + "positioning-automatic": "Auto", + "positioning-manual": "Manuell", + "preview-label": "Dokumentenansicht", + "signed-files-label": "Signierte Dokumente", + "download-zip-button": "Alle speichern unter", + "download-zip-button-tooltip": "Alle signierten Dokumente speichern", + "upload-button-label": "PDF-Dokumente auswählen", + "download-file-button-title": "Signiertes PDF Dokument speichern", + "error-files-label": "Fehlgeschlagene Dokumente", + "re-upload-file-button-title": "Erneut in die Warteschlange stellen", + "upload-status-file-text": "({{fileSize}}) wird hochgeladen und verarbeitet...", + "re-upload-all-button": "Alle wiederholen", + "re-upload-all-button-title": "Alle fehlgeschlagen Signaturvorgänge erneut in die Warteschlange stellen", + "signature-placement-label": "Signatur platzieren", + "positioning": "Positionierung", + "confirm-page-leave": "Sind Sie sicher, dass Sie die Seite verlassen wollen? Es stehen signierte Dokumente zum Download bereit.", + "file-picker-context": "PDF-Dokumente zum Signieren auswählen (max. 32 MB pro Datei)", + "annotation": "Anmerkungen", + "annotation-no": "Nein", + "annotation-yes": "Ja", + "annotation-view-label": "Anmerkungen zu Dokument hinzufügen" + }, + "qualified-pdf-upload": { + "save-field-label": "{{count}} Datei speichern", + "save-field-label_plural": "{{count}} Dateien speichern", + "upload-text": "Das \"Elektronische Signaturservice\" ist eine Applikation, mit der Sie PDF-Dateien mit einer persönlichen, elektronischen (qualifizierten) Signatur versehen können. Eine qualifizierte Signatur ist Ihre persönliche Unterschrift im Internet und der eigenhändigen Unterschrift rechtlich gleichgestellt.", + "upload-area-text": "Sie können in diesem Bereich PDF-Dokumente mit einer Maximalgröße von bis zu 32MB pro Dokument per Drag & Drop oder per Direktauswahl hochladen. Die PDF-Dokumente dürfen sich auch in ZIP-Dateien befinden.", + "current-signing-process-label": "Aktueller Signaturprozess", + "queued-files-label": "Dokumente in der Warteschlange", + "queued-files-empty1": "Kein Dokument in der Warteschlange", + "queued-files-empty2": "Sie können jetzt ein neues Dokument hochladen", + "remove-failed-file-button-title": "Fehlgeschlagenes Dokument entfernen", + "remove-queued-file-button-title": "Dokument aus der Warteschlange entfernen", + "clear-all": "Alle entfernen", + "start-signing-process-button": "Signatur starten", + "stop-signing-process-button": "Unterbrechen", + "show-preview": "Dokument anzeigen", + "positioning-automatic": "Auto", + "positioning-manual": "Manuell", + "preview-label": "Dokumentenansicht", + "signed-files-label": "Signierte Dokumente", + "download-zip-button": "Alle speichern unter", + "download-zip-button-tooltip": "Alle signierten Dokumente speichern", + "upload-button-label": "PDF-Dokumente auswählen", + "download-file-button-title": "Signiertes PDF Dokument speichern", + "error-files-label": "Fehlgeschlagene Dokumente", + "re-upload-file-button-title": "Erneut in die Warteschlange stellen", + "upload-status-file-text": "({{fileSize}}) wird hochgeladen und verarbeitet...", + "re-upload-all-button": "Alle wiederholen", + "re-upload-all-button-title": "Alle fehlgeschlagen Signaturvorgänge erneut in die Warteschlange stellen", + "signature-placement-label": "Signatur platzieren", + "positioning": "Positionierung", + "confirm-page-leave": "Sind Sie sicher, dass Sie die Seite verlassen wollen? Es stehen signierte Dokumente zum Download bereit.", + "file-picker-context": "PDF-Dokumente zum Signieren auswählen (max. 32 MB pro Datei)", + "annotation": "Anmerkungen", + "annotation-no": "Nein", + "annotation-yes": "Ja", + "annotation-view-label": "Anmerkungen zu Dokument hinzufügen" + }, + "signature-verification": { + "upload-text": "Sie können in diesem Bereich PDF-Dokumente mit einer Maximalgröße von bis zu 32MB pro Dokument hochladen. Die PDF-Dokumente dürfen sich auch in ZIP-Dateien befinden.", + "upload-area-text": "Sie können in diesem Bereich PDF-Dokumente mit einer Maximalgröße von bis zu 32MB pro Dokument per Drag & Drop oder per Direktauswahl hochladen. Die PDF-Dokumente dürfen sich auch in ZIP-Dateien befinden.", + "queued-files-label": "Dokumente in der Warteschlange", + "queued-files-empty1": "Kein Dokument in der Warteschlange", + "queued-files-empty2": "Sie können jetzt ein neues Dokument hochladen", + "remove-failed-file-button-title": "Fehlgeschlagenes Dokument entfernen", + "remove-queued-file-button-title": "Dokument aus der Warteschlange entfernen", + "clear-all": "Alle entfernen", + "start-verification-process-button": "Verifikation starten", + "stop-verification-process-button": "Verifikation unterbrechen", + "show-preview": "Dokument anzeigen", + "preview-label": "Dokumentenansicht", + "verified-files-label": "Verifizierte Dokumente", + "upload-button-label": "PDF-Dokumente auswählen", + "error-files-label": "Fehlgeschlagene Dokumente", + "re-upload-file-button-title": "Erneut in die Warteschlange stellen", + "upload-status-file-text": "({{fileSize}}) wird hochgeladen und verifiziert...", + "re-upload-all-button": "Alle wiederholen", + "re-upload-all-button-title": "Alle fehlgeschlagenen Verifikationsprozesse erneut in die Warteschlange stellen", + "given-name": "Vorname", + "last-name": "Nachname", + "nationality": "Nationalität", + "serial-number": "Seriennummer", + "value-message": "Überprüfung", + "no-signatures-found": "Es wurden keine Signaturen gefunden.", + "confirm-page-leave": "Sind Sie sicher, dass Sie die Seite verlassen wollen? Es stehen signierte Dokumente zum Download bereit.", + "file-picker-context": "PDF-Dokumente zum Verifizieren auswählen (max. 32 MB pro Datei)" + }, + "signature-verification-extern": { + "description-text": "Um eine PDF-Signatur auf ihre Gültigkeit zu überprüfen, benutzen Sie bitte das Verifikationsservice der Rundfunk und Telekom Regulierungs-GmbH. Mit diesem Verifikationsservice können Sie überprüfen, ob das Dokument eine valide Signatur enthält.", + "link-label": "Zum RTR Verifikationsservice wechseln", + "adobe-reader-text": "Des Weiteren besteht auch die Möglichkeit, das Dokument lokal mit dem Adobe Reader zu überprüfen." + }, + "pdf-preview": { + "first-page": "Erste Seite", + "previous-page": "Vorherige Seite", + "next-page": "Nächste Seite", + "last-page": "Letzte Seite", + "page-count": "von {{totalPages}}", + "rotate-signature": "Signatur im Uhrzeigersinn rotieren", + "rotate": "Signatur rotieren", + "continue": "Platzierung bestätigen", + "error-message": "Fehler: Dieses Dokument ist beschädigt." + }, + "annotation-view": { + "delete-all-button-text": "Alle entfernen", + "delete-all-button-title": "Alle entfernen", + "save-all-button-text": "Für Dokument übernehmen", + "save-all-button-title": "Für Dokument übernehmen", + "insert-field": "Neues Feld einfügen", + "remove-field": "Feld löschen", + "businessnumber-placeholder": "Fügen Sie hier die Geschäftszahl ein (z.B. 247/1/2020-S)", + "intended-use-placeholder": "Fügen Sie hier den gewünschten Text ein", + "introduction": "In diesem Bereich können Sie zusätzlichen Text definieren, der in der Signatur enthalten sein soll. Klicken Sie dafür auf \"Neues Feld einfügen\" und wählen Sie das gewünschte Feld aus. Klicken Sie dann auf das \"+\" um das Feld einzufügen und den gewünschten Text einzugeben.", + "empty-annotation-title": "{{annotationType}} ist leer!", + "empty-annotation-message": "Bitte tragen Sie einen Wert für die gewählte Anmerkung ein.", + "empty-organization-title": "Organisation wurde nicht ausgewählt!", + "empty-organization-message": "Bitte wählen Sie Ihre Organisation aus, bevor Sie die gewählte Anmerkung übernehmen.", + "invalid-annotation-text-title": "Ungültiger Eingabewert!", + "invalid-annotation-text-message": "Sie haben ein oder mehrere ungültige Zeichen eingegeben. Zulässige Sonderzeichen sind: \\/ !=+-_*&()" + }, + "error-permission-message": "Sie müssen das Recht auf Amtssignaturen besitzen um diese Funktion nutzen zu können!", + "error-login-message": "Sie müssen angemeldet sein um diese Funktion nutzen zu können!", + "error-cancel-message": "Der Signaturprozess wurde manuell abgebrochen.", + "error-rights-message": "Abbruch auf Grund mangelnder Rechte Ihres Accounts.", + "label-manual-positioning-missing": "Bestehende Signatur vorhanden, bitte wählen Sie ihre Positionierung manuell.", + "error-manual-positioning-missing": "Ein oder mehrere Signaturen in der Warteschlange müssen manuell positioniert werden." } diff --git a/src/i18n/en/translation.json b/src/i18n/en/translation.json index 4cdd8b6..50fdfb9 100644 --- a/src/i18n/en/translation.json +++ b/src/i18n/en/translation.json @@ -1,141 +1,141 @@ { - "official-pdf-upload": { - "upload-text": "The official signature of the \"Electronic Signature Service\" is an application with which you can provide PDF files with an electronic (qualified) official signature. A qualified signature is legally equivalent to your personal signature on the Internet and a handwritten signature.", - "upload-area-text": "In this area you can upload PDF-documents up to a size of 32MB via Drag & Drop or by selecting them directly. The PDF-documents can also be located in a ZIP-file.", - "queued-files-label": "Queued documents", - "queued-files-empty1": "No queued documents", - "queued-files-empty2": "You can now upload more documents", - "remove-failed-file-button-title": "Remove failed document", - "remove-queued-file-button-title": "Remove document from queue", - "clear-all": "Clear all", - "start-signing-process-button": "Start signing", - "stop-signing-process-button": "Stop signing", - "show-preview": "Show document", - "positioning-automatic": "Auto", - "positioning-manual": "Manual", - "preview-label": "Document view", - "signed-files-label": "Signed documents", - "download-zip-button": "Save all", - "download-zip-button-tooltip": "Save all signed documents", - "upload-button-label": "Select PDF-documents", - "download-file-button-title": "Save signed PDF", - "error-files-label": "Failed documents", - "re-upload-file-button-title": "Queue again", - "upload-status-file-text": "({{fileSize}}) is currently uploading and being processed...", - "re-upload-all-button": "Queue all", - "re-upload-all-button-title": "Queue all failed documents again", - "signature-placement-label": "Place signature", - "positioning": "Positioning", - "confirm-page-leave": "Are you sure you want to leave this page? There are still signed documents ready to be downloaded.", - "file-picker-context": "Upload PDF-documents to sign (max. 32 MB per file)", - "annotation": "Annotations", - "annotation-no": "No", - "annotation-yes": "Yes", - "annotation-view-label": "Add annotations to document" - }, - "qualified-pdf-upload": { - "save-field-label": "Save {{count}} file", - "save-field-label_plural": "Save {{count}} files", - "upload-text": "The \"Electronic Signature Service\" is an application with which you can provide PDF files with a personal, electronic (qualified) signature. A qualified signature is legally equivalent to your personal signature on the Internet and a handwritten signature.", - "upload-area-text": "In this area you can upload PDF-documents up to a size of 32MB via Drag & Drop or by selecting them directly. The PDF-documents can also be located in a ZIP-file.", - "current-signing-process-label": "Current signing process", - "queued-files-label": "Queued documents", - "queued-files-empty1": "No queued documents", - "queued-files-empty2": "You can now upload more documents", - "remove-failed-file-button-title": "Remove failed document", - "remove-queued-file-button-title": "Remove document from queue", - "clear-all": "Clear all", - "start-signing-process-button": "Start signing", - "stop-signing-process-button": "Stop signing", - "show-preview": "Show document", - "positioning-automatic": "Auto", - "positioning-manual": "Manual", - "preview-label": "Document view", - "signed-files-label": "Signed documents", - "download-zip-button": "Save all", - "download-zip-button-tooltip": "Save all signed documents", - "upload-button-label": "Select PDF-documents", - "download-file-button-title": "Save signed PDF", - "error-files-label": "Failed documents", - "re-upload-file-button-title": "Queue again", - "upload-status-file-text": "({{fileSize}}) is currently uploading and being processed...", - "re-upload-all-button": "Queue all", - "re-upload-all-button-title": "Queue all failed documents again", - "signature-placement-label": "Place signature", - "positioning": "Positioning", - "confirm-page-leave": "Are you sure you want to leave this page? There are still signed documents ready to be downloaded.", - "file-picker-context": "Upload PDF-documents to sign (max. 32 MB per file)", - "annotation": "Annotations", - "annotation-no": "No", - "annotation-yes": "Yes", - "annotation-view-label": "Add annotations to document" - }, - "signature-verification": { - "upload-text": "In this area you can upload PDF-documents up to a size of 32MB. The PDF-documents can also be located in a ZIP-file.", - "upload-area-text": "In this area you can upload PDF-documents up to a size of 32MB via Drag & Drop or by selecting them directly. The PDF-documents can also be located in a ZIP-file.", - "queued-files-label": "Queued documents", - "queued-files-empty1": "No queued documents", - "queued-files-empty2": "You can now upload more documents", - "remove-failed-file-button-title": "Remove failed document", - "remove-queued-file-button-title": "Remove document from queue", - "clear-all": "Clear all", - "start-verification-process-button": "Start verification", - "stop-verification-process-button": "Stop verification", - "show-preview": "Show document", - "preview-label": "Document view", - "verified-files-label": "Verified documents", - "upload-button-label": "Select PDF-documents", - "error-files-label": "Failed verification processes", - "re-upload-file-button-title": "Queue again", - "upload-status-file-text": "({{fileSize}}) is currently uploading and being processed...", - "re-upload-all-button": "Queue all", - "re-upload-all-button-title": "Queue all failed documents again", - "given-name": "Given name", - "last-name": "Last name", - "nationality": "Nationality", - "serial-number": "Serial number", - "value-message": "Verification", - "no-signatures-found": "No signatures were found.", - "confirm-page-leave": "Are you sure you want to leave this page? There are still signed documents ready to be downloaded.", - "file-picker-context": "Upload PDF-documents to verify (max. 32 MB per file)" - }, - "signature-verification-extern": { - "description-text": "To check a PDF signature for validity, please use the verification service of the Rundfunk und Telekom Regulierungs-GmbH. This verification service allows you to check whether the document contains a valid signature.", - "link-label": "Switch to the RTR verification service", - "adobe-reader-text": "Furthermore, it is also possible to verify the signature locally with the Adobe Reader." - }, - "pdf-preview": { - "first-page": "First page", - "previous-page": "Previous page", - "next-page": "Next page", - "last-page": "Last page", - "page-count": "of {{totalPages}}", - "rotate-signature": "Rotate signature clockwise", - "rotate": "Rotate signature", - "continue": "Confirm placement", - "error-message": "Error: This document is incorrect." - }, - "annotation-view": { - "delete-all-button-text": "Clear all", - "delete-all-button-title": "Clear all", - "save-all-button-text": "Add to document", - "save-all-button-title": "Add to document", - "insert-field": "Insert new field", - "remove-field": "Delete field", - "businessnumber-placeholder": "Insert business number here (e.g. 247/1/2020-S)", - "intended-use-placeholder": "Insert text here", - "introduction": "In this area you can define additional text to be included in the signature. To do this, click on \"Insert new field\" and select the desired field. Then click on the \"+\" to insert the field and enter the desired text.", - "empty-annotation-title": "{{annotationType}} is empty!", - "empty-annotation-message": "Please enter a value for the selected annotation.", - "empty-organization-title": "Organization was not selected!", - "empty-organization-message": "Please select your organization before applying the selected annotation.", - "invalid-annotation-text-title": "Invalid Input Value!", - "invalid-annotation-text-message": "You have entered one or more invalid characters. Valid special characters are: \\/ !?=+-_*&()" - }, - "error-permission-message": "You need have permissions to use the official signature to use this function!", - "error-login-message": "You need to be logged in to use this function!", - "error-cancel-message": "The signature process was manually aborted.", - "error-rights-message": "Abort due to insufficient rights of your account.", - "label-manual-positioning-missing": "Existing signature present, please select its positioning manually.", - "error-manual-positioning-missing": "One or more signatures in the queue must be positioned manually." + "official-pdf-upload": { + "upload-text": "The official signature of the \"Electronic Signature Service\" is an application with which you can provide PDF files with an electronic (qualified) official signature. A qualified signature is legally equivalent to your personal signature on the Internet and a handwritten signature.", + "upload-area-text": "In this area you can upload PDF-documents up to a size of 32MB via Drag & Drop or by selecting them directly. The PDF-documents can also be located in a ZIP-file.", + "queued-files-label": "Queued documents", + "queued-files-empty1": "No queued documents", + "queued-files-empty2": "You can now upload more documents", + "remove-failed-file-button-title": "Remove failed document", + "remove-queued-file-button-title": "Remove document from queue", + "clear-all": "Clear all", + "start-signing-process-button": "Start signing", + "stop-signing-process-button": "Stop signing", + "show-preview": "Show document", + "positioning-automatic": "Auto", + "positioning-manual": "Manual", + "preview-label": "Document view", + "signed-files-label": "Signed documents", + "download-zip-button": "Save all", + "download-zip-button-tooltip": "Save all signed documents", + "upload-button-label": "Select PDF-documents", + "download-file-button-title": "Save signed PDF", + "error-files-label": "Failed documents", + "re-upload-file-button-title": "Queue again", + "upload-status-file-text": "({{fileSize}}) is currently uploading and being processed...", + "re-upload-all-button": "Queue all", + "re-upload-all-button-title": "Queue all failed documents again", + "signature-placement-label": "Place signature", + "positioning": "Positioning", + "confirm-page-leave": "Are you sure you want to leave this page? There are still signed documents ready to be downloaded.", + "file-picker-context": "Upload PDF-documents to sign (max. 32 MB per file)", + "annotation": "Annotations", + "annotation-no": "No", + "annotation-yes": "Yes", + "annotation-view-label": "Add annotations to document" + }, + "qualified-pdf-upload": { + "save-field-label": "Save {{count}} file", + "save-field-label_plural": "Save {{count}} files", + "upload-text": "The \"Electronic Signature Service\" is an application with which you can provide PDF files with a personal, electronic (qualified) signature. A qualified signature is legally equivalent to your personal signature on the Internet and a handwritten signature.", + "upload-area-text": "In this area you can upload PDF-documents up to a size of 32MB via Drag & Drop or by selecting them directly. The PDF-documents can also be located in a ZIP-file.", + "current-signing-process-label": "Current signing process", + "queued-files-label": "Queued documents", + "queued-files-empty1": "No queued documents", + "queued-files-empty2": "You can now upload more documents", + "remove-failed-file-button-title": "Remove failed document", + "remove-queued-file-button-title": "Remove document from queue", + "clear-all": "Clear all", + "start-signing-process-button": "Start signing", + "stop-signing-process-button": "Stop signing", + "show-preview": "Show document", + "positioning-automatic": "Auto", + "positioning-manual": "Manual", + "preview-label": "Document view", + "signed-files-label": "Signed documents", + "download-zip-button": "Save all", + "download-zip-button-tooltip": "Save all signed documents", + "upload-button-label": "Select PDF-documents", + "download-file-button-title": "Save signed PDF", + "error-files-label": "Failed documents", + "re-upload-file-button-title": "Queue again", + "upload-status-file-text": "({{fileSize}}) is currently uploading and being processed...", + "re-upload-all-button": "Queue all", + "re-upload-all-button-title": "Queue all failed documents again", + "signature-placement-label": "Place signature", + "positioning": "Positioning", + "confirm-page-leave": "Are you sure you want to leave this page? There are still signed documents ready to be downloaded.", + "file-picker-context": "Upload PDF-documents to sign (max. 32 MB per file)", + "annotation": "Annotations", + "annotation-no": "No", + "annotation-yes": "Yes", + "annotation-view-label": "Add annotations to document" + }, + "signature-verification": { + "upload-text": "In this area you can upload PDF-documents up to a size of 32MB. The PDF-documents can also be located in a ZIP-file.", + "upload-area-text": "In this area you can upload PDF-documents up to a size of 32MB via Drag & Drop or by selecting them directly. The PDF-documents can also be located in a ZIP-file.", + "queued-files-label": "Queued documents", + "queued-files-empty1": "No queued documents", + "queued-files-empty2": "You can now upload more documents", + "remove-failed-file-button-title": "Remove failed document", + "remove-queued-file-button-title": "Remove document from queue", + "clear-all": "Clear all", + "start-verification-process-button": "Start verification", + "stop-verification-process-button": "Stop verification", + "show-preview": "Show document", + "preview-label": "Document view", + "verified-files-label": "Verified documents", + "upload-button-label": "Select PDF-documents", + "error-files-label": "Failed verification processes", + "re-upload-file-button-title": "Queue again", + "upload-status-file-text": "({{fileSize}}) is currently uploading and being processed...", + "re-upload-all-button": "Queue all", + "re-upload-all-button-title": "Queue all failed documents again", + "given-name": "Given name", + "last-name": "Last name", + "nationality": "Nationality", + "serial-number": "Serial number", + "value-message": "Verification", + "no-signatures-found": "No signatures were found.", + "confirm-page-leave": "Are you sure you want to leave this page? There are still signed documents ready to be downloaded.", + "file-picker-context": "Upload PDF-documents to verify (max. 32 MB per file)" + }, + "signature-verification-extern": { + "description-text": "To check a PDF signature for validity, please use the verification service of the Rundfunk und Telekom Regulierungs-GmbH. This verification service allows you to check whether the document contains a valid signature.", + "link-label": "Switch to the RTR verification service", + "adobe-reader-text": "Furthermore, it is also possible to verify the signature locally with the Adobe Reader." + }, + "pdf-preview": { + "first-page": "First page", + "previous-page": "Previous page", + "next-page": "Next page", + "last-page": "Last page", + "page-count": "of {{totalPages}}", + "rotate-signature": "Rotate signature clockwise", + "rotate": "Rotate signature", + "continue": "Confirm placement", + "error-message": "Error: This document is incorrect." + }, + "annotation-view": { + "delete-all-button-text": "Clear all", + "delete-all-button-title": "Clear all", + "save-all-button-text": "Add to document", + "save-all-button-title": "Add to document", + "insert-field": "Insert new field", + "remove-field": "Delete field", + "businessnumber-placeholder": "Insert business number here (e.g. 247/1/2020-S)", + "intended-use-placeholder": "Insert text here", + "introduction": "In this area you can define additional text to be included in the signature. To do this, click on \"Insert new field\" and select the desired field. Then click on the \"+\" to insert the field and enter the desired text.", + "empty-annotation-title": "{{annotationType}} is empty!", + "empty-annotation-message": "Please enter a value for the selected annotation.", + "empty-organization-title": "Organization was not selected!", + "empty-organization-message": "Please select your organization before applying the selected annotation.", + "invalid-annotation-text-title": "Invalid Input Value!", + "invalid-annotation-text-message": "You have entered one or more invalid characters. Valid special characters are: \\/ !?=+-_*&()" + }, + "error-permission-message": "You need have permissions to use the official signature to use this function!", + "error-login-message": "You need to be logged in to use this function!", + "error-cancel-message": "The signature process was manually aborted.", + "error-rights-message": "Abort due to insufficient rights of your account.", + "label-manual-positioning-missing": "Existing signature present, please select its positioning manually.", + "error-manual-positioning-missing": "One or more signatures in the queue must be positioned manually." } diff --git a/src/signature-entry.js b/src/signature-entry.js index 0f6b030..8a85781 100644 --- a/src/signature-entry.js +++ b/src/signature-entry.js @@ -1,7 +1,6 @@ export class SignatureEntry { - constructor(key, file) { this.key = key; this.file = file; } -} \ No newline at end of file +} diff --git a/src/styles.js b/src/styles.js index 355e265..da8fa23 100644 --- a/src/styles.js +++ b/src/styles.js @@ -3,7 +3,6 @@ import {css} from 'lit'; export function getSignatureCss() { // language=css return css` - #annotation-view .button.is-cancel { background: transparent; border: none; @@ -14,19 +13,22 @@ export function getSignatureCss() { padding-right: 2px; } - #annotation-view .box-header, #external-auth .box-header { + #annotation-view .box-header, + #external-auth .box-header { display: flex; justify-content: space-between; align-items: start; } - #annotation-view .box-header .filename, #external-auth .box-header .filename { + #annotation-view .box-header .filename, + #external-auth .box-header .filename { overflow: hidden; text-overflow: ellipsis; margin-right: 0.5em; } - #pdf-preview, #annotation-view { + #pdf-preview, + #annotation-view { min-width: 320px; box-sizing: border-box; } @@ -40,7 +42,8 @@ export function getSignatureCss() { font-weight: 600; } - #pdf-preview .box-header, #annotation-view .box-header { + #pdf-preview .box-header, + #annotation-view .box-header { border: var(--dbp-border-dark); border-bottom-width: 0; padding: 0.5em 0.5em 0 0.5em; @@ -73,7 +76,6 @@ export function getSignatureCss() { vertical-align: middle; } - .file .info strong { font-weight: 600; } @@ -84,7 +86,8 @@ export function getSignatureCss() { margin-right: 5px; } - .error, #cancel-signing-process { + .error, + #cancel-signing-process { color: var(--dbp-danger-dark); } @@ -94,11 +97,12 @@ export function getSignatureCss() { } /* using dbp-icon doesn't work */ - button > [name=close], a > [name=close] { + button > [name='close'], + a > [name='close'] { font-size: 0.8em; } - a > [name=close] { + a > [name='close'] { color: var(--dbp-accent-dark); } @@ -119,17 +123,18 @@ export function getSignatureCss() { margin-right: 0; flex: 1 0; } - - .file-block, .box { + + .file-block, + .box { border: var(--dbp-border-dark); padding: 10px; } - .file-block, .box .file { + .file-block, + .box .file { margin-top: 0; } - .file-block { max-width: 320px; margin-bottom: 10px; @@ -171,7 +176,8 @@ export function getSignatureCss() { text-align: right; } - .file-block .filename, .file-block div.bottom-line .headline { + .file-block .filename, + .file-block div.bottom-line .headline { text-overflow: ellipsis; overflow: hidden; } @@ -183,7 +189,7 @@ export function getSignatureCss() { .bold-filename { font-weight: bold; } - + #pdf-preview .button.is-cancel { color: var(--dbp-accent-dark); } @@ -202,12 +208,14 @@ export function getSignatureCss() { color: inherit; } - .is-disabled, .is-disabled.button[disabled] { + .is-disabled, + .is-disabled.button[disabled] { opacity: 0.2; pointer-events: none; } - #pdf-preview, #annotation-view { + #pdf-preview, + #annotation-view { position: sticky; top: 0px; height: 100vh; @@ -227,12 +235,12 @@ export function getSignatureCss() { margin-right: 0.5em; } - #grid-container{ + #grid-container { margin-top: 2rem; /*padding-top: 2rem;*/ } - .border{ + .border { border-top: var(--dbp-border-dark); margin-top: 2rem; padding-top: 2rem; @@ -243,7 +251,7 @@ export function getSignatureCss() { border-radius: var(--dbp-border-radius); } - .subheadline{ + .subheadline { font-style: italic; padding-left: 2em; margin-top: -1px; @@ -251,11 +259,9 @@ export function getSignatureCss() { margin-bottom: 1.2em; } - @media only screen - and (orientation: portrait) - and (max-width: 768px) { + @media only screen and (orientation: portrait) and (max-width: 768px) { /* Modal preview, upload and external auth */ - div.right-container > * { + div.right-container > * { position: fixed; z-index: 1000; padding: 10px; @@ -284,14 +290,11 @@ export function getSignatureCss() { .file-block { max-width: inherit; } - - #pdf-preview, #annotation-view { + + #pdf-preview, + #annotation-view { position: fixed; } } - - `; - - -} \ No newline at end of file +} diff --git a/src/textswitch.js b/src/textswitch.js index 608d9c0..989992a 100644 --- a/src/textswitch.js +++ b/src/textswitch.js @@ -1,8 +1,8 @@ import {html, LitElement, css} from 'lit'; import * as commonStyles from '@dbp-toolkit/common/styles'; -const BUTTON1 = "button1"; -const BUTTON2 = "button2"; +const BUTTON1 = 'button1'; +const BUTTON2 = 'button2'; /** * Attributes: @@ -10,34 +10,34 @@ const BUTTON2 = "button2"; * name1/name2: The names of the buttons * name: The active name * disabled: Disable the switch - * + * * Events: * change: when button is clicked - * + * * Example: * <my-tag name="one" name1="one" name2="two" value1="One", value2="Two"></my-tag> */ export class TextSwitch extends LitElement { constructor() { super(); - this.value1 = ""; - this.value2 = ""; - this.name1 = ""; - this.name2 = ""; - this.name = ""; + this.value1 = ''; + this.value2 = ''; + this.name1 = ''; + this.name2 = ''; + this.name = ''; this.disabled = false; this._active = BUTTON1; } static get properties() { return { - value1: { type: String }, - value2: { type: String }, - name1: { type: String }, - name2: { type: String }, - name: { type: String, reflect: true }, - disabled: { type: Boolean }, - _active: { type: Boolean }, + value1: {type: String}, + value2: {type: String}, + name1: {type: String}, + name2: {type: String}, + name: {type: String, reflect: true}, + disabled: {type: Boolean}, + _active: {type: Boolean}, }; } @@ -55,12 +55,12 @@ export class TextSwitch extends LitElement { #button1 { border-right-width: 0; } - - .button:first-child{ + + .button:first-child { border-radius: var(--dbp-border-radius) 0 0 var(--dbp-border-radius); } - .button:last-child{ + .button:last-child { border-radius: 0 var(--dbp-border-radius) var(--dbp-border-radius) 0; } @@ -82,7 +82,7 @@ export class TextSwitch extends LitElement { update(changedProperties) { changedProperties.forEach((oldValue, propName) => { - if (propName === "name") { + if (propName === 'name') { if (this[propName] === this.name1) { this._active = BUTTON1; } else if (this[propName] === this.name2) { @@ -100,7 +100,7 @@ export class TextSwitch extends LitElement { this.name = this._active === BUTTON1 ? this.name1 : this.name2; // send event only when buttons are clicked - const event = new CustomEvent("change", { + const event = new CustomEvent('change', { bubbles: true, cancelable: false, }); @@ -110,9 +110,18 @@ export class TextSwitch extends LitElement { return html` <div> - <button @click="${onClick}" class="button ${this._active === BUTTON1 ? `active` : ``}" id="${BUTTON1}" ?disabled="${this.disabled}"> + <button + @click="${onClick}" + class="button ${this._active === BUTTON1 ? `active` : ``}" + id="${BUTTON1}" + ?disabled="${this.disabled}"> ${this.value1} - </button><button @click="${onClick}" class="button ${this._active === BUTTON2 ? `active` : ``}" id="${BUTTON2}" ?disabled="${this.disabled}"> + </button> + <button + @click="${onClick}" + class="button ${this._active === BUTTON2 ? `active` : ``}" + id="${BUTTON2}" + ?disabled="${this.disabled}"> ${this.value2} </button> </div> diff --git a/src/utils.js b/src/utils.js index 0da722e..d4c585c 100644 --- a/src/utils.js +++ b/src/utils.js @@ -9,8 +9,8 @@ import {html} from 'lit'; * @param results * @param identifierAttribute */ -export const findObjectInApiResults = (identifier, results, identifierAttribute = "@id") => { - const members = results["hydra:member"]; +export const findObjectInApiResults = (identifier, results, identifierAttribute = '@id') => { + const members = results['hydra:member']; if (members === undefined) { return; @@ -24,7 +24,7 @@ export const findObjectInApiResults = (identifier, results, identifierAttribute }; export const getPDFFileBase64Content = (file) => { - return file.contentUrl.replace(/data:\s*application\/pdf;\s*base64,/, ""); + return file.contentUrl.replace(/data:\s*application\/pdf;\s*base64,/, ''); }; export const convertDataURIToBinary = (dataURI) => { @@ -35,7 +35,7 @@ export const convertDataURIToBinary = (dataURI) => { const rawLength = raw.length; let array = new Uint8Array(rawLength); - for(let i = 0; i < rawLength; i++) { + for (let i = 0; i < rawLength; i++) { array[i] = raw.charCodeAt(i); } @@ -49,18 +49,16 @@ export const getDataURIContentType = (dataURI) => { return dataURI.substring(5, base64Index); }; -export const baseName = (str) => -{ +export const baseName = (str) => { let base = String(str).substring(str.lastIndexOf('/') + 1); - if (base.lastIndexOf(".") !== -1) { - base = base.substring(0, base.lastIndexOf(".")); + if (base.lastIndexOf('.') !== -1) { + base = base.substring(0, base.lastIndexOf('.')); } return base; }; - export const fabricjs2pdfasPosition = (data) => { let angle = -(data.angle - 360) % 360; let bottom = data.bottom; @@ -81,7 +79,7 @@ export const fabricjs2pdfasPosition = (data) => { x: Math.round(left), r: angle, w: Math.round(data.width), // only width, no "height" allowed in PDF-AS - p: data.currentPage + p: data.currentPage, }; }; @@ -134,8 +132,9 @@ export const readArrayBufferFileContent = async (file) => { */ export const getPDFSignatureCount = async (file) => { const sigRegex = new RegExp( - "/Type\\s*/Sig(.|\\s)*?/SubFilter\\s*(/ETSI\\.CAdES\\.detached|/adbe\\.pkcs7\\.detached)", - "g"); + '/Type\\s*/Sig(.|\\s)*?/SubFilter\\s*(/ETSI\\.CAdES\\.detached|/adbe\\.pkcs7\\.detached)', + 'g' + ); const content = await readBinaryFileContent(file); let matches = 0; while (sigRegex.exec(content) !== null) { @@ -154,7 +153,7 @@ export const getPDFSignatureCount = async (file) => { export const writeAnnotationFactoryToFile = (annotationFactory, file) => { const blob = annotationFactory.write(); - return new File([blob], file.name, { type: file.type }); + return new File([blob], file.name, {type: file.type}); }; /** @@ -183,8 +182,17 @@ export const getAnnotationFactoryFromFile = async (file) => { * @param value * @returns {AnnotationFactory} prepared to annotate */ -export const addKeyValuePdfAnnotationsToAnnotationFactory = (annotationFactory, activityNameDE, activityNameEN, personName, - annotationType, annotationTypeNameDE, annotationTypeNameEN, organizationNumber, value) => { +export const addKeyValuePdfAnnotationsToAnnotationFactory = ( + annotationFactory, + activityNameDE, + activityNameEN, + personName, + annotationType, + annotationTypeNameDE, + annotationTypeNameEN, + organizationNumber, + value +) => { annotationType = annotationType.trim(); annotationTypeNameDE = annotationTypeNameDE.trim(); annotationTypeNameEN = annotationTypeNameEN.trim(); @@ -198,12 +206,13 @@ export const addKeyValuePdfAnnotationsToAnnotationFactory = (annotationFactory, // add human readable annotation let author = personName + ' via "' + activityNameDE + ' / ' + activityNameEN + '"'; - let content = annotationTypeNameDE + ': ' + value +"\n" + annotationTypeNameEN + ': ' + value; + let content = annotationTypeNameDE + ': ' + value + '\n' + annotationTypeNameEN + ': ' + value; annotationFactory = addPdfAnnotationToAnnotationFactory(annotationFactory, author, content); // add machine readable annotation const organizationNumberContent = organizationNumber !== '' ? '_' + organizationNumber : ''; - author = 'Maschinell aufgebracht, bitte nicht entfernen / Applied automatically, please do not remove'; + author = + 'Maschinell aufgebracht, bitte nicht entfernen / Applied automatically, please do not remove'; content = 'dbp_annotation_' + annotationType + organizationNumberContent + '=' + value; annotationFactory = addPdfAnnotationToAnnotationFactory(annotationFactory, author, content); @@ -225,13 +234,16 @@ export const addPdfAnnotationToAnnotationFactory = (annotationFactory, author, c // annotationFactory.checkRect(4, rect); // Create single free text annotation with print flag and 0 font size - let annotation = Object.assign(annotationFactory.createBaseAnnotation(page, rect, content, author), { - annotation_flag: 4, // enable print to be PDF/A conform - color: {r: 1, g: 1, b: 1}, // white to (maybe) hide it better - opacity: 0.001, // we can't set to 0 because of "if (opacity) {" - defaultAppearance: "/Invalid_font 0 Tf" // font size 0 to (maybe) hide it better - }); - annotation.type = "/FreeText"; + let annotation = Object.assign( + annotationFactory.createBaseAnnotation(page, rect, content, author), + { + annotation_flag: 4, // enable print to be PDF/A conform + color: {r: 1, g: 1, b: 1}, // white to (maybe) hide it better + opacity: 0.001, // we can't set to 0 because of "if (opacity) {" + defaultAppearance: '/Invalid_font 0 Tf', // font size 0 to (maybe) hide it better + } + ); + annotation.type = '/FreeText'; annotationFactory.annotations.push(annotation); return annotationFactory; @@ -245,20 +257,20 @@ export const addPdfAnnotationToAnnotationFactory = (annotationFactory, author, c */ export const getAnnotationTypes = (key = null) => { const types = { - 'bbe3a371': { - 'name': { - 'de': 'Geschäftszahl', - 'en': 'Businessnumber', + bbe3a371: { + name: { + de: 'Geschäftszahl', + en: 'Businessnumber', }, - 'hasOrganization': true, + hasOrganization: true, }, '85a4eb4c': { - 'name': { - 'de': 'Verwendungszweck', - 'en': 'Intended use', + name: { + de: 'Verwendungszweck', + en: 'Intended use', }, - 'hasOrganization': false, - } + hasOrganization: false, + }, }; return key === null ? types : types[key] || {}; diff --git a/test/unit.js b/test/unit.js index 8959860..16959e8 100644 --- a/test/unit.js +++ b/test/unit.js @@ -5,63 +5,65 @@ import '../src/dbp-signature.js'; import {getPDFSignatureCount} from '../src/utils.js'; suite('dbp-official-signature-pdf-upload basics', () => { - let node; + let node; - suiteSetup(async () => { - node = document.createElement('dbp-official-signature-pdf-upload'); - document.body.appendChild(node); - await node.updateComplete; - }); + suiteSetup(async () => { + node = document.createElement('dbp-official-signature-pdf-upload'); + document.body.appendChild(node); + await node.updateComplete; + }); - suiteTeardown(() => { - node.remove(); - }); + suiteTeardown(() => { + node.remove(); + }); - test('should render', () => { - assert(node.shadowRoot !== undefined); - }); + test('should render', () => { + assert(node.shadowRoot !== undefined); + }); }); suite('dbp-signature-app basics', () => { - let node; + let node; - suiteSetup(async () => { - node = document.createElement('dbp-app'); - document.body.appendChild(node); - await node.updateComplete; - }); + suiteSetup(async () => { + node = document.createElement('dbp-app'); + document.body.appendChild(node); + await node.updateComplete; + }); - suiteTeardown(() => { - node.remove(); - }); + suiteTeardown(() => { + node.remove(); + }); - test('should render', () => { - assert(node.shadowRoot !== undefined); - }); + test('should render', () => { + assert(node.shadowRoot !== undefined); + }); }); suite('pdf signature detection', () => { - function getPDFFile(data) { return new File([new Blob([data])], 'test.pdf', {type: 'application/pdf'}); } test('getPDFSignatureCount', async () => { // Produced via pdf-as-web - let sig1 = "/Type\n/Sig\n/Filter\n/Adobe.PPKLite\n/SubFilter\n/ETSI.CAdES.detached"; - let sig2 = "/Type\n/Sig\n/Filter\n/Adobe.PPKLite\n/SubFilter\n/adbe.pkcs7.detached"; + let sig1 = '/Type\n/Sig\n/Filter\n/Adobe.PPKLite\n/SubFilter\n/ETSI.CAdES.detached'; + let sig2 = '/Type\n/Sig\n/Filter\n/Adobe.PPKLite\n/SubFilter\n/adbe.pkcs7.detached'; // Produced via https://www.handy-signatur.at - let sig3 = "/Type /Sig\n/Name (Max Meier)\n/Location ()\n/Reason ()\n/M (D:20210201154123+01'00')\n/Filter /asign.ECDSA\n/SubFilter /ETSI.CAdES.detached"; + let sig3 = + "/Type /Sig\n/Name (Max Meier)\n/Location ()\n/Reason ()\n/M (D:20210201154123+01'00')\n/Filter /asign.ECDSA\n/SubFilter /ETSI.CAdES.detached"; - assert(await getPDFSignatureCount(getPDFFile(sig1)) === 1); - assert(await getPDFSignatureCount(getPDFFile(sig2)) === 1); - assert(await getPDFSignatureCount(getPDFFile(sig3)) === 1); - assert(await getPDFSignatureCount(getPDFFile(sig1 + sig2)) === 2); - assert(await getPDFSignatureCount(getPDFFile("foo" + sig1 + "bar" + sig2 + "quux")) === 2); - assert(await getPDFSignatureCount(getPDFFile("\nfoo" + sig1 + "bar\n")) === 1); - assert(await getPDFSignatureCount(getPDFFile("\nfoo" + sig2 + "bar\n")) === 1); + assert((await getPDFSignatureCount(getPDFFile(sig1))) === 1); + assert((await getPDFSignatureCount(getPDFFile(sig2))) === 1); + assert((await getPDFSignatureCount(getPDFFile(sig3))) === 1); + assert((await getPDFSignatureCount(getPDFFile(sig1 + sig2))) === 2); + assert( + (await getPDFSignatureCount(getPDFFile('foo' + sig1 + 'bar' + sig2 + 'quux'))) === 2 + ); + assert((await getPDFSignatureCount(getPDFFile('\nfoo' + sig1 + 'bar\n'))) === 1); + assert((await getPDFSignatureCount(getPDFFile('\nfoo' + sig2 + 'bar\n'))) === 1); - assert(await getPDFSignatureCount(getPDFFile("foobar")) === 0); - assert(await getPDFSignatureCount(getPDFFile("")) === 0); + assert((await getPDFSignatureCount(getPDFFile('foobar'))) === 0); + assert((await getPDFSignatureCount(getPDFFile(''))) === 0); }); }); -- GitLab