mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-26 18:14:37 -05:00
Compare commits
No commits in common. "485dad01b70823f2e562ee0da14274785c53d2ea" and "89e5c08a1fe4ca0b7641ae8fbd5554502199ae40" have entirely different histories.
485dad01b7
...
89e5c08a1f
@ -3,7 +3,7 @@
|
|||||||
"dockerComposeFile": "docker-compose.devcontainer.sqlite-tika.yml",
|
"dockerComposeFile": "docker-compose.devcontainer.sqlite-tika.yml",
|
||||||
"service": "paperless-development",
|
"service": "paperless-development",
|
||||||
"workspaceFolder": "/usr/src/paperless/paperless-ngx",
|
"workspaceFolder": "/usr/src/paperless/paperless-ngx",
|
||||||
"postCreateCommand": "/bin/bash -c 'uv sync --group dev && uv run pre-commit install'",
|
"postCreateCommand": "/bin/bash -c uv sync --dev && uv run pre-commit install",
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"extensions": [
|
"extensions": [
|
||||||
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -271,6 +271,7 @@ jobs:
|
|||||||
name: playwright-report-${{ matrix.shard-index }}
|
name: playwright-report-${{ matrix.shard-index }}
|
||||||
path: src-ui/playwright-report
|
path: src-ui/playwright-report
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
if-no-files-found: error
|
||||||
-
|
-
|
||||||
name: Upload frontend test results
|
name: Upload frontend test results
|
||||||
if: always()
|
if: always()
|
||||||
@ -279,6 +280,7 @@ jobs:
|
|||||||
name: junit-report-${{ matrix.shard-index }}
|
name: junit-report-${{ matrix.shard-index }}
|
||||||
path: src-ui/junit-report-${{ matrix.shard-index }}.xml
|
path: src-ui/junit-report-${{ matrix.shard-index }}.xml
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
tests-coverage-upload:
|
tests-coverage-upload:
|
||||||
name: "Upload to Codecov"
|
name: "Upload to Codecov"
|
||||||
|
@ -75,7 +75,7 @@ first-time setup.
|
|||||||
4. Install the Python dependencies:
|
4. Install the Python dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ uv sync --group dev
|
$ uv sync --dev
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Install pre-commit hooks:
|
5. Install pre-commit hooks:
|
||||||
|
@ -209,18 +209,37 @@ lint.per-file-ignores."src/documents/management/commands/document_consumer.py" =
|
|||||||
lint.per-file-ignores."src/documents/management/commands/document_exporter.py" = [
|
lint.per-file-ignores."src/documents/management/commands/document_exporter.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/documents/migrations/0012_auto_20160305_0040.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/documents/migrations/0014_document_checksum.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/documents/migrations/1003_mime_types.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
lint.per-file-ignores."src/documents/migrations/1012_fix_archive_files.py" = [
|
lint.per-file-ignores."src/documents/migrations/1012_fix_archive_files.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
lint.per-file-ignores."src/documents/models.py" = [
|
lint.per-file-ignores."src/documents/models.py" = [
|
||||||
|
"PTH",
|
||||||
"SIM115",
|
"SIM115",
|
||||||
]
|
] # TODO PTH Enable & remove
|
||||||
lint.per-file-ignores."src/documents/parsers.py" = [
|
lint.per-file-ignores."src/documents/parsers.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
lint.per-file-ignores."src/documents/signals/handlers.py" = [
|
lint.per-file-ignores."src/documents/signals/handlers.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/documents/tasks.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/documents/tests/test_api_app_config.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/documents/tests/test_classifier.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
lint.per-file-ignores."src/documents/tests/test_consumer.py" = [
|
lint.per-file-ignores."src/documents/tests/test_consumer.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
@ -236,6 +255,9 @@ lint.per-file-ignores."src/documents/tests/test_management_consumer.py" = [
|
|||||||
lint.per-file-ignores."src/documents/tests/test_management_exporter.py" = [
|
lint.per-file-ignores."src/documents/tests/test_management_exporter.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/documents/tests/test_management_thumbnails.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
lint.per-file-ignores."src/documents/tests/test_migration_archive_files.py" = [
|
lint.per-file-ignores."src/documents/tests/test_migration_archive_files.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
@ -248,6 +270,12 @@ lint.per-file-ignores."src/documents/tests/test_migration_mime_type.py" = [
|
|||||||
lint.per-file-ignores."src/documents/tests/test_sanity_check.py" = [
|
lint.per-file-ignores."src/documents/tests/test_sanity_check.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/documents/tests/test_tasks.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/documents/tests/test_views.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
lint.per-file-ignores."src/documents/views.py" = [
|
lint.per-file-ignores."src/documents/views.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
@ -257,16 +285,34 @@ lint.per-file-ignores."src/paperless/checks.py" = [
|
|||||||
lint.per-file-ignores."src/paperless/settings.py" = [
|
lint.per-file-ignores."src/paperless/settings.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/paperless/tests/test_checks.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/paperless/urls.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
lint.per-file-ignores."src/paperless/views.py" = [
|
lint.per-file-ignores."src/paperless/views.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
lint.per-file-ignores."src/paperless_mail/mail.py" = [
|
lint.per-file-ignores."src/paperless_mail/mail.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
] # TODO Enable & remove
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/paperless_mail/preprocessor.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/paperless_tesseract/parsers.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
lint.per-file-ignores."src/paperless_tesseract/tests/test_parser.py" = [
|
lint.per-file-ignores."src/paperless_tesseract/tests/test_parser.py" = [
|
||||||
"PTH",
|
"PTH",
|
||||||
"RUF001",
|
"RUF001",
|
||||||
] # TODO PTH Enable & remove
|
] # TODO PTH Enable & remove
|
||||||
|
lint.per-file-ignores."src/paperless_tika/tests/test_live_tika.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
|
lint.per-file-ignores."src/paperless_tika/tests/test_tika_parser.py" = [
|
||||||
|
"PTH",
|
||||||
|
] # TODO Enable & remove
|
||||||
lint.isort.force-single-line = true
|
lint.isort.force-single-line = true
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
|
@ -83,17 +83,10 @@ test('date filtering', async ({ page }) => {
|
|||||||
await page.routeFromHAR(REQUESTS_HAR3, { notFound: 'fallback' })
|
await page.routeFromHAR(REQUESTS_HAR3, { notFound: 'fallback' })
|
||||||
await page.goto('/documents')
|
await page.goto('/documents')
|
||||||
await page.getByRole('button', { name: 'Dates' }).click()
|
await page.getByRole('button', { name: 'Dates' }).click()
|
||||||
await page.locator('.ng-arrow-wrapper').first().click()
|
await page.getByRole('menuitem', { name: 'Within 3 months' }).first().click()
|
||||||
await page.getByRole('option', { name: 'Within 3 months' }).click()
|
|
||||||
await expect(page.locator('pngx-document-list')).toHaveText(/one document/i)
|
await expect(page.locator('pngx-document-list')).toHaveText(/one document/i)
|
||||||
await page
|
await page.getByRole('menuitem', { name: 'Within 3 months' }).first().click()
|
||||||
.getByRole('menuitem', { name: 'Relative dates' })
|
await page.getByLabel('Datesselected').getByRole('button').first().click()
|
||||||
.locator('span')
|
|
||||||
.first()
|
|
||||||
.click()
|
|
||||||
await page.getByRole('option', { name: 'Within 3 months' }).click()
|
|
||||||
await page.getByLabel('Dates selected').locator('button').first().click()
|
|
||||||
await page.getByLabel('Dates selected').locator('button').first().click()
|
|
||||||
await page.getByRole('combobox', { name: 'Select month' }).selectOption('12')
|
await page.getByRole('combobox', { name: 'Select month' }).selectOption('12')
|
||||||
await page.getByRole('combobox', { name: 'Select year' }).selectOption('2022')
|
await page.getByRole('combobox', { name: 'Select year' }).selectOption('2022')
|
||||||
await page.getByText('11', { exact: true }).click()
|
await page.getByText('11', { exact: true }).click()
|
||||||
|
@ -1120,7 +1120,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">193</context>
|
<context context-type="linenumber">173</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8508424367627989968" datatype="html">
|
<trans-unit id="8508424367627989968" datatype="html">
|
||||||
@ -1198,7 +1198,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||||
<context context-type="linenumber">106</context>
|
<context context-type="linenumber">105</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
|
||||||
@ -1284,19 +1284,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">201</context>
|
<context context-type="linenumber">200</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">220</context>
|
<context context-type="linenumber">219</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">287</context>
|
<context context-type="linenumber">286</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">306</context>
|
<context context-type="linenumber">305</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>
|
||||||
@ -1319,19 +1319,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">208</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">227</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">294</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">313</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>
|
||||||
@ -1357,11 +1357,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">234</context>
|
<context context-type="linenumber">233</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">320</context>
|
<context context-type="linenumber">319</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>
|
||||||
@ -1732,11 +1732,11 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">8</context>
|
<context context-type="linenumber">11</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">88</context>
|
<context context-type="linenumber">87</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>
|
||||||
@ -3246,25 +3246,18 @@
|
|||||||
<context context-type="linenumber">24</context>
|
<context context-type="linenumber">24</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2710430925353472741" datatype="html">
|
|
||||||
<source>Try to include archive version in merge for non-PDF files</source>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.html</context>
|
|
||||||
<context context-type="linenumber">32</context>
|
|
||||||
</context-group>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="5612366187076076264" datatype="html">
|
<trans-unit id="5612366187076076264" datatype="html">
|
||||||
<source>Delete original documents after successful merge</source>
|
<source>Delete original documents after successful merge</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.html</context>
|
||||||
<context context-type="linenumber">36</context>
|
<context context-type="linenumber">32</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5138283234724909648" datatype="html">
|
<trans-unit id="5138283234724909648" datatype="html">
|
||||||
<source>Note that only PDFs will be included.</source>
|
<source>Note that only PDFs will be included.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.html</context>
|
||||||
<context context-type="linenumber">39</context>
|
<context context-type="linenumber">34</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8157388568390631653" datatype="html">
|
<trans-unit id="8157388568390631653" datatype="html">
|
||||||
@ -3351,7 +3344,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">52</context>
|
<context context-type="linenumber">50</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
@ -3359,16 +3352,12 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">128</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/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">152</context>
|
<context context-type="linenumber">152</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
|
||||||
<context context-type="linenumber">103</context>
|
|
||||||
</context-group>
|
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context>
|
||||||
<context context-type="linenumber">21</context>
|
<context context-type="linenumber">21</context>
|
||||||
@ -3382,7 +3371,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">53</context>
|
<context context-type="linenumber">51</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
@ -3390,7 +3379,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">129</context>
|
<context context-type="linenumber">127</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
@ -3513,8 +3502,8 @@
|
|||||||
<context context-type="linenumber">168</context>
|
<context context-type="linenumber">168</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6312759212949884929" datatype="html">
|
<trans-unit id="6052766076365105714" datatype="html">
|
||||||
<source>Relative dates</source>
|
<source>now</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">25</context>
|
<context context-type="linenumber">25</context>
|
||||||
@ -3524,26 +3513,15 @@
|
|||||||
<context context-type="linenumber">101</context>
|
<context context-type="linenumber">101</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6052766076365105714" datatype="html">
|
|
||||||
<source>now</source>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
|
||||||
<context context-type="linenumber">29</context>
|
|
||||||
</context-group>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
|
||||||
<context context-type="linenumber">105</context>
|
|
||||||
</context-group>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="5203279511751768967" datatype="html">
|
<trans-unit id="5203279511751768967" datatype="html">
|
||||||
<source>From</source>
|
<source>From</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">44</context>
|
<context context-type="linenumber">42</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">120</context>
|
<context context-type="linenumber">118</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1640609344969975994" datatype="html">
|
<trans-unit id="1640609344969975994" datatype="html">
|
||||||
@ -3561,11 +3539,11 @@
|
|||||||
<source>Added</source>
|
<source>Added</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
|
||||||
<context context-type="linenumber">84</context>
|
<context context-type="linenumber">86</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">84</context>
|
<context context-type="linenumber">83</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>
|
||||||
@ -3584,53 +3562,28 @@
|
|||||||
<source>Within 1 week</source>
|
<source>Within 1 week</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
||||||
<context context-type="linenumber">73</context>
|
<context context-type="linenumber">67</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="123064370501514576" datatype="html">
|
<trans-unit id="123064370501514576" datatype="html">
|
||||||
<source>Within 1 month</source>
|
<source>Within 1 month</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
||||||
<context context-type="linenumber">78</context>
|
<context context-type="linenumber">72</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1027161426440526546" datatype="html">
|
<trans-unit id="1027161426440526546" datatype="html">
|
||||||
<source>Within 3 months</source>
|
<source>Within 3 months</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
||||||
<context context-type="linenumber">83</context>
|
<context context-type="linenumber">77</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="226779700214642230" datatype="html">
|
<trans-unit id="226779700214642230" datatype="html">
|
||||||
<source>Within 1 year</source>
|
<source>Within 1 year</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
||||||
<context context-type="linenumber">88</context>
|
<context context-type="linenumber">82</context>
|
||||||
</context-group>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="8462417627724236320" datatype="html">
|
|
||||||
<source>This year</source>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
|
||||||
<context context-type="linenumber">93</context>
|
|
||||||
</context-group>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="842657237693374355" datatype="html">
|
|
||||||
<source>This month</source>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
|
||||||
<context context-type="linenumber">98</context>
|
|
||||||
</context-group>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="4498682414491138092" datatype="html">
|
|
||||||
<source>Yesterday</source>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
|
|
||||||
<context context-type="linenumber">108</context>
|
|
||||||
</context-group>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
|
||||||
<context context-type="linenumber">29</context>
|
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8743659855412792665" datatype="html">
|
<trans-unit id="8743659855412792665" datatype="html">
|
||||||
@ -4443,7 +4396,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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">130</context>
|
<context context-type="linenumber">129</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.html</context>
|
<context context-type="sourcefile">src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.html</context>
|
||||||
@ -4834,227 +4787,227 @@
|
|||||||
<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">195</context>
|
<context context-type="linenumber">194</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">197</context>
|
<context context-type="linenumber">196</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">216</context>
|
<context context-type="linenumber">215</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">243</context>
|
<context context-type="linenumber">242</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">244</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">250</context>
|
<context context-type="linenumber">249</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">256</context>
|
<context context-type="linenumber">255</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">262</context>
|
<context context-type="linenumber">261</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">268</context>
|
<context context-type="linenumber">267</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">275</context>
|
<context context-type="linenumber">274</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">281</context>
|
<context context-type="linenumber">280</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">249</context>
|
<context context-type="linenumber">248</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">255</context>
|
<context context-type="linenumber">254</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">261</context>
|
<context context-type="linenumber">260</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">267</context>
|
<context context-type="linenumber">266</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">274</context>
|
<context context-type="linenumber">273</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">280</context>
|
<context context-type="linenumber">279</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">283</context>
|
<context context-type="linenumber">282</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">302</context>
|
<context context-type="linenumber">301</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">330</context>
|
<context context-type="linenumber">329</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">331</context>
|
<context context-type="linenumber">330</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">332</context>
|
<context context-type="linenumber">331</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">333</context>
|
<context context-type="linenumber">332</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">341</context>
|
<context context-type="linenumber">340</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">343</context>
|
<context context-type="linenumber">342</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">344</context>
|
<context context-type="linenumber">343</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">347</context>
|
<context context-type="linenumber">346</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">349</context>
|
<context context-type="linenumber">348</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">351</context>
|
<context context-type="linenumber">350</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">352</context>
|
<context context-type="linenumber">351</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4626030417479279989" datatype="html">
|
<trans-unit id="4626030417479279989" datatype="html">
|
||||||
<source>Consume Folder</source>
|
<source>Consume Folder</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">65</context>
|
<context context-type="linenumber">64</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="526966086395145275" datatype="html">
|
<trans-unit id="526966086395145275" datatype="html">
|
||||||
<source>API Upload</source>
|
<source>API Upload</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">69</context>
|
<context context-type="linenumber">68</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7502272564743467653" datatype="html">
|
<trans-unit id="7502272564743467653" datatype="html">
|
||||||
<source>Mail Fetch</source>
|
<source>Mail Fetch</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">73</context>
|
<context context-type="linenumber">72</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="235571817610183244" datatype="html">
|
<trans-unit id="235571817610183244" datatype="html">
|
||||||
<source>Web UI</source>
|
<source>Web UI</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">77</context>
|
<context context-type="linenumber">76</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3553216189604488439" datatype="html">
|
<trans-unit id="3553216189604488439" datatype="html">
|
||||||
<source>Modified</source>
|
<source>Modified</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">92</context>
|
<context context-type="linenumber">91</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/data/document.ts</context>
|
<context context-type="sourcefile">src/app/data/document.ts</context>
|
||||||
@ -5065,70 +5018,70 @@
|
|||||||
<source>Custom Field</source>
|
<source>Custom Field</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">96</context>
|
<context context-type="linenumber">95</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8696908693776094667" datatype="html">
|
<trans-unit id="8696908693776094667" datatype="html">
|
||||||
<source>Consumption Started</source>
|
<source>Consumption Started</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">103</context>
|
<context context-type="linenumber">102</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7858311467093621703" datatype="html">
|
<trans-unit id="7858311467093621703" datatype="html">
|
||||||
<source>Document Added</source>
|
<source>Document Added</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">107</context>
|
<context context-type="linenumber">106</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7955486237346046731" datatype="html">
|
<trans-unit id="7955486237346046731" datatype="html">
|
||||||
<source>Document Updated</source>
|
<source>Document Updated</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">111</context>
|
<context context-type="linenumber">110</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="9172233176401579786" datatype="html">
|
<trans-unit id="9172233176401579786" datatype="html">
|
||||||
<source>Scheduled</source>
|
<source>Scheduled</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">115</context>
|
<context context-type="linenumber">114</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5502398334173581061" datatype="html">
|
<trans-unit id="5502398334173581061" datatype="html">
|
||||||
<source>Assignment</source>
|
<source>Assignment</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">122</context>
|
<context context-type="linenumber">121</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6234812824772766804" datatype="html">
|
<trans-unit id="6234812824772766804" datatype="html">
|
||||||
<source>Removal</source>
|
<source>Removal</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">126</context>
|
<context context-type="linenumber">125</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4206419737792796794" datatype="html">
|
<trans-unit id="4206419737792796794" datatype="html">
|
||||||
<source>Webhook</source>
|
<source>Webhook</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">134</context>
|
<context context-type="linenumber">133</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3138206142174978019" datatype="html">
|
<trans-unit id="3138206142174978019" datatype="html">
|
||||||
<source>Create new workflow</source>
|
<source>Create new workflow</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">231</context>
|
<context context-type="linenumber">229</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5996779210524133604" datatype="html">
|
<trans-unit id="5996779210524133604" datatype="html">
|
||||||
<source>Edit workflow</source>
|
<source>Edit workflow</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.ts</context>
|
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||||
<context context-type="linenumber">235</context>
|
<context context-type="linenumber">233</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7376342558017986274" datatype="html">
|
<trans-unit id="7376342558017986274" datatype="html">
|
||||||
@ -6555,7 +6508,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">180</context>
|
<context context-type="linenumber">160</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/data/document.ts</context>
|
<context context-type="sourcefile">src/app/data/document.ts</context>
|
||||||
@ -7183,7 +7136,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">188</context>
|
<context context-type="linenumber">168</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6475890479659129881" datatype="html">
|
<trans-unit id="6475890479659129881" datatype="html">
|
||||||
@ -7478,21 +7431,21 @@
|
|||||||
<source>Merged document will be queued for consumption.</source>
|
<source>Merged document will be queued for consumption.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||||
<context context-type="linenumber">866</context>
|
<context context-type="linenumber">863</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="476913782630693351" datatype="html">
|
<trans-unit id="476913782630693351" datatype="html">
|
||||||
<source>Custom fields updated.</source>
|
<source>Custom fields updated.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||||
<context context-type="linenumber">888</context>
|
<context context-type="linenumber">885</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3873496751167944011" datatype="html">
|
<trans-unit id="3873496751167944011" datatype="html">
|
||||||
<source>Error updating custom fields.</source>
|
<source>Error updating custom fields.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||||
<context context-type="linenumber">897</context>
|
<context context-type="linenumber">894</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6307402210351946694" datatype="html">
|
<trans-unit id="6307402210351946694" datatype="html">
|
||||||
@ -7760,7 +7713,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
|
||||||
<context context-type="linenumber">112</context>
|
<context context-type="linenumber">111</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1559883523769732271" datatype="html">
|
<trans-unit id="1559883523769732271" datatype="html">
|
||||||
@ -7785,7 +7738,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">185</context>
|
<context context-type="linenumber">165</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/data/document.ts</context>
|
<context context-type="sourcefile">src/app/data/document.ts</context>
|
||||||
@ -7981,154 +7934,154 @@
|
|||||||
<source>Title & content</source>
|
<source>Title & content</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">183</context>
|
<context context-type="linenumber">163</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7408932238599462499" datatype="html">
|
<trans-unit id="7408932238599462499" datatype="html">
|
||||||
<source>File type</source>
|
<source>File type</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">190</context>
|
<context context-type="linenumber">170</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2649431021108393503" datatype="html">
|
<trans-unit id="2649431021108393503" datatype="html">
|
||||||
<source>More like</source>
|
<source>More like</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">199</context>
|
<context context-type="linenumber">179</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3697582909018473071" datatype="html">
|
<trans-unit id="3697582909018473071" datatype="html">
|
||||||
<source>equals</source>
|
<source>equals</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">205</context>
|
<context context-type="linenumber">185</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5325481293405718739" datatype="html">
|
<trans-unit id="5325481293405718739" datatype="html">
|
||||||
<source>is empty</source>
|
<source>is empty</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">209</context>
|
<context context-type="linenumber">189</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6166785695326182482" datatype="html">
|
<trans-unit id="6166785695326182482" datatype="html">
|
||||||
<source>is not empty</source>
|
<source>is not empty</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">213</context>
|
<context context-type="linenumber">193</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4686622206659266699" datatype="html">
|
<trans-unit id="4686622206659266699" datatype="html">
|
||||||
<source>greater than</source>
|
<source>greater than</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">217</context>
|
<context context-type="linenumber">197</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8014012170270529279" datatype="html">
|
<trans-unit id="8014012170270529279" datatype="html">
|
||||||
<source>less than</source>
|
<source>less than</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">221</context>
|
<context context-type="linenumber">201</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5195932016807797291" datatype="html">
|
<trans-unit id="5195932016807797291" datatype="html">
|
||||||
<source>Correspondent: <x id="PH" equiv-text="this.correspondents.find((c) => c.id == +rule.value)?.name"/></source>
|
<source>Correspondent: <x id="PH" equiv-text="this.correspondents.find((c) => c.id == +rule.value)?.name"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">253,255</context>
|
<context context-type="linenumber">233,235</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8170755470576301659" datatype="html">
|
<trans-unit id="8170755470576301659" datatype="html">
|
||||||
<source>Without correspondent</source>
|
<source>Without correspondent</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">257</context>
|
<context context-type="linenumber">237</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="317796810569008208" datatype="html">
|
<trans-unit id="317796810569008208" datatype="html">
|
||||||
<source>Document type: <x id="PH" equiv-text="this.documentTypes.find((dt) => dt.id == +rule.value)?.name"/></source>
|
<source>Document type: <x id="PH" equiv-text="this.documentTypes.find((dt) => dt.id == +rule.value)?.name"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">263,265</context>
|
<context context-type="linenumber">243,245</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4362173610367509215" datatype="html">
|
<trans-unit id="4362173610367509215" datatype="html">
|
||||||
<source>Without document type</source>
|
<source>Without document type</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">267</context>
|
<context context-type="linenumber">247</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="232202047340644471" datatype="html">
|
<trans-unit id="232202047340644471" datatype="html">
|
||||||
<source>Storage path: <x id="PH" equiv-text="this.storagePaths.find((sp) => sp.id == +rule.value)?.name"/></source>
|
<source>Storage path: <x id="PH" equiv-text="this.storagePaths.find((sp) => sp.id == +rule.value)?.name"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">273,275</context>
|
<context context-type="linenumber">253,255</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1562820715074533164" datatype="html">
|
<trans-unit id="1562820715074533164" datatype="html">
|
||||||
<source>Without storage path</source>
|
<source>Without storage path</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">277</context>
|
<context context-type="linenumber">257</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8180755793012580465" datatype="html">
|
<trans-unit id="8180755793012580465" datatype="html">
|
||||||
<source>Tag: <x id="PH" equiv-text="this.tags.find((t) => t.id == +rule.value)?.name"/></source>
|
<source>Tag: <x id="PH" equiv-text="this.tags.find((t) => t.id == +rule.value)?.name"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">281,283</context>
|
<context context-type="linenumber">261,263</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6494566478302448576" datatype="html">
|
<trans-unit id="6494566478302448576" datatype="html">
|
||||||
<source>Without any tag</source>
|
<source>Without any tag</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">287</context>
|
<context context-type="linenumber">267</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8644099678903817943" datatype="html">
|
<trans-unit id="8644099678903817943" datatype="html">
|
||||||
<source>Custom fields query</source>
|
<source>Custom fields query</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">291</context>
|
<context context-type="linenumber">271</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6523384805359286307" datatype="html">
|
<trans-unit id="6523384805359286307" datatype="html">
|
||||||
<source>Title: <x id="PH" equiv-text="rule.value"/></source>
|
<source>Title: <x id="PH" equiv-text="rule.value"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">294</context>
|
<context context-type="linenumber">274</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1872523635812236432" datatype="html">
|
<trans-unit id="1872523635812236432" datatype="html">
|
||||||
<source>ASN: <x id="PH" equiv-text="rule.value"/></source>
|
<source>ASN: <x id="PH" equiv-text="rule.value"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">297</context>
|
<context context-type="linenumber">277</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="102674688969746976" datatype="html">
|
<trans-unit id="102674688969746976" datatype="html">
|
||||||
<source>Owner: <x id="PH" equiv-text="rule.value"/></source>
|
<source>Owner: <x id="PH" equiv-text="rule.value"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">300</context>
|
<context context-type="linenumber">280</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3550877650686009106" datatype="html">
|
<trans-unit id="3550877650686009106" datatype="html">
|
||||||
<source>Owner not in: <x id="PH" equiv-text="rule.value"/></source>
|
<source>Owner not in: <x id="PH" equiv-text="rule.value"/></source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">303</context>
|
<context context-type="linenumber">283</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1082034558646673343" datatype="html">
|
<trans-unit id="1082034558646673343" datatype="html">
|
||||||
<source>Without an owner</source>
|
<source>Without an owner</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||||
<context context-type="linenumber">306</context>
|
<context context-type="linenumber">286</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7210076240260527720" datatype="html">
|
<trans-unit id="7210076240260527720" datatype="html">
|
||||||
@ -9462,6 +9415,13 @@
|
|||||||
<context context-type="linenumber">25</context>
|
<context context-type="linenumber">25</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="4498682414491138092" datatype="html">
|
||||||
|
<source>Yesterday</source>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
|
||||||
|
<context context-type="linenumber">29</context>
|
||||||
|
</context-group>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="5601594741748068208" datatype="html">
|
<trans-unit id="5601594741748068208" datatype="html">
|
||||||
<source>%s days ago</source>
|
<source>%s days ago</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
|
@ -28,16 +28,10 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check form-switch mt-4">
|
<div class="form-check form-switch mt-4">
|
||||||
<input class="form-check-input" type="checkbox" role="switch" id="archiveFallbackSwitch" [(ngModel)]="archiveFallback">
|
|
||||||
<label class="form-check-label" for="archiveFallbackSwitch" i18n>Try to include archive version in merge for non-PDF files</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-switch mt-2">
|
|
||||||
<input class="form-check-input" type="checkbox" role="switch" id="deleteOriginalsSwitch" [(ngModel)]="deleteOriginals" [disabled]="!userOwnsAllDocuments">
|
<input class="form-check-input" type="checkbox" role="switch" id="deleteOriginalsSwitch" [(ngModel)]="deleteOriginals" [disabled]="!userOwnsAllDocuments">
|
||||||
<label class="form-check-label" for="deleteOriginalsSwitch" i18n>Delete original documents after successful merge</label>
|
<label class="form-check-label" for="deleteOriginalsSwitch" i18n>Delete original documents after successful merge</label>
|
||||||
</div>
|
</div>
|
||||||
@if (!archiveFallback) {
|
|
||||||
<p class="small text-muted fst-italic mt-4" i18n>Note that only PDFs will be included.</p>
|
<p class="small text-muted fst-italic mt-4" i18n>Note that only PDFs will be included.</p>
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn" [class]="cancelBtnClass" (click)="cancel()" [disabled]="!buttonsEnabled">
|
<button type="button" class="btn" [class]="cancelBtnClass" (click)="cancel()" [disabled]="!buttonsEnabled">
|
||||||
|
@ -29,7 +29,6 @@ export class MergeConfirmDialogComponent
|
|||||||
implements OnInit
|
implements OnInit
|
||||||
{
|
{
|
||||||
public documentIDs: number[] = []
|
public documentIDs: number[] = []
|
||||||
public archiveFallback: boolean = false
|
|
||||||
public deleteOriginals: boolean = false
|
public deleteOriginals: boolean = false
|
||||||
private _documents: Document[] = []
|
private _documents: Document[] = []
|
||||||
get documents(): Document[] {
|
get documents(): Document[] {
|
||||||
|
@ -34,7 +34,7 @@ import {
|
|||||||
CustomFieldQueryElement,
|
CustomFieldQueryElement,
|
||||||
CustomFieldQueryExpression,
|
CustomFieldQueryExpression,
|
||||||
} from 'src/app/utils/custom-field-query-element'
|
} from 'src/app/utils/custom-field-query-element'
|
||||||
import { pngxPopperOptions } from 'src/app/utils/popper-options'
|
import { popperOptionsReenablePreventOverflow } from 'src/app/utils/popper-options'
|
||||||
import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
|
import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
|
||||||
import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
|
import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
|
||||||
import { DocumentLinkComponent } from '../input/document-link/document-link.component'
|
import { DocumentLinkComponent } from '../input/document-link/document-link.component'
|
||||||
@ -183,7 +183,7 @@ export class CustomFieldsQueryDropdownComponent extends LoadingComponentWithPerm
|
|||||||
public CustomFieldDataType = CustomFieldDataType
|
public CustomFieldDataType = CustomFieldDataType
|
||||||
public CUSTOM_FIELD_QUERY_MAX_DEPTH = CUSTOM_FIELD_QUERY_MAX_DEPTH
|
public CUSTOM_FIELD_QUERY_MAX_DEPTH = CUSTOM_FIELD_QUERY_MAX_DEPTH
|
||||||
public CUSTOM_FIELD_QUERY_MAX_ATOMS = CUSTOM_FIELD_QUERY_MAX_ATOMS
|
public CUSTOM_FIELD_QUERY_MAX_ATOMS = CUSTOM_FIELD_QUERY_MAX_ATOMS
|
||||||
public popperOptions = pngxPopperOptions
|
public popperOptions = popperOptionsReenablePreventOverflow
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
title: string
|
title: string
|
||||||
|
@ -1,37 +1,35 @@
|
|||||||
<div class="btn-group w-100" ngbDropdown role="group" [popperOptions]="popperOptions" [placement]="placement">
|
<div class="btn-group w-100" ngbDropdown role="group" [popperOptions]="popperOptions">
|
||||||
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="createdDateTo || createdDateFrom ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
|
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="createdDateTo || createdDateFrom ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
|
||||||
<i-bs width="1em" height="1em" name="calendar-event-fill"></i-bs>
|
<i-bs width="1em" height="1em" name="calendar-event-fill"></i-bs>
|
||||||
<div class="d-none d-sm-inline"> {{title}}</div>
|
<div class="d-none d-sm-inline"> {{title}}</div>
|
||||||
<pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge><span class="visually-hidden">selected</span>
|
<pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge><span class="visually-hidden">selected</span>
|
||||||
</button>
|
</button>
|
||||||
<div class="dropdown-menu date-dropdown shadow p-2" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
|
<div class="dropdown-menu date-dropdown shadow p-2" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
|
||||||
<h6 class="dropdown-header border-bottom" i18n>Created</h6>
|
<div class="row d-flex">
|
||||||
|
<div class="col border-end">
|
||||||
<div class="list-group list-group-flush">
|
<div class="list-group list-group-flush">
|
||||||
<div class="list-group-item d-flex p-2 select-item" role="menuitem">
|
<h6 class="dropdown-header border-bottom" i18n>Created</h6>
|
||||||
|
@for (rd of relativeDates; track rd) {
|
||||||
|
<button class="list-group-item small list-goup list-group-item-action d-flex p-2" role="menuitem" (click)="setCreatedRelativeDate(rd.id)">
|
||||||
<div class="selected-icon">
|
<div class="selected-icon">
|
||||||
@if (createdRelativeDate) {
|
@if (createdRelativeDate === rd.id) {
|
||||||
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedRelativeDate()">
|
<i-bs width="1em" height="1em" name="check"></i-bs>
|
||||||
<i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
|
|
||||||
<i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
|
|
||||||
</a>
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group input-group-sm small ps-1 pe-2">
|
<div class="d-flex justify-content-between w-100 align-items-center ps-2">
|
||||||
<ng-select class="w-100" name="createdRelativeDate"
|
<div class="pe-4">
|
||||||
[items]="relativeDates" [(ngModel)]="createdRelativeDate"
|
{{rd.name}}
|
||||||
bindValue="id"
|
</div>
|
||||||
bindLabel="name"
|
<div class="text-muted small pe-2">
|
||||||
clearable="false"
|
<span class="small">
|
||||||
placeholder="Relative dates"
|
{{ rd.date | customDate:'mediumDate' }} – <ng-container i18n>now</ng-container>
|
||||||
i18n-placeholder
|
</span>
|
||||||
(change)="onSetCreatedRelativeDate($event)">
|
|
||||||
<ng-template ng-option-tmp let-item="item">
|
|
||||||
<div class="d-flex">{{ item.name }}<span class="ms-auto text-muted small">{{ item.date | customDate:'mediumDate' }} – <ng-container i18n>now</ng-container></span></div>
|
|
||||||
</ng-template>
|
|
||||||
</ng-select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
<div class="list-group-item d-flex p-2" role="menuitem">
|
<div class="list-group-item d-flex p-2" role="menuitem">
|
||||||
|
|
||||||
<div class="selected-icon">
|
<div class="selected-icon">
|
||||||
@if (createdDateFrom) {
|
@if (createdDateFrom) {
|
||||||
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedFrom()">
|
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedFrom()">
|
||||||
@ -54,8 +52,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group-item d-flex p-2" role="menuitem">
|
<div class="list-group-item d-flex p-2" role="menuitem">
|
||||||
|
|
||||||
<div class="selected-icon">
|
<div class="selected-icon">
|
||||||
@if (createdDateTo) {
|
@if (createdDateTo) {
|
||||||
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedTo()">
|
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedTo()">
|
||||||
@ -81,33 +81,31 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
<h6 class="dropdown-header border-bottom" i18n>Added</h6>
|
<h6 class="dropdown-header border-bottom" i18n>Added</h6>
|
||||||
<div class="list-group list-group-flush">
|
<div class="list-group list-group-flush">
|
||||||
<div class="list-group-item d-flex p-2 select-item" role="menuitem">
|
@for (rd of relativeDates; track rd) {
|
||||||
|
<button class="list-group-item small list-goup list-group-item-action d-flex p-2" role="menuitem" (click)="setAddedRelativeDate(rd.id)">
|
||||||
<div class="selected-icon">
|
<div class="selected-icon">
|
||||||
@if (addedRelativeDate) {
|
@if (addedRelativeDate === rd.id) {
|
||||||
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedRelativeDate()">
|
<i-bs width="1em" height="1em" name="check"></i-bs>
|
||||||
<i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
|
|
||||||
<i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
|
|
||||||
</a>
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group input-group-sm small ps-1 pe-2">
|
<div class="d-flex justify-content-between w-100 align-items-center ps-2">
|
||||||
<ng-select class="w-100" name="addedRelativeDate"
|
<div class="pe-4">
|
||||||
[items]="relativeDates" [(ngModel)]="addedRelativeDate"
|
{{rd.name}}
|
||||||
bindValue="id"
|
</div>
|
||||||
bindLabel="name"
|
<div class="text-muted small pe-2">
|
||||||
clearable="false"
|
<span class="small">
|
||||||
placeholder="Relative dates"
|
{{ rd.date | customDate:'mediumDate' }} – <ng-container i18n>now</ng-container>
|
||||||
i18n-placeholder
|
</span>
|
||||||
(change)="onSetAddedRelativeDate($event)">
|
|
||||||
<ng-template ng-option-tmp let-item="item">
|
|
||||||
<div class="d-flex">{{ item.name }}<span class="ms-auto text-muted small">{{ item.date | customDate:'mediumDate' }} – <ng-container i18n>now</ng-container></span></div>
|
|
||||||
</ng-template>
|
|
||||||
</ng-select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
<div class="list-group-item d-flex p-2" role="menuitem">
|
<div class="list-group-item d-flex p-2" role="menuitem">
|
||||||
|
|
||||||
<div class="selected-icon">
|
<div class="selected-icon">
|
||||||
@if (addedDateFrom) {
|
@if (addedDateFrom) {
|
||||||
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedFrom()">
|
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedFrom()">
|
||||||
@ -130,8 +128,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group-item d-flex p-2" role="menuitem">
|
<div class="list-group-item d-flex p-2" role="menuitem">
|
||||||
|
|
||||||
<div class="selected-icon">
|
<div class="selected-icon">
|
||||||
@if (addedDateTo) {
|
@if (addedDateTo) {
|
||||||
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedTo()">
|
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedTo()">
|
||||||
@ -154,6 +154,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
.date-dropdown {
|
.date-dropdown {
|
||||||
--bs-dropdown-min-width: 22rem;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
|
@media(min-width: 768px) {
|
||||||
|
--bs-dropdown-min-width: 40rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
.border-end {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.btn-link {
|
.btn-link {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
@ -12,10 +21,6 @@
|
|||||||
min-height: 1em;
|
min-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-item .selected-icon {
|
|
||||||
line-height: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-group-sm {
|
.input-group-sm {
|
||||||
.form-control {
|
.form-control {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
|
@ -82,12 +82,10 @@ describe('DatesDropdownComponent', () => {
|
|||||||
it('should support relative dates', fakeAsync(() => {
|
it('should support relative dates', fakeAsync(() => {
|
||||||
let result: DateSelection
|
let result: DateSelection
|
||||||
component.datesSet.subscribe((date) => (result = date))
|
component.datesSet.subscribe((date) => (result = date))
|
||||||
component.createdRelativeDate = RelativeDate.WITHIN_1_WEEK // normally set by ngModel binding in dropdown
|
component.setCreatedRelativeDate(null)
|
||||||
component.onSetCreatedRelativeDate({
|
component.setCreatedRelativeDate(RelativeDate.WITHIN_1_WEEK)
|
||||||
id: RelativeDate.WITHIN_1_WEEK,
|
component.setAddedRelativeDate(null)
|
||||||
} as any)
|
component.setAddedRelativeDate(RelativeDate.WITHIN_1_WEEK)
|
||||||
component.addedRelativeDate = RelativeDate.WITHIN_1_WEEK // normally set by ngModel binding in dropdown
|
|
||||||
component.onSetAddedRelativeDate({ id: RelativeDate.WITHIN_1_WEEK } as any)
|
|
||||||
tick(500)
|
tick(500)
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
createdFrom: null,
|
createdFrom: null,
|
||||||
@ -149,19 +147,8 @@ describe('DatesDropdownComponent', () => {
|
|||||||
expect(component.addedDateTo).toBeNull()
|
expect(component.addedDateTo).toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support clearRelativeDate', () => {
|
|
||||||
component.createdRelativeDate = RelativeDate.WITHIN_1_WEEK
|
|
||||||
component.clearCreatedRelativeDate()
|
|
||||||
expect(component.createdRelativeDate).toBeNull()
|
|
||||||
|
|
||||||
component.addedRelativeDate = RelativeDate.WITHIN_1_WEEK
|
|
||||||
component.clearAddedRelativeDate()
|
|
||||||
expect(component.addedRelativeDate).toBeNull()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should limit keyboard events', () => {
|
it('should limit keyboard events', () => {
|
||||||
const input: HTMLInputElement =
|
const input: HTMLInputElement = fixture.nativeElement.querySelector('input')
|
||||||
fixture.nativeElement.querySelector('input.form-control')
|
|
||||||
let event: KeyboardEvent = new KeyboardEvent('keypress', {
|
let event: KeyboardEvent = new KeyboardEvent('keypress', {
|
||||||
key: '9',
|
key: '9',
|
||||||
})
|
})
|
||||||
@ -176,19 +163,4 @@ describe('DatesDropdownComponent', () => {
|
|||||||
input.dispatchEvent(event)
|
input.dispatchEvent(event)
|
||||||
expect(eventSpy).toHaveBeenCalled()
|
expect(eventSpy).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support debounce', fakeAsync(() => {
|
|
||||||
let result: DateSelection
|
|
||||||
component.datesSet.subscribe((date) => (result = date))
|
|
||||||
component.onChangeDebounce()
|
|
||||||
tick(500)
|
|
||||||
expect(result).toEqual({
|
|
||||||
createdFrom: null,
|
|
||||||
createdTo: null,
|
|
||||||
createdRelativeDateID: null,
|
|
||||||
addedFrom: null,
|
|
||||||
addedTo: null,
|
|
||||||
addedRelativeDateID: null,
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
|
@ -13,14 +13,13 @@ import {
|
|||||||
NgbDatepickerModule,
|
NgbDatepickerModule,
|
||||||
NgbDropdownModule,
|
NgbDropdownModule,
|
||||||
} from '@ng-bootstrap/ng-bootstrap'
|
} from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { NgSelectModule } from '@ng-select/ng-select'
|
|
||||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||||
import { Subject, Subscription } from 'rxjs'
|
import { Subject, Subscription } from 'rxjs'
|
||||||
import { debounceTime } from 'rxjs/operators'
|
import { debounceTime } from 'rxjs/operators'
|
||||||
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
|
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
|
||||||
import { SettingsService } from 'src/app/services/settings.service'
|
import { SettingsService } from 'src/app/services/settings.service'
|
||||||
import { ISODateAdapter } from 'src/app/utils/ngb-iso-date-adapter'
|
import { ISODateAdapter } from 'src/app/utils/ngb-iso-date-adapter'
|
||||||
import { pngxPopperOptions } from 'src/app/utils/popper-options'
|
import { popperOptionsReenablePreventOverflow } from 'src/app/utils/popper-options'
|
||||||
import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
|
import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
|
||||||
|
|
||||||
export interface DateSelection {
|
export interface DateSelection {
|
||||||
@ -33,14 +32,10 @@ export interface DateSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum RelativeDate {
|
export enum RelativeDate {
|
||||||
WITHIN_1_WEEK = 1,
|
WITHIN_1_WEEK = 0,
|
||||||
WITHIN_1_MONTH = 2,
|
WITHIN_1_MONTH = 1,
|
||||||
WITHIN_3_MONTHS = 3,
|
WITHIN_3_MONTHS = 2,
|
||||||
WITHIN_1_YEAR = 4,
|
WITHIN_1_YEAR = 3,
|
||||||
THIS_YEAR = 5,
|
|
||||||
THIS_MONTH = 6,
|
|
||||||
TODAY = 7,
|
|
||||||
YESTERDAY = 8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -54,14 +49,13 @@ export enum RelativeDate {
|
|||||||
NgxBootstrapIconsModule,
|
NgxBootstrapIconsModule,
|
||||||
NgbDatepickerModule,
|
NgbDatepickerModule,
|
||||||
NgbDropdownModule,
|
NgbDropdownModule,
|
||||||
NgSelectModule,
|
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
NgClass,
|
NgClass,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class DatesDropdownComponent implements OnInit, OnDestroy {
|
export class DatesDropdownComponent implements OnInit, OnDestroy {
|
||||||
public popperOptions = pngxPopperOptions
|
public popperOptions = popperOptionsReenablePreventOverflow
|
||||||
|
|
||||||
constructor(settings: SettingsService) {
|
constructor(settings: SettingsService) {
|
||||||
this.datePlaceHolder = settings.getLocalizedDateInputFormat()
|
this.datePlaceHolder = settings.getLocalizedDateInputFormat()
|
||||||
@ -88,64 +82,44 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
|
|||||||
name: $localize`Within 1 year`,
|
name: $localize`Within 1 year`,
|
||||||
date: new Date().setFullYear(new Date().getFullYear() - 1),
|
date: new Date().setFullYear(new Date().getFullYear() - 1),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: RelativeDate.THIS_YEAR,
|
|
||||||
name: $localize`This year`,
|
|
||||||
date: new Date('1/1/' + new Date().getFullYear()),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: RelativeDate.THIS_MONTH,
|
|
||||||
name: $localize`This month`,
|
|
||||||
date: new Date().setDate(1),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: RelativeDate.TODAY,
|
|
||||||
name: $localize`Today`,
|
|
||||||
date: new Date().setHours(0, 0, 0, 0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: RelativeDate.YESTERDAY,
|
|
||||||
name: $localize`Yesterday`,
|
|
||||||
date: new Date().setDate(new Date().getDate() - 1),
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
datePlaceHolder: string
|
datePlaceHolder: string
|
||||||
|
|
||||||
// created
|
// created
|
||||||
@Input()
|
@Input()
|
||||||
createdDateTo: string = null
|
createdDateTo: string
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
createdDateToChange = new EventEmitter<string>()
|
createdDateToChange = new EventEmitter<string>()
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
createdDateFrom: string = null
|
createdDateFrom: string
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
createdDateFromChange = new EventEmitter<string>()
|
createdDateFromChange = new EventEmitter<string>()
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
createdRelativeDate: RelativeDate = null
|
createdRelativeDate: RelativeDate
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
createdRelativeDateChange = new EventEmitter<number>()
|
createdRelativeDateChange = new EventEmitter<number>()
|
||||||
|
|
||||||
// added
|
// added
|
||||||
@Input()
|
@Input()
|
||||||
addedDateTo: string = null
|
addedDateTo: string
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
addedDateToChange = new EventEmitter<string>()
|
addedDateToChange = new EventEmitter<string>()
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
addedDateFrom: string = null
|
addedDateFrom: string
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
addedDateFromChange = new EventEmitter<string>()
|
addedDateFromChange = new EventEmitter<string>()
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
addedRelativeDate: RelativeDate = null
|
addedRelativeDate: RelativeDate
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
addedRelativeDateChange = new EventEmitter<number>()
|
addedRelativeDateChange = new EventEmitter<number>()
|
||||||
@ -159,9 +133,6 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
|
|||||||
@Input()
|
@Input()
|
||||||
disabled: boolean = false
|
disabled: boolean = false
|
||||||
|
|
||||||
@Input()
|
|
||||||
placement: string = 'bottom-start'
|
|
||||||
|
|
||||||
public readonly today: string = new Date().toISOString().split('T')[0]
|
public readonly today: string = new Date().toISOString().split('T')[0]
|
||||||
|
|
||||||
get isActive(): boolean {
|
get isActive(): boolean {
|
||||||
@ -201,17 +172,17 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
|
|||||||
this.onChange()
|
this.onChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
onSetCreatedRelativeDate(rd: { id: number; name: string; date: number }) {
|
setCreatedRelativeDate(rd: RelativeDate) {
|
||||||
// createdRelativeDate is set by ngModel
|
|
||||||
this.createdDateTo = null
|
this.createdDateTo = null
|
||||||
this.createdDateFrom = null
|
this.createdDateFrom = null
|
||||||
|
this.createdRelativeDate = this.createdRelativeDate == rd ? null : rd
|
||||||
this.onChange()
|
this.onChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
onSetAddedRelativeDate(rd: { id: number; name: string; date: number }) {
|
setAddedRelativeDate(rd: RelativeDate) {
|
||||||
// addedRelativeDate is set by ngModel
|
|
||||||
this.addedDateTo = null
|
this.addedDateTo = null
|
||||||
this.addedDateFrom = null
|
this.addedDateFrom = null
|
||||||
|
this.addedRelativeDate = this.addedRelativeDate == rd ? null : rd
|
||||||
this.onChange()
|
this.onChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,11 +224,6 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
|
|||||||
this.onChange()
|
this.onChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCreatedRelativeDate() {
|
|
||||||
this.createdRelativeDate = null
|
|
||||||
this.onChange()
|
|
||||||
}
|
|
||||||
|
|
||||||
clearAddedTo() {
|
clearAddedTo() {
|
||||||
this.addedDateTo = null
|
this.addedDateTo = null
|
||||||
this.onChange()
|
this.onChange()
|
||||||
@ -268,11 +234,6 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
|
|||||||
this.onChange()
|
this.onChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
clearAddedRelativeDate() {
|
|
||||||
this.addedRelativeDate = null
|
|
||||||
this.onChange()
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent chars other than numbers and separators
|
// prevent chars other than numbers and separators
|
||||||
onKeyPress(event: KeyboardEvent) {
|
onKeyPress(event: KeyboardEvent) {
|
||||||
if ('Enter' !== event.key && !/[0-9,\.\/-]+/.test(event.key)) {
|
if ('Enter' !== event.key && !/[0-9,\.\/-]+/.test(event.key)) {
|
||||||
|
@ -189,7 +189,6 @@
|
|||||||
<pngx-input-select i18n-title title="Assign correspondent" [items]="correspondents" [allowNull]="true" formControlName="assign_correspondent"></pngx-input-select>
|
<pngx-input-select i18n-title title="Assign correspondent" [items]="correspondents" [allowNull]="true" formControlName="assign_correspondent"></pngx-input-select>
|
||||||
<pngx-input-select i18n-title title="Assign storage path" [items]="storagePaths" [allowNull]="true" formControlName="assign_storage_path"></pngx-input-select>
|
<pngx-input-select i18n-title title="Assign storage path" [items]="storagePaths" [allowNull]="true" formControlName="assign_storage_path"></pngx-input-select>
|
||||||
<pngx-input-select i18n-title title="Assign custom fields" multiple="true" [items]="customFields" [allowNull]="true" formControlName="assign_custom_fields"></pngx-input-select>
|
<pngx-input-select i18n-title title="Assign custom fields" multiple="true" [items]="customFields" [allowNull]="true" formControlName="assign_custom_fields"></pngx-input-select>
|
||||||
<pngx-input-custom-fields-values formControlName="assign_custom_fields_values" [selectedFields]="formGroup.get('assign_custom_fields').value" (removeSelectedField)="removeSelectedCustomField($event, formGroup)"></pngx-input-custom-fields-values>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<pngx-input-select i18n-title title="Assign owner" [items]="users" bindLabel="username" formControlName="assign_owner" [allowNull]="true"></pngx-input-select>
|
<pngx-input-select i18n-title title="Assign owner" [items]="users" bindLabel="username" formControlName="assign_owner" [allowNull]="true"></pngx-input-select>
|
||||||
|
@ -2,12 +2,7 @@ import { CdkDragDrop } from '@angular/cdk/drag-drop'
|
|||||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
||||||
import { provideHttpClientTesting } from '@angular/common/http/testing'
|
import { provideHttpClientTesting } from '@angular/common/http/testing'
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
import {
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
FormControl,
|
|
||||||
FormGroup,
|
|
||||||
FormsModule,
|
|
||||||
ReactiveFormsModule,
|
|
||||||
} from '@angular/forms'
|
|
||||||
import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { NgSelectModule } from '@ng-select/ng-select'
|
import { NgSelectModule } from '@ng-select/ng-select'
|
||||||
import { of } from 'rxjs'
|
import { of } from 'rxjs'
|
||||||
@ -374,19 +369,4 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
expect(component.objectForm.get('actions').value[0].email).toBeNull()
|
expect(component.objectForm.get('actions').value[0].email).toBeNull()
|
||||||
expect(component.objectForm.get('actions').value[0].webhook).toBeNull()
|
expect(component.objectForm.get('actions').value[0].webhook).toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should remove selected custom field from the form group', () => {
|
|
||||||
const formGroup = new FormGroup({
|
|
||||||
assign_custom_fields: new FormControl([1, 2, 3]),
|
|
||||||
})
|
|
||||||
|
|
||||||
component.removeSelectedCustomField(2, formGroup)
|
|
||||||
expect(formGroup.get('assign_custom_fields').value).toEqual([1, 3])
|
|
||||||
|
|
||||||
component.removeSelectedCustomField(1, formGroup)
|
|
||||||
expect(formGroup.get('assign_custom_fields').value).toEqual([3])
|
|
||||||
|
|
||||||
component.removeSelectedCustomField(3, formGroup)
|
|
||||||
expect(formGroup.get('assign_custom_fields').value).toEqual([])
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
@ -47,7 +47,6 @@ import { WorkflowService } from 'src/app/services/rest/workflow.service'
|
|||||||
import { SettingsService } from 'src/app/services/settings.service'
|
import { SettingsService } from 'src/app/services/settings.service'
|
||||||
import { ConfirmButtonComponent } from '../../confirm-button/confirm-button.component'
|
import { ConfirmButtonComponent } from '../../confirm-button/confirm-button.component'
|
||||||
import { CheckComponent } from '../../input/check/check.component'
|
import { CheckComponent } from '../../input/check/check.component'
|
||||||
import { CustomFieldsValuesComponent } from '../../input/custom-fields-values/custom-fields-values.component'
|
|
||||||
import { EntriesComponent } from '../../input/entries/entries.component'
|
import { EntriesComponent } from '../../input/entries/entries.component'
|
||||||
import { NumberComponent } from '../../input/number/number.component'
|
import { NumberComponent } from '../../input/number/number.component'
|
||||||
import { PermissionsGroupComponent } from '../../input/permissions/permissions-group/permissions-group.component'
|
import { PermissionsGroupComponent } from '../../input/permissions/permissions-group/permissions-group.component'
|
||||||
@ -152,7 +151,6 @@ const TRIGGER_MATCHING_ALGORITHMS = MATCHING_ALGORITHMS.filter(
|
|||||||
SelectComponent,
|
SelectComponent,
|
||||||
TextAreaComponent,
|
TextAreaComponent,
|
||||||
TagsComponent,
|
TagsComponent,
|
||||||
CustomFieldsValuesComponent,
|
|
||||||
PermissionsGroupComponent,
|
PermissionsGroupComponent,
|
||||||
PermissionsUserComponent,
|
PermissionsUserComponent,
|
||||||
ConfirmButtonComponent,
|
ConfirmButtonComponent,
|
||||||
@ -441,9 +439,6 @@ export class WorkflowEditDialogComponent
|
|||||||
assign_change_users: new FormControl(action.assign_change_users),
|
assign_change_users: new FormControl(action.assign_change_users),
|
||||||
assign_change_groups: new FormControl(action.assign_change_groups),
|
assign_change_groups: new FormControl(action.assign_change_groups),
|
||||||
assign_custom_fields: new FormControl(action.assign_custom_fields),
|
assign_custom_fields: new FormControl(action.assign_custom_fields),
|
||||||
assign_custom_fields_values: new FormControl(
|
|
||||||
action.assign_custom_fields_values
|
|
||||||
),
|
|
||||||
remove_tags: new FormControl(action.remove_tags),
|
remove_tags: new FormControl(action.remove_tags),
|
||||||
remove_all_tags: new FormControl(action.remove_all_tags),
|
remove_all_tags: new FormControl(action.remove_all_tags),
|
||||||
remove_document_types: new FormControl(action.remove_document_types),
|
remove_document_types: new FormControl(action.remove_document_types),
|
||||||
@ -570,7 +565,6 @@ export class WorkflowEditDialogComponent
|
|||||||
assign_change_users: [],
|
assign_change_users: [],
|
||||||
assign_change_groups: [],
|
assign_change_groups: [],
|
||||||
assign_custom_fields: [],
|
assign_custom_fields: [],
|
||||||
assign_custom_fields_values: {},
|
|
||||||
remove_tags: [],
|
remove_tags: [],
|
||||||
remove_all_tags: false,
|
remove_all_tags: false,
|
||||||
remove_document_types: [],
|
remove_document_types: [],
|
||||||
@ -649,12 +643,4 @@ export class WorkflowEditDialogComponent
|
|||||||
})
|
})
|
||||||
super.save()
|
super.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeSelectedCustomField(fieldId: number, group: FormGroup) {
|
|
||||||
group
|
|
||||||
.get('assign_custom_fields')
|
|
||||||
.setValue(
|
|
||||||
group.get('assign_custom_fields').value.filter((id) => id !== fieldId)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import { ObjectWithPermissions } from 'src/app/data/object-with-permissions'
|
|||||||
import { FilterPipe } from 'src/app/pipes/filter.pipe'
|
import { FilterPipe } from 'src/app/pipes/filter.pipe'
|
||||||
import { HotKeyService } from 'src/app/services/hot-key.service'
|
import { HotKeyService } from 'src/app/services/hot-key.service'
|
||||||
import { SelectionDataItem } from 'src/app/services/rest/document.service'
|
import { SelectionDataItem } from 'src/app/services/rest/document.service'
|
||||||
import { pngxPopperOptions } from 'src/app/utils/popper-options'
|
import { popperOptionsReenablePreventOverflow } from 'src/app/utils/popper-options'
|
||||||
import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
|
import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
|
||||||
import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
|
import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
|
||||||
import {
|
import {
|
||||||
@ -380,7 +380,7 @@ export class FilterableDropdownComponent
|
|||||||
@ViewChild('dropdown') dropdown: NgbDropdown
|
@ViewChild('dropdown') dropdown: NgbDropdown
|
||||||
@ViewChild('buttonItems') buttonItems: ElementRef
|
@ViewChild('buttonItems') buttonItems: ElementRef
|
||||||
|
|
||||||
public popperOptions = pngxPopperOptions
|
public popperOptions = popperOptionsReenablePreventOverflow
|
||||||
|
|
||||||
filterText: string
|
filterText: string
|
||||||
|
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
<div class="list-group mt-3 selected-fields">
|
|
||||||
@for (fieldId of selectedFields; track fieldId) {
|
|
||||||
<div class="list-group-item
|
|
||||||
d-flex
|
|
||||||
justify-content-between
|
|
||||||
align-items-center">
|
|
||||||
@switch (getCustomField(fieldId)?.data_type) {
|
|
||||||
@case (CustomFieldDataType.String) {
|
|
||||||
<pngx-input-text [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)"
|
|
||||||
[title]="getCustomField(fieldId)?.name"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[horizontal]="true"></pngx-input-text>
|
|
||||||
}
|
|
||||||
@case (CustomFieldDataType.Date) {
|
|
||||||
<pngx-input-date [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)"
|
|
||||||
[title]="getCustomField(fieldId)?.name"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[horizontal]="true"></pngx-input-date>
|
|
||||||
}
|
|
||||||
@case (CustomFieldDataType.Integer) {
|
|
||||||
<pngx-input-number [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)"
|
|
||||||
[title]="getCustomField(fieldId)?.name"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[horizontal]="true"
|
|
||||||
[showAdd]="false"></pngx-input-number>
|
|
||||||
}
|
|
||||||
@case (CustomFieldDataType.Float) {
|
|
||||||
<pngx-input-number [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)"
|
|
||||||
[title]="getCustomField(fieldId)?.name"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[horizontal]="true"
|
|
||||||
[showAdd]="false"
|
|
||||||
[step]=".1"></pngx-input-number>
|
|
||||||
}
|
|
||||||
@case (CustomFieldDataType.Monetary) {
|
|
||||||
<pngx-input-monetary [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)"
|
|
||||||
[title]="getCustomField(fieldId)?.name"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[defaultCurrency]="getCustomField(fieldId)?.extra_data?.default_currency"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[horizontal]="true"></pngx-input-monetary>
|
|
||||||
}
|
|
||||||
@case (CustomFieldDataType.Boolean) {
|
|
||||||
<pngx-input-check [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)"
|
|
||||||
[title]="getCustomField(fieldId)?.name"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[horizontal]="true"></pngx-input-check>
|
|
||||||
}
|
|
||||||
@case (CustomFieldDataType.Url) {
|
|
||||||
<pngx-input-url [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)"
|
|
||||||
[title]="getCustomField(fieldId)?.name"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[horizontal]="true"></pngx-input-url>
|
|
||||||
}
|
|
||||||
@case (CustomFieldDataType.DocumentLink) {
|
|
||||||
<pngx-input-document-link [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)"
|
|
||||||
[title]="getCustomField(fieldId)?.name"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[horizontal]="true"></pngx-input-document-link>
|
|
||||||
}
|
|
||||||
@case (CustomFieldDataType.Select) {
|
|
||||||
<pngx-input-select [(ngModel)]="value[fieldId]" (ngModelChange)="onChange(value)"
|
|
||||||
[title]="getCustomField(fieldId)?.name"
|
|
||||||
class="flex-grow-1"
|
|
||||||
[items]="getCustomField(fieldId)?.extra_data.select_options"
|
|
||||||
class="flex-grow-1"
|
|
||||||
bindLabel="label"
|
|
||||||
[allowNull]="true"
|
|
||||||
[horizontal]="true"></pngx-input-select>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
<button type="button" class="btn btn-link text-danger" (click)="removeSelectedField.next(fieldId)">
|
|
||||||
<i-bs name="trash"></i-bs>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
@ -1,3 +0,0 @@
|
|||||||
:host ::ng-deep .list-group-item .mb-3 {
|
|
||||||
margin-bottom: 0 !important;
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
|
||||||
import { provideHttpClientTesting } from '@angular/common/http/testing'
|
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
|
||||||
import {
|
|
||||||
FormsModule,
|
|
||||||
NG_VALUE_ACCESSOR,
|
|
||||||
ReactiveFormsModule,
|
|
||||||
} from '@angular/forms'
|
|
||||||
import { of } from 'rxjs'
|
|
||||||
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
|
|
||||||
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
|
|
||||||
import { CustomFieldsValuesComponent } from './custom-fields-values.component'
|
|
||||||
|
|
||||||
describe('CustomFieldsValuesComponent', () => {
|
|
||||||
let component: CustomFieldsValuesComponent
|
|
||||||
let fixture: ComponentFixture<CustomFieldsValuesComponent>
|
|
||||||
let customFieldsService: CustomFieldsService
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
imports: [FormsModule, ReactiveFormsModule, CustomFieldsValuesComponent],
|
|
||||||
providers: [
|
|
||||||
provideHttpClient(withInterceptorsFromDi()),
|
|
||||||
provideHttpClientTesting(),
|
|
||||||
],
|
|
||||||
}).compileComponents()
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(CustomFieldsValuesComponent)
|
|
||||||
fixture.debugElement.injector.get(NG_VALUE_ACCESSOR)
|
|
||||||
component = fixture.componentInstance
|
|
||||||
customFieldsService = TestBed.inject(CustomFieldsService)
|
|
||||||
jest.spyOn(customFieldsService, 'listAll').mockReturnValue(
|
|
||||||
of({
|
|
||||||
all: [1],
|
|
||||||
count: 1,
|
|
||||||
results: [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'Field 1',
|
|
||||||
data_type: CustomFieldDataType.String,
|
|
||||||
} as CustomField,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
)
|
|
||||||
fixture.detectChanges()
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(CustomFieldsValuesComponent)
|
|
||||||
component = fixture.componentInstance
|
|
||||||
fixture.detectChanges()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should set selectedFields and map values correctly', () => {
|
|
||||||
component.value = { 1: 'value1' }
|
|
||||||
component.selectedFields = [1, 2]
|
|
||||||
expect(component.selectedFields).toEqual([1, 2])
|
|
||||||
expect(component.value).toEqual({ 1: 'value1', 2: null })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should return the correct custom field by id', () => {
|
|
||||||
const field = component.getCustomField(1)
|
|
||||||
expect(field).toEqual({
|
|
||||||
id: 1,
|
|
||||||
name: 'Field 1',
|
|
||||||
data_type: CustomFieldDataType.String,
|
|
||||||
} as CustomField)
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,90 +0,0 @@
|
|||||||
import {
|
|
||||||
Component,
|
|
||||||
EventEmitter,
|
|
||||||
forwardRef,
|
|
||||||
Input,
|
|
||||||
Output,
|
|
||||||
} from '@angular/core'
|
|
||||||
import {
|
|
||||||
FormsModule,
|
|
||||||
NG_VALUE_ACCESSOR,
|
|
||||||
ReactiveFormsModule,
|
|
||||||
} from '@angular/forms'
|
|
||||||
import { RouterModule } from '@angular/router'
|
|
||||||
import { NgSelectModule } from '@ng-select/ng-select'
|
|
||||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
|
||||||
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
|
|
||||||
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
|
|
||||||
import { AbstractInputComponent } from '../abstract-input'
|
|
||||||
import { CheckComponent } from '../check/check.component'
|
|
||||||
import { DateComponent } from '../date/date.component'
|
|
||||||
import { DocumentLinkComponent } from '../document-link/document-link.component'
|
|
||||||
import { MonetaryComponent } from '../monetary/monetary.component'
|
|
||||||
import { NumberComponent } from '../number/number.component'
|
|
||||||
import { SelectComponent } from '../select/select.component'
|
|
||||||
import { TextComponent } from '../text/text.component'
|
|
||||||
import { UrlComponent } from '../url/url.component'
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: NG_VALUE_ACCESSOR,
|
|
||||||
useExisting: forwardRef(() => CustomFieldsValuesComponent),
|
|
||||||
multi: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
selector: 'pngx-input-custom-fields-values',
|
|
||||||
templateUrl: './custom-fields-values.component.html',
|
|
||||||
styleUrl: './custom-fields-values.component.scss',
|
|
||||||
imports: [
|
|
||||||
TextComponent,
|
|
||||||
DateComponent,
|
|
||||||
NumberComponent,
|
|
||||||
DocumentLinkComponent,
|
|
||||||
UrlComponent,
|
|
||||||
SelectComponent,
|
|
||||||
MonetaryComponent,
|
|
||||||
CheckComponent,
|
|
||||||
NgSelectModule,
|
|
||||||
FormsModule,
|
|
||||||
ReactiveFormsModule,
|
|
||||||
RouterModule,
|
|
||||||
NgxBootstrapIconsModule,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class CustomFieldsValuesComponent extends AbstractInputComponent<Object> {
|
|
||||||
public CustomFieldDataType = CustomFieldDataType
|
|
||||||
|
|
||||||
constructor(customFieldsService: CustomFieldsService) {
|
|
||||||
super()
|
|
||||||
customFieldsService.listAll().subscribe((items) => {
|
|
||||||
this.fields = items.results
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fields: CustomField[]
|
|
||||||
|
|
||||||
private _selectedFields: number[]
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
set selectedFields(newFields: number[]) {
|
|
||||||
this._selectedFields = newFields
|
|
||||||
// map the selected fields to an object with field_id as key and value as value
|
|
||||||
this.value = newFields.reduce((acc, fieldId) => {
|
|
||||||
acc[fieldId] = this.value?.[fieldId] || null
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
this.onChange(this.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
get selectedFields(): number[] {
|
|
||||||
return this._selectedFields
|
|
||||||
}
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
public removeSelectedField: EventEmitter<number> = new EventEmitter<number>()
|
|
||||||
|
|
||||||
public getCustomField(id: number): CustomField {
|
|
||||||
return this.fields.find((field) => field.id === id)
|
|
||||||
}
|
|
||||||
}
|
|
@ -48,7 +48,7 @@
|
|||||||
</details>
|
</details>
|
||||||
}
|
}
|
||||||
@if (toast.action) {
|
@if (toast.action) {
|
||||||
<p class="mb-0 mt-2"><button class="btn btn-sm btn-outline-secondary" (click)="closed.emit(toast); toast.action()">{{toast.actionName}}</button></p>
|
<p class="mb-0 mt-2"><button class="btn btn-sm btn-outline-secondary" (click)="close.emit(toast); toast.action()">{{toast.actionName}}</button></p>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn-close ms-auto flex-shrink-0" data-bs-dismiss="toast" aria-label="Close" (click)="closed.emit(toast);"></button>
|
<button type="button" class="btn-close ms-auto flex-shrink-0" data-bs-dismiss="toast" aria-label="Close" (click)="closed.emit(toast);"></button>
|
||||||
|
@ -1040,27 +1040,6 @@ describe('BulkEditorComponent', () => {
|
|||||||
`${environment.apiBaseUrl}documents/?page=1&page_size=100000&fields=id`
|
`${environment.apiBaseUrl}documents/?page=1&page_size=100000&fields=id`
|
||||||
) // listAllFilteredIds
|
) // listAllFilteredIds
|
||||||
expect(documentListViewService.selected.size).toEqual(0)
|
expect(documentListViewService.selected.size).toEqual(0)
|
||||||
|
|
||||||
// Test with archiveFallback enabled
|
|
||||||
modal.componentInstance.deleteOriginals = false
|
|
||||||
modal.componentInstance.archiveFallback = true
|
|
||||||
modal.componentInstance.confirm()
|
|
||||||
req = httpTestingController.expectOne(
|
|
||||||
`${environment.apiBaseUrl}documents/bulk_edit/`
|
|
||||||
)
|
|
||||||
req.flush(true)
|
|
||||||
expect(req.request.body).toEqual({
|
|
||||||
documents: [3, 4],
|
|
||||||
method: 'merge',
|
|
||||||
parameters: { metadata_document_id: 3, archive_fallback: true },
|
|
||||||
})
|
|
||||||
httpTestingController.match(
|
|
||||||
`${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true`
|
|
||||||
) // list reload
|
|
||||||
httpTestingController.match(
|
|
||||||
`${environment.apiBaseUrl}documents/?page=1&page_size=100000&fields=id`
|
|
||||||
) // listAllFilteredIds
|
|
||||||
expect(documentListViewService.selected.size).toEqual(0)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support bulk download with archive, originals or both and file formatting', () => {
|
it('should support bulk download with archive, originals or both and file formatting', () => {
|
||||||
|
@ -857,9 +857,6 @@ export class BulkEditorComponent
|
|||||||
if (mergeDialog.deleteOriginals) {
|
if (mergeDialog.deleteOriginals) {
|
||||||
args['delete_originals'] = true
|
args['delete_originals'] = true
|
||||||
}
|
}
|
||||||
if (mergeDialog.archiveFallback) {
|
|
||||||
args['archive_fallback'] = true
|
|
||||||
}
|
|
||||||
mergeDialog.buttonsEnabled = false
|
mergeDialog.buttonsEnabled = false
|
||||||
this.executeBulkOperation(modal, 'merge', args, mergeDialog.documentIDs)
|
this.executeBulkOperation(modal, 'merge', args, mergeDialog.documentIDs)
|
||||||
this.toastService.showInfo(
|
this.toastService.showInfo(
|
||||||
|
@ -93,7 +93,6 @@
|
|||||||
}
|
}
|
||||||
<pngx-dates-dropdown class="flex-fill fade" [class.show]="show"
|
<pngx-dates-dropdown class="flex-fill fade" [class.show]="show"
|
||||||
title="Dates" i18n-title
|
title="Dates" i18n-title
|
||||||
placement="bottom-end"
|
|
||||||
(datesSet)="updateRules()"
|
(datesSet)="updateRules()"
|
||||||
[(createdDateTo)]="dateCreatedTo"
|
[(createdDateTo)]="dateCreatedTo"
|
||||||
[(createdDateFrom)]="dateCreatedFrom"
|
[(createdDateFrom)]="dateCreatedFrom"
|
||||||
|
@ -96,10 +96,7 @@ import {
|
|||||||
import { environment } from 'src/environments/environment'
|
import { environment } from 'src/environments/environment'
|
||||||
import { ClearableBadgeComponent } from '../../common/clearable-badge/clearable-badge.component'
|
import { ClearableBadgeComponent } from '../../common/clearable-badge/clearable-badge.component'
|
||||||
import { CustomFieldsQueryDropdownComponent } from '../../common/custom-fields-query-dropdown/custom-fields-query-dropdown.component'
|
import { CustomFieldsQueryDropdownComponent } from '../../common/custom-fields-query-dropdown/custom-fields-query-dropdown.component'
|
||||||
import {
|
import { DatesDropdownComponent } from '../../common/dates-dropdown/dates-dropdown.component'
|
||||||
DatesDropdownComponent,
|
|
||||||
RelativeDate,
|
|
||||||
} from '../../common/dates-dropdown/dates-dropdown.component'
|
|
||||||
import {
|
import {
|
||||||
FilterableDropdownComponent,
|
FilterableDropdownComponent,
|
||||||
Intersection,
|
Intersection,
|
||||||
@ -425,7 +422,7 @@ describe('FilterEditorComponent', () => {
|
|||||||
value: 'created:[-1 week to now]',
|
value: 'created:[-1 week to now]',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
expect(component.dateCreatedRelativeDate).toEqual(1) // RELATIVE_DATE_QUERYSTRINGS['-1 week to now']
|
expect(component.dateCreatedRelativeDate).toEqual(0) // RELATIVE_DATE_QUERYSTRINGS['-1 week to now']
|
||||||
expect(component.textFilter).toBeNull()
|
expect(component.textFilter).toBeNull()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@ -437,7 +434,7 @@ describe('FilterEditorComponent', () => {
|
|||||||
value: 'added:[-1 week to now]',
|
value: 'added:[-1 week to now]',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
expect(component.dateAddedRelativeDate).toEqual(1) // RELATIVE_DATE_QUERYSTRINGS['-1 week to now']
|
expect(component.dateAddedRelativeDate).toEqual(0) // RELATIVE_DATE_QUERYSTRINGS['-1 week to now']
|
||||||
expect(component.textFilter).toBeNull()
|
expect(component.textFilter).toBeNull()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@ -1590,8 +1587,10 @@ describe('FilterEditorComponent', () => {
|
|||||||
const dateCreatedDropdown = fixture.debugElement.queryAll(
|
const dateCreatedDropdown = fixture.debugElement.queryAll(
|
||||||
By.directive(DatesDropdownComponent)
|
By.directive(DatesDropdownComponent)
|
||||||
)[0]
|
)[0]
|
||||||
component.dateCreatedRelativeDate = RelativeDate.WITHIN_1_WEEK
|
const dateCreatedBeforeRelativeButton = dateCreatedDropdown.queryAll(
|
||||||
dateCreatedDropdown.triggerEventHandler('datesSet')
|
By.css('button')
|
||||||
|
)[1]
|
||||||
|
dateCreatedBeforeRelativeButton.triggerEventHandler('click')
|
||||||
fixture.detectChanges()
|
fixture.detectChanges()
|
||||||
tick(400)
|
tick(400)
|
||||||
expect(component.filterRules).toEqual([
|
expect(component.filterRules).toEqual([
|
||||||
@ -1607,8 +1606,10 @@ describe('FilterEditorComponent', () => {
|
|||||||
const dateCreatedDropdown = fixture.debugElement.queryAll(
|
const dateCreatedDropdown = fixture.debugElement.queryAll(
|
||||||
By.directive(DatesDropdownComponent)
|
By.directive(DatesDropdownComponent)
|
||||||
)[0]
|
)[0]
|
||||||
component.dateCreatedRelativeDate = RelativeDate.WITHIN_1_WEEK
|
const dateCreatedBeforeRelativeButton = dateCreatedDropdown.queryAll(
|
||||||
dateCreatedDropdown.triggerEventHandler('datesSet')
|
By.css('button')
|
||||||
|
)[1]
|
||||||
|
dateCreatedBeforeRelativeButton.triggerEventHandler('click')
|
||||||
fixture.detectChanges()
|
fixture.detectChanges()
|
||||||
tick(400)
|
tick(400)
|
||||||
expect(component.filterRules).toEqual([
|
expect(component.filterRules).toEqual([
|
||||||
@ -1691,14 +1692,16 @@ describe('FilterEditorComponent', () => {
|
|||||||
const datesDropdown = fixture.debugElement.query(
|
const datesDropdown = fixture.debugElement.query(
|
||||||
By.directive(DatesDropdownComponent)
|
By.directive(DatesDropdownComponent)
|
||||||
)
|
)
|
||||||
component.dateAddedRelativeDate = RelativeDate.WITHIN_1_WEEK
|
const dateCreatedBeforeRelativeButton = datesDropdown.queryAll(
|
||||||
datesDropdown.triggerEventHandler('datesSet')
|
By.css('button')
|
||||||
|
)[1]
|
||||||
|
dateCreatedBeforeRelativeButton.triggerEventHandler('click')
|
||||||
fixture.detectChanges()
|
fixture.detectChanges()
|
||||||
tick(400)
|
tick(400)
|
||||||
expect(component.filterRules).toEqual([
|
expect(component.filterRules).toEqual([
|
||||||
{
|
{
|
||||||
rule_type: FILTER_FULLTEXT_QUERY,
|
rule_type: FILTER_FULLTEXT_QUERY,
|
||||||
value: 'added:[-1 week to now]',
|
value: 'created:[-1 week to now]',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
}))
|
}))
|
||||||
@ -1708,14 +1711,16 @@ describe('FilterEditorComponent', () => {
|
|||||||
const datesDropdown = fixture.debugElement.query(
|
const datesDropdown = fixture.debugElement.query(
|
||||||
By.directive(DatesDropdownComponent)
|
By.directive(DatesDropdownComponent)
|
||||||
)
|
)
|
||||||
component.dateAddedRelativeDate = RelativeDate.WITHIN_1_WEEK
|
const dateCreatedBeforeRelativeButton = datesDropdown.queryAll(
|
||||||
datesDropdown.triggerEventHandler('datesSet')
|
By.css('button')
|
||||||
|
)[1]
|
||||||
|
dateCreatedBeforeRelativeButton.triggerEventHandler('click')
|
||||||
fixture.detectChanges()
|
fixture.detectChanges()
|
||||||
tick(400)
|
tick(400)
|
||||||
expect(component.filterRules).toEqual([
|
expect(component.filterRules).toEqual([
|
||||||
{
|
{
|
||||||
rule_type: FILTER_FULLTEXT_QUERY,
|
rule_type: FILTER_FULLTEXT_QUERY,
|
||||||
value: 'foo,added:[-1 week to now]',
|
value: 'foo,created:[-1 week to now]',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
}))
|
}))
|
||||||
|
@ -135,44 +135,24 @@ const TEXT_FILTER_MODIFIER_NOTNULL = 'not null'
|
|||||||
const TEXT_FILTER_MODIFIER_GT = 'greater'
|
const TEXT_FILTER_MODIFIER_GT = 'greater'
|
||||||
const TEXT_FILTER_MODIFIER_LT = 'less'
|
const TEXT_FILTER_MODIFIER_LT = 'less'
|
||||||
|
|
||||||
const RELATIVE_DATE_QUERY_REGEXP_CREATED = /created:[\["]([^\]]+)[\]"]/g
|
const RELATIVE_DATE_QUERY_REGEXP_CREATED = /created:\[([^\]]+)\]/g
|
||||||
const RELATIVE_DATE_QUERY_REGEXP_ADDED = /added:[\["]([^\]]+)[\]"]/g
|
const RELATIVE_DATE_QUERY_REGEXP_ADDED = /added:\[([^\]]+)\]/g
|
||||||
const RELATIVE_DATE_QUERYSTRINGS = [
|
const RELATIVE_DATE_QUERYSTRINGS = [
|
||||||
{
|
{
|
||||||
relativeDate: RelativeDate.WITHIN_1_WEEK,
|
relativeDate: RelativeDate.WITHIN_1_WEEK,
|
||||||
dateQuery: '-1 week to now',
|
dateQuery: '-1 week to now',
|
||||||
isRange: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
relativeDate: RelativeDate.WITHIN_1_MONTH,
|
relativeDate: RelativeDate.WITHIN_1_MONTH,
|
||||||
dateQuery: '-1 month to now',
|
dateQuery: '-1 month to now',
|
||||||
isRange: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
relativeDate: RelativeDate.WITHIN_3_MONTHS,
|
relativeDate: RelativeDate.WITHIN_3_MONTHS,
|
||||||
dateQuery: '-3 month to now',
|
dateQuery: '-3 month to now',
|
||||||
isRange: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
relativeDate: RelativeDate.WITHIN_1_YEAR,
|
relativeDate: RelativeDate.WITHIN_1_YEAR,
|
||||||
dateQuery: '-1 year to now',
|
dateQuery: '-1 year to now',
|
||||||
isRange: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relativeDate: RelativeDate.THIS_YEAR,
|
|
||||||
dateQuery: 'this year',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relativeDate: RelativeDate.THIS_MONTH,
|
|
||||||
dateQuery: 'this month',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relativeDate: RelativeDate.TODAY,
|
|
||||||
dateQuery: 'today',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relativeDate: RelativeDate.YESTERDAY,
|
|
||||||
dateQuery: 'yesterday',
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -927,11 +907,12 @@ export class FilterEditorComponent
|
|||||||
|
|
||||||
let existingRuleArgs = existingRule?.value.split(',')
|
let existingRuleArgs = existingRule?.value.split(',')
|
||||||
if (this.dateCreatedRelativeDate !== null) {
|
if (this.dateCreatedRelativeDate !== null) {
|
||||||
const rd = RELATIVE_DATE_QUERYSTRINGS.find(
|
|
||||||
(qS) => qS.relativeDate == this.dateCreatedRelativeDate
|
|
||||||
)
|
|
||||||
queryArgs.push(
|
queryArgs.push(
|
||||||
`created:${rd.isRange ? `[${rd.dateQuery}]` : `"${rd.dateQuery}"`}`
|
`created:[${
|
||||||
|
RELATIVE_DATE_QUERYSTRINGS.find(
|
||||||
|
(qS) => qS.relativeDate == this.dateCreatedRelativeDate
|
||||||
|
).dateQuery
|
||||||
|
}]`
|
||||||
)
|
)
|
||||||
if (existingRule) {
|
if (existingRule) {
|
||||||
queryArgs = existingRuleArgs
|
queryArgs = existingRuleArgs
|
||||||
@ -940,11 +921,12 @@ export class FilterEditorComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.dateAddedRelativeDate !== null) {
|
if (this.dateAddedRelativeDate !== null) {
|
||||||
const rd = RELATIVE_DATE_QUERYSTRINGS.find(
|
|
||||||
(qS) => qS.relativeDate == this.dateAddedRelativeDate
|
|
||||||
)
|
|
||||||
queryArgs.push(
|
queryArgs.push(
|
||||||
`added:${rd.isRange ? `[${rd.dateQuery}]` : `"${rd.dateQuery}"`}`
|
`added:[${
|
||||||
|
RELATIVE_DATE_QUERYSTRINGS.find(
|
||||||
|
(qS) => qS.relativeDate == this.dateAddedRelativeDate
|
||||||
|
).dateQuery
|
||||||
|
}]`
|
||||||
)
|
)
|
||||||
if (existingRule) {
|
if (existingRule) {
|
||||||
queryArgs = existingRuleArgs
|
queryArgs = existingRuleArgs
|
||||||
|
@ -58,8 +58,6 @@ export interface WorkflowAction extends ObjectWithId {
|
|||||||
|
|
||||||
assign_custom_fields?: number[] // [CustomField.id]
|
assign_custom_fields?: number[] // [CustomField.id]
|
||||||
|
|
||||||
assign_custom_fields_values?: object
|
|
||||||
|
|
||||||
remove_tags?: number[] // Tag.id
|
remove_tags?: number[] // Tag.id
|
||||||
|
|
||||||
remove_all_tags?: boolean
|
remove_all_tags?: boolean
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Options } from '@popperjs/core'
|
import { Options } from '@popperjs/core'
|
||||||
import { pngxPopperOptions } from './popper-options'
|
import { popperOptionsReenablePreventOverflow } from './popper-options'
|
||||||
|
|
||||||
describe('popperOptionsReenablePreventOverflow', () => {
|
describe('popperOptionsReenablePreventOverflow', () => {
|
||||||
it('should return the config with add padding', () => {
|
it('should return the config without the empty fun preventOverflow, add padding to other', () => {
|
||||||
const config: Partial<Options> = {
|
const config: Partial<Options> = {
|
||||||
modifiers: [
|
modifiers: [
|
||||||
|
{ name: 'preventOverflow', fn: function () {} },
|
||||||
{
|
{
|
||||||
name: 'preventOverflow',
|
name: 'preventOverflow',
|
||||||
fn: function (arg0) {
|
fn: function (arg0) {
|
||||||
@ -14,7 +15,7 @@ describe('popperOptionsReenablePreventOverflow', () => {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = pngxPopperOptions(config)
|
const result = popperOptionsReenablePreventOverflow(config)
|
||||||
|
|
||||||
expect(result.modifiers.length).toBe(1)
|
expect(result.modifiers.length).toBe(1)
|
||||||
expect(result.modifiers[0].name).toBe('preventOverflow')
|
expect(result.modifiers[0].name).toBe('preventOverflow')
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import { Options } from '@popperjs/core'
|
import { Options } from '@popperjs/core'
|
||||||
|
|
||||||
export function pngxPopperOptions(config: Partial<Options>): Partial<Options> {
|
export function popperOptionsReenablePreventOverflow(
|
||||||
const preventOverflowModifier = config.modifiers.find(
|
config: Partial<Options>
|
||||||
|
): Partial<Options> {
|
||||||
|
config.modifiers = config.modifiers?.filter(
|
||||||
|
(m) => !(m.name === 'preventOverflow' && m.fn?.length === 0)
|
||||||
|
)
|
||||||
|
const ogPreventOverflowModifier = config.modifiers.find(
|
||||||
(m) => m.name === 'preventOverflow'
|
(m) => m.name === 'preventOverflow'
|
||||||
)
|
)
|
||||||
if (preventOverflowModifier) {
|
if (ogPreventOverflowModifier) {
|
||||||
preventOverflowModifier.options = {
|
ogPreventOverflowModifier.options = {
|
||||||
padding: 10,
|
padding: 10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,6 @@ def merge(
|
|||||||
*,
|
*,
|
||||||
metadata_document_id: int | None = None,
|
metadata_document_id: int | None = None,
|
||||||
delete_originals: bool = False,
|
delete_originals: bool = False,
|
||||||
archive_fallback: bool = False,
|
|
||||||
user: User | None = None,
|
user: User | None = None,
|
||||||
) -> Literal["OK"]:
|
) -> Literal["OK"]:
|
||||||
logger.info(
|
logger.info(
|
||||||
@ -334,14 +333,7 @@ def merge(
|
|||||||
for doc_id in doc_ids:
|
for doc_id in doc_ids:
|
||||||
doc = qs.get(id=doc_id)
|
doc = qs.get(id=doc_id)
|
||||||
try:
|
try:
|
||||||
doc_path = (
|
with pikepdf.open(str(doc.source_path)) as pdf:
|
||||||
doc.archive_path
|
|
||||||
if archive_fallback
|
|
||||||
and doc.mime_type != "application/pdf"
|
|
||||||
and doc.has_archive_version
|
|
||||||
else doc.source_path
|
|
||||||
)
|
|
||||||
with pikepdf.open(str(doc_path)) as pdf:
|
|
||||||
version = max(version, pdf.pdf_version)
|
version = max(version, pdf.pdf_version)
|
||||||
merged_pdf.pages.extend(pdf.pages)
|
merged_pdf.pages.extend(pdf.pages)
|
||||||
affected_docs.append(doc.id)
|
affected_docs.append(doc.id)
|
||||||
@ -357,7 +349,7 @@ def merge(
|
|||||||
Path(
|
Path(
|
||||||
tempfile.mkdtemp(dir=settings.SCRATCH_DIR),
|
tempfile.mkdtemp(dir=settings.SCRATCH_DIR),
|
||||||
)
|
)
|
||||||
/ f"{'_'.join([str(doc_id) for doc_id in affected_docs])[:100]}_merged.pdf"
|
/ f"{'_'.join([str(doc_id) for doc_id in doc_ids])[:100]}_merged.pdf"
|
||||||
)
|
)
|
||||||
merged_pdf.remove_unreferenced_resources()
|
merged_pdf.remove_unreferenced_resources()
|
||||||
merged_pdf.save(filepath, min_version=version)
|
merged_pdf.save(filepath, min_version=version)
|
||||||
|
@ -806,19 +806,13 @@ class ConsumerPlugin(
|
|||||||
}
|
}
|
||||||
set_permissions_for_object(permissions=permissions, object=document)
|
set_permissions_for_object(permissions=permissions, object=document)
|
||||||
|
|
||||||
if self.metadata.custom_fields:
|
if self.metadata.custom_field_ids:
|
||||||
for field in CustomField.objects.filter(
|
for field_id in self.metadata.custom_field_ids:
|
||||||
id__in=self.metadata.custom_fields.keys(),
|
field = CustomField.objects.get(pk=field_id)
|
||||||
).distinct():
|
CustomFieldInstance.objects.create(
|
||||||
value_field_name = CustomFieldInstance.get_value_field_name(
|
field=field,
|
||||||
data_type=field.data_type,
|
document=document,
|
||||||
)
|
) # adds to document
|
||||||
args = {
|
|
||||||
"field": field,
|
|
||||||
"document": document,
|
|
||||||
value_field_name: self.metadata.custom_fields.get(field.id, None),
|
|
||||||
}
|
|
||||||
CustomFieldInstance.objects.create(**args) # adds to document
|
|
||||||
|
|
||||||
def _write(self, storage_type, source, target):
|
def _write(self, storage_type, source, target):
|
||||||
with (
|
with (
|
||||||
|
@ -29,7 +29,7 @@ class DocumentMetadataOverrides:
|
|||||||
view_groups: list[int] | None = None
|
view_groups: list[int] | None = None
|
||||||
change_users: list[int] | None = None
|
change_users: list[int] | None = None
|
||||||
change_groups: list[int] | None = None
|
change_groups: list[int] | None = None
|
||||||
custom_fields: dict | None = None
|
custom_field_ids: list[int] | None = None
|
||||||
|
|
||||||
def update(self, other: "DocumentMetadataOverrides") -> "DocumentMetadataOverrides":
|
def update(self, other: "DocumentMetadataOverrides") -> "DocumentMetadataOverrides":
|
||||||
"""
|
"""
|
||||||
@ -81,10 +81,11 @@ class DocumentMetadataOverrides:
|
|||||||
self.change_groups.extend(other.change_groups)
|
self.change_groups.extend(other.change_groups)
|
||||||
self.change_groups = list(set(self.change_groups))
|
self.change_groups = list(set(self.change_groups))
|
||||||
|
|
||||||
if self.custom_fields is None:
|
if self.custom_field_ids is None:
|
||||||
self.custom_fields = other.custom_fields
|
self.custom_field_ids = other.custom_field_ids
|
||||||
elif other.custom_fields is not None:
|
elif other.custom_field_ids is not None:
|
||||||
self.custom_fields.update(other.custom_fields)
|
self.custom_field_ids.extend(other.custom_field_ids)
|
||||||
|
self.custom_field_ids = list(set(self.custom_field_ids))
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -113,10 +114,9 @@ class DocumentMetadataOverrides:
|
|||||||
only_with_perms_in=["change_document"],
|
only_with_perms_in=["change_document"],
|
||||||
).values_list("id", flat=True),
|
).values_list("id", flat=True),
|
||||||
)
|
)
|
||||||
overrides.custom_fields = {
|
overrides.custom_field_ids = list(
|
||||||
custom_field.id: custom_field.value
|
doc.custom_fields.values_list("field", flat=True),
|
||||||
for custom_field in doc.custom_fields.all()
|
)
|
||||||
}
|
|
||||||
|
|
||||||
groups_with_perms = get_groups_with_perms(
|
groups_with_perms = get_groups_with_perms(
|
||||||
doc,
|
doc,
|
||||||
|
@ -5,7 +5,6 @@ import re
|
|||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import gnupg
|
import gnupg
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -35,16 +34,16 @@ class GnuPG:
|
|||||||
|
|
||||||
|
|
||||||
def move_documents_and_create_thumbnails(apps, schema_editor):
|
def move_documents_and_create_thumbnails(apps, schema_editor):
|
||||||
(Path(settings.MEDIA_ROOT) / "documents" / "originals").mkdir(
|
os.makedirs(
|
||||||
parents=True,
|
os.path.join(settings.MEDIA_ROOT, "documents", "originals"),
|
||||||
exist_ok=True,
|
exist_ok=True,
|
||||||
)
|
)
|
||||||
(Path(settings.MEDIA_ROOT) / "documents" / "thumbnails").mkdir(
|
os.makedirs(
|
||||||
parents=True,
|
os.path.join(settings.MEDIA_ROOT, "documents", "thumbnails"),
|
||||||
exist_ok=True,
|
exist_ok=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
documents: list[str] = os.listdir(Path(settings.MEDIA_ROOT) / "documents")
|
documents = os.listdir(os.path.join(settings.MEDIA_ROOT, "documents"))
|
||||||
|
|
||||||
if set(documents) == {"originals", "thumbnails"}:
|
if set(documents) == {"originals", "thumbnails"}:
|
||||||
return
|
return
|
||||||
@ -61,7 +60,10 @@ def move_documents_and_create_thumbnails(apps, schema_editor):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
Path(settings.SCRATCH_DIR).mkdir(parents=True, exist_ok=True)
|
try:
|
||||||
|
os.makedirs(settings.SCRATCH_DIR)
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
|
||||||
for f in sorted(documents):
|
for f in sorted(documents):
|
||||||
if not f.endswith("gpg"):
|
if not f.endswith("gpg"):
|
||||||
@ -75,13 +77,14 @@ def move_documents_and_create_thumbnails(apps, schema_editor):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
thumb_temp: str = tempfile.mkdtemp(prefix="paperless", dir=settings.SCRATCH_DIR)
|
thumb_temp = tempfile.mkdtemp(prefix="paperless", dir=settings.SCRATCH_DIR)
|
||||||
orig_temp: str = tempfile.mkdtemp(prefix="paperless", dir=settings.SCRATCH_DIR)
|
orig_temp = tempfile.mkdtemp(prefix="paperless", dir=settings.SCRATCH_DIR)
|
||||||
|
|
||||||
orig_source: Path = Path(settings.MEDIA_ROOT) / "documents" / f
|
orig_source = os.path.join(settings.MEDIA_ROOT, "documents", f)
|
||||||
orig_target: Path = Path(orig_temp) / f.replace(".gpg", "")
|
orig_target = os.path.join(orig_temp, f.replace(".gpg", ""))
|
||||||
|
|
||||||
with orig_source.open("rb") as encrypted, orig_target.open("wb") as unencrypted:
|
with open(orig_source, "rb") as encrypted:
|
||||||
|
with open(orig_target, "wb") as unencrypted:
|
||||||
unencrypted.write(GnuPG.decrypted(encrypted))
|
unencrypted.write(GnuPG.decrypted(encrypted))
|
||||||
|
|
||||||
subprocess.Popen(
|
subprocess.Popen(
|
||||||
@ -92,29 +95,27 @@ def move_documents_and_create_thumbnails(apps, schema_editor):
|
|||||||
"-alpha",
|
"-alpha",
|
||||||
"remove",
|
"remove",
|
||||||
orig_target,
|
orig_target,
|
||||||
Path(thumb_temp) / "convert-%04d.png",
|
os.path.join(thumb_temp, "convert-%04d.png"),
|
||||||
),
|
),
|
||||||
).wait()
|
).wait()
|
||||||
|
|
||||||
thumb_source: Path = Path(thumb_temp) / "convert-0000.png"
|
thumb_source = os.path.join(thumb_temp, "convert-0000.png")
|
||||||
thumb_target: Path = (
|
thumb_target = os.path.join(
|
||||||
Path(settings.MEDIA_ROOT)
|
settings.MEDIA_ROOT,
|
||||||
/ "documents"
|
"documents",
|
||||||
/ "thumbnails"
|
"thumbnails",
|
||||||
/ re.sub(r"(\d+)\.\w+(\.gpg)", "\\1.png\\2", f)
|
re.sub(r"(\d+)\.\w+(\.gpg)", "\\1.png\\2", f),
|
||||||
)
|
)
|
||||||
with (
|
with open(thumb_source, "rb") as unencrypted:
|
||||||
thumb_source.open("rb") as unencrypted,
|
with open(thumb_target, "wb") as encrypted:
|
||||||
thumb_target.open("wb") as encrypted,
|
|
||||||
):
|
|
||||||
encrypted.write(GnuPG.encrypted(unencrypted))
|
encrypted.write(GnuPG.encrypted(unencrypted))
|
||||||
|
|
||||||
shutil.rmtree(thumb_temp)
|
shutil.rmtree(thumb_temp)
|
||||||
shutil.rmtree(orig_temp)
|
shutil.rmtree(orig_temp)
|
||||||
|
|
||||||
shutil.move(
|
shutil.move(
|
||||||
Path(settings.MEDIA_ROOT) / "documents" / f,
|
os.path.join(settings.MEDIA_ROOT, "documents", f),
|
||||||
Path(settings.MEDIA_ROOT) / "documents" / "originals" / f,
|
os.path.join(settings.MEDIA_ROOT, "documents", "originals", f),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Generated by Django 1.9.4 on 2016-03-28 19:09
|
# Generated by Django 1.9.4 on 2016-03-28 19:09
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
from pathlib import Path
|
import os
|
||||||
|
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
import gnupg
|
import gnupg
|
||||||
@ -58,16 +58,16 @@ class Document:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def source_path(self):
|
def source_path(self):
|
||||||
return (
|
return os.path.join(
|
||||||
Path(settings.MEDIA_ROOT)
|
settings.MEDIA_ROOT,
|
||||||
/ "documents"
|
"documents",
|
||||||
/ "originals"
|
"originals",
|
||||||
/ f"{self.pk:07}.{self.file_type}.gpg"
|
f"{self.pk:07}.{self.file_type}.gpg",
|
||||||
).as_posix()
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def source_file(self):
|
def source_file(self):
|
||||||
return Path(self.source_path).open("rb")
|
return open(self.source_path, "rb")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def file_name(self):
|
def file_name(self):
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Generated by Django 3.1.3 on 2020-11-20 11:21
|
# Generated by Django 3.1.3 on 2020-11-20 11:21
|
||||||
from pathlib import Path
|
import os
|
||||||
|
|
||||||
import magic
|
import magic
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -12,15 +12,15 @@ STORAGE_TYPE_UNENCRYPTED = "unencrypted"
|
|||||||
STORAGE_TYPE_GPG = "gpg"
|
STORAGE_TYPE_GPG = "gpg"
|
||||||
|
|
||||||
|
|
||||||
def source_path(self) -> Path:
|
def source_path(self):
|
||||||
if self.filename:
|
if self.filename:
|
||||||
fname: str = str(self.filename)
|
fname = str(self.filename)
|
||||||
else:
|
else:
|
||||||
fname = f"{self.pk:07}.{self.file_type}"
|
fname = f"{self.pk:07}.{self.file_type}"
|
||||||
if self.storage_type == STORAGE_TYPE_GPG:
|
if self.storage_type == STORAGE_TYPE_GPG:
|
||||||
fname += ".gpg"
|
fname += ".gpg"
|
||||||
|
|
||||||
return Path(settings.ORIGINALS_DIR) / fname
|
return os.path.join(settings.ORIGINALS_DIR, fname)
|
||||||
|
|
||||||
|
|
||||||
def add_mime_types(apps, schema_editor):
|
def add_mime_types(apps, schema_editor):
|
||||||
@ -28,7 +28,7 @@ def add_mime_types(apps, schema_editor):
|
|||||||
documents = Document.objects.all()
|
documents = Document.objects.all()
|
||||||
|
|
||||||
for d in documents:
|
for d in documents:
|
||||||
with Path(source_path(d)).open("rb") as f:
|
f = open(source_path(d), "rb")
|
||||||
if d.storage_type == STORAGE_TYPE_GPG:
|
if d.storage_type == STORAGE_TYPE_GPG:
|
||||||
data = GnuPG.decrypted(f)
|
data = GnuPG.decrypted(f)
|
||||||
else:
|
else:
|
||||||
@ -37,13 +37,15 @@ def add_mime_types(apps, schema_editor):
|
|||||||
d.mime_type = magic.from_buffer(data, mime=True)
|
d.mime_type = magic.from_buffer(data, mime=True)
|
||||||
d.save()
|
d.save()
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
def add_file_extensions(apps, schema_editor):
|
def add_file_extensions(apps, schema_editor):
|
||||||
Document = apps.get_model("documents", "Document")
|
Document = apps.get_model("documents", "Document")
|
||||||
documents = Document.objects.all()
|
documents = Document.objects.all()
|
||||||
|
|
||||||
for d in documents:
|
for d in documents:
|
||||||
d.file_type = Path(d.filename).suffix.lstrip(".")
|
d.file_type = os.path.splitext(d.filename)[1].strip(".")
|
||||||
d.save()
|
d.save()
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
# Generated by Django 5.1.6 on 2025-03-01 18:10
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
("documents", "1064_delete_log"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="workflowaction",
|
|
||||||
name="assign_custom_fields_values",
|
|
||||||
field=models.JSONField(
|
|
||||||
blank=True,
|
|
||||||
help_text="Optional values to assign to the custom fields.",
|
|
||||||
null=True,
|
|
||||||
verbose_name="custom field values",
|
|
||||||
default=dict,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -315,7 +315,7 @@ class Document(SoftDeleteModel, ModelWithOwner):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def source_file(self):
|
def source_file(self):
|
||||||
return Path(self.source_path).open("rb")
|
return open(self.source_path, "rb")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_archive_version(self) -> bool:
|
def has_archive_version(self) -> bool:
|
||||||
@ -330,7 +330,7 @@ class Document(SoftDeleteModel, ModelWithOwner):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def archive_file(self):
|
def archive_file(self):
|
||||||
return Path(self.archive_path).open("rb")
|
return open(self.archive_path, "rb")
|
||||||
|
|
||||||
def get_public_filename(self, *, archive=False, counter=0, suffix=None) -> str:
|
def get_public_filename(self, *, archive=False, counter=0, suffix=None) -> str:
|
||||||
"""
|
"""
|
||||||
@ -367,7 +367,7 @@ class Document(SoftDeleteModel, ModelWithOwner):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def thumbnail_file(self):
|
def thumbnail_file(self):
|
||||||
return Path(self.thumbnail_path).open("rb")
|
return open(self.thumbnail_path, "rb")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def created_date(self):
|
def created_date(self):
|
||||||
@ -1271,16 +1271,6 @@ class WorkflowAction(models.Model):
|
|||||||
verbose_name=_("assign these custom fields"),
|
verbose_name=_("assign these custom fields"),
|
||||||
)
|
)
|
||||||
|
|
||||||
assign_custom_fields_values = models.JSONField(
|
|
||||||
_("custom field values"),
|
|
||||||
null=True,
|
|
||||||
blank=True,
|
|
||||||
help_text=_(
|
|
||||||
"Optional values to assign to the custom fields.",
|
|
||||||
),
|
|
||||||
default=dict,
|
|
||||||
)
|
|
||||||
|
|
||||||
remove_tags = models.ManyToManyField(
|
remove_tags = models.ManyToManyField(
|
||||||
Tag,
|
Tag,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
@ -1446,11 +1446,6 @@ class BulkEditSerializer(
|
|||||||
raise serializers.ValidationError("delete_originals must be a boolean")
|
raise serializers.ValidationError("delete_originals must be a boolean")
|
||||||
else:
|
else:
|
||||||
parameters["delete_originals"] = False
|
parameters["delete_originals"] = False
|
||||||
if "archive_fallback" in parameters:
|
|
||||||
if not isinstance(parameters["archive_fallback"], bool):
|
|
||||||
raise serializers.ValidationError("archive_fallback must be a boolean")
|
|
||||||
else:
|
|
||||||
parameters["archive_fallback"] = False
|
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
method = attrs["method"]
|
method = attrs["method"]
|
||||||
@ -2023,7 +2018,6 @@ class WorkflowActionSerializer(serializers.ModelSerializer):
|
|||||||
"assign_change_users",
|
"assign_change_users",
|
||||||
"assign_change_groups",
|
"assign_change_groups",
|
||||||
"assign_custom_fields",
|
"assign_custom_fields",
|
||||||
"assign_custom_fields_values",
|
|
||||||
"remove_all_tags",
|
"remove_all_tags",
|
||||||
"remove_tags",
|
"remove_tags",
|
||||||
"remove_all_correspondents",
|
"remove_all_correspondents",
|
||||||
|
@ -770,40 +770,23 @@ def run_workflows(
|
|||||||
if action.assign_custom_fields.exists():
|
if action.assign_custom_fields.exists():
|
||||||
if not use_overrides:
|
if not use_overrides:
|
||||||
for field in action.assign_custom_fields.all():
|
for field in action.assign_custom_fields.all():
|
||||||
value_field_name = CustomFieldInstance.get_value_field_name(
|
if not CustomFieldInstance.objects.filter(
|
||||||
data_type=field.data_type,
|
|
||||||
)
|
|
||||||
args = {
|
|
||||||
value_field_name: action.assign_custom_fields_values.get(
|
|
||||||
str(field.pk),
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
# for some reason update_or_create doesn't work here
|
|
||||||
instance = CustomFieldInstance.objects.filter(
|
|
||||||
field=field,
|
field=field,
|
||||||
document=document,
|
document=document,
|
||||||
).first()
|
).exists():
|
||||||
if instance:
|
# can be triggered on existing docs, so only add the field if it doesn't already exist
|
||||||
setattr(instance, value_field_name, args[value_field_name])
|
|
||||||
instance.save()
|
|
||||||
else:
|
|
||||||
CustomFieldInstance.objects.create(
|
CustomFieldInstance.objects.create(
|
||||||
**args,
|
|
||||||
field=field,
|
field=field,
|
||||||
document=document,
|
document=document,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if overrides.custom_fields is None:
|
overrides.custom_field_ids = list(
|
||||||
overrides.custom_fields = {}
|
set(
|
||||||
overrides.custom_fields.update(
|
(overrides.custom_field_ids or [])
|
||||||
{
|
+ list(
|
||||||
field.pk: action.assign_custom_fields_values.get(
|
action.assign_custom_fields.values_list("pk", flat=True),
|
||||||
str(field.pk),
|
),
|
||||||
None,
|
),
|
||||||
)
|
|
||||||
for field in action.assign_custom_fields.all()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def removal_action():
|
def removal_action():
|
||||||
@ -961,18 +944,18 @@ def run_workflows(
|
|||||||
if not use_overrides:
|
if not use_overrides:
|
||||||
CustomFieldInstance.objects.filter(document=document).delete()
|
CustomFieldInstance.objects.filter(document=document).delete()
|
||||||
else:
|
else:
|
||||||
overrides.custom_fields = None
|
overrides.custom_field_ids = None
|
||||||
elif action.remove_custom_fields.exists():
|
elif action.remove_custom_fields.exists():
|
||||||
if not use_overrides:
|
if not use_overrides:
|
||||||
CustomFieldInstance.objects.filter(
|
CustomFieldInstance.objects.filter(
|
||||||
field__in=action.remove_custom_fields.all(),
|
field__in=action.remove_custom_fields.all(),
|
||||||
document=document,
|
document=document,
|
||||||
).delete()
|
).delete()
|
||||||
elif overrides.custom_fields:
|
elif overrides.custom_field_ids:
|
||||||
for field in action.remove_custom_fields.filter(
|
for field in action.remove_custom_fields.filter(
|
||||||
pk__in=overrides.custom_fields.keys(),
|
pk__in=overrides.custom_field_ids,
|
||||||
):
|
):
|
||||||
overrides.custom_fields.pop(field.pk, None)
|
overrides.custom_field_ids.remove(field.pk)
|
||||||
|
|
||||||
def email_action():
|
def email_action():
|
||||||
if not settings.EMAIL_ENABLED:
|
if not settings.EMAIL_ENABLED:
|
||||||
|
@ -272,7 +272,7 @@ def update_document_content_maybe_archive_file(document_id):
|
|||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
oldDocument = Document.objects.get(pk=document.pk)
|
oldDocument = Document.objects.get(pk=document.pk)
|
||||||
if parser.get_archive_path():
|
if parser.get_archive_path():
|
||||||
with Path(parser.get_archive_path()).open("rb") as f:
|
with open(parser.get_archive_path(), "rb") as f:
|
||||||
checksum = hashlib.md5(f.read()).hexdigest()
|
checksum = hashlib.md5(f.read()).hexdigest()
|
||||||
# I'm going to save first so that in case the file move
|
# I'm going to save first so that in case the file move
|
||||||
# fails, the database is rolled back.
|
# fails, the database is rolled back.
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
{% extends "paperless-ngx/base.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block head_title %}
|
|
||||||
{% trans "Paperless-ngx account inactive" %}
|
|
||||||
{% endblock head_title %}
|
|
||||||
|
|
||||||
{% block form_top_content %}
|
|
||||||
<h4>{% translate "Account inactve." %}</h4>
|
|
||||||
{% endblock form_top_content %}
|
|
||||||
|
|
||||||
{% block form_content %}
|
|
||||||
{% url 'account_login' as login_url %}
|
|
||||||
<p>{% translate "This account is inactive." %}</p>
|
|
||||||
<div class="d-grid mt-3">
|
|
||||||
<a class="btn btn-lg btn-primary" href="{{ login_url }}">{% translate "Return to login" %}</a>
|
|
||||||
</div>
|
|
||||||
{% endblock form_content %}
|
|
@ -1,5 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
from pathlib import Path
|
import os
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
@ -136,7 +136,10 @@ class TestApiAppConfig(DirectoriesMixin, APITestCase):
|
|||||||
THEN:
|
THEN:
|
||||||
- old app_logo file is deleted
|
- old app_logo file is deleted
|
||||||
"""
|
"""
|
||||||
with (Path(__file__).parent / "samples" / "simple.jpg").open("rb") as f:
|
with open(
|
||||||
|
os.path.join(os.path.dirname(__file__), "samples", "simple.jpg"),
|
||||||
|
"rb",
|
||||||
|
) as f:
|
||||||
self.client.patch(
|
self.client.patch(
|
||||||
f"{self.ENDPOINT}1/",
|
f"{self.ENDPOINT}1/",
|
||||||
{
|
{
|
||||||
@ -145,12 +148,15 @@ class TestApiAppConfig(DirectoriesMixin, APITestCase):
|
|||||||
)
|
)
|
||||||
config = ApplicationConfiguration.objects.first()
|
config = ApplicationConfiguration.objects.first()
|
||||||
old_logo = config.app_logo
|
old_logo = config.app_logo
|
||||||
self.assertTrue(Path(old_logo.path).exists())
|
self.assertTrue(os.path.exists(old_logo.path))
|
||||||
with (Path(__file__).parent / "samples" / "simple.png").open("rb") as f:
|
with open(
|
||||||
|
os.path.join(os.path.dirname(__file__), "samples", "simple.png"),
|
||||||
|
"rb",
|
||||||
|
) as f:
|
||||||
self.client.patch(
|
self.client.patch(
|
||||||
f"{self.ENDPOINT}1/",
|
f"{self.ENDPOINT}1/",
|
||||||
{
|
{
|
||||||
"app_logo": f,
|
"app_logo": f,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.assertFalse(Path(old_logo.path).exists())
|
self.assertFalse(os.path.exists(old_logo.path))
|
||||||
|
@ -28,7 +28,6 @@ from documents.caching import CACHE_50_MINUTES
|
|||||||
from documents.caching import CLASSIFIER_HASH_KEY
|
from documents.caching import CLASSIFIER_HASH_KEY
|
||||||
from documents.caching import CLASSIFIER_MODIFIED_KEY
|
from documents.caching import CLASSIFIER_MODIFIED_KEY
|
||||||
from documents.caching import CLASSIFIER_VERSION_KEY
|
from documents.caching import CLASSIFIER_VERSION_KEY
|
||||||
from documents.data_models import DocumentSource
|
|
||||||
from documents.models import Correspondent
|
from documents.models import Correspondent
|
||||||
from documents.models import CustomField
|
from documents.models import CustomField
|
||||||
from documents.models import CustomFieldInstance
|
from documents.models import CustomFieldInstance
|
||||||
@ -40,10 +39,7 @@ from documents.models import SavedView
|
|||||||
from documents.models import ShareLink
|
from documents.models import ShareLink
|
||||||
from documents.models import StoragePath
|
from documents.models import StoragePath
|
||||||
from documents.models import Tag
|
from documents.models import Tag
|
||||||
from documents.models import Workflow
|
|
||||||
from documents.models import WorkflowAction
|
|
||||||
from documents.models import WorkflowTrigger
|
from documents.models import WorkflowTrigger
|
||||||
from documents.signals.handlers import run_workflows
|
|
||||||
from documents.tests.utils import DirectoriesMixin
|
from documents.tests.utils import DirectoriesMixin
|
||||||
from documents.tests.utils import DocumentConsumeDelayMixin
|
from documents.tests.utils import DocumentConsumeDelayMixin
|
||||||
|
|
||||||
@ -1366,69 +1362,7 @@ class TestDocumentApi(DirectoriesMixin, DocumentConsumeDelayMixin, APITestCase):
|
|||||||
|
|
||||||
self.assertEqual(input_doc.original_file.name, "simple.pdf")
|
self.assertEqual(input_doc.original_file.name, "simple.pdf")
|
||||||
self.assertEqual(overrides.filename, "simple.pdf")
|
self.assertEqual(overrides.filename, "simple.pdf")
|
||||||
self.assertEqual(overrides.custom_fields, {custom_field.id: None})
|
self.assertEqual(overrides.custom_field_ids, [custom_field.id])
|
||||||
|
|
||||||
def test_upload_with_custom_fields_and_workflow(self):
|
|
||||||
"""
|
|
||||||
GIVEN: A document with a source file
|
|
||||||
WHEN: Upload the document with custom fields and a workflow
|
|
||||||
THEN: Metadata is set correctly, mimicking what happens in the real consumer plugin
|
|
||||||
"""
|
|
||||||
self.consume_file_mock.return_value = celery.result.AsyncResult(
|
|
||||||
id=str(uuid.uuid4()),
|
|
||||||
)
|
|
||||||
|
|
||||||
cf = CustomField.objects.create(
|
|
||||||
name="stringfield",
|
|
||||||
data_type=CustomField.FieldDataType.STRING,
|
|
||||||
)
|
|
||||||
cf2 = CustomField.objects.create(
|
|
||||||
name="intfield",
|
|
||||||
data_type=CustomField.FieldDataType.INT,
|
|
||||||
)
|
|
||||||
|
|
||||||
trigger1 = WorkflowTrigger.objects.create(
|
|
||||||
type=WorkflowTrigger.WorkflowTriggerType.CONSUMPTION,
|
|
||||||
sources=f"{DocumentSource.ApiUpload},{DocumentSource.ConsumeFolder},{DocumentSource.MailFetch}",
|
|
||||||
)
|
|
||||||
action1 = WorkflowAction.objects.create(
|
|
||||||
assign_title="Doc title",
|
|
||||||
)
|
|
||||||
action1.assign_custom_fields.add(cf2)
|
|
||||||
action1.assign_custom_fields_values = {cf2.id: 123}
|
|
||||||
action1.save()
|
|
||||||
|
|
||||||
w1 = Workflow.objects.create(
|
|
||||||
name="Workflow 1",
|
|
||||||
order=0,
|
|
||||||
)
|
|
||||||
w1.triggers.add(trigger1)
|
|
||||||
w1.actions.add(action1)
|
|
||||||
w1.save()
|
|
||||||
|
|
||||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
|
||||||
response = self.client.post(
|
|
||||||
"/api/documents/post_document/",
|
|
||||||
{
|
|
||||||
"document": f,
|
|
||||||
"custom_fields": [cf.id],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
||||||
|
|
||||||
self.consume_file_mock.assert_called_once()
|
|
||||||
|
|
||||||
input_doc, overrides = self.get_last_consume_delay_call_args()
|
|
||||||
|
|
||||||
new_overrides, msg = run_workflows(
|
|
||||||
trigger_type=WorkflowTrigger.WorkflowTriggerType.CONSUMPTION,
|
|
||||||
document=input_doc,
|
|
||||||
logging_group=None,
|
|
||||||
overrides=overrides,
|
|
||||||
)
|
|
||||||
overrides.update(new_overrides)
|
|
||||||
self.assertEqual(overrides.custom_fields, {cf.id: None, cf2.id: 123})
|
|
||||||
|
|
||||||
def test_upload_with_webui_source(self):
|
def test_upload_with_webui_source(self):
|
||||||
"""
|
"""
|
||||||
|
@ -514,23 +514,12 @@ class TestPDFActions(DirectoriesMixin, TestCase):
|
|||||||
Path(__file__).parent / "samples" / "simple.jpg",
|
Path(__file__).parent / "samples" / "simple.jpg",
|
||||||
img_doc,
|
img_doc,
|
||||||
)
|
)
|
||||||
img_doc_archive = self.dirs.archive_dir / "sample_image.pdf"
|
|
||||||
shutil.copy(
|
|
||||||
Path(__file__).parent
|
|
||||||
/ "samples"
|
|
||||||
/ "documents"
|
|
||||||
/ "originals"
|
|
||||||
/ "0000001.pdf",
|
|
||||||
img_doc_archive,
|
|
||||||
)
|
|
||||||
self.img_doc = Document.objects.create(
|
self.img_doc = Document.objects.create(
|
||||||
checksum="D",
|
checksum="D",
|
||||||
title="D",
|
title="D",
|
||||||
filename=img_doc,
|
filename=img_doc,
|
||||||
mime_type="image/jpeg",
|
mime_type="image/jpeg",
|
||||||
)
|
)
|
||||||
self.img_doc.archive_filename = img_doc_archive
|
|
||||||
self.img_doc.save()
|
|
||||||
|
|
||||||
@mock.patch("documents.tasks.consume_file.s")
|
@mock.patch("documents.tasks.consume_file.s")
|
||||||
def test_merge(self, mock_consume_file):
|
def test_merge(self, mock_consume_file):
|
||||||
@ -616,32 +605,6 @@ class TestPDFActions(DirectoriesMixin, TestCase):
|
|||||||
doc_ids,
|
doc_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
@mock.patch("documents.tasks.consume_file.s")
|
|
||||||
def test_merge_with_archive_fallback(self, mock_consume_file):
|
|
||||||
"""
|
|
||||||
GIVEN:
|
|
||||||
- Existing documents
|
|
||||||
WHEN:
|
|
||||||
- Merge action is called with 2 documents, one of which is an image and archive_fallback is set to True
|
|
||||||
THEN:
|
|
||||||
- Image document should be included
|
|
||||||
"""
|
|
||||||
doc_ids = [self.doc2.id, self.img_doc.id]
|
|
||||||
|
|
||||||
result = bulk_edit.merge(doc_ids, archive_fallback=True)
|
|
||||||
self.assertEqual(result, "OK")
|
|
||||||
|
|
||||||
expected_filename = (
|
|
||||||
f"{'_'.join([str(doc_id) for doc_id in doc_ids])[:100]}_merged.pdf"
|
|
||||||
)
|
|
||||||
|
|
||||||
mock_consume_file.assert_called()
|
|
||||||
consume_file_args, _ = mock_consume_file.call_args
|
|
||||||
self.assertEqual(
|
|
||||||
Path(consume_file_args[0].original_file).name,
|
|
||||||
expected_filename,
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch("documents.tasks.consume_file.delay")
|
@mock.patch("documents.tasks.consume_file.delay")
|
||||||
@mock.patch("pikepdf.open")
|
@mock.patch("pikepdf.open")
|
||||||
def test_merge_with_errors(self, mock_open_pdf, mock_consume_file):
|
def test_merge_with_errors(self, mock_open_pdf, mock_consume_file):
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -616,7 +617,7 @@ class TestClassifier(DirectoriesMixin, TestCase):
|
|||||||
self.assertListEqual(self.classifier.predict_tags(doc2.content), [])
|
self.assertListEqual(self.classifier.predict_tags(doc2.content), [])
|
||||||
|
|
||||||
def test_load_classifier_not_exists(self):
|
def test_load_classifier_not_exists(self):
|
||||||
self.assertFalse(Path(settings.MODEL_FILE).exists())
|
self.assertFalse(os.path.exists(settings.MODEL_FILE))
|
||||||
self.assertIsNone(load_classifier())
|
self.assertIsNone(load_classifier())
|
||||||
|
|
||||||
@mock.patch("documents.classifier.DocumentClassifier.load")
|
@mock.patch("documents.classifier.DocumentClassifier.load")
|
||||||
@ -631,7 +632,7 @@ class TestClassifier(DirectoriesMixin, TestCase):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
@override_settings(
|
@override_settings(
|
||||||
MODEL_FILE=(Path(__file__).parent / "data" / "model.pickle").as_posix(),
|
MODEL_FILE=os.path.join(os.path.dirname(__file__), "data", "model.pickle"),
|
||||||
)
|
)
|
||||||
@pytest.mark.skip(
|
@pytest.mark.skip(
|
||||||
reason="Disabled caching due to high memory usage - need to investigate.",
|
reason="Disabled caching due to high memory usage - need to investigate.",
|
||||||
@ -647,24 +648,24 @@ class TestClassifier(DirectoriesMixin, TestCase):
|
|||||||
@mock.patch("documents.classifier.DocumentClassifier.load")
|
@mock.patch("documents.classifier.DocumentClassifier.load")
|
||||||
def test_load_classifier_incompatible_version(self, load):
|
def test_load_classifier_incompatible_version(self, load):
|
||||||
Path(settings.MODEL_FILE).touch()
|
Path(settings.MODEL_FILE).touch()
|
||||||
self.assertTrue(Path(settings.MODEL_FILE).exists())
|
self.assertTrue(os.path.exists(settings.MODEL_FILE))
|
||||||
|
|
||||||
load.side_effect = IncompatibleClassifierVersionError("Dummy Error")
|
load.side_effect = IncompatibleClassifierVersionError("Dummy Error")
|
||||||
self.assertIsNone(load_classifier())
|
self.assertIsNone(load_classifier())
|
||||||
self.assertFalse(Path(settings.MODEL_FILE).exists())
|
self.assertFalse(os.path.exists(settings.MODEL_FILE))
|
||||||
|
|
||||||
@mock.patch("documents.classifier.DocumentClassifier.load")
|
@mock.patch("documents.classifier.DocumentClassifier.load")
|
||||||
def test_load_classifier_os_error(self, load):
|
def test_load_classifier_os_error(self, load):
|
||||||
Path(settings.MODEL_FILE).touch()
|
Path(settings.MODEL_FILE).touch()
|
||||||
self.assertTrue(Path(settings.MODEL_FILE).exists())
|
self.assertTrue(os.path.exists(settings.MODEL_FILE))
|
||||||
|
|
||||||
load.side_effect = OSError()
|
load.side_effect = OSError()
|
||||||
self.assertIsNone(load_classifier())
|
self.assertIsNone(load_classifier())
|
||||||
self.assertTrue(Path(settings.MODEL_FILE).exists())
|
self.assertTrue(os.path.exists(settings.MODEL_FILE))
|
||||||
|
|
||||||
def test_load_old_classifier_version(self):
|
def test_load_old_classifier_version(self):
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
Path(__file__).parent / "data" / "v1.17.4.model.pickle",
|
os.path.join(os.path.dirname(__file__), "data", "v1.17.4.model.pickle"),
|
||||||
self.dirs.scratch_dir,
|
self.dirs.scratch_dir,
|
||||||
)
|
)
|
||||||
with override_settings(
|
with override_settings(
|
||||||
|
@ -408,9 +408,7 @@ class TestConsumer(
|
|||||||
|
|
||||||
with self.get_consumer(
|
with self.get_consumer(
|
||||||
self.get_test_file(),
|
self.get_test_file(),
|
||||||
DocumentMetadataOverrides(
|
DocumentMetadataOverrides(custom_field_ids=[cf1.id, cf3.id]),
|
||||||
custom_fields={cf1.id: "value1", cf3.id: "http://example.com"},
|
|
||||||
),
|
|
||||||
) as consumer:
|
) as consumer:
|
||||||
consumer.run()
|
consumer.run()
|
||||||
|
|
||||||
@ -422,11 +420,6 @@ class TestConsumer(
|
|||||||
self.assertIn(cf1, fields_used)
|
self.assertIn(cf1, fields_used)
|
||||||
self.assertNotIn(cf2, fields_used)
|
self.assertNotIn(cf2, fields_used)
|
||||||
self.assertIn(cf3, fields_used)
|
self.assertIn(cf3, fields_used)
|
||||||
self.assertEqual(document.custom_fields.get(field=cf1).value, "value1")
|
|
||||||
self.assertEqual(
|
|
||||||
document.custom_fields.get(field=cf3).value,
|
|
||||||
"http://example.com",
|
|
||||||
)
|
|
||||||
self._assert_first_last_send_progress()
|
self._assert_first_last_send_progress()
|
||||||
|
|
||||||
def testOverrideAsn(self):
|
def testOverrideAsn(self):
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
@ -22,7 +22,7 @@ class TestMakeThumbnails(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
|||||||
filename="test.pdf",
|
filename="test.pdf",
|
||||||
)
|
)
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
Path(__file__).parent / "samples" / "simple.pdf",
|
os.path.join(os.path.dirname(__file__), "samples", "simple.pdf"),
|
||||||
self.d1.source_path,
|
self.d1.source_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class TestMakeThumbnails(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
|||||||
filename="test2.pdf",
|
filename="test2.pdf",
|
||||||
)
|
)
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
Path(__file__).parent / "samples" / "simple.pdf",
|
os.path.join(os.path.dirname(__file__), "samples", "simple.pdf"),
|
||||||
self.d2.source_path,
|
self.d2.source_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ class TestMakeThumbnails(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
|||||||
filename="test3.pdf",
|
filename="test3.pdf",
|
||||||
)
|
)
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
Path(__file__).parent / "samples" / "password-is-test.pdf",
|
os.path.join(os.path.dirname(__file__), "samples", "password-is-test.pdf"),
|
||||||
self.d3.source_path,
|
self.d3.source_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -87,18 +88,18 @@ class TestClassifier(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
|||||||
|
|
||||||
tasks.train_classifier()
|
tasks.train_classifier()
|
||||||
self.assertIsFile(settings.MODEL_FILE)
|
self.assertIsFile(settings.MODEL_FILE)
|
||||||
mtime = Path(settings.MODEL_FILE).stat().st_mtime
|
mtime = os.stat(settings.MODEL_FILE).st_mtime
|
||||||
|
|
||||||
tasks.train_classifier()
|
tasks.train_classifier()
|
||||||
self.assertIsFile(settings.MODEL_FILE)
|
self.assertIsFile(settings.MODEL_FILE)
|
||||||
mtime2 = Path(settings.MODEL_FILE).stat().st_mtime
|
mtime2 = os.stat(settings.MODEL_FILE).st_mtime
|
||||||
self.assertEqual(mtime, mtime2)
|
self.assertEqual(mtime, mtime2)
|
||||||
|
|
||||||
doc.content = "test2"
|
doc.content = "test2"
|
||||||
doc.save()
|
doc.save()
|
||||||
tasks.train_classifier()
|
tasks.train_classifier()
|
||||||
self.assertIsFile(settings.MODEL_FILE)
|
self.assertIsFile(settings.MODEL_FILE)
|
||||||
mtime3 = Path(settings.MODEL_FILE).stat().st_mtime
|
mtime3 = os.stat(settings.MODEL_FILE).st_mtime
|
||||||
self.assertNotEqual(mtime2, mtime3)
|
self.assertNotEqual(mtime2, mtime3)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
@ -107,12 +107,12 @@ class TestViews(DirectoriesMixin, TestCase):
|
|||||||
|
|
||||||
content = b"This is a test"
|
content = b"This is a test"
|
||||||
|
|
||||||
with Path(filename).open("wb") as f:
|
with open(filename, "wb") as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
|
||||||
doc = Document.objects.create(
|
doc = Document.objects.create(
|
||||||
title="none",
|
title="none",
|
||||||
filename=Path(filename).name,
|
filename=os.path.basename(filename),
|
||||||
mime_type="application/pdf",
|
mime_type="application/pdf",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -133,9 +133,6 @@ class TestWorkflows(
|
|||||||
action.assign_change_groups.add(self.group1.pk)
|
action.assign_change_groups.add(self.group1.pk)
|
||||||
action.assign_custom_fields.add(self.cf1.pk)
|
action.assign_custom_fields.add(self.cf1.pk)
|
||||||
action.assign_custom_fields.add(self.cf2.pk)
|
action.assign_custom_fields.add(self.cf2.pk)
|
||||||
action.assign_custom_fields_values = {
|
|
||||||
self.cf2.pk: 42,
|
|
||||||
}
|
|
||||||
action.save()
|
action.save()
|
||||||
w = Workflow.objects.create(
|
w = Workflow.objects.create(
|
||||||
name="Workflow 1",
|
name="Workflow 1",
|
||||||
@ -212,10 +209,6 @@ class TestWorkflows(
|
|||||||
list(document.custom_fields.all().values_list("field", flat=True)),
|
list(document.custom_fields.all().values_list("field", flat=True)),
|
||||||
[self.cf1.pk, self.cf2.pk],
|
[self.cf1.pk, self.cf2.pk],
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
|
||||||
document.custom_fields.get(field=self.cf2.pk).value,
|
|
||||||
42,
|
|
||||||
)
|
|
||||||
|
|
||||||
info = cm.output[0]
|
info = cm.output[0]
|
||||||
expected_str = f"Document matched {trigger} from {w}"
|
expected_str = f"Document matched {trigger} from {w}"
|
||||||
@ -1222,11 +1215,11 @@ class TestWorkflows(
|
|||||||
def test_document_updated_workflow_existing_custom_field(self):
|
def test_document_updated_workflow_existing_custom_field(self):
|
||||||
"""
|
"""
|
||||||
GIVEN:
|
GIVEN:
|
||||||
- Existing workflow with UPDATED trigger and action that assigns a custom field with a value
|
- Existing workflow with UPDATED trigger and action that adds a custom field
|
||||||
WHEN:
|
WHEN:
|
||||||
- Document is updated that already contains the field
|
- Document is updated that already contains the field
|
||||||
THEN:
|
THEN:
|
||||||
- Document update succeeds and updates the field
|
- Document update succeeds without trying to re-create the field
|
||||||
"""
|
"""
|
||||||
trigger = WorkflowTrigger.objects.create(
|
trigger = WorkflowTrigger.objects.create(
|
||||||
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
|
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
|
||||||
@ -1234,8 +1227,6 @@ class TestWorkflows(
|
|||||||
)
|
)
|
||||||
action = WorkflowAction.objects.create()
|
action = WorkflowAction.objects.create()
|
||||||
action.assign_custom_fields.add(self.cf1)
|
action.assign_custom_fields.add(self.cf1)
|
||||||
action.assign_custom_fields_values = {self.cf1.pk: "new value"}
|
|
||||||
action.save()
|
|
||||||
w = Workflow.objects.create(
|
w = Workflow.objects.create(
|
||||||
name="Workflow 1",
|
name="Workflow 1",
|
||||||
order=0,
|
order=0,
|
||||||
@ -1260,9 +1251,6 @@ class TestWorkflows(
|
|||||||
format="json",
|
format="json",
|
||||||
)
|
)
|
||||||
|
|
||||||
doc.refresh_from_db()
|
|
||||||
self.assertEqual(doc.custom_fields.get(field=self.cf1).value, "new value")
|
|
||||||
|
|
||||||
def test_document_updated_workflow_merge_permissions(self):
|
def test_document_updated_workflow_merge_permissions(self):
|
||||||
"""
|
"""
|
||||||
GIVEN:
|
GIVEN:
|
||||||
|
@ -1471,10 +1471,7 @@ class PostDocumentView(GenericAPIView):
|
|||||||
created=created,
|
created=created,
|
||||||
asn=archive_serial_number,
|
asn=archive_serial_number,
|
||||||
owner_id=request.user.id,
|
owner_id=request.user.id,
|
||||||
# TODO: set values
|
custom_field_ids=custom_field_ids,
|
||||||
custom_fields={cf_id: None for cf_id in custom_field_ids}
|
|
||||||
if custom_field_ids
|
|
||||||
else None,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
async_task = consume_file.delay(
|
async_task = consume_file.delay(
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -38,9 +38,9 @@ class TestChecks(DirectoriesMixin, TestCase):
|
|||||||
self.assertTrue(msg.msg.endswith("is set but doesn't exist."))
|
self.assertTrue(msg.msg.endswith("is set but doesn't exist."))
|
||||||
|
|
||||||
def test_paths_check_no_access(self):
|
def test_paths_check_no_access(self):
|
||||||
Path(self.dirs.data_dir).chmod(0o000)
|
os.chmod(self.dirs.data_dir, 0o000)
|
||||||
Path(self.dirs.media_dir).chmod(0o000)
|
os.chmod(self.dirs.media_dir, 0o000)
|
||||||
Path(self.dirs.consumption_dir).chmod(0o000)
|
os.chmod(self.dirs.consumption_dir, 0o000)
|
||||||
|
|
||||||
self.addCleanup(os.chmod, self.dirs.data_dir, 0o777)
|
self.addCleanup(os.chmod, self.dirs.data_dir, 0o777)
|
||||||
self.addCleanup(os.chmod, self.dirs.media_dir, 0o777)
|
self.addCleanup(os.chmod, self.dirs.media_dir, 0o777)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from pathlib import Path
|
import os
|
||||||
|
|
||||||
from allauth.account import views as allauth_account_views
|
from allauth.account import views as allauth_account_views
|
||||||
from allauth.mfa.base import views as allauth_mfa_views
|
from allauth.mfa.base import views as allauth_mfa_views
|
||||||
@ -270,7 +270,7 @@ urlpatterns = [
|
|||||||
re_path(
|
re_path(
|
||||||
r"^logo(?P<path>.*)$",
|
r"^logo(?P<path>.*)$",
|
||||||
serve,
|
serve,
|
||||||
kwargs={"document_root": Path(settings.MEDIA_ROOT) / "logo"},
|
kwargs={"document_root": os.path.join(settings.MEDIA_ROOT, "logo")},
|
||||||
),
|
),
|
||||||
# allauth
|
# allauth
|
||||||
path(
|
path(
|
||||||
@ -278,15 +278,10 @@ urlpatterns = [
|
|||||||
include(
|
include(
|
||||||
[
|
[
|
||||||
# see allauth/account/urls.py
|
# see allauth/account/urls.py
|
||||||
# login, logout, signup, account_inactive
|
# login, logout, signup
|
||||||
path("login/", allauth_account_views.login, name="account_login"),
|
path("login/", allauth_account_views.login, name="account_login"),
|
||||||
path("logout/", allauth_account_views.logout, name="account_logout"),
|
path("logout/", allauth_account_views.logout, name="account_logout"),
|
||||||
path("signup/", allauth_account_views.signup, name="account_signup"),
|
path("signup/", allauth_account_views.signup, name="account_signup"),
|
||||||
path(
|
|
||||||
"account_inactive/",
|
|
||||||
allauth_account_views.account_inactive,
|
|
||||||
name="account_inactive",
|
|
||||||
),
|
|
||||||
# password reset
|
# password reset
|
||||||
path(
|
path(
|
||||||
"password/",
|
"password/",
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import os
|
||||||
from email import message_from_bytes
|
from email import message_from_bytes
|
||||||
from email import policy
|
from email import policy
|
||||||
from email.message import Message
|
from email.message import Message
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from gnupg import GPG
|
from gnupg import GPG
|
||||||
@ -50,7 +50,7 @@ class MailMessageDecryptor(MailMessagePreprocessor, LoggingMixin):
|
|||||||
return False
|
return False
|
||||||
if settings.EMAIL_GNUPG_HOME is None:
|
if settings.EMAIL_GNUPG_HOME is None:
|
||||||
return True
|
return True
|
||||||
return Path(settings.EMAIL_GNUPG_HOME).is_dir()
|
return os.path.isdir(settings.EMAIL_GNUPG_HOME)
|
||||||
|
|
||||||
def run(self, message: MailMessage) -> MailMessage:
|
def run(self, message: MailMessage) -> MailMessage:
|
||||||
if not hasattr(message, "obj"):
|
if not hasattr(message, "obj"):
|
||||||
|
@ -159,7 +159,7 @@ class RasterisedDocumentParser(DocumentParser):
|
|||||||
# the whole text, so do not utilize it in that case
|
# the whole text, so do not utilize it in that case
|
||||||
if (
|
if (
|
||||||
sidecar_file is not None
|
sidecar_file is not None
|
||||||
and sidecar_file.is_file()
|
and os.path.isfile(sidecar_file)
|
||||||
and self.settings.mode != "redo"
|
and self.settings.mode != "redo"
|
||||||
):
|
):
|
||||||
text = self.read_file_handle_unicode_errors(sidecar_file)
|
text = self.read_file_handle_unicode_errors(sidecar_file)
|
||||||
@ -174,7 +174,7 @@ class RasterisedDocumentParser(DocumentParser):
|
|||||||
|
|
||||||
# no success with the sidecar file, try PDF
|
# no success with the sidecar file, try PDF
|
||||||
|
|
||||||
if not Path(pdf_file).is_file():
|
if not os.path.isfile(pdf_file):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -368,8 +368,8 @@ class RasterisedDocumentParser(DocumentParser):
|
|||||||
from ocrmypdf import SubprocessOutputError
|
from ocrmypdf import SubprocessOutputError
|
||||||
from ocrmypdf.exceptions import DigitalSignatureError
|
from ocrmypdf.exceptions import DigitalSignatureError
|
||||||
|
|
||||||
archive_path = Path(self.tempdir) / "archive.pdf"
|
archive_path = Path(os.path.join(self.tempdir, "archive.pdf"))
|
||||||
sidecar_file = Path(self.tempdir) / "sidecar.txt"
|
sidecar_file = Path(os.path.join(self.tempdir, "sidecar.txt"))
|
||||||
|
|
||||||
args = self.construct_ocrmypdf_parameters(
|
args = self.construct_ocrmypdf_parameters(
|
||||||
document_path,
|
document_path,
|
||||||
@ -412,8 +412,12 @@ class RasterisedDocumentParser(DocumentParser):
|
|||||||
f"Attempting force OCR to get the text.",
|
f"Attempting force OCR to get the text.",
|
||||||
)
|
)
|
||||||
|
|
||||||
archive_path_fallback = Path(self.tempdir) / "archive-fallback.pdf"
|
archive_path_fallback = Path(
|
||||||
sidecar_file_fallback = Path(self.tempdir) / "sidecar-fallback.txt"
|
os.path.join(self.tempdir, "archive-fallback.pdf"),
|
||||||
|
)
|
||||||
|
sidecar_file_fallback = Path(
|
||||||
|
os.path.join(self.tempdir, "sidecar-fallback.txt"),
|
||||||
|
)
|
||||||
|
|
||||||
# Attempt to run OCR with safe settings.
|
# Attempt to run OCR with safe settings.
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class TestTikaParserAgainstServer:
|
|||||||
== "This is an DOCX test document, also made September 14, 2022"
|
== "This is an DOCX test document, also made September 14, 2022"
|
||||||
)
|
)
|
||||||
assert tika_parser.archive_path is not None
|
assert tika_parser.archive_path is not None
|
||||||
with Path(tika_parser.archive_path).open("rb") as f:
|
with open(tika_parser.archive_path, "rb") as f:
|
||||||
assert b"PDF-" in f.read()[:10]
|
assert b"PDF-" in f.read()[:10]
|
||||||
|
|
||||||
# self.assertEqual(tika_parser.date, datetime.datetime(2022, 9, 14))
|
# self.assertEqual(tika_parser.date, datetime.datetime(2022, 9, 14))
|
||||||
@ -104,7 +104,7 @@ class TestTikaParserAgainstServer:
|
|||||||
in tika_parser.text
|
in tika_parser.text
|
||||||
)
|
)
|
||||||
assert tika_parser.archive_path is not None
|
assert tika_parser.archive_path is not None
|
||||||
with Path(tika_parser.archive_path).open("rb") as f:
|
with open(tika_parser.archive_path, "rb") as f:
|
||||||
assert b"PDF-" in f.read()[:10]
|
assert b"PDF-" in f.read()[:10]
|
||||||
|
|
||||||
def test_tika_fails_multi_part(
|
def test_tika_fails_multi_part(
|
||||||
@ -130,5 +130,5 @@ class TestTikaParserAgainstServer:
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert tika_parser.archive_path is not None
|
assert tika_parser.archive_path is not None
|
||||||
with Path(tika_parser.archive_path).open("rb") as f:
|
with open(tika_parser.archive_path, "rb") as f:
|
||||||
assert b"PDF-" in f.read()[:10]
|
assert b"PDF-" in f.read()[:10]
|
||||||
|
@ -38,7 +38,7 @@ class TestTikaParser:
|
|||||||
|
|
||||||
assert tika_parser.text == "the content"
|
assert tika_parser.text == "the content"
|
||||||
assert tika_parser.archive_path is not None
|
assert tika_parser.archive_path is not None
|
||||||
with Path(tika_parser.archive_path).open("rb") as f:
|
with open(tika_parser.archive_path, "rb") as f:
|
||||||
assert f.read() == b"PDF document"
|
assert f.read() == b"PDF document"
|
||||||
|
|
||||||
assert tika_parser.date == datetime.datetime(
|
assert tika_parser.date == datetime.datetime(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user