Compare commits

..

63 Commits

Author SHA1 Message Date
jonaswinkler
88042d7072 fix wording 2021-06-13 21:30:20 +02:00
jonaswinkler
bf92e52d5c update dependencies 2021-06-13 21:21:56 +02:00
jonaswinkler
419580b3be changelog, versions 2021-06-13 19:17:29 +02:00
jonaswinkler
5ee1f6b82b Merge branch 'normalize-whitespace' into dev 2021-06-13 19:06:08 +02:00
Michael Lynch
410bb6a84e Fix trailing newlines in configuration.rst 2021-06-13 10:57:58 -04:00
Michael Lynch
af2b5fef13 Add checkout step to whitespace CI job 2021-06-13 10:57:40 -04:00
Michael Lynch
372ac3a40c Normalize whitespace in source files
Ensure that no source files have trailing whitespace at end of lines and ensure that all files end with a single trailing newline.

This also adds Github Actions to enforce whitespace conventions.
2021-06-13 10:57:40 -04:00
jonaswinkler
a1507d6079 update django-q 2021-06-13 16:36:05 +02:00
jonaswinkler
9242a8901a update django-q 2021-06-13 15:43:32 +02:00
jonaswinkler
1d4f25f930 update datepipe implementation due to interface change 2021-06-13 15:27:04 +02:00
jonaswinkler
7323ec8d16 update angular devkit 2021-06-13 15:18:23 +02:00
jonaswinkler
39d45367d0 replace ng-bootstrap with ngx-bootstrap 2021-06-13 15:12:56 +02:00
jonaswinkler
a6521952b0 update to Angular 11 2021-06-13 15:08:56 +02:00
jonaswinkler
7148c10f1b update docker entrypoint 2021-06-13 12:54:24 +02:00
jonaswinkler
4a1a66248d update requirements.txt 2021-06-13 12:40:28 +02:00
Jonas Winkler
67d0773231 Merge pull request #933 from sbrunner/suggest
Add suggest
2021-06-13 12:20:34 +02:00
jonaswinkler
ff370172b5 fix pycodestyle 2021-06-13 12:18:21 +02:00
jonaswinkler
1f707e86cc fix logging getting spammed with pdfminer warnings on JPG files 2021-06-13 12:09:16 +02:00
jonaswinkler
a3dae02cfb write classifier model to temporary file before copying to final location 2021-06-13 12:03:20 +02:00
jonaswinkler
3eae8a2210 update dependencies 2021-06-13 12:02:49 +02:00
Jonas Winkler
0f18fe1853 Merge pull request #1107 from MJWcodr/patch-1
Update setup.rst
2021-06-13 11:34:03 +02:00
Jonas Winkler
513c61eb79 Merge pull request #1113 from magnetic6/master
Document specification of the expected creation date order
2021-06-13 11:33:43 +02:00
Peter M
4031233fd4 Document specification of the expected creation date order 2021-06-12 10:15:51 -04:00
Matthias J. Wünsch
76ff6100a3 Update setup.rst 2021-06-09 16:46:53 +02:00
Jonas Winkler
05c36f91cf Merge pull request #1105 from mtlynch/single-install-cmd
Simplify installation command
2021-06-07 00:48:29 +02:00
Michael Lynch
6625f8962a Simplify installation command
The installation for docker is currently three separate commands, but it can be a single command if the user simply pipes to the sh interpreter directly. I know there are some who object to piping to sh from a URL, but the current method has no security benefit over piping directly to sh.
2021-06-06 18:02:23 -04:00
Jonas Winkler
63402b70d2 Merge pull request #1057 from muued/patch-6
adjust ansible README to installation instructions
2021-06-03 15:14:36 +02:00
Stéphane Brunner
2ae4a7806d Add suggest 2021-05-30 14:50:29 +02:00
Jonas Winkler
fcc4ecd007 Merge pull request #1068 from servusoft/dev
Solving issue with search criteria 'maximum age' for some mail server
2021-05-29 19:13:10 +02:00
Jonas Winkler
45497250cd Merge pull request #1074 from sbrunner/scan-to-paperless
Add Scan to Paperless as affiliated project
2021-05-29 19:12:46 +02:00
Stéphane Brunner
7dd957140e Add Scan to Paperless as affiliated project 2021-05-29 16:38:16 +02:00
servusoft
4cd772a39e Solving issue with search criteria maximum age for some mail server
Some mail servers (mail.ru) do not support search criteria for the maximum age. By setting the maximum age to 0, it is possible to hide the search criteria. This PR solves that problem.
2021-05-27 18:30:57 +02:00
Fabian Ohler
10bf9fd1f8 Adjusted paperlessng_version variable explanation 2021-05-26 08:30:17 +02:00
Jonas Winkler
bd8e68692e New translations django.po (Dutch) (#1048) 2021-05-25 00:01:38 +02:00
Jonas Winkler
b8386a1531 Merge pull request #1052 from muued/patch-5
Use ansible-galaxy during updates
2021-05-25 00:01:20 +02:00
Fabian Ohler
61534fb29d Apply suggestions from code review
Co-authored-by: Fabian Koller <C0nsultant@users.noreply.github.com>
2021-05-24 15:27:11 +02:00
Fabian Ohler
9ad81be38c adjust ansible README to installation instructions
and fix some typos
2021-05-24 15:10:41 +02:00
Fabian Ohler
cf7048e336 Use ansible-galaxy during updates
This mechanism is already used for the installation process.
2021-05-22 23:29:44 +02:00
jonaswinkler
a6105b3ad3 update frontend dependencies 2021-05-21 15:27:10 +02:00
jonaswinkler
a262a82cad Merge branch 'dev' of github.com:jonaswinkler/paperless-ng into dev 2021-05-19 23:11:43 +02:00
jonaswinkler
635c96accf better exception handling 2021-05-19 23:11:24 +02:00
Jonas Winkler
5c174a69c2 New Crowdin updates (#1043) 2021-05-19 23:00:51 +02:00
jonaswinkler
de08d17835 changelog 2021-05-19 23:00:03 +02:00
jonaswinkler
ca1e838c52 catch another exception regarding classifier loading 2021-05-19 22:57:52 +02:00
jonaswinkler
3b73146ecd changelog and version bump 2021-05-19 22:40:56 +02:00
jonaswinkler
8e3822f8e6 Merge remote-tracking branch 'origin/master' into dev 2021-05-19 22:37:01 +02:00
jonaswinkler
3b912a0de1 improved docker startup time 2021-05-19 22:26:51 +02:00
jonaswinkler
c72791bd21 Fix file permissions 2021-05-19 22:05:23 +02:00
jonaswinkler
80ba5b561f codestyle 2021-05-19 20:26:12 +02:00
jonaswinkler
f9f4d4c937 Merge branch 'dev' of github.com:jonaswinkler/paperless-ng into dev 2021-05-19 20:03:05 +02:00
jonaswinkler
0419c52d35 fix file permissions 2021-05-19 20:02:56 +02:00
jonaswinkler
93a79be1e2 delete macOS specific files 2021-05-19 20:02:47 +02:00
jonaswinkler
f8afbae2cd ignore macOS specific files 2021-05-19 19:56:01 +02:00
jonaswinkler
4a52d346f9 remove dead code 2021-05-19 19:55:35 +02:00
Jonas Winkler
7d59d11725 New Crowdin updates (#1026) 2021-05-18 14:46:12 +02:00
Jonas Winkler
5886348188 Merge pull request #1034 from steviehs/patch-1
Update setup.rst
2021-05-18 14:45:52 +02:00
steviehs
a8135528b1 Update setup.rst
Added hint to upgrade pip first.
2021-05-17 09:07:31 +02:00
jonaswinkler
df6b991161 File permissions 2021-05-16 23:01:41 +02:00
Jonas Winkler
3f33f66387 New Crowdin updates (#1023) 2021-05-16 13:13:54 +02:00
jonaswinkler
870808f3c2 add support for configuring mail server character set per server. fixes #548 2021-05-16 11:58:32 +02:00
Jonas Winkler
b12fcca20d Merge remote-tracking branch 'origin/dev' into dev 2021-05-16 01:23:07 +02:00
Jonas Winkler
61b47e358f correct file mode 2021-05-16 01:22:51 +02:00
Jonas Winkler
40a2fb7936 New Crowdin updates (#1022) 2021-05-15 21:14:03 +02:00
127 changed files with 23484 additions and 6185 deletions

2
.env
View File

@@ -1 +1 @@
COMPOSE_PROJECT_NAME=paperless
COMPOSE_PROJECT_NAME=paperless

View File

@@ -0,0 +1,37 @@
#!/bin/bash
# Verify that all text files end in a trailing newline.
# Exit on first failing command.
set -e
# Exit on unset variable.
set -u
success=0
function is_plaintext_file() {
local file="$1"
if [[ $file == *.svg ]]; then
echo ""
return
fi
file --brief "${file}" | grep text
}
# Split strings on newlines.
IFS='
'
for file in $(git ls-files)
do
if [[ -z $(is_plaintext_file "${file}") ]]; then
continue
fi
if ! [[ -z "$(tail -c 1 "${file}")" ]]; then
printf "File must end in a trailing newline: %s\n" "${file}" >&2
success=255
fi
done
exit "${success}"

View File

@@ -0,0 +1,26 @@
#!/bin/bash
# Check for trailing whitespace at end of lines.
# Exit on first failing command.
set -e
# Exit on unset variable.
set -u
FOUND_TRAILING_WHITESPACE=0
while read -r line; do
if grep \
"\s$" \
--line-number \
--with-filename \
--binary-files=without-match \
--exclude="*.svg" \
--exclude="*.eps" \
"${line}"; then
echo "ERROR: Found trailing whitespace" >&2;
FOUND_TRAILING_WHITESPACE=1
fi
done < <(git ls-files)
exit "${FOUND_TRAILING_WHITESPACE}"

View File

@@ -81,6 +81,20 @@ jobs:
run: |
cd src/
pycodestyle
whitespace:
runs-on: ubuntu-20.04
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Ensure there are no trailing spaces
run: |
.github/workflow-scripts/check-trailing-whitespace
-
name: Ensure all text files end with a trailing newline
run: |
.github/workflow-scripts/check-trailing-whitespace
tests:
runs-on: ubuntu-20.04
@@ -158,7 +172,7 @@ jobs:
path: src/documents/static/frontend/
build-release:
needs: [frontend, documentation, tests, codestyle]
needs: [frontend, documentation, tests, whitespace, codestyle]
runs-on: ubuntu-20.04
steps:
-
@@ -268,7 +282,7 @@ jobs:
build-docker-image:
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/ng-'))
runs-on: ubuntu-latest
needs: [frontend, tests, codestyle]
needs: [frontend, tests, whitespace, codestyle]
steps:
-
name: Prepare

View File

@@ -14,7 +14,7 @@ django = "~=3.2"
django-cors-headers = "*"
django-extensions = "*"
django-filter = "~=2.4.0"
django-q = "==1.3.4"
django-q = "~=1.3.4"
djangorestframework = "~=3.12.2"
filelock = "*"
fuzzywuzzy = {extras = ["speedup"], version = "*"}

383
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "2da6572956d27205c496da2ef5f584a9ba53b5f6b3c8bf1724211dc48bfac7b7"
"sha256": "deaa52fcf234236357749005f429cea100e817c694d8f383d931236e02e8bab0"
},
"pipfile-spec": 6,
"requires": {},
@@ -83,22 +83,31 @@
},
"certifi": {
"hashes": [
"sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
"sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
"sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee",
"sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"
],
"version": "==2020.12.5"
"version": "==2021.5.30"
},
"cffi": {
"hashes": [
"sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
"sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
"sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
"sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
"sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
"sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
"sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
"sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
"sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
"sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
"sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
"sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
"sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
"sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
"sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
"sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
"sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
"sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
"sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
"sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
"sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
@@ -107,6 +116,7 @@
"sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
"sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
"sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
"sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
"sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
"sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
"sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
@@ -125,8 +135,10 @@
"sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
"sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
"sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
"sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
"sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
"sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
"sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
"sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
"sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
],
@@ -158,20 +170,19 @@
},
"click": {
"hashes": [
"sha256:a3747c864f8e400a3664f5f4fd6dae11b4605bf6b727dae7b6f22ba9bd0a194a",
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
"sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"
"sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
"sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==7.1.2"
"markers": "python_version >= '3.6'",
"version": "==8.0.1"
},
"coloredlogs": {
"hashes": [
"sha256:5e78691e2673a8e294499e1832bb13efcfb44a86b92e18109fa18951093218ab",
"sha256:b7f630a8297a66984b6bae0f6a1b0e0afb9f2f6838ea3bfa58f50d3d13e133d6"
"sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934",
"sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==15.0"
"version": "==15.0.1"
},
"concurrent-log-handler": {
"hashes": [
@@ -225,11 +236,11 @@
},
"django": {
"hashes": [
"sha256:13ac78dbfd189532cad8f383a27e58e18b3d33f80009ceb476d7fcbfc5dcebd8",
"sha256:7e0a1393d18c16b503663752a8b6790880c5084412618990ce8a81cc908b4962"
"sha256:66c9d8db8cc6fe938a28b7887c1596e42d522e27618562517cc8929eb7e7f296",
"sha256:ea735cbbbb3b2fba6d4da4784a0043d84c67c92f1fdf15ad6db69900e792c10f"
],
"index": "pypi",
"version": "==3.2.3"
"version": "==3.2.4"
},
"django-cors-headers": {
"hashes": [
@@ -265,11 +276,11 @@
},
"django-q": {
"hashes": [
"sha256:523d54dcf1b66152c1b658f914f00ed3b518a3432a9decd4898738ca8dbbe10f",
"sha256:7e5c5c021a15cff6807044a3aa48f5757789ccfef839d71c575f5512931a3e33"
"sha256:681c7e91c58322d0a4ea6d5fa8df21e6e785123fd6ee7c86af201e6a1c08ddc1",
"sha256:db30266fadd6ab9336a8824291910ff1d1c28f7bc9d6e52cdaf33cc275ae6146"
],
"index": "pypi",
"version": "==1.3.4"
"version": "==1.3.8"
},
"djangorestframework": {
"hashes": [
@@ -365,33 +376,32 @@
},
"httptools": {
"hashes": [
"sha256:07659649fe6b3948b6490825f89abe5eb1cec79ebfaaa0b4bf30f3f33f3c2ba8",
"sha256:08b79e09114e6ab5c3dbf560bba2cb2257ea38cdaeaf99b7cb80d8f92622fcd9",
"sha256:1e35aa179b67086cc600a984924a88589b90793c9c1b260152ca4908786e09df",
"sha256:31629e1f1b89959f8c0927bad12184dc07977dcf71e24f4772934aa490aa199b",
"sha256:7792e70ead1d220142a99dde049fdbeddc66fe822953e085d02cd5155c38cdad",
"sha256:851026bd63ec0af7e7592890d97d15c92b62d9e17094353f19a52c8e2b33710a",
"sha256:8fcca4b7efe353b13a24017211334c57d055a6e132c7adffed13a10d28efca57",
"sha256:9abd788465aa46a0f288bd3a99e53edd184177d6379e2098fd6097bb359ad9d6",
"sha256:aebdf0bd7bf7c90ae6b3be458692bf6e9e5b610b501f9f74c7979015a51db4c4",
"sha256:bda99a5723e7eab355ce57435c70853fc137a65aebf2f1cd4d15d96e2956da7b",
"sha256:c1c63d860749841024951b0a78e4dec6f543d23751ef061d6ab60064c7b8b524",
"sha256:c4111a0a8a00eff1e495d43ea5230aaf64968a48ddba8ea2d5f982efae827404",
"sha256:dce59ee45dd6ee6c434346a5ac527c44014326f560866b4b2f414a692ee1aca8",
"sha256:f759717ca1b2ef498c67ba4169c2b33eecf943a89f5329abcff8b89d153eb500",
"sha256:f9545ff74bdf8a6e013ed18af3e24c656c06b6ca2441074be2f6cc28e24f48de",
"sha256:fb7199b8fb0c50a22e77260bb59017e0c075fa80cb03bb2c8692de76e7bb7fe7",
"sha256:fbf7ecd31c39728f251b1c095fd27c84e4d21f60a1d079a0333472ff3ae59d34"
"sha256:01b392a166adcc8bc2f526a939a8aabf89fe079243e1543fd0e7dc1b58d737cb",
"sha256:200fc1cdf733a9ff554c0bb97a4047785cfaad9875307d6087001db3eb2b417f",
"sha256:3ab1f390d8867f74b3b5ee2a7ecc9b8d7f53750bd45714bf1cb72a953d7dfa77",
"sha256:78d03dd39b09c99ec917d50189e6743adbfd18c15d5944392d2eabda688bf149",
"sha256:79dbc21f3612a78b28384e989b21872e2e3cf3968532601544696e4ed0007ce5",
"sha256:80ffa04fe8c8dfacf6e4cef8277347d35b0442c581f5814f3b0cf41b65c43c6e",
"sha256:813871f961edea6cb2fe312f2d9b27d12a51ba92545380126f80d0de1917ea15",
"sha256:94505026be56652d7a530ab03d89474dc6021019d6b8682281977163b3471ea0",
"sha256:a23166e5ae2775709cf4f7ad4c2048755ebfb272767d244e1a96d55ac775cca7",
"sha256:a289c27ccae399a70eacf32df9a44059ca2ba4ac444604b00a19a6c1f0809943",
"sha256:a7594f9a010cdf1e16a58b3bf26c9da39bbf663e3b8d46d39176999d71816658",
"sha256:b08d00d889a118f68f37f3c43e359aab24ee29eb2e3fe96d64c6a2ba8b9d6557",
"sha256:cc9be041e428c10f8b6ab358c6b393648f9457094e1dcc11b4906026d43cd380",
"sha256:d5682eeb10cca0606c4a8286a3391d4c3c5a36f0c448e71b8bd05be4e1694bfb",
"sha256:dd38cad4599d58c23c01bca2102dcce30d61f6466328169bb17efb8a528f4d97",
"sha256:fd3b8905e21431ad306eeaf56644a68fdd621bf8f3097eff54d0f6bdf7262065"
],
"version": "==0.1.2"
"version": "==0.2.0"
},
"humanfriendly": {
"hashes": [
"sha256:066562956639ab21ff2676d1fda0b5987e985c534fc76700a19bd54bcb81121d",
"sha256:d5c731705114b9ad673754f3317d9fa4c23212f36b29bdc4272a892eafc9bc72"
"sha256:332da98c24cc150efcc91b5508b19115209272bfdf4b0764a56795932f854271",
"sha256:f7dba53ac7935fd0b4a2fc9a29e316ddd9ea135fb3052d3d0279d10c18ff9c48"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==9.1"
"version": "==9.2"
},
"hyperlink": {
"hashes": [
@@ -596,11 +606,11 @@
},
"ocrmypdf": {
"hashes": [
"sha256:3a757ac8bc4f822052a363c7fdc1e01e01033ae3e3398123990813eb6b3cf031",
"sha256:c18db17e18984f540eaa774245571e3ec63a74f459b6029de561a06a77e78310"
"sha256:17396579734b4a2e7b8e100a8a2f38a01a83adb949e2c87edd9e5433f8eb6932",
"sha256:60079df8a0407e30b66b2828ffbf802bb8342d1198db41c27e4e2ef63efb06c3"
],
"index": "pypi",
"version": "==12.0.1"
"version": "==12.0.3"
},
"pathvalidate": {
"hashes": [
@@ -620,32 +630,34 @@
},
"pikepdf": {
"hashes": [
"sha256:087dc8e141dcfa0e76e93227a22f6b9cee000b3837b9e048ba96f389d0ee5d41",
"sha256:1bcf4e45a831b302a0b6ae6cbd41aa6c81f95964b1d61e8da41186a4a779f701",
"sha256:22d6615e742e7320a3a77148f65a8ba3591c054133faf6305a525c439b57cf38",
"sha256:24d51dcc2d73e5d123acab4fef5d611f545ff2ce16c837d85833364d4d2cda45",
"sha256:26a3af4845db89f364d18757978fad39ea852b6e7cae3137000a07c44d292b42",
"sha256:36e9d557ef0505a6ec335faf9b2c93d4d062daa339dd1a6cbcda2a6dc886b38e",
"sha256:417abdc29be8ddedabeb100a728b6525c5e1967ba47a03b9e0a81391efb4feb1",
"sha256:5e71dcefdd889538a289cdaa2bb4559e4477e3f17846ffbdfad54b0e76443cf5",
"sha256:62a6f2e2552bfd1bcd17b5e0e024db9ab7e93db39f43bb4246faff9b01154d47",
"sha256:7a054701104c601d72b5ab8b3025a44b1b400f334ee7259dbd4bb1a2c24dad03",
"sha256:7dcf6545c7deb2f6511a3b9220d56297b4165eeedc2eab785acba698cc9d95c0",
"sha256:82da7b5d5a57e4704f7a81e75324b07b19577a96e06f5c5d8a89b29dec814766",
"sha256:8cdafd18013b17f257655e95bfcb4ef14a7fc84a7334a9877b0532db4b55e3ff",
"sha256:a0ff0291f74ef45dd2a1e1316b7d6464b996351365debbf611a5293cf2ff2562",
"sha256:a2ef88f786aed79da559cd1a6a844f99e258971d64670bfba1efad96ed175fb0",
"sha256:a84bbc7b3f9819c1541913bac2781da40d9506255c1cedb7233f9027ce23db92",
"sha256:b1e0cfb6f5abe4d4863c55b2c9424340e5b44095789ef1368a0de99f8b4f852e",
"sha256:ca8efe77f1f44d3c1c0d738407b87816f1445438aa6873d45e58fdd595e96c98",
"sha256:d0f48252f23c128a3ddde16d98fa6567ac7fbce6792209771183b57c744106e1",
"sha256:e1d988ddf063d6abf3d71e7c5bc46e5690fdcf0b06d7f00fced5d0b908f92267",
"sha256:ec9d853c895693dd55b12ae37056808e192e5e2a8d2486cb30d19a5e7d6ff6a9",
"sha256:fcbb6e37426564ccaf6bb301616700277d426225895b00a64283a95ff648f3b9",
"sha256:ff29a8bd50f47554be7e062b3e1a2b466a7f567e1e49417dc62c3948b28304c7"
"sha256:230f98284ae025e641472b5c23d83af3964717ef0fac79a072d05e12212d99f6",
"sha256:23aff2408c169aff7f2453cc807b39427634df4fdbcc1217ff11e62984321772",
"sha256:279cb9786c4757c36fa356214b012f766f3cfc834c6e2c6f661cd7fd1221fac7",
"sha256:2bd8509ca04cfe3fa5c9ad17730eb43addd1b8f81604945c89f666ac3768fc19",
"sha256:311e92958a75d8d73064b1ee1f280572aee03d03ee103ef77e989cc255acf2e9",
"sha256:41e637ce69776990a0a170099000282cbcf7de94ab39a0194677366d923ff48d",
"sha256:4a17030087da78287f3f18f90e4364b20cd1f3a8d511e5cc33171f9262d7dd6c",
"sha256:4ee74e9b9277ae5327c8b19504b66eaa9a725fa4a6b2a23d161d3b2696f6c2e6",
"sha256:59e7c6004d5eafff6d31d8185c5df6b8a2c3c7114c1d194edee520a9b608f09b",
"sha256:5ff35499b1ae7b181277f78ce5b1bcc8d3009182bb389917791c5dc811fcc8e4",
"sha256:60c1d6634e4b66636d731bee3615aa153a877983a499d3c5506f87c033a6d913",
"sha256:77363eb0afcf7a8b8fe3aa9c3391cc12ad40e7e6be55a0b10b72bf70be6b2cbc",
"sha256:838a386836c5d773029f04628ddab7131f6f7cfa3147382bf2a440143f4ef513",
"sha256:9ad09d00186f172f247983d63f60d0572e1fb87b0ae30e3d504de451b8da8889",
"sha256:9c885328d86d919b70decd3ef73ce42d76ab4b365ed3a851aef08e3f29e62c6e",
"sha256:a25a12f2209a0378c57a8201c4add521ebb7cadd439e111cddb1532d347f0cd0",
"sha256:a28e3472915d4881492ba6264f8db8ef3a4f382048dda307de5aa88a43b626d7",
"sha256:b3ccde9aa84fd9663ecf3f39226372bc2c5311e9fabbab07955439c0deb1ecfa",
"sha256:bbaafc08dd77c2e64a87dd6e377e4e8a7efd9a6d7de208ed8c5b908830465887",
"sha256:c039ee6dcbf3f2054b8bddbff9f5002996d0d981d3d82ebe76041c237528aaef",
"sha256:cee7a310e82e0a931b4805a1b25288efcb3f647f4d32c4107889a4b3fac4f159",
"sha256:d245513995e0fe1e849fbb10e14061c229c59db9f8e346bfef4f2bf804847574",
"sha256:db1f2a4b8fb4b91bf43ce8988f2f9d18ea36dbf7919d60a860e3fa68e1955a7e",
"sha256:fb08ce0ec36c8571b167d9cd0fdad7b53b2f535cbd32c1e92f6f2883c353be7e",
"sha256:fb0e1ceabaad4815efe23d1e19beaba33db38cf1e918011cd602cc0a43185056"
],
"index": "pypi",
"version": "==2.12.0"
"version": "==2.12.2"
},
"pillow": {
"hashes": [
@@ -668,6 +680,7 @@
"sha256:63728564c1410d99e6d1ae8e3b810fe012bc440952168af0a2877e8ff5ab96b9",
"sha256:66cc56579fd91f517290ab02c51e3a80f581aba45fd924fcdee01fa06e635812",
"sha256:6c32cc3145928c4305d142ebec682419a6c0a8ce9e33db900027ddca1ec39178",
"sha256:8b56553c0345ad6dcb2e9b433ae47d67f95fc23fe28a0bde15a120f25257e291",
"sha256:8bb1e155a74e1bfbacd84555ea62fa21c58e0b4e7e6b20e4447b8d07990ac78b",
"sha256:95d5ef984eff897850f3a83883363da64aae1000e79cb3c321915468e8c6add5",
"sha256:a013cbe25d20c2e0c4e85a9daf438f85121a4d0344ddc76e33fd7e3965d9af4b",
@@ -832,11 +845,11 @@
},
"python-magic": {
"hashes": [
"sha256:8551e804c09a3398790bd9e392acb26554ae2609f29c72abb0b9dee9a5571eae",
"sha256:ca884349f2c92ce830e3f498c5b7c7051fe2942c3ee4332f65213b8ebff15a62"
"sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626",
"sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf"
],
"index": "pypi",
"version": "==0.4.22"
"version": "==0.4.24"
},
"pytz": {
"hashes": [
@@ -1062,10 +1075,10 @@
},
"sortedcontainers": {
"hashes": [
"sha256:37257a32add0a3ee490bb170b599e93095eed89a55da91fa9f48753ea12fd73f",
"sha256:59cc937650cf60d677c16775597c89a960658a09cf7c1a668f86e1e4464b10a1"
"sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88",
"sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"
],
"version": "==2.3.0"
"version": "==2.4.0"
},
"sqlparse": {
"hashes": [
@@ -1093,11 +1106,11 @@
},
"tqdm": {
"hashes": [
"sha256:daec693491c52e9498632dfbe9ccfc4882a557f5fa08982db1b4d3adbe0887c3",
"sha256:ebdebdb95e3477ceea267decfc0784859aa3df3e27e22d23b83e9b272bf157ae"
"sha256:24be966933e942be5f074c29755a95b315c69a91f839a29139bf26ffffe2d3fd",
"sha256:aa0c29f03f298951ac6318f7c8ce584e48fa22ec26396e6411e43d038243bdb2"
],
"index": "pypi",
"version": "==4.60.0"
"version": "==4.61.1"
},
"twisted": {
"extras": [
@@ -1127,22 +1140,22 @@
},
"urllib3": {
"hashes": [
"sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df",
"sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"
"sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c",
"sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
"version": "==1.26.4"
"version": "==1.26.5"
},
"uvicorn": {
"extras": [
"standard"
],
"hashes": [
"sha256:3292251b3c7978e8e4a7868f4baf7f7f7bb7e40c759ecc125c37e99cdea34202",
"sha256:7587f7b08bd1efd2b9bad809a3d333e972f1d11af8a5e52a9371ee3a5de71524"
"sha256:2a76bb359171a504b3d1c853409af3adbfa5cef374a4a59e5881945a97a93eae",
"sha256:45ad7dfaaa7d55cab4cd1e85e03f27e9d60bc067ddc59db52a2b0aeca8870292"
],
"index": "pypi",
"version": "==0.13.4"
"version": "==0.14.0"
},
"uvloop": {
"hashes": [
@@ -1200,31 +1213,42 @@
},
"websockets": {
"hashes": [
"sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5",
"sha256:1d3f1bf059d04a4e0eb4985a887d49195e15ebabc42364f4eb564b1d065793f5",
"sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308",
"sha256:295359a2cc78736737dd88c343cd0747546b2174b5e1adc223824bcaf3e164cb",
"sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a",
"sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c",
"sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170",
"sha256:3ef56fcc7b1ff90de46ccd5a687bbd13a3180132268c4254fc0fa44ecf4fc422",
"sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8",
"sha256:5c01fd846263a75bc8a2b9542606927cfad57e7282965d96b93c387622487485",
"sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f",
"sha256:745a1c8ca62f7d27de42b517ca7c6f716d1eb96c5aa73cf6407936c0167cbb3c",
"sha256:751a556205d8245ff94aeef23546a1113b1dd4f6e4d102ded66c39b99c2ce6c8",
"sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc",
"sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779",
"sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989",
"sha256:9bef37ee224e104a413f0780e29adb3e514a5b698aabe0d969a6ba426b8435d1",
"sha256:c1ec8db4fac31850286b7cd3b9c0e1b944204668b8eb721674916d4e28744092",
"sha256:c8a116feafdb1f84607cb3b14aa1418424ae71fee131642fc568d21423b51824",
"sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d",
"sha256:d705f8aeecdf3262379644e4b55107a3b55860eb812b673b28d0fbc347a60c55",
"sha256:e898a0863421650f0bebac8ba40840fc02258ef4714cb7e1fd76b6a6354bda36",
"sha256:f8a7bff6e8664afc4e6c28b983845c5bc14965030e3fb98789734d416af77c4b"
"sha256:0dd4eb8e0bbf365d6f652711ce21b8fd2b596f873d32aabb0fbb53ec604418cc",
"sha256:1d0971cc7251aeff955aa742ec541ee8aaea4bb2ebf0245748fbec62f744a37e",
"sha256:1d6b4fddb12ab9adf87b843cd4316c4bd602db8d5efd2fb83147f0458fe85135",
"sha256:230a3506df6b5f446fed2398e58dcaafdff12d67fe1397dff196411a9e820d02",
"sha256:276d2339ebf0df4f45df453923ebd2270b87900eda5dfd4a6b0cfa15f82111c3",
"sha256:2cf04601633a4ec176b9cc3d3e73789c037641001dbfaf7c411f89cd3e04fcaf",
"sha256:3ddff38894c7857c476feb3538dd847514379d6dc844961dc99f04b0384b1b1b",
"sha256:48c222feb3ced18f3dc61168ca18952a22fb88e5eb8902d2bf1b50faefdc34a2",
"sha256:51d04df04ed9d08077d10ccbe21e6805791b78eac49d16d30a1f1fe2e44ba0af",
"sha256:597c28f3aa7a09e8c070a86b03107094ee5cdafcc0d55f2f2eac92faac8dc67d",
"sha256:5c8f0d82ea2468282e08b0cf5307f3ad022290ed50c45d5cb7767957ca782880",
"sha256:7189e51955f9268b2bdd6cc537e0faa06f8fffda7fb386e5922c6391de51b077",
"sha256:7df3596838b2a0c07c6f6d67752c53859a54993d4f062689fdf547cb56d0f84f",
"sha256:826ccf85d4514609219725ba4a7abd569228c2c9f1968e8be05be366f68291ec",
"sha256:836d14eb53b500fd92bd5db2fc5894f7c72b634f9c2a28f546f75967503d8e25",
"sha256:85db8090ba94e22d964498a47fdd933b8875a1add6ebc514c7ac8703eb97bbf0",
"sha256:85e701a6c316b7067f1e8675c638036a796fe5116783a4c932e7eb8e305a3ffe",
"sha256:8c941af1b20971d9e98c2369bdf118ef546b2569957469a9ab1e6d76b97d675f",
"sha256:900589e19200be76dd7cbaa95e9771605b5ce3f62512d039fb3bc5da9014912a",
"sha256:9147868bb0cc01e6846606cd65cbf9c58598f187b96d14dd1ca17338b08793bb",
"sha256:9e7fdc775fe7403dbd8bc883ba59576a6232eac96dacb56512daacf7af5d618d",
"sha256:ab5ee15d3462198c794c49ccd31773d8a2b8c17d622aa184f669d2b98c2f0857",
"sha256:ad893d889bc700a5835e0a95a3e4f2c39e91577ab232a3dc03c262a0f8fc4b5c",
"sha256:b2e71c4670ebe1067fa8632f0d081e47254ee2d3d409de54168b43b0ba9147e0",
"sha256:b43b13e5622c5a53ab12f3272e6f42f1ce37cd5b6684b2676cb365403295cd40",
"sha256:b4ad84b156cf50529b8ac5cc1638c2cf8680490e3fccb6121316c8c02620a2e4",
"sha256:be5fd35e99970518547edc906efab29afd392319f020c3c58b0e1a158e16ed20",
"sha256:caa68c95bc1776d3521f81eeb4d5b9438be92514ec2a79fececda814099c8314",
"sha256:d144b350045c53c8ff09aa1cfa955012dd32f00c7e0862c199edcabb1a8b32da",
"sha256:d2c2d9b24d3c65b5a02cac12cbb4e4194e590314519ed49db2f67ef561c3cf58",
"sha256:e9e5fd6dbdf95d99bc03732ded1fc8ef22ebbc05999ac7e0c7bf57fe6e4e5ae2",
"sha256:ebf459a1c069f9866d8569439c06193c586e72c9330db1390af7c6a0a32c4afd",
"sha256:f31722f1c033c198aa4a39a01905951c00bd1c74f922e8afc1b1c62adbcdd56a",
"sha256:f68c352a68e5fdf1e97288d5cec9296664c590c25932a8476224124aaf90dbcd"
],
"version": "==8.1"
"version": "==9.1"
},
"whitenoise": {
"hashes": [
@@ -1343,10 +1367,10 @@
},
"certifi": {
"hashes": [
"sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
"sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
"sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee",
"sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"
],
"version": "==2020.12.5"
"version": "==2021.5.30"
},
"chardet": {
"hashes": [
@@ -1357,9 +1381,6 @@
"version": "==4.0.0"
},
"coverage": {
"extras": [
"toml"
],
"hashes": [
"sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c",
"sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6",
@@ -1419,18 +1440,18 @@
},
"coveralls": {
"hashes": [
"sha256:7bd173b3425733661ba3063c88f180127cc2b20e9740686f86d2622b31b41385",
"sha256:cbb942ae5ef3d2b55388cb5b43e93a269544911535f1e750e1c656aef019ce60"
"sha256:172fb79c5f61c6ede60554f2cac46deff6d64ee735991fb2124fb414e188bdb4",
"sha256:9b3236e086627340bf2c95f89f757d093cbed43d17179d3f4fb568c347e7d29a"
],
"index": "pypi",
"version": "==3.0.1"
"version": "==3.1.0"
},
"distlib": {
"hashes": [
"sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb",
"sha256:edf6116872c863e1aa9d5bb7cb5e05a022c519a4594dc703843343a9ddd9bff1"
"sha256:106fef6dc37dd8c0e2c0a60d3fca3e77460a48907f335fa28420463a6f799736",
"sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c"
],
"version": "==0.3.1"
"version": "==0.3.2"
},
"docopt": {
"hashes": [
@@ -1449,11 +1470,11 @@
},
"execnet": {
"hashes": [
"sha256:7a13113028b1e1cc4c6492b28098b3c6576c9dccc7973bfe47b342afadafb2ac",
"sha256:b73c5565e517f24b62dea8a5ceac178c661c4309d3aa0c3e420856c072c411b4"
"sha256:7e3c2cdb6389542a91e9855a9cc7545fbed679e96f8808bcbb1beb325345b189",
"sha256:e840ce25562e414ee5684864d510dbeeb0bce016bc89b22a6e5ce323b5e6552f"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==1.8.0"
"version": "==1.8.1"
},
"factory-boy": {
"hashes": [
@@ -1465,11 +1486,11 @@
},
"faker": {
"hashes": [
"sha256:73562fb99b6046c5d26b8dd98a1437a896f8601c96382d835c656166159f4f59",
"sha256:c6a4a0a1dde71f16d489a3097661a87ae96329dbde4c3ece8a5ccc340441ade1"
"sha256:30189045769cb26f91ed218140469fd0b42520b2ea22ff2958ed81071a3ed839",
"sha256:a724ca2325f4af659929052fbbb613caaec237a93fcdc1cbc7aa860e61e3c18f"
],
"markers": "python_version >= '3.6'",
"version": "==8.1.4"
"version": "==8.7.0"
},
"filelock": {
"hashes": [
@@ -1506,52 +1527,52 @@
},
"jinja2": {
"hashes": [
"sha256:2f2de5285cf37f33d33ecd4a9080b75c87cd0c1994d5a9c6df17131ea1f049c6",
"sha256:ea8d7dd814ce9df6de6a761ec7f1cac98afe305b8cdc4aaae4e114b8d8ce24c5"
"sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
"sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
],
"markers": "python_version >= '3.6'",
"version": "==3.0.0"
"version": "==3.0.1"
},
"markupsafe": {
"hashes": [
"sha256:007dc055dbce5b1104876acee177dbfd18757e19d562cd440182e1f492e96b95",
"sha256:031bf79a27d1c42f69c276d6221172417b47cb4b31cdc73d362a9bf5a1889b9f",
"sha256:161d575fa49395860b75da5135162481768b11208490d5a2143ae6785123e77d",
"sha256:24bbc3507fb6dfff663af7900a631f2aca90d5a445f272db5fc84999fa5718bc",
"sha256:2efaeb1baff547063bad2b2893a8f5e9c459c4624e1a96644bbba08910ae34e0",
"sha256:31d4206caf9be06b8e7a85de4df933d159b4877d4fc308ca8192d97faf56a41e",
"sha256:32200f562daaab472921a11cbb63780f1654552ae49518196fc361ed8e12e901",
"sha256:3261fae28155e5c8634dd7710635fe540a05b58f160cef7713c7700cb9980e66",
"sha256:3b54a9c68995ef4164567e2cd1a5e16db5dac30b2a50c39c82db8d4afaf14f63",
"sha256:3c352ff634e289061711608f5e474ec38dbaa21e3e168820d53d5f4015e5b91b",
"sha256:3fb47f97f1d338b943126e90b79cad50d4fcfa0b80637b5a9f468941dbbd9ce5",
"sha256:441ce2a8c17683d97e06447fcbccbdb057cbf587c78eb75ae43ea7858042fe2c",
"sha256:45535241baa0fc0ba2a43961a1ac7562ca3257f46c4c3e9c0de38b722be41bd1",
"sha256:4aca81a687975b35e3e80bcf9aa93fe10cd57fac37bf18b2314c186095f57e05",
"sha256:4cc563836f13c57f1473bc02d1e01fc37bab70ad4ee6be297d58c1d66bc819bf",
"sha256:4fae0677f712ee090721d8b17f412f1cbceefbf0dc180fe91bab3232f38b4527",
"sha256:58bc9fce3e1557d463ef5cee05391a05745fd95ed660f23c1742c711712c0abb",
"sha256:664832fb88b8162268928df233f4b12a144a0c78b01d38b81bdcf0fc96668ecb",
"sha256:70820a1c96311e02449591cbdf5cd1c6a34d5194d5b55094ab725364375c9eb2",
"sha256:79b2ae94fa991be023832e6bcc00f41dbc8e5fe9d997a02db965831402551730",
"sha256:83cf0228b2f694dcdba1374d5312f2277269d798e65f40344964f642935feac1",
"sha256:87de598edfa2230ff274c4de7fcf24c73ffd96208c8e1912d5d0fee459767d75",
"sha256:8f806bfd0f218477d7c46a11d3e52dc7f5fdfaa981b18202b7dc84bbc287463b",
"sha256:90053234a6479738fd40d155268af631c7fca33365f964f2208867da1349294b",
"sha256:a00dce2d96587651ef4fa192c17e039e8cfab63087c67e7d263a5533c7dad715",
"sha256:a08cd07d3c3c17cd33d9e66ea9dee8f8fc1c48e2d11bd88fd2dc515a602c709b",
"sha256:a19d39b02a24d3082856a5b06490b714a9d4179321225bbf22809ff1e1887cc8",
"sha256:d00a669e4a5bec3ee6dbeeeedd82a405ced19f8aeefb109a012ea88a45afff96",
"sha256:dab0c685f21f4a6c95bfc2afd1e7eae0033b403dd3d8c1b6d13a652ada75b348",
"sha256:df561f65049ed3556e5b52541669310e88713fdae2934845ec3606f283337958",
"sha256:e4570d16f88c7f3032ed909dc9e905a17da14a1c4cfd92608e3fda4cb1208bbd",
"sha256:e77e4b983e2441aff0c0d07ee711110c106b625f440292dfe02a2f60c8218bd6",
"sha256:e79212d09fc0e224d20b43ad44bb0a0a3416d1e04cf6b45fed265114a5d43d20",
"sha256:f58b5ba13a5689ca8317b98439fccfbcc673acaaf8241c1869ceea40f5d585bf",
"sha256:fef86115fdad7ae774720d7103aa776144cf9b66673b4afa9bcaa7af990ed07b"
"sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
"sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
"sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
"sha256:060b790af48b3d1cb6776a1e8956fb41106c6befaca717181c41a1728147dc73",
"sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
"sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
"sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
"sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
"sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
"sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
"sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
"sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
"sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
"sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
"sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
"sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
"sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
"sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
"sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
"sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
"sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
"sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
"sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
"sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
"sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
"sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
"sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
"sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
"sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
"sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
"sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
"sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
"sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
"sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
"sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.0"
"version": "==2.0.1"
},
"packaging": {
"hashes": [
@@ -1611,19 +1632,19 @@
},
"pytest-cov": {
"hashes": [
"sha256:8535764137fecce504a49c2b742288e3d34bc09eed298ad65963616cc98fd45e",
"sha256:95d4933dcbbacfa377bb60b29801daa30d90c33981ab2a79e9ab4452c165066e"
"sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a",
"sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7"
],
"index": "pypi",
"version": "==2.12.0"
"version": "==2.12.1"
},
"pytest-django": {
"hashes": [
"sha256:80f8875226ec4dc0b205f0578072034563879d98d9b1bec143a80b9045716cb0",
"sha256:a51150d8962200250e850c6adcab670779b9c2aa07271471059d1fb92a843fa9"
"sha256:65783e78382456528bd9d79a35843adde9e6a47347b20464eb2c885cb0f1f606",
"sha256:b5171e3798bf7e3fc5ea7072fe87324db67a4dd9f1192b037fed4cc3c1b7f455"
],
"index": "pypi",
"version": "==4.2.0"
"version": "==4.4.0"
},
"pytest-env": {
"hashes": [
@@ -1730,11 +1751,11 @@
},
"sphinxcontrib-htmlhelp": {
"hashes": [
"sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f",
"sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"
"sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07",
"sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"
],
"markers": "python_version >= '3.5'",
"version": "==1.0.3"
"markers": "python_version >= '3.6'",
"version": "==2.0.0"
},
"sphinxcontrib-jsmath": {
"hashes": [
@@ -1754,11 +1775,11 @@
},
"sphinxcontrib-serializinghtml": {
"hashes": [
"sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc",
"sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"
"sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd",
"sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"
],
"markers": "python_version >= '3.5'",
"version": "==1.1.4"
"version": "==1.1.5"
},
"termcolor": {
"hashes": [
@@ -1792,19 +1813,19 @@
},
"urllib3": {
"hashes": [
"sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df",
"sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"
"sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c",
"sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
"version": "==1.26.4"
"version": "==1.26.5"
},
"virtualenv": {
"hashes": [
"sha256:307a555cf21e1550885c82120eccaf5acedf42978fd362d32ba8410f9593f543",
"sha256:72cf267afc04bf9c86ec932329b7e94db6a0331ae9847576daaa7ca3c86b29a4"
"sha256:14fdf849f80dbb29a4eb6caa9875d476ee2a5cf76a5f5415fa2f1606010ab467",
"sha256:2b0126166ea7c9c3661f5b8e06773d28f83322de7a3ff7d06f0aed18c9de6a76"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==20.4.6"
"version": "==20.4.7"
}
}
}

View File

@@ -100,6 +100,7 @@ Paperless has been around a while now, and people are starting to build stuff on
* [Paperless App](https://github.com/bauerj/paperless_app): An Android/iOS app for Paperless. Updated to work with paperless-ng.
* [Paperless Share](https://github.com/qcasey/paperless_share). Share any files from your Android application with paperless. Very simple, but works with all of the mobile scanning apps out there that allow you to share scanned documents.
* [Scan to Paperless](https://github.com/sbrunner/scan-to-paperless): Scan and prepare (crop, deskew, OCR, ...) your documents for Paperless.
These projects also exist, but their status and compatibility with paperless-ng is unknown.

View File

@@ -12,27 +12,29 @@ Note that this role requires root access, so either run it in a playbook with a
- hosts: all
roles:
- role: ansible
- role: paperless-ng
become: yes
Role Variables
--------------
Most configuration variables from paperless-ng itself are available and accept their respective arguments.
Every `PAPERLESS_*` configuration varaible is lowercased and instead prefixed with `paperlessng_*` in `defaults/main.yml`.
Every `PAPERLESS_*` configuration variable is lowercased and instead prefixed with `paperlessng_*` in `defaults/main.yml`.
For a full listing including explainations and allowed values, see the current [documentation](https://paperless-ng.readthedocs.io/en/ng-0.9.14/configuration.html).
For a full listing including explanations and allowed values, see the current [documentation](https://paperless-ng.readthedocs.io/en/latest/configuration.html).
Additional variables available in this role are listed below, along with default values:
paperlessng_version: 0.9.14
paperlessng_version: latest
The [release](https://github.com/jonaswinkler/paperless-ng/releases) archive version of paperless-ng to install.
`latest` stands for the latest release of paperless-ng.
To install a specific version of paperless-ng, use the tag name of the release, e. g. `ng-1.4.4`, or specify a branch or commit id.
paperlessng_redis_host: localhost
paperlessng_redis_port: 6379
Seperate configuration values that combine into `PAPERLESS_REDIS`.
Separate configuration values that combine into `PAPERLESS_REDIS`.
paperlessng_db_type: sqlite
@@ -96,11 +98,11 @@ Example Playbook
- hosts: all
become: yes
vars_files:
- vars/main.yml
- vars/paperless-ng.yml
roles:
- ansible
- paperless-ng
`vars/main.yml`:
`vars/paperless-ng.yml`:
paperlessng_media_root: /mnt/media/smbshare

View File

@@ -1 +1 @@
COMPOSE_PROJECT_NAME=paperless
COMPOSE_PROJECT_NAME=paperless

View File

@@ -4,37 +4,37 @@ set -e
# Source: https://github.com/sameersbn/docker-gitlab/
map_uidgid() {
USERMAP_ORIG_UID=$(id -u paperless)
USERMAP_ORIG_GID=$(id -g paperless)
USERMAP_NEW_UID=${USERMAP_UID:-$USERMAP_ORIG_UID}
USERMAP_NEW_GID=${USERMAP_GID:-${USERMAP_ORIG_GID:-$USERMAP_NEW_UID}}
if [[ ${USERMAP_NEW_UID} != "${USERMAP_ORIG_UID}" || ${USERMAP_NEW_GID} != "${USERMAP_ORIG_GID}" ]]; then
echo "Mapping UID and GID for paperless:paperless to $USERMAP_NEW_UID:$USERMAP_NEW_GID"
usermod -u "${USERMAP_NEW_UID}" paperless
groupmod -o -g "${USERMAP_NEW_GID}" paperless
fi
USERMAP_ORIG_UID=$(id -u paperless)
USERMAP_ORIG_GID=$(id -g paperless)
USERMAP_NEW_UID=${USERMAP_UID:-$USERMAP_ORIG_UID}
USERMAP_NEW_GID=${USERMAP_GID:-${USERMAP_ORIG_GID:-$USERMAP_NEW_UID}}
if [[ ${USERMAP_NEW_UID} != "${USERMAP_ORIG_UID}" || ${USERMAP_NEW_GID} != "${USERMAP_ORIG_GID}" ]]; then
echo "Mapping UID and GID for paperless:paperless to $USERMAP_NEW_UID:$USERMAP_NEW_GID"
usermod -u "${USERMAP_NEW_UID}" paperless
groupmod -o -g "${USERMAP_NEW_GID}" paperless
fi
}
initialize() {
map_uidgid
for dir in export data data/index media media/documents media/documents/originals media/documents/thumbnails; do
if [[ ! -d "../$dir" ]]
then
echo "creating directory ../$dir"
if [[ ! -d "../$dir" ]]; then
echo "Creating directory ../$dir"
mkdir ../$dir
fi
done
echo "creating directory /tmp/paperless"
echo "Creating directory /tmp/paperless"
mkdir -p /tmp/paperless
set +e
chown -R paperless:paperless ../
set +e
echo "Adjusting permissions of paperless files. This may take a while."
chown -R paperless:paperless /tmp/paperless
set -e
find .. -not \( -user paperless -and -group paperless \) -exec chown paperless:paperless {} +
set -e
gosu paperless /sbin/docker-prepare.sh
gosu paperless /sbin/docker-prepare.sh
}
install_languages() {
@@ -50,35 +50,35 @@ install_languages() {
apt-get update
for lang in "${langs[@]}"; do
pkg="tesseract-ocr-$lang"
# English is installed by default
#if [[ "$lang" == "eng" ]]; then
# continue
#fi
pkg="tesseract-ocr-$lang"
# English is installed by default
#if [[ "$lang" == "eng" ]]; then
# continue
#fi
if dpkg -s $pkg &> /dev/null; then
echo "package $pkg already installed!"
continue
fi
if dpkg -s $pkg &>/dev/null; then
echo "Package $pkg already installed!"
continue
fi
if ! apt-cache show $pkg &> /dev/null; then
echo "package $pkg not found! :("
continue
fi
if ! apt-cache show $pkg &>/dev/null; then
echo "Package $pkg not found! :("
continue
fi
echo "Installing package $pkg..."
if ! apt-get -y install "$pkg" &> /dev/null; then
echo "Could not install $pkg"
exit 1
fi
done
echo "Installing package $pkg..."
if ! apt-get -y install "$pkg" &>/dev/null; then
echo "Could not install $pkg"
exit 1
fi
done
}
echo "Paperless-ng docker container starting..."
# Install additional languages if specified
if [[ ! -z "$PAPERLESS_OCR_LANGUAGES" ]]; then
install_languages "$PAPERLESS_OCR_LANGUAGES"
if [[ ! -z "$PAPERLESS_OCR_LANGUAGES" ]]; then
install_languages "$PAPERLESS_OCR_LANGUAGES"
fi
initialize

View File

@@ -149,22 +149,15 @@ Ansible Route
Most of the update process is automated when using the ansible role.
1. Backup your defined role variables file outside the paperless source-tree:
1. Update the role to the target release tag to make sure the ansible scripts are compatible:
.. code:: shell-session
$ cp ansible/vars.yml ~/vars.yml.old
$ ansible-galaxy install git+https://github.com/jonaswinkler/paperless-ng.git,master --force
2. Pull the release tag you want to update to:
2. Update the role variable definitions ``vars/paperless-ng.yml`` (where appropriate).
.. code:: shell-session
$ git fetch --all
$ git checkout ng-0.9.14
3. Update the role variable definitions ``ansible/vars.yml`` (where appropriate).
4. Run the ansible playbook you created created during :ref:`installation <setup-ansible>` again:
3. Run the ansible playbook you created created during :ref:`installation <setup-ansible>` again:
.. note::

View File

@@ -5,6 +5,28 @@
Changelog
*********
paperless-ng 1.4.5
##################
This is a maintenance release.
* Updated Python and Angular dependencies.
* Changed the algorithm that changes permissions during startup. This is still fast,
and will hopefully cause less issues.
* Fixed an issue that would sometimes cause paperless to write an incomplete
classification model file to disk.
* Fixed an issue with the OCRmyPDF parser that would always try to extract text
with PDFminer even from non-PDF files.
paperless-ng 1.4.4
##################
* Drastically decreased the startup time of the docker container. The startup script adjusts file permissions of all data only if changes are required.
* Paperless mail: Added ability to specify the character set for each server.
* Document consumption: Ignore Mac OS specific files such as ``.DS_STORE`` and ``._XXXXX.pdf``.
* Fixed an issue with the automatic matching algorithm that prevents paperless from consuming new files.
* Updated translations.
paperless-ng 1.4.3
##################
@@ -16,7 +38,7 @@ paperless-ng 1.4.3
* `Michael Shamoon`_ added dark mode for the login and logout pages.
* `Alexander Menk`_ added additional stylesheets for printing. You can now print any page of paperless and the print result will hide the page header, sidebar, and action buttons.
* Added support for sorting when using full text search.
* Fixes
* `puuu`_ fixed ``PAPERLESS_FORCE_SCRIPT_NAME``. You can now host paperless on sub paths such as ``https://localhost:8000/paperless/``.

View File

@@ -174,11 +174,11 @@ PAPERLESS_AUTO_LOGIN_USERNAME=<username>
Defaults to none, which disables this feature.
PAPERLESS_ADMIN_USER=<username>
If this environment variable is specified, Paperless automatically creates
a superuser with the provided username at start. This is useful in cases
where you can not run the `createsuperuser` command seperately, such as Kubernetes
If this environment variable is specified, Paperless automatically creates
a superuser with the provided username at start. This is useful in cases
where you can not run the `createsuperuser` command seperately, such as Kubernetes
or AWS ECS.
Requires `PAPERLESS_ADMIN_PASSWORD` to be set.
.. note::
@@ -188,7 +188,7 @@ PAPERLESS_ADMIN_USER=<username>
the lifecycle of the containers.
PAPERLESS_ADMIN_MAIL=<email>
(Optional) Specify superuser email address. Only used when
(Optional) Specify superuser email address. Only used when
`PAPERLESS_ADMIN_USER` is set.
Defaults to ``root@localhost``.
@@ -222,17 +222,17 @@ PAPERLESS_ENABLE_HTTP_REMOTE_USER=<bool>
Also see the warning `in the official documentation <https://docs.djangoproject.com/en/3.1/howto/auth-remote-user/#configuration>`.
Defaults to `false` which disables this feature.
PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME=<str>
If `PAPERLESS_ENABLE_HTTP_REMOTE_USER` is enabled, this property allows to
customize the name of the HTTP header from which the authenticated username
If `PAPERLESS_ENABLE_HTTP_REMOTE_USER` is enabled, this property allows to
customize the name of the HTTP header from which the authenticated username
is extracted. Values are in terms of
[HttpRequest.META](https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.HttpRequest.META).
Thus, the configured value must start with `HTTP_` followed by the
Thus, the configured value must start with `HTTP_` followed by the
normalized actual header name.
Defaults to `HTTP_REMOTE_USER`.
.. _configuration-ocr:
OCR settings
@@ -622,6 +622,14 @@ PAPERLESS_IGNORE_DATES=<string>
Defaults to an empty string to not ignore any dates.
PAPERLESS_DATE_ORDER=<format>
Paperless will try to determine the document creation date from its contents.
Specify the date format Paperless should expect to see within your documents.
This option defaults to DMY which translates to day first, month second, and year
last order. Characters D, M, or Y can be shuffled to meet the required order.
Binaries
########

View File

@@ -6,7 +6,7 @@ Contributing to Paperless
.. warning::
This section is not updated to paperless-ng yet.
Maybe you've been using Paperless for a while and want to add a feature or two,
or maybe you've come across a bug that you have some ideas how to solve. The
beauty of Free software is that you can see what's wrong and help to get it

View File

@@ -23,10 +23,10 @@ Apart from that, the folder structure is as follows:
* ``scripts/`` - Various scripts that help with different parts of development.
* ``docker/`` - Files required to build the docker image.
Initial setup and first start
Initial setup and first start
=============================
After you forked and cloned the code from github you need to perform a first-time setup.
After you forked and cloned the code from github you need to perform a first-time setup.
To do the setup you need to perform the steps from the following chapters in a certain order:
1. Install prerequisites + pipenv as mentioned in :ref:`Bare metal route <setup-bare_metal>`
@@ -35,19 +35,19 @@ To do the setup you need to perform the steps from the following chapters in a c
.. code:: shell-session
$ npm install -g @angular/cli
$ npm install -g @angular/cli
4. Create ``consume`` and ``media`` folders in the cloned root folder.
.. code:: shell-session
mkdir -p consume media
5. You can now either ...
* install redis or
* install redis or
* use the included scripts/start-services.sh to use docker to fire up a redis instance (and some other services such as tika, gotenberg and a postgresql server) or
* spin up a bare redis container
* spin up a bare redis container
.. code:: shell-session
@@ -79,7 +79,7 @@ To do the setup you need to perform the steps from the following chapters in a c
python3 manage.py runserver & python3 manage.py document_consumer & python3 manage.py qcluster
10. Login with the superuser credentials provided in step 8 at ``http://localhost:8000`` to create a session that enables you to use the backend.
Backend development environment is now ready, to start Frontend development go to ``/src-ui`` and run ``ng serve``. From there you can use ``http://localhost:4200`` for a preview.
Back end development
@@ -207,7 +207,7 @@ Adding new languages requires adding the translated files in the "src-ui/src/loc
// Add your new language here
]
}
``dateInputFormat`` is a special string that defines the behavior of the date input fields and absolutely needs to contain "dd", "mm" and "yyyy".
3. Import and register the Angular data for this locale in "src-ui/src/app/app.module.ts":
@@ -320,7 +320,7 @@ methods ``parse`` and ``get_thumbnail``. You can provide your own implementation
# The content of the document.
self.text = "content"
# Optional: path to a PDF document that you created from the original.
self.archive_path = os.path.join(self.tempdir, "archived.pdf")

View File

@@ -68,10 +68,10 @@ reuse the text. The web interface is a lot snappier, since it runs
in your browser and paperless has to do much less work to serve the data.
.. note::
You can adjust some of the settings so that paperless uses less processing
power. See :ref:`setup-less_powerful_devices` for details.
**Q:** *How do I install paperless-ng on Raspberry Pi?*

View File

@@ -49,7 +49,7 @@ resources in the documentation:
paperless-ng.
* Paperless is now integrated with a
:ref:`task processing queue <setup-task_processor>` that tells you
at a glance when and why something is not working.
at a glance when and why something is not working.
* The :ref:`changelog <paperless_changelog>` contains a detailed list of all changes
in paperless-ng.

View File

@@ -116,9 +116,7 @@ performs all the steps described in :ref:`setup-docker_hub` automatically.
.. code:: shell-session
$ wget https://raw.githubusercontent.com/jonaswinkler/paperless-ng/master/install-paperless-ng.sh
$ chmod +x install-paperless-ng.sh
$ ./install-paperless-ng.sh
$ curl -L https://raw.githubusercontent.com/jonaswinkler/paperless-ng/master/install-paperless-ng.sh | bash
.. _setup-docker_hub:
@@ -286,7 +284,7 @@ writing. Windows is not and will never be supported.
Use this list for your preferred package management:
.. code::
.. code::
python3 python3-pip python3-dev imagemagick fonts-liberation optipng gnupg libpq-dev libmagic-dev mime-support
@@ -305,7 +303,7 @@ writing. Windows is not and will never be supported.
Use this list for your preferred package management:
.. code::
.. code::
unpaper ghostscript icc-profiles-free qpdf liblept5 libxml2 pngquant zlib1g tesseract-ocr
@@ -360,7 +358,11 @@ writing. Windows is not and will never be supported.
Adjust as necessary if you configured different folders.
8. Install python requirements from the ``requirements.txt`` file.
It is up to you if you wish to use a virtual environment or not.
It is up to you if you wish to use a virtual environment or not. First you should update your pip, so it gets the actual packages.
.. code:: shell-session
sudo -Hu paperless pip3 install --upgrade pip
.. code:: shell-session

View File

@@ -81,7 +81,7 @@ UserWarning in sklearn on every single document
You may encounter warnings like this:
.. code::
/usr/local/lib/python3.7/site-packages/sklearn/base.py:315:
UserWarning: Trying to unpickle estimator CountVectorizer from version 0.23.2 when using version 0.24.0.
This might lead to breaking code or invalid results. Use at your own risk.
@@ -200,13 +200,13 @@ This might have multiple reasons.
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/wsgi.py", line 386, in sendfile
sent += os.sendfile(sockno, fileno, offset + sent, count)
OSError: [Errno 22] Invalid argument
To fix this issue, add
.. code::
SENDFILE=0
to your `docker-compose.env` file.
Error while reading metadata

View File

@@ -71,7 +71,7 @@ your documents:
This process can be configured to fit your needs. If you don't want paperless
to create archived versions for digital documents, you can configure that by
configuring ``PAPERLESS_OCR_MODE=skip_noarchive``. Please read the
configuring ``PAPERLESS_OCR_MODE=skip_noarchive``. Please read the
:ref:`relevant section in the documentation <configuration-ocr>`.
.. note::
@@ -289,7 +289,7 @@ Matching specific tags, correspondents or types:
Matching dates:
.. code::
created:[2005 to 2009]
added:yesterday
modified:today
@@ -306,11 +306,11 @@ Matching inexact words:
auto complete and query correction.
All of these constructs can be combined as you see fit.
If you want to learn more about the query language used by paperless, paperless uses Whoosh's default query language.
If you want to learn more about the query language used by paperless, paperless uses Whoosh's default query language.
Head over to `Whoosh query language <https://whoosh.readthedocs.io/en/latest/querylang.html>`_.
For details on what date parsing utilities are available, see
`Date parsing <https://whoosh.readthedocs.io/en/latest/dates.html#parsing-date-queries>`_.
.. _usage-recommended_workflow:
@@ -385,7 +385,7 @@ Once you have scanned in a document, proceed in paperless as follows.
6. Remove inbox tags from the documents.
.. hint::
You can setup manual matching rules for your correspondents and tags and
paperless will assign them automatically. After consuming a couple documents,
you can even ask paperless to *learn* when to assign tags and correspondents

View File

@@ -15,13 +15,13 @@ attrs==21.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2,
autobahn==21.3.1; python_version >= '3.7'
automat==20.2.0
blessed==1.18.0
certifi==2020.12.5
certifi==2021.5.30
cffi==1.14.5
channels-redis==3.2.0
channels==3.0.3
chardet==4.0.0; python_version >= '3.1'
click==7.1.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
coloredlogs==15.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
click==8.0.1; python_version >= '3.6'
coloredlogs==15.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
concurrent-log-handler==0.9.19
constantly==15.1.0
cryptography==3.4.7
@@ -31,16 +31,16 @@ django-cors-headers==3.7.0
django-extensions==3.1.3
django-filter==2.4.0
django-picklefield==3.0.1; python_version >= '3'
django-q==1.3.4
django==3.2.3
django-q==1.3.8
django==3.2.4
djangorestframework==3.12.4
filelock==3.0.12
fuzzywuzzy[speedup]==0.18.0
gunicorn==20.1.0
h11==0.12.0; python_version >= '3.6'
hiredis==2.0.0; python_version >= '3.6'
httptools==0.1.2
humanfriendly==9.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
httptools==0.2.0
humanfriendly==9.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
hyperlink==21.0.0
idna==2.10; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
imap-tools==0.41.0
@@ -53,10 +53,10 @@ langdetect==1.0.9
lxml==4.6.3; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
msgpack==1.0.2
numpy==1.19.5
ocrmypdf==12.0.1
ocrmypdf==12.0.3
pathvalidate==2.4.1
pdfminer.six==20201018
pikepdf==2.12.0
pikepdf==2.12.2
pillow==8.2.0
pluggy==0.13.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
portalocker==2.3.0; python_version >= '3'
@@ -69,7 +69,7 @@ python-dateutil==2.8.1
python-dotenv==0.17.1
python-gnupg==0.4.7
python-levenshtein==0.12.2
python-magic==0.4.22
python-magic==0.4.24
pytz==2021.1
pyyaml==5.4.1
redis==3.5.3
@@ -80,21 +80,21 @@ scikit-learn==0.24.0
scipy==1.5.4
service-identity==21.1.0
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
sortedcontainers==2.3.0
sortedcontainers==2.4.0
sqlparse==0.4.1; python_version >= '3.5'
threadpoolctl==2.1.0; python_version >= '3.5'
tika==1.24
tqdm==4.60.0
tqdm==4.61.1
twisted[tls]==21.2.0; python_full_version >= '3.5.4'
txaio==21.2.1; python_version >= '3.6'
tzlocal==2.1
urllib3==1.26.4; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'
uvicorn[standard]==0.13.4
urllib3==1.26.5; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'
uvicorn[standard]==0.14.0
uvloop==0.14.0
watchdog==1.0.2
watchgod==0.7
wcwidth==0.2.5
websockets==8.1
websockets==9.1
whitenoise==5.2.0
whoosh==2.7.4
zope.interface==5.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'

View File

@@ -72,7 +72,6 @@
"optimization": true,
"outputHashing": "none",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,

View File

@@ -33,4 +33,4 @@ exports.config = {
}
}));
}
};
};

25149
src-ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,41 +11,41 @@
},
"private": true,
"dependencies": {
"@angular/animations": "~10.1.5",
"@angular/common": "~10.1.5",
"@angular/compiler": "~10.1.5",
"@angular/core": "~10.1.5",
"@angular/forms": "~10.1.5",
"@angular/localize": "~10.1.5",
"@angular/platform-browser": "~10.1.5",
"@angular/platform-browser-dynamic": "~10.1.5",
"@angular/router": "~10.1.5",
"@ng-bootstrap/ng-bootstrap": "^8.0.4",
"@ng-select/ng-select": "^5.0.9",
"@angular/animations": "~11.2.14",
"@angular/common": "~11.2.14",
"@angular/compiler": "~11.2.14",
"@angular/core": "~11.2.14",
"@angular/forms": "~11.2.14",
"@angular/localize": "~11.2.14",
"@angular/platform-browser": "~11.2.14",
"@angular/platform-browser-dynamic": "~11.2.14",
"@angular/router": "~11.2.14",
"@ng-bootstrap/ng-bootstrap": "^9.1.2",
"@ng-select/ng-select": "^7.0.0",
"bootstrap": "^4.5.0",
"file-saver": "^2.0.5",
"ng-bootstrap": "^1.6.3",
"ng2-pdf-viewer": "^6.3.2",
"ngx-bootstrap": "^6.2.0",
"ngx-color": "^6.2.0",
"ngx-cookie-service": "^10.1.1",
"ngx-file-drop": "^10.0.0",
"ngx-file-drop": "^11.1.0",
"ngx-infinite-scroll": "^9.1.0",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
"uuid": "^8.3.1",
"zone.js": "~0.10.2"
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1002.0",
"@angular/cli": "~10.1.5",
"@angular/compiler-cli": "~10.1.5",
"@types/jasmine": "~3.5.0",
"@angular-devkit/build-angular": "~0.1102.13",
"@angular/cli": "~11.2.14",
"@angular/compiler-cli": "~11.2.14",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~5.0.0",
"karma": "~6.3.3",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
@@ -53,6 +53,6 @@
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "~4.0.2"
"typescript": "~4.1.5"
}
}

View File

@@ -33,7 +33,7 @@ const routes: Routes = [
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@@ -1,3 +1,3 @@
<app-toasts></app-toasts>
<router-outlet></router-outlet>
<router-outlet></router-outlet>

View File

@@ -45,7 +45,7 @@ export class AppComponent implements OnInit, OnDestroy {
ngOnInit(): void {
this.consumerStatusService.connect()
this.successSubscription = this.consumerStatusService.onDocumentConsumptionFinished().subscribe(status => {
if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS)) {
this.toastService.show({title: $localize`Document added`, delay: 10000, content: $localize`Document ${status.filename} was added to paperless.`, actionName: $localize`Open document`, action: () => {

View File

@@ -30,7 +30,7 @@ export class ConfirmDialogComponent implements OnInit {
@Input()
buttonsEnabled = true
confirmButtonEnabled = true
seconds = 0

View File

@@ -55,7 +55,7 @@
</button>
</div>
</div>
</div>
</div>
</div>

View File

@@ -83,7 +83,7 @@ export class FilterableDropdownSelectionModel {
if (fireEvent) {
this.changed.next(this)
}
}
private getNonTemporary(id: number) {

View File

@@ -10,7 +10,7 @@
<path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z"/>
</svg>
</ng-container>
</div>
<div class="mr-1">
<app-tag *ngIf="isTag; else displayName" [tag]="item" [clickable]="true" linkTitle="Filter by tag"></app-tag>

View File

@@ -11,7 +11,7 @@ export class AbstractInputComponent<T> implements OnInit, ControlValueAccessor {
constructor() { }
onChange = (newValue: T) => {};
onTouched = () => {};
writeValue(newValue: any): void {

View File

@@ -2,4 +2,4 @@
<input type="checkbox" class="custom-control-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
<label class="custom-control-label" [for]="inputId">{{title}}</label>
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
</div>
</div>

View File

@@ -15,7 +15,7 @@ import { AbstractInputComponent } from '../abstract-input';
})
export class CheckComponent extends AbstractInputComponent<boolean> {
constructor() {
constructor() {
super()
}

View File

@@ -5,12 +5,12 @@
<div class="input-group-prepend">
<span class="input-group-text" [style.background-color]="value">&nbsp;&nbsp;&nbsp;</span>
</div>
<ng-template #popContent>
<div style="min-width: 200px;" class="pb-3">
<color-slider [color]="value" (onChangeComplete)="colorChanged($event.color.hex)"></color-slider>
</div>
</ng-template>
<input class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [autoClose]="'outside'" [ngbPopover]="popContent" placement="bottom" popoverClass="shadow">
@@ -30,4 +30,4 @@
<div class="invalid-feedback">
{{error}}
</div>
</div>
</div>

View File

@@ -11,4 +11,4 @@
</div>
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
</div>
</div>

View File

@@ -5,4 +5,4 @@
<div class="invalid-feedback">
{{error}}
</div>
</div>
</div>

View File

@@ -12,4 +12,4 @@
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="cancelClicked()" i18n>Cancel</button>
<button type="button" class="btn btn-primary" (click)="selectClicked.emit(selected)" i18n>Select</button>
</div>
</div>

View File

@@ -1,2 +1,2 @@
<span *ngIf="!clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</span>
<a [routerLink]="" [title]="linkTitle" *ngIf="clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</a>
<a [routerLink]="" [title]="linkTitle" *ngIf="clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</a>

View File

@@ -23,7 +23,7 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy {
statistics: Statistics = {}
subscription: Subscription
private getStatistics(): Observable<Statistics> {
return this.http.get(`${environment.apiBaseUrl}statistics/`)
}

View File

@@ -13,4 +13,4 @@
<p i18n>Consult the documentation on how to use these features. The section on basic usage also has some information on how to use paperless in general.</p>
</ng-container>
</app-widget-frame>
</app-widget-frame>

View File

@@ -4,9 +4,9 @@
<h5 class="card-title mb-0">{{title}}</h5>
<ng-content select ="[header-buttons]"></ng-content>
</div>
</div>
<div class="card-body text-dark">
<ng-content select ="[content]"></ng-content>
</div>
</div>
</div>

View File

@@ -20,4 +20,4 @@
</tr>
</tbody>
</table>
</div>
</div>

View File

@@ -1,3 +1,3 @@
.metadata-column {
overflow-wrap: anywhere;
}
}

View File

@@ -64,4 +64,4 @@
span ::ng-deep .match {
color: black;
background-color: rgb(255, 211, 66);
}
}

View File

@@ -3,7 +3,7 @@
<div class="form-inline d-flex align-items-center">
<div class="input-group input-group-sm flex-fill w-auto">
<div class="input-group-prepend" ngbDropdown>
<button class="btn btn-outline-primary" ngbDropdownToggle>{{textFilterTargetName}}</button>
<button class="btn btn-outline-primary" ngbDropdownToggle>{{textFilterTargetName}}</button>
<div class="dropdown-menu shadow" ngbDropdownMenu>
<button *ngFor="let t of textFilterTargets" ngbDropdownItem [class.active]="textFilterTarget == t.id" (click)="changeTextFilterTarget(t.id)">{{t.name}}</button>
</div>

View File

@@ -32,6 +32,6 @@ export class CorrespondentEditDialogComponent extends EditDialogComponent<Paperl
match: new FormControl(""),
is_insensitive: new FormControl(true)
})
}
}
}

View File

@@ -18,7 +18,7 @@ export class CorrespondentListComponent extends GenericListComponent<PaperlessCo
constructor(correspondentsService: CorrespondentService, modalService: NgbModal,
private list: DocumentListViewService,
toastService: ToastService
) {
) {
super(correspondentsService,modalService,CorrespondentEditDialogComponent, toastService)
}

View File

@@ -13,7 +13,7 @@ import { ToastService } from 'src/app/services/toast.service';
})
export class DocumentTypeEditDialogComponent extends EditDialogComponent<PaperlessDocumentType> {
constructor(service: DocumentTypeService, activeModal: NgbActiveModal, toastService: ToastService) {
constructor(service: DocumentTypeService, activeModal: NgbActiveModal, toastService: ToastService) {
super(service, activeModal, toastService)
}

View File

@@ -49,4 +49,4 @@
</td>
</tr>
</tbody>
</table>
</table>

View File

@@ -52,4 +52,4 @@
</td>
</tr>
</tbody>
</table>
</table>

View File

@@ -5,4 +5,4 @@
<path d="M7 6.5C7 7.328 6.552 8 6 8s-1-.672-1-1.5S5.448 5 6 5s1 .672 1 1.5zm4 0c0 .828-.448 1.5-1 1.5s-1-.672-1-1.5S9.448 5 10 5s1 .672 1 1.5z"/>
</svg>
<h1 i18n>404 Not Found</h1>
</div>
</div>

View File

@@ -6,7 +6,7 @@ export function cloneFilterRules(filterRules: FilterRule[]): FilterRule[] {
for (let rule of filterRules) {
newRules.push({rule_type: rule.rule_type, value: rule.value})
}
return newRules
return newRules
} else {
return null
}
@@ -19,4 +19,4 @@ export function isFullTextFilterRule(filterRules: FilterRule[]): boolean {
export interface FilterRule {
rule_type: number
value: string
}
}

View File

@@ -1,7 +1,7 @@
import { MatchingModel } from './matching-model';
export interface PaperlessCorrespondent extends MatchingModel {
last_correspondence?: Date
}

View File

@@ -1,5 +1,5 @@
export interface PaperlessDocumentMetadata {
original_checksum?: string
archived_checksum?: string
@@ -10,4 +10,4 @@ export interface PaperlessDocumentMetadata {
has_archive_version?: boolean
}
}

View File

@@ -6,4 +6,4 @@ export interface PaperlessDocumentSuggestions {
document_types?: number[]
}
}

View File

@@ -15,4 +15,4 @@ export interface PaperlessSavedView extends ObjectWithId {
filter_rules: FilterRule[]
}
}

View File

@@ -3,5 +3,5 @@ export interface Results<T> {
count: number
results: T[]
}

View File

@@ -8,4 +8,4 @@ export interface WebsocketConsumerStatusMessage {
message?: string
document_id: number
}
}

View File

@@ -19,7 +19,7 @@ export class ApiVersionInterceptor implements HttpInterceptor {
'Accept': `application/json; version=${environment.apiVersion}`
}
})
return next.handle(request);
}
}

View File

@@ -20,7 +20,7 @@ export class CsrfInterceptor implements HttpInterceptor {
let prefix = ""
if (this.meta.getTag('name=cookie_prefix')) {
prefix = this.meta.getTag('name=cookie_prefix').content
}
}
let csrfToken = this.cookieService.get(`${prefix?prefix:''}csrftoken`)
if (csrfToken) {
request = request.clone({

View File

@@ -11,12 +11,11 @@ const FORMAT_TO_ISO_FORMAT = {
@Pipe({
name: 'customDate'
})
export class CustomDatePipe extends DatePipe implements PipeTransform {
export class CustomDatePipe implements PipeTransform {
private defaultLocale: string
constructor(@Inject(LOCALE_ID) locale: string, private settings: SettingsService) {
super(locale)
constructor(@Inject(LOCALE_ID) locale: string, private datePipe: DatePipe, private settings: SettingsService) {
this.defaultLocale = locale
}
@@ -24,9 +23,9 @@ export class CustomDatePipe extends DatePipe implements PipeTransform {
let l = locale || this.settings.get(SETTINGS_KEYS.DATE_LOCALE) || this.defaultLocale
let f = format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT)
if (l == "iso-8601") {
return super.transform(value, FORMAT_TO_ISO_FORMAT[f], timezone)
return this.datePipe.transform(value, FORMAT_TO_ISO_FORMAT[f], timezone)
} else {
return super.transform(value, format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT), timezone, l)
return this.datePipe.transform(value, format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT), timezone, l)
}
}

View File

@@ -1,6 +1,6 @@
/**
* https://gist.github.com/JonCatmull/ecdf9441aaa37336d9ae2c7f9cb7289a
*
*
* @license
* Copyright (c) 2019 Jonathan Catmull.
*

View File

@@ -16,4 +16,4 @@ export class SafePipe implements PipeTransform {
}
}
}
}

View File

@@ -10,7 +10,7 @@ export class OpenDocumentsService {
private MAX_OPEN_DOCUMENTS = 5
constructor(private documentService: DocumentService) {
constructor(private documentService: DocumentService) {
if (sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS)) {
try {
this.openDocuments = JSON.parse(sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS))

View File

@@ -44,7 +44,7 @@ export class SavedViewService extends AbstractPaperlessService<PaperlessSavedVie
tap(() => this.reload())
)
}
patchMany(objects: PaperlessSavedView[]): Observable<PaperlessSavedView[]> {
return combineLatest(objects.map(o => super.patch(o))).pipe(
tap(() => this.reload())

View File

@@ -10,10 +10,10 @@ import { DocumentService } from './document.service';
providedIn: 'root'
})
export class SearchService {
constructor(private http: HttpClient) { }
autocomplete(term: string): Observable<string[]> {
return this.http.get<string[]>(`${environment.apiBaseUrl}search/autocomplete/`, {params: new HttpParams().set('term', term)})
}
}
}

View File

@@ -6,7 +6,7 @@ function componentToHex(c) {
/**
* https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
*
*
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
@@ -45,4 +45,4 @@ function hslToRgb(h, s, l){
export function randomColor() {
let rgb = hslToRgb(Math.random(), 0.6, Math.random() * 0.4 + 0.4)
return `#${componentToHex(rgb[0])}${componentToHex(rgb[1])}${componentToHex(rgb[2])}`
}
}

View File

@@ -56,4 +56,4 @@ export class LocalizedDateParserFormatter extends NgbDateParserFormatter {
return null
}
}
}
}

View File

@@ -5,7 +5,7 @@ export const environment = {
apiBaseUrl: document.baseURI + "api/",
apiVersion: "2",
appTitle: "Paperless-ng",
version: "1.4.3",
version: "1.4.5",
webSocketHost: window.location.host,
webSocketProtocol: (window.location.protocol == "https:" ? "wss:" : "ws:"),
webSocketBaseUrl: base_url.pathname + "ws/",

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="needs-translation">Download originals</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="needs-translation">Suggestions:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="needs-translation">Save current view</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="needs-translation">Modified</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Originale herunterladen</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="translated">Element hinzufügen</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Vorschläge:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Aktuelle Ansicht speichern</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="translated">Tag hinzufügen</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Geändert am</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="translated">Relevanz</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Download originals</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="translated">Add item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Suggestions:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Save current view</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="translated">Add tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Modified</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="translated">Search score</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Descargar originales</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Sugerencias:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Guardar la vista actual</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Modificado</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Télécharger les originaux</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="translated">Ajouter un élément</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Suggestions : </target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Enregistrer la vue actuelle</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="translated">Ajouter une étiquette</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Date de modification</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="translated">Pertinence</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="needs-translation">Download originals</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="needs-translation">Suggestions:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Jelenlegi nézet mentése</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Módosítva</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1378,7 +1378,7 @@
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
<context context-type="linenumber">87</context>
</context-group>
<target state="translated">Punteggio:</target>
<target state="translated">Rilevanza:</target>
</trans-unit>
<trans-unit id="727d980bba2b3e0b3d8705607f1208eef046479b" datatype="html">
<source>Created: <x id="INTERPOLATION" equiv-text="{{ document.created | customDate}}"/></source>
@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Scarica originali</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="translated">Aggiungi elemento</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Suggerimenti:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Salva vista corrente</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="translated">Aggiungi tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Modificato</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="translated">Rilevanza ricerca</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Originelen downloaden</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="translated">Item toevoegen</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Suggesties:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Huidige view opslaan</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="translated">Label toevoegen</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Gewijzigd</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="translated">Zoekscore</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Pobierz oryginały</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Sugestie:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Zapisz bieżący widok</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Zmodyfikowano</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Descarregar originais</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Sugestões:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Salvar visualização atual</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Modificado</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Descarregar originais</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="translated">Adicionar item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Sugestões:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Guardar a vista atual</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="translated">Adicionar etiqueta</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Modificado</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="translated">Pesquisar pontuação</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Descarcă originalele</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Sugestii:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Salvează vizualizarea curenta</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Modificat</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Скачать оригиналы</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Рекомендации:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Сохранить текущее представление</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Изменено</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="translated">Ladda ner original</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="translated">Lägg till objekt</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="translated">Förslag:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="translated">Spara aktuell vy</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="translated">Lägg till tagg</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="translated">Ändrad</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="translated">Sök resultat</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target>crwdns3238:0crwdne3238:0</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target>crwdns3450:0crwdne3450:0</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target>crwdns3240:0crwdne3240:0</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target>crwdns3242:0crwdne3242:0</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target>crwdns3452:0crwdne3452:0</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target>crwdns3364:0crwdne3364:0</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target>crwdns3454:0crwdne3454:0</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

View File

@@ -1607,11 +1607,20 @@
</context-group>
<target state="needs-translation">Download originals</target>
</trans-unit>
<trans-unit id="0f72a164f5a5d10d1fbdeeb84ac80a63c04b7e1b" datatype="html">
<source>Add item</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
<context context-type="linenumber">29</context>
<context context-type="linenumber">31</context>
</context-group>
<target state="needs-translation">Suggestions:</target>
</trans-unit>
@@ -1623,6 +1632,14 @@
</context-group>
<target state="needs-translation">Save current view</target>
</trans-unit>
<trans-unit id="21fd41eb147f55ca26362f9c398e47733639837a" datatype="html">
<source>Add tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
<context-group purpose="location">
@@ -2157,6 +2174,15 @@
</context-group>
<target state="needs-translation">Modified</target>
</trans-unit>
<trans-unit id="4460262093225954455" datatype="html">
<source>Search score</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>
<context-group purpose="location">

0
src/documents/admin.py Executable file → Normal file
View File

43
src/documents/classifier.py Executable file → Normal file
View File

@@ -3,6 +3,7 @@ import logging
import os
import pickle
import re
import shutil
from django.conf import settings
@@ -13,6 +14,10 @@ class IncompatibleClassifierVersionError(Exception):
pass
class ClassifierModelCorruptError(Exception):
pass
logger = logging.getLogger("paperless.classifier")
@@ -34,7 +39,8 @@ def load_classifier():
try:
classifier.load()
except (EOFError, IncompatibleClassifierVersionError) as e:
except (ClassifierModelCorruptError,
IncompatibleClassifierVersionError):
# there's something wrong with the model file.
logger.exception(
f"Unrecoverable error while loading document "
@@ -42,9 +48,14 @@ def load_classifier():
)
os.unlink(settings.MODEL_FILE)
classifier = None
except OSError as e:
logger.error(
f"Error while loading document classification model: {str(e)}"
except OSError:
logger.exception(
f"IO error while loading document classification model"
)
classifier = None
except Exception:
logger.exception(
f"Unknown error while loading document classification model"
)
classifier = None
@@ -74,16 +85,22 @@ class DocumentClassifier(object):
raise IncompatibleClassifierVersionError(
"Cannor load classifier, incompatible versions.")
else:
self.data_hash = pickle.load(f)
self.data_vectorizer = pickle.load(f)
self.tags_binarizer = pickle.load(f)
try:
self.data_hash = pickle.load(f)
self.data_vectorizer = pickle.load(f)
self.tags_binarizer = pickle.load(f)
self.tags_classifier = pickle.load(f)
self.correspondent_classifier = pickle.load(f)
self.document_type_classifier = pickle.load(f)
self.tags_classifier = pickle.load(f)
self.correspondent_classifier = pickle.load(f)
self.document_type_classifier = pickle.load(f)
except Exception:
raise ClassifierModelCorruptError()
def save(self):
with open(settings.MODEL_FILE, "wb") as f:
target_file = settings.MODEL_FILE
target_file_temp = settings.MODEL_FILE + ".part"
with open(target_file_temp, "wb") as f:
pickle.dump(self.FORMAT_VERSION, f)
pickle.dump(self.data_hash, f)
pickle.dump(self.data_vectorizer, f)
@@ -94,6 +111,10 @@ class DocumentClassifier(object):
pickle.dump(self.correspondent_classifier, f)
pickle.dump(self.document_type_classifier, f)
if os.path.isfile(target_file):
os.unlink(target_file)
shutil.move(target_file_temp, target_file)
def train(self):
data = list()

9
src/documents/consumer.py Executable file → Normal file
View File

@@ -333,6 +333,15 @@ class Consumer(LoggingMixin):
self.log("debug", "Deleting file {}".format(self.path))
os.unlink(self.path)
# https://github.com/jonaswinkler/paperless-ng/discussions/1037
shadow_file = os.path.join(
os.path.dirname(self.path),
"._" + os.path.basename(self.path))
if os.path.isfile(shadow_file):
self.log("debug", "Deleting file {}".format(shadow_file))
os.unlink(shadow_file)
except Exception as e:
self._fail(
str(e),

0
src/documents/filters.py Executable file → Normal file
View File

View File

@@ -36,8 +36,19 @@ def _tags_from_path(filepath):
return tag_ids
def _is_ignored(filepath):
# https://github.com/jonaswinkler/paperless-ng/discussions/1037
basename = os.path.basename(filepath)
if basename == ".DS_STORE":
return True
if basename.startswith("._"):
return True
return False
def _consume(filepath):
if os.path.isdir(filepath):
if os.path.isdir(filepath) or _is_ignored(filepath):
return
if not os.path.isfile(filepath):
@@ -71,6 +82,9 @@ def _consume(filepath):
def _consume_wait_unmodified(file):
if _is_ignored(file):
return
logger.debug(f"Waiting for file {file} to remain unmodified")
mtime = -1
current_try = 0

View File

27
src/documents/management/commands/document_retagger.py Executable file → Normal file
View File

@@ -63,8 +63,20 @@ class Command(BaseCommand):
action="store_true",
help="If set, the progress bar will not be shown"
)
parser.add_argument(
"--suggest",
default=False,
action="store_true",
help="Return the suggestion, don't change anything."
)
parser.add_argument(
"--base-url",
help="The base URL to use to build the link to the documents."
)
def handle(self, *args, **options):
# Detect if we support color
color = self.style.ERROR("test") != "test"
if options["inbox_only"]:
queryset = Document.objects.filter(tags__is_inbox_tag=True)
@@ -85,18 +97,27 @@ class Command(BaseCommand):
document=document,
classifier=classifier,
replace=options['overwrite'],
use_first=options['use_first'])
use_first=options['use_first'],
suggest=options['suggest'],
base_url=options['base_url'],
color=color)
if options['document_type']:
set_document_type(sender=None,
document=document,
classifier=classifier,
replace=options['overwrite'],
use_first=options['use_first'])
use_first=options['use_first'],
suggest=options['suggest'],
base_url=options['base_url'],
color=color)
if options['tags']:
set_tags(
sender=None,
document=document,
classifier=classifier,
replace=options['overwrite'])
replace=options['overwrite'],
suggest=options['suggest'],
base_url=options['base_url'],
color=color)

4
src/documents/models.py Executable file → Normal file
View File

@@ -65,10 +65,6 @@ class MatchingModel(models.Model):
class Correspondent(MatchingModel):
# This regex is probably more restrictive than it needs to be, but it's
# better safe than sorry.
SAFE_REGEX = re.compile(r"^[\w\- ,.']+$")
class Meta:
ordering = ("name",)
verbose_name = _("correspondent")

122
src/documents/signals/handlers.py Executable file → Normal file
View File

@@ -1,6 +1,7 @@
import logging
import os
from django.utils import termcolors
from django.conf import settings
from django.contrib.admin.models import ADDITION, LogEntry
from django.contrib.auth.models import User
@@ -8,14 +9,14 @@ from django.contrib.contenttypes.models import ContentType
from django.db import models, DatabaseError
from django.db.models import Q
from django.dispatch import receiver
from django.utils import timezone
from django.utils import termcolors, timezone
from filelock import FileLock
from .. import matching
from ..file_handling import delete_empty_directories, \
create_source_path_directory, \
generate_unique_filename
from ..models import Document, Tag
from ..models import Document, Tag, MatchingModel
logger = logging.getLogger("paperless.handlers")
@@ -32,6 +33,9 @@ def set_correspondent(sender,
classifier=None,
replace=False,
use_first=True,
suggest=False,
base_url=None,
color=False,
**kwargs):
if document.correspondent and not replace:
return
@@ -60,13 +64,31 @@ def set_correspondent(sender,
return
if selected or replace:
logger.info(
f"Assigning correspondent {selected} to {document}",
extra={'group': logging_group}
)
if suggest:
if base_url:
print(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
)
print(f"{base_url}/documents/{document.pk}")
else:
print(
(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
) + f" [{document.pk}]"
)
print(f"Suggest correspondent {selected}")
else:
logger.info(
f"Assigning correspondent {selected} to {document}",
extra={'group': logging_group}
)
document.correspondent = selected
document.save(update_fields=("correspondent",))
document.correspondent = selected
document.save(update_fields=("correspondent",))
def set_document_type(sender,
@@ -75,6 +97,9 @@ def set_document_type(sender,
classifier=None,
replace=False,
use_first=True,
suggest=False,
base_url=None,
color=False,
**kwargs):
if document.document_type and not replace:
return
@@ -104,13 +129,31 @@ def set_document_type(sender,
return
if selected or replace:
logger.info(
f"Assigning document type {selected} to {document}",
extra={'group': logging_group}
)
if suggest:
if base_url:
print(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
)
print(f"{base_url}/documents/{document.pk}")
else:
print(
(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
) + f" [{document.pk}]"
)
print(f"Sugest document type {selected}")
else:
logger.info(
f"Assigning document type {selected} to {document}",
extra={'group': logging_group}
)
document.document_type = selected
document.save(update_fields=("document_type",))
document.document_type = selected
document.save(update_fields=("document_type",))
def set_tags(sender,
@@ -118,6 +161,9 @@ def set_tags(sender,
logging_group=None,
classifier=None,
replace=False,
suggest=False,
base_url=None,
color=False,
**kwargs):
if replace:
@@ -132,16 +178,48 @@ def set_tags(sender,
relevant_tags = set(matched_tags) - current_tags
if not relevant_tags:
return
if suggest:
extra_tags = current_tags - set(matched_tags)
extra_tags = [
t for t in extra_tags
if t.matching_algorithm == MatchingModel.MATCH_AUTO
]
if not relevant_tags and not extra_tags:
return
if base_url:
print(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
)
print(f"{base_url}/documents/{document.pk}")
else:
print(
(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
) + f" [{document.pk}]"
)
if relevant_tags:
print(
"Suggest tags: " + ", ".join([t.name for t in relevant_tags])
)
if extra_tags:
print("Extra tags: " + ", ".join([t.name for t in extra_tags]))
else:
if not relevant_tags:
return
message = 'Tagging "{}" with "{}"'
logger.info(
message.format(document, ", ".join([t.name for t in relevant_tags])),
extra={'group': logging_group}
)
message = 'Tagging "{}" with "{}"'
logger.info(
message.format(
document, ", ".join([t.name for t in relevant_tags])
),
extra={'group': logging_group}
)
document.tags.add(*relevant_tags)
document.tags.add(*relevant_tags)
@receiver(models.signals.post_delete, sender=Document)

File diff suppressed because one or more lines are too long

View File

@@ -317,6 +317,27 @@ class TestConsumer(DirectoriesMixin, TestCase):
self._assert_first_last_send_progress()
@override_settings(PAPERLESS_FILENAME_FORMAT=None)
def testDeleteMacFiles(self):
# https://github.com/jonaswinkler/paperless-ng/discussions/1037
filename = self.get_test_file()
shadow_file = os.path.join(self.dirs.scratch_dir, "._sample.pdf")
shutil.copy(filename, shadow_file)
self.assertTrue(os.path.isfile(shadow_file))
document = self.consumer.try_consume_file(filename)
self.assertTrue(os.path.isfile(
document.source_path
))
self.assertFalse(os.path.isfile(shadow_file))
self.assertFalse(os.path.isfile(filename))
def testOverrideFilename(self):
filename = self.get_test_file()
override_filename = "Statement for November.pdf"

View File

@@ -60,10 +60,10 @@ class ConsumerMixin:
super(ConsumerMixin, self).tearDown()
def wait_for_task_mock_call(self):
def wait_for_task_mock_call(self, excpeted_call_count=1):
n = 0
while n < 100:
if self.task_mock.call_count > 0:
if self.task_mock.call_count >= excpeted_call_count:
# give task_mock some time to finish and raise errors
sleep(1)
return
@@ -202,6 +202,26 @@ class TestConsumer(DirectoriesMixin, ConsumerMixin, TransactionTestCase):
self.assertRaises(CommandError, call_command, 'document_consumer', '--oneshot')
def test_mac_write(self):
self.task_mock.side_effect = self.bogus_task
self.t_start()
shutil.copy(self.sample_file, os.path.join(self.dirs.consumption_dir, ".DS_STORE"))
shutil.copy(self.sample_file, os.path.join(self.dirs.consumption_dir, "my_file.pdf"))
shutil.copy(self.sample_file, os.path.join(self.dirs.consumption_dir, "._my_file.pdf"))
shutil.copy(self.sample_file, os.path.join(self.dirs.consumption_dir, "my_second_file.pdf"))
shutil.copy(self.sample_file, os.path.join(self.dirs.consumption_dir, "._my_second_file.pdf"))
sleep(5)
self.wait_for_task_mock_call(excpeted_call_count=2)
self.assertEqual(2, self.task_mock.call_count)
fnames = [os.path.basename(args[1]) for args, _ in self.task_mock.call_args_list]
self.assertCountEqual(fnames, ["my_file.pdf", "my_second_file.pdf"])
@override_settings(CONSUMER_POLLING=1, CONSUMER_POLLING_DELAY=1, CONSUMER_POLLING_RETRY_COUNT=20)
class TestConsumerPolling(TestConsumer):

View File

@@ -11,14 +11,17 @@ class TestRetagger(DirectoriesMixin, TestCase):
self.d1 = Document.objects.create(checksum="A", title="A", content="first document")
self.d2 = Document.objects.create(checksum="B", title="B", content="second document")
self.d3 = Document.objects.create(checksum="C", title="C", content="unrelated document")
self.d4 = Document.objects.create(checksum="D", title="D", content="auto document")
self.tag_first = Tag.objects.create(name="tag1", match="first", matching_algorithm=Tag.MATCH_ANY)
self.tag_second = Tag.objects.create(name="tag2", match="second", matching_algorithm=Tag.MATCH_ANY)
self.tag_inbox = Tag.objects.create(name="test", is_inbox_tag=True)
self.tag_no_match = Tag.objects.create(name="test2")
self.tag_auto = Tag.objects.create(name="tagauto", matching_algorithm=Tag.MATCH_AUTO)
self.d3.tags.add(self.tag_inbox)
self.d3.tags.add(self.tag_no_match)
self.d4.tags.add(self.tag_auto)
self.correspondent_first = Correspondent.objects.create(
@@ -32,7 +35,8 @@ class TestRetagger(DirectoriesMixin, TestCase):
name="dt2", match="second", matching_algorithm=DocumentType.MATCH_ANY)
def get_updated_docs(self):
return Document.objects.get(title="A"), Document.objects.get(title="B"), Document.objects.get(title="C")
return Document.objects.get(title="A"), Document.objects.get(title="B"), \
Document.objects.get(title="C"), Document.objects.get(title="D")
def setUp(self) -> None:
super(TestRetagger, self).setUp()
@@ -40,25 +44,26 @@ class TestRetagger(DirectoriesMixin, TestCase):
def test_add_tags(self):
call_command('document_retagger', '--tags')
d_first, d_second, d_unrelated = self.get_updated_docs()
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.tags.count(), 1)
self.assertEqual(d_second.tags.count(), 1)
self.assertEqual(d_unrelated.tags.count(), 2)
self.assertEqual(d_auto.tags.count(), 1)
self.assertEqual(d_first.tags.first(), self.tag_first)
self.assertEqual(d_second.tags.first(), self.tag_second)
def test_add_type(self):
call_command('document_retagger', '--document_type')
d_first, d_second, d_unrelated = self.get_updated_docs()
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.document_type, self.doctype_first)
self.assertEqual(d_second.document_type, self.doctype_second)
def test_add_correspondent(self):
call_command('document_retagger', '--correspondent')
d_first, d_second, d_unrelated = self.get_updated_docs()
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.correspondent, self.correspondent_first)
self.assertEqual(d_second.correspondent, self.correspondent_second)
@@ -68,11 +73,55 @@ class TestRetagger(DirectoriesMixin, TestCase):
call_command('document_retagger', '--tags', '--overwrite')
d_first, d_second, d_unrelated = self.get_updated_docs()
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertIsNotNone(Tag.objects.get(id=self.tag_second.id))
self.assertCountEqual([tag.id for tag in d_first.tags.all()], [self.tag_first.id])
self.assertCountEqual([tag.id for tag in d_second.tags.all()], [self.tag_second.id])
self.assertCountEqual([tag.id for tag in d_unrelated.tags.all()], [self.tag_inbox.id, self.tag_no_match.id])
self.assertEqual(d_auto.tags.count(), 0)
def test_add_tags_suggest(self):
call_command('document_retagger', '--tags', '--suggest')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.tags.count(), 0)
self.assertEqual(d_second.tags.count(), 0)
self.assertEqual(d_auto.tags.count(), 1)
def test_add_type_suggest(self):
call_command('document_retagger', '--document_type', '--suggest')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.document_type, None)
self.assertEqual(d_second.document_type, None)
def test_add_correspondent_suggest(self):
call_command('document_retagger', '--correspondent', '--suggest')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.correspondent, None)
self.assertEqual(d_second.correspondent, None)
def test_add_tags_suggest_url(self):
call_command('document_retagger', '--tags', '--suggest', '--base-url=http://localhost')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.tags.count(), 0)
self.assertEqual(d_second.tags.count(), 0)
self.assertEqual(d_auto.tags.count(), 1)
def test_add_type_suggest_url(self):
call_command('document_retagger', '--document_type', '--suggest', '--base-url=http://localhost')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.document_type, None)
self.assertEqual(d_second.document_type, None)
def test_add_correspondent_suggest_url(self):
call_command('document_retagger', '--correspondent', '--suggest', '--base-url=http://localhost')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.correspondent, None)
self.assertEqual(d_second.correspondent, None)

Some files were not shown because too many files have changed in this diff Show More