mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-28 07:15:19 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c633c2015 | ||
|
|
dd8b51de67 | ||
|
|
5fe846de1d | ||
|
|
4711468598 | ||
|
|
19dfaf1b94 | ||
|
|
183ea24c9f | ||
|
|
99693b6d30 | ||
|
|
c0ad82b695 | ||
|
|
fd36323d1c | ||
|
|
4059c83a21 | ||
|
|
b25c015516 | ||
|
|
8fa52046e4 | ||
|
|
15554322dd | ||
|
|
0ee85aae21 | ||
|
|
839fb34c8e | ||
|
|
928580bf4f | ||
|
|
9cca7aaa08 | ||
|
|
38560cf13a | ||
|
|
474ca08ef9 | ||
|
|
d4fd529e49 | ||
|
|
2260617447 | ||
|
|
7c3ba3e518 | ||
|
|
849e3a10ac | ||
|
|
bdceeef3fb | ||
|
|
8630e5f5b6 | ||
|
|
2312eba5b6 | ||
|
|
ad9d654886 | ||
|
|
fa19a8975e | ||
|
|
8987cd448f | ||
|
|
a7536e3ebf | ||
|
|
9c3bc2eb83 | ||
|
|
d179efbd48 | ||
|
|
801df5f7bd | ||
|
|
d1c3ea7faa | ||
|
|
dcfc53b7f2 | ||
|
|
45002f8083 | ||
|
|
722a2ca1e4 | ||
|
|
2bd8b67d02 | ||
|
|
637efd5cb3 | ||
|
|
ad3dd76c2f | ||
|
|
75aba12589 | ||
|
|
ec33edb2f4 | ||
|
|
4b706fa4dd | ||
|
|
98799d9a69 | ||
|
|
b80070ac0b | ||
|
|
6b2e5559ca | ||
|
|
82340ad6e3 | ||
|
|
f45ab723ae | ||
|
|
8e3ca37b05 | ||
|
|
aef387ed69 | ||
|
|
b93c970635 | ||
|
|
a7d8b5c960 | ||
|
|
56c9a3f270 | ||
|
|
0c3dac45b5 | ||
|
|
6965165c76 | ||
|
|
73d33ff25a | ||
|
|
df153be30e |
No files matched your search
@@ -33,7 +33,7 @@ jobs:
|
||||
-
|
||||
name: Clean temporary images
|
||||
if: "${{ env.TOKEN != '' }}"
|
||||
uses: stumpylog/image-cleaner-action/ephemeral@v0.7.0
|
||||
uses: stumpylog/image-cleaner-action/ephemeral@v0.8.0
|
||||
with:
|
||||
token: "${{ env.TOKEN }}"
|
||||
owner: "${{ github.repository_owner }}"
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
-
|
||||
name: Clean untagged images
|
||||
if: "${{ env.TOKEN != '' }}"
|
||||
uses: stumpylog/image-cleaner-action/untagged@v0.7.0
|
||||
uses: stumpylog/image-cleaner-action/untagged@v0.8.0
|
||||
with:
|
||||
token: "${{ env.TOKEN }}"
|
||||
owner: "${{ github.repository_owner }}"
|
||||
|
||||
@@ -47,7 +47,7 @@ repos:
|
||||
exclude: "(^Pipfile\\.lock$)"
|
||||
# Python hooks
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.5.1'
|
||||
rev: 'v0.5.6'
|
||||
hooks:
|
||||
- id: ruff
|
||||
- id: ruff-format
|
||||
|
||||
@@ -7,7 +7,7 @@ name = "pypi"
|
||||
dateparser = "~=1.2"
|
||||
# WARNING: django does not use semver.
|
||||
# Only patch versions are guaranteed to not introduce breaking changes.
|
||||
django = "~=4.2.14"
|
||||
django = "~=4.2.15"
|
||||
django-allauth = {extras = ["socialaccount"], version = "*"}
|
||||
django-auditlog = "*"
|
||||
django-celery-results = "*"
|
||||
|
||||
Generated
+229
-229
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "dfbdec79ef49972dfb5600bfd01ba2feb4459654a4039635475b7b93a8ad270b"
|
||||
"sha256": "72d88ed3125f33fab90b63af37465adae851541c979242c429bef8a30142356e"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
@@ -454,22 +454,23 @@
|
||||
},
|
||||
"django": {
|
||||
"hashes": [
|
||||
"sha256:3ec32bc2c616ab02834b9cac93143a7dc1cdcd5b822d78ac95fc20a38c534240",
|
||||
"sha256:fc6919875a6226c7ffcae1a7d51e0f2ceaf6f160393180818f6c95f51b1e7b96"
|
||||
"sha256:61ee4a130efb8c451ef3467c67ca99fdce400fedd768634efc86a68c18d80d30",
|
||||
"sha256:c77f926b81129493961e19c0e02188f8d07c112a1162df69bfab178ae447f94a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.2.14"
|
||||
"version": "==4.2.15"
|
||||
},
|
||||
"django-allauth": {
|
||||
"extras": [
|
||||
"socialaccount"
|
||||
],
|
||||
"hashes": [
|
||||
"sha256:2374164c468a309e6badf70bc3405136df6036f24a20a13387f2a063066bdaa9"
|
||||
"sha256:f15f49defb09e0604dad5214e53a69a1f723cb03176bb115c8930bcd19b91749"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==0.63.3"
|
||||
"version": "==0.63.6"
|
||||
},
|
||||
"django-auditlog": {
|
||||
"hashes": [
|
||||
@@ -841,11 +842,11 @@
|
||||
},
|
||||
"imap-tools": {
|
||||
"hashes": [
|
||||
"sha256:1fc97a06a35e18a6d0e775d40b18198f52dae0fa46ee8b6fc6f82dbc7a701699",
|
||||
"sha256:6f6a354a6bb95ab83a24d3321d1a8b62b299ba76ba5774e9f45f0ad2544f093b"
|
||||
"sha256:218ea6495d73275ecc2fa4a34717c137bacf2c4a3d34c9d10a9581a6af1ac94f",
|
||||
"sha256:4c31e9df1d28149436a86871cf84a0b37221a91521fc1a57897e0a152ee3f6d1"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.6.0"
|
||||
"version": "==1.7.2"
|
||||
},
|
||||
"img2pdf": {
|
||||
"hashes": [
|
||||
@@ -1572,114 +1573,115 @@
|
||||
},
|
||||
"rapidfuzz": {
|
||||
"hashes": [
|
||||
"sha256:005a02688a51c7d2451a2d41c79d737aa326ff54167211b78a383fc2aace2c2c",
|
||||
"sha256:015b5080b999404fe06ec2cb4f40b0be62f0710c926ab41e82dfbc28e80675b4",
|
||||
"sha256:01b42a8728c36011718da409aa86b84984396bf0ca3bfb6e62624f2014f6022c",
|
||||
"sha256:04dbdfb0f0bfd3f99cf1e9e24fadc6ded2736d7933f32f1151b0f2abb38f9a25",
|
||||
"sha256:07141aa6099e39d48637ce72a25b893fc1e433c50b3e837c75d8edf99e0c63e1",
|
||||
"sha256:0772150d37bf018110351c01d032bf9ab25127b966a29830faa8ad69b7e2f651",
|
||||
"sha256:098d231d4e51644d421a641f4a5f2f151f856f53c252b03516e01389b2bfef99",
|
||||
"sha256:0c8fc973adde8ed52810f590410e03fb6f0b541bbaeb04c38d77e63442b2df4c",
|
||||
"sha256:10e61bb7bc807968cef09a0e32ce253711a2d450a4dce7841d21d45330ffdb24",
|
||||
"sha256:129627d730db2e11f76169344a032f4e3883d34f20829419916df31d6d1338b1",
|
||||
"sha256:1424e238bc3f20e1759db1e0afb48a988a9ece183724bef91ea2a291c0b92a95",
|
||||
"sha256:15bc397ee9a3ed1210b629b9f5f1da809244adc51ce620c504138c6e7095b7bd",
|
||||
"sha256:167e745f98baa0f3034c13583e6302fb69249a01239f1483d68c27abb841e0a1",
|
||||
"sha256:17ab8b7d10fde8dd763ad428aa961c0f30a1b44426e675186af8903b5d134fb0",
|
||||
"sha256:1869c42e73e2a8910b479be204fa736418741b63ea2325f9cc583c30f2ded41a",
|
||||
"sha256:1950f8597890c0c707cb7e0416c62a1cf03dcdb0384bc0b2dbda7e05efe738ec",
|
||||
"sha256:1bc1a0f29f9119be7a8d3c720f1d2068317ae532e39e4f7f948607c3a6de8396",
|
||||
"sha256:1df0f9e9239132a231c86ae4f545ec2b55409fa44470692fcfb36b1bd00157ad",
|
||||
"sha256:20488ade4e1ddba3cfad04f400da7a9c1b91eff5b7bd3d1c50b385d78b587f4f",
|
||||
"sha256:26aa7eece23e0df55fb75fbc2a8fb678322e07c77d1fd0e9540496e6e2b5f03e",
|
||||
"sha256:2797fb847d89e04040d281cb1902cbeffbc4b5131a5c53fc0db490fd76b2a547",
|
||||
"sha256:2c99d355f37f2b289e978e761f2f8efeedc2b14f4751d9ff7ee344a9a5ca98d9",
|
||||
"sha256:31a2fc60bb2c7face4140010a7aeeafed18b4f9cdfa495cc644a68a8c60d1ff7",
|
||||
"sha256:355fc4a268ffa07bab88d9adee173783ec8d20136059e028d2a9135c623c44e6",
|
||||
"sha256:366bf8947b84e37f2f4cf31aaf5f37c39f620d8c0eddb8b633e6ba0129ca4a0a",
|
||||
"sha256:3a2e75e41ee3274754d3b2163cc6c82cd95b892a85ab031f57112e09da36455f",
|
||||
"sha256:3a555e3c841d6efa350f862204bb0a3fea0c006b8acc9b152b374fa36518a1c6",
|
||||
"sha256:3a944e546a296a5fdcaabb537b01459f1b14d66f74e584cb2a91448bffadc3c1",
|
||||
"sha256:3c522f462d9fc504f2ea8d82e44aa580e60566acc754422c829ad75c752fbf8d",
|
||||
"sha256:3fe4545f89f8d6c27b6bbbabfe40839624873c08bd6700f63ac36970a179f8f5",
|
||||
"sha256:3fe86b82b776554add8f900b6af202b74eb5efe8f25acdb8680a5c977608727f",
|
||||
"sha256:40419e98b10cd6a00ce26e4837a67362f658fc3cd7a71bd8bd25c99f7ee8fea5",
|
||||
"sha256:4968c8bd1df84b42f382549e6226710ad3476f976389839168db3e68fd373298",
|
||||
"sha256:4a6c35f272ec9c430568dc8c1c30cb873f6bc96be2c79795e0bce6db4e0e101d",
|
||||
"sha256:4c72078b5fdce34ba5753f9299ae304e282420e6455e043ad08e4488ca13a2b0",
|
||||
"sha256:4d38b4e026fcd580e0bda6c0ae941e0e9a52c6bc66cdce0b8b0da61e1959f5f8",
|
||||
"sha256:4d81a78f90269190b568a8353d4ea86015289c36d7e525cd4d43176c88eff429",
|
||||
"sha256:4fb96ba96d58c668a17a06b5b5e8340fedc26188e87b0d229d38104556f30cd8",
|
||||
"sha256:52e3d89377744dae68ed7c84ad0ddd3f5e891c82d48d26423b9e066fc835cc7c",
|
||||
"sha256:6022674aa1747d6300f699cd7c54d7dae89bfe1f84556de699c4ac5df0838082",
|
||||
"sha256:60ff67c690acecf381759c16cb06c878328fe2361ddf77b25d0e434ea48a29da",
|
||||
"sha256:62ea7007941fb2795fff305ac858f3521ec694c829d5126e8f52a3e92ae75526",
|
||||
"sha256:698e992436bf7f0afc750690c301215a36ff952a6dcd62882ec13b9a1ebf7a39",
|
||||
"sha256:7fa714fb96ce9e70c37e64c83b62fe8307030081a0bfae74a76fac7ba0f91715",
|
||||
"sha256:84fc1ee19fdad05770c897e793836c002344524301501d71ef2e832847425707",
|
||||
"sha256:8d9d58689aca22057cf1a5851677b8a3ccc9b535ca008c7ed06dc6e1899f7844",
|
||||
"sha256:8f37e9e1f17be193c41a31c864ad4cd3ebd2b40780db11cd5c04abf2bcf4201b",
|
||||
"sha256:90a82143c14e9a14b723a118c9ef8d1bbc0c5a16b1ac622a1e6c916caff44dd8",
|
||||
"sha256:9e618625ffc4660b26dc8e56225f8b966d5842fa190e70c60db6cd393e25b86e",
|
||||
"sha256:9f256c8fb8f3125574c8c0c919ab0a1f75d7cba4d053dda2e762dcc36357969d",
|
||||
"sha256:acc5ceca9c1e1663f3e6c23fb89a311f69b7615a40ddd7645e3435bf3082688a",
|
||||
"sha256:ad04ae301129f0eb5b350a333accd375ce155a0c1cec85ab0ec01f770214e2e4",
|
||||
"sha256:ad61676e9bdae677d577fe80ec1c2cea1d150c86be647e652551dcfe505b1113",
|
||||
"sha256:addcdd3c3deef1bd54075bd7aba0a6ea9f1d01764a08620074b7a7b1e5447cb9",
|
||||
"sha256:aee5f6b8321f90615c184bd8a4c676e9becda69b8e4e451a90923db719d6857c",
|
||||
"sha256:aee9fc9e3bb488d040afc590c0a7904597bf4ccd50d1491c3f4a5e7e67e6cd2c",
|
||||
"sha256:af65020c0dd48d0d8ae405e7e69b9d8ae306eb9b6249ca8bf511a13f465fad85",
|
||||
"sha256:b0fc91ac59f4414d8542454dfd6287a154b8e6f1256718c898f695bdbb993467",
|
||||
"sha256:b5d5072b548db1b313a07d62d88fe0b037bd2783c16607c647e01b070f6cf9e5",
|
||||
"sha256:b712336ad6f2bacdbc9f1452556e8942269ef71f60a9e6883ef1726b52d9228a",
|
||||
"sha256:b76f611935f15a209d3730c360c56b6df8911a9e81e6a38022efbfb96e433bab",
|
||||
"sha256:bc01a223f6605737bec3202e94dcb1a449b6c76d46082cfc4aa980f2a60fd40e",
|
||||
"sha256:c76da20481c906e08400ee9be230f9e611d5931a33707d9df40337c2655c84b5",
|
||||
"sha256:c9b9793c19bdf38656c8eaefbcf4549d798572dadd70581379e666035c9df781",
|
||||
"sha256:cb934363380c60f3a57d14af94325125cd8cded9822611a9f78220444034e36e",
|
||||
"sha256:cd6ac61b74fdb9e23f04d5f068e6cf554f47e77228ca28aa2347a6ca8903972f",
|
||||
"sha256:cf5bcf22e1f0fd273354462631d443ef78d677f7d2fc292de2aec72ae1473e66",
|
||||
"sha256:d070ec5cf96b927c4dc5133c598c7ff6db3b833b363b2919b13417f1002560bc",
|
||||
"sha256:d2c51955329bfccf99ae26f63d5928bf5be9fcfcd9f458f6847fd4b7e2b8986c",
|
||||
"sha256:d395d46b80063d3b5d13c0af43d2c2cedf3ab48c6a0c2aeec715aa5455b0c632",
|
||||
"sha256:d6481e099ff8c4edda85b8b9b5174c200540fd23c8f38120016c765a86fa01f5",
|
||||
"sha256:d8a52fc50ded60d81117d7647f262c529659fb21d23e14ebfd0b35efa4f1b83d",
|
||||
"sha256:d8e9130fe5d7c9182990b366ad78fd632f744097e753e08ace573877d67c32f8",
|
||||
"sha256:db0bf0663b4b6da1507869722420ea9356b6195aa907228d6201303e69837af9",
|
||||
"sha256:db1664eaff5d7d0f2542dd9c25d272478deaf2c8412e4ad93770e2e2d828e175",
|
||||
"sha256:dcb72e5f9762fd469701a7e12e94b924af9004954f8c739f925cb19c00862e38",
|
||||
"sha256:ded58612fe3b0e0d06e935eaeaf5a9fd27da8ba9ed3e2596307f40351923bf72",
|
||||
"sha256:e272df61bee0a056a3daf99f9b1bd82cf73ace7d668894788139c868fdf37d6f",
|
||||
"sha256:e590d5d5443cf56f83a51d3c4867bd1f6be8ef8cfcc44279522bcef3845b2a51",
|
||||
"sha256:e61b03509b1a6eb31bc5582694f6df837d340535da7eba7bedb8ae42a2fcd0b9",
|
||||
"sha256:e81e27e8c32a1e1278a4bb1ce31401bfaa8c2cc697a053b985a6f8d013df83ec",
|
||||
"sha256:eb26d412271e5a76cdee1c2d6bf9881310665d3fe43b882d0ed24edfcb891a84",
|
||||
"sha256:ed01378f605aa1f449bee82cd9c83772883120d6483e90aa6c5a4ce95dc5c3aa",
|
||||
"sha256:f16f5d1c4f02fab18366f2d703391fcdbd87c944ea10736ca1dc3d70d8bd2d8b",
|
||||
"sha256:f187a9c3b940ce1ee324710626daf72c05599946bd6748abe9e289f1daa9a077",
|
||||
"sha256:f2464bb120f135293e9a712e342c43695d3d83168907df05f8c4ead1612310c7",
|
||||
"sha256:f2d2846f3980445864c7e8b8818a29707fcaff2f0261159ef6b7bd27ba139296",
|
||||
"sha256:f46a22506f17c0433e349f2d1dc11907c393d9b3601b91d4e334fa9a439a6a4d",
|
||||
"sha256:f5fdc09cf6e9d8eac3ce48a4615b3a3ee332ea84ac9657dbbefef913b13e632f",
|
||||
"sha256:f74ed072c2b9dc6743fb19994319d443a4330b0e64aeba0aa9105406c7c5b9c2",
|
||||
"sha256:f75639277304e9b75e6a7b3c07042d2264e16740a11e449645689ed28e9c2124",
|
||||
"sha256:fbebf1791a71a2e89f5c12b78abddc018354d5859e305ec3372fdae14f80a826",
|
||||
"sha256:fe833493fb5cc5682c823ea3e2f7066b07612ee8f61ecdf03e1268f262106cdd"
|
||||
"sha256:031806eb035a6f09f4ff23b9d971d50b30b5e93aa3ee620c920bee1dc32827e7",
|
||||
"sha256:0d34b0e8e29f80cb2ac8afe8fb7b01a542b136ffbf7e2b9983d11bce49398f68",
|
||||
"sha256:0d9fdb74df87018dd4146f3d00df9fca2c27f060936a9e8d3015e7bfb9cb69e4",
|
||||
"sha256:0e09abc0d397019bba61c8e6dfe2ec863d4dfb1762f51c9197ce0af5d5fd9adb",
|
||||
"sha256:13eeaeb0d5fe00fa99336f73fb5ab65c46109c7121cf87659b9601908b8b6178",
|
||||
"sha256:14587df847d0d50bd10cde0a198b5d64eedb7484c72b825f5c2ead6e6ff16eee",
|
||||
"sha256:16c982dd3cdd33cf4aac91027a263a081d1a8050dc33a27470367a391a8d1576",
|
||||
"sha256:181073256faec68e6b8ab3329a36cfa1360f7906aa70d9aee4a39cb70889f73f",
|
||||
"sha256:191d1057cca56641f7b919fe712cb7e48cd226342e097a78136127f8bde32caa",
|
||||
"sha256:1d9bcfec5efd55b6268328cccd12956d833582d8da6385231a5c6c6201a1156a",
|
||||
"sha256:24345826b50aafcea26e2e4be5c103d96fe9d7fc549ac9190641300290958f3b",
|
||||
"sha256:252dc3d1c3d613b8db1b59d13381937e420c99f8a351ffa0e78c2f54746e107f",
|
||||
"sha256:257f2406a671371bafd99a2a2c57f991783446bc2176b93a83d1d833e35d36df",
|
||||
"sha256:2b17ecc17322b659962234799e90054e420911b8ca510a7869c2f4419f9f3ecb",
|
||||
"sha256:345011cfcafaa3674c46673baad67d2394eb58285530d8333e65c3c9a143b4f4",
|
||||
"sha256:35088e759b083398ab3c4154517476e116653b7403604677af9a894179f1042f",
|
||||
"sha256:3e33e1d185206730b916b3e7d9bce1941c65b2a1488cdd0457ae21be385a7912",
|
||||
"sha256:3ed0c17e5b6fdd2ac3230bdefa908579971377c36aa4a2f132700fa8145040db",
|
||||
"sha256:42c4d1ba2647c8d2a82313c4dde332de750c936b94f016308339e762c2e5e53d",
|
||||
"sha256:491d3d425b5fe3f61f3b9a70abfd498ce9139d94956db7a8551e537e017c0e57",
|
||||
"sha256:506547889f18db0acca787ffb9f287757cbfe9f0fadddd4e07c64ce0bd924e13",
|
||||
"sha256:518dec750a30f115ba1299ef2547cf468a69f310581a030c8a875257de747c5f",
|
||||
"sha256:529e2cf441746bd492f6c36a38bf9fa6a418df95b9c003f8e92a55d8a979bd9c",
|
||||
"sha256:53fb2f32f14c921d2f673c5b7cd58d4cc626c574a28c0791f283880d8e57022c",
|
||||
"sha256:599714790dfac0a23a473134e6677d0a103690a4e21ba189cfc826e322cdc8d5",
|
||||
"sha256:5dc19c8222475e4f7f528b94d2fa28e7979355c5cf7c6e73902d2abb2be96522",
|
||||
"sha256:5feb75e905281e5c669e21c98d594acc3b222a8694d9342f17df988766d83748",
|
||||
"sha256:62b8f9f58e9dffaa86fef84db2705457a58e191a962124f2b815026ba79d9aba",
|
||||
"sha256:63e34fb3586431589a5e1cd7fc61c6f057576c6c6804c1c673bac3de0516dee7",
|
||||
"sha256:6c741972d64031535cfd76d89cf47259e590e822353be57ec2f5d56758c98296",
|
||||
"sha256:6d8cc7e6e5c6fbcacdfe3cf7a86b60dcaf216216d86e6879ff52d488e5b11e27",
|
||||
"sha256:7252666b85c931d51a59d5308bb6827a67434917ef510747d3ce7e88ec17e7f2",
|
||||
"sha256:72e466e5de12a327a09ed6d0116f024759b5146b335645c32241da84134a7f34",
|
||||
"sha256:73362eb1c3d02f32e4c7f0d77eb284e9a13f278cff224f71e8f60e2aff5b6a5d",
|
||||
"sha256:733bf3d7876bf6d8167e6436f99d6ea16a218ec2c8eb9da6048f20b9cc8733e2",
|
||||
"sha256:7508ef727ef4891141dd3ac7a39a2327384ece070521ac9c58f06c27d57c72d5",
|
||||
"sha256:758719e9613c47a274768f1926460955223fe0a03e7eda264f2b78b1b97a4743",
|
||||
"sha256:7659058863d84a2c36c5a76c28bc8713d33eab03e677e67260d9e1cca43fc3bb",
|
||||
"sha256:7981cc6240d01d4480795d758ea2ee748257771f68127d630045e58fe1b5545a",
|
||||
"sha256:7d5a34b8388ae99bdbd5a3646f45ac318f4c870105bdbe42a2f4c85e5b347761",
|
||||
"sha256:7e2c0c8bbe4f4525009e3ad9b94a39cdff5d6378233e754d0b13c29cdfaa75fc",
|
||||
"sha256:802a018776bd3cb7c5d23ba38ebbb1663a9f742be1d58e73b62d8c7cace6e607",
|
||||
"sha256:80a4c8a2c5ae4b133fec6b5db1af9a4126ffa6eca18a558fe5b6ab8e330d3d78",
|
||||
"sha256:8171fc6e4645e636161a9ef5b44b20605adbefe23cd990b68d72cae0b9c12509",
|
||||
"sha256:8419c18bbbd67058ca1312f35acda2e4e4592650f105cfd166569a2ebccd01f1",
|
||||
"sha256:876e663b11d9067e1096ea76a2de87227c7b513aff2b60667b20417da74183e4",
|
||||
"sha256:8e943c5cbd10e15369be1f371ef303cb413c1008f64d93bd13762ea06ca84d59",
|
||||
"sha256:926701c8e61319ee2e4888619143f58ddcc0e3e886668269b8e053f2d68c1e92",
|
||||
"sha256:9729852038fb2de096e249899f8a9bee90fb1f92e10b6ccc539d5bb798c703bc",
|
||||
"sha256:976ed1105a76935b6a4d2bbc7d577be1b97b43997bcec2f29a0ab48ff6f5d6b1",
|
||||
"sha256:9811a741aa1350ad36689d675ded8b34e423e68b396bd30bff751a9c582f586e",
|
||||
"sha256:99eaa8dd8a44664813e0bef014775993ef75a134a863bc54cd855a60622203fd",
|
||||
"sha256:9a0c878d0980508e90e973a9cbfb591acc370085f2301c6aacadbd8362d52a36",
|
||||
"sha256:9cf2028edb9ccd21d1d5aaacef2fe3e14bee4343df1c2c0f7373ef6e81013bef",
|
||||
"sha256:9dc39435476fb3b3b3c24ab2c08c726056b2b487aa7ee450aee698b808c808ac",
|
||||
"sha256:9e36c4640a789b8c922b69a548968939d1c0433fa7aac83cb08e1334d4e5d7de",
|
||||
"sha256:a42d1f7b8988f50013e703ed27b5e216ef8a725b2f4ac53754ad0476020b26f4",
|
||||
"sha256:a6f1df5b0e602e94199cccb5e241bbc2319644003e34f077741ebf48aea7ed1a",
|
||||
"sha256:a7452d079800cf70a7314f73044f03cbcbd90a651d9dec39443d2a8a2b63ab53",
|
||||
"sha256:abb1ac683671000bd4ec215a494aba687d75a198db72188408154a19ea313ff4",
|
||||
"sha256:ac460d89b9759e37eef23fed05184179654882a241f6b2363df194f8940cc55f",
|
||||
"sha256:adee55488490375c1604b878fbc1eb1a51fe5e6f5bd05047df2f8c6505a48728",
|
||||
"sha256:b0189f691cea4dc9fe074ea6b97da30a91d0882fa69724b4b34b51d2c1983473",
|
||||
"sha256:b6cdca86120c3f9aa069f8d4e1c5422e92f833d705d719a2ba7082412f4c933b",
|
||||
"sha256:bf9ed6988da6a2c1f8df367cb5d6be26a3d8543646c8eba79741ac9e764fbc59",
|
||||
"sha256:bfb47513a17c935f6ee606dcae0ea9d20a3fb0fe9ca597758472ea08be62dc54",
|
||||
"sha256:bfd3b66ee1f0ebb40c672a7a7e5bda00fb763fa9bca082058084175151f8e685",
|
||||
"sha256:cadd66e6ef9901909dc1b11db91048f1bf4613ba7d773386f922e28b1e1df4da",
|
||||
"sha256:cf9aceb4227fd09f9a20e505f78487b2089d6420ce232d288522ea0a78b986b9",
|
||||
"sha256:d047b01637a31d9bf776b66438f574fd1db856ad14cf296c1f48bb6bef8a5aff",
|
||||
"sha256:d26f7299e2872d18fb7df1bc043e53aa94fc5a4a2a6a9537ad8707579fcb1668",
|
||||
"sha256:d4f2e985172bb76c9179e11fb67d9c9ecbee4933740eca2977797094df02498d",
|
||||
"sha256:d6ceea632b0eb97dac54411c29feb190054e91fd0571f585b56e4a9159c55ab0",
|
||||
"sha256:d7b1922b1403ccb3583218e8cd931b08e04c5442ca03dbaf6ea4fcf574ee2b24",
|
||||
"sha256:d9e0a656274ac75ec24499a06c0bc5eee67bcd8276c6061da7c05d549f1b1a61",
|
||||
"sha256:da71e8fdb0d1a21f4b58b2c84bcbc2b89a472c073c5f7bdb9339f4cb3122c0e3",
|
||||
"sha256:e1b024d9d69bb83e125adee4162991f2764f16acc3fb1ed0f0fc1ad5aeb7e394",
|
||||
"sha256:e3c4be3057472c79ba6f4eab35daa9f12908cb697c472d05fbbd47949a87aec6",
|
||||
"sha256:e46cd486289d1d8e3dab779c725f5dde77b286185d32e7b874bfc3d161e3a927",
|
||||
"sha256:e8032492021b0aa55a623d6f6e739a5d4aaabc32af379c2a5656bf1e9e178bf1",
|
||||
"sha256:ebd17688b75b6fa983e8586cad30f36eb9736b860946cc8b633b9442c9481831",
|
||||
"sha256:ebf682bdb0f01b6b1f9a9ffe918aa3ac84fbdadb998ffbfcd5f9b12bd280170f",
|
||||
"sha256:f06f163a0341bad162e972590b73e17f9cea2ed8ee27b193875ccbc3dd6eca2f",
|
||||
"sha256:f080d6709f51a8335e73826b96af9b4e3657631eca6c69e1ac501868dcc84b7f",
|
||||
"sha256:f3e037b9ec621dec0157d81566e7d47a91405e379335cf8f4ed3c20d61db91d8",
|
||||
"sha256:f4e0122603af2119579e9f94e172c6e460860fdcdb713164332c1951c13df999",
|
||||
"sha256:f6dbe1df0b9334e3cf07445d810c81734ae23d137b5efc69e1d676ff55691351",
|
||||
"sha256:f9433cb12731167b358fbcff9828d2294429986a03222031f6d14308eb643c77",
|
||||
"sha256:f9f33d05db5bba1d076446c51347a6d93ff24d8f9d01b0b8b15ca8ec8b1ef382",
|
||||
"sha256:fb28f2b7173ed3678b4630b0c8b21503087d1cd082bae200dc2519ca38b26686",
|
||||
"sha256:fd94d952299ec73ea63a0fa4b699a2750785b6bb82aa56fd886d9023b86f90ab",
|
||||
"sha256:fe5a11eefd0ae90d32d9ff706a894498b4efb4b0c263ad9d1e6401050863504d",
|
||||
"sha256:ffa533acb1a9dcb6e26c4467fdc1347995fb168ec9f794b97545f6b72dee733c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==3.9.4"
|
||||
"version": "==3.9.5"
|
||||
},
|
||||
"redis": {
|
||||
"extras": [
|
||||
"hiredis"
|
||||
],
|
||||
"hashes": [
|
||||
"sha256:0e479e24da960c690be5d9b96d21f7b918a98c0cf49af3b6fafaa0753f93a0db",
|
||||
"sha256:8f611490b93c8109b50adc317b31bfd84fff31def3475b92e7e80bf39f48175b"
|
||||
"sha256:0c5b10d387568dfe0698c6fad6615750c24170e548ca2deac10c649d463e9870",
|
||||
"sha256:56134ee08ea909106090934adc36f65c9bcbbaecea5b21ba704ba6fb561f8eb4"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==5.0.7"
|
||||
"version": "==5.0.8"
|
||||
},
|
||||
"regex": {
|
||||
"hashes": [
|
||||
@@ -1969,11 +1971,11 @@
|
||||
},
|
||||
"sqlparse": {
|
||||
"hashes": [
|
||||
"sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93",
|
||||
"sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663"
|
||||
"sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4",
|
||||
"sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.5.0"
|
||||
"version": "==0.5.1"
|
||||
},
|
||||
"threadpoolctl": {
|
||||
"hashes": [
|
||||
@@ -1985,12 +1987,12 @@
|
||||
},
|
||||
"tika-client": {
|
||||
"hashes": [
|
||||
"sha256:b4271a82f1416a1a62ed9100640b3bc16b1014c244ee787b4be5becd0fdcd304",
|
||||
"sha256:f719fbf20f9ef47d12132b38c5848024b260e79c5f0b9ae5ff95c0b2fe3ba350"
|
||||
"sha256:647f528860aa639d87516ecff0fb25797b4edaa973fe60b320c56c5bd7cb6a88",
|
||||
"sha256:7fcd12d991fa155b2f94fcadb25ecee472c437e757b6737930f924a81feca60b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.5.0"
|
||||
"version": "==0.6.0"
|
||||
},
|
||||
"tornado": {
|
||||
"hashes": [
|
||||
@@ -2011,12 +2013,12 @@
|
||||
},
|
||||
"tqdm": {
|
||||
"hashes": [
|
||||
"sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644",
|
||||
"sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"
|
||||
"sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd",
|
||||
"sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==4.66.4"
|
||||
"version": "==4.66.5"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
@@ -2888,7 +2890,6 @@
|
||||
"sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb",
|
||||
"sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==3.15.4"
|
||||
},
|
||||
@@ -3096,12 +3097,12 @@
|
||||
},
|
||||
"mkdocs-material": {
|
||||
"hashes": [
|
||||
"sha256:9cba305283ad1600e3d0a67abe72d7a058b54793b47be39930911a588fe0336b",
|
||||
"sha256:ff48b11b2a9f705dd210409ec3b418ab443dd36d96915bcba45a41f10ea27bfd"
|
||||
"sha256:1b1f49066fdb3824c1e96d6bacd2d4375de4ac74580b47e79ff44c4d835c5fcb",
|
||||
"sha256:31833ec664772669f5856f4f276bf3fdf0e642a445e64491eda459249c3a1ca8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==9.5.28"
|
||||
"version": "==9.5.31"
|
||||
},
|
||||
"mkdocs-material-extensions": {
|
||||
"hashes": [
|
||||
@@ -3296,12 +3297,12 @@
|
||||
},
|
||||
"pre-commit": {
|
||||
"hashes": [
|
||||
"sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a",
|
||||
"sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5"
|
||||
"sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af",
|
||||
"sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==3.7.1"
|
||||
"version": "==3.8.0"
|
||||
},
|
||||
"pyasn1": {
|
||||
"hashes": [
|
||||
@@ -3337,11 +3338,11 @@
|
||||
},
|
||||
"pymdown-extensions": {
|
||||
"hashes": [
|
||||
"sha256:3ab1db5c9e21728dabf75192d71471f8e50f216627e9a1fa9535ecb0231b9940",
|
||||
"sha256:f938326115884f48c6059c67377c46cf631c733ef3629b6eed1349989d1b30cb"
|
||||
"sha256:6ff740bcd99ec4172a938970d42b96128bdc9d4b9bcad72494f29921dc69b753",
|
||||
"sha256:d323f7e90d83c86113ee78f3fe62fc9dee5f56b54d912660703ea1816fed5626"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==10.8.1"
|
||||
"version": "==10.9"
|
||||
},
|
||||
"pyopenssl": {
|
||||
"hashes": [
|
||||
@@ -3352,12 +3353,12 @@
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343",
|
||||
"sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"
|
||||
"sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5",
|
||||
"sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==8.2.2"
|
||||
"version": "==8.3.2"
|
||||
},
|
||||
"pytest-cov": {
|
||||
"hashes": [
|
||||
@@ -3435,7 +3436,6 @@
|
||||
"sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
|
||||
"sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.9.0.post0"
|
||||
},
|
||||
@@ -3532,6 +3532,7 @@
|
||||
"sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d",
|
||||
"sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==6.0.1"
|
||||
},
|
||||
"pyyaml-env-tag": {
|
||||
@@ -3544,88 +3545,88 @@
|
||||
},
|
||||
"regex": {
|
||||
"hashes": [
|
||||
"sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649",
|
||||
"sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35",
|
||||
"sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb",
|
||||
"sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68",
|
||||
"sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5",
|
||||
"sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133",
|
||||
"sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0",
|
||||
"sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d",
|
||||
"sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da",
|
||||
"sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f",
|
||||
"sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d",
|
||||
"sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53",
|
||||
"sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa",
|
||||
"sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a",
|
||||
"sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890",
|
||||
"sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67",
|
||||
"sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c",
|
||||
"sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2",
|
||||
"sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced",
|
||||
"sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741",
|
||||
"sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f",
|
||||
"sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa",
|
||||
"sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf",
|
||||
"sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4",
|
||||
"sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5",
|
||||
"sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2",
|
||||
"sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384",
|
||||
"sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7",
|
||||
"sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014",
|
||||
"sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704",
|
||||
"sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5",
|
||||
"sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2",
|
||||
"sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49",
|
||||
"sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1",
|
||||
"sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694",
|
||||
"sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629",
|
||||
"sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6",
|
||||
"sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435",
|
||||
"sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c",
|
||||
"sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835",
|
||||
"sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e",
|
||||
"sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201",
|
||||
"sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62",
|
||||
"sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5",
|
||||
"sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16",
|
||||
"sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f",
|
||||
"sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1",
|
||||
"sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f",
|
||||
"sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f",
|
||||
"sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145",
|
||||
"sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3",
|
||||
"sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed",
|
||||
"sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143",
|
||||
"sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca",
|
||||
"sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9",
|
||||
"sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa",
|
||||
"sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850",
|
||||
"sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80",
|
||||
"sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe",
|
||||
"sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656",
|
||||
"sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388",
|
||||
"sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1",
|
||||
"sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294",
|
||||
"sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3",
|
||||
"sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d",
|
||||
"sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b",
|
||||
"sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40",
|
||||
"sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600",
|
||||
"sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c",
|
||||
"sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569",
|
||||
"sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456",
|
||||
"sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9",
|
||||
"sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb",
|
||||
"sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e",
|
||||
"sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f",
|
||||
"sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d",
|
||||
"sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a",
|
||||
"sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a",
|
||||
"sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"
|
||||
"sha256:01b689e887f612610c869421241e075c02f2e3d1ae93a037cb14f88ab6a8934c",
|
||||
"sha256:04ce29e2c5fedf296b1a1b0acc1724ba93a36fb14031f3abfb7abda2806c1535",
|
||||
"sha256:0ffe3f9d430cd37d8fa5632ff6fb36d5b24818c5c986893063b4e5bdb84cdf24",
|
||||
"sha256:18300a1d78cf1290fa583cd8b7cde26ecb73e9f5916690cf9d42de569c89b1ce",
|
||||
"sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc",
|
||||
"sha256:19c65b00d42804e3fbea9708f0937d157e53429a39b7c61253ff15670ff62cb5",
|
||||
"sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce",
|
||||
"sha256:23acc72f0f4e1a9e6e9843d6328177ae3074b4182167e34119ec7233dfeccf53",
|
||||
"sha256:25419b70ba00a16abc90ee5fce061228206173231f004437730b67ac77323f0d",
|
||||
"sha256:2dfbb8baf8ba2c2b9aa2807f44ed272f0913eeeba002478c4577b8d29cde215c",
|
||||
"sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908",
|
||||
"sha256:33e2614a7ce627f0cdf2ad104797d1f68342d967de3695678c0cb84f530709f8",
|
||||
"sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024",
|
||||
"sha256:382281306e3adaaa7b8b9ebbb3ffb43358a7bbf585fa93821300a418bb975281",
|
||||
"sha256:3d974d24edb231446f708c455fd08f94c41c1ff4f04bcf06e5f36df5ef50b95a",
|
||||
"sha256:3f3b6ca8eae6d6c75a6cff525c8530c60e909a71a15e1b731723233331de4169",
|
||||
"sha256:3fac296f99283ac232d8125be932c5cd7644084a30748fda013028c815ba3364",
|
||||
"sha256:416c0e4f56308f34cdb18c3f59849479dde5b19febdcd6e6fa4d04b6c31c9faa",
|
||||
"sha256:438d9f0f4bc64e8dea78274caa5af971ceff0f8771e1a2333620969936ba10be",
|
||||
"sha256:43affe33137fcd679bdae93fb25924979517e011f9dea99163f80b82eadc7e53",
|
||||
"sha256:44fc61b99035fd9b3b9453f1713234e5a7c92a04f3577252b45feefe1b327759",
|
||||
"sha256:45104baae8b9f67569f0f1dca5e1f1ed77a54ae1cd8b0b07aba89272710db61e",
|
||||
"sha256:4fdd1384619f406ad9037fe6b6eaa3de2749e2e12084abc80169e8e075377d3b",
|
||||
"sha256:538d30cd96ed7d1416d3956f94d54e426a8daf7c14527f6e0d6d425fcb4cca52",
|
||||
"sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610",
|
||||
"sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05",
|
||||
"sha256:64bd50cf16bcc54b274e20235bf8edbb64184a30e1e53873ff8d444e7ac656b2",
|
||||
"sha256:65fd3d2e228cae024c411c5ccdffae4c315271eee4a8b839291f84f796b34eca",
|
||||
"sha256:66b4c0731a5c81921e938dcf1a88e978264e26e6ac4ec96a4d21ae0354581ae0",
|
||||
"sha256:68a8f8c046c6466ac61a36b65bb2395c74451df2ffb8458492ef49900efed293",
|
||||
"sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289",
|
||||
"sha256:6b9fc7e9cc983e75e2518496ba1afc524227c163e43d706688a6bb9eca41617e",
|
||||
"sha256:6f51f9556785e5a203713f5efd9c085b4a45aecd2a42573e2b5041881b588d1f",
|
||||
"sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c",
|
||||
"sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94",
|
||||
"sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad",
|
||||
"sha256:7a5486ca56c8869070a966321d5ab416ff0f83f30e0e2da1ab48815c8d165d46",
|
||||
"sha256:7c479f5ae937ec9985ecaf42e2e10631551d909f203e31308c12d703922742f9",
|
||||
"sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9",
|
||||
"sha256:7e37e809b9303ec3a179085415cb5f418ecf65ec98cdfe34f6a078b46ef823ee",
|
||||
"sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9",
|
||||
"sha256:836d3cc225b3e8a943d0b02633fb2f28a66e281290302a79df0e1eaa984ff7c1",
|
||||
"sha256:84c312cdf839e8b579f504afcd7b65f35d60b6285d892b19adea16355e8343c9",
|
||||
"sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799",
|
||||
"sha256:871e3ab2838fbcb4e0865a6e01233975df3a15e6fce93b6f99d75cacbd9862d1",
|
||||
"sha256:88ecc3afd7e776967fa16c80f974cb79399ee8dc6c96423321d6f7d4b881c92b",
|
||||
"sha256:8bc593dcce679206b60a538c302d03c29b18e3d862609317cb560e18b66d10cf",
|
||||
"sha256:8fd5afd101dcf86a270d254364e0e8dddedebe6bd1ab9d5f732f274fa00499a5",
|
||||
"sha256:945352286a541406f99b2655c973852da7911b3f4264e010218bbc1cc73168f2",
|
||||
"sha256:973335b1624859cb0e52f96062a28aa18f3a5fc77a96e4a3d6d76e29811a0e6e",
|
||||
"sha256:994448ee01864501912abf2bad9203bffc34158e80fe8bfb5b031f4f8e16da51",
|
||||
"sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506",
|
||||
"sha256:a2ec4419a3fe6cf8a4795752596dfe0adb4aea40d3683a132bae9c30b81e8d73",
|
||||
"sha256:a4997716674d36a82eab3e86f8fa77080a5d8d96a389a61ea1d0e3a94a582cf7",
|
||||
"sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5",
|
||||
"sha256:a82465ebbc9b1c5c50738536fdfa7cab639a261a99b469c9d4c7dcbb2b3f1e57",
|
||||
"sha256:ae2757ace61bc4061b69af19e4689fa4416e1a04840f33b441034202b5cd02d4",
|
||||
"sha256:b16582783f44fbca6fcf46f61347340c787d7530d88b4d590a397a47583f31dd",
|
||||
"sha256:ba2537ef2163db9e6ccdbeb6f6424282ae4dea43177402152c67ef869cf3978b",
|
||||
"sha256:bf7a89eef64b5455835f5ed30254ec19bf41f7541cd94f266ab7cbd463f00c41",
|
||||
"sha256:c0abb5e4e8ce71a61d9446040c1e86d4e6d23f9097275c5bd49ed978755ff0fe",
|
||||
"sha256:c414cbda77dbf13c3bc88b073a1a9f375c7b0cb5e115e15d4b73ec3a2fbc6f59",
|
||||
"sha256:c51edc3541e11fbe83f0c4d9412ef6c79f664a3745fab261457e84465ec9d5a8",
|
||||
"sha256:c5e69fd3eb0b409432b537fe3c6f44ac089c458ab6b78dcec14478422879ec5f",
|
||||
"sha256:c918b7a1e26b4ab40409820ddccc5d49871a82329640f5005f73572d5eaa9b5e",
|
||||
"sha256:c9bb87fdf2ab2370f21e4d5636e5317775e5d51ff32ebff2cf389f71b9b13750",
|
||||
"sha256:ca5b2028c2f7af4e13fb9fc29b28d0ce767c38c7facdf64f6c2cd040413055f1",
|
||||
"sha256:d0a07763776188b4db4c9c7fb1b8c494049f84659bb387b71c73bbc07f189e96",
|
||||
"sha256:d33a0021893ede5969876052796165bab6006559ab845fd7b515a30abdd990dc",
|
||||
"sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440",
|
||||
"sha256:dac8e84fff5d27420f3c1e879ce9929108e873667ec87e0c8eeb413a5311adfe",
|
||||
"sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38",
|
||||
"sha256:eb462f0e346fcf41a901a126b50f8781e9a474d3927930f3490f38a6e73b6950",
|
||||
"sha256:eb563dd3aea54c797adf513eeec819c4213d7dbfc311874eb4fd28d10f2ff0f2",
|
||||
"sha256:f273674b445bcb6e4409bf8d1be67bc4b58e8b46fd0d560055d515b8830063cd",
|
||||
"sha256:f6442f0f0ff81775eaa5b05af8a0ffa1dda36e9cf6ec1e0d3d245e8564b684ce",
|
||||
"sha256:fb168b5924bef397b5ba13aabd8cf5df7d3d93f10218d7b925e360d436863f66",
|
||||
"sha256:fbf8c2f00904eaf63ff37718eb13acf8e178cb940520e47b2f05027f5bb34ce3",
|
||||
"sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2024.5.15"
|
||||
"version": "==2024.7.24"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
@@ -3637,28 +3638,28 @@
|
||||
},
|
||||
"ruff": {
|
||||
"hashes": [
|
||||
"sha256:204fb0a472f00f2e6280a7c8c7c066e11e20e23a37557d63045bf27a616ba61c",
|
||||
"sha256:2875b7596a740cbbd492f32d24be73e545a4ce0a3daf51e4f4e609962bfd3cd2",
|
||||
"sha256:3164488aebd89b1745b47fd00604fb4358d774465f20d1fcd907f9c0fc1b0655",
|
||||
"sha256:38beace10b8d5f9b6bdc91619310af6d63dd2019f3fb2d17a2da26360d7962fa",
|
||||
"sha256:3a9a9a1b582e37669b0138b7c1d9d60b9edac880b80eb2baba6d0e566bdeca4d",
|
||||
"sha256:5c441d9c24ec09e1cb190a04535c5379b36b73c4bc20aa180c54812c27d1cca4",
|
||||
"sha256:5e478d2f09cf06add143cf8c4540ef77b6599191e0c50ed976582f06e588c994",
|
||||
"sha256:6ecf968fcf94d942d42b700af18ede94b07521bd188aaf2cd7bc898dd8cb63b6",
|
||||
"sha256:b1789bf2cd3d1b5a7d38397cac1398ddf3ad7f73f4de01b1e913e2abc7dfc51d",
|
||||
"sha256:bac6288e82f6296f82ed5285f597713acb2a6ae26618ffc6b429c597b392535c",
|
||||
"sha256:bdd9f723e16003623423affabcc0a807a66552ee6a29f90eddad87a40c750b78",
|
||||
"sha256:be9fd62c1e99539da05fcdc1e90d20f74aec1b7a1613463ed77870057cd6bd96",
|
||||
"sha256:c4c2112e9883a40967827d5c24803525145e7dab315497fae149764979ac7929",
|
||||
"sha256:d235968460e8758d1e1297e1de59a38d94102f60cafb4d5382033c324404ee9d",
|
||||
"sha256:d7ceb9b2fe700ee09a0c6b192c5ef03c56eb82a0514218d8ff700f6ade004108",
|
||||
"sha256:dfaf11c8a116394da3b65cd4b36de30d8552fa45b8119b9ef5ca6638ab964fa3",
|
||||
"sha256:e216fc75a80ea1fbd96af94a6233d90190d5b65cc3d5dfacf2bd48c3e067d3e1",
|
||||
"sha256:f0368d765eec8247b8550251c49ebb20554cc4e812f383ff9f5bf0d5d94190b0"
|
||||
"sha256:07c9e3c2a8e1fe377dd460371c3462671a728c981c3205a5217291422209f642",
|
||||
"sha256:111a99cdb02f69ddb2571e2756e017a1496c2c3a2aeefe7b988ddab38b416d36",
|
||||
"sha256:1f77c1c3aa0669fb230b06fb24ffa3e879391a3ba3f15e3d633a752da5a3e670",
|
||||
"sha256:4d394940f61f7720ad371ddedf14722ee1d6250fd8d020f5ea5a86e7be217daf",
|
||||
"sha256:563a7ae61ad284187d3071d9041c08019975693ff655438d8d4be26e492760bd",
|
||||
"sha256:57c6c0dd997b31b536bff49b9eee5ed3194d60605a4427f735eeb1f9c1b8d264",
|
||||
"sha256:80521b88d26a45e871f31e4b88938fd87db7011bb961d8afd2664982dfc3641a",
|
||||
"sha256:94fe60869bfbf0521e04fd62b74cbca21cbc5beb67cbb75ab33fe8c174f54414",
|
||||
"sha256:a0ef5930799a05522985b9cec8290b185952f3fcd86c1772c3bdbd732667fdcd",
|
||||
"sha256:b652dc14f6ef5d1552821e006f747802cc32d98d5509349e168f6bf0ee9f8f42",
|
||||
"sha256:c476acb43c3c51e3c614a2e878ee1589655fa02dab19fe2db0423a06d6a5b1b6",
|
||||
"sha256:c94e084ba3eaa80c2172918c2ca2eb2230c3f15925f4ed8b6297260c6ef179ad",
|
||||
"sha256:d7fe7dccb1a89dc66785d7aa0ac283b2269712d8ed19c63af908fdccca5ccc1a",
|
||||
"sha256:d9bc8f328a9f1309ae80e4d392836e7dbc77303b38ed4a7112699e63d3b066ab",
|
||||
"sha256:e2ff8003f5252fd68425fd53d27c1f08b201d7ed714bb31a55c9ac1d4c13e2eb",
|
||||
"sha256:e395daba77a79f6dc0d07311f94cc0560375ca20c06f354c7c99af3bf4560c5d",
|
||||
"sha256:e6a584c1de6f8591c2570e171cc7ce482bb983d49c70ddf014393cd39e9dfaed",
|
||||
"sha256:f908148c93c02873210a52cad75a6eda856b2cbb72250370ce3afef6fb99b1ed"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==0.5.1"
|
||||
"version": "==0.5.6"
|
||||
},
|
||||
"scipy": {
|
||||
"hashes": [
|
||||
@@ -3816,7 +3817,6 @@
|
||||
"sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e",
|
||||
"sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.0.1"
|
||||
},
|
||||
|
||||
@@ -37,7 +37,7 @@ Thanks to the generous folks at [DigitalOcean](https://m.do.co/c/8d70b916d462),
|
||||
<a href="https://m.do.co/c/8d70b916d462" style="padding-top: 4px; display: block;">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_white.svg" width="140px">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_black_.svg" width="140px">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" width="140px">
|
||||
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_black_.svg" width="140px">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
@@ -10,8 +10,8 @@ map_uidgid() {
|
||||
local -r usermap_new_gid=${USERMAP_GID:-${usermap_original_gid:-$usermap_new_uid}}
|
||||
if [[ ${usermap_new_uid} != "${usermap_original_uid}" || ${usermap_new_gid} != "${usermap_original_gid}" ]]; then
|
||||
echo "Mapping UID and GID for paperless:paperless to $usermap_new_uid:$usermap_new_gid"
|
||||
usermod -o -u "${usermap_new_uid}" paperless
|
||||
groupmod -o -g "${usermap_new_gid}" paperless
|
||||
usermod --non-unique --uid "${usermap_new_uid}" paperless
|
||||
groupmod --non-unique --gid "${usermap_new_gid}" paperless
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ custom_container_init() {
|
||||
fi
|
||||
|
||||
# Make sure custom init directory has files in it
|
||||
if [ -n "$(/bin/ls -A "${custom_script_dir}" 2>/dev/null)" ]; then
|
||||
if [ -n "$(/bin/ls --almost-all "${custom_script_dir}" 2>/dev/null)" ]; then
|
||||
echo "[custom-init] files found in ${custom_script_dir} executing"
|
||||
# Loop over files in the directory
|
||||
for SCRIPT in "${custom_script_dir}"/*; do
|
||||
@@ -86,13 +86,13 @@ initialize() {
|
||||
"${CONSUME_DIR}"; do
|
||||
if [[ ! -d "${dir}" ]]; then
|
||||
echo "Creating directory ${dir}"
|
||||
mkdir --parents "${dir}"
|
||||
mkdir --parents --verbose "${dir}"
|
||||
fi
|
||||
done
|
||||
|
||||
local -r tmp_dir="${PAPERLESS_SCRATCH_DIR:=/tmp/paperless}"
|
||||
echo "Creating directory scratch directory ${tmp_dir}"
|
||||
mkdir --parents "${tmp_dir}"
|
||||
mkdir --parents --verbose "${tmp_dir}"
|
||||
|
||||
set +e
|
||||
echo "Adjusting permissions of paperless files. This may take a while."
|
||||
@@ -102,7 +102,7 @@ initialize() {
|
||||
"${DATA_DIR}" \
|
||||
"${MEDIA_ROOT_DIR}" \
|
||||
"${CONSUME_DIR}"; do
|
||||
find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown paperless:paperless {} +
|
||||
find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown --changes paperless:paperless {} +
|
||||
done
|
||||
set -e
|
||||
|
||||
@@ -127,7 +127,7 @@ install_languages() {
|
||||
for lang in "${langs[@]}"; do
|
||||
pkg="tesseract-ocr-$lang"
|
||||
|
||||
if dpkg -s "$pkg" &>/dev/null; then
|
||||
if dpkg --status "$pkg" &>/dev/null; then
|
||||
echo "Package $pkg already installed!"
|
||||
continue
|
||||
fi
|
||||
@@ -138,7 +138,7 @@ install_languages() {
|
||||
fi
|
||||
|
||||
echo "Installing package $pkg..."
|
||||
if ! apt-get -y install "$pkg" &>/dev/null; then
|
||||
if ! apt-get --assume-yes install "$pkg" &>/dev/null; then
|
||||
echo "Could not install $pkg"
|
||||
exit 1
|
||||
fi
|
||||
@@ -148,7 +148,7 @@ install_languages() {
|
||||
echo "Paperless-ngx docker container starting..."
|
||||
|
||||
gosu_cmd=(gosu paperless)
|
||||
if [ "$(id -u)" == "$(id -u paperless)" ]; then
|
||||
if [ "$(id --user)" == "$(id --user paperless)" ]; then
|
||||
gosu_cmd=()
|
||||
fi
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ wait_for_postgres() {
|
||||
|
||||
# Disable warning, host and port can't have spaces
|
||||
# shellcheck disable=SC2086
|
||||
while [ ! "$(pg_isready -h ${host} -p ${port})" ]; do
|
||||
while [ ! "$(pg_isready --host ${host} --port ${port})" ]; do
|
||||
|
||||
if [ $attempt_num -eq $max_attempts ]; then
|
||||
echo "Unable to connect to database."
|
||||
@@ -25,6 +25,7 @@ wait_for_postgres() {
|
||||
attempt_num=$(("$attempt_num" + 1))
|
||||
sleep 5
|
||||
done
|
||||
echo "Connected to PostgreSQL"
|
||||
}
|
||||
|
||||
wait_for_mariadb() {
|
||||
@@ -51,6 +52,7 @@ wait_for_mariadb() {
|
||||
attempt_num=$(("$attempt_num" + 1))
|
||||
sleep 5
|
||||
done
|
||||
echo "Connected to MariaDB"
|
||||
}
|
||||
|
||||
wait_for_redis() {
|
||||
|
||||
@@ -187,6 +187,7 @@ variables:
|
||||
| `DOCUMENT_THUMBNAIL_PATH` | Path to the generated thumbnail |
|
||||
| `DOCUMENT_DOWNLOAD_URL` | URL for document download |
|
||||
| `DOCUMENT_THUMBNAIL_URL` | URL for the document thumbnail |
|
||||
| `DOCUMENT_OWNER` | Username of the document owner (if any) |
|
||||
| `DOCUMENT_CORRESPONDENT` | Assigned correspondent (if any) |
|
||||
| `DOCUMENT_TAGS` | Comma separated list of tags applied (if any) |
|
||||
| `DOCUMENT_ORIGINAL_FILENAME` | Filename of original document |
|
||||
|
||||
@@ -1,5 +1,203 @@
|
||||
# Changelog
|
||||
|
||||
## paperless-ngx 2.11.3
|
||||
|
||||
### Features
|
||||
|
||||
- Enhancement: optimize tasks / stats reload [@shamoon](https://github.com/shamoon) ([#7402](https://github.com/paperless-ngx/paperless-ngx/pull/7402))
|
||||
- Enhancement: allow specifying default currency for Monetary custom field [@shamoon](https://github.com/shamoon) ([#7381](https://github.com/paperless-ngx/paperless-ngx/pull/7381))
|
||||
- Enhancement: specify when pre-check fails for documents in trash [@shamoon](https://github.com/shamoon) ([#7355](https://github.com/paperless-ngx/paperless-ngx/pull/7355))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: clear selection after reload for management lists [@shamoon](https://github.com/shamoon) ([#7421](https://github.com/paperless-ngx/paperless-ngx/pull/7421))
|
||||
- Fix: disable inline create buttons if insufficient permissions [@shamoon](https://github.com/shamoon) ([#7401](https://github.com/paperless-ngx/paperless-ngx/pull/7401))
|
||||
- Fix: use entire document for dropzone [@shamoon](https://github.com/shamoon) ([#7342](https://github.com/paperless-ngx/paperless-ngx/pull/7342))
|
||||
|
||||
### Maintenance
|
||||
|
||||
- Chore(deps): Bump stumpylog/image-cleaner-action from 0.7.0 to 0.8.0 in the actions group [@dependabot](https://github.com/dependabot) ([#7371](https://github.com/paperless-ngx/paperless-ngx/pull/7371))
|
||||
|
||||
### Dependencies
|
||||
|
||||
<details>
|
||||
<summary>11 changes</summary>
|
||||
|
||||
- Chore(deps): Bump django from 4.2.14 to 4.2.15 [@dependabot](https://github.com/dependabot) ([#7412](https://github.com/paperless-ngx/paperless-ngx/pull/7412))
|
||||
- Chore(deps-dev): Bump the development group with 3 updates [@dependabot](https://github.com/dependabot) ([#7394](https://github.com/paperless-ngx/paperless-ngx/pull/7394))
|
||||
- Chore(deps): Bump the small-changes group with 5 updates [@dependabot](https://github.com/dependabot) ([#7397](https://github.com/paperless-ngx/paperless-ngx/pull/7397))
|
||||
- Chore(deps-dev): Bump [@<!---->playwright/test from 1.42.1 to 1.45.3 in /src-ui @dependabot](https://github.com/<!---->playwright/test from 1.42.1 to 1.45.3 in /src-ui @dependabot) ([#7367](https://github.com/paperless-ngx/paperless-ngx/pull/7367))
|
||||
- Chore(deps-dev): Bump [@<!---->types/node from 20.12.2 to 22.0.2 in /src-ui @dependabot](https://github.com/<!---->types/node from 20.12.2 to 22.0.2 in /src-ui @dependabot) ([#7366](https://github.com/paperless-ngx/paperless-ngx/pull/7366))
|
||||
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#7365](https://github.com/paperless-ngx/paperless-ngx/pull/7365))
|
||||
- Chore(deps): Bump uuid from 9.0.1 to 10.0.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#7370](https://github.com/paperless-ngx/paperless-ngx/pull/7370))
|
||||
- Chore(deps): Bump stumpylog/image-cleaner-action from 0.7.0 to 0.8.0 in the actions group [@dependabot](https://github.com/dependabot) ([#7371](https://github.com/paperless-ngx/paperless-ngx/pull/7371))
|
||||
- Chore(deps): Bump zone.js from 0.14.4 to 0.14.8 in /src-ui [@dependabot](https://github.com/dependabot) ([#7368](https://github.com/paperless-ngx/paperless-ngx/pull/7368))
|
||||
- Chore(deps-dev): Bump jest-preset-angular from 14.1.1 to 14.2.2 in /src-ui in the frontend-jest-dependencies group [@dependabot](https://github.com/dependabot) ([#7364](https://github.com/paperless-ngx/paperless-ngx/pull/7364))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 20 updates [@dependabot](https://github.com/dependabot) ([#7363](https://github.com/paperless-ngx/paperless-ngx/pull/7363))
|
||||
</details>
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>15 changes</summary>
|
||||
|
||||
- Fix: clear selection after reload for management lists [@shamoon](https://github.com/shamoon) ([#7421](https://github.com/paperless-ngx/paperless-ngx/pull/7421))
|
||||
- Enhancement: optimize tasks / stats reload [@shamoon](https://github.com/shamoon) ([#7402](https://github.com/paperless-ngx/paperless-ngx/pull/7402))
|
||||
- Enhancement: allow specifying default currency for Monetary custom field [@shamoon](https://github.com/shamoon) ([#7381](https://github.com/paperless-ngx/paperless-ngx/pull/7381))
|
||||
- Enhancement: specify when pre-check fails for documents in trash [@shamoon](https://github.com/shamoon) ([#7355](https://github.com/paperless-ngx/paperless-ngx/pull/7355))
|
||||
- Chore(deps-dev): Bump the development group with 3 updates [@dependabot](https://github.com/dependabot) ([#7394](https://github.com/paperless-ngx/paperless-ngx/pull/7394))
|
||||
- Fix: disable inline create buttons if insufficient permissions [@shamoon](https://github.com/shamoon) ([#7401](https://github.com/paperless-ngx/paperless-ngx/pull/7401))
|
||||
- Chore(deps): Bump the small-changes group with 5 updates [@dependabot](https://github.com/dependabot) ([#7397](https://github.com/paperless-ngx/paperless-ngx/pull/7397))
|
||||
- Chore(deps-dev): Bump [@<!---->playwright/test from 1.42.1 to 1.45.3 in /src-ui @dependabot](https://github.com/<!---->playwright/test from 1.42.1 to 1.45.3 in /src-ui @dependabot) ([#7367](https://github.com/paperless-ngx/paperless-ngx/pull/7367))
|
||||
- Chore(deps-dev): Bump [@<!---->types/node from 20.12.2 to 22.0.2 in /src-ui @dependabot](https://github.com/<!---->types/node from 20.12.2 to 22.0.2 in /src-ui @dependabot) ([#7366](https://github.com/paperless-ngx/paperless-ngx/pull/7366))
|
||||
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#7365](https://github.com/paperless-ngx/paperless-ngx/pull/7365))
|
||||
- Chore(deps): Bump uuid from 9.0.1 to 10.0.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#7370](https://github.com/paperless-ngx/paperless-ngx/pull/7370))
|
||||
- Chore(deps): Bump zone.js from 0.14.4 to 0.14.8 in /src-ui [@dependabot](https://github.com/dependabot) ([#7368](https://github.com/paperless-ngx/paperless-ngx/pull/7368))
|
||||
- Chore(deps-dev): Bump jest-preset-angular from 14.1.1 to 14.2.2 in /src-ui in the frontend-jest-dependencies group [@dependabot](https://github.com/dependabot) ([#7364](https://github.com/paperless-ngx/paperless-ngx/pull/7364))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 20 updates [@dependabot](https://github.com/dependabot) ([#7363](https://github.com/paperless-ngx/paperless-ngx/pull/7363))
|
||||
- Fix: use entire document for dropzone [@shamoon](https://github.com/shamoon) ([#7342](https://github.com/paperless-ngx/paperless-ngx/pull/7342))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 2.11.2
|
||||
|
||||
### Changes
|
||||
|
||||
- Change: more clearly handle init permissions error [@shamoon](https://github.com/shamoon) ([#7334](https://github.com/paperless-ngx/paperless-ngx/pull/7334))
|
||||
- Chore: add permissions info link from webUI [@shamoon](https://github.com/shamoon) ([#7310](https://github.com/paperless-ngx/paperless-ngx/pull/7310))
|
||||
- Fix: increase search input text contrast with light custom theme colors [@JayBkr](https://github.com/JayBkr) ([#7303](https://github.com/paperless-ngx/paperless-ngx/pull/7303))
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7296](https://github.com/paperless-ngx/paperless-ngx/pull/7296))
|
||||
- Chore(deps): Bump tika-client from 0.5.0 to 0.6.0 in the small-changes group [@dependabot](https://github.com/dependabot) ([#7297](https://github.com/paperless-ngx/paperless-ngx/pull/7297))
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>5 changes</summary>
|
||||
|
||||
- Change: more clearly handle init permissions error [@shamoon](https://github.com/shamoon) ([#7334](https://github.com/paperless-ngx/paperless-ngx/pull/7334))
|
||||
- Chore: add permissions info link from webUI [@shamoon](https://github.com/shamoon) ([#7310](https://github.com/paperless-ngx/paperless-ngx/pull/7310))
|
||||
- Fix: increase search input text contrast with light custom theme colors [@JayBkr](https://github.com/JayBkr) ([#7303](https://github.com/paperless-ngx/paperless-ngx/pull/7303))
|
||||
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7296](https://github.com/paperless-ngx/paperless-ngx/pull/7296))
|
||||
- Chore(deps): Bump tika-client from 0.5.0 to 0.6.0 in the small-changes group [@dependabot](https://github.com/dependabot) ([#7297](https://github.com/paperless-ngx/paperless-ngx/pull/7297))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 2.11.1
|
||||
|
||||
### Features
|
||||
|
||||
- Enhancement: include owner username in post-consumption variables [@Freddy-0](https://github.com/Freddy-0) ([#7270](https://github.com/paperless-ngx/paperless-ngx/pull/7270))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: support multiple inbox tags from stats widget [@shamoon](https://github.com/shamoon) ([#7281](https://github.com/paperless-ngx/paperless-ngx/pull/7281))
|
||||
- Fix: Removes Turkish from the NLTK languages [@stumpylog](https://github.com/stumpylog) ([#7246](https://github.com/paperless-ngx/paperless-ngx/pull/7246))
|
||||
- Fix: include trashed docs in existing doc check [@shamoon](https://github.com/shamoon) ([#7229](https://github.com/paperless-ngx/paperless-ngx/pull/7229))
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7261](https://github.com/paperless-ngx/paperless-ngx/pull/7261))
|
||||
- Chore(deps): Bump the small-changes group across 1 directory with 2 updates [@dependabot](https://github.com/dependabot) ([#7266](https://github.com/paperless-ngx/paperless-ngx/pull/7266))
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>7 changes</summary>
|
||||
|
||||
- Fix: support multiple inbox tags from stats widget [@shamoon](https://github.com/shamoon) ([#7281](https://github.com/paperless-ngx/paperless-ngx/pull/7281))
|
||||
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7261](https://github.com/paperless-ngx/paperless-ngx/pull/7261))
|
||||
- Chore(deps): Bump the small-changes group across 1 directory with 2 updates [@dependabot](https://github.com/dependabot) ([#7266](https://github.com/paperless-ngx/paperless-ngx/pull/7266))
|
||||
- Enhancement: include owner username in post-consumption variables [@Freddy-0](https://github.com/Freddy-0) ([#7270](https://github.com/paperless-ngx/paperless-ngx/pull/7270))
|
||||
- Chore: Squash older automatic migrations [@stumpylog](https://github.com/stumpylog) ([#7267](https://github.com/paperless-ngx/paperless-ngx/pull/7267))
|
||||
- Fix: Removes Turkish from the NLTK languages [@stumpylog](https://github.com/stumpylog) ([#7246](https://github.com/paperless-ngx/paperless-ngx/pull/7246))
|
||||
- Fix: include trashed docs in existing doc check [@shamoon](https://github.com/shamoon) ([#7229](https://github.com/paperless-ngx/paperless-ngx/pull/7229))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 2.11.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- Feature: Upgrade Gotenberg to v8 [@stumpylog](https://github.com/stumpylog) ([#7094](https://github.com/paperless-ngx/paperless-ngx/pull/7094))
|
||||
|
||||
### Features
|
||||
|
||||
- Enhancement: disable add split button when appropriate [@shamoon](https://github.com/shamoon) ([#7215](https://github.com/paperless-ngx/paperless-ngx/pull/7215))
|
||||
- Enhancement: wrapping of saved view fields d-n-d UI [@shamoon](https://github.com/shamoon) ([#7216](https://github.com/paperless-ngx/paperless-ngx/pull/7216))
|
||||
- Enhancement: support custom field icontains filter for select type [@shamoon](https://github.com/shamoon) ([#7199](https://github.com/paperless-ngx/paperless-ngx/pull/7199))
|
||||
- Feature: select custom field type [@shamoon](https://github.com/shamoon) ([#7167](https://github.com/paperless-ngx/paperless-ngx/pull/7167))
|
||||
- Feature: automatic sso redirect [@shamoon](https://github.com/shamoon) ([#7168](https://github.com/paperless-ngx/paperless-ngx/pull/7168))
|
||||
- Enhancement: show more columns in mail frontend admin [@shamoon](https://github.com/shamoon) ([#7158](https://github.com/paperless-ngx/paperless-ngx/pull/7158))
|
||||
- Enhancement: use request user as owner of split / merge docs [@shamoon](https://github.com/shamoon) ([#7112](https://github.com/paperless-ngx/paperless-ngx/pull/7112))
|
||||
- Enhancement: improve date parsing with accented characters [@fdubuy](https://github.com/fdubuy) ([#7100](https://github.com/paperless-ngx/paperless-ngx/pull/7100))
|
||||
- Feature: improve history display of object names etc [@shamoon](https://github.com/shamoon) ([#7102](https://github.com/paperless-ngx/paperless-ngx/pull/7102))
|
||||
- Feature: Upgrade Gotenberg to v8 [@stumpylog](https://github.com/stumpylog) ([#7094](https://github.com/paperless-ngx/paperless-ngx/pull/7094))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: include documents in trash for existing asn check [@shamoon](https://github.com/shamoon) ([#7189](https://github.com/paperless-ngx/paperless-ngx/pull/7189))
|
||||
- Fix: include documents in trash in sanity check [@shamoon](https://github.com/shamoon) ([#7133](https://github.com/paperless-ngx/paperless-ngx/pull/7133))
|
||||
- Fix: handle errors for trash actions and only show documents user can restore or delete [@shamoon](https://github.com/shamoon) ([#7119](https://github.com/paperless-ngx/paperless-ngx/pull/7119))
|
||||
- Fix: dont include documents in trash in counts [@shamoon](https://github.com/shamoon) ([#7111](https://github.com/paperless-ngx/paperless-ngx/pull/7111))
|
||||
- Fix: use temp dir for split / merge [@shamoon](https://github.com/shamoon) ([#7105](https://github.com/paperless-ngx/paperless-ngx/pull/7105))
|
||||
|
||||
### Maintenance
|
||||
|
||||
- Chore: upgrade to DRF 3.15 [@shamoon](https://github.com/shamoon) ([#7134](https://github.com/paperless-ngx/paperless-ngx/pull/7134))
|
||||
- Chore(deps): Bump docker/build-push-action from 5 to 6 in the actions group [@dependabot](https://github.com/dependabot) ([#7125](https://github.com/paperless-ngx/paperless-ngx/pull/7125))
|
||||
- Chore: Ignores DRF 3.15.2 [@stumpylog](https://github.com/stumpylog) ([#7122](https://github.com/paperless-ngx/paperless-ngx/pull/7122))
|
||||
- Chore: show docker tag in UI for ci test builds [@shamoon](https://github.com/shamoon) ([#7083](https://github.com/paperless-ngx/paperless-ngx/pull/7083))
|
||||
|
||||
### Dependencies
|
||||
|
||||
<details>
|
||||
<summary>11 changes</summary>
|
||||
|
||||
- Chore: Bulk backend updates [@stumpylog](https://github.com/stumpylog) ([#7209](https://github.com/paperless-ngx/paperless-ngx/pull/7209))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 14 updates [@dependabot](https://github.com/dependabot) ([#7200](https://github.com/paperless-ngx/paperless-ngx/pull/7200))
|
||||
- Chore(deps): Bump certifi from 2024.6.2 to 2024.7.4 [@dependabot](https://github.com/dependabot) ([#7166](https://github.com/paperless-ngx/paperless-ngx/pull/7166))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 6 updates [@dependabot](https://github.com/dependabot) ([#7148](https://github.com/paperless-ngx/paperless-ngx/pull/7148))
|
||||
- Chore(deps): Bump django-multiselectfield from 0.1.12 to 0.1.13 in the django group [@dependabot](https://github.com/dependabot) ([#7147](https://github.com/paperless-ngx/paperless-ngx/pull/7147))
|
||||
- Chore(deps): Bump docker/build-push-action from 5 to 6 in the actions group [@dependabot](https://github.com/dependabot) ([#7125](https://github.com/paperless-ngx/paperless-ngx/pull/7125))
|
||||
- Chore(deps): Bump the small-changes group across 1 directory with 4 updates [@dependabot](https://github.com/dependabot) ([#7128](https://github.com/paperless-ngx/paperless-ngx/pull/7128))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 16 updates [@dependabot](https://github.com/dependabot) ([#7126](https://github.com/paperless-ngx/paperless-ngx/pull/7126))
|
||||
- Chore(deps-dev): Bump ruff from 0.4.9 to 0.5.0 in the development group across 1 directory [@dependabot](https://github.com/dependabot) ([#7120](https://github.com/paperless-ngx/paperless-ngx/pull/7120))
|
||||
- Chore(deps-dev): Bump ws from 8.17.0 to 8.17.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#7114](https://github.com/paperless-ngx/paperless-ngx/pull/7114))
|
||||
- Chore: update to Angular v18 [@shamoon](https://github.com/shamoon) ([#7106](https://github.com/paperless-ngx/paperless-ngx/pull/7106))
|
||||
</details>
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>25 changes</summary>
|
||||
|
||||
- Enhancement: disable add split button when appropriate [@shamoon](https://github.com/shamoon) ([#7215](https://github.com/paperless-ngx/paperless-ngx/pull/7215))
|
||||
- Enhancement: wrapping of saved view fields d-n-d UI [@shamoon](https://github.com/shamoon) ([#7216](https://github.com/paperless-ngx/paperless-ngx/pull/7216))
|
||||
- Chore: Bulk backend updates [@stumpylog](https://github.com/stumpylog) ([#7209](https://github.com/paperless-ngx/paperless-ngx/pull/7209))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 14 updates [@dependabot](https://github.com/dependabot) ([#7200](https://github.com/paperless-ngx/paperless-ngx/pull/7200))
|
||||
- Enhancement: support custom field icontains filter for select type [@shamoon](https://github.com/shamoon) ([#7199](https://github.com/paperless-ngx/paperless-ngx/pull/7199))
|
||||
- Chore: upgrade to DRF 3.15 [@shamoon](https://github.com/shamoon) ([#7134](https://github.com/paperless-ngx/paperless-ngx/pull/7134))
|
||||
- Feature: select custom field type [@shamoon](https://github.com/shamoon) ([#7167](https://github.com/paperless-ngx/paperless-ngx/pull/7167))
|
||||
- Feature: automatic sso redirect [@shamoon](https://github.com/shamoon) ([#7168](https://github.com/paperless-ngx/paperless-ngx/pull/7168))
|
||||
- Fix: include documents in trash for existing asn check [@shamoon](https://github.com/shamoon) ([#7189](https://github.com/paperless-ngx/paperless-ngx/pull/7189))
|
||||
- Chore: Initial conversion to pytest fixtures [@stumpylog](https://github.com/stumpylog) ([#7110](https://github.com/paperless-ngx/paperless-ngx/pull/7110))
|
||||
- Enhancement: show more columns in mail frontend admin [@shamoon](https://github.com/shamoon) ([#7158](https://github.com/paperless-ngx/paperless-ngx/pull/7158))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 6 updates [@dependabot](https://github.com/dependabot) ([#7148](https://github.com/paperless-ngx/paperless-ngx/pull/7148))
|
||||
- Chore(deps): Bump django-multiselectfield from 0.1.12 to 0.1.13 in the django group [@dependabot](https://github.com/dependabot) ([#7147](https://github.com/paperless-ngx/paperless-ngx/pull/7147))
|
||||
- Fix: include documents in trash in sanity check [@shamoon](https://github.com/shamoon) ([#7133](https://github.com/paperless-ngx/paperless-ngx/pull/7133))
|
||||
- Chore(deps): Bump the small-changes group across 1 directory with 4 updates [@dependabot](https://github.com/dependabot) ([#7128](https://github.com/paperless-ngx/paperless-ngx/pull/7128))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 16 updates [@dependabot](https://github.com/dependabot) ([#7126](https://github.com/paperless-ngx/paperless-ngx/pull/7126))
|
||||
- Enhancement: use request user as owner of split / merge docs [@shamoon](https://github.com/shamoon) ([#7112](https://github.com/paperless-ngx/paperless-ngx/pull/7112))
|
||||
- Fix: handle errors for trash actions and only show documents user can restore or delete [@shamoon](https://github.com/shamoon) ([#7119](https://github.com/paperless-ngx/paperless-ngx/pull/7119))
|
||||
- Chore(deps-dev): Bump ruff from 0.4.9 to 0.5.0 in the development group across 1 directory [@dependabot](https://github.com/dependabot) ([#7120](https://github.com/paperless-ngx/paperless-ngx/pull/7120))
|
||||
- Chore(deps-dev): Bump ws from 8.17.0 to 8.17.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#7114](https://github.com/paperless-ngx/paperless-ngx/pull/7114))
|
||||
- Chore: update to Angular v18 [@shamoon](https://github.com/shamoon) ([#7106](https://github.com/paperless-ngx/paperless-ngx/pull/7106))
|
||||
- Enhancement: improve date parsing with accented characters [@fdubuy](https://github.com/fdubuy) ([#7100](https://github.com/paperless-ngx/paperless-ngx/pull/7100))
|
||||
- Feature: improve history display of object names etc [@shamoon](https://github.com/shamoon) ([#7102](https://github.com/paperless-ngx/paperless-ngx/pull/7102))
|
||||
- Fix: dont include documents in trash in counts [@shamoon](https://github.com/shamoon) ([#7111](https://github.com/paperless-ngx/paperless-ngx/pull/7111))
|
||||
- Fix: use temp dir for split / merge [@shamoon](https://github.com/shamoon) ([#7105](https://github.com/paperless-ngx/paperless-ngx/pull/7105))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 2.10.2
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -600,7 +600,7 @@ You can optionally also automatically redirect users to the SSO login with [PAPE
|
||||
|
||||
Defaults to False
|
||||
|
||||
#### ['PAPERLESS_REDIRECT_LOGIN_TO_SSO=<bool>`](#PAPERLESS_REDIRECT_LOGIN_TO_SSO) {#PAPERLESS_REDIRECT_LOGIN_TO_SSO}
|
||||
#### [`PAPERLESS_REDIRECT_LOGIN_TO_SSO=<bool>`](#PAPERLESS_REDIRECT_LOGIN_TO_SSO) {#PAPERLESS_REDIRECT_LOGIN_TO_SSO}
|
||||
|
||||
: When this setting is enabled users will automatically be redirected (using javascript) to the first SSO provider login. You may still want to disable the frontend login form for clarity.
|
||||
|
||||
|
||||
+1
-2
@@ -540,8 +540,7 @@ are released, dependency support is confirmed, etc.
|
||||
15. Optional: If using the NLTK machine learning processing (see
|
||||
[`PAPERLESS_ENABLE_NLTK`](configuration.md#PAPERLESS_ENABLE_NLTK) for details),
|
||||
download the NLTK data for the Snowball
|
||||
Stemmer, Stopwords and Punkt tokenizer to your
|
||||
`PAPERLESS_DATA_DIR/nltk`. Refer to the [NLTK
|
||||
Stemmer, Stopwords and Punkt tokenizer to `/usr/share/nltk_data`. Refer to the [NLTK
|
||||
instructions](https://www.nltk.org/data.html) for details on how to
|
||||
download the data.
|
||||
|
||||
|
||||
+26
-22
@@ -237,9 +237,13 @@ Settings > Users & Groups, assuming the user has access. If a user is designated
|
||||
as a member of a group those permissions will be inherited and this is reflected in the UI. Explicit
|
||||
permissions can be granted to limit access to certain parts of the UI (and corresponding API endpoints).
|
||||
|
||||
!!! note
|
||||
!!! tip
|
||||
|
||||
Superusers can access all parts of the front and backend application as well as any and all objects.
|
||||
By default, new users are not granted any permissions, except those inherited from any group(s) of which they are a member.
|
||||
|
||||
#### Superusers
|
||||
|
||||
Superusers can access all parts of the front and backend application as well as any and all objects.
|
||||
|
||||
#### Admin Status
|
||||
|
||||
@@ -248,29 +252,29 @@ as well as accessing the Django backend.
|
||||
|
||||
#### Detailed Explanation of Global Permissions {#global-permissions}
|
||||
|
||||
Global permissions define what areas of the app and API endpoints the user can access. For example, they
|
||||
Global permissions define what areas of the app and API endpoints users can access. For example, they
|
||||
determine if a user can create, edit, delete or view _any_ documents, but individual documents themselves
|
||||
still have "object-level" permissions.
|
||||
|
||||
| Type | Details |
|
||||
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| AppConfig | _Change_ or higher permissions grants access to the "Application Configuration" area. |
|
||||
| Correspondent | Grants global permissions to add, edit, delete or view Correspondents. |
|
||||
| CustomField | Grants global permissions to add, edit, delete or view Custom Fields. |
|
||||
| Document | Grants global permissions to add, edit, delete or view Documents. |
|
||||
| DocumentType | Grants global permissions to add, edit, delete or view Document Types. |
|
||||
| Group | Grants global permissions to add, edit, delete or view Groups. |
|
||||
| MailAccount | Grants global permissions to add, edit, delete or view Mail Accounts. |
|
||||
| MailRule | Grants global permissions to add, edit, delete or view Mail Rules. |
|
||||
| Note | Grants global permissions to add, edit, delete or view Notes. |
|
||||
| PaperlessTask | Grants global permissions to view or dismiss (_Change_) File Tasks. |
|
||||
| SavedView | Grants global permissions to add, edit, delete or view Saved Views. |
|
||||
| ShareLink | Grants global permissions to add, delete or view Share Links. |
|
||||
| StoragePath | Grants global permissions to add, edit, delete or view Storage Paths. |
|
||||
| Tag | Grants global permissions to add, edit, delete or view Tags. |
|
||||
| UISettings | Grants global permissions to add, edit, delete or view the UI settings that are used by the web app.<br/>Users expected to access the web UI should usually be granted at least _View_ permissions. |
|
||||
| User | Grants global permissions to add, edit, delete or view Users. |
|
||||
| Workflow | Grants global permissions to add, edit, delete or view Workflows.<br/>Note that Workflows are global, in other words all users who can access workflows have access to the same set of them. |
|
||||
| Type | Details |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| AppConfig | _Change_ or higher permissions grants access to the "Application Configuration" area. |
|
||||
| Correspondent | Add, edit, delete or view Correspondents. |
|
||||
| CustomField | Add, edit, delete or view Custom Fields. |
|
||||
| Document | Add, edit, delete or view Documents. |
|
||||
| DocumentType | Add, edit, delete or view Document Types. |
|
||||
| Group | Add, edit, delete or view Groups. |
|
||||
| MailAccount | Add, edit, delete or view Mail Accounts. |
|
||||
| MailRule | Add, edit, delete or view Mail Rules. |
|
||||
| Note | Add, edit, delete or view Notes. |
|
||||
| PaperlessTask | View or dismiss (_Change_) File Tasks. |
|
||||
| SavedView | Add, edit, delete or view Saved Views. |
|
||||
| ShareLink | Add, delete or view Share Links. |
|
||||
| StoragePath | Add, edit, delete or view Storage Paths. |
|
||||
| Tag | Add, edit, delete or view Tags. |
|
||||
| UISettings | Add, edit, delete or view the UI settings that are used by the web app.<br/>:warning: **Users that will access the web UI must be granted at least _View_ permissions.** |
|
||||
| User | Add, edit, delete or view Users. |
|
||||
| Workflow | Add, edit, delete or view Workflows.<br/>Note that Workflows are global, in other words all users who can access workflows have access to the same set of them. |
|
||||
|
||||
#### Detailed Explanation of Object Permissions {#object-permissions}
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ markdown_extensions:
|
||||
- name: mermaid
|
||||
class: mermaid
|
||||
format: !!python/name:pymdownx.superfences.fence_code_format
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
strict: true
|
||||
nav:
|
||||
- index.md
|
||||
|
||||
@@ -14,6 +14,7 @@ following additional information about it:
|
||||
* Thumbnail Path: ${DOCUMENT_THUMBNAIL_PATH}
|
||||
* Download URL: ${DOCUMENT_DOWNLOAD_URL}
|
||||
* Thumbnail URL: ${DOCUMENT_THUMBNAIL_URL}
|
||||
* Owner Name: ${DOCUMENT_OWNER}
|
||||
* Correspondent: ${DOCUMENT_CORRESPONDENT}
|
||||
* Tags: ${DOCUMENT_TAGS}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ test('dashboard inbox link', async ({ page }) => {
|
||||
await page.routeFromHAR(REQUESTS_HAR1, { notFound: 'fallback' })
|
||||
await page.goto('/dashboard')
|
||||
await page.getByRole('link', { name: 'Documents in inbox' }).click()
|
||||
await expect(page).toHaveURL(/tags__id__all=9/)
|
||||
await expect(page).toHaveURL(/tags__id__in=9/)
|
||||
await expect(page.locator('pngx-document-list')).toHaveText(/8 documents/)
|
||||
})
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
"content": {
|
||||
"size": -1,
|
||||
"mimeType": "application/json",
|
||||
"text": "{\"documents_total\":61,\"documents_inbox\":8,\"inbox_tag\":9,\"document_file_type_counts\":[{\"mime_type\":\"application/pdf\",\"mime_type_count\":57},{\"mime_type\":\"text/plain\",\"mime_type_count\":3},{\"mime_type\":\"text/csv\",\"mime_type_count\":1}],\"character_count\":2407053}"
|
||||
"text": "{\"documents_total\":61,\"documents_inbox\":8,\"inbox_tags\":[9],\"document_file_type_counts\":[{\"mime_type\":\"application/pdf\",\"mime_type_count\":57},{\"mime_type\":\"text/plain\",\"mime_type_count\":3},{\"mime_type\":\"text/csv\",\"mime_type_count\":1}],\"character_count\":2407053}"
|
||||
},
|
||||
"headersSize": -1,
|
||||
"bodySize": -1,
|
||||
@@ -250,7 +250,7 @@
|
||||
"time": 0.609,
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "http://localhost:8000/api/documents/?page=1&page_size=10&ordering=-created&truncate_content=true&tags__id__all=9",
|
||||
"url": "http://localhost:8000/api/documents/?page=1&page_size=10&ordering=-created&truncate_content=true&tags__id__in=9",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"cookies": [],
|
||||
"headers": [
|
||||
@@ -284,7 +284,7 @@
|
||||
"value": "true"
|
||||
},
|
||||
{
|
||||
"name": "tags__id__all",
|
||||
"name": "tags__id__in",
|
||||
"value": "9"
|
||||
}
|
||||
],
|
||||
@@ -468,7 +468,7 @@
|
||||
"time": 0.951,
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "http://localhost:8000/api/documents/?page=1&page_size=50&ordering=-created&truncate_content=true&tags__id__all=9",
|
||||
"url": "http://localhost:8000/api/documents/?page=1&page_size=50&ordering=-created&truncate_content=true&tags__id__in=9",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"cookies": [],
|
||||
"headers": [
|
||||
@@ -502,7 +502,7 @@
|
||||
"value": "true"
|
||||
},
|
||||
{
|
||||
"name": "tags__id__all",
|
||||
"name": "tags__id__in",
|
||||
"value": "9"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
"content": {
|
||||
"size": -1,
|
||||
"mimeType": "application/json",
|
||||
"text": "{\"documents_total\":61,\"documents_inbox\":8,\"inbox_tag\":9,\"document_file_type_counts\":[{\"mime_type\":\"application/pdf\",\"mime_type_count\":57},{\"mime_type\":\"text/plain\",\"mime_type_count\":3},{\"mime_type\":\"text/csv\",\"mime_type_count\":1}],\"character_count\":2407053}"
|
||||
"text": "{\"documents_total\":61,\"documents_inbox\":8,\"inbox_tags\":[9],\"document_file_type_counts\":[{\"mime_type\":\"application/pdf\",\"mime_type_count\":57},{\"mime_type\":\"text/plain\",\"mime_type_count\":3},{\"mime_type\":\"text/csv\",\"mime_type_count\":1}],\"character_count\":2407053}"
|
||||
},
|
||||
"headersSize": -1,
|
||||
"bodySize": -1,
|
||||
@@ -250,7 +250,7 @@
|
||||
"time": 0.622,
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "http://localhost:8000/api/documents/?page=1&page_size=10&ordering=-created&truncate_content=true&tags__id__all=9",
|
||||
"url": "http://localhost:8000/api/documents/?page=1&page_size=10&ordering=-created&truncate_content=true&tags__id__in=9",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"cookies": [],
|
||||
"headers": [
|
||||
@@ -284,7 +284,7 @@
|
||||
"value": "true"
|
||||
},
|
||||
{
|
||||
"name": "tags__id__all",
|
||||
"name": "tags__id__in",
|
||||
"value": "9"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
"content": {
|
||||
"size": -1,
|
||||
"mimeType": "application/json",
|
||||
"text": "{\"documents_total\":61,\"documents_inbox\":8,\"inbox_tag\":9,\"document_file_type_counts\":[{\"mime_type\":\"application/pdf\",\"mime_type_count\":57},{\"mime_type\":\"text/plain\",\"mime_type_count\":3},{\"mime_type\":\"text/csv\",\"mime_type_count\":1}],\"character_count\":2407053}"
|
||||
"text": "{\"documents_total\":61,\"documents_inbox\":8,\"inbox_tags\":[9],\"document_file_type_counts\":[{\"mime_type\":\"application/pdf\",\"mime_type_count\":57},{\"mime_type\":\"text/plain\",\"mime_type_count\":3},{\"mime_type\":\"text/csv\",\"mime_type_count\":1}],\"character_count\":2407053}"
|
||||
},
|
||||
"headersSize": -1,
|
||||
"bodySize": -1,
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
"content": {
|
||||
"size": -1,
|
||||
"mimeType": "application/json",
|
||||
"text": "{\"documents_total\":61,\"documents_inbox\":8,\"inbox_tag\":9,\"document_file_type_counts\":[{\"mime_type\":\"application/pdf\",\"mime_type_count\":57},{\"mime_type\":\"text/plain\",\"mime_type_count\":3},{\"mime_type\":\"text/csv\",\"mime_type_count\":1}],\"character_count\":2407053}"
|
||||
"text": "{\"documents_total\":61,\"documents_inbox\":8,\"inbox_tags\":[9],\"document_file_type_counts\":[{\"mime_type\":\"application/pdf\",\"mime_type_count\":57},{\"mime_type\":\"text/plain\",\"mime_type_count\":3},{\"mime_type\":\"text/csv\",\"mime_type_count\":1}],\"character_count\":2407053}"
|
||||
},
|
||||
"headersSize": -1,
|
||||
"bodySize": -1,
|
||||
|
||||
@@ -84,13 +84,8 @@ test('date filtering', async ({ page }) => {
|
||||
await page.getByRole('button', { name: 'Dates' }).click()
|
||||
await page.getByRole('menuitem', { name: 'Last 3 months' }).first().click()
|
||||
await expect(page.locator('pngx-document-list')).toHaveText(/one document/i)
|
||||
await page.getByRole('button', { name: 'Dates Clear selected' }).click()
|
||||
await page.getByRole('button', { name: 'Dates' }).click()
|
||||
await page
|
||||
.getByRole('menuitem', { name: 'After mm/dd/yyyy' })
|
||||
.getByRole('button')
|
||||
.first()
|
||||
.click()
|
||||
await page.getByRole('menuitem', { name: 'Last 3 months' }).first().click()
|
||||
await page.getByLabel('Datesselected').getByRole('button').first().click()
|
||||
await page.getByRole('combobox', { name: 'Select month' }).selectOption('12')
|
||||
await page.getByRole('combobox', { name: 'Select year' }).selectOption('2022')
|
||||
await page.getByText('11', { exact: true }).click()
|
||||
|
||||
+190
-140
File diff suppressed because it is too large.
Load diff
Generated
+2235
-2315
File diff suppressed because it is too large.
Load diff
+29
-29
@@ -11,17 +11,17 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/cdk": "^18.0.6",
|
||||
"@angular/common": "~18.0.6",
|
||||
"@angular/compiler": "~18.0.6",
|
||||
"@angular/core": "~18.0.6",
|
||||
"@angular/forms": "~18.0.6",
|
||||
"@angular/localize": "~18.0.6",
|
||||
"@angular/platform-browser": "~18.0.6",
|
||||
"@angular/platform-browser-dynamic": "~18.0.6",
|
||||
"@angular/router": "~18.0.6",
|
||||
"@angular/cdk": "^18.1.3",
|
||||
"@angular/common": "~18.1.3",
|
||||
"@angular/compiler": "~18.1.3",
|
||||
"@angular/core": "~18.1.3",
|
||||
"@angular/forms": "~18.1.3",
|
||||
"@angular/localize": "~18.1.3",
|
||||
"@angular/platform-browser": "~18.1.3",
|
||||
"@angular/platform-browser-dynamic": "~18.1.3",
|
||||
"@angular/router": "~18.1.3",
|
||||
"@ng-bootstrap/ng-bootstrap": "^17.0.0",
|
||||
"@ng-select/ng-select": "^13.4.1",
|
||||
"@ng-select/ng-select": "^13.5.0",
|
||||
"@ngneat/dirty-check-forms": "^3.0.3",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"bootstrap": "^5.3.3",
|
||||
@@ -35,32 +35,32 @@
|
||||
"ngx-ui-tour-ng-bootstrap": "^15.0.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"tslib": "^2.6.2",
|
||||
"uuid": "^9.0.1",
|
||||
"zone.js": "^0.14.4"
|
||||
"uuid": "^10.0.0",
|
||||
"zone.js": "^0.14.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-builders/jest": "^18.0.0",
|
||||
"@angular-devkit/build-angular": "^18.0.7",
|
||||
"@angular-devkit/core": "^18.0.7",
|
||||
"@angular-devkit/schematics": "^18.0.7",
|
||||
"@angular-eslint/builder": "18.1.0",
|
||||
"@angular-eslint/eslint-plugin": "18.1.0",
|
||||
"@angular-eslint/eslint-plugin-template": "18.1.0",
|
||||
"@angular-eslint/schematics": "18.1.0",
|
||||
"@angular-eslint/template-parser": "18.1.0",
|
||||
"@angular/cli": "~18.0.7",
|
||||
"@angular/compiler-cli": "~18.0.3",
|
||||
"@playwright/test": "^1.42.1",
|
||||
"@angular-devkit/build-angular": "^18.1.3",
|
||||
"@angular-devkit/core": "^18.1.3",
|
||||
"@angular-devkit/schematics": "^18.1.3",
|
||||
"@angular-eslint/builder": "18.2.0",
|
||||
"@angular-eslint/eslint-plugin": "18.2.0",
|
||||
"@angular-eslint/eslint-plugin-template": "18.2.0",
|
||||
"@angular-eslint/schematics": "18.2.0",
|
||||
"@angular-eslint/template-parser": "18.2.0",
|
||||
"@angular/cli": "~18.1.3",
|
||||
"@angular/compiler-cli": "~18.1.3",
|
||||
"@playwright/test": "^1.45.3",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.12.2",
|
||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
||||
"@typescript-eslint/parser": "^7.4.0",
|
||||
"@typescript-eslint/utils": "^7.13.0",
|
||||
"@types/node": "^22.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
||||
"@typescript-eslint/parser": "^8.0.0",
|
||||
"@typescript-eslint/utils": "^8.0.0",
|
||||
"concurrently": "^8.2.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint": "^9.8.0",
|
||||
"jest": "29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-preset-angular": "^14.0.0",
|
||||
"jest-preset-angular": "^14.2.2",
|
||||
"jest-websocket-mock": "^2.5.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"ts-node": "~10.9.1",
|
||||
|
||||
@@ -214,6 +214,13 @@
|
||||
<i-bs class="me-1" name="envelope"></i-bs><span> <ng-container i18n>Mail</ng-container></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item app-link" *pngxIfPermissions="{ action: PermissionAction.Delete, type: PermissionType.Document }">
|
||||
<a class="nav-link" routerLink="trash" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Trash"
|
||||
i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body"
|
||||
triggers="mouseenter:mouseleave" popoverClass="popover-slim">
|
||||
<i-bs class="me-1" name="trash"></i-bs><span> <ng-container i18n>Trash</ng-container></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -267,13 +274,6 @@
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
<li class="nav-item app-link" *pngxIfPermissions="{ action: PermissionAction.Delete, type: PermissionType.Document }">
|
||||
<a class="nav-link" routerLink="trash" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Trash"
|
||||
i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body"
|
||||
triggers="mouseenter:mouseleave" popoverClass="popover-slim">
|
||||
<i-bs class="me-1" name="trash"></i-bs><span> <ng-container i18n>Trash</ng-container></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item mt-2" tourAnchor="tour.outro">
|
||||
<a class="px-3 py-2 text-muted small d-flex align-items-center flex-wrap text-decoration-none"
|
||||
target="_blank" rel="noopener noreferrer" href="https://docs.paperless-ngx.com" ngbPopover="Documentation"
|
||||
|
||||
+18
@@ -20,6 +20,12 @@ const customFields: CustomField[] = [
|
||||
select_options: ['Option 1', 'Option 2', 'Option 3'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Field 5',
|
||||
data_type: CustomFieldDataType.Monetary,
|
||||
extra_data: { default_currency: 'JPY' },
|
||||
},
|
||||
]
|
||||
const document: Document = {
|
||||
id: 1,
|
||||
@@ -112,6 +118,18 @@ describe('CustomFieldDisplayComponent', () => {
|
||||
expect(component.value).toEqual(100)
|
||||
})
|
||||
|
||||
it('should respect explicit default currency', () => {
|
||||
component['defaultCurrencyCode'] = 'EUR' // mock default locale injection
|
||||
component.fieldId = 5
|
||||
component.document = {
|
||||
id: 1,
|
||||
title: 'Doc 1',
|
||||
custom_fields: [{ field: 5, document: 1, created: null, value: '100' }],
|
||||
}
|
||||
expect(component.currency).toEqual('JPY')
|
||||
expect(component.value).toEqual(100)
|
||||
})
|
||||
|
||||
it('should show select value', () => {
|
||||
expect(component.getSelectValue(customFields[3], 2)).toEqual('Option 3')
|
||||
})
|
||||
|
||||
+3
-1
@@ -90,7 +90,9 @@ export class CustomFieldDisplayComponent implements OnInit, OnDestroy {
|
||||
)?.value
|
||||
if (this.value && this.field.data_type === CustomFieldDataType.Monetary) {
|
||||
this.currency =
|
||||
this.value.match(/([A-Z]{3})/)?.[0] ?? this.defaultCurrencyCode
|
||||
this.value.match(/([A-Z]{3})/)?.[0] ??
|
||||
this.field.extra_data?.default_currency ??
|
||||
this.defaultCurrencyCode
|
||||
this.value = parseFloat(this.value.replace(this.currency, ''))
|
||||
} else if (
|
||||
this.value?.length &&
|
||||
|
||||
+5
@@ -28,6 +28,11 @@
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@case (CustomFieldDataType.Monetary) {
|
||||
<div class="my-3">
|
||||
<pngx-input-text i18n-title title="Default Currency" hint="3-character currency code" i18n-hint formControlName="default_currency" placeholder="Use locale" i18n-placeholder autocomplete="off"></pngx-input-text>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
@@ -90,6 +90,7 @@ export class CustomFieldEditDialogComponent
|
||||
data_type: new FormControl(null),
|
||||
extra_data: new FormGroup({
|
||||
select_options: new FormArray([new FormControl(null)]),
|
||||
default_currency: new FormControl(null),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
+8
-1
@@ -13,6 +13,7 @@ import { PermissionsSelectComponent } from '../../permissions-select/permissions
|
||||
import { EditDialogMode } from '../edit-dialog.component'
|
||||
import { GroupEditDialogComponent } from './group-edit-dialog.component'
|
||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
||||
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
|
||||
|
||||
describe('GroupEditDialogComponent', () => {
|
||||
let component: GroupEditDialogComponent
|
||||
@@ -30,7 +31,13 @@ describe('GroupEditDialogComponent', () => {
|
||||
PermissionsFormComponent,
|
||||
PermissionsSelectComponent,
|
||||
],
|
||||
imports: [FormsModule, ReactiveFormsModule, NgSelectModule, NgbModule],
|
||||
imports: [
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
NgSelectModule,
|
||||
NgbModule,
|
||||
NgxBootstrapIconsModule.pick(allIcons),
|
||||
],
|
||||
providers: [
|
||||
NgbActiveModal,
|
||||
provideHttpClient(withInterceptorsFromDi()),
|
||||
|
||||
+8
-1
@@ -20,6 +20,7 @@ import { PermissionsSelectComponent } from '../../permissions-select/permissions
|
||||
import { EditDialogMode } from '../edit-dialog.component'
|
||||
import { UserEditDialogComponent } from './user-edit-dialog.component'
|
||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
||||
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
|
||||
|
||||
describe('UserEditDialogComponent', () => {
|
||||
let component: UserEditDialogComponent
|
||||
@@ -38,7 +39,13 @@ describe('UserEditDialogComponent', () => {
|
||||
PermissionsFormComponent,
|
||||
PermissionsSelectComponent,
|
||||
],
|
||||
imports: [FormsModule, ReactiveFormsModule, NgSelectModule, NgbModule],
|
||||
imports: [
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
NgSelectModule,
|
||||
NgbModule,
|
||||
NgxBootstrapIconsModule.pick(allIcons),
|
||||
],
|
||||
providers: [
|
||||
NgbActiveModal,
|
||||
{
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@
|
||||
</div>
|
||||
@if (formGroup.get('type').value === WorkflowTriggerType.DocumentAdded || formGroup.get('type').value === WorkflowTriggerType.DocumentUpdated) {
|
||||
<div class="col-md-6">
|
||||
<pngx-input-tags [allowCreate]="false" i18n-title title="Has tags" formControlName="filter_has_tags"></pngx-input-tags>
|
||||
<pngx-input-tags [allowCreate]="false" i18n-title title="Has any of tags" formControlName="filter_has_tags"></pngx-input-tags>
|
||||
<pngx-input-select i18n-title title="Has correspondent" [items]="correspondents" [allowNull]="true" formControlName="filter_has_correspondent"></pngx-input-select>
|
||||
<pngx-input-select i18n-title title="Has document type" [items]="documentTypes" [allowNull]="true" formControlName="filter_has_document_type"></pngx-input-select>
|
||||
</div>
|
||||
|
||||
@@ -52,6 +52,11 @@ describe('MonetaryComponent', () => {
|
||||
expect(component.defaultCurrencyCode).toEqual('BRL')
|
||||
})
|
||||
|
||||
it('should support setting a default currency code', () => {
|
||||
component.defaultCurrency = 'EUR'
|
||||
expect(component.defaultCurrencyCode).toEqual('EUR')
|
||||
})
|
||||
|
||||
it('should parse monetary value correctly', () => {
|
||||
expect(component['parseMonetaryValue']('123.4')).toEqual('123.4')
|
||||
expect(component['parseMonetaryValue']('123.4', true)).toEqual('123.40')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, forwardRef, Inject, LOCALE_ID } from '@angular/core'
|
||||
import { Component, forwardRef, Inject, Input, LOCALE_ID } from '@angular/core'
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms'
|
||||
import { AbstractInputComponent } from '../abstract-input'
|
||||
import { getLocaleCurrencyCode } from '@angular/common'
|
||||
@@ -29,11 +29,16 @@ export class MonetaryComponent extends AbstractInputComponent<string> {
|
||||
|
||||
defaultCurrencyCode: string
|
||||
|
||||
@Input()
|
||||
set defaultCurrency(currency: string) {
|
||||
if (currency) this.defaultCurrencyCode = currency
|
||||
}
|
||||
|
||||
constructor(@Inject(LOCALE_ID) currentLocale: string) {
|
||||
super()
|
||||
|
||||
this.currency = this.defaultCurrencyCode =
|
||||
getLocaleCurrencyCode(currentLocale)
|
||||
this.defaultCurrency ?? getLocaleCurrencyCode(currentLocale)
|
||||
}
|
||||
|
||||
writeValue(newValue: any): void {
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-select>
|
||||
@if (allowCreate) {
|
||||
@if (allowCreate && !hideAddButton) {
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="createTag()" [disabled]="disabled">
|
||||
<i-bs width="1.2em" height="1.2em" name="plus"></i-bs>
|
||||
</button>
|
||||
|
||||
@@ -74,6 +74,9 @@ export class TagsComponent implements OnInit, ControlValueAccessor {
|
||||
@Input()
|
||||
allowCreate: boolean = true
|
||||
|
||||
@Input()
|
||||
hideAddButton: boolean = false
|
||||
|
||||
@Input()
|
||||
showFilter: boolean = false
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
}
|
||||
</div>
|
||||
<div class="position-relative" [class.col-md-9]="horizontal">
|
||||
<input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete">
|
||||
<input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete" [placeholder]="placeholder">
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ export class TextComponent extends AbstractInputComponent<string> {
|
||||
@Input()
|
||||
autocomplete: string
|
||||
|
||||
@Input()
|
||||
placeholder: string = ''
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
+11
-1
@@ -1,5 +1,15 @@
|
||||
<form [formGroup]="form" [class.opacity-50]="disabled">
|
||||
<label class="form-label">{{title}}</label>
|
||||
<label class="form-label">
|
||||
{{title}}
|
||||
<button class="btn btn-sm btn-link text-muted me-auto p-0 p-md-2" title="What's this?" i18n-title type="button" [ngbPopover]="infoPopover" [autoClose]="true" container="body">
|
||||
<i-bs name="question-circle"></i-bs>
|
||||
</button>
|
||||
<ng-template #infoPopover>
|
||||
<p i18n>Global permissions define what areas of the app and API endpoints users can access.</p>
|
||||
<a href="https://docs.paperless-ngx.com/usage/#global-permissions" target="_blank" referrerpolicy="noopener noreferrer" i18n>Read more</a>
|
||||
<i-bs class="ms-1" width=".8em" height=".8em" name="box-arrow-up-right"></i-bs>
|
||||
</ng-template>
|
||||
</label>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item d-flex">
|
||||
<div class="col-3" i18n>Type</div>
|
||||
|
||||
@@ -36,10 +36,10 @@
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto col-lg-4 col-xl-3 col-sidebar">
|
||||
<div class="col-12 col-lg-4 col-xl-3 col-sidebar">
|
||||
<div class="row row-cols-1 g-4 mb-4 sticky-lg-top z-0">
|
||||
<div class="col">
|
||||
<pngx-statistics-widget></pngx-statistics-widget>
|
||||
<pngx-statistics-widget *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.UISettings }"></pngx-statistics-widget>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pngx-upload-file-widget></pngx-upload-file-widget>
|
||||
|
||||
+9
-2
@@ -71,11 +71,18 @@ describe('StatisticsWidgetComponent', () => {
|
||||
expect(reloadSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not call statistics endpoint on reload if already loading', () => {
|
||||
httpTestingController.expectOne(`${environment.apiBaseUrl}statistics/`)
|
||||
component.loading = true
|
||||
component.reload()
|
||||
httpTestingController.expectNone(`${environment.apiBaseUrl}statistics/`)
|
||||
})
|
||||
|
||||
it('should display inbox link with count', () => {
|
||||
const mockStats = {
|
||||
documents_total: 200,
|
||||
documents_inbox: 18,
|
||||
inbox_tag: 10,
|
||||
inbox_tags: [10],
|
||||
}
|
||||
|
||||
const req = httpTestingController.expectOne(
|
||||
@@ -100,7 +107,7 @@ describe('StatisticsWidgetComponent', () => {
|
||||
const mockStats = {
|
||||
documents_total: 200,
|
||||
documents_inbox: 18,
|
||||
inbox_tag: 10,
|
||||
inbox_tags: [10],
|
||||
document_file_type_counts: [
|
||||
{
|
||||
mime_type: 'application/pdf',
|
||||
|
||||
+33
-28
@@ -1,7 +1,7 @@
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core'
|
||||
import { Observable, Subscription } from 'rxjs'
|
||||
import { FILTER_HAS_TAGS_ALL } from 'src/app/data/filter-rule-type'
|
||||
import { first, Observable, Subject, Subscription, takeUntil } from 'rxjs'
|
||||
import { FILTER_HAS_TAGS_ANY } from 'src/app/data/filter-rule-type'
|
||||
import { ConsumerStatusService } from 'src/app/services/consumer-status.service'
|
||||
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
|
||||
import { environment } from 'src/environments/environment'
|
||||
@@ -11,7 +11,7 @@ import { ComponentWithPermissions } from 'src/app/components/with-permissions/wi
|
||||
export interface Statistics {
|
||||
documents_total?: number
|
||||
documents_inbox?: number
|
||||
inbox_tag?: number
|
||||
inbox_tags?: number[]
|
||||
document_file_type_counts?: DocumentFileType[]
|
||||
character_count?: number
|
||||
tag_count?: number
|
||||
@@ -35,7 +35,7 @@ export class StatisticsWidgetComponent
|
||||
extends ComponentWithPermissions
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
loading: boolean = true
|
||||
loading: boolean = false
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
@@ -48,31 +48,32 @@ export class StatisticsWidgetComponent
|
||||
statistics: Statistics = {}
|
||||
|
||||
subscription: Subscription
|
||||
|
||||
private getStatistics(): Observable<Statistics> {
|
||||
return this.http.get(`${environment.apiBaseUrl}statistics/`)
|
||||
}
|
||||
private unsubscribeNotifer: Subject<any> = new Subject()
|
||||
|
||||
reload() {
|
||||
if (this.loading) return
|
||||
this.loading = true
|
||||
this.getStatistics().subscribe((statistics) => {
|
||||
this.loading = false
|
||||
const fileTypeMax = 5
|
||||
if (statistics.document_file_type_counts?.length > fileTypeMax) {
|
||||
const others = statistics.document_file_type_counts.slice(fileTypeMax)
|
||||
statistics.document_file_type_counts =
|
||||
statistics.document_file_type_counts.slice(0, fileTypeMax)
|
||||
statistics.document_file_type_counts.push({
|
||||
mime_type: $localize`Other`,
|
||||
mime_type_count: others.reduce(
|
||||
(currentValue, documentFileType) =>
|
||||
documentFileType.mime_type_count + currentValue,
|
||||
0
|
||||
),
|
||||
})
|
||||
}
|
||||
this.statistics = statistics
|
||||
})
|
||||
this.http
|
||||
.get<Statistics>(`${environment.apiBaseUrl}statistics/`)
|
||||
.pipe(takeUntil(this.unsubscribeNotifer), first())
|
||||
.subscribe((statistics) => {
|
||||
this.loading = false
|
||||
const fileTypeMax = 5
|
||||
if (statistics.document_file_type_counts?.length > fileTypeMax) {
|
||||
const others = statistics.document_file_type_counts.slice(fileTypeMax)
|
||||
statistics.document_file_type_counts =
|
||||
statistics.document_file_type_counts.slice(0, fileTypeMax)
|
||||
statistics.document_file_type_counts.push({
|
||||
mime_type: $localize`Other`,
|
||||
mime_type_count: others.reduce(
|
||||
(currentValue, documentFileType) =>
|
||||
documentFileType.mime_type_count + currentValue,
|
||||
0
|
||||
),
|
||||
})
|
||||
}
|
||||
this.statistics = statistics
|
||||
})
|
||||
}
|
||||
|
||||
getFileTypeExtension(filetype: DocumentFileType): string {
|
||||
@@ -105,13 +106,17 @@ export class StatisticsWidgetComponent
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.subscription.unsubscribe()
|
||||
this.unsubscribeNotifer.next(true)
|
||||
this.unsubscribeNotifer.complete()
|
||||
}
|
||||
|
||||
goToInbox() {
|
||||
this.documentListViewService.quickFilter([
|
||||
{
|
||||
rule_type: FILTER_HAS_TAGS_ALL,
|
||||
value: this.statistics.inbox_tag.toString(),
|
||||
rule_type: FILTER_HAS_TAGS_ANY,
|
||||
value: this.statistics.inbox_tags
|
||||
.map((tagID) => tagID.toString())
|
||||
.join(','),
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
@@ -110,12 +110,12 @@
|
||||
<pngx-input-date i18n-title title="Date created" formControlName="created_date" [suggestions]="suggestions?.dates" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event)"
|
||||
[error]="error?.created_date"></pngx-input-date>
|
||||
<pngx-input-select [items]="correspondents" i18n-title title="Correspondent" formControlName="correspondent" [allowNull]="true" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.Correspondent)"
|
||||
(createNew)="createCorrespondent($event)" [suggestions]="suggestions?.correspondents" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Correspondent }"></pngx-input-select>
|
||||
(createNew)="createCorrespondent($event)" [hideAddButton]="createDisabled(DataType.Correspondent)" [suggestions]="suggestions?.correspondents" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Correspondent }"></pngx-input-select>
|
||||
<pngx-input-select [items]="documentTypes" i18n-title title="Document type" formControlName="document_type" [allowNull]="true" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.DocumentType)"
|
||||
(createNew)="createDocumentType($event)" [suggestions]="suggestions?.document_types" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.DocumentType }"></pngx-input-select>
|
||||
(createNew)="createDocumentType($event)" [hideAddButton]="createDisabled(DataType.DocumentType)" [suggestions]="suggestions?.document_types" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.DocumentType }"></pngx-input-select>
|
||||
<pngx-input-select [items]="storagePaths" i18n-title title="Storage path" formControlName="storage_path" [allowNull]="true" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.StoragePath)"
|
||||
(createNew)="createStoragePath($event)" [suggestions]="suggestions?.storage_paths" i18n-placeholder placeholder="Default" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.StoragePath }"></pngx-input-select>
|
||||
<pngx-input-tags formControlName="tags" [suggestions]="suggestions?.tags" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.Tag)" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Tag }"></pngx-input-tags>
|
||||
(createNew)="createStoragePath($event)" [hideAddButton]="createDisabled(DataType.StoragePath)" [suggestions]="suggestions?.storage_paths" i18n-placeholder placeholder="Default" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.StoragePath }"></pngx-input-select>
|
||||
<pngx-input-tags formControlName="tags" [suggestions]="suggestions?.tags" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.Tag)" [hideAddButton]="createDisabled(DataType.Tag)" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Tag }"></pngx-input-tags>
|
||||
@for (fieldInstance of document?.custom_fields; track fieldInstance.field; let i = $index) {
|
||||
<div [formGroup]="customFieldFormFields.controls[i]">
|
||||
@switch (getCustomFieldFromInstance(fieldInstance)?.data_type) {
|
||||
@@ -157,6 +157,7 @@
|
||||
@case (CustomFieldDataType.Monetary) {
|
||||
<pngx-input-monetary formControlName="value"
|
||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||
[defaultCurrency]="getCustomFieldFromInstance(fieldInstance)?.extra_data?.default_currency"
|
||||
[removable]="userIsOwner"
|
||||
(removed)="removeField(fieldInstance)"
|
||||
[horizontal]="true"
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
--page-border: 0;
|
||||
}
|
||||
|
||||
::ng-deep form .ng-select-taggable {
|
||||
max-width: calc(100% - 90px); // fudge factor for (2x) ng-select button width
|
||||
}
|
||||
|
||||
.btn-group .dropdown-toggle-split {
|
||||
border-top-right-radius: inherit;
|
||||
border-bottom-right-radius: inherit;
|
||||
|
||||
@@ -1244,4 +1244,20 @@ describe('DocumentDetailComponent', () => {
|
||||
)
|
||||
fixture.detectChanges()
|
||||
}
|
||||
|
||||
it('createDisabled should return true if the user does not have permission to add the specified data type', () => {
|
||||
currentUserCan = false
|
||||
expect(component.createDisabled(DataType.Correspondent)).toBeTruthy()
|
||||
expect(component.createDisabled(DataType.DocumentType)).toBeTruthy()
|
||||
expect(component.createDisabled(DataType.StoragePath)).toBeTruthy()
|
||||
expect(component.createDisabled(DataType.Tag)).toBeTruthy()
|
||||
})
|
||||
|
||||
it('createDisabled should return false if the user has permission to add the specified data type', () => {
|
||||
currentUserCan = true
|
||||
expect(component.createDisabled(DataType.Correspondent)).toBeFalsy()
|
||||
expect(component.createDisabled(DataType.DocumentType)).toBeFalsy()
|
||||
expect(component.createDisabled(DataType.StoragePath)).toBeFalsy()
|
||||
expect(component.createDisabled(DataType.Tag)).toBeFalsy()
|
||||
})
|
||||
})
|
||||
@@ -651,6 +651,31 @@ export class DocumentDetailComponent
|
||||
})
|
||||
}
|
||||
|
||||
createDisabled(dataType: DataType) {
|
||||
switch (dataType) {
|
||||
case DataType.Correspondent:
|
||||
return !this.permissionsService.currentUserCan(
|
||||
PermissionAction.Add,
|
||||
PermissionType.Correspondent
|
||||
)
|
||||
case DataType.DocumentType:
|
||||
return !this.permissionsService.currentUserCan(
|
||||
PermissionAction.Add,
|
||||
PermissionType.DocumentType
|
||||
)
|
||||
case DataType.StoragePath:
|
||||
return !this.permissionsService.currentUserCan(
|
||||
PermissionAction.Add,
|
||||
PermissionType.StoragePath
|
||||
)
|
||||
case DataType.Tag:
|
||||
return !this.permissionsService.currentUserCan(
|
||||
PermissionAction.Add,
|
||||
PermissionType.Tag
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
discard() {
|
||||
this.documentsService
|
||||
.get(this.documentId)
|
||||
|
||||
@@ -157,191 +157,194 @@
|
||||
</div>
|
||||
}
|
||||
@if (list.displayMode === DisplayMode.TABLE) {
|
||||
<table class="table table-sm align-middle border shadow-sm">
|
||||
<thead>
|
||||
<th></th>
|
||||
@if (activeDisplayFields.includes(DisplayField.ASN)) {
|
||||
<th class="d-none d-lg-table-cell cursor-pointer"
|
||||
pngxSortable="archive_serial_number"
|
||||
title="Sort by ASN" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>ASN</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.CORRESPONDENT) && permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) {
|
||||
<th class="d-none d-md-table-cell cursor-pointer"
|
||||
pngxSortable="correspondent__name"
|
||||
title="Sort by correspondent" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Correspondent</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.TITLE)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="title"
|
||||
title="Sort by title" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Title</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.TAGS) && !activeDisplayFields.includes(DisplayField.TITLE)) {
|
||||
<th i18n>Tags</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.OWNER) && permissionService.currentUserCan(PermissionAction.View, PermissionType.User)) {
|
||||
<th class="d-none d-xl-table-cell cursor-pointer"
|
||||
pngxSortable="owner"
|
||||
title="Sort by owner" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Owner</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.NOTES) && notesEnabled) {
|
||||
<th class="d-none d-xl-table-cell cursor-pointer"
|
||||
pngxSortable="num_notes"
|
||||
title="Sort by notes" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Notes</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.DOCUMENT_TYPE) && permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) {
|
||||
<th class="d-none d-xl-table-cell cursor-pointer"
|
||||
pngxSortable="document_type__name"
|
||||
title="Sort by document type" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Document type</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.STORAGE_PATH) && permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) {
|
||||
<th class="d-none d-xl-table-cell cursor-pointer"
|
||||
pngxSortable="storage_path__name"
|
||||
title="Sort by storage path" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Storage path</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.CREATED)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="created"
|
||||
title="Sort by created date" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Created</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.ADDED)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="added"
|
||||
title="Sort by added date" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Added</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.SHARED)) {
|
||||
<th i18n>
|
||||
Shared
|
||||
</th>
|
||||
}
|
||||
@for (field of activeDisplayCustomFields; track field) {
|
||||
<th>
|
||||
{{getDisplayCustomFieldTitle(field)}}
|
||||
</th>
|
||||
}
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (d of list.documents; track trackByDocumentId($index, d)) {
|
||||
<tr (click)="toggleSelected(d, $event); $event.stopPropagation();" (dblclick)="openDocumentDetail(d)" [ngClass]="list.isSelected(d) ? 'table-row-selected' : ''">
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="docCheck{{d.id}}" [checked]="list.isSelected(d)" (click)="toggleSelected(d, $event); $event.stopPropagation();">
|
||||
<label class="form-check-label" for="docCheck{{d.id}}"></label>
|
||||
</div>
|
||||
</td>
|
||||
@if (activeDisplayFields.includes(DisplayField.ASN)) {
|
||||
<td class="d-none d-xl-table-cell">
|
||||
{{d.archive_serial_number}}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm align-middle border shadow-sm">
|
||||
<thead>
|
||||
<th></th>
|
||||
@if (activeDisplayFields.includes(DisplayField.ASN)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="archive_serial_number"
|
||||
title="Sort by ASN" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>ASN</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.CORRESPONDENT) && permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="correspondent__name"
|
||||
title="Sort by correspondent" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Correspondent</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.TITLE)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="title"
|
||||
title="Sort by title" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
style="min-width: 150px;"
|
||||
i18n>Title</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.TAGS) && !activeDisplayFields.includes(DisplayField.TITLE)) {
|
||||
<th i18n>Tags</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.OWNER) && permissionService.currentUserCan(PermissionAction.View, PermissionType.User)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="owner"
|
||||
title="Sort by owner" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Owner</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.NOTES) && notesEnabled) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="num_notes"
|
||||
title="Sort by notes" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Notes</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.DOCUMENT_TYPE) && permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="document_type__name"
|
||||
title="Sort by document type" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Document type</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.STORAGE_PATH) && permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="storage_path__name"
|
||||
title="Sort by storage path" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Storage path</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.CREATED)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="created"
|
||||
title="Sort by created date" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Created</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.ADDED)) {
|
||||
<th class="cursor-pointer"
|
||||
pngxSortable="added"
|
||||
title="Sort by added date" i18n-title
|
||||
[currentSortField]="list.sortField"
|
||||
[currentSortReverse]="list.sortReverse"
|
||||
(sort)="onSort($event)"
|
||||
i18n>Added</th>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.SHARED)) {
|
||||
<th i18n>
|
||||
Shared
|
||||
</th>
|
||||
}
|
||||
@for (field of activeDisplayCustomFields; track field) {
|
||||
<th>
|
||||
{{getDisplayCustomFieldTitle(field)}}
|
||||
</th>
|
||||
}
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (d of list.documents; track trackByDocumentId($index, d)) {
|
||||
<tr (click)="toggleSelected(d, $event); $event.stopPropagation();" (dblclick)="openDocumentDetail(d)" [ngClass]="list.isSelected(d) ? 'table-row-selected' : ''">
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="docCheck{{d.id}}" [checked]="list.isSelected(d)" (click)="toggleSelected(d, $event); $event.stopPropagation();">
|
||||
<label class="form-check-label" for="docCheck{{d.id}}"></label>
|
||||
</div>
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.CORRESPONDENT) && permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) {
|
||||
<td class="d-none d-xl-table-cell">
|
||||
@if (d.correspondent) {
|
||||
<a (click)="clickCorrespondent(d.correspondent);$event.stopPropagation()" title="Filter by correspondent" i18n-title>{{(d.correspondent$ | async)?.name}}</a>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.TITLE) || activeDisplayFields.includes(DisplayField.TAGS)) {
|
||||
<td width="30%">
|
||||
@if (activeDisplayFields.includes(DisplayField.TITLE)) {
|
||||
<a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.TAGS)) {
|
||||
@for (t of d.tags$ | async; track t) {
|
||||
<pngx-tag [tag]="t" class="ms-1" clickable="true" linkTitle="Filter by tag" i18n-linkTitle (click)="clickTag(t.id);$event.stopPropagation()"></pngx-tag>
|
||||
@if (activeDisplayFields.includes(DisplayField.ASN)) {
|
||||
<td class="">
|
||||
{{d.archive_serial_number}}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.CORRESPONDENT) && permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) {
|
||||
<td class="">
|
||||
@if (d.correspondent) {
|
||||
<a (click)="clickCorrespondent(d.correspondent);$event.stopPropagation()" title="Filter by correspondent" i18n-title>{{(d.correspondent$ | async)?.name}}</a>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.OWNER) && permissionService.currentUserCan(PermissionAction.View, PermissionType.User)) {
|
||||
<td>
|
||||
{{d.owner | username}}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.NOTES) && notesEnabled) {
|
||||
<td class="d-none d-xl-table-cell">
|
||||
@if (d.notes.length) {
|
||||
<a routerLink="/documents/{{d.id}}/notes" class="btn btn-sm p-0">
|
||||
<span class="badge rounded-pill bg-light border text-primary">
|
||||
<i-bs width="1.2em" height="1.2em" class="ms-1 me-1" name="chat-left-text"></i-bs>
|
||||
{{d.notes.length}}</span>
|
||||
</a>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.DOCUMENT_TYPE) && permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) {
|
||||
<td class="d-none d-xl-table-cell">
|
||||
@if (d.document_type) {
|
||||
<a (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type" i18n-title>{{(d.document_type$ | async)?.name}}</a>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.STORAGE_PATH) && permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) {
|
||||
<td class="d-none d-xl-table-cell">
|
||||
@if (d.storage_path) {
|
||||
<a (click)="clickStoragePath(d.storage_path);$event.stopPropagation()" title="Filter by storage path" i18n-title>{{(d.storage_path$ | async)?.name}}</a>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.CREATED)) {
|
||||
<td>
|
||||
{{d.created_date | customDate}}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.ADDED)) {
|
||||
<td>
|
||||
{{d.added | customDate}}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.SHARED)) {
|
||||
<td>
|
||||
@if (d.is_shared_by_requester) { <ng-container i18n>Yes</ng-container> } @else { <ng-container i18n>No</ng-container> }
|
||||
</td>
|
||||
}
|
||||
@for (field of activeDisplayCustomFields; track field) {
|
||||
<td class="d-none d-xl-table-cell">
|
||||
<pngx-custom-field-display [document]="d" [fieldDisplayKey]="field"></pngx-custom-field-display>
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.TITLE) || activeDisplayFields.includes(DisplayField.TAGS)) {
|
||||
<td width="30%">
|
||||
@if (activeDisplayFields.includes(DisplayField.TITLE)) {
|
||||
<a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.TAGS)) {
|
||||
@for (t of d.tags$ | async; track t) {
|
||||
<pngx-tag [tag]="t" class="ms-1" clickable="true" linkTitle="Filter by tag" i18n-linkTitle (click)="clickTag(t.id);$event.stopPropagation()"></pngx-tag>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.OWNER) && permissionService.currentUserCan(PermissionAction.View, PermissionType.User)) {
|
||||
<td>
|
||||
{{d.owner | username}}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.NOTES) && notesEnabled) {
|
||||
<td class="">
|
||||
@if (d.notes.length) {
|
||||
<a routerLink="/documents/{{d.id}}/notes" class="btn btn-sm p-0">
|
||||
<span class="badge rounded-pill bg-light border text-primary">
|
||||
<i-bs width="1.2em" height="1.2em" class="ms-1 me-1" name="chat-left-text"></i-bs>
|
||||
{{d.notes.length}}</span>
|
||||
</a>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.DOCUMENT_TYPE) && permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) {
|
||||
<td class="">
|
||||
@if (d.document_type) {
|
||||
<a (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type" i18n-title>{{(d.document_type$ | async)?.name}}</a>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.STORAGE_PATH) && permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) {
|
||||
<td class="">
|
||||
@if (d.storage_path) {
|
||||
<a (click)="clickStoragePath(d.storage_path);$event.stopPropagation()" title="Filter by storage path" i18n-title>{{(d.storage_path$ | async)?.name}}</a>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.CREATED)) {
|
||||
<td>
|
||||
{{d.created_date | customDate}}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.ADDED)) {
|
||||
<td>
|
||||
{{d.added | customDate}}
|
||||
</td>
|
||||
}
|
||||
@if (activeDisplayFields.includes(DisplayField.SHARED)) {
|
||||
<td>
|
||||
@if (d.is_shared_by_requester) { <ng-container i18n>Yes</ng-container> } @else { <ng-container i18n>No</ng-container> }
|
||||
</td>
|
||||
}
|
||||
@for (field of activeDisplayCustomFields; track field) {
|
||||
<td class="">
|
||||
<pngx-custom-field-display [document]="d" [fieldDisplayKey]="field"></pngx-custom-field-display>
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@if (list.displayMode === DisplayMode.SMALL_CARDS) {
|
||||
<div class="row row-cols-paperless-cards">
|
||||
|
||||
@@ -38,7 +38,7 @@ export class FileDropComponent {
|
||||
|
||||
@ViewChild('ngxFileDrop') ngxFileDrop: NgxFileDropComponent
|
||||
|
||||
@HostListener('dragover', ['$event']) onDragOver(event: DragEvent) {
|
||||
@HostListener('document:dragover', ['$event']) onDragOver(event: DragEvent) {
|
||||
if (!this.dragDropEnabled || !event.dataTransfer?.types?.includes('Files'))
|
||||
return
|
||||
event.preventDefault()
|
||||
@@ -53,7 +53,7 @@ export class FileDropComponent {
|
||||
clearTimeout(this.fileLeaveTimeoutID)
|
||||
}
|
||||
|
||||
@HostListener('dragleave', ['$event']) public onDragLeave(
|
||||
@HostListener('document:dragleave', ['$event']) public onDragLeave(
|
||||
event: DragEvent,
|
||||
immediate: boolean = false
|
||||
) {
|
||||
@@ -73,7 +73,7 @@ export class FileDropComponent {
|
||||
}, ms)
|
||||
}
|
||||
|
||||
@HostListener('drop', ['$event']) public onDrop(event: DragEvent) {
|
||||
@HostListener('document:drop', ['$event']) public onDrop(event: DragEvent) {
|
||||
if (!this.dragDropEnabled) return
|
||||
event.preventDefault()
|
||||
event.stopImmediatePropagation()
|
||||
|
||||
@@ -66,6 +66,7 @@ export class CorrespondentListComponent extends ManagementListComponent<Correspo
|
||||
|
||||
public reloadData(): void {
|
||||
this.isLoading = true
|
||||
this.clearSelection()
|
||||
this.service
|
||||
.listFiltered(
|
||||
this.page,
|
||||
|
||||
@@ -132,6 +132,7 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
|
||||
|
||||
reloadData() {
|
||||
this.isLoading = true
|
||||
this.clearSelection()
|
||||
this.service
|
||||
.listFiltered(
|
||||
this.page,
|
||||
|
||||
@@ -57,5 +57,6 @@ export interface CustomField extends ObjectWithId {
|
||||
created?: Date
|
||||
extra_data?: {
|
||||
select_options?: string[]
|
||||
default_currency?: string
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,9 @@ export enum FileStatusPhase {
|
||||
|
||||
export const FILE_STATUS_MESSAGES = {
|
||||
document_already_exists: $localize`Document already exists.`,
|
||||
document_already_exists_in_trash: $localize`Document already exists. Note: existing document is in the trash.`,
|
||||
asn_already_exists: $localize`Document with ASN already exists.`,
|
||||
asn_already_exists_in_trash: $localize`Document with ASN already exists. Note: existing document is in the trash.`,
|
||||
file_not_found: $localize`File not found.`,
|
||||
pre_consume_script_not_found: $localize`:Pre-Consume is a term that appears like that in the documentation as well and does not need a specific translation:Pre-consume script does not exist.`,
|
||||
pre_consume_script_error: $localize`:Pre-Consume is a term that appears like that in the documentation as well and does not need a specific translation:Error while executing pre-consume script.`,
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
HttpTestingController,
|
||||
provideHttpClientTesting,
|
||||
} from '@angular/common/http/testing'
|
||||
import { TestBed } from '@angular/core/testing'
|
||||
import { fakeAsync, TestBed, tick } from '@angular/core/testing'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { RouterTestingModule } from '@angular/router/testing'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
@@ -18,6 +18,7 @@ import { CustomFieldDataType } from '../data/custom-field'
|
||||
import { PermissionsService } from './permissions.service'
|
||||
import { DEFAULT_DISPLAY_FIELDS, DisplayField } from '../data/document'
|
||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
||||
import { ToastService } from './toast.service'
|
||||
|
||||
const customFields = [
|
||||
{
|
||||
@@ -41,6 +42,7 @@ describe('SettingsService', () => {
|
||||
let customFieldsService: CustomFieldsService
|
||||
let permissionService: PermissionsService
|
||||
let subscription: Subscription
|
||||
let toastService: ToastService
|
||||
|
||||
const ui_settings: UiSettings = {
|
||||
user: {
|
||||
@@ -105,6 +107,7 @@ describe('SettingsService', () => {
|
||||
customFieldsService = TestBed.inject(CustomFieldsService)
|
||||
permissionService = TestBed.inject(PermissionsService)
|
||||
settingsService = TestBed.inject(SettingsService)
|
||||
toastService = TestBed.inject(ToastService)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
@@ -119,6 +122,18 @@ describe('SettingsService', () => {
|
||||
expect(req.request.method).toEqual('GET')
|
||||
})
|
||||
|
||||
it('should catch error and show toast on retrieve ui_settings error', fakeAsync(() => {
|
||||
const toastSpy = jest.spyOn(toastService, 'showError')
|
||||
httpTestingController
|
||||
.expectOne(`${environment.apiBaseUrl}ui_settings/`)
|
||||
.flush(
|
||||
{ detail: 'You do not have permission to perform this action.' },
|
||||
{ status: 403, statusText: 'Forbidden' }
|
||||
)
|
||||
tick(500)
|
||||
expect(toastSpy).toHaveBeenCalled()
|
||||
}))
|
||||
|
||||
it('calls ui_settings api endpoint with POST on store', () => {
|
||||
let req = httpTestingController.expectOne(
|
||||
`${environment.apiBaseUrl}ui_settings/`
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from '@angular/core'
|
||||
import { Meta } from '@angular/platform-browser'
|
||||
import { CookieService } from 'ngx-cookie-service'
|
||||
import { first, Observable, tap } from 'rxjs'
|
||||
import { catchError, first, Observable, of, tap } from 'rxjs'
|
||||
import {
|
||||
BRIGHTNESS,
|
||||
estimateBrightnessForColor,
|
||||
@@ -288,6 +288,19 @@ export class SettingsService {
|
||||
public initializeSettings(): Observable<UiSettings> {
|
||||
return this.http.get<UiSettings>(this.baseUrl).pipe(
|
||||
first(),
|
||||
catchError((error) => {
|
||||
setTimeout(() => {
|
||||
this.toastService.showError('Error loading settings', error)
|
||||
}, 500)
|
||||
return of({
|
||||
settings: {
|
||||
documentListSize: 10,
|
||||
update_checking: { backend_setting: 'default' },
|
||||
},
|
||||
user: {},
|
||||
permissions: [],
|
||||
})
|
||||
}),
|
||||
tap((uisettings) => {
|
||||
Object.assign(this.settings, uisettings.settings)
|
||||
if (this.get(SETTINGS_KEYS.APP_TITLE)?.length) {
|
||||
|
||||
@@ -39,6 +39,12 @@ describe('TasksService', () => {
|
||||
expect(req.request.method).toEqual('GET')
|
||||
})
|
||||
|
||||
it('does not call tasks api endpoint on reload if already loading', () => {
|
||||
tasksService.loading = true
|
||||
tasksService.reload()
|
||||
httpTestingController.expectNone(`${environment.apiBaseUrl}tasks/`)
|
||||
})
|
||||
|
||||
it('calls acknowledge_tasks api endpoint on dismiss and reloads', () => {
|
||||
tasksService.dismissTasks(new Set([1, 2, 3]))
|
||||
const req = httpTestingController.expectOne(
|
||||
|
||||
@@ -50,6 +50,7 @@ export class TasksService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
public reload() {
|
||||
if (this.loading) return
|
||||
this.loading = true
|
||||
|
||||
this.http
|
||||
|
||||
@@ -53,7 +53,7 @@ export class UploadDocumentsService {
|
||||
)
|
||||
status.message = $localize`Uploading...`
|
||||
} else if (event.type == HttpEventType.Response) {
|
||||
status.taskId = event.body['task_id']
|
||||
status.taskId = event.body['task_id'] ?? event.body.toString()
|
||||
status.message = $localize`Upload complete, waiting...`
|
||||
this.uploadSubscriptions[file.name]?.complete()
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ export const environment = {
|
||||
apiBaseUrl: document.baseURI + 'api/',
|
||||
apiVersion: '5',
|
||||
appTitle: 'Paperless-ngx',
|
||||
version: '2.11.0',
|
||||
version: '2.11.4',
|
||||
webSocketHost: window.location.host,
|
||||
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
|
||||
webSocketBaseUrl: base_url.pathname + 'ws/',
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -130,7 +130,7 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='htt
|
||||
.btn-outline-secondary {
|
||||
&:hover, &:focus, &.active, &:active {
|
||||
background-color: var(--pngx-bg-darker);
|
||||
color: var(--bs-primary);
|
||||
color: var(--pngx-body-color-accent) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='htt
|
||||
}
|
||||
|
||||
.search-container {
|
||||
input, input:focus {
|
||||
color: var(--bs-body-color) !important;
|
||||
input, input:focus, i-bs[name="search"] , ::placeholder {
|
||||
color: var(--pngx-primary-text-contrast) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,9 @@ class ConsumerError(Exception):
|
||||
|
||||
class ConsumerStatusShortMessage(str, Enum):
|
||||
DOCUMENT_ALREADY_EXISTS = "document_already_exists"
|
||||
DOCUMENT_ALREADY_EXISTS_IN_TRASH = "document_already_exists_in_trash"
|
||||
ASN_ALREADY_EXISTS = "asn_already_exists"
|
||||
ASN_ALREADY_EXISTS_IN_TRASH = "asn_already_exists_in_trash"
|
||||
ASN_RANGE = "asn_value_out_of_range"
|
||||
FILE_NOT_FOUND = "file_not_found"
|
||||
PRE_CONSUME_SCRIPT_NOT_FOUND = "pre_consume_script_not_found"
|
||||
@@ -317,16 +319,22 @@ class ConsumerPlugin(
|
||||
"""
|
||||
with open(self.input_doc.original_file, "rb") as f:
|
||||
checksum = hashlib.md5(f.read()).hexdigest()
|
||||
existing_doc = Document.objects.filter(
|
||||
existing_doc = Document.global_objects.filter(
|
||||
Q(checksum=checksum) | Q(archive_checksum=checksum),
|
||||
)
|
||||
if existing_doc.exists():
|
||||
msg = ConsumerStatusShortMessage.DOCUMENT_ALREADY_EXISTS
|
||||
log_msg = f"Not consuming {self.filename}: It is a duplicate of {existing_doc.get().title} (#{existing_doc.get().pk})."
|
||||
|
||||
if existing_doc.first().deleted_at is not None:
|
||||
msg = ConsumerStatusShortMessage.DOCUMENT_ALREADY_EXISTS_IN_TRASH
|
||||
log_msg += " Note: existing document is in the trash."
|
||||
|
||||
if settings.CONSUMER_DELETE_DUPLICATES:
|
||||
os.unlink(self.input_doc.original_file)
|
||||
self._fail(
|
||||
ConsumerStatusShortMessage.DOCUMENT_ALREADY_EXISTS,
|
||||
f"Not consuming {self.filename}: It is a duplicate of"
|
||||
f" {existing_doc.get().title} (#{existing_doc.get().pk})",
|
||||
msg,
|
||||
log_msg,
|
||||
)
|
||||
|
||||
def pre_check_directories(self):
|
||||
@@ -358,12 +366,20 @@ class ConsumerPlugin(
|
||||
f"[{Document.ARCHIVE_SERIAL_NUMBER_MIN:,}, "
|
||||
f"{Document.ARCHIVE_SERIAL_NUMBER_MAX:,}]",
|
||||
)
|
||||
if Document.global_objects.filter(
|
||||
existing_asn_doc = Document.global_objects.filter(
|
||||
archive_serial_number=self.metadata.asn,
|
||||
).exists():
|
||||
)
|
||||
if existing_asn_doc.exists():
|
||||
msg = ConsumerStatusShortMessage.ASN_ALREADY_EXISTS
|
||||
log_msg = f"Not consuming {self.filename}: Given ASN {self.metadata.asn} already exists!"
|
||||
|
||||
if existing_asn_doc.first().deleted_at is not None:
|
||||
msg = ConsumerStatusShortMessage.ASN_ALREADY_EXISTS_IN_TRASH
|
||||
log_msg += " Note: existing document is in the trash."
|
||||
|
||||
self._fail(
|
||||
ConsumerStatusShortMessage.ASN_ALREADY_EXISTS,
|
||||
f"Not consuming {self.filename}: Given ASN {self.metadata.asn} already exists!",
|
||||
msg,
|
||||
log_msg,
|
||||
)
|
||||
|
||||
def run_pre_consume_script(self):
|
||||
@@ -450,6 +466,9 @@ class ConsumerPlugin(
|
||||
"document-thumb",
|
||||
kwargs={"pk": document.pk},
|
||||
)
|
||||
script_env["DOCUMENT_OWNER"] = (
|
||||
document.owner.get_username() if document.owner else ""
|
||||
)
|
||||
script_env["DOCUMENT_CORRESPONDENT"] = str(document.correspondent)
|
||||
script_env["DOCUMENT_TAGS"] = str(
|
||||
",".join(document.tags.all().values_list("name", flat=True)),
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
# Generated by Django 4.2.13 on 2024-06-28 17:52
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
("documents", "0004_auto_20160114_1844"),
|
||||
("documents", "0005_auto_20160123_0313"),
|
||||
("documents", "0006_auto_20160123_0430"),
|
||||
("documents", "0007_auto_20160126_2114"),
|
||||
("documents", "0008_document_file_type"),
|
||||
("documents", "0009_auto_20160214_0040"),
|
||||
("documents", "0010_log"),
|
||||
("documents", "0011_auto_20160303_1929"),
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
("documents", "0003_sender"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="document",
|
||||
name="sender",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="documents",
|
||||
to="documents.sender",
|
||||
),
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name="sender",
|
||||
options={"ordering": ("name",)},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Tag",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=128, unique=True)),
|
||||
("slug", models.SlugField(blank=True)),
|
||||
(
|
||||
"colour",
|
||||
models.PositiveIntegerField(
|
||||
choices=[
|
||||
(1, "#a6cee3"),
|
||||
(2, "#1f78b4"),
|
||||
(3, "#b2df8a"),
|
||||
(4, "#33a02c"),
|
||||
(5, "#fb9a99"),
|
||||
(6, "#e31a1c"),
|
||||
(7, "#fdbf6f"),
|
||||
(8, "#ff7f00"),
|
||||
(9, "#cab2d6"),
|
||||
(10, "#6a3d9a"),
|
||||
(11, "#b15928"),
|
||||
(12, "#000000"),
|
||||
(13, "#cccccc"),
|
||||
],
|
||||
default=1,
|
||||
),
|
||||
),
|
||||
("match", models.CharField(blank=True, max_length=256)),
|
||||
(
|
||||
"matching_algorithm",
|
||||
models.PositiveIntegerField(
|
||||
choices=[
|
||||
(1, "Any"),
|
||||
(2, "All"),
|
||||
(3, "Literal"),
|
||||
(4, "Regular Expression"),
|
||||
],
|
||||
default=1,
|
||||
help_text='Which algorithm you want to use when matching text to the OCR\'d PDF. Here, "any" looks for any occurrence of any word provided in the PDF, while "all" requires that every word provided appear in the PDF, albeit not in the order provided. A "literal" match means that the text you enter must appear in the PDF exactly as you\'ve entered it, and "regular expression" uses a regex to match the PDF. If you don\'t know what a regex is, you probably don\'t want this option.',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="sender",
|
||||
name="slug",
|
||||
field=models.SlugField(blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="document",
|
||||
name="file_type",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("pdf", "PDF"),
|
||||
("png", "PNG"),
|
||||
("jpg", "JPG"),
|
||||
("gif", "GIF"),
|
||||
("tiff", "TIFF"),
|
||||
],
|
||||
default="pdf",
|
||||
editable=False,
|
||||
max_length=4,
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="document",
|
||||
name="tags",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name="documents",
|
||||
to="documents.tag",
|
||||
),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Log",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("group", models.UUIDField(blank=True)),
|
||||
("message", models.TextField()),
|
||||
(
|
||||
"level",
|
||||
models.PositiveIntegerField(
|
||||
choices=[
|
||||
(10, "Debugging"),
|
||||
(20, "Informational"),
|
||||
(30, "Warning"),
|
||||
(40, "Error"),
|
||||
(50, "Critical"),
|
||||
],
|
||||
default=20,
|
||||
),
|
||||
),
|
||||
(
|
||||
"component",
|
||||
models.PositiveIntegerField(
|
||||
choices=[(1, "Consumer"), (2, "Mail Fetcher")],
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("modified", models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
"ordering": ("-modified",),
|
||||
},
|
||||
),
|
||||
migrations.RenameModel(
|
||||
old_name="Sender",
|
||||
new_name="Correspondent",
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name="document",
|
||||
options={"ordering": ("correspondent", "title")},
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="document",
|
||||
old_name="sender",
|
||||
new_name="correspondent",
|
||||
),
|
||||
]
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
# Generated by Django 4.2.13 on 2024-06-28 17:57
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
("documents", "0015_add_insensitive_to_match"),
|
||||
("documents", "0016_auto_20170325_1558"),
|
||||
("documents", "0017_auto_20170512_0507"),
|
||||
("documents", "0018_auto_20170715_1712"),
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
("documents", "0014_document_checksum"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="document",
|
||||
name="checksum",
|
||||
field=models.CharField(
|
||||
editable=False,
|
||||
help_text="The checksum of the original document (before it was encrypted). We use this to prevent duplicate document imports.",
|
||||
max_length=32,
|
||||
unique=True,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="correspondent",
|
||||
name="is_insensitive",
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="tag",
|
||||
name="is_insensitive",
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="document",
|
||||
name="content",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text="The raw, text-only data of the document. This field is primarily used for searching.",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="correspondent",
|
||||
name="matching_algorithm",
|
||||
field=models.PositiveIntegerField(
|
||||
choices=[
|
||||
(1, "Any"),
|
||||
(2, "All"),
|
||||
(3, "Literal"),
|
||||
(4, "Regular Expression"),
|
||||
(5, "Fuzzy Match"),
|
||||
],
|
||||
default=1,
|
||||
help_text='Which algorithm you want to use when matching text to the OCR\'d PDF. Here, "any" looks for any occurrence of any word provided in the PDF, while "all" requires that every word provided appear in the PDF, albeit not in the order provided. A "literal" match means that the text you enter must appear in the PDF exactly as you\'ve entered it, and "regular expression" uses a regex to match the PDF. (If you don\'t know what a regex is, you probably don\'t want this option.) Finally, a "fuzzy match" looks for words or phrases that are mostly—but not exactly—the same, which can be useful for matching against documents containing imperfections that foil accurate OCR.',
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="tag",
|
||||
name="matching_algorithm",
|
||||
field=models.PositiveIntegerField(
|
||||
choices=[
|
||||
(1, "Any"),
|
||||
(2, "All"),
|
||||
(3, "Literal"),
|
||||
(4, "Regular Expression"),
|
||||
(5, "Fuzzy Match"),
|
||||
],
|
||||
default=1,
|
||||
help_text='Which algorithm you want to use when matching text to the OCR\'d PDF. Here, "any" looks for any occurrence of any word provided in the PDF, while "all" requires that every word provided appear in the PDF, albeit not in the order provided. A "literal" match means that the text you enter must appear in the PDF exactly as you\'ve entered it, and "regular expression" uses a regex to match the PDF. (If you don\'t know what a regex is, you probably don\'t want this option.) Finally, a "fuzzy match" looks for words or phrases that are mostly—but not exactly—the same, which can be useful for matching against documents containing imperfections that foil accurate OCR.',
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="document",
|
||||
name="correspondent",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="documents",
|
||||
to="documents.correspondent",
|
||||
),
|
||||
),
|
||||
]
|
||||
Loaded 100 of 129 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user