Compare commits

..

102 Commits

Author SHA1 Message Date
jonaswinkler
f95fd4ced2 Merge branch 'dev' 2021-01-21 22:55:10 +01:00
jonaswinkler
227f7b6946 revert a change 2021-01-21 22:29:47 +01:00
jonaswinkler
1a0b954397 Merge branch 'dev' of github.com:jonaswinkler/paperless-ng into dev 2021-01-21 21:32:21 +01:00
jonaswinkler
87ad2ce1d6 added a note regarding updates after 0.9.13 2021-01-21 21:32:08 +01:00
Jonas Winkler
63cd16e29e Merge pull request #407 from jonaswinkler/translations_src-ui-messages-xlf--dev_fr
Translate '/src-ui/messages.xlf' in 'fr'
2021-01-21 21:16:02 +01:00
Jonas Winkler
66fc9e9111 Merge pull request #408 from jonaswinkler/translations_src-ui-messages-xlf--dev_de
Translate '/src-ui/messages.xlf' in 'de'
2021-01-21 21:15:49 +01:00
Jonas Winkler
43bee38b3c Merge pull request #406 from jonaswinkler/translations_src-ui-messages-xlf--dev_nl_NL
Translate '/src-ui/messages.xlf' in 'nl_NL'
2021-01-21 21:15:32 +01:00
transifex-integration[bot]
18ebb58dc9 Translate /src-ui/messages.xlf in de
translation completed for the source file '/src-ui/messages.xlf'
on the 'de' language.
2021-01-21 20:08:58 +00:00
transifex-integration[bot]
099b84a66d Translate /src-ui/messages.xlf in fr
translation completed for the source file '/src-ui/messages.xlf'
on the 'fr' language.
2021-01-21 20:08:46 +00:00
transifex-integration[bot]
3b22d7131d Translate /src-ui/messages.xlf in nl_NL
translation completed for the source file '/src-ui/messages.xlf'
on the 'nl_NL' language.
2021-01-21 20:08:36 +00:00
jonaswinkler
11f9616411 improve locale selection options 2021-01-21 21:05:16 +01:00
Jonas Winkler
10b53bdfd0 Update README.md 2021-01-21 13:49:12 +01:00
jonaswinkler
aeb10d3407 fixes duplicate documents with tags__id__in 2021-01-21 12:07:50 +01:00
jonaswinkler
ddf386c4d4 add temporary directory during startup and ensure correct permissions 2021-01-21 01:02:41 +01:00
jonaswinkler
9575b0fe32 fixes #397 2021-01-20 20:28:42 +01:00
jonaswinkler
6c7290bd34 Merge branch 'dev' of github.com:jonaswinkler/paperless-ng into dev 2021-01-20 15:25:33 +01:00
Jonas Winkler
19032fe433 Merge pull request #396 from jonaswinkler/translations_src-ui-messages-xlf--dev_de
Translate '/src-ui/messages.xlf' in 'de' [manual sync]
2021-01-20 14:46:46 +01:00
Jonas Winkler
8fce8d4677 Merge pull request #395 from jonaswinkler/translations_src-ui-messages-xlf--dev_fr
Translate '/src-ui/messages.xlf' in 'fr' [manual sync]
2021-01-20 14:45:53 +01:00
Jonas Winkler
2333ea9dc7 Merge pull request #394 from jonaswinkler/translations_src-ui-messages-xlf--dev_nl_NL
Translate '/src-ui/messages.xlf' in 'nl_NL' [manual sync]
2021-01-20 14:45:31 +01:00
transifex-integration[bot]
937cdaccad Translate /src-ui/messages.xlf in de
at least 99% translated for the source file '/src-ui/messages.xlf'
on the 'de' language.

 Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
2021-01-20 13:44:37 +00:00
transifex-integration[bot]
54916fec2e Translate /src-ui/messages.xlf in fr
at least 99% translated for the source file '/src-ui/messages.xlf'
on the 'fr' language.

 Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
2021-01-20 13:44:31 +00:00
transifex-integration[bot]
03e159f67c Translate /src-ui/messages.xlf in nl_NL
at least 99% translated for the source file '/src-ui/messages.xlf'
on the 'nl_NL' language.

 Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
2021-01-20 13:44:24 +00:00
jonaswinkler
482ef6313d changelog 2021-01-20 14:35:38 +01:00
jonaswinkler
43685baff3 fix tag clicking on document table list 2021-01-20 14:29:30 +01:00
jonaswinkler
f6a2cc74e8 clicking on small and large cards changed 2021-01-20 14:25:52 +01:00
jonaswinkler
9f1436a865 more test 2021-01-20 12:34:01 +01:00
jonaswinkler
020df6c8ea Merge branch 'dev' of github.com:jonaswinkler/paperless-ng into dev 2021-01-20 11:56:27 +01:00
jonaswinkler
08046cb83f revert changes for #351 2021-01-20 11:56:09 +01:00
Jonas Winkler
f06edebbd8 Update Crowdin configuration file 2021-01-20 11:39:20 +01:00
Jonas Winkler
c808011b75 Update Crowdin configuration file 2021-01-20 11:37:32 +01:00
jonaswinkler
da60fc8150 Merge branch 'master' into dev 2021-01-19 16:55:18 +01:00
Jonas Winkler
04a0d01b21 Merge pull request #367 from C0nsultant/ansible-verifyupdates
Ansible - Verify that updates between versions work
2021-01-19 16:53:49 +01:00
Jonas Winkler
02a066f8f3 Update README.md 2021-01-19 16:43:12 +01:00
jonaswinkler
7834d369c6 txt preview #338 2021-01-19 16:23:49 +01:00
jonaswinkler
5e841531be more test 2021-01-19 16:14:28 +01:00
jonaswinkler
5355f2b027 fixes #351 2021-01-19 14:43:55 +01:00
jonaswinkler
e1533202fc Merge branch 'dev' of github.com:jonaswinkler/paperless-ng into dev 2021-01-19 14:01:16 +01:00
jonaswinkler
0b949a14c0 add filtering to management pages #356 2021-01-19 14:00:15 +01:00
Jonas Winkler
5175206179 Merge pull request #384 from jonaswinkler/translations_src-ui-messages-xlf--dev_fr
Translate '/src-ui/messages.xlf' in 'fr'
2021-01-19 00:30:04 +01:00
transifex-integration[bot]
0af0dffeda Translate /src-ui/messages.xlf in fr
translation completed for the source file '/src-ui/messages.xlf'
on the 'fr' language.
2021-01-18 23:28:17 +00:00
Fabian Koller
74a1b36005 Update administration docs with ansible update 2021-01-18 23:19:16 +01:00
Fabian Koller
8884a4dfdf molecule scenario to test upgrading from releases
Provide a separate scenario to install the last release, then update to
the current one.
Also includes improved deployment verification (check if uploading a
.txt through the API works).
2021-01-18 22:51:40 +01:00
Fabian Koller
19f73f5782 Make update ansible role paths explicit 2021-01-18 22:51:40 +01:00
Fabian Koller
8e95310602 Fix ENV var name for user args in documentation
Follow-up to #214
2021-01-18 22:51:40 +01:00
Jonas Winkler
fe31b8d160 Merge pull request #382 from jonaswinkler/translations_src-ui-messages-xlf--dev_de
Translate '/src-ui/messages.xlf' in 'de'
2021-01-18 22:32:01 +01:00
Jonas Winkler
6515d1ae85 Merge pull request #383 from jonaswinkler/translations_src-ui-messages-xlf--dev_nl_NL
Translate '/src-ui/messages.xlf' in 'nl_NL'
2021-01-18 22:31:49 +01:00
transifex-integration[bot]
a8ec9f29cd Translate /src-ui/messages.xlf in nl_NL
translation completed for the source file '/src-ui/messages.xlf'
on the 'nl_NL' language.
2021-01-18 21:31:31 +00:00
transifex-integration[bot]
bab53838ec Translate /src-ui/messages.xlf in de
translation completed for the source file '/src-ui/messages.xlf'
on the 'de' language.
2021-01-18 21:30:59 +00:00
jonaswinkler
bf2e98527c updated messages 2021-01-18 22:30:06 +01:00
jonaswinkler
e1e11de2b5 mail tests 2021-01-18 22:23:53 +01:00
jonaswinkler
4fda8f3348 changelog 2021-01-18 22:23:19 +01:00
jonaswinkler
8427d58337 Merge branch 'master' into dev 2021-01-18 15:44:26 +01:00
jonaswinkler
385076cf28 documentation and changelog 2021-01-18 15:43:48 +01:00
jonaswinkler
b9725437d9 delete option for exporter, short options, tests 2021-01-18 15:33:05 +01:00
jonaswinkler
72616def4f locking for the document archiver 2021-01-18 15:18:03 +01:00
jonaswinkler
6c972bd08a more tests 2021-01-18 14:47:19 +01:00
jonaswinkler
a71a991084 fix some test cases due to renamed test files 2021-01-18 14:20:45 +01:00
jonaswinkler
0927f9d477 some bug fixes and tests 2021-01-18 14:16:32 +01:00
jonaswinkler
a68b858733 new exporter that updates the export in place, fixes #376 #343 #166 2021-01-18 01:15:39 +01:00
jonaswinkler
08199f09b6 fixes for #374 2021-01-17 12:14:19 +01:00
Jonas Winkler
5f8151282b Merge pull request #374 from shamoon/fix/issue-325-2
Allow "live" visualizing of date locale in settings
2021-01-17 12:10:28 +01:00
Jonas Winkler
efde4828d6 Merge pull request #375 from jonaswinkler/translations_src-ui-messages-xlf--dev_nl_NL
Translate '/src-ui/messages.xlf' in 'nl_NL'
2021-01-17 11:11:38 +01:00
transifex-integration[bot]
016c168404 Translate /src-ui/messages.xlf in nl_NL
translation completed for the source file '/src-ui/messages.xlf'
on the 'nl_NL' language.
2021-01-17 09:04:39 +00:00
Michael Shamoon
741ccfa280 Fix svg attribute error
Unrelated to the rest of this branch but not worth a separate PR
2021-01-16 21:39:13 -08:00
Michael Shamoon
31b74515b6 Allow "live" changing of date format 2021-01-16 20:49:12 -08:00
Jonas Winkler
b9a2f82ce0 Merge pull request #370 from shamoon/fix/issue-350
Prevent close button in modal dialogs 'stealing' focus
2021-01-17 01:32:21 +01:00
jonaswinkler
3c59d9b787 Merge branch 'dev' of github.com:jonaswinkler/paperless-ng into dev 2021-01-17 00:53:32 +01:00
jonaswinkler
f919ec0d57 version bump 2021-01-17 00:52:54 +01:00
Jonas Winkler
9c380f5aac Merge pull request #371 from jonaswinkler/translations_src-ui-messages-xlf--dev_de
Translate '/src-ui/messages.xlf' in 'de'
2021-01-17 00:30:08 +01:00
transifex-integration[bot]
fc5def157d Translate /src-ui/messages.xlf in de
translation completed for the source file '/src-ui/messages.xlf'
on the 'de' language.
2021-01-16 23:28:01 +00:00
jonaswinkler
d5eff386db update translation messages 2021-01-17 00:25:40 +01:00
jonaswinkler
864e421cd3 add configuration option for changing date display in paperless #325 2021-01-17 00:15:45 +01:00
Michael Shamoon
2c9825193b Comment typo 2021-01-16 14:14:05 -08:00
Michael Shamoon
98f3e99e2e Prevent close button 'stealing' focus from modal input fields 2021-01-16 14:09:23 -08:00
Jonas Winkler
961354aa8a Merge pull request #362 from shamoon/fix/issue-347
Allow shift-select in documents list
2021-01-16 20:58:34 +01:00
Jonas Winkler
fa27c895ed Merge pull request #355 from C0nsultant/ansible-documentation
Ansible - Provide documentation
2021-01-16 14:30:07 +01:00
Michael Shamoon
c31b6e63f5 Prevent text selection on table rows 2021-01-15 16:13:22 -08:00
Michael Shamoon
ef924e896b Fix reverting old selection in all cases by always doing it 2021-01-15 07:57:01 -08:00
Jonas Winkler
5b1619cba3 Merge pull request #364 from jonaswinkler/translations_src-ui-messages-xlf--dev_fr
Translate '/src-ui/messages.xlf' in 'fr'
2021-01-15 13:49:47 +01:00
transifex-integration[bot]
a3a9949ebc Translate /src-ui/messages.xlf in fr
translation completed for the source file '/src-ui/messages.xlf'
on the 'fr' language.
2021-01-15 12:42:26 +00:00
Jonas Winkler
ada8493838 Merge pull request #363 from jonaswinkler/translations_src-ui-messages-xlf--dev_de
Translate '/src-ui/messages.xlf' in 'de'
2021-01-15 12:53:53 +01:00
transifex-integration[bot]
cc06d528cb Translate /src-ui/messages.xlf in de
translation completed for the source file '/src-ui/messages.xlf'
on the 'de' language.
2021-01-15 11:52:06 +00:00
jonaswinkler
0926266663 add a language switcher fixes #352 2021-01-15 12:50:34 +01:00
Michael Shamoon
59008ea765 remove new line =/ 2021-01-15 02:22:10 -08:00
Michael Shamoon
01cd4c7546 Refactor variable names for clarity 2021-01-15 02:15:26 -08:00
Michael Shamoon
8d606b9f34 Handle shift-clicking orignal item 2021-01-15 02:13:21 -08:00
Michael Shamoon
86376c8c5f Fix repeat range selections were clashing 2021-01-15 02:09:13 -08:00
Michael Shamoon
48220ceeb8 Refactor selection functions to two separate ones for clarity 2021-01-15 01:59:29 -08:00
Michael Shamoon
f94da1cf27 Allow reversing selection range 2021-01-15 01:54:33 -08:00
Michael Shamoon
6d786f8987 remove log statement 2021-01-15 01:11:06 -08:00
Fabian Koller
8d433ac0de Update setup docs with ansible instructions 2021-01-15 10:10:36 +01:00
Michael Shamoon
4b42c97d0a Allow select anywhere in tr or card 2021-01-15 01:10:01 -08:00
Jonas Winkler
d8637ff4b1 Merge pull request #349 from C0nsultant/patch-4
Fix ENV var name for user args in documentation
2021-01-14 23:31:16 +01:00
Jonas Winkler
342e9c9734 Merge pull request #353 from C0nsultant/ansible-0.9.14
Ansible - Update to 0.9.14
2021-01-14 23:30:57 +01:00
Jonas Winkler
af1d084391 Merge pull request #354 from C0nsultant/patch-5
Only provide legal cors allowed hosts in example
2021-01-14 23:30:29 +01:00
Michael Shamoon
e6961d5287 Allow range selection with shift 2021-01-14 14:10:23 -08:00
jonaswinkler
7562bdb218 update the CI/CD scripts to not build and push docker images from master, update 'latest' version together with tagged releases. 2021-01-14 22:51:27 +01:00
Fabian Koller
cb94e15ba7 Update ansible README.md 2021-01-14 21:50:07 +01:00
Fabian Koller
c8b0674b93 Update to 0.9.14 2021-01-14 21:23:44 +01:00
Fabian Koller
4fa1779ef3 Only provide legal cors allowed hosts in example
Addresses that do not carry a scheme cause errors on database migration.


SystemCheckError: System check identified some issues:

ERRORS:
?: (corsheaders.E013) Origin 'example.com' in CORS_ALLOWED_ORIGINS is missing scheme or netloc
    HINT: Add a scheme (e.g. https://) or netloc (e.g. example.com).
2021-01-14 21:14:46 +01:00
Fabian Koller
db23a5cf37 Fix ENV var name for user args in documentation
Follow-up to #214
2021-01-14 20:21:34 +01:00
Michael Shamoon
7cc3c73994 Convert selection functions on cards to toggling, let service handle setting selected
Also because we need to capture mouseevents
2021-01-14 10:56:30 -08:00
81 changed files with 2212 additions and 676 deletions

View File

@@ -26,10 +26,15 @@ jobs:
docker --version docker --version
molecule --version molecule --version
python --version python --version
- name: Test with molecule - name: Test fresh installation with molecule
run: | run: |
cd ansible cd ansible
molecule test molecule test -s fresh
working-directory: "${{ github.repository }}"
- name: Test release update with molecule
run: |
cd ansible
molecule test -s update
working-directory: "${{ github.repository }}" working-directory: "${{ github.repository }}"
# # https://galaxy.ansible.com/docs/contributing/importing.html # # https://galaxy.ansible.com/docs/contributing/importing.html
# release: # release:

View File

@@ -208,7 +208,7 @@ jobs:
tag_name: ng-${{ steps.get_version.outputs.version }} tag_name: ng-${{ steps.get_version.outputs.version }}
release_name: Paperless-ng ${{ steps.get_version.outputs.version }} release_name: Paperless-ng ${{ steps.get_version.outputs.version }}
draft: false draft: false
prerelease: true prerelease: false
body: | body: |
For a complete list of changes, see the changelog at https://paperless-ng.readthedocs.io/en/latest/changelog.html. For a complete list of changes, see the changelog at https://paperless-ng.readthedocs.io/en/latest/changelog.html.
- -
@@ -225,7 +225,7 @@ jobs:
# build and push image to docker hub. # build and push image to docker hub.
build-docker-image: build-docker-image:
if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/ng-')) if: github.event_name == 'push' && (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/ng-'))
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [frontend, tests] needs: [frontend, tests]
steps: steps:
@@ -233,15 +233,18 @@ jobs:
name: Prepare name: Prepare
id: prepare id: prepare
run: | run: |
VERSION=edge IMAGE_NAME=jonaswinkler/paperless-ng
if [[ $GITHUB_REF == refs/tags/ng-* ]]; then if [[ $GITHUB_REF == refs/tags/ng-* ]]; then
VERSION=${GITHUB_REF#refs/tags/ng-} TAGS=${IMAGE_NAME}:${GITHUB_REF#refs/tags/ng-},${IMAGE_NAME}:latest
elif [[ $GITHUB_REF == refs/heads/master ]]; then INSPECT_TAG=${IMAGE_NAME}:latest
VERSION=latest
elif [[ $GITHUB_REF == refs/heads/* ]]; then elif [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=${GITHUB_REF#refs/heads/} TAGS=${IMAGE_NAME}:${GITHUB_REF#refs/heads/}
INSPECT_TAG=${TAGS}
else
exit 1
fi fi
echo ::set-output name=version::${VERSION} echo ::set-output name=tags::${TAGS}
echo ::set-output name=inspect_tag::${INSPECT_TAG}
- -
name: Checkout name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -279,10 +282,10 @@ jobs:
file: ./Dockerfile file: ./Dockerfile
platforms: linux/amd64,linux/arm/v7,linux/arm64 platforms: linux/amd64,linux/arm/v7,linux/arm64
push: true push: true
tags: jonaswinkler/paperless-ng:${{ steps.prepare.outputs.version }} tags: ${{ steps.prepare.outputs.tags }}
cache-from: type=local,src=/tmp/.buildx-cache cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache
- -
name: Inspect image name: Inspect image
run: | run: |
docker buildx imagetools inspect jonaswinkler/paperless-ng:${{ steps.prepare.outputs.version }} docker buildx imagetools inspect ${{ steps.prepare.outputs.inspect_tag }}

View File

@@ -10,7 +10,9 @@
Paperless-ng is a fork of the original project, adding a new interface and many other changes under the hood. For a detailed list of changes, have a look at the changelog in the documentation. Paperless-ng is a fork of the original project, adding a new interface and many other changes under the hood. For a detailed list of changes, have a look at the changelog in the documentation.
This project is still in development and some things may not work as expected. # Survey
If you already used Paperless-ng for a bit, would like to give some anonymous feedback, and help me decide on what to focus on next: I've created a survey, [see here](https://github.com/jonaswinkler/paperless-ng/issues/402). Thank you!
# How it Works # How it Works
@@ -48,7 +50,7 @@ Here's what you get:
* Paperless learns from your documents and will be able to automatically assign tags, correspondents and types to documents once you've stored a few documents in paperless. * Paperless learns from your documents and will be able to automatically assign tags, correspondents and types to documents once you've stored a few documents in paperless.
* A task processor that processes documents in parallel and also tells you when something goes wrong. On modern multi core systems, consumption is blazing fast. * A task processor that processes documents in parallel and also tells you when something goes wrong. On modern multi core systems, consumption is blazing fast.
If you want to see some screenshots of paperless-ng in action, [some are available in the documentation](https://paperless-ng.readthedocs.io/en/latest/screenshots.html). If you want to see some screenshots of paperless-ng in action, [some are available in the documentation](https://paperless-ng.readthedocs.io/en/latest/screenshots.html). However, some parts of the UI have changed since I took these.
For a complete list of changes from paperless, check out the [changelog](https://paperless-ng.readthedocs.io/en/latest/changelog.html) For a complete list of changes from paperless, check out the [changelog](https://paperless-ng.readthedocs.io/en/latest/changelog.html)
@@ -58,20 +60,6 @@ For a complete list of changes from paperless, check out the [changelog](https:/
- Fix whatever bugs I and you find. - Fix whatever bugs I and you find.
- Make the documentation nice. - Make the documentation nice.
## Roadmap for versions beyond 1.0
These are things that I want to add to paperless eventually. They are sorted by priority.
- **More search.** The search backend is incredibly versatile and customizable. Searching is the most important feature of this project and thus, I want to implement things like:
- Group and limit search results by correspondent, show “more from this” links in the results.
- **Nested tags**. Organize tags in a hierarchical structure. This will combine the benefits of folders and tags in one coherent system.
- **An interactive consumer** that shows its progress for documents it processes on the web page.
- With live updates and websockets. This already works on a dev branch, but requires a lot of new dependencies, which I'm not particularly happy about.
- Notifications when a document was added with buttons to open the new document right away.
- **Arbitrary tag colors**. Allow the selection of any color with a color picker.
Apart from that, paperless is pretty much feature complete.
## On the chopping block. ## On the chopping block.
- **GnuPG encrypion.** [Here's a note about encryption in paperless](https://paperless-ng.readthedocs.io/en/latest/administration.html#managing-encryption). The gist of it is that I don't see which attacks this implementation protects against. It gives a false sense of security to users who don't care about how it works. - **GnuPG encrypion.** [Here's a note about encryption in paperless](https://paperless-ng.readthedocs.io/en/latest/administration.html#managing-encryption). The gist of it is that I don't see which attacks this implementation protects against. It gives a false sense of security to users who don't care about how it works.

View File

@@ -1,38 +1,114 @@
Role Name Ansible Role: paperless-ng
========= ==========================
A brief description of the role goes here. Installs and configures paperless-ng EDMS on Debian/Ubuntu systems.
Requirements Requirements
------------ ------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. No special system requirements. Ansible 2.7 or newer is required.
Note that this role requires root access, so either run it in a playbook with a global `become: yes`, or invoke the role in your playbook like:
- hosts: all
roles:
- role: ansible
become: yes
Role Variables Role Variables
-------------- --------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. Most configuration variables from paperless-ng itself are available and accept their respective arguments.
Every `PAPERLESS_*` configuration varaible is lowercased and instead prefixed with `paperlessng_*` in `defaults/main.yml`.
For a full listing including explainations and allowed values, see the current [documentation](https://paperless-ng.readthedocs.io/en/ng-0.9.14/configuration.html).
Additional variables available in this role are listed below, along with default values:
paperlessng_version: 0.9.14
The [release](https://github.com/jonaswinkler/paperless-ng/releases) archive version of paperless-ng to install.
paperlessng_redis_host: localhost
paperlessng_redis_port: 6379
Seperate configuration values that combine into `PAPERLESS_REDIS`.
paperlessng_db_type: sqlite
Database to use. Default is file-based SQLite.
paperlessng_db_host: localhost
paperlessng_db_port: 5432
paperlessng_db_name: paperlessng
paperlessng_db_user: paperlessng
paperlessng_db_pass: paperlessng
paperlessng_db_sslmode: prefer
Database configuration (only applicable if `paperlessng_db_type == 'postgresql'`).
paperlessng_directory: /opt/paperless-ng
Root directory paperless-ng is installed into.
paperlessng_virtualenv: "{{ paperlessng_directory }}/.venv"
Directory used for the virtual environment for paperless-ng.
paperlessng_ocr_languages:
- eng
List of OCR languages to install and configure (`apt search tesseract-ocr-*`).
paperlessng_use_jbig2enc: True
Whether to install and use [jbig2enc](https://github.com/agl/jbig2enc) for OCRmyPDF.
paperlessng_big2enc_lossy: False
Whether to use jbig2enc's lossy compression mode.
paperlessng_superuser_name: paperlessng
paperlessng_superuser_email: paperlessng@example.com
paperlessng_superuser_password: paperlessng
Credentials of the initial superuser in paperless-ng.
paperlessng_system_user: paperlessng
paperlessng_system_group: paperlessng
System user and group to run the paperless-ng services as (will be created if required).
paperlessng_listen_address: 127.0.0.1
paperlessng_listen_port: 8000
Address and port for the paperless-ng service to listen on.
Dependencies Dependencies
------------ ------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. No ansible dependencies.
Example Playbook Example Playbook
---------------- ----------------
`playbook.yml`:
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: - hosts: all
become: yes
- hosts: servers vars_files:
- vars/main.yml
roles: roles:
- { role: username.rolename, x: 42 } - ansible
License `vars/main.yml`:
-------
BSD paperlessng_media_root: /mnt/media/smbshare
Author Information paperlessng_db_type: postgresql
------------------ paperlessng_db_pass: PLEASEPROVIDEASTRONGPASSWORDHERE
An optional section for the role authors to include contact information, or a website (HTML is not allowed). paperless_secret_key: AGAINPLEASECHANGETHISNOW
paperlessng_ocr_languages:
- eng
- deu

View File

@@ -1,5 +1,19 @@
--- ---
paperlessng_version: 0.9.13 paperlessng_version: 0.9.14
# Required services
paperlessng_redis_host: localhost
paperlessng_redis_port: 6379
paperlessng_db_type: sqlite # or postgresql
# Below entries only apply for paperlessng_db_type=='postgresql'
paperlessng_db_host: localhost
paperlessng_db_port: 5432
paperlessng_db_name: paperlessng
paperlessng_db_user: paperlessng
paperlessng_db_pass: paperlessng
paperlessng_db_sslmode: prefer
# Paths and folders
paperlessng_directory: /opt/paperless-ng paperlessng_directory: /opt/paperless-ng
paperlessng_consumption_dir: "{{ paperlessng_directory }}/consumption" paperlessng_consumption_dir: "{{ paperlessng_directory }}/consumption"
paperlessng_data_dir: "{{ paperlessng_directory }}/data" paperlessng_data_dir: "{{ paperlessng_directory }}/data"
@@ -8,36 +22,57 @@ paperlessng_static_dir: "{{ paperlessng_directory }}/static"
paperlessng_filename_format: paperlessng_filename_format:
paperlessng_virtualenv: "{{ paperlessng_directory }}/.venv" paperlessng_virtualenv: "{{ paperlessng_directory }}/.venv"
# Hosting & Security
paperless_secret_key: PLEASECHANGETHISFORTHELOVEOFGOD
paperless_allowed_hosts: "*"
paperless_cors_allowed_hosts: http://localhost:8000
paperless_force_script_name:
paperless_static_url: /static/
paperless_auto_login_username:
paperless_cookie_prefix: ""
paperless_enable_http_remote_user: False
# OCR settings
paperlessng_ocr_languages: paperlessng_ocr_languages:
- eng - eng
paperlessng_time_zone: Europe/Berlin paperlessng_ocr_mode: skip
paperlessng_ocr_output_type: pdfa
paperlessng_ocr_pages: 0
paperlessng_ocr_image_dpi:
# see https://ocrmypdf.readthedocs.io/en/latest/api.html#ocrmypdf.ocr # see https://ocrmypdf.readthedocs.io/en/latest/api.html#ocrmypdf.ocr
paperlessng_ocrmypdf_args: paperlessng_ocr_user_args:
#- "deskew": true # https://github.com/jonaswinkler/paperless-ng/issues/231 #- "deskew": True # https://github.com/jonaswinkler/paperless-ng/issues/231
- "optimize": 1 - "optimize": 1
paperlessng_use_jbig2enc: true paperlessng_use_jbig2enc: True
paperlessng_big2enc_lossy: false paperlessng_big2enc_lossy: False
paperlessng_tika_enabled: false
# Tika settings
paperlessng_tika_enabled: False
paperlessng_tika_endpoint: http://localhost:9998 paperlessng_tika_endpoint: http://localhost:9998
paperlessng_tika_gotenberg_endpoint: http://localhost:3000 paperlessng_tika_gotenberg_endpoint: http://localhost:3000
# Software tweaks
paperlessng_time_zone: Europe/Berlin
paperlessng_consumer_polling: 0
paperlessng_consumer_delete_duplicates: False
paperlessng_consumer_recursive: False
paperlessng_consumer_subdirs_as_tags: False
paperlessng_optimize_thumbnails: True
paperlessng_post_consume_script:
paperlessng_filename_date_order:
paperlessng_filename_parse_transforms:
paperlessng_thumbnail_font_name: /usr/share/fonts/liberation/LiberationSerif-Regular.ttf
paperlessng_ignore_dates: ""
# Superuser settings
paperlessng_superuser_name: paperlessng paperlessng_superuser_name: paperlessng
paperlessng_superuser_email: paperlessng@example.com paperlessng_superuser_email: paperlessng@example.com
paperlessng_superuser_password: paperlessng paperlessng_superuser_password: paperlessng
# System user settings
paperlessng_system_user: paperlessng paperlessng_system_user: paperlessng
paperlessng_system_group: paperlessng paperlessng_system_group: paperlessng
# Webserver settings
paperlessng_listen_address: 127.0.0.1 paperlessng_listen_address: 127.0.0.1
paperlessng_listen_port: 8000 paperlessng_listen_port: 8000
paperlessng_redis_host: localhost
paperlessng_redis_port: 6379
paperlessng_db_type: sqlite # or postgresql
# Below entries only apply for paperlessng_db_type=='postgresql'
paperlessng_db_host: localhost
paperlessng_db_port: 5432
paperlessng_db_name: paperlessng
paperlessng_db_user: paperlessng
paperlessng_db_pass: paperlessng

View File

@@ -1,7 +0,0 @@
---
- name: Converge
hosts: all
tasks:
- name: "Include ansible"
include_role:
name: "ansible"

View File

@@ -1,14 +0,0 @@
---
# This is an example playbook to execute Ansible tests.
- name: Verify
hosts: all
gather_facts: false
tasks:
- name: check if webserver is up
uri:
url: http://localhost:8000
status_code: [200, 302]
return_content: yes
register: landingpage
failed_when: "'Sign in</button>' not in landingpage.content"

View File

@@ -0,0 +1,7 @@
---
- name: fresh installation
hosts: all
tasks:
- name: install paperless-ng with default parameters
include_role:
name: ansible

View File

@@ -0,0 +1,60 @@
---
- name: Verify
hosts: all
gather_facts: false
vars_files:
- ../../defaults/main.yml
tasks:
- name: check if webserver is up
uri:
url: http://localhost:8000
status_code: [200, 302]
return_content: yes
register: landingpage
failed_when: "'Sign in</button>' not in landingpage.content"
- name: check if document posting works
uri:
url: http://localhost:8000/api/documents/post_document/
method: POST
body_format: form-multipart
body:
document:
content: FOO
filename: document.txt
mime_type: text/plain
headers:
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
return_content: yes
register: post_document
failed_when: "'OK' not in post_document.content"
- name: verify uploaded document has been accepted
uri:
url: http://localhost:8000/api/logs/
headers:
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
return_content: yes
register: logs
failed_when: "'Consuming document.txt' not in logs.content"
# assumes txt consumption finished by now, might have to sleep a bit
- name: verify uploaded document has been consumed
uri:
url: http://localhost:8000/api/logs/
headers:
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
return_content: yes
register: logs
failed_when: "'document consumption finished' not in logs.content"
- name: verify uploaded document is avaiable
uri:
url: http://localhost:8000/api/documents/1/
headers:
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
return_content: yes
register: document
failed_when: "'Not found.' in document.content or 'FOO' not in document.content"

View File

@@ -0,0 +1,11 @@
---
- name: update previous release to newest release
hosts: all
tasks:
- name: set current version as installation target
set_fact:
paperlessng_version: 0.9.14
- name: update to newest paperless-ng release
include_role:
name: ansible

View File

@@ -0,0 +1,35 @@
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: ubuntu_focal
image: jrei/systemd-ubuntu:20.04
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
tmpfs:
- /tmp
- /run
- /run/lock
override_command: False
# ubuntu 18.04 bionic works except that
# the default redis configuration expects IPv6 which is not enabled in docker by default
# the default Python environment is configured for ASCII instead of UTF-8
# ubuntu 16.04 xenial only has Python 3.5 which is EOL and breaks multiple dependencies
- name: debian_buster
image: jrei/systemd-debian:10
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
tmpfs:
- /tmp
- /run
- /run/lock
override_command: False
# debian 9 stretch only has Python 3.5 which is EOL and breaks multiple dependencies
provisioner:
name: ansible
verifier:
name: ansible

View File

@@ -0,0 +1,10 @@
- name: install previous release
hosts: all
tasks:
- name: set previous version as installation target
set_fact:
paperlessng_version: 0.9.13
- name: install previous paperless-ng release
include_role:
name: ansible

View File

@@ -0,0 +1,60 @@
---
- name: Verify
hosts: all
gather_facts: false
vars_files:
- ../../defaults/main.yml
tasks:
- name: check if webserver is up
uri:
url: http://localhost:8000
status_code: [200, 302]
return_content: yes
register: landingpage
failed_when: "'Sign in</button>' not in landingpage.content"
- name: check if document posting works
uri:
url: http://localhost:8000/api/documents/post_document/
method: POST
body_format: form-multipart
body:
document:
content: FOO
filename: document.txt
mime_type: text/plain
headers:
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
return_content: yes
register: post_document
failed_when: "'OK' not in post_document.content"
- name: verify uploaded document has been accepted
uri:
url: http://localhost:8000/api/logs/
headers:
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
return_content: yes
register: logs
failed_when: "'Consuming document.txt' not in logs.content"
# assumes txt consumption finished by now, might have to sleep a bit
- name: verify uploaded document has been consumed
uri:
url: http://localhost:8000/api/logs/
headers:
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
return_content: yes
register: logs
failed_when: "'document consumption finished' not in logs.content"
- name: verify uploaded document is avaiable
uri:
url: http://localhost:8000/api/documents/1/
headers:
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
return_content: yes
register: document
failed_when: "'Not found.' in document.content or 'FOO' not in document.content"

View File

@@ -9,26 +9,26 @@
update_cache: yes update_cache: yes
pkg: pkg:
# paperless-ng # paperless-ng
- python3-dev
- python3-pip - python3-pip
- gettext - python3-dev
- fonts-liberation - fonts-liberation
- imagemagick - imagemagick
- unpaper
- ghostscript
- optipng - optipng
- tesseract-ocr
- gnupg - gnupg
- libpoppler-cpp-dev - libpoppler-cpp-dev
- libmagic-dev
- libpq-dev - libpq-dev
- libmagic-dev
- mime-support
# OCRmyPDF # OCRmyPDF
- unpaper
- ghostscript
- icc-profiles-free - icc-profiles-free
- qpdf - qpdf
- liblept5 - liblept5
- libxml2 - libxml2
- pngquant - pngquant
- zlib1g - zlib1g
- tesseract-ocr
# dev # dev
- sudo - sudo
- build-essential - build-essential
@@ -105,46 +105,64 @@
ignore_errors: yes ignore_errors: yes
register: paperlessng_current_version register: paperlessng_current_version
- name: register current state
set_fact:
fresh_installation: '{{ "No such file or directory" in paperlessng_current_version.stderr }}'
update_installation: '{{ "No such file or directory" not in paperlessng_current_version.stderr and paperlessng_current_version.stdout != paperlessng_version | string }}'
reconfigure_only: '{{ paperlessng_current_version.stdout == paperlessng_version | string }}'
- name: backup current paperless-ng installation - name: backup current paperless-ng installation
copy: copy:
src: "{{ paperlessng_directory }}" src: "{{ paperlessng_directory }}"
remote_src: yes remote_src: yes
dest: "{{ paperlessng_directory }}-{{ ansible_date_time.iso8601 }}/" dest: "{{ paperlessng_directory }}-{{ ansible_date_time.iso8601 }}/"
when: '"No such file or directory" not in paperlessng_current_version.stderr and paperlessng_current_version.stdout != paperlessng_version | string' when: update_installation
- name: remove current paperless sources
file:
path: "{{ paperlessng_directory }}/{{ item }}"
state: absent
with_items:
- docker
- docs
- scripts
- src
- static
when: update_installation
- name: create temporary directory - name: create temporary directory
tempfile: tempfile:
state: directory state: directory
register: tempdir register: tempdir
when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' when: not reconfigure_only
- name: extract paperless-ng - name: extract paperless-ng
unarchive: unarchive:
src: "https://github.com/jonaswinkler/paperless-ng/releases/download/ng-{{ paperlessng_version }}/paperless-ng-{{ paperlessng_version }}.tar.xz" src: "https://github.com/jonaswinkler/paperless-ng/releases/download/ng-{{ paperlessng_version }}/paperless-ng-{{ paperlessng_version }}.tar.xz"
remote_src: yes remote_src: yes
dest: "{{ tempdir.path }}" dest: "{{ tempdir.path }}"
when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' when: not reconfigure_only
- name: change owner and permissions of paperless-ng - name: change owner and permissions of paperless-ng
command: command:
cmd: "{{ item }}" cmd: "{{ item }}"
warn: false warn: false
with_items: with_items:
- "chown -R {{ paperlessng_system_user }}:{{ paperlessng_system_group }} {{ tempdir.path }}" - "chown -R {{ paperlessng_system_user }}:{{ paperlessng_system_group }} {{ tempdir.path }}"
- "find {{ tempdir.path }} -type d -exec chmod 0750 {} ;" - "find {{ tempdir.path }} -type d -exec chmod 0750 {} ;"
- "find {{ tempdir.path }} -type f -exec chmod 0640 {} ;" - "find {{ tempdir.path }} -type f -exec chmod 0640 {} ;"
when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' when: not reconfigure_only
- name: move paperless-ng - name: move paperless-ng
command: command:
cmd: "cp -a {{ tempdir.path }}/paperless-ng/ {{ paperlessng_directory }}" cmd: "cp -a {{ tempdir.path }}/paperless-ng/. {{ paperlessng_directory }}"
when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' when: not reconfigure_only
- name: remove temporary directory - name: remove temporary directory
file: file:
path: "{{ tempdir.path }}" path: "{{ tempdir.path }}"
state: absent state: absent
when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' when: not reconfigure_only
- name: create paperless-ng directories and set permissions - name: create paperless-ng directories and set permissions
file: file:
@@ -154,7 +172,7 @@
group: "{{ paperlessng_system_group }}" group: "{{ paperlessng_system_group }}"
mode: "750" mode: "750"
with_items: with_items:
- "{{ paperlessng_directory }}" # ansible `copy:` does not set correct permissions on `dest:` for recursive copies - "{{ paperlessng_directory }}"
- "{{ paperlessng_consumption_dir }}" - "{{ paperlessng_consumption_dir }}"
- "{{ paperlessng_data_dir }}" - "{{ paperlessng_data_dir }}"
- "{{ paperlessng_media_root }}" - "{{ paperlessng_media_root }}"
@@ -171,8 +189,10 @@
regexp: "^#?{{ item.regexp }}=" regexp: "^#?{{ item.regexp }}="
line: "{{ item.line }}" line: "{{ item.line }}"
with_items: with_items:
# Required services
- regexp: PAPERLESS_REDIS - regexp: PAPERLESS_REDIS
line: "PAPERLESS_REDIS=redis://{{ paperlessng_redis_host }}:{{ paperlessng_redis_port }}" line: "PAPERLESS_REDIS=redis://{{ paperlessng_redis_host }}:{{ paperlessng_redis_port }}"
# Paths and folders
- regexp: PAPERLESS_CONSUMPTION_DIR - regexp: PAPERLESS_CONSUMPTION_DIR
line: "PAPERLESS_CONSUMPTION_DIR={{ paperlessng_consumption_dir }}" line: "PAPERLESS_CONSUMPTION_DIR={{ paperlessng_consumption_dir }}"
- regexp: PAPERLESS_DATA_DIR - regexp: PAPERLESS_DATA_DIR
@@ -183,26 +203,65 @@
line: "PAPERLESS_STATICDIR={{ paperlessng_static_dir }}" line: "PAPERLESS_STATICDIR={{ paperlessng_static_dir }}"
- regexp: PAPERLESS_FILENAME_FORMAT - regexp: PAPERLESS_FILENAME_FORMAT
line: "PAPERLESS_FILENAME_FORMAT={{ paperlessng_filename_format }}" line: "PAPERLESS_FILENAME_FORMAT={{ paperlessng_filename_format }}"
# Hosting & Security
- regexp: PAPERLESS_SECRET_KEY
line: "PAPERLESS_SECRET_KEY={{ paperless_secret_key }}"
- regexp: PAPERLESS_ALLOWED_HOSTS
line: "PAPERLESS_ALLOWED_HOSTS={{ paperless_allowed_hosts }}"
- regexp: PAPERLESS_CORS_ALLOWED_HOSTS
line: "PAPERLESS_CORS_ALLOWED_HOSTS={{ paperless_cors_allowed_hosts }}"
- regexp: PAPERLESS_FORCE_SCRIPT_NAME
line: "PAPERLESS_FORCE_SCRIPT_NAME={{ paperless_force_script_name }}"
- regexp: PAPERLESS_STATIC_URL
line: "PAPERLESS_STATIC_URL={{ paperless_static_url }}"
- regexp: PAPERLESS_AUTO_LOGIN_USERNAME
line: "PAPERLESS_AUTO_LOGIN_USERNAME={{ paperless_auto_login_username }}"
- regexp: PAPERLESS_COOKIE_PREFIX
line: "PAPERLESS_COOKIE_PREFIX={{ paperless_cookie_prefix }}"
- regexp: PAPERLESS_ENABLE_HTTP_REMOTE_USER
line: "PAPERLESS_ENABLE_HTTP_REMOTE_USER={{ paperless_enable_http_remote_user }}"
# OCR settings
- regexp: PAPERLESS_OCR_LANGUAGE - regexp: PAPERLESS_OCR_LANGUAGE
line: "PAPERLESS_OCR_LANGUAGE={{ paperlessng_ocr_languages | join('+') }}" line: "PAPERLESS_OCR_LANGUAGE={{ paperlessng_ocr_languages | join('+') }}"
- regexp: PAPERLESS_OCR_MODE
line: "PAPERLESS_OCR_MODE={{ paperlessng_ocr_mode }}"
- regexp: PAPERLESS_OCR_OUTPUT_TYPE
line: "PAPERLESS_OCR_OUTPUT_TYPE={{ paperlessng_ocr_output_type }}"
- regexp: PAPERLESS_OCR_PAGES
line: "PAPERLESS_OCR_PAGES={{ paperlessng_ocr_pages }}"
- regexp: PAPERLESS_OCR_IMAGE_DPI
line: "PAPERLESS_OCR_IMAGE_DPI={{ paperlessng_ocr_image_dpi }}"
- regexp: PAPERLESS_OCR_USER_ARGS - regexp: PAPERLESS_OCR_USER_ARGS
line: "PAPERLESS_OCR_USER_ARGS={{ paperlessng_ocrmypdf_args | combine({'jbig2_lossy': true} if paperlessng_big2enc_lossy else {}) | to_json }}" line: "PAPERLESS_OCR_USER_ARGS={{ paperlessng_ocr_user_args | combine({'jbig2_lossy': true} if paperlessng_big2enc_lossy else {}) | to_json }}"
- regexp: PAPERLESS_TIME_ZONE # Tika settings
line: "PAPERLESS_TIME_ZONE={{ paperlessng_time_zone }}"
- regexp: PAPERLESS_TIKA_ENABLED - regexp: PAPERLESS_TIKA_ENABLED
line: "PAPERLESS_TIKA_ENABLED={{ paperlessng_tika_enabled }}" line: "PAPERLESS_TIKA_ENABLED={{ paperlessng_tika_enabled }}"
no_log: yes
- name: configure paperless-ng [tika]
lineinfile:
path: "{{ paperlessng_directory }}/paperless.conf.template"
regexp: "^#?{{ item.regexp }}="
line: "'{{ item.line }}' if paperlessng_tika_enabled else '#{{ item.line }}'"
with_items:
- regexp: PAPERLESS_TIKA_ENDPOINT - regexp: PAPERLESS_TIKA_ENDPOINT
line: "PAPERLESS_TIKA_ENDPOINT={{ paperlessng_tika_endpoint }}" line: "PAPERLESS_TIKA_ENDPOINT={{ paperlessng_tika_endpoint }}"
- regexp: PAPERLESS_TIKA_GOTENBERG_ENDPOINT - regexp: PAPERLESS_TIKA_GOTENBERG_ENDPOINT
line: "PAPERLESS_TIKA_GOTENBERG_ENDPOINT={{ paperlessng_tika_endpoint }}" line: "PAPERLESS_TIKA_GOTENBERG_ENDPOINT={{ paperlessng_tika_endpoint }}"
# Software tweaks
- regexp: PAPERLESS_TIME_ZONE
line: "PAPERLESS_TIME_ZONE={{ paperlessng_time_zone }}"
- regexp: PAPERLESS_CONSUMER_POLLING
line: "PAPERLESS_CONSUMER_POLLING={{ paperlessng_consumer_polling }}"
- regexp: PAPERLESS_CONSUMER_DELETE_DUPLICATES
line: "PAPERLESS_CONSUMER_DELETE_DUPLICATES={{ paperlessng_consumer_delete_duplicates }}"
- regexp: PAPERLESS_CONSUMER_RECURSIVE
line: "PAPERLESS_CONSUMER_RECURSIVE={{ paperlessng_consumer_recursive }}"
- regexp: PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS
line: "PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS={{ paperlessng_consumer_subdirs_as_tags }}"
- regexp: PAPERLESS_OPTIMIZE_THUMBNAILS
line: "PAPERLESS_OPTIMIZE_THUMBNAILS={{ paperlessng_optimize_thumbnails }}"
- regexp: PAPERLESS_POST_CONSUME_SCRIPT
line: "PAPERLESS_POST_CONSUME_SCRIPT={{ paperlessng_post_consume_script }}"
- regexp: PAPERLESS_FILENAME_DATE_ORDER
line: "PAPERLESS_FILENAME_DATE_ORDER={{ paperlessng_filename_date_order }}"
- regexp: PAPERLESS_THUMBNAIL_FONT_NAME
line: "PAPERLESS_THUMBNAIL_FONT_NAME={{ paperlessng_thumbnail_font_name }}"
- regexp: PAPERLESS_IGNORE_DATES
line: "PAPERLESS_IGNORE_DATES={{ paperlessng_ignore_dates }}"
no_log: yes
- name: configure paperless-ng database [sqlite] - name: configure paperless-ng database [sqlite]
lineinfile: lineinfile:
@@ -228,6 +287,8 @@
line: "PAPERLESS_DBUSER={{ paperlessng_db_user }}" line: "PAPERLESS_DBUSER={{ paperlessng_db_user }}"
- regexp: PAPERLESS_DBPASS - regexp: PAPERLESS_DBPASS
line: "PAPERLESS_DBPASS={{ paperlessng_db_pass }}" line: "PAPERLESS_DBPASS={{ paperlessng_db_pass }}"
- regexp: PAPERLESS_DBSSLMODE
line: "PAPERLESS_DBSSLMODE={{ paperlessng_db_sslmode }}"
when: paperlessng_db_type == 'postgresql' when: paperlessng_db_type == 'postgresql'
no_log: yes no_log: yes
@@ -238,7 +299,7 @@
dest: /etc/paperless.conf dest: /etc/paperless.conf
owner: root owner: root
group: root group: root
mode: '0644' mode: "0644"
register: configuration register: configuration
- name: create paperlessng venv - name: create paperlessng venv
@@ -256,29 +317,15 @@
requirements: "{{ paperlessng_directory }}/requirements.txt" requirements: "{{ paperlessng_directory }}/requirements.txt"
executable: "{{ paperlessng_virtualenv }}/bin/pip3" executable: "{{ paperlessng_virtualenv }}/bin/pip3"
extra_args: --upgrade extra_args: --upgrade
when: paperlessng_current_version.stdout != paperlessng_version | string when: not reconfigure_only
- name: collect static files - name: migrate database schema
become: yes
become_user: "{{ paperlessng_system_user }}"
command: "{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py collectstatic --no-input"
when: paperlessng_current_version.stdout != paperlessng_version | string
register: static_files
changed_when: static_files.stdout is not match("0 static files copied .*")
- name: create database schema
become: yes become: yes
become_user: "{{ paperlessng_system_user }}" become_user: "{{ paperlessng_system_user }}"
command: "{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py migrate" command: "{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py migrate"
when: paperlessng_current_version.stdout != paperlessng_version | string
register: database_schema register: database_schema
changed_when: '"No migrations to apply." not in database_schema.stdout' changed_when: '"No migrations to apply." not in database_schema.stdout'
when: not reconfigure_only
- name: compile translations
become: yes
become_user: "{{ paperlessng_system_user }}"
command: "{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py compilemessages"
when: paperlessng_current_version.stdout != paperlessng_version | string
- name: configure paperless superuser - name: configure paperless superuser
become: yes become: yes
@@ -307,7 +354,7 @@
else: else:
User.objects.create_superuser('{{ paperlessng_superuser_name }}', '{{ paperlessng_superuser_email }}', '{{ paperlessng_superuser_password }}') User.objects.create_superuser('{{ paperlessng_superuser_name }}', '{{ paperlessng_superuser_email }}', '{{ paperlessng_superuser_password }}')
print('changed') print('changed')
command: "{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py shell -c \"{{ creation_script }}\"" command: '{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py shell -c "{{ creation_script }}"'
register: superuser register: superuser
changed_when: superuser.stdout == 'changed' changed_when: superuser.stdout == 'changed'
no_log: yes no_log: yes
@@ -320,7 +367,7 @@
owner: "{{ paperlessng_system_user }}" owner: "{{ paperlessng_system_user }}"
group: "{{ paperlessng_system_group }}" group: "{{ paperlessng_system_group }}"
mode: g-w,o-rwx mode: g-w,o-rwx
when: venv.changed or paperlessng_current_version.stdout != paperlessng_version | string when: venv.changed or not reconfigure_only
- name: configure ghostscript for PDF - name: configure ghostscript for PDF
lineinfile: lineinfile:
@@ -343,34 +390,13 @@
] ]
- [ - [
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html # https://www.freedesktop.org/software/systemd/man/systemd.exec.html
{ { option: "User", value: "{{ paperlessng_system_user }}" },
option: "User", { option: "Group", value: "{{ paperlessng_system_group }}" },
value: "{{ paperlessng_system_user }}", { option: "WorkingDirectory", value: "{{ paperlessng_directory }}/src", },
}, { option: "ProtectSystem", value: "full" },
{ { option: "NoNewPrivileges", value: "true" },
option: "Group", { option: "PrivateUsers", value: "true" },
value: "{{ paperlessng_system_group }}", { option: "PrivateDevices", value: "true" },
},
{
option: "WorkingDirectory",
value: "{{ paperlessng_directory }}/src",
},
{
option: "ProtectSystem",
value: "full",
},
{
option: "NoNewPrivileges",
value: "true",
},
{
option: "PrivateUsers",
value: "true",
},
{
option: "PrivateDevices",
value: "true",
}
] ]
- name: configure paperless-consumer service - name: configure paperless-consumer service

5
crowdin.yml Normal file
View File

@@ -0,0 +1,5 @@
files:
- source: /src/locale/en-us/LC_MESSAGES/django.po
translation: /src/locale/%two_letters_code%/LC_MESSAGES/django.po
- source: /src-ui/messages.xlf
translation: /src-ui/src/locale/messages.%two_letters_code%.xlf

View File

@@ -79,7 +79,11 @@ initialize() {
fi fi
done done
echo "creating directory /tmp/paperless"
mkdir -p /tmp/paperless
chown -R paperless:paperless ../ chown -R paperless:paperless ../
chown -R paperless:paperless /tmp/paperless
migrations migrations

View File

@@ -20,6 +20,8 @@ Options available to any installation of paperless:
metadata to a specific folder. You may import your documents into a metadata to a specific folder. You may import your documents into a
fresh instance of paperless again or store your documents in another fresh instance of paperless again or store your documents in another
DMS with this export. DMS with this export.
* The document exporter is also able to update an already existing export.
Therefore, incremental backups with ``rsync`` are entirely possible.
Options available to docker installations: Options available to docker installations:
@@ -53,6 +55,9 @@ Restoring
Updating Paperless Updating Paperless
################## ##################
Docker Route
============
If a new release of paperless-ng is available, upgrading depends on how you If a new release of paperless-ng is available, upgrading depends on how you
installed paperless-ng in the first place. The releases are available at the installed paperless-ng in the first place. The releases are available at the
`release page <https://github.com/jonaswinkler/paperless-ng/releases>`_. `release page <https://github.com/jonaswinkler/paperless-ng/releases>`_.
@@ -85,12 +90,30 @@ B. If you built the image yourself, do the following:
$ docker-compose build $ docker-compose build
$ docker-compose up $ docker-compose up
Running `docker-compose up` will also apply any new database migrations. Running ``docker-compose up`` will also apply any new database migrations.
If you see everything working, press CTRL+C once to gracefully stop paperless. If you see everything working, press CTRL+C once to gracefully stop paperless.
Then you can start paperless-ng with ``-d`` to have it run in the background. Then you can start paperless-ng with ``-d`` to have it run in the background.
Updating paperless without docker .. note::
=================================
In version 0.9.14, the update process was changed. In 0.9.13 and earlier, the
docker-compose files specified exact versions and pull won't automatically
update to newer versions. In order to enable updates as described above, either
get the new ``docker-compose.yml`` file from `here <https://github.com/jonaswinkler/paperless-ng/tree/master/docker/compose>`_
or edit the ``docker-compose.yml`` file, find the line that says
.. code::
image: jonaswinkler/paperless-ng:0.9.x
and replace the version with ``latest``:
.. code::
image: jonaswinkler/paperless-ng:latest
Bare Metal Route
================
After grabbing the new release and unpacking the contents, do the following: After grabbing the new release and unpacking the contents, do the following:
@@ -123,6 +146,38 @@ After grabbing the new release and unpacking the contents, do the following:
This might not actually do anything. Not every new paperless version comes with new This might not actually do anything. Not every new paperless version comes with new
database migrations. database migrations.
Ansible Route
=============
Most of the update process is automated when using the ansible role.
1. Backup your defined role variables file outside the paperless source-tree:
.. code:: shell-session
$ cp ansible/vars.yml ~/vars.yml.old
2. Pull the release tag you want to update to:
.. code:: shell-session
$ git fetch --all
$ git checkout ng-0.9.14
3. Update the role variable definitions ``ansible/vars.yml`` (where appropriate).
4. Run the ansible playbook you created created during :ref:`installation <setup-ansible>` again:
.. note::
When ansible detects that an update run is in progress, it backs up the entire ``paperlessng_directory`` to ``paperlessng_directory-TIMESTAMP``.
Updates can be rolled back by simply moving the timestamped folder back to the original location.
If the update succeeds and you want to continue using the new release, please don't forget to delete the backup folder.
.. code:: shell-session
$ ansible-playbook playbook.yml
Management utilities Management utilities
#################### ####################
@@ -157,7 +212,12 @@ backup or migration to another DMS.
.. code:: .. code::
document_exporter target document_exporter target [-c] [-f] [-d]
optional arguments:
-c, --compare-checksums
-f, --use-filename-format
-d, --delete
``target`` is a folder to which the data gets written. This includes documents, ``target`` is a folder to which the data gets written. This includes documents,
thumbnails and a ``manifest.json`` file. The manifest contains all metadata from thumbnails and a ``manifest.json`` file. The manifest contains all metadata from
@@ -167,6 +227,24 @@ When you use the provided docker compose script, specify ``../export`` as the
target. This path inside the container is automatically mounted on your host on target. This path inside the container is automatically mounted on your host on
the folder ``export``. the folder ``export``.
If the target directory already exists and contains files, paperless will assume
that the contents of the export directory are a previous export and will attempt
to update the previous export. Paperless will only export changed and added files.
Paperless determines whether a file has changed by inspecting the file attributes
"date/time modified" and "size". If that does not work out for you, specify
``--compare-checksums`` and paperless will attempt to compare file checksums instead.
This is slower.
Paperless will not remove any existing files in the export directory. If you want
paperless to also remove files that do not belong to the current export such as files
from deleted documents, specify ``--delete``. Be careful when pointing paperless to
a directory that already contains other files.
The filenames generated by this command follow the format
``[date created] [correspondent] [title].[extension]``.
If you want paperless to use ``PAPERLESS_FILENAME_FORMAT`` for exported filenames
instead, specify ``--use-filename-format``.
.. _utilities-importer: .. _utilities-importer:

View File

@@ -5,6 +5,29 @@
Changelog Changelog
********* *********
paperless-ng 1.0.0
##################
Nothing special about this release, but since there are relatively few bug reports coming in, I think that this is reasonably stable.
* Document export
* The document exporter has been rewritten to support updating an already existing export in place.
This enables incremental backups with ``rsync``.
* The document exporter supports naming exported files according to ``PAPERLESS_FILENAME_FORMAT``.
* The document exporter locks the media directory and the database during execution to ensure that
the resulting export is consistent.
* See the :ref:`updated documentation <utilities-exporter>` for more details.
* Other changes and additions
* Added a language selector to the settings.
* Added date format options to the settings.
* Range selection with shift clicking is now possible in the document list.
* Filtering correspondent, type and tag management pages by name.
* Focus "Name" field in dialogs by default.
paperless-ng 0.9.14 paperless-ng 0.9.14
################### ###################

View File

@@ -267,7 +267,7 @@ PAPERLESS_OCR_IMAGE_DPI=<num>
present in an image. present in an image.
PAPERLESS_OCR_USER_ARG=<json> PAPERLESS_OCR_USER_ARGS=<json>
OCRmyPDF offers many more options. Use this parameter to specify any OCRmyPDF offers many more options. Use this parameter to specify any
additional arguments you wish to pass to OCRmyPDF. Since Paperless uses additional arguments you wish to pass to OCRmyPDF. Since Paperless uses
the API of OCRmyPDF, you have to specify these in a format that can be the API of OCRmyPDF, you have to specify these in a format that can be

View File

@@ -83,7 +83,8 @@ You can go multiple routes with setting up and running Paperless:
* :ref:`Pull the image from Docker Hub <setup-docker_hub>` * :ref:`Pull the image from Docker Hub <setup-docker_hub>`
* :ref:`Build the Docker image yourself <setup-docker_build>` * :ref:`Build the Docker image yourself <setup-docker_build>`
* :ref:`Install Paperless directly on your system (bare metal) <setup-bare_metal>` * :ref:`Install Paperless directly on your system manually (bare metal) <setup-bare_metal>`
* :ref:`Use ansible to install Paperless on your system automatically (bare metal) <setup-ansible>`
The Docker routes are quick & easy. These are the recommended routes. This configures all the stuff The Docker routes are quick & easy. These are the recommended routes. This configures all the stuff
from above automatically so that it just works and uses sensible defaults for all configuration options. from above automatically so that it just works and uses sensible defaults for all configuration options.
@@ -92,6 +93,11 @@ The bare metal route is more complicated to setup but makes it easier
should you want to contribute some code back. You need to configure and should you want to contribute some code back. You need to configure and
run the above mentioned components yourself. run the above mentioned components yourself.
The ansible route cobines benefits from both options:
the setup process is fully automated, reproducible and idempotent,
it includes the same sensible defaults,
and it simultaneously provides the flexibility of a bare metal installation.
.. _setup-docker_hub: .. _setup-docker_hub:
Install Paperless from Docker Hub Install Paperless from Docker Hub
@@ -392,6 +398,121 @@ writing. Windows is not and will never be supported.
to compile this by yourself, because this software has been patented until around 2017 and to compile this by yourself, because this software has been patented until around 2017 and
binary packages are not available for most distributions. binary packages are not available for most distributions.
.. _setup-ansible:
Install Paperless using ansible
===============================
.. note::
This role currently only supports Debian 10 Buster and Ubuntu 20.04 Focal or later as target hosts.
1. Install ansible 2.7+ on the management node.
This may be the target host paperless-ng is being installed on or any remote host which can access the target host.
For further details, check the ansible `inventory <https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html>`_ documentation.
On Debian and Ubuntu, the official repositories should provide a suitable version:
.. code:: bash
apt install ansible
ansible --version
Alternatively, you can install the most recent ansible release using PyPI:
.. code:: bash
python3 -m pip install ansible
ansible --version
Make sure your taget hosts are accessible:
.. code:: sh
ansible -m ping YourAnsibleTargetHostGoesHere
2. Clone the repository of paperless-ng:
.. code:: sh
git clone https://github.com/jonaswinkler/paperless-ng
Checkout the latest release tag:
.. code:: sh
cd paperless-ng
git checkout ng-0.9.14
3. Create an ansible ``playbook.yml`` in the paperless-ng root directory:
.. code:: yaml
- hosts: YourAnsibleTargetHostGoesHere
become: yes
vars_files:
- ansible/vars.yml
roles:
- ansible
Optional: If you also want to use PostgreSQL on the target system, install and add (for example) the `geerlingguy.postgresql <https://github.com/geerlingguy/ansible-role-postgresql>`_ role:
.. code:: sh
ansible-galaxy install geerlingguy.postgresql
.. code:: yaml
- hosts: YourAnsibleTargetHostGoesHere
become: yes
vars_files:
- ansible/vars.yml
roles:
- geerlingguy.postgresql
- ansible
Optional: If you also want to use a reverse proxy on the target system, install and add (for example) the `geerlingguy.nginx <https://github.com/geerlingguy/ansible-role-nginx>`_ role:
.. code:: sh
ansible-galaxy install geerlingguy.nginx
.. code:: yaml
- hosts: YourAnsibleTargetHostGoesHere
become: yes
vars_files:
- ansible/vars.yml
roles:
- geerlingguy.postgresql
- ansible
- geerlingguy.nginx
4. Create ``ansible/vars.yml`` to configure your ansible deployment:
.. code:: yaml
paperless_secret_key: PleaseGenerateAStrongKeyForThis
paperlessng_superuser_name: YourUserName
paperlessng_superuser_email: name@domain.tld
paperlessng_superuser_password: YourDesiredPasswordUsedForFirstLogin
paperlessng_ocr_languages:
- eng
- deu
For all of the available options, please check ``ansible/README.md`` and :ref:`configuration`.
Optional configurations for the above-mentioned PostgreSQL and nginx roles would also go here.
5. Run the ansible playbook from the management node:
.. code:: sh
ansible-playbook playbook.yml
When this step completes successfully, paperless-ng will be available on the target host at ``http://127.0.0.1:8000`` (or the address you configured).
Migration to paperless-ng Migration to paperless-ng
######################### #########################

View File

@@ -27,7 +27,7 @@
#PAPERLESS_SECRET_KEY=change-me #PAPERLESS_SECRET_KEY=change-me
#PAPERLESS_ALLOWED_HOSTS=example.com,www.example.com #PAPERLESS_ALLOWED_HOSTS=example.com,www.example.com
#PAPERLESS_CORS_ALLOWED_HOSTS=localhost:8080,example.com,localhost:8000 #PAPERLESS_CORS_ALLOWED_HOSTS=http://example.com,http://localhost:8000
#PAPERLESS_FORCE_SCRIPT_NAME= #PAPERLESS_FORCE_SCRIPT_NAME=
#PAPERLESS_STATIC_URL=/static/ #PAPERLESS_STATIC_URL=/static/
#PAPERLESS_AUTO_LOGIN_USERNAME= #PAPERLESS_AUTO_LOGIN_USERNAME=

View File

@@ -394,53 +394,60 @@
<context context-type="linenumber">2</context> <context context-type="linenumber">2</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="ddb40946e790522301687ecddb9ce1cb8ad40dd1" datatype="html">
<source>Filter by:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">8</context>
</context-group>
</trans-unit>
<trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html"> <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
<source>Name</source> <source>Name</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">9</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8fa4d523f7b91df4390120b85ed0406138273e1a" datatype="html"> <trans-unit id="8fa4d523f7b91df4390120b85ed0406138273e1a" datatype="html">
<source>Color</source> <source>Color</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">14</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="d0c4488f742efeba0915e90e285a022da813deff" datatype="html"> <trans-unit id="d0c4488f742efeba0915e90e285a022da813deff" datatype="html">
<source>Matching</source> <source>Matching</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">21</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="9bcf8d20d23c111eca1431abd2d2ce0de324499c" datatype="html"> <trans-unit id="9bcf8d20d23c111eca1431abd2d2ce0de324499c" datatype="html">
<source>Document count</source> <source>Document count</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">22</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="030b4423b92167200e39519599f9b863b4f7c62c" datatype="html"> <trans-unit id="030b4423b92167200e39519599f9b863b4f7c62c" datatype="html">
<source>Actions</source> <source>Actions</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">23</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="9d51b3c90afda70700229d1b8a55371c13cb3bce" datatype="html"> <trans-unit id="9d51b3c90afda70700229d1b8a55371c13cb3bce" datatype="html">
<source>Documents</source> <source>Documents</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">32</context> <context context-type="linenumber">38</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html"> <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
<source>Edit</source> <source>Edit</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">37</context> <context context-type="linenumber">43</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4990731724078522539" datatype="html"> <trans-unit id="4990731724078522539" datatype="html">
@@ -475,21 +482,35 @@
<source>Saved view &quot;<x id="PH" equiv-text="savedView.name"/>&quot; deleted.</source> <source>Saved view &quot;<x id="PH" equiv-text="savedView.name"/>&quot; deleted.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">55</context> <context context-type="linenumber">63</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5647210819299459618" datatype="html"> <trans-unit id="5647210819299459618" datatype="html">
<source>Settings saved successfully.</source> <source>Settings saved successfully.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">68</context> <context context-type="linenumber">79</context>
</context-group>
</trans-unit>
<trans-unit id="6839066544204061364" datatype="html">
<source>Use system language</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">83</context>
</context-group>
</trans-unit>
<trans-unit id="7729897675462249787" datatype="html">
<source>Use date format of display language</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8488620293789898901" datatype="html"> <trans-unit id="8488620293789898901" datatype="html">
<source>Error while storing settings on server: <x id="PH" equiv-text="JSON.stringify(error.error)"/></source> <source>Error while storing settings on server: <x id="PH" equiv-text="JSON.stringify(error.error)"/></source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">80</context> <context context-type="linenumber">103</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html"> <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
@@ -510,7 +531,7 @@
<source>Saved views</source> <source>Saved views</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">64</context> <context context-type="linenumber">114</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="bbe41ac2ea4a6c00ea941a41b33105048f8e9f13" datatype="html"> <trans-unit id="bbe41ac2ea4a6c00ea941a41b33105048f8e9f13" datatype="html">
@@ -520,109 +541,158 @@
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="75f8908d266f7cc9b9e68e0be906fd080a223606" datatype="html">
<source>Display language</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="1284a077dc18a2d1ff1b744f16f1797eea28ae37" datatype="html">
<source>You need to reload the page after applying a new language.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">25</context>
</context-group>
</trans-unit>
<trans-unit id="0cd55822928764cc82a62ee3e6f3adbc1c630479" datatype="html">
<source>Date display</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="7df4de0d0704a06a302d853e31f2580eba98f127" datatype="html">
<source>Date format</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">45</context>
</context-group>
</trans-unit>
<trans-unit id="69852399a18b8ca4fca8c5bfddd3f00a6d137593" datatype="html">
<source>Short: <x id="INTERPOLATION" equiv-text="{{today | customDate:&apos;shortDate&apos;:null:computedDateLocale}}"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit id="d01a59285e711252b98c4f193394e4b854615c78" datatype="html">
<source>Medium: <x id="INTERPOLATION" equiv-text="{{today | customDate:&apos;mediumDate&apos;:null:computedDateLocale}}"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="00481629776699b1caebd12b3b1176e2e23740a8" datatype="html">
<source>Long: <x id="INTERPOLATION" equiv-text="{{today | customDate:&apos;longDate&apos;:null:computedDateLocale}}"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">59</context>
</context-group>
</trans-unit>
<trans-unit id="2045151788cbdda7512752e408da59a6b54a8ef0" datatype="html"> <trans-unit id="2045151788cbdda7512752e408da59a6b54a8ef0" datatype="html">
<source>Items per page</source> <source>Items per page</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">67</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="c4435e56bf0289e78fedc462f1d21fb30b9de55d" datatype="html"> <trans-unit id="c4435e56bf0289e78fedc462f1d21fb30b9de55d" datatype="html">
<source>Document editor</source> <source>Document editor</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">83</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4903e521c9bfd11ce88e7a5575106ef638912e0d" datatype="html"> <trans-unit id="4903e521c9bfd11ce88e7a5575106ef638912e0d" datatype="html">
<source>Use PDF viewer provided by the browser</source> <source>Use PDF viewer provided by the browser</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">37</context> <context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="d7db07023e53f8396d18d375c2b78c25fc81c197" datatype="html"> <trans-unit id="d7db07023e53f8396d18d375c2b78c25fc81c197" datatype="html">
<source>This is usually faster for displaying large PDF documents, but it might not work on some browsers.</source> <source>This is usually faster for displaying large PDF documents, but it might not work on some browsers.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">37</context> <context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="9ee5d1cbfd6ee168dae37aaba2b59b50bcabb2ff" datatype="html"> <trans-unit id="9ee5d1cbfd6ee168dae37aaba2b59b50bcabb2ff" datatype="html">
<source>Dark mode</source> <source>Dark mode</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">44</context> <context context-type="linenumber">94</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="f8cb5506e70fd71fddc9bb71cee18bfff7b29637" datatype="html"> <trans-unit id="f8cb5506e70fd71fddc9bb71cee18bfff7b29637" datatype="html">
<source>Use system settings</source> <source>Use system settings</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">47</context> <context context-type="linenumber">97</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8ee474504043fa89821d626e4f3413240fa91b53" datatype="html"> <trans-unit id="8ee474504043fa89821d626e4f3413240fa91b53" datatype="html">
<source>Enable dark mode</source> <source>Enable dark mode</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">48</context> <context context-type="linenumber">98</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3863a86cd9e69a61d143d3daf51df44203df4a82" datatype="html"> <trans-unit id="3863a86cd9e69a61d143d3daf51df44203df4a82" datatype="html">
<source>Bulk editing</source> <source>Bulk editing</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">52</context> <context context-type="linenumber">102</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="c0ac61661c6c326d6e0e00c231b95cf2ac0c6586" datatype="html"> <trans-unit id="c0ac61661c6c326d6e0e00c231b95cf2ac0c6586" datatype="html">
<source>Show confirmation dialogs</source> <source>Show confirmation dialogs</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">56</context> <context context-type="linenumber">106</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="291bbe56ecbe945dcf05580a57d679fa7bd1e06a" datatype="html"> <trans-unit id="291bbe56ecbe945dcf05580a57d679fa7bd1e06a" datatype="html">
<source>Deleting documents will always ask for confirmation.</source> <source>Deleting documents will always ask for confirmation.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">56</context> <context context-type="linenumber">106</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8cfddc13e04f5545ac63f419ef363505d6f78c2e" datatype="html"> <trans-unit id="8cfddc13e04f5545ac63f419ef363505d6f78c2e" datatype="html">
<source>Apply on close</source> <source>Apply on close</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">57</context> <context context-type="linenumber">107</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8cb90334f5dfd7fc67205085f59381e2a334ccfc" datatype="html"> <trans-unit id="8cb90334f5dfd7fc67205085f59381e2a334ccfc" datatype="html">
<source>Appears on</source> <source>Appears on</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">76</context> <context context-type="linenumber">126</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="6717cf1acf04728fc2b7c39f6d3297f8ff15fde5" datatype="html"> <trans-unit id="6717cf1acf04728fc2b7c39f6d3297f8ff15fde5" datatype="html">
<source>Show on dashboard</source> <source>Show on dashboard</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">79</context> <context context-type="linenumber">129</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="541bfc5b123b3f8867fd681eaceefb663a811973" datatype="html"> <trans-unit id="541bfc5b123b3f8867fd681eaceefb663a811973" datatype="html">
<source>Show in sidebar</source> <source>Show in sidebar</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">83</context> <context context-type="linenumber">133</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="abba764a7a595d04dc8c3b26e04b3780d4fdb540" datatype="html"> <trans-unit id="abba764a7a595d04dc8c3b26e04b3780d4fdb540" datatype="html">
<source>No saved views defined.</source> <source>No saved views defined.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">143</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="ef60a738a565f498b858e903e42bc5ffc3cc1299" datatype="html"> <trans-unit id="ef60a738a565f498b858e903e42bc5ffc3cc1299" datatype="html">
@@ -650,7 +720,7 @@
<source>Last correspondence</source> <source>Last correspondence</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">22</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1234709746630139322" datatype="html"> <trans-unit id="1234709746630139322" datatype="html">
@@ -692,21 +762,21 @@
<source>Matching algorithm</source> <source>Matching algorithm</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">10</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="eab7fc7cf2d663e54de934b779fce4275a303f0f" datatype="html"> <trans-unit id="eab7fc7cf2d663e54de934b779fce4275a303f0f" datatype="html">
<source>Matching pattern</source> <source>Matching pattern</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">11</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="632e529f49cf3d367dfbd15bd055e9b53aef30fb" datatype="html"> <trans-unit id="632e529f49cf3d367dfbd15bd055e9b53aef30fb" datatype="html">
<source>Case insensitive</source> <source>Case insensitive</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="9153094873118985366" datatype="html"> <trans-unit id="9153094873118985366" datatype="html">
@@ -913,13 +983,6 @@
<context context-type="linenumber">46</context> <context context-type="linenumber">46</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="ddb40946e790522301687ecddb9ce1cb8ad40dd1" datatype="html">
<source>Filter by:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">4</context>
</context-group>
</trans-unit>
<trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html"> <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
<source>Filter tags</source> <source>Filter tags</source>
<context-group purpose="location"> <context-group purpose="location">
@@ -1019,8 +1082,8 @@
<context context-type="linenumber">50</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1b29a8153575e5ad26cc7dd8bd75c4f45f6bfe7e" datatype="html"> <trans-unit id="849b42384616374df49bd8b3711ec159cb10b845" datatype="html">
<source>Created: <x id="INTERPOLATION" equiv-text="{{document.created | date}}"/></source> <source>Created: <x id="INTERPOLATION" equiv-text="{{document.created | customDate}}"/></source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
<context context-type="linenumber">67</context> <context context-type="linenumber">67</context>
@@ -1400,6 +1463,34 @@
<context context-type="linenumber">12</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1206520795340730278" datatype="html">
<source>English (US)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">74</context>
</context-group>
</trans-unit>
<trans-unit id="1858110241312746425" datatype="html">
<source>German</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">75</context>
</context-group>
</trans-unit>
<trans-unit id="3071065188816255493" datatype="html">
<source>Dutch</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">76</context>
</context-group>
</trans-unit>
<trans-unit id="7633754075223722162" datatype="html">
<source>French</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">77</context>
</context-group>
</trans-unit>
<trans-unit id="1519954996184640001" datatype="html"> <trans-unit id="1519954996184640001" datatype="html">
<source>Error</source> <source>Error</source>
<context-group purpose="location"> <context-group purpose="location">
@@ -1558,56 +1649,56 @@
<source>Create new item</source> <source>Create new item</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">43</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5324147361912094446" datatype="html"> <trans-unit id="5324147361912094446" datatype="html">
<source>Edit item</source> <source>Edit item</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">47</context> <context context-type="linenumber">54</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="1699589597032579396" datatype="html"> <trans-unit id="1699589597032579396" datatype="html">
<source>Could not save element: <x id="PH" equiv-text="error"/></source> <source>Could not save element: <x id="PH" equiv-text="error"/></source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">51</context> <context context-type="linenumber">58</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="810888510148304696" datatype="html"> <trans-unit id="810888510148304696" datatype="html">
<source>Automatic</source> <source>Automatic</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5044611416737085530" datatype="html"> <trans-unit id="5044611416737085530" datatype="html">
<source>Do you really want to delete this element?</source> <source>Do you really want to delete this element?</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">76</context> <context context-type="linenumber">97</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="8371896857609524947" datatype="html"> <trans-unit id="8371896857609524947" datatype="html">
<source>Associated documents will not be deleted.</source> <source>Associated documents will not be deleted.</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">83</context> <context context-type="linenumber">104</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7022070615528435141" datatype="html"> <trans-unit id="7022070615528435141" datatype="html">
<source>Delete</source> <source>Delete</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">85</context> <context context-type="linenumber">106</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5467489005440577210" datatype="html"> <trans-unit id="5467489005440577210" datatype="html">
<source>Error while deleting element: <x id="PH" equiv-text="JSON.stringify(error.error)"/></source> <source>Error while deleting element: <x id="PH" equiv-text="JSON.stringify(error.error)"/></source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">114</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5851669019930456395" datatype="html"> <trans-unit id="5851669019930456395" datatype="html">

View File

@@ -13,7 +13,7 @@ import { DocumentTypeListComponent } from './components/manage/document-type-lis
import { LogsComponent } from './components/manage/logs/logs.component'; import { LogsComponent } from './components/manage/logs/logs.component';
import { SettingsComponent } from './components/manage/settings/settings.component'; import { SettingsComponent } from './components/manage/settings/settings.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { DatePipe } from '@angular/common'; import { DatePipe, registerLocaleData } from '@angular/common';
import { NotFoundComponent } from './components/not-found/not-found.component'; import { NotFoundComponent } from './components/not-found/not-found.component';
import { CorrespondentListComponent } from './components/manage/correspondent-list/correspondent-list.component'; import { CorrespondentListComponent } from './components/manage/correspondent-list/correspondent-list.component';
import { ConfirmDialogComponent } from './components/common/confirm-dialog/confirm-dialog.component'; import { ConfirmDialogComponent } from './components/common/confirm-dialog/confirm-dialog.component';
@@ -59,6 +59,15 @@ import { SelectDialogComponent } from './components/common/select-dialog/select-
import { NgSelectModule } from '@ng-select/ng-select'; import { NgSelectModule } from '@ng-select/ng-select';
import { NumberComponent } from './components/common/input/number/number.component'; import { NumberComponent } from './components/common/input/number/number.component';
import { SafePipe } from './pipes/safe.pipe'; import { SafePipe } from './pipes/safe.pipe';
import { CustomDatePipe } from './pipes/custom-date.pipe';
import localeFr from '@angular/common/locales/fr';
import localeNl from '@angular/common/locales/nl';
import localeDe from '@angular/common/locales/de';
registerLocaleData(localeFr)
registerLocaleData(localeNl)
registerLocaleData(localeDe)
@NgModule({ @NgModule({
declarations: [ declarations: [
@@ -108,7 +117,8 @@ import { SafePipe } from './pipes/safe.pipe';
MetadataCollapseComponent, MetadataCollapseComponent,
SelectDialogComponent, SelectDialogComponent,
NumberComponent, NumberComponent,
SafePipe SafePipe,
CustomDatePipe
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@@ -27,6 +27,8 @@ export abstract class EditDialogComponent<T extends ObjectWithId> implements OnI
networkActive = false networkActive = false
closeEnabled = false
error = null error = null
abstract getForm(): FormGroup abstract getForm(): FormGroup
@@ -37,6 +39,11 @@ export abstract class EditDialogComponent<T extends ObjectWithId> implements OnI
if (this.object != null) { if (this.object != null) {
this.objectForm.patchValue(this.object) this.objectForm.patchValue(this.object)
} }
// wait to enable close button so it doesnt steal focus from input since its the first clickable element in the DOM
setTimeout(() => {
this.closeEnabled = true
});
} }
getCreateTitle() { getCreateTitle() {

File diff suppressed because one or more lines are too long

View File

@@ -12,7 +12,7 @@
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let doc of documents" routerLink="/documents/{{doc.id}}"> <tr *ngFor="let doc of documents" routerLink="/documents/{{doc.id}}">
<td>{{doc.created | date}}</td> <td>{{doc.created | customDate}}</td>
<td>{{doc.title | documentTitle}}<app-tag [tag]="t" *ngFor="let t of doc.tags$ | async" class="ml-1"></app-tag> <td>{{doc.title | documentTitle}}<app-tag [tag]="t" *ngFor="let t of doc.tags$ | async" class="ml-1"></app-tag>
</tr> </tr>
</tbody> </tbody>

View File

@@ -34,7 +34,7 @@ export class SavedViewWidgetComponent implements OnInit {
} else { } else {
this.list.load(this.savedView) this.list.load(this.savedView)
this.router.navigate(["documents"]) this.router.navigate(["documents"])
} }
} }
} }

View File

@@ -85,11 +85,11 @@
<tbody> <tbody>
<tr> <tr>
<td i18n>Date modified</td> <td i18n>Date modified</td>
<td>{{document.modified | date:'medium'}}</td> <td>{{document.modified | customDate}}</td>
</tr> </tr>
<tr> <tr>
<td i18n>Date added</td> <td i18n>Date added</td>
<td>{{document.added | date:'medium'}}</td> <td>{{document.added | customDate}}</td>
</tr> </tr>
<tr> <tr>
<td i18n>Media filename</td> <td i18n>Media filename</td>
@@ -142,5 +142,9 @@
<object [data]="previewUrl | safe" type="application/pdf" class="preview-sticky" width="100%"></object> <object [data]="previewUrl | safe" type="application/pdf" class="preview-sticky" width="100%"></object>
</ng-template> </ng-template>
</ng-container> </ng-container>
<ng-container *ngIf="getContentType() == 'text/plain'">
<object [data]="previewUrl | safe" type="text/plain" class="preview-sticky" width="100%"></object>
</ng-container>
</div> </div>
</div> </div>

View File

@@ -1,11 +1,11 @@
<div class="card mb-3 shadow-sm" [class.card-selected]="selected" [class.document-card]="selectable"> <div class="card mb-3 shadow-sm" [class.card-selected]="selected" [class.document-card]="selectable">
<div class="row no-gutters"> <div class="row no-gutters">
<div class="col-md-2 d-none d-lg-block doc-img-background rounded-left" [class.doc-img-background-selected]="selected"> <div class="col-md-2 d-none d-lg-block doc-img-background rounded-left" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)">
<img [src]="getThumbUrl()" class="card-img doc-img border-right rounded-left" (click)="setSelected(selectable ? !selected : false)"> <img [src]="getThumbUrl()" class="card-img doc-img border-right rounded-left">
<div style="top: 0; left: 0" class="position-absolute border-right border-bottom bg-light p-1" [class.document-card-check]="!selected"> <div style="top: 0; left: 0" class="position-absolute border-right border-bottom bg-light p-1" [class.document-card-check]="!selected">
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="smallCardCheck{{document.id}}" [checked]="selected" (change)="setSelected($event.target.checked)"> <input type="checkbox" class="custom-control-input" id="smallCardCheck{{document.id}}" [checked]="selected" (click)="this.toggleSelected.emit($event)">
<label class="custom-control-label" for="smallCardCheck{{document.id}}"></label> <label class="custom-control-label" for="smallCardCheck{{document.id}}"></label>
</div> </div>
</div> </div>
@@ -17,11 +17,11 @@
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<h5 class="card-title"> <h5 class="card-title">
<ng-container *ngIf="document.correspondent"> <ng-container *ngIf="document.correspondent">
<a *ngIf="clickCorrespondent.observers.length ; else nolink" [routerLink]="" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent)" class="font-weight-bold">{{(document.correspondent$ | async)?.name}}</a> <a *ngIf="clickCorrespondent.observers.length ; else nolink" [routerLink]="" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="font-weight-bold">{{(document.correspondent$ | async)?.name}}</a>
<ng-template #nolink>{{(document.correspondent$ | async)?.name}}</ng-template>: <ng-template #nolink>{{(document.correspondent$ | async)?.name}}</ng-template>:
</ng-container> </ng-container>
{{document.title | documentTitle}} {{document.title | documentTitle}}
<app-tag [tag]="t" linkTitle="Filter by tag" i18n-linkTitle *ngFor="let t of document.tags$ | async" class="ml-1" (click)="clickTag.emit(t.id)" [clickable]="clickTag.observers.length"></app-tag> <app-tag [tag]="t" linkTitle="Filter by tag" i18n-linkTitle *ngFor="let t of document.tags$ | async" class="ml-1" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="clickTag.observers.length"></app-tag>
</h5> </h5>
<h5 class="card-title" *ngIf="document.archive_serial_number">#{{document.archive_serial_number}}</h5> <h5 class="card-title" *ngIf="document.archive_serial_number">#{{document.archive_serial_number}}</h5>
</div> </div>
@@ -64,7 +64,7 @@
<ngb-progressbar [type]="searchScoreClass" [value]="searchScore" class="search-score-bar mx-2" [max]="1"></ngb-progressbar> <ngb-progressbar [type]="searchScoreClass" [value]="searchScore" class="search-score-bar mx-2" [max]="1"></ngb-progressbar>
</div> </div>
<small class="text-muted" [class.ml-auto]="!searchScore" i18n>Created: {{document.created | date}}</small> <small class="text-muted" [class.ml-auto]="!searchScore" i18n>Created: {{document.created | customDate}}</small>
</div> </div>
</div> </div>

View File

@@ -15,16 +15,11 @@ export class DocumentCardLargeComponent implements OnInit {
@Input() @Input()
selected = false selected = false
setSelected(value: boolean) {
this.selected = value
this.selectedChange.emit(value)
}
@Output() @Output()
selectedChange = new EventEmitter<boolean>() toggleSelected = new EventEmitter()
get selectable() { get selectable() {
return this.selectedChange.observers.length > 0 return this.toggleSelected.observers.length > 0
} }
@Input() @Input()

View File

@@ -1,18 +1,18 @@
<div class="col p-2 h-100"> <div class="col p-2 h-100">
<div class="card h-100 shadow-sm document-card" [class.card-selected]="selected"> <div class="card h-100 shadow-sm document-card" [class.card-selected]="selected">
<div class="border-bottom doc-img-container" [class.doc-img-background-selected]="selected"> <div class="border-bottom doc-img-container" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)">
<img class="card-img doc-img rounded-top" [src]="getThumbUrl()" (click)="setSelected(!selected)"> <img class="card-img doc-img rounded-top" [src]="getThumbUrl()">
<div class="border-right border-bottom bg-light p-1 rounded document-card-check"> <div class="border-right border-bottom bg-light p-1 rounded document-card-check">
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="smallCardCheck{{document.id}}" [checked]="selected" (change)="setSelected($event.target.checked)"> <input type="checkbox" class="custom-control-input" id="smallCardCheck{{document.id}}" [checked]="selected" (click)="this.toggleSelected.emit($event)">
<label class="custom-control-label" for="smallCardCheck{{document.id}}"></label> <label class="custom-control-label" for="smallCardCheck{{document.id}}"></label>
</div> </div>
</div> </div>
<div style="top: 0; right: 0; font-size: large" class="text-right position-absolute mr-1"> <div style="top: 0; right: 0; font-size: large" class="text-right position-absolute mr-1">
<div *ngFor="let t of getTagsLimited$() | async"> <div *ngFor="let t of getTagsLimited$() | async">
<app-tag [tag]="t" (click)="clickTag.emit(t.id)" [clickable]="true" linkTitle="Filter by tag" i18n-linkTitle></app-tag> <app-tag [tag]="t" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="true" linkTitle="Filter by tag" i18n-linkTitle></app-tag>
</div> </div>
<div *ngIf="moreTags"> <div *ngIf="moreTags">
<span class="badge badge-secondary">+ {{moreTags}}</span> <span class="badge badge-secondary">+ {{moreTags}}</span>
@@ -23,7 +23,7 @@
<div class="card-body p-2"> <div class="card-body p-2">
<p class="card-text"> <p class="card-text">
<ng-container *ngIf="document.correspondent"> <ng-container *ngIf="document.correspondent">
<a [routerLink]="" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent)" class="font-weight-bold">{{(document.correspondent$ | async)?.name}}</a>: <a [routerLink]="" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="font-weight-bold">{{(document.correspondent$ | async)?.name}}</a>:
</ng-container> </ng-container>
{{document.title | documentTitle}} <span *ngIf="document.archive_serial_number">(#{{document.archive_serial_number}})</span> {{document.title | documentTitle}} <span *ngIf="document.archive_serial_number">(#{{document.archive_serial_number}})</span>
</p> </p>
@@ -43,14 +43,14 @@
<path fill-rule="evenodd" d="M6.5 12a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zM13 6.5a6.5 6.5 0 1 1-13 0 6.5 6.5 0 0 1 13 0z"/> <path fill-rule="evenodd" d="M6.5 12a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zM13 6.5a6.5 6.5 0 1 1-13 0 6.5 6.5 0 0 1 13 0z"/>
</svg> </svg>
</a> </a>
<a [href]="getDownloadUrl()" class="btn btn-sm btn-outline-secondary" title="Download" i18n-title> <a [href]="getDownloadUrl()" class="btn btn-sm btn-outline-secondary" title="Download" (click)="$event.stopPropagation()" i18n-title>
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-download" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-download" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/> <path fill-rule="evenodd" d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
<path fill-rule="evenodd" d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/> <path fill-rule="evenodd" d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/>
</svg> </svg>
</a> </a>
</div> </div>
<small class="text-muted pl-1">{{document.created | date}}</small> <small class="text-muted pl-1">{{document.created | customDate:'shortDate'}}</small>
</div> </div>
</div> </div>

View File

@@ -15,13 +15,8 @@ export class DocumentCardSmallComponent implements OnInit {
@Input() @Input()
selected = false selected = false
setSelected(value: boolean) {
this.selected = value
this.selectedChange.emit(value)
}
@Output() @Output()
selectedChange = new EventEmitter<boolean>() toggleSelected = new EventEmitter()
@Input() @Input()
document: PaperlessDocument document: PaperlessDocument

View File

@@ -90,7 +90,7 @@
</div> </div>
<div *ngIf="displayMode == 'largeCards'"> <div *ngIf="displayMode == 'largeCards'">
<app-document-card-large [selected]="list.isSelected(d)" (selectedChange)="list.setSelected(d, $event)" *ngFor="let d of list.documents; trackBy: trackByDocumentId" [document]="d" [details]="d.content" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)"> <app-document-card-large [selected]="list.isSelected(d)" (toggleSelected)="toggleSelected(d, $event)" *ngFor="let d of list.documents; trackBy: trackByDocumentId" [document]="d" [details]="d.content" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)">
</app-document-card-large> </app-document-card-large>
</div> </div>
@@ -135,10 +135,10 @@
i18n>Added</th> i18n>Added</th>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let d of list.documents; trackBy: trackByDocumentId" [ngClass]="list.isSelected(d) ? 'table-row-selected' : ''"> <tr *ngFor="let d of list.documents; trackBy: trackByDocumentId" (click)="toggleSelected(d, $event)" [ngClass]="list.isSelected(d) ? 'table-row-selected' : ''">
<td> <td>
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="docCheck{{d.id}}" [checked]="list.isSelected(d)" (change)="list.setSelected(d, $event.target.checked)"> <input type="checkbox" class="custom-control-input" id="docCheck{{d.id}}" [checked]="list.isSelected(d)" (click)="toggleSelected(d, $event)">
<label class="custom-control-label" for="docCheck{{d.id}}"></label> <label class="custom-control-label" for="docCheck{{d.id}}"></label>
</div> </div>
</td> </td>
@@ -147,28 +147,28 @@
</td> </td>
<td class="d-none d-md-table-cell"> <td class="d-none d-md-table-cell">
<ng-container *ngIf="d.correspondent"> <ng-container *ngIf="d.correspondent">
<a [routerLink]="" (click)="clickCorrespondent(d.correspondent)" title="Filter by correspondent">{{(d.correspondent$ | async)?.name}}</a> <a [routerLink]="" (click)="clickCorrespondent(d.correspondent);$event.stopPropagation()" title="Filter by correspondent">{{(d.correspondent$ | async)?.name}}</a>
</ng-container> </ng-container>
</td> </td>
<td> <td>
<a routerLink="/documents/{{d.id}}" title="Edit document" style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a> <a routerLink="/documents/{{d.id}}" title="Edit document" style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
<app-tag [tag]="t" *ngFor="let t of d.tags$ | async" class="ml-1" clickable="true" linkTitle="Filter by tag" (click)="clickTag(t.id)"></app-tag> <app-tag [tag]="t" *ngFor="let t of d.tags$ | async" class="ml-1" clickable="true" linkTitle="Filter by tag" (click)="clickTag(t.id);$event.stopPropagation()"></app-tag>
</td> </td>
<td class="d-none d-xl-table-cell"> <td class="d-none d-xl-table-cell">
<ng-container *ngIf="d.document_type"> <ng-container *ngIf="d.document_type">
<a [routerLink]="" (click)="clickDocumentType(d.document_type)" title="Filter by document type">{{(d.document_type$ | async)?.name}}</a> <a [routerLink]="" (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type">{{(d.document_type$ | async)?.name}}</a>
</ng-container> </ng-container>
</td> </td>
<td> <td>
{{d.created | date}} {{d.created | customDate}}
</td> </td>
<td class="d-none d-xl-table-cell"> <td class="d-none d-xl-table-cell">
{{d.added | date}} {{d.added | customDate}}
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div class="m-n2 row row-cols-paperless-cards" *ngIf="displayMode == 'smallCards'"> <div class="m-n2 row row-cols-paperless-cards" *ngIf="displayMode == 'smallCards'">
<app-document-card-small [selected]="list.isSelected(d)" (selectedChange)="list.setSelected(d, $event)" [document]="d" *ngFor="let d of list.documents; trackBy: trackByDocumentId" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)"></app-document-card-small> <app-document-card-small [selected]="list.isSelected(d)" (toggleSelected)="toggleSelected(d, $event)" [document]="d" *ngFor="let d of list.documents; trackBy: trackByDocumentId" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)"></app-document-card-small>
</div> </div>

View File

@@ -1,5 +1,9 @@
@import "/src/theme"; @import "/src/theme";
tr {
user-select: none;
}
.table-row-selected { .table-row-selected {
background-color: $primaryFaded; background-color: $primaryFaded;
} }

View File

@@ -160,6 +160,11 @@ export class DocumentListComponent implements OnInit {
this.filterRulesModified = modified this.filterRulesModified = modified
} }
toggleSelected(document: PaperlessDocument, event: MouseEvent): void {
if (!event.shiftKey) this.list.toggleSelected(document)
else this.list.selectRangeTo(document)
}
clickTag(tagID: number) { clickTag(tagID: number) {
this.list.selectNone() this.list.selectNone()
setTimeout(() => { setTimeout(() => {

View File

@@ -1,7 +1,7 @@
<form [formGroup]="saveViewConfigForm" (ngSubmit)="save()"> <form [formGroup]="saveViewConfigForm" (ngSubmit)="save()">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title" id="modal-basic-title" i18n>Save current view</h4> <h4 class="modal-title" id="modal-basic-title" i18n>Save current view</h4>
<button type="button" class="close" aria-label="Close" (click)="cancel()"> <button type="button" [disabled]="!closeEnabled" class="close" aria-label="Close" (click)="cancel()">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
</div> </div>

View File

@@ -20,6 +20,8 @@ export class SaveViewConfigDialogComponent implements OnInit {
@Input() @Input()
buttonsEnabled = true buttonsEnabled = true
closeEnabled = false
_defaultName = "" _defaultName = ""
get defaultName() { get defaultName() {
@@ -39,6 +41,10 @@ export class SaveViewConfigDialogComponent implements OnInit {
}) })
ngOnInit(): void { ngOnInit(): void {
// wait to enable close button so it doesnt steal focus from input since its the first clickable element in the DOM
setTimeout(() => {
this.closeEnabled = true
});
} }
save() { save() {

View File

@@ -1,12 +1,11 @@
<form [formGroup]="objectForm" (ngSubmit)="save()"> <form [formGroup]="objectForm" (ngSubmit)="save()">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4> <h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
<button type="button" class="close" aria-label="Close" (click)="cancel()"> <button type="button" [disabled]="!closeEnabled" class="close" aria-label="Close" (click)="cancel()">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<app-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></app-input-text> <app-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></app-input-text>
<app-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> <app-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select>
<app-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match"></app-input-text> <app-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match"></app-input-text>

View File

@@ -2,8 +2,15 @@
<button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()" i18n>Create</button> <button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()" i18n>Create</button>
</app-page-header> </app-page-header>
<div class="row m-0 justify-content-end"> <div class="row">
<ngb-pagination [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination> <div class="col-md mb-2 mb-xl-0">
<div class="form-inline d-flex align-items-center">
<label class="text-muted mr-2 mb-0" i18n>Filter by:</label>
<input class="form-control form-control-sm flex-fill w-auto" type="text" [(ngModel)]="nameFilter" placeholder="Name" i18n-placeholder>
</div>
</div>
<ngb-pagination class="col-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
</div> </div>
<table class="table table-striped border shadow-sm"> <table class="table table-striped border shadow-sm">
@@ -21,7 +28,7 @@
<td scope="row">{{ correspondent.name }}</td> <td scope="row">{{ correspondent.name }}</td>
<td scope="row">{{ getMatching(correspondent) }}</td> <td scope="row">{{ getMatching(correspondent) }}</td>
<td scope="row">{{ correspondent.document_count }}</td> <td scope="row">{{ correspondent.document_count }}</td>
<td scope="row">{{ correspondent.last_correspondence | date }}</td> <td scope="row">{{ correspondent.last_correspondence | customDate }}</td>
<td scope="row"> <td scope="row">
<div class="btn-group"> <div class="btn-group">
<button class="btn btn-sm btn-outline-secondary" (click)="filterDocuments(correspondent)"> <button class="btn btn-sm btn-outline-secondary" (click)="filterDocuments(correspondent)">

View File

@@ -1,7 +1,7 @@
<form [formGroup]="objectForm" (ngSubmit)="save()"> <form [formGroup]="objectForm" (ngSubmit)="save()">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4> <h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
<button type="button" class="close" aria-label="Close" (click)="cancel()"> <button type="button" [disabled]="!closeEnabled" class="close" aria-label="Close" (click)="cancel()">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
</div> </div>

View File

@@ -2,9 +2,15 @@
<button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()" i18n>Create</button> <button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()" i18n>Create</button>
</app-page-header> </app-page-header>
<div class="row m-0 justify-content-end"> <div class="row">
<ngb-pagination [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" <div class="col-md mb-2 mb-xl-0">
aria-label="Default pagination"></ngb-pagination> <div class="form-inline d-flex align-items-center">
<label class="text-muted mr-2 mb-0" i18n>Filter by:</label>
<input class="form-control form-control-sm flex-fill w-auto" type="text" [(ngModel)]="nameFilter" placeholder="Name" i18n-placeholder>
</div>
</div>
<ngb-pagination class="col-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
</div> </div>
<table class="table table-striped border shadow-sm"> <table class="table table-striped border shadow-sm">

View File

@@ -1,17 +1,19 @@
import { Directive, OnInit, QueryList, ViewChildren } from '@angular/core'; import { Directive, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { MatchingModel, MATCHING_ALGORITHMS, MATCH_AUTO } from 'src/app/data/matching-model'; import { MatchingModel, MATCHING_ALGORITHMS, MATCH_AUTO } from 'src/app/data/matching-model';
import { ObjectWithId } from 'src/app/data/object-with-id'; import { ObjectWithId } from 'src/app/data/object-with-id';
import { SortableDirective, SortEvent } from 'src/app/directives/sortable.directive'; import { SortableDirective, SortEvent } from 'src/app/directives/sortable.directive';
import { AbstractPaperlessService } from 'src/app/services/rest/abstract-paperless-service'; import { AbstractNameFilterService } from 'src/app/services/rest/abstract-name-filter-service';
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'; import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component';
@Directive() @Directive()
export abstract class GenericListComponent<T extends ObjectWithId> implements OnInit { export abstract class GenericListComponent<T extends ObjectWithId> implements OnInit, OnDestroy {
constructor( constructor(
private service: AbstractPaperlessService<T>, private service: AbstractNameFilterService<T>,
private modalService: NgbModal, private modalService: NgbModal,
private editDialogComponent: any, private editDialogComponent: any,
private toastService: ToastService) { private toastService: ToastService) {
@@ -28,6 +30,10 @@ export abstract class GenericListComponent<T extends ObjectWithId> implements On
public sortField: string public sortField: string
public sortReverse: boolean public sortReverse: boolean
private nameFilterDebounce: Subject<string>
private subscription: Subscription
private _nameFilter: string
getMatching(o: MatchingModel) { getMatching(o: MatchingModel) {
if (o.matching_algorithm == MATCH_AUTO) { if (o.matching_algorithm == MATCH_AUTO) {
return $localize`Automatic` return $localize`Automatic`
@@ -44,12 +50,27 @@ export abstract class GenericListComponent<T extends ObjectWithId> implements On
this.reloadData() this.reloadData()
} }
ngOnInit(): void { ngOnInit(): void {
this.reloadData() this.reloadData()
this.nameFilterDebounce = new Subject<string>()
this.subscription = this.nameFilterDebounce.pipe(
debounceTime(400),
distinctUntilChanged()
).subscribe(title => {
this._nameFilter = title
this.reloadData()
})
}
ngOnDestroy() {
this.subscription.unsubscribe()
} }
reloadData() { reloadData() {
this.service.list(this.page, null, this.sortField, this.sortReverse).subscribe(c => { this.service.listFiltered(this.page, null, this.sortField, this.sortReverse, this._nameFilter).subscribe(c => {
this.data = c.results this.data = c.results
this.collectionSize = c.count this.collectionSize = c.count
}); });
@@ -95,4 +116,12 @@ export abstract class GenericListComponent<T extends ObjectWithId> implements On
} }
) )
} }
get nameFilter() {
return this._nameFilter
}
set nameFilter(nameFilter: string) {
this.nameFilterDebounce.next(nameFilter)
}
} }

View File

@@ -20,7 +20,7 @@
<p <p
class="m-0 p-0 log-entry-{{log.level}}" class="m-0 p-0 log-entry-{{log.level}}"
*ngFor="let log of logs"> *ngFor="let log of logs">
{{log.created | date:'short'}} {{log.created | customDate:'short'}}
{{getLevelText(log.level)}} {{getLevelText(log.level)}}
{{log.message}} {{log.message}}
</p> </p>

View File

@@ -12,6 +12,56 @@
<h4 i18n>Appearance</h4> <h4 i18n>Appearance</h4>
<div class="form-row form-group">
<div class="col-md-3 col-form-label">
<span i18n>Display language</span>
</div>
<div class="col">
<select class="form-control" formControlName="displayLanguage">
<option *ngFor="let lang of displayLanguageOptions" [ngValue]="lang.code">{{lang.name}}<span *ngIf="lang.code && currentLocale != 'en-US'"> - {{lang.englishName}}</span></option>
</select>
<small class="form-text text-muted" i18n>You need to reload the page after applying a new language.</small>
</div>
</div>
<div class="form-row form-group">
<div class="col-md-3 col-form-label">
<span i18n>Date display</span>
</div>
<div class="col">
<select class="form-control" formControlName="dateLocale">
<option *ngFor="let lang of dateLocaleOptions" [ngValue]="lang.code">{{lang.name}}<span *ngIf="lang.code"> - {{today | date:'shortDate':null:lang.code}}</span></option>
</select>
</div>
</div>
<div class="form-row form-group">
<div class="col-md-3 col-form-label">
<span i18n>Date format</span>
</div>
<div class="col">
<div class="custom-control custom-radio">
<input type="radio" id="dateFormatShort" name="dateFormat" class="custom-control-input" formControlName="dateFormat" value="shortDate">
<label class="custom-control-label" for="dateFormatShort" i18n>Short: {{today | customDate:'shortDate':null:computedDateLocale}}</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" id="dateFormatMedium" name="dateFormat" class="custom-control-input" formControlName="dateFormat" value="mediumDate">
<label class="custom-control-label" for="dateFormatMedium" i18n>Medium: {{today | customDate:'mediumDate':null:computedDateLocale}}</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" id="dateFormatLong" name="dateFormat" class="custom-control-input" formControlName="dateFormat" value="longDate">
<label class="custom-control-label" for="dateFormatLong" i18n>Long: {{today | customDate:'longDate':null:computedDateLocale}}</label>
</div>
</div>
</div>
<div class="form-row form-group"> <div class="form-row form-group">
<div class="col-md-3 col-form-label"> <div class="col-md-3 col-form-label">
<span i18n>Items per page</span> <span i18n>Items per page</span>

View File

@@ -1,9 +1,9 @@
import { Component, OnInit, Renderer2 } from '@angular/core'; import { Component, Inject, LOCALE_ID, OnInit, Renderer2 } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms'; import { FormControl, FormGroup } from '@angular/forms';
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'; import { PaperlessSavedView } from 'src/app/data/paperless-saved-view';
import { DocumentListViewService } from 'src/app/services/document-list-view.service'; import { DocumentListViewService } from 'src/app/services/document-list-view.service';
import { SavedViewService } from 'src/app/services/rest/saved-view.service'; import { SavedViewService } from 'src/app/services/rest/saved-view.service';
import { SettingsService, SETTINGS_KEYS } from 'src/app/services/settings.service'; import { LanguageOption, SettingsService, SETTINGS_KEYS } from 'src/app/services/settings.service';
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
@Component({ @Component({
@@ -22,16 +22,24 @@ export class SettingsComponent implements OnInit {
'darkModeUseSystem': new FormControl(this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM)), 'darkModeUseSystem': new FormControl(this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM)),
'darkModeEnabled': new FormControl(this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED)), 'darkModeEnabled': new FormControl(this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED)),
'useNativePdfViewer': new FormControl(this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)), 'useNativePdfViewer': new FormControl(this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)),
'savedViews': this.savedViewGroup 'savedViews': this.savedViewGroup,
'displayLanguage': new FormControl(this.settings.getLanguage()),
'dateLocale': new FormControl(this.settings.get(SETTINGS_KEYS.DATE_LOCALE)),
'dateFormat': new FormControl(this.settings.get(SETTINGS_KEYS.DATE_FORMAT)),
}) })
savedViews: PaperlessSavedView[] savedViews: PaperlessSavedView[]
get computedDateLocale(): string {
return this.settingsForm.value.dateLocale || this.settingsForm.value.displayLanguage
}
constructor( constructor(
public savedViewService: SavedViewService, public savedViewService: SavedViewService,
private documentListViewService: DocumentListViewService, private documentListViewService: DocumentListViewService,
private toastService: ToastService, private toastService: ToastService,
private settings: SettingsService private settings: SettingsService,
@Inject(LOCALE_ID) public currentLocale: string
) { } ) { }
ngOnInit() { ngOnInit() {
@@ -63,11 +71,26 @@ export class SettingsComponent implements OnInit {
this.settings.set(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem) this.settings.set(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem)
this.settings.set(SETTINGS_KEYS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString()) this.settings.set(SETTINGS_KEYS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString())
this.settings.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, this.settingsForm.value.useNativePdfViewer) this.settings.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, this.settingsForm.value.useNativePdfViewer)
this.settings.set(SETTINGS_KEYS.DATE_LOCALE, this.settingsForm.value.dateLocale)
this.settings.set(SETTINGS_KEYS.DATE_FORMAT, this.settingsForm.value.dateFormat)
this.settings.setLanguage(this.settingsForm.value.displayLanguage)
this.documentListViewService.updatePageSize() this.documentListViewService.updatePageSize()
this.settings.updateDarkModeSettings() this.settings.updateDarkModeSettings()
this.toastService.showInfo($localize`Settings saved successfully.`) this.toastService.showInfo($localize`Settings saved successfully.`)
} }
get displayLanguageOptions(): LanguageOption[] {
return [{code: "", name: $localize`Use system language`}].concat(this.settings.getLanguageOptions())
}
get dateLocaleOptions(): LanguageOption[] {
return [{code: "", name: $localize`Use date format of display language`}].concat(this.settings.getLanguageOptions())
}
get today() {
return new Date()
}
saveSettings() { saveSettings() {
let x = [] let x = []
for (let id in this.savedViewGroup.value) { for (let id in this.savedViewGroup.value) {

View File

@@ -1,7 +1,7 @@
<form [formGroup]="objectForm" (ngSubmit)="save()"> <form [formGroup]="objectForm" (ngSubmit)="save()">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4> <h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
<button type="button" class="close" aria-label="Close" (click)="cancel()"> <button type="button" [disabled]="!closeEnabled" class="close" aria-label="Close" (click)="cancel()">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
</div> </div>

View File

@@ -2,9 +2,15 @@
<button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()" i18n>Create</button> <button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()" i18n>Create</button>
</app-page-header> </app-page-header>
<div class="row m-0 justify-content-end"> <div class="row">
<ngb-pagination [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" <div class="col-md mb-2 mb-xl-0">
aria-label="Default pagination"></ngb-pagination> <div class="form-inline d-flex align-items-center">
<label class="text-muted mr-2 mb-0" i18n>Filter by:</label>
<input class="form-control form-control-sm flex-fill w-auto" type="text" [(ngModel)]="nameFilter" placeholder="Name" i18n-placeholder>
</div>
</div>
<ngb-pagination class="col-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
</div> </div>
<table class="table table-striped border shadow-sm"> <table class="table table-striped border shadow-sm">

View File

@@ -0,0 +1,8 @@
import { CustomDatePipe } from './custom-date.pipe';
describe('CustomDatePipe', () => {
it('create an instance', () => {
const pipe = new CustomDatePipe();
expect(pipe).toBeTruthy();
});
});

View File

@@ -0,0 +1,19 @@
import { DatePipe } from '@angular/common';
import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core';
import { SettingsService, SETTINGS_KEYS } from '../services/settings.service';
@Pipe({
name: 'customDate'
})
export class CustomDatePipe extends DatePipe implements PipeTransform {
constructor(@Inject(LOCALE_ID) locale: string, private settings: SettingsService) {
super(settings.get(SETTINGS_KEYS.DATE_LOCALE) || locale)
}
transform(value: any, format?: string, timezone?: string, locale?: string): string | null {
return super.transform(value, format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT), timezone, locale)
}
}

View File

@@ -27,6 +27,8 @@ export class DocumentListViewService {
currentPage = 1 currentPage = 1
currentPageSize: number = this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE) currentPageSize: number = this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE)
collectionSize: number collectionSize: number
rangeSelectionAnchorIndex: number
lastRangeSelectionToIndex: number
/** /**
* This is the current config for the document list. The service will always remember the last settings used for the document list. * This is the current config for the document list. The service will always remember the last settings used for the document list.
@@ -108,6 +110,7 @@ export class DocumentListViewService {
if (onFinish) { if (onFinish) {
onFinish() onFinish()
} }
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
this.isReloading = false this.isReloading = false
}, },
error => { error => {
@@ -218,6 +221,7 @@ export class DocumentListViewService {
selectNone() { selectNone() {
this.selected.clear() this.selected.clear()
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
} }
reduceSelectionToFilter() { reduceSelectionToFilter() {
@@ -249,14 +253,39 @@ export class DocumentListViewService {
return this.selected.has(d.id) return this.selected.has(d.id)
} }
setSelected(d: PaperlessDocument, value: boolean) { toggleSelected(d: PaperlessDocument): void {
if (value) { if (this.selected.has(d.id)) this.selected.delete(d.id)
this.selected.add(d.id) else this.selected.add(d.id)
} else if (!value) { this.rangeSelectionAnchorIndex = this.documentIndexInCurrentView(d.id)
this.selected.delete(d.id) this.lastRangeSelectionToIndex = null
}
selectRangeTo(d: PaperlessDocument) {
if (this.rangeSelectionAnchorIndex !== null) {
const documentToIndex = this.documentIndexInCurrentView(d.id)
const fromIndex = Math.min(this.rangeSelectionAnchorIndex, documentToIndex)
const toIndex = Math.max(this.rangeSelectionAnchorIndex, documentToIndex)
if (this.lastRangeSelectionToIndex !== null) {
// revert the old selection
this.documents.slice(Math.min(this.rangeSelectionAnchorIndex, this.lastRangeSelectionToIndex), Math.max(this.rangeSelectionAnchorIndex, this.lastRangeSelectionToIndex) + 1).forEach(d => {
this.selected.delete(d.id)
})
}
this.documents.slice(fromIndex, toIndex + 1).forEach(d => {
this.selected.add(d.id)
})
this.lastRangeSelectionToIndex = documentToIndex
} else { // e.g. shift key but was first click
this.toggleSelected(d)
} }
} }
documentIndexInCurrentView(documentID: number): number {
return this.documents.map(d => d.id).indexOf(documentID)
}
constructor(private documentService: DocumentService, private settings: SettingsService, private router: Router) { constructor(private documentService: DocumentService, private settings: SettingsService, private router: Router) {
let documentListViewConfigJson = sessionStorage.getItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG) let documentListViewConfigJson = sessionStorage.getItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG)
if (documentListViewConfigJson) { if (documentListViewConfigJson) {

View File

@@ -0,0 +1,14 @@
import { ObjectWithId } from 'src/app/data/object-with-id'
import { AbstractPaperlessService } from './abstract-paperless-service'
export abstract class AbstractNameFilterService<T extends ObjectWithId> extends AbstractPaperlessService<T> {
listFiltered(page?: number, pageSize?: number, sortField?: string, sortReverse?: boolean, nameFilter?: string) {
let params = {}
if (nameFilter) {
params = {'name__icontains': nameFilter}
}
return this.list(page, pageSize, sortField, sortReverse, params)
}
}

View File

@@ -1,12 +1,12 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'; import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent';
import { AbstractPaperlessService } from './abstract-paperless-service'; import { AbstractNameFilterService } from './abstract-name-filter-service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class CorrespondentService extends AbstractPaperlessService<PaperlessCorrespondent> { export class CorrespondentService extends AbstractNameFilterService<PaperlessCorrespondent> {
constructor(http: HttpClient) { constructor(http: HttpClient) {
super(http, 'correspondents') super(http, 'correspondents')

View File

@@ -1,12 +1,12 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'; import { PaperlessDocumentType } from 'src/app/data/paperless-document-type';
import { AbstractPaperlessService } from './abstract-paperless-service'; import { AbstractNameFilterService } from './abstract-name-filter-service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class DocumentTypeService extends AbstractPaperlessService<PaperlessDocumentType> { export class DocumentTypeService extends AbstractNameFilterService<PaperlessDocumentType> {
constructor(http: HttpClient) { constructor(http: HttpClient) {
super(http, 'document_types') super(http, 'document_types')

View File

@@ -1,12 +1,12 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { PaperlessTag } from 'src/app/data/paperless-tag'; import { PaperlessTag } from 'src/app/data/paperless-tag';
import { AbstractPaperlessService } from './abstract-paperless-service'; import { AbstractNameFilterService } from './abstract-name-filter-service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class TagService extends AbstractPaperlessService<PaperlessTag> { export class TagService extends AbstractNameFilterService<PaperlessTag> {
constructor(http: HttpClient) { constructor(http: HttpClient) {
super(http, 'tags') super(http, 'tags')

View File

@@ -1,5 +1,7 @@
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core'; import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core';
import { Meta } from '@angular/platform-browser';
import { CookieService } from 'ngx-cookie-service';
export interface PaperlessSettings { export interface PaperlessSettings {
key: string key: string
@@ -7,13 +9,21 @@ export interface PaperlessSettings {
default: any default: any
} }
export interface LanguageOption {
code: string,
name: string,
englishName?: string
}
export const SETTINGS_KEYS = { export const SETTINGS_KEYS = {
BULK_EDIT_CONFIRMATION_DIALOGS: 'general-settings:bulk-edit:confirmation-dialogs', BULK_EDIT_CONFIRMATION_DIALOGS: 'general-settings:bulk-edit:confirmation-dialogs',
BULK_EDIT_APPLY_ON_CLOSE: 'general-settings:bulk-edit:apply-on-close', BULK_EDIT_APPLY_ON_CLOSE: 'general-settings:bulk-edit:apply-on-close',
DOCUMENT_LIST_SIZE: 'general-settings:documentListSize', DOCUMENT_LIST_SIZE: 'general-settings:documentListSize',
DARK_MODE_USE_SYSTEM: 'general-settings:dark-mode:use-system', DARK_MODE_USE_SYSTEM: 'general-settings:dark-mode:use-system',
DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled', DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled',
USE_NATIVE_PDF_VIEWER: 'general-settings:document-details:native-pdf-viewer' USE_NATIVE_PDF_VIEWER: 'general-settings:document-details:native-pdf-viewer',
DATE_LOCALE: 'general-settings:date-display:date-locale',
DATE_FORMAT: 'general-settings:date-display:date-format'
} }
const SETTINGS: PaperlessSettings[] = [ const SETTINGS: PaperlessSettings[] = [
@@ -22,7 +32,9 @@ const SETTINGS: PaperlessSettings[] = [
{key: SETTINGS_KEYS.DOCUMENT_LIST_SIZE, type: "number", default: 50}, {key: SETTINGS_KEYS.DOCUMENT_LIST_SIZE, type: "number", default: 50},
{key: SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, type: "boolean", default: true}, {key: SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, type: "boolean", default: true},
{key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false}, {key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false},
{key: SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, type: "boolean", default: false} {key: SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, type: "boolean", default: false},
{key: SETTINGS_KEYS.DATE_LOCALE, type: "string", default: ""},
{key: SETTINGS_KEYS.DATE_FORMAT, type: "string", default: "mediumDate"}
] ]
@Injectable({ @Injectable({
@@ -34,7 +46,9 @@ export class SettingsService {
constructor( constructor(
private rendererFactory: RendererFactory2, private rendererFactory: RendererFactory2,
@Inject(DOCUMENT) private document @Inject(DOCUMENT) private document,
private cookieService: CookieService,
private meta: Meta
) { ) {
this.renderer = rendererFactory.createRenderer(null, null); this.renderer = rendererFactory.createRenderer(null, null);
@@ -55,6 +69,35 @@ export class SettingsService {
} }
getLanguageOptions(): LanguageOption[] {
return [
{code: "en-US", name: $localize`English (US)`, englishName: "English (US)"},
{code: "de", name: $localize`German`, englishName: "German"},
{code: "nl", name: $localize`Dutch`, englishName: "Dutch"},
{code: "fr", name: $localize`French`, englishName: "French"}
]
}
private getLanguageCookieName() {
let prefix = ""
if (this.meta.getTag('name=cookie_prefix')) {
prefix = this.meta.getTag('name=cookie_prefix').content
}
return `${prefix || ''}django_language`
}
getLanguage(): string {
return this.cookieService.get(this.getLanguageCookieName())
}
setLanguage(language: string) {
if (language) {
this.cookieService.set(this.getLanguageCookieName(), language)
} else {
this.cookieService.delete(this.getLanguageCookieName())
}
}
get(key: string): any { get(key: string): any {
let setting = SETTINGS.find(s => s.key == key) let setting = SETTINGS.find(s => s.key == key)

View File

@@ -2,5 +2,5 @@ export const environment = {
production: true, production: true,
apiBaseUrl: "/api/", apiBaseUrl: "/api/",
appTitle: "Paperless-ng", appTitle: "Paperless-ng",
version: "0.9.14" version: "1.0.0"
}; };

View File

@@ -449,12 +449,20 @@
<context context-type="linenumber">2</context> <context context-type="linenumber">2</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ddb40946e790522301687ecddb9ce1cb8ad40dd1">
<source>Filter by:</source>
<target>Filtern nach:</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">8</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="cff1428d10d59d14e45edec3c735a27b5482db59"> <trans-unit datatype="html" id="cff1428d10d59d14e45edec3c735a27b5482db59">
<source>Name</source> <source>Name</source>
<target>Name</target> <target>Name</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">9</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8fa4d523f7b91df4390120b85ed0406138273e1a"> <trans-unit datatype="html" id="8fa4d523f7b91df4390120b85ed0406138273e1a">
@@ -462,7 +470,7 @@
<target>Farbe</target> <target>Farbe</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">14</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="d0c4488f742efeba0915e90e285a022da813deff"> <trans-unit datatype="html" id="d0c4488f742efeba0915e90e285a022da813deff">
@@ -470,7 +478,7 @@
<target>Zuweisung</target> <target>Zuweisung</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">21</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9bcf8d20d23c111eca1431abd2d2ce0de324499c"> <trans-unit datatype="html" id="9bcf8d20d23c111eca1431abd2d2ce0de324499c">
@@ -478,7 +486,7 @@
<target>Anzahl Dokumente</target> <target>Anzahl Dokumente</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">22</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="030b4423b92167200e39519599f9b863b4f7c62c"> <trans-unit datatype="html" id="030b4423b92167200e39519599f9b863b4f7c62c">
@@ -486,7 +494,7 @@
<target>Aktionen</target> <target>Aktionen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">23</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9d51b3c90afda70700229d1b8a55371c13cb3bce"> <trans-unit datatype="html" id="9d51b3c90afda70700229d1b8a55371c13cb3bce">
@@ -494,7 +502,7 @@
<target>Dokumente</target> <target>Dokumente</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">32</context> <context context-type="linenumber">38</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="28f86ffd419b869711aa13f5e5ff54be6d70731c"> <trans-unit datatype="html" id="28f86ffd419b869711aa13f5e5ff54be6d70731c">
@@ -502,7 +510,7 @@
<target>Bearbeiten</target> <target>Bearbeiten</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">37</context> <context context-type="linenumber">43</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="4990731724078522539"> <trans-unit datatype="html" id="4990731724078522539">
@@ -542,7 +550,7 @@
<target>Gespeicherte Ansicht &quot;<x equiv-text="savedView.name" id="PH"/>&quot; gelöscht.</target> <target>Gespeicherte Ansicht &quot;<x equiv-text="savedView.name" id="PH"/>&quot; gelöscht.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">55</context> <context context-type="linenumber">63</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5647210819299459618"> <trans-unit datatype="html" id="5647210819299459618">
@@ -550,7 +558,23 @@
<target>Einstellungen erfolgreich gespeichert.</target> <target>Einstellungen erfolgreich gespeichert.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">68</context> <context context-type="linenumber">79</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="6839066544204061364">
<source>Use system language</source>
<target>Benutze Systemsprache</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">83</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="7729897675462249787">
<source>Use date format of display language</source>
<target>Benutze Datumsformat der Anzeigesprache</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8488620293789898901"> <trans-unit datatype="html" id="8488620293789898901">
@@ -558,7 +582,7 @@
<target>Fehler beim Speichern der Einstellungen auf dem Server: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> <target>Fehler beim Speichern der Einstellungen auf dem Server: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">80</context> <context context-type="linenumber">103</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716"> <trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716">
@@ -582,7 +606,7 @@
<target>Gespeicherte Ansichten</target> <target>Gespeicherte Ansichten</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">64</context> <context context-type="linenumber">114</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="bbe41ac2ea4a6c00ea941a41b33105048f8e9f13"> <trans-unit datatype="html" id="bbe41ac2ea4a6c00ea941a41b33105048f8e9f13">
@@ -593,12 +617,68 @@
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="75f8908d266f7cc9b9e68e0be906fd080a223606">
<source>Display language</source>
<target>Anzeigesprache</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="1284a077dc18a2d1ff1b744f16f1797eea28ae37">
<source>You need to reload the page after applying a new language.</source>
<target>Nachdem Sie eine neue Sprache ausgewählt haben, müssen Sie die Seite neu laden.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">25</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="0cd55822928764cc82a62ee3e6f3adbc1c630479">
<source>Date display</source>
<target>Datumsanzeige</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="7df4de0d0704a06a302d853e31f2580eba98f127">
<source>Date format</source>
<target>Datumsformat</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">45</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="69852399a18b8ca4fca8c5bfddd3f00a6d137593">
<source>Short: <x equiv-text="{{today | customDate:'shortDate':null:computedDateLocale}}" id="INTERPOLATION"/></source>
<target>Kurz: <x equiv-text="{{today | customDate:'shortDate':null:computedDateLocale}}" id="INTERPOLATION"/></target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="d01a59285e711252b98c4f193394e4b854615c78">
<source>Medium: <x equiv-text="{{today | customDate:'mediumDate':null:computedDateLocale}}" id="INTERPOLATION"/></source>
<target>Mittel: <x equiv-text="{{today | customDate:'mediumDate':null:computedDateLocale}}" id="INTERPOLATION"/></target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="00481629776699b1caebd12b3b1176e2e23740a8">
<source>Long: <x equiv-text="{{today | customDate:'longDate':null:computedDateLocale}}" id="INTERPOLATION"/></source>
<target>Lang: <x equiv-text="{{today | customDate:'longDate':null:computedDateLocale}}" id="INTERPOLATION"/></target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">59</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="2045151788cbdda7512752e408da59a6b54a8ef0"> <trans-unit datatype="html" id="2045151788cbdda7512752e408da59a6b54a8ef0">
<source>Items per page</source> <source>Items per page</source>
<target>Dokumente pro Seite</target> <target>Dokumente pro Seite</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">67</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="c4435e56bf0289e78fedc462f1d21fb30b9de55d"> <trans-unit datatype="html" id="c4435e56bf0289e78fedc462f1d21fb30b9de55d">
@@ -606,7 +686,7 @@
<target>Dokumenteditor</target> <target>Dokumenteditor</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">83</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="4903e521c9bfd11ce88e7a5575106ef638912e0d"> <trans-unit datatype="html" id="4903e521c9bfd11ce88e7a5575106ef638912e0d">
@@ -614,7 +694,7 @@
<target>Benutze PDF-Betrachter des Web Browsers</target> <target>Benutze PDF-Betrachter des Web Browsers</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">37</context> <context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="d7db07023e53f8396d18d375c2b78c25fc81c197"> <trans-unit datatype="html" id="d7db07023e53f8396d18d375c2b78c25fc81c197">
@@ -622,7 +702,7 @@
<target>Der integrierte PDF-Betrachter des Web-Browsers ist in der Regel schneller bei der Anzeige besonders großer Dokumente, funktioniert aber nicht in allen Browsern.</target> <target>Der integrierte PDF-Betrachter des Web-Browsers ist in der Regel schneller bei der Anzeige besonders großer Dokumente, funktioniert aber nicht in allen Browsern.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">37</context> <context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9ee5d1cbfd6ee168dae37aaba2b59b50bcabb2ff"> <trans-unit datatype="html" id="9ee5d1cbfd6ee168dae37aaba2b59b50bcabb2ff">
@@ -630,7 +710,7 @@
<target>Dunkler Modus</target> <target>Dunkler Modus</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">44</context> <context context-type="linenumber">94</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="f8cb5506e70fd71fddc9bb71cee18bfff7b29637"> <trans-unit datatype="html" id="f8cb5506e70fd71fddc9bb71cee18bfff7b29637">
@@ -638,7 +718,7 @@
<target>Benutze Systemeinstellungen</target> <target>Benutze Systemeinstellungen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">47</context> <context context-type="linenumber">97</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8ee474504043fa89821d626e4f3413240fa91b53"> <trans-unit datatype="html" id="8ee474504043fa89821d626e4f3413240fa91b53">
@@ -646,7 +726,7 @@
<target>Dunklen Modus aktivieren</target> <target>Dunklen Modus aktivieren</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">48</context> <context context-type="linenumber">98</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="3863a86cd9e69a61d143d3daf51df44203df4a82"> <trans-unit datatype="html" id="3863a86cd9e69a61d143d3daf51df44203df4a82">
@@ -654,7 +734,7 @@
<target>Massenbearbeitung</target> <target>Massenbearbeitung</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">52</context> <context context-type="linenumber">102</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="c0ac61661c6c326d6e0e00c231b95cf2ac0c6586"> <trans-unit datatype="html" id="c0ac61661c6c326d6e0e00c231b95cf2ac0c6586">
@@ -662,7 +742,7 @@
<target>Bestätigungsdialoge anzeigen</target> <target>Bestätigungsdialoge anzeigen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">56</context> <context context-type="linenumber">106</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="291bbe56ecbe945dcf05580a57d679fa7bd1e06a"> <trans-unit datatype="html" id="291bbe56ecbe945dcf05580a57d679fa7bd1e06a">
@@ -670,7 +750,7 @@
<target>Beim Löschen von Dokumenten wird immer nach einer Bestätigung gefragt.</target> <target>Beim Löschen von Dokumenten wird immer nach einer Bestätigung gefragt.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">56</context> <context context-type="linenumber">106</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8cfddc13e04f5545ac63f419ef363505d6f78c2e"> <trans-unit datatype="html" id="8cfddc13e04f5545ac63f419ef363505d6f78c2e">
@@ -678,7 +758,7 @@
<target>Anwenden beim Schließen</target> <target>Anwenden beim Schließen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">57</context> <context context-type="linenumber">107</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8cb90334f5dfd7fc67205085f59381e2a334ccfc"> <trans-unit datatype="html" id="8cb90334f5dfd7fc67205085f59381e2a334ccfc">
@@ -686,7 +766,7 @@
<target>Erscheint auf</target> <target>Erscheint auf</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">76</context> <context context-type="linenumber">126</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="6717cf1acf04728fc2b7c39f6d3297f8ff15fde5"> <trans-unit datatype="html" id="6717cf1acf04728fc2b7c39f6d3297f8ff15fde5">
@@ -694,7 +774,7 @@
<target>Auf Startseite zeigen</target> <target>Auf Startseite zeigen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">79</context> <context context-type="linenumber">129</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="541bfc5b123b3f8867fd681eaceefb663a811973"> <trans-unit datatype="html" id="541bfc5b123b3f8867fd681eaceefb663a811973">
@@ -702,7 +782,7 @@
<target>In Seitenleiste zeigen</target> <target>In Seitenleiste zeigen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">83</context> <context context-type="linenumber">133</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="abba764a7a595d04dc8c3b26e04b3780d4fdb540"> <trans-unit datatype="html" id="abba764a7a595d04dc8c3b26e04b3780d4fdb540">
@@ -710,7 +790,7 @@
<target>Keine gespeicherten Ansichten vorhanden.</target> <target>Keine gespeicherten Ansichten vorhanden.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">143</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ef60a738a565f498b858e903e42bc5ffc3cc1299"> <trans-unit datatype="html" id="ef60a738a565f498b858e903e42bc5ffc3cc1299">
@@ -742,7 +822,7 @@
<target>Letzter Kontakt</target> <target>Letzter Kontakt</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">22</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1234709746630139322"> <trans-unit datatype="html" id="1234709746630139322">
@@ -790,7 +870,7 @@
<target>Zuweisungsalgorithmus</target> <target>Zuweisungsalgorithmus</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">10</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="eab7fc7cf2d663e54de934b779fce4275a303f0f"> <trans-unit datatype="html" id="eab7fc7cf2d663e54de934b779fce4275a303f0f">
@@ -798,7 +878,7 @@
<target>Zuweisungsmuster</target> <target>Zuweisungsmuster</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">11</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="632e529f49cf3d367dfbd15bd055e9b53aef30fb"> <trans-unit datatype="html" id="632e529f49cf3d367dfbd15bd055e9b53aef30fb">
@@ -806,7 +886,7 @@
<target>Groß-/Kleinschreibung irrelevant</target> <target>Groß-/Kleinschreibung irrelevant</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9153094873118985366"> <trans-unit datatype="html" id="9153094873118985366">
@@ -1042,14 +1122,6 @@
<context context-type="linenumber">46</context> <context context-type="linenumber">46</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ddb40946e790522301687ecddb9ce1cb8ad40dd1">
<source>Filter by:</source>
<target>Filtern nach:</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">4</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="02d184c288f567825a1fcbf83bcd3099a10853d5"> <trans-unit datatype="html" id="02d184c288f567825a1fcbf83bcd3099a10853d5">
<source>Filter tags</source> <source>Filter tags</source>
<target>Tags filtern</target> <target>Tags filtern</target>
@@ -1163,9 +1235,9 @@
<context context-type="linenumber">50</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1b29a8153575e5ad26cc7dd8bd75c4f45f6bfe7e"> <trans-unit datatype="html" id="849b42384616374df49bd8b3711ec159cb10b845">
<source>Created: <x equiv-text="{{document.created | date}}" id="INTERPOLATION"/></source> <source>Created: <x equiv-text="{{document.created | customDate}}" id="INTERPOLATION"/></source>
<target>Erstellt: <x equiv-text="{{document.created | date}}" id="INTERPOLATION"/></target> <target>Erstellt: <x equiv-text="{{document.created | customDate}}" id="INTERPOLATION"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
<context context-type="linenumber">67</context> <context context-type="linenumber">67</context>
@@ -1598,6 +1670,38 @@
<context context-type="linenumber">12</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1206520795340730278">
<source>English (US)</source>
<target>Englisch (US)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">74</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="1858110241312746425">
<source>German</source>
<target>Deutsch</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">75</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="3071065188816255493">
<source>Dutch</source>
<target>Niederländisch</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">76</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="7633754075223722162">
<source>French</source>
<target>Französisch</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">77</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="1519954996184640001"> <trans-unit datatype="html" id="1519954996184640001">
<source>Error</source> <source>Error</source>
<target>Fehler</target> <target>Fehler</target>
@@ -1779,7 +1883,7 @@
<target>Neues Element erstellen</target> <target>Neues Element erstellen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">43</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5324147361912094446"> <trans-unit datatype="html" id="5324147361912094446">
@@ -1787,7 +1891,7 @@
<target>Element bearbeiten</target> <target>Element bearbeiten</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">47</context> <context context-type="linenumber">54</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1699589597032579396"> <trans-unit datatype="html" id="1699589597032579396">
@@ -1795,7 +1899,7 @@
<target>Konnte Element nicht speichern: <x equiv-text="error" id="PH"/></target> <target>Konnte Element nicht speichern: <x equiv-text="error" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">51</context> <context context-type="linenumber">58</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="810888510148304696"> <trans-unit datatype="html" id="810888510148304696">
@@ -1803,7 +1907,7 @@
<target>Automatisch</target> <target>Automatisch</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5044611416737085530"> <trans-unit datatype="html" id="5044611416737085530">
@@ -1811,7 +1915,7 @@
<target>Möchten Sie dieses Element wirklich löschen?</target> <target>Möchten Sie dieses Element wirklich löschen?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">76</context> <context context-type="linenumber">97</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8371896857609524947"> <trans-unit datatype="html" id="8371896857609524947">
@@ -1819,7 +1923,7 @@
<target>Assoziierte Dokumente werden nicht gelöscht.</target> <target>Assoziierte Dokumente werden nicht gelöscht.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">83</context> <context context-type="linenumber">104</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7022070615528435141"> <trans-unit datatype="html" id="7022070615528435141">
@@ -1827,7 +1931,7 @@
<target>Löschen</target> <target>Löschen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">85</context> <context context-type="linenumber">106</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5467489005440577210"> <trans-unit datatype="html" id="5467489005440577210">
@@ -1835,7 +1939,7 @@
<target>Fehler beim Löschen des Elements: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> <target>Fehler beim Löschen des Elements: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">114</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5851669019930456395"> <trans-unit datatype="html" id="5851669019930456395">
@@ -1912,7 +2016,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8419167206585286450"> <trans-unit datatype="html" id="8419167206585286450">
<source>Fuzzy: Document contains a word similar to this word</source> <source>Fuzzy: Document contains a word similar to this word</source>
<target>Ungenau: Dokument enthält ein zum folgdendem Wort ähnliches Wort</target> <target>Ungenau: Dokument enthält ein zum folgendem Wort ähnliches Wort</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/data/matching-model.ts</context> <context context-type="sourcefile">src/app/data/matching-model.ts</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">16</context>

View File

@@ -38,7 +38,7 @@
<target>Sélectionner aucun</target> <target>Sélectionner aucun</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">10</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="2ed8a0c2ce4968f8614151eefed20a0aa3daeeb9"> <trans-unit datatype="html" id="2ed8a0c2ce4968f8614151eefed20a0aa3daeeb9">
@@ -46,7 +46,7 @@
<target>Sélectionner la page</target> <target>Sélectionner la page</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">11</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="b463541a7e303aa4d0b1102eaff8afbaf34e7a74"> <trans-unit datatype="html" id="b463541a7e303aa4d0b1102eaff8afbaf34e7a74">
@@ -54,15 +54,15 @@
<target>Sélectionner tout</target> <target>Sélectionner tout</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ec97f67072a83aaa972536b18d83179f6e4bbec9"> <trans-unit datatype="html" id="5d43539fc358c3a548b9d487be821db73e2702ff">
<source>Sort by</source> <source>Sort</source>
<target>Trier par</target> <target>Trier</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">41</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="b7641aed03492978b4ec6843b1e53f30464294d9"> <trans-unit datatype="html" id="b7641aed03492978b4ec6843b1e53f30464294d9">
@@ -94,7 +94,7 @@
<target>{VAR_PLURAL, plural, =1 {<x id="INTERPOLATION"/> document sélectionné sur 1} other {<x id="INTERPOLATION"/> documents sélectionnés sur <x id="INTERPOLATION_1"/>}}</target> <target>{VAR_PLURAL, plural, =1 {<x id="INTERPOLATION"/> document sélectionné sur 1} other {<x id="INTERPOLATION"/> documents sélectionnés sur <x id="INTERPOLATION_1"/>}}</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">87</context> <context context-type="linenumber">85</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="bb773fdeaad5e7fb8e6cd77e1cc558e1b194a0c9"> <trans-unit datatype="html" id="bb773fdeaad5e7fb8e6cd77e1cc558e1b194a0c9">
@@ -102,7 +102,7 @@
<target>{VAR_PLURAL, plural, =1 {Un document} other {<x id="INTERPOLATION"/> documents}}</target> <target>{VAR_PLURAL, plural, =1 {Un document} other {<x id="INTERPOLATION"/> documents}}</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">88</context> <context context-type="linenumber">86</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="bb91083b44e3f77dd68de773ceab467ca3d57507"> <trans-unit datatype="html" id="bb91083b44e3f77dd68de773ceab467ca3d57507">
@@ -110,7 +110,7 @@
<target>(filtré)</target> <target>(filtré)</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">88</context> <context context-type="linenumber">86</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ca0b795795658155d44ddca02e95f1feeeb4a88f"> <trans-unit datatype="html" id="ca0b795795658155d44ddca02e95f1feeeb4a88f">
@@ -118,7 +118,7 @@
<target>NSA</target> <target>NSA</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">107</context> <context context-type="linenumber">105</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7b5c6286aaded63fb279d6deb8aa8c704e085ced"> <trans-unit datatype="html" id="7b5c6286aaded63fb279d6deb8aa8c704e085ced">
@@ -126,7 +126,7 @@
<target>Correspondant</target> <target>Correspondant</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">113</context> <context context-type="linenumber">111</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="fdf7cbdc140d0aab0f0b6c06065a0fd448ed6a2e"> <trans-unit datatype="html" id="fdf7cbdc140d0aab0f0b6c06065a0fd448ed6a2e">
@@ -134,7 +134,7 @@
<target>Titre</target> <target>Titre</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">119</context> <context context-type="linenumber">117</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="2bd5919e8098513664a89d5b7b52d61e3063950f"> <trans-unit datatype="html" id="2bd5919e8098513664a89d5b7b52d61e3063950f">
@@ -142,7 +142,7 @@
<target>Type de document</target> <target>Type de document</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">125</context> <context context-type="linenumber">123</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1b051734b0ee9021991c91b3ed4e81c244322462"> <trans-unit datatype="html" id="1b051734b0ee9021991c91b3ed4e81c244322462">
@@ -150,7 +150,7 @@
<target>Date de création</target> <target>Date de création</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">131</context> <context context-type="linenumber">129</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="80e3b490720757978c99a7b5af3885faf202b955"> <trans-unit datatype="html" id="80e3b490720757978c99a7b5af3885faf202b955">
@@ -158,7 +158,7 @@
<target>Date d'ajout</target> <target>Date d'ajout</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">137</context> <context context-type="linenumber">135</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9021887951960049161"> <trans-unit datatype="html" id="9021887951960049161">
@@ -166,7 +166,7 @@
<target>Confirmer la suppression</target> <target>Confirmer la suppression</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">186</context> <context context-type="linenumber">192</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5382975254277698192"> <trans-unit datatype="html" id="5382975254277698192">
@@ -174,7 +174,7 @@
<target>Voulez-vous vraiment supprimer le document &quot;<x equiv-text="this.document.title" id="PH"/>&quot; ?</target> <target>Voulez-vous vraiment supprimer le document &quot;<x equiv-text="this.document.title" id="PH"/>&quot; ?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">187</context> <context context-type="linenumber">193</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="6691075929777935948"> <trans-unit datatype="html" id="6691075929777935948">
@@ -182,7 +182,7 @@
<target>Les fichiers liés à ce document seront supprimés définitivement. Cette action est irréversible.</target> <target>Les fichiers liés à ce document seront supprimés définitivement. Cette action est irréversible.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">188</context> <context context-type="linenumber">194</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="719892092227206532"> <trans-unit datatype="html" id="719892092227206532">
@@ -190,7 +190,7 @@
<target>Supprimer le document</target> <target>Supprimer le document</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">190</context> <context context-type="linenumber">196</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1844801255494293730"> <trans-unit datatype="html" id="1844801255494293730">
@@ -198,7 +198,7 @@
<target>Une erreur s'est produite lors de la suppression du document : <x equiv-text="JSON.stringify(error)" id="PH"/></target> <target>Une erreur s'est produite lors de la suppression du document : <x equiv-text="JSON.stringify(error)" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">197</context> <context context-type="linenumber">203</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="826b25211922a1b46436589233cb6f1a163d89b7"> <trans-unit datatype="html" id="826b25211922a1b46436589233cb6f1a163d89b7">
@@ -449,12 +449,20 @@
<context context-type="linenumber">2</context> <context context-type="linenumber">2</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ddb40946e790522301687ecddb9ce1cb8ad40dd1">
<source>Filter by:</source>
<target>Filtrer par : </target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">8</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="cff1428d10d59d14e45edec3c735a27b5482db59"> <trans-unit datatype="html" id="cff1428d10d59d14e45edec3c735a27b5482db59">
<source>Name</source> <source>Name</source>
<target>Nom</target> <target>Nom</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">9</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8fa4d523f7b91df4390120b85ed0406138273e1a"> <trans-unit datatype="html" id="8fa4d523f7b91df4390120b85ed0406138273e1a">
@@ -462,7 +470,7 @@
<target>Couleur</target> <target>Couleur</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">14</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="d0c4488f742efeba0915e90e285a022da813deff"> <trans-unit datatype="html" id="d0c4488f742efeba0915e90e285a022da813deff">
@@ -470,7 +478,7 @@
<target>Rapprochement</target> <target>Rapprochement</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">21</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9bcf8d20d23c111eca1431abd2d2ce0de324499c"> <trans-unit datatype="html" id="9bcf8d20d23c111eca1431abd2d2ce0de324499c">
@@ -478,7 +486,7 @@
<target>Nombre de documents</target> <target>Nombre de documents</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">22</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="030b4423b92167200e39519599f9b863b4f7c62c"> <trans-unit datatype="html" id="030b4423b92167200e39519599f9b863b4f7c62c">
@@ -486,7 +494,7 @@
<target>Actions</target> <target>Actions</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">23</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9d51b3c90afda70700229d1b8a55371c13cb3bce"> <trans-unit datatype="html" id="9d51b3c90afda70700229d1b8a55371c13cb3bce">
@@ -494,7 +502,7 @@
<target>Documents</target> <target>Documents</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">32</context> <context context-type="linenumber">38</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="28f86ffd419b869711aa13f5e5ff54be6d70731c"> <trans-unit datatype="html" id="28f86ffd419b869711aa13f5e5ff54be6d70731c">
@@ -502,7 +510,7 @@
<target>Éditer</target> <target>Éditer</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">37</context> <context context-type="linenumber">43</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="4990731724078522539"> <trans-unit datatype="html" id="4990731724078522539">
@@ -542,7 +550,7 @@
<target>Vue &quot;<x equiv-text="savedView.name" id="PH"/>&quot; supprimée.</target> <target>Vue &quot;<x equiv-text="savedView.name" id="PH"/>&quot; supprimée.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">54</context> <context context-type="linenumber">63</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5647210819299459618"> <trans-unit datatype="html" id="5647210819299459618">
@@ -550,7 +558,23 @@
<target>Paramètres enregistrés avec succès.</target> <target>Paramètres enregistrés avec succès.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">74</context> <context context-type="linenumber">79</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="6839066544204061364">
<source>Use system language</source>
<target>Utiliser la langue du système</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">83</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="7729897675462249787">
<source>Use date format of display language</source>
<target>Utiliser le format de date de la langue d'affichage</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8488620293789898901"> <trans-unit datatype="html" id="8488620293789898901">
@@ -558,7 +582,7 @@
<target>Une erreur s'est produite lors de l'enregistrement des paramètres sur le serveur : <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> <target>Une erreur s'est produite lors de l'enregistrement des paramètres sur le serveur : <x equiv-text="JSON.stringify(error.error)" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">86</context> <context context-type="linenumber">103</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716"> <trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716">
@@ -582,7 +606,7 @@
<target>Vues enregistrées</target> <target>Vues enregistrées</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">56</context> <context context-type="linenumber">114</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="bbe41ac2ea4a6c00ea941a41b33105048f8e9f13"> <trans-unit datatype="html" id="bbe41ac2ea4a6c00ea941a41b33105048f8e9f13">
@@ -593,12 +617,92 @@
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="75f8908d266f7cc9b9e68e0be906fd080a223606">
<source>Display language</source>
<target>Langue d'affichage</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="1284a077dc18a2d1ff1b744f16f1797eea28ae37">
<source>You need to reload the page after applying a new language.</source>
<target>Vous devez recharger la page après avoir sélectionné une nouvelle langue.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">25</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="0cd55822928764cc82a62ee3e6f3adbc1c630479">
<source>Date display</source>
<target>Affichage de la date</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="7df4de0d0704a06a302d853e31f2580eba98f127">
<source>Date format</source>
<target>Format de date</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">45</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="69852399a18b8ca4fca8c5bfddd3f00a6d137593">
<source>Short: <x equiv-text="{{today | customDate:'shortDate':null:computedDateLocale}}" id="INTERPOLATION"/></source>
<target>Court : <x equiv-text="{{today | customDate:'shortDate':null:computedDateLocale}}" id="INTERPOLATION"/></target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="d01a59285e711252b98c4f193394e4b854615c78">
<source>Medium: <x equiv-text="{{today | customDate:'mediumDate':null:computedDateLocale}}" id="INTERPOLATION"/></source>
<target>Moyen : <x equiv-text="{{today | customDate:'mediumDate':null:computedDateLocale}}" id="INTERPOLATION"/></target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="00481629776699b1caebd12b3b1176e2e23740a8">
<source>Long: <x equiv-text="{{today | customDate:'longDate':null:computedDateLocale}}" id="INTERPOLATION"/></source>
<target>Long : <x equiv-text="{{today | customDate:'longDate':null:computedDateLocale}}" id="INTERPOLATION"/></target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">59</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="2045151788cbdda7512752e408da59a6b54a8ef0"> <trans-unit datatype="html" id="2045151788cbdda7512752e408da59a6b54a8ef0">
<source>Items per page</source> <source>Items per page</source>
<target>Éléments par page</target> <target>Éléments par page</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">67</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="c4435e56bf0289e78fedc462f1d21fb30b9de55d">
<source>Document editor</source>
<target>Visionneuse de documents</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">83</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="4903e521c9bfd11ce88e7a5575106ef638912e0d">
<source>Use PDF viewer provided by the browser</source>
<target>Utiliser la visionneuse PDF fournie par le navigateur</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">87</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="d7db07023e53f8396d18d375c2b78c25fc81c197">
<source>This is usually faster for displaying large PDF documents, but it might not work on some browsers.</source>
<target>Cette option est généralement plus rapide pour l'affichage de grands documents PDF, mais elle peut ne pas fonctionner sur certains navigateurs.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9ee5d1cbfd6ee168dae37aaba2b59b50bcabb2ff"> <trans-unit datatype="html" id="9ee5d1cbfd6ee168dae37aaba2b59b50bcabb2ff">
@@ -606,7 +710,7 @@
<target>Mode sombre</target> <target>Mode sombre</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">94</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="f8cb5506e70fd71fddc9bb71cee18bfff7b29637"> <trans-unit datatype="html" id="f8cb5506e70fd71fddc9bb71cee18bfff7b29637">
@@ -614,39 +718,7 @@
<target>Utiliser les paramètres du système</target> <target>Utiliser les paramètres du système</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">36</context> <context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="3863a86cd9e69a61d143d3daf51df44203df4a82">
<source>Bulk editing</source>
<target>Edition en masse</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="c0ac61661c6c326d6e0e00c231b95cf2ac0c6586">
<source>Show confirmation dialogs</source>
<target>Afficher les messages de confirmation</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">48</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="291bbe56ecbe945dcf05580a57d679fa7bd1e06a">
<source>Deleting documents will always ask for confirmation.</source>
<target>La suppression de documents requiert toujours une confirmation.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">48</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="8cfddc13e04f5545ac63f419ef363505d6f78c2e">
<source>Apply on close</source>
<target>Appliquer lors de la fermeture</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">49</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8ee474504043fa89821d626e4f3413240fa91b53"> <trans-unit datatype="html" id="8ee474504043fa89821d626e4f3413240fa91b53">
@@ -654,7 +726,39 @@
<target>Activer le mode sombre</target> <target>Activer le mode sombre</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">39</context> <context context-type="linenumber">98</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="3863a86cd9e69a61d143d3daf51df44203df4a82">
<source>Bulk editing</source>
<target>Edition en masse</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">102</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="c0ac61661c6c326d6e0e00c231b95cf2ac0c6586">
<source>Show confirmation dialogs</source>
<target>Afficher les messages de confirmation</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">106</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="291bbe56ecbe945dcf05580a57d679fa7bd1e06a">
<source>Deleting documents will always ask for confirmation.</source>
<target>La suppression de documents requiert toujours une confirmation.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">106</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="8cfddc13e04f5545ac63f419ef363505d6f78c2e">
<source>Apply on close</source>
<target>Appliquer lors de la fermeture</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">107</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8cb90334f5dfd7fc67205085f59381e2a334ccfc"> <trans-unit datatype="html" id="8cb90334f5dfd7fc67205085f59381e2a334ccfc">
@@ -662,7 +766,7 @@
<target>Apparaît sur</target> <target>Apparaît sur</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">68</context> <context context-type="linenumber">126</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="6717cf1acf04728fc2b7c39f6d3297f8ff15fde5"> <trans-unit datatype="html" id="6717cf1acf04728fc2b7c39f6d3297f8ff15fde5">
@@ -670,7 +774,7 @@
<target>Montrer sur le tableau de bord</target> <target>Montrer sur le tableau de bord</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">71</context> <context context-type="linenumber">129</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="541bfc5b123b3f8867fd681eaceefb663a811973"> <trans-unit datatype="html" id="541bfc5b123b3f8867fd681eaceefb663a811973">
@@ -678,7 +782,7 @@
<target>Montrer dans la barre latérale</target> <target>Montrer dans la barre latérale</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">75</context> <context context-type="linenumber">133</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="abba764a7a595d04dc8c3b26e04b3780d4fdb540"> <trans-unit datatype="html" id="abba764a7a595d04dc8c3b26e04b3780d4fdb540">
@@ -686,7 +790,7 @@
<target>Aucune vue sauvegardée n'est définie.</target> <target>Aucune vue sauvegardée n'est définie.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">85</context> <context context-type="linenumber">143</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ef60a738a565f498b858e903e42bc5ffc3cc1299"> <trans-unit datatype="html" id="ef60a738a565f498b858e903e42bc5ffc3cc1299">
@@ -718,7 +822,7 @@
<target>Dernière correspondance</target> <target>Dernière correspondance</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">22</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1234709746630139322"> <trans-unit datatype="html" id="1234709746630139322">
@@ -766,7 +870,7 @@
<target>Algorithme de rapprochement</target> <target>Algorithme de rapprochement</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">10</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="eab7fc7cf2d663e54de934b779fce4275a303f0f"> <trans-unit datatype="html" id="eab7fc7cf2d663e54de934b779fce4275a303f0f">
@@ -774,7 +878,7 @@
<target>Modèle de rapprochement</target> <target>Modèle de rapprochement</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">11</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="632e529f49cf3d367dfbd15bd055e9b53aef30fb"> <trans-unit datatype="html" id="632e529f49cf3d367dfbd15bd055e9b53aef30fb">
@@ -782,7 +886,7 @@
<target>Insensible à la casse</target> <target>Insensible à la casse</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9153094873118985366"> <trans-unit datatype="html" id="9153094873118985366">
@@ -1018,14 +1122,6 @@
<context context-type="linenumber">46</context> <context context-type="linenumber">46</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ddb40946e790522301687ecddb9ce1cb8ad40dd1">
<source>Filter by:</source>
<target>Filtrer par : </target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">4</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="02d184c288f567825a1fcbf83bcd3099a10853d5"> <trans-unit datatype="html" id="02d184c288f567825a1fcbf83bcd3099a10853d5">
<source>Filter tags</source> <source>Filter tags</source>
<target>Filtrer les étiquettes</target> <target>Filtrer les étiquettes</target>
@@ -1039,7 +1135,7 @@
<target>Filtrer les correspondants</target> <target>Filtrer les correspondants</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">19</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="0ad509732aaf702b7ea8c771c7809fa84bc85908"> <trans-unit datatype="html" id="0ad509732aaf702b7ea8c771c7809fa84bc85908">
@@ -1047,7 +1143,7 @@
<target>Filtrer les types de documents</target> <target>Filtrer les types de documents</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">25</context> <context context-type="linenumber">27</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="2d9d55f1b70142ff4597ba32179d16888fd9c6b2"> <trans-unit datatype="html" id="2d9d55f1b70142ff4597ba32179d16888fd9c6b2">
@@ -1055,7 +1151,7 @@
<target>Réinitialiser les filtres</target> <target>Réinitialiser les filtres</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">47</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7593728289020204896"> <trans-unit datatype="html" id="7593728289020204896">
@@ -1063,7 +1159,7 @@
<target>Non affecté</target> <target>Non affecté</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts</context> <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts</context>
<context context-type="linenumber">161</context> <context context-type="linenumber">166</context>
</context-group> </context-group>
<note from="description" priority="1">Filter drop down element to filter for documents with no correspondent/type/tag assigned</note> <note from="description" priority="1">Filter drop down element to filter for documents with no correspondent/type/tag assigned</note>
</trans-unit> </trans-unit>
@@ -1072,7 +1168,7 @@
<target>Appliquer</target> <target>Appliquer</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
<context context-type="linenumber">28</context> <context context-type="linenumber">26</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="4873149362496451858"> <trans-unit datatype="html" id="4873149362496451858">
@@ -1139,12 +1235,12 @@
<context context-type="linenumber">50</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1b29a8153575e5ad26cc7dd8bd75c4f45f6bfe7e"> <trans-unit datatype="html" id="849b42384616374df49bd8b3711ec159cb10b845">
<source>Created: <x equiv-text="{{document.created | date}}" id="INTERPOLATION"/></source> <source>Created: <x equiv-text="{{document.created | customDate}}" id="INTERPOLATION"/></source>
<target>Créé le : <x equiv-text="{{document.created | date}}" id="INTERPOLATION"/></target> <target>Créé le : <x equiv-text="{{document.created | customDate}}" id="INTERPOLATION"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
<context context-type="linenumber">65</context> <context context-type="linenumber">67</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="cd6f3fd48957e1fea6545c2b2defc7b2435ebfa8"> <trans-unit datatype="html" id="cd6f3fd48957e1fea6545c2b2defc7b2435ebfa8">
@@ -1168,7 +1264,7 @@
<target>Score :</target> <target>Score :</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
<context context-type="linenumber">61</context> <context context-type="linenumber">62</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="2840db547019ce8c76b2cdbe3a1653c5b68b06af"> <trans-unit datatype="html" id="2840db547019ce8c76b2cdbe3a1653c5b68b06af">
@@ -1355,7 +1451,7 @@
<target>Sélectionner :</target> <target>Sélectionner :</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">10</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="dfc3c34e182ea73c5d784ff7c8135f087992dac1"> <trans-unit datatype="html" id="dfc3c34e182ea73c5d784ff7c8135f087992dac1">
@@ -1363,7 +1459,7 @@
<target>Tout</target> <target>Tout</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">21</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="907df6a2b68daecc3c399cf40a764b358bd9fd84"> <trans-unit datatype="html" id="907df6a2b68daecc3c399cf40a764b358bd9fd84">
@@ -1371,7 +1467,7 @@
<target>Éditer :</target> <target>Éditer :</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">28</context> <context context-type="linenumber">27</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="27d158b47717ff9305d19866960418c603f19d55"> <trans-unit datatype="html" id="27d158b47717ff9305d19866960418c603f19d55">
@@ -1574,6 +1670,38 @@
<context context-type="linenumber">12</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1206520795340730278">
<source>English (US)</source>
<target>Anglais (US)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">74</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="1858110241312746425">
<source>German</source>
<target>Allemand</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">75</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="3071065188816255493">
<source>Dutch</source>
<target>Néerlandais</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">76</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="7633754075223722162">
<source>French</source>
<target>Français</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">77</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="1519954996184640001"> <trans-unit datatype="html" id="1519954996184640001">
<source>Error</source> <source>Error</source>
<target>Erreur</target> <target>Erreur</target>
@@ -1755,7 +1883,7 @@
<target>Créer un nouvel élément</target> <target>Créer un nouvel élément</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">43</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5324147361912094446"> <trans-unit datatype="html" id="5324147361912094446">
@@ -1763,7 +1891,7 @@
<target>Éditer l'élément</target> <target>Éditer l'élément</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">47</context> <context context-type="linenumber">54</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1699589597032579396"> <trans-unit datatype="html" id="1699589597032579396">
@@ -1771,7 +1899,7 @@
<target>Impossible d'enregistrer l'élément : <x equiv-text="error" id="PH"/></target> <target>Impossible d'enregistrer l'élément : <x equiv-text="error" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">51</context> <context context-type="linenumber">58</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="810888510148304696"> <trans-unit datatype="html" id="810888510148304696">
@@ -1779,7 +1907,7 @@
<target>Automatique</target> <target>Automatique</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5044611416737085530"> <trans-unit datatype="html" id="5044611416737085530">
@@ -1787,7 +1915,7 @@
<target>Voulez-vous vraiment supprimer cet élément ?</target> <target>Voulez-vous vraiment supprimer cet élément ?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">76</context> <context context-type="linenumber">97</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8371896857609524947"> <trans-unit datatype="html" id="8371896857609524947">
@@ -1795,7 +1923,7 @@
<target>Les documents associés ne seront pas supprimés.</target> <target>Les documents associés ne seront pas supprimés.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">83</context> <context context-type="linenumber">104</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7022070615528435141"> <trans-unit datatype="html" id="7022070615528435141">
@@ -1803,7 +1931,7 @@
<target>Supprimer</target> <target>Supprimer</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">85</context> <context context-type="linenumber">106</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5467489005440577210"> <trans-unit datatype="html" id="5467489005440577210">
@@ -1811,7 +1939,7 @@
<target>Une erreur s'est produite lors de la suppression de l'élément : <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> <target>Une erreur s'est produite lors de la suppression de l'élément : <x equiv-text="JSON.stringify(error.error)" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">114</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5851669019930456395"> <trans-unit datatype="html" id="5851669019930456395">

View File

@@ -11,7 +11,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="2155249406916744630"> <trans-unit datatype="html" id="2155249406916744630">
<source>View &quot;<x equiv-text="this.list.savedView.name" id="PH"/>&quot; saved successfully.</source> <source>View &quot;<x equiv-text="this.list.savedView.name" id="PH"/>&quot; saved successfully.</source>
<target>View &amp;quot;<x equiv-text="this.list.savedView.name" id="PH"/>&amp;quot; met succes opgeslagen.</target> <target>View &quot;<x equiv-text="this.list.savedView.name" id="PH"/>&quot; met succes opgeslagen.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context>
<context context-type="linenumber">94</context> <context context-type="linenumber">94</context>
@@ -19,7 +19,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="6837554170707123455"> <trans-unit datatype="html" id="6837554170707123455">
<source>View &quot;<x equiv-text="savedView.name" id="PH"/>&quot; created successfully.</source> <source>View &quot;<x equiv-text="savedView.name" id="PH"/>&quot; created successfully.</source>
<target>View &amp;quot;<x equiv-text="savedView.name" id="PH"/>&amp;quot; met succes gemaakt.</target> <target>View &quot;<x equiv-text="savedView.name" id="PH"/>&quot; met succes gemaakt.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context>
<context context-type="linenumber">115</context> <context context-type="linenumber">115</context>
@@ -38,7 +38,7 @@
<target>Niets selecteren</target> <target>Niets selecteren</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">10</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="2ed8a0c2ce4968f8614151eefed20a0aa3daeeb9"> <trans-unit datatype="html" id="2ed8a0c2ce4968f8614151eefed20a0aa3daeeb9">
@@ -46,7 +46,7 @@
<target>Selecteer pagina</target> <target>Selecteer pagina</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">11</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="b463541a7e303aa4d0b1102eaff8afbaf34e7a74"> <trans-unit datatype="html" id="b463541a7e303aa4d0b1102eaff8afbaf34e7a74">
@@ -54,15 +54,15 @@
<target>Alles selecteren</target> <target>Alles selecteren</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ec97f67072a83aaa972536b18d83179f6e4bbec9"> <trans-unit datatype="html" id="5d43539fc358c3a548b9d487be821db73e2702ff">
<source>Sort by</source> <source>Sort</source>
<target>Sorteer op</target> <target>Sorteren</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">41</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="b7641aed03492978b4ec6843b1e53f30464294d9"> <trans-unit datatype="html" id="b7641aed03492978b4ec6843b1e53f30464294d9">
@@ -83,7 +83,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="72e7d343f9165602cce1ca7faffbc565fd31ef92"> <trans-unit datatype="html" id="72e7d343f9165602cce1ca7faffbc565fd31ef92">
<source>Save &quot;<x equiv-text="{{list.savedViewTitle}}" id="INTERPOLATION"/>&quot;</source> <source>Save &quot;<x equiv-text="{{list.savedViewTitle}}" id="INTERPOLATION"/>&quot;</source>
<target>Opslaan &amp;quot;<x equiv-text="{{list.savedViewTitle}}" id="INTERPOLATION"/>&amp;quot;</target> <target>Opslaan &quot;<x equiv-text="{{list.savedViewTitle}}" id="INTERPOLATION"/>&quot;</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">71</context> <context context-type="linenumber">71</context>
@@ -94,7 +94,7 @@
<target>{VAR_PLURAL, plural, =1 {<x id="INTERPOLATION"/> van één document geselecteerd} other {<x id="INTERPOLATION"/> van <x id="INTERPOLATION_1"/> documenten geselecteerd}}</target> <target>{VAR_PLURAL, plural, =1 {<x id="INTERPOLATION"/> van één document geselecteerd} other {<x id="INTERPOLATION"/> van <x id="INTERPOLATION_1"/> documenten geselecteerd}}</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">87</context> <context context-type="linenumber">85</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="bb773fdeaad5e7fb8e6cd77e1cc558e1b194a0c9"> <trans-unit datatype="html" id="bb773fdeaad5e7fb8e6cd77e1cc558e1b194a0c9">
@@ -102,7 +102,7 @@
<target>{VAR_PLURAL, plural, =1 {Eén document} other {<x id="INTERPOLATION"/> documenten}}</target> <target>{VAR_PLURAL, plural, =1 {Eén document} other {<x id="INTERPOLATION"/> documenten}}</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">88</context> <context context-type="linenumber">86</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="bb91083b44e3f77dd68de773ceab467ca3d57507"> <trans-unit datatype="html" id="bb91083b44e3f77dd68de773ceab467ca3d57507">
@@ -110,7 +110,7 @@
<target>(gefilterd)</target> <target>(gefilterd)</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">88</context> <context context-type="linenumber">86</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ca0b795795658155d44ddca02e95f1feeeb4a88f"> <trans-unit datatype="html" id="ca0b795795658155d44ddca02e95f1feeeb4a88f">
@@ -118,7 +118,7 @@
<target>ASN</target> <target>ASN</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">107</context> <context context-type="linenumber">105</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7b5c6286aaded63fb279d6deb8aa8c704e085ced"> <trans-unit datatype="html" id="7b5c6286aaded63fb279d6deb8aa8c704e085ced">
@@ -126,7 +126,7 @@
<target>Correspondent</target> <target>Correspondent</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">113</context> <context context-type="linenumber">111</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="fdf7cbdc140d0aab0f0b6c06065a0fd448ed6a2e"> <trans-unit datatype="html" id="fdf7cbdc140d0aab0f0b6c06065a0fd448ed6a2e">
@@ -134,7 +134,7 @@
<target>Titel</target> <target>Titel</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">119</context> <context context-type="linenumber">117</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="2bd5919e8098513664a89d5b7b52d61e3063950f"> <trans-unit datatype="html" id="2bd5919e8098513664a89d5b7b52d61e3063950f">
@@ -142,7 +142,7 @@
<target>Documenttype</target> <target>Documenttype</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">125</context> <context context-type="linenumber">123</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1b051734b0ee9021991c91b3ed4e81c244322462"> <trans-unit datatype="html" id="1b051734b0ee9021991c91b3ed4e81c244322462">
@@ -150,7 +150,7 @@
<target>Aangemaakt</target> <target>Aangemaakt</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">131</context> <context context-type="linenumber">129</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="80e3b490720757978c99a7b5af3885faf202b955"> <trans-unit datatype="html" id="80e3b490720757978c99a7b5af3885faf202b955">
@@ -158,7 +158,7 @@
<target>Toegevoegd</target> <target>Toegevoegd</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">137</context> <context context-type="linenumber">135</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9021887951960049161"> <trans-unit datatype="html" id="9021887951960049161">
@@ -166,15 +166,15 @@
<target>Bevestig het verwijderen</target> <target>Bevestig het verwijderen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">186</context> <context context-type="linenumber">192</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5382975254277698192"> <trans-unit datatype="html" id="5382975254277698192">
<source>Do you really want to delete document &quot;<x equiv-text="this.document.title" id="PH"/>&quot;?</source> <source>Do you really want to delete document &quot;<x equiv-text="this.document.title" id="PH"/>&quot;?</source>
<target>Wilt u het document echt verwijderen &amp;quot;<x equiv-text="this.document.title" id="PH"/>&amp;quot;?</target> <target>Wilt u het document echt verwijderen &quot;<x equiv-text="this.document.title" id="PH"/>&quot;?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">187</context> <context context-type="linenumber">193</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="6691075929777935948"> <trans-unit datatype="html" id="6691075929777935948">
@@ -182,7 +182,7 @@
<target>De bestanden voor dit document worden definitief verwijderd. Deze bewerking kan niet ongedaan worden gemaakt.</target> <target>De bestanden voor dit document worden definitief verwijderd. Deze bewerking kan niet ongedaan worden gemaakt.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">188</context> <context context-type="linenumber">194</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="719892092227206532"> <trans-unit datatype="html" id="719892092227206532">
@@ -190,7 +190,7 @@
<target>Verwijder document</target> <target>Verwijder document</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">190</context> <context context-type="linenumber">196</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1844801255494293730"> <trans-unit datatype="html" id="1844801255494293730">
@@ -198,7 +198,7 @@
<target>Fout bij het verwijderen van het document: <x equiv-text="JSON.stringify(error)" id="PH"/></target> <target>Fout bij het verwijderen van het document: <x equiv-text="JSON.stringify(error)" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
<context context-type="linenumber">197</context> <context context-type="linenumber">203</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="826b25211922a1b46436589233cb6f1a163d89b7"> <trans-unit datatype="html" id="826b25211922a1b46436589233cb6f1a163d89b7">
@@ -427,7 +427,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="93754014749412887"> <trans-unit datatype="html" id="93754014749412887">
<source>Do you really want to delete the tag &quot;<x equiv-text="object.name" id="PH"/>&quot;?</source> <source>Do you really want to delete the tag &quot;<x equiv-text="object.name" id="PH"/>&quot;?</source>
<target>Wil je het etiket echt verwijderen &amp;quot;<x equiv-text="object.name" id="PH"/>&amp;quot;?</target> <target>Wil je het etiket echt verwijderen &quot;<x equiv-text="object.name" id="PH"/>&quot;?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.ts</context>
<context context-type="linenumber">30</context> <context context-type="linenumber">30</context>
@@ -449,12 +449,20 @@
<context context-type="linenumber">2</context> <context context-type="linenumber">2</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ddb40946e790522301687ecddb9ce1cb8ad40dd1">
<source>Filter by:</source>
<target>Filter op:</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">8</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="cff1428d10d59d14e45edec3c735a27b5482db59"> <trans-unit datatype="html" id="cff1428d10d59d14e45edec3c735a27b5482db59">
<source>Name</source> <source>Name</source>
<target>Naam</target> <target>Naam</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">9</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8fa4d523f7b91df4390120b85ed0406138273e1a"> <trans-unit datatype="html" id="8fa4d523f7b91df4390120b85ed0406138273e1a">
@@ -462,7 +470,7 @@
<target>Kleur</target> <target>Kleur</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">14</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="d0c4488f742efeba0915e90e285a022da813deff"> <trans-unit datatype="html" id="d0c4488f742efeba0915e90e285a022da813deff">
@@ -470,7 +478,7 @@
<target>Overeenkomend</target> <target>Overeenkomend</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">21</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9bcf8d20d23c111eca1431abd2d2ce0de324499c"> <trans-unit datatype="html" id="9bcf8d20d23c111eca1431abd2d2ce0de324499c">
@@ -478,7 +486,7 @@
<target>Aantal documenten</target> <target>Aantal documenten</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">22</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="030b4423b92167200e39519599f9b863b4f7c62c"> <trans-unit datatype="html" id="030b4423b92167200e39519599f9b863b4f7c62c">
@@ -486,7 +494,7 @@
<target>Acties</target> <target>Acties</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">23</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9d51b3c90afda70700229d1b8a55371c13cb3bce"> <trans-unit datatype="html" id="9d51b3c90afda70700229d1b8a55371c13cb3bce">
@@ -494,7 +502,7 @@
<target>Documenten</target> <target>Documenten</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">32</context> <context context-type="linenumber">38</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="28f86ffd419b869711aa13f5e5ff54be6d70731c"> <trans-unit datatype="html" id="28f86ffd419b869711aa13f5e5ff54be6d70731c">
@@ -502,12 +510,12 @@
<target>Bewerk</target> <target>Bewerk</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/tag-list/tag-list.component.html</context>
<context context-type="linenumber">37</context> <context context-type="linenumber">43</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="4990731724078522539"> <trans-unit datatype="html" id="4990731724078522539">
<source>Do you really want to delete the document type &quot;<x equiv-text="object.name" id="PH"/>&quot;?</source> <source>Do you really want to delete the document type &quot;<x equiv-text="object.name" id="PH"/>&quot;?</source>
<target>Wilt u het documenttype echt verwijderen &amp;quot;<x equiv-text="object.name" id="PH"/>&amp;quot;?</target> <target>Wilt u het documenttype echt verwijderen &quot;<x equiv-text="object.name" id="PH"/>&quot;?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/document-type-list/document-type-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/document-type-list/document-type-list.component.ts</context>
<context context-type="linenumber">26</context> <context context-type="linenumber">26</context>
@@ -539,10 +547,10 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5610279464668232148"> <trans-unit datatype="html" id="5610279464668232148">
<source>Saved view &quot;<x equiv-text="savedView.name" id="PH"/>&quot; deleted.</source> <source>Saved view &quot;<x equiv-text="savedView.name" id="PH"/>&quot; deleted.</source>
<target>Opgeslagen view &amp;quot;<x equiv-text="savedView.name" id="PH"/>&amp;quot; verwijderd.</target> <target>Opgeslagen view &quot;<x equiv-text="savedView.name" id="PH"/>&quot; verwijderd.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">54</context> <context context-type="linenumber">63</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5647210819299459618"> <trans-unit datatype="html" id="5647210819299459618">
@@ -550,7 +558,23 @@
<target>Instellingen succesvol opgeslagen.</target> <target>Instellingen succesvol opgeslagen.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">74</context> <context context-type="linenumber">79</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="6839066544204061364">
<source>Use system language</source>
<target>Gebruik de systeemtaal</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">83</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="7729897675462249787">
<source>Use date format of display language</source>
<target>Datumopmaak van weergavetaal gebruiken</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8488620293789898901"> <trans-unit datatype="html" id="8488620293789898901">
@@ -558,7 +582,7 @@
<target>Fout bij het opslaan van de instellingen: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> <target>Fout bij het opslaan van de instellingen: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">86</context> <context context-type="linenumber">103</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716"> <trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716">
@@ -582,7 +606,7 @@
<target>Opgeslagen views</target> <target>Opgeslagen views</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">56</context> <context context-type="linenumber">114</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="bbe41ac2ea4a6c00ea941a41b33105048f8e9f13"> <trans-unit datatype="html" id="bbe41ac2ea4a6c00ea941a41b33105048f8e9f13">
@@ -593,12 +617,92 @@
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="75f8908d266f7cc9b9e68e0be906fd080a223606">
<source>Display language</source>
<target>Taal</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="1284a077dc18a2d1ff1b744f16f1797eea28ae37">
<source>You need to reload the page after applying a new language.</source>
<target>De pagina moet herladen worden nadat een andere taal werd gekozen.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">25</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="0cd55822928764cc82a62ee3e6f3adbc1c630479">
<source>Date display</source>
<target>Datumweergave</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="7df4de0d0704a06a302d853e31f2580eba98f127">
<source>Date format</source>
<target>Datumopmaak</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">45</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="69852399a18b8ca4fca8c5bfddd3f00a6d137593">
<source>Short: <x equiv-text="{{today | customDate:'shortDate':null:computedDateLocale}}" id="INTERPOLATION"/></source>
<target>Kort: <x equiv-text="{{today | customDate:'shortDate':null:computedDateLocale}}" id="INTERPOLATION"/></target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="d01a59285e711252b98c4f193394e4b854615c78">
<source>Medium: <x equiv-text="{{today | customDate:'mediumDate':null:computedDateLocale}}" id="INTERPOLATION"/></source>
<target>Medium: <x equiv-text="{{today | customDate:'mediumDate':null:computedDateLocale}}" id="INTERPOLATION"/></target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="00481629776699b1caebd12b3b1176e2e23740a8">
<source>Long: <x equiv-text="{{today | customDate:'longDate':null:computedDateLocale}}" id="INTERPOLATION"/></source>
<target>Lang: <x equiv-text="{{today | customDate:'longDate':null:computedDateLocale}}" id="INTERPOLATION"/></target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">59</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="2045151788cbdda7512752e408da59a6b54a8ef0"> <trans-unit datatype="html" id="2045151788cbdda7512752e408da59a6b54a8ef0">
<source>Items per page</source> <source>Items per page</source>
<target>Resultaten per pagina</target> <target>Resultaten per pagina</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">67</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="c4435e56bf0289e78fedc462f1d21fb30b9de55d">
<source>Document editor</source>
<target>Documentbewerker</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">83</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="4903e521c9bfd11ce88e7a5575106ef638912e0d">
<source>Use PDF viewer provided by the browser</source>
<target>Gebruik de PDF lezer ingebouwd in uw browser</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">87</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="d7db07023e53f8396d18d375c2b78c25fc81c197">
<source>This is usually faster for displaying large PDF documents, but it might not work on some browsers.</source>
<target>Dit is gewoonlijk sneller om grote PDF's te tonen, maar werkt niet bij elke browser.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">87</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9ee5d1cbfd6ee168dae37aaba2b59b50bcabb2ff"> <trans-unit datatype="html" id="9ee5d1cbfd6ee168dae37aaba2b59b50bcabb2ff">
@@ -606,7 +710,7 @@
<target>Nachtmodus</target> <target>Nachtmodus</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">94</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="f8cb5506e70fd71fddc9bb71cee18bfff7b29637"> <trans-unit datatype="html" id="f8cb5506e70fd71fddc9bb71cee18bfff7b29637">
@@ -614,39 +718,7 @@
<target>Gebruik systeeminstellingen</target> <target>Gebruik systeeminstellingen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">36</context> <context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="3863a86cd9e69a61d143d3daf51df44203df4a82">
<source>Bulk editing</source>
<target>Massabewerking</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="c0ac61661c6c326d6e0e00c231b95cf2ac0c6586">
<source>Show confirmation dialogs</source>
<target>Toon dialoogvenster ter bevestiging</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">48</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="291bbe56ecbe945dcf05580a57d679fa7bd1e06a">
<source>Deleting documents will always ask for confirmation.</source>
<target>Er zal altijd om bevestiging gevraagd worden voor het verwijderen van documenten.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">48</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="8cfddc13e04f5545ac63f419ef363505d6f78c2e">
<source>Apply on close</source>
<target>Toepassen bij het sluiten</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">49</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8ee474504043fa89821d626e4f3413240fa91b53"> <trans-unit datatype="html" id="8ee474504043fa89821d626e4f3413240fa91b53">
@@ -654,7 +726,39 @@
<target>Gebruik nachtmodus</target> <target>Gebruik nachtmodus</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">39</context> <context context-type="linenumber">98</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="3863a86cd9e69a61d143d3daf51df44203df4a82">
<source>Bulk editing</source>
<target>Massabewerking</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">102</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="c0ac61661c6c326d6e0e00c231b95cf2ac0c6586">
<source>Show confirmation dialogs</source>
<target>Toon dialoogvenster ter bevestiging</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">106</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="291bbe56ecbe945dcf05580a57d679fa7bd1e06a">
<source>Deleting documents will always ask for confirmation.</source>
<target>Er zal altijd om bevestiging gevraagd worden voor het verwijderen van documenten.</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">106</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="8cfddc13e04f5545ac63f419ef363505d6f78c2e">
<source>Apply on close</source>
<target>Toepassen bij het sluiten</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">107</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8cb90334f5dfd7fc67205085f59381e2a334ccfc"> <trans-unit datatype="html" id="8cb90334f5dfd7fc67205085f59381e2a334ccfc">
@@ -662,7 +766,7 @@
<target>Komt voor bij</target> <target>Komt voor bij</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">68</context> <context context-type="linenumber">126</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="6717cf1acf04728fc2b7c39f6d3297f8ff15fde5"> <trans-unit datatype="html" id="6717cf1acf04728fc2b7c39f6d3297f8ff15fde5">
@@ -670,7 +774,7 @@
<target>Toon op het dashboard</target> <target>Toon op het dashboard</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">71</context> <context context-type="linenumber">129</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="541bfc5b123b3f8867fd681eaceefb663a811973"> <trans-unit datatype="html" id="541bfc5b123b3f8867fd681eaceefb663a811973">
@@ -678,7 +782,7 @@
<target>Toon in de zijbalk</target> <target>Toon in de zijbalk</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">75</context> <context context-type="linenumber">133</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="abba764a7a595d04dc8c3b26e04b3780d4fdb540"> <trans-unit datatype="html" id="abba764a7a595d04dc8c3b26e04b3780d4fdb540">
@@ -686,7 +790,7 @@
<target>Geen opgeslagen views gedefinieerd.</target> <target>Geen opgeslagen views gedefinieerd.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">85</context> <context context-type="linenumber">143</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ef60a738a565f498b858e903e42bc5ffc3cc1299"> <trans-unit datatype="html" id="ef60a738a565f498b858e903e42bc5ffc3cc1299">
@@ -699,7 +803,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7427874343955308724"> <trans-unit datatype="html" id="7427874343955308724">
<source>Do you really want to delete the correspondent &quot;<x equiv-text="object.name" id="PH"/>&quot;?</source> <source>Do you really want to delete the correspondent &quot;<x equiv-text="object.name" id="PH"/>&quot;?</source>
<target>Bent u zeker dat u correspondent &amp;quot;<x equiv-text="object.name" id="PH"/>&amp;quot; wilt verwijderen?</target> <target>Bent u zeker dat u correspondent &quot;<x equiv-text="object.name" id="PH"/>&quot; wilt verwijderen?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.ts</context>
<context context-type="linenumber">26</context> <context context-type="linenumber">26</context>
@@ -718,7 +822,7 @@
<target>Laatste correspondentie</target> <target>Laatste correspondentie</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-list.component.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">22</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1234709746630139322"> <trans-unit datatype="html" id="1234709746630139322">
@@ -766,7 +870,7 @@
<target>Algoritme voor het bepalen van de overeenkomst</target> <target>Algoritme voor het bepalen van de overeenkomst</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">10</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="eab7fc7cf2d663e54de934b779fce4275a303f0f"> <trans-unit datatype="html" id="eab7fc7cf2d663e54de934b779fce4275a303f0f">
@@ -774,7 +878,7 @@
<target>Patroon voor overeenkomst</target> <target>Patroon voor overeenkomst</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">11</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="632e529f49cf3d367dfbd15bd055e9b53aef30fb"> <trans-unit datatype="html" id="632e529f49cf3d367dfbd15bd055e9b53aef30fb">
@@ -782,7 +886,7 @@
<target>Niet hoofdlettergevoelig</target> <target>Niet hoofdlettergevoelig</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> <context context-type="sourcefile">src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="9153094873118985366"> <trans-unit datatype="html" id="9153094873118985366">
@@ -867,7 +971,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="afa760e48c97d64d19c1455d18b7834a2256e23f"> <trans-unit datatype="html" id="afa760e48c97d64d19c1455d18b7834a2256e23f">
<source>Did you mean &quot;<x equiv-text="&lt;a [routerLink]=&quot;&quot; (click)=&quot;searchCorrectedQuery()&quot;&gt;{{correctedQuery}}" id="START_LINK"/><x equiv-text="{{correctedQuery}}&lt;/a&gt;" id="INTERPOLATION"/><x equiv-text="&lt;/a&gt;" id="CLOSE_LINK"/>&quot;?</source> <source>Did you mean &quot;<x equiv-text="&lt;a [routerLink]=&quot;&quot; (click)=&quot;searchCorrectedQuery()&quot;&gt;{{correctedQuery}}" id="START_LINK"/><x equiv-text="{{correctedQuery}}&lt;/a&gt;" id="INTERPOLATION"/><x equiv-text="&lt;/a&gt;" id="CLOSE_LINK"/>&quot;?</source>
<target>Bedoelde u &amp;quot;<x equiv-text="&lt;a [routerLink]=&quot;&quot; (click)=&quot;searchCorrectedQuery()&quot;&gt;{{correctedQuery}}" id="START_LINK"/><x equiv-text="{{correctedQuery}}&lt;/a&gt;" id="INTERPOLATION"/><x equiv-text="&lt;/a&gt;" id="CLOSE_LINK"/>&amp;quot;?</target> <target>Bedoelde u &quot;<x equiv-text="&lt;a [routerLink]=&quot;&quot; (click)=&quot;searchCorrectedQuery()&quot;&gt;{{correctedQuery}}" id="START_LINK"/><x equiv-text="{{correctedQuery}}&lt;/a&gt;" id="INTERPOLATION"/><x equiv-text="&lt;/a&gt;" id="CLOSE_LINK"/>&quot;?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/search/search.component.html</context> <context context-type="sourcefile">src/app/components/search/search.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
@@ -1018,14 +1122,6 @@
<context context-type="linenumber">46</context> <context context-type="linenumber">46</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="ddb40946e790522301687ecddb9ce1cb8ad40dd1">
<source>Filter by:</source>
<target>Filter op:</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">4</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="02d184c288f567825a1fcbf83bcd3099a10853d5"> <trans-unit datatype="html" id="02d184c288f567825a1fcbf83bcd3099a10853d5">
<source>Filter tags</source> <source>Filter tags</source>
<target>Etiketten filteren</target> <target>Etiketten filteren</target>
@@ -1039,7 +1135,7 @@
<target>Correspondenten filteren</target> <target>Correspondenten filteren</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">19</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="0ad509732aaf702b7ea8c771c7809fa84bc85908"> <trans-unit datatype="html" id="0ad509732aaf702b7ea8c771c7809fa84bc85908">
@@ -1047,7 +1143,7 @@
<target>Documenttypes filteren</target> <target>Documenttypes filteren</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">25</context> <context context-type="linenumber">27</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="2d9d55f1b70142ff4597ba32179d16888fd9c6b2"> <trans-unit datatype="html" id="2d9d55f1b70142ff4597ba32179d16888fd9c6b2">
@@ -1055,7 +1151,7 @@
<target>Filters terug zetten</target> <target>Filters terug zetten</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">47</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7593728289020204896"> <trans-unit datatype="html" id="7593728289020204896">
@@ -1063,7 +1159,7 @@
<target>Niet toegekend</target> <target>Niet toegekend</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts</context> <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts</context>
<context context-type="linenumber">161</context> <context context-type="linenumber">166</context>
</context-group> </context-group>
<note from="description" priority="1">Filter drop down element to filter for documents with no correspondent/type/tag assigned</note> <note from="description" priority="1">Filter drop down element to filter for documents with no correspondent/type/tag assigned</note>
</trans-unit> </trans-unit>
@@ -1072,7 +1168,7 @@
<target>Toepassen</target> <target>Toepassen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context> <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
<context context-type="linenumber">28</context> <context context-type="linenumber">26</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="4873149362496451858"> <trans-unit datatype="html" id="4873149362496451858">
@@ -1139,12 +1235,12 @@
<context context-type="linenumber">50</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1b29a8153575e5ad26cc7dd8bd75c4f45f6bfe7e"> <trans-unit datatype="html" id="849b42384616374df49bd8b3711ec159cb10b845">
<source>Created: <x equiv-text="{{document.created | date}}" id="INTERPOLATION"/></source> <source>Created: <x equiv-text="{{document.created | customDate}}" id="INTERPOLATION"/></source>
<target>Aangemaakt op: <x equiv-text="{{document.created | date}}" id="INTERPOLATION"/></target> <target>Aangemaakt op: <x equiv-text="{{document.created | customDate}}" id="INTERPOLATION"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
<context context-type="linenumber">65</context> <context context-type="linenumber">67</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="cd6f3fd48957e1fea6545c2b2defc7b2435ebfa8"> <trans-unit datatype="html" id="cd6f3fd48957e1fea6545c2b2defc7b2435ebfa8">
@@ -1168,7 +1264,7 @@
<target>Score:</target> <target>Score:</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context> <context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
<context context-type="linenumber">61</context> <context context-type="linenumber">62</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="2840db547019ce8c76b2cdbe3a1653c5b68b06af"> <trans-unit datatype="html" id="2840db547019ce8c76b2cdbe3a1653c5b68b06af">
@@ -1189,7 +1285,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8639884465898458690"> <trans-unit datatype="html" id="8639884465898458690">
<source>&quot;<x equiv-text="items[0].name" id="PH"/>&quot; and &quot;<x equiv-text="items[1].name" id="PH_1"/>&quot;</source> <source>&quot;<x equiv-text="items[0].name" id="PH"/>&quot; and &quot;<x equiv-text="items[1].name" id="PH_1"/>&quot;</source>
<target>&amp;quot;<x equiv-text="items[0].name" id="PH"/>&amp;quot; en &amp;quot;<x equiv-text="items[1].name" id="PH_1"/>&amp;quot;</target> <target>&quot;<x equiv-text="items[0].name" id="PH"/>&quot; en &quot;<x equiv-text="items[1].name" id="PH_1"/>&quot;</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">114</context> <context context-type="linenumber">114</context>
@@ -1198,7 +1294,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7894972847287473517"> <trans-unit datatype="html" id="7894972847287473517">
<source>&quot;<x equiv-text="i.name" id="PH"/>&quot;</source> <source>&quot;<x equiv-text="i.name" id="PH"/>&quot;</source>
<target>&amp;quot;<x equiv-text="i.name" id="PH"/>&amp;quot;</target> <target>&quot;<x equiv-text="i.name" id="PH"/>&quot;</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">116</context> <context context-type="linenumber">116</context>
@@ -1215,7 +1311,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1822679894391095557"> <trans-unit datatype="html" id="1822679894391095557">
<source><x equiv-text="list" id="PH"/> and &quot;<x equiv-text="items[items.length - 1].name" id="PH_1"/>&quot;</source> <source><x equiv-text="list" id="PH"/> and &quot;<x equiv-text="items[items.length - 1].name" id="PH_1"/>&quot;</source>
<target><x equiv-text="list" id="PH"/> en &amp;quot;<x equiv-text="items[items.length - 1].name" id="PH_1"/>&amp;quot;</target> <target><x equiv-text="list" id="PH"/> en &quot;<x equiv-text="items[items.length - 1].name" id="PH_1"/>&quot;</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">117</context> <context context-type="linenumber">117</context>
@@ -1232,7 +1328,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="6619516195038467207"> <trans-unit datatype="html" id="6619516195038467207">
<source>This operation will add the tag &quot;<x equiv-text="tag.name" id="PH"/>&quot; to <x equiv-text="this.list.selected.size" id="PH_1"/> selected document(s).</source> <source>This operation will add the tag &quot;<x equiv-text="tag.name" id="PH"/>&quot; to <x equiv-text="this.list.selected.size" id="PH_1"/> selected document(s).</source>
<target>Het etiket &amp;quot;<x equiv-text="tag.name" id="PH"/>&amp;quot; zal aan <x equiv-text="this.list.selected.size" id="PH_1"/> geselecteerd(e) document(en) worden toegewezen.</target> <target>Het etiket &quot;<x equiv-text="tag.name" id="PH"/>&quot; zal aan <x equiv-text="this.list.selected.size" id="PH_1"/> geselecteerd(e) document(en) worden toegewezen.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">129</context> <context context-type="linenumber">129</context>
@@ -1248,7 +1344,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7181166515756808573"> <trans-unit datatype="html" id="7181166515756808573">
<source>This operation will remove the tag &quot;<x equiv-text="tag.name" id="PH"/>&quot; from <x equiv-text="this.list.selected.size" id="PH_1"/> selected document(s).</source> <source>This operation will remove the tag &quot;<x equiv-text="tag.name" id="PH"/>&quot; from <x equiv-text="this.list.selected.size" id="PH_1"/> selected document(s).</source>
<target>Het etiket &amp;quot;<x equiv-text="tag.name" id="PH"/>&amp;quot; zal verwijderd worden van <x equiv-text="this.list.selected.size" id="PH_1"/> geselecteerd(e) document(en).</target> <target>Het etiket &quot;<x equiv-text="tag.name" id="PH"/>&quot; zal verwijderd worden van <x equiv-text="this.list.selected.size" id="PH_1"/> geselecteerd(e) document(en).</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">134</context> <context context-type="linenumber">134</context>
@@ -1280,7 +1376,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="6900893559485781849"> <trans-unit datatype="html" id="6900893559485781849">
<source>This operation will assign the correspondent &quot;<x equiv-text="correspondent.name" id="PH"/>&quot; to <x equiv-text="this.list.selected.size" id="PH_1"/> selected document(s).</source> <source>This operation will assign the correspondent &quot;<x equiv-text="correspondent.name" id="PH"/>&quot; to <x equiv-text="this.list.selected.size" id="PH_1"/> selected document(s).</source>
<target>De correspondent &amp;quot;<x equiv-text="correspondent.name" id="PH"/>&amp;quot; zal aan <x equiv-text="this.list.selected.size" id="PH_1"/> geselecteerd(e) document(en) worden toegewezen.</target> <target>De correspondent &quot;<x equiv-text="correspondent.name" id="PH"/>&quot; zal aan <x equiv-text="this.list.selected.size" id="PH_1"/> geselecteerd(e) document(en) worden toegewezen.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">160</context> <context context-type="linenumber">160</context>
@@ -1304,7 +1400,7 @@
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="332180123895325027"> <trans-unit datatype="html" id="332180123895325027">
<source>This operation will assign the document type &quot;<x equiv-text="documentType.name" id="PH"/>&quot; to <x equiv-text="this.list.selected.size" id="PH_1"/> selected document(s).</source> <source>This operation will assign the document type &quot;<x equiv-text="documentType.name" id="PH"/>&quot; to <x equiv-text="this.list.selected.size" id="PH_1"/> selected document(s).</source>
<target>Het documenttype &amp;quot;<x equiv-text="documentType.name" id="PH"/>&amp;quot; zal aan <x equiv-text="this.list.selected.size" id="PH_1"/> geselecteerd(e) document(en) worden toegewezen.</target> <target>Het documenttype &quot;<x equiv-text="documentType.name" id="PH"/>&quot; zal aan <x equiv-text="this.list.selected.size" id="PH_1"/> geselecteerd(e) document(en) worden toegewezen.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">183</context> <context context-type="linenumber">183</context>
@@ -1355,7 +1451,7 @@
<target>Selecteer:</target> <target>Selecteer:</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">10</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="dfc3c34e182ea73c5d784ff7c8135f087992dac1"> <trans-unit datatype="html" id="dfc3c34e182ea73c5d784ff7c8135f087992dac1">
@@ -1363,7 +1459,7 @@
<target>Alles</target> <target>Alles</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">21</context> <context context-type="linenumber">20</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="907df6a2b68daecc3c399cf40a764b358bd9fd84"> <trans-unit datatype="html" id="907df6a2b68daecc3c399cf40a764b358bd9fd84">
@@ -1371,7 +1467,7 @@
<target>Bewerk:</target> <target>Bewerk:</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">28</context> <context context-type="linenumber">27</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="27d158b47717ff9305d19866960418c603f19d55"> <trans-unit datatype="html" id="27d158b47717ff9305d19866960418c603f19d55">
@@ -1574,6 +1670,38 @@
<context context-type="linenumber">12</context> <context context-type="linenumber">12</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1206520795340730278">
<source>English (US)</source>
<target>Engels (US)</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">74</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="1858110241312746425">
<source>German</source>
<target>Duits</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">75</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="3071065188816255493">
<source>Dutch</source>
<target>Nederlands</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">76</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="7633754075223722162">
<source>French</source>
<target>Frans</target>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">77</context>
</context-group>
</trans-unit>
<trans-unit datatype="html" id="1519954996184640001"> <trans-unit datatype="html" id="1519954996184640001">
<source>Error</source> <source>Error</source>
<target>Fout</target> <target>Fout</target>
@@ -1755,7 +1883,7 @@
<target>Maak nieuw item</target> <target>Maak nieuw item</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">43</context> <context context-type="linenumber">50</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5324147361912094446"> <trans-unit datatype="html" id="5324147361912094446">
@@ -1763,7 +1891,7 @@
<target>Item bewerken</target> <target>Item bewerken</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">47</context> <context context-type="linenumber">54</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="1699589597032579396"> <trans-unit datatype="html" id="1699589597032579396">
@@ -1771,7 +1899,7 @@
<target>Kon het element niet opslaan: <x equiv-text="error" id="PH"/></target> <target>Kon het element niet opslaan: <x equiv-text="error" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context>
<context context-type="linenumber">51</context> <context context-type="linenumber">58</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="810888510148304696"> <trans-unit datatype="html" id="810888510148304696">
@@ -1779,7 +1907,7 @@
<target>Automatisch</target> <target>Automatisch</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">39</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5044611416737085530"> <trans-unit datatype="html" id="5044611416737085530">
@@ -1787,7 +1915,7 @@
<target>Wil je dit element echt verwijderen?</target> <target>Wil je dit element echt verwijderen?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">76</context> <context context-type="linenumber">97</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="8371896857609524947"> <trans-unit datatype="html" id="8371896857609524947">
@@ -1795,7 +1923,7 @@
<target>Geassocieerde documenten zullen niet verwijderd worden.</target> <target>Geassocieerde documenten zullen niet verwijderd worden.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">83</context> <context context-type="linenumber">104</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="7022070615528435141"> <trans-unit datatype="html" id="7022070615528435141">
@@ -1803,7 +1931,7 @@
<target>Verwijderen</target> <target>Verwijderen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">85</context> <context context-type="linenumber">106</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5467489005440577210"> <trans-unit datatype="html" id="5467489005440577210">
@@ -1811,7 +1939,7 @@
<target>Fout bij het verwijderen van het element: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> <target>Fout bij het verwijderen van het element: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context> <context context-type="sourcefile">src/app/components/manage/generic-list/generic-list.component.ts</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">114</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit datatype="html" id="5851669019930456395"> <trans-unit datatype="html" id="5851669019930456395">

View File

@@ -91,7 +91,7 @@ def generate_unique_filename(doc, root):
return new_filename return new_filename
def generate_filename(doc, counter=0): def generate_filename(doc, counter=0, append_gpg=True):
path = "" path = ""
try: try:
@@ -151,7 +151,7 @@ def generate_filename(doc, counter=0):
filename = f"{doc.pk:07}{counter_str}{doc.file_type}" filename = f"{doc.pk:07}{counter_str}{doc.file_type}"
# Append .gpg for encrypted files # Append .gpg for encrypted files
if doc.storage_type == doc.STORAGE_TYPE_GPG: if append_gpg and doc.storage_type == doc.STORAGE_TYPE_GPG:
filename += ".gpg" filename += ".gpg"
return filename return filename

View File

@@ -11,6 +11,7 @@ from django import db
from django.conf import settings from django.conf import settings
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import transaction from django.db import transaction
from filelock import FileLock
from whoosh.writing import AsyncWriter from whoosh.writing import AsyncWriter
from documents.models import Document from documents.models import Document
@@ -47,8 +48,10 @@ def handle_document(document_id):
archive_checksum=checksum, archive_checksum=checksum,
content=parser.get_text() content=parser.get_text()
) )
create_source_path_directory(document.archive_path) with FileLock(settings.MEDIA_LOCK):
shutil.move(parser.get_archive_path(), document.archive_path) create_source_path_directory(document.archive_path)
shutil.move(parser.get_archive_path(),
document.archive_path)
with AsyncWriter(index.open_index()) as writer: with AsyncWriter(index.open_index()) as writer:
index.update_document(writer, document) index.update_document(writer, document)

View File

@@ -5,7 +5,6 @@ from time import sleep
from django.conf import settings from django.conf import settings
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.utils.text import slugify
from django_q.tasks import async_task from django_q.tasks import async_task
from watchdog.events import FileSystemEventHandler from watchdog.events import FileSystemEventHandler
from watchdog.observers.polling import PollingObserver from watchdog.observers.polling import PollingObserver

View File

@@ -1,15 +1,21 @@
import hashlib
import json import json
import os import os
import shutil import shutil
import time import time
import tqdm
from django.conf import settings
from django.core import serializers from django.core import serializers
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from filelock import FileLock
from documents.models import Document, Correspondent, Tag, DocumentType from documents.models import Document, Correspondent, Tag, DocumentType
from documents.settings import EXPORTER_FILE_NAME, EXPORTER_THUMBNAIL_NAME, \ from documents.settings import EXPORTER_FILE_NAME, EXPORTER_THUMBNAIL_NAME, \
EXPORTER_ARCHIVE_NAME EXPORTER_ARCHIVE_NAME
from paperless.db import GnuPG from paperless.db import GnuPG
from ...file_handling import generate_filename, delete_empty_directories
from ...mixins import Renderable from ...mixins import Renderable
@@ -24,13 +30,47 @@ class Command(Renderable, BaseCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument("target") parser.add_argument("target")
parser.add_argument(
"-c", "--compare-checksums",
default=False,
action="store_true",
help="Compare file checksums when determining whether to export "
"a file or not. If not specified, file size and time "
"modified is used instead."
)
parser.add_argument(
"-f", "--use-filename-format",
default=False,
action="store_true",
help="Use PAPERLESS_FILENAME_FORMAT for storing files in the "
"export directory, if configured."
)
parser.add_argument(
"-d", "--delete",
default=False,
action="store_true",
help="After exporting, delete files in the export directory that "
"do not belong to the current export, such as files from "
"deleted documents."
)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
BaseCommand.__init__(self, *args, **kwargs) BaseCommand.__init__(self, *args, **kwargs)
self.target = None self.target = None
self.files_in_export_dir = []
self.exported_files = []
self.compare_checksums = False
self.use_filename_format = False
self.delete = False
def handle(self, *args, **options): def handle(self, *args, **options):
self.target = options["target"] self.target = options["target"]
self.compare_checksums = options['compare_checksums']
self.use_filename_format = options['use_filename_format']
self.delete = options['delete']
if not os.path.exists(self.target): if not os.path.exists(self.target):
raise CommandError("That path doesn't exist") raise CommandError("That path doesn't exist")
@@ -38,83 +78,148 @@ class Command(Renderable, BaseCommand):
if not os.access(self.target, os.W_OK): if not os.access(self.target, os.W_OK):
raise CommandError("That path doesn't appear to be writable") raise CommandError("That path doesn't appear to be writable")
if os.listdir(self.target): with FileLock(settings.MEDIA_LOCK):
raise CommandError("That directory is not empty.") self.dump()
self.dump()
def dump(self): def dump(self):
# 1. Take a snapshot of what files exist in the current export folder
for root, dirs, files in os.walk(self.target):
self.files_in_export_dir.extend(
map(lambda f: os.path.abspath(os.path.join(root, f)), files)
)
documents = Document.objects.all() # 2. Create manifest, containing all correspondents, types, tags and
document_map = {d.pk: d for d in documents} # documents
manifest = json.loads(serializers.serialize("json", documents)) with transaction.atomic():
manifest = json.loads(
serializers.serialize("json", Correspondent.objects.all()))
for index, document_dict in enumerate(manifest): manifest += json.loads(serializers.serialize(
"json", Tag.objects.all()))
# Force output to unencrypted as that will be the current state. manifest += json.loads(serializers.serialize(
# The importer will make the decision to encrypt or not. "json", DocumentType.objects.all()))
manifest[index]["fields"]["storage_type"] = Document.STORAGE_TYPE_UNENCRYPTED # NOQA: E501
documents = Document.objects.order_by("id")
document_map = {d.pk: d for d in documents}
document_manifest = json.loads(
serializers.serialize("json", documents))
manifest += document_manifest
# 3. Export files from each document
for index, document_dict in tqdm.tqdm(enumerate(document_manifest),
total=len(document_manifest)):
# 3.1. store files unencrypted
document_dict["fields"]["storage_type"] = Document.STORAGE_TYPE_UNENCRYPTED # NOQA: E501
document = document_map[document_dict["pk"]] document = document_map[document_dict["pk"]]
print(f"Exporting: {document}") # 3.2. generate a unique filename
filename_counter = 0 filename_counter = 0
while True: while True:
original_name = document.get_public_filename( if self.use_filename_format:
counter=filename_counter) base_name = generate_filename(
original_target = os.path.join(self.target, original_name) document, counter=filename_counter,
append_gpg=False)
else:
base_name = document.get_public_filename(
counter=filename_counter)
if not os.path.exists(original_target): if base_name not in self.exported_files:
self.exported_files.append(base_name)
break break
else: else:
filename_counter += 1 filename_counter += 1
thumbnail_name = original_name + "-thumbnail.png" # 3.3. write filenames into manifest
thumbnail_target = os.path.join(self.target, thumbnail_name) original_name = base_name
original_target = os.path.join(self.target, original_name)
document_dict[EXPORTER_FILE_NAME] = original_name document_dict[EXPORTER_FILE_NAME] = original_name
thumbnail_name = base_name + "-thumbnail.png"
thumbnail_target = os.path.join(self.target, thumbnail_name)
document_dict[EXPORTER_THUMBNAIL_NAME] = thumbnail_name document_dict[EXPORTER_THUMBNAIL_NAME] = thumbnail_name
if os.path.exists(document.archive_path): if os.path.exists(document.archive_path):
archive_name = document.get_public_filename( archive_name = base_name + "-archive.pdf"
archive=True, counter=filename_counter, suffix="_archive")
archive_target = os.path.join(self.target, archive_name) archive_target = os.path.join(self.target, archive_name)
document_dict[EXPORTER_ARCHIVE_NAME] = archive_name document_dict[EXPORTER_ARCHIVE_NAME] = archive_name
else: else:
archive_target = None archive_target = None
# 3.4. write files to target folder
t = int(time.mktime(document.created.timetuple())) t = int(time.mktime(document.created.timetuple()))
if document.storage_type == Document.STORAGE_TYPE_GPG: if document.storage_type == Document.STORAGE_TYPE_GPG:
os.makedirs(os.path.dirname(original_target), exist_ok=True)
with open(original_target, "wb") as f: with open(original_target, "wb") as f:
f.write(GnuPG.decrypted(document.source_file)) f.write(GnuPG.decrypted(document.source_file))
os.utime(original_target, times=(t, t)) os.utime(original_target, times=(t, t))
os.makedirs(os.path.dirname(thumbnail_target), exist_ok=True)
with open(thumbnail_target, "wb") as f: with open(thumbnail_target, "wb") as f:
f.write(GnuPG.decrypted(document.thumbnail_file)) f.write(GnuPG.decrypted(document.thumbnail_file))
os.utime(thumbnail_target, times=(t, t)) os.utime(thumbnail_target, times=(t, t))
if archive_target: if archive_target:
os.makedirs(os.path.dirname(archive_target), exist_ok=True)
with open(archive_target, "wb") as f: with open(archive_target, "wb") as f:
f.write(GnuPG.decrypted(document.archive_path)) f.write(GnuPG.decrypted(document.archive_path))
os.utime(archive_target, times=(t, t)) os.utime(archive_target, times=(t, t))
else: else:
self.check_and_copy(document.source_path,
document.checksum,
original_target)
shutil.copy(document.source_path, original_target) self.check_and_copy(document.thumbnail_path,
shutil.copy(document.thumbnail_path, thumbnail_target) None,
thumbnail_target)
if archive_target: if archive_target:
shutil.copy(document.archive_path, archive_target) self.check_and_copy(document.archive_path,
document.archive_checksum,
archive_target)
manifest += json.loads( # 4. write manifest to target forlder
serializers.serialize("json", Correspondent.objects.all())) manifest_path = os.path.abspath(
os.path.join(self.target, "manifest.json"))
manifest += json.loads(serializers.serialize( with open(manifest_path, "w") as f:
"json", Tag.objects.all()))
manifest += json.loads(serializers.serialize(
"json", DocumentType.objects.all()))
with open(os.path.join(self.target, "manifest.json"), "w") as f:
json.dump(manifest, f, indent=2) json.dump(manifest, f, indent=2)
if self.delete:
# 5. Remove files which we did not explicitly export in this run
if manifest_path in self.files_in_export_dir:
self.files_in_export_dir.remove(manifest_path)
for f in self.files_in_export_dir:
os.remove(f)
delete_empty_directories(os.path.abspath(os.path.dirname(f)),
os.path.abspath(self.target))
def check_and_copy(self, source, source_checksum, target):
if os.path.abspath(target) in self.files_in_export_dir:
self.files_in_export_dir.remove(os.path.abspath(target))
perform_copy = False
if os.path.exists(target):
source_stat = os.stat(source)
target_stat = os.stat(target)
if self.compare_checksums and source_checksum:
with open(target, "rb") as f:
target_checksum = hashlib.md5(f.read()).hexdigest()
perform_copy = target_checksum != source_checksum
elif source_stat.st_mtime != target_stat.st_mtime:
perform_copy = True
elif source_stat.st_size != target_stat.st_size:
perform_copy = True
else:
# Copy if it does not exist
perform_copy = True
if perform_copy:
os.makedirs(os.path.dirname(target), exist_ok=True)
shutil.copy2(source, target)

View File

@@ -148,10 +148,10 @@ class Command(Renderable, BaseCommand):
create_source_path_directory(document.source_path) create_source_path_directory(document.source_path)
shutil.copy(document_path, document.source_path) shutil.copy2(document_path, document.source_path)
shutil.copy(thumbnail_path, document.thumbnail_path) shutil.copy2(thumbnail_path, document.thumbnail_path)
if archive_path: if archive_path:
create_source_path_directory(document.archive_path) create_source_path_directory(document.archive_path)
shutil.copy(archive_path, document.archive_path) shutil.copy2(archive_path, document.archive_path)
document.save() document.save()

View File

@@ -63,12 +63,6 @@ class MatchingModel(models.Model):
def __str__(self): def __str__(self):
return self.name return self.name
def save(self, *args, **kwargs):
self.match = self.match.lower()
models.Model.save(self, *args, **kwargs)
class Correspondent(MatchingModel): class Correspondent(MatchingModel):

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -228,6 +228,12 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
self.assertEqual(len(results), 2) self.assertEqual(len(results), 2)
self.assertCountEqual([results[0]['id'], results[1]['id']], [doc1.id, doc3.id]) self.assertCountEqual([results[0]['id'], results[1]['id']], [doc1.id, doc3.id])
response = self.client.get("/api/documents/?tags__id__in={},{}".format(tag_2.id, tag_3.id))
self.assertEqual(response.status_code, 200)
results = response.data['results']
self.assertEqual(len(results), 2)
self.assertCountEqual([results[0]['id'], results[1]['id']], [doc2.id, doc3.id])
response = self.client.get("/api/documents/?tags__id__all={},{}".format(tag_2.id, tag_3.id)) response = self.client.get("/api/documents/?tags__id__all={},{}".format(tag_2.id, tag_3.id))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
results = response.data['results'] results = response.data['results']
@@ -923,6 +929,14 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
doc2 = Document.objects.get(id=self.doc2.id) doc2 = Document.objects.get(id=self.doc2.id)
self.assertEqual(doc2.correspondent, self.c1) self.assertEqual(doc2.correspondent, self.c1)
def test_api_no_correspondent(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "set_correspondent",
"parameters": {}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_invalid_document_type(self): def test_api_invalid_document_type(self):
self.assertEqual(self.doc2.document_type, self.dt1) self.assertEqual(self.doc2.document_type, self.dt1)
response = self.client.post("/api/documents/bulk_edit/", json.dumps({ response = self.client.post("/api/documents/bulk_edit/", json.dumps({
@@ -935,6 +949,14 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
doc2 = Document.objects.get(id=self.doc2.id) doc2 = Document.objects.get(id=self.doc2.id)
self.assertEqual(doc2.document_type, self.dt1) self.assertEqual(doc2.document_type, self.dt1)
def test_api_no_document_type(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "set_document_type",
"parameters": {}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_add_invalid_tag(self): def test_api_add_invalid_tag(self):
self.assertEqual(list(self.doc2.tags.all()), [self.t1]) self.assertEqual(list(self.doc2.tags.all()), [self.t1])
response = self.client.post("/api/documents/bulk_edit/", json.dumps({ response = self.client.post("/api/documents/bulk_edit/", json.dumps({
@@ -946,6 +968,14 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
self.assertEqual(list(self.doc2.tags.all()), [self.t1]) self.assertEqual(list(self.doc2.tags.all()), [self.t1])
def test_api_add_tag_no_tag(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "add_tag",
"parameters": {}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_delete_invalid_tag(self): def test_api_delete_invalid_tag(self):
self.assertEqual(list(self.doc2.tags.all()), [self.t1]) self.assertEqual(list(self.doc2.tags.all()), [self.t1])
response = self.client.post("/api/documents/bulk_edit/", json.dumps({ response = self.client.post("/api/documents/bulk_edit/", json.dumps({
@@ -957,6 +987,14 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
self.assertEqual(list(self.doc2.tags.all()), [self.t1]) self.assertEqual(list(self.doc2.tags.all()), [self.t1])
def test_api_delete_tag_no_tag(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "remove_tag",
"parameters": {}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_modify_invalid_tags(self): def test_api_modify_invalid_tags(self):
self.assertEqual(list(self.doc2.tags.all()), [self.t1]) self.assertEqual(list(self.doc2.tags.all()), [self.t1])
response = self.client.post("/api/documents/bulk_edit/", json.dumps({ response = self.client.post("/api/documents/bulk_edit/", json.dumps({
@@ -966,6 +1004,21 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
}), content_type='application/json') }), content_type='application/json')
self.assertEqual(response.status_code, 400) self.assertEqual(response.status_code, 400)
def test_api_modify_tags_no_tags(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "modify_tags",
"parameters": {"remove_tags": [1123123]}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "modify_tags",
"parameters": {'add_tags': [self.t2.id, 1657]}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_selection_data_empty(self): def test_api_selection_data_empty(self):
response = self.client.post("/api/documents/selection_data/", json.dumps({ response = self.client.post("/api/documents/selection_data/", json.dumps({
"documents": [] "documents": []

View File

@@ -70,18 +70,18 @@ class TestDecryptDocuments(TestCase):
PASSPHRASE="test" PASSPHRASE="test"
).enable() ).enable()
doc = Document.objects.create(checksum="9c9691e51741c1f4f41a20896af31770", title="wow", filename="0000002.pdf.gpg", mime_type="application/pdf", storage_type=Document.STORAGE_TYPE_GPG) doc = Document.objects.create(checksum="82186aaa94f0b98697d704b90fd1c072", title="wow", filename="0000004.pdf.gpg", mime_type="application/pdf", storage_type=Document.STORAGE_TYPE_GPG)
shutil.copy(os.path.join(os.path.dirname(__file__), "samples", "documents", "originals", "0000002.pdf.gpg"), os.path.join(originals_dir, "0000002.pdf.gpg")) shutil.copy(os.path.join(os.path.dirname(__file__), "samples", "documents", "originals", "0000004.pdf.gpg"), os.path.join(originals_dir, "0000004.pdf.gpg"))
shutil.copy(os.path.join(os.path.dirname(__file__), "samples", "documents", "thumbnails", f"0000002.png.gpg"), os.path.join(thumb_dir, f"{doc.id:07}.png.gpg")) shutil.copy(os.path.join(os.path.dirname(__file__), "samples", "documents", "thumbnails", f"0000004.png.gpg"), os.path.join(thumb_dir, f"{doc.id:07}.png.gpg"))
call_command('decrypt_documents') call_command('decrypt_documents')
doc.refresh_from_db() doc.refresh_from_db()
self.assertEqual(doc.storage_type, Document.STORAGE_TYPE_UNENCRYPTED) self.assertEqual(doc.storage_type, Document.STORAGE_TYPE_UNENCRYPTED)
self.assertEqual(doc.filename, "0000002.pdf") self.assertEqual(doc.filename, "0000004.pdf")
self.assertTrue(os.path.isfile(os.path.join(originals_dir, "0000002.pdf"))) self.assertTrue(os.path.isfile(os.path.join(originals_dir, "0000004.pdf")))
self.assertTrue(os.path.isfile(doc.source_path)) self.assertTrue(os.path.isfile(doc.source_path))
self.assertTrue(os.path.isfile(os.path.join(thumb_dir, f"{doc.id:07}.png"))) self.assertTrue(os.path.isfile(os.path.join(thumb_dir, f"{doc.id:07}.png")))
self.assertTrue(os.path.isfile(doc.thumbnail_path)) self.assertTrue(os.path.isfile(doc.thumbnail_path))

View File

@@ -3,6 +3,8 @@ import json
import os import os
import shutil import shutil
import tempfile import tempfile
from pathlib import Path
from unittest import mock
from django.core.management import call_command from django.core.management import call_command
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
@@ -10,54 +12,87 @@ from django.test import TestCase, override_settings
from documents.management.commands import document_exporter from documents.management.commands import document_exporter
from documents.models import Document, Tag, DocumentType, Correspondent from documents.models import Document, Tag, DocumentType, Correspondent
from documents.sanity_checker import check_sanity from documents.sanity_checker import check_sanity
from documents.settings import EXPORTER_FILE_NAME
from documents.tests.utils import DirectoriesMixin, paperless_environment from documents.tests.utils import DirectoriesMixin, paperless_environment
class TestExportImport(DirectoriesMixin, TestCase): class TestExportImport(DirectoriesMixin, TestCase):
def setUp(self) -> None:
self.target = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, self.target)
self.d1 = Document.objects.create(content="Content", checksum="42995833e01aea9b3edee44bbfdd7ce1", archive_checksum="62acb0bcbfbcaa62ca6ad3668e4e404b", title="wow1", filename="0000001.pdf", mime_type="application/pdf")
self.d2 = Document.objects.create(content="Content", checksum="9c9691e51741c1f4f41a20896af31770", title="wow2", filename="0000002.pdf", mime_type="application/pdf")
self.d3 = Document.objects.create(content="Content", checksum="d38d7ed02e988e072caf924e0f3fcb76", title="wow2", filename="0000003.pdf", mime_type="application/pdf")
self.d4 = Document.objects.create(content="Content", checksum="82186aaa94f0b98697d704b90fd1c072", title="wow_dec", filename="0000004.pdf.gpg", mime_type="application/pdf", storage_type=Document.STORAGE_TYPE_GPG)
self.t1 = Tag.objects.create(name="t")
self.dt1 = DocumentType.objects.create(name="dt")
self.c1 = Correspondent.objects.create(name="c")
self.d1.tags.add(self.t1)
self.d1.correspondent = self.c1
self.d1.document_type = self.dt1
self.d1.save()
super(TestExportImport, self).setUp()
def _get_document_from_manifest(self, manifest, id):
f = list(filter(lambda d: d['model'] == "documents.document" and d['pk'] == id, manifest))
if len(f) == 1:
return f[0]
else:
raise ValueError(f"document with id {id} does not exist in manifest")
@override_settings( @override_settings(
PASSPHRASE="test" PASSPHRASE="test"
) )
def test_exporter(self): def _do_export(self, use_filename_format=False, compare_checksums=False, delete=False):
args = ['document_exporter', self.target]
if use_filename_format:
args += ["--use-filename-format"]
if compare_checksums:
args += ["--compare-checksums"]
if delete:
args += ["--delete"]
call_command(*args)
with open(os.path.join(self.target, "manifest.json")) as f:
manifest = json.load(f)
return manifest
def test_exporter(self, use_filename_format=False):
shutil.rmtree(os.path.join(self.dirs.media_dir, "documents")) shutil.rmtree(os.path.join(self.dirs.media_dir, "documents"))
shutil.copytree(os.path.join(os.path.dirname(__file__), "samples", "documents"), os.path.join(self.dirs.media_dir, "documents")) shutil.copytree(os.path.join(os.path.dirname(__file__), "samples", "documents"), os.path.join(self.dirs.media_dir, "documents"))
file = os.path.join(self.dirs.originals_dir, "0000001.pdf") manifest = self._do_export(use_filename_format=use_filename_format)
d1 = Document.objects.create(content="Content", checksum="42995833e01aea9b3edee44bbfdd7ce1", archive_checksum="62acb0bcbfbcaa62ca6ad3668e4e404b", title="wow", filename="0000001.pdf", mime_type="application/pdf") self.assertEqual(len(manifest), 7)
d2 = Document.objects.create(content="Content", checksum="9c9691e51741c1f4f41a20896af31770", title="wow", filename="0000002.pdf.gpg", mime_type="application/pdf", storage_type=Document.STORAGE_TYPE_GPG) self.assertEqual(len(list(filter(lambda e: e['model'] == 'documents.document', manifest))), 4)
t1 = Tag.objects.create(name="t")
dt1 = DocumentType.objects.create(name="dt")
c1 = Correspondent.objects.create(name="c")
d1.tags.add(t1) self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))
d1.correspondents = c1
d1.document_type = dt1
d1.save()
d2.save()
target = tempfile.mkdtemp() self.assertEqual(self._get_document_from_manifest(manifest, self.d1.id)['fields']['title'], "wow1")
self.addCleanup(shutil.rmtree, target) self.assertEqual(self._get_document_from_manifest(manifest, self.d2.id)['fields']['title'], "wow2")
self.assertEqual(self._get_document_from_manifest(manifest, self.d3.id)['fields']['title'], "wow2")
call_command('document_exporter', target) self.assertEqual(self._get_document_from_manifest(manifest, self.d4.id)['fields']['title'], "wow_dec")
with open(os.path.join(target, "manifest.json")) as f:
manifest = json.load(f)
self.assertEqual(len(manifest), 5)
for element in manifest: for element in manifest:
if element['model'] == 'documents.document': if element['model'] == 'documents.document':
fname = os.path.join(target, element[document_exporter.EXPORTER_FILE_NAME]) fname = os.path.join(self.target, element[document_exporter.EXPORTER_FILE_NAME])
self.assertTrue(os.path.exists(fname)) self.assertTrue(os.path.exists(fname))
self.assertTrue(os.path.exists(os.path.join(target, element[document_exporter.EXPORTER_THUMBNAIL_NAME]))) self.assertTrue(os.path.exists(os.path.join(self.target, element[document_exporter.EXPORTER_THUMBNAIL_NAME])))
with open(fname, "rb") as f: with open(fname, "rb") as f:
checksum = hashlib.md5(f.read()).hexdigest() checksum = hashlib.md5(f.read()).hexdigest()
self.assertEqual(checksum, element['fields']['checksum']) self.assertEqual(checksum, element['fields']['checksum'])
self.assertEqual(element['fields']['storage_type'], Document.STORAGE_TYPE_UNENCRYPTED)
if document_exporter.EXPORTER_ARCHIVE_NAME in element: if document_exporter.EXPORTER_ARCHIVE_NAME in element:
fname = os.path.join(target, element[document_exporter.EXPORTER_ARCHIVE_NAME]) fname = os.path.join(self.target, element[document_exporter.EXPORTER_ARCHIVE_NAME])
self.assertTrue(os.path.exists(fname)) self.assertTrue(os.path.exists(fname))
with open(fname, "rb") as f: with open(fname, "rb") as f:
@@ -65,24 +100,123 @@ class TestExportImport(DirectoriesMixin, TestCase):
self.assertEqual(checksum, element['fields']['archive_checksum']) self.assertEqual(checksum, element['fields']['archive_checksum'])
with paperless_environment() as dirs: with paperless_environment() as dirs:
self.assertEqual(Document.objects.count(), 2) self.assertEqual(Document.objects.count(), 4)
Document.objects.all().delete() Document.objects.all().delete()
Correspondent.objects.all().delete() Correspondent.objects.all().delete()
DocumentType.objects.all().delete() DocumentType.objects.all().delete()
Tag.objects.all().delete() Tag.objects.all().delete()
self.assertEqual(Document.objects.count(), 0) self.assertEqual(Document.objects.count(), 0)
call_command('document_importer', target) call_command('document_importer', self.target)
self.assertEqual(Document.objects.count(), 2) self.assertEqual(Document.objects.count(), 4)
self.assertEqual(Tag.objects.count(), 1)
self.assertEqual(Correspondent.objects.count(), 1)
self.assertEqual(DocumentType.objects.count(), 1)
self.assertEqual(Document.objects.get(id=self.d1.id).title, "wow1")
self.assertEqual(Document.objects.get(id=self.d2.id).title, "wow2")
self.assertEqual(Document.objects.get(id=self.d3.id).title, "wow2")
self.assertEqual(Document.objects.get(id=self.d4.id).title, "wow_dec")
messages = check_sanity() messages = check_sanity()
# everything is alright after the test # everything is alright after the test
self.assertEqual(len(messages), 0, str([str(m) for m in messages])) self.assertEqual(len(messages), 0, str([str(m) for m in messages]))
@override_settings(
PAPERLESS_FILENAME_FORMAT="{title}"
)
def test_exporter_with_filename_format(self): def test_exporter_with_filename_format(self):
self.test_exporter() shutil.rmtree(os.path.join(self.dirs.media_dir, "documents"))
shutil.copytree(os.path.join(os.path.dirname(__file__), "samples", "documents"), os.path.join(self.dirs.media_dir, "documents"))
with override_settings(PAPERLESS_FILENAME_FORMAT="{created_year}/{correspondent}/{title}"):
self.test_exporter(use_filename_format=True)
def test_update_export_changed_time(self):
shutil.rmtree(os.path.join(self.dirs.media_dir, "documents"))
shutil.copytree(os.path.join(os.path.dirname(__file__), "samples", "documents"), os.path.join(self.dirs.media_dir, "documents"))
self._do_export()
self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))
st_mtime_1 = os.stat(os.path.join(self.target, "manifest.json")).st_mtime
with mock.patch("documents.management.commands.document_exporter.shutil.copy2") as m:
self._do_export()
m.assert_not_called()
self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))
st_mtime_2 = os.stat(os.path.join(self.target, "manifest.json")).st_mtime
Path(self.d1.source_path).touch()
with mock.patch("documents.management.commands.document_exporter.shutil.copy2") as m:
self._do_export()
self.assertEqual(m.call_count, 1)
st_mtime_3 = os.stat(os.path.join(self.target, "manifest.json")).st_mtime
self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))
self.assertNotEqual(st_mtime_1, st_mtime_2)
self.assertNotEqual(st_mtime_2, st_mtime_3)
def test_update_export_changed_checksum(self):
shutil.rmtree(os.path.join(self.dirs.media_dir, "documents"))
shutil.copytree(os.path.join(os.path.dirname(__file__), "samples", "documents"), os.path.join(self.dirs.media_dir, "documents"))
self._do_export()
self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))
with mock.patch("documents.management.commands.document_exporter.shutil.copy2") as m:
self._do_export()
m.assert_not_called()
self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))
self.d2.checksum = "asdfasdgf3"
self.d2.save()
with mock.patch("documents.management.commands.document_exporter.shutil.copy2") as m:
self._do_export(compare_checksums=True)
self.assertEqual(m.call_count, 1)
self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))
def test_update_export_deleted_document(self):
shutil.rmtree(os.path.join(self.dirs.media_dir, "documents"))
shutil.copytree(os.path.join(os.path.dirname(__file__), "samples", "documents"), os.path.join(self.dirs.media_dir, "documents"))
manifest = self._do_export()
self.assertTrue(len(manifest), 7)
doc_from_manifest = self._get_document_from_manifest(manifest, self.d3.id)
self.assertTrue(os.path.isfile(os.path.join(self.target, doc_from_manifest[EXPORTER_FILE_NAME])))
self.d3.delete()
manifest = self._do_export()
self.assertRaises(ValueError, self._get_document_from_manifest, manifest, self.d3.id)
self.assertTrue(os.path.isfile(os.path.join(self.target, doc_from_manifest[EXPORTER_FILE_NAME])))
manifest = self._do_export(delete=True)
self.assertFalse(os.path.isfile(os.path.join(self.target, doc_from_manifest[EXPORTER_FILE_NAME])))
self.assertTrue(len(manifest), 6)
@override_settings(PAPERLESS_FILENAME_FORMAT="{title}/{correspondent}")
def test_update_export_changed_location(self):
shutil.rmtree(os.path.join(self.dirs.media_dir, "documents"))
shutil.copytree(os.path.join(os.path.dirname(__file__), "samples", "documents"), os.path.join(self.dirs.media_dir, "documents"))
m = self._do_export(use_filename_format=True)
self.assertTrue(os.path.isfile(os.path.join(self.target, "wow1", "c.pdf")))
self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))
self.d1.title = "new_title"
self.d1.save()
self._do_export(use_filename_format=True, delete=True)
self.assertFalse(os.path.isfile(os.path.join(self.target, "wow1", "c.pdf")))
self.assertFalse(os.path.isdir(os.path.join(self.target, "wow1")))
self.assertTrue(os.path.isfile(os.path.join(self.target, "new_title", "c.pdf")))
self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))
self.assertTrue(os.path.isfile(os.path.join(self.target, "wow2", "none.pdf")))
self.assertTrue(os.path.isfile(os.path.join(self.target, "wow2", "none_01.pdf")))
def test_export_missing_files(self): def test_export_missing_files(self):

View File

@@ -98,7 +98,7 @@ class TestMigrateMimeType(DirectoriesMixin, TestMigrations):
doc2 = Document.objects.create(checksum="B", file_type="pdf", storage_type=STORAGE_TYPE_GPG) doc2 = Document.objects.create(checksum="B", file_type="pdf", storage_type=STORAGE_TYPE_GPG)
self.doc2_id = doc2.id self.doc2_id = doc2.id
shutil.copy(os.path.join(os.path.dirname(__file__), "samples", "documents", "originals", "0000002.pdf.gpg"), source_path_before(doc2)) shutil.copy(os.path.join(os.path.dirname(__file__), "samples", "documents", "originals", "0000004.pdf.gpg"), source_path_before(doc2))
def testMimeTypesMigrated(self): def testMimeTypesMigrated(self):
Document = self.apps.get_model('documents', 'Document') Document = self.apps.get_model('documents', 'Document')

View File

@@ -120,3 +120,4 @@ class TestParserAvailability(TestCase):
self.assertTrue(is_file_ext_supported('.pdf')) self.assertTrue(is_file_ext_supported('.pdf'))
self.assertFalse(is_file_ext_supported('.hsdfh')) self.assertFalse(is_file_ext_supported('.hsdfh'))
self.assertFalse(is_file_ext_supported(''))

View File

@@ -159,6 +159,9 @@ class DocumentViewSet(RetrieveModelMixin,
"added", "added",
"archive_serial_number") "archive_serial_number")
def get_queryset(self):
return Document.objects.distinct()
def get_serializer(self, *args, **kwargs): def get_serializer(self, *args, **kwargs):
fields_param = self.request.query_params.get('fields', None) fields_param = self.request.query_params.get('fields', None)
if fields_param: if fields_param:

View File

@@ -1 +1 @@
__version__ = (0, 9, 14) __version__ = (1, 0, 0)

View File

@@ -1,3 +1,4 @@
import os
import uuid import uuid
from collections import namedtuple from collections import namedtuple
from typing import ContextManager from typing import ContextManager
@@ -9,6 +10,7 @@ from django.test import TestCase
from imap_tools import MailMessageFlags, MailboxFolderSelectError from imap_tools import MailMessageFlags, MailboxFolderSelectError
from documents.models import Correspondent from documents.models import Correspondent
from documents.tests.utils import DirectoriesMixin
from paperless_mail import tasks from paperless_mail import tasks
from paperless_mail.mail import MailError, MailAccountHandler from paperless_mail.mail import MailError, MailAccountHandler
from paperless_mail.models import MailRule, MailAccount from paperless_mail.models import MailRule, MailAccount
@@ -130,7 +132,7 @@ def fake_magic_from_buffer(buffer, mime=False):
@mock.patch('paperless_mail.mail.magic.from_buffer', fake_magic_from_buffer) @mock.patch('paperless_mail.mail.magic.from_buffer', fake_magic_from_buffer)
class TestMail(TestCase): class TestMail(DirectoriesMixin, TestCase):
def setUp(self): def setUp(self):
patcher = mock.patch('paperless_mail.mail.MailBox') patcher = mock.patch('paperless_mail.mail.MailBox')
@@ -146,6 +148,7 @@ class TestMail(TestCase):
self.reset_bogus_mailbox() self.reset_bogus_mailbox()
self.mail_account_handler = MailAccountHandler() self.mail_account_handler = MailAccountHandler()
super(TestMail, self).setUp()
def reset_bogus_mailbox(self): def reset_bogus_mailbox(self):
self.bogus_mailbox.messages = [] self.bogus_mailbox.messages = []
@@ -220,9 +223,13 @@ class TestMail(TestCase):
args1, kwargs1 = self.async_task.call_args_list[0] args1, kwargs1 = self.async_task.call_args_list[0]
args2, kwargs2 = self.async_task.call_args_list[1] args2, kwargs2 = self.async_task.call_args_list[1]
self.assertTrue(os.path.isfile(kwargs1['path']), kwargs1['path'])
self.assertEqual(kwargs1['override_title'], "file_0") self.assertEqual(kwargs1['override_title'], "file_0")
self.assertEqual(kwargs1['override_filename'], "file_0.pdf") self.assertEqual(kwargs1['override_filename'], "file_0.pdf")
self.assertTrue(os.path.isfile(kwargs2['path']), kwargs1['path'])
self.assertEqual(kwargs2['override_title'], "file_1") self.assertEqual(kwargs2['override_title'], "file_1")
self.assertEqual(kwargs2['override_filename'], "file_1.pdf") self.assertEqual(kwargs2['override_filename'], "file_1.pdf")
@@ -253,6 +260,7 @@ class TestMail(TestCase):
self.assertEqual(self.async_task.call_count, 1) self.assertEqual(self.async_task.call_count, 1)
args, kwargs = self.async_task.call_args args, kwargs = self.async_task.call_args
self.assertTrue(os.path.isfile(kwargs['path']), kwargs['path'])
self.assertEqual(kwargs['override_filename'], "f1.pdf") self.assertEqual(kwargs['override_filename'], "f1.pdf")
def test_handle_disposition(self): def test_handle_disposition(self):