mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
Feature: pngx PDF viewer with updated pdfjs (#4679)
This commit is contained in:
parent
80ff5677ea
commit
826322b610
@ -1,7 +1,8 @@
|
||||
{
|
||||
"root": true,
|
||||
"ignorePatterns": [
|
||||
"projects/**/*"
|
||||
"projects/**/*",
|
||||
"/src/app/components/common/pdf-viewer/**"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
|
@ -65,7 +65,7 @@
|
||||
"src/assets",
|
||||
"src/manifest.webmanifest",
|
||||
{
|
||||
"glob": "pdf.worker.min.js",
|
||||
"glob": "{pdf.worker.min.js,pdf.min.js}",
|
||||
"input": "node_modules/pdfjs-dist/build/",
|
||||
"output": "/assets/js/"
|
||||
}
|
||||
@ -75,7 +75,8 @@
|
||||
],
|
||||
"scripts": [],
|
||||
"allowedCommonJsDependencies": [
|
||||
"ng2-pdf-viewer"
|
||||
"pdfjs-dist",
|
||||
"pdfjs-dist/web/pdf_viewer"
|
||||
],
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
@ -109,7 +110,7 @@
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
"maximumError": "30kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -79,7 +79,7 @@ test('should show a mobile preview', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 400, height: 1000 })
|
||||
await expect(page.getByRole('tab', { name: 'Preview' })).toBeVisible()
|
||||
await page.getByRole('tab', { name: 'Preview' }).click()
|
||||
await page.waitForSelector('pdf-viewer')
|
||||
await page.waitForSelector('pngx-pdf-viewer')
|
||||
})
|
||||
|
||||
test('should show a list of notes', async ({ page }) => {
|
||||
|
@ -7,6 +7,7 @@ module.exports = {
|
||||
'abstract-name-filter-service',
|
||||
'abstract-paperless-service',
|
||||
],
|
||||
coveragePathIgnorePatterns: ['/src/app/components/common/pdf-viewer/*'],
|
||||
transformIgnorePatterns: [`<rootDir>/node_modules/(?!.*\\.mjs$|lodash-es)`],
|
||||
moduleNameMapper: {
|
||||
'^src/(.*)': '<rootDir>/src/$1',
|
||||
|
376
src-ui/package-lock.json
generated
376
src-ui/package-lock.json
generated
@ -25,11 +25,11 @@
|
||||
"bootstrap": "^5.3.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"mime-names": "^1.0.0",
|
||||
"ng2-pdf-viewer": "^10.0.0",
|
||||
"ngx-color": "^9.0.0",
|
||||
"ngx-cookie-service": "^16.0.1",
|
||||
"ngx-file-drop": "^16.0.0",
|
||||
"ngx-ui-tour-ng-bootstrap": "^13.0.6",
|
||||
"pdfjs-dist": "^3.11.174",
|
||||
"rxjs": "^7.8.1",
|
||||
"tslib": "^2.6.2",
|
||||
"uuid": "^9.0.1",
|
||||
@ -4728,6 +4728,116 @@
|
||||
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
|
||||
"integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"make-dir": "^3.1.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"nopt": "^5.0.0",
|
||||
"npmlog": "^5.0.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.5",
|
||||
"tar": "^6.1.11"
|
||||
},
|
||||
"bin": {
|
||||
"node-pre-gyp": "bin/node-pre-gyp"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/are-we-there-yet": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
|
||||
"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/gauge": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
|
||||
"integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"aproba": "^1.0.3 || ^2.0.0",
|
||||
"color-support": "^1.1.2",
|
||||
"console-control-strings": "^1.0.0",
|
||||
"has-unicode": "^2.0.1",
|
||||
"object-assign": "^4.1.1",
|
||||
"signal-exit": "^3.0.0",
|
||||
"string-width": "^4.2.3",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wide-align": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"semver": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/nopt": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"abbrev": "1"
|
||||
},
|
||||
"bin": {
|
||||
"nopt": "bin/nopt.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/npmlog": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
|
||||
"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"are-we-there-yet": "^2.0.0",
|
||||
"console-control-strings": "^1.1.0",
|
||||
"gauge": "^3.0.0",
|
||||
"set-blocking": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@ng-bootstrap/ng-bootstrap": {
|
||||
"version": "15.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-15.1.2.tgz",
|
||||
@ -6728,7 +6838,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
@ -6823,7 +6933,7 @@
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
@ -6974,7 +7084,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
|
||||
"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/are-we-there-yet": {
|
||||
"version": "3.0.1",
|
||||
@ -7332,7 +7442,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
@ -7476,7 +7586,7 @@
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@ -7682,6 +7792,21 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/canvas": {
|
||||
"version": "2.11.2",
|
||||
"resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz",
|
||||
"integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@mapbox/node-pre-gyp": "^1.0.0",
|
||||
"nan": "^2.17.0",
|
||||
"simple-get": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
@ -7740,7 +7865,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@ -7884,7 +8009,7 @@
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
|
||||
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"bin": {
|
||||
"color-support": "bin.js"
|
||||
}
|
||||
@ -7974,7 +8099,7 @@
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/concurrently": {
|
||||
"version": "8.2.2",
|
||||
@ -8101,7 +8226,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "0.5.4",
|
||||
@ -8616,6 +8741,18 @@
|
||||
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/decompress-response": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
|
||||
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"mimic-response": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/dedent": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
|
||||
@ -8705,7 +8842,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
@ -8735,6 +8872,15 @@
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
|
||||
"integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-newline": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
|
||||
@ -8863,12 +9009,6 @@
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dommatrix": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dommatrix/-/dommatrix-1.0.3.tgz",
|
||||
"integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww==",
|
||||
"deprecated": "dommatrix is no longer maintained. Please use @thednp/dommatrix."
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
||||
@ -10175,7 +10315,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
@ -10469,7 +10609,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.0",
|
||||
@ -10706,7 +10846,7 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
@ -10907,7 +11047,7 @@
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
@ -10917,7 +11057,7 @@
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "4.1.1",
|
||||
@ -13824,6 +13964,18 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-response": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
|
||||
"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/mini-css-extract-plugin": {
|
||||
"version": "2.7.6",
|
||||
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz",
|
||||
@ -13853,7 +14005,7 @@
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
@ -13874,7 +14026,7 @@
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@ -14048,7 +14200,7 @@
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
@ -14061,7 +14213,7 @@
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
@ -14073,13 +14225,13 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
@ -14129,6 +14281,12 @@
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.18.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz",
|
||||
"integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
@ -14209,18 +14367,6 @@
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ng2-pdf-viewer": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ng2-pdf-viewer/-/ng2-pdf-viewer-10.0.0.tgz",
|
||||
"integrity": "sha512-zEefcAsTpDoxFceQYs3ycPMaUAkt5UX4OcTstVQoNqRK6w+vOY+V8z8aFCuBwnt+7iN1EHaIpquOf4S9mWc04g==",
|
||||
"dependencies": {
|
||||
"pdfjs-dist": "~2.16.105",
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"pdfjs-dist": "~2.16.105"
|
||||
}
|
||||
},
|
||||
"node_modules/ngx-color": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ngx-color/-/ngx-color-9.0.0.tgz",
|
||||
@ -14312,6 +14458,48 @@
|
||||
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch/node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/node-fetch/node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/node-fetch/node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||
@ -14776,6 +14964,15 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
||||
@ -14825,7 +15022,7 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@ -15396,7 +15593,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -15456,21 +15653,25 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path2d-polyfill": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz",
|
||||
"integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/pdfjs-dist": {
|
||||
"version": "2.16.105",
|
||||
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz",
|
||||
"integrity": "sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==",
|
||||
"dependencies": {
|
||||
"dommatrix": "^1.0.3",
|
||||
"web-streams-polyfill": "^3.2.1"
|
||||
"version": "3.11.174",
|
||||
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz",
|
||||
"integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"worker-loader": "^3.0.8"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"worker-loader": {
|
||||
"optional": true
|
||||
}
|
||||
"optionalDependencies": {
|
||||
"canvas": "^2.11.2",
|
||||
"path2d-polyfill": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
@ -15990,7 +16191,7 @@
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
@ -16243,7 +16444,7 @@
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
@ -16258,7 +16459,7 @@
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
@ -16333,7 +16534,7 @@
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@ -16647,7 +16848,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.1.1",
|
||||
@ -16755,6 +16956,37 @@
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-concat": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
||||
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/simple-get": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
|
||||
"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"decompress-response": "^4.2.0",
|
||||
"once": "^1.3.1",
|
||||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sisteransi": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||
@ -17018,7 +17250,7 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
@ -17186,7 +17418,7 @@
|
||||
"version": "6.1.15",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz",
|
||||
"integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
@ -17219,7 +17451,7 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
@ -17231,7 +17463,7 @@
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
@ -17243,7 +17475,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.19.2",
|
||||
@ -17892,7 +18124,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/utils-merge": {
|
||||
"version": "1.0.1",
|
||||
@ -18108,14 +18340,6 @@
|
||||
"defaults": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
|
||||
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
@ -18484,7 +18708,7 @@
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
|
||||
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||
}
|
||||
@ -18596,7 +18820,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/write-file-atomic": {
|
||||
"version": "4.0.2",
|
||||
|
@ -27,11 +27,11 @@
|
||||
"bootstrap": "^5.3.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"mime-names": "^1.0.0",
|
||||
"ng2-pdf-viewer": "^10.0.0",
|
||||
"ngx-color": "^9.0.0",
|
||||
"ngx-cookie-service": "^16.0.1",
|
||||
"ngx-file-drop": "^16.0.0",
|
||||
"ngx-ui-tour-ng-bootstrap": "^13.0.6",
|
||||
"pdfjs-dist": "^3.11.174",
|
||||
"rxjs": "^7.8.1",
|
||||
"tslib": "^2.6.2",
|
||||
"uuid": "^9.0.1",
|
||||
|
@ -51,7 +51,6 @@ import { SavedViewWidgetComponent } from './components/dashboard/widgets/saved-v
|
||||
import { StatisticsWidgetComponent } from './components/dashboard/widgets/statistics-widget/statistics-widget.component'
|
||||
import { UploadFileWidgetComponent } from './components/dashboard/widgets/upload-file-widget/upload-file-widget.component'
|
||||
import { WidgetFrameComponent } from './components/dashboard/widgets/widget-frame/widget-frame.component'
|
||||
import { PdfViewerModule } from 'ng2-pdf-viewer'
|
||||
import { WelcomeWidgetComponent } from './components/dashboard/widgets/welcome-widget/welcome-widget.component'
|
||||
import { YesNoPipe } from './pipes/yes-no.pipe'
|
||||
import { FileSizePipe } from './pipes/file-size.pipe'
|
||||
@ -106,6 +105,7 @@ import { CustomFieldsComponent } from './components/manage/custom-fields/custom-
|
||||
import { CustomFieldEditDialogComponent } from './components/common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component'
|
||||
import { CustomFieldsDropdownComponent } from './components/common/custom-fields-dropdown/custom-fields-dropdown.component'
|
||||
import { ProfileEditDialogComponent } from './components/common/profile-edit-dialog/profile-edit-dialog.component'
|
||||
import { PdfViewerComponent } from './components/common/pdf-viewer/pdf-viewer.component'
|
||||
|
||||
import localeAf from '@angular/common/locales/af'
|
||||
import localeAr from '@angular/common/locales/ar'
|
||||
@ -258,6 +258,7 @@ function initializeApp(settings: SettingsService) {
|
||||
CustomFieldEditDialogComponent,
|
||||
CustomFieldsDropdownComponent,
|
||||
ProfileEditDialogComponent,
|
||||
PdfViewerComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@ -267,7 +268,6 @@ function initializeApp(settings: SettingsService) {
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
NgxFileDropModule,
|
||||
PdfViewerModule,
|
||||
NgSelectModule,
|
||||
ColorSliderModule,
|
||||
TourNgBootstrapModule,
|
||||
|
@ -0,0 +1,3 @@
|
||||
<div #pdfViewerContainer class="pngx-pdf-viewer-container">
|
||||
<div class="pdfViewer"></div>
|
||||
</div>
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,599 @@
|
||||
/**
|
||||
* This file is taken and modified from https://github.com/VadimDez/ng2-pdf-viewer/blob/10.0.0/src/app/pdf-viewer/pdf-viewer.component.ts
|
||||
* Created by vadimdez on 21/06/16.
|
||||
*/
|
||||
import {
|
||||
Component,
|
||||
Input,
|
||||
Output,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
OnChanges,
|
||||
SimpleChanges,
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
ViewChild,
|
||||
AfterViewChecked,
|
||||
NgZone,
|
||||
} from '@angular/core'
|
||||
import { from, fromEvent, Subject } from 'rxjs'
|
||||
import { debounceTime, filter, takeUntil } from 'rxjs/operators'
|
||||
import * as PDFJS from 'pdfjs-dist'
|
||||
import * as PDFJSViewer from 'pdfjs-dist/web/pdf_viewer'
|
||||
|
||||
import { createEventBus } from './utils/event-bus-utils'
|
||||
|
||||
import type {
|
||||
PDFSource,
|
||||
PDFPageProxy,
|
||||
PDFProgressData,
|
||||
PDFDocumentProxy,
|
||||
PDFDocumentLoadingTask,
|
||||
PDFViewerOptions,
|
||||
ZoomScale,
|
||||
} from './typings'
|
||||
import { PDFSinglePageViewer } from 'pdfjs-dist/web/pdf_viewer'
|
||||
|
||||
PDFJS['verbosity'] = PDFJS.VerbosityLevel.ERRORS
|
||||
|
||||
// Yea this is a straight hack
|
||||
declare global {
|
||||
interface WeakKeyTypes {
|
||||
symbol: Object
|
||||
}
|
||||
|
||||
type WeakKey = WeakKeyTypes[keyof WeakKeyTypes]
|
||||
}
|
||||
|
||||
export enum RenderTextMode {
|
||||
DISABLED,
|
||||
ENABLED,
|
||||
ENHANCED,
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'pngx-pdf-viewer',
|
||||
templateUrl: './pdf-viewer.component.html',
|
||||
styleUrls: ['./pdf-viewer.component.scss'],
|
||||
})
|
||||
export class PdfViewerComponent
|
||||
implements OnChanges, OnInit, OnDestroy, AfterViewChecked
|
||||
{
|
||||
static CSS_UNITS = 96.0 / 72.0
|
||||
static BORDER_WIDTH = 9
|
||||
|
||||
@ViewChild('pdfViewerContainer')
|
||||
pdfViewerContainer!: ElementRef<HTMLDivElement>
|
||||
|
||||
public eventBus!: PDFJSViewer.EventBus
|
||||
public pdfLinkService!: PDFJSViewer.PDFLinkService
|
||||
public pdfViewer!: PDFJSViewer.PDFViewer | PDFSinglePageViewer
|
||||
|
||||
private isVisible = false
|
||||
|
||||
private _cMapsUrl =
|
||||
typeof PDFJS !== 'undefined'
|
||||
? `https://unpkg.com/pdfjs-dist@${(PDFJS as any).version}/cmaps/`
|
||||
: null
|
||||
private _imageResourcesPath =
|
||||
typeof PDFJS !== 'undefined'
|
||||
? `https://unpkg.com/pdfjs-dist@${(PDFJS as any).version}/web/images/`
|
||||
: undefined
|
||||
private _renderText = true
|
||||
private _renderTextMode: RenderTextMode = RenderTextMode.ENABLED
|
||||
private _stickToPage = false
|
||||
private _originalSize = true
|
||||
private _pdf: PDFDocumentProxy | undefined
|
||||
private _page = 1
|
||||
private _zoom = 1
|
||||
private _zoomScale: ZoomScale = 'page-width'
|
||||
private _rotation = 0
|
||||
private _showAll = true
|
||||
private _canAutoResize = true
|
||||
private _fitToPage = false
|
||||
private _externalLinkTarget = 'blank'
|
||||
private _showBorders = false
|
||||
private lastLoaded!: string | Uint8Array | PDFSource | null
|
||||
private _latestScrolledPage!: number
|
||||
|
||||
private resizeTimeout: number | null = null
|
||||
private pageScrollTimeout: number | null = null
|
||||
private isInitialized = false
|
||||
private loadingTask?: PDFDocumentLoadingTask | null
|
||||
private destroy$ = new Subject<void>()
|
||||
|
||||
@Output('after-load-complete') afterLoadComplete =
|
||||
new EventEmitter<PDFDocumentProxy>()
|
||||
@Output('page-rendered') pageRendered = new EventEmitter<CustomEvent>()
|
||||
@Output('pages-initialized') pageInitialized = new EventEmitter<CustomEvent>()
|
||||
@Output('text-layer-rendered') textLayerRendered =
|
||||
new EventEmitter<CustomEvent>()
|
||||
@Output('error') onError = new EventEmitter<any>()
|
||||
@Output('on-progress') onProgress = new EventEmitter<PDFProgressData>()
|
||||
@Output() pageChange: EventEmitter<number> = new EventEmitter<number>(true)
|
||||
@Input() src?: string | Uint8Array | PDFSource
|
||||
|
||||
@Input('c-maps-url')
|
||||
set cMapsUrl(cMapsUrl: string) {
|
||||
this._cMapsUrl = cMapsUrl
|
||||
}
|
||||
|
||||
@Input('page')
|
||||
set page(_page: number | string | any) {
|
||||
_page = parseInt(_page, 10) || 1
|
||||
const originalPage = _page
|
||||
|
||||
if (this._pdf) {
|
||||
_page = this.getValidPageNumber(_page)
|
||||
}
|
||||
|
||||
this._page = _page
|
||||
if (originalPage !== _page) {
|
||||
this.pageChange.emit(_page)
|
||||
}
|
||||
}
|
||||
|
||||
@Input('render-text')
|
||||
set renderText(renderText: boolean) {
|
||||
this._renderText = renderText
|
||||
}
|
||||
|
||||
@Input('render-text-mode')
|
||||
set renderTextMode(renderTextMode: RenderTextMode) {
|
||||
this._renderTextMode = renderTextMode
|
||||
}
|
||||
|
||||
@Input('original-size')
|
||||
set originalSize(originalSize: boolean) {
|
||||
this._originalSize = originalSize
|
||||
}
|
||||
|
||||
@Input('show-all')
|
||||
set showAll(value: boolean) {
|
||||
this._showAll = value
|
||||
}
|
||||
|
||||
@Input('stick-to-page')
|
||||
set stickToPage(value: boolean) {
|
||||
this._stickToPage = value
|
||||
}
|
||||
|
||||
@Input('zoom')
|
||||
set zoom(value: number) {
|
||||
if (value <= 0) {
|
||||
return
|
||||
}
|
||||
|
||||
this._zoom = value
|
||||
}
|
||||
|
||||
get zoom() {
|
||||
return this._zoom
|
||||
}
|
||||
|
||||
@Input('zoom-scale')
|
||||
set zoomScale(value: ZoomScale) {
|
||||
this._zoomScale = value
|
||||
}
|
||||
|
||||
get zoomScale() {
|
||||
return this._zoomScale
|
||||
}
|
||||
|
||||
@Input('rotation')
|
||||
set rotation(value: number) {
|
||||
if (!(typeof value === 'number' && value % 90 === 0)) {
|
||||
console.warn('Invalid pages rotation angle.')
|
||||
return
|
||||
}
|
||||
|
||||
this._rotation = value
|
||||
}
|
||||
|
||||
@Input('external-link-target')
|
||||
set externalLinkTarget(value: string) {
|
||||
this._externalLinkTarget = value
|
||||
}
|
||||
|
||||
@Input('autoresize')
|
||||
set autoresize(value: boolean) {
|
||||
this._canAutoResize = Boolean(value)
|
||||
}
|
||||
|
||||
@Input('fit-to-page')
|
||||
set fitToPage(value: boolean) {
|
||||
this._fitToPage = Boolean(value)
|
||||
}
|
||||
|
||||
@Input('show-borders')
|
||||
set showBorders(value: boolean) {
|
||||
this._showBorders = Boolean(value)
|
||||
}
|
||||
|
||||
static getLinkTarget(type: string) {
|
||||
switch (type) {
|
||||
case 'blank':
|
||||
return (PDFJSViewer as any).LinkTarget.BLANK
|
||||
case 'none':
|
||||
return (PDFJSViewer as any).LinkTarget.NONE
|
||||
case 'self':
|
||||
return (PDFJSViewer as any).LinkTarget.SELF
|
||||
case 'parent':
|
||||
return (PDFJSViewer as any).LinkTarget.PARENT
|
||||
case 'top':
|
||||
return (PDFJSViewer as any).LinkTarget.TOP
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
constructor(
|
||||
private element: ElementRef<HTMLElement>,
|
||||
private ngZone: NgZone
|
||||
) {
|
||||
PDFJS.GlobalWorkerOptions['workerSrc'] = '/assets/js/pdf.worker.min.js'
|
||||
}
|
||||
|
||||
ngAfterViewChecked(): void {
|
||||
if (this.isInitialized) {
|
||||
return
|
||||
}
|
||||
|
||||
const offset = this.pdfViewerContainer.nativeElement.offsetParent
|
||||
|
||||
if (this.isVisible === true && offset == null) {
|
||||
this.isVisible = false
|
||||
return
|
||||
}
|
||||
|
||||
if (this.isVisible === false && offset != null) {
|
||||
this.isVisible = true
|
||||
|
||||
setTimeout(() => {
|
||||
this.initialize()
|
||||
this.ngOnChanges({ src: this.src } as any)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initialize()
|
||||
this.setupResizeListener()
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.clear()
|
||||
this.destroy$.next()
|
||||
this.loadingTask = null
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (!this.isVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
if ('src' in changes) {
|
||||
this.loadPDF()
|
||||
} else if (this._pdf) {
|
||||
if ('renderText' in changes || 'showAll' in changes) {
|
||||
this.setupViewer()
|
||||
this.resetPdfDocument()
|
||||
}
|
||||
if ('page' in changes) {
|
||||
const { page } = changes
|
||||
if (page.currentValue === this._latestScrolledPage) {
|
||||
return
|
||||
}
|
||||
|
||||
// New form of page changing: The viewer will now jump to the specified page when it is changed.
|
||||
// This behavior is introduced by using the PDFSinglePageViewer
|
||||
this.pdfViewer.scrollPageIntoView({ pageNumber: this._page })
|
||||
}
|
||||
|
||||
this.update()
|
||||
}
|
||||
}
|
||||
|
||||
public updateSize() {
|
||||
from(
|
||||
this._pdf!.getPage(
|
||||
this.pdfViewer.currentPageNumber
|
||||
) as unknown as Promise<PDFPageProxy>
|
||||
)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe({
|
||||
next: (page: PDFPageProxy) => {
|
||||
const rotation = this._rotation + page.rotate
|
||||
const viewportWidth =
|
||||
(page as any).getViewport({
|
||||
scale: this._zoom,
|
||||
rotation,
|
||||
}).width * PdfViewerComponent.CSS_UNITS
|
||||
let scale = this._zoom
|
||||
let stickToPage = true
|
||||
|
||||
// Scale the document when it shouldn't be in original size or doesn't fit into the viewport
|
||||
if (
|
||||
!this._originalSize ||
|
||||
(this._fitToPage &&
|
||||
viewportWidth > this.pdfViewerContainer.nativeElement.clientWidth)
|
||||
) {
|
||||
const viewPort = (page as any).getViewport({ scale: 1, rotation })
|
||||
scale = this.getScale(viewPort.width, viewPort.height)
|
||||
stickToPage = !this._stickToPage
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.pdfViewer.currentScale = scale
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
public clear() {
|
||||
if (this.loadingTask && !this.loadingTask.destroyed) {
|
||||
this.loadingTask.destroy()
|
||||
}
|
||||
|
||||
if (this._pdf) {
|
||||
this._latestScrolledPage = 0
|
||||
this._pdf.destroy()
|
||||
this._pdf = undefined
|
||||
}
|
||||
}
|
||||
|
||||
private getPDFLinkServiceConfig() {
|
||||
const linkTarget = PdfViewerComponent.getLinkTarget(
|
||||
this._externalLinkTarget
|
||||
)
|
||||
|
||||
if (linkTarget) {
|
||||
return { externalLinkTarget: linkTarget }
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
private initEventBus() {
|
||||
this.eventBus = createEventBus(PDFJSViewer, this.destroy$)
|
||||
|
||||
fromEvent<CustomEvent>(this.eventBus, 'pagerendered')
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((event) => {
|
||||
this.pageRendered.emit(event)
|
||||
})
|
||||
|
||||
fromEvent<CustomEvent>(this.eventBus, 'pagesinit')
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((event) => {
|
||||
this.pageInitialized.emit(event)
|
||||
})
|
||||
|
||||
fromEvent(this.eventBus, 'pagechanging')
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(({ pageNumber }: any) => {
|
||||
if (this.pageScrollTimeout) {
|
||||
clearTimeout(this.pageScrollTimeout)
|
||||
}
|
||||
|
||||
this.pageScrollTimeout = window.setTimeout(() => {
|
||||
this._latestScrolledPage = pageNumber
|
||||
this.pageChange.emit(pageNumber)
|
||||
}, 100)
|
||||
})
|
||||
|
||||
fromEvent<CustomEvent>(this.eventBus, 'textlayerrendered')
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((event) => {
|
||||
this.textLayerRendered.emit(event)
|
||||
})
|
||||
}
|
||||
|
||||
private initPDFServices() {
|
||||
this.pdfLinkService = new PDFJSViewer.PDFLinkService({
|
||||
eventBus: this.eventBus,
|
||||
...this.getPDFLinkServiceConfig(),
|
||||
})
|
||||
}
|
||||
|
||||
private getPDFOptions(): PDFViewerOptions {
|
||||
return {
|
||||
eventBus: this.eventBus,
|
||||
container: this.element.nativeElement.querySelector('div')!,
|
||||
removePageBorders: !this._showBorders,
|
||||
linkService: this.pdfLinkService,
|
||||
textLayerMode: this._renderText
|
||||
? this._renderTextMode
|
||||
: RenderTextMode.DISABLED,
|
||||
imageResourcesPath: this._imageResourcesPath,
|
||||
}
|
||||
}
|
||||
|
||||
private setupViewer() {
|
||||
PDFJS['disableTextLayer'] = !this._renderText
|
||||
|
||||
this.initPDFServices()
|
||||
|
||||
if (this._showAll) {
|
||||
this.pdfViewer = new PDFJSViewer.PDFViewer(this.getPDFOptions())
|
||||
} else {
|
||||
this.pdfViewer = new PDFJSViewer.PDFSinglePageViewer(this.getPDFOptions())
|
||||
}
|
||||
this.pdfLinkService.setViewer(this.pdfViewer)
|
||||
|
||||
this.pdfViewer._currentPageNumber = this._page
|
||||
}
|
||||
|
||||
private getValidPageNumber(page: number): number {
|
||||
if (page < 1) {
|
||||
return 1
|
||||
}
|
||||
|
||||
if (page > this._pdf!.numPages) {
|
||||
return this._pdf!.numPages
|
||||
}
|
||||
|
||||
return page
|
||||
}
|
||||
|
||||
private getDocumentParams() {
|
||||
const srcType = typeof this.src
|
||||
|
||||
if (!this._cMapsUrl) {
|
||||
return this.src
|
||||
}
|
||||
|
||||
const params: any = {
|
||||
cMapUrl: this._cMapsUrl,
|
||||
cMapPacked: true,
|
||||
enableXfa: true,
|
||||
}
|
||||
|
||||
if (srcType === 'string') {
|
||||
params.url = this.src
|
||||
} else if (srcType === 'object') {
|
||||
if ((this.src as any).byteLength !== undefined) {
|
||||
params.data = this.src
|
||||
} else {
|
||||
Object.assign(params, this.src)
|
||||
}
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
private loadPDF() {
|
||||
if (!this.src) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.lastLoaded === this.src) {
|
||||
this.update()
|
||||
return
|
||||
}
|
||||
|
||||
this.clear()
|
||||
|
||||
this.setupViewer()
|
||||
|
||||
this.loadingTask = PDFJS.getDocument(this.getDocumentParams())
|
||||
|
||||
this.loadingTask!.onProgress = (progressData: PDFProgressData) => {
|
||||
this.onProgress.emit(progressData)
|
||||
}
|
||||
|
||||
const src = this.src
|
||||
|
||||
from(this.loadingTask!.promise as Promise<PDFDocumentProxy>)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe({
|
||||
next: (pdf) => {
|
||||
this._pdf = pdf
|
||||
this.lastLoaded = src
|
||||
|
||||
this.afterLoadComplete.emit(pdf)
|
||||
this.resetPdfDocument()
|
||||
|
||||
this.update()
|
||||
},
|
||||
error: (error) => {
|
||||
this.lastLoaded = null
|
||||
this.onError.emit(error)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
private update() {
|
||||
this.page = this._page
|
||||
|
||||
this.render()
|
||||
}
|
||||
|
||||
private render() {
|
||||
this._page = this.getValidPageNumber(this._page)
|
||||
|
||||
if (
|
||||
this._rotation !== 0 ||
|
||||
this.pdfViewer.pagesRotation !== this._rotation
|
||||
) {
|
||||
setTimeout(() => {
|
||||
this.pdfViewer.pagesRotation = this._rotation
|
||||
})
|
||||
}
|
||||
|
||||
if (this._stickToPage) {
|
||||
setTimeout(() => {
|
||||
this.pdfViewer.currentPageNumber = this._page
|
||||
})
|
||||
}
|
||||
|
||||
this.updateSize()
|
||||
}
|
||||
|
||||
private getScale(viewportWidth: number, viewportHeight: number) {
|
||||
const borderSize = this._showBorders
|
||||
? 2 * PdfViewerComponent.BORDER_WIDTH
|
||||
: 0
|
||||
const pdfContainerWidth =
|
||||
this.pdfViewerContainer.nativeElement.clientWidth - borderSize
|
||||
const pdfContainerHeight =
|
||||
this.pdfViewerContainer.nativeElement.clientHeight - borderSize
|
||||
|
||||
if (
|
||||
pdfContainerHeight === 0 ||
|
||||
viewportHeight === 0 ||
|
||||
pdfContainerWidth === 0 ||
|
||||
viewportWidth === 0
|
||||
) {
|
||||
return 1
|
||||
}
|
||||
|
||||
let ratio = 1
|
||||
switch (this._zoomScale) {
|
||||
case 'page-fit':
|
||||
ratio = Math.min(
|
||||
pdfContainerHeight / viewportHeight,
|
||||
pdfContainerWidth / viewportWidth
|
||||
)
|
||||
break
|
||||
case 'page-height':
|
||||
ratio = pdfContainerHeight / viewportHeight
|
||||
break
|
||||
case 'page-width':
|
||||
default:
|
||||
ratio = pdfContainerWidth / viewportWidth
|
||||
break
|
||||
}
|
||||
|
||||
return (this._zoom * ratio) / PdfViewerComponent.CSS_UNITS
|
||||
}
|
||||
|
||||
private resetPdfDocument() {
|
||||
this.pdfLinkService.setDocument(this._pdf, null)
|
||||
this.pdfViewer.setDocument(this._pdf!)
|
||||
}
|
||||
|
||||
private initialize(): void {
|
||||
if (!this.isVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
this.isInitialized = true
|
||||
this.initEventBus()
|
||||
this.setupViewer()
|
||||
}
|
||||
|
||||
private setupResizeListener(): void {
|
||||
this.ngZone.runOutsideAngular(() => {
|
||||
fromEvent(window, 'resize')
|
||||
.pipe(
|
||||
debounceTime(100),
|
||||
filter(() => this._canAutoResize && !!this._pdf),
|
||||
takeUntil(this.destroy$)
|
||||
)
|
||||
.subscribe(() => {
|
||||
this.updateSize()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
17
src-ui/src/app/components/common/pdf-viewer/typings.ts
Normal file
17
src-ui/src/app/components/common/pdf-viewer/typings.ts
Normal file
@ -0,0 +1,17 @@
|
||||
export type PDFPageProxy =
|
||||
import('pdfjs-dist/types/src/display/api').PDFPageProxy
|
||||
export type PDFSource =
|
||||
import('pdfjs-dist/types/src/display/api').DocumentInitParameters
|
||||
export type PDFDocumentProxy =
|
||||
import('pdfjs-dist/types/src/display/api').PDFDocumentProxy
|
||||
export type PDFDocumentLoadingTask =
|
||||
import('pdfjs-dist/types/src/display/api').PDFDocumentLoadingTask
|
||||
export type PDFViewerOptions =
|
||||
import('pdfjs-dist/types/web/pdf_viewer').PDFViewerOptions
|
||||
|
||||
export interface PDFProgressData {
|
||||
loaded: number
|
||||
total: number
|
||||
}
|
||||
|
||||
export type ZoomScale = 'page-height' | 'page-fit' | 'page-width'
|
@ -0,0 +1,182 @@
|
||||
/**
|
||||
* This file is taken and modified from https://github.com/VadimDez/ng2-pdf-viewer/blob/10.0.0/src/app/pdf-viewer/utils/event-bus-utils.ts
|
||||
* Created by vadimdez on 21/06/16.
|
||||
*/
|
||||
import { fromEvent, Subject } from 'rxjs'
|
||||
import { takeUntil } from 'rxjs/operators'
|
||||
|
||||
import type { EventBus } from 'pdfjs-dist/web/pdf_viewer'
|
||||
|
||||
// interface EventBus {
|
||||
// on(eventName: string, listener: Function): void;
|
||||
// off(eventName: string, listener: Function): void;
|
||||
// _listeners: any;
|
||||
// dispatch(eventName: string, data: Object): void;
|
||||
// _on(eventName: any, listener: any, options?: null): void;
|
||||
// _off(eventName: any, listener: any, options?: null): void;
|
||||
// }
|
||||
|
||||
export function createEventBus(pdfJsViewer: any, destroy$: Subject<void>) {
|
||||
const globalEventBus: EventBus = new pdfJsViewer.EventBus()
|
||||
attachDOMEventsToEventBus(globalEventBus, destroy$)
|
||||
return globalEventBus
|
||||
}
|
||||
|
||||
function attachDOMEventsToEventBus(
|
||||
eventBus: EventBus,
|
||||
destroy$: Subject<void>
|
||||
): void {
|
||||
fromEvent(eventBus, 'documentload')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(() => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('documentload', true, true, {})
|
||||
window.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'pagerendered')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ pageNumber, cssTransform, source }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('pagerendered', true, true, {
|
||||
pageNumber,
|
||||
cssTransform,
|
||||
})
|
||||
source.div.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'textlayerrendered')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ pageNumber, source }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('textlayerrendered', true, true, { pageNumber })
|
||||
source.textLayerDiv?.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'pagechanging')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ pageNumber, source }: any) => {
|
||||
const event = document.createEvent('UIEvents') as any
|
||||
event.initEvent('pagechanging', true, true)
|
||||
/* tslint:disable:no-string-literal */
|
||||
event['pageNumber'] = pageNumber
|
||||
source.container.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'pagesinit')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ source }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('pagesinit', true, true, null)
|
||||
source.container.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'pagesloaded')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ pagesCount, source }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('pagesloaded', true, true, { pagesCount })
|
||||
source.container.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'scalechange')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ scale, presetValue, source }: any) => {
|
||||
const event = document.createEvent('UIEvents') as any
|
||||
event.initEvent('scalechange', true, true)
|
||||
/* tslint:disable:no-string-literal */
|
||||
event['scale'] = scale
|
||||
/* tslint:disable:no-string-literal */
|
||||
event['presetValue'] = presetValue
|
||||
source.container.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'updateviewarea')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ location, source }: any) => {
|
||||
const event = document.createEvent('UIEvents') as any
|
||||
event.initEvent('updateviewarea', true, true)
|
||||
event['location'] = location
|
||||
source.container.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'find')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(
|
||||
({
|
||||
source,
|
||||
type,
|
||||
query,
|
||||
phraseSearch,
|
||||
caseSensitive,
|
||||
highlightAll,
|
||||
findPrevious,
|
||||
}: any) => {
|
||||
if (source === window) {
|
||||
return // event comes from FirefoxCom, no need to replicate
|
||||
}
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('find' + type, true, true, {
|
||||
query,
|
||||
phraseSearch,
|
||||
caseSensitive,
|
||||
highlightAll,
|
||||
findPrevious,
|
||||
})
|
||||
window.dispatchEvent(event)
|
||||
}
|
||||
)
|
||||
|
||||
fromEvent(eventBus, 'attachmentsloaded')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ attachmentsCount, source }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('attachmentsloaded', true, true, {
|
||||
attachmentsCount,
|
||||
})
|
||||
source.container.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'sidebarviewchanged')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ view, source }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('sidebarviewchanged', true, true, { view })
|
||||
source.outerContainer.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'pagemode')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ mode, source }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('pagemode', true, true, { mode })
|
||||
source.pdfViewer.container.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'namedaction')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ action, source }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('namedaction', true, true, { action })
|
||||
source.pdfViewer.container.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'presentationmodechanged')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ active, switchInProgress }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('presentationmodechanged', true, true, {
|
||||
active,
|
||||
switchInProgress,
|
||||
})
|
||||
window.dispatchEvent(event)
|
||||
})
|
||||
|
||||
fromEvent(eventBus, 'outlineloaded')
|
||||
.pipe(takeUntil(destroy$))
|
||||
.subscribe(({ outlineCount, source }: any) => {
|
||||
const event = document.createEvent('CustomEvent')
|
||||
event.initCustomEvent('outlineloaded', true, true, { outlineCount })
|
||||
source.container.dispatchEvent(event)
|
||||
})
|
||||
}
|
@ -1,9 +1,20 @@
|
||||
<pngx-page-header [(title)]="title">
|
||||
<div class="input-group input-group-sm me-5 d-none d-md-flex" *ngIf="getContentType() === 'application/pdf' && !useNativePdfViewer">
|
||||
<div class="input-group-text" i18n>Page</div>
|
||||
<input class="form-control flex-grow-0 w-auto" type="number" min="1" [max]="previewNumPages" [(ngModel)]="previewCurrentPage" />
|
||||
<div class="input-group-text" i18n>of {{previewNumPages}}</div>
|
||||
</div>
|
||||
<ng-container *ngIf="getContentType() === 'application/pdf' && !useNativePdfViewer">
|
||||
<div class="input-group input-group-sm me-2 d-none d-md-flex">
|
||||
<div class="input-group-text" i18n>Page</div>
|
||||
<input class="form-control flex-grow-0 w-auto" type="number" min="1" [max]="previewNumPages" [(ngModel)]="previewCurrentPage" />
|
||||
<div class="input-group-text" i18n>of {{previewNumPages}}</div>
|
||||
</div>
|
||||
<div class="input-group input-group-sm me-5 d-none d-md-flex">
|
||||
<button class="btn btn-outline-secondary" (click)="decreaseZoom()" i18n>-</button>
|
||||
<select class="form-select" (change)="onZoomSelect($event)">
|
||||
<option *ngFor="let setting of zoomSettings" [value]="setting" [selected]="previewZoomSetting === setting">
|
||||
{{ getZoomSettingTitle(setting) }}
|
||||
</option>
|
||||
</select>
|
||||
<button class="btn btn-outline-secondary" (click)="increaseZoom()" i18n>+</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<button type="button" class="btn btn-sm btn-outline-danger me-4" (click)="delete()" [disabled]="!userIsOwner" *pngxIfPermissions="{ action: PermissionAction.Delete, type: PermissionType.Document }">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
@ -189,24 +200,7 @@
|
||||
<li [ngbNavItem]="DocumentDetailNavIDs.Preview" class="d-md-none">
|
||||
<a ngbNavLink i18n>Preview</a>
|
||||
<ng-template ngbNavContent *ngIf="!pdfPreview.offsetParent">
|
||||
<div class="position-relative">
|
||||
<ng-container *ngIf="getContentType() === 'application/pdf'">
|
||||
<div class="preview-sticky pdf-viewer-container" *ngIf="!useNativePdfViewer ; else nativePdfViewer">
|
||||
<pdf-viewer [src]="{ url: previewUrl, password: password }" [original-size]="false" [show-borders]="true" [show-all]="true" [(page)]="previewCurrentPage" [render-text-mode]="2" (error)="onError($event)" (after-load-complete)="pdfPreviewLoaded($event)"></pdf-viewer>
|
||||
</div>
|
||||
<ng-template #nativePdfViewer>
|
||||
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="getContentType() === 'text/plain'">
|
||||
<object [data]="previewUrl | safeUrl" type="text/plain" class="preview-sticky bg-light overflow-auto" width="100%"></object>
|
||||
</ng-container>
|
||||
<div *ngIf="requiresPassword" class="password-prompt">
|
||||
<form>
|
||||
<input autocomplete="" class="form-control" i18n-placeholder placeholder="Enter Password" type="password" (keyup)="onPasswordKeyUp($event)" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngTemplateOutlet="previewContent"></ng-container>
|
||||
</ng-template>
|
||||
</li>
|
||||
|
||||
@ -233,14 +227,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-xl-8 mb-3 d-none d-md-block position-relative" #pdfPreview>
|
||||
<ng-container *ngIf="getContentType() === 'application/pdf'">
|
||||
<div class="preview-sticky pdf-viewer-container" *ngIf="!useNativePdfViewer ; else nativePdfViewer">
|
||||
<pdf-viewer [src]="{ url: previewUrl, password: password }" [original-size]="false" [show-borders]="true" [show-all]="true" [(page)]="previewCurrentPage" [render-text-mode]="2" (error)="onError($event)" (after-load-complete)="pdfPreviewLoaded($event)"></pdf-viewer>
|
||||
</div>
|
||||
<ng-template #nativePdfViewer>
|
||||
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<ng-container *ngTemplateOutlet="previewContent"></ng-container>
|
||||
<ng-container *ngIf="renderAsPlainText">
|
||||
<div [innerText]="previewText" class="preview-sticky bg-light p-3 overflow-auto" width="100%"></div>
|
||||
</ng-container>
|
||||
@ -252,3 +239,39 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<ng-template #previewContent>
|
||||
<div *ngIf="!metadata" class="w-100 h-100 d-flex align-items-center justify-content-center">
|
||||
<div>
|
||||
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||
<ng-container i18n>Loading...</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="getContentType() === 'application/pdf'">
|
||||
<div class="preview-sticky pdf-viewer-container" *ngIf="!useNativePdfViewer ; else nativePdfViewer">
|
||||
<pngx-pdf-viewer
|
||||
[src]="{ url: previewUrl, password: password }"
|
||||
[original-size]="false"
|
||||
[show-borders]="true"
|
||||
[show-all]="true"
|
||||
[(page)]="previewCurrentPage"
|
||||
[zoom-scale]="previewZoomScale"
|
||||
[zoom]="previewZoomSetting"
|
||||
[render-text-mode]="2"
|
||||
(error)="onError($event)"
|
||||
(after-load-complete)="pdfPreviewLoaded($event)">
|
||||
</pngx-pdf-viewer>
|
||||
</div>
|
||||
<ng-template #nativePdfViewer>
|
||||
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="renderAsPlainText">
|
||||
<div [innerText]="previewText" class="preview-sticky bg-light p-3 overflow-auto" width="100%"></div>
|
||||
</ng-container>
|
||||
<div *ngIf="showPasswordField" class="password-prompt">
|
||||
<form>
|
||||
<input autocomplete="" autofocus="true" class="form-control" i18n-placeholder placeholder="Enter Password" type="password" (keyup)="onPasswordKeyUp($event)" />
|
||||
</form>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@ -7,19 +7,14 @@
|
||||
.pdf-viewer-container {
|
||||
background-color: gray;
|
||||
|
||||
pdf-viewer {
|
||||
pngx-pdf-viewer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .ng2-pdf-viewer-container .page {
|
||||
--page-margin: 1px 0 10px;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
::ng-deep .ng2-pdf-viewer-container .page:last-child {
|
||||
--page-margin: 1px 0 20px;
|
||||
::ng-deep .pngx-pdf-viewer-container .page {
|
||||
--page-margin: 10px auto;
|
||||
}
|
||||
|
||||
::ng-deep .ng-select-taggable {
|
||||
@ -41,3 +36,11 @@
|
||||
textarea.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.form-select {
|
||||
padding-right: 2.5em;
|
||||
}
|
||||
|
||||
.input-group .btn-outline-secondary {
|
||||
border-color: var(--bs-border-color);
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import {
|
||||
NgbDateStruct,
|
||||
} from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgSelectModule } from '@ng-select/ng-select'
|
||||
import { PdfViewerComponent } from 'ng2-pdf-viewer'
|
||||
import { of, throwError } from 'rxjs'
|
||||
import { routes } from 'src/app/app-routing.module'
|
||||
import {
|
||||
@ -70,6 +69,7 @@ import { ShareLinksDropdownComponent } from '../common/share-links-dropdown/shar
|
||||
import { CustomFieldsDropdownComponent } from '../common/custom-fields-dropdown/custom-fields-dropdown.component'
|
||||
import { PaperlessCustomFieldDataType } from 'src/app/data/paperless-custom-field'
|
||||
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
|
||||
import { PdfViewerComponent } from '../common/pdf-viewer/pdf-viewer.component'
|
||||
|
||||
const doc: PaperlessDocument = {
|
||||
id: 3,
|
||||
@ -160,10 +160,10 @@ describe('DocumentDetailComponent', () => {
|
||||
PermissionsFormComponent,
|
||||
SafeHtmlPipe,
|
||||
ConfirmDialogComponent,
|
||||
PdfViewerComponent,
|
||||
SafeUrlPipe,
|
||||
ShareLinksDropdownComponent,
|
||||
CustomFieldsDropdownComponent,
|
||||
PdfViewerComponent,
|
||||
],
|
||||
providers: [
|
||||
DocumentTitlePipe,
|
||||
@ -683,6 +683,35 @@ describe('DocumentDetailComponent', () => {
|
||||
expect(component.previewNumPages).toEqual(1000)
|
||||
})
|
||||
|
||||
it('should support zoom controls', () => {
|
||||
initNormally()
|
||||
component.onZoomSelect({ target: { value: '1' } } as any) // from select
|
||||
expect(component.previewZoomSetting).toEqual('1')
|
||||
component.increaseZoom()
|
||||
expect(component.previewZoomSetting).toEqual('1.5')
|
||||
component.increaseZoom()
|
||||
expect(component.previewZoomSetting).toEqual('2')
|
||||
component.decreaseZoom()
|
||||
expect(component.previewZoomSetting).toEqual('1.5')
|
||||
component.onZoomSelect({ target: { value: '1' } } as any) // from select
|
||||
component.decreaseZoom()
|
||||
expect(component.previewZoomSetting).toEqual('.75')
|
||||
|
||||
component.onZoomSelect({ target: { value: 'page-fit' } } as any) // from select
|
||||
expect(component.previewZoomScale).toEqual('page-fit')
|
||||
expect(component.previewZoomSetting).toEqual('1')
|
||||
component.increaseZoom()
|
||||
expect(component.previewZoomSetting).toEqual('1.5')
|
||||
expect(component.previewZoomScale).toEqual('page-width')
|
||||
|
||||
component.onZoomSelect({ target: { value: 'page-fit' } } as any) // from select
|
||||
expect(component.previewZoomScale).toEqual('page-fit')
|
||||
expect(component.previewZoomSetting).toEqual('1')
|
||||
component.decreaseZoom()
|
||||
expect(component.previewZoomSetting).toEqual('.5')
|
||||
expect(component.previewZoomScale).toEqual('page-width')
|
||||
})
|
||||
|
||||
it('should support updating notes dynamically', () => {
|
||||
const notes = [
|
||||
{
|
||||
@ -806,7 +835,7 @@ describe('DocumentDetailComponent', () => {
|
||||
jest.spyOn(settingsService, 'get').mockReturnValue(false)
|
||||
expect(component.useNativePdfViewer).toBeFalsy()
|
||||
fixture.detectChanges()
|
||||
expect(fixture.debugElement.query(By.css('pdf-viewer'))).not.toBeNull()
|
||||
expect(fixture.debugElement.query(By.css('pngx-pdf-viewer'))).not.toBeNull()
|
||||
})
|
||||
|
||||
it('should display native pdf viewer if enabled', () => {
|
||||
|
@ -21,7 +21,6 @@ import { DocumentService } from 'src/app/services/rest/document.service'
|
||||
import { ConfirmDialogComponent } from '../common/confirm-dialog/confirm-dialog.component'
|
||||
import { CorrespondentEditDialogComponent } from '../common/edit-dialog/correspondent-edit-dialog/correspondent-edit-dialog.component'
|
||||
import { DocumentTypeEditDialogComponent } from '../common/edit-dialog/document-type-edit-dialog/document-type-edit-dialog.component'
|
||||
import { PDFDocumentProxy } from 'ng2-pdf-viewer'
|
||||
import { ToastService } from 'src/app/services/toast.service'
|
||||
import { TextComponent } from '../common/input/text/text.component'
|
||||
import { SettingsService } from 'src/app/services/settings.service'
|
||||
@ -69,6 +68,7 @@ import {
|
||||
} from 'src/app/data/paperless-custom-field'
|
||||
import { PaperlessCustomFieldInstance } from 'src/app/data/paperless-custom-field-instance'
|
||||
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
|
||||
import { PDFDocumentProxy } from '../common/pdf-viewer/typings'
|
||||
|
||||
enum DocumentDetailNavIDs {
|
||||
Details = 1,
|
||||
@ -79,6 +79,18 @@ enum DocumentDetailNavIDs {
|
||||
Permissions = 6,
|
||||
}
|
||||
|
||||
enum ZoomSetting {
|
||||
PageFit = 'page-fit',
|
||||
PageWidth = 'page-width',
|
||||
Quarter = '.25',
|
||||
Half = '.5',
|
||||
ThreeQuarters = '.75',
|
||||
One = '1',
|
||||
OneAndHalf = '1.5',
|
||||
Two = '2',
|
||||
Three = '3',
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'pngx-document-detail',
|
||||
templateUrl: './document-detail.component.html',
|
||||
@ -130,6 +142,8 @@ export class DocumentDetailComponent
|
||||
|
||||
previewCurrentPage: number = 1
|
||||
previewNumPages: number = 1
|
||||
previewZoomSetting: ZoomSetting = ZoomSetting.One
|
||||
previewZoomScale: ZoomSetting = ZoomSetting.PageWidth
|
||||
|
||||
store: BehaviorSubject<any>
|
||||
isDirty$: Observable<boolean>
|
||||
@ -744,6 +758,54 @@ export class DocumentDetailComponent
|
||||
}
|
||||
}
|
||||
|
||||
onZoomSelect(event: Event) {
|
||||
const setting = (event.target as HTMLSelectElement)?.value as ZoomSetting
|
||||
if (ZoomSetting.PageFit === setting) {
|
||||
this.previewZoomSetting = ZoomSetting.One
|
||||
this.previewZoomScale = setting
|
||||
} else {
|
||||
this.previewZoomScale = ZoomSetting.PageWidth
|
||||
this.previewZoomSetting = setting
|
||||
}
|
||||
}
|
||||
|
||||
get zoomSettings() {
|
||||
return Object.values(ZoomSetting).filter(
|
||||
(setting) => setting !== ZoomSetting.PageWidth
|
||||
)
|
||||
}
|
||||
|
||||
getZoomSettingTitle(setting: ZoomSetting): string {
|
||||
switch (setting) {
|
||||
case ZoomSetting.PageFit:
|
||||
return $localize`Page Fit`
|
||||
default:
|
||||
return `${parseFloat(setting) * 100}%`
|
||||
}
|
||||
}
|
||||
|
||||
increaseZoom(): void {
|
||||
let currentIndex = Object.values(ZoomSetting).indexOf(
|
||||
this.previewZoomSetting
|
||||
)
|
||||
if (this.previewZoomScale === ZoomSetting.PageFit) currentIndex = 5
|
||||
this.previewZoomScale = ZoomSetting.PageWidth
|
||||
this.previewZoomSetting =
|
||||
Object.values(ZoomSetting)[
|
||||
Math.min(Object.values(ZoomSetting).length - 1, currentIndex + 1)
|
||||
]
|
||||
}
|
||||
|
||||
decreaseZoom(): void {
|
||||
let currentIndex = Object.values(ZoomSetting).indexOf(
|
||||
this.previewZoomSetting
|
||||
)
|
||||
if (this.previewZoomScale === ZoomSetting.PageFit) currentIndex = 4
|
||||
this.previewZoomScale = ZoomSetting.PageWidth
|
||||
this.previewZoomSetting =
|
||||
Object.values(ZoomSetting)[Math.max(2, currentIndex - 1)]
|
||||
}
|
||||
|
||||
get showPermissions(): boolean {
|
||||
return (
|
||||
this.permissionsService.currentUserCan(
|
||||
|
Loading…
x
Reference in New Issue
Block a user