mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-10-30 03:56:23 -05:00
Compare commits
9 Commits
84942a4e69
...
1709aee903
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1709aee903 | ||
|
|
c4346124c3 | ||
|
|
44b8c4881a | ||
|
|
d3d8eef0b6 | ||
|
|
a283c1c320 | ||
|
|
f3220ce981 | ||
|
|
2dc4f1f49b | ||
|
|
17509171bb | ||
|
|
9e11e7fd05 |
@@ -506,6 +506,7 @@ for the possible codes and their meanings.
|
|||||||
The `localize_date` filter formats a date or datetime object into a localized string using Babel internationalization.
|
The `localize_date` filter formats a date or datetime object into a localized string using Babel internationalization.
|
||||||
This takes into account the provided locale for translation. Since this must be used on a date or datetime object,
|
This takes into account the provided locale for translation. Since this must be used on a date or datetime object,
|
||||||
you must access the field directly, i.e. `document.created`.
|
you must access the field directly, i.e. `document.created`.
|
||||||
|
An ISO string can also be provided to control the output format.
|
||||||
|
|
||||||
###### Syntax
|
###### Syntax
|
||||||
|
|
||||||
@@ -516,7 +517,7 @@ you must access the field directly, i.e. `document.created`.
|
|||||||
|
|
||||||
###### Parameters
|
###### Parameters
|
||||||
|
|
||||||
- `value` (date | datetime): Date or datetime object to format (datetime should be timezone-aware)
|
- `value` (date | datetime | str): Date, datetime object or ISO string to format (datetime should be timezone-aware)
|
||||||
- `format` (str): Format type - either a Babel preset ('short', 'medium', 'long', 'full') or custom pattern
|
- `format` (str): Format type - either a Babel preset ('short', 'medium', 'long', 'full') or custom pattern
|
||||||
- `locale` (str): Locale code for localization (e.g., 'en_US', 'fr_FR', 'de_DE')
|
- `locale` (str): Locale code for localization (e.g., 'en_US', 'fr_FR', 'de_DE')
|
||||||
|
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ Currently, there are three events that correspond to workflow trigger 'types':
|
|||||||
but the document content has been extracted and metadata such as document type, tags, etc. have been set, so these can now
|
but the document content has been extracted and metadata such as document type, tags, etc. have been set, so these can now
|
||||||
be used for filtering.
|
be used for filtering.
|
||||||
3. **Document Updated**: when a document is updated. Similar to 'added' events, triggers can include filtering by content matching,
|
3. **Document Updated**: when a document is updated. Similar to 'added' events, triggers can include filtering by content matching,
|
||||||
tags, doc type, or correspondent.
|
tags, doc type, correspondent or storage path.
|
||||||
4. **Scheduled**: a scheduled trigger that can be used to run workflows at a specific time. The date used can be either the document
|
4. **Scheduled**: a scheduled trigger that can be used to run workflows at a specific time. The date used can be either the document
|
||||||
added, created, updated date or you can specify a (date) custom field. You can also specify a day offset from the date (positive
|
added, created, updated date or you can specify a (date) custom field. You can also specify a day offset from the date (positive
|
||||||
offsets will trigger after the date, negative offsets will trigger before).
|
offsets will trigger after the date, negative offsets will trigger before).
|
||||||
@@ -452,10 +452,11 @@ Workflows allow you to filter by:
|
|||||||
- File path, including wildcards. Note that enabling `PAPERLESS_CONSUMER_RECURSIVE` would allow, for
|
- File path, including wildcards. Note that enabling `PAPERLESS_CONSUMER_RECURSIVE` would allow, for
|
||||||
example, automatically assigning documents to different owners based on the upload directory.
|
example, automatically assigning documents to different owners based on the upload directory.
|
||||||
- Mail rule. Choosing this option will force 'mail fetch' to be the workflow source.
|
- Mail rule. Choosing this option will force 'mail fetch' to be the workflow source.
|
||||||
- Content matching (`Added` and `Updated` triggers only). Filter document content using the matching settings.
|
- Content matching (`Added`, `Updated` and `Scheduled` triggers only). Filter document content using the matching settings.
|
||||||
- Tags (`Added` and `Updated` triggers only). Filter for documents with any of the specified tags
|
- Tags (`Added`, `Updated` and `Scheduled` triggers only). Filter for documents with any of the specified tags
|
||||||
- Document type (`Added` and `Updated` triggers only). Filter documents with this doc type
|
- Document type (`Added`, `Updated` and `Scheduled` triggers only). Filter documents with this doc type
|
||||||
- Correspondent (`Added` and `Updated` triggers only). Filter documents with this correspondent
|
- Correspondent (`Added`, `Updated` and `Scheduled` triggers only). Filter documents with this correspondent
|
||||||
|
- Storage path (`Added`, `Updated` and `Scheduled` triggers only). Filter documents with this storage path
|
||||||
|
|
||||||
### Workflow Actions
|
### Workflow Actions
|
||||||
|
|
||||||
@@ -505,35 +506,52 @@ you may want to adjust these settings to prevent abuse.
|
|||||||
|
|
||||||
#### Workflow placeholders
|
#### Workflow placeholders
|
||||||
|
|
||||||
Some workflow text can include placeholders but the available options differ depending on the type of
|
Titles can be assigned by workflows using [Jinja templates](https://jinja.palletsprojects.com/en/3.1.x/templates/).
|
||||||
workflow trigger. This is because at the time of consumption (when the text is to be set), no automatic tags etc. have been
|
This allows for complex logic to be used to generate the title, including [logical structures](https://jinja.palletsprojects.com/en/3.1.x/templates/#list-of-control-structures)
|
||||||
applied. You can use the following placeholders with any trigger type:
|
and [filters](https://jinja.palletsprojects.com/en/3.1.x/templates/#id11).
|
||||||
|
The template is provided as a string.
|
||||||
|
|
||||||
- `{correspondent}`: assigned correspondent name
|
Using Jinja2 Templates is also useful for [Date localization](advanced_usage.md#Date-Localization) in the title.
|
||||||
- `{document_type}`: assigned document type name
|
|
||||||
- `{owner_username}`: assigned owner username
|
The available inputs differ depending on the type of workflow trigger.
|
||||||
- `{added}`: added datetime
|
This is because at the time of consumption (when the text is to be set), no automatic tags etc. have been
|
||||||
- `{added_year}`: added year
|
applied. You can use the following placeholders in the template with any trigger type:
|
||||||
- `{added_year_short}`: added year
|
|
||||||
- `{added_month}`: added month
|
- `{{correspondent}}`: assigned correspondent name
|
||||||
- `{added_month_name}`: added month name
|
- `{{document_type}}`: assigned document type name
|
||||||
- `{added_month_name_short}`: added month short name
|
- `{{owner_username}}`: assigned owner username
|
||||||
- `{added_day}`: added day
|
- `{{added}}`: added datetime
|
||||||
- `{added_time}`: added time in HH:MM format
|
- `{{added_year}}`: added year
|
||||||
- `{original_filename}`: original file name without extension
|
- `{{added_year_short}}`: added year
|
||||||
- `{filename}`: current file name without extension
|
- `{{added_month}}`: added month
|
||||||
|
- `{{added_month_name}}`: added month name
|
||||||
|
- `{{added_month_name_short}}`: added month short name
|
||||||
|
- `{{added_day}}`: added day
|
||||||
|
- `{{added_time}}`: added time in HH:MM format
|
||||||
|
- `{{original_filename}}`: original file name without extension
|
||||||
|
- `{{filename}}`: current file name without extension
|
||||||
|
|
||||||
The following placeholders are only available for "added" or "updated" triggers
|
The following placeholders are only available for "added" or "updated" triggers
|
||||||
|
|
||||||
- `{created}`: created datetime
|
- `{{created}}`: created datetime
|
||||||
- `{created_year}`: created year
|
- `{{created_year}}`: created year
|
||||||
- `{created_year_short}`: created year
|
- `{{created_year_short}}`: created year
|
||||||
- `{created_month}`: created month
|
- `{{created_month}}`: created month
|
||||||
- `{created_month_name}`: created month name
|
- `{{created_month_name}}`: created month name
|
||||||
- `{created_month_name_short}`: created month short name
|
- `{created_month_name_short}}`: created month short name
|
||||||
- `{created_day}`: created day
|
- `{{created_day}}`: created day
|
||||||
- `{created_time}`: created time in HH:MM format
|
- `{{created_time}}`: created time in HH:MM format
|
||||||
- `{doc_url}`: URL to the document in the web UI. Requires the `PAPERLESS_URL` setting to be set.
|
- `{{doc_url}}`: URL to the document in the web UI. Requires the `PAPERLESS_URL` setting to be set.
|
||||||
|
|
||||||
|
##### Examples
|
||||||
|
|
||||||
|
```jinja2
|
||||||
|
{{ created | localize_date('MMMM', 'en_US') }}
|
||||||
|
<!-- Output: "January" -->
|
||||||
|
|
||||||
|
{{ added | localize_date('MMMM', 'de_DE') }}
|
||||||
|
<!-- Output: "Juni" --> # codespell:ignore
|
||||||
|
```
|
||||||
|
|
||||||
### Workflow permissions
|
### Workflow permissions
|
||||||
|
|
||||||
|
|||||||
@@ -385,7 +385,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">109</context>
|
<context context-type="linenumber">113</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1241348629231510663" datatype="html">
|
<trans-unit id="1241348629231510663" datatype="html">
|
||||||
@@ -534,7 +534,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">362</context>
|
<context context-type="linenumber">366</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3768927257183755959" datatype="html">
|
<trans-unit id="3768927257183755959" datatype="html">
|
||||||
@@ -593,7 +593,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">355</context>
|
<context context-type="linenumber">359</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/custom-fields-bulk-edit-dialog/custom-fields-bulk-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/custom-fields-bulk-edit-dialog/custom-fields-bulk-edit-dialog.component.html</context>
|
||||||
@@ -739,7 +739,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">375</context>
|
<context context-type="linenumber">379</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
|
||||||
@@ -1197,7 +1197,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">331</context>
|
<context context-type="linenumber">335</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
||||||
@@ -1291,19 +1291,19 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">209</context>
|
<context context-type="linenumber">210</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<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 context-type="linenumber">229</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">295</context>
|
<context context-type="linenumber">296</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">314</context>
|
<context context-type="linenumber">315</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context>
|
||||||
@@ -1326,19 +1326,19 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">217</context>
|
<context context-type="linenumber">218</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">236</context>
|
<context context-type="linenumber">237</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">303</context>
|
<context context-type="linenumber">304</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">322</context>
|
<context context-type="linenumber">323</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context>
|
||||||
@@ -1364,11 +1364,11 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">242</context>
|
<context context-type="linenumber">243</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">328</context>
|
<context context-type="linenumber">329</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context>
|
||||||
@@ -2544,11 +2544,11 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1019</context>
|
<context context-type="linenumber">1023</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1384</context>
|
<context context-type="linenumber">1388</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||||
@@ -3156,7 +3156,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">972</context>
|
<context context-type="linenumber">976</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||||
@@ -3346,7 +3346,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">103</context>
|
<context context-type="linenumber">107</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context>
|
<context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context>
|
||||||
@@ -4055,7 +4055,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">196</context>
|
<context context-type="linenumber">197</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4754802869258527587" datatype="html">
|
<trans-unit id="4754802869258527587" datatype="html">
|
||||||
@@ -4073,7 +4073,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">197</context>
|
<context context-type="linenumber">198</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1519954996184640001" datatype="html">
|
<trans-unit id="1519954996184640001" datatype="html">
|
||||||
@@ -4291,7 +4291,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">297</context>
|
<context context-type="linenumber">301</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8057014866157903311" datatype="html">
|
<trans-unit id="8057014866157903311" datatype="html">
|
||||||
@@ -4395,7 +4395,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">88</context>
|
<context context-type="linenumber">92</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5342432350421167093" datatype="html">
|
<trans-unit id="5342432350421167093" datatype="html">
|
||||||
@@ -4739,238 +4739,245 @@
|
|||||||
<context context-type="linenumber">179</context>
|
<context context-type="linenumber">179</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="4277260190522078330" datatype="html">
|
||||||
|
<source>Has storage path</source>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
|
<context context-type="linenumber">180</context>
|
||||||
|
</context-group>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="6417103744331194518" datatype="html">
|
<trans-unit id="6417103744331194518" datatype="html">
|
||||||
<source>Action type</source>
|
<source>Action type</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">189</context>
|
<context context-type="linenumber">190</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6019822389883736115" datatype="html">
|
<trans-unit id="6019822389883736115" datatype="html">
|
||||||
<source>Assign title</source>
|
<source>Assign title</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">194</context>
|
<context context-type="linenumber">195</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1098196422099517191" datatype="html">
|
<trans-unit id="1098196422099517191" datatype="html">
|
||||||
<source>Can include some placeholders, see <a target='_blank' href='https://docs.paperless-ngx.com/usage/#workflows'>documentation</a>.</source>
|
<source>Can include some placeholders, see <a target='_blank' href='https://docs.paperless-ngx.com/usage/#workflows'>documentation</a>.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">194</context>
|
<context context-type="linenumber">195</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6528897010417701530" datatype="html">
|
<trans-unit id="6528897010417701530" datatype="html">
|
||||||
<source>Assign tags</source>
|
<source>Assign tags</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">195</context>
|
<context context-type="linenumber">196</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7198346314713788799" datatype="html">
|
<trans-unit id="7198346314713788799" datatype="html">
|
||||||
<source>Assign storage path</source>
|
<source>Assign storage path</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">198</context>
|
<context context-type="linenumber">199</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="475685412372379925" datatype="html">
|
<trans-unit id="475685412372379925" datatype="html">
|
||||||
<source>Assign custom fields</source>
|
<source>Assign custom fields</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">199</context>
|
<context context-type="linenumber">200</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5057200219587080996" datatype="html">
|
<trans-unit id="5057200219587080996" datatype="html">
|
||||||
<source>Assign owner</source>
|
<source>Assign owner</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">203</context>
|
<context context-type="linenumber">204</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1749184201773078639" datatype="html">
|
<trans-unit id="1749184201773078639" datatype="html">
|
||||||
<source>Assign view permissions</source>
|
<source>Assign view permissions</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">205</context>
|
<context context-type="linenumber">206</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1744964187586405039" datatype="html">
|
<trans-unit id="1744964187586405039" datatype="html">
|
||||||
<source>Assign edit permissions</source>
|
<source>Assign edit permissions</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">224</context>
|
<context context-type="linenumber">225</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6236311670364192011" datatype="html">
|
<trans-unit id="6236311670364192011" datatype="html">
|
||||||
<source>Remove tags</source>
|
<source>Remove tags</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">251</context>
|
<context context-type="linenumber">252</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7890599006071681081" datatype="html">
|
<trans-unit id="7890599006071681081" datatype="html">
|
||||||
<source>Remove all</source>
|
<source>Remove all</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">252</context>
|
<context context-type="linenumber">253</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">258</context>
|
<context context-type="linenumber">259</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">264</context>
|
<context context-type="linenumber">265</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">270</context>
|
<context context-type="linenumber">271</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">276</context>
|
<context context-type="linenumber">277</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">283</context>
|
<context context-type="linenumber">284</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">289</context>
|
<context context-type="linenumber">290</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8636414563726517994" datatype="html">
|
<trans-unit id="8636414563726517994" datatype="html">
|
||||||
<source>Remove correspondents</source>
|
<source>Remove correspondents</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">257</context>
|
<context context-type="linenumber">258</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5305293055593064952" datatype="html">
|
<trans-unit id="5305293055593064952" datatype="html">
|
||||||
<source>Remove document types</source>
|
<source>Remove document types</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">263</context>
|
<context context-type="linenumber">264</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2400388879708187" datatype="html">
|
<trans-unit id="2400388879708187" datatype="html">
|
||||||
<source>Remove storage paths</source>
|
<source>Remove storage paths</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">269</context>
|
<context context-type="linenumber">270</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4324304327041955720" datatype="html">
|
<trans-unit id="4324304327041955720" datatype="html">
|
||||||
<source>Remove custom fields</source>
|
<source>Remove custom fields</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">275</context>
|
<context context-type="linenumber">276</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8367536502602515064" datatype="html">
|
<trans-unit id="8367536502602515064" datatype="html">
|
||||||
<source>Remove owners</source>
|
<source>Remove owners</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">282</context>
|
<context context-type="linenumber">283</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3393772184866313281" datatype="html">
|
<trans-unit id="3393772184866313281" datatype="html">
|
||||||
<source>Remove permissions</source>
|
<source>Remove permissions</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">288</context>
|
<context context-type="linenumber">289</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3145629643370481114" datatype="html">
|
<trans-unit id="3145629643370481114" datatype="html">
|
||||||
<source>View permissions</source>
|
<source>View permissions</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">291</context>
|
<context context-type="linenumber">292</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1946660694635960249" datatype="html">
|
<trans-unit id="1946660694635960249" datatype="html">
|
||||||
<source>Edit permissions</source>
|
<source>Edit permissions</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">310</context>
|
<context context-type="linenumber">311</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8987736563240025468" datatype="html">
|
<trans-unit id="8987736563240025468" datatype="html">
|
||||||
<source>Email subject</source>
|
<source>Email subject</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">338</context>
|
<context context-type="linenumber">339</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8239445959209739142" datatype="html">
|
<trans-unit id="8239445959209739142" datatype="html">
|
||||||
<source>Email body</source>
|
<source>Email body</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">339</context>
|
<context context-type="linenumber">340</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1222152280703048012" datatype="html">
|
<trans-unit id="1222152280703048012" datatype="html">
|
||||||
<source>Email recipients</source>
|
<source>Email recipients</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">340</context>
|
<context context-type="linenumber">341</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7916910101279824329" datatype="html">
|
<trans-unit id="7916910101279824329" datatype="html">
|
||||||
<source>Attach document</source>
|
<source>Attach document</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">341</context>
|
<context context-type="linenumber">342</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5028001922785731600" datatype="html">
|
<trans-unit id="5028001922785731600" datatype="html">
|
||||||
<source>Webhook url</source>
|
<source>Webhook url</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">349</context>
|
<context context-type="linenumber">350</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7491983459027245019" datatype="html">
|
<trans-unit id="7491983459027245019" datatype="html">
|
||||||
<source>Use parameters for webhook body</source>
|
<source>Use parameters for webhook body</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">351</context>
|
<context context-type="linenumber">352</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4078214298308732810" datatype="html">
|
<trans-unit id="4078214298308732810" datatype="html">
|
||||||
<source>Send webhook payload as JSON</source>
|
<source>Send webhook payload as JSON</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">352</context>
|
<context context-type="linenumber">353</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6806149889743731985" datatype="html">
|
<trans-unit id="6806149889743731985" datatype="html">
|
||||||
<source>Webhook params</source>
|
<source>Webhook params</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">355</context>
|
<context context-type="linenumber">356</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7089924379374330" datatype="html">
|
<trans-unit id="7089924379374330" datatype="html">
|
||||||
<source>Webhook body</source>
|
<source>Webhook body</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">357</context>
|
<context context-type="linenumber">358</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3829826512656746316" datatype="html">
|
<trans-unit id="3829826512656746316" datatype="html">
|
||||||
<source>Webhook headers</source>
|
<source>Webhook headers</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">359</context>
|
<context context-type="linenumber">360</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2114525789021600887" datatype="html">
|
<trans-unit id="2114525789021600887" datatype="html">
|
||||||
<source>Include document</source>
|
<source>Include document</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||||
<context context-type="linenumber">360</context>
|
<context context-type="linenumber">361</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4626030417479279989" datatype="html">
|
<trans-unit id="4626030417479279989" datatype="html">
|
||||||
@@ -6012,7 +6019,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">84</context>
|
<context context-type="linenumber">88</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3429210839568770054" datatype="html">
|
<trans-unit id="3429210839568770054" datatype="html">
|
||||||
@@ -6578,11 +6585,18 @@
|
|||||||
<context context-type="linenumber">107</context>
|
<context context-type="linenumber">107</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="7049887240439736400" datatype="html">
|
||||||
|
<source>Print</source>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
|
<context context-type="linenumber">58</context>
|
||||||
|
</context-group>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="1418444397960583910" datatype="html">
|
<trans-unit id="1418444397960583910" datatype="html">
|
||||||
<source>More like this</source>
|
<source>More like this</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">58</context>
|
<context context-type="linenumber">62</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context>
|
||||||
@@ -6593,39 +6607,39 @@
|
|||||||
<source>PDF Editor</source>
|
<source>PDF Editor</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">62</context>
|
<context context-type="linenumber">66</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1383</context>
|
<context context-type="linenumber">1387</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6490688569532630280" datatype="html">
|
<trans-unit id="6490688569532630280" datatype="html">
|
||||||
<source>Send</source>
|
<source>Send</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">80</context>
|
<context context-type="linenumber">84</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4452427314943113135" datatype="html">
|
<trans-unit id="4452427314943113135" datatype="html">
|
||||||
<source>Previous</source>
|
<source>Previous</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">106</context>
|
<context context-type="linenumber">110</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5028777105388019087" datatype="html">
|
<trans-unit id="5028777105388019087" datatype="html">
|
||||||
<source>Details</source>
|
<source>Details</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">119</context>
|
<context context-type="linenumber">123</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5701618810648052610" datatype="html">
|
<trans-unit id="5701618810648052610" datatype="html">
|
||||||
<source>Title</source>
|
<source>Title</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">122</context>
|
<context context-type="linenumber">126</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
|
||||||
@@ -6648,21 +6662,21 @@
|
|||||||
<source>Archive serial number</source>
|
<source>Archive serial number</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">123</context>
|
<context context-type="linenumber">127</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5114742157723900905" datatype="html">
|
<trans-unit id="5114742157723900905" datatype="html">
|
||||||
<source>Date created</source>
|
<source>Date created</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">124</context>
|
<context context-type="linenumber">128</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2691296884221415710" datatype="html">
|
<trans-unit id="2691296884221415710" datatype="html">
|
||||||
<source>Correspondent</source>
|
<source>Correspondent</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">126</context>
|
<context context-type="linenumber">130</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
||||||
@@ -6689,7 +6703,7 @@
|
|||||||
<source>Document type</source>
|
<source>Document type</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">128</context>
|
<context context-type="linenumber">132</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
||||||
@@ -6716,7 +6730,7 @@
|
|||||||
<source>Storage path</source>
|
<source>Storage path</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">130</context>
|
<context context-type="linenumber">134</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
||||||
@@ -6739,7 +6753,7 @@
|
|||||||
<source>Default</source>
|
<source>Default</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">131</context>
|
<context context-type="linenumber">135</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/saved-views/saved-views.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/saved-views/saved-views.component.html</context>
|
||||||
@@ -6750,14 +6764,14 @@
|
|||||||
<source>Content</source>
|
<source>Content</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">227</context>
|
<context context-type="linenumber">231</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="218403386307979629" datatype="html">
|
<trans-unit id="218403386307979629" datatype="html">
|
||||||
<source>Metadata</source>
|
<source>Metadata</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">236</context>
|
<context context-type="linenumber">240</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/metadata-collapse/metadata-collapse.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/metadata-collapse/metadata-collapse.component.ts</context>
|
||||||
@@ -6768,175 +6782,175 @@
|
|||||||
<source>Date modified</source>
|
<source>Date modified</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">243</context>
|
<context context-type="linenumber">247</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6392918669949841614" datatype="html">
|
<trans-unit id="6392918669949841614" datatype="html">
|
||||||
<source>Date added</source>
|
<source>Date added</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">247</context>
|
<context context-type="linenumber">251</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="146828917013192897" datatype="html">
|
<trans-unit id="146828917013192897" datatype="html">
|
||||||
<source>Media filename</source>
|
<source>Media filename</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">251</context>
|
<context context-type="linenumber">255</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4500855521601039868" datatype="html">
|
<trans-unit id="4500855521601039868" datatype="html">
|
||||||
<source>Original filename</source>
|
<source>Original filename</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">255</context>
|
<context context-type="linenumber">259</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7985558498848210210" datatype="html">
|
<trans-unit id="7985558498848210210" datatype="html">
|
||||||
<source>Original MD5 checksum</source>
|
<source>Original MD5 checksum</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">259</context>
|
<context context-type="linenumber">263</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5888243105821763422" datatype="html">
|
<trans-unit id="5888243105821763422" datatype="html">
|
||||||
<source>Original file size</source>
|
<source>Original file size</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">263</context>
|
<context context-type="linenumber">267</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2696647325713149563" datatype="html">
|
<trans-unit id="2696647325713149563" datatype="html">
|
||||||
<source>Original mime type</source>
|
<source>Original mime type</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">267</context>
|
<context context-type="linenumber">271</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="342875990758166588" datatype="html">
|
<trans-unit id="342875990758166588" datatype="html">
|
||||||
<source>Archive MD5 checksum</source>
|
<source>Archive MD5 checksum</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">272</context>
|
<context context-type="linenumber">276</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6033581412811562084" datatype="html">
|
<trans-unit id="6033581412811562084" datatype="html">
|
||||||
<source>Archive file size</source>
|
<source>Archive file size</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">278</context>
|
<context context-type="linenumber">282</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6992781481378431874" datatype="html">
|
<trans-unit id="6992781481378431874" datatype="html">
|
||||||
<source>Original document metadata</source>
|
<source>Original document metadata</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">287</context>
|
<context context-type="linenumber">291</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2846565152091361585" datatype="html">
|
<trans-unit id="2846565152091361585" datatype="html">
|
||||||
<source>Archived document metadata</source>
|
<source>Archived document metadata</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">290</context>
|
<context context-type="linenumber">294</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7206723502037428235" datatype="html">
|
<trans-unit id="7206723502037428235" datatype="html">
|
||||||
<source>Notes <x id="START_BLOCK_IF" equiv-text="@if (document?.notes.length) {"/><x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="badge text-bg-secondary ms-1">"/><x id="INTERPOLATION" equiv-text="ngth}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span"/><x id="CLOSE_BLOCK_IF" equiv-text="}"/></source>
|
<source>Notes <x id="START_BLOCK_IF" equiv-text="@if (document?.notes.length) {"/><x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="badge text-bg-secondary ms-1">"/><x id="INTERPOLATION" equiv-text="ngth}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span"/><x id="CLOSE_BLOCK_IF" equiv-text="}"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">309,312</context>
|
<context context-type="linenumber">313,316</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="186236568870281953" datatype="html">
|
<trans-unit id="186236568870281953" datatype="html">
|
||||||
<source>History</source>
|
<source>History</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">320</context>
|
<context context-type="linenumber">324</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5129524307369213584" datatype="html">
|
<trans-unit id="5129524307369213584" datatype="html">
|
||||||
<source>Save & next</source>
|
<source>Save & next</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">357</context>
|
<context context-type="linenumber">361</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4910102545766233758" datatype="html">
|
<trans-unit id="4910102545766233758" datatype="html">
|
||||||
<source>Save & close</source>
|
<source>Save & close</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">360</context>
|
<context context-type="linenumber">364</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1309556917227148591" datatype="html">
|
<trans-unit id="1309556917227148591" datatype="html">
|
||||||
<source>Document loading...</source>
|
<source>Document loading...</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">370</context>
|
<context context-type="linenumber">374</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8191371354890763172" datatype="html">
|
<trans-unit id="8191371354890763172" datatype="html">
|
||||||
<source>Enter Password</source>
|
<source>Enter Password</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||||
<context context-type="linenumber">424</context>
|
<context context-type="linenumber">428</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2218903673684131427" datatype="html">
|
<trans-unit id="2218903673684131427" datatype="html">
|
||||||
<source>An error occurred loading content: <x id="PH" equiv-text="err.message ?? err.toString()"/></source>
|
<source>An error occurred loading content: <x id="PH" equiv-text="err.message ?? err.toString()"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">410,412</context>
|
<context context-type="linenumber">414,416</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3200733026060976258" datatype="html">
|
<trans-unit id="3200733026060976258" datatype="html">
|
||||||
<source>Document changes detected</source>
|
<source>Document changes detected</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">444</context>
|
<context context-type="linenumber">448</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2887155916749964" datatype="html">
|
<trans-unit id="2887155916749964" datatype="html">
|
||||||
<source>The version of this document in your browser session appears older than the existing version.</source>
|
<source>The version of this document in your browser session appears older than the existing version.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">445</context>
|
<context context-type="linenumber">449</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="237142428785956348" datatype="html">
|
<trans-unit id="237142428785956348" datatype="html">
|
||||||
<source>Saving the document here may overwrite other changes that were made. To restore the existing version, discard your changes or close the document.</source>
|
<source>Saving the document here may overwrite other changes that were made. To restore the existing version, discard your changes or close the document.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">446</context>
|
<context context-type="linenumber">450</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8720977247725652816" datatype="html">
|
<trans-unit id="8720977247725652816" datatype="html">
|
||||||
<source>Ok</source>
|
<source>Ok</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">448</context>
|
<context context-type="linenumber">452</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6142395741265832184" datatype="html">
|
<trans-unit id="6142395741265832184" datatype="html">
|
||||||
<source>Next document</source>
|
<source>Next document</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">574</context>
|
<context context-type="linenumber">578</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="651985345816518480" datatype="html">
|
<trans-unit id="651985345816518480" datatype="html">
|
||||||
<source>Previous document</source>
|
<source>Previous document</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">584</context>
|
<context context-type="linenumber">588</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2885986061416655600" datatype="html">
|
<trans-unit id="2885986061416655600" datatype="html">
|
||||||
<source>Close document</source>
|
<source>Close document</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">592</context>
|
<context context-type="linenumber">596</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/services/open-documents.service.ts</context>
|
<context context-type="sourcefile">src/app/services/open-documents.service.ts</context>
|
||||||
@@ -6947,67 +6961,67 @@
|
|||||||
<source>Save document</source>
|
<source>Save document</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">599</context>
|
<context context-type="linenumber">603</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1784543155727940353" datatype="html">
|
<trans-unit id="1784543155727940353" datatype="html">
|
||||||
<source>Save and close / next</source>
|
<source>Save and close / next</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">608</context>
|
<context context-type="linenumber">612</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5758784066858623886" datatype="html">
|
<trans-unit id="5758784066858623886" datatype="html">
|
||||||
<source>Error retrieving metadata</source>
|
<source>Error retrieving metadata</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">660</context>
|
<context context-type="linenumber">664</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3456881259945295697" datatype="html">
|
<trans-unit id="3456881259945295697" datatype="html">
|
||||||
<source>Error retrieving suggestions.</source>
|
<source>Error retrieving suggestions.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">689</context>
|
<context context-type="linenumber">693</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2194092841814123758" datatype="html">
|
<trans-unit id="2194092841814123758" datatype="html">
|
||||||
<source>Document "<x id="PH" equiv-text="newValues.title"/>" saved successfully.</source>
|
<source>Document "<x id="PH" equiv-text="newValues.title"/>" saved successfully.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">861</context>
|
<context context-type="linenumber">865</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">885</context>
|
<context context-type="linenumber">889</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6626387786259219838" datatype="html">
|
<trans-unit id="6626387786259219838" datatype="html">
|
||||||
<source>Error saving document "<x id="PH" equiv-text="this.document.title"/>"</source>
|
<source>Error saving document "<x id="PH" equiv-text="this.document.title"/>"</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">891</context>
|
<context context-type="linenumber">895</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="448882439049417053" datatype="html">
|
<trans-unit id="448882439049417053" datatype="html">
|
||||||
<source>Error saving document</source>
|
<source>Error saving document</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">941</context>
|
<context context-type="linenumber">945</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8410796510716511826" datatype="html">
|
<trans-unit id="8410796510716511826" datatype="html">
|
||||||
<source>Do you really want to move the document "<x id="PH" equiv-text="this.document.title"/>" to the trash?</source>
|
<source>Do you really want to move the document "<x id="PH" equiv-text="this.document.title"/>" to the trash?</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">973</context>
|
<context context-type="linenumber">977</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="282586936710748252" datatype="html">
|
<trans-unit id="282586936710748252" datatype="html">
|
||||||
<source>Documents can be restored prior to permanent deletion.</source>
|
<source>Documents can be restored prior to permanent deletion.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">974</context>
|
<context context-type="linenumber">978</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||||
@@ -7018,7 +7032,7 @@
|
|||||||
<source>Move to trash</source>
|
<source>Move to trash</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">976</context>
|
<context context-type="linenumber">980</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||||
@@ -7029,14 +7043,14 @@
|
|||||||
<source>Error deleting document</source>
|
<source>Error deleting document</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">995</context>
|
<context context-type="linenumber">999</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="619486176823357521" datatype="html">
|
<trans-unit id="619486176823357521" datatype="html">
|
||||||
<source>Reprocess confirm</source>
|
<source>Reprocess confirm</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1015</context>
|
<context context-type="linenumber">1019</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||||
@@ -7047,67 +7061,81 @@
|
|||||||
<source>This operation will permanently recreate the archive file for this document.</source>
|
<source>This operation will permanently recreate the archive file for this document.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1016</context>
|
<context context-type="linenumber">1020</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="302054111564709516" datatype="html">
|
<trans-unit id="302054111564709516" datatype="html">
|
||||||
<source>The archive file will be re-generated with the current settings.</source>
|
<source>The archive file will be re-generated with the current settings.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1017</context>
|
<context context-type="linenumber">1021</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8251197608401006898" datatype="html">
|
<trans-unit id="8251197608401006898" datatype="html">
|
||||||
<source>Reprocess operation for "<x id="PH" equiv-text="this.document.title"/>" will begin in the background. Close and re-open or reload this document after the operation has completed to see new content.</source>
|
<source>Reprocess operation for "<x id="PH" equiv-text="this.document.title"/>" will begin in the background. Close and re-open or reload this document after the operation has completed to see new content.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1027</context>
|
<context context-type="linenumber">1031</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4409560272830824468" datatype="html">
|
<trans-unit id="4409560272830824468" datatype="html">
|
||||||
<source>Error executing operation</source>
|
<source>Error executing operation</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1038</context>
|
<context context-type="linenumber">1042</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6030453331794586802" datatype="html">
|
<trans-unit id="6030453331794586802" datatype="html">
|
||||||
<source>Error downloading document</source>
|
<source>Error downloading document</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1087</context>
|
<context context-type="linenumber">1091</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4458954481601077369" datatype="html">
|
<trans-unit id="4458954481601077369" datatype="html">
|
||||||
<source>Page Fit</source>
|
<source>Page Fit</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1164</context>
|
<context context-type="linenumber">1168</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4663705961777238777" datatype="html">
|
<trans-unit id="4663705961777238777" datatype="html">
|
||||||
<source>PDF edit operation for "<x id="PH" equiv-text="this.document.title"/>" will begin in the background.</source>
|
<source>PDF edit operation for "<x id="PH" equiv-text="this.document.title"/>" will begin in the background.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1402</context>
|
<context context-type="linenumber">1406</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="9043972994040261999" datatype="html">
|
<trans-unit id="9043972994040261999" datatype="html">
|
||||||
<source>Error executing PDF edit operation</source>
|
<source>Error executing PDF edit operation</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1414</context>
|
<context context-type="linenumber">1418</context>
|
||||||
|
</context-group>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="3740891324955700797" datatype="html">
|
||||||
|
<source>Print failed.</source>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
|
<context context-type="linenumber">1450</context>
|
||||||
|
</context-group>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="6457245677384603573" datatype="html">
|
||||||
|
<source>Error loading document for printing.</source>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
|
<context context-type="linenumber">1458</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6085793215710522488" datatype="html">
|
<trans-unit id="6085793215710522488" datatype="html">
|
||||||
<source>An error occurred loading tiff: <x id="PH" equiv-text="err.toString()"/></source>
|
<source>An error occurred loading tiff: <x id="PH" equiv-text="err.toString()"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1481</context>
|
<context context-type="linenumber">1523</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||||
<context context-type="linenumber">1485</context>
|
<context context-type="linenumber">1527</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4958946940233632319" datatype="html">
|
<trans-unit id="4958946940233632319" datatype="html">
|
||||||
|
|||||||
@@ -177,6 +177,7 @@
|
|||||||
<pngx-input-tags [allowCreate]="false" i18n-title title="Has any of tags" formControlName="filter_has_tags"></pngx-input-tags>
|
<pngx-input-tags [allowCreate]="false" i18n-title title="Has any of tags" formControlName="filter_has_tags"></pngx-input-tags>
|
||||||
<pngx-input-select i18n-title title="Has correspondent" [items]="correspondents" [allowNull]="true" formControlName="filter_has_correspondent"></pngx-input-select>
|
<pngx-input-select i18n-title title="Has correspondent" [items]="correspondents" [allowNull]="true" formControlName="filter_has_correspondent"></pngx-input-select>
|
||||||
<pngx-input-select i18n-title title="Has document type" [items]="documentTypes" [allowNull]="true" formControlName="filter_has_document_type"></pngx-input-select>
|
<pngx-input-select i18n-title title="Has document type" [items]="documentTypes" [allowNull]="true" formControlName="filter_has_document_type"></pngx-input-select>
|
||||||
|
<pngx-input-select i18n-title title="Has storage path" [items]="storagePaths" [allowNull]="true" formControlName="filter_has_storage_path"></pngx-input-select>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -412,6 +412,9 @@ export class WorkflowEditDialogComponent
|
|||||||
filter_has_document_type: new FormControl(
|
filter_has_document_type: new FormControl(
|
||||||
trigger.filter_has_document_type
|
trigger.filter_has_document_type
|
||||||
),
|
),
|
||||||
|
filter_has_storage_path: new FormControl(
|
||||||
|
trigger.filter_has_storage_path
|
||||||
|
),
|
||||||
schedule_offset_days: new FormControl(trigger.schedule_offset_days),
|
schedule_offset_days: new FormControl(trigger.schedule_offset_days),
|
||||||
schedule_is_recurring: new FormControl(trigger.schedule_is_recurring),
|
schedule_is_recurring: new FormControl(trigger.schedule_is_recurring),
|
||||||
schedule_recurring_interval_days: new FormControl(
|
schedule_recurring_interval_days: new FormControl(
|
||||||
@@ -536,6 +539,7 @@ export class WorkflowEditDialogComponent
|
|||||||
filter_has_tags: [],
|
filter_has_tags: [],
|
||||||
filter_has_correspondent: null,
|
filter_has_correspondent: null,
|
||||||
filter_has_document_type: null,
|
filter_has_document_type: null,
|
||||||
|
filter_has_storage_path: null,
|
||||||
matching_algorithm: MATCH_NONE,
|
matching_algorithm: MATCH_NONE,
|
||||||
match: '',
|
match: '',
|
||||||
is_insensitive: true,
|
is_insensitive: true,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<i-bs width="0.9em" height="0.9em" name="exclamation-triangle"></i-bs>
|
<i-bs width="0.9em" height="0.9em" name="exclamation-triangle"></i-bs>
|
||||||
}
|
}
|
||||||
<div>
|
<div>
|
||||||
<p class="ms-2 mb-0">{{toast.content}}</p>
|
<p class="ms-2 mb-0 text-break">{{toast.content}}</p>
|
||||||
@if (toast.error) {
|
@if (toast.error) {
|
||||||
<details class="ms-2">
|
<details class="ms-2">
|
||||||
<div class="mt-2 ms-n4 me-n2 small">
|
<div class="mt-2 ms-n4 me-n2 small">
|
||||||
|
|||||||
@@ -54,6 +54,10 @@
|
|||||||
<i-bs width="1em" height="1em" name="arrow-counterclockwise"></i-bs> <span i18n>Reprocess</span>
|
<i-bs width="1em" height="1em" name="arrow-counterclockwise"></i-bs> <span i18n>Reprocess</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button ngbDropdownItem (click)="printDocument()" [hidden]="useNativePdfViewer || isMobile">
|
||||||
|
<i-bs width="1em" height="1em" name="printer"></i-bs> <span i18n>Print</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button ngbDropdownItem (click)="moreLike()">
|
<button ngbDropdownItem (click)="moreLike()">
|
||||||
<i-bs width="1em" height="1em" name="diagram-3"></i-bs> <span i18n>More like this</span>
|
<i-bs width="1em" height="1em" name="diagram-3"></i-bs> <span i18n>More like this</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1415,4 +1415,151 @@ describe('DocumentDetailComponent', () => {
|
|||||||
.flush('fail', { status: 500, statusText: 'Server Error' })
|
.flush('fail', { status: 500, statusText: 'Server Error' })
|
||||||
expect(component.previewText).toContain('An error occurred loading content')
|
expect(component.previewText).toContain('An error occurred loading content')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should print document successfully', fakeAsync(() => {
|
||||||
|
initNormally()
|
||||||
|
|
||||||
|
const appendChildSpy = jest
|
||||||
|
.spyOn(document.body, 'appendChild')
|
||||||
|
.mockImplementation((node: Node) => node)
|
||||||
|
const removeChildSpy = jest
|
||||||
|
.spyOn(document.body, 'removeChild')
|
||||||
|
.mockImplementation((node: Node) => node)
|
||||||
|
const createObjectURLSpy = jest
|
||||||
|
.spyOn(URL, 'createObjectURL')
|
||||||
|
.mockReturnValue('blob:mock-url')
|
||||||
|
const revokeObjectURLSpy = jest
|
||||||
|
.spyOn(URL, 'revokeObjectURL')
|
||||||
|
.mockImplementation(() => {})
|
||||||
|
|
||||||
|
const mockContentWindow = {
|
||||||
|
focus: jest.fn(),
|
||||||
|
print: jest.fn(),
|
||||||
|
onafterprint: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockIframe = {
|
||||||
|
style: {},
|
||||||
|
src: '',
|
||||||
|
onload: null,
|
||||||
|
contentWindow: mockContentWindow,
|
||||||
|
}
|
||||||
|
|
||||||
|
const createElementSpy = jest
|
||||||
|
.spyOn(document, 'createElement')
|
||||||
|
.mockReturnValue(mockIframe as any)
|
||||||
|
|
||||||
|
const blob = new Blob(['test'], { type: 'application/pdf' })
|
||||||
|
component.printDocument()
|
||||||
|
|
||||||
|
const req = httpTestingController.expectOne(
|
||||||
|
`${environment.apiBaseUrl}documents/${doc.id}/download/`
|
||||||
|
)
|
||||||
|
req.flush(blob)
|
||||||
|
|
||||||
|
tick()
|
||||||
|
|
||||||
|
expect(createElementSpy).toHaveBeenCalledWith('iframe')
|
||||||
|
expect(appendChildSpy).toHaveBeenCalledWith(mockIframe)
|
||||||
|
expect(createObjectURLSpy).toHaveBeenCalledWith(blob)
|
||||||
|
|
||||||
|
if (mockIframe.onload) {
|
||||||
|
mockIframe.onload({} as any)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(mockContentWindow.focus).toHaveBeenCalled()
|
||||||
|
expect(mockContentWindow.print).toHaveBeenCalled()
|
||||||
|
|
||||||
|
if (mockIframe.onload) {
|
||||||
|
mockIframe.onload(new Event('load'))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mockContentWindow.onafterprint) {
|
||||||
|
mockContentWindow.onafterprint(new Event('afterprint'))
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(removeChildSpy).toHaveBeenCalledWith(mockIframe)
|
||||||
|
expect(revokeObjectURLSpy).toHaveBeenCalledWith('blob:mock-url')
|
||||||
|
|
||||||
|
createElementSpy.mockRestore()
|
||||||
|
appendChildSpy.mockRestore()
|
||||||
|
removeChildSpy.mockRestore()
|
||||||
|
createObjectURLSpy.mockRestore()
|
||||||
|
revokeObjectURLSpy.mockRestore()
|
||||||
|
}))
|
||||||
|
|
||||||
|
it('should show error toast if print document fails', () => {
|
||||||
|
initNormally()
|
||||||
|
const toastSpy = jest.spyOn(toastService, 'showError')
|
||||||
|
component.printDocument()
|
||||||
|
const req = httpTestingController.expectOne(
|
||||||
|
`${environment.apiBaseUrl}documents/${doc.id}/download/`
|
||||||
|
)
|
||||||
|
req.error(new ErrorEvent('failed'))
|
||||||
|
expect(toastSpy).toHaveBeenCalledWith(
|
||||||
|
'Error loading document for printing.'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should show error toast if printing throws inside iframe', fakeAsync(() => {
|
||||||
|
initNormally()
|
||||||
|
|
||||||
|
const appendChildSpy = jest
|
||||||
|
.spyOn(document.body, 'appendChild')
|
||||||
|
.mockImplementation((node: Node) => node)
|
||||||
|
const removeChildSpy = jest
|
||||||
|
.spyOn(document.body, 'removeChild')
|
||||||
|
.mockImplementation((node: Node) => node)
|
||||||
|
const createObjectURLSpy = jest
|
||||||
|
.spyOn(URL, 'createObjectURL')
|
||||||
|
.mockReturnValue('blob:mock-url')
|
||||||
|
const revokeObjectURLSpy = jest
|
||||||
|
.spyOn(URL, 'revokeObjectURL')
|
||||||
|
.mockImplementation(() => {})
|
||||||
|
|
||||||
|
const toastSpy = jest.spyOn(toastService, 'showError')
|
||||||
|
|
||||||
|
const mockContentWindow = {
|
||||||
|
focus: jest.fn().mockImplementation(() => {
|
||||||
|
throw new Error('focus failed')
|
||||||
|
}),
|
||||||
|
print: jest.fn(),
|
||||||
|
onafterprint: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockIframe: any = {
|
||||||
|
style: {},
|
||||||
|
src: '',
|
||||||
|
onload: null,
|
||||||
|
contentWindow: mockContentWindow,
|
||||||
|
}
|
||||||
|
|
||||||
|
const createElementSpy = jest
|
||||||
|
.spyOn(document, 'createElement')
|
||||||
|
.mockReturnValue(mockIframe as any)
|
||||||
|
|
||||||
|
const blob = new Blob(['test'], { type: 'application/pdf' })
|
||||||
|
component.printDocument()
|
||||||
|
|
||||||
|
const req = httpTestingController.expectOne(
|
||||||
|
`${environment.apiBaseUrl}documents/${doc.id}/download/`
|
||||||
|
)
|
||||||
|
req.flush(blob)
|
||||||
|
|
||||||
|
tick()
|
||||||
|
|
||||||
|
if (mockIframe.onload) {
|
||||||
|
mockIframe.onload(new Event('load'))
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(toastSpy).toHaveBeenCalled()
|
||||||
|
expect(removeChildSpy).toHaveBeenCalledWith(mockIframe)
|
||||||
|
expect(revokeObjectURLSpy).toHaveBeenCalledWith('blob:mock-url')
|
||||||
|
|
||||||
|
createElementSpy.mockRestore()
|
||||||
|
appendChildSpy.mockRestore()
|
||||||
|
removeChildSpy.mockRestore()
|
||||||
|
createObjectURLSpy.mockRestore()
|
||||||
|
revokeObjectURLSpy.mockRestore()
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -291,6 +291,10 @@ export class DocumentDetailComponent
|
|||||||
return this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)
|
return this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isMobile(): boolean {
|
||||||
|
return this.deviceDetectorService.isMobile()
|
||||||
|
}
|
||||||
|
|
||||||
get archiveContentRenderType(): ContentRenderType {
|
get archiveContentRenderType(): ContentRenderType {
|
||||||
return this.document?.archived_file_name
|
return this.document?.archived_file_name
|
||||||
? this.getRenderType('application/pdf')
|
? this.getRenderType('application/pdf')
|
||||||
@@ -1419,6 +1423,44 @@ export class DocumentDetailComponent
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printDocument() {
|
||||||
|
const printUrl = this.documentsService.getDownloadUrl(
|
||||||
|
this.document.id,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
this.http
|
||||||
|
.get(printUrl, { responseType: 'blob' })
|
||||||
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
|
.subscribe({
|
||||||
|
next: (blob) => {
|
||||||
|
const blobUrl = URL.createObjectURL(blob)
|
||||||
|
const iframe = document.createElement('iframe')
|
||||||
|
iframe.style.display = 'none'
|
||||||
|
iframe.src = blobUrl
|
||||||
|
document.body.appendChild(iframe)
|
||||||
|
iframe.onload = () => {
|
||||||
|
try {
|
||||||
|
iframe.contentWindow.focus()
|
||||||
|
iframe.contentWindow.print()
|
||||||
|
iframe.contentWindow.onafterprint = () => {
|
||||||
|
document.body.removeChild(iframe)
|
||||||
|
URL.revokeObjectURL(blobUrl)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.toastService.showError($localize`Print failed.`, err)
|
||||||
|
document.body.removeChild(iframe)
|
||||||
|
URL.revokeObjectURL(blobUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.toastService.showError(
|
||||||
|
$localize`Error loading document for printing.`
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
public openShareLinks() {
|
public openShareLinks() {
|
||||||
const modal = this.modalService.open(ShareLinksDialogComponent)
|
const modal = this.modalService.open(ShareLinksDialogComponent)
|
||||||
modal.componentInstance.documentId = this.document.id
|
modal.componentInstance.documentId = this.document.id
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ export interface WorkflowTrigger extends ObjectWithId {
|
|||||||
|
|
||||||
filter_has_document_type?: number // DocumentType.id
|
filter_has_document_type?: number // DocumentType.id
|
||||||
|
|
||||||
|
filter_has_storage_path?: number // StoragePath.id
|
||||||
|
|
||||||
schedule_offset_days?: number
|
schedule_offset_days?: number
|
||||||
|
|
||||||
schedule_is_recurring?: boolean
|
schedule_is_recurring?: boolean
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ import {
|
|||||||
playFill,
|
playFill,
|
||||||
plus,
|
plus,
|
||||||
plusCircle,
|
plusCircle,
|
||||||
|
printer,
|
||||||
questionCircle,
|
questionCircle,
|
||||||
scissors,
|
scissors,
|
||||||
search,
|
search,
|
||||||
@@ -319,6 +320,7 @@ const icons = {
|
|||||||
playFill,
|
playFill,
|
||||||
plus,
|
plus,
|
||||||
plusCircle,
|
plusCircle,
|
||||||
|
printer,
|
||||||
questionCircle,
|
questionCircle,
|
||||||
scissors,
|
scissors,
|
||||||
search,
|
search,
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ def modify_custom_fields(
|
|||||||
defaults[value_field] = value
|
defaults[value_field] = value
|
||||||
if (
|
if (
|
||||||
custom_field.data_type == CustomField.FieldDataType.DOCUMENTLINK
|
custom_field.data_type == CustomField.FieldDataType.DOCUMENTLINK
|
||||||
|
and value
|
||||||
and doc_id in value
|
and doc_id in value
|
||||||
):
|
):
|
||||||
# Prevent self-linking
|
# Prevent self-linking
|
||||||
|
|||||||
@@ -386,6 +386,16 @@ def existing_document_matches_workflow(
|
|||||||
)
|
)
|
||||||
trigger_matched = False
|
trigger_matched = False
|
||||||
|
|
||||||
|
# Document storage_path vs trigger has_storage_path
|
||||||
|
if (
|
||||||
|
trigger.filter_has_storage_path is not None
|
||||||
|
and document.storage_path != trigger.filter_has_storage_path
|
||||||
|
):
|
||||||
|
reason = (
|
||||||
|
f"Document storage path {document.storage_path} does not match {trigger.filter_has_storage_path}",
|
||||||
|
)
|
||||||
|
trigger_matched = False
|
||||||
|
|
||||||
# Document original_filename vs trigger filename
|
# Document original_filename vs trigger filename
|
||||||
if (
|
if (
|
||||||
trigger.filter_filename is not None
|
trigger.filter_filename is not None
|
||||||
@@ -430,6 +440,11 @@ def prefilter_documents_by_workflowtrigger(
|
|||||||
document_type=trigger.filter_has_document_type,
|
document_type=trigger.filter_has_document_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if trigger.filter_has_storage_path is not None:
|
||||||
|
documents = documents.filter(
|
||||||
|
storage_path=trigger.filter_has_storage_path,
|
||||||
|
)
|
||||||
|
|
||||||
if trigger.filter_filename is not None and len(trigger.filter_filename) > 0:
|
if trigger.filter_filename is not None and len(trigger.filter_filename) > 0:
|
||||||
# the true fnmatch will actually run later so we just want a loose filter here
|
# the true fnmatch will actually run later so we just want a loose filter here
|
||||||
regex = fnmatch_translate(trigger.filter_filename).lstrip("^").rstrip("$")
|
regex = fnmatch_translate(trigger.filter_filename).lstrip("^").rstrip("$")
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 5.2.6 on 2025-09-11 17:29
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("documents", "1068_alter_document_created"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="workflowtrigger",
|
||||||
|
name="filter_has_storage_path",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="documents.storagepath",
|
||||||
|
verbose_name="has this storage path",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="workflowaction",
|
||||||
|
name="assign_title",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Assign a document title, must be a Jinja2 template, see documentation.",
|
||||||
|
null=True,
|
||||||
|
verbose_name="assign title",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1044,6 +1044,14 @@ class WorkflowTrigger(models.Model):
|
|||||||
verbose_name=_("has this correspondent"),
|
verbose_name=_("has this correspondent"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
filter_has_storage_path = models.ForeignKey(
|
||||||
|
StoragePath,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
verbose_name=_("has this storage path"),
|
||||||
|
)
|
||||||
|
|
||||||
schedule_offset_days = models.IntegerField(
|
schedule_offset_days = models.IntegerField(
|
||||||
_("schedule offset days"),
|
_("schedule offset days"),
|
||||||
default=0,
|
default=0,
|
||||||
@@ -1207,14 +1215,12 @@ class WorkflowAction(models.Model):
|
|||||||
default=WorkflowActionType.ASSIGNMENT,
|
default=WorkflowActionType.ASSIGNMENT,
|
||||||
)
|
)
|
||||||
|
|
||||||
assign_title = models.CharField(
|
assign_title = models.TextField(
|
||||||
_("assign title"),
|
_("assign title"),
|
||||||
max_length=256,
|
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text=_(
|
help_text=_(
|
||||||
"Assign a document title, can include some placeholders, "
|
"Assign a document title, must be a Jinja2 template, see documentation.",
|
||||||
"see documentation.",
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2054,6 +2054,7 @@ class WorkflowTriggerSerializer(serializers.ModelSerializer):
|
|||||||
"filter_has_tags",
|
"filter_has_tags",
|
||||||
"filter_has_correspondent",
|
"filter_has_correspondent",
|
||||||
"filter_has_document_type",
|
"filter_has_document_type",
|
||||||
|
"filter_has_storage_path",
|
||||||
"schedule_offset_days",
|
"schedule_offset_days",
|
||||||
"schedule_is_recurring",
|
"schedule_is_recurring",
|
||||||
"schedule_recurring_interval_days",
|
"schedule_recurring_interval_days",
|
||||||
|
|||||||
27
src/documents/templating/environment.py
Normal file
27
src/documents/templating/environment.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
from jinja2.sandbox import SandboxedEnvironment
|
||||||
|
|
||||||
|
|
||||||
|
class JinjaEnvironment(SandboxedEnvironment):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.undefined_tracker = None
|
||||||
|
|
||||||
|
def is_safe_callable(self, obj):
|
||||||
|
# Block access to .save() and .delete() methods
|
||||||
|
if callable(obj) and getattr(obj, "__name__", None) in (
|
||||||
|
"save",
|
||||||
|
"delete",
|
||||||
|
"update",
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
# Call the parent method for other cases
|
||||||
|
return super().is_safe_callable(obj)
|
||||||
|
|
||||||
|
|
||||||
|
_template_environment = JinjaEnvironment(
|
||||||
|
trim_blocks=True,
|
||||||
|
lstrip_blocks=True,
|
||||||
|
keep_trailing_newline=False,
|
||||||
|
autoescape=False,
|
||||||
|
extensions=["jinja2.ext.loopcontrols"],
|
||||||
|
)
|
||||||
@@ -2,22 +2,16 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from datetime import date
|
|
||||||
from datetime import datetime
|
|
||||||
from pathlib import PurePath
|
from pathlib import PurePath
|
||||||
|
|
||||||
import pathvalidate
|
import pathvalidate
|
||||||
from babel import Locale
|
|
||||||
from babel import dates
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.dateparse import parse_date
|
|
||||||
from django.utils.text import slugify as django_slugify
|
from django.utils.text import slugify as django_slugify
|
||||||
from jinja2 import StrictUndefined
|
from jinja2 import StrictUndefined
|
||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
from jinja2 import TemplateSyntaxError
|
from jinja2 import TemplateSyntaxError
|
||||||
from jinja2 import UndefinedError
|
from jinja2 import UndefinedError
|
||||||
from jinja2 import make_logging_undefined
|
from jinja2 import make_logging_undefined
|
||||||
from jinja2.sandbox import SandboxedEnvironment
|
|
||||||
from jinja2.sandbox import SecurityError
|
from jinja2.sandbox import SecurityError
|
||||||
|
|
||||||
from documents.models import Correspondent
|
from documents.models import Correspondent
|
||||||
@@ -27,39 +21,16 @@ from documents.models import Document
|
|||||||
from documents.models import DocumentType
|
from documents.models import DocumentType
|
||||||
from documents.models import StoragePath
|
from documents.models import StoragePath
|
||||||
from documents.models import Tag
|
from documents.models import Tag
|
||||||
|
from documents.templating.environment import _template_environment
|
||||||
|
from documents.templating.filters import format_datetime
|
||||||
|
from documents.templating.filters import get_cf_value
|
||||||
|
from documents.templating.filters import localize_date
|
||||||
|
|
||||||
logger = logging.getLogger("paperless.templating")
|
logger = logging.getLogger("paperless.templating")
|
||||||
|
|
||||||
_LogStrictUndefined = make_logging_undefined(logger, StrictUndefined)
|
_LogStrictUndefined = make_logging_undefined(logger, StrictUndefined)
|
||||||
|
|
||||||
|
|
||||||
class FilePathEnvironment(SandboxedEnvironment):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.undefined_tracker = None
|
|
||||||
|
|
||||||
def is_safe_callable(self, obj):
|
|
||||||
# Block access to .save() and .delete() methods
|
|
||||||
if callable(obj) and getattr(obj, "__name__", None) in (
|
|
||||||
"save",
|
|
||||||
"delete",
|
|
||||||
"update",
|
|
||||||
):
|
|
||||||
return False
|
|
||||||
# Call the parent method for other cases
|
|
||||||
return super().is_safe_callable(obj)
|
|
||||||
|
|
||||||
|
|
||||||
_template_environment = FilePathEnvironment(
|
|
||||||
trim_blocks=True,
|
|
||||||
lstrip_blocks=True,
|
|
||||||
keep_trailing_newline=False,
|
|
||||||
autoescape=False,
|
|
||||||
extensions=["jinja2.ext.loopcontrols"],
|
|
||||||
undefined=_LogStrictUndefined,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class FilePathTemplate(Template):
|
class FilePathTemplate(Template):
|
||||||
def render(self, *args, **kwargs) -> str:
|
def render(self, *args, **kwargs) -> str:
|
||||||
def clean_filepath(value: str) -> str:
|
def clean_filepath(value: str) -> str:
|
||||||
@@ -81,54 +52,7 @@ class FilePathTemplate(Template):
|
|||||||
return clean_filepath(original_render)
|
return clean_filepath(original_render)
|
||||||
|
|
||||||
|
|
||||||
def get_cf_value(
|
_template_environment.undefined = _LogStrictUndefined
|
||||||
custom_field_data: dict[str, dict[str, str]],
|
|
||||||
name: str,
|
|
||||||
default: str | None = None,
|
|
||||||
) -> str | None:
|
|
||||||
if name in custom_field_data and custom_field_data[name]["value"] is not None:
|
|
||||||
return custom_field_data[name]["value"]
|
|
||||||
elif default is not None:
|
|
||||||
return default
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def format_datetime(value: str | datetime, format: str) -> str:
|
|
||||||
if isinstance(value, str):
|
|
||||||
value = parse_date(value)
|
|
||||||
return value.strftime(format=format)
|
|
||||||
|
|
||||||
|
|
||||||
def localize_date(value: date | datetime, format: str, locale: str) -> str:
|
|
||||||
"""
|
|
||||||
Format a date or datetime object into a localized string using Babel.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value (date | datetime): The date or datetime to format. If a datetime
|
|
||||||
is provided, it should be timezone-aware (e.g., UTC from a Django DB object).
|
|
||||||
format (str): The format to use. Can be one of Babel's preset formats
|
|
||||||
('short', 'medium', 'long', 'full') or a custom pattern string.
|
|
||||||
locale (str): The locale code (e.g., 'en_US', 'fr_FR') to use for
|
|
||||||
localization.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: The localized, formatted date string.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
TypeError: If `value` is not a date or datetime instance.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
Locale.parse(locale)
|
|
||||||
except Exception as e:
|
|
||||||
raise ValueError(f"Invalid locale identifier: {locale}") from e
|
|
||||||
|
|
||||||
if isinstance(value, datetime):
|
|
||||||
return dates.format_datetime(value, format=format, locale=locale)
|
|
||||||
elif isinstance(value, date):
|
|
||||||
return dates.format_date(value, format=format, locale=locale)
|
|
||||||
else:
|
|
||||||
raise TypeError(f"Unsupported type {type(value)} for localize_date")
|
|
||||||
|
|
||||||
|
|
||||||
_template_environment.filters["get_cf_value"] = get_cf_value
|
_template_environment.filters["get_cf_value"] = get_cf_value
|
||||||
|
|
||||||
|
|||||||
60
src/documents/templating/filters.py
Normal file
60
src/documents/templating/filters.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
from datetime import date
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from babel import Locale
|
||||||
|
from babel import dates
|
||||||
|
from django.utils.dateparse import parse_date
|
||||||
|
from django.utils.dateparse import parse_datetime
|
||||||
|
|
||||||
|
|
||||||
|
def localize_date(value: date | datetime | str, format: str, locale: str) -> str:
|
||||||
|
"""
|
||||||
|
Format a date, datetime or str object into a localized string using Babel.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value (date | datetime | str): The date or datetime to format. If a datetime
|
||||||
|
is provided, it should be timezone-aware (e.g., UTC from a Django DB object).
|
||||||
|
if str is provided is is parsed as date.
|
||||||
|
format (str): The format to use. Can be one of Babel's preset formats
|
||||||
|
('short', 'medium', 'long', 'full') or a custom pattern string.
|
||||||
|
locale (str): The locale code (e.g., 'en_US', 'fr_FR') to use for
|
||||||
|
localization.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The localized, formatted date string.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If `value` is not a date, datetime or str instance.
|
||||||
|
"""
|
||||||
|
if isinstance(value, str):
|
||||||
|
value = parse_datetime(value)
|
||||||
|
|
||||||
|
try:
|
||||||
|
Locale.parse(locale)
|
||||||
|
except Exception as e:
|
||||||
|
raise ValueError(f"Invalid locale identifier: {locale}") from e
|
||||||
|
|
||||||
|
if isinstance(value, datetime):
|
||||||
|
return dates.format_datetime(value, format=format, locale=locale)
|
||||||
|
elif isinstance(value, date):
|
||||||
|
return dates.format_date(value, format=format, locale=locale)
|
||||||
|
else:
|
||||||
|
raise TypeError(f"Unsupported type {type(value)} for localize_date")
|
||||||
|
|
||||||
|
|
||||||
|
def format_datetime(value: str | datetime, format: str) -> str:
|
||||||
|
if isinstance(value, str):
|
||||||
|
value = parse_date(value)
|
||||||
|
return value.strftime(format=format)
|
||||||
|
|
||||||
|
|
||||||
|
def get_cf_value(
|
||||||
|
custom_field_data: dict[str, dict[str, str]],
|
||||||
|
name: str,
|
||||||
|
default: str | None = None,
|
||||||
|
) -> str | None:
|
||||||
|
if name in custom_field_data and custom_field_data[name]["value"] is not None:
|
||||||
|
return custom_field_data[name]["value"]
|
||||||
|
elif default is not None:
|
||||||
|
return default
|
||||||
|
return None
|
||||||
@@ -1,7 +1,33 @@
|
|||||||
|
import logging
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from django.utils.text import slugify as django_slugify
|
||||||
|
from jinja2 import StrictUndefined
|
||||||
|
from jinja2 import Template
|
||||||
|
from jinja2 import TemplateSyntaxError
|
||||||
|
from jinja2 import UndefinedError
|
||||||
|
from jinja2 import make_logging_undefined
|
||||||
|
from jinja2.sandbox import SecurityError
|
||||||
|
|
||||||
|
from documents.templating.environment import _template_environment
|
||||||
|
from documents.templating.filters import format_datetime
|
||||||
|
from documents.templating.filters import localize_date
|
||||||
|
|
||||||
|
logger = logging.getLogger("paperless.templating")
|
||||||
|
|
||||||
|
_LogStrictUndefined = make_logging_undefined(logger, StrictUndefined)
|
||||||
|
|
||||||
|
|
||||||
|
_template_environment.undefined = _LogStrictUndefined
|
||||||
|
|
||||||
|
_template_environment.filters["datetime"] = format_datetime
|
||||||
|
|
||||||
|
_template_environment.filters["slugify"] = django_slugify
|
||||||
|
|
||||||
|
_template_environment.filters["localize_date"] = localize_date
|
||||||
|
|
||||||
|
|
||||||
def parse_w_workflow_placeholders(
|
def parse_w_workflow_placeholders(
|
||||||
text: str,
|
text: str,
|
||||||
@@ -20,6 +46,7 @@ def parse_w_workflow_placeholders(
|
|||||||
e.g. for pre-consumption triggers created will not have been parsed yet, but it will
|
e.g. for pre-consumption triggers created will not have been parsed yet, but it will
|
||||||
for added / updated triggers
|
for added / updated triggers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
formatting = {
|
formatting = {
|
||||||
"correspondent": correspondent_name,
|
"correspondent": correspondent_name,
|
||||||
"document_type": doc_type_name,
|
"document_type": doc_type_name,
|
||||||
@@ -52,4 +79,28 @@ def parse_w_workflow_placeholders(
|
|||||||
formatting.update({"doc_title": doc_title})
|
formatting.update({"doc_title": doc_title})
|
||||||
if doc_url is not None:
|
if doc_url is not None:
|
||||||
formatting.update({"doc_url": doc_url})
|
formatting.update({"doc_url": doc_url})
|
||||||
return text.format(**formatting).strip()
|
|
||||||
|
logger.debug(f"Jinja Template is : {text}")
|
||||||
|
try:
|
||||||
|
template = _template_environment.from_string(
|
||||||
|
text,
|
||||||
|
template_class=Template,
|
||||||
|
)
|
||||||
|
rendered_template = template.render(formatting)
|
||||||
|
|
||||||
|
# We're good!
|
||||||
|
return rendered_template
|
||||||
|
except UndefinedError as e:
|
||||||
|
# The undefined class logs this already for us
|
||||||
|
raise e
|
||||||
|
except TemplateSyntaxError as e:
|
||||||
|
logger.warning(f"Template syntax error in title generation: {e}")
|
||||||
|
except SecurityError as e:
|
||||||
|
logger.warning(f"Template attempted restricted operation: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Unknown error in title generation: {e}")
|
||||||
|
logger.warning(
|
||||||
|
f"Invalid title format '{text}', workflow not applied: {e}",
|
||||||
|
)
|
||||||
|
raise e
|
||||||
|
return None
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ class TestApiWorkflows(DirectoriesMixin, APITestCase):
|
|||||||
"filter_has_tags": [self.t1.id],
|
"filter_has_tags": [self.t1.id],
|
||||||
"filter_has_document_type": self.dt.id,
|
"filter_has_document_type": self.dt.id,
|
||||||
"filter_has_correspondent": self.c.id,
|
"filter_has_correspondent": self.c.id,
|
||||||
|
"filter_has_storage_path": self.sp.id,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": [
|
||||||
|
|||||||
@@ -304,22 +304,6 @@ class TestConsumer(
|
|||||||
self.assertEqual(document.title, "Override Title")
|
self.assertEqual(document.title, "Override Title")
|
||||||
self._assert_first_last_send_progress()
|
self._assert_first_last_send_progress()
|
||||||
|
|
||||||
def testOverrideTitleInvalidPlaceholders(self):
|
|
||||||
with self.assertLogs("paperless.consumer", level="ERROR") as cm:
|
|
||||||
with self.get_consumer(
|
|
||||||
self.get_test_file(),
|
|
||||||
DocumentMetadataOverrides(title="Override {correspondent]"),
|
|
||||||
) as consumer:
|
|
||||||
consumer.run()
|
|
||||||
|
|
||||||
document = Document.objects.first()
|
|
||||||
|
|
||||||
self.assertIsNotNone(document)
|
|
||||||
|
|
||||||
self.assertEqual(document.title, "sample")
|
|
||||||
expected_str = "Error occurred parsing title override 'Override {correspondent]', falling back to original"
|
|
||||||
self.assertIn(expected_str, cm.output[0])
|
|
||||||
|
|
||||||
def testOverrideCorrespondent(self):
|
def testOverrideCorrespondent(self):
|
||||||
c = Correspondent.objects.create(name="test")
|
c = Correspondent.objects.create(name="test")
|
||||||
|
|
||||||
@@ -437,7 +421,7 @@ class TestConsumer(
|
|||||||
DocumentMetadataOverrides(
|
DocumentMetadataOverrides(
|
||||||
correspondent_id=c.pk,
|
correspondent_id=c.pk,
|
||||||
document_type_id=dt.pk,
|
document_type_id=dt.pk,
|
||||||
title="{correspondent}{document_type} {added_month}-{added_year_short}",
|
title="{{correspondent}}{{document_type}} {{added_month}}-{{added_year_short}}",
|
||||||
),
|
),
|
||||||
) as consumer:
|
) as consumer:
|
||||||
consumer.run()
|
consumer.run()
|
||||||
|
|||||||
@@ -18,14 +18,17 @@ class TestDocument(TestCase):
|
|||||||
self.originals_dir = tempfile.mkdtemp()
|
self.originals_dir = tempfile.mkdtemp()
|
||||||
self.thumb_dir = tempfile.mkdtemp()
|
self.thumb_dir = tempfile.mkdtemp()
|
||||||
|
|
||||||
override_settings(
|
self.overrides = override_settings(
|
||||||
ORIGINALS_DIR=self.originals_dir,
|
ORIGINALS_DIR=self.originals_dir,
|
||||||
THUMBNAIL_DIR=self.thumb_dir,
|
THUMBNAIL_DIR=self.thumb_dir,
|
||||||
).enable()
|
)
|
||||||
|
|
||||||
|
self.overrides.enable()
|
||||||
|
|
||||||
def tearDown(self) -> None:
|
def tearDown(self) -> None:
|
||||||
shutil.rmtree(self.originals_dir)
|
shutil.rmtree(self.originals_dir)
|
||||||
shutil.rmtree(self.thumb_dir)
|
shutil.rmtree(self.thumb_dir)
|
||||||
|
self.overrides.disable()
|
||||||
|
|
||||||
def test_file_deletion(self):
|
def test_file_deletion(self):
|
||||||
document = Document.objects.create(
|
document = Document.objects.create(
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ from documents.models import Document
|
|||||||
from documents.models import DocumentType
|
from documents.models import DocumentType
|
||||||
from documents.models import StoragePath
|
from documents.models import StoragePath
|
||||||
from documents.tasks import empty_trash
|
from documents.tasks import empty_trash
|
||||||
from documents.templating.filepath import localize_date
|
|
||||||
from documents.tests.factories import DocumentFactory
|
from documents.tests.factories import DocumentFactory
|
||||||
from documents.tests.utils import DirectoriesMixin
|
from documents.tests.utils import DirectoriesMixin
|
||||||
from documents.tests.utils import FileSystemAssertsMixin
|
from documents.tests.utils import FileSystemAssertsMixin
|
||||||
@@ -1591,166 +1590,13 @@ class TestFilenameGeneration(DirectoriesMixin, TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestDateLocalization:
|
class TestPathDateLocalization:
|
||||||
"""
|
"""
|
||||||
Groups all tests related to the `localize_date` function.
|
Groups all tests related to the `localize_date` function.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
TEST_DATE = datetime.date(2023, 10, 26)
|
TEST_DATE = datetime.date(2023, 10, 26)
|
||||||
|
|
||||||
TEST_DATETIME = datetime.datetime(
|
|
||||||
2023,
|
|
||||||
10,
|
|
||||||
26,
|
|
||||||
14,
|
|
||||||
30,
|
|
||||||
5,
|
|
||||||
tzinfo=datetime.timezone.utc,
|
|
||||||
)
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"value, format_style, locale_str, expected_output",
|
|
||||||
[
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATE,
|
|
||||||
"EEEE, MMM d, yyyy",
|
|
||||||
"en_US",
|
|
||||||
"Thursday, Oct 26, 2023",
|
|
||||||
id="date-en_US-custom",
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATE,
|
|
||||||
"dd.MM.yyyy",
|
|
||||||
"de_DE",
|
|
||||||
"26.10.2023",
|
|
||||||
id="date-de_DE-custom",
|
|
||||||
),
|
|
||||||
# German weekday and month name translation
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATE,
|
|
||||||
"EEEE",
|
|
||||||
"de_DE",
|
|
||||||
"Donnerstag",
|
|
||||||
id="weekday-de_DE",
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATE,
|
|
||||||
"MMMM",
|
|
||||||
"de_DE",
|
|
||||||
"Oktober",
|
|
||||||
id="month-de_DE",
|
|
||||||
),
|
|
||||||
# French weekday and month name translation
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATE,
|
|
||||||
"EEEE",
|
|
||||||
"fr_FR",
|
|
||||||
"jeudi",
|
|
||||||
id="weekday-fr_FR",
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATE,
|
|
||||||
"MMMM",
|
|
||||||
"fr_FR",
|
|
||||||
"octobre",
|
|
||||||
id="month-fr_FR",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_localize_date_with_date_objects(
|
|
||||||
self,
|
|
||||||
value: datetime.date,
|
|
||||||
format_style: str,
|
|
||||||
locale_str: str,
|
|
||||||
expected_output: str,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Tests `localize_date` with `date` objects across different locales and formats.
|
|
||||||
"""
|
|
||||||
assert localize_date(value, format_style, locale_str) == expected_output
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"value, format_style, locale_str, expected_output",
|
|
||||||
[
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATETIME,
|
|
||||||
"yyyy.MM.dd G 'at' HH:mm:ss zzz",
|
|
||||||
"en_US",
|
|
||||||
"2023.10.26 AD at 14:30:05 UTC",
|
|
||||||
id="datetime-en_US-custom",
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATETIME,
|
|
||||||
"dd.MM.yyyy",
|
|
||||||
"fr_FR",
|
|
||||||
"26.10.2023",
|
|
||||||
id="date-fr_FR-custom",
|
|
||||||
),
|
|
||||||
# Spanish weekday and month translation
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATETIME,
|
|
||||||
"EEEE",
|
|
||||||
"es_ES",
|
|
||||||
"jueves",
|
|
||||||
id="weekday-es_ES",
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATETIME,
|
|
||||||
"MMMM",
|
|
||||||
"es_ES",
|
|
||||||
"octubre",
|
|
||||||
id="month-es_ES",
|
|
||||||
),
|
|
||||||
# Italian weekday and month translation
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATETIME,
|
|
||||||
"EEEE",
|
|
||||||
"it_IT",
|
|
||||||
"giovedì",
|
|
||||||
id="weekday-it_IT",
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
TEST_DATETIME,
|
|
||||||
"MMMM",
|
|
||||||
"it_IT",
|
|
||||||
"ottobre",
|
|
||||||
id="month-it_IT",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_localize_date_with_datetime_objects(
|
|
||||||
self,
|
|
||||||
value: datetime.datetime,
|
|
||||||
format_style: str,
|
|
||||||
locale_str: str,
|
|
||||||
expected_output: str,
|
|
||||||
):
|
|
||||||
# To handle the non-breaking space in French and other locales
|
|
||||||
result = localize_date(value, format_style, locale_str)
|
|
||||||
assert result.replace("\u202f", " ") == expected_output.replace("\u202f", " ")
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"invalid_value",
|
|
||||||
[
|
|
||||||
"2023-10-26",
|
|
||||||
1698330605,
|
|
||||||
None,
|
|
||||||
[],
|
|
||||||
{},
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_localize_date_raises_type_error_for_invalid_input(self, invalid_value):
|
|
||||||
with pytest.raises(TypeError) as excinfo:
|
|
||||||
localize_date(invalid_value, "medium", "en_US")
|
|
||||||
|
|
||||||
assert f"Unsupported type {type(invalid_value)}" in str(excinfo.value)
|
|
||||||
|
|
||||||
def test_localize_date_raises_error_for_invalid_locale(self):
|
|
||||||
with pytest.raises(ValueError) as excinfo:
|
|
||||||
localize_date(self.TEST_DATE, "medium", "invalid_locale_code")
|
|
||||||
|
|
||||||
assert "Invalid locale identifier" in str(excinfo.value)
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"filename_format,expected_filename",
|
"filename_format,expected_filename",
|
||||||
|
|||||||
296
src/documents/tests/test_filters.py
Normal file
296
src/documents/tests/test_filters.py
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
import datetime
|
||||||
|
from typing import Any
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from documents.templating.filters import localize_date
|
||||||
|
|
||||||
|
|
||||||
|
class TestDateLocalization:
|
||||||
|
"""
|
||||||
|
Groups all tests related to the `localize_date` function.
|
||||||
|
"""
|
||||||
|
|
||||||
|
TEST_DATE = datetime.date(2023, 10, 26)
|
||||||
|
|
||||||
|
TEST_DATETIME = datetime.datetime(
|
||||||
|
2023,
|
||||||
|
10,
|
||||||
|
26,
|
||||||
|
14,
|
||||||
|
30,
|
||||||
|
5,
|
||||||
|
tzinfo=datetime.timezone.utc,
|
||||||
|
)
|
||||||
|
|
||||||
|
TEST_DATETIME_STRING: str = "2023-10-26T14:30:05+00:00"
|
||||||
|
|
||||||
|
TEST_DATE_STRING: str = "2023-10-26"
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"value, format_style, locale_str, expected_output",
|
||||||
|
[
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE,
|
||||||
|
"EEEE, MMM d, yyyy",
|
||||||
|
"en_US",
|
||||||
|
"Thursday, Oct 26, 2023",
|
||||||
|
id="date-en_US-custom",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE,
|
||||||
|
"dd.MM.yyyy",
|
||||||
|
"de_DE",
|
||||||
|
"26.10.2023",
|
||||||
|
id="date-de_DE-custom",
|
||||||
|
),
|
||||||
|
# German weekday and month name translation
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE,
|
||||||
|
"EEEE",
|
||||||
|
"de_DE",
|
||||||
|
"Donnerstag",
|
||||||
|
id="weekday-de_DE",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE,
|
||||||
|
"MMMM",
|
||||||
|
"de_DE",
|
||||||
|
"Oktober",
|
||||||
|
id="month-de_DE",
|
||||||
|
),
|
||||||
|
# French weekday and month name translation
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE,
|
||||||
|
"EEEE",
|
||||||
|
"fr_FR",
|
||||||
|
"jeudi",
|
||||||
|
id="weekday-fr_FR",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE,
|
||||||
|
"MMMM",
|
||||||
|
"fr_FR",
|
||||||
|
"octobre",
|
||||||
|
id="month-fr_FR",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_localize_date_with_date_objects(
|
||||||
|
self,
|
||||||
|
value: datetime.date,
|
||||||
|
format_style: str,
|
||||||
|
locale_str: str,
|
||||||
|
expected_output: str,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Tests `localize_date` with `date` objects across different locales and formats.
|
||||||
|
"""
|
||||||
|
assert localize_date(value, format_style, locale_str) == expected_output
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"value, format_style, locale_str, expected_output",
|
||||||
|
[
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME,
|
||||||
|
"yyyy.MM.dd G 'at' HH:mm:ss zzz",
|
||||||
|
"en_US",
|
||||||
|
"2023.10.26 AD at 14:30:05 UTC",
|
||||||
|
id="datetime-en_US-custom",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME,
|
||||||
|
"dd.MM.yyyy",
|
||||||
|
"fr_FR",
|
||||||
|
"26.10.2023",
|
||||||
|
id="date-fr_FR-custom",
|
||||||
|
),
|
||||||
|
# Spanish weekday and month translation
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME,
|
||||||
|
"EEEE",
|
||||||
|
"es_ES",
|
||||||
|
"jueves",
|
||||||
|
id="weekday-es_ES",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME,
|
||||||
|
"MMMM",
|
||||||
|
"es_ES",
|
||||||
|
"octubre",
|
||||||
|
id="month-es_ES",
|
||||||
|
),
|
||||||
|
# Italian weekday and month translation
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME,
|
||||||
|
"EEEE",
|
||||||
|
"it_IT",
|
||||||
|
"giovedì",
|
||||||
|
id="weekday-it_IT",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME,
|
||||||
|
"MMMM",
|
||||||
|
"it_IT",
|
||||||
|
"ottobre",
|
||||||
|
id="month-it_IT",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_localize_date_with_datetime_objects(
|
||||||
|
self,
|
||||||
|
value: datetime.datetime,
|
||||||
|
format_style: str,
|
||||||
|
locale_str: str,
|
||||||
|
expected_output: str,
|
||||||
|
):
|
||||||
|
# To handle the non-breaking space in French and other locales
|
||||||
|
result = localize_date(value, format_style, locale_str)
|
||||||
|
assert result.replace("\u202f", " ") == expected_output.replace("\u202f", " ")
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"invalid_value",
|
||||||
|
[
|
||||||
|
1698330605,
|
||||||
|
None,
|
||||||
|
[],
|
||||||
|
{},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_localize_date_raises_type_error_for_invalid_input(
|
||||||
|
self,
|
||||||
|
invalid_value: None | list[object] | dict[Any, Any] | Literal[1698330605],
|
||||||
|
):
|
||||||
|
with pytest.raises(TypeError) as excinfo:
|
||||||
|
localize_date(invalid_value, "medium", "en_US")
|
||||||
|
|
||||||
|
assert f"Unsupported type {type(invalid_value)}" in str(excinfo.value)
|
||||||
|
|
||||||
|
def test_localize_date_raises_error_for_invalid_locale(self):
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
localize_date(self.TEST_DATE, "medium", "invalid_locale_code")
|
||||||
|
|
||||||
|
assert "Invalid locale identifier" in str(excinfo.value)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"value, format_style, locale_str, expected_output",
|
||||||
|
[
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME_STRING,
|
||||||
|
"EEEE, MMM d, yyyy",
|
||||||
|
"en_US",
|
||||||
|
"Thursday, Oct 26, 2023",
|
||||||
|
id="date-en_US-custom",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME_STRING,
|
||||||
|
"dd.MM.yyyy",
|
||||||
|
"de_DE",
|
||||||
|
"26.10.2023",
|
||||||
|
id="date-de_DE-custom",
|
||||||
|
),
|
||||||
|
# German weekday and month name translation
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME_STRING,
|
||||||
|
"EEEE",
|
||||||
|
"de_DE",
|
||||||
|
"Donnerstag",
|
||||||
|
id="weekday-de_DE",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME_STRING,
|
||||||
|
"MMMM",
|
||||||
|
"de_DE",
|
||||||
|
"Oktober",
|
||||||
|
id="month-de_DE",
|
||||||
|
),
|
||||||
|
# French weekday and month name translation
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME_STRING,
|
||||||
|
"EEEE",
|
||||||
|
"fr_FR",
|
||||||
|
"jeudi",
|
||||||
|
id="weekday-fr_FR",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATETIME_STRING,
|
||||||
|
"MMMM",
|
||||||
|
"fr_FR",
|
||||||
|
"octobre",
|
||||||
|
id="month-fr_FR",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_localize_date_with_datetime_string(
|
||||||
|
self,
|
||||||
|
value: str,
|
||||||
|
format_style: str,
|
||||||
|
locale_str: str,
|
||||||
|
expected_output: str,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Tests `localize_date` with `date` string across different locales and formats.
|
||||||
|
"""
|
||||||
|
assert localize_date(value, format_style, locale_str) == expected_output
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"value, format_style, locale_str, expected_output",
|
||||||
|
[
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE_STRING,
|
||||||
|
"EEEE, MMM d, yyyy",
|
||||||
|
"en_US",
|
||||||
|
"Thursday, Oct 26, 2023",
|
||||||
|
id="date-en_US-custom",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE_STRING,
|
||||||
|
"dd.MM.yyyy",
|
||||||
|
"de_DE",
|
||||||
|
"26.10.2023",
|
||||||
|
id="date-de_DE-custom",
|
||||||
|
),
|
||||||
|
# German weekday and month name translation
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE_STRING,
|
||||||
|
"EEEE",
|
||||||
|
"de_DE",
|
||||||
|
"Donnerstag",
|
||||||
|
id="weekday-de_DE",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE_STRING,
|
||||||
|
"MMMM",
|
||||||
|
"de_DE",
|
||||||
|
"Oktober",
|
||||||
|
id="month-de_DE",
|
||||||
|
),
|
||||||
|
# French weekday and month name translation
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE_STRING,
|
||||||
|
"EEEE",
|
||||||
|
"fr_FR",
|
||||||
|
"jeudi",
|
||||||
|
id="weekday-fr_FR",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
TEST_DATE_STRING,
|
||||||
|
"MMMM",
|
||||||
|
"fr_FR",
|
||||||
|
"octobre",
|
||||||
|
id="month-fr_FR",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_localize_date_with_date_string(
|
||||||
|
self,
|
||||||
|
value: str,
|
||||||
|
format_style: str,
|
||||||
|
locale_str: str,
|
||||||
|
expected_output: str,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Tests `localize_date` with `date` string across different locales and formats.
|
||||||
|
"""
|
||||||
|
assert localize_date(value, format_style, locale_str) == expected_output
|
||||||
@@ -97,12 +97,6 @@ class TestArchiver(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestDecryptDocuments(FileSystemAssertsMixin, TestCase):
|
class TestDecryptDocuments(FileSystemAssertsMixin, TestCase):
|
||||||
@override_settings(
|
|
||||||
ORIGINALS_DIR=(Path(__file__).parent / "samples" / "originals"),
|
|
||||||
THUMBNAIL_DIR=(Path(__file__).parent / "samples" / "thumb"),
|
|
||||||
PASSPHRASE="test",
|
|
||||||
FILENAME_FORMAT=None,
|
|
||||||
)
|
|
||||||
@mock.patch("documents.management.commands.decrypt_documents.input")
|
@mock.patch("documents.management.commands.decrypt_documents.input")
|
||||||
def test_decrypt(self, m):
|
def test_decrypt(self, m):
|
||||||
media_dir = tempfile.mkdtemp()
|
media_dir = tempfile.mkdtemp()
|
||||||
@@ -111,55 +105,55 @@ class TestDecryptDocuments(FileSystemAssertsMixin, TestCase):
|
|||||||
originals_dir.mkdir(parents=True, exist_ok=True)
|
originals_dir.mkdir(parents=True, exist_ok=True)
|
||||||
thumb_dir.mkdir(parents=True, exist_ok=True)
|
thumb_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
override_settings(
|
with override_settings(
|
||||||
ORIGINALS_DIR=originals_dir,
|
ORIGINALS_DIR=originals_dir,
|
||||||
THUMBNAIL_DIR=thumb_dir,
|
THUMBNAIL_DIR=thumb_dir,
|
||||||
PASSPHRASE="test",
|
PASSPHRASE="test",
|
||||||
).enable()
|
FILENAME_FORMAT=None,
|
||||||
|
):
|
||||||
|
doc = Document.objects.create(
|
||||||
|
checksum="82186aaa94f0b98697d704b90fd1c072",
|
||||||
|
title="wow",
|
||||||
|
filename="0000004.pdf.gpg",
|
||||||
|
mime_type="application/pdf",
|
||||||
|
storage_type=Document.STORAGE_TYPE_GPG,
|
||||||
|
)
|
||||||
|
|
||||||
doc = Document.objects.create(
|
shutil.copy(
|
||||||
checksum="82186aaa94f0b98697d704b90fd1c072",
|
(
|
||||||
title="wow",
|
Path(__file__).parent
|
||||||
filename="0000004.pdf.gpg",
|
/ "samples"
|
||||||
mime_type="application/pdf",
|
/ "documents"
|
||||||
storage_type=Document.STORAGE_TYPE_GPG,
|
/ "originals"
|
||||||
)
|
/ "0000004.pdf.gpg"
|
||||||
|
),
|
||||||
|
originals_dir / "0000004.pdf.gpg",
|
||||||
|
)
|
||||||
|
shutil.copy(
|
||||||
|
(
|
||||||
|
Path(__file__).parent
|
||||||
|
/ "samples"
|
||||||
|
/ "documents"
|
||||||
|
/ "thumbnails"
|
||||||
|
/ "0000004.webp.gpg"
|
||||||
|
),
|
||||||
|
thumb_dir / f"{doc.id:07}.webp.gpg",
|
||||||
|
)
|
||||||
|
|
||||||
shutil.copy(
|
call_command("decrypt_documents")
|
||||||
(
|
|
||||||
Path(__file__).parent
|
|
||||||
/ "samples"
|
|
||||||
/ "documents"
|
|
||||||
/ "originals"
|
|
||||||
/ "0000004.pdf.gpg"
|
|
||||||
),
|
|
||||||
originals_dir / "0000004.pdf.gpg",
|
|
||||||
)
|
|
||||||
shutil.copy(
|
|
||||||
(
|
|
||||||
Path(__file__).parent
|
|
||||||
/ "samples"
|
|
||||||
/ "documents"
|
|
||||||
/ "thumbnails"
|
|
||||||
/ "0000004.webp.gpg"
|
|
||||||
),
|
|
||||||
thumb_dir / f"{doc.id:07}.webp.gpg",
|
|
||||||
)
|
|
||||||
|
|
||||||
call_command("decrypt_documents")
|
doc.refresh_from_db()
|
||||||
|
|
||||||
doc.refresh_from_db()
|
self.assertEqual(doc.storage_type, Document.STORAGE_TYPE_UNENCRYPTED)
|
||||||
|
self.assertEqual(doc.filename, "0000004.pdf")
|
||||||
|
self.assertIsFile(Path(originals_dir) / "0000004.pdf")
|
||||||
|
self.assertIsFile(doc.source_path)
|
||||||
|
self.assertIsFile(Path(thumb_dir) / f"{doc.id:07}.webp")
|
||||||
|
self.assertIsFile(doc.thumbnail_path)
|
||||||
|
|
||||||
self.assertEqual(doc.storage_type, Document.STORAGE_TYPE_UNENCRYPTED)
|
with doc.source_file as f:
|
||||||
self.assertEqual(doc.filename, "0000004.pdf")
|
checksum: str = hashlib.md5(f.read()).hexdigest()
|
||||||
self.assertIsFile(Path(originals_dir) / "0000004.pdf")
|
self.assertEqual(checksum, doc.checksum)
|
||||||
self.assertIsFile(doc.source_path)
|
|
||||||
self.assertIsFile(Path(thumb_dir) / f"{doc.id:07}.webp")
|
|
||||||
self.assertIsFile(doc.thumbnail_path)
|
|
||||||
|
|
||||||
with doc.source_file as f:
|
|
||||||
checksum: str = hashlib.md5(f.read()).hexdigest()
|
|
||||||
self.assertEqual(checksum, doc.checksum)
|
|
||||||
|
|
||||||
|
|
||||||
class TestMakeIndex(TestCase):
|
class TestMakeIndex(TestCase):
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
import datetime
|
||||||
import shutil
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
@@ -15,6 +17,7 @@ from guardian.shortcuts import get_users_with_perms
|
|||||||
from httpx import HTTPError
|
from httpx import HTTPError
|
||||||
from httpx import HTTPStatusError
|
from httpx import HTTPStatusError
|
||||||
from pytest_httpx import HTTPXMock
|
from pytest_httpx import HTTPXMock
|
||||||
|
from rest_framework.test import APIClient
|
||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from documents.signals.handlers import run_workflows
|
from documents.signals.handlers import run_workflows
|
||||||
@@ -22,7 +25,7 @@ from documents.signals.handlers import send_webhook
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
|
from pytest_django.fixtures import SettingsWrapper
|
||||||
|
|
||||||
from documents import tasks
|
from documents import tasks
|
||||||
from documents.data_models import ConsumableDocument
|
from documents.data_models import ConsumableDocument
|
||||||
@@ -122,7 +125,7 @@ class TestWorkflows(
|
|||||||
filter_path=f"*/{self.dirs.scratch_dir.parts[-1]}/*",
|
filter_path=f"*/{self.dirs.scratch_dir.parts[-1]}/*",
|
||||||
)
|
)
|
||||||
action = WorkflowAction.objects.create(
|
action = WorkflowAction.objects.create(
|
||||||
assign_title="Doc from {correspondent}",
|
assign_title="Doc from {{correspondent}}",
|
||||||
assign_correspondent=self.c,
|
assign_correspondent=self.c,
|
||||||
assign_document_type=self.dt,
|
assign_document_type=self.dt,
|
||||||
assign_storage_path=self.sp,
|
assign_storage_path=self.sp,
|
||||||
@@ -241,7 +244,7 @@ class TestWorkflows(
|
|||||||
)
|
)
|
||||||
|
|
||||||
action = WorkflowAction.objects.create(
|
action = WorkflowAction.objects.create(
|
||||||
assign_title="Doc from {correspondent}",
|
assign_title="Doc from {{correspondent}}",
|
||||||
assign_correspondent=self.c,
|
assign_correspondent=self.c,
|
||||||
assign_document_type=self.dt,
|
assign_document_type=self.dt,
|
||||||
assign_storage_path=self.sp,
|
assign_storage_path=self.sp,
|
||||||
@@ -892,7 +895,7 @@ class TestWorkflows(
|
|||||||
filter_filename="*sample*",
|
filter_filename="*sample*",
|
||||||
)
|
)
|
||||||
action = WorkflowAction.objects.create(
|
action = WorkflowAction.objects.create(
|
||||||
assign_title="Doc created in {created_year}",
|
assign_title="Doc created in {{created_year}}",
|
||||||
assign_correspondent=self.c2,
|
assign_correspondent=self.c2,
|
||||||
assign_document_type=self.dt,
|
assign_document_type=self.dt,
|
||||||
assign_storage_path=self.sp,
|
assign_storage_path=self.sp,
|
||||||
@@ -1147,6 +1150,38 @@ class TestWorkflows(
|
|||||||
expected_str = f"Document correspondent {doc.correspondent} does not match {trigger.filter_has_correspondent}"
|
expected_str = f"Document correspondent {doc.correspondent} does not match {trigger.filter_has_correspondent}"
|
||||||
self.assertIn(expected_str, cm.output[1])
|
self.assertIn(expected_str, cm.output[1])
|
||||||
|
|
||||||
|
def test_document_added_no_match_storage_path(self):
|
||||||
|
trigger = WorkflowTrigger.objects.create(
|
||||||
|
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_ADDED,
|
||||||
|
filter_has_storage_path=self.sp,
|
||||||
|
)
|
||||||
|
action = WorkflowAction.objects.create(
|
||||||
|
assign_title="Doc assign owner",
|
||||||
|
assign_owner=self.user2,
|
||||||
|
)
|
||||||
|
w = Workflow.objects.create(
|
||||||
|
name="Workflow 1",
|
||||||
|
order=0,
|
||||||
|
)
|
||||||
|
w.triggers.add(trigger)
|
||||||
|
w.actions.add(action)
|
||||||
|
w.save()
|
||||||
|
|
||||||
|
doc = Document.objects.create(
|
||||||
|
title="sample test",
|
||||||
|
original_filename="sample.pdf",
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertLogs("paperless.matching", level="DEBUG") as cm:
|
||||||
|
document_consumption_finished.send(
|
||||||
|
sender=self.__class__,
|
||||||
|
document=doc,
|
||||||
|
)
|
||||||
|
expected_str = f"Document did not match {w}"
|
||||||
|
self.assertIn(expected_str, cm.output[0])
|
||||||
|
expected_str = f"Document storage path {doc.storage_path} does not match {trigger.filter_has_storage_path}"
|
||||||
|
self.assertIn(expected_str, cm.output[1])
|
||||||
|
|
||||||
def test_document_added_invalid_title_placeholders(self):
|
def test_document_added_invalid_title_placeholders(self):
|
||||||
"""
|
"""
|
||||||
GIVEN:
|
GIVEN:
|
||||||
@@ -1155,7 +1190,7 @@ class TestWorkflows(
|
|||||||
WHEN:
|
WHEN:
|
||||||
- File that matches is added
|
- File that matches is added
|
||||||
THEN:
|
THEN:
|
||||||
- Title is not updated, error is output
|
- Title is updated but the placeholder isn't replaced
|
||||||
"""
|
"""
|
||||||
trigger = WorkflowTrigger.objects.create(
|
trigger = WorkflowTrigger.objects.create(
|
||||||
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_ADDED,
|
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_ADDED,
|
||||||
@@ -1181,15 +1216,12 @@ class TestWorkflows(
|
|||||||
created=created,
|
created=created,
|
||||||
)
|
)
|
||||||
|
|
||||||
with self.assertLogs("paperless.handlers", level="ERROR") as cm:
|
document_consumption_finished.send(
|
||||||
document_consumption_finished.send(
|
sender=self.__class__,
|
||||||
sender=self.__class__,
|
document=doc,
|
||||||
document=doc,
|
)
|
||||||
)
|
|
||||||
expected_str = f"Error occurred parsing title assignment '{action.assign_title}', falling back to original"
|
|
||||||
self.assertIn(expected_str, cm.output[0])
|
|
||||||
|
|
||||||
self.assertEqual(doc.title, "sample test")
|
self.assertEqual(doc.title, "Doc {created_year]")
|
||||||
|
|
||||||
def test_document_updated_workflow(self):
|
def test_document_updated_workflow(self):
|
||||||
trigger = WorkflowTrigger.objects.create(
|
trigger = WorkflowTrigger.objects.create(
|
||||||
@@ -1223,6 +1255,45 @@ class TestWorkflows(
|
|||||||
|
|
||||||
self.assertEqual(doc.custom_fields.all().count(), 1)
|
self.assertEqual(doc.custom_fields.all().count(), 1)
|
||||||
|
|
||||||
|
def test_document_consumption_workflow_month_placeholder_addded(self):
|
||||||
|
trigger = WorkflowTrigger.objects.create(
|
||||||
|
type=WorkflowTrigger.WorkflowTriggerType.CONSUMPTION,
|
||||||
|
sources=f"{DocumentSource.ApiUpload}",
|
||||||
|
filter_filename="simple*",
|
||||||
|
)
|
||||||
|
|
||||||
|
action = WorkflowAction.objects.create(
|
||||||
|
assign_title="Doc added in {{added_month_name_short}}",
|
||||||
|
)
|
||||||
|
|
||||||
|
w = Workflow.objects.create(
|
||||||
|
name="Workflow 1",
|
||||||
|
order=0,
|
||||||
|
)
|
||||||
|
w.triggers.add(trigger)
|
||||||
|
w.actions.add(action)
|
||||||
|
w.save()
|
||||||
|
|
||||||
|
superuser = User.objects.create_superuser("superuser")
|
||||||
|
self.client.force_authenticate(user=superuser)
|
||||||
|
test_file = shutil.copy(
|
||||||
|
self.SAMPLE_DIR / "simple.pdf",
|
||||||
|
self.dirs.scratch_dir / "simple.pdf",
|
||||||
|
)
|
||||||
|
with mock.patch("documents.tasks.ProgressManager", DummyProgressManager):
|
||||||
|
tasks.consume_file(
|
||||||
|
ConsumableDocument(
|
||||||
|
source=DocumentSource.ApiUpload,
|
||||||
|
original_file=test_file,
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
document = Document.objects.first()
|
||||||
|
self.assertRegex(
|
||||||
|
document.title,
|
||||||
|
r"Doc added in \w{3,}",
|
||||||
|
) # Match any 3-letter month name
|
||||||
|
|
||||||
def test_document_updated_workflow_existing_custom_field(self):
|
def test_document_updated_workflow_existing_custom_field(self):
|
||||||
"""
|
"""
|
||||||
GIVEN:
|
GIVEN:
|
||||||
@@ -1777,6 +1848,7 @@ class TestWorkflows(
|
|||||||
filter_filename="*sample*",
|
filter_filename="*sample*",
|
||||||
filter_has_document_type=self.dt,
|
filter_has_document_type=self.dt,
|
||||||
filter_has_correspondent=self.c,
|
filter_has_correspondent=self.c,
|
||||||
|
filter_has_storage_path=self.sp,
|
||||||
)
|
)
|
||||||
trigger.filter_has_tags.set([self.t1])
|
trigger.filter_has_tags.set([self.t1])
|
||||||
trigger.save()
|
trigger.save()
|
||||||
@@ -1797,6 +1869,7 @@ class TestWorkflows(
|
|||||||
title=f"sample test {i}",
|
title=f"sample test {i}",
|
||||||
checksum=f"checksum{i}",
|
checksum=f"checksum{i}",
|
||||||
correspondent=self.c,
|
correspondent=self.c,
|
||||||
|
storage_path=self.sp,
|
||||||
original_filename=f"sample_{i}.pdf",
|
original_filename=f"sample_{i}.pdf",
|
||||||
document_type=self.dt if i % 2 == 0 else None,
|
document_type=self.dt if i % 2 == 0 else None,
|
||||||
)
|
)
|
||||||
@@ -2035,7 +2108,7 @@ class TestWorkflows(
|
|||||||
filter_filename="*simple*",
|
filter_filename="*simple*",
|
||||||
)
|
)
|
||||||
action = WorkflowAction.objects.create(
|
action = WorkflowAction.objects.create(
|
||||||
assign_title="Doc from {correspondent}",
|
assign_title="Doc from {{correspondent}}",
|
||||||
assign_correspondent=self.c,
|
assign_correspondent=self.c,
|
||||||
assign_document_type=self.dt,
|
assign_document_type=self.dt,
|
||||||
assign_storage_path=self.sp,
|
assign_storage_path=self.sp,
|
||||||
@@ -2614,7 +2687,7 @@ class TestWorkflows(
|
|||||||
)
|
)
|
||||||
webhook_action = WorkflowActionWebhook.objects.create(
|
webhook_action = WorkflowActionWebhook.objects.create(
|
||||||
use_params=False,
|
use_params=False,
|
||||||
body="Test message: {doc_url}",
|
body="Test message: {{doc_url}}",
|
||||||
url="http://paperless-ngx.com",
|
url="http://paperless-ngx.com",
|
||||||
include_document=False,
|
include_document=False,
|
||||||
)
|
)
|
||||||
@@ -2673,7 +2746,7 @@ class TestWorkflows(
|
|||||||
)
|
)
|
||||||
webhook_action = WorkflowActionWebhook.objects.create(
|
webhook_action = WorkflowActionWebhook.objects.create(
|
||||||
use_params=False,
|
use_params=False,
|
||||||
body="Test message: {doc_url}",
|
body="Test message: {{doc_url}}",
|
||||||
url="http://paperless-ngx.com",
|
url="http://paperless-ngx.com",
|
||||||
include_document=True,
|
include_document=True,
|
||||||
)
|
)
|
||||||
@@ -3130,3 +3203,238 @@ class TestWebhookSecurity:
|
|||||||
req = httpx_mock.get_request()
|
req = httpx_mock.get_request()
|
||||||
assert req.headers["Host"] == "paperless-ngx.com"
|
assert req.headers["Host"] == "paperless-ngx.com"
|
||||||
assert "evil.test" not in req.headers.get("Host", "")
|
assert "evil.test" not in req.headers.get("Host", "")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
class TestDateWorkflowLocalization(
|
||||||
|
SampleDirMixin,
|
||||||
|
):
|
||||||
|
"""Test cases for workflows that use date localization in templates."""
|
||||||
|
|
||||||
|
TEST_DATETIME = datetime.datetime(
|
||||||
|
2023,
|
||||||
|
6,
|
||||||
|
26,
|
||||||
|
14,
|
||||||
|
30,
|
||||||
|
5,
|
||||||
|
tzinfo=datetime.timezone.utc,
|
||||||
|
)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"title_template,expected_title",
|
||||||
|
[
|
||||||
|
pytest.param(
|
||||||
|
"Created at {{ created | localize_date('MMMM', 'es_ES') }}",
|
||||||
|
"Created at junio",
|
||||||
|
id="spanish_month",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"Created at {{ created | localize_date('MMMM', 'de_DE') }}",
|
||||||
|
"Created at Juni", # codespell:ignore
|
||||||
|
id="german_month",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"Created at {{ created | localize_date('dd/MM/yyyy', 'en_GB') }}",
|
||||||
|
"Created at 26/06/2023",
|
||||||
|
id="british_date_format",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_document_added_workflow_localization(
|
||||||
|
self,
|
||||||
|
title_template: str,
|
||||||
|
expected_title: str,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
GIVEN:
|
||||||
|
- Document added workflow with title template using localize_date filter
|
||||||
|
WHEN:
|
||||||
|
- Document is consumed
|
||||||
|
THEN:
|
||||||
|
- Document title is set with localized date
|
||||||
|
"""
|
||||||
|
trigger = WorkflowTrigger.objects.create(
|
||||||
|
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_ADDED,
|
||||||
|
filter_filename="*sample*",
|
||||||
|
)
|
||||||
|
|
||||||
|
action = WorkflowAction.objects.create(
|
||||||
|
assign_title=title_template,
|
||||||
|
)
|
||||||
|
|
||||||
|
workflow = Workflow.objects.create(
|
||||||
|
name="Workflow 1",
|
||||||
|
order=0,
|
||||||
|
)
|
||||||
|
workflow.triggers.add(trigger)
|
||||||
|
workflow.actions.add(action)
|
||||||
|
workflow.save()
|
||||||
|
|
||||||
|
doc = Document.objects.create(
|
||||||
|
title="sample test",
|
||||||
|
correspondent=None,
|
||||||
|
original_filename="sample.pdf",
|
||||||
|
created=self.TEST_DATETIME,
|
||||||
|
)
|
||||||
|
|
||||||
|
document_consumption_finished.send(
|
||||||
|
sender=self.__class__,
|
||||||
|
document=doc,
|
||||||
|
)
|
||||||
|
|
||||||
|
doc.refresh_from_db()
|
||||||
|
assert doc.title == expected_title
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"title_template,expected_title",
|
||||||
|
[
|
||||||
|
pytest.param(
|
||||||
|
"Created at {{ created | localize_date('MMMM', 'es_ES') }}",
|
||||||
|
"Created at junio",
|
||||||
|
id="spanish_month",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"Created at {{ created | localize_date('MMMM', 'de_DE') }}",
|
||||||
|
"Created at Juni", # codespell:ignore
|
||||||
|
id="german_month",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"Created at {{ created | localize_date('dd/MM/yyyy', 'en_GB') }}",
|
||||||
|
"Created at 26/06/2023",
|
||||||
|
id="british_date_format",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_document_updated_workflow_localization(
|
||||||
|
self,
|
||||||
|
title_template: str,
|
||||||
|
expected_title: str,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
GIVEN:
|
||||||
|
- Document updated workflow with title template using localize_date filter
|
||||||
|
WHEN:
|
||||||
|
- Document is updated via API
|
||||||
|
THEN:
|
||||||
|
- Document title is set with localized date
|
||||||
|
"""
|
||||||
|
# Setup test data
|
||||||
|
dt = DocumentType.objects.create(name="DocType Name")
|
||||||
|
c = Correspondent.objects.create(name="Correspondent Name")
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
superuser = User.objects.create_superuser("superuser")
|
||||||
|
client.force_authenticate(user=superuser)
|
||||||
|
|
||||||
|
trigger = WorkflowTrigger.objects.create(
|
||||||
|
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
|
||||||
|
filter_has_document_type=dt,
|
||||||
|
)
|
||||||
|
|
||||||
|
doc = Document.objects.create(
|
||||||
|
title="sample test",
|
||||||
|
correspondent=c,
|
||||||
|
original_filename="sample.pdf",
|
||||||
|
created=self.TEST_DATETIME,
|
||||||
|
)
|
||||||
|
|
||||||
|
action = WorkflowAction.objects.create(
|
||||||
|
assign_title=title_template,
|
||||||
|
)
|
||||||
|
|
||||||
|
workflow = Workflow.objects.create(
|
||||||
|
name="Workflow 1",
|
||||||
|
order=0,
|
||||||
|
)
|
||||||
|
workflow.triggers.add(trigger)
|
||||||
|
workflow.actions.add(action)
|
||||||
|
workflow.save()
|
||||||
|
|
||||||
|
client.patch(
|
||||||
|
f"/api/documents/{doc.id}/",
|
||||||
|
{"document_type": dt.id},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
|
||||||
|
doc.refresh_from_db()
|
||||||
|
assert doc.title == expected_title
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"title_template,expected_title",
|
||||||
|
[
|
||||||
|
pytest.param(
|
||||||
|
"Added at {{ added | localize_date('MMMM', 'es_ES') }}",
|
||||||
|
"Added at junio",
|
||||||
|
id="spanish_month",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"Added at {{ added | localize_date('MMMM', 'de_DE') }}",
|
||||||
|
"Added at Juni", # codespell:ignore
|
||||||
|
id="german_month",
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"Added at {{ added | localize_date('dd/MM/yyyy', 'en_GB') }}",
|
||||||
|
"Added at 26/06/2023",
|
||||||
|
id="british_date_format",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_document_consumption_workflow_localization(
|
||||||
|
self,
|
||||||
|
tmp_path: Path,
|
||||||
|
settings: SettingsWrapper,
|
||||||
|
title_template: str,
|
||||||
|
expected_title: str,
|
||||||
|
):
|
||||||
|
trigger = WorkflowTrigger.objects.create(
|
||||||
|
type=WorkflowTrigger.WorkflowTriggerType.CONSUMPTION,
|
||||||
|
sources=f"{DocumentSource.ApiUpload}",
|
||||||
|
filter_filename="simple*",
|
||||||
|
)
|
||||||
|
|
||||||
|
test_file = shutil.copy(
|
||||||
|
self.SAMPLE_DIR / "simple.pdf",
|
||||||
|
tmp_path / "simple.pdf",
|
||||||
|
)
|
||||||
|
|
||||||
|
action = WorkflowAction.objects.create(
|
||||||
|
assign_title=title_template,
|
||||||
|
)
|
||||||
|
|
||||||
|
w = Workflow.objects.create(
|
||||||
|
name="Workflow 1",
|
||||||
|
order=0,
|
||||||
|
)
|
||||||
|
w.triggers.add(trigger)
|
||||||
|
w.actions.add(action)
|
||||||
|
w.save()
|
||||||
|
|
||||||
|
(tmp_path / "scratch").mkdir(parents=True, exist_ok=True)
|
||||||
|
(tmp_path / "thumbnails").mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# Temporarily override "now" for the environment so templates using
|
||||||
|
# added/created placeholders behave as if it's a different system date.
|
||||||
|
with (
|
||||||
|
mock.patch(
|
||||||
|
"documents.tasks.ProgressManager",
|
||||||
|
DummyProgressManager,
|
||||||
|
),
|
||||||
|
mock.patch(
|
||||||
|
"django.utils.timezone.now",
|
||||||
|
return_value=self.TEST_DATETIME,
|
||||||
|
),
|
||||||
|
override_settings(
|
||||||
|
SCRATCH_DIR=tmp_path / "scratch",
|
||||||
|
THUMBNAIL_DIR=tmp_path / "thumbnails",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
tasks.consume_file(
|
||||||
|
ConsumableDocument(
|
||||||
|
source=DocumentSource.ApiUpload,
|
||||||
|
original_file=test_file,
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
document = Document.objects.first()
|
||||||
|
assert document.title == expected_title
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: paperless-ngx\n"
|
"Project-Id-Version: paperless-ngx\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-09 20:04+0000\n"
|
"POT-Creation-Date: 2025-09-11 17:43+0000\n"
|
||||||
"PO-Revision-Date: 2022-02-17 04:17\n"
|
"PO-Revision-Date: 2022-02-17 04:17\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: English\n"
|
"Language-Team: English\n"
|
||||||
@@ -89,7 +89,7 @@ msgstr ""
|
|||||||
msgid "Automatic"
|
msgid "Automatic"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:62 documents/models.py:423 documents/models.py:1441
|
#: documents/models.py:62 documents/models.py:423 documents/models.py:1447
|
||||||
#: paperless_mail/models.py:23 paperless_mail/models.py:143
|
#: paperless_mail/models.py:23 paperless_mail/models.py:143
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -256,7 +256,7 @@ msgid "The position of this document in your physical document archive."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:294 documents/models.py:666 documents/models.py:720
|
#: documents/models.py:294 documents/models.py:666 documents/models.py:720
|
||||||
#: documents/models.py:1484
|
#: documents/models.py:1490
|
||||||
msgid "document"
|
msgid "document"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -860,319 +860,322 @@ msgstr ""
|
|||||||
msgid "has this correspondent"
|
msgid "has this correspondent"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1048
|
#: documents/models.py:1052
|
||||||
msgid "schedule offset days"
|
msgid "has this storage path"
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: documents/models.py:1051
|
|
||||||
msgid "The number of days to offset the schedule trigger by."
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1056
|
#: documents/models.py:1056
|
||||||
msgid "schedule is recurring"
|
msgid "schedule offset days"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1059
|
#: documents/models.py:1059
|
||||||
msgid "If the schedule should be recurring."
|
msgid "The number of days to offset the schedule trigger by."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1064
|
#: documents/models.py:1064
|
||||||
|
msgid "schedule is recurring"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: documents/models.py:1067
|
||||||
|
msgid "If the schedule should be recurring."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: documents/models.py:1072
|
||||||
msgid "schedule recurring delay in days"
|
msgid "schedule recurring delay in days"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1068
|
#: documents/models.py:1076
|
||||||
msgid "The number of days between recurring schedule triggers."
|
msgid "The number of days between recurring schedule triggers."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1073
|
#: documents/models.py:1081
|
||||||
msgid "schedule date field"
|
msgid "schedule date field"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1078
|
#: documents/models.py:1086
|
||||||
msgid "The field to check for a schedule trigger."
|
msgid "The field to check for a schedule trigger."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1087
|
#: documents/models.py:1095
|
||||||
msgid "schedule date custom field"
|
msgid "schedule date custom field"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1091
|
#: documents/models.py:1099
|
||||||
msgid "workflow trigger"
|
msgid "workflow trigger"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1092
|
#: documents/models.py:1100
|
||||||
msgid "workflow triggers"
|
msgid "workflow triggers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1100
|
#: documents/models.py:1108
|
||||||
msgid "email subject"
|
msgid "email subject"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1104
|
#: documents/models.py:1112
|
||||||
msgid ""
|
msgid ""
|
||||||
"The subject of the email, can include some placeholders, see documentation."
|
"The subject of the email, can include some placeholders, see documentation."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1110
|
#: documents/models.py:1118
|
||||||
msgid "email body"
|
msgid "email body"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1113
|
#: documents/models.py:1121
|
||||||
msgid ""
|
msgid ""
|
||||||
"The body (message) of the email, can include some placeholders, see "
|
"The body (message) of the email, can include some placeholders, see "
|
||||||
"documentation."
|
"documentation."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1119
|
#: documents/models.py:1127
|
||||||
msgid "emails to"
|
msgid "emails to"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1122
|
#: documents/models.py:1130
|
||||||
msgid "The destination email addresses, comma separated."
|
msgid "The destination email addresses, comma separated."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1128
|
#: documents/models.py:1136
|
||||||
msgid "include document in email"
|
msgid "include document in email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1139
|
#: documents/models.py:1147
|
||||||
msgid "webhook url"
|
msgid "webhook url"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1142
|
#: documents/models.py:1150
|
||||||
msgid "The destination URL for the notification."
|
msgid "The destination URL for the notification."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1147
|
#: documents/models.py:1155
|
||||||
msgid "use parameters"
|
msgid "use parameters"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1152
|
#: documents/models.py:1160
|
||||||
msgid "send as JSON"
|
msgid "send as JSON"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1156
|
#: documents/models.py:1164
|
||||||
msgid "webhook parameters"
|
msgid "webhook parameters"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1159
|
#: documents/models.py:1167
|
||||||
msgid "The parameters to send with the webhook URL if body not used."
|
msgid "The parameters to send with the webhook URL if body not used."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1163
|
#: documents/models.py:1171
|
||||||
msgid "webhook body"
|
msgid "webhook body"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1166
|
#: documents/models.py:1174
|
||||||
msgid "The body to send with the webhook URL if parameters not used."
|
msgid "The body to send with the webhook URL if parameters not used."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1170
|
#: documents/models.py:1178
|
||||||
msgid "webhook headers"
|
msgid "webhook headers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1173
|
#: documents/models.py:1181
|
||||||
msgid "The headers to send with the webhook URL."
|
msgid "The headers to send with the webhook URL."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1178
|
#: documents/models.py:1186
|
||||||
msgid "include document in webhook"
|
msgid "include document in webhook"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1189
|
#: documents/models.py:1197
|
||||||
msgid "Assignment"
|
msgid "Assignment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1193
|
#: documents/models.py:1201
|
||||||
msgid "Removal"
|
msgid "Removal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1197 documents/templates/account/password_reset.html:15
|
#: documents/models.py:1205 documents/templates/account/password_reset.html:15
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1201
|
#: documents/models.py:1209
|
||||||
msgid "Webhook"
|
msgid "Webhook"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1205
|
#: documents/models.py:1213
|
||||||
msgid "Workflow Action Type"
|
msgid "Workflow Action Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1211
|
#: documents/models.py:1219
|
||||||
msgid "assign title"
|
msgid "assign title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1216
|
#: documents/models.py:1223
|
||||||
msgid ""
|
msgid "Assign a document title, must be a Jinja2 template, see documentation."
|
||||||
"Assign a document title, can include some placeholders, see documentation."
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1225 paperless_mail/models.py:274
|
#: documents/models.py:1231 paperless_mail/models.py:274
|
||||||
msgid "assign this tag"
|
msgid "assign this tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1234 paperless_mail/models.py:282
|
#: documents/models.py:1240 paperless_mail/models.py:282
|
||||||
msgid "assign this document type"
|
msgid "assign this document type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1243 paperless_mail/models.py:296
|
#: documents/models.py:1249 paperless_mail/models.py:296
|
||||||
msgid "assign this correspondent"
|
msgid "assign this correspondent"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1252
|
#: documents/models.py:1258
|
||||||
msgid "assign this storage path"
|
msgid "assign this storage path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1261
|
#: documents/models.py:1267
|
||||||
msgid "assign this owner"
|
msgid "assign this owner"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1268
|
#: documents/models.py:1274
|
||||||
msgid "grant view permissions to these users"
|
msgid "grant view permissions to these users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1275
|
#: documents/models.py:1281
|
||||||
msgid "grant view permissions to these groups"
|
msgid "grant view permissions to these groups"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1282
|
#: documents/models.py:1288
|
||||||
msgid "grant change permissions to these users"
|
msgid "grant change permissions to these users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1289
|
#: documents/models.py:1295
|
||||||
msgid "grant change permissions to these groups"
|
msgid "grant change permissions to these groups"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1296
|
#: documents/models.py:1302
|
||||||
msgid "assign these custom fields"
|
msgid "assign these custom fields"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1300
|
#: documents/models.py:1306
|
||||||
msgid "custom field values"
|
msgid "custom field values"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1304
|
#: documents/models.py:1310
|
||||||
msgid "Optional values to assign to the custom fields."
|
msgid "Optional values to assign to the custom fields."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1313
|
#: documents/models.py:1319
|
||||||
msgid "remove these tag(s)"
|
msgid "remove these tag(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1318
|
#: documents/models.py:1324
|
||||||
msgid "remove all tags"
|
msgid "remove all tags"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1325
|
#: documents/models.py:1331
|
||||||
msgid "remove these document type(s)"
|
msgid "remove these document type(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1330
|
#: documents/models.py:1336
|
||||||
msgid "remove all document types"
|
msgid "remove all document types"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1337
|
#: documents/models.py:1343
|
||||||
msgid "remove these correspondent(s)"
|
msgid "remove these correspondent(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1342
|
#: documents/models.py:1348
|
||||||
msgid "remove all correspondents"
|
msgid "remove all correspondents"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1349
|
#: documents/models.py:1355
|
||||||
msgid "remove these storage path(s)"
|
msgid "remove these storage path(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1354
|
#: documents/models.py:1360
|
||||||
msgid "remove all storage paths"
|
msgid "remove all storage paths"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1361
|
#: documents/models.py:1367
|
||||||
msgid "remove these owner(s)"
|
msgid "remove these owner(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1366
|
#: documents/models.py:1372
|
||||||
msgid "remove all owners"
|
msgid "remove all owners"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1373
|
#: documents/models.py:1379
|
||||||
msgid "remove view permissions for these users"
|
msgid "remove view permissions for these users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1380
|
#: documents/models.py:1386
|
||||||
msgid "remove view permissions for these groups"
|
msgid "remove view permissions for these groups"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1387
|
#: documents/models.py:1393
|
||||||
msgid "remove change permissions for these users"
|
msgid "remove change permissions for these users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1394
|
#: documents/models.py:1400
|
||||||
msgid "remove change permissions for these groups"
|
msgid "remove change permissions for these groups"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1399
|
#: documents/models.py:1405
|
||||||
msgid "remove all permissions"
|
msgid "remove all permissions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1406
|
#: documents/models.py:1412
|
||||||
msgid "remove these custom fields"
|
msgid "remove these custom fields"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1411
|
#: documents/models.py:1417
|
||||||
msgid "remove all custom fields"
|
msgid "remove all custom fields"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1420
|
#: documents/models.py:1426
|
||||||
msgid "email"
|
msgid "email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1429
|
#: documents/models.py:1435
|
||||||
msgid "webhook"
|
msgid "webhook"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1433
|
#: documents/models.py:1439
|
||||||
msgid "workflow action"
|
msgid "workflow action"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1434
|
#: documents/models.py:1440
|
||||||
msgid "workflow actions"
|
msgid "workflow actions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1443 paperless_mail/models.py:145
|
#: documents/models.py:1449 paperless_mail/models.py:145
|
||||||
msgid "order"
|
msgid "order"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1449
|
#: documents/models.py:1455
|
||||||
msgid "triggers"
|
msgid "triggers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1456
|
#: documents/models.py:1462
|
||||||
msgid "actions"
|
msgid "actions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1459 paperless_mail/models.py:154
|
#: documents/models.py:1465 paperless_mail/models.py:154
|
||||||
msgid "enabled"
|
msgid "enabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1470
|
#: documents/models.py:1476
|
||||||
msgid "workflow"
|
msgid "workflow"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1474
|
#: documents/models.py:1480
|
||||||
msgid "workflow trigger type"
|
msgid "workflow trigger type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1488
|
#: documents/models.py:1494
|
||||||
msgid "date run"
|
msgid "date run"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1494
|
#: documents/models.py:1500
|
||||||
msgid "workflow run"
|
msgid "workflow run"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/models.py:1495
|
#: documents/models.py:1501
|
||||||
msgid "workflow runs"
|
msgid "workflow runs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user