Compare commits

..
79 Commits
Author SHA1 Message Date
shamoon 3b7fdb2f37 Bump version to 2.12.1 2024-09-15 20:08:24 -07:00
shamoon bd1f05df24 Merge branch 'dev' 2024-09-15 20:07:59 -07:00
github-actions[bot]andCrowdin Bot eeeec498d4 New Crowdin translations by GitHub Action (#7668)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2024-09-15 19:40:35 -07:00
shamoon 0af2b967e4 Fix: wait to apply tag changes until other changes saved with multiple workflows (#7711) 2024-09-16 01:26:24 +00:00
shamoon 4193401be7 Fix: delete_pages should require ownership (#7714) 2024-09-15 16:24:40 -07:00
shamoon 36df6fd3e5 Enhancement: improve text contrast for selected documents in list view dark mode (#7712) 2024-09-15 11:40:59 -07:00
shamoon 86a540e68e Fix: filter out shown custom fields that have been deleted from saved view edit (#7710) 2024-09-15 08:02:38 -07:00
shamoon fb3a881387 Refactor: allow filterpipe to specify key 2024-09-13 22:21:38 -07:00
shamoon 8e555cce9e Fix: only filter by string or number properties for filter pipe (#7699) 2024-09-13 20:41:31 -07:00
shamoon 4f8e59030e Documentation: move usually-unneeded 'mime-support' from bare-metal docs (#7689) 2024-09-11 12:58:53 -07:00
shamoon 5075d0bab0 Documentation: missed incorrect gpg decryptor reference 2024-09-11 10:53:52 -07:00
shamoon fb3a136b32 Documentation: fix PAPERLESS_ENABLE_GPG_DECRYPTOR (#7688) 2024-09-11 10:39:41 -07:00
shamoon 66a8057e31 Fix: fix display of permissions filter users dropdown 2024-09-11 09:47:48 -07:00
shamoon cb6cf7f771 Chore: Add codecov bundle analysis (#7673) 2024-09-10 17:55:12 -07:00
shamoon 9a7f95865f Chore: mark some more tests as flaky 2024-09-10 16:41:11 -07:00
shamoonanddependabot[bot] 0d1e0bc70e Chore(deps): Bump express and related dependencies in /src-ui (#7674)
* Chore(deps): Bump send and express in /src-ui

Bumps [send](https://github.com/pillarjs/send) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `send` from 0.18.0 to 0.19.0
- [Release notes](https://github.com/pillarjs/send/releases)
- [Changelog](https://github.com/pillarjs/send/blob/master/HISTORY.md)
- [Commits](https://github.com/pillarjs/send/compare/0.18.0...0.19.0)

Updates `express` from 4.19.2 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

---
updated-dependencies:
- dependency-name: send
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Chore(deps): Bump body-parser and express in /src-ui (#7676)

Bumps [body-parser](https://github.com/expressjs/body-parser) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `body-parser` from 1.20.2 to 1.20.3
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3)

Updates `express` from 4.19.2 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

---
updated-dependencies:
- dependency-name: body-parser
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Chore(deps): Bump serve-static and express in /src-ui (#7677)

Bumps [serve-static](https://github.com/expressjs/serve-static) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `serve-static` from 1.15.0 to 1.16.0
- [Release notes](https://github.com/expressjs/serve-static/releases)
- [Changelog](https://github.com/expressjs/serve-static/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...1.16.0)

Updates `express` from 4.19.2 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

---
updated-dependencies:
- dependency-name: serve-static
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 14:02:33 -07:00
shamoon bee963c23d Fix: saved view permissions fixes (#7672) 2024-09-10 13:33:19 -07:00
shamoon f1559b7108 Fix: add permissions to OPTIONS requests for notes (#7661) 2024-09-09 08:34:21 -07:00
github-actions[bot]andshamoon a64a182fc3 Documentation: Add v2.12.0 changelog (#7659)
---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-09-08 18:37:26 -07:00
shamoon aeb49898e5 Bump version to 2.12.0 2024-09-08 17:47:20 -07:00
shamoon a2c8fcd46b Merge branch 'dev' 2024-09-08 17:46:41 -07:00
github-actions[bot]andCrowdin Bot 357ae92d88 New Crowdin translations by GitHub Action (#7658)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2024-09-08 16:53:13 -07:00
github-actions[bot]andCrowdin Bot 74330623b3 New Crowdin translations by GitHub Action (#7528)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2024-09-08 16:51:37 -07:00
Trenton H 3813dc2e18 Chore: Update backend dependencies in bulk (#7656) 2024-09-08 20:03:38 +00:00
Trenton H 3df8be0bc7 Fix: Rework system check so it won't crash if tesseract is not found (#7640) 2024-09-08 12:17:32 -07:00
Lukas Metzgerandshamoon cc25cbc026 Refactor: performance and storage optimization of barcode scanning (#7646)
---------

Co-authored-by: Lukas Metzger <1814751+loewexy@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-09-07 16:11:36 -07:00
shamoon e98d52830f Fix: use JSON for note audit log entries (#7650) 2024-09-07 16:09:11 -07:00
shamoon 4903e4290d Enhancement: re-work mail rule dialog, support multiple include patterns (#7635) 2024-09-05 15:32:03 -07:00
shamoon e1ba1a1898 Fix: correct broken worker src after upgrade to pdfjs v4 (#7626) 2024-09-05 00:26:16 -07:00
shamoon b29c1e91d1 Fix: Re-fix non-clickable scroll wheel in file uploads list (#7591)
This partially reverts commit ee529c2276.
2024-09-04 23:37:23 -07:00
dependabot[bot] a03c7701a5 Chore(deps): Bump cryptography from 42.0.8 to 43.0.1 (#7620)
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.8 to 43.0.1.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.8...43.0.1)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 20:25:09 -07:00
shamoon b8c9d1316c Update bug-report.yml 2024-09-02 16:13:49 -07:00
dependabot[bot]andshamoon a63ef26d38 Chore(deps-dev): Bump the development group with 3 updates (#7608)
* Chore(deps-dev): Bump the development group with 3 updates

Bumps the development group with 3 updates: [ruff](https://github.com/astral-sh/ruff), [pytest-django](https://github.com/pytest-dev/pytest-django) and [mkdocs-material](https://github.com/squidfunk/mkdocs-material).


Updates `ruff` from 0.6.2 to 0.6.3
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.2...0.6.3)

Updates `pytest-django` from 4.8.0 to 4.9.0
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.8.0...v4.9.0)

Updates `mkdocs-material` from 9.5.33 to 9.5.34
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.5.33...9.5.34)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
- dependency-name: pytest-django
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development
- dependency-name: mkdocs-material
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update .pre-commit-config.yaml

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-09-02 23:13:23 +00:00
dependabot[bot] 96b2884458 Chore(deps): Bump rapidfuzz in the small-changes group (#7611)
Bumps the small-changes group with 1 update: [rapidfuzz](https://github.com/rapidfuzz/RapidFuzz).


Updates `rapidfuzz` from 3.9.6 to 3.9.7
- [Release notes](https://github.com/rapidfuzz/RapidFuzz/releases)
- [Changelog](https://github.com/rapidfuzz/RapidFuzz/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/rapidfuzz/RapidFuzz/compare/v3.9.6...v3.9.7)

---
updated-dependencies:
- dependency-name: rapidfuzz
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 15:58:15 -07:00
shamoon 8543202723 Chore: remove unused frontend dependencies (#7607) 2024-09-01 17:11:19 -07:00
dependabot[bot] a63904b7af Chore(deps): Bump tslib from 2.6.3 to 2.7.0 in /src-ui (#7606)
Bumps [tslib](https://github.com/Microsoft/tslib) from 2.6.3 to 2.7.0.
- [Release notes](https://github.com/Microsoft/tslib/releases)
- [Commits](https://github.com/Microsoft/tslib/compare/v2.6.3...v2.7.0)

---
updated-dependencies:
- dependency-name: tslib
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 00:07:08 +00:00
dependabot[bot] eb27bc9e7d Chore(deps-dev): Bump @playwright/test from 1.45.3 to 1.46.1 in /src-ui (#7603)
Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.45.3 to 1.46.1.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.45.3...v1.46.1)

---
updated-dependencies:
- dependency-name: "@playwright/test"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-01 16:58:36 -07:00
dependabot[bot] 489b24ad65 Chore(deps-dev): Bump typescript from 5.4.5 to 5.5.4 in /src-ui (#7604)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.4.5 to 5.5.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.5...v5.5.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-01 16:03:02 -07:00
dependabot[bot] 5349eb2302 Chore(deps-dev): Bump the frontend-eslint-dependencies group (#7600)
Bumps the frontend-eslint-dependencies group in /src-ui with 4 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin), [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser), [@typescript-eslint/utils](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/utils) and [eslint](https://github.com/eslint/eslint).


Updates `@typescript-eslint/eslint-plugin` from 8.0.0 to 8.3.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.3.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.0.0 to 8.3.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.3.0/packages/parser)

Updates `@typescript-eslint/utils` from 8.0.0 to 8.3.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/utils/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.3.0/packages/utils)

Updates `eslint` from 9.8.0 to 9.9.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.8.0...v9.9.1)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-01 22:32:56 +00:00
dependabot[bot] a8fd023398 Chore(deps): Bump the frontend-angular-dependencies group (#7599)
Bumps the frontend-angular-dependencies group in /src-ui with 21 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/cdk](https://github.com/angular/components) | `18.1.3` | `18.2.2` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `18.1.3` | `18.2.2` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `18.1.3` | `18.2.2` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `18.1.3` | `18.2.2` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `18.1.3` | `18.2.2` |
| [@angular/localize](https://github.com/angular/angular) | `18.1.3` | `18.2.2` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `18.1.3` | `18.2.2` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `18.1.3` | `18.2.2` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `18.1.3` | `18.2.2` |
| [@ng-select/ng-select](https://github.com/ng-select/ng-select) | `13.5.0` | `13.7.0` |
| [ng2-pdf-viewer](https://github.com/VadimDez/ng2-pdf-viewer) | `10.2.2` | `10.3.0` |
| [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `18.1.3` | `18.2.2` |
| [@angular-devkit/core](https://github.com/angular/angular-cli) | `18.1.3` | `18.2.2` |
| [@angular-devkit/schematics](https://github.com/angular/angular-cli) | `18.1.3` | `18.2.2` |
| [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) | `18.2.0` | `18.3.0` |
| [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) | `18.2.0` | `18.3.0` |
| [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) | `18.2.0` | `18.3.0` |
| [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) | `18.2.0` | `18.3.0` |
| [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) | `18.2.0` | `18.3.0` |
| [@angular/cli](https://github.com/angular/angular-cli) | `18.1.3` | `18.2.2` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `18.1.3` | `18.2.2` |


Updates `@angular/cdk` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/components/releases)
- [Changelog](https://github.com/angular/components/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/components/compare/18.1.3...18.2.2)

Updates `@angular/common` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/18.2.2/packages/common)

Updates `@angular/compiler` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/18.2.2/packages/compiler)

Updates `@angular/core` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/18.2.2/packages/core)

Updates `@angular/forms` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/18.2.2/packages/forms)

Updates `@angular/localize` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/compare/18.1.3...18.2.2)

Updates `@angular/platform-browser` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/18.2.2/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/18.2.2/packages/platform-browser-dynamic)

Updates `@angular/router` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/18.2.2/packages/router)

Updates `@ng-select/ng-select` from 13.5.0 to 13.7.0
- [Release notes](https://github.com/ng-select/ng-select/releases)
- [Changelog](https://github.com/ng-select/ng-select/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ng-select/ng-select/compare/v13.5.0...v13.7.0)

Updates `ng2-pdf-viewer` from 10.2.2 to 10.3.0
- [Release notes](https://github.com/VadimDez/ng2-pdf-viewer/releases)
- [Changelog](https://github.com/VadimDez/ng2-pdf-viewer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/VadimDez/ng2-pdf-viewer/compare/10.2.2...10.3.0)

Updates `@angular-devkit/build-angular` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular-cli/compare/18.1.3...18.2.2)

Updates `@angular-devkit/core` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular-cli/compare/18.1.3...18.2.2)

Updates `@angular-devkit/schematics` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular-cli/compare/18.1.3...18.2.2)

Updates `@angular-eslint/builder` from 18.2.0 to 18.3.0
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/builder/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v18.3.0/packages/builder)

Updates `@angular-eslint/eslint-plugin` from 18.2.0 to 18.3.0
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v18.3.0/packages/eslint-plugin)

Updates `@angular-eslint/eslint-plugin-template` from 18.2.0 to 18.3.0
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v18.3.0/packages/eslint-plugin-template)

Updates `@angular-eslint/schematics` from 18.2.0 to 18.3.0
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/schematics/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v18.3.0/packages/schematics)

Updates `@angular-eslint/template-parser` from 18.2.0 to 18.3.0
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/template-parser/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v18.3.0/packages/template-parser)

Updates `@angular/cli` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular-cli/compare/18.1.3...18.2.2)

Updates `@angular/compiler-cli` from 18.1.3 to 18.2.2
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/18.2.2/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/cdk"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/common"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-select/ng-select"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: ng2-pdf-viewer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/build-angular"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/schematics"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/builder"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin-template"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/schematics"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/template-parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-01 15:18:46 -07:00
tooomm e34d48d913 Documentation: support use system preferences for light/dark mode (#7586) 2024-08-31 14:36:29 -07:00
shamoon ee529c2276 Fix: fix non-clickable scroll wheel in file uploads list (#7591) 2024-08-31 14:02:47 -07:00
shamoon 3d5e45c20a Fix: deselect file tasks select all button on dismiss (#7592) 2024-08-31 14:02:37 -07:00
shamoon b8283047ae Fix: saved view sidebar heading not always visible (#7584) 2024-08-30 15:43:08 -07:00
shamoon dad3a1ff28 Feature: add Korean language (#7573) 2024-08-28 20:10:23 -07:00
Daniel Bankmannandshamoon ce663398e6 Enhancement: mail message preprocessor for gpg encrypted mails (#7456)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-08-29 00:22:44 +00:00
shamoon f5ec6de047 Fix: correct select field wrapping with long text (#7572) 2024-08-28 16:39:14 -07:00
shamoon 807f788f92 Fix: update ng-bootstrap to fix datepicker bug (#7567) 2024-08-28 07:32:46 -07:00
Dennis Melzerandshamoon eaaaa575b8 Enhancement: allow multiple filename attachment exclusion patterns for a mail rule (#5524)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-08-27 09:31:46 -07:00
dependabot[bot] e21552e053 Chore(deps): Bump pathvalidate in the small-changes group (#7548)
Bumps the small-changes group with 1 update: [pathvalidate](https://github.com/thombashi/pathvalidate).


Updates `pathvalidate` from 3.2.0 to 3.2.1
- [Release notes](https://github.com/thombashi/pathvalidate/releases)
- [Changelog](https://github.com/thombashi/pathvalidate/blob/master/CHANGELOG.md)
- [Commits](https://github.com/thombashi/pathvalidate/compare/v3.2.0...v3.2.1)

---
updated-dependencies:
- dependency-name: pathvalidate
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 16:31:23 +00:00
dependabot[bot] 6a7274c414 Chore(deps): Bump micromatch from 4.0.5 to 4.0.8 in /src-ui (#7551)
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 19:48:12 -07:00
dependabot[bot]andshamoon 35de04a2ce Chore(deps-dev): Bump the development group with 2 updates (#7545)
* Chore(deps-dev): Bump the development group with 2 updates

Bumps the development group with 2 updates: [ruff](https://github.com/astral-sh/ruff) and [mkdocs-material](https://github.com/squidfunk/mkdocs-material).


Updates `ruff` from 0.6.1 to 0.6.2
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.1...0.6.2)

Updates `mkdocs-material` from 9.5.32 to 9.5.33
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.5.32...9.5.33)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
- dependency-name: mkdocs-material
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update .pre-commit-config.yaml

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-08-27 00:53:37 +00:00
Yichi Yang a0c227fe55 Refactor: Use django-filter logic for filtering full text search queries (#7507) 2024-08-24 21:20:43 -07:00
Yichi Yang 057ce29676 Refactor: Reduce number of SQL queries when serializing List[Document] (#7505) 2024-08-24 21:20:24 -07:00
github-actions[bot]andshamoon 982eeb0d24 Documentation: Add v2.11.6 changelog (#7523)
* Changelog v2.11.6 - GHA

* Update changelog.md

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-08-22 21:06:24 -07:00
shamoon dfa25343a3 Bump version to 2.11.6 2024-08-22 20:40:13 -07:00
shamoon dcfb4494c9 Merge branch 'dev' 2024-08-22 20:40:01 -07:00
shamoon 5a1ef27224 Fix: fix nltk tokenizer breaking change (#7522) 2024-08-22 20:32:02 -07:00
github-actions[bot] 6f79ee9877 Changelog v2.11.5 - GHA (#7518)
Co-Authored-By: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-22 20:21:06 -07:00
github-actions[bot] bc0e420d67 Changelog v2.11.5 - GHA (#7518)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-22 17:11:38 -07:00
shamoon 8e34756e6b Bump version to 2.11.5 2024-08-22 16:20:53 -07:00
github-actions[bot]andCrowdin Bot 76951ea482 New Crowdin translations by GitHub Action (#7446)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2024-08-22 16:19:35 -07:00
shamoon b5e4aaa778 Revert "Chore: add line to log indexing"
This reverts commit b34f9c3b20.
2024-08-20 22:11:20 -07:00
shamoon 39998cb34f Update backend translation strings 2024-08-19 23:30:59 -07:00
shamoon a771d2afd9 Fix: use JSON for update archive file auditlog entries (#7503) 2024-08-19 23:29:24 -07:00
dependabot[bot]andshamoon dac3def6b9 Chore(deps): Bump the small-changes group across 1 directory with 6 updates (#7502)
* Chore(deps): Bump the small-changes group across 1 directory with 6 updates

Bumps the small-changes group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [django-filter](https://github.com/carltongibson/django-filter) | `24.2` | `24.3` |
| [django-soft-delete](https://github.com/san4ezy/django_softdelete) | `1.0.13` | `1.0.14` |
| [nltk](https://github.com/nltk/nltk) | `3.8.1` | `3.9.1` |
| [rapidfuzz](https://github.com/rapidfuzz/RapidFuzz) | `3.9.5` | `3.9.6` |
| [watchdog](https://github.com/gorakhargosh/watchdog) | `4.0.1` | `4.0.2` |
| [factory-boy](https://github.com/FactoryBoy/factory_boy) | `3.3.0` | `3.3.1` |



Updates `django-filter` from 24.2 to 24.3
- [Release notes](https://github.com/carltongibson/django-filter/releases)
- [Changelog](https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst)
- [Commits](https://github.com/carltongibson/django-filter/compare/24.2...24.3)

Updates `django-soft-delete` from 1.0.13 to 1.0.14
- [Commits](https://github.com/san4ezy/django_softdelete/commits)

Updates `nltk` from 3.8.1 to 3.9.1
- [Changelog](https://github.com/nltk/nltk/blob/develop/ChangeLog)
- [Commits](https://github.com/nltk/nltk/compare/3.8.1...3.9.1)

Updates `rapidfuzz` from 3.9.5 to 3.9.6
- [Release notes](https://github.com/rapidfuzz/RapidFuzz/releases)
- [Changelog](https://github.com/rapidfuzz/RapidFuzz/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/rapidfuzz/RapidFuzz/compare/v3.9.5...v3.9.6)

Updates `watchdog` from 4.0.1 to 4.0.2
- [Release notes](https://github.com/gorakhargosh/watchdog/releases)
- [Changelog](https://github.com/gorakhargosh/watchdog/blob/master/changelog.rst)
- [Commits](https://github.com/gorakhargosh/watchdog/compare/v4.0.1...v4.0.2)

Updates `factory-boy` from 3.3.0 to 3.3.1
- [Changelog](https://github.com/FactoryBoy/factory_boy/blob/master/docs/changelog.rst)
- [Commits](https://github.com/FactoryBoy/factory_boy/compare/3.3.0...3.3.1)

---
updated-dependencies:
- dependency-name: django-filter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: django-soft-delete
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: nltk
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: rapidfuzz
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: watchdog
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: factory-boy
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: small-changes
...

Signed-off-by: dependabot[bot] <support@github.com>

* Create 1052_document_transaction_id.py

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-08-19 19:51:02 -07:00
shamoon 674b4a839c Fix: respect deskew / rotate pages from AppConfig if set (#7501) 2024-08-19 19:38:40 -07:00
dependabot[bot]andshamoon 037dcb6a11 Chore(deps-dev): Bump the development group with 2 updates (#7497)
* Chore(deps-dev): Bump the development group with 2 updates

Bumps the development group with 2 updates: [ruff](https://github.com/astral-sh/ruff) and [mkdocs-material](https://github.com/squidfunk/mkdocs-material).


Updates `ruff` from 0.5.7 to 0.6.1
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.5.7...0.6.1)

Updates `mkdocs-material` from 9.5.31 to 9.5.32
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.5.31...9.5.32)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development
- dependency-name: mkdocs-material
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update .pre-commit-config.yaml

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-08-20 00:38:54 +00:00
Nicola Apicellaandshamoon ad8c60d153 Documentation: add no-progress-bar option to importer/exporter (#7477)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-08-17 02:57:03 +00:00
dependabot[bot]andshamoon 3ea312e136 Chore(deps-dev): Bump axios from 1.6.7 to 1.7.4 in /src-ui (#7472)
* Revert "Chore(deps): Bump the small-changes group with 3 updates (#7460)"

This reverts commit 0042e3eca4.

* Chore(deps-dev): Bump axios from 1.6.7 to 1.7.4 in /src-ui

Bumps [axios](https://github.com/axios/axios) from 1.6.7 to 1.7.4.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.6.7...v1.7.4)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-15 15:32:14 +00:00
shamoon d2a04743eb Revert "Chore(deps): Bump the small-changes group with 3 updates (#7460)"
This reverts commit 0042e3eca4.

See https://github.com/nltk/nltk/issues/3301
2024-08-15 08:24:17 -07:00
shamoon b34f9c3b20 Chore: add line to log indexing 2024-08-15 08:03:35 -07:00
dependabot[bot]andshamoon fea7b0ec8c Chore(deps-dev): Bump ruff from 0.5.6 to 0.5.7 in the development group (#7457)
* Chore(deps-dev): Bump ruff from 0.5.6 to 0.5.7 in the development group

Bumps the development group with 1 update: [ruff](https://github.com/astral-sh/ruff).


Updates `ruff` from 0.5.6 to 0.5.7
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.5.6...0.5.7)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update .pre-commit-config.yaml

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2024-08-12 22:23:56 +00:00
dependabot[bot] 0042e3eca4 Chore(deps): Bump the small-changes group with 3 updates (#7460)
Bumps the small-changes group with 3 updates: [nltk](https://github.com/nltk/nltk), [rapidfuzz](https://github.com/rapidfuzz/RapidFuzz) and [watchdog](https://github.com/gorakhargosh/watchdog).


Updates `nltk` from 3.8.1 to 3.8.2
- [Changelog](https://github.com/nltk/nltk/blob/develop/ChangeLog)
- [Commits](https://github.com/nltk/nltk/compare/3.8.1...3.8.2)

Updates `rapidfuzz` from 3.9.5 to 3.9.6
- [Release notes](https://github.com/rapidfuzz/RapidFuzz/releases)
- [Changelog](https://github.com/rapidfuzz/RapidFuzz/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/rapidfuzz/RapidFuzz/compare/v3.9.5...v3.9.6)

Updates `watchdog` from 4.0.1 to 4.0.2
- [Release notes](https://github.com/gorakhargosh/watchdog/releases)
- [Changelog](https://github.com/gorakhargosh/watchdog/blob/master/changelog.rst)
- [Commits](https://github.com/gorakhargosh/watchdog/compare/v4.0.1...v4.0.2)

---
updated-dependencies:
- dependency-name: nltk
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: rapidfuzz
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: watchdog
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-12 15:08:38 -07:00
github-actions[bot] 36db6f3d4b Changelog v2.11.4 - GHA (#7442)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-10 09:06:56 -07:00
shamoon 3c633c2015 Bump version to 2.11.4 2024-08-10 08:48:26 -07:00
github-actions[bot]andCrowdin Bot dd8b51de67 New Crowdin translations by GitHub Action (#7350)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2024-08-10 08:36:39 -07:00
shamoon 5fe846de1d Fix: initial upload message not being dismissed (#7438) 2024-08-10 08:32:06 -07:00
github-actions[bot] 4711468598 Changelog v2.11.3 - GHA (#7422)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-08 08:17:59 -07:00
145 changed files with 31193 additions and 16824 deletions

No files matched your search

+2
View File
@@ -14,6 +14,8 @@ flag_management:
# codecov will only comment if coverage changes
comment:
require_changes: true
require_bundle_changes: true
bundle_change_threshold: "1Kb"
coverage:
status:
project:
+2
View File
@@ -110,6 +110,8 @@ body:
options:
- label: I believe this issue is a bug that affects all users of Paperless-ngx, not something specific to my installation.
required: true
- label: This issue is not about the OCR or archive creation of a specific file(s). Otherwise, please see above regarding OCR tools.
required: true
- label: I have already searched for relevant existing issues and discussions before opening this report.
required: true
- label: I have updated the title field above with a concise description.
+25 -1
View File
@@ -260,7 +260,7 @@ jobs:
retention-days: 7
tests-coverage-upload:
name: "Upload Coverage"
name: "Upload to Codecov"
runs-on: ubuntu-22.04
needs:
- tests-backend
@@ -306,6 +306,30 @@ jobs:
# future expansion
flags: backend
directory: src/
-
name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'npm'
cache-dependency-path: 'src-ui/package-lock.json'
-
name: Cache frontend dependencies
id: cache-frontend-deps
uses: actions/cache@v4
with:
path: |
~/.npm
~/.cache
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
-
name: Re-link Angular cli
run: cd src-ui && npm link @angular/cli
-
name: Build frontend and upload analysis
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
run: cd src-ui && ng build --configuration=production
build-docker-image:
name: Build Docker image for ${{ github.ref_name }}
+4 -3
View File
@@ -36,8 +36,9 @@ repos:
exclude_types:
- pofile
- json
- repo: https://github.com/pre-commit/mirrors-prettier
rev: 'v3.1.0'
# See https://github.com/prettier/prettier/issues/15742 for the fork reason
- repo: https://github.com/rbubley/mirrors-prettier
rev: 'v3.3.3'
hooks:
- id: prettier
types_or:
@@ -47,7 +48,7 @@ repos:
exclude: "(^Pipfile\\.lock$)"
# Python hooks
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.5.6'
rev: 'v0.6.4'
hooks:
- id: ruff
- id: ruff-format
+3 -1
View File
@@ -246,7 +246,7 @@ RUN --mount=type=cache,target=/root/.cache/pip/,id=pip-cache \
&& echo "Installing NLTK data" \
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" snowball_data \
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" stopwords \
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" punkt \
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" punkt_tab \
&& echo "Cleaning up image" \
&& apt-get --yes purge ${BUILD_PACKAGES} \
&& apt-get --yes autoremove --purge \
@@ -275,6 +275,8 @@ RUN set -eux \
&& mkdir --parents --verbose /usr/src/paperless/media \
&& mkdir --parents --verbose /usr/src/paperless/consume \
&& mkdir --parents --verbose /usr/src/paperless/export \
&& echo "Creating gnupg directory" \
&& mkdir -m700 --verbose /usr/src/paperless/.gnupg \
&& echo "Adjusting all permissions" \
&& chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \
&& echo "Collecting static files" \
+1 -1
View File
@@ -14,7 +14,7 @@ django-celery-results = "*"
django-compression-middleware = "*"
django-cors-headers = "*"
django-extensions = "*"
django-filter = "~=24.2"
django-filter = "~=24.3"
django-guardian = "*"
django-multiselectfield = "*"
django-soft-delete = "*"
Generated
+1772 -1543
View File
File diff suppressed because it is too large. Load diff
+11 -5
View File
@@ -248,6 +248,7 @@ optional arguments:
-z, --zip
-zn, --zip-name
--data-only
--no-progress-bar
--passphrase
```
@@ -310,6 +311,10 @@ value set in `-zn` or `--zip-name`.
If `--data-only` is provided, only the database will be exported. This option is intended
to facilitate database upgrades without needing to clean documents and thumbnails from the media directory.
If `--no-progress-bar` is provided, the progress bar will be hidden, rendering the
exporter quiet. This option is useful for scripting scenarios, such as when using the
exporter with `crontab`.
If `--passphrase` is provided, it will be used to encrypt certain fields in the export. This value
must be provided to import. If this value is lost, the export cannot be imported.
@@ -331,11 +336,12 @@ and the script does the rest of the work:
document_importer source
```
| Option | Required | Default | Description |
| -------------- | -------- | ------- | ------------------------------------------------------------------------- |
| source | Yes | N/A | The directory containing an export |
| `--data-only` | No | False | If provided, only import data, do not import document files or thumbnails |
| `--passphrase` | No | N/A | If your export was encrypted with a passphrase, must be provided |
| Option | Required | Default | Description |
| ------------------- | -------- | ------- | ------------------------------------------------------------------------- |
| source | Yes | N/A | The directory containing an export |
| `--no-progress-bar` | No | False | If provided, the progress bar will be hidden |
| `--data-only` | No | False | If provided, only import data, do not import document files or thumbnails |
| `--passphrase` | No | N/A | If your export was encrypted with a passphrase, must be provided |
When you use the provided docker compose script, put the export inside
the `export` folder in your paperless source directory. Specify
+54
View File
@@ -690,3 +690,57 @@ More details about configuration option for various providers can be found in th
Once external auth is set up, 'regular' login can be disabled with the [PAPERLESS_DISABLE_REGULAR_LOGIN](configuration.md#PAPERLESS_DISABLE_REGULAR_LOGIN) setting and / or users can be automatically
redirected with the [PAPERLESS_REDIRECT_LOGIN_TO_SSO](configuration.md#PAPERLESS_REDIRECT_LOGIN_TO_SSO) setting.
## Decryption of encrypted emails before consumption {#gpg-decryptor}
Paperless-ngx can be configured to decrypt gpg encrypted emails before consumption.
### Requirements
You need a recent version of `gpg-agent >= 2.1.1` installed on your host.
Your host needs to be setup for decrypting your emails via `gpg-agent`, see this [tutorial](https://www.digitalocean.com/community/tutorials/how-to-use-gpg-to-encrypt-and-sign-messages#encrypt-and-decrypt-messages-with-gpg) for instance.
Test your setup and make sure that you can encrypt and decrypt files using your key
```
gpg --encrypt --armor -r person@email.com name_of_file
gpg --decrypt name_of_file.asc
```
### Setup
First, enable the [PAPERLESS_ENABLE_GPG_DECRYPTOR environment variable](configuration.md#PAPERLESS_ENABLE_GPG_DECRYPTOR).
Then determine your local `gpg-agent.extra` socket by invoking
```
gpgconf --list-dir agent-extra-socket
```
on your host. A possible output is `~/.gnupg/S.gpg-agent.extra`.
Also find the location of your public keyring.
If using docker, you'll need to add the following volume mounts to your `docker-compose.yml` file:
```yaml
webserver:
volumes:
- /home/user/.gnupg/pubring.gpg:/usr/src/paperless/.gnupg/pubring.gpg
- <path to gpg-agent.extra socket>:/usr/src/paperless/.gnupg/S.gpg-agent
```
For a 'bare-metal' installation no further configuration is necessary. If you
want to use a separate `GNUPG_HOME`, you can do so by configuring the [PAPERLESS_EMAIL_GNUPG_HOME environment variable](configuration.md#PAPERLESS_EMAIL_GNUPG_HOME).
### Troubleshooting
- Make sure, that `gpg-agent` is running on your host machine
- Make sure, that encryption and decryption works from inside the container using the `gpg` commands from above.
- Check that all files in `/usr/src/paperless/.gnupg` have correct permissions
```shell
paperless@9da1865df327:~/.gnupg$ ls -al
drwx------ 1 paperless paperless 4096 Aug 18 17:52 .
drwxr-xr-x 1 paperless paperless 4096 Aug 18 17:52 ..
srw------- 1 paperless paperless 0 Aug 18 17:22 S.gpg-agent
-rw------- 1 paperless paperless 147940 Jul 24 10:23 pubring.gpg
```
+189
View File
@@ -1,5 +1,194 @@
# Changelog
## paperless-ngx 2.12.0
### Features / Enhancements
- Enhancement: re-work mail rule dialog, support multiple include patterns [@shamoon](https://github.com/shamoon) ([#7635](https://github.com/paperless-ngx/paperless-ngx/pull/7635))
- Enhancement: add Korean language [@shamoon](https://github.com/shamoon) ([#7573](https://github.com/paperless-ngx/paperless-ngx/pull/7573))
- Enhancement: allow multiple filename attachment exclusion patterns for a mail rule [@MelleD](https://github.com/MelleD) ([#5524](https://github.com/paperless-ngx/paperless-ngx/pull/5524))
- Refactor: Use django-filter logic for filtering full text search queries [@yichi-yang](https://github.com/yichi-yang) ([#7507](https://github.com/paperless-ngx/paperless-ngx/pull/7507))
- Refactor: Reduce number of SQL queries when serializing List[Document] [@yichi-yang](https://github.com/yichi-yang) ([#7505](https://github.com/paperless-ngx/paperless-ngx/pull/7505))
### Bug Fixes
- Fix: use JSON for note audit log entries [@shamoon](https://github.com/shamoon) ([#7650](https://github.com/paperless-ngx/paperless-ngx/pull/7650))
- Fix: Rework system check so it won't crash if tesseract is not found [@stumpylog](https://github.com/stumpylog) ([#7640](https://github.com/paperless-ngx/paperless-ngx/pull/7640))
- Fix: correct broken pdfjs worker src after upgrade to pdfjs v4 [@shamoon](https://github.com/shamoon) ([#7626](https://github.com/paperless-ngx/paperless-ngx/pull/7626))
- Chore: remove unused frontend dependencies [@shamoon](https://github.com/shamoon) ([#7607](https://github.com/paperless-ngx/paperless-ngx/pull/7607))
- Fix: fix non-clickable scroll wheel in file uploads list [@shamoon](https://github.com/shamoon) ([#7591](https://github.com/paperless-ngx/paperless-ngx/pull/7591))
- Fix: deselect file tasks select all button on dismiss [@shamoon](https://github.com/shamoon) ([#7592](https://github.com/paperless-ngx/paperless-ngx/pull/7592))
- Fix: saved view sidebar heading not always visible [@shamoon](https://github.com/shamoon) ([#7584](https://github.com/paperless-ngx/paperless-ngx/pull/7584))
- Fix: correct select field wrapping with long text [@shamoon](https://github.com/shamoon) ([#7572](https://github.com/paperless-ngx/paperless-ngx/pull/7572))
- Fix: update ng-bootstrap to fix datepicker bug [@shamoon](https://github.com/shamoon) ([#7567](https://github.com/paperless-ngx/paperless-ngx/pull/7567))
### Dependencies
<details>
<summary>11 changes</summary>
- Chore(deps): Bump cryptography from 42.0.8 to 43.0.1 [@dependabot](https://github.com/dependabot) ([#7620](https://github.com/paperless-ngx/paperless-ngx/pull/7620))
- Chore(deps-dev): Bump the development group with 3 updates [@dependabot](https://github.com/dependabot) ([#7608](https://github.com/paperless-ngx/paperless-ngx/pull/7608))
- Chore(deps): Bump rapidfuzz from 3.9.6 to 3.9.7 in the small-changes group [@dependabot](https://github.com/dependabot) ([#7611](https://github.com/paperless-ngx/paperless-ngx/pull/7611))
- Chore(deps): Bump tslib from 2.6.3 to 2.7.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#7606](https://github.com/paperless-ngx/paperless-ngx/pull/7606))
- Chore(deps-dev): Bump [@<!---->playwright/test from 1.45.3 to 1.46.1 in /src-ui @dependabot](https://github.com/<!---->playwright/test from 1.45.3 to 1.46.1 in /src-ui @dependabot) ([#7603](https://github.com/paperless-ngx/paperless-ngx/pull/7603))
- Chore(deps-dev): Bump typescript from 5.4.5 to 5.5.4 in /src-ui [@dependabot](https://github.com/dependabot) ([#7604](https://github.com/paperless-ngx/paperless-ngx/pull/7604))
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#7600](https://github.com/paperless-ngx/paperless-ngx/pull/7600))
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 21 updates [@dependabot](https://github.com/dependabot) ([#7599](https://github.com/paperless-ngx/paperless-ngx/pull/7599))
- Chore(deps): Bump pathvalidate from 3.2.0 to 3.2.1 in the small-changes group [@dependabot](https://github.com/dependabot) ([#7548](https://github.com/paperless-ngx/paperless-ngx/pull/7548))
- Chore(deps): Bump micromatch from 4.0.5 to 4.0.8 in /src-ui [@dependabot](https://github.com/dependabot) ([#7551](https://github.com/paperless-ngx/paperless-ngx/pull/7551))
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7545](https://github.com/paperless-ngx/paperless-ngx/pull/7545))
</details>
### All App Changes
<details>
<summary>27 changes</summary>
- Chore: Update backend dependencies in bulk [@stumpylog](https://github.com/stumpylog) ([#7656](https://github.com/paperless-ngx/paperless-ngx/pull/7656))
- Fix: Rework system check so it won't crash if tesseract is not found [@stumpylog](https://github.com/stumpylog) ([#7640](https://github.com/paperless-ngx/paperless-ngx/pull/7640))
- Refactor: performance and storage optimization of barcode scanning [@loewexy](https://github.com/loewexy) ([#7646](https://github.com/paperless-ngx/paperless-ngx/pull/7646))
- Fix: use JSON for note audit log entries [@shamoon](https://github.com/shamoon) ([#7650](https://github.com/paperless-ngx/paperless-ngx/pull/7650))
- Enhancement: re-work mail rule dialog, support multiple include patterns [@shamoon](https://github.com/shamoon) ([#7635](https://github.com/paperless-ngx/paperless-ngx/pull/7635))
- Fix: correct broken pdfjs worker src after upgrade to pdfjs v4 [@shamoon](https://github.com/shamoon) ([#7626](https://github.com/paperless-ngx/paperless-ngx/pull/7626))
- Chore(deps-dev): Bump the development group with 3 updates [@dependabot](https://github.com/dependabot) ([#7608](https://github.com/paperless-ngx/paperless-ngx/pull/7608))
- Chore(deps): Bump rapidfuzz from 3.9.6 to 3.9.7 in the small-changes group [@dependabot](https://github.com/dependabot) ([#7611](https://github.com/paperless-ngx/paperless-ngx/pull/7611))
- Chore: remove unused frontend dependencies [@shamoon](https://github.com/shamoon) ([#7607](https://github.com/paperless-ngx/paperless-ngx/pull/7607))
- Chore(deps): Bump tslib from 2.6.3 to 2.7.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#7606](https://github.com/paperless-ngx/paperless-ngx/pull/7606))
- Chore(deps-dev): Bump [@<!---->playwright/test from 1.45.3 to 1.46.1 in /src-ui @dependabot](https://github.com/<!---->playwright/test from 1.45.3 to 1.46.1 in /src-ui @dependabot) ([#7603](https://github.com/paperless-ngx/paperless-ngx/pull/7603))
- Chore(deps-dev): Bump typescript from 5.4.5 to 5.5.4 in /src-ui [@dependabot](https://github.com/dependabot) ([#7604](https://github.com/paperless-ngx/paperless-ngx/pull/7604))
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#7600](https://github.com/paperless-ngx/paperless-ngx/pull/7600))
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 21 updates [@dependabot](https://github.com/dependabot) ([#7599](https://github.com/paperless-ngx/paperless-ngx/pull/7599))
- Fix: fix non-clickable scroll wheel in file uploads list [@shamoon](https://github.com/shamoon) ([#7591](https://github.com/paperless-ngx/paperless-ngx/pull/7591))
- Fix: deselect file tasks select all button on dismiss [@shamoon](https://github.com/shamoon) ([#7592](https://github.com/paperless-ngx/paperless-ngx/pull/7592))
- Fix: saved view sidebar heading not always visible [@shamoon](https://github.com/shamoon) ([#7584](https://github.com/paperless-ngx/paperless-ngx/pull/7584))
- Enhancement: add Korean language [@shamoon](https://github.com/shamoon) ([#7573](https://github.com/paperless-ngx/paperless-ngx/pull/7573))
- Enhancement: mail message preprocessor for gpg encrypted mails [@dbankmann](https://github.com/dbankmann) ([#7456](https://github.com/paperless-ngx/paperless-ngx/pull/7456))
- Fix: correct select field wrapping with long text [@shamoon](https://github.com/shamoon) ([#7572](https://github.com/paperless-ngx/paperless-ngx/pull/7572))
- Fix: update ng-bootstrap to fix datepicker bug [@shamoon](https://github.com/shamoon) ([#7567](https://github.com/paperless-ngx/paperless-ngx/pull/7567))
- Enhancement: allow multiple filename attachment exclusion patterns for a mail rule [@MelleD](https://github.com/MelleD) ([#5524](https://github.com/paperless-ngx/paperless-ngx/pull/5524))
- Chore(deps): Bump pathvalidate from 3.2.0 to 3.2.1 in the small-changes group [@dependabot](https://github.com/dependabot) ([#7548](https://github.com/paperless-ngx/paperless-ngx/pull/7548))
- Chore(deps): Bump micromatch from 4.0.5 to 4.0.8 in /src-ui [@dependabot](https://github.com/dependabot) ([#7551](https://github.com/paperless-ngx/paperless-ngx/pull/7551))
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7545](https://github.com/paperless-ngx/paperless-ngx/pull/7545))
- Refactor: Use django-filter logic for filtering full text search queries [@yichi-yang](https://github.com/yichi-yang) ([#7507](https://github.com/paperless-ngx/paperless-ngx/pull/7507))
- Refactor: Reduce number of SQL queries when serializing List[Document] [@yichi-yang](https://github.com/yichi-yang) ([#7505](https://github.com/paperless-ngx/paperless-ngx/pull/7505))
</details>
## paperless-ngx 2.11.6
### Bug Fixes
- Fix: fix nltk tokenizer breaking change [@shamoon](https://github.com/shamoon) ([#7522](https://github.com/paperless-ngx/paperless-ngx/pull/7522))
### All App Changes
<details>
<summary>1 change</summary>
- Fix: fix nltk tokenizer breaking change [@shamoon](https://github.com/shamoon) ([#7522](https://github.com/paperless-ngx/paperless-ngx/pull/7522))
</details>
## paperless-ngx 2.11.5
### Bug Fixes
- Fix: use JSON for update archive file auditlog entries [@shamoon](https://github.com/shamoon) ([#7503](https://github.com/paperless-ngx/paperless-ngx/pull/7503))
- Fix: respect deskew / rotate pages from AppConfig if set [@shamoon](https://github.com/shamoon) ([#7501](https://github.com/paperless-ngx/paperless-ngx/pull/7501))
### Dependencies
<details>
<summary>5 changes</summary>
- Chore(deps): Bump the small-changes group across 1 directory with 6 updates [@dependabot](https://github.com/dependabot) ([#7502](https://github.com/paperless-ngx/paperless-ngx/pull/7502))
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7497](https://github.com/paperless-ngx/paperless-ngx/pull/7497))
- Chore(deps-dev): Bump axios from 1.6.7 to 1.7.4 in /src-ui [@dependabot](https://github.com/dependabot) ([#7472](https://github.com/paperless-ngx/paperless-ngx/pull/7472))
- Chore(deps-dev): Bump ruff from 0.5.6 to 0.5.7 in the development group [@dependabot](https://github.com/dependabot) ([#7457](https://github.com/paperless-ngx/paperless-ngx/pull/7457))
- Chore(deps): Bump the small-changes group with 3 updates [@dependabot](https://github.com/dependabot) ([#7460](https://github.com/paperless-ngx/paperless-ngx/pull/7460))
</details>
### All App Changes
<details>
<summary>7 changes</summary>
- Fix: use JSON for update archive file auditlog entries [@shamoon](https://github.com/shamoon) ([#7503](https://github.com/paperless-ngx/paperless-ngx/pull/7503))
- Chore(deps): Bump the small-changes group across 1 directory with 6 updates [@dependabot](https://github.com/dependabot) ([#7502](https://github.com/paperless-ngx/paperless-ngx/pull/7502))
- Fix: respect deskew / rotate pages from AppConfig if set [@shamoon](https://github.com/shamoon) ([#7501](https://github.com/paperless-ngx/paperless-ngx/pull/7501))
- Chore(deps-dev): Bump the development group with 2 updates [@dependabot](https://github.com/dependabot) ([#7497](https://github.com/paperless-ngx/paperless-ngx/pull/7497))
- Chore(deps-dev): Bump axios from 1.6.7 to 1.7.4 in /src-ui [@dependabot](https://github.com/dependabot) ([#7472](https://github.com/paperless-ngx/paperless-ngx/pull/7472))
- Chore(deps-dev): Bump ruff from 0.5.6 to 0.5.7 in the development group [@dependabot](https://github.com/dependabot) ([#7457](https://github.com/paperless-ngx/paperless-ngx/pull/7457))
- Chore(deps): Bump the small-changes group with 3 updates [@dependabot](https://github.com/dependabot) ([#7460](https://github.com/paperless-ngx/paperless-ngx/pull/7460))
</details>
## paperless-ngx 2.11.4
### Bug Fixes
- Fix: initial upload message not being dismissed [@shamoon](https://github.com/shamoon) ([#7438](https://github.com/paperless-ngx/paperless-ngx/pull/7438))
### All App Changes
- Fix: initial upload message not being dismissed [@shamoon](https://github.com/shamoon) ([#7438](https://github.com/paperless-ngx/paperless-ngx/pull/7438))
## paperless-ngx 2.11.3
### Features
- Enhancement: optimize tasks / stats reload [@shamoon](https://github.com/shamoon) ([#7402](https://github.com/paperless-ngx/paperless-ngx/pull/7402))
- Enhancement: allow specifying default currency for Monetary custom field [@shamoon](https://github.com/shamoon) ([#7381](https://github.com/paperless-ngx/paperless-ngx/pull/7381))
- Enhancement: specify when pre-check fails for documents in trash [@shamoon](https://github.com/shamoon) ([#7355](https://github.com/paperless-ngx/paperless-ngx/pull/7355))
### Bug Fixes
- Fix: clear selection after reload for management lists [@shamoon](https://github.com/shamoon) ([#7421](https://github.com/paperless-ngx/paperless-ngx/pull/7421))
- Fix: disable inline create buttons if insufficient permissions [@shamoon](https://github.com/shamoon) ([#7401](https://github.com/paperless-ngx/paperless-ngx/pull/7401))
- Fix: use entire document for dropzone [@shamoon](https://github.com/shamoon) ([#7342](https://github.com/paperless-ngx/paperless-ngx/pull/7342))
### Maintenance
- Chore(deps): Bump stumpylog/image-cleaner-action from 0.7.0 to 0.8.0 in the actions group [@dependabot](https://github.com/dependabot) ([#7371](https://github.com/paperless-ngx/paperless-ngx/pull/7371))
### Dependencies
<details>
<summary>11 changes</summary>
- Chore(deps): Bump django from 4.2.14 to 4.2.15 [@dependabot](https://github.com/dependabot) ([#7412](https://github.com/paperless-ngx/paperless-ngx/pull/7412))
- Chore(deps-dev): Bump the development group with 3 updates [@dependabot](https://github.com/dependabot) ([#7394](https://github.com/paperless-ngx/paperless-ngx/pull/7394))
- Chore(deps): Bump the small-changes group with 5 updates [@dependabot](https://github.com/dependabot) ([#7397](https://github.com/paperless-ngx/paperless-ngx/pull/7397))
- Chore(deps-dev): Bump [@<!---->playwright/test from 1.42.1 to 1.45.3 in /src-ui @dependabot](https://github.com/<!---->playwright/test from 1.42.1 to 1.45.3 in /src-ui @dependabot) ([#7367](https://github.com/paperless-ngx/paperless-ngx/pull/7367))
- Chore(deps-dev): Bump [@<!---->types/node from 20.12.2 to 22.0.2 in /src-ui @dependabot](https://github.com/<!---->types/node from 20.12.2 to 22.0.2 in /src-ui @dependabot) ([#7366](https://github.com/paperless-ngx/paperless-ngx/pull/7366))
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#7365](https://github.com/paperless-ngx/paperless-ngx/pull/7365))
- Chore(deps): Bump uuid from 9.0.1 to 10.0.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#7370](https://github.com/paperless-ngx/paperless-ngx/pull/7370))
- Chore(deps): Bump stumpylog/image-cleaner-action from 0.7.0 to 0.8.0 in the actions group [@dependabot](https://github.com/dependabot) ([#7371](https://github.com/paperless-ngx/paperless-ngx/pull/7371))
- Chore(deps): Bump zone.js from 0.14.4 to 0.14.8 in /src-ui [@dependabot](https://github.com/dependabot) ([#7368](https://github.com/paperless-ngx/paperless-ngx/pull/7368))
- Chore(deps-dev): Bump jest-preset-angular from 14.1.1 to 14.2.2 in /src-ui in the frontend-jest-dependencies group [@dependabot](https://github.com/dependabot) ([#7364](https://github.com/paperless-ngx/paperless-ngx/pull/7364))
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 20 updates [@dependabot](https://github.com/dependabot) ([#7363](https://github.com/paperless-ngx/paperless-ngx/pull/7363))
</details>
### All App Changes
<details>
<summary>15 changes</summary>
- Fix: clear selection after reload for management lists [@shamoon](https://github.com/shamoon) ([#7421](https://github.com/paperless-ngx/paperless-ngx/pull/7421))
- Enhancement: optimize tasks / stats reload [@shamoon](https://github.com/shamoon) ([#7402](https://github.com/paperless-ngx/paperless-ngx/pull/7402))
- Enhancement: allow specifying default currency for Monetary custom field [@shamoon](https://github.com/shamoon) ([#7381](https://github.com/paperless-ngx/paperless-ngx/pull/7381))
- Enhancement: specify when pre-check fails for documents in trash [@shamoon](https://github.com/shamoon) ([#7355](https://github.com/paperless-ngx/paperless-ngx/pull/7355))
- Chore(deps-dev): Bump the development group with 3 updates [@dependabot](https://github.com/dependabot) ([#7394](https://github.com/paperless-ngx/paperless-ngx/pull/7394))
- Fix: disable inline create buttons if insufficient permissions [@shamoon](https://github.com/shamoon) ([#7401](https://github.com/paperless-ngx/paperless-ngx/pull/7401))
- Chore(deps): Bump the small-changes group with 5 updates [@dependabot](https://github.com/dependabot) ([#7397](https://github.com/paperless-ngx/paperless-ngx/pull/7397))
- Chore(deps-dev): Bump [@<!---->playwright/test from 1.42.1 to 1.45.3 in /src-ui @dependabot](https://github.com/<!---->playwright/test from 1.42.1 to 1.45.3 in /src-ui @dependabot) ([#7367](https://github.com/paperless-ngx/paperless-ngx/pull/7367))
- Chore(deps-dev): Bump [@<!---->types/node from 20.12.2 to 22.0.2 in /src-ui @dependabot](https://github.com/<!---->types/node from 20.12.2 to 22.0.2 in /src-ui @dependabot) ([#7366](https://github.com/paperless-ngx/paperless-ngx/pull/7366))
- Chore(deps-dev): Bump the frontend-eslint-dependencies group in /src-ui with 4 updates [@dependabot](https://github.com/dependabot) ([#7365](https://github.com/paperless-ngx/paperless-ngx/pull/7365))
- Chore(deps): Bump uuid from 9.0.1 to 10.0.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#7370](https://github.com/paperless-ngx/paperless-ngx/pull/7370))
- Chore(deps): Bump zone.js from 0.14.4 to 0.14.8 in /src-ui [@dependabot](https://github.com/dependabot) ([#7368](https://github.com/paperless-ngx/paperless-ngx/pull/7368))
- Chore(deps-dev): Bump jest-preset-angular from 14.1.1 to 14.2.2 in /src-ui in the frontend-jest-dependencies group [@dependabot](https://github.com/dependabot) ([#7364](https://github.com/paperless-ngx/paperless-ngx/pull/7364))
- Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 20 updates [@dependabot](https://github.com/dependabot) ([#7363](https://github.com/paperless-ngx/paperless-ngx/pull/7363))
- Fix: use entire document for dropzone [@shamoon](https://github.com/shamoon) ([#7342](https://github.com/paperless-ngx/paperless-ngx/pull/7342))
</details>
## paperless-ngx 2.11.2
### Changes
+21
View File
@@ -1149,6 +1149,18 @@ within your documents.
second, and year last order. Characters D, M, or Y can be shuffled
to meet the required order.
#### [`PAPERLESS_ENABLE_GPG_DECRYPTOR=<bool>`](#PAPERLESS_ENABLE_GPG_DECRYPTOR) {#PAPERLESS_ENABLE_GPG_DECRYPTOR}
: Enable or disable the GPG decryptor for encrypted emails. See [GPG Decryptor](advanced_usage.md#gpg-decryptor) for more information.
Defaults to false.
#### [`PAPERLESS_EMAIL_GNUPG_HOME=<str>`](#PAPERLESS_EMAIL_GNUPG_HOME) {#PAPERLESS_EMAIL_GNUPG_HOME}
: Optional, sets the `GNUPG_HOME` path to use with GPG decryptor for encrypted emails. See [GPG Decryptor](advanced_usage.md#gpg-decryptor) for more information. If not set, defaults to the default `GNUPG_HOME` path.
Defaults to <not set>.
### Polling {#polling}
#### [`PAPERLESS_CONSUMER_POLLING=<num>`](#PAPERLESS_CONSUMER_POLLING) {#PAPERLESS_CONSUMER_POLLING}
@@ -1277,6 +1289,15 @@ combination with PAPERLESS_CONSUMER_BARCODE_UPSCALE bigger than 1.0.
Defaults to "300"
#### [`PAPERLESS_CONSUMER_BARCODE_MAX_PAGES=<int>`](#PAPERLESS_CONSUMER_BARCODE_MAX_PAGES) {#PAPERLESS_CONSUMER_BARCODE_MAX_PAGES}
: Because barcode detection is a computationally-intensive operation, this setting
limits the detection of barcodes to a number of first pages. If your scanner has
a limit for the number of pages that can be scanned it would be sensible to set this
as the limit here.
Defaults to "0", allowing all pages to be checked for barcodes.
#### [`PAPERLESS_CONSUMER_ENABLE_TAG_BARCODE=<bool>`](#PAPERLESS_CONSUMER_ENABLE_TAG_BARCODE) {#PAPERLESS_CONSUMER_ENABLE_TAG_BARCODE}
: Enables the detection of barcodes in the scanned document and
+2 -2
View File
@@ -269,14 +269,13 @@ are released, dependency support is confirmed, etc.
- `libpq-dev` for PostgreSQL
- `libmagic-dev` for mime type detection
- `mariadb-client` for MariaDB compile time
- `mime-support` for mime type detection
- `libzbar0` for barcode detection
- `poppler-utils` for barcode detection
Use this list for your preferred package management:
```
python3 python3-pip python3-dev imagemagick fonts-liberation gnupg libpq-dev default-libmysqlclient-dev pkg-config libmagic-dev mime-support libzbar0 poppler-utils
python3 python3-pip python3-dev imagemagick fonts-liberation gnupg libpq-dev default-libmysqlclient-dev pkg-config libmagic-dev libzbar0 poppler-utils
```
These dependencies are required for OCRmyPDF, which is used for text
@@ -304,6 +303,7 @@ are released, dependency support is confirmed, etc.
- `libatlas-base-dev`
- `libxslt1-dev`
- `mime-support`
You will also need these for installing some of the python dependencies:
+2 -1
View File
@@ -136,7 +136,8 @@ These rules perform the following:
Paperless will check all emails only once and completely ignore messages
that do not match your filters. It will also only perform the rule action
on e-mails that it has consumed documents from.
on e-mails that it has consumed documents from. The filename attachment
patterns can include wildcards and multiple patterns separated by a comma.
The actions all ensure that the same mail is not consumed twice by
different means. These are as follows:
+7 -1
View File
@@ -6,6 +6,12 @@ theme:
text: Roboto
code: Roboto Mono
palette:
# Palette toggle for automatic mode
- media: "(prefers-color-scheme)"
toggle:
icon: material/brightness-auto
name: Switch to light mode
# Palette toggle for light mode
- media: "(prefers-color-scheme: light)"
scheme: default
@@ -18,7 +24,7 @@ theme:
scheme: slate
toggle:
icon: material/brightness-4
name: Switch to light mode
name: Switch to system preference
features:
- navigation.tabs
- navigation.top
+9 -5
View File
@@ -33,6 +33,7 @@
"it-IT": "src/locale/messages.it_IT.xlf",
"ja-JP": "src/locale/messages.ja_JP.xlf",
"lb-LU": "src/locale/messages.lb_LU.xlf",
"ko-KR": "src/locale/messages.ko_KR.xlf",
"nl-NL": "src/locale/messages.nl_NL.xlf",
"no-NO": "src/locale/messages.no_NO.xlf",
"pl-PL": "src/locale/messages.pl_PL.xlf",
@@ -51,8 +52,11 @@
},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./extra-webpack.config.ts"
},
"outputPath": "dist/paperless-ui",
"outputHashing": "none",
"index": "src/index.html",
@@ -66,8 +70,8 @@
"src/assets",
"src/manifest.webmanifest",
{
"glob": "{pdf.worker.min.js,pdf.min.js}",
"input": "node_modules/pdfjs-dist/build/",
"glob": "{pdf.worker.min.mjs,pdf.min.mjs}",
"input": "node_modules/pdfjs-dist/legacy/build/",
"output": "/assets/js/"
}
],
@@ -124,7 +128,7 @@
"defaultConfiguration": ""
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"buildTarget": "paperless-ui:build:en-US"
},
@@ -135,7 +139,7 @@
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"builder": "@angular-builders/custom-webpack:extract-i18n",
"options": {
"buildTarget": "paperless-ui:build"
}
+24
View File
@@ -0,0 +1,24 @@
import * as webpack from 'webpack'
import {
CustomWebpackBrowserSchema,
TargetOptions,
} from '@angular-builders/custom-webpack'
const { codecovWebpackPlugin } = require('@codecov/webpack-plugin')
export default (
config: webpack.Configuration,
options: CustomWebpackBrowserSchema,
targetOptions: TargetOptions
) => {
if (config.plugins) {
config.plugins.push(
codecovWebpackPlugin({
enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined,
bundleName: 'paperless-ngx',
uploadToken: process.env.CODECOV_TOKEN,
})
)
}
return config
}
+160 -161
View File
@@ -358,11 +358,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">235</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">237</context>
<context context-type="linenumber">239</context>
</context-group>
</trans-unit>
<trans-unit id="2501522447884928778" datatype="html">
@@ -560,7 +560,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">51</context>
<context context-type="linenumber">72</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
@@ -641,11 +641,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">270</context>
<context context-type="linenumber">272</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">273</context>
<context context-type="linenumber">275</context>
</context-group>
</trans-unit>
<trans-unit id="2272120016352772836" datatype="html">
@@ -1309,6 +1309,10 @@
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">98</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">103</context>
</context-group>
</trans-unit>
<trans-unit id="1595668988802980095" datatype="html">
<source>Show warning when closing saved views with unsaved changes</source>
@@ -1644,7 +1648,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">50</context>
<context context-type="linenumber">71</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
@@ -1755,7 +1759,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.ts</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">125</context>
</context-group>
</trans-unit>
<trans-unit id="5260584511980773458" datatype="html">
@@ -1773,11 +1777,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">258</context>
<context context-type="linenumber">260</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">260</context>
<context context-type="linenumber">262</context>
</context-group>
</trans-unit>
<trans-unit id="103921551219467537" datatype="html">
@@ -2082,11 +2086,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">218</context>
<context context-type="linenumber">220</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">221</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="3818027200170621545" datatype="html">
@@ -2296,11 +2300,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">249</context>
<context context-type="linenumber">251</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">251</context>
<context context-type="linenumber">253</context>
</context-group>
</trans-unit>
<trans-unit id="4569276013106377105" datatype="html">
@@ -2318,7 +2322,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/permissions-filter-dropdown/permissions-filter-dropdown.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">76</context>
</context-group>
</trans-unit>
<trans-unit id="2941198503117307737" datatype="html">
@@ -2645,47 +2649,47 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">279</context>
<context context-type="linenumber">281</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">282</context>
<context context-type="linenumber">284</context>
</context-group>
</trans-unit>
<trans-unit id="6988090220128974198" datatype="html">
<source>Open documents</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">128</context>
<context context-type="linenumber">130</context>
</context-group>
</trans-unit>
<trans-unit id="5687256342387781369" datatype="html">
<source>Close all</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">148</context>
<context context-type="linenumber">150</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">152</context>
</context-group>
</trans-unit>
<trans-unit id="3897348120591552265" datatype="html">
<source>Manage</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">159</context>
<context context-type="linenumber">161</context>
</context-group>
</trans-unit>
<trans-unit id="7437910965833684826" datatype="html">
<source>Correspondents</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">165</context>
<context context-type="linenumber">167</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">167</context>
<context context-type="linenumber">169</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html</context>
@@ -2696,11 +2700,11 @@
<source>Tags</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">172</context>
<context context-type="linenumber">174</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">177</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.ts</context>
@@ -2731,11 +2735,11 @@
<source>Document Types</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">181</context>
<context context-type="linenumber">183</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">183</context>
<context context-type="linenumber">185</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html</context>
@@ -2746,11 +2750,11 @@
<source>Storage Paths</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">188</context>
<context context-type="linenumber">190</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">190</context>
<context context-type="linenumber">192</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html</context>
@@ -2761,11 +2765,11 @@
<source>Custom Fields</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">195</context>
<context context-type="linenumber">197</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">197</context>
<context context-type="linenumber">199</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.html</context>
@@ -2780,11 +2784,11 @@
<source>Workflows</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">204</context>
<context context-type="linenumber">206</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">206</context>
<context context-type="linenumber">208</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context>
@@ -2795,92 +2799,92 @@
<source>Mail</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">211</context>
<context context-type="linenumber">213</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">216</context>
</context-group>
</trans-unit>
<trans-unit id="7844706011418789951" datatype="html">
<source>Administration</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">229</context>
<context context-type="linenumber">231</context>
</context-group>
</trans-unit>
<trans-unit id="3008420115644088420" datatype="html">
<source>Configuration</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">242</context>
<context context-type="linenumber">244</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">244</context>
<context context-type="linenumber">246</context>
</context-group>
</trans-unit>
<trans-unit id="1534029177398918729" datatype="html">
<source>GitHub</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">291</context>
</context-group>
</trans-unit>
<trans-unit id="4112664765954374539" datatype="html">
<source>is available.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">298,299</context>
<context context-type="linenumber">300,301</context>
</context-group>
</trans-unit>
<trans-unit id="1175891574282637937" datatype="html">
<source>Click to view.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">299</context>
<context context-type="linenumber">301</context>
</context-group>
</trans-unit>
<trans-unit id="9811291095862612" datatype="html">
<source>Paperless-ngx can automatically check for updates</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">303</context>
<context context-type="linenumber">305</context>
</context-group>
</trans-unit>
<trans-unit id="894819944961861800" datatype="html">
<source> How does this work? </source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">310,312</context>
<context context-type="linenumber">312,314</context>
</context-group>
</trans-unit>
<trans-unit id="509090351011426949" datatype="html">
<source>Update available</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">323</context>
<context context-type="linenumber">325</context>
</context-group>
</trans-unit>
<trans-unit id="1542489069631984294" datatype="html">
<source>Sidebar views updated</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.ts</context>
<context context-type="linenumber">209</context>
<context context-type="linenumber">208</context>
</context-group>
</trans-unit>
<trans-unit id="3547923076537026828" datatype="html">
<source>Error updating sidebar views</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.ts</context>
<context context-type="linenumber">212</context>
<context context-type="linenumber">211</context>
</context-group>
</trans-unit>
<trans-unit id="2526035785704676448" datatype="html">
<source>An error occurred while saving update checking settings.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.ts</context>
<context context-type="linenumber">233</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="4580988005648117665" datatype="html">
@@ -3646,162 +3650,166 @@
<context context-type="linenumber">88</context>
</context-group>
</trans-unit>
<trans-unit id="5163375362523428079" datatype="html">
<source>Rule order</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">16</context>
</context-group>
</trans-unit>
<trans-unit id="4086606389696938932" datatype="html">
<source>Account</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">14</context>
<context context-type="linenumber">19</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
<context context-type="linenumber">68</context>
</context-group>
</trans-unit>
<trans-unit id="4348351765075925931" datatype="html">
<source>Paperless will only process mails that match <x id="START_EMPHASISED_TEXT" ctype="x-em" equiv-text="&lt;em&gt;"/>all<x id="CLOSE_EMPHASISED_TEXT" ctype="x-em" equiv-text="&lt;/em&gt;"/> of the criteria specified below.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">24</context>
</context-group>
</trans-unit>
<trans-unit id="7046259383943324039" datatype="html">
<source>Folder</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">15</context>
<context context-type="linenumber">26</context>
</context-group>
</trans-unit>
<trans-unit id="1391527525114848695" datatype="html">
<source>Subfolders must be separated by a delimiter, often a dot (&apos;.&apos;) or slash (&apos;/&apos;), but it varies by mail server.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">15</context>
<context context-type="linenumber">26</context>
</context-group>
</trans-unit>
<trans-unit id="101686279614365671" datatype="html">
<source>Maximum age (days)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">16</context>
</context-group>
</trans-unit>
<trans-unit id="7093509971705471817" datatype="html">
<source>Attachment type</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="559099472394646919" datatype="html">
<source>Consumption scope</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">18</context>
</context-group>
</trans-unit>
<trans-unit id="56643687972548912" datatype="html">
<source>See docs for .eml processing requirements</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">18</context>
</context-group>
</trans-unit>
<trans-unit id="5163375362523428079" datatype="html">
<source>Rule order</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="5488632521862493221" datatype="html">
<source>Paperless will only process mails that match <x id="START_EMPHASISED_TEXT" ctype="x-em" equiv-text="&lt;em&gt;"/>all<x id="CLOSE_EMPHASISED_TEXT" ctype="x-em" equiv-text="&lt;/em&gt;"/> of the filters specified below.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">22</context>
<context context-type="linenumber">27</context>
</context-group>
</trans-unit>
<trans-unit id="6925928412364847639" datatype="html">
<source>Filter from</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="8977094263269822022" datatype="html">
<source>Filter to</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">24</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="8497813481090627874" datatype="html">
<source>Filter subject</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">25</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="7314357616097563149" datatype="html">
<source>Filter body</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">26</context>
<context context-type="linenumber">33</context>
</context-group>
</trans-unit>
<trans-unit id="4603548543464136402" datatype="html">
<source>Filter attachment filename includes</source>
<trans-unit id="559099472394646919" datatype="html">
<source>Consumption scope</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">27</context>
<context context-type="linenumber">39</context>
</context-group>
</trans-unit>
<trans-unit id="4245210767172267486" datatype="html">
<source>Only consume documents which entirely match this filename if specified. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive.</source>
<trans-unit id="56643687972548912" datatype="html">
<source>See docs for .eml processing requirements</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">27</context>
<context context-type="linenumber">39</context>
</context-group>
</trans-unit>
<trans-unit id="6869675473865305593" datatype="html">
<source>Filter attachment filename excluding</source>
<trans-unit id="7093509971705471817" datatype="html">
<source>Attachment type</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">28</context>
<context context-type="linenumber">40</context>
</context-group>
</trans-unit>
<trans-unit id="6774472763442688477" datatype="html">
<source>Do not consume documents which entirely match this filename if specified. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive.</source>
<trans-unit id="2873939123535615966" datatype="html">
<source>Include only files matching</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">28</context>
<context context-type="linenumber">43</context>
</context-group>
</trans-unit>
<trans-unit id="7233407036155150477" datatype="html">
<source>Optional. Wildcards e.g. *.pdf or *invoice* allowed. Can be comma-separated list. Case insensitive.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">43</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="1546332577833742677" datatype="html">
<source>Exclude files matching</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="9216117865911519658" datatype="html">
<source>Action</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">31</context>
<context context-type="linenumber">50</context>
</context-group>
</trans-unit>
<trans-unit id="4274038999388817994" datatype="html">
<source>Action is only performed when documents are consumed from the mail. Mails without attachments remain entirely untouched.</source>
<trans-unit id="7841986067387421166" datatype="html">
<source>Only performed if the mail is processed.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">31</context>
<context context-type="linenumber">50</context>
</context-group>
</trans-unit>
<trans-unit id="1261794314435932203" datatype="html">
<source>Action parameter</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">33</context>
<context context-type="linenumber">52</context>
</context-group>
</trans-unit>
<trans-unit id="6093797930511670257" datatype="html">
<source>Assign title from</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">35</context>
<context context-type="linenumber">54</context>
</context-group>
</trans-unit>
<trans-unit id="5232720756589450549" datatype="html">
<source>Assign owner from rule</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="6695990587380209737" datatype="html">
<source>Assign document type</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">37</context>
<context context-type="linenumber">59</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
@@ -3812,32 +3820,25 @@
<source>Assign correspondent from</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">38</context>
<context context-type="linenumber">60</context>
</context-group>
</trans-unit>
<trans-unit id="4875491778188965469" datatype="html">
<source>Assign correspondent</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">40</context>
<context context-type="linenumber">62</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
<context context-type="linenumber">163</context>
</context-group>
</trans-unit>
<trans-unit id="5232720756589450549" datatype="html">
<source>Assign owner from rule</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">42</context>
</context-group>
</trans-unit>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">69</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
@@ -4929,7 +4930,7 @@
<source>Hide unowned</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/permissions-filter-dropdown/permissions-filter-dropdown.component.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="941924371433275463" datatype="html">
@@ -7097,9 +7098,7 @@
</context-group>
</trans-unit>
<trans-unit id="5195932016807797291" datatype="html">
<source>Correspondent: <x id="PH" equiv-text="this.correspondents.find(
(c) =&gt; c.id == +rule.value
)?.name"/></source>
<source>Correspondent: <x id="PH" equiv-text="this.correspondents.find((c) =&gt; c.id == +rule.value)?.name"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">191,193</context>
@@ -7113,9 +7112,7 @@
</context-group>
</trans-unit>
<trans-unit id="317796810569008208" datatype="html">
<source>Document type: <x id="PH" equiv-text="this.documentTypes.find(
(dt) =&gt; dt.id == +rule.value
)?.name"/></source>
<source>Document type: <x id="PH" equiv-text="this.documentTypes.find((dt) =&gt; dt.id == +rule.value)?.name"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">201,203</context>
@@ -7129,9 +7126,7 @@
</context-group>
</trans-unit>
<trans-unit id="232202047340644471" datatype="html">
<source>Storage path: <x id="PH" equiv-text="this.storagePaths.find(
(sp) =&gt; sp.id == +rule.value
)?.name"/></source>
<source>Storage path: <x id="PH" equiv-text="this.storagePaths.find((sp) =&gt; sp.id == +rule.value)?.name"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">211,213</context>
@@ -7145,69 +7140,66 @@
</context-group>
</trans-unit>
<trans-unit id="8180755793012580465" datatype="html">
<source>Tag: <x id="PH" equiv-text="this.tags.find((t) =&gt; t.id == +rule.value)
?.name"/></source>
<source>Tag: <x id="PH" equiv-text="this.tags.find((t) =&gt; t.id == +rule.value)?.name"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">219,220</context>
<context context-type="linenumber">219,221</context>
</context-group>
</trans-unit>
<trans-unit id="6494566478302448576" datatype="html">
<source>Without any tag</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">225</context>
</context-group>
</trans-unit>
<trans-unit id="6370692707013694620" datatype="html">
<source>Custom fields: <x id="PH" equiv-text="this.customFields.find(
(f) =&gt; f.id == +rule.value
)?.name"/></source>
<source>Custom fields: <x id="PH" equiv-text="this.customFields.find((f) =&gt; f.id == +rule.value)?.name"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">228,230</context>
<context context-type="linenumber">229,231</context>
</context-group>
</trans-unit>
<trans-unit id="5297600960590041873" datatype="html">
<source>Without any custom field</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">234</context>
<context context-type="linenumber">235</context>
</context-group>
</trans-unit>
<trans-unit id="6523384805359286307" datatype="html">
<source>Title: <x id="PH" equiv-text="rule.value"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">238</context>
<context context-type="linenumber">239</context>
</context-group>
</trans-unit>
<trans-unit id="1872523635812236432" datatype="html">
<source>ASN: <x id="PH" equiv-text="rule.value"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">241</context>
<context context-type="linenumber">242</context>
</context-group>
</trans-unit>
<trans-unit id="102674688969746976" datatype="html">
<source>Owner: <x id="PH" equiv-text="rule.value"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">244</context>
<context context-type="linenumber">245</context>
</context-group>
</trans-unit>
<trans-unit id="3550877650686009106" datatype="html">
<source>Owner not in: <x id="PH" equiv-text="rule.value"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">247</context>
<context context-type="linenumber">248</context>
</context-group>
</trans-unit>
<trans-unit id="1082034558646673343" datatype="html">
<source>Without an owner</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">250</context>
<context context-type="linenumber">251</context>
</context-group>
</trans-unit>
<trans-unit id="7210076240260527720" datatype="html">
@@ -8602,137 +8594,144 @@
<context context-type="linenumber">142</context>
</context-group>
</trans-unit>
<trans-unit id="6145439649200570157" datatype="html">
<source>Korean</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">148</context>
</context-group>
</trans-unit>
<trans-unit id="1334425850005897370" datatype="html">
<source>Luxembourgish</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">148</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
<trans-unit id="3071065188816255493" datatype="html">
<source>Dutch</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">154</context>
<context context-type="linenumber">160</context>
</context-group>
</trans-unit>
<trans-unit id="8069284467804715623" datatype="html">
<source>Norwegian</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">160</context>
<context context-type="linenumber">166</context>
</context-group>
</trans-unit>
<trans-unit id="792060551707690640" datatype="html">
<source>Polish</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">166</context>
<context context-type="linenumber">172</context>
</context-group>
</trans-unit>
<trans-unit id="9184513005098760425" datatype="html">
<source>Portuguese (Brazil)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">172</context>
<context context-type="linenumber">178</context>
</context-group>
</trans-unit>
<trans-unit id="153799456510623899" datatype="html">
<source>Portuguese</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">184</context>
</context-group>
</trans-unit>
<trans-unit id="8118856427047826368" datatype="html">
<source>Romanian</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">184</context>
<context context-type="linenumber">190</context>
</context-group>
</trans-unit>
<trans-unit id="7137419789978325708" datatype="html">
<source>Russian</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">190</context>
<context context-type="linenumber">196</context>
</context-group>
</trans-unit>
<trans-unit id="9102963095355753902" datatype="html">
<source>Slovak</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">196</context>
<context context-type="linenumber">202</context>
</context-group>
</trans-unit>
<trans-unit id="4287008301409320881" datatype="html">
<source>Slovenian</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">208</context>
</context-group>
</trans-unit>
<trans-unit id="8608389829607915090" datatype="html">
<source>Serbian</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">208</context>
<context context-type="linenumber">214</context>
</context-group>
</trans-unit>
<trans-unit id="499386805970351976" datatype="html">
<source>Swedish</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="5682359291233237791" datatype="html">
<source>Turkish</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">220</context>
<context context-type="linenumber">226</context>
</context-group>
</trans-unit>
<trans-unit id="3578644052206125685" datatype="html">
<source>Ukrainian</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">226</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="4689443708886954687" datatype="html">
<source>Chinese Simplified</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">232</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="4912706592792948707" datatype="html">
<source>ISO 8601</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">240</context>
<context context-type="linenumber">246</context>
</context-group>
</trans-unit>
<trans-unit id="313643372755303297" datatype="html">
<source>Successfully completed one-time migratration of settings to the database!</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">567</context>
<context context-type="linenumber">573</context>
</context-group>
</trans-unit>
<trans-unit id="5558341108007064934" datatype="html">
<source>Unable to migrate settings to the database, please try saving manually.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">568</context>
<context context-type="linenumber">574</context>
</context-group>
</trans-unit>
<trans-unit id="1168781785897678748" datatype="html">
<source>You can restart the tour from the settings page.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">638</context>
<context context-type="linenumber">644</context>
</context-group>
</trans-unit>
<trans-unit id="3852289441366561594" datatype="html">
+2098 -2246
View File
File diff suppressed because it is too large. Load diff
+30 -30
View File
@@ -11,60 +11,60 @@
},
"private": true,
"dependencies": {
"@angular/cdk": "^18.1.3",
"@angular/common": "~18.1.3",
"@angular/compiler": "~18.1.3",
"@angular/core": "~18.1.3",
"@angular/forms": "~18.1.3",
"@angular/localize": "~18.1.3",
"@angular/platform-browser": "~18.1.3",
"@angular/platform-browser-dynamic": "~18.1.3",
"@angular/router": "~18.1.3",
"@ng-bootstrap/ng-bootstrap": "^17.0.0",
"@ng-select/ng-select": "^13.5.0",
"@angular/cdk": "^18.2.2",
"@angular/common": "~18.2.2",
"@angular/compiler": "~18.2.2",
"@angular/core": "~18.2.2",
"@angular/forms": "~18.2.2",
"@angular/localize": "~18.2.2",
"@angular/platform-browser": "~18.2.2",
"@angular/platform-browser-dynamic": "~18.2.2",
"@angular/router": "~18.2.2",
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
"@ng-select/ng-select": "^13.7.0",
"@ngneat/dirty-check-forms": "^3.0.3",
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.3",
"file-saver": "^2.0.5",
"mime-names": "^1.0.0",
"ng2-pdf-viewer": "^10.2.2",
"ng2-pdf-viewer": "^10.3.0",
"ngx-bootstrap-icons": "^1.9.3",
"ngx-color": "^9.0.0",
"ngx-cookie-service": "^18.0.0",
"ngx-file-drop": "^16.0.0",
"ngx-ui-tour-ng-bootstrap": "^15.0.0",
"rxjs": "^7.8.1",
"tslib": "^2.6.2",
"tslib": "^2.7.0",
"uuid": "^10.0.0",
"zone.js": "^0.14.8"
},
"devDependencies": {
"@angular-builders/custom-webpack": "^18.0.0",
"@angular-builders/jest": "^18.0.0",
"@angular-devkit/build-angular": "^18.1.3",
"@angular-devkit/core": "^18.1.3",
"@angular-devkit/schematics": "^18.1.3",
"@angular-eslint/builder": "18.2.0",
"@angular-eslint/eslint-plugin": "18.2.0",
"@angular-eslint/eslint-plugin-template": "18.2.0",
"@angular-eslint/schematics": "18.2.0",
"@angular-eslint/template-parser": "18.2.0",
"@angular/cli": "~18.1.3",
"@angular/compiler-cli": "~18.1.3",
"@playwright/test": "^1.45.3",
"@angular-devkit/build-angular": "^18.2.2",
"@angular-devkit/core": "^18.2.2",
"@angular-devkit/schematics": "^18.2.2",
"@angular-eslint/builder": "18.3.0",
"@angular-eslint/eslint-plugin": "18.3.0",
"@angular-eslint/eslint-plugin-template": "18.3.0",
"@angular-eslint/schematics": "18.3.0",
"@angular-eslint/template-parser": "18.3.0",
"@angular/cli": "~18.2.2",
"@angular/compiler-cli": "~18.2.2",
"@codecov/webpack-plugin": "^1.0.1",
"@playwright/test": "^1.46.1",
"@types/jest": "^29.5.12",
"@types/node": "^22.0.2",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"@typescript-eslint/eslint-plugin": "^8.3.0",
"@typescript-eslint/parser": "^8.3.0",
"@typescript-eslint/utils": "^8.0.0",
"concurrently": "^8.2.2",
"eslint": "^9.8.0",
"eslint": "^9.9.1",
"jest": "29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-preset-angular": "^14.2.2",
"jest-websocket-mock": "^2.5.0",
"patch-package": "^8.0.0",
"ts-node": "~10.9.1",
"typescript": "^5.3.3",
"wait-on": "^7.2.0"
"typescript": "^5.5.4"
}
}
+2
View File
@@ -24,6 +24,7 @@ import localeFr from '@angular/common/locales/fr'
import localeHu from '@angular/common/locales/hu'
import localeIt from '@angular/common/locales/it'
import localeJa from '@angular/common/locales/ja'
import localeKo from '@angular/common/locales/ko'
import localeLb from '@angular/common/locales/lb'
import localeNl from '@angular/common/locales/nl'
import localeNo from '@angular/common/locales/no'
@@ -55,6 +56,7 @@ registerLocaleData(localeFr)
registerLocaleData(localeHu)
registerLocaleData(localeIt)
registerLocaleData(localeJa)
registerLocaleData(localeKo)
registerLocaleData(localeLb)
registerLocaleData(localeNl)
registerLocaleData(localeNo)
+1 -1
View File
@@ -36,7 +36,7 @@ export class AppComponent implements OnInit, OnDestroy {
private hotKeyService: HotKeyService
) {
let anyWindow = window as any
anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.js'
anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.mjs'
this.settings.updateAppearanceSettings()
}
+2
View File
@@ -347,6 +347,7 @@ import localeFr from '@angular/common/locales/fr'
import localeHu from '@angular/common/locales/hu'
import localeIt from '@angular/common/locales/it'
import localeJa from '@angular/common/locales/ja'
import localeKo from '@angular/common/locales/ko'
import localeLb from '@angular/common/locales/lb'
import localeNl from '@angular/common/locales/nl'
import localeNo from '@angular/common/locales/no'
@@ -378,6 +379,7 @@ registerLocaleData(localeFr)
registerLocaleData(localeHu)
registerLocaleData(localeIt)
registerLocaleData(localeJa)
registerLocaleData(localeKo)
registerLocaleData(localeLb)
registerLocaleData(localeNl)
registerLocaleData(localeNo)
@@ -332,7 +332,7 @@
</ng-template>
</li>
<li [ngbNavItem]="SettingsNavIDs.SavedViews">
<li [ngbNavItem]="SettingsNavIDs.SavedViews" *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.SavedView }">
<a ngbNavLink i18n>Saved views</a>
<ng-template ngbNavContent>
@@ -70,11 +70,11 @@ export class TasksComponent
modal.componentInstance.buttonsEnabled = false
modal.close()
this.tasksService.dismissTasks(tasks)
this.selectedTasks.clear()
this.clearSelection()
})
} else {
this.tasksService.dismissTasks(tasks)
this.selectedTasks.clear()
this.clearSelection()
}
}
@@ -93,33 +93,35 @@
</ul>
<div class="nav-group mt-3 mb-1" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.SavedView }">
@if (savedViewService.loading || savedViewService.sidebarViews?.length > 0) {
@if (savedViewService.loading) {
<h6 class="sidebar-heading px-3 text-muted">
<span i18n>Saved views</span>
@if (savedViewService.loading) {
<div class="spinner-border spinner-border-sm fw-normal ms-2" role="status"></div>
}
<div class="spinner-border spinner-border-sm fw-normal ms-2" role="status"></div>
</h6>
} @else if (savedViewService.sidebarViews?.length > 0) {
<h6 class="sidebar-heading px-3 text-muted">
<span i18n>Saved views</span>
</h6>
<ul class="nav flex-column mb-2" cdkDropList (cdkDropListDropped)="onDrop($event)">
@for (view of savedViewService.sidebarViews; track view.id) {
<li class="nav-item w-100 app-link" cdkDrag [cdkDragDisabled]="!settingsService.organizingSidebarSavedViews"
cdkDragPreviewContainer="parent" cdkDragPreviewClass="navItemDrag" (cdkDragStarted)="onDragStart($event)"
(cdkDragEnded)="onDragEnd($event)">
<a class="nav-link" [class.text-truncate]="!slimSidebarEnabled" routerLink="view/{{view.id}}"
routerLinkActive="active" (click)="closeMenu()" [ngbPopover]="view.name"
[disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave"
popoverClass="popover-slim">
<i-bs class="me-1" name="funnel"></i-bs><span>&nbsp;{{view.name}}</span>
</a>
@if (settingsService.organizingSidebarSavedViews) {
<div class="position-absolute end-0 top-0 px-3 py-2" [class.me-n3]="slimSidebarEnabled" cdkDragHandle>
<i-bs name="grip-vertical"></i-bs>
</div>
}
</li>
}
</ul>
}
<ul class="nav flex-column mb-2" cdkDropList (cdkDropListDropped)="onDrop($event)">
@for (view of savedViewService.sidebarViews; track view.id) {
<li class="nav-item w-100 app-link" cdkDrag [cdkDragDisabled]="!settingsService.organizingSidebarSavedViews"
cdkDragPreviewContainer="parent" cdkDragPreviewClass="navItemDrag" (cdkDragStarted)="onDragStart($event)"
(cdkDragEnded)="onDragEnd($event)">
<a class="nav-link" [class.text-truncate]="!slimSidebarEnabled" routerLink="view/{{view.id}}"
routerLinkActive="active" (click)="closeMenu()" [ngbPopover]="view.name"
[disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave"
popoverClass="popover-slim">
<i-bs class="me-1" name="funnel"></i-bs><span>&nbsp;{{view.name}}</span>
</a>
@if (settingsService.organizingSidebarSavedViews) {
<div class="position-absolute end-0 top-0 px-3 py-2" [class.me-n3]="slimSidebarEnabled" cdkDragHandle>
<i-bs name="grip-vertical"></i-bs>
</div>
}
</li>
}
</ul>
</div>
<div class="nav-group mt-3 mb-1" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Document }">
@@ -115,7 +115,7 @@ describe('AppFrameComponent', () => {
{
provide: SavedViewService,
useValue: {
initialize: () => {},
reload: () => {},
listAll: () =>
of({
all: [saved_views.map((v) => v.id)],
@@ -170,7 +170,7 @@ describe('AppFrameComponent', () => {
.mockReturnValue('Hello World')
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
savedViewSpy = jest.spyOn(savedViewService, 'initialize')
savedViewSpy = jest.spyOn(savedViewService, 'reload')
fixture = TestBed.createComponent(AppFrameComponent)
component = fixture.componentInstance
@@ -35,7 +35,6 @@ import {
} from '@angular/cdk/drag-drop'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ProfileEditDialogComponent } from '../common/profile-edit-dialog/profile-edit-dialog.component'
import { ObjectWithId } from 'src/app/data/object-with-id'
@Component({
selector: 'pngx-app-frame',
@@ -74,7 +73,7 @@ export class AppFrameComponent
PermissionType.SavedView
)
) {
this.savedViewService.initialize()
this.savedViewService.reload()
}
}
@@ -10,36 +10,57 @@
<div class="modal-body">
<div class="row">
<div class="col-md-4">
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name" autocomplete="off"></pngx-input-text>
<pngx-input-select i18n-title title="Account" [items]="accounts" formControlName="account"></pngx-input-select>
<pngx-input-text i18n-title title="Folder" formControlName="folder" i18n-hint hint="Subfolders must be separated by a delimiter, often a dot ('.') or slash ('/'), but it varies by mail server." [error]="error?.folder"></pngx-input-text>
<pngx-input-number i18n-title title="Maximum age (days)" formControlName="maximum_age" [showAdd]="false" [error]="error?.maximum_age"></pngx-input-number>
<pngx-input-select i18n-title title="Attachment type" [items]="attachmentTypeOptions" formControlName="attachment_type"></pngx-input-select>
<pngx-input-select i18n-title title="Consumption scope" [items]="consumptionScopeOptions" formControlName="consumption_scope" i18n-hint hint="See docs for .eml processing requirements"></pngx-input-select>
<pngx-input-number i18n-title title="Rule order" formControlName="order" [showAdd]="false" [error]="error?.order"></pngx-input-number>
<pngx-input-text [horizontal]="true" i18n-title title="Name" formControlName="name" [error]="error?.name" autocomplete="off"></pngx-input-text>
</div>
<div class="col-md-4">
<p class="small" i18n>Paperless will only process mails that match <em>all</em> of the filters specified below.</p>
<pngx-input-text i18n-title title="Filter from" formControlName="filter_from" [error]="error?.filter_from"></pngx-input-text>
<pngx-input-text i18n-title title="Filter to" formControlName="filter_to" [error]="error?.filter_to"></pngx-input-text>
<pngx-input-text i18n-title title="Filter subject" formControlName="filter_subject" [error]="error?.filter_subject"></pngx-input-text>
<pngx-input-text i18n-title title="Filter body" formControlName="filter_body" [error]="error?.filter_body"></pngx-input-text>
<pngx-input-text i18n-title title="Filter attachment filename includes" formControlName="filter_attachment_filename_include" i18n-hint hint="Only consume documents which entirely match this filename if specified. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive." [error]="error?.filter_attachment_filename_include"></pngx-input-text>
<pngx-input-text i18n-title title="Filter attachment filename excluding" formControlName="filter_attachment_filename_exclude" i18n-hint hint="Do not consume documents which entirely match this filename if specified. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive." [error]="error?.filter_attachment_filename_exclude"></pngx-input-text>
<pngx-input-number [horizontal]="true" i18n-title title="Rule order" formControlName="order" [showAdd]="false" [error]="error?.order"></pngx-input-number>
</div>
<div class="col-md-4">
<pngx-input-select i18n-title title="Action" [items]="actionOptions" formControlName="action" i18n-hint hint="Action is only performed when documents are consumed from the mail. Mails without attachments remain entirely untouched."></pngx-input-select>
<pngx-input-select [horizontal]="true" i18n-title title="Account" [items]="accounts" formControlName="account"></pngx-input-select>
</div>
</div>
<hr class="mt-0"/>
<div class="row">
<p class="small" i18n>Paperless will only process mails that match <em>all</em> of the criteria specified below.</p>
<div class="col-md-6">
<pngx-input-text [horizontal]="true" i18n-title title="Folder" formControlName="folder" i18n-hint hint="Subfolders must be separated by a delimiter, often a dot ('.') or slash ('/'), but it varies by mail server." [error]="error?.folder"></pngx-input-text>
<pngx-input-number [horizontal]="true" i18n-title title="Maximum age (days)" formControlName="maximum_age" [showAdd]="false" [error]="error?.maximum_age"></pngx-input-number>
</div>
<div class="col-md-6">
<pngx-input-text [horizontal]="true" i18n-title title="Filter from" formControlName="filter_from" [error]="error?.filter_from"></pngx-input-text>
<pngx-input-text [horizontal]="true" i18n-title title="Filter to" formControlName="filter_to" [error]="error?.filter_to"></pngx-input-text>
<pngx-input-text [horizontal]="true" i18n-title title="Filter subject" formControlName="filter_subject" [error]="error?.filter_subject"></pngx-input-text>
<pngx-input-text [horizontal]="true" i18n-title title="Filter body" formControlName="filter_body" [error]="error?.filter_body"></pngx-input-text>
</div>
</div>
<hr class="mt-0"/>
<div class="row">
<div class="col-md-6">
<pngx-input-select [horizontal]="true" i18n-title title="Consumption scope" [items]="consumptionScopeOptions" formControlName="consumption_scope" i18n-hint hint="See docs for .eml processing requirements"></pngx-input-select>
<pngx-input-select [horizontal]="true" i18n-title title="Attachment type" [items]="attachmentTypeOptions" formControlName="attachment_type"></pngx-input-select>
</div>
<div class="col-md-6">
<pngx-input-text [horizontal]="true" i18n-title title="Include only files matching" formControlName="filter_attachment_filename_include" i18n-hint hint="Optional. Wildcards e.g. *.pdf or *invoice* allowed. Can be comma-separated list. Case insensitive." [error]="error?.filter_attachment_filename_include"></pngx-input-text>
<pngx-input-text [horizontal]="true" i18n-title title="Exclude files matching" formControlName="filter_attachment_filename_exclude" i18n-hint hint="Optional. Wildcards e.g. *.pdf or *invoice* allowed. Can be comma-separated list. Case insensitive." [error]="error?.filter_attachment_filename_exclude"></pngx-input-text>
</div>
</div>
<hr class="mt-0"/>
<div class="row">
<div class="col-md-6">
<pngx-input-select [horizontal]="true" i18n-title title="Action" [items]="actionOptions" formControlName="action" i18n-hint hint="Only performed if the mail is processed."></pngx-input-select>
@if (showActionParamField) {
<pngx-input-text i18n-title title="Action parameter" formControlName="action_parameter" [error]="error?.action_parameter"></pngx-input-text>
<pngx-input-text [horizontal]="true" i18n-title title="Action parameter" formControlName="action_parameter" [error]="error?.action_parameter"></pngx-input-text>
}
<pngx-input-select i18n-title title="Assign title from" [items]="metadataTitleOptions" formControlName="assign_title_from"></pngx-input-select>
<pngx-input-tags [allowCreate]="false" formControlName="assign_tags"></pngx-input-tags>
<pngx-input-select i18n-title title="Assign document type" [items]="documentTypes" [allowNull]="true" formControlName="assign_document_type"></pngx-input-select>
<pngx-input-select i18n-title title="Assign correspondent from" [items]="metadataCorrespondentOptions" formControlName="assign_correspondent_from"></pngx-input-select>
<pngx-input-select [horizontal]="true" i18n-title title="Assign title from" [items]="metadataTitleOptions" formControlName="assign_title_from"></pngx-input-select>
<pngx-input-check [horizontal]="true" i18n-title title="Assign owner from rule" formControlName="assign_owner_from_rule"></pngx-input-check>
</div>
<div class="col-md-6">
<pngx-input-tags [horizontal]="true" [allowCreate]="false" formControlName="assign_tags"></pngx-input-tags>
<pngx-input-select [horizontal]="true" i18n-title title="Assign document type" [items]="documentTypes" [allowNull]="true" formControlName="assign_document_type"></pngx-input-select>
<pngx-input-select [horizontal]="true" i18n-title title="Assign correspondent from" [items]="metadataCorrespondentOptions" formControlName="assign_correspondent_from"></pngx-input-select>
@if (showCorrespondentField) {
<pngx-input-select i18n-title title="Assign correspondent" [items]="correspondents" [allowNull]="true" formControlName="assign_correspondent"></pngx-input-select>
<pngx-input-select [horizontal]="true" i18n-title title="Assign correspondent" [items]="correspondents" [allowNull]="true" formControlName="assign_correspondent"></pngx-input-select>
}
<pngx-input-check i18n-title title="Assign owner from rule" formControlName="assign_owner_from_rule"></pngx-input-check>
</div>
</div>
</div>
@@ -35,7 +35,7 @@
</div>
@if (selectionModel.items) {
<div class="items" #buttonItems>
@for (item of selectionModel.itemsSorted | filter: filterText; track item; let i = $index) {
@for (item of selectionModel.itemsSorted | filter: filterText:'name'; track item; let i = $index) {
@if (allowSelectNone || item.id) {
<pngx-toggleable-dropdown-button
[item]="item" [hideCount]="hideCount(item)" [state]="selectionModel.get(item.id)" [count]="getUpdatedDocumentCount(item.id)" (toggle)="selectionModel.toggle(item.id)" (exclude)="excludeClicked(item.id)" (click)="setButtonItemIndex(i - 1)" [disabled]="disabled">
@@ -45,13 +45,13 @@
</div>
}
@if (editing) {
@if ((selectionModel.itemsSorted | filter: filterText).length === 0 && createRef !== undefined) {
@if ((selectionModel.itemsSorted | filter: filterText:'name').length === 0 && createRef !== undefined) {
<button class="list-group-item list-group-item-action bg-light" (click)="createClicked()" [disabled]="disabled">
<small class="ms-2"><ng-container i18n>Create</ng-container> "{{filterText}}"</small>
<i-bs width="1.5em" height="1em" name="plus"></i-bs>
</button>
}
@if ((selectionModel.itemsSorted | filter: filterText).length > 0) {
@if ((selectionModel.itemsSorted | filter: filterText:'name').length > 0) {
<button class="list-group-item list-group-item-action bg-light" (click)="applyClicked()" [disabled]="!modelIsDirty || disabled">
<small class="ms-2" [ngClass]="{'fw-bold': modelIsDirty}" i18n>Apply</small>
<i-bs width="1.5em" height="1em" name="arrow-right"></i-bs>
@@ -38,7 +38,9 @@ export class DragDropSelectComponent extends AbstractInputComponent<string[]> {
writeValue(newValue: string[]): void {
super.writeValue(newValue)
this.selectedItems =
newValue?.map((id) => this.items.find((i) => i.id === id)) ?? []
newValue
?.map((id) => this.items.find((i) => i.id === id))
.filter((item) => item) ?? []
}
public drop(event: CdkDragDrop<string[]>) {
@@ -27,3 +27,11 @@
background-position: right calc(0.375em + 0.1875rem) center !important;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) !important;
}
.input-group .ng-select-taggable:first-child:nth-last-child(2) {
max-width: calc(100% - 45px); // fudge factor for (1x) ng-select button width
}
.input-group .ng-select-taggable:first-child:nth-last-child(3) {
max-width: calc(100% - 90px); // fudge factor for (2x) ng-select button width
}
@@ -56,30 +56,28 @@
<small i18n>Unowned</small>
</div>
</button>
<button *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.User }" class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" [disabled]="disabled">
<button *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.User }" class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" [disabled]="disabled">
<div class="selected-icon me-1">
@if (selectionModel.ownerFilter === OwnerFilterType.OTHERS) {
<i-bs width="1em" height="1em" name="check"></i-bs>
}
</div>
@if (permissionsService.currentUserCan(PermissionAction.View, PermissionType.User)) {
<div class="me-1 w-100">
<ng-select
name="user"
class="user-select small"
[(ngModel)]="selectionModel.includeUsers"
[disabled]="disabled"
[clearable]="false"
[items]="users"
bindLabel="username"
multiple="true"
bindValue="id"
placeholder="Users"
i18n-placeholder
(change)="onUserSelect()">
</ng-select>
</div>
}
<div class="me-1 w-100">
<ng-select
name="user"
class="user-select small"
[(ngModel)]="selectionModel.includeUsers"
[disabled]="disabled"
[clearable]="false"
[items]="users"
bindLabel="username"
multiple="true"
bindValue="id"
placeholder="Users"
i18n-placeholder
(change)="onUserSelect()">
</ng-select>
</div>
</button>
@if (selectionModel.ownerFilter === OwnerFilterType.NONE || selectionModel.ownerFilter === OwnerFilterType.NOT_SELF) {
<div class="list-group-item list-group-item-action d-flex align-items-center p-2 ps-3 border-bottom-0 border-start-0 border-end-0">
@@ -6,8 +6,8 @@
<input type="file" class="visually-hidden" (change)="onFileSelected($event)" multiple #fileUpload>
</form>
@if (getStatus().length > 0) {
<div class="fixed-bottom p-2 p-md-4 d-flex justify-content-end pe-none max-vh100-40 overflow-y-scroll" [ngClass]="slimSidebarEnabled ? 'col-slim' : 'offset-md-3 offset-lg-2'">
<div class="col col-lg-4 col-xl-3 ps-0 pe-0 ps-lg-3 pe-lg-0 pe-auto">
<div class="fixed-bottom p-2 p-md-4 d-flex justify-content-end pe-none max-vh100-40" [ngClass]="slimSidebarEnabled ? 'col-slim' : 'offset-md-3 offset-lg-2'">
<div class="col col-lg-4 col-xl-3 ps-0 pe-0 ps-lg-3 pe-lg-0 pe-auto overflow-y-scroll">
<div class="card shadow-sm consumer-status-card">
<div class="card-body">
<div class="row">
@@ -12,7 +12,7 @@ import { DragDropModule } from '@angular/cdk/drag-drop'
<button
*pngxIfObjectPermissions="{
object: { id: 2, owner: user1 },
action: 'view'
action: 'view',
}"
>
Some Text
@@ -188,9 +188,9 @@ export class FilterEditorComponent
case FILTER_CORRESPONDENT:
case FILTER_HAS_CORRESPONDENT_ANY:
if (rule.value) {
return $localize`Correspondent: ${this.correspondents.find(
(c) => c.id == +rule.value
)?.name}`
return $localize`Correspondent: ${
this.correspondents.find((c) => c.id == +rule.value)?.name
}`
} else {
return $localize`Without correspondent`
}
@@ -198,9 +198,9 @@ export class FilterEditorComponent
case FILTER_DOCUMENT_TYPE:
case FILTER_HAS_DOCUMENT_TYPE_ANY:
if (rule.value) {
return $localize`Document type: ${this.documentTypes.find(
(dt) => dt.id == +rule.value
)?.name}`
return $localize`Document type: ${
this.documentTypes.find((dt) => dt.id == +rule.value)?.name
}`
} else {
return $localize`Without document type`
}
@@ -208,16 +208,17 @@ export class FilterEditorComponent
case FILTER_STORAGE_PATH:
case FILTER_HAS_STORAGE_PATH_ANY:
if (rule.value) {
return $localize`Storage path: ${this.storagePaths.find(
(sp) => sp.id == +rule.value
)?.name}`
return $localize`Storage path: ${
this.storagePaths.find((sp) => sp.id == +rule.value)?.name
}`
} else {
return $localize`Without storage path`
}
case FILTER_HAS_TAGS_ALL:
return $localize`Tag: ${this.tags.find((t) => t.id == +rule.value)
?.name}`
return $localize`Tag: ${
this.tags.find((t) => t.id == +rule.value)?.name
}`
case FILTER_HAS_ANY_TAG:
if (rule.value == 'false') {
@@ -225,9 +226,9 @@ export class FilterEditorComponent
}
case FILTER_HAS_CUSTOM_FIELDS_ALL:
return $localize`Custom fields: ${this.customFields.find(
(f) => f.id == +rule.value
)?.name}`
return $localize`Custom fields: ${
this.customFields.find((f) => f.id == +rule.value)?.name
}`
case FILTER_HAS_ANY_CUSTOM_FIELDS:
if (rule.value == 'false') {
@@ -9,7 +9,7 @@ import { PermissionsService } from '../services/permissions.service'
<button
*pngxIfObjectPermissions="{
object: { id: 2, owner: user1 },
action: 'view'
action: 'view',
}"
>
Some Text
+21
View File
@@ -25,4 +25,25 @@ describe('FilterPipe', () => {
itemsReturned = pipe.transform(items, null)
expect(itemsReturned).toEqual(items)
})
it('should filter matchingmodel items by key', () => {
const pipe = new FilterPipe()
const items: MatchingModel[] = [
{
id: 1,
name: 'Hello World',
slug: 'slug-1',
},
{
id: 2,
name: 'Hello with slug',
slug: 'not this',
},
]
let itemsReturned = pipe.transform(items, 'slug')
expect(itemsReturned).toEqual(items)
itemsReturned = pipe.transform(items, 'slug', 'slug')
expect(itemsReturned).toEqual([items[0]])
})
})
+12 -2
View File
@@ -5,12 +5,22 @@ import { MatchingModel } from '../data/matching-model'
name: 'filter',
})
export class FilterPipe implements PipeTransform {
transform(items: MatchingModel[], searchText: string): MatchingModel[] {
transform(
items: MatchingModel[],
searchText: string,
key?: string
): MatchingModel[] {
if (!items) return []
if (!searchText) return items
return items.filter((item) => {
return Object.keys(item).some((key) => {
const keys = key
? [key]
: Object.keys(item).filter(
(key) =>
typeof item[key] === 'string' || typeof item[key] === 'number'
)
return keys.some((key) => {
return String(item[key])
.toLowerCase()
.includes(searchText.toLowerCase())
+1 -1
View File
@@ -29,7 +29,7 @@ export class UsernamePipe implements PipeTransform {
transform(userID: number): string {
return this.users
? this.getName(this.users.find((u) => u.id === userID)) ?? ''
? (this.getName(this.users.find((u) => u.id === userID)) ?? '')
: $localize`Shared`
}
@@ -298,8 +298,9 @@ export class DocumentListViewService {
errorMessage = Object.keys(error.error)
.map((fieldName) => {
const fieldError: Array<string> = error.error[fieldName]
return `${this.sortFields.find((f) => f.field == fieldName)
?.name}: ${fieldError[0]}`
return `${
this.sortFields.find((f) => f.field == fieldName)?.name
}: ${fieldError[0]}`
})
.join(', ')
} else {
@@ -57,7 +57,7 @@ describe(`Additional service tests for SavedViewService`, () => {
let settingsService
it('should retrieve saved views and sort them', () => {
service.initialize()
service.reload()
const req = httpTestingController.expectOne(
`${environment.apiBaseUrl}${endpoint}/?page=1&page_size=100000`
)
@@ -69,6 +69,16 @@ describe(`Additional service tests for SavedViewService`, () => {
expect(service.sidebarViews).toHaveLength(3)
})
it('should gracefully handle errors', () => {
service.reload()
const req = httpTestingController.expectOne(
`${environment.apiBaseUrl}${endpoint}/?page=1&page_size=100000`
)
req.error(new ErrorEvent('error'))
expect(service.loading).toBeFalsy()
expect(service.allViews).toHaveLength(0)
})
it('should support patchMany', () => {
subscription = service.patchMany(saved_views).subscribe()
saved_views.forEach((saved_view) => {
@@ -3,40 +3,52 @@ import { Injectable } from '@angular/core'
import { combineLatest, Observable } from 'rxjs'
import { tap } from 'rxjs/operators'
import { SavedView } from 'src/app/data/saved-view'
import { PermissionsService } from '../permissions.service'
import { AbstractPaperlessService } from './abstract-paperless-service'
import { SettingsService } from '../settings.service'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { Results } from 'src/app/data/results'
@Injectable({
providedIn: 'root',
})
export class SavedViewService extends AbstractPaperlessService<SavedView> {
loading: boolean
public loading: boolean = true
private savedViews: SavedView[] = []
constructor(
http: HttpClient,
permissionService: PermissionsService,
protected http: HttpClient,
private settingsService: SettingsService
) {
super(http, 'saved_views')
}
public initialize() {
this.reload()
public list(
page?: number,
pageSize?: number,
sortField?: string,
sortReverse?: boolean,
extraParams?: any
): Observable<Results<SavedView>> {
return super.list(page, pageSize, sortField, sortReverse, extraParams).pipe(
tap({
next: (r) => {
this.savedViews = r.results
this.loading = false
this.settingsService.dashboardIsEmpty =
this.dashboardViews.length === 0
},
error: () => {
this.loading = false
this.settingsService.dashboardIsEmpty = true
},
})
)
}
private reload() {
this.loading = true
this.listAll().subscribe((r) => {
this.savedViews = r.results
this.loading = false
this.settingsService.dashboardIsEmpty = this.dashboardViews.length === 0
})
public reload() {
this.listAll().subscribe()
}
private savedViews: SavedView[] = []
get allViews() {
return this.savedViews
}
@@ -143,6 +143,12 @@ const LANGUAGE_OPTIONS = [
englishName: 'Japanese',
dateInputFormat: 'yyyy/mm/dd',
},
{
code: 'ko-kr',
name: $localize`Korean`,
englishName: 'Korean',
dateInputFormat: 'yyyy-mm-dd',
},
{
code: 'lb-lu',
name: $localize`Luxembourgish`,
@@ -53,7 +53,7 @@ export class UploadDocumentsService {
)
status.message = $localize`Uploading...`
} else if (event.type == HttpEventType.Response) {
status.taskId = event.body['task_id']
status.taskId = event.body['task_id'] ?? event.body.toString()
status.message = $localize`Upload complete, waiting...`
this.uploadSubscriptions[file.name]?.complete()
}
+1 -1
View File
@@ -5,7 +5,7 @@ export const environment = {
apiBaseUrl: document.baseURI + 'api/',
apiVersion: '5',
appTitle: 'Paperless-ngx',
version: '2.11.3',
version: '2.12.1',
webSocketHost: window.location.host,
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
webSocketBaseUrl: base_url.pathname + 'ws/',
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+6
View File
@@ -233,6 +233,12 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='htt
}
}
.table-row-selected {
td, a {
color: var(--pngx-primary-text-contrast) !important;
}
}
.card .table {
border-color: var(--bs-gray-800);
}
+39 -7
View File
@@ -7,8 +7,8 @@ from typing import Optional
from django.conf import settings
from pdf2image import convert_from_path
from pdf2image.exceptions import PDFPageCountError
from pikepdf import Page
from pikepdf import PasswordError
from pikepdf import Pdf
from PIL import Image
@@ -231,13 +231,41 @@ class BarcodePlugin(ConsumeTaskPlugin):
logger.debug("Scanning for barcodes using ZXING")
try:
pages_from_path = convert_from_path(
self.pdf_file,
dpi=settings.CONSUMER_BARCODE_DPI,
output_folder=self.temp_dir.name,
# Read number of pages from pdf
with Pdf.open(self.pdf_file) as pdf:
num_of_pages = len(pdf.pages)
logger.debug(f"PDF has {num_of_pages} pages")
# Get limit from configuration
barcode_max_pages = (
num_of_pages
if settings.CONSUMER_BARCODE_MAX_PAGES == 0
else settings.CONSUMER_BARCODE_MAX_PAGES
)
for current_page_number, page in enumerate(pages_from_path):
if barcode_max_pages < num_of_pages: # pragma: no cover
logger.debug(
f"Barcodes detection will be limited to the first {barcode_max_pages} pages",
)
# Loop al page
for current_page_number in range(min(num_of_pages, barcode_max_pages)):
logger.debug(f"Processing page {current_page_number}")
# Convert page to image
page = convert_from_path(
self.pdf_file,
dpi=settings.CONSUMER_BARCODE_DPI,
output_folder=self.temp_dir.name,
first_page=current_page_number + 1,
last_page=current_page_number + 1,
)[0]
# Remember filename, since it is lost by upscaling
page_filepath = Path(page.filename)
logger.debug(f"Image is at {page_filepath}")
# Upscale image if configured
factor = settings.CONSUMER_BARCODE_UPSCALE
if factor > 1.0:
logger.debug(
@@ -248,14 +276,18 @@ class BarcodePlugin(ConsumeTaskPlugin):
(int(round(x * factor)), (int(round(y * factor)))),
)
# Detect barcodes
for barcode_value in reader(page):
self.barcodes.append(
Barcode(current_page_number, barcode_value),
)
# Delete temporary image file
page_filepath.unlink()
# Password protected files can't be checked
# This is the exception raised for those
except PDFPageCountError as e:
except PasswordError as e:
logger.warning(
f"File is likely password protected, not checking for barcodes: {e}",
)
+37 -110
View File
@@ -8,8 +8,8 @@ from datetime import timezone
from shutil import rmtree
from typing import Optional
from dateutil.parser import isoparse
from django.conf import settings
from django.db.models import QuerySet
from django.utils import timezone as django_timezone
from guardian.shortcuts import get_users_with_perms
from whoosh import classify
@@ -22,6 +22,8 @@ from whoosh.fields import NUMERIC
from whoosh.fields import TEXT
from whoosh.fields import Schema
from whoosh.highlight import HtmlFormatter
from whoosh.idsets import BitSet
from whoosh.idsets import DocIdSet
from whoosh.index import FileIndex
from whoosh.index import create_in
from whoosh.index import exists_in
@@ -31,6 +33,7 @@ from whoosh.qparser import QueryParser
from whoosh.qparser.dateparse import DateParserPlugin
from whoosh.qparser.dateparse import English
from whoosh.qparser.plugins import FieldsPlugin
from whoosh.reading import IndexReader
from whoosh.scoring import TF_IDF
from whoosh.searching import ResultsPage
from whoosh.searching import Searcher
@@ -201,114 +204,32 @@ def remove_document_from_index(document: Document):
remove_document(writer, document)
class MappedDocIdSet(DocIdSet):
"""
A DocIdSet backed by a set of `Document` IDs.
Supports efficiently looking up if a whoosh docnum is in the provided `filter_queryset`.
"""
def __init__(self, filter_queryset: QuerySet, ixreader: IndexReader) -> None:
super().__init__()
document_ids = filter_queryset.order_by("id").values_list("id", flat=True)
max_id = document_ids.last() or 0
self.document_ids = BitSet(document_ids, size=max_id)
self.ixreader = ixreader
def __contains__(self, docnum):
document_id = self.ixreader.stored_fields(docnum)["id"]
return document_id in self.document_ids
def __bool__(self):
# searcher.search ignores a filter if it's "falsy".
# We use this hack so this DocIdSet, when used as a filter, is never ignored.
return True
class DelayedQuery:
param_map = {
"correspondent": ("correspondent", ["id", "id__in", "id__none", "isnull"]),
"document_type": ("type", ["id", "id__in", "id__none", "isnull"]),
"storage_path": ("path", ["id", "id__in", "id__none", "isnull"]),
"owner": ("owner", ["id", "id__in", "id__none", "isnull"]),
"shared_by": ("shared_by", ["id"]),
"tags": ("tag", ["id__all", "id__in", "id__none"]),
"added": ("added", ["date__lt", "date__gt"]),
"created": ("created", ["date__lt", "date__gt"]),
"checksum": ("checksum", ["icontains", "istartswith"]),
"original_filename": ("original_filename", ["icontains", "istartswith"]),
"custom_fields": (
"custom_fields",
["icontains", "istartswith", "id__all", "id__in", "id__none"],
),
}
def _get_query(self):
raise NotImplementedError
def _get_query_filter(self):
criterias = []
for key, value in self.query_params.items():
# is_tagged is a special case
if key == "is_tagged":
criterias.append(query.Term("has_tag", self.evalBoolean(value)))
continue
if key == "has_custom_fields":
criterias.append(
query.Term("has_custom_fields", self.evalBoolean(value)),
)
continue
# Don't process query params without a filter
if "__" not in key:
continue
# All other query params consist of a parameter and a query filter
param, query_filter = key.split("__", 1)
try:
field, supported_query_filters = self.param_map[param]
except KeyError:
logger.error(f"Unable to build a query filter for parameter {key}")
continue
# We only support certain filters per parameter
if query_filter not in supported_query_filters:
logger.info(
f"Query filter {query_filter} not supported for parameter {param}",
)
continue
if query_filter == "id":
if param == "shared_by":
criterias.append(query.Term("is_shared", True))
criterias.append(query.Term("owner_id", value))
else:
criterias.append(query.Term(f"{field}_id", value))
elif query_filter == "id__in":
in_filter = []
for object_id in value.split(","):
in_filter.append(
query.Term(f"{field}_id", object_id),
)
criterias.append(query.Or(in_filter))
elif query_filter == "id__none":
for object_id in value.split(","):
criterias.append(
query.Not(query.Term(f"{field}_id", object_id)),
)
elif query_filter == "isnull":
criterias.append(
query.Term(f"has_{field}", self.evalBoolean(value) is False),
)
elif query_filter == "id__all":
for object_id in value.split(","):
criterias.append(query.Term(f"{field}_id", object_id))
elif query_filter == "date__lt":
criterias.append(
query.DateRange(field, start=None, end=isoparse(value)),
)
elif query_filter == "date__gt":
criterias.append(
query.DateRange(field, start=isoparse(value), end=None),
)
elif query_filter == "icontains":
criterias.append(
query.Term(field, value),
)
elif query_filter == "istartswith":
criterias.append(
query.Prefix(field, value),
)
user_criterias = get_permissions_criterias(
user=self.user,
)
if len(criterias) > 0:
if len(user_criterias) > 0:
criterias.append(query.Or(user_criterias))
return query.And(criterias)
else:
return query.Or(user_criterias) if len(user_criterias) > 0 else None
def evalBoolean(self, val):
return val.lower() in {"true", "1"}
raise NotImplementedError # pragma: no cover
def _get_query_sortedby(self):
if "ordering" not in self.query_params:
@@ -339,13 +260,19 @@ class DelayedQuery:
else:
return sort_fields_map[field], reverse
def __init__(self, searcher: Searcher, query_params, page_size, user):
def __init__(
self,
searcher: Searcher,
query_params,
page_size,
filter_queryset: QuerySet,
):
self.searcher = searcher
self.query_params = query_params
self.page_size = page_size
self.saved_results = dict()
self.first_score = None
self.user = user
self.filter_queryset = filter_queryset
def __len__(self):
page = self[0:1]
@@ -361,7 +288,7 @@ class DelayedQuery:
page: ResultsPage = self.searcher.search_page(
q,
mask=mask,
filter=self._get_query_filter(),
filter=MappedDocIdSet(self.filter_queryset, self.searcher.ixreader),
pagenum=math.floor(item.start / self.page_size) + 1,
pagelen=self.page_size,
sortedby=sortedby,
@@ -0,0 +1,18 @@
# Generated by Django 4.2.15 on 2024-08-20 02:41
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("documents", "1051_alter_correspondent_owner_alter_document_owner_and_more"),
]
operations = [
migrations.AddField(
model_name="document",
name="transaction_id",
field=models.UUIDField(blank=True, null=True),
),
]
+1
View File
@@ -146,6 +146,7 @@ class PaperlessNotePermissions(BasePermission):
"""
perms_map = {
"OPTIONS": ["documents.view_note"],
"GET": ["documents.view_note"],
"POST": ["documents.add_note"],
"DELETE": ["documents.delete_note"],
+91 -25
View File
@@ -2,6 +2,7 @@ import datetime
import math
import re
import zoneinfo
from collections.abc import Iterable
from decimal import Decimal
import magic
@@ -232,22 +233,45 @@ class OwnedObjectSerializer(
)
)
def get_is_shared_by_requester(self, obj: Document):
ctype = ContentType.objects.get_for_model(obj)
@staticmethod
def get_shared_object_pks(objects: Iterable):
"""
Return the primary keys of the subset of objects that are shared.
"""
try:
first_obj = next(iter(objects))
except StopIteration:
return set()
ctype = ContentType.objects.get_for_model(first_obj)
object_pks = list(obj.pk for obj in objects)
pk_type = type(first_obj.pk)
def get_pks_for_permission_type(model):
return map(
pk_type, # coerce the pk to be the same type of the provided objects
model.objects.filter(
content_type=ctype,
object_pk__in=object_pks,
)
.values_list("object_pk", flat=True)
.distinct(),
)
UserObjectPermission = get_user_obj_perms_model()
GroupObjectPermission = get_group_obj_perms_model()
return obj.owner == self.user and (
UserObjectPermission.objects.filter(
content_type=ctype,
object_pk=obj.pk,
).count()
> 0
or GroupObjectPermission.objects.filter(
content_type=ctype,
object_pk=obj.pk,
).count()
> 0
)
user_permission_pks = get_pks_for_permission_type(UserObjectPermission)
group_permission_pks = get_pks_for_permission_type(GroupObjectPermission)
return set(user_permission_pks) | set(group_permission_pks)
def get_is_shared_by_requester(self, obj: Document):
# First check the context to see if `shared_object_pks` is set by the parent.
shared_object_pks = self.context.get("shared_object_pks")
# If not just check if the current object is shared.
if shared_object_pks is None:
shared_object_pks = self.get_shared_object_pks([obj])
return obj.owner == self.user and obj.id in shared_object_pks
permissions = SerializerMethodField(read_only=True)
user_can_change = SerializerMethodField(read_only=True)
@@ -303,6 +327,14 @@ class OwnedObjectSerializer(
return super().update(instance, validated_data)
class OwnedObjectListSerializer(serializers.ListSerializer):
def to_representation(self, documents):
self.child.context["shared_object_pks"] = self.child.get_shared_object_pks(
documents,
)
return super().to_representation(documents)
class CorrespondentSerializer(MatchingModelSerializer, OwnedObjectSerializer):
last_correspondence = serializers.DateTimeField(read_only=True, required=False)
@@ -863,35 +895,69 @@ class DocumentSerializer(
"custom_fields",
"remove_inbox_tags",
)
list_serializer_class = OwnedObjectListSerializer
class SearchResultListSerializer(serializers.ListSerializer):
def to_representation(self, hits):
document_ids = [hit["id"] for hit in hits]
# Fetch all Document objects in the list in one SQL query.
documents = self.child.fetch_documents(document_ids)
self.child.context["documents"] = documents
# Also check if they are shared with other users / groups.
self.child.context["shared_object_pks"] = self.child.get_shared_object_pks(
documents.values(),
)
return super().to_representation(hits)
class SearchResultSerializer(DocumentSerializer):
def to_representation(self, instance):
doc = (
Document.objects.select_related(
@staticmethod
def fetch_documents(ids):
"""
Return a dict that maps given document IDs to Document objects.
"""
return {
document.id: document
for document in Document.objects.select_related(
"correspondent",
"storage_path",
"document_type",
"owner",
)
.prefetch_related("tags", "custom_fields", "notes")
.get(id=instance["id"])
)
.filter(id__in=ids)
}
def to_representation(self, hit):
# Again we first check if the parent has already fetched the documents.
documents = self.context.get("documents")
# Otherwise we fetch this document.
if documents is None: # pragma: no cover
# In practice we only serialize **lists** of whoosh.searching.Hit.
# I'm keeping this check for completeness but marking it no cover for now.
documents = self.fetch_documents([hit["id"]])
document = documents[hit["id"]]
notes = ",".join(
[str(c.note) for c in doc.notes.all()],
[str(c.note) for c in document.notes.all()],
)
r = super().to_representation(doc)
r = super().to_representation(document)
r["__search_hit__"] = {
"score": instance.score,
"highlights": instance.highlights("content", text=doc.content),
"score": hit.score,
"highlights": hit.highlights("content", text=document.content),
"note_highlights": (
instance.highlights("notes", text=notes) if doc else None
hit.highlights("notes", text=notes) if document else None
),
"rank": instance.rank,
"rank": hit.rank,
}
return r
class Meta(DocumentSerializer.Meta):
list_serializer_class = SearchResultListSerializer
class SavedViewFilterRuleSerializer(serializers.ModelSerializer):
class Meta:
+8 -3
View File
@@ -535,7 +535,9 @@ def run_workflow(
):
def assignment_action():
if action.assign_tags.all().count() > 0:
document.tags.add(*action.assign_tags.all())
doc_tag_ids.extend(
list(action.assign_tags.all().values_list("pk", flat=True)),
)
if action.assign_correspondent is not None:
document.correspondent = action.assign_correspondent
@@ -641,12 +643,12 @@ def run_workflow(
def removal_action():
if action.remove_all_tags:
document.tags.clear()
doc_tag_ids.clear()
else:
for tag in action.remove_tags.filter(
pk__in=list(document.tags.values_list("pk", flat=True)),
).all():
document.tags.remove(tag.pk)
doc_tag_ids.remove(tag.pk)
if action.remove_all_correspondents or (
document.correspondent
@@ -747,6 +749,7 @@ def run_workflow(
# Refresh this so the matching data is fresh and instance fields are re-freshed
# Otherwise, this instance might be behind and overwrite the work another process did
document.refresh_from_db()
doc_tag_ids = list(document.tags.all().values_list("pk", flat=True))
if matching.document_matches_workflow(
document,
workflow,
@@ -765,7 +768,9 @@ def run_workflow(
elif action.type == WorkflowAction.WorkflowActionType.REMOVAL:
removal_action()
# save first before setting tags
document.save()
document.tags.set(doc_tag_ids)
@before_task_publish.connect
+14 -20
View File
@@ -47,8 +47,6 @@ from documents.signals import document_updated
from documents.signals.handlers import cleanup_document_deletion
if settings.AUDIT_LOG_ENABLED:
import json
from auditlog.models import LogEntry
logger = logging.getLogger("paperless.tasks")
@@ -259,24 +257,20 @@ def update_document_archive_file(document_id):
if settings.AUDIT_LOG_ENABLED:
LogEntry.objects.log_create(
instance=oldDocument,
changes=json.dumps(
{
"content": [oldDocument.content, newDocument.content],
"archive_checksum": [
oldDocument.archive_checksum,
newDocument.archive_checksum,
],
"archive_filename": [
oldDocument.archive_filename,
newDocument.archive_filename,
],
},
),
additional_data=json.dumps(
{
"reason": "Redo OCR called",
},
),
changes={
"content": [oldDocument.content, newDocument.content],
"archive_checksum": [
oldDocument.archive_checksum,
newDocument.archive_checksum,
],
"archive_filename": [
oldDocument.archive_filename,
newDocument.archive_filename,
],
},
additional_data={
"reason": "Update document archive file",
},
action=LogEntry.Action.UPDATE,
)
+31 -5
View File
@@ -15,6 +15,7 @@ from rest_framework.test import APITestCase
from whoosh.writing import AsyncWriter
from documents import index
from documents.bulk_edit import set_permissions
from documents.models import Correspondent
from documents.models import CustomField
from documents.models import CustomFieldInstance
@@ -1159,7 +1160,8 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
[d3.id, d2.id, d1.id],
)
def test_global_search(self):
@mock.patch("documents.bulk_edit.bulk_update_documents")
def test_global_search(self, m):
"""
GIVEN:
- Multiple documents and objects
@@ -1186,11 +1188,38 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
checksum="C",
pk=3,
)
# The below two documents are owned by user2 and shouldn't show up in results!
d4 = Document.objects.create(
title="doc 4 owned by user2",
content="bank bank bank bank 4",
checksum="D",
pk=4,
)
d5 = Document.objects.create(
title="doc 5 owned by user2",
content="bank bank bank bank 5",
checksum="E",
pk=5,
)
user1 = User.objects.create_user("bank user1")
user2 = User.objects.create_superuser("user2")
group1 = Group.objects.create(name="bank group1")
Group.objects.create(name="group2")
user1.user_permissions.add(
*Permission.objects.filter(codename__startswith="view_").exclude(
content_type__app_label="admin",
),
)
set_permissions([4, 5], set_permissions=[], owner=user2, merge=False)
with index.open_index_writer() as writer:
index.update_document(writer, d1)
index.update_document(writer, d2)
index.update_document(writer, d3)
index.update_document(writer, d4)
index.update_document(writer, d5)
correspondent1 = Correspondent.objects.create(name="bank correspondent 1")
Correspondent.objects.create(name="correspondent 2")
@@ -1200,10 +1229,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
StoragePath.objects.create(name="path 2", path="path2")
tag1 = Tag.objects.create(name="bank tag1")
Tag.objects.create(name="tag2")
user1 = User.objects.create_superuser("bank user1")
User.objects.create_user("user2")
group1 = Group.objects.create(name="bank group1")
Group.objects.create(name="group2")
SavedView.objects.create(
name="bank view",
show_on_dashboard=True,
-161
View File
@@ -1,8 +1,6 @@
from dateutil.parser import isoparse
from django.test import TestCase
from whoosh import query
from documents.index import DelayedQuery
from documents.index import get_permissions_criterias
from documents.models import User
@@ -58,162 +56,3 @@ class TestDelayedQuery(TestCase):
)
for user, expected in tests:
self.assertEqual(get_permissions_criterias(user), expected)
def test_no_query_filters(self):
dq = DelayedQuery(None, {}, None, None)
self.assertEqual(dq._get_query_filter(), self.has_no_owner)
def test_date_query_filters(self):
def _get_testset(param: str):
date_str = "1970-01-01T02:44"
date_obj = isoparse(date_str)
return (
(
{f"{param}__date__lt": date_str},
query.And(
[
query.DateRange(param, start=None, end=date_obj),
self.has_no_owner,
],
),
),
(
{f"{param}__date__gt": date_str},
query.And(
[
query.DateRange(param, start=date_obj, end=None),
self.has_no_owner,
],
),
),
)
query_params = ["created", "added"]
for param in query_params:
for params, expected in _get_testset(param):
dq = DelayedQuery(None, params, None, None)
got = dq._get_query_filter()
self.assertCountEqual(got, expected)
def test_is_tagged_query_filter(self):
tests = (
("True", True),
("true", True),
("1", True),
("False", False),
("false", False),
("0", False),
("foo", False),
)
for param, expected in tests:
dq = DelayedQuery(None, {"is_tagged": param}, None, None)
self.assertEqual(
dq._get_query_filter(),
query.And([query.Term("has_tag", expected), self.has_no_owner]),
)
def test_tags_query_filters(self):
# tests contains tuples of query_parameter dics and the expected whoosh query
param = "tags"
field, _ = DelayedQuery.param_map[param]
tests = (
(
{f"{param}__id__all": "42,43"},
query.And(
[
query.Term(f"{field}_id", "42"),
query.Term(f"{field}_id", "43"),
self.has_no_owner,
],
),
),
# tags does not allow __id
(
{f"{param}__id": "42"},
self.has_no_owner,
),
# tags does not allow __isnull
(
{f"{param}__isnull": "true"},
self.has_no_owner,
),
self._get_testset__id__in(param, field),
self._get_testset__id__none(param, field),
)
for params, expected in tests:
dq = DelayedQuery(None, params, None, None)
got = dq._get_query_filter()
self.assertCountEqual(got, expected)
def test_generic_query_filters(self):
def _get_testset(param: str):
field, _ = DelayedQuery.param_map[param]
return (
(
{f"{param}__id": "42"},
query.And(
[
query.Term(f"{field}_id", "42"),
self.has_no_owner,
],
),
),
self._get_testset__id__in(param, field),
self._get_testset__id__none(param, field),
(
{f"{param}__isnull": "true"},
query.And(
[
query.Term(f"has_{field}", False),
self.has_no_owner,
],
),
),
(
{f"{param}__isnull": "false"},
query.And(
[
query.Term(f"has_{field}", True),
self.has_no_owner,
],
),
),
)
query_params = ["correspondent", "document_type", "storage_path", "owner"]
for param in query_params:
for params, expected in _get_testset(param):
dq = DelayedQuery(None, params, None, None)
got = dq._get_query_filter()
self.assertCountEqual(got, expected)
def test_char_query_filter(self):
def _get_testset(param: str):
return (
(
{f"{param}__icontains": "foo"},
query.And(
[
query.Term(f"{param}", "foo"),
self.has_no_owner,
],
),
),
(
{f"{param}__istartswith": "foo"},
query.And(
[
query.Prefix(f"{param}", "foo"),
self.has_no_owner,
],
),
),
)
query_params = ["checksum", "original_filename"]
for param in query_params:
for params, expected in _get_testset(param):
dq = DelayedQuery(None, params, None, None)
got = dq._get_query_filter()
self.assertCountEqual(got, expected)
+49
View File
@@ -1758,3 +1758,52 @@ class TestWorkflows(DirectoriesMixin, FileSystemAssertsMixin, APITestCase):
info = cm.output[0]
expected_str = f"Document matched {trigger} from {w}"
self.assertIn(expected_str, info)
def test_workflow_with_tag_actions_doesnt_overwrite_other_actions(self):
"""
GIVEN:
- Document updated workflow filtered by has tag with two actions, first adds owner, second removes a tag
WHEN:
- File that matches is consumed
THEN:
- Both actions are applied correctly
"""
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
)
trigger.filter_has_tags.add(self.t1)
action1 = WorkflowAction.objects.create(
assign_owner=self.user2,
)
action2 = WorkflowAction.objects.create(
type=WorkflowAction.WorkflowActionType.REMOVAL,
)
action2.remove_tags.add(self.t1)
w = Workflow.objects.create(
name="Workflow Add Owner and Remove Tag",
order=0,
)
w.triggers.add(trigger)
w.actions.add(action1)
w.actions.add(action2)
w.save()
doc = Document.objects.create(
title="sample test",
correspondent=self.c,
original_filename="sample.pdf",
)
superuser = User.objects.create_superuser("superuser")
self.client.force_authenticate(user=superuser)
self.client.patch(
f"/api/documents/{doc.id}/",
{"tags": [self.t1.id, self.t2.id]},
format="json",
)
doc.refresh_from_db()
self.assertEqual(doc.owner, self.user2)
self.assertEqual(doc.tags.all().count(), 1)
self.assertIn(self.t2, doc.tags.all())
+25 -24
View File
@@ -678,11 +678,9 @@ class DocumentViewSet(
if settings.AUDIT_LOG_ENABLED:
LogEntry.objects.log_create(
instance=doc,
changes=json.dumps(
{
"Note Added": ["None", c.id],
},
),
changes={
"Note Added": ["None", c.id],
},
action=LogEntry.Action.UPDATE,
)
@@ -715,11 +713,9 @@ class DocumentViewSet(
if settings.AUDIT_LOG_ENABLED:
LogEntry.objects.log_create(
instance=doc,
changes=json.dumps(
{
"Note Deleted": [note.id, "None"],
},
),
changes={
"Note Deleted": [note.id, "None"],
},
action=LogEntry.Action.UPDATE,
)
@@ -852,6 +848,8 @@ class UnifiedSearchViewSet(DocumentViewSet):
)
def filter_queryset(self, queryset):
filtered_queryset = super().filter_queryset(queryset)
if self._is_search_request():
from documents import index
@@ -866,10 +864,10 @@ class UnifiedSearchViewSet(DocumentViewSet):
self.searcher,
self.request.query_params,
self.paginator.get_page_size(self.request),
self.request.user,
filter_queryset=filtered_queryset,
)
else:
return super().filter_queryset(queryset)
return filtered_queryset
def list(self, request, *args, **kwargs):
if self._is_search_request():
@@ -982,6 +980,7 @@ class BulkEditView(PassUserMixin):
bulk_edit.set_permissions,
bulk_edit.delete,
bulk_edit.rotate,
bulk_edit.delete_pages,
]
else all(
has_perms_owner_aware(user, "change_document", doc)
@@ -1199,14 +1198,16 @@ class GlobalSearchView(PassUserMixin):
from documents import index
with index.open_index_searcher() as s:
q, _ = index.DelayedFullTextQuery(
fts_query = index.DelayedFullTextQuery(
s,
request.query_params,
10,
request.user,
)._get_query()
results = s.search(q, limit=OBJECT_LIMIT)
docs = docs | all_docs.filter(id__in=[r["id"] for r in results])
OBJECT_LIMIT,
filter_queryset=all_docs,
)
results = fts_query[0:1]
docs = docs | Document.objects.filter(
id__in=[r["id"] for r in results],
)
docs = docs[:OBJECT_LIMIT]
saved_views = (
SavedView.objects.filter(owner=request.user, name__icontains=query)
@@ -1452,12 +1453,12 @@ class StatisticsView(APIView):
{
"documents_total": documents_total,
"documents_inbox": documents_inbox,
"inbox_tag": inbox_tags.first().pk
if inbox_tags.exists()
else None, # backwards compatibility
"inbox_tags": [tag.pk for tag in inbox_tags]
if inbox_tags.exists()
else None,
"inbox_tag": (
inbox_tags.first().pk if inbox_tags.exists() else None
), # backwards compatibility
"inbox_tags": (
[tag.pk for tag in inbox_tags] if inbox_tags.exists() else None
),
"document_file_type_counts": document_file_type_counts,
"character_count": character_count,
"tag_count": len(tags),
+24 -20
View File
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-09 11:27-0700\n"
"PO-Revision-Date: 2024-07-09 18:28\n"
"POT-Creation-Date: 2024-08-28 17:12-0700\n"
"PO-Revision-Date: 2024-08-29 03:10\n"
"Last-Translator: \n"
"Language-Team: Afrikaans\n"
"Language: af_ZA\n"
@@ -927,21 +927,21 @@ msgstr ""
msgid "enabled"
msgstr ""
#: documents/serialisers.py:119
#: documents/serialisers.py:120
#, python-format
msgid "Invalid regular expression: %(error)s"
msgstr "Ongeldige reguliere uitdrukking: %(error)s"
#: documents/serialisers.py:435
#: documents/serialisers.py:467
msgid "Invalid color."
msgstr "Ongeldige kleur."
#: documents/serialisers.py:1314
#: documents/serialisers.py:1397
#, python-format
msgid "File type %(type)s not supported"
msgstr "Lêertipe %(type)s word nie ondersteun nie"
#: documents/serialisers.py:1423
#: documents/serialisers.py:1506
msgid "Invalid variable detected."
msgstr "Ongeldige veranderlike bespeur."
@@ -1369,62 +1369,66 @@ msgid "Japanese"
msgstr ""
#: paperless/settings.py:699
msgid "Korean"
msgstr ""
#: paperless/settings.py:700
msgid "Luxembourgish"
msgstr "Luxemburgs"
#: paperless/settings.py:700
#: paperless/settings.py:701
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:701
#: paperless/settings.py:702
msgid "Dutch"
msgstr "Nederlands"
#: paperless/settings.py:702
#: paperless/settings.py:703
msgid "Polish"
msgstr "Pools"
#: paperless/settings.py:703
#: paperless/settings.py:704
msgid "Portuguese (Brazil)"
msgstr "Portugees (Brasilië)"
#: paperless/settings.py:704
#: paperless/settings.py:705
msgid "Portuguese"
msgstr "Portugees"
#: paperless/settings.py:705
#: paperless/settings.py:706
msgid "Romanian"
msgstr "Roemeens"
#: paperless/settings.py:706
#: paperless/settings.py:707
msgid "Russian"
msgstr "Russies"
#: paperless/settings.py:707
#: paperless/settings.py:708
msgid "Slovak"
msgstr ""
#: paperless/settings.py:708
#: paperless/settings.py:709
msgid "Slovenian"
msgstr "Sloweens"
#: paperless/settings.py:709
#: paperless/settings.py:710
msgid "Serbian"
msgstr "Serwies"
#: paperless/settings.py:710
#: paperless/settings.py:711
msgid "Swedish"
msgstr "Sweeds"
#: paperless/settings.py:711
#: paperless/settings.py:712
msgid "Turkish"
msgstr "Turks"
#: paperless/settings.py:712
#: paperless/settings.py:713
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:713
#: paperless/settings.py:714
msgid "Chinese Simplified"
msgstr "Vereenvoudigde Sjinees"
+27 -23
View File
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-09 11:27-0700\n"
"PO-Revision-Date: 2024-07-09 18:28\n"
"POT-Creation-Date: 2024-08-28 17:12-0700\n"
"PO-Revision-Date: 2024-08-29 03:10\n"
"Last-Translator: \n"
"Language-Team: Arabic\n"
"Language: ar_SA\n"
@@ -677,7 +677,7 @@ msgstr "رابط المستند"
#: documents/models.py:812
msgid "Select"
msgstr ""
msgstr "تحديد"
#: documents/models.py:824
msgid "data type"
@@ -685,11 +685,11 @@ msgstr "نوع البيانات"
#: documents/models.py:831
msgid "extra data"
msgstr ""
msgstr "بيانات إضافية"
#: documents/models.py:835
msgid "Extra data for the custom field, such as select options"
msgstr ""
msgstr "بيانات إضافية للحقل المخصص، مثل تحديد خيارات"
#: documents/models.py:841
msgid "custom field"
@@ -927,21 +927,21 @@ msgstr "إجراءات"
msgid "enabled"
msgstr "مفعل"
#: documents/serialisers.py:119
#: documents/serialisers.py:120
#, python-format
msgid "Invalid regular expression: %(error)s"
msgstr "التعبير النظامي خاطىء: %(error)s"
#: documents/serialisers.py:435
#: documents/serialisers.py:467
msgid "Invalid color."
msgstr "لون خاطئ."
#: documents/serialisers.py:1314
#: documents/serialisers.py:1397
#, python-format
msgid "File type %(type)s not supported"
msgstr "نوع الملف %(type)s غير مدعوم"
#: documents/serialisers.py:1423
#: documents/serialisers.py:1506
msgid "Invalid variable detected."
msgstr "اكتشاف متغير خاطئ."
@@ -1370,62 +1370,66 @@ msgid "Japanese"
msgstr "اليابانية"
#: paperless/settings.py:699
msgid "Korean"
msgstr ""
#: paperless/settings.py:700
msgid "Luxembourgish"
msgstr "اللوكسمبرجية"
#: paperless/settings.py:700
#: paperless/settings.py:701
msgid "Norwegian"
msgstr "النرويجية"
#: paperless/settings.py:701
#: paperless/settings.py:702
msgid "Dutch"
msgstr "الهولندية"
#: paperless/settings.py:702
#: paperless/settings.py:703
msgid "Polish"
msgstr "البولندية"
#: paperless/settings.py:703
#: paperless/settings.py:704
msgid "Portuguese (Brazil)"
msgstr "البرتغالية (البرازيل)"
#: paperless/settings.py:704
#: paperless/settings.py:705
msgid "Portuguese"
msgstr "البرتغالية"
#: paperless/settings.py:705
#: paperless/settings.py:706
msgid "Romanian"
msgstr "الرومانية"
#: paperless/settings.py:706
#: paperless/settings.py:707
msgid "Russian"
msgstr "الروسية"
#: paperless/settings.py:707
#: paperless/settings.py:708
msgid "Slovak"
msgstr "السلوفاكية"
#: paperless/settings.py:708
#: paperless/settings.py:709
msgid "Slovenian"
msgstr "السلوفانية"
#: paperless/settings.py:709
#: paperless/settings.py:710
msgid "Serbian"
msgstr "الصربية"
#: paperless/settings.py:710
#: paperless/settings.py:711
msgid "Swedish"
msgstr "السويدية"
#: paperless/settings.py:711
#: paperless/settings.py:712
msgid "Turkish"
msgstr "التركية"
#: paperless/settings.py:712
#: paperless/settings.py:713
msgid "Ukrainian"
msgstr "الأوكرانية"
#: paperless/settings.py:713
#: paperless/settings.py:714
msgid "Chinese Simplified"
msgstr "الصينية المبسطة"
+24 -20
View File
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-09 11:27-0700\n"
"PO-Revision-Date: 2024-07-09 18:28\n"
"POT-Creation-Date: 2024-08-28 17:12-0700\n"
"PO-Revision-Date: 2024-08-29 03:10\n"
"Last-Translator: \n"
"Language-Team: Belarusian\n"
"Language: be_BY\n"
@@ -927,21 +927,21 @@ msgstr ""
msgid "enabled"
msgstr ""
#: documents/serialisers.py:119
#: documents/serialisers.py:120
#, python-format
msgid "Invalid regular expression: %(error)s"
msgstr "Няправільны рэгулярны выраз: %(error)s"
#: documents/serialisers.py:435
#: documents/serialisers.py:467
msgid "Invalid color."
msgstr "Няправільны колер."
#: documents/serialisers.py:1314
#: documents/serialisers.py:1397
#, python-format
msgid "File type %(type)s not supported"
msgstr "Тып файла %(type)s не падтрымліваецца"
#: documents/serialisers.py:1423
#: documents/serialisers.py:1506
msgid "Invalid variable detected."
msgstr "Выяўлена няправільная зменная."
@@ -1369,62 +1369,66 @@ msgid "Japanese"
msgstr ""
#: paperless/settings.py:699
msgid "Korean"
msgstr ""
#: paperless/settings.py:700
msgid "Luxembourgish"
msgstr "Люксембургская"
#: paperless/settings.py:700
#: paperless/settings.py:701
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:701
#: paperless/settings.py:702
msgid "Dutch"
msgstr "Нідэрландская"
#: paperless/settings.py:702
#: paperless/settings.py:703
msgid "Polish"
msgstr "Польская"
#: paperless/settings.py:703
#: paperless/settings.py:704
msgid "Portuguese (Brazil)"
msgstr "Партугальская (Бразілія)"
#: paperless/settings.py:704
#: paperless/settings.py:705
msgid "Portuguese"
msgstr "Партугальская"
#: paperless/settings.py:705
#: paperless/settings.py:706
msgid "Romanian"
msgstr "Румынская"
#: paperless/settings.py:706
#: paperless/settings.py:707
msgid "Russian"
msgstr "Руская"
#: paperless/settings.py:707
#: paperless/settings.py:708
msgid "Slovak"
msgstr ""
#: paperless/settings.py:708
#: paperless/settings.py:709
msgid "Slovenian"
msgstr "Славенская"
#: paperless/settings.py:709
#: paperless/settings.py:710
msgid "Serbian"
msgstr "Сербская"
#: paperless/settings.py:710
#: paperless/settings.py:711
msgid "Swedish"
msgstr "Шведская"
#: paperless/settings.py:711
#: paperless/settings.py:712
msgid "Turkish"
msgstr "Турэцкая"
#: paperless/settings.py:712
#: paperless/settings.py:713
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:713
#: paperless/settings.py:714
msgid "Chinese Simplified"
msgstr "Кітайская спрошчаная"
+24 -20
View File
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-09 11:27-0700\n"
"PO-Revision-Date: 2024-07-09 18:28\n"
"POT-Creation-Date: 2024-08-28 17:12-0700\n"
"PO-Revision-Date: 2024-08-29 03:10\n"
"Last-Translator: \n"
"Language-Team: Bulgarian\n"
"Language: bg_BG\n"
@@ -927,21 +927,21 @@ msgstr "действия"
msgid "enabled"
msgstr "активирано"
#: documents/serialisers.py:119
#: documents/serialisers.py:120
#, python-format
msgid "Invalid regular expression: %(error)s"
msgstr "Невалиден регулярен израз: %(error)s"
#: documents/serialisers.py:435
#: documents/serialisers.py:467
msgid "Invalid color."
msgstr "Невалиден цвят."
#: documents/serialisers.py:1314
#: documents/serialisers.py:1397
#, python-format
msgid "File type %(type)s not supported"
msgstr "Файловия тип %(type)s не се поддържа"
#: documents/serialisers.py:1423
#: documents/serialisers.py:1506
msgid "Invalid variable detected."
msgstr "Засечена е невалидна променлива."
@@ -1370,62 +1370,66 @@ msgid "Japanese"
msgstr "Японски"
#: paperless/settings.py:699
msgid "Korean"
msgstr ""
#: paperless/settings.py:700
msgid "Luxembourgish"
msgstr "Люксембургски"
#: paperless/settings.py:700
#: paperless/settings.py:701
msgid "Norwegian"
msgstr "Норвежки"
#: paperless/settings.py:701
#: paperless/settings.py:702
msgid "Dutch"
msgstr "Холандски"
#: paperless/settings.py:702
#: paperless/settings.py:703
msgid "Polish"
msgstr "Полски"
#: paperless/settings.py:703
#: paperless/settings.py:704
msgid "Portuguese (Brazil)"
msgstr "Португалски (Бразилия)"
#: paperless/settings.py:704
#: paperless/settings.py:705
msgid "Portuguese"
msgstr "Португалски"
#: paperless/settings.py:705
#: paperless/settings.py:706
msgid "Romanian"
msgstr "Румънски"
#: paperless/settings.py:706
#: paperless/settings.py:707
msgid "Russian"
msgstr "Руски"
#: paperless/settings.py:707
#: paperless/settings.py:708
msgid "Slovak"
msgstr "Словашки"
#: paperless/settings.py:708
#: paperless/settings.py:709
msgid "Slovenian"
msgstr "Словенски"
#: paperless/settings.py:709
#: paperless/settings.py:710
msgid "Serbian"
msgstr "Сръбски"
#: paperless/settings.py:710
#: paperless/settings.py:711
msgid "Swedish"
msgstr "Шведски"
#: paperless/settings.py:711
#: paperless/settings.py:712
msgid "Turkish"
msgstr "Турски"
#: paperless/settings.py:712
#: paperless/settings.py:713
msgid "Ukrainian"
msgstr "Украински"
#: paperless/settings.py:713
#: paperless/settings.py:714
msgid "Chinese Simplified"
msgstr "Китайски опростен"
Loaded 100 of 145 files, more files were not shown because too many files have changed in this diff. Show more