mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-05-19 12:42:14 -05:00
Fix/Chore: replace file drop package (#9926)
This commit is contained in:
parent
2c9e690dfb
commit
0ab85b5122
@ -7,8 +7,7 @@
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"test": "ng test --no-watch --coverage",
|
||||
"lint": "ng lint",
|
||||
"postinstall": "patch-package"
|
||||
"lint": "ng lint"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
@ -33,7 +32,6 @@
|
||||
"ngx-color": "^10.0.0",
|
||||
"ngx-cookie-service": "^19.1.2",
|
||||
"ngx-device-detector": "^9.0.0",
|
||||
"ngx-file-drop": "^16.0.0",
|
||||
"ngx-ui-tour-ng-bootstrap": "^16.0.0",
|
||||
"rxjs": "^7.8.2",
|
||||
"tslib": "^2.8.1",
|
||||
@ -67,7 +65,6 @@
|
||||
"jest-junit": "^16.0.0",
|
||||
"jest-preset-angular": "^14.5.5",
|
||||
"jest-websocket-mock": "^2.5.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"ts-node": "~10.9.1",
|
||||
"typescript": "^5.5.4"
|
||||
|
File diff suppressed because one or more lines are too long
224
src-ui/pnpm-lock.yaml
generated
224
src-ui/pnpm-lock.yaml
generated
@ -71,12 +71,9 @@ importers:
|
||||
ngx-device-detector:
|
||||
specifier: ^9.0.0
|
||||
version: 9.0.0(@angular/common@19.2.9(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))
|
||||
ngx-file-drop:
|
||||
specifier: ^16.0.0
|
||||
version: 16.0.0(@angular/common@19.2.9(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))
|
||||
ngx-ui-tour-ng-bootstrap:
|
||||
specifier: ^16.0.0
|
||||
version: 16.0.0(nfyq54qpjcnpjhdwpvrgi4nyra)
|
||||
version: 16.0.0(9bfbf45bdfd1029869b23707ee6bb312)
|
||||
rxjs:
|
||||
specifier: ^7.8.2
|
||||
version: 7.8.2
|
||||
@ -98,7 +95,7 @@ importers:
|
||||
version: 19.0.1(@angular/compiler-cli@19.2.9(@angular/compiler@19.2.9)(typescript@5.5.4))(@angular/compiler@19.2.9)(@angular/localize@19.2.9(@angular/compiler-cli@19.2.9(@angular/compiler@19.2.9)(typescript@5.5.4))(@angular/compiler@19.2.9))(@types/node@22.15.3)(chokidar@4.0.3)(jest-environment-jsdom@29.7.0)(jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.5.4)))(jiti@1.21.7)(typescript@5.5.4)(vite@6.2.7(@types/node@22.15.3)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.7.0))(yaml@2.7.0)
|
||||
'@angular-builders/jest':
|
||||
specifier: ^19.0.1
|
||||
version: 19.0.1(2xzflpchozqzu223xxigbxxvgu)
|
||||
version: 19.0.1(025d537e0c22047bb48e08c4eeeaebf1)
|
||||
'@angular-devkit/build-angular':
|
||||
specifier: ^19.2.10
|
||||
version: 19.2.10(@angular/compiler-cli@19.2.9(@angular/compiler@19.2.9)(typescript@5.5.4))(@angular/compiler@19.2.9)(@angular/localize@19.2.9(@angular/compiler-cli@19.2.9(@angular/compiler@19.2.9)(typescript@5.5.4))(@angular/compiler@19.2.9))(@types/node@22.15.3)(chokidar@4.0.3)(jest-environment-jsdom@29.7.0)(jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.5.4)))(jiti@1.21.7)(typescript@5.5.4)(vite@6.2.7(@types/node@22.15.3)(jiti@1.21.7)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(yaml@2.7.0))(yaml@2.7.0)
|
||||
@ -168,9 +165,6 @@ importers:
|
||||
jest-websocket-mock:
|
||||
specifier: ^2.5.0
|
||||
version: 2.5.0
|
||||
patch-package:
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.0
|
||||
prettier-plugin-organize-imports:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0(prettier@3.4.2)(typescript@5.5.4)
|
||||
@ -2780,10 +2774,6 @@ packages:
|
||||
asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
|
||||
at-least-node@1.0.0:
|
||||
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
|
||||
autoprefixer@10.4.20:
|
||||
resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@ -2931,10 +2921,6 @@ packages:
|
||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
call-bind@1.0.7:
|
||||
resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
call-bound@1.0.4:
|
||||
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -3226,10 +3212,6 @@ packages:
|
||||
defaults@1.0.4:
|
||||
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
|
||||
|
||||
define-data-property@1.1.4:
|
||||
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
define-lazy-prop@3.0.0:
|
||||
resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
|
||||
engines: {node: '>=12'}
|
||||
@ -3607,9 +3589,6 @@ packages:
|
||||
resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
find-yarn-workspace-root@2.0.0:
|
||||
resolution: {integrity: sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==}
|
||||
|
||||
flat-cache@4.0.1:
|
||||
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
|
||||
engines: {node: '>=16'}
|
||||
@ -3652,10 +3631,6 @@ packages:
|
||||
fs-constants@1.0.0:
|
||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||
|
||||
fs-extra@9.1.0:
|
||||
resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
fs-minipass@2.1.0:
|
||||
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
|
||||
engines: {node: '>= 8'}
|
||||
@ -3692,10 +3667,6 @@ packages:
|
||||
resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
get-intrinsic@1.2.7:
|
||||
resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -3763,9 +3734,6 @@ packages:
|
||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
has-property-descriptors@1.0.2:
|
||||
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
|
||||
|
||||
has-symbols@1.1.0:
|
||||
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -3943,11 +3911,6 @@ packages:
|
||||
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-docker@2.2.1:
|
||||
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
is-docker@3.0.0:
|
||||
resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
@ -4020,10 +3983,6 @@ packages:
|
||||
is-what@3.14.1:
|
||||
resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==}
|
||||
|
||||
is-wsl@2.2.0:
|
||||
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-wsl@3.1.0:
|
||||
resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
|
||||
engines: {node: '>=16'}
|
||||
@ -4031,9 +3990,6 @@ packages:
|
||||
isarray@1.0.0:
|
||||
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
|
||||
|
||||
isarray@2.0.5:
|
||||
resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
|
||||
|
||||
isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
|
||||
@ -4310,10 +4266,6 @@ packages:
|
||||
json-stable-stringify-without-jsonify@1.0.1:
|
||||
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
|
||||
|
||||
json-stable-stringify@1.1.0:
|
||||
resolution: {integrity: sha512-zfA+5SuwYN2VWqN1/5HZaDzQKLJHaBVMZIIM+wuYjdptkaQsqzDdqjqf+lZZJUuJq1aanHiY8LhH8LmH+qBYJA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
json5@2.2.3:
|
||||
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
|
||||
engines: {node: '>=6'}
|
||||
@ -4322,12 +4274,6 @@ packages:
|
||||
jsonc-parser@3.3.1:
|
||||
resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}
|
||||
|
||||
jsonfile@6.1.0:
|
||||
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
|
||||
|
||||
jsonify@0.0.1:
|
||||
resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==}
|
||||
|
||||
jsonparse@1.3.1:
|
||||
resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
|
||||
engines: {'0': node >= 0.2.0}
|
||||
@ -4342,9 +4288,6 @@ packages:
|
||||
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
klaw-sync@6.0.0:
|
||||
resolution: {integrity: sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==}
|
||||
|
||||
kleur@3.0.3:
|
||||
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
|
||||
engines: {node: '>=6'}
|
||||
@ -4708,13 +4651,6 @@ packages:
|
||||
'@angular/common': ^19.0.0
|
||||
'@angular/core': ^19.0.0
|
||||
|
||||
ngx-file-drop@16.0.0:
|
||||
resolution: {integrity: sha512-33RPoZBAiMkV110Rzu3iOrzGcG5M20S4sAiwLzNylfJobu9qVw5XR83FhUelSeqJRoaDxXBRKAozYCSnUf2CNw==}
|
||||
engines: {node: '>= 14.5.0', npm: '>= 6.9.0'}
|
||||
peerDependencies:
|
||||
'@angular/common': '>=14.0.0'
|
||||
'@angular/core': '>=14.0.0'
|
||||
|
||||
ngx-ui-tour-core@14.0.0:
|
||||
resolution: {integrity: sha512-6pzzEwxn/gCS3puEXDqgINBRbhvhzHYjmiA9DTCNEx1dPfYwjZVmPqNvNeZIVHucVnVZViAAKvA6MTc3Gm7aOw==}
|
||||
peerDependencies:
|
||||
@ -4814,10 +4750,6 @@ packages:
|
||||
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
object-keys@1.1.1:
|
||||
resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
obuf@1.1.2:
|
||||
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
|
||||
|
||||
@ -4844,10 +4776,6 @@ packages:
|
||||
resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
open@7.4.2:
|
||||
resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
optionator@0.9.4:
|
||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@ -4935,11 +4863,6 @@ packages:
|
||||
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
patch-package@8.0.0:
|
||||
resolution: {integrity: sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==}
|
||||
engines: {node: '>=14', npm: '>5'}
|
||||
hasBin: true
|
||||
|
||||
path-exists@4.0.0:
|
||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||
engines: {node: '>=8'}
|
||||
@ -5265,11 +5188,6 @@ packages:
|
||||
rfdc@1.4.1:
|
||||
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
|
||||
|
||||
rimraf@2.7.1:
|
||||
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
|
||||
deprecated: Rimraf versions prior to v4 are no longer supported
|
||||
hasBin: true
|
||||
|
||||
rollup@4.34.8:
|
||||
resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
@ -5369,10 +5287,6 @@ packages:
|
||||
resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
set-function-length@1.2.1:
|
||||
resolution: {integrity: sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
setprototypeof@1.1.0:
|
||||
resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==}
|
||||
|
||||
@ -5434,10 +5348,6 @@ packages:
|
||||
sisteransi@1.0.5:
|
||||
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
|
||||
|
||||
slash@2.0.0:
|
||||
resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
slash@3.0.0:
|
||||
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
|
||||
engines: {node: '>=8'}
|
||||
@ -5825,10 +5735,6 @@ packages:
|
||||
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
|
||||
universalify@2.0.1:
|
||||
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
||||
unpipe@1.0.0:
|
||||
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -6233,7 +6139,7 @@ snapshots:
|
||||
- webpack-cli
|
||||
- yaml
|
||||
|
||||
'@angular-builders/jest@19.0.1(2xzflpchozqzu223xxigbxxvgu)':
|
||||
'@angular-builders/jest@19.0.1(025d537e0c22047bb48e08c4eeeaebf1)':
|
||||
dependencies:
|
||||
'@angular-builders/common': 3.0.1(@types/node@22.15.3)(chokidar@4.0.3)(typescript@5.5.4)
|
||||
'@angular-devkit/architect': 0.1902.8(chokidar@4.0.3)
|
||||
@ -8995,8 +8901,6 @@ snapshots:
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
|
||||
at-least-node@1.0.0: {}
|
||||
|
||||
autoprefixer@10.4.20(postcss@8.5.2):
|
||||
dependencies:
|
||||
browserslist: 4.24.4
|
||||
@ -9215,14 +9119,6 @@ snapshots:
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
|
||||
call-bind@1.0.7:
|
||||
dependencies:
|
||||
es-define-property: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
get-intrinsic: 1.2.7
|
||||
set-function-length: 1.2.1
|
||||
|
||||
call-bound@1.0.4:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@ -9497,12 +9393,6 @@ snapshots:
|
||||
dependencies:
|
||||
clone: 1.0.4
|
||||
|
||||
define-data-property@1.1.4:
|
||||
dependencies:
|
||||
es-define-property: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
gopd: 1.2.0
|
||||
|
||||
define-lazy-prop@3.0.0: {}
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
@ -9970,10 +9860,6 @@ snapshots:
|
||||
locate-path: 7.2.0
|
||||
path-exists: 5.0.0
|
||||
|
||||
find-yarn-workspace-root@2.0.0:
|
||||
dependencies:
|
||||
micromatch: 4.0.8
|
||||
|
||||
flat-cache@4.0.1:
|
||||
dependencies:
|
||||
flatted: 3.3.3
|
||||
@ -10007,13 +9893,6 @@ snapshots:
|
||||
fs-constants@1.0.0:
|
||||
optional: true
|
||||
|
||||
fs-extra@9.1.0:
|
||||
dependencies:
|
||||
at-least-node: 1.0.0
|
||||
graceful-fs: 4.2.11
|
||||
jsonfile: 6.1.0
|
||||
universalify: 2.0.1
|
||||
|
||||
fs-minipass@2.1.0:
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
@ -10038,19 +9917,6 @@ snapshots:
|
||||
|
||||
get-east-asian-width@1.3.0: {}
|
||||
|
||||
get-intrinsic@1.2.7:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
es-define-property: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
es-object-atoms: 1.1.1
|
||||
function-bind: 1.1.2
|
||||
get-proto: 1.0.1
|
||||
gopd: 1.2.0
|
||||
has-symbols: 1.1.0
|
||||
hasown: 2.0.2
|
||||
math-intrinsics: 1.1.0
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@ -10127,10 +9993,6 @@ snapshots:
|
||||
|
||||
has-flag@4.0.0: {}
|
||||
|
||||
has-property-descriptors@1.0.2:
|
||||
dependencies:
|
||||
es-define-property: 1.0.1
|
||||
|
||||
has-symbols@1.1.0: {}
|
||||
|
||||
hasown@2.0.2:
|
||||
@ -10320,8 +10182,6 @@ snapshots:
|
||||
dependencies:
|
||||
hasown: 2.0.2
|
||||
|
||||
is-docker@2.2.1: {}
|
||||
|
||||
is-docker@3.0.0: {}
|
||||
|
||||
is-extglob@2.1.1: {}
|
||||
@ -10366,18 +10226,12 @@ snapshots:
|
||||
|
||||
is-what@3.14.1: {}
|
||||
|
||||
is-wsl@2.2.0:
|
||||
dependencies:
|
||||
is-docker: 2.2.1
|
||||
|
||||
is-wsl@3.1.0:
|
||||
dependencies:
|
||||
is-inside-container: 1.0.0
|
||||
|
||||
isarray@1.0.0: {}
|
||||
|
||||
isarray@2.0.5: {}
|
||||
|
||||
isexe@2.0.0: {}
|
||||
|
||||
isexe@3.1.1: {}
|
||||
@ -10896,25 +10750,10 @@ snapshots:
|
||||
|
||||
json-stable-stringify-without-jsonify@1.0.1: {}
|
||||
|
||||
json-stable-stringify@1.1.0:
|
||||
dependencies:
|
||||
call-bind: 1.0.7
|
||||
isarray: 2.0.5
|
||||
jsonify: 0.0.1
|
||||
object-keys: 1.1.1
|
||||
|
||||
json5@2.2.3: {}
|
||||
|
||||
jsonc-parser@3.3.1: {}
|
||||
|
||||
jsonfile@6.1.0:
|
||||
dependencies:
|
||||
universalify: 2.0.1
|
||||
optionalDependencies:
|
||||
graceful-fs: 4.2.11
|
||||
|
||||
jsonify@0.0.1: {}
|
||||
|
||||
jsonparse@1.3.1: {}
|
||||
|
||||
karma-source-map-support@1.4.0:
|
||||
@ -10927,10 +10766,6 @@ snapshots:
|
||||
|
||||
kind-of@6.0.3: {}
|
||||
|
||||
klaw-sync@6.0.0:
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
|
||||
kleur@3.0.3: {}
|
||||
|
||||
launch-editor@2.10.0:
|
||||
@ -11289,12 +11124,6 @@ snapshots:
|
||||
'@angular/core': 19.2.9(rxjs@7.8.2)(zone.js@0.15.0)
|
||||
tslib: 2.8.1
|
||||
|
||||
ngx-file-drop@16.0.0(@angular/common@19.2.9(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0)):
|
||||
dependencies:
|
||||
'@angular/common': 19.2.9(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
|
||||
'@angular/core': 19.2.9(rxjs@7.8.2)(zone.js@0.15.0)
|
||||
tslib: 2.8.1
|
||||
|
||||
ngx-ui-tour-core@14.0.0(@angular/common@19.2.9(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(@angular/router@19.2.9(@angular/common@19.2.9(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@19.2.9(@angular/common@19.2.9(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0)))(rxjs@7.8.2))(rxjs@7.8.2):
|
||||
dependencies:
|
||||
'@angular/common': 19.2.9(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
|
||||
@ -11303,7 +11132,7 @@ snapshots:
|
||||
rxjs: 7.8.2
|
||||
tslib: 2.8.1
|
||||
|
||||
ngx-ui-tour-ng-bootstrap@16.0.0(nfyq54qpjcnpjhdwpvrgi4nyra):
|
||||
ngx-ui-tour-ng-bootstrap@16.0.0(9bfbf45bdfd1029869b23707ee6bb312):
|
||||
dependencies:
|
||||
'@angular/common': 19.2.9(@angular/core@19.2.9(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
|
||||
'@angular/core': 19.2.9(rxjs@7.8.2)(zone.js@0.15.0)
|
||||
@ -11412,8 +11241,6 @@ snapshots:
|
||||
|
||||
object-inspect@1.13.4: {}
|
||||
|
||||
object-keys@1.1.1: {}
|
||||
|
||||
obuf@1.1.2: {}
|
||||
|
||||
on-finished@2.4.1:
|
||||
@ -11441,11 +11268,6 @@ snapshots:
|
||||
is-inside-container: 1.0.0
|
||||
is-wsl: 3.1.0
|
||||
|
||||
open@7.4.2:
|
||||
dependencies:
|
||||
is-docker: 2.2.1
|
||||
is-wsl: 2.2.0
|
||||
|
||||
optionator@0.9.4:
|
||||
dependencies:
|
||||
deep-is: 0.1.4
|
||||
@ -11561,24 +11383,6 @@ snapshots:
|
||||
|
||||
parseurl@1.3.3: {}
|
||||
|
||||
patch-package@8.0.0:
|
||||
dependencies:
|
||||
'@yarnpkg/lockfile': 1.1.0
|
||||
chalk: 4.1.2
|
||||
ci-info: 3.9.0
|
||||
cross-spawn: 7.0.6
|
||||
find-yarn-workspace-root: 2.0.0
|
||||
fs-extra: 9.1.0
|
||||
json-stable-stringify: 1.1.0
|
||||
klaw-sync: 6.0.0
|
||||
minimist: 1.2.8
|
||||
open: 7.4.2
|
||||
rimraf: 2.7.1
|
||||
semver: 7.7.1
|
||||
slash: 2.0.0
|
||||
tmp: 0.0.33
|
||||
yaml: 2.7.0
|
||||
|
||||
path-exists@4.0.0: {}
|
||||
|
||||
path-exists@5.0.0: {}
|
||||
@ -11883,10 +11687,6 @@ snapshots:
|
||||
|
||||
rfdc@1.4.1: {}
|
||||
|
||||
rimraf@2.7.1:
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
|
||||
rollup@4.34.8:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.6
|
||||
@ -12018,15 +11818,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
set-function-length@1.2.1:
|
||||
dependencies:
|
||||
define-data-property: 1.1.4
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
get-intrinsic: 1.2.7
|
||||
gopd: 1.2.0
|
||||
has-property-descriptors: 1.0.2
|
||||
|
||||
setprototypeof@1.1.0: {}
|
||||
|
||||
setprototypeof@1.2.0: {}
|
||||
@ -12105,8 +11896,6 @@ snapshots:
|
||||
|
||||
sisteransi@1.0.5: {}
|
||||
|
||||
slash@2.0.0: {}
|
||||
|
||||
slash@3.0.0: {}
|
||||
|
||||
slash@5.1.0: {}
|
||||
@ -12517,8 +12306,6 @@ snapshots:
|
||||
|
||||
universalify@0.2.0: {}
|
||||
|
||||
universalify@2.0.1: {}
|
||||
|
||||
unpipe@1.0.0: {}
|
||||
|
||||
unplugin@1.16.1:
|
||||
@ -12783,7 +12570,8 @@ snapshots:
|
||||
|
||||
yallist@5.0.0: {}
|
||||
|
||||
yaml@2.7.0: {}
|
||||
yaml@2.7.0:
|
||||
optional: true
|
||||
|
||||
yargs-parser@21.1.1: {}
|
||||
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
import { Router, RouterModule } from '@angular/router'
|
||||
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { allIcons, NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
import { NgxFileDropModule } from 'ngx-file-drop'
|
||||
import { TourNgBootstrapModule, TourService } from 'ngx-ui-tour-ng-bootstrap'
|
||||
import { Subject } from 'rxjs'
|
||||
import { routes } from './app-routing.module'
|
||||
@ -43,7 +42,6 @@ describe('AppComponent', () => {
|
||||
imports: [
|
||||
TourNgBootstrapModule,
|
||||
RouterModule.forRoot(routes),
|
||||
NgxFileDropModule,
|
||||
NgbModalModule,
|
||||
AppComponent,
|
||||
ToastsComponent,
|
||||
|
@ -82,10 +82,20 @@ describe('UploadFileWidgetComponent', () => {
|
||||
})
|
||||
|
||||
it('should upload files', () => {
|
||||
const uploadSpy = jest.spyOn(uploadDocumentsService, 'uploadFiles')
|
||||
fixture.debugElement
|
||||
.query(By.css('input'))
|
||||
.nativeElement.dispatchEvent(new Event('change'))
|
||||
const uploadSpy = jest.spyOn(uploadDocumentsService, 'uploadFile')
|
||||
const file = new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
const fileInput = fixture.debugElement.query(By.css('input'))
|
||||
jest.spyOn(fileInput.nativeElement, 'files', 'get').mockReturnValue({
|
||||
item: () => file,
|
||||
length: 1,
|
||||
[Symbol.iterator]: () => ({
|
||||
next: () => ({ done: false, value: file }),
|
||||
}),
|
||||
} as any)
|
||||
fileInput.nativeElement.dispatchEvent(new Event('change'))
|
||||
expect(uploadSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
|
@ -134,9 +134,11 @@ export class UploadFileWidgetComponent extends ComponentWithPermissions {
|
||||
}
|
||||
|
||||
public onFileSelected(event: Event) {
|
||||
this.uploadDocumentsService.uploadFiles(
|
||||
(event.target as HTMLInputElement).files
|
||||
)
|
||||
const files = (event.target as HTMLInputElement).files
|
||||
for (let i = 0; i < files?.length; i++) {
|
||||
const file = files.item(i)
|
||||
file && this.uploadDocumentsService.uploadFile(file)
|
||||
}
|
||||
}
|
||||
|
||||
get slimSidebarEnabled(): boolean {
|
||||
|
@ -2,13 +2,6 @@
|
||||
<ng-content select="[content]"></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="global-dropzone-overlay position-fixed top-0 start-0 bottom-0 end-0 text-center pe-none fade" [class.show]="fileIsOver" [class.hide]="hidden">
|
||||
<div class="global-dropzone-overlay position-fixed top-0 start-0 bottom-0 end-0 text-center pe-none" [class.active]="fileIsOver && !hidden">
|
||||
<h2 class="pe-none position-absolute top-50 start-50 translate-middle" i18n>Drop files to begin upload</h2>
|
||||
</div>
|
||||
|
||||
<ngx-file-drop
|
||||
dropZoneClassName="visually-hidden"
|
||||
contentClassName="visually-hidden"
|
||||
(onFileDrop)="dropped($event)"
|
||||
#ngxFileDrop>
|
||||
</ngx-file-drop>
|
||||
|
@ -1,8 +1,14 @@
|
||||
.global-dropzone-overlay {
|
||||
opacity: 0;
|
||||
transition: opacity 0.25s ease-in-out;
|
||||
background-color: hsla(var(--pngx-primary), var(--pngx-primary-lightness), .8);
|
||||
z-index: 1200;
|
||||
|
||||
h2 {
|
||||
color: var(--pngx-primary-text-contrast)
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
tick,
|
||||
} from '@angular/core/testing'
|
||||
import { By } from '@angular/platform-browser'
|
||||
import { NgxFileDropEntry, NgxFileDropModule } from 'ngx-file-drop'
|
||||
import { PermissionsService } from 'src/app/services/permissions.service'
|
||||
import { SettingsService } from 'src/app/services/settings.service'
|
||||
import { ToastService } from 'src/app/services/toast.service'
|
||||
@ -27,7 +26,7 @@ describe('FileDropComponent', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [NgxFileDropModule, FileDropComponent, ToastsComponent],
|
||||
imports: [FileDropComponent, ToastsComponent],
|
||||
providers: [
|
||||
provideHttpClient(withInterceptorsFromDi()),
|
||||
provideHttpClientTesting(),
|
||||
@ -66,12 +65,12 @@ describe('FileDropComponent', () => {
|
||||
const dropzone = fixture.debugElement.query(
|
||||
By.css('.global-dropzone-overlay')
|
||||
)
|
||||
expect(dropzone.classes['hide']).toBeTruthy()
|
||||
expect(dropzone.classes['active']).toBeFalsy()
|
||||
component.onDragLeave(new Event('dragleave') as DragEvent)
|
||||
tick(700)
|
||||
fixture.detectChanges()
|
||||
// drop
|
||||
const uploadSpy = jest.spyOn(uploadDocumentsService, 'uploadFiles')
|
||||
const uploadSpy = jest.spyOn(uploadDocumentsService, 'uploadFile')
|
||||
const dragEvent = new Event('drop')
|
||||
dragEvent['dataTransfer'] = {
|
||||
files: {
|
||||
@ -93,53 +92,209 @@ describe('FileDropComponent', () => {
|
||||
tick(1)
|
||||
fixture.detectChanges()
|
||||
expect(component.fileIsOver).toBeTruthy()
|
||||
const dropzone = fixture.debugElement.query(
|
||||
By.css('.global-dropzone-overlay')
|
||||
)
|
||||
component.onDragLeave(new Event('dragleave') as DragEvent)
|
||||
tick(700)
|
||||
fixture.detectChanges()
|
||||
expect(dropzone.classes['hide']).toBeTruthy()
|
||||
// drop
|
||||
const toastSpy = jest.spyOn(toastService, 'show')
|
||||
const uploadSpy = jest.spyOn(
|
||||
UploadDocumentsService.prototype as any,
|
||||
'uploadFile'
|
||||
const uploadSpy = jest.spyOn(uploadDocumentsService, 'uploadFile')
|
||||
const file = new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
const dragEvent = new Event('drop')
|
||||
dragEvent['dataTransfer'] = {
|
||||
files: {
|
||||
item: () => {
|
||||
return new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
items: [
|
||||
{
|
||||
kind: 'file',
|
||||
type: 'application/pdf',
|
||||
getAsFile: () => file,
|
||||
},
|
||||
length: 1,
|
||||
} as unknown as FileList,
|
||||
],
|
||||
}
|
||||
component.onDrop(dragEvent as DragEvent)
|
||||
component.dropped([
|
||||
{
|
||||
fileEntry: {
|
||||
isFile: true,
|
||||
file: (callback) => {
|
||||
callback(
|
||||
new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
)
|
||||
},
|
||||
},
|
||||
} as unknown as NgxFileDropEntry,
|
||||
])
|
||||
tick(3000)
|
||||
expect(toastSpy).toHaveBeenCalled()
|
||||
expect(uploadSpy).toHaveBeenCalled()
|
||||
discardPeriodicTasks()
|
||||
}))
|
||||
|
||||
it('should support drag drop, initiate upload with webkitGetAsEntry', fakeAsync(() => {
|
||||
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
|
||||
expect(component.fileIsOver).toBeFalsy()
|
||||
const overEvent = new Event('dragover') as DragEvent
|
||||
;(overEvent as any).dataTransfer = { types: ['Files'] }
|
||||
component.onDragOver(overEvent)
|
||||
tick(1)
|
||||
fixture.detectChanges()
|
||||
expect(component.fileIsOver).toBeTruthy()
|
||||
component.onDragLeave(new Event('dragleave') as DragEvent)
|
||||
tick(700)
|
||||
fixture.detectChanges()
|
||||
// drop
|
||||
const toastSpy = jest.spyOn(toastService, 'show')
|
||||
const uploadSpy = jest.spyOn(uploadDocumentsService, 'uploadFile')
|
||||
const file = new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
const dragEvent = new Event('drop')
|
||||
dragEvent['dataTransfer'] = {
|
||||
items: [
|
||||
{
|
||||
kind: 'file',
|
||||
type: 'application/pdf',
|
||||
webkitGetAsEntry: () => ({
|
||||
isFile: true,
|
||||
isDirectory: false,
|
||||
file: (cb: (file: File) => void) => cb(file),
|
||||
}),
|
||||
},
|
||||
],
|
||||
files: [],
|
||||
}
|
||||
component.onDrop(dragEvent as DragEvent)
|
||||
tick(3000)
|
||||
expect(toastSpy).toHaveBeenCalled()
|
||||
expect(uploadSpy).toHaveBeenCalled()
|
||||
discardPeriodicTasks()
|
||||
}))
|
||||
|
||||
it('should show an error on traverseFileTree error', fakeAsync(() => {
|
||||
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
|
||||
const toastSpy = jest.spyOn(toastService, 'showError')
|
||||
const traverseSpy = jest
|
||||
.spyOn(component as any, 'traverseFileTree')
|
||||
.mockReturnValue(Promise.reject(new Error('Error traversing file tree')))
|
||||
fixture.detectChanges()
|
||||
|
||||
// Simulate a drop with a directory entry
|
||||
const mockEntry = {
|
||||
isDirectory: true,
|
||||
isFile: false,
|
||||
createReader: () => ({ readEntries: jest.fn() }),
|
||||
} as unknown as FileSystemDirectoryEntry
|
||||
|
||||
const event = {
|
||||
preventDefault: () => {},
|
||||
stopImmediatePropagation: () => {},
|
||||
dataTransfer: {
|
||||
items: [
|
||||
{
|
||||
kind: 'file',
|
||||
webkitGetAsEntry: () => mockEntry,
|
||||
},
|
||||
],
|
||||
},
|
||||
} as unknown as DragEvent
|
||||
|
||||
component.onDrop(event)
|
||||
|
||||
tick() // flush microtasks (e.g., Promise.reject)
|
||||
|
||||
expect(traverseSpy).toHaveBeenCalled()
|
||||
expect(toastSpy).toHaveBeenCalledWith(
|
||||
$localize`Failed to read dropped items: Error traversing file tree`
|
||||
)
|
||||
|
||||
discardPeriodicTasks()
|
||||
}))
|
||||
|
||||
it('should support drag drop, initiate upload without DataTransfer API support', fakeAsync(() => {
|
||||
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
|
||||
expect(component.fileIsOver).toBeFalsy()
|
||||
const overEvent = new Event('dragover') as DragEvent
|
||||
;(overEvent as any).dataTransfer = { types: ['Files'] }
|
||||
component.onDragOver(overEvent)
|
||||
tick(1)
|
||||
fixture.detectChanges()
|
||||
expect(component.fileIsOver).toBeTruthy()
|
||||
component.onDragLeave(new Event('dragleave') as DragEvent)
|
||||
tick(700)
|
||||
fixture.detectChanges()
|
||||
// drop
|
||||
const toastSpy = jest.spyOn(toastService, 'show')
|
||||
const uploadSpy = jest.spyOn(uploadDocumentsService, 'uploadFile')
|
||||
const file = new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
const dragEvent = new Event('drop')
|
||||
dragEvent['dataTransfer'] = {
|
||||
items: [],
|
||||
files: [file],
|
||||
}
|
||||
component.onDrop(dragEvent as DragEvent)
|
||||
tick(3000)
|
||||
expect(toastSpy).toHaveBeenCalled()
|
||||
expect(uploadSpy).toHaveBeenCalled()
|
||||
discardPeriodicTasks()
|
||||
}))
|
||||
|
||||
it('should resolve a single file when entry isFile', () => {
|
||||
const mockFile = new File(['data'], 'test.txt', { type: 'text/plain' })
|
||||
const mockEntry = {
|
||||
isFile: true,
|
||||
isDirectory: false,
|
||||
file: (cb: (f: File) => void) => cb(mockFile),
|
||||
} as unknown as FileSystemFileEntry
|
||||
|
||||
return (component as any)
|
||||
.traverseFileTree(mockEntry)
|
||||
.then((result: File[]) => {
|
||||
expect(result).toEqual([mockFile])
|
||||
})
|
||||
})
|
||||
|
||||
it('should resolve all files in a flat directory', async () => {
|
||||
const file1 = new File(['data'], 'file1.txt')
|
||||
const file2 = new File(['data'], 'file2.txt')
|
||||
|
||||
const mockFileEntry1 = {
|
||||
isFile: true,
|
||||
isDirectory: false,
|
||||
file: (cb: (f: File) => void) => cb(file1),
|
||||
} as unknown as FileSystemFileEntry
|
||||
|
||||
const mockFileEntry2 = {
|
||||
isFile: true,
|
||||
isDirectory: false,
|
||||
file: (cb: (f: File) => void) => cb(file2),
|
||||
} as unknown as FileSystemFileEntry
|
||||
|
||||
let callCount = 0
|
||||
|
||||
const mockDirEntry = {
|
||||
isFile: false,
|
||||
isDirectory: true,
|
||||
createReader: () => ({
|
||||
readEntries: (cb: (batch: FileSystemEntry[]) => void) => {
|
||||
if (callCount++ === 0) {
|
||||
cb([mockFileEntry1, mockFileEntry2])
|
||||
} else {
|
||||
cb([]) // second call: signal EOF
|
||||
}
|
||||
},
|
||||
}),
|
||||
} as unknown as FileSystemDirectoryEntry
|
||||
|
||||
const result = await (component as any).traverseFileTree(mockDirEntry)
|
||||
expect(result).toEqual([file1, file2])
|
||||
})
|
||||
|
||||
it('should resolve a non-file non-directory entry as an empty array', () => {
|
||||
const mockEntry = {
|
||||
isFile: false,
|
||||
isDirectory: false,
|
||||
file: (cb: (f: File) => void) => cb(new File([], '')),
|
||||
} as unknown as FileSystemEntry
|
||||
return (component as any)
|
||||
.traverseFileTree(mockEntry)
|
||||
.then((result: File[]) => {
|
||||
expect(result).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
it('should ignore events if disabled', fakeAsync(() => {
|
||||
settingsService.globalDropzoneEnabled = false
|
||||
expect(settingsService.globalDropzoneActive).toBeFalsy()
|
||||
|
@ -1,9 +1,4 @@
|
||||
import { Component, HostListener, ViewChild } from '@angular/core'
|
||||
import {
|
||||
NgxFileDropComponent,
|
||||
NgxFileDropEntry,
|
||||
NgxFileDropModule,
|
||||
} from 'ngx-file-drop'
|
||||
import { Component, HostListener } from '@angular/core'
|
||||
import {
|
||||
PermissionAction,
|
||||
PermissionsService,
|
||||
@ -17,7 +12,7 @@ import { UploadDocumentsService } from 'src/app/services/upload-documents.servic
|
||||
selector: 'pngx-file-drop',
|
||||
templateUrl: './file-drop.component.html',
|
||||
styleUrls: ['./file-drop.component.scss'],
|
||||
imports: [NgxFileDropModule],
|
||||
imports: [],
|
||||
})
|
||||
export class FileDropComponent {
|
||||
private fileLeaveTimeoutID: any
|
||||
@ -41,8 +36,6 @@ export class FileDropComponent {
|
||||
)
|
||||
}
|
||||
|
||||
@ViewChild('ngxFileDrop') ngxFileDrop: NgxFileDropComponent
|
||||
|
||||
@HostListener('document:dragover', ['$event']) onDragOver(event: DragEvent) {
|
||||
if (!this.dragDropEnabled || !event.dataTransfer?.types?.includes('Files'))
|
||||
return
|
||||
@ -78,19 +71,85 @@ export class FileDropComponent {
|
||||
}, ms)
|
||||
}
|
||||
|
||||
private traverseFileTree(entry: FileSystemEntry): Promise<File[]> {
|
||||
if (entry.isFile) {
|
||||
return new Promise((resolve, reject) => {
|
||||
;(entry as FileSystemFileEntry).file(resolve, reject)
|
||||
}).then((file: File) => [file])
|
||||
}
|
||||
|
||||
if (entry.isDirectory) {
|
||||
return new Promise<File[]>((resolve, reject) => {
|
||||
const dirReader = (entry as FileSystemDirectoryEntry).createReader()
|
||||
const allEntries: FileSystemEntry[] = []
|
||||
|
||||
const readEntries = () => {
|
||||
dirReader.readEntries((batch) => {
|
||||
if (batch.length === 0) {
|
||||
const promises = allEntries.map((child) =>
|
||||
this.traverseFileTree(child)
|
||||
)
|
||||
Promise.all(promises)
|
||||
.then((results) => resolve([].concat(...results)))
|
||||
.catch(reject)
|
||||
} else {
|
||||
allEntries.push(...batch)
|
||||
readEntries() // keep reading
|
||||
}
|
||||
}, reject)
|
||||
}
|
||||
|
||||
readEntries()
|
||||
})
|
||||
}
|
||||
|
||||
return Promise.resolve([])
|
||||
}
|
||||
|
||||
@HostListener('document:drop', ['$event']) public onDrop(event: DragEvent) {
|
||||
if (!this.dragDropEnabled) return
|
||||
event.preventDefault()
|
||||
event.stopImmediatePropagation()
|
||||
// pass event onto ngx-file-drop to handle files
|
||||
this.ngxFileDrop.dropFiles(event)
|
||||
this.onDragLeave(event, true)
|
||||
}
|
||||
|
||||
public dropped(files: NgxFileDropEntry[]) {
|
||||
this.uploadDocumentsService.onNgxFileDrop(files)
|
||||
if (files.length > 0)
|
||||
const files: File[] = []
|
||||
const entries: FileSystemEntry[] = []
|
||||
if (event.dataTransfer?.items && event.dataTransfer.items.length) {
|
||||
for (const item of Array.from(event.dataTransfer.items)) {
|
||||
if (item.webkitGetAsEntry) {
|
||||
// webkitGetAsEntry not standard, but is widely supported
|
||||
const entry = item.webkitGetAsEntry()
|
||||
if (entry) entries.push(entry)
|
||||
} else if (item.kind === 'file') {
|
||||
const file = item.getAsFile()
|
||||
if (file) files.push(file)
|
||||
}
|
||||
}
|
||||
} else if (event.dataTransfer?.files) {
|
||||
// Fallback for browsers without DataTransferItem API
|
||||
for (const file of Array.from(event.dataTransfer.files)) {
|
||||
files.push(file)
|
||||
}
|
||||
}
|
||||
|
||||
if (entries.length) {
|
||||
const promises = entries.map((entry) => this.traverseFileTree(entry))
|
||||
Promise.all(promises)
|
||||
.then((results) => {
|
||||
files.push(...[].concat(...results))
|
||||
this.toastService.showInfo($localize`Initiating upload...`, 3000)
|
||||
files.forEach((file) => this.uploadDocumentsService.uploadFile(file))
|
||||
})
|
||||
.catch((e) => {
|
||||
this.toastService.showError(
|
||||
$localize`Failed to read dropped items: ${e.message}`
|
||||
)
|
||||
})
|
||||
} else if (files.length) {
|
||||
this.toastService.showInfo($localize`Initiating upload...`, 3000)
|
||||
files.forEach((file) => this.uploadDocumentsService.uploadFile(file))
|
||||
}
|
||||
|
||||
this.onDragLeave(event, true)
|
||||
}
|
||||
|
||||
@HostListener('window:blur', ['$event']) public onWindowBlur() {
|
||||
|
@ -15,33 +15,6 @@ import {
|
||||
WebsocketStatusService,
|
||||
} from './websocket-status.service'
|
||||
|
||||
const files = [
|
||||
{
|
||||
lastModified: 1693349892540,
|
||||
lastModifiedDate: new Date(),
|
||||
name: 'file1.pdf',
|
||||
size: 386,
|
||||
type: 'application/pdf',
|
||||
},
|
||||
{
|
||||
lastModified: 1695618533892,
|
||||
lastModifiedDate: new Date(),
|
||||
name: 'file2.pdf',
|
||||
size: 358265,
|
||||
type: 'application/pdf',
|
||||
},
|
||||
]
|
||||
|
||||
const fileList = {
|
||||
item: (x) => {
|
||||
return new File(
|
||||
[new Blob(['testing'], { type: files[x].type })],
|
||||
files[x].name
|
||||
)
|
||||
},
|
||||
length: files.length,
|
||||
} as unknown as FileList
|
||||
|
||||
describe('UploadDocumentsService', () => {
|
||||
let httpTestingController: HttpTestingController
|
||||
let uploadDocumentsService: UploadDocumentsService
|
||||
@ -68,7 +41,11 @@ describe('UploadDocumentsService', () => {
|
||||
})
|
||||
|
||||
it('calls post_document api endpoint on upload', () => {
|
||||
uploadDocumentsService.uploadFiles(fileList)
|
||||
const file = new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
uploadDocumentsService.uploadFile(file)
|
||||
const req = httpTestingController.match(
|
||||
`${environment.apiBaseUrl}documents/post_document/`
|
||||
)
|
||||
@ -78,7 +55,16 @@ describe('UploadDocumentsService', () => {
|
||||
})
|
||||
|
||||
it('updates progress during upload and failure', () => {
|
||||
uploadDocumentsService.uploadFiles(fileList)
|
||||
const file = new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
const file2 = new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file2.pdf'
|
||||
)
|
||||
uploadDocumentsService.uploadFile(file)
|
||||
uploadDocumentsService.uploadFile(file2)
|
||||
|
||||
expect(websocketStatusService.getConsumerStatusNotCompleted()).toHaveLength(
|
||||
2
|
||||
@ -103,7 +89,11 @@ describe('UploadDocumentsService', () => {
|
||||
})
|
||||
|
||||
it('updates progress on failure', () => {
|
||||
uploadDocumentsService.uploadFiles(fileList)
|
||||
const file = new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
uploadDocumentsService.uploadFile(file)
|
||||
|
||||
let req = httpTestingController.match(
|
||||
`${environment.apiBaseUrl}documents/post_document/`
|
||||
@ -125,7 +115,7 @@ describe('UploadDocumentsService', () => {
|
||||
websocketStatusService.getConsumerStatus(FileStatusPhase.FAILED)
|
||||
).toHaveLength(1)
|
||||
|
||||
uploadDocumentsService.uploadFiles(fileList)
|
||||
uploadDocumentsService.uploadFile(file)
|
||||
|
||||
req = httpTestingController.match(
|
||||
`${environment.apiBaseUrl}documents/post_document/`
|
||||
@ -143,35 +133,4 @@ describe('UploadDocumentsService', () => {
|
||||
websocketStatusService.getConsumerStatus(FileStatusPhase.FAILED)
|
||||
).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('accepts files via drag and drop', () => {
|
||||
const uploadSpy = jest.spyOn(
|
||||
UploadDocumentsService.prototype as any,
|
||||
'uploadFile'
|
||||
)
|
||||
const fileEntry = {
|
||||
name: 'file.pdf',
|
||||
isDirectory: false,
|
||||
isFile: true,
|
||||
file: (callback) => {
|
||||
return callback(
|
||||
new File(
|
||||
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||
'file.pdf'
|
||||
)
|
||||
)
|
||||
},
|
||||
}
|
||||
uploadDocumentsService.onNgxFileDrop([
|
||||
{
|
||||
relativePath: 'path/to/file.pdf',
|
||||
fileEntry,
|
||||
},
|
||||
])
|
||||
expect(uploadSpy).toHaveBeenCalled()
|
||||
|
||||
let req = httpTestingController.match(
|
||||
`${environment.apiBaseUrl}documents/post_document/`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { HttpEventType } from '@angular/common/http'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { DocumentService } from './rest/document.service'
|
||||
import {
|
||||
@ -19,22 +18,7 @@ export class UploadDocumentsService {
|
||||
private websocketStatusService: WebsocketStatusService
|
||||
) {}
|
||||
|
||||
onNgxFileDrop(files: NgxFileDropEntry[]) {
|
||||
for (const droppedFile of files) {
|
||||
if (droppedFile.fileEntry.isFile) {
|
||||
const fileEntry = droppedFile.fileEntry as FileSystemFileEntry
|
||||
fileEntry.file((file: File) => this.uploadFile(file))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uploadFiles(files: FileList) {
|
||||
for (let index = 0; index < files.length; index++) {
|
||||
this.uploadFile(files.item(index))
|
||||
}
|
||||
}
|
||||
|
||||
private uploadFile(file: File) {
|
||||
public uploadFile(file: File) {
|
||||
let formData = new FormData()
|
||||
formData.append('document', file, file.name)
|
||||
formData.append('from_webui', 'true')
|
||||
|
@ -135,7 +135,6 @@ import {
|
||||
} from 'ngx-bootstrap-icons'
|
||||
import { ColorSliderModule } from 'ngx-color/slider'
|
||||
import { CookieService } from 'ngx-cookie-service'
|
||||
import { NgxFileDropModule } from 'ngx-file-drop'
|
||||
import { TourNgBootstrapModule } from 'ngx-ui-tour-ng-bootstrap'
|
||||
import { AppRoutingModule } from './app/app-routing.module'
|
||||
import { AppComponent } from './app/app.component'
|
||||
@ -353,7 +352,6 @@ bootstrapApplication(AppComponent, {
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
PdfViewerModule,
|
||||
NgxFileDropModule,
|
||||
NgSelectModule,
|
||||
ColorSliderModule,
|
||||
TourNgBootstrapModule,
|
||||
|
Loading…
x
Reference in New Issue
Block a user