mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-08-20 00:56:26 +00:00
Compare commits
8 Commits
v2.13.4
...
feature-re
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ec12e71487 | ||
![]() |
62b470f691 | ||
![]() |
a2e4977201 | ||
![]() |
0fcd69b739 | ||
![]() |
af1c64e969 | ||
![]() |
85c661dff2 | ||
![]() |
3a7eee2c2e | ||
![]() |
bc4d3925cc |
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -98,7 +98,7 @@ body:
|
||||
label: Browser
|
||||
description: Which browser you are using, if relevant.
|
||||
placeholder: e.g. Chrome, Safari
|
||||
- type: textarea
|
||||
- type: input
|
||||
id: config-changes
|
||||
attributes:
|
||||
label: Configuration changes
|
||||
|
@@ -1,52 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## paperless-ngx 2.13.3
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: fix auto-clean PDFs, create parent dir for storing unmodified original [@shamoon](https://github.com/shamoon) ([#8157](https://github.com/paperless-ngx/paperless-ngx/pull/8157))
|
||||
- Fix: correctly handle exists, false in custom field query filter @yichi-yang ([#8158](https://github.com/paperless-ngx/paperless-ngx/pull/8158))
|
||||
- Fix: dont use filters for inverted thumbnails in Safari [@shamoon](https://github.com/shamoon) ([#8121](https://github.com/paperless-ngx/paperless-ngx/pull/8121))
|
||||
- Fix: use static object for activedisplayfields to prevent changes [@shamoon](https://github.com/shamoon) ([#8120](https://github.com/paperless-ngx/paperless-ngx/pull/8120))
|
||||
- Fix: dont invert pdf colors in FF [@shamoon](https://github.com/shamoon) ([#8110](https://github.com/paperless-ngx/paperless-ngx/pull/8110))
|
||||
- Fix: make mail account password and refresh token text fields [@shamoon](https://github.com/shamoon) ([#8107](https://github.com/paperless-ngx/paperless-ngx/pull/8107))
|
||||
|
||||
### Dependencies
|
||||
|
||||
<details>
|
||||
<summary>8 changes</summary>
|
||||
|
||||
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#8145](https://github.com/paperless-ngx/paperless-ngx/pull/8145))
|
||||
- Chore(deps-dev): Bump @types/node from 22.7.4 to 22.8.6 in /src-ui [@dependabot](https://github.com/dependabot) ([#8148](https://github.com/paperless-ngx/paperless-ngx/pull/8148))
|
||||
- Chore(deps-dev): Bump @playwright/test from 1.47.2 to 1.48.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#8147](https://github.com/paperless-ngx/paperless-ngx/pull/8147))
|
||||
- Chore(deps): Bump uuid from 10.0.0 to 11.0.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#8146](https://github.com/paperless-ngx/paperless-ngx/pull/8146))
|
||||
- Chore(deps): Bump tslib from 2.7.0 to 2.8.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#8149](https://github.com/paperless-ngx/paperless-ngx/pull/8149))
|
||||
- Chore(deps-dev): Bump @codecov/webpack-plugin from 1.2.0 to 1.2.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#8150](https://github.com/paperless-ngx/paperless-ngx/pull/8150))
|
||||
- Chore(deps-dev): Bump @types/jest from 29.5.13 to 29.5.14 in /src-ui in the frontend-jest-dependencies group [@dependabot](https://github.com/dependabot) ([#8144](https://github.com/paperless-ngx/paperless-ngx/pull/8144))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 21 updates [@dependabot](https://github.com/dependabot) ([#8143](https://github.com/paperless-ngx/paperless-ngx/pull/8143))
|
||||
</details>
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>14 changes</summary>
|
||||
|
||||
- Fix: fix auto-clean PDFs, create parent dir for storing unmodified original [@shamoon](https://github.com/shamoon) ([#8157](https://github.com/paperless-ngx/paperless-ngx/pull/8157))
|
||||
- Fix: correctly handle exists, false in custom field query filter @yichi-yang ([#8158](https://github.com/paperless-ngx/paperless-ngx/pull/8158))
|
||||
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#8145](https://github.com/paperless-ngx/paperless-ngx/pull/8145))
|
||||
- Chore(deps-dev): Bump @types/node from 22.7.4 to 22.8.6 in /src-ui [@dependabot](https://github.com/dependabot) ([#8148](https://github.com/paperless-ngx/paperless-ngx/pull/8148))
|
||||
- Chore(deps-dev): Bump @playwright/test from 1.47.2 to 1.48.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#8147](https://github.com/paperless-ngx/paperless-ngx/pull/8147))
|
||||
- Chore(deps): Bump uuid from 10.0.0 to 11.0.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#8146](https://github.com/paperless-ngx/paperless-ngx/pull/8146))
|
||||
- Chore(deps): Bump tslib from 2.7.0 to 2.8.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#8149](https://github.com/paperless-ngx/paperless-ngx/pull/8149))
|
||||
- Chore(deps-dev): Bump @codecov/webpack-plugin from 1.2.0 to 1.2.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#8150](https://github.com/paperless-ngx/paperless-ngx/pull/8150))
|
||||
- Chore(deps-dev): Bump @types/jest from 29.5.13 to 29.5.14 in /src-ui in the frontend-jest-dependencies group [@dependabot](https://github.com/dependabot) ([#8144](https://github.com/paperless-ngx/paperless-ngx/pull/8144))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 21 updates [@dependabot](https://github.com/dependabot) ([#8143](https://github.com/paperless-ngx/paperless-ngx/pull/8143))
|
||||
- Fix: dont use filters for inverted thumbnails in Safari [@shamoon](https://github.com/shamoon) ([#8121](https://github.com/paperless-ngx/paperless-ngx/pull/8121))
|
||||
- Fix: use static object for activedisplayfields to prevent changes [@shamoon](https://github.com/shamoon) ([#8120](https://github.com/paperless-ngx/paperless-ngx/pull/8120))
|
||||
- Fix: dont invert pdf colors in FF [@shamoon](https://github.com/shamoon) ([#8110](https://github.com/paperless-ngx/paperless-ngx/pull/8110))
|
||||
- Fix: make mail account password and refresh token text fields [@shamoon](https://github.com/shamoon) ([#8107](https://github.com/paperless-ngx/paperless-ngx/pull/8107))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 2.13.2
|
||||
|
||||
### Bug Fixes
|
||||
@@ -105,120 +58,6 @@
|
||||
- Fix: oauth settings without base url [@shamoon](https://github.com/shamoon) ([#8020](https://github.com/paperless-ngx/paperless-ngx/pull/8020))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 2.13.0
|
||||
|
||||
### Notable Changes
|
||||
|
||||
- Feature: OAuth2 Gmail and Outlook email support [@shamoon](https://github.com/shamoon) ([#7866](https://github.com/paperless-ngx/paperless-ngx/pull/7866))
|
||||
- Feature: Enhanced templating for filename format [@stumpylog](https://github.com/stumpylog) ([#7836](https://github.com/paperless-ngx/paperless-ngx/pull/7836))
|
||||
- Feature: custom fields queries [@shamoon](https://github.com/shamoon) ([#7761](https://github.com/paperless-ngx/paperless-ngx/pull/7761))
|
||||
- Chore: Drop Python 3.9 support [@stumpylog](https://github.com/stumpylog) ([#7774](https://github.com/paperless-ngx/paperless-ngx/pull/7774))
|
||||
|
||||
### Features
|
||||
|
||||
- Enhancement: QoL, auto-focus default select field in custom field dropdown [@shamoon](https://github.com/shamoon) ([#7961](https://github.com/paperless-ngx/paperless-ngx/pull/7961))
|
||||
- Change: open not edit [@shamoon](https://github.com/shamoon) ([#7942](https://github.com/paperless-ngx/paperless-ngx/pull/7942))
|
||||
- Enhancement: support retain barcode split pages [@shamoon](https://github.com/shamoon) ([#7912](https://github.com/paperless-ngx/paperless-ngx/pull/7912))
|
||||
- Enhancement: don't wait for doc API to load preview [@shamoon](https://github.com/shamoon) ([#7894](https://github.com/paperless-ngx/paperless-ngx/pull/7894))
|
||||
- Feature: OAuth2 Gmail and Outlook email support [@shamoon](https://github.com/shamoon) ([#7866](https://github.com/paperless-ngx/paperless-ngx/pull/7866))
|
||||
- Enhancement: live preview of storage path [@shamoon](https://github.com/shamoon) ([#7870](https://github.com/paperless-ngx/paperless-ngx/pull/7870))
|
||||
- Enhancement: management list button improvements [@shamoon](https://github.com/shamoon) ([#7848](https://github.com/paperless-ngx/paperless-ngx/pull/7848))
|
||||
- Enhancement: check for mail destination directory, log post-consume errors [@mrichtarsky](https://github.com/mrichtarsky) ([#7808](https://github.com/paperless-ngx/paperless-ngx/pull/7808))
|
||||
- Enhancement: workflow overview toggle enable button [@shamoon](https://github.com/shamoon) ([#7818](https://github.com/paperless-ngx/paperless-ngx/pull/7818))
|
||||
- Enhancement: disable-able mail rules, add toggle to overview [@shamoon](https://github.com/shamoon) ([#7810](https://github.com/paperless-ngx/paperless-ngx/pull/7810))
|
||||
- Feature: auto-clean some invalid pdfs [@shamoon](https://github.com/shamoon) ([#7651](https://github.com/paperless-ngx/paperless-ngx/pull/7651))
|
||||
- Feature: page count [@s0llvan](https://github.com/s0llvan) ([#7750](https://github.com/paperless-ngx/paperless-ngx/pull/7750))
|
||||
- Enhancement: use apt only when needed docker-entrypoint.sh [@gawa971](https://github.com/gawa971) ([#7756](https://github.com/paperless-ngx/paperless-ngx/pull/7756))
|
||||
- Enhancement: set Django SESSION_EXPIRE_AT_BROWSER_CLOSE from PAPERLESS_ACCOUNT_SESSION_REMEMBER [@shamoon](https://github.com/shamoon) ([#7748](https://github.com/paperless-ngx/paperless-ngx/pull/7748))
|
||||
- Enhancement: allow setting session cookie age [@shamoon](https://github.com/shamoon) ([#7743](https://github.com/paperless-ngx/paperless-ngx/pull/7743))
|
||||
- Feature: copy workflows and mail rules, improve layout [@shamoon](https://github.com/shamoon) ([#7727](https://github.com/paperless-ngx/paperless-ngx/pull/7727))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: remove space before my profile button in dropdown [@tooomm](https://github.com/tooomm) ([#7963](https://github.com/paperless-ngx/paperless-ngx/pull/7963))
|
||||
- Fix: v2.13.0 RC1 - Handling of Nones when using custom fields in filepath templating [@stumpylog](https://github.com/stumpylog) ([#7933](https://github.com/paperless-ngx/paperless-ngx/pull/7933))
|
||||
- Fix: v2.13.0 RC1 - trigger move and rename after CustomFieldInstance saved [@shamoon](https://github.com/shamoon) ([#7927](https://github.com/paperless-ngx/paperless-ngx/pull/7927))
|
||||
- Fix: v2.13.0 RC1 - increase field max lengths to accommodate larger tokens [@shamoon](https://github.com/shamoon) ([#7916](https://github.com/paperless-ngx/paperless-ngx/pull/7916))
|
||||
- Fix: preserve text linebreaks in doc edit [@shamoon](https://github.com/shamoon) ([#7908](https://github.com/paperless-ngx/paperless-ngx/pull/7908))
|
||||
- Fix: only show colon on cards if correspondent and title shown [@shamoon](https://github.com/shamoon) ([#7893](https://github.com/paperless-ngx/paperless-ngx/pull/7893))
|
||||
- Fix: Allow ASN values of 0 from barcodes [@stumpylog](https://github.com/stumpylog) ([#7878](https://github.com/paperless-ngx/paperless-ngx/pull/7878))
|
||||
- Fix: fix auto-dismiss completed tasks on open document [@shamoon](https://github.com/shamoon) ([#7869](https://github.com/paperless-ngx/paperless-ngx/pull/7869))
|
||||
- Fix: trigger change warning for saved views with default fields if changed [@shamoon](https://github.com/shamoon) ([#7865](https://github.com/paperless-ngx/paperless-ngx/pull/7865))
|
||||
- Fix: hidden canvas element causes scroll bug [@shamoon](https://github.com/shamoon) ([#7770](https://github.com/paperless-ngx/paperless-ngx/pull/7770))
|
||||
- Fix: handle overflowing dropdowns on mobile [@shamoon](https://github.com/shamoon) ([#7758](https://github.com/paperless-ngx/paperless-ngx/pull/7758))
|
||||
- Fix: chrome scrolling in >= 129 [@shamoon](https://github.com/shamoon) ([#7738](https://github.com/paperless-ngx/paperless-ngx/pull/7738))
|
||||
|
||||
### Maintenance
|
||||
|
||||
- Enhancement: use apt only when needed docker-entrypoint.sh [@gawa971](https://github.com/gawa971) ([#7756](https://github.com/paperless-ngx/paperless-ngx/pull/7756))
|
||||
|
||||
### Dependencies
|
||||
|
||||
<details>
|
||||
<summary>10 changes</summary>
|
||||
|
||||
- Chore(deps-dev): Bump @codecov/webpack-plugin from 1.0.1 to 1.2.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#7830](https://github.com/paperless-ngx/paperless-ngx/pull/7830))
|
||||
- Chore(deps-dev): Bump @types/node from 22.5.2 to 22.7.4 in /src-ui [@dependabot](https://github.com/dependabot) ([#7829](https://github.com/paperless-ngx/paperless-ngx/pull/7829))
|
||||
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#7827](https://github.com/paperless-ngx/paperless-ngx/pull/7827))
|
||||
- Chore(deps-dev): Bump the frontend-jest-dependencies group in /src-ui with 2 updates [@dependabot](https://github.com/dependabot) ([#7826](https://github.com/paperless-ngx/paperless-ngx/pull/7826))
|
||||
- Chore(deps-dev): Bump @playwright/test from 1.46.1 to 1.47.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#7828](https://github.com/paperless-ngx/paperless-ngx/pull/7828))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 21 updates [@dependabot](https://github.com/dependabot) ([#7825](https://github.com/paperless-ngx/paperless-ngx/pull/7825))
|
||||
- Chore: Upgrades OCRMyPDF to v16 [@stumpylog](https://github.com/stumpylog) ([#7815](https://github.com/paperless-ngx/paperless-ngx/pull/7815))
|
||||
- Chore: Upgrades the Docker image to use Python 3.12 [@stumpylog](https://github.com/stumpylog) ([#7796](https://github.com/paperless-ngx/paperless-ngx/pull/7796))
|
||||
- Chore: Upgrade Django to 5.1 [@stumpylog](https://github.com/stumpylog) ([#7795](https://github.com/paperless-ngx/paperless-ngx/pull/7795))
|
||||
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7723](https://github.com/paperless-ngx/paperless-ngx/pull/7723))
|
||||
</details>
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>43 changes</summary>
|
||||
|
||||
- Change: Use a TextField for the storage path field [@stumpylog](https://github.com/stumpylog) ([#7967](https://github.com/paperless-ngx/paperless-ngx/pull/7967))
|
||||
- Fix: remove space before my profile button in dropdown [@tooomm](https://github.com/tooomm) ([#7963](https://github.com/paperless-ngx/paperless-ngx/pull/7963))
|
||||
- Enhancement: QoL, auto-focus default select field in custom field dropdown [@shamoon](https://github.com/shamoon) ([#7961](https://github.com/paperless-ngx/paperless-ngx/pull/7961))
|
||||
- Change: open not edit [@shamoon](https://github.com/shamoon) ([#7942](https://github.com/paperless-ngx/paperless-ngx/pull/7942))
|
||||
- Fix: v2.13.0 RC1 - Handling of Nones when using custom fields in filepath templating [@stumpylog](https://github.com/stumpylog) ([#7933](https://github.com/paperless-ngx/paperless-ngx/pull/7933))
|
||||
- Fix: v2.13.0 RC1 - trigger move and rename after CustomFieldInstance saved [@shamoon](https://github.com/shamoon) ([#7927](https://github.com/paperless-ngx/paperless-ngx/pull/7927))
|
||||
- Fix: v2.13.0 RC1 - increase field max lengths to accommodate larger tokens [@shamoon](https://github.com/shamoon) ([#7916](https://github.com/paperless-ngx/paperless-ngx/pull/7916))
|
||||
- Enhancement: support retain barcode split pages [@shamoon](https://github.com/shamoon) ([#7912](https://github.com/paperless-ngx/paperless-ngx/pull/7912))
|
||||
- Fix: preserve text linebreaks in doc edit [@shamoon](https://github.com/shamoon) ([#7908](https://github.com/paperless-ngx/paperless-ngx/pull/7908))
|
||||
- Enhancement: don't wait for doc API to load preview [@shamoon](https://github.com/shamoon) ([#7894](https://github.com/paperless-ngx/paperless-ngx/pull/7894))
|
||||
- Fix: only show colon on cards if correspondent and title shown [@shamoon](https://github.com/shamoon) ([#7893](https://github.com/paperless-ngx/paperless-ngx/pull/7893))
|
||||
- Feature: OAuth2 Gmail and Outlook email support [@shamoon](https://github.com/shamoon) ([#7866](https://github.com/paperless-ngx/paperless-ngx/pull/7866))
|
||||
- Chore: Consolidate workflow logic [@shamoon](https://github.com/shamoon) ([#7880](https://github.com/paperless-ngx/paperless-ngx/pull/7880))
|
||||
- Enhancement: live preview of storage path [@shamoon](https://github.com/shamoon) ([#7870](https://github.com/paperless-ngx/paperless-ngx/pull/7870))
|
||||
- Fix: Allow ASN values of 0 from barcodes [@stumpylog](https://github.com/stumpylog) ([#7878](https://github.com/paperless-ngx/paperless-ngx/pull/7878))
|
||||
- Fix: fix auto-dismiss completed tasks on open document [@shamoon](https://github.com/shamoon) ([#7869](https://github.com/paperless-ngx/paperless-ngx/pull/7869))
|
||||
- Fix: trigger change warning for saved views with default fields if changed [@shamoon](https://github.com/shamoon) ([#7865](https://github.com/paperless-ngx/paperless-ngx/pull/7865))
|
||||
- Feature: Enhanced templating for filename format [@stumpylog](https://github.com/stumpylog) ([#7836](https://github.com/paperless-ngx/paperless-ngx/pull/7836))
|
||||
- Enhancement: management list button improvements [@shamoon](https://github.com/shamoon) ([#7848](https://github.com/paperless-ngx/paperless-ngx/pull/7848))
|
||||
- Enhancement: check for mail destination directory, log post-consume errors [@mrichtarsky](https://github.com/mrichtarsky) ([#7808](https://github.com/paperless-ngx/paperless-ngx/pull/7808))
|
||||
- Feature: custom fields queries [@shamoon](https://github.com/shamoon) ([#7761](https://github.com/paperless-ngx/paperless-ngx/pull/7761))
|
||||
- Chore(deps-dev): Bump @codecov/webpack-plugin from 1.0.1 to 1.2.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#7830](https://github.com/paperless-ngx/paperless-ngx/pull/7830))
|
||||
- Chore(deps-dev): Bump @types/node from 22.5.2 to 22.7.4 in /src-ui [@dependabot](https://github.com/dependabot) ([#7829](https://github.com/paperless-ngx/paperless-ngx/pull/7829))
|
||||
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#7827](https://github.com/paperless-ngx/paperless-ngx/pull/7827))
|
||||
- Chore(deps-dev): Bump the frontend-jest-dependencies group in /src-ui with 2 updates [@dependabot](https://github.com/dependabot) ([#7826](https://github.com/paperless-ngx/paperless-ngx/pull/7826))
|
||||
- Chore(deps-dev): Bump @playwright/test from 1.46.1 to 1.47.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#7828](https://github.com/paperless-ngx/paperless-ngx/pull/7828))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 21 updates [@dependabot](https://github.com/dependabot) ([#7825](https://github.com/paperless-ngx/paperless-ngx/pull/7825))
|
||||
- Chore: Upgrades OCRMyPDF to v16 [@stumpylog](https://github.com/stumpylog) ([#7815](https://github.com/paperless-ngx/paperless-ngx/pull/7815))
|
||||
- Enhancement: workflow overview toggle enable button [@shamoon](https://github.com/shamoon) ([#7818](https://github.com/paperless-ngx/paperless-ngx/pull/7818))
|
||||
- Enhancement: disable-able mail rules, add toggle to overview [@shamoon](https://github.com/shamoon) ([#7810](https://github.com/paperless-ngx/paperless-ngx/pull/7810))
|
||||
- Chore: Upgrades the Docker image to use Python 3.12 [@stumpylog](https://github.com/stumpylog) ([#7796](https://github.com/paperless-ngx/paperless-ngx/pull/7796))
|
||||
- Chore: Upgrade Django to 5.1 [@stumpylog](https://github.com/stumpylog) ([#7795](https://github.com/paperless-ngx/paperless-ngx/pull/7795))
|
||||
- Chore: Drop Python 3.9 support [@stumpylog](https://github.com/stumpylog) ([#7774](https://github.com/paperless-ngx/paperless-ngx/pull/7774))
|
||||
- Feature: auto-clean some invalid pdfs [@shamoon](https://github.com/shamoon) ([#7651](https://github.com/paperless-ngx/paperless-ngx/pull/7651))
|
||||
- Feature: page count [@s0llvan](https://github.com/s0llvan) ([#7750](https://github.com/paperless-ngx/paperless-ngx/pull/7750))
|
||||
- Fix: hidden canvas element causes scroll bug [@shamoon](https://github.com/shamoon) ([#7770](https://github.com/paperless-ngx/paperless-ngx/pull/7770))
|
||||
- Enhancement: compactify dates dropdown [@shamoon](https://github.com/shamoon) ([#7759](https://github.com/paperless-ngx/paperless-ngx/pull/7759))
|
||||
- Fix: handle overflowing dropdowns on mobile [@shamoon](https://github.com/shamoon) ([#7758](https://github.com/paperless-ngx/paperless-ngx/pull/7758))
|
||||
- Enhancement: set Django SESSION_EXPIRE_AT_BROWSER_CLOSE from PAPERLESS_ACCOUNT_SESSION_REMEMBER [@shamoon](https://github.com/shamoon) ([#7748](https://github.com/paperless-ngx/paperless-ngx/pull/7748))
|
||||
- Enhancement: allow setting session cookie age [@shamoon](https://github.com/shamoon) ([#7743](https://github.com/paperless-ngx/paperless-ngx/pull/7743))
|
||||
- Fix: chrome scrolling in >= 129 [@shamoon](https://github.com/shamoon) ([#7738](https://github.com/paperless-ngx/paperless-ngx/pull/7738))
|
||||
- Feature: copy workflows and mail rules, improve layout [@shamoon](https://github.com/shamoon) ([#7727](https://github.com/paperless-ngx/paperless-ngx/pull/7727))
|
||||
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7723](https://github.com/paperless-ngx/paperless-ngx/pull/7723))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 2.12.1
|
||||
|
||||
### Bug Fixes
|
||||
|
@@ -18,6 +18,7 @@
|
||||
# Paths and folders
|
||||
|
||||
#PAPERLESS_CONSUMPTION_DIR=../consume
|
||||
#PAPERLESS_CONSUMPTION_FAILED_DIR=../consume/failed
|
||||
#PAPERLESS_DATA_DIR=../data
|
||||
#PAPERLESS_EMPTY_TRASH_DIR=
|
||||
#PAPERLESS_MEDIA_ROOT=../media
|
||||
|
@@ -1994,120 +1994,141 @@
|
||||
<context context-type="linenumber">72</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7934833136974560675" datatype="html">
|
||||
<source>Retry</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context>
|
||||
<context context-type="linenumber">86</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1536087519743707362" datatype="html">
|
||||
<source>Dismiss</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context>
|
||||
<context context-type="linenumber">85</context>
|
||||
<context context-type="linenumber">90</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">68</context>
|
||||
<context context-type="linenumber">71</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2134950584701094962" datatype="html">
|
||||
<source>Open Document</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context>
|
||||
<context context-type="linenumber">90</context>
|
||||
<context context-type="linenumber">95</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="428536141871853903" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =1 {One <x id="INTERPOLATION"/> task} other {<x id="INTERPOLATION_1"/> total <x id="INTERPOLATION"/> tasks}}</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context>
|
||||
<context context-type="linenumber">109</context>
|
||||
<context context-type="linenumber">114</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1943508481059904274" datatype="html">
|
||||
<source> (<x id="INTERPOLATION" equiv-text="{{selectedTasks.size}}"/> selected)</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context>
|
||||
<context context-type="linenumber">111</context>
|
||||
<context context-type="linenumber">116</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5639839509673911668" datatype="html">
|
||||
<source>Failed<x id="START_BLOCK_IF" equiv-text="@if (tasksService.failedFileTasks.length > 0) {"/><x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="badge bg-danger ms-2">"/><x id="INTERPOLATION" equiv-text="{{tasksService.failedFileTasks.length}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/><x id="CLOSE_BLOCK_IF" equiv-text="}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context>
|
||||
<context context-type="linenumber">123,125</context>
|
||||
<context context-type="linenumber">128,130</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8210778930307085868" datatype="html">
|
||||
<source>Complete<x id="START_BLOCK_IF" equiv-text="@if (tasksService.completedFileTasks.length > 0) {"/><x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="badge bg-secondary ms-2">"/><x id="INTERPOLATION" equiv-text="{{tasksService.completedFileTasks.length}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/><x id="CLOSE_BLOCK_IF" equiv-text="}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context>
|
||||
<context context-type="linenumber">131,133</context>
|
||||
<context context-type="linenumber">136,138</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3522801015717851360" datatype="html">
|
||||
<source>Started<x id="START_BLOCK_IF" equiv-text="@if (tasksService.startedFileTasks.length > 0) {"/><x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="badge bg-secondary ms-2">"/><x id="INTERPOLATION" equiv-text="{{tasksService.startedFileTasks.length}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/><x id="CLOSE_BLOCK_IF" equiv-text="}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context>
|
||||
<context context-type="linenumber">139,141</context>
|
||||
<context context-type="linenumber">144,146</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2341807459308874922" datatype="html">
|
||||
<source>Queued<x id="START_BLOCK_IF" equiv-text="@if (tasksService.queuedFileTasks.length > 0) {"/><x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="badge bg-secondary ms-2">"/><x id="INTERPOLATION" equiv-text="{{tasksService.queuedFileTasks.length}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/><x id="CLOSE_BLOCK_IF" equiv-text="}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context>
|
||||
<context context-type="linenumber">147,149</context>
|
||||
<context context-type="linenumber">152,154</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5404910960991552159" datatype="html">
|
||||
<source>Dismiss selected</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">31</context>
|
||||
<context context-type="linenumber">33</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8829078752502782653" datatype="html">
|
||||
<source>Dismiss all</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">32</context>
|
||||
<context context-type="linenumber">34</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1323591410517879795" datatype="html">
|
||||
<source>Confirm Dismiss All</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">65</context>
|
||||
<context context-type="linenumber">68</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4157200209636243740" datatype="html">
|
||||
<source>Dismiss all <x id="PH" equiv-text="tasks.size"/> tasks?</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">66</context>
|
||||
<context context-type="linenumber">69</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7611027432301841688" datatype="html">
|
||||
<source>Retrying task...</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">92</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5445438607105804721" datatype="html">
|
||||
<source>Failed to retry task</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">95</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="9011556615675272238" datatype="html">
|
||||
<source>queued</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">135</context>
|
||||
<context context-type="linenumber">149</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6415892379431855826" datatype="html">
|
||||
<source>started</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">137</context>
|
||||
<context context-type="linenumber">151</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7510279840486540181" datatype="html">
|
||||
<source>completed</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">139</context>
|
||||
<context context-type="linenumber">153</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4083337005045748464" datatype="html">
|
||||
<source>failed</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context>
|
||||
<context context-type="linenumber">141</context>
|
||||
<context context-type="linenumber">155</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3418677553313974490" datatype="html">
|
||||
|
4079
src-ui/package-lock.json
generated
4079
src-ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,54 +11,54 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/cdk": "^18.2.11",
|
||||
"@angular/common": "~18.2.10",
|
||||
"@angular/compiler": "~18.2.10",
|
||||
"@angular/core": "~18.2.10",
|
||||
"@angular/forms": "~18.2.10",
|
||||
"@angular/localize": "~18.2.10",
|
||||
"@angular/platform-browser": "~18.2.10",
|
||||
"@angular/platform-browser-dynamic": "~18.2.10",
|
||||
"@angular/router": "~18.2.10",
|
||||
"@angular/cdk": "^18.2.6",
|
||||
"@angular/common": "~18.2.6",
|
||||
"@angular/compiler": "~18.2.6",
|
||||
"@angular/core": "~18.2.6",
|
||||
"@angular/forms": "~18.2.6",
|
||||
"@angular/localize": "~18.2.6",
|
||||
"@angular/platform-browser": "~18.2.6",
|
||||
"@angular/platform-browser-dynamic": "~18.2.6",
|
||||
"@angular/router": "~18.2.6",
|
||||
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
|
||||
"@ng-select/ng-select": "^13.9.1",
|
||||
"@ng-select/ng-select": "^13.9.0",
|
||||
"@ngneat/dirty-check-forms": "^3.0.3",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"bootstrap": "^5.3.3",
|
||||
"file-saver": "^2.0.5",
|
||||
"mime-names": "^1.0.0",
|
||||
"ng2-pdf-viewer": "^10.3.4",
|
||||
"ng2-pdf-viewer": "^10.3.1",
|
||||
"ngx-bootstrap-icons": "^1.9.3",
|
||||
"ngx-color": "^9.0.0",
|
||||
"ngx-cookie-service": "^18.0.0",
|
||||
"ngx-file-drop": "^16.0.0",
|
||||
"ngx-ui-tour-ng-bootstrap": "^15.0.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"tslib": "^2.8.1",
|
||||
"uuid": "^11.0.2",
|
||||
"tslib": "^2.7.0",
|
||||
"uuid": "^10.0.0",
|
||||
"zone.js": "^0.14.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-builders/custom-webpack": "^18.0.0",
|
||||
"@angular-builders/jest": "^18.0.0",
|
||||
"@angular-devkit/build-angular": "^18.2.2",
|
||||
"@angular-devkit/core": "^18.2.11",
|
||||
"@angular-devkit/schematics": "^18.2.11",
|
||||
"@angular-eslint/builder": "18.4.0",
|
||||
"@angular-eslint/eslint-plugin": "18.4.0",
|
||||
"@angular-eslint/eslint-plugin-template": "18.4.0",
|
||||
"@angular-eslint/schematics": "18.4.0",
|
||||
"@angular-eslint/template-parser": "18.4.0",
|
||||
"@angular/cli": "~18.2.11",
|
||||
"@angular-devkit/core": "^18.2.6",
|
||||
"@angular-devkit/schematics": "^18.2.6",
|
||||
"@angular-eslint/builder": "18.3.1",
|
||||
"@angular-eslint/eslint-plugin": "18.3.1",
|
||||
"@angular-eslint/eslint-plugin-template": "18.3.1",
|
||||
"@angular-eslint/schematics": "18.3.1",
|
||||
"@angular-eslint/template-parser": "18.3.1",
|
||||
"@angular/cli": "~18.2.6",
|
||||
"@angular/compiler-cli": "~18.2.2",
|
||||
"@codecov/webpack-plugin": "^1.2.1",
|
||||
"@playwright/test": "^1.48.2",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/node": "^22.8.6",
|
||||
"@typescript-eslint/eslint-plugin": "^8.12.2",
|
||||
"@typescript-eslint/parser": "^8.12.2",
|
||||
"@codecov/webpack-plugin": "^1.2.0",
|
||||
"@playwright/test": "^1.47.2",
|
||||
"@types/jest": "^29.5.13",
|
||||
"@types/node": "^22.7.4",
|
||||
"@typescript-eslint/eslint-plugin": "^8.8.0",
|
||||
"@typescript-eslint/parser": "^8.8.0",
|
||||
"@typescript-eslint/utils": "^8.0.0",
|
||||
"eslint": "^9.14.0",
|
||||
"eslint": "^9.11.1",
|
||||
"jest": "29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-preset-angular": "^14.2.4",
|
||||
|
@@ -81,6 +81,9 @@
|
||||
</td>
|
||||
<td scope="row">
|
||||
<div class="btn-group" role="group">
|
||||
@if (task.status === PaperlessTaskStatus.Failed) {
|
||||
<ng-container *ngTemplateOutlet="retryDropdown; context: { task: task }"></ng-container>
|
||||
}
|
||||
<button class="btn btn-sm btn-outline-secondary" (click)="dismissTask(task); $event.stopPropagation();" *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.PaperlessTask }">
|
||||
<i-bs name="check"></i-bs> <ng-container i18n>Dismiss</ng-container>
|
||||
</button>
|
||||
@@ -153,3 +156,25 @@
|
||||
</li>
|
||||
</ul>
|
||||
<div [ngbNavOutlet]="nav"></div>
|
||||
|
||||
<ng-template #retryDropdown let-task="task">
|
||||
<div ngbDropdown>
|
||||
<button class="btn btn-sm btn-outline-primary" (click)="$event.stopImmediatePropagation()" ngbDropdownToggle>
|
||||
<i-bs name="arrow-repeat"></i-bs> <ng-container i18n>Retry</ng-container>
|
||||
</button>
|
||||
<div ngbDropdownMenu class="shadow retry-dropdown">
|
||||
<div class="p-2">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item small" i18n>
|
||||
<pngx-input-check [(ngModel)]="retryClean" i18n-title title="Attempt to clean pdf"></pngx-input-check>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="d-flex justify-content-end">
|
||||
<button class="btn btn-sm btn-outline-primary" (click)="retryTask(task); $event.stopPropagation();">
|
||||
<ng-container i18n>Proceed</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@@ -26,3 +26,7 @@ pre {
|
||||
max-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.retry-dropdown {
|
||||
width: 300px;
|
||||
}
|
||||
|
@@ -31,6 +31,9 @@ import { PermissionsGuard } from 'src/app/guards/permissions.guard'
|
||||
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
||||
import { ToastService } from 'src/app/services/toast.service'
|
||||
import { of, throwError } from 'rxjs'
|
||||
import { CheckComponent } from '../../common/input/check/check.component'
|
||||
|
||||
const tasks: PaperlessTask[] = [
|
||||
{
|
||||
@@ -115,6 +118,7 @@ describe('TasksComponent', () => {
|
||||
let modalService: NgbModal
|
||||
let router: Router
|
||||
let httpTestingController: HttpTestingController
|
||||
let toastService: ToastService
|
||||
let reloadSpy
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -125,6 +129,7 @@ describe('TasksComponent', () => {
|
||||
IfPermissionsDirective,
|
||||
CustomDatePipe,
|
||||
ConfirmDialogComponent,
|
||||
CheckComponent,
|
||||
],
|
||||
imports: [
|
||||
NgbModule,
|
||||
@@ -152,6 +157,7 @@ describe('TasksComponent', () => {
|
||||
httpTestingController = TestBed.inject(HttpTestingController)
|
||||
modalService = TestBed.inject(NgbModal)
|
||||
router = TestBed.inject(Router)
|
||||
toastService = TestBed.inject(ToastService)
|
||||
fixture = TestBed.createComponent(TasksComponent)
|
||||
component = fixture.componentInstance
|
||||
jest.useFakeTimers()
|
||||
@@ -173,8 +179,10 @@ describe('TasksComponent', () => {
|
||||
`Failed${currentTasksLength}`
|
||||
)
|
||||
expect(
|
||||
fixture.debugElement.queryAll(By.css('table input[type="checkbox"]'))
|
||||
).toHaveLength(currentTasksLength + 1)
|
||||
fixture.debugElement.queryAll(
|
||||
By.css('table td > .form-check input[type="checkbox"]')
|
||||
)
|
||||
).toHaveLength(currentTasksLength)
|
||||
|
||||
currentTasksLength = tasks.filter(
|
||||
(t) => t.status === PaperlessTaskStatus.Complete
|
||||
@@ -289,4 +297,20 @@ describe('TasksComponent', () => {
|
||||
jest.advanceTimersByTime(6000)
|
||||
expect(reloadSpy).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('should retry a task, show toast on error or success', () => {
|
||||
const retrySpy = jest.spyOn(tasksService, 'retryTask')
|
||||
const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
|
||||
const toastErrorSpy = jest.spyOn(toastService, 'showError')
|
||||
retrySpy.mockReturnValueOnce(of({ task_id: '123' }))
|
||||
component.retryTask(tasks[0])
|
||||
expect(retrySpy).toHaveBeenCalledWith(tasks[0], false)
|
||||
expect(toastInfoSpy).toHaveBeenCalledWith('Retrying task...')
|
||||
retrySpy.mockReturnValueOnce(throwError(() => new Error('test')))
|
||||
component.retryTask(tasks[0])
|
||||
expect(toastErrorSpy).toHaveBeenCalledWith(
|
||||
'Failed to retry task',
|
||||
new Error('test')
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@@ -2,10 +2,11 @@ import { Component, OnInit, OnDestroy } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { first } from 'rxjs'
|
||||
import { PaperlessTask } from 'src/app/data/paperless-task'
|
||||
import { PaperlessTask, PaperlessTaskStatus } from 'src/app/data/paperless-task'
|
||||
import { TasksService } from 'src/app/services/tasks.service'
|
||||
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
|
||||
import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
|
||||
import { ToastService } from 'src/app/services/toast.service'
|
||||
|
||||
@Component({
|
||||
selector: 'pngx-tasks',
|
||||
@@ -16,6 +17,7 @@ export class TasksComponent
|
||||
extends ComponentWithPermissions
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
public PaperlessTaskStatus = PaperlessTaskStatus
|
||||
public activeTab: string
|
||||
public selectedTasks: Set<number> = new Set()
|
||||
public togggleAll: boolean = false
|
||||
@@ -26,6 +28,8 @@ export class TasksComponent
|
||||
|
||||
public autoRefreshInterval: any
|
||||
|
||||
public retryClean: boolean = false
|
||||
|
||||
get dismissButtonText(): string {
|
||||
return this.selectedTasks.size > 0
|
||||
? $localize`Dismiss selected`
|
||||
@@ -35,6 +39,7 @@ export class TasksComponent
|
||||
constructor(
|
||||
public tasksService: TasksService,
|
||||
private modalService: NgbModal,
|
||||
private toastService: ToastService,
|
||||
private readonly router: Router
|
||||
) {
|
||||
super()
|
||||
@@ -83,6 +88,17 @@ export class TasksComponent
|
||||
this.router.navigate(['documents', task.related_document])
|
||||
}
|
||||
|
||||
retryTask(task: PaperlessTask) {
|
||||
this.tasksService.retryTask(task, this.retryClean).subscribe({
|
||||
next: () => {
|
||||
this.toastService.showInfo($localize`Retrying task...`)
|
||||
},
|
||||
error: (e) => {
|
||||
this.toastService.showError($localize`Failed to retry task`, e)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
expandTask(task: PaperlessTask) {
|
||||
this.expandedTask = this.expandedTask == task.id ? undefined : task.id
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@
|
||||
@for (item of selectionModel.itemsSorted | filter: filterText:'name'; track item; let i = $index) {
|
||||
@if (allowSelectNone || item.id) {
|
||||
<pngx-toggleable-dropdown-button
|
||||
[item]="item" [hideCount]="hideCount(item)" [state]="selectionModel.get(item.id)" [count]="getUpdatedDocumentCount(item.id)" (toggled)="selectionModel.toggle(item.id)" (exclude)="excludeClicked(item.id)" (click)="setButtonItemIndex(i - 1)" [disabled]="disabled">
|
||||
[item]="item" [hideCount]="hideCount(item)" [state]="selectionModel.get(item.id)" [count]="getUpdatedDocumentCount(item.id)" (toggle)="selectionModel.toggle(item.id)" (exclude)="excludeClicked(item.id)" (click)="setButtonItemIndex(i - 1)" [disabled]="disabled">
|
||||
</pngx-toggleable-dropdown-button>
|
||||
}
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@ describe('ToggleableDropdownButtonComponent', () => {
|
||||
let toggleResult
|
||||
component.state = ToggleableItemState.Selected
|
||||
component.exclude.subscribe(() => (excludeResult = true))
|
||||
component.toggled.subscribe(() => (toggleResult = true))
|
||||
component.toggle.subscribe(() => (toggleResult = true))
|
||||
const button = fixture.nativeElement.querySelector('button')
|
||||
button.dispatchEvent(new MouseEvent('click'))
|
||||
expect(excludeResult).toBeTruthy()
|
||||
@@ -70,7 +70,7 @@ describe('ToggleableDropdownButtonComponent', () => {
|
||||
let toggleResult
|
||||
component.state = ToggleableItemState.Excluded
|
||||
component.exclude.subscribe(() => (excludeResult = true))
|
||||
component.toggled.subscribe(() => (toggleResult = true))
|
||||
component.toggle.subscribe(() => (toggleResult = true))
|
||||
const button = fixture.nativeElement.querySelector('button')
|
||||
button.dispatchEvent(new MouseEvent('click'))
|
||||
expect(excludeResult).toBeFalsy()
|
||||
|
@@ -30,7 +30,7 @@ export class ToggleableDropdownButtonComponent {
|
||||
hideCount: boolean = false
|
||||
|
||||
@Output()
|
||||
toggled = new EventEmitter()
|
||||
toggle = new EventEmitter()
|
||||
|
||||
@Output()
|
||||
exclude = new EventEmitter()
|
||||
@@ -43,7 +43,7 @@ export class ToggleableDropdownButtonComponent {
|
||||
if (this.state == ToggleableItemState.Selected) {
|
||||
this.exclude.emit()
|
||||
} else {
|
||||
this.toggled.emit()
|
||||
this.toggle.emit()
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
} @else {
|
||||
@if (renderAsObject) {
|
||||
<object [data]="previewURL | safeUrl" width="100%" class="bg-light" [class.p-2]="!isPdf" [class.pdf]="isPdf"></object>
|
||||
<object [data]="previewURL | safeUrl" width="100%" class="bg-light" [class.p-2]="!isPdf"></object>
|
||||
} @else {
|
||||
@if (requiresPassword) {
|
||||
<div class="w-100 h-100 position-relative">
|
||||
|
@@ -17,7 +17,7 @@
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
|
||||
object:not(.pdf) {
|
||||
object {
|
||||
mix-blend-mode: difference;
|
||||
&.p-2 {
|
||||
padding: 0 !important;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<div class="card mb-3 shadow-sm bg-light" [class.card-selected]="selected" [class.document-card]="selectable" [class.popover-hidden]="popoverHidden" (mouseleave)="mouseLeaveCard()">
|
||||
<div class="row g-0">
|
||||
<div class="col-md-2 doc-img-container rounded-start" (click)="this.toggleSelected.emit($event)" (dblclick)="dblClickDocument.emit()">
|
||||
<div class="col-md-2 doc-img-background rounded-start" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)" (dblclick)="dblClickDocument.emit()">
|
||||
<img [src]="getThumbUrl()" class="card-img doc-img border-end rounded-start" [class.inverted]="getIsThumbInverted()">
|
||||
|
||||
<div class="border-end border-bottom bg-light document-card-check">
|
||||
|
@@ -2,7 +2,7 @@
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.doc-img-container {
|
||||
.doc-img-background {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
object-position: top left;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
@@ -48,6 +49,18 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.card-selected {
|
||||
border-color: var(--bs-primary);
|
||||
|
||||
.document-card-check {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.doc-img-background-selected {
|
||||
background-color: var(--pngx-primary-faded);
|
||||
}
|
||||
|
||||
.card-info {
|
||||
line-height: 1;
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<div class="col p-2 h-100">
|
||||
<div class="card h-100 shadow-sm document-card" [class.card-selected]="selected" [class.popover-hidden]="popoverHidden" (mouseleave)="mouseLeaveCard()">
|
||||
<div class="border-bottom doc-img-container" (click)="this.toggleSelected.emit($event)" (dblclick)="dblClickDocument.emit(this)">
|
||||
<img class="card-img doc-img" [class.inverted]="getIsThumbInverted()" [src]="getThumbUrl()">
|
||||
<div class="border-bottom doc-img-container" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)" (dblclick)="dblClickDocument.emit(this)">
|
||||
<img class="card-img doc-img rounded-top" [class.inverted]="getIsThumbInverted()" [src]="getThumbUrl()">
|
||||
|
||||
<div class="border-end border-bottom bg-light py-1 px-2 document-card-check">
|
||||
<div class="form-check">
|
||||
|
@@ -6,6 +6,7 @@
|
||||
object-fit: cover;
|
||||
object-position: top left;
|
||||
height: 180px;
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.document-card-check {
|
||||
@@ -39,6 +40,18 @@
|
||||
top: 142px;
|
||||
}
|
||||
|
||||
.card-selected {
|
||||
border-color:var(--bs-primary);
|
||||
|
||||
.document-card-check {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.doc-img-background-selected {
|
||||
background-color: var(--pngx-primary-faded);
|
||||
}
|
||||
|
||||
.card-info {
|
||||
line-height: 1;
|
||||
|
||||
|
@@ -1204,7 +1204,7 @@ describe('FilterEditorComponent', () => {
|
||||
const tagButton = tagsFilterableDropdown.queryAll(
|
||||
By.directive(ToggleableDropdownButtonComponent)
|
||||
)[0]
|
||||
tagButton.triggerEventHandler('toggled')
|
||||
tagButton.triggerEventHandler('toggle')
|
||||
fixture.detectChanges()
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
@@ -1222,8 +1222,8 @@ describe('FilterEditorComponent', () => {
|
||||
const tagButtons = tagsFilterableDropdown.queryAll(
|
||||
By.directive(ToggleableDropdownButtonComponent)
|
||||
)
|
||||
tagButtons[1].triggerEventHandler('toggled')
|
||||
tagButtons[2].triggerEventHandler('toggled')
|
||||
tagButtons[1].triggerEventHandler('toggle')
|
||||
tagButtons[2].triggerEventHandler('toggle')
|
||||
fixture.detectChanges()
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
@@ -1273,8 +1273,8 @@ describe('FilterEditorComponent', () => {
|
||||
const correspondentButtons = correspondentsFilterableDropdown.queryAll(
|
||||
By.directive(ToggleableDropdownButtonComponent)
|
||||
)
|
||||
correspondentButtons[1].triggerEventHandler('toggled')
|
||||
correspondentButtons[2].triggerEventHandler('toggled')
|
||||
correspondentButtons[1].triggerEventHandler('toggle')
|
||||
correspondentButtons[2].triggerEventHandler('toggle')
|
||||
fixture.detectChanges()
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
@@ -1312,7 +1312,7 @@ describe('FilterEditorComponent', () => {
|
||||
const notAssignedButton = correspondentsFilterableDropdown.queryAll(
|
||||
By.directive(ToggleableDropdownButtonComponent)
|
||||
)[0]
|
||||
notAssignedButton.triggerEventHandler('toggled')
|
||||
notAssignedButton.triggerEventHandler('toggle')
|
||||
fixture.detectChanges()
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
@@ -1330,8 +1330,8 @@ describe('FilterEditorComponent', () => {
|
||||
const documentTypeButtons = documentTypesFilterableDropdown.queryAll(
|
||||
By.directive(ToggleableDropdownButtonComponent)
|
||||
)
|
||||
documentTypeButtons[1].triggerEventHandler('toggled')
|
||||
documentTypeButtons[2].triggerEventHandler('toggled')
|
||||
documentTypeButtons[1].triggerEventHandler('toggle')
|
||||
documentTypeButtons[2].triggerEventHandler('toggle')
|
||||
fixture.detectChanges()
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
@@ -1369,7 +1369,7 @@ describe('FilterEditorComponent', () => {
|
||||
const notAssignedButton = docTypesFilterableDropdown.queryAll(
|
||||
By.directive(ToggleableDropdownButtonComponent)
|
||||
)[0]
|
||||
notAssignedButton.triggerEventHandler('toggled')
|
||||
notAssignedButton.triggerEventHandler('toggle')
|
||||
fixture.detectChanges()
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
@@ -1387,8 +1387,8 @@ describe('FilterEditorComponent', () => {
|
||||
const storagePathButtons = storagePathFilterableDropdown.queryAll(
|
||||
By.directive(ToggleableDropdownButtonComponent)
|
||||
)
|
||||
storagePathButtons[1].triggerEventHandler('toggled')
|
||||
storagePathButtons[2].triggerEventHandler('toggled')
|
||||
storagePathButtons[1].triggerEventHandler('toggle')
|
||||
storagePathButtons[2].triggerEventHandler('toggle')
|
||||
fixture.detectChanges()
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
@@ -1426,7 +1426,7 @@ describe('FilterEditorComponent', () => {
|
||||
const notAssignedButton = storagePathsFilterableDropdown.queryAll(
|
||||
By.directive(ToggleableDropdownButtonComponent)
|
||||
)[0]
|
||||
notAssignedButton.triggerEventHandler('toggled')
|
||||
notAssignedButton.triggerEventHandler('toggle')
|
||||
fixture.detectChanges()
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
|
@@ -599,17 +599,14 @@ describe('DocumentListViewService', () => {
|
||||
it('should not filter out custom fields if settings not initialized', () => {
|
||||
const customFields = ['custom_field_1', 'custom_field_2']
|
||||
documentListViewService.displayFields = customFields as any
|
||||
settingsService.displayFieldsInitialized = false
|
||||
expect(documentListViewService.displayFields).toEqual(customFields)
|
||||
jest.spyOn(settingsService, 'allDisplayFields', 'get').mockReturnValue([
|
||||
{ id: DisplayField.ADDED, name: 'Added' },
|
||||
{ id: DisplayField.TITLE, name: 'Title' },
|
||||
{ id: 'custom_field_1', name: 'Custom Field 1' },
|
||||
] as any)
|
||||
settingsService.displayFieldsInit.emit(true)
|
||||
expect(documentListViewService.displayFields).toEqual(['custom_field_1'])
|
||||
|
||||
// will now filter on set
|
||||
documentListViewService.displayFields = customFields as any
|
||||
settingsService.displayFieldsInitialized = true
|
||||
expect(documentListViewService.displayFields).toEqual(['custom_field_1'])
|
||||
})
|
||||
})
|
||||
|
@@ -20,10 +20,6 @@ import { paramsFromViewState, paramsToViewState } from '../utils/query-params'
|
||||
import { DocumentService, SelectionData } from './rest/document.service'
|
||||
import { SettingsService } from './settings.service'
|
||||
|
||||
const LIST_DEFAULT_DISPLAY_FIELDS: DisplayField[] = DEFAULT_DISPLAY_FIELDS.map(
|
||||
(f) => f.id
|
||||
).filter((f) => f !== DisplayField.ADDED)
|
||||
|
||||
/**
|
||||
* Captures the current state of the list view.
|
||||
*/
|
||||
@@ -106,8 +102,6 @@ export class DocumentListViewService {
|
||||
|
||||
private _activeSavedViewId: number = null
|
||||
|
||||
private displayFieldsInitialized: boolean = false
|
||||
|
||||
get activeSavedViewId() {
|
||||
return this._activeSavedViewId
|
||||
}
|
||||
@@ -140,19 +134,6 @@ export class DocumentListViewService {
|
||||
localStorage.removeItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG)
|
||||
}
|
||||
}
|
||||
|
||||
this.settings.displayFieldsInit.subscribe(() => {
|
||||
this.displayFieldsInitialized = true
|
||||
if (this.activeListViewState.displayFields) {
|
||||
this.activeListViewState.displayFields =
|
||||
this.activeListViewState.displayFields.filter(
|
||||
(field) =>
|
||||
this.settings.allDisplayFields.find((f) => f.id === field) !==
|
||||
undefined
|
||||
)
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private defaultListViewState(): ListViewState {
|
||||
@@ -434,17 +415,23 @@ export class DocumentListViewService {
|
||||
}
|
||||
|
||||
get displayFields(): DisplayField[] {
|
||||
return this.activeListViewState.displayFields ?? LIST_DEFAULT_DISPLAY_FIELDS
|
||||
}
|
||||
|
||||
set displayFields(fields: DisplayField[]) {
|
||||
this.activeListViewState.displayFields = this.displayFieldsInitialized
|
||||
? fields?.filter(
|
||||
let fields =
|
||||
this.activeListViewState.displayFields ??
|
||||
DEFAULT_DISPLAY_FIELDS.map((f) => f.id)
|
||||
if (!this.activeListViewState.displayFields) {
|
||||
fields = fields.filter((f) => f !== DisplayField.ADDED)
|
||||
}
|
||||
return this.settings.displayFieldsInitialized
|
||||
? fields.filter(
|
||||
(field) =>
|
||||
this.settings.allDisplayFields.find((f) => f.id === field) !==
|
||||
undefined
|
||||
)
|
||||
: fields
|
||||
}
|
||||
|
||||
set displayFields(fields: DisplayField[]) {
|
||||
this.activeListViewState.displayFields = fields
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
|
||||
|
@@ -274,7 +274,7 @@ export class SettingsService {
|
||||
public get allDisplayFields(): Array<{ id: DisplayField; name: string }> {
|
||||
return this._allDisplayFields
|
||||
}
|
||||
public displayFieldsInit: EventEmitter<boolean> = new EventEmitter()
|
||||
public displayFieldsInitialized: boolean = false
|
||||
|
||||
constructor(
|
||||
rendererFactory: RendererFactory2,
|
||||
@@ -382,10 +382,10 @@ export class SettingsService {
|
||||
}
|
||||
})
|
||||
)
|
||||
this.displayFieldsInit.emit(true)
|
||||
this.displayFieldsInitialized = true
|
||||
})
|
||||
} else {
|
||||
this.displayFieldsInit.emit(true)
|
||||
this.displayFieldsInitialized = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -118,4 +118,29 @@ describe('TasksService', () => {
|
||||
expect(tasksService.queuedFileTasks).toHaveLength(1)
|
||||
expect(tasksService.startedFileTasks).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('should call retry task api endpoint', () => {
|
||||
const task = {
|
||||
id: 1,
|
||||
type: PaperlessTaskType.File,
|
||||
status: PaperlessTaskStatus.Failed,
|
||||
acknowledged: false,
|
||||
task_id: '1234',
|
||||
task_file_name: 'file1.pdf',
|
||||
date_created: new Date(),
|
||||
}
|
||||
|
||||
tasksService.retryTask(task, true).subscribe()
|
||||
const reloadSpy = jest.spyOn(tasksService, 'reload')
|
||||
const req = httpTestingController.expectOne(
|
||||
`${environment.apiBaseUrl}tasks/${task.id}/retry/`
|
||||
)
|
||||
expect(req.request.method).toEqual('POST')
|
||||
expect(req.request.body).toEqual({
|
||||
clean: true,
|
||||
})
|
||||
req.flush({ task_id: 12345 })
|
||||
expect(reloadSpy).toHaveBeenCalled()
|
||||
httpTestingController.expectOne(`${environment.apiBaseUrl}tasks/`).flush([])
|
||||
})
|
||||
})
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Subject } from 'rxjs'
|
||||
import { first, takeUntil } from 'rxjs/operators'
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
import { first, takeUntil, tap } from 'rxjs/operators'
|
||||
import {
|
||||
PaperlessTask,
|
||||
PaperlessTaskStatus,
|
||||
@@ -73,6 +73,20 @@ export class TasksService {
|
||||
})
|
||||
}
|
||||
|
||||
public retryTask(task: PaperlessTask, clean: boolean): Observable<any> {
|
||||
return this.http
|
||||
.post(`${this.baseUrl}tasks/${task.id}/retry/`, {
|
||||
clean,
|
||||
})
|
||||
.pipe(
|
||||
takeUntil(this.unsubscribeNotifer),
|
||||
first(),
|
||||
tap(() => {
|
||||
this.reload()
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
public cancelPending(): void {
|
||||
this.unsubscribeNotifer.next(true)
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ export const environment = {
|
||||
apiBaseUrl: document.baseURI + 'api/',
|
||||
apiVersion: '5',
|
||||
appTitle: 'Paperless-ngx',
|
||||
version: '2.13.4',
|
||||
version: '2.13.2',
|
||||
webSocketHost: window.location.host,
|
||||
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
|
||||
webSocketBaseUrl: base_url.pathname + 'ws/',
|
||||
|
@@ -3605,7 +3605,7 @@
|
||||
</context-group>
|
||||
<target state="final">Fehler beim Speichern des Feldes.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4465085913683915434" datatype="html" approved="yes">
|
||||
<trans-unit id="4465085913683915434" datatype="html">
|
||||
<source>True</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
@@ -3619,9 +3619,9 @@
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">79</context>
|
||||
</context-group>
|
||||
<target state="final">Wahr</target>
|
||||
<target state="translated">Wahr</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3800326155195149498" datatype="html" approved="yes">
|
||||
<trans-unit id="3800326155195149498" datatype="html">
|
||||
<source>False</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
@@ -3635,15 +3635,15 @@
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">80</context>
|
||||
</context-group>
|
||||
<target state="final">Falsch</target>
|
||||
<target state="translated">Falsch</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7551700625201096185" datatype="html" approved="yes">
|
||||
<trans-unit id="7551700625201096185" datatype="html">
|
||||
<source>Search docs...</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">96</context>
|
||||
</context-group>
|
||||
<target state="final">Suche Dokumente...</target>
|
||||
<target state="translated">Suche Dokumente...</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3184700926171002527" datatype="html" approved="yes">
|
||||
<source>Any</source>
|
||||
@@ -3685,29 +3685,29 @@
|
||||
</context-group>
|
||||
<target state="final">Alle</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1496549861742963591" datatype="html" approved="yes">
|
||||
<trans-unit id="1496549861742963591" datatype="html">
|
||||
<source>Not</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">131</context>
|
||||
</context-group>
|
||||
<target state="final">Nicht</target>
|
||||
<target state="translated">Nicht</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6548676277933116532" datatype="html" approved="yes">
|
||||
<trans-unit id="6548676277933116532" datatype="html">
|
||||
<source>Add query</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">150</context>
|
||||
</context-group>
|
||||
<target state="final">Abfrage hinzufügen</target>
|
||||
<target state="translated">Abfrage hinzufügen</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5599577087865387184" datatype="html" approved="yes">
|
||||
<trans-unit id="5599577087865387184" datatype="html">
|
||||
<source>Add expression</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">153</context>
|
||||
</context-group>
|
||||
<target state="final">Ausdruck hinzufügen</target>
|
||||
<target state="translated">Ausdruck hinzufügen</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6052766076365105714" datatype="html" approved="yes">
|
||||
<source>now</source>
|
||||
@@ -4513,13 +4513,13 @@
|
||||
</context-group>
|
||||
<target state="final">Pfad</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2816147949408898105" datatype="html" approved="yes">
|
||||
<trans-unit id="2816147949408898105" datatype="html">
|
||||
<source>See <a target='_blank' href='https://docs.paperless-ngx.com/advanced_usage/#file-name-handling'>the documentation</a>.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="final">Siehe <a target='_blank' href='https://docs.paperless-ngx.com/advanced_usage/#file-name-handling'>Dokumentation</a>.</target>
|
||||
<target state="translated">Siehe <a target='_blank' href='https://docs.paperless-ngx.com/advanced_usage/#file-name-handling'>Dokumentation</a>.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1295614462098694869" datatype="html" approved="yes">
|
||||
<source>Preview</source>
|
||||
@@ -4533,29 +4533,29 @@
|
||||
</context-group>
|
||||
<target state="final">Vorschau</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8057014866157903311" datatype="html" approved="yes">
|
||||
<trans-unit id="8057014866157903311" datatype="html">
|
||||
<source>Path test failed</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">30</context>
|
||||
</context-group>
|
||||
<target state="final">Pfadüberprüfung fehlgeschlagen</target>
|
||||
<target state="translated">Pfadüberprüfung fehlgeschlagen</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="9116034231465034307" datatype="html" approved="yes">
|
||||
<trans-unit id="9116034231465034307" datatype="html">
|
||||
<source>No document selected</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">32</context>
|
||||
</context-group>
|
||||
<target state="final">Kein Dokument ausgewählt</target>
|
||||
<target state="translated">Kein Dokument ausgewählt</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2083498114116917092" datatype="html" approved="yes">
|
||||
<trans-unit id="2083498114116917092" datatype="html">
|
||||
<source>Search for a document</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">38</context>
|
||||
</context-group>
|
||||
<target state="final">Ein Dokument suchen</target>
|
||||
<target state="translated">Ein Dokument suchen</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6423278459497515329" datatype="html" approved="yes">
|
||||
<source>No documents found</source>
|
||||
@@ -5342,21 +5342,21 @@
|
||||
</context-group>
|
||||
<target state="final">Link öffnen</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6595008830732269870" datatype="html" approved="yes">
|
||||
<trans-unit id="6595008830732269870" datatype="html">
|
||||
<source>Not found</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/input/document-link/document-link.component.html</context>
|
||||
<context context-type="linenumber">50</context>
|
||||
</context-group>
|
||||
<target state="final">Nicht gefunden</target>
|
||||
<target state="needs-translation">Not found</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5676637575587497817" datatype="html" approved="yes">
|
||||
<trans-unit id="5676637575587497817" datatype="html">
|
||||
<source>Search for documents</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/input/document-link/document-link.component.ts</context>
|
||||
<context context-type="linenumber">53</context>
|
||||
</context-group>
|
||||
<target state="final">Nach Dokumenten suchen</target>
|
||||
<target state="translated">Nach Dokumenten suchen</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8627133593113147800" datatype="html" approved="yes">
|
||||
<source>Selected items</source>
|
||||
@@ -8100,13 +8100,13 @@
|
||||
</context-group>
|
||||
<target state="final">Ohne Tag</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8644099678903817943" datatype="html" approved="yes">
|
||||
<trans-unit id="8644099678903817943" datatype="html">
|
||||
<source>Custom fields query</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">238</context>
|
||||
</context-group>
|
||||
<target state="final">Benutzerdefinierte Feldabfrage</target>
|
||||
<target state="translated">Benutzerdefinierte Feldabfrage</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6523384805359286307" datatype="html" approved="yes">
|
||||
<source>Title: <x id="PH" equiv-text="rule.value"/></source>
|
||||
@@ -8296,7 +8296,7 @@
|
||||
</context-group>
|
||||
<target state="final">Datentyp</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6209318295562170730" datatype="html" approved="yes">
|
||||
<trans-unit id="6209318295562170730" datatype="html">
|
||||
<source>Filter Documents (<x id="INTERPOLATION" equiv-text="{{ field.document_count }}"/>)</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
||||
@@ -8318,7 +8318,7 @@
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||
<context context-type="linenumber">85</context>
|
||||
</context-group>
|
||||
<target state="final">Dokumente filtern (<x id="INTERPOLATION" equiv-text="{{ field.document_count }}"/>)</target>
|
||||
<target state="translated">Dokumente filtern (<x id="INTERPOLATION" equiv-text="{{ field.document_count }}"/>)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="651372623796033489" datatype="html" approved="yes">
|
||||
<source>No fields defined.</source>
|
||||
@@ -8408,21 +8408,21 @@
|
||||
</context-group>
|
||||
<target state="final">Konto hinzufügen</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5088684330574277786" datatype="html" approved="yes">
|
||||
<trans-unit id="5088684330574277786" datatype="html">
|
||||
<source>Connect Gmail Account</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
|
||||
<context context-type="linenumber">18</context>
|
||||
</context-group>
|
||||
<target state="final">Gmail-Konto verbinden</target>
|
||||
<target state="translated">Gmail-Konto verbinden</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6630732552154686829" datatype="html" approved="yes">
|
||||
<trans-unit id="6630732552154686829" datatype="html">
|
||||
<source>Connect Outlook Account</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
|
||||
<context context-type="linenumber">23</context>
|
||||
</context-group>
|
||||
<target state="final">Outlook-Konto verbinden</target>
|
||||
<target state="translated">Outlook-Konto verbinden</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2188854519574316630" datatype="html" approved="yes">
|
||||
<source>Server</source>
|
||||
@@ -8500,21 +8500,21 @@
|
||||
</context-group>
|
||||
<target state="final">Fehler beim Abrufen der E-Mail-Regeln</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="763945516325093575" datatype="html" approved="yes">
|
||||
<trans-unit id="763945516325093575" datatype="html">
|
||||
<source>OAuth2 authentication success</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context>
|
||||
<context context-type="linenumber">101</context>
|
||||
</context-group>
|
||||
<target state="final">OAuth2-Authentifizierung erfolgreich</target>
|
||||
<target state="translated">OAuth2-Authentifizierung erfolgreich</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="9022978370268070156" datatype="html" approved="yes">
|
||||
<trans-unit id="9022978370268070156" datatype="html">
|
||||
<source>OAuth2 authentication failed, see logs for details</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context>
|
||||
<context context-type="linenumber">112</context>
|
||||
</context-group>
|
||||
<target state="final">OAuth2-Authentifizierung fehlgeschlagen, siehe Protokolle für Details</target>
|
||||
<target state="translated">OAuth2-Authentifizierung fehlgeschlagen, siehe Protokolle für Details</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6327501535846658797" datatype="html" approved="yes">
|
||||
<source>Saved account "<x id="PH" equiv-text="newMailAccount.name"/>".</source>
|
||||
@@ -9000,93 +9000,93 @@
|
||||
</context-group>
|
||||
<target state="final">Zur Startseite</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7088714514100361567" datatype="html" approved="yes">
|
||||
<trans-unit id="7088714514100361567" datatype="html">
|
||||
<source>Equal to</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">24</context>
|
||||
</context-group>
|
||||
<target state="final">Ist gleich</target>
|
||||
<target state="translated">Ist gleich</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2841739558138901231" datatype="html" approved="yes">
|
||||
<trans-unit id="2841739558138901231" datatype="html">
|
||||
<source>In</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">25</context>
|
||||
</context-group>
|
||||
<target state="final">In</target>
|
||||
<target state="translated">In</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6504828068656625171" datatype="html" approved="yes">
|
||||
<trans-unit id="6504828068656625171" datatype="html">
|
||||
<source>Is null</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">26</context>
|
||||
</context-group>
|
||||
<target state="final">Ist null</target>
|
||||
<target state="translated">Ist null</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4112599358351148632" datatype="html" approved="yes">
|
||||
<trans-unit id="4112599358351148632" datatype="html">
|
||||
<source>Exists</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">27</context>
|
||||
</context-group>
|
||||
<target state="final">Existiert</target>
|
||||
<target state="translated">Existiert</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6238291467288576076" datatype="html" approved="yes">
|
||||
<trans-unit id="6238291467288576076" datatype="html">
|
||||
<source>Contains</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">28</context>
|
||||
</context-group>
|
||||
<target state="final">Enthält</target>
|
||||
<target state="translated">Enthält</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="870133374397538941" datatype="html" approved="yes">
|
||||
<trans-unit id="870133374397538941" datatype="html">
|
||||
<source>Contains (case-insensitive)</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">29</context>
|
||||
</context-group>
|
||||
<target state="final">Enthält (beachte Groß- und Kleinschreibung)</target>
|
||||
<target state="translated">Enthält (beachte Groß- und Kleinschreibung)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7732309408488818531" datatype="html" approved="yes">
|
||||
<trans-unit id="7732309408488818531" datatype="html">
|
||||
<source>Greater than</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">30</context>
|
||||
</context-group>
|
||||
<target state="final">Größer als</target>
|
||||
<target state="translated">Größer als</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="9087788064443057357" datatype="html" approved="yes">
|
||||
<trans-unit id="9087788064443057357" datatype="html">
|
||||
<source>Greater than or equal to</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">31</context>
|
||||
</context-group>
|
||||
<target state="final">Größer oder gleich</target>
|
||||
<target state="translated">Größer oder gleich</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5995604223909447366" datatype="html" approved="yes">
|
||||
<trans-unit id="5995604223909447366" datatype="html">
|
||||
<source>Less than</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">32</context>
|
||||
</context-group>
|
||||
<target state="final">Kleiner als</target>
|
||||
<target state="translated">Kleiner als</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6989379963430864867" datatype="html" approved="yes">
|
||||
<trans-unit id="6989379963430864867" datatype="html">
|
||||
<source>Less than or equal to</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">33</context>
|
||||
</context-group>
|
||||
<target state="final">Kleiner oder gleich</target>
|
||||
<target state="translated">Kleiner oder gleich</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2348971518300945764" datatype="html" approved="yes">
|
||||
<trans-unit id="2348971518300945764" datatype="html">
|
||||
<source>Range</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/custom-field-query.ts</context>
|
||||
<context context-type="linenumber">34</context>
|
||||
</context-group>
|
||||
<target state="final">Bereich</target>
|
||||
<target state="translated">Bereich</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="969459137986754249" datatype="html" approved="yes">
|
||||
<source>Boolean</source>
|
||||
|
@@ -1743,7 +1743,7 @@
|
||||
<context context-type="sourcefile">src/app/components/admin/settings/settings.component.html</context>
|
||||
<context context-type="linenumber">385</context>
|
||||
</context-group>
|
||||
<target state="translated">Tabell</target>
|
||||
<target state="needs-translation">Table</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4236040382842528005" datatype="html">
|
||||
<source>Small Cards</source>
|
||||
@@ -1771,7 +1771,7 @@
|
||||
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
|
||||
<context context-type="linenumber">17</context>
|
||||
</context-group>
|
||||
<target state="translated">Visa</target>
|
||||
<target state="needs-translation">Show</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5607669932062416162" datatype="html">
|
||||
<source>Default</source>
|
||||
@@ -2303,7 +2303,7 @@
|
||||
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
|
||||
<context context-type="linenumber">223</context>
|
||||
</context-group>
|
||||
<target state="translated">Papperskorg</target>
|
||||
<target state="needs-translation">Trash</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3818027200170621545" datatype="html">
|
||||
<source>Manage trashed documents that are pending deletion.</source>
|
||||
@@ -3307,7 +3307,7 @@
|
||||
<context context-type="sourcefile">src/app/components/app-frame/global-search/global-search.component.html</context>
|
||||
<context context-type="linenumber">131</context>
|
||||
</context-group>
|
||||
<target state="translated">Användare</target>
|
||||
<target state="needs-translation">Users</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="searchResults.groups" datatype="html">
|
||||
<source>Groups</source>
|
||||
@@ -3315,7 +3315,7 @@
|
||||
<context context-type="sourcefile">src/app/components/app-frame/global-search/global-search.component.html</context>
|
||||
<context context-type="linenumber">138</context>
|
||||
</context-group>
|
||||
<target state="translated">Grupper</target>
|
||||
<target state="needs-translation">Groups</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="searchResults.customFields" datatype="html">
|
||||
<source>Custom fields</source>
|
||||
@@ -3471,7 +3471,7 @@
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">7,8</context>
|
||||
</context-group>
|
||||
<target state="translated">av <x id="INTERPOLATION" equiv-text="{{totalPages}}"/></target>
|
||||
<target state="needs-translation">of <x id="INTERPOLATION" equiv-text="{{totalPages}}"/></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6903610408081711391" datatype="html">
|
||||
<source>Pages to remove</source>
|
||||
@@ -3487,7 +3487,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.html</context>
|
||||
<context context-type="linenumber">9</context>
|
||||
</context-group>
|
||||
<target state="translated">Dokument:</target>
|
||||
<target state="needs-translation">Documents:</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7508164375697837821" datatype="html">
|
||||
<source>Use metadata from:</source>
|
||||
@@ -3579,7 +3579,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.html</context>
|
||||
<context context-type="linenumber">21</context>
|
||||
</context-group>
|
||||
<target state="translated">Skapa nytt fält</target>
|
||||
<target state="needs-translation">Create new field</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6973528734330066202" datatype="html">
|
||||
<source>Saved field "<x id="PH" equiv-text="newField.name"/>".</source>
|
||||
@@ -3939,7 +3939,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">84</context>
|
||||
</context-group>
|
||||
<target state="translated">Redigera anpassat fält</target>
|
||||
<target state="needs-translation">Edit custom field</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6672809941092516947" datatype="html" approved="yes">
|
||||
<source>Create new document type</source>
|
||||
@@ -5356,7 +5356,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/input/document-link/document-link.component.ts</context>
|
||||
<context context-type="linenumber">53</context>
|
||||
</context-group>
|
||||
<target state="translated">Sök efter dokument</target>
|
||||
<target state="needs-translation">Search for documents</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8627133593113147800" datatype="html">
|
||||
<source>Selected items</source>
|
||||
@@ -5653,7 +5653,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">23</context>
|
||||
</context-group>
|
||||
<target state="translated">Bekräfta lösenord</target>
|
||||
<target state="needs-translation">Confirm Password</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7554924397178347823" datatype="html">
|
||||
<source>API Auth Token</source>
|
||||
@@ -5905,7 +5905,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/share-links-dropdown/share-links-dropdown.component.ts</context>
|
||||
<context context-type="linenumber">94</context>
|
||||
</context-group>
|
||||
<target state="translated">1 dag</target>
|
||||
<target state="needs-translation">1 day</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8542568275115626925" datatype="html">
|
||||
<source>7 days</source>
|
||||
@@ -5945,7 +5945,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/share-links-dropdown/share-links-dropdown.component.ts</context>
|
||||
<context context-type="linenumber">94</context>
|
||||
</context-group>
|
||||
<target state="translated"><x id="PH" equiv-text="days"/> dagar</target>
|
||||
<target state="needs-translation"><x id="PH" equiv-text="days"/> days</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2897042887615940599" datatype="html">
|
||||
<source>Error deleting link</source>
|
||||
@@ -6025,7 +6025,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
|
||||
<context context-type="linenumber">41</context>
|
||||
</context-group>
|
||||
<target state="translated">Databas</target>
|
||||
<target state="needs-translation">Database</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5611592591303869712" datatype="html">
|
||||
<source>Status</source>
|
||||
@@ -6045,7 +6045,7 @@
|
||||
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context>
|
||||
<context context-type="linenumber">19</context>
|
||||
</context-group>
|
||||
<target state="translated">Status</target>
|
||||
<target state="needs-translation">Status</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2256165083739630668" datatype="html">
|
||||
<source>Migration Status</source>
|
||||
@@ -6085,7 +6085,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
|
||||
<context context-type="linenumber">83</context>
|
||||
</context-group>
|
||||
<target state="translated">Uppgifter</target>
|
||||
<target state="needs-translation">Tasks</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6911698235105017958" datatype="html">
|
||||
<source>Redis Status</source>
|
||||
@@ -6157,7 +6157,7 @@
|
||||
<context context-type="sourcefile">src/app/components/dashboard/dashboard.component.ts</context>
|
||||
<context context-type="linenumber">40</context>
|
||||
</context-group>
|
||||
<target state="translated">Välkommen till <x id="PH" equiv-text="environment.appTitle"/></target>
|
||||
<target state="needs-translation">Welcome to <x id="PH" equiv-text="environment.appTitle"/></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1325877348738783391" datatype="html">
|
||||
<source>Dashboard updated</source>
|
||||
@@ -6892,7 +6892,7 @@
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">502</context>
|
||||
</context-group>
|
||||
<target state="translated">Spara dokument</target>
|
||||
<target state="needs-translation">Save document</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5758784066858623886" datatype="html">
|
||||
<source>Error retrieving metadata</source>
|
||||
@@ -9142,7 +9142,7 @@
|
||||
<context context-type="sourcefile">src/app/data/custom-field.ts</context>
|
||||
<context context-type="linenumber">42</context>
|
||||
</context-group>
|
||||
<target state="translated">URL</target>
|
||||
<target state="needs-translation">Url</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3650316326183661476" datatype="html">
|
||||
<source>Document Link</source>
|
||||
@@ -9295,7 +9295,7 @@
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">83</context>
|
||||
</context-group>
|
||||
<target state="translated">Språk</target>
|
||||
<target state="needs-translation">Language</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1713271461473302108" datatype="html">
|
||||
<source>Mode</source>
|
||||
@@ -9487,7 +9487,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">14</context>
|
||||
</context-group>
|
||||
<target state="translated">%s år sedan</target>
|
||||
<target state="needs-translation">%s year ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3393387677918927062" datatype="html">
|
||||
<source>%s years ago</source>
|
||||
@@ -9495,7 +9495,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">15</context>
|
||||
</context-group>
|
||||
<target state="translated">%s år sedan</target>
|
||||
<target state="needs-translation">%s years ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3053246523831285824" datatype="html">
|
||||
<source>%s month ago</source>
|
||||
@@ -9503,7 +9503,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">19</context>
|
||||
</context-group>
|
||||
<target state="translated">%s månad sedan</target>
|
||||
<target state="needs-translation">%s month ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1158628882375251480" datatype="html">
|
||||
<source>%s months ago</source>
|
||||
@@ -9511,7 +9511,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">20</context>
|
||||
</context-group>
|
||||
<target state="translated">%s månader sedan</target>
|
||||
<target state="needs-translation">%s months ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7039133412826927309" datatype="html">
|
||||
<source>%s week ago</source>
|
||||
@@ -9519,7 +9519,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">24</context>
|
||||
</context-group>
|
||||
<target state="translated">%s vecka sedan</target>
|
||||
<target state="needs-translation">%s week ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2896962543647781653" datatype="html">
|
||||
<source>%s weeks ago</source>
|
||||
@@ -9527,7 +9527,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">25</context>
|
||||
</context-group>
|
||||
<target state="translated">%s veckor sedan</target>
|
||||
<target state="needs-translation">%s weeks ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="91416192007234700" datatype="html">
|
||||
<source>%s day ago</source>
|
||||
@@ -9535,7 +9535,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">29</context>
|
||||
</context-group>
|
||||
<target state="translated">%s dag sedan</target>
|
||||
<target state="needs-translation">%s day ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5601594741748068208" datatype="html">
|
||||
<source>%s days ago</source>
|
||||
@@ -9543,7 +9543,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">30</context>
|
||||
</context-group>
|
||||
<target state="translated">%s dagar sedan</target>
|
||||
<target state="needs-translation">%s days ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8387405724402999437" datatype="html">
|
||||
<source>%s hour ago</source>
|
||||
@@ -9551,7 +9551,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">34</context>
|
||||
</context-group>
|
||||
<target state="translated">%s timme sedan</target>
|
||||
<target state="needs-translation">%s hour ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2008395012733474465" datatype="html">
|
||||
<source>%s hours ago</source>
|
||||
@@ -9559,7 +9559,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">35</context>
|
||||
</context-group>
|
||||
<target state="translated">%s timmar sedan</target>
|
||||
<target state="needs-translation">%s hours ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5782387980670840884" datatype="html">
|
||||
<source>%s minute ago</source>
|
||||
@@ -9567,7 +9567,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">39</context>
|
||||
</context-group>
|
||||
<target state="translated">%s minut sedan</target>
|
||||
<target state="needs-translation">%s minute ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7573942914011074807" datatype="html">
|
||||
<source>%s minutes ago</source>
|
||||
@@ -9575,7 +9575,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">40</context>
|
||||
</context-group>
|
||||
<target state="translated">%s minuter sedan</target>
|
||||
<target state="needs-translation">%s minutes ago</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4272436583644511364" datatype="html">
|
||||
<source>Just now</source>
|
||||
@@ -9583,7 +9583,7 @@
|
||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||
<context context-type="linenumber">72</context>
|
||||
</context-group>
|
||||
<target state="translated">Just nu</target>
|
||||
<target state="needs-translation">Just now</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7536524521722799066" datatype="html" approved="yes">
|
||||
<source>(no title)</source>
|
||||
@@ -9923,7 +9923,7 @@
|
||||
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
|
||||
<context context-type="linenumber">166</context>
|
||||
</context-group>
|
||||
<target state="translated">Norska</target>
|
||||
<target state="needs-translation">Norwegian</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="792060551707690640" datatype="html" approved="yes">
|
||||
<source>Polish</source>
|
||||
|
@@ -1743,7 +1743,7 @@
|
||||
<context context-type="sourcefile">src/app/components/admin/settings/settings.component.html</context>
|
||||
<context context-type="linenumber">385</context>
|
||||
</context-group>
|
||||
<target state="translated">表格</target>
|
||||
<target state="needs-translation">Table</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4236040382842528005" datatype="html">
|
||||
<source>Small Cards</source>
|
||||
@@ -2371,7 +2371,7 @@
|
||||
<context context-type="sourcefile">src/app/components/admin/trash/trash.component.html</context>
|
||||
<context context-type="linenumber">89</context>
|
||||
</context-group>
|
||||
<target state="translated">{VAR_PLURAL, plural, =1 {垃圾桶中有一份文件} other {垃圾桶中共有 <x id="INTERPOLATION"/> 份文件}}</target>
|
||||
<target state="needs-translation">{VAR_PLURAL, plural, =1 {One document in trash} other {<x id="INTERPOLATION"/> total documents in trash}}</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="9021887951960049161" datatype="html">
|
||||
<source>Confirm delete</source>
|
||||
@@ -3619,7 +3619,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">79</context>
|
||||
</context-group>
|
||||
<target state="translated">真</target>
|
||||
<target state="needs-translation">True</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3800326155195149498" datatype="html">
|
||||
<source>False</source>
|
||||
@@ -3635,7 +3635,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">80</context>
|
||||
</context-group>
|
||||
<target state="translated">假</target>
|
||||
<target state="needs-translation">False</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7551700625201096185" datatype="html">
|
||||
<source>Search docs...</source>
|
||||
@@ -3643,7 +3643,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">96</context>
|
||||
</context-group>
|
||||
<target state="translated">搜索文档...</target>
|
||||
<target state="needs-translation">Search docs...</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3184700926171002527" datatype="html">
|
||||
<source>Any</source>
|
||||
@@ -3691,7 +3691,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">131</context>
|
||||
</context-group>
|
||||
<target state="translated">否</target>
|
||||
<target state="needs-translation">Not</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6548676277933116532" datatype="html">
|
||||
<source>Add query</source>
|
||||
@@ -3699,7 +3699,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">150</context>
|
||||
</context-group>
|
||||
<target state="translated">添加查询</target>
|
||||
<target state="needs-translation">Add query</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5599577087865387184" datatype="html">
|
||||
<source>Add expression</source>
|
||||
@@ -3707,7 +3707,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
|
||||
<context context-type="linenumber">153</context>
|
||||
</context-group>
|
||||
<target state="translated">添加表达式</target>
|
||||
<target state="needs-translation">Add expression</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6052766076365105714" datatype="html">
|
||||
<source>now</source>
|
||||
@@ -4135,7 +4135,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">19</context>
|
||||
</context-group>
|
||||
<target state="translated">顺序</target>
|
||||
<target state="needs-translation">Order</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4816216590591222133" datatype="html">
|
||||
<source>Enabled</source>
|
||||
@@ -4519,7 +4519,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">请参阅 <a target='_blank' href='https://docs.paperless-ngx.com/advanced_usage/#file-name-handling'>文档</a>。</target>
|
||||
<target state="needs-translation">See <a target='_blank' href='https://docs.paperless-ngx.com/advanced_usage/#file-name-handling'>the documentation</a>.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1295614462098694869" datatype="html">
|
||||
<source>Preview</source>
|
||||
@@ -4539,7 +4539,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">30</context>
|
||||
</context-group>
|
||||
<target state="translated">路径测试失败</target>
|
||||
<target state="needs-translation">Path test failed</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="9116034231465034307" datatype="html">
|
||||
<source>No document selected</source>
|
||||
@@ -4547,7 +4547,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">32</context>
|
||||
</context-group>
|
||||
<target state="translated">没有选择文档</target>
|
||||
<target state="needs-translation">No document selected</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2083498114116917092" datatype="html">
|
||||
<source>Search for a document</source>
|
||||
@@ -4555,7 +4555,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">38</context>
|
||||
</context-group>
|
||||
<target state="translated">搜索文档</target>
|
||||
<target state="needs-translation">Search for a document</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6423278459497515329" datatype="html">
|
||||
<source>No documents found</source>
|
||||
@@ -4759,7 +4759,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">33</context>
|
||||
</context-group>
|
||||
<target state="translated">添加触发器</target>
|
||||
<target state="needs-translation">Add Trigger</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6882912390704300247" datatype="html">
|
||||
<source>Apply Actions:</source>
|
||||
@@ -4767,7 +4767,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">73</context>
|
||||
</context-group>
|
||||
<target state="translated">应用操作:</target>
|
||||
<target state="needs-translation">Apply Actions:</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="51883444329775670" datatype="html">
|
||||
<source>Add Action</source>
|
||||
@@ -4775,7 +4775,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">75</context>
|
||||
</context-group>
|
||||
<target state="translated">添加动作</target>
|
||||
<target state="needs-translation">Add Action</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3288318211116868972" datatype="html">
|
||||
<source>Trigger type</source>
|
||||
@@ -4783,7 +4783,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">121</context>
|
||||
</context-group>
|
||||
<target state="translated">触发类型</target>
|
||||
<target state="needs-translation">Trigger type</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8727727835543352574" datatype="html">
|
||||
<source>Trigger for documents that match <x id="START_EMPHASISED_TEXT" ctype="x-em" equiv-text="<em>"/>all<x id="CLOSE_EMPHASISED_TEXT" ctype="x-em" equiv-text="</em>"/> filters specified below.</source>
|
||||
@@ -4791,7 +4791,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">122</context>
|
||||
</context-group>
|
||||
<target state="translated">触发匹配下面指定的 <x id="START_EMPHASISED_TEXT" ctype="x-em" equiv-text="<em>"/>所有<x id="CLOSE_EMPHASISED_TEXT" ctype="x-em" equiv-text="</em>"/> 过滤器的文档。</target>
|
||||
<target state="needs-translation">Trigger for documents that match <x id="START_EMPHASISED_TEXT" ctype="x-em" equiv-text="<em>"/>all<x id="CLOSE_EMPHASISED_TEXT" ctype="x-em" equiv-text="</em>"/> filters specified below.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7467799586957602479" datatype="html">
|
||||
<source>Filter filename</source>
|
||||
@@ -4831,7 +4831,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">128</context>
|
||||
</context-group>
|
||||
<target state="translated">应用于匹配此路径的文档。允许指定为*的通配符。不区分大小写。</a></target>
|
||||
<target state="needs-translation">Apply to documents that match this path. Wildcards specified as * are allowed. Case-normalized.</a></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7468453896129193641" datatype="html">
|
||||
<source>Filter mail rule</source>
|
||||
@@ -4847,7 +4847,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">129</context>
|
||||
</context-group>
|
||||
<target state="translated">应用于通过此邮件规则消费的文档。</target>
|
||||
<target state="needs-translation">Apply to documents consumed via this mail rule.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6840369584127435743" datatype="html">
|
||||
<source>Content matching algorithm</source>
|
||||
@@ -4855,7 +4855,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">132</context>
|
||||
</context-group>
|
||||
<target state="translated">内容匹配算法</target>
|
||||
<target state="needs-translation">Content matching algorithm</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="510635115034690805" datatype="html">
|
||||
<source>Content matching pattern</source>
|
||||
@@ -4863,7 +4863,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">134</context>
|
||||
</context-group>
|
||||
<target state="translated">内容匹配模式</target>
|
||||
<target state="needs-translation">Content matching pattern</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3484236514968690689" datatype="html">
|
||||
<source>Has any of tags</source>
|
||||
@@ -4871,7 +4871,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">143</context>
|
||||
</context-group>
|
||||
<target state="translated">有任何标签</target>
|
||||
<target state="needs-translation">Has any of tags</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5281365940563983618" datatype="html">
|
||||
<source>Has correspondent</source>
|
||||
@@ -4879,7 +4879,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">144</context>
|
||||
</context-group>
|
||||
<target state="translated">已有联系人</target>
|
||||
<target state="needs-translation">Has correspondent</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4806713133917046341" datatype="html">
|
||||
<source>Has document type</source>
|
||||
@@ -4887,7 +4887,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">145</context>
|
||||
</context-group>
|
||||
<target state="translated">有文档类型</target>
|
||||
<target state="needs-translation">Has document type</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6417103744331194518" datatype="html">
|
||||
<source>Action type</source>
|
||||
@@ -4895,7 +4895,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">155</context>
|
||||
</context-group>
|
||||
<target state="translated">操作类型</target>
|
||||
<target state="needs-translation">Action type</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6019822389883736115" datatype="html">
|
||||
<source>Assign title</source>
|
||||
@@ -4911,7 +4911,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">160</context>
|
||||
</context-group>
|
||||
<target state="translated">可以包含一些占位符,请参阅 <a target='_blank' href='https://docs.paperless-ngx.com/usage/#workflows'>文档</a>。</target>
|
||||
<target state="needs-translation">Can include some placeholders, see <a target='_blank' href='https://docs.paperless-ngx.com/usage/#workflows'>documentation</a>.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6528897010417701530" datatype="html">
|
||||
<source>Assign tags</source>
|
||||
@@ -4967,7 +4967,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">216</context>
|
||||
</context-group>
|
||||
<target state="translated">移除标签</target>
|
||||
<target state="needs-translation">Remove tags</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7890599006071681081" datatype="html">
|
||||
<source>Remove all</source>
|
||||
@@ -4999,7 +4999,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">254</context>
|
||||
</context-group>
|
||||
<target state="translated">移除全部</target>
|
||||
<target state="needs-translation">Remove all</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8636414563726517994" datatype="html">
|
||||
<source>Remove correspondents</source>
|
||||
@@ -5007,7 +5007,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">222</context>
|
||||
</context-group>
|
||||
<target state="translated">移除所有通讯员</target>
|
||||
<target state="needs-translation">Remove correspondents</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5305293055593064952" datatype="html">
|
||||
<source>Remove document types</source>
|
||||
@@ -5015,7 +5015,7 @@
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">228</context>
|
||||
</context-group>
|
||||
<target state="translated">移除所有文档类型</target>
|
||||
<target state="needs-translation">Remove document types</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2400388879708187" datatype="html">
|
||||
<source>Remove storage paths</source>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">關閉</target>
|
||||
<target state="needs-translation">Close</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.timepicker.HH" datatype="html">
|
||||
<source>HH</source>
|
||||
@@ -16,7 +16,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">HH</target>
|
||||
<target state="needs-translation">HH</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.toast.close-aria" datatype="html">
|
||||
<source>Close</source>
|
||||
@@ -24,7 +24,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">關閉</target>
|
||||
<target state="needs-translation">Close</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.datepicker.select-month" datatype="html">
|
||||
<source>Select month</source>
|
||||
@@ -36,7 +36,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">選取月份</target>
|
||||
<target state="needs-translation">Select month</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.pagination.first" datatype="html">
|
||||
<source>««</source>
|
||||
@@ -56,7 +56,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">上個月</target>
|
||||
<target state="needs-translation">Previous month</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.progressbar.value" datatype="html">
|
||||
<source>
|
||||
@@ -82,7 +82,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">小時</target>
|
||||
<target state="needs-translation">Hours</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.pagination.previous" datatype="html">
|
||||
<source>«</source>
|
||||
@@ -98,7 +98,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">上一個</target>
|
||||
<target state="needs-translation">Previous</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.timepicker.MM" datatype="html">
|
||||
<source>MM</source>
|
||||
@@ -106,7 +106,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">MM</target>
|
||||
<target state="needs-translation">MM</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.pagination.next" datatype="html">
|
||||
<source>»</source>
|
||||
@@ -126,7 +126,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">選擇年份</target>
|
||||
<target state="needs-translation">Select year</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.datepicker.next-month" datatype="html">
|
||||
<source>Next month</source>
|
||||
@@ -138,7 +138,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">下一個月</target>
|
||||
<target state="needs-translation">Next month</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.carousel.next" datatype="html">
|
||||
<source>Next</source>
|
||||
@@ -146,7 +146,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">下一個</target>
|
||||
<target state="needs-translation">Next</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.timepicker.minutes" datatype="html">
|
||||
<source>Minutes</source>
|
||||
@@ -154,7 +154,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">分鐘</target>
|
||||
<target state="needs-translation">Minutes</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.pagination.last" datatype="html">
|
||||
<source>»»</source>
|
||||
@@ -170,7 +170,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">第一頁</target>
|
||||
<target state="needs-translation">First</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.timepicker.increment-hours" datatype="html">
|
||||
<source>Increment hours</source>
|
||||
@@ -186,7 +186,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">上一頁</target>
|
||||
<target state="needs-translation">Previous</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.timepicker.decrement-hours" datatype="html">
|
||||
<source>Decrement hours</source>
|
||||
@@ -202,7 +202,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">下一頁</target>
|
||||
<target state="needs-translation">Next</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.timepicker.increment-minutes" datatype="html">
|
||||
<source>Increment minutes</source>
|
||||
@@ -218,7 +218,7 @@
|
||||
<context context-type="sourcefile">node_modules/src/ngb-config.ts</context>
|
||||
<context context-type="linenumber">13</context>
|
||||
</context-group>
|
||||
<target state="translated">最後一頁</target>
|
||||
<target state="needs-translation">Last</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ngb.timepicker.decrement-minutes" datatype="html">
|
||||
<source>Decrement minutes</source>
|
||||
|
@@ -490,23 +490,9 @@ ul.pagination {
|
||||
|
||||
.doc-img-container {
|
||||
border: none !important;
|
||||
border-top-left-radius: .25rem;
|
||||
border-top-right-radius: .25rem;
|
||||
overflow: hidden;
|
||||
|
||||
.doc-img {
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.card-selected {
|
||||
border-color:var(--bs-primary);
|
||||
|
||||
.document-card-check {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.doc-img-container {
|
||||
background-color: var(--pngx-primary-faded);
|
||||
}
|
||||
}
|
||||
|
||||
table.table {
|
||||
@@ -719,8 +705,6 @@ i-bs svg {
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.document-card {
|
||||
.card-footer i-bs svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.document-card .card-footer i-bs svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
@@ -183,7 +183,7 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='htt
|
||||
}
|
||||
|
||||
.doc-img {
|
||||
mix-blend-mode: normal;
|
||||
mix-blend-mode: normal !important;
|
||||
border-radius: 0;
|
||||
border-color: var(--bs-border-color);
|
||||
filter: invert(10%);
|
||||
@@ -201,24 +201,6 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='htt
|
||||
mix-blend-mode: luminosity;
|
||||
}
|
||||
|
||||
@supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none) {
|
||||
// Safari does not like the filters on the image, see https://github.com/paperless-ngx/paperless-ngx/pull/8121
|
||||
.doc-img-container {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.doc-img {
|
||||
filter: none !important;
|
||||
box-shadow: inset 0px 0px 0px 10px rgba(0,0,0,1);
|
||||
}
|
||||
|
||||
.doc-img.inverted {
|
||||
filter: none !important;
|
||||
mix-blend-mode: difference;
|
||||
opacity: 0.95;
|
||||
}
|
||||
}
|
||||
|
||||
.paperless-input-select .ng-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option:not(.ng-option-selected):hover,
|
||||
.paperless-input-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {
|
||||
background-color: var(--bs-light) !important;
|
||||
|
@@ -148,6 +148,17 @@ class ConsumerPlugin(
|
||||
):
|
||||
self._send_progress(100, 100, ProgressStatusOptions.FAILED, message)
|
||||
self.log.error(log_message or message, exc_info=exc_info)
|
||||
# Move the file to the failed directory
|
||||
if (
|
||||
self.input_doc.original_file.exists()
|
||||
and not Path(
|
||||
settings.CONSUMPTION_FAILED_DIR / self.input_doc.original_file.name,
|
||||
).exists()
|
||||
):
|
||||
copy_file_with_basic_stats(
|
||||
self.input_doc.original_file,
|
||||
settings.CONSUMPTION_FAILED_DIR / self.input_doc.original_file.name,
|
||||
)
|
||||
raise ConsumerError(f"{self.filename}: {log_message or message}") from exception
|
||||
|
||||
def pre_check_file_exists(self):
|
||||
@@ -411,7 +422,6 @@ class ConsumerPlugin(
|
||||
self.unmodified_original = (
|
||||
Path(tempdir.name) / Path("uo") / Path(self.filename)
|
||||
)
|
||||
self.unmodified_original.parent.mkdir(exist_ok=True)
|
||||
copy_file_with_basic_stats(
|
||||
self.input_doc.original_file,
|
||||
self.unmodified_original,
|
||||
|
@@ -424,28 +424,20 @@ class CustomFieldQueryParser:
|
||||
value_field_name = "value_monetary_amount"
|
||||
has_field = Q(custom_fields__field=custom_field)
|
||||
|
||||
# We need to use an annotation here because different atoms
|
||||
# might be referring to different instances of custom fields.
|
||||
annotation_name = f"_custom_field_filter_{len(self._annotations)}"
|
||||
|
||||
# Our special exists operator.
|
||||
if op == "exists":
|
||||
annotation = Count("custom_fields", filter=has_field)
|
||||
# A Document should have > 0 match if it has this field, or 0 if doesn't.
|
||||
query_op = "gt" if value else "exact"
|
||||
query = Q(**{f"{annotation_name}__{query_op}": 0})
|
||||
field_filter = has_field if value else ~has_field
|
||||
else:
|
||||
# Check if 1) custom field name matches, and 2) value satisfies condition
|
||||
field_filter = has_field & Q(
|
||||
**{f"custom_fields__{value_field_name}__{op}": value},
|
||||
)
|
||||
# Annotate how many matching custom fields each document has
|
||||
annotation = Count("custom_fields", filter=field_filter)
|
||||
# Filter document by count
|
||||
query = Q(**{f"{annotation_name}__gt": 0})
|
||||
|
||||
self._annotations[annotation_name] = annotation
|
||||
return query
|
||||
# We need to use an annotation here because different atoms
|
||||
# might be referring to different instances of custom fields.
|
||||
annotation_name = f"_custom_field_filter_{len(self._annotations)}"
|
||||
self._annotations[annotation_name] = Count("custom_fields", filter=field_filter)
|
||||
|
||||
return Q(**{f"{annotation_name}__gt": 0})
|
||||
|
||||
@handle_validation_prefix
|
||||
def _get_custom_field(self, id_or_name):
|
||||
|
@@ -679,24 +679,28 @@ class PaperlessTask(models.Model):
|
||||
verbose_name=_("Task State"),
|
||||
help_text=_("Current state of the task being run"),
|
||||
)
|
||||
|
||||
date_created = models.DateTimeField(
|
||||
null=True,
|
||||
default=timezone.now,
|
||||
verbose_name=_("Created DateTime"),
|
||||
help_text=_("Datetime field when the task result was created in UTC"),
|
||||
)
|
||||
|
||||
date_started = models.DateTimeField(
|
||||
null=True,
|
||||
default=None,
|
||||
verbose_name=_("Started DateTime"),
|
||||
help_text=_("Datetime field when the task was started in UTC"),
|
||||
)
|
||||
|
||||
date_done = models.DateTimeField(
|
||||
null=True,
|
||||
default=None,
|
||||
verbose_name=_("Completed DateTime"),
|
||||
help_text=_("Datetime field when the task was completed in UTC"),
|
||||
)
|
||||
|
||||
result = models.TextField(
|
||||
null=True,
|
||||
default=None,
|
||||
|
@@ -1585,6 +1585,14 @@ class TasksViewSerializer(serializers.ModelSerializer):
|
||||
return result
|
||||
|
||||
|
||||
class RetryTaskSerializer(serializers.Serializer):
|
||||
clean = serializers.BooleanField(
|
||||
default=False,
|
||||
write_only=True,
|
||||
required=False,
|
||||
)
|
||||
|
||||
|
||||
class AcknowledgeTasksViewSerializer(serializers.Serializer):
|
||||
tasks = serializers.ListField(
|
||||
required=True,
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from celery import states
|
||||
from celery.signals import before_task_publish
|
||||
@@ -520,6 +521,19 @@ def update_filename_and_move_files(
|
||||
)
|
||||
|
||||
|
||||
@receiver(models.signals.post_save, sender=PaperlessTask)
|
||||
def cleanup_failed_documents(sender, instance: PaperlessTask, **kwargs):
|
||||
if instance.status != states.FAILURE or not instance.acknowledged:
|
||||
return
|
||||
|
||||
if instance.task_file_name:
|
||||
try:
|
||||
Path(settings.CONSUMPTION_FAILED_DIR / instance.task_file_name).unlink()
|
||||
logger.debug(f"Cleaned up failed file {instance.task_file_name}")
|
||||
except FileNotFoundError:
|
||||
logger.warning(f"Failed to clean up failed file {instance.task_file_name}")
|
||||
|
||||
|
||||
def set_log_entry(sender, document: Document, logging_group=None, **kwargs):
|
||||
ct = ContentType.objects.get(model="document")
|
||||
user = User.objects.get(username="consumer")
|
||||
|
@@ -9,6 +9,7 @@ from tempfile import TemporaryDirectory
|
||||
import tqdm
|
||||
from celery import Task
|
||||
from celery import shared_task
|
||||
from celery import states
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.db import transaction
|
||||
@@ -27,12 +28,14 @@ from documents.consumer import ConsumerPlugin
|
||||
from documents.consumer import WorkflowTriggerPlugin
|
||||
from documents.data_models import ConsumableDocument
|
||||
from documents.data_models import DocumentMetadataOverrides
|
||||
from documents.data_models import DocumentSource
|
||||
from documents.double_sided import CollatePlugin
|
||||
from documents.file_handling import create_source_path_directory
|
||||
from documents.file_handling import generate_unique_filename
|
||||
from documents.models import Correspondent
|
||||
from documents.models import Document
|
||||
from documents.models import DocumentType
|
||||
from documents.models import PaperlessTask
|
||||
from documents.models import StoragePath
|
||||
from documents.models import Tag
|
||||
from documents.parsers import DocumentParser
|
||||
@@ -44,6 +47,8 @@ from documents.plugins.helpers import ProgressStatusOptions
|
||||
from documents.sanity_checker import SanityCheckFailedException
|
||||
from documents.signals import document_updated
|
||||
from documents.signals.handlers import cleanup_document_deletion
|
||||
from documents.utils import copy_file_with_basic_stats
|
||||
from documents.utils import run_subprocess
|
||||
|
||||
if settings.AUDIT_LOG_ENABLED:
|
||||
from auditlog.models import LogEntry
|
||||
@@ -169,6 +174,48 @@ def consume_file(
|
||||
return msg
|
||||
|
||||
|
||||
@shared_task
|
||||
def retry_failed_file(task_id: str, clean: bool = False, skip_ocr: bool = False):
|
||||
task = PaperlessTask.objects.get(task_id=task_id, status=states.FAILURE)
|
||||
if task:
|
||||
failed_file = settings.CONSUMPTION_FAILED_DIR / task.task_file_name
|
||||
if not failed_file.exists():
|
||||
logger.error(f"File {failed_file} not found")
|
||||
raise FileNotFoundError(f"File {failed_file} not found")
|
||||
working_copy = settings.SCRATCH_DIR / failed_file.name
|
||||
copy_file_with_basic_stats(failed_file, working_copy)
|
||||
|
||||
if clean:
|
||||
try:
|
||||
result = run_subprocess(
|
||||
[
|
||||
"qpdf",
|
||||
"--replace-input",
|
||||
"--warning-exit-0",
|
||||
working_copy,
|
||||
],
|
||||
logger=logger,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
raise Exception(
|
||||
f"qpdf failed with exit code {result.returncode}, error: {result.stderr}",
|
||||
)
|
||||
else:
|
||||
logger.debug("PDF cleaned successfully")
|
||||
except Exception as e:
|
||||
logger.error(f"Error while cleaning PDF: {e}")
|
||||
raise e
|
||||
|
||||
task = consume_file.delay(
|
||||
ConsumableDocument(
|
||||
source=DocumentSource.ConsumeFolder,
|
||||
original_file=working_copy,
|
||||
),
|
||||
)
|
||||
|
||||
return task.id
|
||||
|
||||
|
||||
@shared_task
|
||||
def sanity_check():
|
||||
messages = sanity_checker.check_sanity()
|
||||
|
BIN
src/documents/tests/samples/corrupted.pdf
Normal file
BIN
src/documents/tests/samples/corrupted.pdf
Normal file
Binary file not shown.
@@ -289,12 +289,6 @@ class TestCustomFieldsSearch(DirectoriesMixin, APITestCase):
|
||||
lambda document: "string_field" in document,
|
||||
)
|
||||
|
||||
def test_exists_false(self):
|
||||
self._assert_query_match_predicate(
|
||||
["string_field", "exists", False],
|
||||
lambda document: "string_field" not in document,
|
||||
)
|
||||
|
||||
def test_select(self):
|
||||
# For select fields, you can either specify the index
|
||||
# or the name of the option. They function exactly the same.
|
||||
|
@@ -1,5 +1,8 @@
|
||||
import os
|
||||
import shutil
|
||||
import uuid
|
||||
from datetime import timedelta
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
from django.conf import settings
|
||||
@@ -7,15 +10,22 @@ from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
|
||||
from documents import tasks
|
||||
from documents.data_models import ConsumableDocument
|
||||
from documents.data_models import DocumentSource
|
||||
from documents.models import Correspondent
|
||||
from documents.models import Document
|
||||
from documents.models import DocumentType
|
||||
from documents.models import PaperlessTask
|
||||
from documents.models import Tag
|
||||
from documents.sanity_checker import SanityCheckFailedException
|
||||
from documents.sanity_checker import SanityCheckMessages
|
||||
from documents.signals.handlers import before_task_publish_handler
|
||||
from documents.signals.handlers import task_failure_handler
|
||||
from documents.tests.test_classifier import dummy_preprocess
|
||||
from documents.tests.utils import DirectoriesMixin
|
||||
from documents.tests.utils import DummyProgressManager
|
||||
from documents.tests.utils import FileSystemAssertsMixin
|
||||
from documents.tests.utils import SampleDirMixin
|
||||
|
||||
|
||||
class TestIndexReindex(DirectoriesMixin, TestCase):
|
||||
@@ -184,3 +194,68 @@ class TestEmptyTrashTask(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
||||
|
||||
tasks.empty_trash()
|
||||
self.assertEqual(Document.global_objects.count(), 0)
|
||||
|
||||
|
||||
class TestRetryConsumeTask(
|
||||
DirectoriesMixin,
|
||||
SampleDirMixin,
|
||||
FileSystemAssertsMixin,
|
||||
TestCase,
|
||||
):
|
||||
def do_failed_task(self, test_file: Path) -> PaperlessTask:
|
||||
temp_copy = self.dirs.scratch_dir / test_file.name
|
||||
shutil.copy(test_file, temp_copy)
|
||||
|
||||
headers = {
|
||||
"id": str(uuid.uuid4()),
|
||||
"task": "documents.tasks.consume_file",
|
||||
}
|
||||
body = (
|
||||
# args
|
||||
(
|
||||
ConsumableDocument(
|
||||
source=DocumentSource.ConsumeFolder,
|
||||
original_file=str(temp_copy),
|
||||
),
|
||||
None,
|
||||
),
|
||||
# kwargs
|
||||
{},
|
||||
# celery stuff
|
||||
{"callbacks": None, "errbacks": None, "chain": None, "chord": None},
|
||||
)
|
||||
before_task_publish_handler(headers=headers, body=body)
|
||||
|
||||
with mock.patch("documents.tasks.ProgressManager", DummyProgressManager):
|
||||
with self.assertRaises(Exception):
|
||||
tasks.consume_file(
|
||||
ConsumableDocument(
|
||||
source=DocumentSource.ConsumeFolder,
|
||||
original_file=temp_copy,
|
||||
),
|
||||
)
|
||||
|
||||
task_failure_handler(
|
||||
task_id=headers["id"],
|
||||
exception="Example failure",
|
||||
)
|
||||
|
||||
task = PaperlessTask.objects.first()
|
||||
# Ensure the file is moved to the failed dir
|
||||
self.assertIsFile(settings.CONSUMPTION_FAILED_DIR / task.task_file_name)
|
||||
return task
|
||||
|
||||
@mock.patch("documents.tasks.consume_file.delay")
|
||||
@mock.patch("documents.tasks.run_subprocess")
|
||||
def test_retry_consume_clean(self, m_subprocess, m_consume_file):
|
||||
task = self.do_failed_task(self.SAMPLE_DIR / "corrupted.pdf")
|
||||
m_subprocess.return_value.returncode = 0
|
||||
task_id = tasks.retry_failed_file(task_id=task.task_id, clean=True)
|
||||
self.assertIsNotNone(task_id)
|
||||
m_consume_file.assert_called_once()
|
||||
|
||||
def test_cleanup(self):
|
||||
task = self.do_failed_task(self.SAMPLE_DIR / "corrupted.pdf")
|
||||
task.acknowledged = True
|
||||
task.save() # simulate the task being acknowledged
|
||||
self.assertIsNotFile(settings.CONSUMPTION_FAILED_DIR / task.task_file_name)
|
||||
|
@@ -35,6 +35,7 @@ def setup_directories():
|
||||
dirs.scratch_dir = Path(tempfile.mkdtemp())
|
||||
dirs.media_dir = Path(tempfile.mkdtemp())
|
||||
dirs.consumption_dir = Path(tempfile.mkdtemp())
|
||||
dirs.consumption_failed_dir = Path(tempfile.mkdtemp("failed"))
|
||||
dirs.static_dir = Path(tempfile.mkdtemp())
|
||||
dirs.index_dir = dirs.data_dir / "index"
|
||||
dirs.originals_dir = dirs.media_dir / "documents" / "originals"
|
||||
@@ -56,6 +57,7 @@ def setup_directories():
|
||||
THUMBNAIL_DIR=dirs.thumbnail_dir,
|
||||
ARCHIVE_DIR=dirs.archive_dir,
|
||||
CONSUMPTION_DIR=dirs.consumption_dir,
|
||||
CONSUMPTION_FAILED_DIR=dirs.consumption_failed_dir,
|
||||
LOGGING_DIR=dirs.logging_dir,
|
||||
INDEX_DIR=dirs.index_dir,
|
||||
STATIC_ROOT=dirs.static_dir,
|
||||
@@ -72,6 +74,7 @@ def remove_dirs(dirs):
|
||||
shutil.rmtree(dirs.data_dir, ignore_errors=True)
|
||||
shutil.rmtree(dirs.scratch_dir, ignore_errors=True)
|
||||
shutil.rmtree(dirs.consumption_dir, ignore_errors=True)
|
||||
shutil.rmtree(dirs.consumption_failed_dir, ignore_errors=True)
|
||||
shutil.rmtree(dirs.static_dir, ignore_errors=True)
|
||||
dirs.settings_override.disable()
|
||||
|
||||
|
@@ -136,6 +136,7 @@ from documents.serialisers import DocumentListSerializer
|
||||
from documents.serialisers import DocumentSerializer
|
||||
from documents.serialisers import DocumentTypeSerializer
|
||||
from documents.serialisers import PostDocumentSerializer
|
||||
from documents.serialisers import RetryTaskSerializer
|
||||
from documents.serialisers import SavedViewSerializer
|
||||
from documents.serialisers import SearchResultSerializer
|
||||
from documents.serialisers import ShareLinkSerializer
|
||||
@@ -152,6 +153,7 @@ from documents.serialisers import WorkflowTriggerSerializer
|
||||
from documents.signals import document_updated
|
||||
from documents.tasks import consume_file
|
||||
from documents.tasks import empty_trash
|
||||
from documents.tasks import retry_failed_file
|
||||
from documents.templating.filepath import validate_filepath_template_and_render
|
||||
from paperless import version
|
||||
from paperless.celery import app as celery_app
|
||||
@@ -1718,6 +1720,25 @@ class TasksViewSet(ReadOnlyModelViewSet):
|
||||
queryset = PaperlessTask.objects.filter(task_id=task_id)
|
||||
return queryset
|
||||
|
||||
@action(methods=["post"], detail=True)
|
||||
def retry(self, request, pk=None):
|
||||
task = self.get_object()
|
||||
|
||||
serializer = RetryTaskSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
clean = serializer.validated_data.get("clean")
|
||||
|
||||
try:
|
||||
new_task_id = retry_failed_file(task.task_id, clean)
|
||||
return Response({"task_id": new_task_id})
|
||||
except FileNotFoundError:
|
||||
return HttpResponseBadRequest("Original file not found")
|
||||
except Exception as e:
|
||||
logger.warning(f"An error occurred retrying task: {e!s}")
|
||||
return HttpResponseBadRequest(
|
||||
"Error retrying task, check logs for more detail.",
|
||||
)
|
||||
|
||||
|
||||
class AcknowledgeTasksView(GenericAPIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-19 22:56-0700\n"
|
||||
"PO-Revision-Date: 2024-11-02 00:29\n"
|
||||
"PO-Revision-Date: 2024-10-20 12:11\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: German\n"
|
||||
"Language: de_DE\n"
|
||||
@@ -47,7 +47,7 @@ msgstr "{name!r} ist kein gültiges benutzerdefiniertes Feld."
|
||||
|
||||
#: documents/filters.py:492
|
||||
msgid "{data_type} does not support query expr {expr!r}."
|
||||
msgstr "{data_type} unterstützt den Abfrageausdruck {expr!r} nicht."
|
||||
msgstr "{data_type} unterstützt Abfrage expr {expr!r} nicht."
|
||||
|
||||
#: documents/filters.py:600
|
||||
msgid "Maximum nesting depth exceeded."
|
||||
@@ -1547,11 +1547,11 @@ msgstr "IMAP"
|
||||
|
||||
#: paperless_mail/models.py:20
|
||||
msgid "Gmail OAuth"
|
||||
msgstr "Gmail-OAuth"
|
||||
msgstr "Gmail OAuth"
|
||||
|
||||
#: paperless_mail/models.py:21
|
||||
msgid "Outlook OAuth"
|
||||
msgstr "Outlook-OAuth"
|
||||
msgstr "Outlook OAuh"
|
||||
|
||||
#: paperless_mail/models.py:25
|
||||
msgid "IMAP server"
|
||||
@@ -1599,7 +1599,7 @@ msgstr "Aktualisierungstoken"
|
||||
|
||||
#: paperless_mail/models.py:71
|
||||
msgid "The refresh token to use for token authentication e.g. with oauth2."
|
||||
msgstr "Das Aktualisierungstoken, das für die Tokenauthentifizierung (z.B. mit OAuth2) verwendet werden soll."
|
||||
msgstr "Das Aktualisierungstoken für die Tokenauthentifizierung z.B. mit OAuth2."
|
||||
|
||||
#: paperless_mail/models.py:80
|
||||
msgid "The expiration date of the refresh token. "
|
||||
|
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-19 22:56-0700\n"
|
||||
"PO-Revision-Date: 2024-11-03 04:57\n"
|
||||
"PO-Revision-Date: 2024-10-20 05:58\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish\n"
|
||||
"Language: es_ES\n"
|
||||
@@ -23,35 +23,35 @@ msgstr "Documentos"
|
||||
|
||||
#: documents/filters.py:334
|
||||
msgid "Value must be valid JSON."
|
||||
msgstr "El valor debe ser JSON válido."
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:353
|
||||
msgid "Invalid custom field query expression"
|
||||
msgstr "Expresión de consulta de campo personalizado no válida"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:363
|
||||
msgid "Invalid expression list. Must be nonempty."
|
||||
msgstr "Lista de expresiones no válida. Debe ser no vacía."
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:384
|
||||
msgid "Invalid logical operator {op!r}"
|
||||
msgstr "Operador lógico inválido {op!r}"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:398
|
||||
msgid "Maximum number of query conditions exceeded."
|
||||
msgstr "Se ha superado el número máximo de condiciones de consulta."
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:455
|
||||
msgid "{name!r} is not a valid custom field."
|
||||
msgstr "{nombre!r} no es un campo personalizado válido."
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:492
|
||||
msgid "{data_type} does not support query expr {expr!r}."
|
||||
msgstr "{data_type} no admite la consulta expr {expr!r}."
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:600
|
||||
msgid "Maximum nesting depth exceeded."
|
||||
msgstr "Profundidad máxima de nidificación superada."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:41 documents/models.py:802
|
||||
msgid "owner"
|
||||
@@ -192,11 +192,11 @@ msgstr "La cadena de verificación del documento archivado."
|
||||
|
||||
#: documents/models.py:211
|
||||
msgid "page count"
|
||||
msgstr "número de páginas"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:218
|
||||
msgid "The number of pages of the document."
|
||||
msgstr "El número de páginas del documento."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:222 documents/models.py:402 documents/models.py:722
|
||||
#: documents/models.py:760 documents/models.py:831 documents/models.py:889
|
||||
@@ -353,7 +353,7 @@ msgstr "ASN"
|
||||
|
||||
#: documents/models.py:431
|
||||
msgid "Pages"
|
||||
msgstr "Páginas"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:437
|
||||
msgid "show on dashboard"
|
||||
@@ -561,7 +561,7 @@ msgstr "no tiene campo personalizado"
|
||||
|
||||
#: documents/models.py:525
|
||||
msgid "custom fields query"
|
||||
msgstr "consulta de campos personalizados"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:535
|
||||
msgid "rule type"
|
||||
@@ -1543,7 +1543,7 @@ msgstr "Usar STARTTLS"
|
||||
|
||||
#: paperless_mail/models.py:19
|
||||
msgid "IMAP"
|
||||
msgstr "IMAP"
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:20
|
||||
msgid "Gmail OAuth"
|
||||
|
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-19 22:56-0700\n"
|
||||
"PO-Revision-Date: 2024-11-03 00:33\n"
|
||||
"PO-Revision-Date: 2024-10-29 18:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Italian\n"
|
||||
"Language: it_IT\n"
|
||||
@@ -23,11 +23,11 @@ msgstr "Documenti"
|
||||
|
||||
#: documents/filters.py:334
|
||||
msgid "Value must be valid JSON."
|
||||
msgstr "Il valore deve essere un JSON valido."
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:353
|
||||
msgid "Invalid custom field query expression"
|
||||
msgstr "Espressione della query del campo personalizzato non valida"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:363
|
||||
msgid "Invalid expression list. Must be nonempty."
|
||||
@@ -35,7 +35,7 @@ msgstr ""
|
||||
|
||||
#: documents/filters.py:384
|
||||
msgid "Invalid logical operator {op!r}"
|
||||
msgstr "Operatore logico non valido {op!r}"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:398
|
||||
msgid "Maximum number of query conditions exceeded."
|
||||
@@ -43,7 +43,7 @@ msgstr ""
|
||||
|
||||
#: documents/filters.py:455
|
||||
msgid "{name!r} is not a valid custom field."
|
||||
msgstr "{name!r} non è un campo personalizzato valido."
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:492
|
||||
msgid "{data_type} does not support query expr {expr!r}."
|
||||
|
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-19 22:56-0700\n"
|
||||
"PO-Revision-Date: 2024-11-02 00:29\n"
|
||||
"PO-Revision-Date: 2024-10-25 12:12\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Swedish\n"
|
||||
"Language: sv_SE\n"
|
||||
@@ -1015,7 +1015,7 @@ msgstr "Vänligen logga in."
|
||||
#: documents/templates/account/login.html:12
|
||||
#, python-format
|
||||
msgid "Don't have an account yet? <a href=\"%(signup_url)s\">Sign up</a>"
|
||||
msgstr "Har du inget konto än? <a href=\"%(signup_url)s\">Registrera dig</a>"
|
||||
msgstr ""
|
||||
|
||||
#: documents/templates/account/login.html:19
|
||||
#: documents/templates/account/signup.html:15
|
||||
@@ -1117,7 +1117,7 @@ msgstr ""
|
||||
#: documents/templates/account/signup.html:10
|
||||
#, python-format
|
||||
msgid "Already have an account? <a href=\"%(login_url)s\">Sign in</a>"
|
||||
msgstr "Har du redan ett konto? <a href=\"%(login_url)s\">Logga in</a>"
|
||||
msgstr ""
|
||||
|
||||
#: documents/templates/account/signup.html:16
|
||||
#: documents/templates/socialaccount/signup.html:14
|
||||
@@ -1131,7 +1131,7 @@ msgstr ""
|
||||
#: documents/templates/account/signup.html:36
|
||||
#: documents/templates/socialaccount/signup.html:27
|
||||
msgid "Sign up"
|
||||
msgstr "Registrera dig"
|
||||
msgstr ""
|
||||
|
||||
#: documents/templates/index.html:61
|
||||
msgid "Paperless-ngx is loading..."
|
||||
@@ -1170,7 +1170,7 @@ msgstr ""
|
||||
|
||||
#: documents/templates/socialaccount/login.html:13
|
||||
msgid "Continue"
|
||||
msgstr "Fortsätt"
|
||||
msgstr ""
|
||||
|
||||
#: documents/templates/socialaccount/signup.html:5
|
||||
msgid "Paperless-ngx social account sign up"
|
||||
@@ -1366,7 +1366,7 @@ msgstr "Belarusiska"
|
||||
|
||||
#: paperless/settings.py:688
|
||||
msgid "Bulgarian"
|
||||
msgstr "Bulgariska"
|
||||
msgstr ""
|
||||
|
||||
#: paperless/settings.py:689
|
||||
msgid "Catalan"
|
||||
@@ -1386,7 +1386,7 @@ msgstr "Tyska"
|
||||
|
||||
#: paperless/settings.py:693
|
||||
msgid "Greek"
|
||||
msgstr "Grekiska"
|
||||
msgstr ""
|
||||
|
||||
#: paperless/settings.py:694
|
||||
msgid "English (GB)"
|
||||
@@ -1414,7 +1414,7 @@ msgstr "Italienska"
|
||||
|
||||
#: paperless/settings.py:700
|
||||
msgid "Japanese"
|
||||
msgstr "Japanska"
|
||||
msgstr ""
|
||||
|
||||
#: paperless/settings.py:701
|
||||
msgid "Korean"
|
||||
@@ -1426,7 +1426,7 @@ msgstr "Luxemburgiska"
|
||||
|
||||
#: paperless/settings.py:703
|
||||
msgid "Norwegian"
|
||||
msgstr "Norska"
|
||||
msgstr ""
|
||||
|
||||
#: paperless/settings.py:704
|
||||
msgid "Dutch"
|
||||
@@ -1542,7 +1542,7 @@ msgstr "Använd STARTTLS"
|
||||
|
||||
#: paperless_mail/models.py:19
|
||||
msgid "IMAP"
|
||||
msgstr "IMAP"
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:20
|
||||
msgid "Gmail OAuth"
|
||||
|
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-19 22:56-0700\n"
|
||||
"PO-Revision-Date: 2024-10-31 12:12\n"
|
||||
"PO-Revision-Date: 2024-10-20 05:58\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Thai\n"
|
||||
"Language: th_TH\n"
|
||||
@@ -23,35 +23,35 @@ msgstr "เอกสาร"
|
||||
|
||||
#: documents/filters.py:334
|
||||
msgid "Value must be valid JSON."
|
||||
msgstr "ค่า ต้องอยู่ในรูปแบบ JSON ที่ถูกต้อง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:353
|
||||
msgid "Invalid custom field query expression"
|
||||
msgstr "รูปแบบการค้นหาฟิลด์ที่กำหนดเองไม่ถูกต้อง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:363
|
||||
msgid "Invalid expression list. Must be nonempty."
|
||||
msgstr "รายการคำสั่งไม่ถูกต้อง ต้องไม่เว้นว่าง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:384
|
||||
msgid "Invalid logical operator {op!r}"
|
||||
msgstr "ตัวดำเนินการเชิงตรรกะ {op!r} ไม่ถูกต้อง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:398
|
||||
msgid "Maximum number of query conditions exceeded."
|
||||
msgstr "จำนวนเงื่อนไขในการค้นหาเกินกำหนด"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:455
|
||||
msgid "{name!r} is not a valid custom field."
|
||||
msgstr "{name!r} ไม่ใช่ฟิลด์ที่กำหนดเองที่ถูกต้อง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:492
|
||||
msgid "{data_type} does not support query expr {expr!r}."
|
||||
msgstr "{data_type} ไม่รองรับรูปแบบการค้นหา {expr!r}"
|
||||
msgstr ""
|
||||
|
||||
#: documents/filters.py:600
|
||||
msgid "Maximum nesting depth exceeded."
|
||||
msgstr "จำนวนการซ้อนเงื่อนไขสูงสุดเกินขีดจำกัด"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:41 documents/models.py:802
|
||||
msgid "owner"
|
||||
@@ -192,11 +192,11 @@ msgstr "ค่า checksum ของเอกสารประเภทเก
|
||||
|
||||
#: documents/models.py:211
|
||||
msgid "page count"
|
||||
msgstr "จำนวนหน้า"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:218
|
||||
msgid "The number of pages of the document."
|
||||
msgstr "จำนวนหน้าทั้งหมดของเอกสาร"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:222 documents/models.py:402 documents/models.py:722
|
||||
#: documents/models.py:760 documents/models.py:831 documents/models.py:889
|
||||
@@ -301,11 +301,11 @@ msgstr "ตาราง"
|
||||
|
||||
#: documents/models.py:416
|
||||
msgid "Small Cards"
|
||||
msgstr "การ์ดขนาดเล็ก"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:417
|
||||
msgid "Large Cards"
|
||||
msgstr "การ์ดขนาดใหญ่"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:420
|
||||
msgid "Title"
|
||||
@@ -313,11 +313,11 @@ msgstr ""
|
||||
|
||||
#: documents/models.py:421
|
||||
msgid "Created"
|
||||
msgstr "วันที่สร้าง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:422
|
||||
msgid "Added"
|
||||
msgstr "วันที่เพิ่ม"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:423
|
||||
msgid "Tags"
|
||||
@@ -333,7 +333,7 @@ msgstr "ประเภทเอกสาร"
|
||||
|
||||
#: documents/models.py:426
|
||||
msgid "Storage Path"
|
||||
msgstr "ตำแหน่งจัดเก็บ"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:427
|
||||
msgid "Note"
|
||||
@@ -345,7 +345,7 @@ msgstr "เจ้าของ"
|
||||
|
||||
#: documents/models.py:429
|
||||
msgid "Shared"
|
||||
msgstr "แชร์แล้ว"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:430
|
||||
msgid "ASN"
|
||||
@@ -353,7 +353,7 @@ msgstr ""
|
||||
|
||||
#: documents/models.py:431
|
||||
msgid "Pages"
|
||||
msgstr "หน้า"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:437
|
||||
msgid "show on dashboard"
|
||||
@@ -373,15 +373,15 @@ msgstr "เรียงย้อนกลับ"
|
||||
|
||||
#: documents/models.py:452
|
||||
msgid "View page size"
|
||||
msgstr "ขนาดการแสดงผลหน้า"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:460
|
||||
msgid "View display mode"
|
||||
msgstr "โหมดการแสดงผล"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:467
|
||||
msgid "Document display fields"
|
||||
msgstr "ฟิลด์การแสดงผลของเอกสาร"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:474 documents/models.py:532
|
||||
msgid "saved view"
|
||||
@@ -537,31 +537,31 @@ msgstr "ไม่มีเจ้าของเป็น"
|
||||
|
||||
#: documents/models.py:519
|
||||
msgid "has custom field value"
|
||||
msgstr "มีค่าฟิลด์ที่กำหนดเอง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:520
|
||||
msgid "is shared by me"
|
||||
msgstr "แชร์โดยฉัน"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:521
|
||||
msgid "has custom fields"
|
||||
msgstr "มีฟิลด์ที่กำหนดเอง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:522
|
||||
msgid "has custom field in"
|
||||
msgstr "มีฟิลด์ที่กำหนดเองใน"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:523
|
||||
msgid "does not have custom field in"
|
||||
msgstr "ไม่มีฟิลด์ที่กำหนดเอง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:524
|
||||
msgid "does not have custom field"
|
||||
msgstr "ไม่มีฟิลด์ที่กำหนดเองใน"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:525
|
||||
msgid "custom fields query"
|
||||
msgstr "การค้นหาฟิลด์ที่กำหนดเอง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:535
|
||||
msgid "rule type"
|
||||
@@ -717,11 +717,11 @@ msgstr "Float"
|
||||
|
||||
#: documents/models.py:826
|
||||
msgid "Monetary"
|
||||
msgstr "จำนวนเงิน"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:827
|
||||
msgid "Document Link"
|
||||
msgstr "ลิงก์ของเอกสาร"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:828
|
||||
msgid "Select"
|
||||
@@ -733,23 +733,23 @@ msgstr "ชนิดข้อมูล"
|
||||
|
||||
#: documents/models.py:847
|
||||
msgid "extra data"
|
||||
msgstr "ข้อมูลเพิ่มเติม"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:851
|
||||
msgid "Extra data for the custom field, such as select options"
|
||||
msgstr "ข้อมูลเพิ่มเติมสำหรับฟิลด์ที่กำหนดเอง เช่น ตัวเลือก"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:857
|
||||
msgid "custom field"
|
||||
msgstr "ฟิลด์ที่กำหนดเอง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:858
|
||||
msgid "custom fields"
|
||||
msgstr "ฟิลด์ที่กำหนดเอง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:955
|
||||
msgid "custom field instance"
|
||||
msgstr "ชุดข้อมูลฟิลด์ที่กำหนดเอง"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:956
|
||||
msgid "custom field instances"
|
||||
@@ -757,7 +757,7 @@ msgstr ""
|
||||
|
||||
#: documents/models.py:1017
|
||||
msgid "Consumption Started"
|
||||
msgstr "เริ่มใช้งาน"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1018
|
||||
msgid "Document Added"
|
||||
@@ -769,7 +769,7 @@ msgstr "ปรับปรุงเอกสารแล้ว"
|
||||
|
||||
#: documents/models.py:1022
|
||||
msgid "Consume Folder"
|
||||
msgstr "โฟลเดอร์ใช้งาน"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1023
|
||||
msgid "Api Upload"
|
||||
|
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-19 22:56-0700\n"
|
||||
"PO-Revision-Date: 2024-11-03 04:57\n"
|
||||
"PO-Revision-Date: 2024-10-29 12:12\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"Language: zh_CN\n"
|
||||
@@ -1603,7 +1603,7 @@ msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:80
|
||||
msgid "The expiration date of the refresh token. "
|
||||
msgstr "刷新令牌的到期日期。 "
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:90
|
||||
msgid "mail rule"
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,10 @@ def paths_check(app_configs, **kwargs):
|
||||
+ path_check("PAPERLESS_EMPTY_TRASH_DIR", settings.EMPTY_TRASH_DIR)
|
||||
+ path_check("PAPERLESS_MEDIA_ROOT", settings.MEDIA_ROOT)
|
||||
+ path_check("PAPERLESS_CONSUMPTION_DIR", settings.CONSUMPTION_DIR)
|
||||
+ path_check(
|
||||
"PAPERLESS_CONSUMPTION_FAILED_DIR",
|
||||
settings.CONSUMPTION_FAILED_DIR,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
@@ -281,6 +281,11 @@ CONSUMPTION_DIR = __get_path(
|
||||
BASE_DIR.parent / "consume",
|
||||
)
|
||||
|
||||
CONSUMPTION_FAILED_DIR = __get_path(
|
||||
"PAPERLESS_CONSUMPTION_FAILED_DIR",
|
||||
CONSUMPTION_DIR / "failed",
|
||||
)
|
||||
|
||||
# This will be created if it doesn't exist
|
||||
SCRATCH_DIR = __get_path(
|
||||
"PAPERLESS_SCRATCH_DIR",
|
||||
@@ -890,6 +895,8 @@ CONSUMER_IGNORE_PATTERNS = list(
|
||||
),
|
||||
),
|
||||
)
|
||||
if CONSUMPTION_DIR in CONSUMPTION_FAILED_DIR.parents:
|
||||
CONSUMER_IGNORE_PATTERNS.append(CONSUMPTION_FAILED_DIR.name)
|
||||
|
||||
CONSUMER_SUBDIRS_AS_TAGS = __get_boolean("PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS")
|
||||
|
||||
|
@@ -29,10 +29,11 @@ class TestChecks(DirectoriesMixin, TestCase):
|
||||
MEDIA_ROOT="uuh",
|
||||
DATA_DIR="whatever",
|
||||
CONSUMPTION_DIR="idontcare",
|
||||
CONSUMPTION_FAILED_DIR="nope",
|
||||
)
|
||||
def test_paths_check_dont_exist(self):
|
||||
msgs = paths_check(None)
|
||||
self.assertEqual(len(msgs), 3, str(msgs))
|
||||
self.assertEqual(len(msgs), 4, str(msgs))
|
||||
|
||||
for msg in msgs:
|
||||
self.assertTrue(msg.msg.endswith("is set but doesn't exist."))
|
||||
@@ -41,13 +42,15 @@ class TestChecks(DirectoriesMixin, TestCase):
|
||||
os.chmod(self.dirs.data_dir, 0o000)
|
||||
os.chmod(self.dirs.media_dir, 0o000)
|
||||
os.chmod(self.dirs.consumption_dir, 0o000)
|
||||
os.chmod(self.dirs.consumption_failed_dir, 0o000)
|
||||
|
||||
self.addCleanup(os.chmod, self.dirs.data_dir, 0o777)
|
||||
self.addCleanup(os.chmod, self.dirs.media_dir, 0o777)
|
||||
self.addCleanup(os.chmod, self.dirs.consumption_dir, 0o777)
|
||||
self.addCleanup(os.chmod, self.dirs.consumption_failed_dir, 0o777)
|
||||
|
||||
msgs = paths_check(None)
|
||||
self.assertEqual(len(msgs), 3)
|
||||
self.assertEqual(len(msgs), 4)
|
||||
|
||||
for msg in msgs:
|
||||
self.assertTrue(msg.msg.endswith("is not writeable"))
|
||||
|
@@ -1,6 +1,6 @@
|
||||
from typing import Final
|
||||
|
||||
__version__: Final[tuple[int, int, int]] = (2, 13, 4)
|
||||
__version__: Final[tuple[int, int, int]] = (2, 13, 2)
|
||||
# Version string like X.Y.Z
|
||||
__full_version_str__: Final[str] = ".".join(map(str, __version__))
|
||||
# Version string like X.Y
|
||||
|
Reference in New Issue
Block a user