From 7333a3d3b83d0adc68ca0048dac755d5cf54e8f1 Mon Sep 17 00:00:00 2001 From: carlobeltrame Date: Wed, 20 Aug 2025 17:21:44 +0200 Subject: [PATCH 1/4] Display progress of printing pdf Fixes #5069 --- common/locales/de.json | 17 +- common/locales/en.json | 15 +- common/locales/fr.json | 15 +- common/locales/it.json | 15 +- frontend/eslint.config.mjs | 2 +- frontend/package-lock.json | 292 ++++++++++++++++++ frontend/package.json | 3 +- .../patches/@react-pdf+layout+4.4.0.patch | 17 + .../print/__tests__/repairPrintConfig.spec.js | 231 ++++++++++++++ .../config/DialogScheduleEntryFilter.vue | 16 +- .../print-client/DownloadClientPdfButton.vue | 35 ++- .../DownloadClientPdfListItem.vue | 19 +- .../print/print-client/PrintPreviewClient.vue | 30 +- .../print/print-client/generatePdf.js | 7 +- .../print/print-client/generatePdfMixin.js | 68 +++- .../print/print-client/renderPdf.js | 6 +- .../print/print-client/renderPdf.worker.js | 4 +- .../src/components/print/repairPrintConfig.js | 1 + frontend/src/locales/de.json | 13 +- pdf/eslint.config.mjs | 2 +- pdf/src/CampPrint.vue | 3 + pdf/src/PdfComponent.js | 12 + pdf/src/campPrint/summary/Story.vue | 2 +- pdf/src/campPrint/summary/SummaryPeriod.vue | 2 +- .../entry/SafetyConsiderations.vue | 5 +- .../campPrint/tableOfContents/entry/Story.vue | 2 +- pdf/src/index.js | 2 +- .../story_overview.spec.json.snap | 4 +- pdf/src/renderer/index.js | 6 +- pdf/src/renderer/reactPdfRenderer.js | 23 +- pdf/src/renderer/vueRenderer.js | 3 +- .../Toc/TocSafetyConsiderations.vue | 2 +- print/components/Toc/TocStory.vue | 2 +- print/components/summary/SummaryPeriod.vue | 2 +- print/eslint.config.mjs | 2 +- 35 files changed, 799 insertions(+), 81 deletions(-) create mode 100644 frontend/patches/@react-pdf+layout+4.4.0.patch diff --git a/common/locales/de.json b/common/locales/de.json index 0d5d4474de..54b884ec9b 100644 --- a/common/locales/de.json +++ b/common/locales/de.json @@ -262,8 +262,11 @@ "shortScheduleEntryDescription": "Tag {dayNumber} {startTime}" }, "print": { + "activity": { + "title": "Einzelne Aktivität" + }, "activityList": { - "title": "Aktivitätsliste" + "title": "Aktivitätenliste" }, "config": { "periods": "Lagerabschnitt(e)" @@ -283,13 +286,11 @@ "program": { "title": "Detailprogramm" }, - "summary": { - "safetyConsiderations": { - "title": "Sicherheitsüberlegungen" - }, - "storycontext": { - "title": "Geschichte" - } + "safetyConsiderations": { + "title": "Sicherheitsüberlegungen" + }, + "story": { + "title": "Geschichte" }, "toc": { "title": "Inhaltsverzeichnis" diff --git a/common/locales/en.json b/common/locales/en.json index 69bf6d9c0b..d59e6f5bbb 100644 --- a/common/locales/en.json +++ b/common/locales/en.json @@ -262,6 +262,9 @@ "shortScheduleEntryDescription": "day {dayNumber} {startTime}" }, "print": { + "activity": { + "title": "Single activity" + }, "activityList": { "title": "Activity list" }, @@ -283,13 +286,11 @@ "program": { "title": "Program" }, - "summary": { - "safetyConsiderations": { - "title": "Safety considerations" - }, - "storycontext": { - "title": "Story" - } + "safetyConsiderations": { + "title": "Safety considerations" + }, + "story": { + "title": "Story" }, "toc": { "title": "Table of contents" diff --git a/common/locales/fr.json b/common/locales/fr.json index 2b3f1c257f..9b53d4f44e 100644 --- a/common/locales/fr.json +++ b/common/locales/fr.json @@ -262,6 +262,9 @@ "shortScheduleEntryDescription": "jour{dayNumber} {startTime}" }, "print": { + "activity": { + "title": "Activité" + }, "activityList": { "title": "Liste d'activités" }, @@ -283,13 +286,11 @@ "program": { "title": "Programme" }, - "summary": { - "safetyConsiderations": { - "title": "Considérations sur la sécurité" - }, - "storycontext": { - "title": "Histoire" - } + "safetyConsiderations": { + "title": "Considérations sur la sécurité" + }, + "story": { + "title": "Histoire" }, "toc": { "title": "Table des matières" diff --git a/common/locales/it.json b/common/locales/it.json index a35244b580..0861ef1088 100644 --- a/common/locales/it.json +++ b/common/locales/it.json @@ -222,6 +222,9 @@ } }, "print": { + "activity": { + "title": "Attività" + }, "config": { "periods": "Sezione/i portante/i" }, @@ -234,13 +237,11 @@ "program": { "title": "Programma" }, - "summary": { - "safetyConsiderations": { - "title": "Considerazioni sulla sicurezza" - }, - "storycontext": { - "title": "Storia" - } + "safetyConsiderations": { + "title": "Considerazioni sulla sicurezza" + }, + "story": { + "title": "Storia" }, "toc": { "title": "Indice dei contenuti" diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 594de35aa8..8c2987bc7b 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -79,7 +79,7 @@ export default [ 'error', { ignoreKeysRegex: - '^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|config|summary|toc|activityList))\\..+', + '^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|config|story|safetyConsiderations|toc|activityList))\\..+', translationKeyPropRegex: '[a-zA-Z0-9]-i18n-key$', }, ], diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c2941ffa7b..0d7ae451ad 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -98,6 +98,7 @@ "jest-serializer-vue-tjw": "3.20.0", "jsdom": "26.1.0", "lint-staged": "16.1.6", + "patch-package": "8.0.0", "prettier": "3.6.2", "sass": "1.78.0", "source-map": "0.7.4", @@ -4744,6 +4745,13 @@ "vue-template-compiler": "^2.x" } }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/@zxcvbn-ts/core": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@zxcvbn-ts/core/-/core-3.0.4.tgz", @@ -4999,6 +5007,16 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -5530,6 +5548,22 @@ "node": ">= 6" } }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -7092,6 +7126,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -7219,6 +7263,22 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -7948,6 +8008,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -8218,6 +8294,19 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -8548,6 +8637,26 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stable-stringify": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", + "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -8568,6 +8677,29 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "dev": true, + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -8591,6 +8723,16 @@ "node": ">=0.10.0" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -9080,6 +9222,16 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", @@ -9379,6 +9531,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -9403,6 +9572,16 @@ "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", "license": "MIT" }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -9529,6 +9708,50 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/patch-package": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", + "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^9.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "rimraf": "^2.6.3", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -10352,6 +10575,42 @@ "dev": true, "license": "MIT" }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "4.49.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.49.0.tgz", @@ -10667,6 +10926,16 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", @@ -11296,6 +11565,19 @@ "dev": true, "license": "MIT" }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -11513,6 +11795,16 @@ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", "license": "MIT" }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unplugin": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 4f3d55fe27..e66085727a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,7 +17,7 @@ "test:unit": "vitest run --coverage", "test:unit:debug": "node --inspect-brk=0.0.0.0:9229 ./node_modules/.bin/vitest --no-cache --runInBand", "test:unit:watch": "vitest --watch", - "postinstall": "./scripts/install-twemoji.sh" + "postinstall": "./scripts/install-twemoji.sh && patch-package" }, "dependencies": { "@intlify/core": "11.1.11", @@ -111,6 +111,7 @@ "jest-serializer-vue-tjw": "3.20.0", "jsdom": "26.1.0", "lint-staged": "16.1.6", + "patch-package": "8.0.0", "prettier": "3.6.2", "sass": "1.78.0", "source-map": "0.7.4", diff --git a/frontend/patches/@react-pdf+layout+4.4.0.patch b/frontend/patches/@react-pdf+layout+4.4.0.patch new file mode 100644 index 0000000000..d835c38dd1 --- /dev/null +++ b/frontend/patches/@react-pdf+layout+4.4.0.patch @@ -0,0 +1,17 @@ +diff --git a/node_modules/@react-pdf/layout/lib/index.js b/node_modules/@react-pdf/layout/lib/index.js +index b318728..5e9efed 100644 +--- a/node_modules/@react-pdf/layout/lib/index.js ++++ b/node_modules/@react-pdf/layout/lib/index.js +@@ -2717,10 +2717,12 @@ const paginate = (page, pageNumber, fontStore, yoga) => { + return []; + if (page.props?.wrap === false) + return [page]; ++ dispatchEvent(new Event('layoutPage')); + let splittedPage = splitPage(page, pageNumber, fontStore, yoga); + const pages = [splittedPage[0]]; + let nextPage = splittedPage[1]; + while (nextPage !== null) { ++ dispatchEvent(new Event('layoutPage')); + splittedPage = splitPage(nextPage, pageNumber + pages.length, fontStore, yoga); + pages.push(splittedPage[0]); + nextPage = splittedPage[1]; diff --git a/frontend/src/components/print/__tests__/repairPrintConfig.spec.js b/frontend/src/components/print/__tests__/repairPrintConfig.spec.js index ecb6f043af..e6ef25191d 100644 --- a/frontend/src/components/print/__tests__/repairPrintConfig.spec.js +++ b/frontend/src/components/print/__tests__/repairPrintConfig.spec.js @@ -95,6 +95,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, } const defaultContents = [ { @@ -1157,6 +1158,7 @@ describe('repairConfig', () => { category: ['/categories/1a2b3c4d'], progressLabel: ['/progress_labels/1a2b3c4d'], responsible: ['/camp_collaborations/1a2b3c4d'], + activityCount: 0, }, }, }, @@ -1184,6 +1186,7 @@ describe('repairConfig', () => { category: ['/categories/1a2b3c4d'], progressLabel: ['/progress_labels/1a2b3c4d'], responsible: ['/camp_collaborations/1a2b3c4d'], + activityCount: 0, }, }, }, @@ -1249,6 +1252,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -1296,6 +1300,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -1342,6 +1347,7 @@ describe('repairConfig', () => { day: [], category: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -1389,6 +1395,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: ['/camp_collaborations/00000000'], + activityCount: 0, }, }, }, @@ -1435,6 +1442,7 @@ describe('repairConfig', () => { day: [], responsible: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -1482,6 +1490,7 @@ describe('repairConfig', () => { category: ['/categories/00000000'], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -1528,6 +1537,7 @@ describe('repairConfig', () => { category: [], responsible: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -1575,6 +1585,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -1621,6 +1632,7 @@ describe('repairConfig', () => { day: [], category: [], responsible: [], + activityCount: 0, }, }, }, @@ -1668,6 +1680,53 @@ describe('repairConfig', () => { category: [], progressLabel: ['/progress_labels/00000000'], responsible: [], + activityCount: 0, + }, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { + periods: ['/periods/1a2b3c4d'], + dayOverview: false, + filter: defaultFilter, + }, + }, + ], + documentName: 'test camp', + options: { pageNumbers: false }, + language: 'en-GB', + }) + }) + + test('adds dummy activityCount if missing', () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { + periods: ['/periods/1a2b3c4d'], + dayOverview: false, + filter: { + period: null, + day: [], + category: [], + progressLabel: [], + responsible: [], }, }, }, @@ -1911,6 +1970,7 @@ describe('repairConfig', () => { category: ['/categories/1a2b3c4d'], progressLabel: ['/progress_labels/1a2b3c4d'], responsible: ['/camp_collaborations/1a2b3c4d'], + activityCount: 0, }, }, }, @@ -1938,6 +1998,7 @@ describe('repairConfig', () => { category: ['/categories/1a2b3c4d'], progressLabel: ['/progress_labels/1a2b3c4d'], responsible: ['/camp_collaborations/1a2b3c4d'], + activityCount: 0, }, }, }, @@ -2003,6 +2064,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -2050,6 +2112,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -2096,6 +2159,7 @@ describe('repairConfig', () => { day: [], category: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -2143,6 +2207,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: ['/camp_collaborations/00000000'], + activityCount: 0, }, }, }, @@ -2189,6 +2254,7 @@ describe('repairConfig', () => { day: [], responsible: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -2236,6 +2302,7 @@ describe('repairConfig', () => { category: ['/categories/00000000'], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -2282,6 +2349,7 @@ describe('repairConfig', () => { category: [], responsible: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -2329,6 +2397,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -2375,6 +2444,7 @@ describe('repairConfig', () => { day: [], category: [], responsible: [], + activityCount: 0, }, }, }, @@ -2422,6 +2492,53 @@ describe('repairConfig', () => { category: [], progressLabel: ['/progress_labels/00000000'], responsible: [], + activityCount: 0, + }, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Story', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'Storycontext', + filter: defaultFilter, + }, + }, + ], + documentName: 'test camp', + options: { pageNumbers: false }, + language: 'en-GB', + }) + }) + + test('adds dummy activityCount if missing', () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Story', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'Storycontext', + filter: { + period: null, + day: [], + category: [], + progressLabel: [], + responsible: [], }, }, }, @@ -2673,6 +2790,7 @@ describe('repairConfig', () => { category: ['/categories/1a2b3c4d'], progressLabel: ['/progress_labels/1a2b3c4d'], responsible: ['/camp_collaborations/1a2b3c4d'], + activityCount: 0, }, }, }, @@ -2700,6 +2818,7 @@ describe('repairConfig', () => { category: ['/categories/1a2b3c4d'], progressLabel: ['/progress_labels/1a2b3c4d'], responsible: ['/camp_collaborations/1a2b3c4d'], + activityCount: 0, }, }, }, @@ -2765,6 +2884,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -2812,6 +2932,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -2858,6 +2979,7 @@ describe('repairConfig', () => { day: [], category: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -2905,6 +3027,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: ['/camp_collaborations/00000000'], + activityCount: 0, }, }, }, @@ -2951,6 +3074,7 @@ describe('repairConfig', () => { day: [], responsible: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -2998,6 +3122,7 @@ describe('repairConfig', () => { category: ['/categories/00000000'], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -3044,6 +3169,7 @@ describe('repairConfig', () => { category: [], responsible: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -3091,6 +3217,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -3137,6 +3264,7 @@ describe('repairConfig', () => { day: [], category: [], responsible: [], + activityCount: 0, }, }, }, @@ -3184,6 +3312,53 @@ describe('repairConfig', () => { category: [], progressLabel: ['/progress_labels/00000000'], responsible: [], + activityCount: 0, + }, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'SafetyConsiderations', + filter: defaultFilter, + }, + }, + ], + documentName: 'test camp', + options: { pageNumbers: false }, + language: 'en-GB', + }) + }) + + test('adds dummy activityCount if missing', () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'SafetyConsiderations', + filter: { + period: null, + day: [], + category: [], + progressLabel: [], + responsible: [], }, }, }, @@ -3409,6 +3584,7 @@ describe('repairConfig', () => { category: ['/categories/1a2b3c4d'], progressLabel: ['/progress_labels/1a2b3c4d'], responsible: ['/camp_collaborations/1a2b3c4d'], + activityCount: 0, }, }, }, @@ -3435,6 +3611,7 @@ describe('repairConfig', () => { category: ['/categories/1a2b3c4d'], progressLabel: ['/progress_labels/1a2b3c4d'], responsible: ['/camp_collaborations/1a2b3c4d'], + activityCount: 0, }, }, }, @@ -3497,6 +3674,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -3542,6 +3720,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -3586,6 +3765,7 @@ describe('repairConfig', () => { day: [], category: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -3631,6 +3811,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: ['/camp_collaborations/00000000'], + activityCount: 0, }, }, }, @@ -3675,6 +3856,7 @@ describe('repairConfig', () => { day: [], responsible: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -3720,6 +3902,7 @@ describe('repairConfig', () => { category: ['/categories/00000000'], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -3764,6 +3947,7 @@ describe('repairConfig', () => { category: [], responsible: [], progressLabel: [], + activityCount: 0, }, }, }, @@ -3809,6 +3993,7 @@ describe('repairConfig', () => { category: [], progressLabel: [], responsible: [], + activityCount: 0, }, }, }, @@ -3853,6 +4038,7 @@ describe('repairConfig', () => { day: [], category: [], responsible: [], + activityCount: 0, }, }, }, @@ -3898,6 +4084,51 @@ describe('repairConfig', () => { category: [], progressLabel: ['/progress_labels/00000000'], responsible: [], + activityCount: 0, + }, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'ActivityList', + options: { + periods: ['/periods/1a2b3c4d'], + filter: defaultFilter, + }, + }, + ], + documentName: 'test camp', + options: { pageNumbers: false }, + language: 'en-GB', + }) + }) + + test('adds dummy activityCount if missing', () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'ActivityList', + options: { + periods: ['/periods/1a2b3c4d'], + filter: { + period: null, + day: [], + category: [], + progressLabel: [], + responsible: [], }, }, }, diff --git a/frontend/src/components/print/config/DialogScheduleEntryFilter.vue b/frontend/src/components/print/config/DialogScheduleEntryFilter.vue index 590b7a00f7..93c96a0721 100644 --- a/frontend/src/components/print/config/DialogScheduleEntryFilter.vue +++ b/frontend/src/components/print/config/DialogScheduleEntryFilter.vue @@ -56,13 +56,16 @@ export default { } }, computed: { + filteredCount() { + return this.filterFn(this.localFilter).length + }, activatorLabel() { if (this.anyFilter) return this.$tc( 'components.print.config.dialogScheduleEntryFilter.filterActive', 1, { - filtered: this.filterFn(this.localFilter).length, + filtered: this.filteredCount, total: this.filterFn({}).length, } ) @@ -79,7 +82,7 @@ export default { 'components.print.config.dialogScheduleEntryFilter.resultCount', 1, { - filtered: this.filterFn(this.localFilter).length, + filtered: this.filteredCount, total: this.filterFn({}).length, } ) @@ -96,6 +99,15 @@ export default { ) }, }, + watch: { + filteredCount: { + handler(val) { + this.localFilter.activityCount = val + this.$emit('input', this.localFilter) + }, + immediate: true, + }, + }, methods: { emit(dialogOpen) { if (dialogOpen) return // only emit when closing dialog diff --git a/frontend/src/components/print/print-client/DownloadClientPdfButton.vue b/frontend/src/components/print/print-client/DownloadClientPdfButton.vue index f72b67c835..54310b6e19 100644 --- a/frontend/src/components/print/print-client/DownloadClientPdfButton.vue +++ b/frontend/src/components/print/print-client/DownloadClientPdfButton.vue @@ -1,11 +1,20 @@ @@ -17,3 +26,25 @@ export default { mixins: [generatePdfMixin], } + diff --git a/frontend/src/components/print/print-client/DownloadClientPdfListItem.vue b/frontend/src/components/print/print-client/DownloadClientPdfListItem.vue index d737eb67c1..8a0bee99fe 100644 --- a/frontend/src/components/print/print-client/DownloadClientPdfListItem.vue +++ b/frontend/src/components/print/print-client/DownloadClientPdfListItem.vue @@ -1,9 +1,20 @@