mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-08-01 18:37:42 -05:00
Compare commits
47 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
37e0c2667b | ||
![]() |
252abb41c3 | ||
![]() |
fb2af341d8 | ||
![]() |
931f5f9c27 | ||
![]() |
b5d04e575e | ||
![]() |
3d395601fe | ||
![]() |
6630ce646c | ||
![]() |
f5508eea1c | ||
![]() |
c8c460432f | ||
![]() |
18299dafd2 | ||
![]() |
817d09026e | ||
![]() |
d76b009390 | ||
![]() |
9effed3ce1 | ||
![]() |
c1bbfc5dcf | ||
![]() |
b6c9cfb76f | ||
![]() |
59ca7bbcf2 | ||
![]() |
52c8d5e999 | ||
![]() |
5851e7f1b7 | ||
![]() |
e05b3441de | ||
![]() |
0d6e79cb93 | ||
![]() |
76a102d901 | ||
![]() |
0880420ef6 | ||
![]() |
2351c79282 | ||
![]() |
d6016fc798 | ||
![]() |
bc17291006 | ||
![]() |
ed6cb14c4d | ||
![]() |
08de8a04b8 | ||
![]() |
5c67de8b47 | ||
![]() |
38b0408b1a | ||
![]() |
9ccad7ea86 | ||
![]() |
4a4e810a14 | ||
![]() |
76d2df3bde | ||
![]() |
c02563d894 | ||
![]() |
574ec6780b | ||
![]() |
9e0f56982b | ||
![]() |
1c66daf12b | ||
![]() |
59d683849e | ||
![]() |
9946acb1a0 | ||
![]() |
83a760644d | ||
![]() |
25ccff8640 | ||
![]() |
5c4c5a7794 | ||
![]() |
cb6af97595 | ||
![]() |
c4407dccf6 | ||
![]() |
ecdea4c3c8 | ||
![]() |
26d6f302cf | ||
![]() |
ecf10622ef | ||
![]() |
0fb553675b |
14
.codecov.yml
14
.codecov.yml
@@ -1,3 +1,17 @@
|
||||
codecov:
|
||||
require_ci_to_pass: true
|
||||
# https://docs.codecov.com/docs/flags#recommended-automatic-flag-management
|
||||
# Require each flag to have 1 upload before notification
|
||||
flag_management:
|
||||
default_rules:
|
||||
after_n_builds: 1
|
||||
individual_flags:
|
||||
- name: backend
|
||||
paths:
|
||||
- src/
|
||||
- name: frontend
|
||||
paths:
|
||||
- src-ui/
|
||||
# https://docs.codecov.com/docs/pull-request-comments
|
||||
# codecov will only comment if coverage changes
|
||||
comment:
|
||||
|
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -20,11 +20,16 @@ NOTE: Please check only one box!
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Other (please explain)
|
||||
- [ ] Other (please explain):
|
||||
|
||||
## Checklist:
|
||||
|
||||
<!--
|
||||
NOTE: PRs that do not address the following will not be merged, please do not skip any relevant items.
|
||||
-->
|
||||
|
||||
- [ ] I have read & agree with the [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md).
|
||||
- [ ] If applicable, I have included testing coverage for new code in this PR, for [backend](https://docs.paperless-ngx.com/development/#testing) and / or [front-end](https://docs.paperless-ngx.com/development/#testing-and-code-style) changes.
|
||||
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.
|
||||
- [ ] If applicable, I have checked that all tests pass, see [documentation](https://docs.paperless-ngx.com/development/#back-end-development).
|
||||
- [ ] I have run all `pre-commit` hooks, see [documentation](https://docs.paperless-ngx.com/development/#code-formatting-with-pre-commit-hooks).
|
||||
|
23
.github/stale.yml
vendored
23
.github/stale.yml
vendored
@@ -1,23 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 30
|
||||
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
|
||||
# Only issues or pull requests with any of these labels are check if stale. Defaults to `[]` (disabled)
|
||||
any-of-labels: ['cant-reproduce','not a bug','unconfirmed']
|
||||
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
|
||||
# See https://github.com/marketplace/stale for more info on the app
|
||||
# and https://github.com/probot/stale for the configuration docs
|
6
.github/workflows/repo-maintenance.yml
vendored
6
.github/workflows/repo-maintenance.yml
vendored
@@ -19,9 +19,9 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
days-before-stale: 30
|
||||
days-before-close: 7
|
||||
only-labels: 'cant-reproduce'
|
||||
days-before-stale: 7
|
||||
days-before-close: 14
|
||||
any-of-labels: 'cant-reproduce,not a bug'
|
||||
stale-issue-label: stale
|
||||
stale-pr-label: stale
|
||||
stale-issue-message: >
|
||||
|
1
Pipfile
1
Pipfile
@@ -66,6 +66,7 @@ scipy = "==1.8.1"
|
||||
reportlab = "==3.6.12"
|
||||
# Pin this until piwheels is building a newer version (see https://www.piwheels.org/project/cryptography/)
|
||||
cryptography = "==40.0.1"
|
||||
httpx = "*"
|
||||
|
||||
[dev-packages]
|
||||
# Linting
|
||||
|
10
Pipfile.lock
generated
10
Pipfile.lock
generated
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "db3fc8c37931534327f89c6211581495328b6f6bf2c533df848fa23faa5d0cd3"
|
||||
"sha256": "e63cdbb928210fc4dcf0554bde381abd0ff956923ae03ab9f6984025cd5a454d"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
@@ -712,7 +712,7 @@
|
||||
"sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd",
|
||||
"sha256:5853a43053df830c20f8110c5e69fe44d035d850b2dfe795e196f00fdb774bdd"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"index": "pypi",
|
||||
"version": "==0.24.1"
|
||||
},
|
||||
"humanfriendly": {
|
||||
@@ -1746,11 +1746,11 @@
|
||||
},
|
||||
"tika-client": {
|
||||
"hashes": [
|
||||
"sha256:29b702d64bbbaa324a75f99062efb3253239762cbf0a3419a47549c2de9379d0",
|
||||
"sha256:63a93593068dc0da07108dc47c12cd3ff00f07403cff72c86bea6a89abafbf6d"
|
||||
"sha256:6110bd73eaa133f9c8eb1ef2566e6c0c8123a0e4efbcfb85b86f8c1b26cb4de2",
|
||||
"sha256:e8eaa52771c72426f5531c53dcc8dfc5e3bb6e1f91f89fc93674a81bfca59d6d"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.1.1"
|
||||
"version": "==0.2.0"
|
||||
},
|
||||
"tornado": {
|
||||
"hashes": [
|
||||
|
@@ -37,7 +37,7 @@ services:
|
||||
- redisdata:/data
|
||||
|
||||
db:
|
||||
image: docker.io/library/postgres:13
|
||||
image: docker.io/library/postgres:15
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
|
@@ -39,7 +39,7 @@ services:
|
||||
- redisdata:/data
|
||||
|
||||
db:
|
||||
image: docker.io/library/postgres:13
|
||||
image: docker.io/library/postgres:15
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
|
@@ -35,7 +35,7 @@ services:
|
||||
- redisdata:/data
|
||||
|
||||
db:
|
||||
image: docker.io/library/postgres:13
|
||||
image: docker.io/library/postgres:15
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
|
@@ -15,6 +15,7 @@ stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment = HOME="/usr/src/paperless",USER="paperless"
|
||||
|
||||
[program:consumer]
|
||||
command=python3 manage.py document_consumer
|
||||
@@ -25,6 +26,7 @@ stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment = HOME="/usr/src/paperless",USER="paperless"
|
||||
|
||||
[program:celery]
|
||||
|
||||
@@ -37,6 +39,7 @@ stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment = HOME="/usr/src/paperless",USER="paperless"
|
||||
|
||||
[program:celery-beat]
|
||||
|
||||
@@ -48,6 +51,7 @@ stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment = HOME="/usr/src/paperless",USER="paperless"
|
||||
|
||||
[program:celery-flower]
|
||||
command = /usr/local/bin/flower-conditional.sh
|
||||
@@ -58,3 +62,4 @@ stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
environment = HOME="/usr/src/paperless",USER="paperless"
|
||||
|
@@ -167,6 +167,16 @@ following:
|
||||
This might not actually do anything. Not every new paperless version
|
||||
comes with new database migrations.
|
||||
|
||||
### Database Upgrades
|
||||
|
||||
In general, paperless does not require a specific version of PostgreSQL or MariaDB and it is
|
||||
safe to update them to newer versions. However, you should always take a backup and follow
|
||||
the instructions from your database's documentation for how to upgrade between major versions.
|
||||
|
||||
For PostgreSQL, refer to [Upgrading a PostgreSQL Cluster](https://www.postgresql.org/docs/current/upgrading.html).
|
||||
|
||||
For MariaDB, refer to [Upgrading MariaDB](https://mariadb.com/kb/en/upgrading/)
|
||||
|
||||
## Downgrading Paperless {#downgrade-paperless}
|
||||
|
||||
Downgrades are possible. However, some updates also contain database
|
||||
|
13
docs/api.md
13
docs/api.md
@@ -288,10 +288,23 @@ with an optional `set_permissions` parameter which is of the form:
|
||||
}
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
Arrays should contain user or group ID numbers.
|
||||
|
||||
If this parameter is supplied the object's permissions will be overwritten,
|
||||
assuming the authenticated user has permission to do so (the user must be
|
||||
the object owner or a superuser).
|
||||
|
||||
### Retrieving full permissions
|
||||
|
||||
By default, the API will return a truncated version of object-level
|
||||
permissions, returning `user_can_change` indicating whether the current user
|
||||
can edit the object (either because they are the object owner or have permissions
|
||||
granted). You can pass the parameter `full_perms=true` to API calls to view the
|
||||
full permissions of objects in a format that mirrors the `set_permissions`
|
||||
parameter above.
|
||||
|
||||
## API Versioning
|
||||
|
||||
The REST API is versioned since Paperless-ngx 1.3.0.
|
||||
|
@@ -1,5 +1,82 @@
|
||||
# Changelog
|
||||
|
||||
## paperless-ngx 1.16.4
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: prevent button wrapping when sidebar narrows in MS Edge [@shamoon](https://github.com/shamoon) ([#3682](https://github.com/paperless-ngx/paperless-ngx/pull/3682))
|
||||
- Fix: Handling for filenames with non-ascii and no content attribute [@stumpylog](https://github.com/stumpylog) ([#3695](https://github.com/paperless-ngx/paperless-ngx/pull/3695))
|
||||
- Fix: Generation of thumbnails for existing stored emails [@stumpylog](https://github.com/stumpylog) ([#3696](https://github.com/paperless-ngx/paperless-ngx/pull/3696))
|
||||
- Fix: Use row gap for filter editor [@kleinweby](https://github.com/kleinweby) ([#3662](https://github.com/paperless-ngx/paperless-ngx/pull/3662))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Documentation: update API docs re permissions [@shamoon](https://github.com/shamoon) ([#3697](https://github.com/paperless-ngx/paperless-ngx/pull/3697))
|
||||
|
||||
### Maintenance
|
||||
|
||||
- Chore: Updates codecov configuration for the flag settings and notification delay [@stumpylog](https://github.com/stumpylog) ([#3656](https://github.com/paperless-ngx/paperless-ngx/pull/3656))
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>4 changes</summary>
|
||||
|
||||
- Fix: prevent button wrapping when sidebar narrows in MS Edge [@shamoon](https://github.com/shamoon) ([#3682](https://github.com/paperless-ngx/paperless-ngx/pull/3682))
|
||||
- Fix: Handling for filenames with non-ascii and no content attribute [@stumpylog](https://github.com/stumpylog) ([#3695](https://github.com/paperless-ngx/paperless-ngx/pull/3695))
|
||||
- Fix: Generation of thumbnails for existing stored emails [@stumpylog](https://github.com/stumpylog) ([#3696](https://github.com/paperless-ngx/paperless-ngx/pull/3696))
|
||||
- Fix: Use row gap for filter editor [@kleinweby](https://github.com/kleinweby) ([#3662](https://github.com/paperless-ngx/paperless-ngx/pull/3662))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 1.16.3
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: Set user and home environment through supervisord [@stumpylog](https://github.com/stumpylog) ([#3638](https://github.com/paperless-ngx/paperless-ngx/pull/3638))
|
||||
- Fix: Ignore errors when trying to copy the original file's stats [@stumpylog](https://github.com/stumpylog) ([#3652](https://github.com/paperless-ngx/paperless-ngx/pull/3652))
|
||||
- Fix: Copy default thumbnail if thumbnail generation fails [@plu](https://github.com/plu) ([#3632](https://github.com/paperless-ngx/paperless-ngx/pull/3632))
|
||||
- Fix: Set user and home environment through supervisord [@stumpylog](https://github.com/stumpylog) ([#3638](https://github.com/paperless-ngx/paperless-ngx/pull/3638))
|
||||
- Fix: Fix quick install with external database not being fully ready [@stumpylog](https://github.com/stumpylog) ([#3637](https://github.com/paperless-ngx/paperless-ngx/pull/3637))
|
||||
|
||||
### Maintenance
|
||||
|
||||
- Chore: Update default Postgres version for new installs [@stumpylog](https://github.com/stumpylog) ([#3640](https://github.com/paperless-ngx/paperless-ngx/pull/3640))
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>2 changes</summary>
|
||||
|
||||
- Fix: Ignore errors when trying to copy the original file's stats [@stumpylog](https://github.com/stumpylog) ([#3652](https://github.com/paperless-ngx/paperless-ngx/pull/3652))
|
||||
- Fix: Copy default thumbnail if thumbnail generation fails [@plu](https://github.com/plu) ([#3632](https://github.com/paperless-ngx/paperless-ngx/pull/3632))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 1.16.2
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: Increase httpx operation timeouts to 30s [@stumpylog](https://github.com/stumpylog) ([#3627](https://github.com/paperless-ngx/paperless-ngx/pull/3627))
|
||||
- Fix: Better error handling and checking when parsing documents via Tika [@stumpylog](https://github.com/stumpylog) ([#3617](https://github.com/paperless-ngx/paperless-ngx/pull/3617))
|
||||
|
||||
### Development
|
||||
|
||||
- Development: frontend unit testing [@shamoon](https://github.com/shamoon) ([#3597](https://github.com/paperless-ngx/paperless-ngx/pull/3597))
|
||||
|
||||
### Maintenance
|
||||
|
||||
- Chore: Bumps the CI/Docker pipenv version [@stumpylog](https://github.com/stumpylog) ([#3622](https://github.com/paperless-ngx/paperless-ngx/pull/3622))
|
||||
- Chore: Set CI artifact retention days [@stumpylog](https://github.com/stumpylog) ([#3621](https://github.com/paperless-ngx/paperless-ngx/pull/3621))
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>3 changes</summary>
|
||||
|
||||
- Fix: Increase httpx operation timeouts to 30s [@stumpylog](https://github.com/stumpylog) ([#3627](https://github.com/paperless-ngx/paperless-ngx/pull/3627))
|
||||
- Fix: Better error handling and checking when parsing documents via Tika [@stumpylog](https://github.com/stumpylog) ([#3617](https://github.com/paperless-ngx/paperless-ngx/pull/3617))
|
||||
- Development: frontend unit testing [@shamoon](https://github.com/shamoon) ([#3597](https://github.com/paperless-ngx/paperless-ngx/pull/3597))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 1.16.1
|
||||
|
||||
### Bug Fixes
|
||||
|
@@ -1095,6 +1095,27 @@ barcode.
|
||||
|
||||
Defaults to "ASN"
|
||||
|
||||
`PAPERLESS_CONSUMER_BARCODE_UPSCALE=<float>`
|
||||
|
||||
: Defines the upscale factor used in barcode detection.
|
||||
Improves the detection of small barcodes, i.e. with a value of 1.5 by
|
||||
upscaling the document beforce the detection process. Upscaling will
|
||||
only take place if value is bigger than 1.0. Otherwise upscaling will
|
||||
not be performed to save resources. Try using in combination with
|
||||
PAPERLESS_CONSUMER_BARCODE_DPI set to a value higher than default.
|
||||
|
||||
Defaults to 0.0
|
||||
|
||||
`PAPERLESS_CONSUMER_BARCODE_DPI=<int>`
|
||||
|
||||
: During barcode detection every page from a PDF document needs
|
||||
to be converted to an image. A dpi value can be specified in the
|
||||
conversion process. Default is 300. If the detection of small barcodes
|
||||
fails a bigger dpi value i.e. 600 can fix the issue. Try using in
|
||||
combination with PAPERLESS_CONSUMER_BARCODE_UPSCALE bigger than 1.0.
|
||||
|
||||
Defaults to "300"
|
||||
|
||||
## Binaries
|
||||
|
||||
There are a few external software packages that Paperless expects to
|
||||
|
@@ -384,6 +384,14 @@ fi
|
||||
|
||||
${DOCKER_COMPOSE_CMD} pull
|
||||
|
||||
if [ "$DATABASE_BACKEND" == "postgres" ] || [ "$DATABASE_BACKEND" == "mariadb" ] ; then
|
||||
echo "Starting DB first for initilzation"
|
||||
${DOCKER_COMPOSE_CMD} up --detach db
|
||||
# hopefully enough time for even the slower systems
|
||||
sleep 15
|
||||
${DOCKER_COMPOSE_CMD} stop
|
||||
fi
|
||||
|
||||
${DOCKER_COMPOSE_CMD} run --rm -e DJANGO_SUPERUSER_PASSWORD="$PASSWORD" webserver createsuperuser --noinput --username "$USERNAME" --email "$EMAIL"
|
||||
|
||||
${DOCKER_COMPOSE_CMD} up --detach
|
||||
|
@@ -66,6 +66,8 @@
|
||||
#PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=false
|
||||
#PAPERLESS_CONSUMER_ENABLE_BARCODES=false
|
||||
#PAPERLESS_CONSUMER_BARCODE_STRING=PATCHT
|
||||
#PAPERLESS_CONSUMER_BARCODE_UPSCALE=0.0
|
||||
#PAPERLESS_CONSUMER_BARCODE_DPI=300
|
||||
#PAPERLESS_PRE_CONSUME_SCRIPT=/path/to/an/arbitrary/script.sh
|
||||
#PAPERLESS_POST_CONSUME_SCRIPT=/path/to/an/arbitrary/script.sh
|
||||
#PAPERLESS_FILENAME_DATE_ORDER=YMD
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
docker run -p 5432:5432 -e POSTGRES_PASSWORD=password -v paperless_pgdata:/var/lib/postgresql/data -d postgres:13
|
||||
docker run -p 5432:5432 -e POSTGRES_PASSWORD=password -v paperless_pgdata:/var/lib/postgresql/data -d postgres:15
|
||||
docker run -d -p 6379:6379 redis:latest
|
||||
docker run -p 3000:3000 -d gotenberg/gotenberg:7.8 gotenberg --chromium-disable-javascript=true --chromium-allow-list="file:///tmp/.*"
|
||||
docker run -p 9998:9998 -d ghcr.io/paperless-ngx/tika:latest
|
||||
|
@@ -578,7 +578,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">27</context>
|
||||
<context context-type="linenumber">26</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3079652255369035" datatype="html">
|
||||
@@ -1150,7 +1150,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">77</context>
|
||||
<context context-type="linenumber">76</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7878445132438733225" datatype="html">
|
||||
@@ -1916,17 +1916,6 @@
|
||||
</context-group>
|
||||
<note priority="1" from="description">Filter drop down element to filter for documents with no correspondent/type/tag assigned</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="2088622872854972056" datatype="html">
|
||||
<source>Filter documents with this <x id="INTERPOLATION" equiv-text="{{title}}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context>
|
||||
<context context-type="linenumber">12</context>
|
||||
</context-group>
|
||||
<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-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="445302259125375799" datatype="html">
|
||||
<source>Invalid date.</source>
|
||||
<context-group purpose="location">
|
||||
@@ -1949,6 +1938,17 @@
|
||||
<context context-type="linenumber">47</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6344437738844463465" datatype="html">
|
||||
<source>Filter documents with this <x id="PH" equiv-text="this.title"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/input/date/date.component.ts</context>
|
||||
<context context-type="linenumber">103</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/input/select/select.component.ts</context>
|
||||
<context context-type="linenumber">149</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="594042705136125260" datatype="html">
|
||||
<source>Edit Permissions</source>
|
||||
<context-group purpose="location">
|
||||
@@ -2269,7 +2269,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">63</context>
|
||||
<context context-type="linenumber">62</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/tasks/tasks.component.html</context>
|
||||
@@ -2585,7 +2585,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">36</context>
|
||||
<context context-type="linenumber">35</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
|
||||
@@ -2608,7 +2608,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">44</context>
|
||||
<context context-type="linenumber">43</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
|
||||
@@ -2631,7 +2631,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">52</context>
|
||||
<context context-type="linenumber">51</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5607669932062416162" datatype="html">
|
||||
@@ -2978,7 +2978,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">28</context>
|
||||
<context context-type="linenumber">27</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="184185893993764098" datatype="html">
|
||||
@@ -2989,7 +2989,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">37</context>
|
||||
<context context-type="linenumber">36</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2947613869920454977" datatype="html">
|
||||
@@ -3000,7 +3000,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">45</context>
|
||||
<context context-type="linenumber">44</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8816999377397522522" datatype="html">
|
||||
@@ -3011,7 +3011,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">53</context>
|
||||
<context context-type="linenumber">52</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3193976279273491157" datatype="html">
|
||||
@@ -3474,7 +3474,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">85</context>
|
||||
<context context-type="linenumber">84</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1559883523769732271" datatype="html">
|
||||
@@ -3596,7 +3596,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||
<context context-type="linenumber">69</context>
|
||||
<context context-type="linenumber">68</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/services/rest/document.service.ts</context>
|
||||
|
@@ -137,6 +137,7 @@ main {
|
||||
|
||||
.sidebar .nav-link {
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover, &.active, &:focus {
|
||||
color: var(--bs-primary);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button *ngIf="showFilter" class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="this.value === null" i18n-title title="Filter documents with this {{title}}">
|
||||
<button *ngIf="showFilter" class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="this.value === null" title="{{ fitlerButtonTitle }}">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#filter" />
|
||||
</svg>
|
||||
|
@@ -98,4 +98,8 @@ export class DateComponent
|
||||
onFilterDocuments() {
|
||||
this.filterDocuments.emit([this.ngbDateParserFormatter.parse(this.value)])
|
||||
}
|
||||
|
||||
get filterButtonTitle() {
|
||||
return $localize`Filter documents with this ${this.title}`
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@
|
||||
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
||||
</svg>
|
||||
</button>
|
||||
<button *ngIf="showFilter" class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="isPrivate || this.value === null" i18n-title title="Filter documents with this {{title}}">
|
||||
<button *ngIf="showFilter" class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="isPrivate || this.value === null" title="{{ filterButtonTitle }}">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#filter" />
|
||||
</svg>
|
||||
|
@@ -144,4 +144,8 @@ export class SelectComponent extends AbstractInputComponent<number> {
|
||||
onFilterDocuments() {
|
||||
this.filterDocuments.emit([this.items.find((i) => i.id === this.value)])
|
||||
}
|
||||
|
||||
get filterButtonTitle() {
|
||||
return $localize`Filter documents with this ${this.title}`
|
||||
}
|
||||
}
|
||||
|
@@ -1,90 +1,89 @@
|
||||
<div class="row flex-wrap" tourAnchor="tour.documents-filter-editor">
|
||||
<div class="col mb-3 mb-xxl-0">
|
||||
<div class="form-inline d-flex align-items-center">
|
||||
<div class="input-group input-group-sm flex-fill w-auto flex-nowrap">
|
||||
<div ngbDropdown>
|
||||
<button class="btn btn-sm 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>
|
||||
<div class="row flex-wrap row-gap-3" tourAnchor="tour.documents-filter-editor">
|
||||
<div class="col">
|
||||
<div class="form-inline d-flex align-items-center">
|
||||
<div class="input-group input-group-sm flex-fill w-auto flex-nowrap">
|
||||
<div ngbDropdown>
|
||||
<button class="btn btn-sm 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>
|
||||
<select *ngIf="textFilterTarget === 'asn'" class="form-select flex-grow-0 w-auto" [(ngModel)]="textFilterModifier" (change)="textFilterModifierChange()">
|
||||
<option *ngFor="let m of textFilterModifiers" ngbDropdownItem [value]="m.id">{{m.label}}</option>
|
||||
</select>
|
||||
<button *ngIf="_textFilter" class="btn btn-link btn-sm px-0 position-absolute top-0 end-0 z-10" (click)="resetTextField()">
|
||||
<svg fill="currentColor" class="buttonicon-sm me-1">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg>
|
||||
</button>
|
||||
<input #textFilterInput class="form-control form-control-sm" type="text" [disabled]="textFilterModifierIsNull" [(ngModel)]="textFilter" (keyup)="textFilterKeyup($event)" [readonly]="textFilterTarget === 'fulltext-morelike'">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<select *ngIf="textFilterTarget === 'asn'" class="form-select flex-grow-0 w-auto" [(ngModel)]="textFilterModifier" (change)="textFilterModifierChange()">
|
||||
<option *ngFor="let m of textFilterModifiers" ngbDropdownItem [value]="m.id">{{m.label}}</option>
|
||||
</select>
|
||||
<button *ngIf="_textFilter" class="btn btn-link btn-sm px-0 position-absolute top-0 end-0 z-10" (click)="resetTextField()">
|
||||
<svg fill="currentColor" class="buttonicon-sm me-1">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg>
|
||||
</button>
|
||||
<input #textFilterInput class="form-control form-control-sm" type="text" [disabled]="textFilterModifierIsNull" [(ngModel)]="textFilter" (keyup)="textFilterKeyup($event)" [readonly]="textFilterTarget === 'fulltext-morelike'">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="d-flex flex-wrap gap-3">
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<app-filterable-dropdown class="flex-fill" title="Tags" icon="tag-fill" i18n-title
|
||||
filterPlaceholder="Filter tags" i18n-filterPlaceholder
|
||||
[items]="tags"
|
||||
[manyToOne]="true"
|
||||
[(selectionModel)]="tagSelectionModel"
|
||||
(selectionModelChange)="updateRules()"
|
||||
(opened)="onTagsDropdownOpen()"
|
||||
[documentCounts]="tagDocumentCounts"
|
||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||
<app-filterable-dropdown class="flex-fill" title="Correspondent" icon="person-fill" i18n-title
|
||||
filterPlaceholder="Filter correspondents" i18n-filterPlaceholder
|
||||
[items]="correspondents"
|
||||
[(selectionModel)]="correspondentSelectionModel"
|
||||
(selectionModelChange)="updateRules()"
|
||||
(opened)="onCorrespondentDropdownOpen()"
|
||||
[documentCounts]="correspondentDocumentCounts"
|
||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||
<app-filterable-dropdown class="flex-fill" title="Document type" icon="file-earmark-fill" i18n-title
|
||||
filterPlaceholder="Filter document types" i18n-filterPlaceholder
|
||||
[items]="documentTypes"
|
||||
[(selectionModel)]="documentTypeSelectionModel"
|
||||
(selectionModelChange)="updateRules()"
|
||||
(opened)="onDocumentTypeDropdownOpen()"
|
||||
[documentCounts]="documentTypeDocumentCounts"
|
||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||
<app-filterable-dropdown class="flex-fill" title="Storage path" icon="folder-fill" i18n-title
|
||||
filterPlaceholder="Filter storage paths" i18n-filterPlaceholder
|
||||
[items]="storagePaths"
|
||||
[(selectionModel)]="storagePathSelectionModel"
|
||||
(selectionModelChange)="updateRules()"
|
||||
(opened)="onStoragePathDropdownOpen()"
|
||||
[documentCounts]="storagePathDocumentCounts"
|
||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<app-date-dropdown
|
||||
title="Created" i18n-title
|
||||
(datesSet)="updateRules()"
|
||||
[(dateBefore)]="dateCreatedBefore"
|
||||
[(dateAfter)]="dateCreatedAfter"
|
||||
[(relativeDate)]="dateCreatedRelativeDate"></app-date-dropdown>
|
||||
<app-date-dropdown
|
||||
title="Added" i18n-title
|
||||
(datesSet)="updateRules()"
|
||||
[(dateBefore)]="dateAddedBefore"
|
||||
[(dateAfter)]="dateAddedAfter"
|
||||
[(relativeDate)]="dateAddedRelativeDate"></app-date-dropdown>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap">
|
||||
<app-permissions-filter-dropdown
|
||||
title="Permissions" i18n-title
|
||||
(ownerFilterSet)="updateRules()"
|
||||
[(selectionModel)]="permissionsSelectionModel"></app-permissions-filter-dropdown>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap d-none d-sm-inline-block">
|
||||
<button class="btn btn-outline-secondary btn-sm" [disabled]="!rulesModified" (click)="resetSelected()">
|
||||
<svg class="toolbaricon ms-n1" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"></use>
|
||||
</svg><ng-container i18n>Reset filters</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-100 d-xxl-none"></div>
|
||||
<div class="col col-xl-auto">
|
||||
<div class="d-flex flex-wrap gap-3">
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<app-filterable-dropdown class="flex-fill" title="Tags" icon="tag-fill" i18n-title
|
||||
filterPlaceholder="Filter tags" i18n-filterPlaceholder
|
||||
[items]="tags"
|
||||
[manyToOne]="true"
|
||||
[(selectionModel)]="tagSelectionModel"
|
||||
(selectionModelChange)="updateRules()"
|
||||
(opened)="onTagsDropdownOpen()"
|
||||
[documentCounts]="tagDocumentCounts"
|
||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||
<app-filterable-dropdown class="flex-fill" title="Correspondent" icon="person-fill" i18n-title
|
||||
filterPlaceholder="Filter correspondents" i18n-filterPlaceholder
|
||||
[items]="correspondents"
|
||||
[(selectionModel)]="correspondentSelectionModel"
|
||||
(selectionModelChange)="updateRules()"
|
||||
(opened)="onCorrespondentDropdownOpen()"
|
||||
[documentCounts]="correspondentDocumentCounts"
|
||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||
<app-filterable-dropdown class="flex-fill" title="Document type" icon="file-earmark-fill" i18n-title
|
||||
filterPlaceholder="Filter document types" i18n-filterPlaceholder
|
||||
[items]="documentTypes"
|
||||
[(selectionModel)]="documentTypeSelectionModel"
|
||||
(selectionModelChange)="updateRules()"
|
||||
(opened)="onDocumentTypeDropdownOpen()"
|
||||
[documentCounts]="documentTypeDocumentCounts"
|
||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||
<app-filterable-dropdown class="flex-fill" title="Storage path" icon="folder-fill" i18n-title
|
||||
filterPlaceholder="Filter storage paths" i18n-filterPlaceholder
|
||||
[items]="storagePaths"
|
||||
[(selectionModel)]="storagePathSelectionModel"
|
||||
(selectionModelChange)="updateRules()"
|
||||
(opened)="onStoragePathDropdownOpen()"
|
||||
[documentCounts]="storagePathDocumentCounts"
|
||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<app-date-dropdown
|
||||
title="Created" i18n-title
|
||||
(datesSet)="updateRules()"
|
||||
[(dateBefore)]="dateCreatedBefore"
|
||||
[(dateAfter)]="dateCreatedAfter"
|
||||
[(relativeDate)]="dateCreatedRelativeDate"></app-date-dropdown>
|
||||
<app-date-dropdown
|
||||
title="Added" i18n-title
|
||||
(datesSet)="updateRules()"
|
||||
[(dateBefore)]="dateAddedBefore"
|
||||
[(dateAfter)]="dateAddedAfter"
|
||||
[(relativeDate)]="dateAddedRelativeDate"></app-date-dropdown>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap">
|
||||
<app-permissions-filter-dropdown
|
||||
title="Permissions" i18n-title
|
||||
(ownerFilterSet)="updateRules()"
|
||||
[(selectionModel)]="permissionsSelectionModel"></app-permissions-filter-dropdown>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap d-none d-sm-inline-block">
|
||||
<button class="btn btn-outline-secondary btn-sm" [disabled]="!rulesModified" (click)="resetSelected()">
|
||||
<svg class="toolbaricon ms-n1" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"></use>
|
||||
</svg><ng-container i18n>Reset filters</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -5,7 +5,7 @@ export const environment = {
|
||||
apiBaseUrl: document.baseURI + 'api/',
|
||||
apiVersion: '3',
|
||||
appTitle: 'Paperless-ngx',
|
||||
version: '1.16.2',
|
||||
version: '1.16.5',
|
||||
webSocketHost: window.location.host,
|
||||
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
|
||||
webSocketBaseUrl: base_url.pathname + 'ws/',
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -203,11 +203,21 @@ class BarcodeReader:
|
||||
try:
|
||||
pages_from_path = convert_from_path(
|
||||
self.pdf_file,
|
||||
dpi=300,
|
||||
dpi=settings.CONSUMER_BARCODE_DPI,
|
||||
output_folder=self.temp_dir.name,
|
||||
)
|
||||
|
||||
for current_page_number, page in enumerate(pages_from_path):
|
||||
factor = settings.CONSUMER_BARCODE_UPSCALE
|
||||
if factor > 1.0:
|
||||
logger.debug(
|
||||
f"Upscaling image by {factor} for better barcode detection",
|
||||
)
|
||||
x, y = page.size
|
||||
page = page.resize(
|
||||
(int(round(x * factor)), (int(round(y * factor)))),
|
||||
)
|
||||
|
||||
for barcode_value in reader(page):
|
||||
self.barcodes.append(
|
||||
Barcode(current_page_number, barcode_value),
|
||||
|
@@ -582,7 +582,12 @@ class Consumer(LoggingMixin):
|
||||
def _write(self, storage_type, source, target):
|
||||
with open(source, "rb") as read_file, open(target, "wb") as write_file:
|
||||
write_file.write(read_file.read())
|
||||
shutil.copystat(source, target)
|
||||
|
||||
# Attempt to copy file's original stats, but it's ok if we can't
|
||||
try:
|
||||
shutil.copystat(source, target)
|
||||
except Exception: # pragma: no cover
|
||||
pass
|
||||
|
||||
def _log_script_outputs(self, completed_process: CompletedProcess):
|
||||
"""
|
||||
|
@@ -202,7 +202,12 @@ def make_thumbnail_from_pdf_gs_fallback(in_path, temp_dir, logging_group=None) -
|
||||
return out_path
|
||||
|
||||
except ParseError:
|
||||
return get_default_thumbnail()
|
||||
# The caller might expect a generated thumbnail that can be moved,
|
||||
# so we need to copy it before it gets moved.
|
||||
# https://github.com/paperless-ngx/paperless-ngx/issues/3631
|
||||
default_thumbnail_path = os.path.join(temp_dir, "document.png")
|
||||
shutil.copy2(get_default_thumbnail(), default_thumbnail_path)
|
||||
return default_thumbnail_path
|
||||
|
||||
|
||||
def make_thumbnail_from_pdf(in_path, temp_dir, logging_group=None) -> str:
|
||||
|
@@ -213,15 +213,12 @@ class OwnedObjectSerializer(serializers.ModelSerializer, SetPermissionsMixin):
|
||||
# other methods in mixin
|
||||
|
||||
def create(self, validated_data):
|
||||
if self.user and (
|
||||
"owner" not in validated_data or validated_data["owner"] is None
|
||||
):
|
||||
# default to current user if not set
|
||||
if "owner" not in validated_data and self.user:
|
||||
validated_data["owner"] = self.user
|
||||
permissions = None
|
||||
if "set_permissions" in validated_data:
|
||||
permissions = validated_data.pop("set_permissions")
|
||||
if "user" not in permissions or permissions["user"] is None:
|
||||
validated_data["owner"] = None
|
||||
instance = super().create(validated_data)
|
||||
if permissions is not None:
|
||||
self._set_permissions(permissions, instance)
|
||||
|
Binary file not shown.
@@ -28,6 +28,7 @@ from django.contrib.auth.models import User
|
||||
from django.test import override_settings
|
||||
from django.utils import timezone
|
||||
from guardian.shortcuts import assign_perm
|
||||
from guardian.shortcuts import get_perms
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
from whoosh.writing import AsyncWriter
|
||||
@@ -3855,7 +3856,7 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
def test_object_permissions(self):
|
||||
def test_api_get_object_permissions(self):
|
||||
user1 = User.objects.create_user(username="test1")
|
||||
user2 = User.objects.create_user(username="test2")
|
||||
user1.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
@@ -3886,18 +3887,16 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
status.HTTP_404_NOT_FOUND,
|
||||
)
|
||||
|
||||
def test_api_set_permissions(self):
|
||||
def test_api_default_owner(self):
|
||||
"""
|
||||
GIVEN:
|
||||
- API request to create an object (Tag) that supplies set_permissions object
|
||||
- API request to create an object (Tag)
|
||||
WHEN:
|
||||
- owner is passed as null or as a user id
|
||||
- view > users is set
|
||||
- owner is not set at all
|
||||
THEN:
|
||||
- Object permissions are set appropriately
|
||||
- Object created with current user as owner
|
||||
"""
|
||||
user1 = User.objects.create_superuser(username="user1")
|
||||
user2 = User.objects.create(username="user2")
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
@@ -3907,11 +3906,73 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
{
|
||||
"name": "test1",
|
||||
"matching_algorithm": MatchingModel.MATCH_AUTO,
|
||||
},
|
||||
),
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
tag1 = Tag.objects.filter(name="test1").first()
|
||||
self.assertEqual(tag1.owner, user1)
|
||||
|
||||
def test_api_set_no_owner(self):
|
||||
"""
|
||||
GIVEN:
|
||||
- API request to create an object (Tag)
|
||||
WHEN:
|
||||
- owner is passed as None
|
||||
THEN:
|
||||
- Object created with no owner
|
||||
"""
|
||||
user1 = User.objects.create_superuser(username="user1")
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
response = self.client.post(
|
||||
"/api/tags/",
|
||||
json.dumps(
|
||||
{
|
||||
"name": "test1",
|
||||
"matching_algorithm": MatchingModel.MATCH_AUTO,
|
||||
"owner": None,
|
||||
},
|
||||
),
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
tag1 = Tag.objects.filter(name="test1").first()
|
||||
self.assertEqual(tag1.owner, None)
|
||||
|
||||
def test_api_set_owner_w_permissions(self):
|
||||
"""
|
||||
GIVEN:
|
||||
- API request to create an object (Tag) that supplies set_permissions object
|
||||
WHEN:
|
||||
- owner is passed as user id
|
||||
- view > users is set & view > groups is set
|
||||
THEN:
|
||||
- Object permissions are set appropriately
|
||||
"""
|
||||
user1 = User.objects.create_superuser(username="user1")
|
||||
user2 = User.objects.create(username="user2")
|
||||
group1 = Group.objects.create(name="group1")
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
response = self.client.post(
|
||||
"/api/tags/",
|
||||
json.dumps(
|
||||
{
|
||||
"name": "test1",
|
||||
"matching_algorithm": MatchingModel.MATCH_AUTO,
|
||||
"owner": user1.id,
|
||||
"set_permissions": {
|
||||
"owner": None,
|
||||
"view": {
|
||||
"users": None,
|
||||
"groups": None,
|
||||
"users": [user2.id],
|
||||
"groups": [group1.id],
|
||||
},
|
||||
"change": {
|
||||
"users": None,
|
||||
@@ -3926,19 +3987,43 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
tag1 = Tag.objects.filter(name="test1").first()
|
||||
self.assertEqual(tag1.owner, None)
|
||||
|
||||
response = self.client.post(
|
||||
"/api/tags/",
|
||||
from guardian.core import ObjectPermissionChecker
|
||||
|
||||
checker = ObjectPermissionChecker(user2)
|
||||
self.assertEqual(checker.has_perm("view_tag", tag1), True)
|
||||
self.assertIn("view_tag", get_perms(group1, tag1))
|
||||
|
||||
def test_api_set_doc_permissions(self):
|
||||
"""
|
||||
GIVEN:
|
||||
- API request to update doc permissions and owner
|
||||
WHEN:
|
||||
- owner is set
|
||||
- view > users is set & view > groups is set
|
||||
THEN:
|
||||
- Object permissions are set appropriately
|
||||
"""
|
||||
doc = Document.objects.create(
|
||||
title="test",
|
||||
mime_type="application/pdf",
|
||||
content="this is a document",
|
||||
)
|
||||
user1 = User.objects.create_superuser(username="user1")
|
||||
user2 = User.objects.create(username="user2")
|
||||
group1 = Group.objects.create(name="group1")
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
response = self.client.patch(
|
||||
f"/api/documents/{doc.id}/",
|
||||
json.dumps(
|
||||
{
|
||||
"name": "test2",
|
||||
"matching_algorithm": MatchingModel.MATCH_AUTO,
|
||||
"owner": user1.id,
|
||||
"set_permissions": {
|
||||
"owner": user1.id,
|
||||
"view": {
|
||||
"users": [user2.id],
|
||||
"groups": None,
|
||||
"groups": [group1.id],
|
||||
},
|
||||
"change": {
|
||||
"users": None,
|
||||
@@ -3950,12 +4035,15 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
tag2 = Tag.objects.filter(name="test2").first()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
doc = Document.objects.get(pk=doc.id)
|
||||
|
||||
self.assertEqual(doc.owner, user1)
|
||||
from guardian.core import ObjectPermissionChecker
|
||||
|
||||
checker = ObjectPermissionChecker(user2)
|
||||
self.assertEqual(checker.has_perm("view_tag", tag2), True)
|
||||
self.assertTrue(checker.has_perm("view_document", doc))
|
||||
self.assertIn("view_document", get_perms(group1, doc))
|
||||
|
||||
def test_dynamic_permissions_fields(self):
|
||||
user1 = User.objects.create_user(username="user1")
|
||||
|
@@ -906,6 +906,47 @@ class TestAsnBarcode(DirectoriesMixin, TestCase):
|
||||
input_doc,
|
||||
)
|
||||
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
||||
def test_scan_file_for_qrcode_without_upscale(self):
|
||||
"""
|
||||
GIVEN:
|
||||
- A printed and scanned PDF document with a rather small QR code
|
||||
WHEN:
|
||||
- ASN barcode detection is run with default settings
|
||||
- pyzbar is used for detection, as zxing would behave differently, and detect the QR code
|
||||
THEN:
|
||||
- ASN is not detected
|
||||
"""
|
||||
|
||||
test_file = self.BARCODE_SAMPLE_DIR / "barcode-qr-asn-000123-upscale-dpi.pdf"
|
||||
|
||||
with BarcodeReader(test_file, "application/pdf") as reader:
|
||||
reader.detect()
|
||||
self.assertEqual(len(reader.barcodes), 0)
|
||||
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
||||
@override_settings(CONSUMER_BARCODE_DPI=600)
|
||||
@override_settings(CONSUMER_BARCODE_UPSCALE=1.5)
|
||||
def test_scan_file_for_qrcode_with_upscale(self):
|
||||
"""
|
||||
GIVEN:
|
||||
- A printed and scanned PDF document with a rather small QR code
|
||||
WHEN:
|
||||
- ASN barcode detection is run with 600dpi and an upscale factor of 1.5 and pyzbar
|
||||
- pyzbar is used for detection, as zxing would behave differently.
|
||||
Upscaling is a workaround for detection problems with pyzbar,
|
||||
when you cannot switch to zxing (aarch64 build problems of zxing)
|
||||
THEN:
|
||||
- ASN 123 is detected
|
||||
"""
|
||||
|
||||
test_file = self.BARCODE_SAMPLE_DIR / "barcode-qr-asn-000123-upscale-dpi.pdf"
|
||||
|
||||
with BarcodeReader(test_file, "application/pdf") as reader:
|
||||
reader.detect()
|
||||
self.assertEqual(len(reader.barcodes), 1)
|
||||
self.assertEqual(reader.asn, 123)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not HAS_ZXING_LIB,
|
||||
|
@@ -7,6 +7,7 @@ from django.test import TestCase
|
||||
|
||||
from documents.management.commands.document_thumbnails import _process_document
|
||||
from documents.models import Document
|
||||
from documents.parsers import get_default_thumbnail
|
||||
from documents.tests.utils import DirectoriesMixin
|
||||
from documents.tests.utils import FileSystemAssertsMixin
|
||||
|
||||
@@ -26,9 +27,9 @@ class TestMakeThumbnails(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
||||
)
|
||||
|
||||
self.d2 = Document.objects.create(
|
||||
checksum="Ass",
|
||||
title="A",
|
||||
content="first document",
|
||||
checksum="B",
|
||||
title="B",
|
||||
content="second document",
|
||||
mime_type="application/pdf",
|
||||
filename="test2.pdf",
|
||||
)
|
||||
@@ -37,6 +38,18 @@ class TestMakeThumbnails(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
||||
self.d2.source_path,
|
||||
)
|
||||
|
||||
self.d3 = Document.objects.create(
|
||||
checksum="C",
|
||||
title="C",
|
||||
content="third document",
|
||||
mime_type="application/pdf",
|
||||
filename="test3.pdf",
|
||||
)
|
||||
shutil.copy(
|
||||
os.path.join(os.path.dirname(__file__), "samples", "password-is-test.pdf"),
|
||||
self.d3.source_path,
|
||||
)
|
||||
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
self.make_models()
|
||||
@@ -46,6 +59,14 @@ class TestMakeThumbnails(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
||||
_process_document(self.d1.id)
|
||||
self.assertIsFile(self.d1.thumbnail_path)
|
||||
|
||||
def test_process_document_password_protected(self):
|
||||
self.assertIsFile(get_default_thumbnail())
|
||||
self.assertIsNotFile(self.d3.thumbnail_path)
|
||||
_process_document(self.d3.id)
|
||||
# Ensure default thumbnail is still there
|
||||
self.assertIsFile(get_default_thumbnail())
|
||||
self.assertIsFile(self.d3.thumbnail_path)
|
||||
|
||||
@mock.patch("documents.management.commands.document_thumbnails.shutil.move")
|
||||
def test_process_document_invalid_mime_type(self, m: mock.Mock):
|
||||
self.d1.mime_type = "asdasdasd"
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-03 19:15+0000\n"
|
||||
"PO-Revision-Date: 2023-03-05 23:45\n"
|
||||
"PO-Revision-Date: 2023-06-24 08:28\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Dutch\n"
|
||||
"Language: nl_NL\n"
|
||||
@@ -670,7 +670,7 @@ msgstr "Acties"
|
||||
|
||||
#: paperless_mail/admin.py:69
|
||||
msgid "The action applied to the mail. This action is only performed when the mail body or attachments were consumed from the mail."
|
||||
msgstr ""
|
||||
msgstr "De actie uitgevoerd op de email. Deze actie wordt alleen uitgevoerd wanneer de email inhoud of bijlagen van de email zijn geïmporteerd."
|
||||
|
||||
#: paperless_mail/admin.py:77
|
||||
msgid "Metadata"
|
||||
@@ -750,11 +750,11 @@ msgstr "Alleen bijlagen verwerken"
|
||||
|
||||
#: paperless_mail/models.py:62
|
||||
msgid "Process full Mail (with embedded attachments in file) as .eml"
|
||||
msgstr ""
|
||||
msgstr "Verwerk volledige email (met ingesloten bijlagen in bestand) als .eml"
|
||||
|
||||
#: paperless_mail/models.py:64
|
||||
msgid "Process full Mail (with embedded attachments in file) as .eml + process attachments as separate documents"
|
||||
msgstr ""
|
||||
msgstr "Verwerk volledige email (met ingesloten bijlagen als bestand) als .eml en verwerk bijlagen als aparte documenten"
|
||||
|
||||
#: paperless_mail/models.py:70
|
||||
msgid "Process all files, including 'inline' attachments."
|
||||
@@ -858,7 +858,7 @@ msgstr "\"Inline\" bijlagen bevatten vaak ook afbeeldingen. In dit geval valt he
|
||||
|
||||
#: paperless_mail/models.py:158
|
||||
msgid "consumption scope"
|
||||
msgstr ""
|
||||
msgstr "verwerkingsscope"
|
||||
|
||||
#: paperless_mail/models.py:164
|
||||
msgid "action"
|
||||
@@ -894,7 +894,7 @@ msgstr "wijs deze correspondent toe"
|
||||
|
||||
#: paperless_mail/models.py:239
|
||||
msgid "uid"
|
||||
msgstr ""
|
||||
msgstr "uid"
|
||||
|
||||
#: paperless_mail/models.py:247
|
||||
msgid "subject"
|
||||
|
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-03 19:15+0000\n"
|
||||
"PO-Revision-Date: 2023-05-29 21:58\n"
|
||||
"PO-Revision-Date: 2023-06-15 10:39\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Slovak\n"
|
||||
"Language: sk_SK\n"
|
||||
@@ -23,7 +23,7 @@ msgstr "Dokumenty"
|
||||
|
||||
#: documents/models.py:36
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
msgstr "Žiadny"
|
||||
|
||||
#: documents/models.py:37
|
||||
msgid "Any word"
|
||||
@@ -112,11 +112,11 @@ msgstr "cesta"
|
||||
|
||||
#: documents/models.py:117 documents/models.py:145
|
||||
msgid "storage path"
|
||||
msgstr ""
|
||||
msgstr "cesta k úložisku"
|
||||
|
||||
#: documents/models.py:118
|
||||
msgid "storage paths"
|
||||
msgstr ""
|
||||
msgstr "cesty k úložisku"
|
||||
|
||||
#: documents/models.py:126
|
||||
msgid "Unencrypted"
|
||||
@@ -140,7 +140,7 @@ msgstr "Nespracované, iba textové údaje dokumentu. Toto pole sa primárne pou
|
||||
|
||||
#: documents/models.py:168
|
||||
msgid "mime type"
|
||||
msgstr ""
|
||||
msgstr "MIME typ"
|
||||
|
||||
#: documents/models.py:178
|
||||
msgid "checksum"
|
||||
@@ -196,7 +196,7 @@ msgstr "pôvodný názov súboru"
|
||||
|
||||
#: documents/models.py:245
|
||||
msgid "The original name of the file when it was uploaded"
|
||||
msgstr ""
|
||||
msgstr "Pôvodný názov súboru pri nahratí"
|
||||
|
||||
#: documents/models.py:252
|
||||
msgid "archive serial number"
|
||||
@@ -204,19 +204,19 @@ msgstr "archivovať sériové číslo"
|
||||
|
||||
#: documents/models.py:262
|
||||
msgid "The position of this document in your physical document archive."
|
||||
msgstr ""
|
||||
msgstr "Umiestnenie dokumentu vo vašom fyzickom archíve."
|
||||
|
||||
#: documents/models.py:268 documents/models.py:641
|
||||
msgid "document"
|
||||
msgstr ""
|
||||
msgstr "dokument"
|
||||
|
||||
#: documents/models.py:269
|
||||
msgid "documents"
|
||||
msgstr ""
|
||||
msgstr "dokumenty"
|
||||
|
||||
#: documents/models.py:359
|
||||
msgid "debug"
|
||||
msgstr ""
|
||||
msgstr "odstraňovanie chýb"
|
||||
|
||||
#: documents/models.py:360
|
||||
msgid "information"
|
||||
@@ -256,659 +256,659 @@ msgstr "logy"
|
||||
|
||||
#: documents/models.py:391 documents/models.py:446
|
||||
msgid "saved view"
|
||||
msgstr ""
|
||||
msgstr "uložené zobrazenie"
|
||||
|
||||
#: documents/models.py:392
|
||||
msgid "saved views"
|
||||
msgstr ""
|
||||
msgstr "uložené zobrazenia"
|
||||
|
||||
#: documents/models.py:397
|
||||
msgid "show on dashboard"
|
||||
msgstr ""
|
||||
msgstr "zobraziť na hlavnom paneli"
|
||||
|
||||
#: documents/models.py:400
|
||||
msgid "show in sidebar"
|
||||
msgstr ""
|
||||
msgstr "zobraziť na bočnom paneli"
|
||||
|
||||
#: documents/models.py:404
|
||||
msgid "sort field"
|
||||
msgstr ""
|
||||
msgstr "zoraďovacie pole"
|
||||
|
||||
#: documents/models.py:409
|
||||
msgid "sort reverse"
|
||||
msgstr ""
|
||||
msgstr "zoradiť opačne"
|
||||
|
||||
#: documents/models.py:414
|
||||
msgid "title contains"
|
||||
msgstr ""
|
||||
msgstr "názov obsahuje"
|
||||
|
||||
#: documents/models.py:415
|
||||
msgid "content contains"
|
||||
msgstr ""
|
||||
msgstr "dokument obsahuje"
|
||||
|
||||
#: documents/models.py:416
|
||||
msgid "ASN is"
|
||||
msgstr ""
|
||||
msgstr "ASN je"
|
||||
|
||||
#: documents/models.py:417
|
||||
msgid "correspondent is"
|
||||
msgstr ""
|
||||
msgstr "odosielateľ je"
|
||||
|
||||
#: documents/models.py:418
|
||||
msgid "document type is"
|
||||
msgstr ""
|
||||
msgstr "typ dokumentu je"
|
||||
|
||||
#: documents/models.py:419
|
||||
msgid "is in inbox"
|
||||
msgstr ""
|
||||
msgstr "je v doručenej pošte"
|
||||
|
||||
#: documents/models.py:420
|
||||
msgid "has tag"
|
||||
msgstr ""
|
||||
msgstr "má štítok"
|
||||
|
||||
#: documents/models.py:421
|
||||
msgid "has any tag"
|
||||
msgstr ""
|
||||
msgstr "má niektorý zo štítkov"
|
||||
|
||||
#: documents/models.py:422
|
||||
msgid "created before"
|
||||
msgstr ""
|
||||
msgstr "vytvorený pred"
|
||||
|
||||
#: documents/models.py:423
|
||||
msgid "created after"
|
||||
msgstr ""
|
||||
msgstr "vytvorený po"
|
||||
|
||||
#: documents/models.py:424
|
||||
msgid "created year is"
|
||||
msgstr ""
|
||||
msgstr "rok vytvorenia je"
|
||||
|
||||
#: documents/models.py:425
|
||||
msgid "created month is"
|
||||
msgstr ""
|
||||
msgstr "mesiac vytvorenia je"
|
||||
|
||||
#: documents/models.py:426
|
||||
msgid "created day is"
|
||||
msgstr ""
|
||||
msgstr "deň vytvorenia je"
|
||||
|
||||
#: documents/models.py:427
|
||||
msgid "added before"
|
||||
msgstr ""
|
||||
msgstr "pridaný pred"
|
||||
|
||||
#: documents/models.py:428
|
||||
msgid "added after"
|
||||
msgstr ""
|
||||
msgstr "pridaný po"
|
||||
|
||||
#: documents/models.py:429
|
||||
msgid "modified before"
|
||||
msgstr ""
|
||||
msgstr "zmenený pred"
|
||||
|
||||
#: documents/models.py:430
|
||||
msgid "modified after"
|
||||
msgstr ""
|
||||
msgstr "zmenený po"
|
||||
|
||||
#: documents/models.py:431
|
||||
msgid "does not have tag"
|
||||
msgstr ""
|
||||
msgstr "nemá štítok"
|
||||
|
||||
#: documents/models.py:432
|
||||
msgid "does not have ASN"
|
||||
msgstr ""
|
||||
msgstr "nemá ASN"
|
||||
|
||||
#: documents/models.py:433
|
||||
msgid "title or content contains"
|
||||
msgstr ""
|
||||
msgstr "názov alebo dokument obsahuje"
|
||||
|
||||
#: documents/models.py:434
|
||||
msgid "fulltext query"
|
||||
msgstr ""
|
||||
msgstr "fulltextový dopyt"
|
||||
|
||||
#: documents/models.py:435
|
||||
msgid "more like this"
|
||||
msgstr ""
|
||||
msgstr "viac podobných"
|
||||
|
||||
#: documents/models.py:436
|
||||
msgid "has tags in"
|
||||
msgstr ""
|
||||
msgstr "má štítok v"
|
||||
|
||||
#: documents/models.py:437
|
||||
msgid "ASN greater than"
|
||||
msgstr ""
|
||||
msgstr "ASN väčšie ako"
|
||||
|
||||
#: documents/models.py:438
|
||||
msgid "ASN less than"
|
||||
msgstr ""
|
||||
msgstr "ASN menšie ako"
|
||||
|
||||
#: documents/models.py:439
|
||||
msgid "storage path is"
|
||||
msgstr ""
|
||||
msgstr "cesta k úložisku je"
|
||||
|
||||
#: documents/models.py:449
|
||||
msgid "rule type"
|
||||
msgstr ""
|
||||
msgstr "typ pravidla"
|
||||
|
||||
#: documents/models.py:451
|
||||
msgid "value"
|
||||
msgstr ""
|
||||
msgstr "hodnota"
|
||||
|
||||
#: documents/models.py:454
|
||||
msgid "filter rule"
|
||||
msgstr ""
|
||||
msgstr "pravidlo filtra"
|
||||
|
||||
#: documents/models.py:455
|
||||
msgid "filter rules"
|
||||
msgstr ""
|
||||
msgstr "pravidlá filtra"
|
||||
|
||||
#: documents/models.py:563
|
||||
msgid "Task ID"
|
||||
msgstr ""
|
||||
msgstr "ID úlohy"
|
||||
|
||||
#: documents/models.py:564
|
||||
msgid "Celery ID for the Task that was run"
|
||||
msgstr ""
|
||||
msgstr "Celery ID úlohy, ktorá bola vykonaná"
|
||||
|
||||
#: documents/models.py:569
|
||||
msgid "Acknowledged"
|
||||
msgstr ""
|
||||
msgstr "Potvrdené"
|
||||
|
||||
#: documents/models.py:570
|
||||
msgid "If the task is acknowledged via the frontend or API"
|
||||
msgstr ""
|
||||
msgstr "Ak je úloha potvrdená prostredníctvom rozhrania alebo API"
|
||||
|
||||
#: documents/models.py:576
|
||||
msgid "Task Filename"
|
||||
msgstr ""
|
||||
msgstr "Názov súboru úlohy"
|
||||
|
||||
#: documents/models.py:577
|
||||
msgid "Name of the file which the Task was run for"
|
||||
msgstr ""
|
||||
msgstr "Názov súboru, na ktorom bola vykonaná úloha"
|
||||
|
||||
#: documents/models.py:583
|
||||
msgid "Task Name"
|
||||
msgstr ""
|
||||
msgstr "Názov úlohy"
|
||||
|
||||
#: documents/models.py:584
|
||||
msgid "Name of the Task which was run"
|
||||
msgstr ""
|
||||
msgstr "Názov vykonanej úlohy"
|
||||
|
||||
#: documents/models.py:591
|
||||
msgid "Task State"
|
||||
msgstr ""
|
||||
msgstr "Stav úlohy"
|
||||
|
||||
#: documents/models.py:592
|
||||
msgid "Current state of the task being run"
|
||||
msgstr ""
|
||||
msgstr "Aktuálny stav bežiacej úlohy"
|
||||
|
||||
#: documents/models.py:597
|
||||
msgid "Created DateTime"
|
||||
msgstr ""
|
||||
msgstr "Dátum a čas vytvorenia"
|
||||
|
||||
#: documents/models.py:598
|
||||
msgid "Datetime field when the task result was created in UTC"
|
||||
msgstr ""
|
||||
msgstr "Dátum a čas výsledku úlohy v UTC"
|
||||
|
||||
#: documents/models.py:603
|
||||
msgid "Started DateTime"
|
||||
msgstr ""
|
||||
msgstr "Dátum a čas začiatku"
|
||||
|
||||
#: documents/models.py:604
|
||||
msgid "Datetime field when the task was started in UTC"
|
||||
msgstr ""
|
||||
msgstr "Dátum a čas začiatku úlohy v UTC"
|
||||
|
||||
#: documents/models.py:609
|
||||
msgid "Completed DateTime"
|
||||
msgstr ""
|
||||
msgstr "Dátum a čas skončenia"
|
||||
|
||||
#: documents/models.py:610
|
||||
msgid "Datetime field when the task was completed in UTC"
|
||||
msgstr ""
|
||||
msgstr "Dátum a čas skončenia úlohy v UTC"
|
||||
|
||||
#: documents/models.py:615
|
||||
msgid "Result Data"
|
||||
msgstr ""
|
||||
msgstr "Výsledné dáta"
|
||||
|
||||
#: documents/models.py:617
|
||||
msgid "The data returned by the task"
|
||||
msgstr ""
|
||||
msgstr "Výsledné dáta úlohy"
|
||||
|
||||
#: documents/models.py:626
|
||||
msgid "Comment for the document"
|
||||
msgstr ""
|
||||
msgstr "Komentár k dokumentu"
|
||||
|
||||
#: documents/models.py:650
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
msgstr "užívateľ"
|
||||
|
||||
#: documents/models.py:655
|
||||
msgid "comment"
|
||||
msgstr ""
|
||||
msgstr "komentár"
|
||||
|
||||
#: documents/models.py:656
|
||||
msgid "comments"
|
||||
msgstr ""
|
||||
msgstr "komentáre"
|
||||
|
||||
#: documents/serialisers.py:80
|
||||
#, python-format
|
||||
msgid "Invalid regular expression: %(error)s"
|
||||
msgstr ""
|
||||
msgstr "Neplatný regulárny výraz: %(error)s"
|
||||
|
||||
#: documents/serialisers.py:320
|
||||
msgid "Invalid color."
|
||||
msgstr ""
|
||||
msgstr "Neplatná farba."
|
||||
|
||||
#: documents/serialisers.py:700
|
||||
#, python-format
|
||||
msgid "File type %(type)s not supported"
|
||||
msgstr ""
|
||||
msgstr "Typ súboru %(type)s nie je podporovaný"
|
||||
|
||||
#: documents/serialisers.py:794
|
||||
msgid "Invalid variable detected."
|
||||
msgstr ""
|
||||
msgstr "Zistená neplatná premenná."
|
||||
|
||||
#: documents/templates/index.html:78
|
||||
msgid "Paperless-ngx is loading..."
|
||||
msgstr ""
|
||||
msgstr "Paperless-ngx sa načítava..."
|
||||
|
||||
#: documents/templates/index.html:79
|
||||
msgid "Still here?! Hmm, something might be wrong."
|
||||
msgstr ""
|
||||
msgstr "Ešte stále tu?! Hmm, niečo sa možno prihodilo."
|
||||
|
||||
#: documents/templates/index.html:79
|
||||
msgid "Here's a link to the docs."
|
||||
msgstr ""
|
||||
msgstr "Tu je odkaz na dokumentáciu."
|
||||
|
||||
#: documents/templates/registration/logged_out.html:14
|
||||
msgid "Paperless-ngx signed out"
|
||||
msgstr ""
|
||||
msgstr "Paperless-ngx bol odhlásený"
|
||||
|
||||
#: documents/templates/registration/logged_out.html:59
|
||||
msgid "You have been successfully logged out. Bye!"
|
||||
msgstr ""
|
||||
msgstr "Boli ste úspešne odhlásený. Dovidenia!"
|
||||
|
||||
#: documents/templates/registration/logged_out.html:60
|
||||
msgid "Sign in again"
|
||||
msgstr ""
|
||||
msgstr "Prihlásiť sa znova"
|
||||
|
||||
#: documents/templates/registration/login.html:15
|
||||
msgid "Paperless-ngx sign in"
|
||||
msgstr ""
|
||||
msgstr "Prihlásiť Paperless-ngx"
|
||||
|
||||
#: documents/templates/registration/login.html:61
|
||||
msgid "Please sign in."
|
||||
msgstr ""
|
||||
msgstr "Prihláste sa, prosím."
|
||||
|
||||
#: documents/templates/registration/login.html:64
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr ""
|
||||
msgstr "Vaše prihlasovacie údaje nie sú správne. Prosím, skúste to znova."
|
||||
|
||||
#: documents/templates/registration/login.html:67
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
msgstr "Užívateľské meno"
|
||||
|
||||
#: documents/templates/registration/login.html:68
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
msgstr "Heslo"
|
||||
|
||||
#: documents/templates/registration/login.html:73
|
||||
msgid "Sign in"
|
||||
msgstr ""
|
||||
msgstr "Prihlásiť sa"
|
||||
|
||||
#: paperless/apps.py:9
|
||||
msgid "Paperless"
|
||||
msgstr ""
|
||||
msgstr "Paperless"
|
||||
|
||||
#: paperless/settings.py:521
|
||||
msgid "English (US)"
|
||||
msgstr ""
|
||||
msgstr "Angličtina (US)"
|
||||
|
||||
#: paperless/settings.py:522
|
||||
msgid "Arabic"
|
||||
msgstr ""
|
||||
msgstr "Arabčina"
|
||||
|
||||
#: paperless/settings.py:523
|
||||
msgid "Belarusian"
|
||||
msgstr ""
|
||||
msgstr "Bieloruština"
|
||||
|
||||
#: paperless/settings.py:524
|
||||
msgid "Czech"
|
||||
msgstr ""
|
||||
msgstr "Čeština"
|
||||
|
||||
#: paperless/settings.py:525
|
||||
msgid "Danish"
|
||||
msgstr ""
|
||||
msgstr "Dánčina"
|
||||
|
||||
#: paperless/settings.py:526
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
msgstr "Nemčina"
|
||||
|
||||
#: paperless/settings.py:527
|
||||
msgid "English (GB)"
|
||||
msgstr ""
|
||||
msgstr "Angličtina (GB)"
|
||||
|
||||
#: paperless/settings.py:528
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
msgstr "Španielčina"
|
||||
|
||||
#: paperless/settings.py:529
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
msgstr "Francúzština"
|
||||
|
||||
#: paperless/settings.py:530
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
msgstr "Taliančina"
|
||||
|
||||
#: paperless/settings.py:531
|
||||
msgid "Luxembourgish"
|
||||
msgstr ""
|
||||
msgstr "Luxemburčina"
|
||||
|
||||
#: paperless/settings.py:532
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
msgstr "Holandčina"
|
||||
|
||||
#: paperless/settings.py:533
|
||||
msgid "Polish"
|
||||
msgstr ""
|
||||
msgstr "Polština"
|
||||
|
||||
#: paperless/settings.py:534
|
||||
msgid "Portuguese (Brazil)"
|
||||
msgstr ""
|
||||
msgstr "Portugalčina (Brazília)"
|
||||
|
||||
#: paperless/settings.py:535
|
||||
msgid "Portuguese"
|
||||
msgstr ""
|
||||
msgstr "Portugalčina"
|
||||
|
||||
#: paperless/settings.py:536
|
||||
msgid "Romanian"
|
||||
msgstr ""
|
||||
msgstr "Rumunčina"
|
||||
|
||||
#: paperless/settings.py:537
|
||||
msgid "Russian"
|
||||
msgstr ""
|
||||
msgstr "Ruština"
|
||||
|
||||
#: paperless/settings.py:538
|
||||
msgid "Slovenian"
|
||||
msgstr ""
|
||||
msgstr "Slovinčina"
|
||||
|
||||
#: paperless/settings.py:539
|
||||
msgid "Serbian"
|
||||
msgstr ""
|
||||
msgstr "Srbčina"
|
||||
|
||||
#: paperless/settings.py:540
|
||||
msgid "Swedish"
|
||||
msgstr ""
|
||||
msgstr "Švédčina"
|
||||
|
||||
#: paperless/settings.py:541
|
||||
msgid "Turkish"
|
||||
msgstr ""
|
||||
msgstr "Turečtina"
|
||||
|
||||
#: paperless/settings.py:542
|
||||
msgid "Chinese Simplified"
|
||||
msgstr ""
|
||||
msgstr "Čínština (zjednodušená)"
|
||||
|
||||
#: paperless/urls.py:169
|
||||
msgid "Paperless-ngx administration"
|
||||
msgstr ""
|
||||
msgstr "Správa Paperless-ngx"
|
||||
|
||||
#: paperless_mail/admin.py:30
|
||||
msgid "Authentication"
|
||||
msgstr ""
|
||||
msgstr "Autentifikácia"
|
||||
|
||||
#: paperless_mail/admin.py:31
|
||||
msgid "Advanced settings"
|
||||
msgstr ""
|
||||
msgstr "Pokročilé nastavenia"
|
||||
|
||||
#: paperless_mail/admin.py:48
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
msgstr "Filter"
|
||||
|
||||
#: paperless_mail/admin.py:51
|
||||
msgid "Paperless will only process mails that match ALL of the filters given below."
|
||||
msgstr ""
|
||||
msgstr "Paperless spracuje iba e-maily, ktoré spĺňajú všetky filtre definované nižšie."
|
||||
|
||||
#: paperless_mail/admin.py:66
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
msgstr "Akcie"
|
||||
|
||||
#: paperless_mail/admin.py:69
|
||||
msgid "The action applied to the mail. This action is only performed when the mail body or attachments were consumed from the mail."
|
||||
msgstr ""
|
||||
msgstr "Akcia aplikovaná na e-mail. Táto akcia sa vykonáva iba v prípade, ak boli z e-mailu spracované jeho obsah alebo prílohy."
|
||||
|
||||
#: paperless_mail/admin.py:77
|
||||
msgid "Metadata"
|
||||
msgstr ""
|
||||
msgstr "Metadáta"
|
||||
|
||||
#: paperless_mail/admin.py:80
|
||||
msgid "Assign metadata to documents consumed from this rule automatically. If you do not assign tags, types or correspondents here, paperless will still process all matching rules that you have defined."
|
||||
msgstr ""
|
||||
msgstr "Automaticky priradiť metadáta dokumentom, ktoré sú spracovávané na základe tohto pravidla. Ak aj v tomto kroku nepriradíte dokumentom štítky, typy alebo odosielateľov, paperless skontroluje a vykoná všetky definované pravidlá."
|
||||
|
||||
#: paperless_mail/apps.py:10
|
||||
msgid "Paperless mail"
|
||||
msgstr ""
|
||||
msgstr "Paperless e-mail"
|
||||
|
||||
#: paperless_mail/models.py:9
|
||||
msgid "mail account"
|
||||
msgstr ""
|
||||
msgstr "e-mailový účet"
|
||||
|
||||
#: paperless_mail/models.py:10
|
||||
msgid "mail accounts"
|
||||
msgstr ""
|
||||
msgstr "e-mailové účty"
|
||||
|
||||
#: paperless_mail/models.py:13
|
||||
msgid "No encryption"
|
||||
msgstr ""
|
||||
msgstr "Žiadne šifrovanie"
|
||||
|
||||
#: paperless_mail/models.py:14
|
||||
msgid "Use SSL"
|
||||
msgstr ""
|
||||
msgstr "Použiť SSL"
|
||||
|
||||
#: paperless_mail/models.py:15
|
||||
msgid "Use STARTTLS"
|
||||
msgstr ""
|
||||
msgstr "Použiť STARTTLS"
|
||||
|
||||
#: paperless_mail/models.py:19
|
||||
msgid "IMAP server"
|
||||
msgstr ""
|
||||
msgstr "IMAP server"
|
||||
|
||||
#: paperless_mail/models.py:22
|
||||
msgid "IMAP port"
|
||||
msgstr ""
|
||||
msgstr "IMAP port"
|
||||
|
||||
#: paperless_mail/models.py:26
|
||||
msgid "This is usually 143 for unencrypted and STARTTLS connections, and 993 for SSL connections."
|
||||
msgstr ""
|
||||
msgstr "Zvyčajne 143 pre nešifrované a STARTTLS pripojenia a 993 pre SSL pripojenia."
|
||||
|
||||
#: paperless_mail/models.py:32
|
||||
msgid "IMAP security"
|
||||
msgstr ""
|
||||
msgstr "IMAP zabezpečenie"
|
||||
|
||||
#: paperless_mail/models.py:37
|
||||
msgid "username"
|
||||
msgstr ""
|
||||
msgstr "meno používateľa"
|
||||
|
||||
#: paperless_mail/models.py:39
|
||||
msgid "password"
|
||||
msgstr ""
|
||||
msgstr "heslo"
|
||||
|
||||
#: paperless_mail/models.py:42
|
||||
msgid "character set"
|
||||
msgstr ""
|
||||
msgstr "znaková sada"
|
||||
|
||||
#: paperless_mail/models.py:46
|
||||
msgid "The character set to use when communicating with the mail server, such as 'UTF-8' or 'US-ASCII'."
|
||||
msgstr ""
|
||||
msgstr "Znaková sada využívaná pri komunikácii s e-mailovým serverom, napr. 'UTF-8' alebo 'US-ASCII'."
|
||||
|
||||
#: paperless_mail/models.py:57
|
||||
msgid "mail rule"
|
||||
msgstr ""
|
||||
msgstr "e-mailové pravidlo"
|
||||
|
||||
#: paperless_mail/models.py:58
|
||||
msgid "mail rules"
|
||||
msgstr ""
|
||||
msgstr "e-mailové pravidlá"
|
||||
|
||||
#: paperless_mail/models.py:61 paperless_mail/models.py:69
|
||||
msgid "Only process attachments."
|
||||
msgstr ""
|
||||
msgstr "Spracovať iba prílohy."
|
||||
|
||||
#: paperless_mail/models.py:62
|
||||
msgid "Process full Mail (with embedded attachments in file) as .eml"
|
||||
msgstr ""
|
||||
msgstr "Spracovať celý e-mail (s prílohami vloženými do súboru) ako .eml"
|
||||
|
||||
#: paperless_mail/models.py:64
|
||||
msgid "Process full Mail (with embedded attachments in file) as .eml + process attachments as separate documents"
|
||||
msgstr ""
|
||||
msgstr "Spracovať celý e-mail (s prílohami vloženými do súboru) ako .eml + prílohy spracovať ako samostatné dokumenty"
|
||||
|
||||
#: paperless_mail/models.py:70
|
||||
msgid "Process all files, including 'inline' attachments."
|
||||
msgstr ""
|
||||
msgstr "Spracovať všetky súbory, vrátane 'inline' príloh."
|
||||
|
||||
#: paperless_mail/models.py:73
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
msgstr "Vymazať"
|
||||
|
||||
#: paperless_mail/models.py:74
|
||||
msgid "Move to specified folder"
|
||||
msgstr ""
|
||||
msgstr "Presunúť do vybraného priečinka"
|
||||
|
||||
#: paperless_mail/models.py:75
|
||||
msgid "Mark as read, don't process read mails"
|
||||
msgstr ""
|
||||
msgstr "Označiť ako prečítané, nespracovať prečítané e-maily"
|
||||
|
||||
#: paperless_mail/models.py:76
|
||||
msgid "Flag the mail, don't process flagged mails"
|
||||
msgstr ""
|
||||
msgstr "Označiť e-mail, nespracovať označené e-maily"
|
||||
|
||||
#: paperless_mail/models.py:77
|
||||
msgid "Tag the mail with specified tag, don't process tagged mails"
|
||||
msgstr ""
|
||||
msgstr "Priradiť e-mailu vybraný štítok, nespracovať e-maily so štítkami"
|
||||
|
||||
#: paperless_mail/models.py:80
|
||||
msgid "Use subject as title"
|
||||
msgstr ""
|
||||
msgstr "Použiť predmet ako názov"
|
||||
|
||||
#: paperless_mail/models.py:81
|
||||
msgid "Use attachment filename as title"
|
||||
msgstr ""
|
||||
msgstr "Použiť názov súboru prílohy ako názov"
|
||||
|
||||
#: paperless_mail/models.py:84
|
||||
msgid "Do not assign a correspondent"
|
||||
msgstr ""
|
||||
msgstr "Nepriradiť odosielateľa"
|
||||
|
||||
#: paperless_mail/models.py:85
|
||||
msgid "Use mail address"
|
||||
msgstr ""
|
||||
msgstr "Použiť e-mailovú adresu"
|
||||
|
||||
#: paperless_mail/models.py:86
|
||||
msgid "Use name (or mail address if not available)"
|
||||
msgstr ""
|
||||
msgstr "Použiť meno (alebo e-mailovú adresu, ak nie je vyplnené)"
|
||||
|
||||
#: paperless_mail/models.py:87
|
||||
msgid "Use correspondent selected below"
|
||||
msgstr ""
|
||||
msgstr "Použiť odosielateľa zvoleného nižšie"
|
||||
|
||||
#: paperless_mail/models.py:91
|
||||
msgid "order"
|
||||
msgstr ""
|
||||
msgstr "poradie"
|
||||
|
||||
#: paperless_mail/models.py:97
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
msgstr "účet"
|
||||
|
||||
#: paperless_mail/models.py:101 paperless_mail/models.py:231
|
||||
msgid "folder"
|
||||
msgstr ""
|
||||
msgstr "priečinok"
|
||||
|
||||
#: paperless_mail/models.py:105
|
||||
msgid "Subfolders must be separated by a delimiter, often a dot ('.') or slash ('/'), but it varies by mail server."
|
||||
msgstr ""
|
||||
msgstr "Podpriečinky musia byť oddelené oddeľovačom, najčastejšie bodkou ('.') alebo lomítkom ('/'), podľa mailového servera."
|
||||
|
||||
#: paperless_mail/models.py:111
|
||||
msgid "filter from"
|
||||
msgstr ""
|
||||
msgstr "filtrovať od"
|
||||
|
||||
#: paperless_mail/models.py:117
|
||||
msgid "filter subject"
|
||||
msgstr ""
|
||||
msgstr "filtrovať predmet"
|
||||
|
||||
#: paperless_mail/models.py:123
|
||||
msgid "filter body"
|
||||
msgstr ""
|
||||
msgstr "filtrovať podľa obsahu"
|
||||
|
||||
#: paperless_mail/models.py:130
|
||||
msgid "filter attachment filename"
|
||||
msgstr ""
|
||||
msgstr "filtrovať názov prílohy"
|
||||
|
||||
#: paperless_mail/models.py:135
|
||||
msgid "Only consume documents which entirely match this filename if specified. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive."
|
||||
msgstr ""
|
||||
msgstr "Spracuje iba dokumenty so zhodným názvom, ak je vyplnený. Použitie zástupných znakov ako *.pdf alebo *invoice* je povolené. Rozoznáva malé a veľké písmená."
|
||||
|
||||
#: paperless_mail/models.py:142
|
||||
msgid "maximum age"
|
||||
msgstr ""
|
||||
msgstr "maximálny vek"
|
||||
|
||||
#: paperless_mail/models.py:144
|
||||
msgid "Specified in days."
|
||||
msgstr ""
|
||||
msgstr "Určené v dňoch."
|
||||
|
||||
#: paperless_mail/models.py:148
|
||||
msgid "attachment type"
|
||||
msgstr ""
|
||||
msgstr "typ prílohy"
|
||||
|
||||
#: paperless_mail/models.py:152
|
||||
msgid "Inline attachments include embedded images, so it's best to combine this option with a filename filter."
|
||||
msgstr ""
|
||||
msgstr "'Inline' prílohy obsahujú vložené obrázky, preto je najvhodnejšie kombinovať túto možnosť s filtrovaním podľa názvu súboru."
|
||||
|
||||
#: paperless_mail/models.py:158
|
||||
msgid "consumption scope"
|
||||
msgstr ""
|
||||
msgstr "rozsah spracovania"
|
||||
|
||||
#: paperless_mail/models.py:164
|
||||
msgid "action"
|
||||
msgstr ""
|
||||
msgstr "akcia"
|
||||
|
||||
#: paperless_mail/models.py:170
|
||||
msgid "action parameter"
|
||||
msgstr ""
|
||||
msgstr "parameter akcie"
|
||||
|
||||
#: paperless_mail/models.py:175
|
||||
msgid "Additional parameter for the action selected above, i.e., the target folder of the move to folder action. Subfolders must be separated by dots."
|
||||
msgstr ""
|
||||
msgstr "Prídavný parameter akcie vybranej vyššie, konkrétne cieľový priečinok akcie presunutia priečinku. Podpriečinky musia byť oddelené bodkami."
|
||||
|
||||
#: paperless_mail/models.py:183
|
||||
msgid "assign title from"
|
||||
msgstr ""
|
||||
msgstr "priradiť názov podľa"
|
||||
|
||||
#: paperless_mail/models.py:191
|
||||
msgid "assign this tag"
|
||||
msgstr ""
|
||||
msgstr "priradiť tento štítok"
|
||||
|
||||
#: paperless_mail/models.py:199
|
||||
msgid "assign this document type"
|
||||
msgstr ""
|
||||
msgstr "priradiť tento typ dokumentu"
|
||||
|
||||
#: paperless_mail/models.py:203
|
||||
msgid "assign correspondent from"
|
||||
msgstr ""
|
||||
msgstr "priradiť odosielateľa podľa"
|
||||
|
||||
#: paperless_mail/models.py:213
|
||||
msgid "assign this correspondent"
|
||||
msgstr ""
|
||||
msgstr "priradiť tohto odosielateľa"
|
||||
|
||||
#: paperless_mail/models.py:239
|
||||
msgid "uid"
|
||||
msgstr ""
|
||||
msgstr "uid"
|
||||
|
||||
#: paperless_mail/models.py:247
|
||||
msgid "subject"
|
||||
msgstr ""
|
||||
msgstr "predmet"
|
||||
|
||||
#: paperless_mail/models.py:255
|
||||
msgid "received"
|
||||
msgstr ""
|
||||
msgstr "doručené"
|
||||
|
||||
#: paperless_mail/models.py:262
|
||||
msgid "processed"
|
||||
msgstr ""
|
||||
msgstr "spracované"
|
||||
|
||||
#: paperless_mail/models.py:268
|
||||
msgid "status"
|
||||
msgstr ""
|
||||
msgstr "stav"
|
||||
|
||||
|
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-03 19:15+0000\n"
|
||||
"PO-Revision-Date: 2023-03-24 15:12\n"
|
||||
"PO-Revision-Date: 2023-06-04 20:53\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Swedish\n"
|
||||
"Language: sv_SE\n"
|
||||
@@ -23,7 +23,7 @@ msgstr "Dokument"
|
||||
|
||||
#: documents/models.py:36
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
msgstr "Ingen"
|
||||
|
||||
#: documents/models.py:37
|
||||
msgid "Any word"
|
||||
@@ -68,7 +68,7 @@ msgstr "är ej skiftlägeskänsligt"
|
||||
|
||||
#: documents/models.py:71
|
||||
msgid "owner"
|
||||
msgstr ""
|
||||
msgstr "ägare"
|
||||
|
||||
#: documents/models.py:81 documents/models.py:136
|
||||
msgid "correspondent"
|
||||
@@ -112,7 +112,7 @@ msgstr "sökväg"
|
||||
|
||||
#: documents/models.py:117 documents/models.py:145
|
||||
msgid "storage path"
|
||||
msgstr "sökväg till lagring"
|
||||
msgstr "sökväg för lagring"
|
||||
|
||||
#: documents/models.py:118
|
||||
msgid "storage paths"
|
||||
@@ -404,7 +404,7 @@ msgstr "Uppgifts-ID"
|
||||
|
||||
#: documents/models.py:564
|
||||
msgid "Celery ID for the Task that was run"
|
||||
msgstr ""
|
||||
msgstr "Celery ID för uppgiften som kördes"
|
||||
|
||||
#: documents/models.py:569
|
||||
msgid "Acknowledged"
|
||||
@@ -416,7 +416,7 @@ msgstr "Om uppgiften bekräftas via frontend eller API"
|
||||
|
||||
#: documents/models.py:576
|
||||
msgid "Task Filename"
|
||||
msgstr ""
|
||||
msgstr "Uppgiftens filnamn"
|
||||
|
||||
#: documents/models.py:577
|
||||
msgid "Name of the file which the Task was run for"
|
||||
@@ -468,7 +468,7 @@ msgstr "Resultatdata"
|
||||
|
||||
#: documents/models.py:617
|
||||
msgid "The data returned by the task"
|
||||
msgstr ""
|
||||
msgstr "De data som returneras av uppgiften"
|
||||
|
||||
#: documents/models.py:626
|
||||
msgid "Comment for the document"
|
||||
@@ -502,19 +502,19 @@ msgstr "Filtypen %(type)s stöds inte"
|
||||
|
||||
#: documents/serialisers.py:794
|
||||
msgid "Invalid variable detected."
|
||||
msgstr ""
|
||||
msgstr "Ogiltig variabel upptäckt."
|
||||
|
||||
#: documents/templates/index.html:78
|
||||
msgid "Paperless-ngx is loading..."
|
||||
msgstr ""
|
||||
msgstr "Paperless-ngx laddar..."
|
||||
|
||||
#: documents/templates/index.html:79
|
||||
msgid "Still here?! Hmm, something might be wrong."
|
||||
msgstr ""
|
||||
msgstr "Fortfarande här?! Hmm, någonting kan vara fel."
|
||||
|
||||
#: documents/templates/index.html:79
|
||||
msgid "Here's a link to the docs."
|
||||
msgstr ""
|
||||
msgstr "Här är en länk till dokumentationen."
|
||||
|
||||
#: documents/templates/registration/logged_out.html:14
|
||||
msgid "Paperless-ngx signed out"
|
||||
@@ -530,7 +530,7 @@ msgstr "Logga in igen"
|
||||
|
||||
#: documents/templates/registration/login.html:15
|
||||
msgid "Paperless-ngx sign in"
|
||||
msgstr ""
|
||||
msgstr "Paperless-ngx inloggning"
|
||||
|
||||
#: documents/templates/registration/login.html:61
|
||||
msgid "Please sign in."
|
||||
@@ -554,7 +554,7 @@ msgstr "Logga in"
|
||||
|
||||
#: paperless/apps.py:9
|
||||
msgid "Paperless"
|
||||
msgstr ""
|
||||
msgstr "Paperless"
|
||||
|
||||
#: paperless/settings.py:521
|
||||
msgid "English (US)"
|
||||
@@ -562,19 +562,19 @@ msgstr "Engelska (USA)"
|
||||
|
||||
#: paperless/settings.py:522
|
||||
msgid "Arabic"
|
||||
msgstr ""
|
||||
msgstr "Arabiska"
|
||||
|
||||
#: paperless/settings.py:523
|
||||
msgid "Belarusian"
|
||||
msgstr ""
|
||||
msgstr "Belarusiska"
|
||||
|
||||
#: paperless/settings.py:524
|
||||
msgid "Czech"
|
||||
msgstr ""
|
||||
msgstr "Tjeckiska"
|
||||
|
||||
#: paperless/settings.py:525
|
||||
msgid "Danish"
|
||||
msgstr ""
|
||||
msgstr "Danska"
|
||||
|
||||
#: paperless/settings.py:526
|
||||
msgid "German"
|
||||
@@ -626,11 +626,11 @@ msgstr "Ryska"
|
||||
|
||||
#: paperless/settings.py:538
|
||||
msgid "Slovenian"
|
||||
msgstr ""
|
||||
msgstr "Slovenska"
|
||||
|
||||
#: paperless/settings.py:539
|
||||
msgid "Serbian"
|
||||
msgstr ""
|
||||
msgstr "Serbiska"
|
||||
|
||||
#: paperless/settings.py:540
|
||||
msgid "Swedish"
|
||||
@@ -638,15 +638,15 @@ msgstr "Svenska"
|
||||
|
||||
#: paperless/settings.py:541
|
||||
msgid "Turkish"
|
||||
msgstr ""
|
||||
msgstr "Turkiska"
|
||||
|
||||
#: paperless/settings.py:542
|
||||
msgid "Chinese Simplified"
|
||||
msgstr ""
|
||||
msgstr "Kinesiska (förenklad)"
|
||||
|
||||
#: paperless/urls.py:169
|
||||
msgid "Paperless-ngx administration"
|
||||
msgstr ""
|
||||
msgstr "Paperless-ngx administration"
|
||||
|
||||
#: paperless_mail/admin.py:30
|
||||
msgid "Authentication"
|
||||
@@ -658,7 +658,7 @@ msgstr "Avancerade inställningar"
|
||||
|
||||
#: paperless_mail/admin.py:48
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
msgstr "Filter"
|
||||
|
||||
#: paperless_mail/admin.py:51
|
||||
msgid "Paperless will only process mails that match ALL of the filters given below."
|
||||
@@ -674,7 +674,7 @@ msgstr ""
|
||||
|
||||
#: paperless_mail/admin.py:77
|
||||
msgid "Metadata"
|
||||
msgstr ""
|
||||
msgstr "Metadata"
|
||||
|
||||
#: paperless_mail/admin.py:80
|
||||
msgid "Assign metadata to documents consumed from this rule automatically. If you do not assign tags, types or correspondents here, paperless will still process all matching rules that you have defined."
|
||||
@@ -750,11 +750,11 @@ msgstr "Behandla endast bilagor."
|
||||
|
||||
#: paperless_mail/models.py:62
|
||||
msgid "Process full Mail (with embedded attachments in file) as .eml"
|
||||
msgstr ""
|
||||
msgstr "Behandla helt e-postmeddelande (med inbäddade bilagor i fil) som .eml"
|
||||
|
||||
#: paperless_mail/models.py:64
|
||||
msgid "Process full Mail (with embedded attachments in file) as .eml + process attachments as separate documents"
|
||||
msgstr ""
|
||||
msgstr "Behandla helt e-postmeddelande (med inbäddade bilagor i fil) som .eml + processbilagor som separata dokument"
|
||||
|
||||
#: paperless_mail/models.py:70
|
||||
msgid "Process all files, including 'inline' attachments."
|
||||
@@ -894,21 +894,21 @@ msgstr "tilldela denna korrespondent"
|
||||
|
||||
#: paperless_mail/models.py:239
|
||||
msgid "uid"
|
||||
msgstr ""
|
||||
msgstr "uid"
|
||||
|
||||
#: paperless_mail/models.py:247
|
||||
msgid "subject"
|
||||
msgstr ""
|
||||
msgstr "ämne"
|
||||
|
||||
#: paperless_mail/models.py:255
|
||||
msgid "received"
|
||||
msgstr ""
|
||||
msgstr "mottaget"
|
||||
|
||||
#: paperless_mail/models.py:262
|
||||
msgid "processed"
|
||||
msgstr ""
|
||||
msgstr "bearbetat"
|
||||
|
||||
#: paperless_mail/models.py:268
|
||||
msgid "status"
|
||||
msgstr ""
|
||||
msgstr "status"
|
||||
|
||||
|
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-03 19:15+0000\n"
|
||||
"PO-Revision-Date: 2023-03-03 20:41\n"
|
||||
"PO-Revision-Date: 2023-06-22 01:26\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"Language: zh_CN\n"
|
||||
@@ -23,7 +23,7 @@ msgstr "文档"
|
||||
|
||||
#: documents/models.py:36
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
msgstr "无"
|
||||
|
||||
#: documents/models.py:37
|
||||
msgid "Any word"
|
||||
@@ -68,7 +68,7 @@ msgstr "忽略大小写"
|
||||
|
||||
#: documents/models.py:71
|
||||
msgid "owner"
|
||||
msgstr ""
|
||||
msgstr "所有者"
|
||||
|
||||
#: documents/models.py:81 documents/models.py:136
|
||||
msgid "correspondent"
|
||||
@@ -192,11 +192,11 @@ msgstr "当前存储中的归档文件名"
|
||||
|
||||
#: documents/models.py:239
|
||||
msgid "original filename"
|
||||
msgstr ""
|
||||
msgstr "原文件名"
|
||||
|
||||
#: documents/models.py:245
|
||||
msgid "The original name of the file when it was uploaded"
|
||||
msgstr ""
|
||||
msgstr "文件上传时的原始名称"
|
||||
|
||||
#: documents/models.py:252
|
||||
msgid "archive serial number"
|
||||
@@ -372,15 +372,15 @@ msgstr "有标签包含于"
|
||||
|
||||
#: documents/models.py:437
|
||||
msgid "ASN greater than"
|
||||
msgstr ""
|
||||
msgstr "ASN 大于"
|
||||
|
||||
#: documents/models.py:438
|
||||
msgid "ASN less than"
|
||||
msgstr ""
|
||||
msgstr "ASN 小于"
|
||||
|
||||
#: documents/models.py:439
|
||||
msgid "storage path is"
|
||||
msgstr ""
|
||||
msgstr "保存路径"
|
||||
|
||||
#: documents/models.py:449
|
||||
msgid "rule type"
|
||||
@@ -400,79 +400,79 @@ msgstr "过滤规则"
|
||||
|
||||
#: documents/models.py:563
|
||||
msgid "Task ID"
|
||||
msgstr ""
|
||||
msgstr "任务ID"
|
||||
|
||||
#: documents/models.py:564
|
||||
msgid "Celery ID for the Task that was run"
|
||||
msgstr ""
|
||||
msgstr "正在运行的任务的 Celery ID"
|
||||
|
||||
#: documents/models.py:569
|
||||
msgid "Acknowledged"
|
||||
msgstr ""
|
||||
msgstr "已确认"
|
||||
|
||||
#: documents/models.py:570
|
||||
msgid "If the task is acknowledged via the frontend or API"
|
||||
msgstr ""
|
||||
msgstr "如果任务通过前端或 API 确认"
|
||||
|
||||
#: documents/models.py:576
|
||||
msgid "Task Filename"
|
||||
msgstr ""
|
||||
msgstr "任务文件名"
|
||||
|
||||
#: documents/models.py:577
|
||||
msgid "Name of the file which the Task was run for"
|
||||
msgstr ""
|
||||
msgstr "正在运行的任务文件名称"
|
||||
|
||||
#: documents/models.py:583
|
||||
msgid "Task Name"
|
||||
msgstr ""
|
||||
msgstr "任务名称"
|
||||
|
||||
#: documents/models.py:584
|
||||
msgid "Name of the Task which was run"
|
||||
msgstr ""
|
||||
msgstr "运行中的任务名称"
|
||||
|
||||
#: documents/models.py:591
|
||||
msgid "Task State"
|
||||
msgstr ""
|
||||
msgstr "任务状态"
|
||||
|
||||
#: documents/models.py:592
|
||||
msgid "Current state of the task being run"
|
||||
msgstr ""
|
||||
msgstr "当前任务运行状态"
|
||||
|
||||
#: documents/models.py:597
|
||||
msgid "Created DateTime"
|
||||
msgstr ""
|
||||
msgstr "创建日期"
|
||||
|
||||
#: documents/models.py:598
|
||||
msgid "Datetime field when the task result was created in UTC"
|
||||
msgstr ""
|
||||
msgstr "任务结果创建时间(UTC)"
|
||||
|
||||
#: documents/models.py:603
|
||||
msgid "Started DateTime"
|
||||
msgstr ""
|
||||
msgstr "开始时间"
|
||||
|
||||
#: documents/models.py:604
|
||||
msgid "Datetime field when the task was started in UTC"
|
||||
msgstr ""
|
||||
msgstr "任务开始时间(UTC)"
|
||||
|
||||
#: documents/models.py:609
|
||||
msgid "Completed DateTime"
|
||||
msgstr ""
|
||||
msgstr "完成时间"
|
||||
|
||||
#: documents/models.py:610
|
||||
msgid "Datetime field when the task was completed in UTC"
|
||||
msgstr ""
|
||||
msgstr "任务完成时间(UTC)"
|
||||
|
||||
#: documents/models.py:615
|
||||
msgid "Result Data"
|
||||
msgstr ""
|
||||
msgstr "结果数据"
|
||||
|
||||
#: documents/models.py:617
|
||||
msgid "The data returned by the task"
|
||||
msgstr ""
|
||||
msgstr "任务返回的数据"
|
||||
|
||||
#: documents/models.py:626
|
||||
msgid "Comment for the document"
|
||||
msgstr ""
|
||||
msgstr "文档评论"
|
||||
|
||||
#: documents/models.py:650
|
||||
msgid "user"
|
||||
@@ -480,11 +480,11 @@ msgstr "用户"
|
||||
|
||||
#: documents/models.py:655
|
||||
msgid "comment"
|
||||
msgstr ""
|
||||
msgstr "备注"
|
||||
|
||||
#: documents/models.py:656
|
||||
msgid "comments"
|
||||
msgstr ""
|
||||
msgstr "备注"
|
||||
|
||||
#: documents/serialisers.py:80
|
||||
#, python-format
|
||||
@@ -554,7 +554,7 @@ msgstr "登录"
|
||||
|
||||
#: paperless/apps.py:9
|
||||
msgid "Paperless"
|
||||
msgstr ""
|
||||
msgstr "无纸版"
|
||||
|
||||
#: paperless/settings.py:521
|
||||
msgid "English (US)"
|
||||
@@ -562,7 +562,7 @@ msgstr "英语(美国)"
|
||||
|
||||
#: paperless/settings.py:522
|
||||
msgid "Arabic"
|
||||
msgstr ""
|
||||
msgstr "阿拉伯语"
|
||||
|
||||
#: paperless/settings.py:523
|
||||
msgid "Belarusian"
|
||||
@@ -670,7 +670,7 @@ msgstr "操作"
|
||||
|
||||
#: paperless_mail/admin.py:69
|
||||
msgid "The action applied to the mail. This action is only performed when the mail body or attachments were consumed from the mail."
|
||||
msgstr ""
|
||||
msgstr "邮件中的操作。仅当邮件正文或附件已被读取时执行此操作。"
|
||||
|
||||
#: paperless_mail/admin.py:77
|
||||
msgid "Metadata"
|
||||
@@ -750,11 +750,11 @@ msgstr "只处理附件。"
|
||||
|
||||
#: paperless_mail/models.py:62
|
||||
msgid "Process full Mail (with embedded attachments in file) as .eml"
|
||||
msgstr ""
|
||||
msgstr "处理.eml邮件文件(包含文件中的嵌入附件) "
|
||||
|
||||
#: paperless_mail/models.py:64
|
||||
msgid "Process full Mail (with embedded attachments in file) as .eml + process attachments as separate documents"
|
||||
msgstr ""
|
||||
msgstr "处理.eml邮件文件(包含文件中的嵌入附件) + 将附件作为单独的文档处理"
|
||||
|
||||
#: paperless_mail/models.py:70
|
||||
msgid "Process all files, including 'inline' attachments."
|
||||
@@ -858,7 +858,7 @@ msgstr "内嵌附件包含嵌入图像,所以最好将此选项与文件名过
|
||||
|
||||
#: paperless_mail/models.py:158
|
||||
msgid "consumption scope"
|
||||
msgstr ""
|
||||
msgstr "消费范围"
|
||||
|
||||
#: paperless_mail/models.py:164
|
||||
msgid "action"
|
||||
@@ -894,21 +894,21 @@ msgstr "分配此联系人"
|
||||
|
||||
#: paperless_mail/models.py:239
|
||||
msgid "uid"
|
||||
msgstr ""
|
||||
msgstr "UID"
|
||||
|
||||
#: paperless_mail/models.py:247
|
||||
msgid "subject"
|
||||
msgstr ""
|
||||
msgstr "标题"
|
||||
|
||||
#: paperless_mail/models.py:255
|
||||
msgid "received"
|
||||
msgstr ""
|
||||
msgstr "已接收"
|
||||
|
||||
#: paperless_mail/models.py:262
|
||||
msgid "processed"
|
||||
msgstr ""
|
||||
msgstr "已处理"
|
||||
|
||||
#: paperless_mail/models.py:268
|
||||
msgid "status"
|
||||
msgstr ""
|
||||
msgstr "状态"
|
||||
|
||||
|
@@ -781,6 +781,16 @@ CONSUMER_ASN_BARCODE_PREFIX: Final[str] = os.getenv(
|
||||
)
|
||||
|
||||
|
||||
CONSUMER_BARCODE_UPSCALE: Final[float] = float(
|
||||
os.getenv("PAPERLESS_CONSUMER_BARCODE_UPSCALE", 0.0),
|
||||
)
|
||||
|
||||
|
||||
CONSUMER_BARCODE_DPI: Final[str] = int(
|
||||
os.getenv("PAPERLESS_CONSUMER_BARCODE_DPI", 300),
|
||||
)
|
||||
|
||||
|
||||
OCR_PAGES = int(os.getenv("PAPERLESS_OCR_PAGES", 0))
|
||||
|
||||
# The default language that tesseract will attempt to use when parsing
|
||||
|
@@ -1,7 +1,7 @@
|
||||
from typing import Final
|
||||
from typing import Tuple
|
||||
|
||||
__version__: Final[Tuple[int, int, int]] = (1, 16, 2)
|
||||
__version__: Final[Tuple[int, int, int]] = (1, 16, 5)
|
||||
# Version string like X.Y.Z
|
||||
__full_version_str__: Final[str] = ".".join(map(str, __version__))
|
||||
# Version string like X.Y
|
||||
|
@@ -13,7 +13,6 @@ from humanfriendly import format_size
|
||||
from imap_tools import MailAttachment
|
||||
from imap_tools import MailMessage
|
||||
from tika_client import TikaClient
|
||||
from tika_client.data_models import TikaKey
|
||||
|
||||
from documents.parsers import DocumentParser
|
||||
from documents.parsers import ParseError
|
||||
@@ -33,7 +32,9 @@ class MailDocumentParser(DocumentParser):
|
||||
|
||||
def get_thumbnail(self, document_path: Path, mime_type: str, file_name=None):
|
||||
if not self.archive_path:
|
||||
self.archive_path = self.generate_pdf(document_path)
|
||||
self.archive_path = self.generate_pdf(
|
||||
self.parse_file_to_message(document_path),
|
||||
)
|
||||
|
||||
return make_thumbnail_from_pdf(
|
||||
self.archive_path,
|
||||
@@ -173,12 +174,8 @@ class MailDocumentParser(DocumentParser):
|
||||
with TikaClient(tika_url=self.tika_server) as client:
|
||||
parsed = client.tika.as_text.from_buffer(html, "text/html")
|
||||
|
||||
if hasattr(parsed, "content") and parsed.content is not None:
|
||||
if parsed.content is not None:
|
||||
return parsed.content.strip()
|
||||
elif TikaKey.Content in parsed.data:
|
||||
# May not be a completely handled type, but
|
||||
# the Tika response may still include content
|
||||
return parsed.data[TikaKey.Content].strip()
|
||||
return ""
|
||||
except Exception as err:
|
||||
raise ParseError(
|
||||
@@ -300,9 +297,6 @@ class MailDocumentParser(DocumentParser):
|
||||
css_file = Path(__file__).parent / "templates" / "output.css"
|
||||
email_html_file = self.mail_to_html(mail)
|
||||
|
||||
print(css_file)
|
||||
print(email_html_file)
|
||||
|
||||
with css_file.open("rb") as css_handle, email_html_file.open(
|
||||
"rb",
|
||||
) as email_html_handle:
|
||||
|
@@ -293,9 +293,7 @@ class TestEmailThumbnailGenerate(BaseMailParserTestCase):
|
||||
"message/rfc822",
|
||||
)
|
||||
|
||||
mock_generate_pdf.assert_called_once_with(
|
||||
test_file,
|
||||
)
|
||||
mock_generate_pdf.assert_called_once()
|
||||
mock_make_thumbnail_from_pdf.assert_called_once_with(
|
||||
"Mocked return value..",
|
||||
self.parser.tempdir,
|
||||
|
@@ -4,7 +4,6 @@ from pathlib import Path
|
||||
import httpx
|
||||
from django.conf import settings
|
||||
from tika_client import TikaClient
|
||||
from tika_client.data_models import TikaKey
|
||||
|
||||
from documents.parsers import DocumentParser
|
||||
from documents.parsers import ParseError
|
||||
@@ -59,13 +58,9 @@ class TikaDocumentParser(DocumentParser):
|
||||
f"{settings.TIKA_ENDPOINT}: {err}",
|
||||
) from err
|
||||
|
||||
self.text = None
|
||||
if hasattr(parsed, "content") and parsed.content is not None:
|
||||
self.text = parsed.content.strip()
|
||||
elif TikaKey.Content in parsed.data:
|
||||
# May not be a completely handled type, but
|
||||
# the Tika response may still include content
|
||||
self.text = parsed.data[TikaKey.Content].strip()
|
||||
self.text = parsed.content
|
||||
if self.text is not None:
|
||||
self.text = self.text.strip()
|
||||
|
||||
self.date = parsed.created
|
||||
self.archive_path = self.convert_to_pdf(document_path, file_name)
|
||||
|
Reference in New Issue
Block a user