Compare commits

..

664 Commits
v2.15.1 ... dev

Author SHA1 Message Date
shamoon
7604a0b583
Fix: prevent ASN collisions for merge operations (#11634) 2025-12-19 20:05:34 -08:00
shamoon
4e789acf2d
Chore: mark test_error_skip_rule as flaky 2025-12-18 10:15:04 -08:00
shamoon
d9459d04ea
Chore: refactor preview URL variable naming and safeUrl usage 2025-12-18 09:59:14 -08:00
github-actions[bot]
305d764805
Changelog v2.20.3 - GHA (#11623) 2025-12-18 08:12:05 -08:00
shamoon
eca2ba3657
Bump version to 2.20.3 2025-12-18 07:29:56 -08:00
shamoon
220c70b27d
Merge branch 'dev' 2025-12-18 07:29:04 -08:00
github-actions[bot]
ccaebabe0a
New Crowdin translations by GitHub Action (#11596) 2025-12-18 07:21:46 -08:00
shamoon
598540fda0
Chore: mark another test flaky 2025-12-18 07:17:50 -08:00
GitHub Actions
b1a75b0166 Auto translate strings 2025-12-18 14:38:17 +00:00
shamoon
bf38ae98f1
Security: remove safe html pipe 2025-12-18 06:31:25 -08:00
shamoon
84c59f45da
Chore: harden SafeUrlPipe 2025-12-18 06:30:58 -08:00
GitHub Actions
d8397ac77e Auto translate strings 2025-12-18 08:22:30 +00:00
shamoon
7c0a13b339
Fix typo in filter path hint text 2025-12-18 00:17:43 -08:00
shamoon
7c8db78a62
Chore: use the MS playwright image for e2e testing in CI (#11607) 2025-12-16 08:46:12 -08:00
github-actions[bot]
04f81bf17d
Changelog v2.20.2 - GHA (#11594) 2025-12-12 15:52:24 -08:00
shamoon
f96a29db5d
Bump version to 2.20.2 2025-12-12 15:10:55 -08:00
shamoon
5af3039d62
Merge branch 'dev' 2025-12-12 15:10:08 -08:00
shamoon
078cba4bd1
Fix: allow safe <style> tags in SVG uploads (#11593) 2025-12-12 22:01:56 +00:00
shamoon
43e29598b3
Add more allowed SVG attributes to validator 2025-12-12 13:18:38 -08:00
Trenton H
d9a596d67a
Fix: Expanded SVG validation whitelist and additional checks (#11590) 2025-12-12 20:04:04 +00:00
shamoon
a1026f03db
Fix: use request.stream instead of request.content (#11591) 2025-12-12 19:50:14 +00:00
github-actions[bot]
6c8a9b0373
New Crowdin translations by GitHub Action (#11520) 2025-12-12 18:12:29 +00:00
GitHub Actions
7130c0bd06 Auto translate strings 2025-12-12 17:42:19 +00:00
shamoon
d391fdec64
Resolve CodeQL warning 2025-12-12 09:39:56 -08:00
GitHub Actions
4d7aa8e1a2 Auto translate strings 2025-12-12 17:30:36 +00:00
shamoon
9bdbfd362f
Merge commit from fork
* Add safe regex matching with timeouts and validation

* Remove redundant length check

* Remove timeouterror workaround
2025-12-12 09:28:47 -08:00
shamoon
9ba1d93e15
Merge commit from fork
* Uses a custom transport to resolve the slim chance of a DNS rebinding affecting the webhook

* Fix WebhookTransport hostname resolution and validation

* Fix test failures

* Lint

* Keep all internal logic inside WebhookTransport

* Fix test failure

* Update handlers.py

* Update handlers.py

---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-12-12 09:28:17 -08:00
shamoon
a9c73e2846
Update validators.py 2025-12-12 09:27:19 -08:00
GitHub Actions
332136df8b Auto translate strings 2025-12-12 16:44:49 +00:00
shamoon
3a1d33225e
Fixhancement: pass ordering to tag children (#11556) 2025-12-12 16:43:16 +00:00
Jan Kleine
e770ff572e
Documentation: Document missing workflows env variable and complete diagram (#11554) 2025-12-12 16:12:23 +00:00
Trenton H
402f2ead59
Fixes the workflow configuration being nested under the consumption documentation (#11588) 2025-12-12 07:51:45 -08:00
shamoon
3b4d958b97
Performance: avoid unnecessary filename operations on bulk custom field updates (#11558) 2025-12-12 07:50:51 -08:00
shamoon
3f81b432ec
Fix: normalize SVG tag and attribute names, add version (#11586) 2025-12-11 19:17:55 -08:00
shamoon
66d363bdc5
Chore: refactor workflows code (#11563) 2025-12-11 12:13:10 -08:00
GitHub Actions
c845cf0a19 Auto translate strings 2025-12-10 16:40:14 +00:00
shamoon
317f239d09
Fix: pass additional arguments to TagSerializer for permissions (#11576) 2025-12-10 08:38:28 -08:00
shamoon
128c3539d5
Chore: fix set_permissions_for_object type (#11564) 2025-12-10 00:12:40 +00:00
GitHub Actions
26975868a0 Auto translate strings 2025-12-09 20:17:39 +00:00
shamoon
f3fc3febf1
Chore: update Angular dependencies to 20.3.15 (#11568) 2025-12-09 12:15:49 -08:00
shamoon
8efc998687
Chore: refactor permission checks to use queryset.exists() 2025-12-08 15:53:10 -08:00
dependabot[bot]
3f47900f06
Chore(deps): Bump actions/checkout from 5 to 6 in the actions group (#11515)
Bumps the actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 5 to 6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 04:53:32 +00:00
dependabot[bot]
963a519e5c
Chore(deps-dev): Bump webpack from 5.102.1 to 5.103.0 in /src-ui (#11513)
Bumps [webpack](https://github.com/webpack/webpack) from 5.102.1 to 5.103.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.102.1...v5.103.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.103.0
  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>
2025-12-08 04:08:40 +00:00
dependabot[bot]
59e5d15cf0
Chore(deps-dev): Bump @playwright/test from 1.56.1 to 1.57.0 in /src-ui (#11514)
Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.56.1 to 1.57.0.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.56.1...v1.57.0)

---
updated-dependencies:
- dependency-name: "@playwright/test"
  dependency-version: 1.57.0
  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>
2025-12-08 03:54:27 +00:00
GitHub Actions
ef2f65fcb8 Auto translate strings 2025-12-08 03:09:28 +00:00
shamoon
555ba8bb19
Chore: remove use of logs ngFor 2025-12-07 19:07:28 -08:00
dependabot[bot]
01992bb5c6
Chore(deps-dev): Bump the frontend-eslint-dependencies group (#11512)
Bumps the frontend-eslint-dependencies group in /src-ui with 3 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) and [@typescript-eslint/utils](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/utils).


Updates `@typescript-eslint/eslint-plugin` from 8.47.0 to 8.48.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.48.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.47.0 to 8.48.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.48.0/packages/parser)

Updates `@typescript-eslint/utils` from 8.47.0 to 8.48.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.48.0/packages/utils)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.48.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.48.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.48.0
  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>
2025-12-08 03:05:46 +00:00
shamoon
21032ac008
Tweakhancement: dim inactive users in users-groups list (#11537) 2025-12-04 20:45:49 +00:00
dependabot[bot]
b63e095a60
docker(deps): bump astral-sh/uv (#11533)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.9.14-python3.12-trixie-slim to 0.9.15-python3.12-trixie-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.9.14...0.9.15)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.9.15-python3.12-trixie-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-04 07:06:08 -08:00
shamoon
ce642409e8
Chore: add some output of social login errors (#11527) 2025-12-03 18:52:49 +00:00
Trenton H
2e5bd02e7e
chore: Improves dependabot groups, in particular the Django group not catching everything (#11397) 2025-12-03 09:25:59 -08:00
github-actions[bot]
7032da53c5
Documentation: Add v2.20.1 changelog (#11510)
* Changelog v2.20.1 - 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>
2025-12-01 23:13:18 +00:00
Trenton H
6f3451bce0 Bumps version to 2.20.1 2025-12-01 14:01:09 -08:00
github-actions[bot]
8c5b5cd77b
New Crowdin translations by GitHub Action (#11442)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-12-01 21:58:07 +00:00
dependabot[bot]
919c54c6ba
docker(deps): Bump astral-sh/uv (#11450)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.9.10-python3.12-trixie-slim to 0.9.14-python3.12-trixie-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.9.10...0.9.14)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.9.11-python3.12-trixie-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 18:28:42 +00:00
shamoon
4632ad3a36
Fix: set search term when using advanced search from global search (#11503) 2025-11-30 07:20:24 -08:00
shamoon
0c43b50f01
Fix: change async handling of select custom field updates (#11490) 2025-11-30 03:54:15 +00:00
Daniel Rheinbay
67d079fe14
fix: Skip SSL for MariaDB ping in init script (#11491)
Restore compatibility with MariaDB server versions < 11.4, which do not use SSL by default.
2025-11-28 14:25:57 -08:00
GitHub Actions
ca674e5a02 Auto translate strings 2025-11-27 00:25:48 +00:00
dependabot[bot]
71e08a1e98
Chore(deps): Bump @angular/common from 20.3.12 to 20.3.14 in /src-ui (#11481)
Bumps [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) from 20.3.12 to 20.3.14.
- [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/20.3.14/packages/common)

---
updated-dependencies:
- dependency-name: "@angular/common"
  dependency-version: 20.3.14
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-26 16:24:05 -08:00
shamoon
1e61a6cd6a
Fix: handle allauth groups location breaking change (#11471) 2025-11-25 09:18:05 -08:00
Cary Kempston
a76731ca89
Development: sync Dockerfile changes to .devcontainer/Dockerfile (#11463) 2025-11-25 07:18:56 -08:00
Daniel Rheinbay
ffc56bddda
fix: Add user parameter to MariaDB connection check (#11441) 2025-11-23 15:03:35 -08:00
github-actions[bot]
4c2cc373f2
Documentation: Add v2.20.0 changelog (#11433) 2025-11-22 14:00:59 -08:00
shamoon
76bb6d3422
Bump version to 2.20.0 2025-11-22 13:18:06 -08:00
github-actions[bot]
85a2a0a416
New Crowdin translations by GitHub Action (#11399) 2025-11-22 17:45:22 +00:00
Trenton H
5036aa1ea3
Feature: Upgrade underlying Docker image to Trixie (#10562) 2025-11-22 02:08:47 +00:00
GitHub Actions
f7da273ab7 Auto translate strings 2025-11-21 23:54:02 +00:00
shamoon
93338a0a82
Fixhancement: more log viewer improvements (#11426) 2025-11-21 15:52:12 -08:00
Trenton H
a96db50b0a
Feature: Replace duplicated static files with symlinks (#11418) 2025-11-21 20:07:57 +00:00
Trenton H
c5e80a7e4f
chore: Upgrades psycopg to 3.2.12 (#11420) 2025-11-21 11:42:22 -08:00
Trenton H
bc622d67fc
Chore: Configure pre-commit to format our s6-overlay files (#11414) 2025-11-19 21:34:29 +00:00
shamoon
4a8d3c858c
Chore: re-enable docker builds for PRs (#11398) 2025-11-19 20:58:10 +00:00
GitHub Actions
8c335321cd Auto translate strings 2025-11-19 16:56:11 +00:00
shamoon
27966858fd
Enhancement: add more relative dates, support modified (#11411) 2025-11-19 16:54:24 +00:00
dependabot[bot]
d3bfb186e0
Chore(deps-dev): Bump glob in /src/paperless_mail/templates (#11413)
Bumps [glob](https://github.com/isaacs/node-glob) from 10.4.1 to 10.5.0.
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v10.4.1...v10.5.0)

---
updated-dependencies:
- dependency-name: glob
  dependency-version: 10.5.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-19 15:49:19 +00:00
shamoon
cf5ac596ed
Performance: make move files after select custom field change async (#11391) 2025-11-19 15:21:33 +00:00
Trenton H
25b5e8fede
Improves the MariaDB wait command to use mariadb-admin ping for a better check if the server is up (#11396) 2025-11-18 23:45:49 +00:00
shamoon
80be6793cf
Fix: prevent focus loss from change detection in cf query dropdown (#11409) 2025-11-18 12:05:48 -08:00
david-loe
7b175ec1b3
Development: fix correct test delete select option (#11406) 2025-11-18 19:28:52 +00:00
Ed Bardsley
36d45ecf4d
Development: fix unreachable code around assertRaises blocks (#11365)
* tests: general cleanup and fixes for runnning under docker

This now allows tests to be run under a locally built or production
docker image with something like:

  `docker run --rm -v $PWD:/usr/src/paperless --entrypoint=bash paperlessngx/paperless-ngx:latest -c "uv run pytest"`

Specific fixes:
- fix unreachable code around `assertRaises` blocks
- fix `assertInt` typos
- fix `str(e)` vs `str(e.exception)` issues
- skip permission-based checks when root (in a docker container)
- catch `OSError` problems when instantiating `INotify` and
  skip inotify-based tests when it's unavailable.

* Reverts most files to dev while keeping the exception assert fixes

---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-11-18 18:28:43 +00:00
dependabot[bot]
4bf681387a
docker-compose(deps): bump gotenberg/gotenberg in /docker/compose (#11393)
Bumps gotenberg/gotenberg from 8.24 to 8.25.

---
updated-dependencies:
- dependency-name: gotenberg/gotenberg
  dependency-version: '8.25'
  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>
2025-11-18 09:29:39 -08:00
GitHub Actions
c05d75dab0 Auto translate strings 2025-11-18 15:58:50 +00:00
shamoon
7a50157164
Fix: sort editing filterable dropdowns sooner (#11404) 2025-11-18 07:57:09 -08:00
GitHub Actions
a93d83119e Auto translate strings 2025-11-18 04:55:39 +00:00
dependabot[bot]
addaf92a61
Chore(deps): Bump the frontend-angular-dependencies group (#11260)
Bumps the frontend-angular-dependencies group in /src-ui with 21 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/cdk](https://github.com/angular/components) | `20.2.6` | `20.2.11` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `20.3.2` | `20.3.9` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `20.3.2` | `20.3.9` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `20.3.2` | `20.3.9` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `20.3.2` | `20.3.9` |
| [@angular/localize](https://github.com/angular/angular) | `20.3.2` | `20.3.9` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `20.3.2` | `20.3.9` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `20.3.2` | `20.3.9` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `20.3.2` | `20.3.9` |
| [@ng-select/ng-select](https://github.com/ng-select/ng-select) | `20.2.2` | `20.6.1` |
| [ngx-cookie-service](https://github.com/stevermeister/ngx-cookie-service) | `20.1.0` | `20.1.1` |
| [@angular-devkit/core](https://github.com/angular/angular-cli) | `20.3.3` | `20.3.8` |
| [@angular-devkit/schematics](https://github.com/angular/angular-cli) | `20.3.3` | `20.3.8` |
| [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) | `20.3.0` | `20.5.0` |
| [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) | `20.3.0` | `20.5.0` |
| [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) | `20.3.0` | `20.5.0` |
| [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) | `20.3.0` | `20.5.0` |
| [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) | `20.3.0` | `20.5.0` |
| [@angular/build](https://github.com/angular/angular-cli) | `20.3.3` | `20.3.8` |
| [@angular/cli](https://github.com/angular/angular-cli) | `20.3.3` | `20.3.8` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `20.3.2` | `20.3.9` |


Updates `@angular/cdk` from 20.2.6 to 20.2.11
- [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/20.2.6...20.2.11)

Updates `@angular/common` from 20.3.2 to 20.3.9
- [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/20.3.9/packages/common)

Updates `@angular/compiler` from 20.3.2 to 20.3.9
- [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/20.3.9/packages/compiler)

Updates `@angular/core` from 20.3.2 to 20.3.9
- [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/20.3.9/packages/core)

Updates `@angular/forms` from 20.3.2 to 20.3.9
- [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/20.3.9/packages/forms)

Updates `@angular/localize` from 20.3.2 to 20.3.9
- [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/20.3.2...20.3.9)

Updates `@angular/platform-browser` from 20.3.2 to 20.3.9
- [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/20.3.9/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 20.3.2 to 20.3.9
- [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/20.3.9/packages/platform-browser-dynamic)

Updates `@angular/router` from 20.3.2 to 20.3.9
- [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/20.3.9/packages/router)

Updates `@ng-select/ng-select` from 20.2.2 to 20.6.1
- [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/v20.2.2...v20.6.1)

Updates `ngx-cookie-service` from 20.1.0 to 20.1.1
- [Release notes](https://github.com/stevermeister/ngx-cookie-service/releases)
- [Changelog](https://github.com/stevermeister/ngx-cookie-service/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stevermeister/ngx-cookie-service/compare/v20.1.0...v20.1.1)

Updates `@angular-devkit/core` from 20.3.3 to 20.3.8
- [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/20.3.3...20.3.8)

Updates `@angular-devkit/schematics` from 20.3.3 to 20.3.8
- [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/20.3.3...20.3.8)

Updates `@angular-eslint/builder` from 20.3.0 to 20.5.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/v20.5.0/packages/builder)

Updates `@angular-eslint/eslint-plugin` from 20.3.0 to 20.5.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/v20.5.0/packages/eslint-plugin)

Updates `@angular-eslint/eslint-plugin-template` from 20.3.0 to 20.5.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/v20.5.0/packages/eslint-plugin-template)

Updates `@angular-eslint/schematics` from 20.3.0 to 20.5.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/v20.5.0/packages/schematics)

Updates `@angular-eslint/template-parser` from 20.3.0 to 20.5.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/v20.5.0/packages/template-parser)

Updates `@angular/build` from 20.3.3 to 20.3.8
- [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/20.3.3...20.3.8)

Updates `@angular/cli` from 20.3.3 to 20.3.8
- [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/20.3.3...20.3.8)

Updates `@angular/compiler-cli` from 20.3.2 to 20.3.9
- [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/20.3.9/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/cdk"
  dependency-version: 20.2.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/common"
  dependency-version: 20.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-version: 20.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-version: 20.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-version: 20.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-version: 20.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-version: 20.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 20.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-version: 20.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-select/ng-select"
  dependency-version: 20.6.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-cookie-service
  dependency-version: 20.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/core"
  dependency-version: 20.3.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/schematics"
  dependency-version: 20.3.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/builder"
  dependency-version: 20.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin"
  dependency-version: 20.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin-template"
  dependency-version: 20.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/schematics"
  dependency-version: 20.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/template-parser"
  dependency-version: 20.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/build"
  dependency-version: 20.3.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-version: 20.3.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-version: 20.3.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  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>
2025-11-17 20:53:54 -08:00
dependabot[bot]
8c7fa4e165
Chore(deps-dev): Bump @playwright/test from 1.55.1 to 1.56.1 in /src-ui (#11263)
Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.55.1 to 1.56.1.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.55.1...v1.56.1)

---
updated-dependencies:
- dependency-name: "@playwright/test"
  dependency-version: 1.56.1
  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>
2025-11-18 04:12:40 +00:00
dependabot[bot]
22a47a28dc
Chore(deps-dev): Bump webpack from 5.102.0 to 5.102.1 in /src-ui (#11264)
Bumps [webpack](https://github.com/webpack/webpack) from 5.102.0 to 5.102.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.102.0...v5.102.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.102.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-18 03:57:10 +00:00
dependabot[bot]
20d921142e
Chore(deps-dev): Bump the frontend-eslint-dependencies group (#11262)
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.45.0 to 8.46.2
- [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.46.2/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.45.0 to 8.46.2
- [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.46.2/packages/parser)

Updates `@typescript-eslint/utils` from 8.45.0 to 8.46.2
- [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.46.2/packages/utils)

Updates `eslint` from 9.36.0 to 9.39.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.36.0...v9.39.0)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.46.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.46.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.46.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: eslint
  dependency-version: 9.39.0
  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>
2025-11-18 03:41:15 +00:00
dependabot[bot]
1ed8f1d086
Chore(deps-dev): Bump jest-preset-angular (#11261)
Bumps the frontend-jest-dependencies group in /src-ui with 1 update: [jest-preset-angular](https://github.com/thymikee/jest-preset-angular).


Updates `jest-preset-angular` from 15.0.2 to 15.0.3
- [Release notes](https://github.com/thymikee/jest-preset-angular/releases)
- [Changelog](https://github.com/thymikee/jest-preset-angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/thymikee/jest-preset-angular/compare/v15.0.2...v15.0.3)

---
updated-dependencies:
- dependency-name: jest-preset-angular
  dependency-version: 15.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-jest-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-18 03:20:27 +00:00
dependabot[bot]
46853e10dc
Chore(deps-dev): Bump @types/node from 24.6.1 to 24.9.2 in /src-ui (#11265)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.6.1 to 24.9.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.9.2
  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>
2025-11-18 03:04:23 +00:00
dependabot[bot]
c31c244b54
Chore(deps): Bump the small-changes group across 1 directory with 11 updates (#11337)
Bumps the small-changes group with 11 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [bleach](https://github.com/mozilla/bleach) | `6.2.0` | `6.3.0` |
| [ocrmypdf](https://github.com/ocrmypdf/OCRmyPDF) | `16.11.0` | `16.11.1` |
| [python-dotenv](https://github.com/theskumar/python-dotenv) | `1.1.1` | `1.2.1` |
| [rapidfuzz](https://github.com/rapidfuzz/RapidFuzz) | `3.14.1` | `3.14.3` |
| [psycopg-pool](https://github.com/psycopg/psycopg) | `3.2.6` | `3.2.7` |
| [mkdocs-glightbox](https://github.com/blueswen/mkdocs-glightbox) | `0.5.1` | `0.5.2` |
| [mkdocs-material](https://github.com/squidfunk/mkdocs-material) | `9.6.22` | `9.6.23` |
| [pre-commit](https://github.com/pre-commit/pre-commit) | `4.3.0` | `4.4.0` |
| [ruff](https://github.com/astral-sh/ruff) | `0.14.0` | `0.14.4` |
| [types-bleach](https://github.com/typeshed-internal/stub_uploader) | `6.2.0.20250809` | `6.3.0.20251029` |
| [types-markdown](https://github.com/typeshed-internal/stub_uploader) | `3.9.0.20250906` | `3.10.0.20251106` |



Updates `bleach` from 6.2.0 to 6.3.0
- [Changelog](https://github.com/mozilla/bleach/blob/main/CHANGES)
- [Commits](https://github.com/mozilla/bleach/compare/v6.2.0...v6.3.0)

Updates `ocrmypdf` from 16.11.0 to 16.11.1
- [Release notes](https://github.com/ocrmypdf/OCRmyPDF/releases)
- [Changelog](https://github.com/ocrmypdf/OCRmyPDF/blob/main/docs/release_notes.md)
- [Commits](https://github.com/ocrmypdf/OCRmyPDF/compare/v16.11.0...v16.11.1)

Updates `python-dotenv` from 1.1.1 to 1.2.1
- [Release notes](https://github.com/theskumar/python-dotenv/releases)
- [Changelog](https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/theskumar/python-dotenv/compare/v1.1.1...v1.2.1)

Updates `rapidfuzz` from 3.14.1 to 3.14.3
- [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.14.1...v3.14.3)

Updates `psycopg-pool` from 3.2.6 to 3.2.7
- [Changelog](https://github.com/psycopg/psycopg/blob/master/docs/news.rst)
- [Commits](https://github.com/psycopg/psycopg/compare/3.2.6...3.2.7)

Updates `mkdocs-glightbox` from 0.5.1 to 0.5.2
- [Release notes](https://github.com/blueswen/mkdocs-glightbox/releases)
- [Changelog](https://github.com/blueswen/mkdocs-glightbox/blob/main/CHANGELOG)
- [Commits](https://github.com/blueswen/mkdocs-glightbox/compare/v0.5.1...v0.5.2)

Updates `mkdocs-material` from 9.6.22 to 9.6.23
- [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.6.22...9.6.23)

Updates `pre-commit` from 4.3.0 to 4.4.0
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v4.3.0...v4.4.0)

Updates `ruff` from 0.14.0 to 0.14.4
- [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.14.0...0.14.4)

Updates `types-bleach` from 6.2.0.20250809 to 6.3.0.20251029
- [Commits](https://github.com/typeshed-internal/stub_uploader/commits)

Updates `types-markdown` from 3.9.0.20250906 to 3.10.0.20251106
- [Commits](https://github.com/typeshed-internal/stub_uploader/commits)

---
updated-dependencies:
- dependency-name: bleach
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: ocrmypdf
  dependency-version: 16.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: python-dotenv
  dependency-version: 1.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: rapidfuzz
  dependency-version: 3.14.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: psycopg-pool
  dependency-version: 3.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: mkdocs-glightbox
  dependency-version: 0.5.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: mkdocs-material
  dependency-version: 9.6.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: pre-commit
  dependency-version: 4.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: ruff
  dependency-version: 0.14.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: types-bleach
  dependency-version: 6.3.0.20251029
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: types-markdown
  dependency-version: 3.10.0.20251106
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-17 18:47:16 -08:00
dependabot[bot]
56493d6640
Chore(deps): Bump django-auditlog from 3.2.1 to 3.3.0 (#11021)
Bumps [django-auditlog](https://github.com/jazzband/django-auditlog) from 3.2.1 to 3.3.0.
- [Release notes](https://github.com/jazzband/django-auditlog/releases)
- [Changelog](https://github.com/jazzband/django-auditlog/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jazzband/django-auditlog/compare/v3.2.1...v3.3.0)

---
updated-dependencies:
- dependency-name: django-auditlog
  dependency-version: 3.3.0
  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>
2025-11-17 23:52:47 +00:00
dependabot[bot]
f7f94762b6
Chore(deps): Bump the actions group with 7 updates (#11259)
Bumps the actions group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) | `6` | `7` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4` | `5` |
| [actions/setup-node](https://github.com/actions/setup-node) | `5` | `6` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `5` | `6` |
| [stumpylog/image-cleaner-action](https://github.com/stumpylog/image-cleaner-action) | `0.11.0` | `0.12.0` |
| [github/codeql-action](https://github.com/github/codeql-action) | `3` | `4` |
| [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action) | `6` | `7` |


Updates `astral-sh/setup-uv` from 6 to 7
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v6...v7)

Updates `actions/upload-artifact` from 4 to 5
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

Updates `actions/setup-node` from 5 to 6
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v5...v6)

Updates `actions/download-artifact` from 5 to 6
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

Updates `stumpylog/image-cleaner-action` from 0.11.0 to 0.12.0
- [Release notes](https://github.com/stumpylog/image-cleaner-action/releases)
- [Changelog](https://github.com/stumpylog/image-cleaner-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stumpylog/image-cleaner-action/compare/v0.11.0...v0.12.0)

Updates `github/codeql-action` from 3 to 4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

Updates `stefanzweifel/git-auto-commit-action` from 6 to 7
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: stumpylog/image-cleaner-action
  dependency-version: 0.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-17 23:13:30 +00:00
dependabot[bot]
beb5fe2232
Chore(deps): Bump drf-spectacular-sidecar from 2025.9.1 to 2025.10.1 (#11019)
Bumps [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar) from 2025.9.1 to 2025.10.1.
- [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2025.9.1...2025.10.1)

---
updated-dependencies:
- dependency-name: drf-spectacular-sidecar
  dependency-version: 2025.10.1
  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>
2025-11-17 22:55:50 +00:00
dependabot[bot]
c924213f32
Chore(deps): Bump django-filter from 25.1 to 25.2 (#11020)
Bumps [django-filter](https://github.com/carltongibson/django-filter) from 25.1 to 25.2.
- [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/25.1...25.2)

---
updated-dependencies:
- dependency-name: django-filter
  dependency-version: '25.2'
  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>
2025-11-17 22:26:33 +00:00
dependabot[bot]
b053b35332
Chore(deps): Update django-allauth[mfa,socialaccount] requirement from ~=65.4.0 to ~=65.12.1 (#11198)
* Chore(deps): Update django-allauth[mfa,socialaccount] requirement

---
updated-dependencies:
- dependency-name: django-allauth[mfa,socialaccount]
  dependency-version: 65.12.1
  dependency-type: direct:production
...

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

* Update ratelimit mock path

---------

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>
2025-11-17 21:58:10 +00:00
dependabot[bot]
a45692aa0f
docker(deps): bump astral-sh/uv (#11394)
---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.9.10-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-17 13:38:26 -08:00
Michael Martin
c3ac102eba
Enhancement: speed-up docker container startup (#11134)
This alters the retry/backoff logic in the init-wait-for-db script to be more
optimistic about database availability. During regular deployment and
operations of paperless-ngx, it's common to restart the application server with
the database instance already running, so we should optimize for this case.

Instead of unconditionally delaying 5 seconds between each connection attempt,
start with a minimum delay of 1 second and increase the delay linearly with
each attempt, maxing out at 10 seconds. This makes the retry count-based
failure mode less practical, so instead we just use a timeout-based approach.*

*NOTE: the original implementation would have an effective timeout of 25s. This
alters the behavior to 60s.

Additionally, this removes an unnecessary 5s delay that was injected in the
postgres case. The script uses a more comprehensive connection check for
postgres than it does mariadb, so if anything this 5s delay after getting an
"ok" response from the DB was extra unnecessary in the postgres case.
2025-11-17 13:11:49 -08:00
shamoon
0e5ab7f3e0
Fix: support for custom field ordering w advanced search (#11383) 2025-11-17 20:47:55 +00:00
shamoon
533b64cb70
Chore: replace test image URLs to our own files (#11390) 2025-11-17 10:22:54 -08:00
shamoon
b3d6359afc
Chore: set signal receivers with weak=False 2025-11-17 10:02:32 -08:00
github-actions[bot]
b6e3827ab1
Documentation: Add v2.19.6 changelog (#11374)
---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-11-15 19:03:46 -08:00
shamoon
7cd802cf48
Bump version to 2.19.6 2025-11-15 14:24:15 -08:00
shamoon
7470b799a3
Merge branch 'dev' 2025-11-15 14:23:38 -08:00
shamoon
b5df90156e
Documentation: update redis security link (#11373) 2025-11-15 13:31:03 -08:00
github-actions[bot]
733d2e19a0
New Crowdin translations by GitHub Action (#11310) 2025-11-15 16:32:37 +00:00
shamoon
fe7419484b
Chore: Update PR template AI disclosure 2025-11-15 08:18:08 -08:00
shamoon
0d827e8511
Documentation: add {{doc_title}} placeholder 2025-11-14 21:41:07 -08:00
shamoon
69514d8d70
Chore: add backoff ro handle 429 Wikimedia requests in tests (#11364) 2025-11-14 15:58:29 -08:00
dependabot[bot]
dd6f7fad32
docker(deps): bump astral-sh/uv (#11338)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.9.7-python3.12-bookworm-slim to 0.9.9-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.9.7...0.9.9)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.9.8-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-14 18:37:33 +00:00
Ed Bardsley
c5ad148dc7
Fix: include BASE_URL when constructing doc_url for workflows (#11360)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-11-14 17:45:13 +00:00
shamoon
b12f1e757c
Fixhancement: refactor email attachment logic (#11336) 2025-11-14 17:28:46 +00:00
GitHub Actions
0cbab1ae80 Auto translate strings 2025-11-14 16:10:47 +00:00
shamoon
0219df5b67
Fixhancement: trim whitespace for some text searches (#11357) 2025-11-14 08:09:09 -08:00
shamoon
005ef4fce6
Fix: update Outlook refresh token when refreshed (#11341) 2025-11-11 08:27:24 -08:00
shamoon
44f0191bfb
Fix: only cache remote version for version checking (#11320) 2025-11-09 00:34:46 +00:00
shamoon
e9f846ca24
Fix: include replace none logic in storage path preview, improve jinja conditionals for empty metadata (#11315) 2025-11-08 13:31:57 -08:00
GitHub Actions
2049497b76 Auto translate strings 2025-11-07 19:23:35 +00:00
shamoon
2a9d1fce0d
Chore: include password validation on user edit (#11308) 2025-11-07 11:20:27 -08:00
shamoon
808c074f48
Merge branch 'main' into dev 2025-11-06 13:04:32 -08:00
github-actions[bot]
7927e5c436
Changelog v2.19.5 - GHA (#11305) 2025-11-06 13:01:52 -08:00
shamoon
cac48c9855
Bump version to 2.19.5 2025-11-06 11:39:08 -08:00
github-actions[bot]
3fda648f37
New Crowdin translations by GitHub Action (#11288) 2025-11-06 19:36:26 +00:00
dependabot[bot]
95736eebc4
docker(deps): Bump astral-sh/uv (#11283)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.9.4-python3.12-bookworm-slim to 0.9.7-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.9.4...0.9.7)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.9.7-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-04 20:12:56 -08:00
shamoon
85027dbffd
Fix: ensure custom field query propagation, change detection (#11291) 2025-11-04 12:40:05 -08:00
github-actions[bot]
74f72e417d
Documentation: Add v2.19.4 changelog (#11285)
* Changelog v2.19.4 - GHA

* Update changelog for paperless-ngx 2.19.4

Reorganize changelog to include performance enhancements.

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-11-03 17:39:28 -08:00
shamoon
fe3c424d7d
Bump version to 2.19.4 2025-11-03 16:02:09 -08:00
shamoon
a0172a2754
Chore: fix test error 2025-11-03 16:01:45 -08:00
shamoon
810bf3d612
Fix: fix log loading spinner display condition 2025-11-03 15:54:43 -08:00
github-actions[bot]
846cc47565
New Crowdin translations by GitHub Action (#11238) 2025-11-03 15:34:23 -08:00
GitHub Actions
1d396d9160 Auto translate strings 2025-11-03 17:48:25 +00:00
shamoon
2a4e8f9acd
Performance: re-enable virtual scroll, bump ng-select (#11279) 2025-11-03 09:46:35 -08:00
shamoon
a9dfe8f3f7
Fix: use original_file when attaching docs to workflow emails with added trigger (#11266) 2025-11-03 08:42:29 -08:00
GitHub Actions
906e841ded Auto translate strings 2025-11-03 14:21:38 +00:00
shamoon
6684e80ffc
Fix: mark 'Select' button in doc list for translation (#11278) 2025-11-03 06:18:41 -08:00
GitHub Actions
3dc7cf3da1 Auto translate strings 2025-11-01 20:22:23 +00:00
shamoon
819f606335
Chore: hide slim toggler if insufficient permissions 2025-11-01 13:18:49 -07:00
shamoon
ad45e3f747
Fix: respect fields parameter for created field (#11251) 2025-11-01 13:13:39 -07:00
shamoon
74b10db028
Fix: improve legibility of processed mail error popover in light mode (#11258) 2025-11-01 12:49:05 -07:00
shamoon
cffb9c34f0
Chore: add headers for wikipedia CI tests (#11253) 2025-11-01 09:37:49 -07:00
GitHub Actions
6f52614817 Auto translate strings 2025-11-01 14:53:03 +00:00
shamoon
a0d3527d20
Fixhancement: truncate large logs, improve auto-scroll (#11239) 2025-11-01 07:49:52 -07:00
shamoon
4e64ca7ca6
Chore: add max-height and overflow to processedmail error popover (#11252) 2025-11-01 07:49:31 -07:00
GitHub Actions
e9511bd3da Auto translate strings 2025-10-31 01:28:27 +00:00
shamoon
8b9ca75a90
Fix: delay iframe DOM removal, handle onafterprint error for print in FF (#11237) 2025-10-30 18:26:42 -07:00
shamoon
9f0a4ac19d
Sure sonar, consolidate 2025-10-30 18:00:19 -07:00
shamoon
8f969ecab5
Fix: delay iframe DOM removal for print in FF 2025-10-30 17:24:44 -07:00
shamoon
245e52a4eb Coverage 2025-10-30 17:00:15 -07:00
shamoon
a8c75d95d8 Update document-detail.component.ts 2025-10-30 17:00:15 -07:00
shamoon
d6e2456baf Update document-detail.component.ts 2025-10-30 17:00:15 -07:00
shamoon
3b75d3271e Fix: delay iframe DOM removal for print in FF 2025-10-30 17:00:15 -07:00
GitHub Actions
e88816d141 Auto translate strings 2025-10-30 23:36:37 +00:00
CanbiZ
e5bd4713ac
Performance: use virtual scroll container and log level parsing for logs view (#11233)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-10-30 23:34:53 +00:00
shamoon
b9aced07fb
Chore: cache Github version check for 15 minutes (#11235) 2025-10-30 13:53:30 -07:00
shamoon
6b55740f56
Fix: de-deduplicate children in tag list when filtering (#11229) 2025-10-30 07:02:00 -07:00
github-actions[bot]
9aee063347
Documentation: Add v2.19.3 changelog (#11223)
---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-10-29 11:08:29 -07:00
shamoon
7fe411bb1a
Bump version to 2.19.3 2025-10-29 10:22:28 -07:00
shamoon
34b5f4c565
Merge branch 'dev' 2025-10-29 10:21:56 -07:00
github-actions[bot]
3808a4e14a
New Crowdin translations by GitHub Action (#11161) 2025-10-29 16:27:40 +00:00
dependabot[bot]
3bd4135aba
Chore(deps): Bump django from 5.2.6 to 5.2.7 (#11200)
Bumps [django](https://github.com/django/django) from 5.2.6 to 5.2.7.
- [Commits](https://github.com/django/django/compare/5.2.6...5.2.7)

---
updated-dependencies:
- dependency-name: django
  dependency-version: 5.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-29 14:29:42 +00:00
shamoon
b60fb8ed82
Fix: remove unnecessary permission requirements for new email endpoint (#11215) 2025-10-29 07:14:51 -07:00
GitHub Actions
3f32ed319a Auto translate strings 2025-10-29 02:56:27 +00:00
shamoon
03e6d58f86
Fix: refactor nested sorting in filterable dropdowns (#11214) 2025-10-28 19:54:39 -07:00
GitHub Actions
c197487374 Auto translate strings 2025-10-28 18:07:20 +00:00
shamoon
d718d7d29f
Fix: add root tag filtering for tag list page consistency, fix toggle all (#11208) 2025-10-28 11:04:22 -07:00
GitHub Actions
ce112cda0e Auto translate strings 2025-10-28 17:17:48 +00:00
shamoon
d904aaef60
Change: make workflow action only title draggable (#11209) 2025-10-28 10:14:42 -07:00
shamoon
35bc673648
Update workflows.py 2025-10-27 21:09:19 -07:00
shamoon
d0bd111eab
Change: make workflowrun a softdeletemodel (#11194) 2025-10-27 20:51:39 +00:00
Trenton H
cd81f750b4
Chore: Minor migration optimization for workflow titles (#11197)
* Makes the migration just a little more efficient

* Do it in batches, just in case

* Fixes the model klass name
2025-10-27 13:24:57 -07:00
shamoon
48d21da13b
Fix: support ConsumableDocument in email attachments (#11196) 2025-10-27 10:37:57 -07:00
shamoon
701aafce06
Update issue and discussion templates 2025-10-26 12:14:31 -07:00
Lukas Behrendt
cbe8bc35d6
Chore: fix Postgres compose volume mount path in install script (#11184)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-10-26 14:40:37 +00:00
Tom Hu
1c4fa7237c
Chore: Move to using the codecov action instead of the test-results-action (#11179) 2025-10-26 07:07:36 -07:00
shamoon
63dab0ab09
Change: restrict superuser modifications to superusers only 2025-10-24 16:25:59 -07:00
shamoon
276dc31abe
Fix: add missing import of ConfirmButtonComponent in user-edit-dialog (#11167) 2025-10-24 15:50:46 -07:00
shamoon
a11a2ec13f
Fix: resolve migration warning in 2.19.2 (#11157) 2025-10-23 15:29:49 -07:00
github-actions[bot]
df9136e7d4
Changelog v2.19.2 - GHA (#11153)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-10-23 10:56:48 -07:00
Trenton H
1d8fadcb3c Bumps version to 2.19.2 2025-10-23 09:24:48 -07:00
github-actions[bot]
4e85262781
New Crowdin translations by GitHub Action (#11139)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-10-23 09:10:11 -07:00
GitHub Actions
7e5d80fa38 Auto translate strings 2025-10-23 12:53:46 +00:00
shamoon
3cfd64b77a
Fix: Remove edit requirement for bulk email, show based on setting (#11149) 2025-10-23 05:50:27 -07:00
shamoon
0fc595a16a
Fix: handle undefined IDs in getOriginalObject (#11147) 2025-10-23 05:40:01 -07:00
GitHub Actions
91e2220f23 Auto translate strings 2025-10-23 01:05:32 +00:00
shamoon
893c05dfdc
Fixhancement: display loading status for tags instead of 'Private' (#11140) 2025-10-22 18:01:50 -07:00
github-actions[bot]
faf3e8dc0d
Changelog v2.19.1 - GHA (#11138) 2025-10-22 13:46:41 -07:00
shamoon
41b9fff407
Bump version to 2.19.1 2025-10-22 13:03:28 -07:00
github-actions[bot]
26f61c900f
New Crowdin translations by GitHub Action (#11112) 2025-10-22 19:33:35 +00:00
shamoon
8d0e07e931
Fix: skip workflow title migration for empty titles (#11136) 2025-10-22 12:17:06 -07:00
shamoon
bf9e3fca48
Fix: restore workflow title migration (#11131) 2025-10-22 18:40:13 +00:00
GitHub Actions
144dd8cdf3 Auto translate strings 2025-10-22 18:16:33 +00:00
shamoon
13161ebb01
Fix: retrieve document_count for tag children (#11125) 2025-10-22 11:13:15 -07:00
shamoon
0ebd9f24b5
Fix: move hierarchical order logic in dropdown sorting (#11128) 2025-10-22 10:27:39 -07:00
GitHub Actions
c9f49f390a Auto translate strings 2025-10-22 16:45:15 +00:00
shamoon
31cee7481b
Fix: use original object for children in tag list (#11127) 2025-10-22 09:42:39 -07:00
GitHub Actions
78893292f8 Auto translate strings 2025-10-22 07:39:01 +00:00
shamoon
e4ac079cd7
Fix: dont display or fetch users or groups with insufficient perms (#11111) 2025-10-22 00:36:40 -07:00
github-actions[bot]
597c2629dd
Changelog v2.19.0 - GHA (#11102)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-10-21 10:55:49 -07:00
shamoon
264166810c
Bump version to 2.19.0 2025-10-21 10:03:11 -07:00
dependabot[bot]
a8b42a3c7a
docker(deps): bump astral-sh/uv from 0.9.2-python3.12-bookworm-slim to 0.9.4-python3.12-bookworm-slim (#11091)
* docker(deps): bump astral-sh/uv

Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.9.2-python3.12-bookworm-slim to 0.9.4-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.9.2...0.9.4)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.9.4-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

* Syncs up the CI uv version as well

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-10-21 08:45:57 -07:00
github-actions[bot]
af7bac03f1
New Crowdin translations by GitHub Action (#11094)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-10-21 08:22:49 -07:00
GitHub Actions
363fd5a97f Auto translate strings 2025-10-21 05:45:10 +00:00
shamoon
fcae006afa
Tweak: improve tag parent validation error handling (#11096) 2025-10-20 22:42:01 -07:00
shamoon
a206ac78dd
Chore: update Postgres compose volume mount path (#11084) 2025-10-20 16:18:36 +00:00
github-actions[bot]
4456be72c6
New Crowdin translations by GitHub Action (#10874)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-10-20 09:01:02 -07:00
GitHub Actions
557612f7a2 Auto translate strings 2025-10-20 00:47:20 +00:00
shamoon
bf18eaa5c2
Fix: remove obsolete warning for custom field value index (#11083) 2025-10-19 17:43:02 -07:00
Elias Holzmann
d1c11bcf08
Documentation: correct info re PAPERLESS_THREADS_PER_WORKER (#11031) 2025-10-18 23:01:28 +00:00
shamoon
15e6809a71
Fix: correct infoLink in mail component header 2025-10-15 20:30:56 -07:00
dependabot[bot]
7326224888
docker-compose(deps): Bump gotenberg/gotenberg in /docker/compose (#11050)
Bumps gotenberg/gotenberg from 8.23 to 8.24.

---
updated-dependencies:
- dependency-name: gotenberg/gotenberg
  dependency-version: '8.24'
  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>
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-10-15 13:52:58 -07:00
dependabot[bot]
04a01fb9f4
Chore(deps): Bump the small-changes group across 1 directory with 8 updates (#11065)
* Chore(deps): Bump the small-changes group across 1 directory with 8 updates

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

| Package | From | To |
| --- | --- | --- |
| [filelock](https://github.com/tox-dev/py-filelock) | `3.19.1` | `3.20.0` |
| [gotenberg-client](https://github.com/stumpylog/gotenberg-client) | `0.11.0` | `0.12.0` |
| [nltk](https://github.com/nltk/nltk) | `3.9.1` | `3.9.2` |
| [mkdocs-material](https://github.com/squidfunk/mkdocs-material) | `9.6.20` | `9.6.22` |
| [pytest-env](https://github.com/pytest-dev/pytest-env) | `1.1.5` | `1.2.0` |
| [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) | `16.0.1` | `16.1` |
| [pre-commit-uv](https://github.com/tox-dev/pre-commit-uv) | `4.1.5` | `4.2.0` |
| [ruff](https://github.com/astral-sh/ruff) | `0.13.2` | `0.14.0` |



Updates `filelock` from 3.19.1 to 3.20.0
- [Release notes](https://github.com/tox-dev/py-filelock/releases)
- [Changelog](https://github.com/tox-dev/filelock/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/py-filelock/compare/3.19.1...3.20.0)

Updates `gotenberg-client` from 0.11.0 to 0.12.0
- [Release notes](https://github.com/stumpylog/gotenberg-client/releases)
- [Changelog](https://github.com/stumpylog/gotenberg-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stumpylog/gotenberg-client/compare/0.11.0...0.12.0)

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

Updates `mkdocs-material` from 9.6.20 to 9.6.22
- [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.6.20...9.6.22)

Updates `pytest-env` from 1.1.5 to 1.2.0
- [Release notes](https://github.com/pytest-dev/pytest-env/releases)
- [Commits](https://github.com/pytest-dev/pytest-env/compare/1.1.5...1.2.0)

Updates `pytest-rerunfailures` from 16.0.1 to 16.1
- [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst)
- [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/16.0.1...16.1)

Updates `pre-commit-uv` from 4.1.5 to 4.2.0
- [Release notes](https://github.com/tox-dev/pre-commit-uv/releases)
- [Commits](https://github.com/tox-dev/pre-commit-uv/compare/4.1.5...4.2.0)

Updates `ruff` from 0.13.2 to 0.14.0
- [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.13.2...0.14.0)

---
updated-dependencies:
- dependency-name: filelock
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: gotenberg-client
  dependency-version: 0.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: nltk
  dependency-version: 3.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: mkdocs-material
  dependency-version: 9.6.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: pytest-env
  dependency-version: 1.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: pytest-rerunfailures
  dependency-version: '16.1'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: pre-commit-uv
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: ruff
  dependency-version: 0.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
...

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

* Sync up the ruff version and generally update hooks

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-10-15 13:07:30 -07:00
Jan Kleine
340754d865
Enhancement: use friendly file names when emailing documents (#11055) 2025-10-15 17:10:25 +00:00
shamoon
39c429bb87
Fix: set min-height for drag-drop items container (#11064) 2025-10-15 07:08:04 -07:00
GitHub Actions
8686f264cf Auto translate strings 2025-10-13 22:26:49 +00:00
shamoon
f6c004183e
Feature: Advanced Workflow Trigger Filters (#11029) 2025-10-13 22:23:56 +00:00
dependabot[bot]
d394053ddc
docker(deps): Bump astral-sh/uv from 0.8.22-python3.12-bookworm-slim to 0.9.2-python3.12-bookworm-slim (#11052)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.8.22-python3.12-bookworm-slim to 0.9.2-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.8.22...0.9.2)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.9.2-python3.12-bookworm-slim
  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>
2025-10-13 14:28:59 -07:00
GitHub Actions
a36c28418c Auto translate strings 2025-10-13 20:19:53 +00:00
Jan Kleine
f0d1c75fac
Feature: add support for emailing multiple documents (#10666)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-10-13 13:16:43 -07:00
shamoon
495159f0b2
Fix custom field query dropdown toggle corners (#11028) 2025-10-07 11:14:51 -07:00
GitHub Actions
33fd8a6579 Auto translate strings 2025-10-07 14:21:52 +00:00
shamoon
e08e34fb90
Fix: correct save hotkey action when no next document exists (#11027) 2025-10-07 07:20:11 -07:00
GitHub Actions
6164bac66e Auto translate strings 2025-10-07 07:58:19 +00:00
shamoon
df86882e8e
Fix: require only change permissions for task dismissal, add frontend error handling (#11023) 2025-10-07 00:56:16 -07:00
shamoon
79b30fbade
Enhancement: ignore same files in sanity checker as consumer (#10999) 2025-10-06 09:59:01 -07:00
shamoon
d609b386fe
Enhancement: open color picker on swatch button click (#10994) 2025-10-02 21:29:59 -07:00
Trenton H
502bbb2420
Chore: Transition the trigger to either time or manual run, reducing runs and rate limit issues (#10993) 2025-10-02 17:54:47 -07:00
shamoon
27574009e1
Merge branch 'main' into dev 2025-10-02 10:20:00 -07:00
dependabot[bot]
bd73555ecc
Chore(deps): Bump the actions group with 5 updates (#10978)
* Chore(deps): Bump the actions group with 5 updates

Bumps the actions group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [actions/github-script](https://github.com/actions/github-script) | `7` | `8` |
| [actions/setup-python](https://github.com/actions/setup-python) | `5` | `6` |
| [actions/setup-node](https://github.com/actions/setup-node) | `4` | `5` |
| [actions/labeler](https://github.com/actions/labeler) | `5` | `6` |
| [actions/stale](https://github.com/actions/stale) | `9` | `10` |


Updates `actions/github-script` from 7 to 8
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

Updates `actions/setup-python` from 5 to 6
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5...v6)

Updates `actions/setup-node` from 4 to 5
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v5)

Updates `actions/labeler` from 5 to 6
- [Release notes](https://github.com/actions/labeler/releases)
- [Commits](https://github.com/actions/labeler/compare/v5...v6)

Updates `actions/stale` from 9 to 10
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v9...v10)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-node
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/labeler
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/stale
  dependency-version: '10'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

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

* Add pnpm packageManager

---------

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>
2025-10-01 19:06:07 -07:00
dependabot[bot]
613c922dd2
Chore(deps): Bump uuid from 11.1.0 to 13.0.0 in /src-ui (#10983)
* Chore(deps): Bump uuid from 11.1.0 to 13.0.0 in /src-ui

Bumps [uuid](https://github.com/uuidjs/uuid) from 11.1.0 to 13.0.0.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v11.1.0...v13.0.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 13.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

* Mock uuid in Jest setup

---------

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>
2025-10-02 00:09:36 +00:00
dependabot[bot]
1659aa08e4
Chore(deps-dev): Bump @playwright/test from 1.55.0 to 1.55.1 in /src-ui (#10982)
Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.55.0 to 1.55.1.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.55.0...v1.55.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-01 23:53:09 +00:00
dependabot[bot]
68dfb4a930
Chore(deps-dev): Bump the frontend-eslint-dependencies group (#10981)
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.41.0 to 8.45.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.45.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.41.0 to 8.45.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.45.0/packages/parser)

Updates `@typescript-eslint/utils` from 8.41.0 to 8.45.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.45.0/packages/utils)

Updates `eslint` from 9.34.0 to 9.36.0
- [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.34.0...v9.36.0)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.45.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.45.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.45.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: eslint
  dependency-version: 9.36.0
  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>
2025-10-01 23:34:27 +00:00
dependabot[bot]
3c439b970f
Chore(deps-dev): Bump webpack from 5.101.3 to 5.102.0 in /src-ui (#10986)
Bumps [webpack](https://github.com/webpack/webpack) from 5.101.3 to 5.102.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.101.3...v5.102.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.102.0
  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>
2025-10-01 23:16:45 +00:00
dependabot[bot]
962f7994d1
Chore(deps-dev): Bump prettier-plugin-organize-imports in /src-ui (#10985)
Bumps [prettier-plugin-organize-imports](https://github.com/simonhaenisch/prettier-plugin-organize-imports) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/simonhaenisch/prettier-plugin-organize-imports/releases)
- [Changelog](https://github.com/simonhaenisch/prettier-plugin-organize-imports/blob/master/changelog.md)
- [Commits](https://github.com/simonhaenisch/prettier-plugin-organize-imports/compare/v4.2.0...v4.3.0)

---
updated-dependencies:
- dependency-name: prettier-plugin-organize-imports
  dependency-version: 4.3.0
  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>
2025-10-01 22:55:35 +00:00
dependabot[bot]
93eea80f3e
Chore(deps-dev): Bump the frontend-jest-dependencies group (#10980)
Bumps the frontend-jest-dependencies group in /src-ui with 3 updates: [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest), [jest-environment-jsdom](https://github.com/jestjs/jest/tree/HEAD/packages/jest-environment-jsdom) and [jest-preset-angular](https://github.com/thymikee/jest-preset-angular).


Updates `jest` from 30.1.3 to 30.2.0
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.2.0/packages/jest)

Updates `jest-environment-jsdom` from 30.1.2 to 30.2.0
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.2.0/packages/jest-environment-jsdom)

Updates `jest-preset-angular` from 15.0.0 to 15.0.2
- [Release notes](https://github.com/thymikee/jest-preset-angular/releases)
- [Changelog](https://github.com/thymikee/jest-preset-angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/thymikee/jest-preset-angular/compare/v15.0.0...v15.0.2)

---
updated-dependencies:
- dependency-name: jest
  dependency-version: 30.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-jest-dependencies
- dependency-name: jest-environment-jsdom
  dependency-version: 30.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-jest-dependencies
- dependency-name: jest-preset-angular
  dependency-version: 15.0.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-jest-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-01 22:35:00 +00:00
dependabot[bot]
5bc27eb4b2
Chore(deps-dev): Bump @types/node from 24.3.0 to 24.6.1 in /src-ui (#10984)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.3.0 to 24.6.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.6.1
  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>
2025-10-01 22:09:31 +00:00
GitHub Actions
b19701cb96 Auto translate strings 2025-10-01 21:33:09 +00:00
dependabot[bot]
9c552bc2d7
Chore(deps): Bump the frontend-angular-dependencies group (#10979)
Bumps the frontend-angular-dependencies group in /src-ui with 21 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/cdk](https://github.com/angular/components) | `20.2.2` | `20.2.6` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `20.2.4` | `20.3.2` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `20.2.4` | `20.3.2` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `20.2.4` | `20.3.2` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `20.2.4` | `20.3.2` |
| [@angular/localize](https://github.com/angular/angular) | `20.2.4` | `20.3.2` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `20.2.4` | `20.3.2` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `20.2.4` | `20.3.2` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `20.2.4` | `20.3.2` |
| [@ng-select/ng-select](https://github.com/ng-select/ng-select) | `20.1.3` | `20.2.2` |
| [ngx-color](https://github.com/scttcper/ngx-color) | `10.0.0` | `10.1.0` |
| [@angular-devkit/core](https://github.com/angular/angular-cli) | `20.2.2` | `20.3.3` |
| [@angular-devkit/schematics](https://github.com/angular/angular-cli) | `20.2.2` | `20.3.3` |
| [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) | `20.2.0` | `20.3.0` |
| [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) | `20.2.0` | `20.3.0` |
| [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) | `20.2.0` | `20.3.0` |
| [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) | `20.2.0` | `20.3.0` |
| [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) | `20.2.0` | `20.3.0` |
| [@angular/build](https://github.com/angular/angular-cli) | `20.2.2` | `20.3.3` |
| [@angular/cli](https://github.com/angular/angular-cli) | `20.2.2` | `20.3.3` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `20.2.4` | `20.3.2` |


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

Updates `@angular/common` from 20.2.4 to 20.3.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/20.3.2/packages/common)

Updates `@angular/compiler` from 20.2.4 to 20.3.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/20.3.2/packages/compiler)

Updates `@angular/core` from 20.2.4 to 20.3.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/20.3.2/packages/core)

Updates `@angular/forms` from 20.2.4 to 20.3.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/20.3.2/packages/forms)

Updates `@angular/localize` from 20.2.4 to 20.3.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/20.2.4...20.3.2)

Updates `@angular/platform-browser` from 20.2.4 to 20.3.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/20.3.2/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 20.2.4 to 20.3.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/20.3.2/packages/platform-browser-dynamic)

Updates `@angular/router` from 20.2.4 to 20.3.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/20.3.2/packages/router)

Updates `@ng-select/ng-select` from 20.1.3 to 20.2.2
- [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/v20.1.3...v20.2.2)

Updates `ngx-color` from 10.0.0 to 10.1.0
- [Release notes](https://github.com/scttcper/ngx-color/releases)
- [Commits](https://github.com/scttcper/ngx-color/compare/v10.0.0...v10.1.0)

Updates `@angular-devkit/core` from 20.2.2 to 20.3.3
- [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/20.2.2...20.3.3)

Updates `@angular-devkit/schematics` from 20.2.2 to 20.3.3
- [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/20.2.2...20.3.3)

Updates `@angular-eslint/builder` from 20.2.0 to 20.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/v20.3.0/packages/builder)

Updates `@angular-eslint/eslint-plugin` from 20.2.0 to 20.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/v20.3.0/packages/eslint-plugin)

Updates `@angular-eslint/eslint-plugin-template` from 20.2.0 to 20.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/v20.3.0/packages/eslint-plugin-template)

Updates `@angular-eslint/schematics` from 20.2.0 to 20.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/v20.3.0/packages/schematics)

Updates `@angular-eslint/template-parser` from 20.2.0 to 20.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/v20.3.0/packages/template-parser)

Updates `@angular/build` from 20.2.2 to 20.3.3
- [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/20.2.2...20.3.3)

Updates `@angular/cli` from 20.2.2 to 20.3.3
- [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/20.2.2...20.3.3)

Updates `@angular/compiler-cli` from 20.2.4 to 20.3.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/20.3.2/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/cdk"
  dependency-version: 20.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/common"
  dependency-version: 20.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-version: 20.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-version: 20.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-version: 20.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-version: 20.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-version: 20.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 20.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-version: 20.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-select/ng-select"
  dependency-version: 20.2.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-color
  dependency-version: 10.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/core"
  dependency-version: 20.3.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/schematics"
  dependency-version: 20.3.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/builder"
  dependency-version: 20.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin"
  dependency-version: 20.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin-template"
  dependency-version: 20.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/schematics"
  dependency-version: 20.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/template-parser"
  dependency-version: 20.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/build"
  dependency-version: 20.3.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-version: 20.3.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-version: 20.3.2
  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>
2025-10-01 14:31:18 -07:00
Trenton H
80fabb0b56 Fixes extra dependency on psycopg-pool which should only have been in the Postgres group 2025-10-01 08:33:43 -07:00
guleyupo
af1c235af5
Documentation: fix typo (#10974) 2025-10-01 06:11:45 +00:00
dependabot[bot]
92ee906701
docker-compose(deps): Bump library/postgres in /docker/compose (#10965)
Bumps library/postgres from 17 to 18.

---
updated-dependencies:
- dependency-name: library/postgres
  dependency-version: '18'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-30 20:25:02 +00:00
shamoon
d6710de486
Chore: refactor for clarity 2025-09-30 12:16:22 -07:00
GitHub Actions
f71b13b82a Auto translate strings 2025-09-30 16:51:15 +00:00
Antoine Mérino
3df43d828a
Performance: Cache django-guardian permissions when counting documents (#10657)
Fixes N+1 queries in tag, correspondent, storage path, custom field,
and document type list views.
Reduces SQL queries from 160 to 9.
2025-09-30 09:48:44 -07:00
Trenton H
643e2b4a8e
Chore(deps): Bulk upgrade backend dependencies (#10971)
* Stop this dependabot nonsense with a bulk upgrade and lock

* Downgrades fido2 as allauth MFA doesn't support it yet
2025-09-30 08:51:06 -07:00
dependabot[bot]
6fa896df39
Chore(deps): Bump the major-versions group with 2 updates (#10960)
Bumps the major-versions group with 2 updates: [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) and [types-setuptools](https://github.com/typeshed-internal/stub_uploader).


Updates `pytest-rerunfailures` from 15.1 to 16.0.1
- [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst)
- [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/15.1...16.0.1)

Updates `types-setuptools` from 75.8.2.20250301 to 80.9.0.20250822
- [Commits](https://github.com/typeshed-internal/stub_uploader/commits)

---
updated-dependencies:
- dependency-name: pytest-rerunfailures
  dependency-version: 16.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: major-versions
- dependency-name: types-setuptools
  dependency-version: 80.9.0.20250822
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: major-versions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-30 07:09:22 -07:00
dependabot[bot]
6aeb5a5503
Chore(deps): Bump types-colorama from 0.4.15.20240311 to 0.4.15.20250801 (#10961)
Bumps [types-colorama](https://github.com/typeshed-internal/stub_uploader) from 0.4.15.20240311 to 0.4.15.20250801.
- [Commits](https://github.com/typeshed-internal/stub_uploader/commits)

---
updated-dependencies:
- dependency-name: types-colorama
  dependency-version: 0.4.15.20250801
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-29 15:24:36 -07:00
dependabot[bot]
86dbeb3a27
Chore(deps): Bump django-guardian from 3.1.3 to 3.2.0 (#10909)
Bumps [django-guardian](https://github.com/django-guardian/django-guardian) from 3.1.3 to 3.2.0.
- [Release notes](https://github.com/django-guardian/django-guardian/releases)
- [Commits](https://github.com/django-guardian/django-guardian/compare/3.1.3...3.2.0)

---
updated-dependencies:
- dependency-name: django-guardian
  dependency-version: 3.2.0
  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>
2025-09-29 11:54:56 -07:00
dependabot[bot]
e97217f267
Chore(deps): Bump django-soft-delete from 1.0.19 to 1.0.21 (#10908)
Bumps [django-soft-delete](https://github.com/san4ezy/django_softdelete) from 1.0.19 to 1.0.21.
- [Changelog](https://github.com/san4ezy/django_softdelete/blob/master/CHANGELOG.md)
- [Commits](https://github.com/san4ezy/django_softdelete/commits)

---
updated-dependencies:
- dependency-name: django-soft-delete
  dependency-version: 1.0.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-29 09:38:39 -07:00
dependabot[bot]
05d5d7e796
Chore(deps): Bump whitenoise from 6.10.0 to 6.11.0 (#10910)
Bumps [whitenoise](https://github.com/evansd/whitenoise) from 6.10.0 to 6.11.0.
- [Changelog](https://github.com/evansd/whitenoise/blob/main/docs/changelog.rst)
- [Commits](https://github.com/evansd/whitenoise/compare/6.10.0...6.11.0)

---
updated-dependencies:
- dependency-name: whitenoise
  dependency-version: 6.11.0
  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>
2025-09-29 08:38:35 -07:00
Dakota Dunn
ab7875cc76
Documentation: correct workflow description (#10947) 2025-09-27 02:16:15 +00:00
GitHub Actions
e8957de4a7 Auto translate strings 2025-09-26 20:49:13 +00:00
shamoon
1717517e70
Tweakhancement: reorganize some list & bulk editing buttons (#10944) 2025-09-26 13:47:24 -07:00
dependabot[bot]
af544177d4
Chore(deps): Bump django-cors-headers from 4.8.0 to 4.9.0 (#10907)
Bumps [django-cors-headers](https://github.com/adamchainz/django-cors-headers) from 4.8.0 to 4.9.0.
- [Changelog](https://github.com/adamchainz/django-cors-headers/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/adamchainz/django-cors-headers/compare/4.8.0...4.9.0)

---
updated-dependencies:
- dependency-name: django-cors-headers
  dependency-version: 4.9.0
  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>
2025-09-26 12:21:18 -07:00
dependabot[bot]
766af6a48a
docker(deps): bump astral-sh/uv (#10906)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.8.17-python3.12-bookworm-slim to 0.8.19-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.8.17...0.8.19)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.8.19-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-26 18:42:28 +00:00
shamoon
e985051890
Chore: remove Codecov token from CI workflow (#10941) 2025-09-26 10:01:31 -07:00
shamoon
764ad059d1
Revert "Chore: Enable SonarQube scanning (#10904)" (#10934)
This reverts commit 8d1f23e9d61066b95e2e4a11d806e0651ddcf8a8.
2025-09-25 00:45:36 -07:00
shamoon
5e47069934
Fix select option removal and pagination update (#10933) 2025-09-25 00:42:43 -07:00
DerRockWolf
4ff09c4cf4
Enhancement: support workflow path matching of barcode-split documents (#10723) 2025-09-24 21:03:03 +00:00
shamoon
53b393dab5
Chore: remove conditional from pre-commit job in CI (#10916) 2025-09-24 13:43:09 -07:00
shamoon
0114993ac6
Documentation: fix config admonitions 2025-09-23 09:22:52 -07:00
shamoon
6119c215e7
Fix: skip fuzzy matching for empty document content (#10914) 2025-09-22 23:30:24 -07:00
Trenton H
8d1f23e9d6
Chore: Enable SonarQube scanning (#10904)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-09-22 19:53:32 +00:00
GitHub Actions
c8850fa752 Auto translate strings 2025-09-22 18:21:26 +00:00
shamoon
19a54b3b23
Feature: processed mail UI (#10866) 2025-09-22 18:17:42 +00:00
shamoon
1cdd8d9ba8 Clarify repo maintenance rules 2025-09-21 16:32:21 -07:00
shamoon
4449dbadb5
Merge branch 'main' into dev 2025-09-21 16:10:00 -07:00
shamoon
43b4f36026
Documentation: add note about logo file visibility and exif data 2025-09-21 16:07:29 -07:00
shamoon
0e35acaef5
Fix: add extra error handling to _consume for file checks (#10897) 2025-09-21 13:21:40 -07:00
shamoon
19ff339804
Fix: show children in tag list when filtering (#10899) 2025-09-21 10:09:05 -07:00
shamoon
6b868a5ecb
Fix: restore str celery beat schedule filename (#10893) 2025-09-20 18:54:56 -07:00
GitHub Actions
6231211f9b Auto translate strings 2025-09-17 22:45:21 +00:00
shamoon
6dbd32759d
Enhancement: support custom field values on post document (#10859) 2025-09-17 22:42:06 +00:00
GitHub Actions
e0512e35a2 Auto translate strings 2025-09-17 21:44:56 +00:00
shamoon
4cff907ba0
Feature: Nested Tags (#10833)
---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-09-17 21:41:39 +00:00
dependabot[bot]
4b32c3228e
docker(deps): Bump astral-sh/uv (#10864)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.8.15-python3.12-bookworm-slim to 0.8.17-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.8.15...0.8.17)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.8.17-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-17 13:48:08 -07:00
dependabot[bot]
4ddac79f0f
Chore(deps): Bump the small-changes group across 1 directory with 3 updates (#10880)
* Chore(deps): Bump the small-changes group across 1 directory with 3 updates

Bumps the small-changes group with 3 updates in the / directory: [ocrmypdf](https://github.com/ocrmypdf/OCRmyPDF), [mkdocs-material](https://github.com/squidfunk/mkdocs-material) and [ruff](https://github.com/astral-sh/ruff).


Updates `ocrmypdf` from 16.10.4 to 16.11.0
- [Release notes](https://github.com/ocrmypdf/OCRmyPDF/releases)
- [Changelog](https://github.com/ocrmypdf/OCRmyPDF/blob/main/docs/release_notes.md)
- [Commits](https://github.com/ocrmypdf/OCRmyPDF/compare/v16.10.4...v16.11.0)

Updates `mkdocs-material` from 9.6.19 to 9.6.20
- [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.6.19...9.6.20)

Updates `ruff` from 0.12.12 to 0.13.0
- [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.12.12...0.13.0)

---
updated-dependencies:
- dependency-name: ocrmypdf
  dependency-version: 16.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: mkdocs-material
  dependency-version: 9.6.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: ruff
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
...

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

* Applies the new Ruff rule for unpacking

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-09-17 13:16:34 -07:00
dependabot[bot]
d4be3bd31d
Chore(deps): Bump django-guardian in the django group (#10863)
Bumps the django group with 1 update: [django-guardian](https://github.com/django-guardian/django-guardian).


Updates `django-guardian` from 3.1.2 to 3.1.3
- [Release notes](https://github.com/django-guardian/django-guardian/releases)
- [Commits](https://github.com/django-guardian/django-guardian/compare/3.1.2...3.1.3)

---
updated-dependencies:
- dependency-name: django-guardian
  dependency-version: 3.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: django
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-17 16:35:35 +00:00
ExploracuriousAlex
d5aba09de9
Development: devcontainer fixes for Windows (#10843)
* chore(devcontainer): drop read-only host .gitconfig bind mount

The bind mount prevented adjusting git config inside the dev container, and VS Code Dev Containers already copies the host .gitconfig automatically, making the mount unnecessary. This restores ability to manage git settings within the container.

* chore(gitignore): ignore .pnpm-store folder for pnpm package management

Add .pnpm-store/ to .gitignore to prevent local pnpm package store from being tracked by git when using the devcontainer.

* docs(development): clarify VS Code devcontainer setup steps for Windows

Add instructions, how to overcome some issues caused by using Windows as host system.
2025-09-17 16:16:58 +00:00
github-actions[bot]
f2ef9af291
New Crowdin translations by GitHub Action (#10808)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-09-14 15:59:56 -07:00
GitHub Actions
4905edbf79 Auto translate strings 2025-09-14 03:22:02 +00:00
jojo2357
feb5d534b5
Enhancement: long text custom field (#10846)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-09-14 03:19:00 +00:00
shamoon
d230514dd3
Fix: fix pdf editor hover rotate counterclockwise button (#10848) 2025-09-13 14:19:50 -07:00
shamoon
1709aee903
Development: fix localization failing tests (#10840)
---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-09-12 16:42:52 -07:00
shamoon
3e4aa87cc5
Fix formatting 2025-09-12 15:55:22 -07:00
shamoon
fc95d42b35
Documentation: add guidance for feature PRs in CONTRIBUTING.md 2025-09-12 15:51:49 -07:00
shamoon
c4346124c3
Fix: warp long words in toast content (#10839) 2025-09-12 06:56:40 -07:00
shamoon
44b8c4881a
Fix: fix error when bulk adding empty doc link custom fields (#10832) 2025-09-11 13:19:23 -07:00
GitHub Actions
d3d8eef0b6 Auto translate strings 2025-09-11 18:00:58 +00:00
Mattia Paletti
a283c1c320
Enhancement: Add print button (#10626)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-09-11 17:59:11 +00:00
GitHub Actions
f3220ce981 Auto translate strings 2025-09-11 17:44:22 +00:00
david-loe
2dc4f1f49b
Enhancement: add storage path as workflow trigger filter (#10771)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-09-11 17:41:04 +00:00
GitHub Actions
17509171bb Auto translate strings 2025-09-11 13:58:01 +00:00
sidey79
9e11e7fd05
Enhancement: jinja template support for workflow title assignment (#10700)
---------

Co-authored-by: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-09-11 06:56:16 -07:00
dependabot[bot]
84942a4e69
Chore(deps): Bump pytest-cov in the development group across 1 directory (#10822)
Bumps the development group with 1 update in the / directory: [pytest-cov](https://github.com/pytest-dev/pytest-cov).


Updates `pytest-cov` from 6.2.1 to 7.0.0
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v6.2.1...v7.0.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-10 07:16:22 -07:00
dependabot[bot]
48168df320
Chore(deps): Bump the django group with 4 updates (#10811)
Bumps the django group with 4 updates: [django](https://github.com/django/django), [django-cors-headers](https://github.com/adamchainz/django-cors-headers), [django-guardian](https://github.com/django-guardian/django-guardian) and [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar).


Updates `django` from 5.2.5 to 5.2.6
- [Commits](https://github.com/django/django/compare/5.2.5...5.2.6)

Updates `django-cors-headers` from 4.7.0 to 4.8.0
- [Changelog](https://github.com/adamchainz/django-cors-headers/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/adamchainz/django-cors-headers/compare/4.7.0...4.8.0)

Updates `django-guardian` from 3.0.3 to 3.1.2
- [Release notes](https://github.com/django-guardian/django-guardian/releases)
- [Commits](https://github.com/django-guardian/django-guardian/compare/3.0.3...3.1.2)

Updates `drf-spectacular-sidecar` from 2025.8.1 to 2025.9.1
- [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2025.8.1...2025.9.1)

---
updated-dependencies:
- dependency-name: django
  dependency-version: 5.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: django
- dependency-name: django-cors-headers
  dependency-version: 4.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
- dependency-name: django-guardian
  dependency-version: 3.1.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
- dependency-name: drf-spectacular-sidecar
  dependency-version: 2025.9.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 22:08:29 +00:00
GitHub Actions
cec665f8d5 Auto translate strings 2025-09-09 20:04:58 +00:00
Antoine Mérino
8adc26e09d
Enhancement: Limit excessively long content length when computing suggestions (#10656)
This helps prevent excessive processing times on very large documents
by limiting the text analyzed during date parsing, tag prediction,
and correspondent matching.

If the document exceeds 1.2M chars, crop to 1M char.
2025-09-09 13:02:16 -07:00
dependabot[bot]
84d85d7a23
docker-compose(deps): Bump gotenberg/gotenberg from 8.22 to 8.23 in /docker/compose (#10812)
Bumps gotenberg/gotenberg from 8.22 to 8.23.

---
updated-dependencies:
- dependency-name: gotenberg/gotenberg
  dependency-version: '8.23'
  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>
2025-09-09 12:47:25 -07:00
dependabot[bot]
71f20f62d0
Chore(deps): Bump the small-changes group across 1 directory with 8 updates (#10821)
Bumps the small-changes group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [rapidfuzz](https://github.com/rapidfuzz/RapidFuzz) | `3.14.0` | `3.14.1` |
| [scikit-learn](https://github.com/scikit-learn/scikit-learn) | `1.7.1` | `1.7.2` |
| [setproctitle](https://github.com/dvarrazzo/py-setproctitle) | `1.3.6` | `1.3.7` |
| [whitenoise](https://github.com/evansd/whitenoise) | `6.9.0` | `6.10.0` |
| [mkdocs-glightbox](https://github.com/blueswen/mkdocs-glightbox) | `0.4.0` | `0.5.1` |
| [mkdocs-material](https://github.com/squidfunk/mkdocs-material) | `9.6.18` | `9.6.19` |
| [pytest](https://github.com/pytest-dev/pytest) | `8.4.1` | `8.4.2` |
| [ruff](https://github.com/astral-sh/ruff) | `0.12.11` | `0.12.12` |



Updates `rapidfuzz` from 3.14.0 to 3.14.1
- [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.14.0...v3.14.1)

Updates `scikit-learn` from 1.7.1 to 1.7.2
- [Release notes](https://github.com/scikit-learn/scikit-learn/releases)
- [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.7.1...1.7.2)

Updates `setproctitle` from 1.3.6 to 1.3.7
- [Changelog](https://github.com/dvarrazzo/py-setproctitle/blob/master/HISTORY.rst)
- [Commits](https://github.com/dvarrazzo/py-setproctitle/compare/version-1.3.6...version-1.3.7)

Updates `whitenoise` from 6.9.0 to 6.10.0
- [Changelog](https://github.com/evansd/whitenoise/blob/main/docs/changelog.rst)
- [Commits](https://github.com/evansd/whitenoise/compare/6.9.0...6.10.0)

Updates `mkdocs-glightbox` from 0.4.0 to 0.5.1
- [Release notes](https://github.com/blueswen/mkdocs-glightbox/releases)
- [Changelog](https://github.com/blueswen/mkdocs-glightbox/blob/main/CHANGELOG)
- [Commits](https://github.com/blueswen/mkdocs-glightbox/compare/v0.4.0...v0.5.1)

Updates `mkdocs-material` from 9.6.18 to 9.6.19
- [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.6.18...9.6.19)

Updates `pytest` from 8.4.1 to 8.4.2
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.4.1...8.4.2)

Updates `ruff` from 0.12.11 to 0.12.12
- [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.12.11...0.12.12)

---
updated-dependencies:
- dependency-name: rapidfuzz
  dependency-version: 3.14.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: scikit-learn
  dependency-version: 1.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: setproctitle
  dependency-version: 1.3.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: whitenoise
  dependency-version: 6.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: mkdocs-glightbox
  dependency-version: 0.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: mkdocs-material
  dependency-version: 9.6.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: pytest
  dependency-version: 8.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: ruff
  dependency-version: 0.12.12
  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>
2025-09-09 17:35:45 +00:00
dependabot[bot]
a94a8e4c6f
docker(deps): Bump astral-sh/uv from 0.8.13-python3.12-bookworm-slim to 0.8.15-python3.12-bookworm-slim (#10810)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.8.13-python3.12-bookworm-slim to 0.8.15-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.8.13...0.8.15)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.8.15-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 16:49:39 +00:00
shamoon
7a1aae7749
Fix: set match value for correspondents created by mail rule (#10820) 2025-09-09 09:14:48 -07:00
shamoon
894939e492
Chore: add debug log line to reindex 2025-09-09 05:49:35 -07:00
shamoon
f431578f43
Documentation: v2.18.14 changelog (#10804) 2025-09-07 17:10:52 -07:00
shamoon
1b18c14188
Bump version to 2.18.4 2025-09-07 16:29:23 -07:00
github-actions[bot]
d721a88a2f
New Crowdin translations by GitHub Action (#10756)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-09-07 23:26:24 +00:00
GitHub Actions
f7b4d38e39 Auto translate strings 2025-09-07 23:12:29 +00:00
shamoon
46cf6b4583
Revert "Performance: Enable virtual scrolling for large custom field selects (#10708)" (#10803)
This reverts commit d9459ac37f71da6011d1911d6987daf26fe49aa8.
2025-09-07 16:10:11 -07:00
shamoon
2d701c5c1b
Fix error in system status test 2025-09-06 07:56:15 -07:00
GitHub Actions
1123d845ec Auto translate strings 2025-09-06 14:54:14 +00:00
shamoon
dfa6308ca4
Fixhancement: update sidebar view counts on save & next also (#10793) 2025-09-06 07:51:36 -07:00
Sebastian Steinbeißer
b5a17a8d11
Fix: Make mypy work with uv (#10783)
* Add option to run mypy on the project via `uv run mypy .`

* Remove deprecated mypy plugin

* Add missing typing dependencies
2025-09-05 11:49:09 -07:00
GitHub Actions
cfac74319f Auto translate strings 2025-09-05 18:11:26 +00:00
shamoon
f9f069b092
Enhancement: report websocket status (#10777) 2025-09-05 11:09:42 -07:00
shamoon
b2703b4605
Fix: revert pathlib change to database name (#10774) 2025-09-04 06:58:13 -07:00
shamoon
852eb0ef36
Fix chore label assignment logic in PR bot workflow 2025-09-03 17:08:20 -07:00
shamoon
0870d42eae
Chore(deps-dev): Bump the frontend-jest-dependencies group in /src-ui with 2 updates (#10770) 2025-09-03 17:06:50 -07:00
dependabot[bot]
e2cf95f8af
Chore(deps-dev): Bump the frontend-eslint-dependencies group (#10745)
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.38.0 to 8.41.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.41.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.38.0 to 8.41.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.41.0/packages/parser)

Updates `@typescript-eslint/utils` from 8.38.0 to 8.41.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.41.0/packages/utils)

Updates `eslint` from 9.32.0 to 9.34.0
- [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.32.0...v9.34.0)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.41.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.41.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.41.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: eslint
  dependency-version: 9.34.0
  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>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-09-03 16:53:48 -07:00
GitHub Actions
a79c8dc51c Auto translate strings 2025-09-03 23:29:22 +00:00
dependabot[bot]
4b95c2f0e5
Chore(deps): Bump the frontend-angular-dependencies group (#10744)
Bumps the frontend-angular-dependencies group in /src-ui with 22 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/cdk](https://github.com/angular/components) | `20.1.4` | `20.2.1` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `20.1.4` | `20.2.3` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `20.1.4` | `20.2.3` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `20.1.4` | `20.2.3` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `20.1.4` | `20.2.3` |
| [@angular/localize](https://github.com/angular/angular) | `20.1.4` | `20.2.3` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `20.1.4` | `20.2.3` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `20.1.4` | `20.2.3` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `20.1.4` | `20.2.3` |
| [@ng-select/ng-select](https://github.com/ng-select/ng-select) | `20.0.1` | `20.1.3` |
| [ngx-cookie-service](https://github.com/stevermeister/ngx-cookie-service) | `20.0.1` | `20.1.0` |
| [ngx-device-detector](https://github.com/AhsanAyaz/ngx-device-detector) | `10.0.2` | `10.1.0` |
| [@angular-devkit/core](https://github.com/angular/angular-cli) | `20.1.4` | `20.2.1` |
| [@angular-devkit/schematics](https://github.com/angular/angular-cli) | `20.1.4` | `20.2.1` |
| [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) | `20.1.1` | `20.2.0` |
| [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) | `20.1.1` | `20.2.0` |
| [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) | `20.1.1` | `20.2.0` |
| [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) | `20.1.1` | `20.2.0` |
| [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) | `20.1.1` | `20.2.0` |
| [@angular/build](https://github.com/angular/angular-cli) | `20.1.4` | `20.2.1` |
| [@angular/cli](https://github.com/angular/angular-cli) | `20.1.4` | `20.2.1` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `20.1.4` | `20.2.3` |


Updates `@angular/cdk` from 20.1.4 to 20.2.1
- [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/20.1.4...20.2.1)

Updates `@angular/common` from 20.1.4 to 20.2.3
- [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/20.2.3/packages/common)

Updates `@angular/compiler` from 20.1.4 to 20.2.3
- [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/20.2.3/packages/compiler)

Updates `@angular/core` from 20.1.4 to 20.2.3
- [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/20.2.3/packages/core)

Updates `@angular/forms` from 20.1.4 to 20.2.3
- [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/20.2.3/packages/forms)

Updates `@angular/localize` from 20.1.4 to 20.2.3
- [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/20.1.4...20.2.3)

Updates `@angular/platform-browser` from 20.1.4 to 20.2.3
- [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/20.2.3/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 20.1.4 to 20.2.3
- [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/20.2.3/packages/platform-browser-dynamic)

Updates `@angular/router` from 20.1.4 to 20.2.3
- [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/20.2.3/packages/router)

Updates `@ng-select/ng-select` from 20.0.1 to 20.1.3
- [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/v20.0.1...v20.1.3)

Updates `ngx-cookie-service` from 20.0.1 to 20.1.0
- [Release notes](https://github.com/stevermeister/ngx-cookie-service/releases)
- [Changelog](https://github.com/stevermeister/ngx-cookie-service/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stevermeister/ngx-cookie-service/compare/v20.0.1...v20.1.0)

Updates `ngx-device-detector` from 10.0.2 to 10.1.0
- [Release notes](https://github.com/AhsanAyaz/ngx-device-detector/releases)
- [Changelog](https://github.com/AhsanAyaz/ngx-device-detector/blob/master/steps-to-release.md)
- [Commits](https://github.com/AhsanAyaz/ngx-device-detector/compare/v10.0.2...v10.1.0)

Updates `@angular-devkit/core` from 20.1.4 to 20.2.1
- [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/20.1.4...20.2.1)

Updates `@angular-devkit/schematics` from 20.1.4 to 20.2.1
- [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/20.1.4...20.2.1)

Updates `@angular-eslint/builder` from 20.1.1 to 20.2.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/v20.2.0/packages/builder)

Updates `@angular-eslint/eslint-plugin` from 20.1.1 to 20.2.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/v20.2.0/packages/eslint-plugin)

Updates `@angular-eslint/eslint-plugin-template` from 20.1.1 to 20.2.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/v20.2.0/packages/eslint-plugin-template)

Updates `@angular-eslint/schematics` from 20.1.1 to 20.2.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/v20.2.0/packages/schematics)

Updates `@angular-eslint/template-parser` from 20.1.1 to 20.2.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/v20.2.0/packages/template-parser)

Updates `@angular/build` from 20.1.4 to 20.2.1
- [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/20.1.4...20.2.1)

Updates `@angular/cli` from 20.1.4 to 20.2.1
- [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/20.1.4...20.2.1)

Updates `@angular/compiler-cli` from 20.1.4 to 20.2.3
- [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/20.2.3/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/cdk"
  dependency-version: 20.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/common"
  dependency-version: 20.2.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-version: 20.2.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-version: 20.2.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-version: 20.2.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-version: 20.2.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-version: 20.2.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 20.2.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-version: 20.2.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-select/ng-select"
  dependency-version: 20.1.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-cookie-service
  dependency-version: 20.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-device-detector
  dependency-version: 10.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/core"
  dependency-version: 20.2.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/schematics"
  dependency-version: 20.2.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/builder"
  dependency-version: 20.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin"
  dependency-version: 20.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin-template"
  dependency-version: 20.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/schematics"
  dependency-version: 20.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/template-parser"
  dependency-version: 20.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/build"
  dependency-version: 20.2.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-version: 20.2.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-version: 20.2.3
  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>
2025-09-03 16:27:08 -07:00
dependabot[bot]
e1c8cd779b
Chore(deps): Bump bootstrap from 5.3.7 to 5.3.8 in /src-ui (#10740)
* Chore(deps): Bump bootstrap from 5.3.7 to 5.3.8 in /src-ui

Bumps [bootstrap](https://github.com/twbs/bootstrap) from 5.3.7 to 5.3.8.
- [Release notes](https://github.com/twbs/bootstrap/releases)
- [Commits](https://github.com/twbs/bootstrap/compare/v5.3.7...v5.3.8)

---
updated-dependencies:
- dependency-name: bootstrap
  dependency-version: 5.3.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

* Upgrades backend Bootstrap to 5.3.8 as well

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-09-03 21:58:53 +00:00
dependabot[bot]
cc7c7f31ba
Chore(deps-dev): Bump @playwright/test from 1.54.2 to 1.55.0 in /src-ui (#10743)
Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.54.2 to 1.55.0.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.54.2...v1.55.0)

---
updated-dependencies:
- dependency-name: "@playwright/test"
  dependency-version: 1.55.0
  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>
2025-09-03 20:29:57 +00:00
dependabot[bot]
1d30ce2afa
Chore(deps-dev): Bump webpack from 5.101.0 to 5.101.3 in /src-ui (#10751)
Bumps [webpack](https://github.com/webpack/webpack) from 5.101.0 to 5.101.3.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.101.0...v5.101.3)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.101.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 20:19:14 +00:00
dependabot[bot]
5aa86f8755
Chore(deps-dev): Bump @types/node from 24.1.0 to 24.3.0 in /src-ui (#10750)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.1.0 to 24.3.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.3.0
  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>
2025-09-03 20:08:34 +00:00
shamoon
de2ddad5ee
Update PR auto-labeling for chore titles 2025-09-03 10:14:41 -07:00
Sebastian Steinbeißer
d2064a2535
Chore: switch from os.path to pathlib.Path (#10539) 2025-09-03 08:12:41 -07:00
dependabot[bot]
cc621cf729
Chore(deps): Bump the actions group with 3 updates (#10757)
Bumps the actions group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [actions/download-artifact](https://github.com/actions/download-artifact) and [stumpylog/image-cleaner-action](https://github.com/stumpylog/image-cleaner-action).


Updates `actions/checkout` from 4 to 5
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

Updates `actions/download-artifact` from 4 to 5
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

Updates `stumpylog/image-cleaner-action` from 0.10.0 to 0.11.0
- [Release notes](https://github.com/stumpylog/image-cleaner-action/releases)
- [Changelog](https://github.com/stumpylog/image-cleaner-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stumpylog/image-cleaner-action/compare/v0.10.0...v0.11.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: stumpylog/image-cleaner-action
  dependency-version: 0.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-09-03 14:22:35 +00:00
sidey79
fc4134e15c
Development: clean devcontainer .venv dir (#10705) 2025-09-02 20:13:14 +00:00
GitHub Actions
ac1b420966 Auto translate strings 2025-09-02 18:48:36 +00:00
shamoon
80595899c1
Performance fix: add paging for custom field select options (#10755) 2025-09-02 11:46:54 -07:00
github-actions[bot]
9463a8fd26
Documentation: Add v2.18.3 changelog (#10734)
* Changelog v2.18.3 - GHA

* Update changelog for version 2.18.3

Removed feature enhancements section and duplicate performance entry from changelog.

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-09-01 18:45:46 -07:00
shamoon
58ab137282
Bump version to 2.18.3 2025-08-31 20:41:47 -07:00
shamoon
05c216b2a8
Merge branch 'dev' 2025-08-31 20:41:36 -07:00
github-actions[bot]
d6db2d3fce
New Crowdin translations by GitHub Action (#10699)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-08-31 20:39:21 -07:00
GitHub Actions
a6e41b4145 Auto translate strings 2025-08-31 22:25:05 +00:00
shamoon
cb927c5b22
Fix: include application config language settings for dateparser auto-detection (#10722) 2025-08-31 15:22:39 -07:00
GitHub Actions
107374af71 Auto translate strings 2025-08-30 16:11:17 +00:00
shamoon
a77141e133
Fix: ensure title gets marked as dirty 2025-08-30 09:09:43 -07:00
dependabot[bot]
117dfb83fe
Chore(deps): Update granian[uvloop] requirement from ~=2.4.1 to ~=2.5.0 (#10529)
Updates the requirements on [granian[uvloop]](https://github.com/emmett-framework/granian) to permit the latest version.
- [Release notes](https://github.com/emmett-framework/granian/releases)
- [Commits](https://github.com/emmett-framework/granian/compare/v2.4.1...v2.5.0)

---
updated-dependencies:
- dependency-name: granian[uvloop]
  dependency-version: 2.5.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-29 12:44:17 -07:00
dependabot[bot]
fdef774a16
Chore(deps): Bump the small-changes group across 1 directory with 6 updates (#10714)
Bumps the small-changes group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [filelock](https://github.com/tox-dev/py-filelock) | `3.18.0` | `3.19.1` |
| [gotenberg-client](https://github.com/stumpylog/gotenberg-client) | `0.10.0` | `0.11.0` |
| [rapidfuzz](https://github.com/rapidfuzz/RapidFuzz) | `3.13.0` | `3.14.0` |
| [mkdocs-material](https://github.com/squidfunk/mkdocs-material) | `9.6.17` | `9.6.18` |
| [pre-commit-uv](https://github.com/tox-dev/pre-commit-uv) | `4.1.4` | `4.1.5` |
| [ruff](https://github.com/astral-sh/ruff) | `0.12.9` | `0.12.11` |



Updates `filelock` from 3.18.0 to 3.19.1
- [Release notes](https://github.com/tox-dev/py-filelock/releases)
- [Changelog](https://github.com/tox-dev/filelock/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/py-filelock/compare/3.18.0...3.19.1)

Updates `gotenberg-client` from 0.10.0 to 0.11.0
- [Release notes](https://github.com/stumpylog/gotenberg-client/releases)
- [Changelog](https://github.com/stumpylog/gotenberg-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stumpylog/gotenberg-client/compare/0.10.0...0.11.0)

Updates `rapidfuzz` from 3.13.0 to 3.14.0
- [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.13.0...v3.14.0)

Updates `mkdocs-material` from 9.6.17 to 9.6.18
- [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.6.17...9.6.18)

Updates `pre-commit-uv` from 4.1.4 to 4.1.5
- [Release notes](https://github.com/tox-dev/pre-commit-uv/releases)
- [Commits](https://github.com/tox-dev/pre-commit-uv/compare/4.1.4...4.1.5)

Updates `ruff` from 0.12.9 to 0.12.11
- [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.12.9...0.12.11)

---
updated-dependencies:
- dependency-name: filelock
  dependency-version: 3.19.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: gotenberg-client
  dependency-version: 0.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: rapidfuzz
  dependency-version: 3.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: mkdocs-material
  dependency-version: 9.6.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: pre-commit-uv
  dependency-version: 4.1.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: ruff
  dependency-version: 0.12.11
  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>
2025-08-29 18:07:40 +00:00
shamoon
08887cb8e3
Fix: hide sidebar counts during saved views organization (#10716) 2025-08-29 09:55:43 -07:00
shamoon
7b679e11bc
Fix: wrap long view titles in sidebar (#10715) 2025-08-29 09:37:58 -07:00
GitHub Actions
dbbebaeb89 Auto translate strings 2025-08-28 15:09:58 +00:00
david-loe
d9459ac37f
Performance: Enable virtual scrolling for large custom field selects (#10708) 2025-08-28 15:07:34 +00:00
sidey79
4e0f5dff95
Development: allow devcontainer pytest to find tests (#10671)
* Fix:[settings.json]:  update pytest configuration in VSCode settings

* chore[pckage.json]: Add pnmp as packagemanager

* Chore[package.json]: revert

---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-08-27 15:23:23 -07:00
dependabot[bot]
10ccccc987
docker-compose(deps): Bump library/mariadb from 11 to 12 in /docker/compose (#10621)
Bumps library/mariadb from 11 to 12.

---
updated-dependencies:
- dependency-name: library/mariadb
  dependency-version: '12'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-27 15:07:50 -07:00
dependabot[bot]
27d72ebb18
docker-compose(deps): Bump gotenberg/gotenberg from 8.20 to 8.22 in /docker/compose (#10687)
Bumps gotenberg/gotenberg from 8.20 to 8.22.

---
updated-dependencies:
- dependency-name: gotenberg/gotenberg
  dependency-version: '8.22'
  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>
2025-08-27 14:53:35 -07:00
dependabot[bot]
909ccebb34
docker(deps): Bump astral-sh/uv to 0.8.13 (#10685)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.8.8-python3.12-bookworm-slim to 0.8.13-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.8.8...0.8.13)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.8.13-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 14:59:05 -07:00
GitHub Actions
4275e18c10 Auto translate strings 2025-08-26 20:31:30 +00:00
shamoon
0088333360
Chore: refactor document details component (#10662) 2025-08-26 13:29:38 -07:00
GitHub Actions
ed1d488d6e Auto translate strings 2025-08-26 20:29:22 +00:00
shamoon
b25b15ba32
Fixhancement: more saved view count refreshes (#10694) 2025-08-26 13:27:49 -07:00
shamoon
f2fabc81d4
Fix: include array items for pagination openapi schema (#10682) 2025-08-25 13:25:54 -07:00
shamoon
f94c3eeea8
Fix: prevent scroll for view name in sidebar (#10676) 2025-08-24 05:13:09 -07:00
shamoon
bf468ac64f
Documentation: fix cache invalidation command in documentation (#10665) 2025-08-23 04:00:02 -07:00
shamoon
22064ed004
Chore: add test for navigation on document load error 2025-08-22 20:03:06 -07:00
shamoon
23daa0b974
Chore: add tests for previewText handling in DocumentDetail 2025-08-22 19:31:41 -07:00
shamoon
7b63f5a98c
Merge branch 'main' into dev 2025-08-22 18:59:33 -07:00
shamoon
7c76377477
Fix: center document close button in app frame (#10661) 2025-08-22 18:58:09 -07:00
github-actions[bot]
56c70bf177
Documentation: Add v2.18.2 changelog (#10660)
* Changelog v2.18.2 - 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>
2025-08-23 00:08:57 +00:00
shamoon
daf47f377b
Bump version to 2.18.2 2025-08-22 16:27:27 -07:00
github-actions[bot]
64f31cac0c
New Crowdin translations by GitHub Action (#10611) 2025-08-22 16:19:30 -07:00
GitHub Actions
dcc503c35f Auto translate strings 2025-08-22 23:07:12 +00:00
shamoon
a583cff21c
Fix: prevent loss of changes when switching between open docs (#10659) 2025-08-22 16:04:40 -07:00
shamoon
bfd468103b
Revert "Update ci.yml"
This reverts commit be0c1fd1ed5393f234600f79ad6f40274606da46.
2025-08-22 08:46:01 -07:00
shamoon
be0c1fd1ed
Update ci.yml 2025-08-22 08:45:33 -07:00
shamoon
82370963da
Fix: ignore incomplete tasks for system status 'last run' (#10641) 2025-08-21 21:44:41 +00:00
shamoon
0fdfa42a83
Tweak: improve dateparser auto-detection messages (#10640) 2025-08-21 21:14:25 +00:00
shamoon
0f0ba92e15
Fix: increase legibility of date filter clear button in light mode (#10649) 2025-08-21 07:25:21 -07:00
Guntbert Reiter
5f0281e427
Documentation: fix typo in troubleshooting docs (#10643) 2025-08-20 13:25:42 -07:00
shamoon
a0c7785881
Dont require_changes for codecov comment 2025-08-20 11:18:38 -07:00
GitHub Actions
349fbce579 Auto translate strings 2025-08-18 15:10:11 +00:00
shamoon
217b004884
Fix: ensure saved view count is visible with long names (#10616) 2025-08-18 08:08:25 -07:00
dependabot[bot]
29c36542fa
Chore(deps): Bump the development group across 1 directory with 3 updates (#10578)
Bumps the development group with 3 updates in the / directory: [mkdocs-material](https://github.com/squidfunk/mkdocs-material), [pre-commit](https://github.com/pre-commit/pre-commit) and [ruff](https://github.com/astral-sh/ruff).


Updates `mkdocs-material` from 9.6.16 to 9.6.17
- [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.6.16...9.6.17)

Updates `pre-commit` from 4.2.0 to 4.3.0
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v4.2.0...v4.3.0)

Updates `ruff` from 0.12.8 to 0.12.9
- [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.12.8...0.12.9)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-version: 9.6.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: development
- dependency-name: pre-commit
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: development
- dependency-name: ruff
  dependency-version: 0.12.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 06:35:25 -07:00
shamoon
d5b87aeffb
Enable Docker build for l10n_ branches in CI 2025-08-17 18:22:36 -07:00
github-actions[bot]
9225a38458
Changelog v2.18.1 - GHA (#10605)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-08-17 14:18:29 -07:00
shamoon
3fa89b85d7
Merge branch 'dev' 2025-08-17 13:46:35 -07:00
github-actions[bot]
5e6b49971f
New Crowdin translations by GitHub Action (#10603)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-08-17 13:46:06 -07:00
shamoon
be63c79db1
Bump version to 2.18.1 2025-08-17 13:22:39 -07:00
shamoon
26c70b69c4
Merge branch 'main' into dev 2025-08-17 13:21:52 -07:00
github-actions[bot]
e0b0dd8548
New Crowdin translations by GitHub Action (#10589) 2025-08-17 13:21:27 -07:00
shamoon
1bbac9948a
Development: add tomli as codespell additional dep for py < 3.11 2025-08-17 10:45:51 -07:00
shamoon
ca9b5d9586
Documentation: fix filters docs (#10600) 2025-08-17 09:25:42 -07:00
shamoon
521fd1c957
Fix: fix app logo validation with no file (#10599) 2025-08-17 07:19:50 -07:00
shamoon
f00a565130
Documentation: fix Postgres version 2025-08-17 01:33:52 -07:00
shamoon
d878bc153a
Fix some button consistency (#10593) 2025-08-17 01:13:27 -07:00
shamoon
f5e6951910
Update CONTRIBUTING.md 2025-08-17 00:46:03 -07:00
shamoon
91102d0335
Update pyproject.toml 2025-08-17 00:19:54 -07:00
shamoon
82ec1be622
Fix: restore version tag display (#10592) 2025-08-16 23:57:53 -07:00
GitHub Actions
01a8cf6f36 Auto translate strings 2025-08-16 19:07:50 +00:00
shamoon
6bdb365f87
Fixhancement: mobile layout improvements for pdf editor (#10588) 2025-08-16 12:06:21 -07:00
shamoon
696e591a3b
Merge branch 'main' into dev 2025-08-16 11:00:18 -07:00
github-actions[bot]
3c2782c3a9
Documentation: Add v2.18.0 changelog (#10585) 2025-08-16 10:59:56 -07:00
shamoon
a68800d53c
See if this helps with intermittent mail test failure 2025-08-16 10:30:25 -07:00
shamoon
52a937cdcc
Bump version to 2.18.0 2025-08-16 10:07:36 -07:00
shamoon
00e629d957
Merge branch 'dev' 2025-08-16 09:47:48 -07:00
github-actions[bot]
243b3bc812
New Crowdin translations by GitHub Action (#10234)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-08-16 08:07:47 -07:00
shamoon
0ccc2da9bb
Fix some tests from b1c406680f345f4aeec0989424dbcc839c75e438 2025-08-16 07:53:48 -07:00
GitHub Actions
b6dbbec019 Auto translate strings 2025-08-16 14:35:36 +00:00
shamoon
b1c406680f
Merge commit from fork
* Security: prevent XSS with storage path template rendering

* Security: prevent XSS svg uploads

* Security: force attachment disposition for logo

* Add suggestions from code review

* Improve SVG validation with allowlist for tags and attributes
2025-08-16 07:34:00 -07:00
Trenton H
42bdbc1b2d
Small targeted upgrades to bugfix releases mostly. Unsure why dependabot isn't doing these (#10561) 2025-08-15 11:37:07 -07:00
Trenton H
2f529a9500
Feature: Add filter to localize dates for filepath templating (#10559) 2025-08-14 09:13:08 -07:00
dependabot[bot]
ee6b700243
docker(deps): Bump astral-sh/uv (#10564)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.8.4-python3.12-bookworm-slim to 0.8.8-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.8.4...0.8.8)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.8.8-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 06:39:43 -07:00
Trenton H
b1a84c65ed
chore: Removes duplication and spread out config for codespell (#10560) 2025-08-11 13:55:36 -07:00
dependabot[bot]
edb8c06e2a
Chore(deps): Bump the django group across 1 directory with 9 updates (#10538)
* Chore(deps): Bump the django group across 1 directory with 9 updates

Bumps the django group with 9 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [django](https://github.com/django/django) | `5.1.8` | `5.2.5` |
| [django-auditlog](https://github.com/jazzband/django-auditlog) | `3.1.2` | `3.2.1` |
| [django-guardian](https://github.com/django-guardian/django-guardian) | `2.4.0` | `3.0.3` |
| [django-multiselectfield](https://github.com/goinnn/django-multiselectfield) | `0.1.13` | `1.0.1` |
| [django-soft-delete](https://github.com/san4ezy/django_softdelete) | `1.0.18` | `1.0.19` |
| [djangorestframework](https://github.com/encode/django-rest-framework) | `3.16.0` | `3.16.1` |
| [djangorestframework-guardian](https://github.com/rpkilby/django-rest-framework-guardian) | `0.3.0` | `0.4.0` |
| [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar) | `2025.4.1` | `2025.8.1` |
| [pytest-django](https://github.com/pytest-dev/pytest-django) | `4.10.0` | `4.11.1` |



Updates `django` from 5.1.8 to 5.2.5
- [Commits](https://github.com/django/django/compare/5.1.8...5.2.5)

Updates `django-auditlog` from 3.1.2 to 3.2.1
- [Release notes](https://github.com/jazzband/django-auditlog/releases)
- [Changelog](https://github.com/jazzband/django-auditlog/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jazzband/django-auditlog/compare/v3.1.2...v3.2.1)

Updates `django-guardian` from 2.4.0 to 3.0.3
- [Release notes](https://github.com/django-guardian/django-guardian/releases)
- [Commits](https://github.com/django-guardian/django-guardian/compare/v2.4.0...3.0.3)

Updates `django-multiselectfield` from 0.1.13 to 1.0.1
- [Release notes](https://github.com/goinnn/django-multiselectfield/releases)
- [Changelog](https://github.com/goinnn/django-multiselectfield/blob/master/CHANGES.rst)
- [Commits](https://github.com/goinnn/django-multiselectfield/compare/v0.1.13...v1.0.1)

Updates `django-soft-delete` from 1.0.18 to 1.0.19
- [Changelog](https://github.com/san4ezy/django_softdelete/blob/master/CHANGELOG.md)
- [Commits](https://github.com/san4ezy/django_softdelete/commits)

Updates `djangorestframework` from 3.16.0 to 3.16.1
- [Release notes](https://github.com/encode/django-rest-framework/releases)
- [Commits](https://github.com/encode/django-rest-framework/compare/3.16.0...3.16.1)

Updates `djangorestframework-guardian` from 0.3.0 to 0.4.0
- [Changelog](https://github.com/rpkilby/django-rest-framework-guardian/blob/master/CHANGELOG)
- [Commits](https://github.com/rpkilby/django-rest-framework-guardian/compare/0.3.0...0.4.0)

Updates `drf-spectacular-sidecar` from 2025.4.1 to 2025.8.1
- [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2025.4.1...2025.8.1)

Updates `pytest-django` from 4.10.0 to 4.11.1
- [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.10.0...v4.11.1)

---
updated-dependencies:
- dependency-name: django
  dependency-version: 5.2.5
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
- dependency-name: django-auditlog
  dependency-version: 3.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
- dependency-name: django-guardian
  dependency-version: 3.0.3
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: django
- dependency-name: django-multiselectfield
  dependency-version: 1.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: django
- dependency-name: django-soft-delete
  dependency-version: 1.0.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: django
- dependency-name: djangorestframework
  dependency-version: 3.16.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: django
- dependency-name: djangorestframework-guardian
  dependency-version: 0.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
- dependency-name: drf-spectacular-sidecar
  dependency-version: 2025.8.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
- dependency-name: pytest-django
  dependency-version: 4.11.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
...

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

* Fix log matches related to newlines, add newlines to stdout.writelines

* Fix disable api remote auth test, Django 5.2 no longer uses process_request

* Remove postgres version check

* Update administration.md

* Handle django-multiselectfield v1.0 changes

* Update administration.md

---------

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>
2025-08-11 13:45:14 -07:00
GitHub Actions
1b6ec65f6e Auto translate strings 2025-08-11 17:32:05 +00:00
shamoon
6d72ee795f
Feature: PDF editor (#10318) 2025-08-11 17:29:48 +00:00
shamoon
6730896894
Enhancement: support webhook restrictions (#10555) 2025-08-11 10:15:30 -07:00
shamoon
5d6ea70434
Update zxing hash 2025-08-07 08:13:05 -04:00
shamoon
fac1ee4283
Documentation: miscellaneous fixes 2025-08-07 07:54:24 -04:00
Antoine Mérino
1bee1495cf
Performance: Classifier performance optimizations (#10363) 2025-08-06 16:00:11 -04:00
Sebastian Steinbeißer
6dca4daea5
Chore: switch from os.path to pathlib.Path (#10397) 2025-08-06 10:50:42 -07:00
dependabot[bot]
54e2b916e6
Chore(deps): Bump the small-changes group with 3 updates (#10528)
Bumps the small-changes group with 3 updates: [channels](https://github.com/django/channels), [python-gnupg](https://github.com/vsajip/python-gnupg) and [tika-client](https://github.com/stumpylog/tika-rest-client).


Updates `channels` from 4.3.0 to 4.3.1
- [Changelog](https://github.com/django/channels/blob/main/CHANGELOG.txt)
- [Commits](https://github.com/django/channels/compare/4.3.0...4.3.1)

Updates `python-gnupg` from 0.5.4 to 0.5.5
- [Release notes](https://github.com/vsajip/python-gnupg/releases)
- [Changelog](https://github.com/vsajip/python-gnupg/blob/master/release)
- [Commits](https://github.com/vsajip/python-gnupg/compare/0.5.4...0.5.5)

Updates `tika-client` from 0.9.0 to 0.10.0
- [Release notes](https://github.com/stumpylog/tika-rest-client/releases)
- [Changelog](https://github.com/stumpylog/tika-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stumpylog/tika-rest-client/compare/0.9.0...0.10.0)

---
updated-dependencies:
- dependency-name: channels
  dependency-version: 4.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: python-gnupg
  dependency-version: 0.5.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: tika-client
  dependency-version: 0.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-05 10:31:03 -07:00
GitHub Actions
ea62e30c90
Auto translate strings 2025-08-05 07:37:04 -04:00
shamoon
91511b45cd
Chore: add info buttons for core metadata items 2025-08-05 07:37:04 -04:00
shamoon
b5dd751b67
Fix: address some button consistency 2025-08-04 23:46:43 -04:00
GitHub Actions
07c298523a Auto translate strings 2025-08-02 12:55:48 +00:00
Antoine Mérino
0ea159683d
Performance: add setting to enable DB connection pooling for PostgreSQL (#10354)
---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-08-02 12:54:13 +00:00
GitHub Actions
f0b6e79d14 Auto translate strings 2025-08-02 03:45:01 +00:00
dependabot[bot]
302cb22ec6
Chore(deps-dev): Bump the frontend-jest-dependencies group in /src-ui with 4 updates (#10497)
* Chore(deps-dev): Bump the frontend-jest-dependencies group

Bumps the frontend-jest-dependencies group in /src-ui with 4 updates: [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest), [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest), [jest-environment-jsdom](https://github.com/jestjs/jest/tree/HEAD/packages/jest-environment-jsdom) and [jest-preset-angular](https://github.com/thymikee/jest-preset-angular).


Updates `jest` from 29.7.0 to 30.0.5
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.0.5/packages/jest)

Updates `@types/jest` from 29.5.14 to 30.0.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

Updates `jest-environment-jsdom` from 29.7.0 to 30.0.5
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.0.5/packages/jest-environment-jsdom)

Updates `jest-preset-angular` from 14.5.5 to 15.0.0
- [Release notes](https://github.com/thymikee/jest-preset-angular/releases)
- [Changelog](https://github.com/thymikee/jest-preset-angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/thymikee/jest-preset-angular/compare/v14.5.5...v15.0.0)

---
updated-dependencies:
- dependency-name: jest
  dependency-version: 30.0.5
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: frontend-jest-dependencies
- dependency-name: "@types/jest"
  dependency-version: 30.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: frontend-jest-dependencies
- dependency-name: jest-environment-jsdom
  dependency-version: 30.0.5
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: frontend-jest-dependencies
- dependency-name: jest-preset-angular
  dependency-version: 15.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: frontend-jest-dependencies
...

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

* Update Jest setup for Node util imports and typings

* Refactor navigation actions to utility functions

---------

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>
2025-08-02 03:43:31 +00:00
dependabot[bot]
4210addb46
Chore(deps-dev): Bump the frontend-eslint-dependencies group (#10498)
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.35.1 to 8.38.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.38.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.35.1 to 8.38.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.38.0/packages/parser)

Updates `@typescript-eslint/utils` from 8.35.1 to 8.38.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.38.0/packages/utils)

Updates `eslint` from 9.30.1 to 9.32.0
- [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.30.1...v9.32.0)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.38.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.38.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.38.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: eslint
  dependency-version: 9.32.0
  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>
2025-08-01 23:04:02 +00:00
dependabot[bot]
06746b4b31
Chore(deps-dev): Bump @playwright/test from 1.53.2 to 1.54.2 in /src-ui (#10499)
Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.53.2 to 1.54.2.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.53.2...v1.54.2)

---
updated-dependencies:
- dependency-name: "@playwright/test"
  dependency-version: 1.54.2
  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>
2025-08-01 22:52:45 +00:00
dependabot[bot]
2f5533a179
Chore(deps-dev): Bump webpack from 5.99.9 to 5.101.0 in /src-ui (#10501)
Bumps [webpack](https://github.com/webpack/webpack) from 5.99.9 to 5.101.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.99.9...v5.101.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.101.0
  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>
2025-08-01 22:41:36 +00:00
dependabot[bot]
2f267341f8
Chore(deps-dev): Bump prettier-plugin-organize-imports in /src-ui (#10500)
Bumps [prettier-plugin-organize-imports](https://github.com/simonhaenisch/prettier-plugin-organize-imports) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/simonhaenisch/prettier-plugin-organize-imports/releases)
- [Changelog](https://github.com/simonhaenisch/prettier-plugin-organize-imports/blob/master/changelog.md)
- [Commits](https://github.com/simonhaenisch/prettier-plugin-organize-imports/compare/v4.1.0...v4.2.0)

---
updated-dependencies:
- dependency-name: prettier-plugin-organize-imports
  dependency-version: 4.2.0
  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>
2025-08-01 22:26:48 +00:00
dependabot[bot]
88befee527
Chore(deps-dev): Bump @types/node from 24.0.10 to 24.1.0 in /src-ui (#10502)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.0.10 to 24.1.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.1.0
  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>
2025-08-01 22:11:45 +00:00
GitHub Actions
c4a7186cd2 Auto translate strings 2025-08-01 21:43:22 +00:00
dependabot[bot]
d974f092aa
Chore(deps): Bump the frontend-angular-dependencies group (#10496)
Bumps the frontend-angular-dependencies group in /src-ui with 16 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/cdk](https://github.com/angular/components) | `20.0.4` | `20.1.4` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `20.0.6` | `20.1.4` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `20.0.6` | `20.1.4` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `20.0.6` | `20.1.4` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `20.0.6` | `20.1.4` |
| [@angular/localize](https://github.com/angular/angular) | `20.0.6` | `20.1.4` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `20.0.6` | `20.1.4` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `20.0.6` | `20.1.4` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `20.0.6` | `20.1.4` |
| [@ng-select/ng-select](https://github.com/ng-select/ng-select) | `15.1.3` | `20.0.1` |
| [ngx-ui-tour-ng-bootstrap](https://github.com/hakimio/ngx-ui-tour) | `17.0.0` | `17.0.1` |
| [@angular-devkit/core](https://github.com/angular/angular-cli) | `20.0.4` | `20.1.4` |
| [@angular-devkit/schematics](https://github.com/angular/angular-cli) | `20.0.4` | `20.1.4` |
| [@angular/build](https://github.com/angular/angular-cli) | `20.0.4` | `20.1.4` |
| [@angular/cli](https://github.com/angular/angular-cli) | `20.0.4` | `20.1.4` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `20.0.6` | `20.1.4` |


Updates `@angular/cdk` from 20.0.4 to 20.1.4
- [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/20.0.4...20.1.4)

Updates `@angular/common` from 20.0.6 to 20.1.4
- [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/20.1.4/packages/common)

Updates `@angular/compiler` from 20.0.6 to 20.1.4
- [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/20.1.4/packages/compiler)

Updates `@angular/core` from 20.0.6 to 20.1.4
- [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/20.1.4/packages/core)

Updates `@angular/forms` from 20.0.6 to 20.1.4
- [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/20.1.4/packages/forms)

Updates `@angular/localize` from 20.0.6 to 20.1.4
- [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/20.0.6...20.1.4)

Updates `@angular/platform-browser` from 20.0.6 to 20.1.4
- [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/20.1.4/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 20.0.6 to 20.1.4
- [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/20.1.4/packages/platform-browser-dynamic)

Updates `@angular/router` from 20.0.6 to 20.1.4
- [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/20.1.4/packages/router)

Updates `@ng-select/ng-select` from 15.1.3 to 20.0.1
- [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/v15.1.3...v20.0.1)

Updates `ngx-ui-tour-ng-bootstrap` from 17.0.0 to 17.0.1
- [Release notes](https://github.com/hakimio/ngx-ui-tour/releases)
- [Commits](https://github.com/hakimio/ngx-ui-tour/commits)

Updates `@angular-devkit/core` from 20.0.4 to 20.1.4
- [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/20.0.4...20.1.4)

Updates `@angular-devkit/schematics` from 20.0.4 to 20.1.4
- [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/20.0.4...20.1.4)

Updates `@angular/build` from 20.0.4 to 20.1.4
- [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/20.0.4...20.1.4)

Updates `@angular/cli` from 20.0.4 to 20.1.4
- [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/20.0.4...20.1.4)

Updates `@angular/compiler-cli` from 20.0.6 to 20.1.4
- [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/20.1.4/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/cdk"
  dependency-version: 20.1.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/common"
  dependency-version: 20.1.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-version: 20.1.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-version: 20.1.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-version: 20.1.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-version: 20.1.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-version: 20.1.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 20.1.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-version: 20.1.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-select/ng-select"
  dependency-version: 20.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-ui-tour-ng-bootstrap
  dependency-version: 17.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/core"
  dependency-version: 20.1.4
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/schematics"
  dependency-version: 20.1.4
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/build"
  dependency-version: 20.1.4
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-version: 20.1.4
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-version: 20.1.4
  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>
2025-08-01 17:41:46 -04:00
shamoon
23501b9060
Fixhancement: improve text thumbnail generation for large files (#10483) 2025-08-01 10:26:35 -07:00
TheDodger
f09965464a
Enhancement: disable auto spellcheck on filtering dropdowns (#10487) 2025-08-01 10:27:19 -04:00
dependabot[bot]
ae5bd2d2fd
Chore(deps): Bump the small-changes group across 1 directory with 8 updates (#10481)
Bumps the small-changes group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [channels](https://github.com/django/channels) | `4.2.2` | `4.3.0` |
| [channels-redis](https://github.com/django/channels_redis) | `4.2.1` | `4.3.0` |
| [scikit-learn](https://github.com/scikit-learn/scikit-learn) | `1.7.0` | `1.7.1` |
| [mkdocs-material](https://github.com/squidfunk/mkdocs-material) | `9.6.15` | `9.6.16` |
| [pytest](https://github.com/pytest-dev/pytest) | `8.3.5` | `8.4.1` |
| [pytest-cov](https://github.com/pytest-dev/pytest-cov) | `6.0.0` | `6.2.1` |
| [pre-commit](https://github.com/pre-commit/pre-commit) | `4.1.0` | `4.2.0` |
| [ruff](https://github.com/astral-sh/ruff) | `0.12.2` | `0.12.7` |



Updates `channels` from 4.2.2 to 4.3.0
- [Changelog](https://github.com/django/channels/blob/main/CHANGELOG.txt)
- [Commits](https://github.com/django/channels/compare/4.2.2...4.3.0)

Updates `channels-redis` from 4.2.1 to 4.3.0
- [Changelog](https://github.com/django/channels_redis/blob/main/CHANGELOG.txt)
- [Commits](https://github.com/django/channels_redis/compare/4.2.1...4.3.0)

Updates `scikit-learn` from 1.7.0 to 1.7.1
- [Release notes](https://github.com/scikit-learn/scikit-learn/releases)
- [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.7.0...1.7.1)

Updates `mkdocs-material` from 9.6.15 to 9.6.16
- [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.6.15...9.6.16)

Updates `pytest` from 8.3.5 to 8.4.1
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.5...8.4.1)

Updates `pytest-cov` from 6.0.0 to 6.2.1
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v6.0.0...v6.2.1)

Updates `pre-commit` from 4.1.0 to 4.2.0
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v4.1.0...v4.2.0)

Updates `ruff` from 0.12.2 to 0.12.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.12.2...0.12.7)

---
updated-dependencies:
- dependency-name: channels
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: channels-redis
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: scikit-learn
  dependency-version: 1.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: mkdocs-material
  dependency-version: 9.6.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: pytest
  dependency-version: 8.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: pytest-cov
  dependency-version: 6.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: pre-commit
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: ruff
  dependency-version: 0.12.7
  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>
2025-07-31 18:08:41 +00:00
dependabot[bot]
2b73007e7e
docker(deps): bump astral-sh/uv from 0.7.19-python3.12-bookworm-slim to 0.8.3-python3.12-bookworm-slim (#10465)
* docker(deps): bump astral-sh/uv

Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.7.19-python3.12-bookworm-slim to 0.8.3-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.7.19...0.8.3)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.8.3-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

* Bumps CI uv version to the 0.8.x branch

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-07-31 17:46:30 +00:00
shamoon
8505fa3e54
Fix: include ignore for config logos in sanity checker (#10473) 2025-07-29 23:20:39 -04:00
shamoon
a51093afc2
Chore: add tasks task_id param to openapi spec (#10469) 2025-07-29 00:47:51 -04:00
GitHub Actions
2fdae59288 Auto translate strings 2025-07-29 04:41:02 +00:00
shamoon
4637f5c5e5
Fix: track and restore changed document fields from session storage (#10468) 2025-07-29 00:38:43 -04:00
shamoon
5e7ee924ff
Chore: update stale settings 2025-07-26 20:26:59 -07:00
shamoon
fded55dc70
Documentation: include advanced search query param in API spec (#10449) 2025-07-24 15:13:01 -07:00
GitHub Actions
20da51278e Auto translate strings 2025-07-24 05:09:35 +00:00
shamoon
293c84d871
Enhancement: display saved view counts (#10246) 2025-07-23 22:07:13 -07:00
shamoon
1fe8599266
Fix: Make some natural keyword date searches timezone-aware (#10416) 2025-07-23 22:05:55 -07:00
Katrin Leinweber
5410074062
Documentation: copy-edits (#10417) 2025-07-20 17:27:04 +00:00
V0idC0de
4b8f6ed643
Fixhancement: follow redirects in curl health check (#10415) 2025-07-20 06:31:49 -07:00
Boyuan Yang
f8689c4819
Documentation: Fix URL for PAPERLESS_OCR_LANGUAGE example in docker-compose.env (#10408) 2025-07-19 02:25:31 +00:00
shamoon
cebc227701
Fixhancement: add missing exact operator for boolean CF queries (#10402) 2025-07-17 17:48:18 -07:00
shamoon
814df94e8d
Fix: dont use translated verbose_name for getting object perms (#10399) 2025-07-16 17:03:03 -07:00
shamoon
fa496dfc8d
Fix: also fix frontend date format in other places
See #10369
2025-07-11 00:46:20 -07:00
shamoon
924471b59c
Fix: fix date format for 'today' in DateComponent (#10369) 2025-07-11 00:43:52 -07:00
GitHub Actions
feb320cae9 Auto translate strings 2025-07-08 21:14:57 +00:00
shamoon
9178af5fb2
Feature: add Vietnamese translation (#10352) 2025-07-08 14:13:20 -07:00
dependabot[bot]
850444c2fc
docker(deps): Bump astral-sh/uv (#10343)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.7.9-python3.12-bookworm-slim to 0.7.19-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.7.9...0.7.19)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.7.19-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 12:26:24 -07:00
GitHub Actions
90baba2cec Auto translate strings 2025-07-08 16:31:30 +00:00
dependabot[bot]
9889c59d3d
Chore(deps): Bump the small-changes group across 1 directory with 7 updates (#10347)
* Chore(deps): Bump the small-changes group across 1 directory with 7 updates

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

| Package | From | To |
| --- | --- | --- |
| [concurrent-log-handler](https://github.com/Preston-Landers/concurrent-log-handler) | `0.9.26` | `0.9.28` |
| [dateparser](https://github.com/scrapinghub/dateparser) | `1.2.1` | `1.2.2` |
| [imap-tools](https://github.com/ikvk/imap_tools) | `1.10.0` | `1.11.0` |
| [ocrmypdf](https://github.com/ocrmypdf/OCRmyPDF) | `16.10.2` | `16.10.4` |
| [pathvalidate](https://github.com/thombashi/pathvalidate) | `3.2.3` | `3.3.1` |
| [python-dotenv](https://github.com/theskumar/python-dotenv) | `1.1.0` | `1.1.1` |
| [scikit-learn](https://github.com/scikit-learn/scikit-learn) | `1.6.1` | `1.7.0` |



Updates `concurrent-log-handler` from 0.9.26 to 0.9.28
- [Release notes](https://github.com/Preston-Landers/concurrent-log-handler/releases)
- [Changelog](https://github.com/Preston-Landers/concurrent-log-handler/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Preston-Landers/concurrent-log-handler/compare/0.9.26...0.9.28)

Updates `dateparser` from 1.2.1 to 1.2.2
- [Release notes](https://github.com/scrapinghub/dateparser/releases)
- [Changelog](https://github.com/scrapinghub/dateparser/blob/master/HISTORY.rst)
- [Commits](https://github.com/scrapinghub/dateparser/compare/v1.2.1...v1.2.2)

Updates `imap-tools` from 1.10.0 to 1.11.0
- [Release notes](https://github.com/ikvk/imap_tools/releases)
- [Changelog](https://github.com/ikvk/imap_tools/blob/master/docs/release_notes.rst)
- [Commits](https://github.com/ikvk/imap_tools/compare/v1.10.0...v1.11.0)

Updates `ocrmypdf` from 16.10.2 to 16.10.4
- [Release notes](https://github.com/ocrmypdf/OCRmyPDF/releases)
- [Changelog](https://github.com/ocrmypdf/OCRmyPDF/blob/main/docs/release_notes.md)
- [Commits](https://github.com/ocrmypdf/OCRmyPDF/compare/v16.10.2...v16.10.4)

Updates `pathvalidate` from 3.2.3 to 3.3.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.3...v3.3.1)

Updates `python-dotenv` from 1.1.0 to 1.1.1
- [Release notes](https://github.com/theskumar/python-dotenv/releases)
- [Changelog](https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/theskumar/python-dotenv/compare/v1.1.0...v1.1.1)

Updates `scikit-learn` from 1.6.1 to 1.7.0
- [Release notes](https://github.com/scikit-learn/scikit-learn/releases)
- [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.6.1...1.7.0)

---
updated-dependencies:
- dependency-name: concurrent-log-handler
  dependency-version: 0.9.28
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: dateparser
  dependency-version: 1.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: imap-tools
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: ocrmypdf
  dependency-version: 16.10.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: pathvalidate
  dependency-version: 3.3.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: python-dotenv
  dependency-version: 1.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: scikit-learn
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
...

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

* Removes the setup_logging_queues call which is no longer needed

* Renames the MailboxTLS

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
2025-07-08 09:29:47 -07:00
Trenton H
3d2a3ede71
Chore: Updates dependency groups (#10339) 2025-07-07 17:37:58 -07:00
shamoon
bc019fab96
Fix: default to empty permissions for group creation (#10337) 2025-07-07 07:21:27 -07:00
shamoon
1cd21d0f38
Fix check scheduled workflows docstring 2025-07-03 00:11:12 -07:00
Antoine Mérino
f940ed0b7b
Fix: Fallback to Redis URL if no DB read cache Redis URL provided (#10315)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-07-02 10:59:24 -07:00
dependabot[bot]
3180ccf4cb
Chore(deps): Bump stefanzweifel/git-auto-commit-action (#10302)
Bumps the actions group with 1 update: [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action).


Updates `stefanzweifel/git-auto-commit-action` from 5 to 6
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 14:26:07 +00:00
dependabot[bot]
43abb0541b
Chore(deps-dev): Bump the frontend-eslint-dependencies group across 1 directory with 4 updates (#10311)
Bumps the frontend-eslint-dependencies group with 4 updates in the /src-ui directory: [@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.35.0 to 8.35.1
- [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.35.1/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.35.0 to 8.35.1
- [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.35.1/packages/parser)

Updates `@typescript-eslint/utils` from 8.35.0 to 8.35.1
- [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.35.1/packages/utils)

Updates `eslint` from 9.28.0 to 9.30.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.28.0...v9.30.1)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.35.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.35.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.35.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-eslint-dependencies
- dependency-name: eslint
  dependency-version: 9.30.1
  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>
2025-07-01 22:14:01 +00:00
dependabot[bot]
a3a405354f
Chore(deps-dev): Bump @types/node from 22.15.29 to 24.0.10 in /src-ui (#10306)
---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.10
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 22:03:30 +00:00
dependabot[bot]
09e98d600e
Chore(deps): Bump bootstrap from 5.3.6 to 5.3.7 in /src-ui (#10308)
---
updated-dependencies:
- dependency-name: bootstrap
  dependency-version: 5.3.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:52:26 +00:00
dependabot[bot]
01a39b9bb4
Chore(deps-dev): Bump webpack from 5.98.0 to 5.99.9 in /src-ui (#10309)
---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.99.9
  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>
2025-07-01 21:39:13 +00:00
dependabot[bot]
3b0b40f071
Chore(deps-dev): Bump @playwright/test from 1.51.1 to 1.53.2 in /src-ui (#10307)
---
updated-dependencies:
- dependency-name: "@playwright/test"
  dependency-version: 1.53.2
  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>
2025-07-01 21:19:26 +00:00
GitHub Actions
6dce83865f Auto translate strings 2025-07-01 20:47:25 +00:00
dependabot[bot]
18252a19d7
Chore(deps): Bump the frontend-angular-dependencies group (#10303)
Bumps the frontend-angular-dependencies group in /src-ui with 13 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `20.0.5` | `20.0.6` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `20.0.5` | `20.0.6` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `20.0.5` | `20.0.6` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `20.0.5` | `20.0.6` |
| [@angular/localize](https://github.com/angular/angular) | `20.0.5` | `20.0.6` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `20.0.5` | `20.0.6` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `20.0.5` | `20.0.6` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `20.0.5` | `20.0.6` |
| [@ng-bootstrap/ng-bootstrap](https://github.com/ng-bootstrap/ng-bootstrap) | `19.0.0` | `19.0.1` |
| [@ng-select/ng-select](https://github.com/ng-select/ng-select) | `15.1.2` | `15.1.3` |
| [ngx-cookie-service](https://github.com/stevermeister/ngx-cookie-service) | `19.1.2` | `20.0.1` |
| [ngx-device-detector](https://github.com/AhsanAyaz/ngx-device-detector) | `9.0.0` | `10.0.2` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `20.0.5` | `20.0.6` |


Updates `@angular/common` from 20.0.5 to 20.0.6
- [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/20.0.6/packages/common)

Updates `@angular/compiler` from 20.0.5 to 20.0.6
- [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/20.0.6/packages/compiler)

Updates `@angular/core` from 20.0.5 to 20.0.6
- [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/20.0.6/packages/core)

Updates `@angular/forms` from 20.0.5 to 20.0.6
- [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/20.0.6/packages/forms)

Updates `@angular/localize` from 20.0.5 to 20.0.6
- [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/20.0.5...20.0.6)

Updates `@angular/platform-browser` from 20.0.5 to 20.0.6
- [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/20.0.6/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 20.0.5 to 20.0.6
- [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/20.0.6/packages/platform-browser-dynamic)

Updates `@angular/router` from 20.0.5 to 20.0.6
- [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/20.0.6/packages/router)

Updates `@ng-bootstrap/ng-bootstrap` from 19.0.0 to 19.0.1
- [Release notes](https://github.com/ng-bootstrap/ng-bootstrap/releases)
- [Changelog](https://github.com/ng-bootstrap/ng-bootstrap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ng-bootstrap/ng-bootstrap/compare/19.0.0...19.0.1)

Updates `@ng-select/ng-select` from 15.1.2 to 15.1.3
- [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/v15.1.2...v15.1.3)

Updates `ngx-cookie-service` from 19.1.2 to 20.0.1
- [Release notes](https://github.com/stevermeister/ngx-cookie-service/releases)
- [Changelog](https://github.com/stevermeister/ngx-cookie-service/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stevermeister/ngx-cookie-service/compare/v19.1.2...v20.0.1)

Updates `ngx-device-detector` from 9.0.0 to 10.0.2
- [Release notes](https://github.com/AhsanAyaz/ngx-device-detector/releases)
- [Changelog](https://github.com/AhsanAyaz/ngx-device-detector/blob/master/steps-to-release.md)
- [Commits](https://github.com/AhsanAyaz/ngx-device-detector/compare/v9.0.0...v10.0.2)

Updates `@angular/compiler-cli` from 20.0.5 to 20.0.6
- [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/20.0.6/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/common"
  dependency-version: 20.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-version: 20.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-version: 20.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-version: 20.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-version: 20.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-version: 20.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 20.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-version: 20.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-bootstrap/ng-bootstrap"
  dependency-version: 19.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-select/ng-select"
  dependency-version: 15.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-cookie-service
  dependency-version: 20.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-device-detector
  dependency-version: 10.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-version: 20.0.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  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>
2025-07-01 13:44:44 -07:00
Antoine Mérino
733a9674d6
Fix: prevent duplicate cachalot app in Django settings (#10300)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-07-01 09:11:58 -07:00
GitHub Actions
f3b6e15321 Auto translate strings 2025-07-01 05:59:21 +00:00
Antoine Mérino
6591d5da63
Performance: Add support for configuring date parser languages (#10181)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-07-01 05:57:38 +00:00
GitHub Actions
c974dc9400 Auto translate strings 2025-07-01 05:41:44 +00:00
Antoine Mérino
1671d49d44
Enhancement: Add a database caching for improved performance (#9784)
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-06-30 22:36:24 -07:00
GitHub Actions
6b248ef140 Auto translate strings 2025-06-29 04:40:53 +00:00
shamoon
735681d294
Fix: correct api created coercion with timezone (#10287) 2025-06-28 21:39:14 -07:00
shamoon
a9085c65c5
Chore: fix some test warnings / errors 2025-06-27 15:03:10 -07:00
shamoon
e312425b1c
Fix: reset search query for preview on reset filter (#10279) 2025-06-27 14:36:38 -07:00
GitHub Actions
13fe064f6e Auto translate strings 2025-06-27 21:08:27 +00:00
shamoon
958f98d7e5
Chore: update to Angular 20 (#10273) 2025-06-27 14:06:40 -07:00
shamoon
dfad3c4d8e
Chore: clarify file deletion logging 2025-06-27 13:34:44 -07:00
shamoon
37267f3f04
Chore: add webpack directly 2025-06-22 20:03:48 -07:00
shamoon
b34538d991
Update support.yml 2025-06-22 08:03:41 -07:00
shamoon
fc97bd1315
Chore: create support discussion template 2025-06-22 08:02:26 -07:00
shamoon
dbf3721ec2
Chore: reject absurd max age values (#10243) 2025-06-22 07:39:36 -07:00
shamoon
59afbe09b1
Chore: remove PAPERLESS_DEBUG references to avoid confusion 2025-06-20 20:46:11 -07:00
shamoon
bfeaa1b119
Chore: update settings to pathlib 2025-06-20 10:50:44 -07:00
github-actions[bot]
e1c3124698
Changelog v2.17.1 - GHA (#10229) 2025-06-19 12:40:37 -07:00
shamoon
f2e22e103b
Bump version to 2.17.1 2025-06-19 12:07:49 -07:00
github-actions[bot]
dda94f013e
New Crowdin translations by GitHub Action (#10228)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-06-19 12:06:52 -07:00
GitHub Actions
caf00e7ead Auto translate strings 2025-06-19 18:52:01 +00:00
shamoon
f214440d2e
Fix: correct PAPERLESS_EMPTY_TRASH_DIR to Path (#10227) 2025-06-19 11:50:23 -07:00
github-actions[bot]
240c9ac511
Changelog v2.17.0 - GHA (#10225) 2025-06-19 10:43:13 -07:00
shamoon
a2c9bc346a
Bump version to 2.17.0 2025-06-19 10:12:41 -07:00
github-actions[bot]
b1cbb1c73a
New Crowdin translations by GitHub Action (#10131)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-06-19 09:32:51 -07:00
shamoon
434b1e3245
Fix: replace strtobool 2025-06-19 09:02:10 -07:00
GitHub Actions
497fdcaf4e Auto translate strings 2025-06-19 15:31:10 +00:00
shamoon
52b95f2b62
QoL: log version at startup, show backend vs frontend mismatch in system status (#10214) 2025-06-19 08:29:34 -07:00
shamoon
83391af866
Fix: more api fixes (#10204) 2025-06-19 08:28:41 -07:00
GitHub Actions
0a1786f39b Auto translate strings 2025-06-19 14:50:29 +00:00
shamoon
3b069ac034
Fix: restore expected pre-2.16 scheduled workflow offset behavior (#10218) 2025-06-19 14:47:54 +00:00
Sebastian Steinbeißer
07882b918b
Chore: switch from os.path to pathlib.Path (#9933)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-06-18 17:16:59 +00:00
shamoon
cc5ba71f06
Chore: remove spaces from run log 2025-06-17 16:02:45 -07:00
GitHub Actions
f16b8fbe2a Auto translate strings 2025-06-17 19:02:55 +00:00
shamoon
fe54d99356
Chore: bump angular to 19.12.14 (#10212) 2025-06-17 12:01:15 -07:00
GitHub Actions
a49efb07ea Auto translate strings 2025-06-17 05:46:29 +00:00
shamoon
e4fd008441
Fix: fix some API crashes (#10196) 2025-06-16 22:44:39 -07:00
robertmx
de12023311
Fix: remove duplicate base path in websocket urls (#10194) 2025-06-16 10:50:15 -07:00
shamoon
60ebdc0ad6
Fix: use hard delete for custom fields with workflow removal (#10191) 2025-06-16 07:09:22 -07:00
Michael Hobl
cbd9823ad6
Documentation: correct Gotenberg API timeout value (#10186) 2025-06-15 07:36:49 -07:00
shamoon
ce76303a32
Feature: add Persian translation (#10183) 2025-06-14 19:14:51 -07:00
Kilian
246f17c6c8
Enhancement: support import of zipped export (#10073) 2025-06-13 10:06:37 -07:00
shamoon
4313635b01
Revert "Development: fix dependabot by specifying pnpm version (#10103)"
This reverts commit 9c9a0e4496abfd9d4eb72dfabb73256b791a273b.
2025-06-10 09:19:00 -07:00
shamoon
7ca2bd0666
Fix: fix mail account test api schema (#10164) 2025-06-10 07:09:24 -07:00
shamoon
4c6075e962
Fix: correct api schema for mail_account process (#10157) 2025-06-09 14:51:58 -07:00
shamoon
8d48e99487
Fix: correct api schema for next_asn (#10151) 2025-06-09 09:32:34 -07:00
shamoon
454a2d9e9e
Fix: fix email and notes endpoints api spec (#10148) 2025-06-09 07:09:28 -07:00
shamoon
b8c713d4b9
Chore: get CI running on crowdin PRs 2025-06-06 00:29:06 -07:00
github-actions[bot]
2a8cb87232
Changelog v2.16.3 - GHA (#10129)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-06-05 14:41:33 -07:00
shamoon
e5673e4817
Bump version to 2.16.3 2025-06-05 13:26:20 -07:00
shamoon
ed48392450
Merge branch 'dev' 2025-06-05 13:25:32 -07:00
github-actions[bot]
48d6bedf1c
New Crowdin translations by GitHub Action (#10127) 2025-06-05 13:09:27 -07:00
github-actions[bot]
ec2dc6cd80
New Crowdin translations by GitHub Action (#10032) 2025-06-05 12:47:57 -07:00
shamoon
51e6eed72a
Fix: handle whoosh query correction errors (#10121) 2025-06-05 08:57:25 -07:00
shamoon
422bffe1a6
Performance: pre-filter document list in scheduled workflow checks (#10031) 2025-06-03 21:47:29 +00:00
dependabot[bot]
31351c5f5c
Chore(deps): Bump the small-changes group across 1 directory with 3 updates (#10085)
Bumps the small-changes group with 3 updates in the / directory: [concurrent-log-handler](https://github.com/Preston-Landers/concurrent-log-handler), [ocrmypdf](https://github.com/ocrmypdf/OCRmyPDF) and [setproctitle](https://github.com/dvarrazzo/py-setproctitle).


Updates `concurrent-log-handler` from 0.9.25 to 0.9.26
- [Release notes](https://github.com/Preston-Landers/concurrent-log-handler/releases)
- [Changelog](https://github.com/Preston-Landers/concurrent-log-handler/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Preston-Landers/concurrent-log-handler/compare/0.9.25...0.9.26)

Updates `ocrmypdf` from 16.10.0 to 16.10.2
- [Release notes](https://github.com/ocrmypdf/OCRmyPDF/releases)
- [Changelog](https://github.com/ocrmypdf/OCRmyPDF/blob/main/docs/release_notes.md)
- [Commits](https://github.com/ocrmypdf/OCRmyPDF/compare/v16.10.0...v16.10.2)

Updates `setproctitle` from 1.3.5 to 1.3.6
- [Changelog](https://github.com/dvarrazzo/py-setproctitle/blob/master/HISTORY.rst)
- [Commits](https://github.com/dvarrazzo/py-setproctitle/compare/version-1.3.5...version-1.3.6)

---
updated-dependencies:
- dependency-name: concurrent-log-handler
  dependency-version: 0.9.26
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: ocrmypdf
  dependency-version: 16.10.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: setproctitle
  dependency-version: 1.3.6
  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>
2025-06-03 19:57:32 +00:00
shamoon
c30cf2e0cd
Chore: fix naive datetime warnings 2025-06-03 12:42:18 -07:00
shamoon
e97cfb9b5e
Chore: refactor consumer plugin checks to a pre-flight plugin (#9994) 2025-06-03 19:28:49 +00:00
dependabot[bot]
42100588d5
Chore(deps): Update granian[uvloop] requirement from ~=2.2.0 to ~=2.3.2 (#10055)
Updates the requirements on [granian[uvloop]](https://github.com/emmett-framework/granian) to permit the latest version.
- [Release notes](https://github.com/emmett-framework/granian/releases)
- [Commits](https://github.com/emmett-framework/granian/compare/v2.2.0...v2.3.2)

---
updated-dependencies:
- dependency-name: granian[uvloop]
  dependency-version: 2.3.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-03 12:15:00 -07:00
shamoon
bc2facc87f
Chore: use pathlib in remaining tests 2025-06-03 11:48:17 -07:00
shamoon
b4c6c4b61e
Documentation: clarify db behavior (#10113) 2025-06-03 09:41:29 -07:00
shamoon
4e082f997c
Fix: better handle favicon with static dir (#10107) 2025-06-03 08:05:59 -07:00
GitHub Actions
1512599f4f Auto translate strings 2025-06-02 19:12:59 +00:00
dependabot[bot]
6c8f0b54ad
Chore(deps): Bump the frontend-angular-dependencies group in /src-ui with 18 updates (#10099)
* Chore(deps): Bump the frontend-angular-dependencies group

Bumps the frontend-angular-dependencies group in /src-ui with 22 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/cdk](https://github.com/angular/components) | `19.2.14` | `20.0.1` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `19.2.9` | `19.2.14` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `19.2.9` | `19.2.14` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `19.2.9` | `19.2.14` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `19.2.9` | `19.2.14` |
| [@angular/localize](https://github.com/angular/angular) | `19.2.9` | `19.2.14` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `19.2.9` | `19.2.14` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `19.2.9` | `19.2.14` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `19.2.9` | `19.2.14` |
| [@ng-select/ng-select](https://github.com/ng-select/ng-select) | `14.7.0` | `14.9.0` |
| [ngx-cookie-service](https://github.com/stevermeister/ngx-cookie-service) | `19.1.2` | `20.0.1` |
| [ngx-device-detector](https://github.com/AhsanAyaz/ngx-device-detector) | `9.0.0` | `10.0.2` |
| [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `19.2.10` | `19.2.14` |
| [@angular-devkit/core](https://github.com/angular/angular-cli) | `19.2.10` | `19.2.14` |
| [@angular-devkit/schematics](https://github.com/angular/angular-cli) | `19.2.10` | `19.2.14` |
| [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) | `19.3.0` | `19.6.0` |
| [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) | `19.3.0` | `19.6.0` |
| [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) | `19.3.0` | `19.6.0` |
| [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) | `19.3.0` | `19.6.0` |
| [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) | `19.3.0` | `19.6.0` |
| [@angular/cli](https://github.com/angular/angular-cli) | `19.2.10` | `19.2.14` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `19.2.9` | `19.2.14` |


Updates `@angular/cdk` from 19.2.14 to 20.0.1
- [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/19.2.14...20.0.1)

Updates `@angular/common` from 19.2.9 to 19.2.14
- [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/19.2.14/packages/common)

Updates `@angular/compiler` from 19.2.9 to 19.2.14
- [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/19.2.14/packages/compiler)

Updates `@angular/core` from 19.2.9 to 19.2.14
- [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/19.2.14/packages/core)

Updates `@angular/forms` from 19.2.9 to 19.2.14
- [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/19.2.14/packages/forms)

Updates `@angular/localize` from 19.2.9 to 19.2.14
- [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/19.2.9...19.2.14)

Updates `@angular/platform-browser` from 19.2.9 to 19.2.14
- [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/19.2.14/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 19.2.9 to 19.2.14
- [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/19.2.14/packages/platform-browser-dynamic)

Updates `@angular/router` from 19.2.9 to 19.2.14
- [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/19.2.14/packages/router)

Updates `@ng-select/ng-select` from 14.7.0 to 14.9.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/v14.7.0...v14.9.0)

Updates `ngx-cookie-service` from 19.1.2 to 20.0.1
- [Release notes](https://github.com/stevermeister/ngx-cookie-service/releases)
- [Changelog](https://github.com/stevermeister/ngx-cookie-service/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stevermeister/ngx-cookie-service/compare/v19.1.2...v20.0.1)

Updates `ngx-device-detector` from 9.0.0 to 10.0.2
- [Release notes](https://github.com/AhsanAyaz/ngx-device-detector/releases)
- [Changelog](https://github.com/AhsanAyaz/ngx-device-detector/blob/master/steps-to-release.md)
- [Commits](https://github.com/AhsanAyaz/ngx-device-detector/compare/v9.0.0...v10.0.2)

Updates `@angular-devkit/build-angular` from 19.2.10 to 19.2.14
- [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/19.2.10...19.2.14)

Updates `@angular-devkit/core` from 19.2.10 to 19.2.14
- [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/19.2.10...19.2.14)

Updates `@angular-devkit/schematics` from 19.2.10 to 19.2.14
- [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/19.2.10...19.2.14)

Updates `@angular-eslint/builder` from 19.3.0 to 19.6.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/v19.6.0/packages/builder)

Updates `@angular-eslint/eslint-plugin` from 19.3.0 to 19.6.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/v19.6.0/packages/eslint-plugin)

Updates `@angular-eslint/eslint-plugin-template` from 19.3.0 to 19.6.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/v19.6.0/packages/eslint-plugin-template)

Updates `@angular-eslint/schematics` from 19.3.0 to 19.6.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/v19.6.0/packages/schematics)

Updates `@angular-eslint/template-parser` from 19.3.0 to 19.6.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/v19.6.0/packages/template-parser)

Updates `@angular/cli` from 19.2.10 to 19.2.14
- [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/19.2.10...19.2.14)

Updates `@angular/compiler-cli` from 19.2.9 to 19.2.14
- [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/19.2.14/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/cdk"
  dependency-version: 20.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/common"
  dependency-version: 19.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-version: 19.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-version: 19.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-version: 19.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-version: 19.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-version: 19.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 19.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-version: 19.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-select/ng-select"
  dependency-version: 14.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-cookie-service
  dependency-version: 20.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-device-detector
  dependency-version: 10.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/build-angular"
  dependency-version: 19.2.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/core"
  dependency-version: 19.2.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/schematics"
  dependency-version: 19.2.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/builder"
  dependency-version: 19.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin"
  dependency-version: 19.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin-template"
  dependency-version: 19.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/schematics"
  dependency-version: 19.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/template-parser"
  dependency-version: 19.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-version: 19.2.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-version: 19.2.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
...

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

* Revert "Chore(deps): Bump the frontend-angular-dependencies group"

This reverts commit 9bd02e2bc9287331a2134262ea0120a88ab2f625.

* Bump core angular cli to 19.2.14

* Bump @angular-devkit/build-angular to 19.2.14

* Bump @angular-devkit/core to 19.2.14

* bump @angular-devkit/schematics@ to 19.2.14

* bump @angular-eslint packages to 19.7.0

* Bump @ng-select/ng-select to 14.9.0

* Upgrade angular core and compiler to 19.2.14

* pnpm up @angular/forms@~19.2.14

* pnpm up @angular/localize@~19.2.14 --lockfile-only

* pnpm up @angular/platform-browser@~19.2.14 --lockfile-only

* pnpm up @angular/platform-browser-dynamic@~19.2.14 --lockfile-only

* pnpm up @angular/router@~19.2.14 --lockfile-only

* pnpm up @angular/compiler-cli@~19.2.14 --lockfile-only

* @angular/common to 19.2.13

---------

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>
2025-06-02 12:11:17 -07:00
dependabot[bot]
419ee9d6e7
Chore(deps-dev): Bump the frontend-eslint-dependencies group (#10100)
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.31.1 to 8.33.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.33.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.31.1 to 8.33.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.33.0/packages/parser)

Updates `@typescript-eslint/utils` from 8.31.1 to 8.33.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.33.0/packages/utils)

Updates `eslint` from 9.25.1 to 9.28.0
- [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.25.1...v9.28.0)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: eslint
  dependency-version: 9.28.0
  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>
2025-06-02 16:43:57 +00:00
dependabot[bot]
34b649aa01
Chore(deps): Bump bootstrap from 5.3.3 to 5.3.6 in /src-ui (#10091)
Bumps [bootstrap](https://github.com/twbs/bootstrap) from 5.3.3 to 5.3.6.
- [Release notes](https://github.com/twbs/bootstrap/releases)
- [Commits](https://github.com/twbs/bootstrap/compare/v5.3.3...v5.3.6)

---
updated-dependencies:
- dependency-name: bootstrap
  dependency-version: 5.3.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 16:32:53 +00:00
dependabot[bot]
a9982abde8
Chore(deps-dev): Bump @codecov/webpack-plugin in /src-ui (#10090)
Bumps @codecov/webpack-plugin from 1.9.0 to 1.9.1.

---
updated-dependencies:
- dependency-name: "@codecov/webpack-plugin"
  dependency-version: 1.9.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 16:18:22 +00:00
dependabot[bot]
a94cc62207
Chore(deps-dev): Bump @types/node from 22.15.3 to 22.15.29 in /src-ui (#10089)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.15.3 to 22.15.29.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.15.29
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 16:07:50 +00:00
GitHub Actions
fc1b3e674b Auto translate strings 2025-06-02 15:52:11 +00:00
dependabot[bot]
603ad6c817
Chore(deps): Bump zone.js from 0.15.0 to 0.15.1 in /src-ui (#10088) 2025-06-02 15:50:25 +00:00
shamoon
9c9a0e4496
Development: fix dependabot by specifying pnpm version (#10103) 2025-06-02 08:28:14 -07:00
sidey79
7c33785c07
Development: devcontainer setup, docs and enable dependabot (#10081)
* fix: container setup and task description

* feat: enable dependabot for devcontainer

* fix: dont install latest uv and dont install uvx

* Cleanup decontainer readme

* Fix the reset venv command

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-06-01 17:59:46 +00:00
shamoon
9c32d931bc
Dont label dependabot as enhancments 2025-05-31 17:02:07 -07:00
dependabot[bot]
d7b2e002ce
docker(deps): bump astral-sh/uv (#10084)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.7.8-python3.12-bookworm-slim to 0.7.9-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.7.8...0.7.9)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.7.9-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-31 09:27:59 -07:00
Trenton H
51e70f0a20
Removes the reviewers field, excludes Django and related from the small changes group (#10076) 2025-05-31 15:35:51 +00:00
mamasch19
bd257925bd
Documentation: fix typo in configuration.md (#10077) 2025-05-29 15:18:30 -07:00
shamoon
15b1b83c66
Chore/fix: cleanup user or group references in settings upon deletion (#10049) 2025-05-29 19:05:48 +00:00
dependabot[bot]
b06c0a0eba
docker(deps): Bump astral-sh/uv from 0.6.16-python3.12-bookworm-slim to 0.7.8-python3.12-bookworm-slim (#10056)
* docker(deps): Bump astral-sh/uv

Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.16-python3.12-bookworm-slim to 0.7.8-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.6.16...0.7.8)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.7.8-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

* Upgrades the CI workflow to also use 0.7.x

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-05-29 11:17:15 -07:00
matthesrieke
e9746aa0e3
Enhancement: include DOCUMENT_TYPE to post consume scripts (#9977)
* expose DOCUMENT_TYPE to post consume scripts

* Apply suggestions from code review

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-05-28 23:32:59 +00:00
Freilichtbühne
bfaab21589
Fix: Add exception to utime in copy_basic_file_stats (#10070) 2025-05-28 15:13:03 -07:00
GitHub Actions
3849569bd1 Auto translate strings 2025-05-27 23:01:05 +00:00
shamoon
c40a7751b9
Fix: include base href when opening global search result in new window (#10066) 2025-05-27 15:59:17 -07:00
shamoon
f39463ff4e
Add a more helpful docstring to schedule logic, scheduled test 2025-05-27 13:05:42 -07:00
shamoon
2ada8ec681
Chore: silence migration result if no docs 2025-05-26 10:31:37 -07:00
shamoon
bdbf1b57ce
Documentation: add workflow permissions note (#10038) 2025-05-25 09:18:48 -07:00
github-actions[bot]
4c6fdbb21f
Documentation: Add v2.16.2 changelog (#10029)
* Changelog v2.16.2 - 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>
2025-05-24 11:57:09 -07:00
shamoon
889c4378a9
Merge branch 'dev' 2025-05-24 11:55:16 -07:00
shamoon
06dd039083
Revert "Chore: remove invalid branches-ignores"
This reverts commit 28a1b9d1ac1ba8120aa33c85efbf2e1f686f36aa.
2025-05-24 11:46:47 -07:00
shamoon
00acbd4f1d
Bump version to 2.16.2 2025-05-24 10:54:17 -07:00
shamoon
28a1b9d1ac
Chore: remove invalid branches-ignores 2025-05-24 10:51:52 -07:00
github-actions[bot]
4f8a931a61
New Crowdin translations by GitHub Action (#10028) 2025-05-24 10:37:58 -07:00
github-actions[bot]
716ebfe08a
New Crowdin translations by GitHub Action (#9989)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-05-24 10:19:35 -07:00
GitHub Actions
e1760db85c Auto translate strings 2025-05-24 17:15:50 +00:00
shamoon
3cbb5239fb
Fix: accept datetime for created (#10021) 2025-05-24 17:14:15 +00:00
Samuel Kosmann
aed629269d
add fallback to copyfile on PermissionError (#10023)
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-05-24 16:54:24 +00:00
shamoon
59bf25edb1
Fix: created date fixes in v2.16 (#10026) 2025-05-24 09:45:07 -07:00
GitHub Actions
eb07876657 Auto translate strings 2025-05-24 14:29:39 +00:00
shamoon
ae3ac2b719
Fix: mark fields for created objects as dirty (#10022) 2025-05-24 07:28:04 -07:00
shamoon
5b4b316bbc
Chore: warn users about removal of postgres v13 support (#9980) 2025-05-21 18:17:50 +00:00
shamoon
1583783a0b
Resolve test timezone warnings 2025-05-21 00:51:53 -07:00
shamoon
bd5f05ff2b
Documentation: remove duplicates from changelog 2025-05-19 22:17:56 -07:00
github-actions[bot]
9be6b28141
Changelog v2.16.1 - GHA (#9978)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-19 14:29:13 -07:00
shamoon
3de8c9073d
Bump version to 2.16.1 2025-05-19 13:57:41 -07:00
github-actions[bot]
e90a2aa4eb
New Crowdin translations by GitHub Action (#9964)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-05-19 13:56:03 -07:00
GitHub Actions
edef851c89 Auto translate strings 2025-05-19 20:53:46 +00:00
shamoon
7b37e037e4
Fix: fix created dater filtering in 2.16.0 (#9976) 2025-05-19 13:52:09 -07:00
shamoon
e092627da6
Chore: improve PR labeling move all labelling to pr-bot workflow (#9970) 2025-05-19 13:44:25 -07:00
shamoon
0a03ca94c7
Fix dev API version 2025-05-19 13:34:22 -07:00
github-actions[bot]
86dec8f344
Documentation: Add v2.16.0 changelog (#9969)
* Changelog v2.16.0 - GHA

* Fix categorizations

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-05-19 13:01:43 -07:00
shamoon
0b079f57ed
Partially Revert "Chore(deps): Bump the small-changes group across 1 directory with 6 updates (#9921)"
This partially reverts commit 1fe166e014ebde9a6fb6861819efa7e705175cd6.
2025-05-19 12:20:05 -07:00
shamoon
ba80790826
Bump version to 2.16.0 2025-05-19 11:37:27 -07:00
shamoon
2f8b2944f1
Merge branch 'dev' 2025-05-19 11:37:01 -07:00
github-actions[bot]
46ddba4579
New Crowdin translations by GitHub Action (#9724) 2025-05-19 11:06:03 -07:00
dependabot[bot]
1fe166e014
Chore(deps): Bump the small-changes group across 1 directory with 6 updates (#9921)
* 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 |
| --- | --- | --- |
| [concurrent-log-handler](https://github.com/Preston-Landers/concurrent-log-handler) | `0.9.25` | `0.9.26` |
| [django](https://github.com/django/django) | `5.1.8` | `5.2.1` |
| [django-auditlog](https://github.com/jazzband/django-auditlog) | `3.0.0` | `3.1.2` |
| [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar) | `2025.4.1` | `2025.5.1` |
| [ocrmypdf](https://github.com/ocrmypdf/OCRmyPDF) | `16.10.0` | `16.10.1` |
| [setproctitle](https://github.com/dvarrazzo/py-setproctitle) | `1.3.5` | `1.3.6` |



Updates `concurrent-log-handler` from 0.9.25 to 0.9.26
- [Release notes](https://github.com/Preston-Landers/concurrent-log-handler/releases)
- [Changelog](https://github.com/Preston-Landers/concurrent-log-handler/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Preston-Landers/concurrent-log-handler/compare/0.9.25...0.9.26)

Updates `django` from 5.1.8 to 5.2.1
- [Commits](https://github.com/django/django/compare/5.1.8...5.2.1)

Updates `django-auditlog` from 3.0.0 to 3.1.2
- [Release notes](https://github.com/jazzband/django-auditlog/releases)
- [Changelog](https://github.com/jazzband/django-auditlog/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jazzband/django-auditlog/compare/v3.0.0...v3.1.2)

Updates `drf-spectacular-sidecar` from 2025.4.1 to 2025.5.1
- [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2025.4.1...2025.5.1)

Updates `ocrmypdf` from 16.10.0 to 16.10.1
- [Release notes](https://github.com/ocrmypdf/OCRmyPDF/releases)
- [Changelog](https://github.com/ocrmypdf/OCRmyPDF/blob/main/docs/release_notes.md)
- [Commits](https://github.com/ocrmypdf/OCRmyPDF/compare/v16.10.0...v16.10.1)

Updates `setproctitle` from 1.3.5 to 1.3.6
- [Changelog](https://github.com/dvarrazzo/py-setproctitle/blob/master/HISTORY.rst)
- [Commits](https://github.com/dvarrazzo/py-setproctitle/compare/version-1.3.5...version-1.3.6)

---
updated-dependencies:
- dependency-name: concurrent-log-handler
  dependency-version: 0.9.26
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: django
  dependency-version: 5.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: django-auditlog
  dependency-version: 3.1.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: drf-spectacular-sidecar
  dependency-version: 2025.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: ocrmypdf
  dependency-version: 16.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: setproctitle
  dependency-version: 1.3.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
...

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

* Fix log matches related to newlines, add newlines to stdout.writelines

* Fix disable api remote auth test, Django 5.2 no longer uses process_request

---------

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>
2025-05-19 11:03:02 -07:00
GitHub Actions
71bc483eec Auto translate strings 2025-05-19 16:41:14 +00:00
shamoon
55917fcabe
Fix: handle created change with api version increment, use created only on frontend, deprecate created_date (#9962) 2025-05-19 09:38:01 -07:00
GitHub Actions
fae4116504 Auto translate strings 2025-05-17 05:22:59 +00:00
shamoon
83db0355f3
Chore: automatically disable email verification if no smtp setup (#9949) 2025-05-16 22:21:24 -07:00
shamoon
6647b32ac0
Fix: ignore logo file from sanity checker (#9946) 2025-05-16 17:30:34 -07:00
GitHub Actions
3365fc92fd Auto translate strings 2025-05-16 14:25:26 +00:00
shamoon
1a6f32534c
Change: treat created as date not datetime (#9793) 2025-05-16 14:23:04 +00:00
GitHub Actions
ce5d4e9c92 Auto translate strings 2025-05-13 06:07:40 +00:00
shamoon
0ab85b5122
Fix/Chore: replace file drop package (#9926) 2025-05-12 23:05:34 -07:00
shamoon
2c9e690dfb
Chore: resolve dynamic import warnings from pdfjs, again (#9924) 2025-05-12 21:04:18 -07:00
shamoon
344cc70cd5
Enhancement: support negative offset in scheduled workflows (#9746) 2025-05-11 20:04:46 +00:00
shamoon
73f0f1212d
Fixhancement: better handle removed social apps in profile (#9876) 2025-05-11 19:55:33 +00:00
GitHub Actions
a61f5ac64c Auto translate strings 2025-05-11 19:45:45 +00:00
shamoon
6a5be992c0
Enhancement: add barcode frontend config (#9742) 2025-05-11 19:44:06 +00:00
dependabot[bot]
bcb0ae1ee5
docker-compose(deps): Bump library/redis from 7 to 8 in /docker/compose (#9879)
Bumps library/redis from 7 to 8.

---
updated-dependencies:
- dependency-name: library/redis
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 16:49:18 +00:00
dependabot[bot]
6bc385b49b
Chore(deps): Bump astral-sh/setup-uv from 5 to 6 in the actions group (#9842)
Bumps the actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 5 to 6
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v5...v6)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 16:22:08 +00:00
shamoon
c6b3fd8bcb
Chore: update s6-overlay to v3.2.1.0 (#9893) 2025-05-07 08:56:11 -07:00
shamoon
7cabb5bf98
Documentation: correct custom field search example 2025-05-07 06:41:49 -07:00
shamoon
011056a9d5
Documentation: clarify disable consumer setting 2025-05-03 22:55:29 -07:00
shamoon
384a197c6f
Documentation: clarify PAPERLESS_CONSUMER_DISABLE (#9862) 2025-05-03 07:57:06 -07:00
shamoon
0542758641
Chore: split ci frontend e2e vs unit tests (#9851) 2025-05-02 00:38:20 -07:00
GitHub Actions
848148afd5 Auto translate strings 2025-05-02 07:13:21 +00:00
dependabot[bot]
42226adda0
Chore(deps): Bump the frontend-angular-dependencies group (#9848)
Bumps the frontend-angular-dependencies group in /src-ui with 14 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/cdk](https://github.com/angular/components) | `19.2.10` | `19.2.14` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `19.2.7` | `19.2.9` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `19.2.7` | `19.2.9` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `19.2.7` | `19.2.9` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `19.2.7` | `19.2.9` |
| [@angular/localize](https://github.com/angular/angular) | `19.2.7` | `19.2.9` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `19.2.7` | `19.2.9` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `19.2.7` | `19.2.9` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `19.2.7` | `19.2.9` |
| [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `19.2.8` | `19.2.10` |
| [@angular-devkit/core](https://github.com/angular/angular-cli) | `19.2.8` | `19.2.10` |
| [@angular-devkit/schematics](https://github.com/angular/angular-cli) | `19.2.8` | `19.2.10` |
| [@angular/cli](https://github.com/angular/angular-cli) | `19.2.8` | `19.2.10` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `19.2.7` | `19.2.9` |


Updates `@angular/cdk` from 19.2.10 to 19.2.14
- [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/19.2.10...19.2.14)

Updates `@angular/common` from 19.2.7 to 19.2.9
- [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/19.2.9/packages/common)

Updates `@angular/compiler` from 19.2.7 to 19.2.9
- [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/19.2.9/packages/compiler)

Updates `@angular/core` from 19.2.7 to 19.2.9
- [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/19.2.9/packages/core)

Updates `@angular/forms` from 19.2.7 to 19.2.9
- [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/19.2.9/packages/forms)

Updates `@angular/localize` from 19.2.7 to 19.2.9
- [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/19.2.7...19.2.9)

Updates `@angular/platform-browser` from 19.2.7 to 19.2.9
- [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/19.2.9/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 19.2.7 to 19.2.9
- [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/19.2.9/packages/platform-browser-dynamic)

Updates `@angular/router` from 19.2.7 to 19.2.9
- [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/19.2.9/packages/router)

Updates `@angular-devkit/build-angular` from 19.2.8 to 19.2.10
- [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/19.2.8...19.2.10)

Updates `@angular-devkit/core` from 19.2.8 to 19.2.10
- [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/19.2.8...19.2.10)

Updates `@angular-devkit/schematics` from 19.2.8 to 19.2.10
- [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/19.2.8...19.2.10)

Updates `@angular/cli` from 19.2.8 to 19.2.10
- [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/19.2.8...19.2.10)

Updates `@angular/compiler-cli` from 19.2.7 to 19.2.9
- [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/19.2.9/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/cdk"
  dependency-version: 19.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/common"
  dependency-version: 19.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-version: 19.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-version: 19.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-version: 19.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-version: 19.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-version: 19.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 19.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-version: 19.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/build-angular"
  dependency-version: 19.2.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/core"
  dependency-version: 19.2.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/schematics"
  dependency-version: 19.2.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-version: 19.2.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-version: 19.2.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  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>
2025-05-02 07:10:29 +00:00
dependabot[bot]
c2412c0955
Chore(deps-dev): Bump the frontend-eslint-dependencies group (#9849)
Bumps the frontend-eslint-dependencies group in /src-ui with 3 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) and [@typescript-eslint/utils](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/utils).


Updates `@typescript-eslint/eslint-plugin` from 8.31.0 to 8.31.1
- [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.31.1/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.31.0 to 8.31.1
- [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.31.1/packages/parser)

Updates `@typescript-eslint/utils` from 8.31.0 to 8.31.1
- [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.31.1/packages/utils)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.31.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.31.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.31.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  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>
2025-05-02 06:58:21 +00:00
dependabot[bot]
c58b68e597
Chore(deps-dev): Bump @types/node from 22.13.17 to 22.15.3 in /src-ui (#9850)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.13.17 to 22.15.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.15.3
  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>
2025-05-02 06:47:56 +00:00
shamoon
1b4a52aaa1
Development: always try playwright install on ci, cache browsers (#9847) 2025-05-01 23:34:21 -07:00
shamoon
86adc377a0
Fix: correctly handle empty user for old notes api format, fix frontend API version (#9846) 2025-05-01 14:45:37 -07:00
Trenton H
c83b0bfca6
Fix: Trim off the path portion so the comparision can properly skip (#9839) 2025-05-01 13:50:25 -07:00
shamoon
1b3a91f63f
Fix: fix single select in filterable dropdowns when editing (#9834) 2025-04-30 01:48:02 -07:00
shamoon
924a13f724
Fix: always update classifier task result (#9817) 2025-04-29 11:46:18 -07:00
GitHub Actions
7236b8b682 Auto translate strings 2025-04-27 06:32:48 +00:00
shamoon
a3b85c64ca
Fixhancement: check more permissions for status consumer messages (#9804) 2025-04-26 23:31:04 -07:00
shamoon
278ef3a364
Documentation: add note that actions can modify the original 2025-04-26 12:20:04 -07:00
dependabot[bot]
0cefdc8475
docker(deps): Bump astral-sh/uv from 0.6.14-python3.12-bookworm-slim to 0.6.16-python3.12-bookworm-slim (#9767)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.14-python3.12-bookworm-slim to 0.6.16-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.6.14...0.6.16)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.6.16-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-24 17:14:44 +00:00
dependabot[bot]
915584551c
docker-compose(deps): bump gotenberg/gotenberg from 8.19 to 8.20 in /docker/compose (#9661)
Bumps gotenberg/gotenberg from 8.19 to 8.20.

---
updated-dependencies:
- dependency-name: gotenberg/gotenberg
  dependency-version: '8.20'
  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>
2025-04-24 10:06:07 -07:00
shamoon
855c9aa28d
Chore: only use single trigger for pr bot 2025-04-24 07:43:21 -07:00
GitHub Actions
e277a8e1ea Auto translate strings 2025-04-23 16:32:16 +00:00
shamoon
6d8c507169
Chore: auto-generate translation strings (#9462) 2025-04-23 09:30:30 -07:00
shamoon
00050f7c7b
Enhancement: support heic images (#9771) 2025-04-23 09:22:21 -07:00
shamoon
5a278381e3
Chore: add coverage for missing lines in patch change 2025-04-22 23:33:11 -07:00
dependabot[bot]
af95963c5f
Chore(deps): Bump the frontend-angular-dependencies group (#9768)
Bumps the frontend-angular-dependencies group in /src-ui with 17 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/cdk](https://github.com/angular/components) | `19.2.7` | `19.2.10` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `19.2.4` | `19.2.7` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `19.2.4` | `19.2.7` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `19.2.4` | `19.2.7` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `19.2.4` | `19.2.7` |
| [@angular/localize](https://github.com/angular/angular) | `19.2.4` | `19.2.7` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `19.2.4` | `19.2.7` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `19.2.4` | `19.2.7` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `19.2.4` | `19.2.7` |
| [@ng-select/ng-select](https://github.com/ng-select/ng-select) | `14.2.6` | `14.7.0` |
| [@angular-builders/custom-webpack](https://github.com/just-jeb/angular-builders/tree/HEAD/packages/custom-webpack) | `19.0.0` | `19.0.1` |
| [@angular-builders/jest](https://github.com/just-jeb/angular-builders/tree/HEAD/packages/jest) | `19.0.0` | `19.0.1` |
| [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `19.2.5` | `19.2.8` |
| [@angular-devkit/core](https://github.com/angular/angular-cli) | `19.2.5` | `19.2.8` |
| [@angular-devkit/schematics](https://github.com/angular/angular-cli) | `19.2.5` | `19.2.8` |
| [@angular/cli](https://github.com/angular/angular-cli) | `19.2.5` | `19.2.8` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `19.2.4` | `19.2.7` |


Updates `@angular/cdk` from 19.2.7 to 19.2.10
- [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/19.2.7...19.2.10)

Updates `@angular/common` from 19.2.4 to 19.2.7
- [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/19.2.7/packages/common)

Updates `@angular/compiler` from 19.2.4 to 19.2.7
- [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/19.2.7/packages/compiler)

Updates `@angular/core` from 19.2.4 to 19.2.7
- [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/19.2.7/packages/core)

Updates `@angular/forms` from 19.2.4 to 19.2.7
- [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/19.2.7/packages/forms)

Updates `@angular/localize` from 19.2.4 to 19.2.7
- [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/19.2.4...19.2.7)

Updates `@angular/platform-browser` from 19.2.4 to 19.2.7
- [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/19.2.7/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 19.2.4 to 19.2.7
- [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/19.2.7/packages/platform-browser-dynamic)

Updates `@angular/router` from 19.2.4 to 19.2.7
- [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/19.2.7/packages/router)

Updates `@ng-select/ng-select` from 14.2.6 to 14.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/v14.2.6...v14.7.0)

Updates `@angular-builders/custom-webpack` from 19.0.0 to 19.0.1
- [Release notes](https://github.com/just-jeb/angular-builders/releases)
- [Changelog](https://github.com/just-jeb/angular-builders/blob/master/packages/custom-webpack/CHANGELOG.md)
- [Commits](https://github.com/just-jeb/angular-builders/commits/@angular-builders/custom-webpack@19.0.1/packages/custom-webpack)

Updates `@angular-builders/jest` from 19.0.0 to 19.0.1
- [Release notes](https://github.com/just-jeb/angular-builders/releases)
- [Changelog](https://github.com/just-jeb/angular-builders/blob/master/packages/jest/CHANGELOG.md)
- [Commits](https://github.com/just-jeb/angular-builders/commits/@angular-builders/jest@19.0.1/packages/jest)

Updates `@angular-devkit/build-angular` from 19.2.5 to 19.2.8
- [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/19.2.5...19.2.8)

Updates `@angular-devkit/core` from 19.2.5 to 19.2.8
- [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/19.2.5...19.2.8)

Updates `@angular-devkit/schematics` from 19.2.5 to 19.2.8
- [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/19.2.5...19.2.8)

Updates `@angular/cli` from 19.2.5 to 19.2.8
- [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/19.2.5...19.2.8)

Updates `@angular/compiler-cli` from 19.2.4 to 19.2.7
- [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/19.2.7/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/cdk"
  dependency-version: 19.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/common"
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-select/ng-select"
  dependency-version: 14.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-builders/custom-webpack"
  dependency-version: 19.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-builders/jest"
  dependency-version: 19.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/build-angular"
  dependency-version: 19.2.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/core"
  dependency-version: 19.2.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/schematics"
  dependency-version: 19.2.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-version: 19.2.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-version: 19.2.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  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>
2025-04-22 16:34:21 -07:00
dependabot[bot]
c724436fc4
Chore(deps-dev): Bump the frontend-eslint-dependencies group (#9770)
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.29.0 to 8.31.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.31.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.29.0 to 8.31.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.31.0/packages/parser)

Updates `@typescript-eslint/utils` from 8.29.0 to 8.31.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.31.0/packages/utils)

Updates `eslint` from 9.23.0 to 9.25.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.23.0...v9.25.1)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.31.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.31.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.31.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-eslint-dependencies
- dependency-name: eslint
  dependency-version: 9.25.1
  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>
2025-04-22 22:46:35 +00:00
dependabot[bot]
e288824963
Chore(deps-dev): Bump jest-preset-angular (#9769)
Bumps the frontend-jest-dependencies group in /src-ui with 1 update: [jest-preset-angular](https://github.com/thymikee/jest-preset-angular).


Updates `jest-preset-angular` from 14.5.4 to 14.5.5
- [Release notes](https://github.com/thymikee/jest-preset-angular/releases)
- [Changelog](https://github.com/thymikee/jest-preset-angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/thymikee/jest-preset-angular/compare/v14.5.4...v14.5.5)

---
updated-dependencies:
- dependency-name: jest-preset-angular
  dependency-version: 14.5.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-jest-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-22 15:36:36 -07:00
shamoon
312bb743b9
Chore: add ymlfmt (#9745) 2025-04-22 22:20:54 +00:00
shamoon
7436a97684
Enhancement: support allauth disable unknown account emails (#9743) 2025-04-22 21:58:33 +00:00
shamoon
cbaceb95af
Enhancement: use patch instead of put for frontend document changes (#9744) 2025-04-22 19:58:28 +00:00
dependabot[bot]
2abf38f98e
Chore(deps): Bump the small-changes group across 1 directory with 6 updates (#9764)
* 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 |
| --- | --- | --- |
| [channels](https://github.com/django/channels) | `4.2.0` | `4.2.2` |
| [filelock](https://github.com/tox-dev/py-filelock) | `3.17.0` | `3.18.0` |
| [gotenberg-client](https://github.com/stumpylog/gotenberg-client) | `0.9.0` | `0.10.0` |
| [jinja2](https://github.com/pallets/jinja) | `3.1.5` | `3.1.6` |
| [python-dotenv](https://github.com/theskumar/python-dotenv) | `1.0.1` | `1.1.0` |
| [rapidfuzz](https://github.com/rapidfuzz/RapidFuzz) | `3.12.1` | `3.13.0` |



Updates `channels` from 4.2.0 to 4.2.2
- [Changelog](https://github.com/django/channels/blob/main/CHANGELOG.txt)
- [Commits](https://github.com/django/channels/compare/4.2.0...4.2.2)

Updates `filelock` from 3.17.0 to 3.18.0
- [Release notes](https://github.com/tox-dev/py-filelock/releases)
- [Changelog](https://github.com/tox-dev/filelock/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/py-filelock/compare/3.17.0...3.18.0)

Updates `gotenberg-client` from 0.9.0 to 0.10.0
- [Release notes](https://github.com/stumpylog/gotenberg-client/releases)
- [Changelog](https://github.com/stumpylog/gotenberg-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stumpylog/gotenberg-client/compare/0.9.0...0.10.0)

Updates `jinja2` from 3.1.5 to 3.1.6
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.5...3.1.6)

Updates `python-dotenv` from 1.0.1 to 1.1.0
- [Release notes](https://github.com/theskumar/python-dotenv/releases)
- [Changelog](https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/theskumar/python-dotenv/compare/v1.0.1...v1.1.0)

Updates `rapidfuzz` from 3.12.1 to 3.13.0
- [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.12.1...v3.13.0)

---
updated-dependencies:
- dependency-name: channels
  dependency-version: 4.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: filelock
  dependency-version: 3.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: gotenberg-client
  dependency-version: 0.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: jinja2
  dependency-version: 3.1.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: small-changes
- dependency-name: python-dotenv
  dependency-version: 1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
- dependency-name: rapidfuzz
  dependency-version: 3.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: small-changes
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2025-04-22 10:32:27 -07:00
dependabot[bot]
b40e1f7d01
Chore(deps): Bump the django group across 1 directory with 6 updates (#9753)
Bumps the django group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [django](https://github.com/django/django) | `5.1.7` | `5.1.8` |
| [django-celery-results](https://github.com/celery/django-celery-results) | `2.5.1` | `2.6.0` |
| [django-extensions](https://github.com/django-extensions/django-extensions) | `3.2.3` | `4.1` |
| [djangorestframework](https://github.com/encode/django-rest-framework) | `3.15.2` | `3.16.0` |
| [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar) | `2025.3.1` | `2025.4.1` |
| [drf-writable-nested](https://github.com/beda-software/drf-writable-nested) | `0.7.1` | `0.7.2` |



Updates `django` from 5.1.7 to 5.1.8
- [Commits](https://github.com/django/django/compare/5.1.7...5.1.8)

Updates `django-celery-results` from 2.5.1 to 2.6.0
- [Release notes](https://github.com/celery/django-celery-results/releases)
- [Changelog](https://github.com/celery/django-celery-results/blob/main/Changelog)
- [Commits](https://github.com/celery/django-celery-results/compare/v2.5.1...v2.6.0)

Updates `django-extensions` from 3.2.3 to 4.1
- [Release notes](https://github.com/django-extensions/django-extensions/releases)
- [Changelog](https://github.com/django-extensions/django-extensions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/django-extensions/django-extensions/compare/3.2.3...4.1)

Updates `djangorestframework` from 3.15.2 to 3.16.0
- [Release notes](https://github.com/encode/django-rest-framework/releases)
- [Commits](https://github.com/encode/django-rest-framework/compare/3.15.2...3.16.0)

Updates `drf-spectacular-sidecar` from 2025.3.1 to 2025.4.1
- [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2025.3.1...2025.4.1)

Updates `drf-writable-nested` from 0.7.1 to 0.7.2
- [Release notes](https://github.com/beda-software/drf-writable-nested/releases)
- [Changelog](https://github.com/beda-software/drf-writable-nested/blob/master/CHANGELOG.md)
- [Commits](https://github.com/beda-software/drf-writable-nested/compare/v0.7.1...v0.7.2)

---
updated-dependencies:
- dependency-name: django
  dependency-version: 5.1.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: django
- dependency-name: django-celery-results
  dependency-version: 2.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
- dependency-name: django-extensions
  dependency-version: '4.1'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: django
- dependency-name: djangorestframework
  dependency-version: 3.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
- dependency-name: drf-spectacular-sidecar
  dependency-version: 2025.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: django
- dependency-name: drf-writable-nested
  dependency-version: 0.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: django
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-22 09:18:22 -07:00
shamoon
15d4ac8ba2
Fixhancement: tag plus button should add tag to doc (#9762) 2025-04-22 08:02:55 -07:00
shamoon
fcb7349e8e
Fix: fix zoom increase/decrease buttons in FF (#9761) 2025-04-22 08:02:43 -07:00
Sebastian Steinbeißer
648cfd9d05
Chore: switch from os.path to pathlib.Path (#9339) 2025-04-21 12:16:52 -07:00
Trenton H
c3df7d3439
Chore: Group additional Django dependencies together (#9741) 2025-04-21 12:16:34 -07:00
shamoon
a5cd545a1b
Chore: replace secretary with GHA (#9723) 2025-04-21 19:02:54 +00:00
dependabot[bot]
96227f785a
docker(deps): bump astral-sh/uv from 0.6.13-python3.12-bookworm-slim to 0.6.14-python3.12-bookworm-slim (#9656)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.13-python3.12-bookworm-slim to 0.6.14-python3.12-bookworm-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.6.13...0.6.14)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.6.14-python3.12-bookworm-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 18:46:19 +00:00
shamoon
7f98c4b794
Fix: include subpath in drf-spectacular settings if set (#9738) 2025-04-21 11:24:08 -07:00
github-actions[bot]
d914a82dea
Changelog v2.15.3 - GHA (#9720)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-04-19 16:15:35 -07:00
shamoon
1a72efa3c9
Bump version to 2.15.3 2025-04-19 15:34:42 -07:00
shamoon
aa6c58103f
Merge branch 'dev' 2025-04-19 15:34:04 -07:00
github-actions[bot]
ba6976bdbb
New Crowdin translations by GitHub Action (#9705) 2025-04-19 15:15:46 -07:00
shamoon
7a1be6bff2
Update translation strings 2025-04-19 15:13:53 -07:00
shamoon
c3bd587cbf
Documentation: note api v8 bump 2025-04-19 15:12:55 -07:00
shamoon
a57a3dbb30
Fix: do not try deleting original that was moved to trash dir (#9684) 2025-04-19 15:11:29 -07:00
shamoon
f52ebc7bf0
Fix: preserve non-ASCII filenames in document downloads (#9702) 2025-04-19 22:10:34 +00:00
shamoon
abf910fd93
Fix: fix breaking api change to document notes user field (#9714) 2025-04-19 22:02:33 +00:00
shamoon
1b0aa193bd
Fix: fix missing archive file size 2025-04-19 14:26:53 -07:00
shamoon
eac12fe031
Documentation: tweaks to sharing, links 2025-04-18 09:49:34 -07:00
shamoon
62f46b706e
Fix: another doc link fix (#9700) 2025-04-17 21:15:53 -07:00
shamoon
df5af5c8ad
Fix: correctly handle dict data with webhook (#9674) 2025-04-16 00:07:08 -07:00
shamoon
67a97ffc4d
Documentation: expound email config explanation 2025-04-15 07:52:53 -07:00
github-actions[bot]
45b39f36d6
Documentation: Add v2.15.2 changelog (#9660) 2025-04-14 14:08:18 -07:00
shamoon
a339853bc5
Merge branch 'dev' 2025-04-14 13:25:39 -07:00
shamoon
6c2e06d40b
Bump version to 2.15.2 2025-04-14 13:04:21 -07:00
github-actions[bot]
2d6a4d108f
New Crowdin translations by GitHub Action (#9655)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-04-14 12:49:25 -07:00
github-actions[bot]
703db0f01f
New Crowdin translations by GitHub Action (#9611)
* New Crowdin translations by GitHub Action

* Trigger ci

---------

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-04-14 12:47:38 -07:00
Trenton H
8b5d6bf3db
Chore: Upgrades granian to latest patch version (#9652) 2025-04-14 16:03:25 +00:00
shamoon
2d93e95848
Update translation strings 2025-04-14 08:54:58 -07:00
Trenton H
ab8c75958d
Fix: Adds better handling during folder checking/creation/permissions for non-root (#9616)
* Adds better handling during folder checking/creation/permissions for when the image is running as non-root

* Prefers the long options to commands
2025-04-14 15:51:57 +00:00
shamoon
9db3923d35
Tweak: consistently use created date when displaying doc in list (#9651) 2025-04-14 08:27:30 -07:00
Trenton H
e2860ed36d
Fix: Explicitly set the HOME environment variable for running as root at startup (#9643)
* Explicitly set the HOME environment for the migrations to fix issue with certificates

* Defines the HOME globally when we're running as root for startup
2025-04-14 15:21:45 +00:00
Thom Wiggers
82a5680217
Delete unused docker/docker-entrypoint.sh (#9615) 2025-04-14 07:39:56 -07:00
Hannes Ortmeier
588fd0207d
chore: Bump celery to 5.5.1 (#9642) 2025-04-14 14:28:04 +00:00
shamoon
6dea158de9
Fix: prevent self-linking when bulk edit doc link (#9629) 2025-04-14 07:12:50 -07:00
shamoon
d956269d5f
Update faq 2025-04-10 20:25:16 -07:00
github-actions[bot]
f269919410
Documentation: Add v2.15.1 changelog (#9606)
---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2025-04-09 15:48:56 -07:00
shamoon
5f00066dff
Manually bump version in uv.lock 2025-04-09 15:48:20 -07:00
581 changed files with 170869 additions and 86439 deletions

View File

@ -10,10 +10,8 @@ component_management:
paths: paths:
- src-ui/** - src-ui/**
# https://docs.codecov.com/docs/pull-request-comments # https://docs.codecov.com/docs/pull-request-comments
# codecov will only comment if coverage changes
comment: comment:
layout: "header, diff, components, flags, files" layout: "header, diff, components, flags, files"
require_changes: true
# https://docs.codecov.com/docs/javascript-bundle-analysis # https://docs.codecov.com/docs/javascript-bundle-analysis
require_bundle_changes: true require_bundle_changes: true
bundle_change_threshold: "50Kb" bundle_change_threshold: "50Kb"

View File

@ -1,3 +0,0 @@
[codespell]
write-changes = True
ignore-words-list = criterias,afterall,valeu,ureue,equest,ure,assertIn

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM docker.io/node:20-bookworm-slim as main-app FROM --platform=$BUILDPLATFORM docker.io/node:20-trixie-slim as main-app
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
@ -8,16 +8,17 @@ ARG DEBIAN_FRONTEND=noninteractive
ARG TARGETARCH ARG TARGETARCH
# Can be workflow provided, defaults set for manual building # Can be workflow provided, defaults set for manual building
ARG JBIG2ENC_VERSION=0.29 ARG JBIG2ENC_VERSION=0.30
ARG QPDF_VERSION=11.9.0
ARG GS_VERSION=10.03.1
# Set Python environment variables # Set Python environment variables
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
# Ignore warning from Whitenoise # Ignore warning from Whitenoise
PYTHONWARNINGS="ignore:::django.http.response:517" \ PYTHONWARNINGS="ignore:::django.http.response:517" \
PNGX_CONTAINERIZED=1 PNGX_CONTAINERIZED=1 \
# https://docs.astral.sh/uv/reference/settings/#link-mode
UV_LINK_MODE=copy \
UV_CACHE_DIR=/cache/uv/
# #
# Begin installation and configuration # Begin installation and configuration
@ -83,36 +84,15 @@ RUN set -eux \
&& apt-get update \ && apt-get update \
&& apt-get install --yes --quiet ${PYTHON_PACKAGES} && apt-get install --yes --quiet ${PYTHON_PACKAGES}
COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /bin/uv COPY --from=ghcr.io/astral-sh/uv:0.9.10 /uv /bin/uv
RUN set -eux \ RUN set -eux \
&& echo "Installing pre-built updates" \ && echo "Installing pre-built updates" \
&& echo "Installing qpdf ${QPDF_VERSION}" \
&& curl --fail --silent --show-error --location \
--output libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
&& curl --fail --silent --show-error --location \
--output qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
&& dpkg --install ./libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
&& dpkg --install ./qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
&& echo "Installing Ghostscript ${GS_VERSION}" \
&& curl --fail --silent --show-error --location \
--output libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
&& curl --fail --silent --show-error --location \
--output ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
&& curl --fail --silent --show-error --location \
--output libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
&& dpkg --install ./libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
&& dpkg --install ./libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
&& dpkg --install ./ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
&& echo "Installing jbig2enc" \ && echo "Installing jbig2enc" \
&& curl --fail --silent --show-error --location \ && curl --fail --silent --show-error --location \
--output jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ --output jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ https://github.com/paperless-ngx/builder/releases/download/jbig2enc-trixie-v${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
&& dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb && dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb
# setup docker-specific things # setup docker-specific things
@ -126,9 +106,9 @@ COPY [ \
RUN set -eux \ RUN set -eux \
&& echo "Configuring ImageMagick" \ && echo "Configuring ImageMagick" \
&& mkdir -p /etc/ImageMagick-6 \
&& mv paperless-policy.xml /etc/ImageMagick-6/policy.xml && mv paperless-policy.xml /etc/ImageMagick-6/policy.xml
COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /bin/uv
# Packages needed only for building a few quick Python # Packages needed only for building a few quick Python
# dependencies # dependencies
@ -142,7 +122,7 @@ ARG BUILD_PACKAGES="\
pkg-config" pkg-config"
# hadolint ignore=DL3042 # hadolint ignore=DL3042
RUN --mount=type=cache,target=/root/.cache/uv,id=pip-cache \ RUN --mount=type=cache,target=/cache/uv/,id=uv-cache \
set -eux \ set -eux \
&& echo "Installing build system packages" \ && echo "Installing build system packages" \
&& apt-get update \ && apt-get update \

View File

@ -47,39 +47,19 @@ To start the DevContainer:
1. Open VSCode. 1. Open VSCode.
2. Open the project folder. 2. Open the project folder.
3. Open the command palette: 3. Open the command palette and choose `Dev Containers: Rebuild and Reopen in Container`.
- **Windows/Linux**: `Ctrl+Shift+P`
- **Mac**: `Cmd+Shift+P`
4. Type and select `Dev Containers: Rebuild and Reopen in Container`.
VSCode will build and start the DevContainer environment. VSCode will build and start the DevContainer environment.
### Step 2: Initial Setup ### Step 2: Initial Setup
Once the DevContainer is up and running, perform the following steps: Once the DevContainer is up and running, run the `Project Setup: Run all Init Tasks` task to initialize the project.
1. **Compile Frontend Assets**: Alternatively, the Project Setup can be done with individual tasks:
- Open the command palette: 1. **Compile Frontend Assets**: `Maintenance: Compile frontend for production`.
- **Windows/Linux**: `Ctrl+Shift+P` 2. **Run Database Migrations**: `Maintenance: manage.py migrate`.
- **Mac**: `Cmd+Shift+P` 3. **Create Superuser**: `Maintenance: manage.py createsuperuser`.
- Select `Tasks: Run Task`.
- Choose `Frontend Compile`.
2. **Run Database Migrations**:
- Open the command palette:
- **Windows/Linux**: `Ctrl+Shift+P`
- **Mac**: `Cmd+Shift+P`
- Select `Tasks: Run Task`.
- Choose `Migrate Database`.
3. **Create Superuser**:
- Open the command palette:
- **Windows/Linux**: `Ctrl+Shift+P`
- **Mac**: `Cmd+Shift+P`
- Select `Tasks: Run Task`.
- Choose `Create Superuser`.
### Debugging and Running Services ### Debugging and Running Services
@ -95,11 +75,8 @@ You can start and debug backend services either as debugging sessions via `launc
#### Using Tasks #### Using Tasks
1. Open the command palette: 1. Open the command palette and select `Tasks: Run Task`.
- **Windows/Linux**: `Ctrl+Shift+P` 2. Choose the desired task:
- **Mac**: `Cmd+Shift+P`
2. Select `Tasks: Run Task`.
3. Choose the desired task:
- `Runserver` - `Runserver`
- `Document Consumer` - `Document Consumer`
- `Celery` - `Celery`

View File

@ -3,7 +3,7 @@
"dockerComposeFile": "docker-compose.devcontainer.sqlite-tika.yml", "dockerComposeFile": "docker-compose.devcontainer.sqlite-tika.yml",
"service": "paperless-development", "service": "paperless-development",
"workspaceFolder": "/usr/src/paperless/paperless-ngx", "workspaceFolder": "/usr/src/paperless/paperless-ngx",
"postCreateCommand": "/bin/bash -c 'uv sync --group dev && uv run pre-commit install'", "postCreateCommand": "/bin/bash -c 'rm -rf .venv/.* && uv sync --group dev && uv run pre-commit install'",
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": [ "extensions": [

View File

@ -20,15 +20,12 @@
# #
# This file is intended only to be used through VSCOde devcontainers. See README.md # This file is intended only to be used through VSCOde devcontainers. See README.md
# in the folder .devcontainer. # in the folder .devcontainer.
services: services:
broker: broker:
image: docker.io/library/redis:7 image: docker.io/library/redis:7
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- ./redisdata:/data - ./redisdata:/data
# No ports need to be exposed; the VSCode DevContainer plugin manages them. # No ports need to be exposed; the VSCode DevContainer plugin manages them.
paperless-development: paperless-development:
image: paperless-ngx image: paperless-ngx
@ -52,7 +49,6 @@ services:
- ./data:/usr/src/paperless/paperless-ngx/data - ./data:/usr/src/paperless/paperless-ngx/data
- ./media:/usr/src/paperless/paperless-ngx/media - ./media:/usr/src/paperless/paperless-ngx/media
- ./consume:/usr/src/paperless/paperless-ngx/consume - ./consume:/usr/src/paperless/paperless-ngx/consume
- ~/.gitconfig:/usr/src/paperless/.gitconfig:ro
environment: environment:
PAPERLESS_REDIS: redis://broker:6379 PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_TIKA_ENABLED: 1 PAPERLESS_TIKA_ENABLED: 1
@ -60,25 +56,20 @@ services:
PAPERLESS_TIKA_ENDPOINT: http://tika:9998 PAPERLESS_TIKA_ENDPOINT: http://tika:9998
PAPERLESS_STATICDIR: ./src/documents/static PAPERLESS_STATICDIR: ./src/documents/static
PAPERLESS_DEBUG: true PAPERLESS_DEBUG: true
# Overrides default command so things don't shut down after the process ends. # Overrides default command so things don't shut down after the process ends.
command: /bin/sh -c "chown -R paperless:paperless /usr/src/paperless/paperless-ngx/src/documents/static/frontend && chown -R paperless:paperless /usr/src/paperless/paperless-ngx/.ruff_cache && while sleep 1000; do :; done" command: /bin/sh -c "chown -R paperless:paperless /usr/src/paperless/paperless-ngx/src/documents/static/frontend && chown -R paperless:paperless /usr/src/paperless/paperless-ngx/.ruff_cache && while sleep 1000; do :; done"
gotenberg: gotenberg:
image: docker.io/gotenberg/gotenberg:8.17 image: docker.io/gotenberg/gotenberg:8.17
restart: unless-stopped restart: unless-stopped
# The Gotenberg Chromium route is used to convert .eml files. We do not # The Gotenberg Chromium route is used to convert .eml files. We do not
# want to allow external content like tracking pixels or even JavaScript. # want to allow external content like tracking pixels or even JavaScript.
command: command:
- "gotenberg" - "gotenberg"
- "--chromium-disable-javascript=true" - "--chromium-disable-javascript=true"
- "--chromium-allow-list=file:///tmp/.*" - "--chromium-allow-list=file:///tmp/.*"
tika: tika:
image: docker.io/apache/tika:latest image: docker.io/apache/tika:latest
restart: unless-stopped restart: unless-stopped
volumes: volumes:
data: data:
media: media:

View File

@ -1,11 +1,10 @@
{ {
"python.testing.pytestArgs": [ "python.testing.pytestArgs": [],
"src"
],
"python.testing.unittestEnabled": false, "python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true, "python.testing.pytestEnabled": true,
"files.watcherExclude": { "files.watcherExclude": {
"**/.venv/**": true, "**/.venv/**": true,
"**/pytest_cache/**": true "**/pytest_cache/**": true
} },
"python.testing.cwd": "${workspaceFolder}/src"
} }

View File

@ -156,7 +156,7 @@
"label": "Maintenance: recreate .venv", "label": "Maintenance: recreate .venv",
"description": "Recreate the python virtual environment and install python dependencies", "description": "Recreate the python virtual environment and install python dependencies",
"type": "shell", "type": "shell",
"command": "rm -R -v .venv/* || uv install --dev", "command": "rm -rf .venv && uv venv && uv sync --dev",
"group": "none", "group": "none",
"presentation": { "presentation": {
"echo": true, "echo": true,

View File

@ -11,6 +11,10 @@ end_of_line = lf
charset = utf-8 charset = utf-8
max_line_length = 79 max_line_length = 79
[*.sh]
indent_style = tab
indent_size = 1
[{*.html,*.css,*.js}] [{*.html,*.css,*.js}]
max_line_length = off max_line_length = off

55
.github/DISCUSSION_TEMPLATE/support.yml vendored Normal file
View File

@ -0,0 +1,55 @@
title: "[Support] "
body:
- type: textarea
id: description
attributes:
label: What's your question or issue?
description: Provide a clear and concise description of what you're trying to do, and what's going wrong.
placeholder: |
I'm trying to...
[Include screenshots if helpful]
validations:
required: true
- type: textarea
id: steps
attributes:
label: What have you tried?
description: Describe any steps you've already taken to troubleshoot or solve the issue.
placeholder: |
- I checked the logs and saw...
- I followed the install guide and tried...
- type: input
id: version
attributes:
label: Paperless-ngx version
placeholder: e.g. 1.14.0
validations:
required: true
- type: input
id: host-os
attributes:
label: Host OS
description: Include architecture if relevant.
placeholder: e.g. Ubuntu 22.04 / Raspberry Pi arm64
- type: dropdown
id: install-method
attributes:
label: Installation method
options:
- Docker - official image
- Docker - linuxserver.io image
- Bare metal
- Other (please describe above)
- type: textarea
id: system-status
attributes:
label: System status
description: If available, copy & paste the system status output from Settings > System Status > Copy
render: json
- type: textarea
id: logs
attributes:
label: Relevant logs or output
description: If you have logs, errors that might help, paste it here. For example other containers or services (database, redis, etc).
render: bash

View File

@ -6,8 +6,8 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
### ⚠️ Please remember: issues are for *bugs* ### ⚠️ Please remember: issues are for *bugs* only! ⚠️
That is, something you believe affects every single user of Paperless-ngx, not just you. If you're not sure, start with one of the other options below. That is, something you believe affects every single user of Paperless-ngx (and the demo, for example), not just you. If you are not sure, start with one of the other options below.
Also, note that **Paperless-ngx does not perform OCR or archive file creation itself**, those are handled by other tools. Problems with OCR or archive versions of specific files should likely be raised 'upstream', see https://github.com/ocrmypdf/OCRmyPDF/issues or https://github.com/tesseract-ocr/tesseract/issues Also, note that **Paperless-ngx does not perform OCR or archive file creation itself**, those are handled by other tools. Problems with OCR or archive versions of specific files should likely be raised 'upstream', see https://github.com/ocrmypdf/OCRmyPDF/issues or https://github.com/tesseract-ocr/tesseract/issues
- type: markdown - type: markdown
@ -59,6 +59,12 @@ body:
label: Browser logs label: Browser logs
description: Logs from the web browser related to your issue, if needed description: Logs from the web browser related to your issue, if needed
render: bash render: bash
- type: textarea
id: logs_services
attributes:
label: Services logs
description: Logs from other services (or containers) related to your issue, if needed. For example, the database or redis logs.
render: bash
- type: input - type: input
id: version id: version
attributes: attributes:

View File

@ -35,8 +35,8 @@ NOTE: PRs that do not address the following will not be merged, please do not sk
- [ ] I have read & agree with the [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md). - [ ] I have read & agree with the [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md).
- [ ] If applicable, I have included testing coverage for new code in this PR, for [backend](https://docs.paperless-ngx.com/development/#testing) and / or [front-end](https://docs.paperless-ngx.com/development/#testing-and-code-style) changes. - [ ] If applicable, I have included testing coverage for new code in this PR, for [backend](https://docs.paperless-ngx.com/development/#testing) and / or [front-end](https://docs.paperless-ngx.com/development/#testing-and-code-style) changes.
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers. - [ ] If applicable, I have tested my code for breaking changes & regressions on both mobile & desktop devices, using the latest version of major browsers.
- [ ] If applicable, I have checked that all tests pass, see [documentation](https://docs.paperless-ngx.com/development/#back-end-development). - [ ] If applicable, I have checked that all tests pass, see [documentation](https://docs.paperless-ngx.com/development/#back-end-development).
- [ ] I have run all `pre-commit` hooks, see [documentation](https://docs.paperless-ngx.com/development/#code-formatting-with-pre-commit-hooks). - [ ] I have run all `pre-commit` hooks, see [documentation](https://docs.paperless-ngx.com/development/#code-formatting-with-pre-commit-hooks).
- [ ] I have made corresponding changes to the documentation as needed. - [ ] I have made corresponding changes to the documentation as needed.
- [ ] I have checked my modifications for any breaking changes. - [ ] In the description of the PR above I have disclosed the use of AI tools in the coding of this PR.

View File

@ -1,11 +1,9 @@
# Please see the documentation for all configuration options: # Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2 version: 2
# Required for uv support for now # Required for uv support for now
enable-beta-ecosystems: true enable-beta-ecosystems: true
updates: updates:
# Enable version updates for pnpm # Enable version updates for pnpm
- package-ecosystem: "npm" - package-ecosystem: "npm"
target-branch: "dev" target-branch: "dev"
@ -17,9 +15,6 @@ updates:
labels: labels:
- "frontend" - "frontend"
- "dependencies" - "dependencies"
# Add reviewers
reviewers:
- "paperless-ngx/frontend"
groups: groups:
frontend-angular-dependencies: frontend-angular-dependencies:
patterns: patterns:
@ -35,7 +30,6 @@ updates:
patterns: patterns:
- "@typescript-eslint*" - "@typescript-eslint*"
- "eslint" - "eslint"
# Enable version updates for Python # Enable version updates for Python
- package-ecosystem: "uv" - package-ecosystem: "uv"
target-branch: "dev" target-branch: "dev"
@ -46,31 +40,57 @@ updates:
labels: labels:
- "backend" - "backend"
- "dependencies" - "dependencies"
# Add reviewers
reviewers:
- "paperless-ngx/backend"
groups: groups:
# Development & CI/CD Tooling
development: development:
patterns: patterns:
- "*pytest*" - "*pytest*"
- "ruff" - "ruff"
- "mkdocs-material" - "mkdocs-material"
- "pre-commit*" - "pre-commit*"
django: # Django & DRF Ecosystem
django-ecosystem:
patterns: patterns:
- "*django*" - "*django*"
major-versions: - "drf-*"
- "djangorestframework"
- "whitenoise"
- "bleach"
- "jinja2"
# Async, Task Queuing & Caching
async-tasks:
patterns:
- "celery*"
- "channels*"
- "flower"
- "redis"
# Document, PDF, and OCR Processing
document-processing:
patterns:
- "ocrmypdf"
- "pdf2image"
- "pyzbar"
- "zxing-cpp"
- "tika-client"
- "gotenberg-client"
- "python-magic"
- "python-gnupg"
# Data, NLP, and Search
data-nlp-search:
patterns:
- "nltk"
- "scikit-learn"
- "langdetect"
- "rapidfuzz"
- "whoosh-reloaded"
# Utilities (Patch Updates)
utilities-patch:
update-types: update-types:
- "major" - "patch"
small-changes: # Utilities (Minor Updates)
utilities-minor:
update-types: update-types:
- "minor" - "minor"
- "patch"
pre-built:
patterns:
- psycopg*
- zxing-cpp
# Enable updates for GitHub Actions # Enable updates for GitHub Actions
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
target-branch: "dev" target-branch: "dev"
@ -81,41 +101,32 @@ updates:
labels: labels:
- "ci-cd" - "ci-cd"
- "dependencies" - "dependencies"
# Add reviewers
reviewers:
- "paperless-ngx/ci-cd"
groups: groups:
actions: actions:
update-types: update-types:
- "major" - "major"
- "minor" - "minor"
- "patch" - "patch"
# Update Dockerfile in root directory # Update Dockerfile in root directory
- package-ecosystem: "docker" - package-ecosystem: "docker"
directory: "/" directories:
- "/"
- "/.devcontainer/"
schedule: schedule:
interval: "weekly" interval: "weekly"
open-pull-requests-limit: 5 open-pull-requests-limit: 5
reviewers:
- "paperless-ngx/ci-cd"
labels: labels:
- "ci-cd"
- "dependencies" - "dependencies"
commit-message: commit-message:
prefix: "docker" prefix: "docker"
include: "scope" include: "scope"
# Update Docker Compose files in docker/compose directory # Update Docker Compose files in docker/compose directory
- package-ecosystem: "docker-compose" - package-ecosystem: "docker-compose"
directory: "/docker/compose/" directory: "/docker/compose/"
schedule: schedule:
interval: "weekly" interval: "weekly"
open-pull-requests-limit: 5 open-pull-requests-limit: 5
reviewers:
- "paperless-ngx/ci-cd"
labels: labels:
- "ci-cd"
- "dependencies" - "dependencies"
commit-message: commit-message:
prefix: "docker-compose" prefix: "docker-compose"

26
.github/labeler.yml vendored Normal file
View File

@ -0,0 +1,26 @@
backend:
- changed-files:
- any-glob-to-any-file:
- 'src/**'
- 'pyproject.toml'
- 'uv.lock'
- 'requirements.txt'
frontend:
- changed-files:
- any-glob-to-any-file:
- 'src-ui/**'
documentation:
- changed-files:
- any-glob-to-any-file:
- 'docs/**'
ci-cd:
- changed-files:
- any-glob-to-any-file:
- '.github/**'
# pr types
bug:
- head-branch:
- ['^fix']
enhancement:
- head-branch:
- ['^feature']

View File

@ -1,15 +1,3 @@
autolabeler:
- label: "bug"
branch:
- '/^fix/'
title:
- "/^fix/i"
- "/^Bugfix/i"
- label: "enhancement"
branch:
- '/^feature/'
title:
- "/^feature/i"
categories: categories:
- title: 'Breaking Changes' - title: 'Breaking Changes'
labels: labels:
@ -17,7 +5,7 @@ categories:
- title: 'Notable Changes' - title: 'Notable Changes'
labels: labels:
- 'notable' - 'notable'
- title: 'Features' - title: 'Features / Enhancements'
labels: labels:
- 'enhancement' - 'enhancement'
- title: 'Bug Fixes' - title: 'Bug Fixes'

View File

@ -1,5 +1,4 @@
name: ci name: ci
on: on:
push: push:
tags: tags:
@ -12,72 +11,99 @@ on:
pull_request: pull_request:
branches-ignore: branches-ignore:
- 'translations**' - 'translations**'
env: env:
DEFAULT_UV_VERSION: "0.6.x" DEFAULT_UV_VERSION: "0.9.x"
# This is the default version of Python to use in most steps which aren't specific # This is the default version of Python to use in most steps which aren't specific
DEFAULT_PYTHON_VERSION: "3.11" DEFAULT_PYTHON_VERSION: "3.11"
NLTK_DATA: "/usr/share/nltk_data"
jobs: jobs:
pre-commit: detect-duplicate:
# We want to run on external PRs, but not on our own internal PRs as they'll be run name: Detect Duplicate Run
# by the push to the branch. Without this if check, checks are duplicated since runs-on: ubuntu-24.04
# internal PRs match both the push and pull_request events. outputs:
if: should_run: ${{ steps.check.outputs.should_run }}
github.event_name == 'push' || github.event.pull_request.head.repo.full_name != steps:
github.repository - name: Check if workflow should run
id: check
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
if (context.eventName !== 'push') {
core.info('Not a push event; running workflow.');
core.setOutput('should_run', 'true');
return;
}
const ref = context.ref || '';
if (!ref.startsWith('refs/heads/')) {
core.info('Push is not to a branch; running workflow.');
core.setOutput('should_run', 'true');
return;
}
const branch = ref.substring('refs/heads/'.length);
const { owner, repo } = context.repo;
const prs = await github.paginate(github.rest.pulls.list, {
owner,
repo,
state: 'open',
head: `${owner}:${branch}`,
per_page: 100,
});
if (prs.length === 0) {
core.info(`No open PR found for ${branch}; running workflow.`);
core.setOutput('should_run', 'true');
} else {
core.info(`Found ${prs.length} open PR(s) for ${branch}; skipping duplicate push run.`);
core.setOutput('should_run', 'false');
}
pre-commit:
needs:
- detect-duplicate
if: needs.detect-duplicate.outputs.should_run == 'true'
name: Linting Checks name: Linting Checks
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- - name: Checkout repository
name: Checkout repository uses: actions/checkout@v6
uses: actions/checkout@v4 - name: Install python
- uses: actions/setup-python@v6
name: Install python
uses: actions/setup-python@v5
with: with:
python-version: ${{ env.DEFAULT_PYTHON_VERSION }} python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
- - name: Check files
name: Check files
uses: pre-commit/action@v3.0.1 uses: pre-commit/action@v3.0.1
documentation: documentation:
name: "Build & Deploy Documentation" name: "Build & Deploy Documentation"
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: needs:
- pre-commit - pre-commit
steps: steps:
- - name: Checkout
name: Checkout uses: actions/checkout@v6
uses: actions/checkout@v4 - name: Set up Python
-
name: Set up Python
id: setup-python id: setup-python
uses: actions/setup-python@v5 uses: actions/setup-python@v6
with: with:
python-version: ${{ env.DEFAULT_PYTHON_VERSION }} python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
- - name: Install uv
name: Install uv uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v5
with: with:
version: ${{ env.DEFAULT_UV_VERSION }} version: ${{ env.DEFAULT_UV_VERSION }}
enable-cache: true enable-cache: true
python-version: ${{ env.DEFAULT_PYTHON_VERSION }} python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
- - name: Install Python dependencies
name: Install Python dependencies
run: | run: |
uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen
- - name: Make documentation
name: Make documentation
run: | run: |
uv run \ uv run \
--python ${{ steps.setup-python.outputs.python-version }} \ --python ${{ steps.setup-python.outputs.python-version }} \
--dev \ --dev \
--frozen \ --frozen \
mkdocs build --config-file ./mkdocs.yml mkdocs build --config-file ./mkdocs.yml
- - name: Deploy documentation
name: Deploy documentation
if: github.event_name == 'push' && github.ref == 'refs/heads/main' if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: | run: |
echo "docs.paperless-ngx.com" > "${{ github.workspace }}/docs/CNAME" echo "docs.paperless-ngx.com" > "${{ github.workspace }}/docs/CNAME"
@ -88,14 +114,12 @@ jobs:
--dev \ --dev \
--frozen \ --frozen \
mkdocs gh-deploy --force --no-history mkdocs gh-deploy --force --no-history
- - name: Upload artifact
name: Upload artifact uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with: with:
name: documentation name: documentation
path: site/ path: site/
retention-days: 7 retention-days: 7
tests-backend: tests-backend:
name: "Backend Tests (Python ${{ matrix.python-version }})" name: "Backend Tests (Python ${{ matrix.python-version }})"
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
@ -106,50 +130,44 @@ jobs:
python-version: ['3.10', '3.11', '3.12'] python-version: ['3.10', '3.11', '3.12']
fail-fast: false fail-fast: false
steps: steps:
- - name: Checkout
name: Checkout uses: actions/checkout@v6
uses: actions/checkout@v4 - name: Start containers
-
name: Start containers
run: | run: |
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml pull --quiet docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml pull --quiet
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml up --detach docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml up --detach
- - name: Set up Python
name: Set up Python
id: setup-python id: setup-python
uses: actions/setup-python@v5 uses: actions/setup-python@v6
with: with:
python-version: "${{ matrix.python-version }}" python-version: "${{ matrix.python-version }}"
- - name: Install uv
name: Install uv uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v5
with: with:
version: ${{ env.DEFAULT_UV_VERSION }} version: ${{ env.DEFAULT_UV_VERSION }}
enable-cache: true enable-cache: true
python-version: ${{ steps.setup-python.outputs.python-version }} python-version: ${{ steps.setup-python.outputs.python-version }}
- - name: Install system dependencies
name: Install system dependencies
run: | run: |
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript libzbar0 poppler-utils sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript libzbar0 poppler-utils
- - name: Configure ImageMagick
name: Configure ImageMagick
run: | run: |
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml
- - name: Install Python dependencies
name: Install Python dependencies
run: | run: |
uv sync \ uv sync \
--python ${{ steps.setup-python.outputs.python-version }} \ --python ${{ steps.setup-python.outputs.python-version }} \
--group testing \ --group testing \
--frozen --frozen
- - name: List installed Python dependencies
name: List installed Python dependencies
run: | run: |
uv pip list uv pip list
- - name: Install or update NLTK dependencies
name: Tests run: uv run python -m nltk.downloader punkt punkt_tab snowball_data stopwords -d ${{ env.NLTK_DATA }}
- name: Tests
env: env:
NLTK_DATA: ${{ env.NLTK_DATA }}
PAPERLESS_CI_TEST: 1 PAPERLESS_CI_TEST: 1
# Enable paperless_mail testing against real server # Enable paperless_mail testing against real server
PAPERLESS_MAIL_TEST_HOST: ${{ secrets.TEST_MAIL_HOST }} PAPERLESS_MAIL_TEST_HOST: ${{ secrets.TEST_MAIL_HOST }}
@ -161,42 +179,36 @@ jobs:
--dev \ --dev \
--frozen \ --frozen \
pytest pytest
- - name: Upload backend test results to Codecov
name: Upload backend test results to Codecov
if: always() if: always()
uses: codecov/test-results-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: backend-python-${{ matrix.python-version }}
files: junit.xml
-
name: Upload backend coverage to Codecov
uses: codecov/codecov-action@v5 uses: codecov/codecov-action@v5
with: with:
token: ${{ secrets.CODECOV_TOKEN }} flags: backend-python-${{ matrix.python-version }}
files: junit.xml
report_type: test_results
- name: Upload backend coverage to Codecov
uses: codecov/codecov-action@v5
with:
flags: backend-python-${{ matrix.python-version }} flags: backend-python-${{ matrix.python-version }}
files: coverage.xml files: coverage.xml
- - name: Stop containers
name: Stop containers
if: always() if: always()
run: | run: |
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml logs docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml logs
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml down docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml down
install-frontend-dependencies: install-frontend-dependencies:
name: "Install Frontend Dependencies" name: "Install Frontend Dependencies"
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: needs:
- pre-commit - pre-commit
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
with: with:
version: 10 version: 10
- - name: Use Node.js 20
name: Use Node.js 20 uses: actions/setup-node@v6
uses: actions/setup-node@v4
with: with:
node-version: 20.x node-version: 20.x
cache: 'pnpm' cache: 'pnpm'
@ -209,17 +221,10 @@ jobs:
~/.pnpm-store ~/.pnpm-store
~/.cache ~/.cache
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }} key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
- - name: Install dependencies
name: Install dependencies
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
run: cd src-ui && pnpm install run: cd src-ui && pnpm install
-
name: Install Playwright
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
run: cd src-ui && pnpm playwright install --with-deps
tests-frontend: tests-frontend:
name: "Frontend Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})" name: "Frontend Unit Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})"
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: needs:
- install-frontend-dependencies - install-frontend-dependencies
@ -230,14 +235,13 @@ jobs:
shard-index: [1, 2, 3, 4] shard-index: [1, 2, 3, 4]
shard-count: [4] shard-count: [4]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
with: with:
version: 10 version: 10
- - name: Use Node.js 20
name: Use Node.js 20 uses: actions/setup-node@v6
uses: actions/setup-node@v4
with: with:
node-version: 20.x node-version: 20.x
cache: 'pnpm' cache: 'pnpm'
@ -252,52 +256,82 @@ jobs:
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }} key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
- name: Re-link Angular cli - name: Re-link Angular cli
run: cd src-ui && pnpm link @angular/cli run: cd src-ui && pnpm link @angular/cli
- - name: Linting checks
name: Linting checks
run: cd src-ui && pnpm run lint run: cd src-ui && pnpm run lint
- - name: Run Jest unit tests
name: Run Jest unit tests
run: cd src-ui && pnpm run test --max-workers=2 --shard=${{ matrix.shard-index }}/${{ matrix.shard-count }} run: cd src-ui && pnpm run test --max-workers=2 --shard=${{ matrix.shard-index }}/${{ matrix.shard-count }}
- - name: Upload frontend test results to Codecov
name: Run Playwright e2e tests
run: cd src-ui && pnpm exec playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }}
-
name: Upload frontend test results to Codecov
uses: codecov/test-results-action@v1
if: always() if: always()
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: frontend-node-${{ matrix.node-version }}
directory: src-ui/
-
name: Upload frontend coverage to Codecov
uses: codecov/codecov-action@v5 uses: codecov/codecov-action@v5
with: with:
token: ${{ secrets.CODECOV_TOKEN }} flags: frontend-node-${{ matrix.node-version }}
directory: src-ui/
report_type: test_results
- name: Upload frontend coverage to Codecov
uses: codecov/codecov-action@v5
with:
flags: frontend-node-${{ matrix.node-version }} flags: frontend-node-${{ matrix.node-version }}
directory: src-ui/coverage/ directory: src-ui/coverage/
tests-frontend-e2e:
name: "Frontend E2E Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})"
runs-on: ubuntu-24.04
container: mcr.microsoft.com/playwright:v1.57.0-noble
needs:
- install-frontend-dependencies
env:
PLAYWRIGHT_BROWSERS_PATH: /ms-playwright
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
strategy:
fail-fast: false
matrix:
node-version: [20.x]
shard-index: [1, 2]
shard-count: [2]
steps:
- uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Use Node.js 20
uses: actions/setup-node@v6
with:
node-version: 20.x
cache: 'pnpm'
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
- name: Cache frontend dependencies
id: cache-frontend-deps
uses: actions/cache@v4
with:
path: |
~/.pnpm-store
~/.cache
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
- name: Re-link Angular cli
run: cd src-ui && pnpm link @angular/cli
- name: Install dependencies
run: cd src-ui && pnpm install --no-frozen-lockfile
- name: Run Playwright e2e tests
run: cd src-ui && pnpm exec playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }}
frontend-bundle-analysis: frontend-bundle-analysis:
name: "Frontend Bundle Analysis" name: "Frontend Bundle Analysis"
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: needs:
- tests-frontend - tests-frontend
- tests-frontend-e2e
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- - name: Install pnpm
name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
with: with:
version: 10 version: 10
- - name: Use Node.js 20
name: Use Node.js 20 uses: actions/setup-node@v6
uses: actions/setup-node@v4
with: with:
node-version: 20.x node-version: 20.x
cache: 'pnpm' cache: 'pnpm'
cache-dependency-path: 'src-ui/pnpm-lock.yaml' cache-dependency-path: 'src-ui/pnpm-lock.yaml'
- - name: Cache frontend dependencies
name: Cache frontend dependencies
id: cache-frontend-deps id: cache-frontend-deps
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
@ -305,28 +339,42 @@ jobs:
~/.pnpm-store ~/.pnpm-store
~/.cache ~/.cache
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }} key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
- - name: Re-link Angular cli
name: Re-link Angular cli
run: cd src-ui && pnpm link @angular/cli run: cd src-ui && pnpm link @angular/cli
- - name: Build frontend and upload analysis
name: Build frontend and upload analysis
env: env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
run: cd src-ui && pnpm run build --configuration=production run: cd src-ui && pnpm run build --configuration=production
build-docker-image: build-docker-image:
name: Build Docker image for ${{ github.ref_name }} name: Build Docker image for ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }}
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || startsWith(github.ref, 'refs/heads/fix-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || contains(github.ref, 'beta.rc') || startsWith(github.ref, 'refs/tags/v')) if: (github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || startsWith(github.ref, 'refs/heads/fix-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || contains(github.ref, 'beta.rc') || startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/l10n_'))) || (github.event_name == 'pull_request' && (startsWith(github.head_ref, 'feature-') || startsWith(github.head_ref, 'fix-') || github.head_ref == 'dev' || github.head_ref == 'beta' || contains(github.head_ref, 'beta.rc') || startsWith(github.head_ref, 'l10n_')))
concurrency: concurrency:
group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }} group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }}
cancel-in-progress: true cancel-in-progress: true
needs: needs:
- tests-backend - tests-backend
- tests-frontend - tests-frontend
- tests-frontend-e2e
steps: steps:
- - name: Prepare build variables
name: Check pushing to Docker Hub id: build-vars
uses: actions/github-script@v8
with:
result-encoding: string
script: |
const isPR = context.eventName === 'pull_request';
const defaultRefName = context.ref.replace('refs/heads/', '');
const headRef = isPR ? context.payload.pull_request.head.ref : defaultRefName;
const buildRef = isPR ? `refs/heads/${headRef}` : context.ref;
const buildCacheKey = headRef.split('/').join('-');
const canPush = context.eventName === 'push' || (isPR && context.payload.pull_request.head.repo.full_name === `${context.repo.owner}/${context.repo.repo}`);
core.setOutput('build-ref', buildRef);
core.setOutput('build-ref-name', headRef);
core.setOutput('build-cache-key', buildCacheKey);
core.setOutput('can-push', canPush ? 'true' : 'false');
- name: Check pushing to Docker Hub
id: push-other-places id: push-other-places
# Only push to Dockerhub from the main repo AND the ref is either: # Only push to Dockerhub from the main repo AND the ref is either:
# main # main
@ -334,23 +382,24 @@ jobs:
# beta # beta
# a tag # a tag
# Otherwise forks would require a Docker Hub account and secrets setup # Otherwise forks would require a Docker Hub account and secrets setup
env:
BUILD_REF: ${{ steps.build-vars.outputs.build-ref }}
BUILD_REF_NAME: ${{ steps.build-vars.outputs.build-ref-name }}
run: | run: |
if [[ ${{ github.repository_owner }} == "paperless-ngx" && ( ${{ github.ref_name }} == "dev" || ${{ github.ref_name }} == "beta" || ${{ startsWith(github.ref, 'refs/tags/v') }} == "true" ) ]] ; then if [[ ${{ github.repository_owner }} == "paperless-ngx" && ( "$BUILD_REF_NAME" == "dev" || "$BUILD_REF_NAME" == "beta" || $BUILD_REF == refs/tags/v* || $BUILD_REF == *beta.rc* ) ]] ; then
echo "Enabling DockerHub image push" echo "Enabling DockerHub image push"
echo "enable=true" >> $GITHUB_OUTPUT echo "enable=true" >> $GITHUB_OUTPUT
else else
echo "Not pushing to DockerHub" echo "Not pushing to DockerHub"
echo "enable=false" >> $GITHUB_OUTPUT echo "enable=false" >> $GITHUB_OUTPUT
fi fi
- - name: Set ghcr repository name
name: Set ghcr repository name
id: set-ghcr-repository id: set-ghcr-repository
run: | run: |
ghcr_name=$(echo "${{ github.repository }}" | awk '{ print tolower($0) }') ghcr_name=$(echo "${{ github.repository }}" | awk '{ print tolower($0) }')
echo "Name is ${ghcr_name}" echo "Name is ${ghcr_name}"
echo "ghcr-repository=${ghcr_name}" >> $GITHUB_OUTPUT echo "ghcr-repository=${ghcr_name}" >> $GITHUB_OUTPUT
- - name: Gather Docker metadata
name: Gather Docker metadata
id: docker-meta id: docker-meta
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
@ -361,41 +410,37 @@ jobs:
tags: | tags: |
# Tag branches with branch name # Tag branches with branch name
type=ref,event=branch type=ref,event=branch
# Pull requests need a sanitized branch tag for pushing images
type=raw,value=${{ steps.build-vars.outputs.build-cache-key }},enable=${{ github.event_name == 'pull_request' }}
# Process semver tags # Process semver tags
# For a tag x.y.z or vX.Y.Z, output an x.y.z and x.y image tag # For a tag x.y.z or vX.Y.Z, output an x.y.z and x.y image tag
type=semver,pattern={{version}} type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}}.{{minor}}
- - name: Checkout
name: Checkout uses: actions/checkout@v6
uses: actions/checkout@v4
# If https://github.com/docker/buildx/issues/1044 is resolved, # If https://github.com/docker/buildx/issues/1044 is resolved,
# the append input with a native arm64 arch could be used to # the append input with a native arm64 arch could be used to
# significantly speed up building # significantly speed up building
- - name: Set up Docker Buildx
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- - name: Set up QEMU
name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v3
with: with:
platforms: arm64 platforms: arm64
- - name: Login to GitHub Container Registry
name: Login to GitHub Container Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- - name: Login to Docker Hub
name: Login to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v3
# Don't attempt to login if not pushing to Docker Hub # Don't attempt to login if not pushing to Docker Hub
if: steps.push-other-places.outputs.enable == 'true' if: steps.push-other-places.outputs.enable == 'true'
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Login to Quay.io
name: Login to Quay.io
uses: docker/login-action@v3 uses: docker/login-action@v3
# Don't attempt to login if not pushing to Quay.io # Don't attempt to login if not pushing to Quay.io
if: steps.push-other-places.outputs.enable == 'true' if: steps.push-other-places.outputs.enable == 'true'
@ -403,14 +448,13 @@ jobs:
registry: quay.io registry: quay.io
username: ${{ secrets.QUAY_USERNAME }} username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_ROBOT_TOKEN }} password: ${{ secrets.QUAY_ROBOT_TOKEN }}
- - name: Build and push
name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }} push: ${{ steps.build-vars.outputs.can-push == 'true' }}
tags: ${{ steps.docker-meta.outputs.tags }} tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker-meta.outputs.labels }} labels: ${{ steps.docker-meta.outputs.labels }}
build-args: | build-args: |
@ -418,91 +462,79 @@ jobs:
# Get cache layers from this branch, then dev # Get cache layers from this branch, then dev
# This allows new branches to get at least some cache benefits, generally from dev # This allows new branches to get at least some cache benefits, generally from dev
cache-from: | cache-from: |
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:${{ github.ref_name }} type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:${{ steps.build-vars.outputs.build-cache-key }}
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:dev type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:dev
cache-to: | cache-to: ${{ steps.build-vars.outputs.can-push == 'true' && format('type=registry,mode=max,ref=ghcr.io/{0}/builder/cache/app:{1}', steps.set-ghcr-repository.outputs.ghcr-repository, steps.build-vars.outputs.build-cache-key) || '' }}
type=registry,mode=max,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:${{ github.ref_name }} - name: Inspect image
- if: steps.build-vars.outputs.can-push == 'true'
name: Inspect image
run: | run: |
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }} docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
- - name: Export frontend artifact from docker
name: Export frontend artifact from docker if: steps.build-vars.outputs.can-push == 'true'
run: | run: |
docker create --name frontend-extract ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }} docker create --name frontend-extract ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
docker cp frontend-extract:/usr/src/paperless/src/documents/static/frontend src/documents/static/frontend/ docker cp frontend-extract:/usr/src/paperless/src/documents/static/frontend src/documents/static/frontend/
- - name: Upload frontend artifact
name: Upload frontend artifact if: steps.build-vars.outputs.can-push == 'true'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: frontend-compiled name: frontend-compiled
path: src/documents/static/frontend/ path: src/documents/static/frontend/
retention-days: 7 retention-days: 7
build-release: build-release:
name: "Build Release" name: "Build Release"
needs: needs:
- build-docker-image - build-docker-image
- documentation - documentation
if: github.event_name == 'push'
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- - name: Checkout
name: Checkout uses: actions/checkout@v6
uses: actions/checkout@v4 - name: Set up Python
-
name: Set up Python
id: setup-python id: setup-python
uses: actions/setup-python@v5 uses: actions/setup-python@v6
with: with:
python-version: ${{ env.DEFAULT_PYTHON_VERSION }} python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
- - name: Install uv
name: Install uv uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v5
with: with:
version: ${{ env.DEFAULT_UV_VERSION }} version: ${{ env.DEFAULT_UV_VERSION }}
enable-cache: true enable-cache: true
python-version: ${{ steps.setup-python.outputs.python-version }} python-version: ${{ steps.setup-python.outputs.python-version }}
- - name: Install Python dependencies
name: Install Python dependencies
run: | run: |
uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen
- - name: Install system dependencies
name: Install system dependencies
run: | run: |
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qq --no-install-recommends gettext liblept5 sudo apt-get install -qq --no-install-recommends gettext liblept5
- - name: Download frontend artifact
name: Download frontend artifact uses: actions/download-artifact@v6
uses: actions/download-artifact@v4
with: with:
name: frontend-compiled name: frontend-compiled
path: src/documents/static/frontend/ path: src/documents/static/frontend/
- - name: Download documentation artifact
name: Download documentation artifact uses: actions/download-artifact@v6
uses: actions/download-artifact@v4
with: with:
name: documentation name: documentation
path: docs/_build/html/ path: docs/_build/html/
- - name: Generate requirements file
name: Generate requirements file
run: | run: |
uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt
- - name: Compile messages
name: Compile messages
run: | run: |
cd src/ cd src/
uv run \ uv run \
--python ${{ steps.setup-python.outputs.python-version }} \ --python ${{ steps.setup-python.outputs.python-version }} \
manage.py compilemessages manage.py compilemessages
- - name: Collect static files
name: Collect static files
run: | run: |
cd src/ cd src/
uv run \ uv run \
--python ${{ steps.setup-python.outputs.python-version }} \ --python ${{ steps.setup-python.outputs.python-version }} \
manage.py collectstatic --no-input manage.py collectstatic --no-input
- - name: Move files
name: Move files
run: | run: |
echo "Making dist folders" echo "Making dist folders"
for directory in dist \ for directory in dist \
@ -539,21 +571,18 @@ jobs:
cp --recursive docs/_build/html/ dist/paperless-ngx/docs cp --recursive docs/_build/html/ dist/paperless-ngx/docs
mv --verbose static dist/paperless-ngx mv --verbose static dist/paperless-ngx
- - name: Make release package
name: Make release package
run: | run: |
echo "Creating release archive" echo "Creating release archive"
cd dist cd dist
sudo chown -R 1000:1000 paperless-ngx/ sudo chown -R 1000:1000 paperless-ngx/
tar -cJf paperless-ngx.tar.xz paperless-ngx/ tar -cJf paperless-ngx.tar.xz paperless-ngx/
- - name: Upload release artifact
name: Upload release artifact uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with: with:
name: release name: release
path: dist/paperless-ngx.tar.xz path: dist/paperless-ngx.tar.xz
retention-days: 7 retention-days: 7
publish-release: publish-release:
name: "Publish Release" name: "Publish Release"
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
@ -565,14 +594,12 @@ jobs:
- build-release - build-release
if: github.ref_type == 'tag' && (startsWith(github.ref_name, 'v') || contains(github.ref_name, '-beta.rc')) if: github.ref_type == 'tag' && (startsWith(github.ref_name, 'v') || contains(github.ref_name, '-beta.rc'))
steps: steps:
- - name: Download release artifact
name: Download release artifact uses: actions/download-artifact@v6
uses: actions/download-artifact@v4
with: with:
name: release name: release
path: ./ path: ./
- - name: Get version
name: Get version
id: get_version id: get_version
run: | run: |
echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
@ -581,8 +608,7 @@ jobs:
else else
echo "prerelease=false" >> $GITHUB_OUTPUT echo "prerelease=false" >> $GITHUB_OUTPUT
fi fi
- - name: Create Release and Changelog
name: Create Release and Changelog
id: create-release id: create-release
uses: release-drafter/release-drafter@v6 uses: release-drafter/release-drafter@v6
with: with:
@ -593,8 +619,7 @@ jobs:
publish: true # ensures release is not marked as draft publish: true # ensures release is not marked as draft
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- - name: Upload release archive
name: Upload release archive
id: upload-release-asset id: upload-release-asset
uses: shogo82148/actions-upload-release-asset@v1 uses: shogo82148/actions-upload-release-asset@v1
with: with:
@ -603,7 +628,6 @@ jobs:
asset_path: ./paperless-ngx.tar.xz asset_path: ./paperless-ngx.tar.xz
asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz
asset_content_type: application/x-xz asset_content_type: application/x-xz
append-changelog: append-changelog:
name: "Append Changelog" name: "Append Changelog"
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
@ -611,26 +635,22 @@ jobs:
- publish-release - publish-release
if: needs.publish-release.outputs.prerelease == 'false' if: needs.publish-release.outputs.prerelease == 'false'
steps: steps:
- - name: Checkout
name: Checkout uses: actions/checkout@v6
uses: actions/checkout@v4
with: with:
ref: main ref: main
- - name: Set up Python
name: Set up Python
id: setup-python id: setup-python
uses: actions/setup-python@v5 uses: actions/setup-python@v6
with: with:
python-version: ${{ env.DEFAULT_PYTHON_VERSION }} python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
- - name: Install uv
name: Install uv uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v5
with: with:
version: ${{ env.DEFAULT_UV_VERSION }} version: ${{ env.DEFAULT_UV_VERSION }}
enable-cache: true enable-cache: true
python-version: ${{ env.DEFAULT_PYTHON_VERSION }} python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
- - name: Append Changelog to docs
name: Append Changelog to docs
id: append-Changelog id: append-Changelog
working-directory: docs working-directory: docs
run: | run: |
@ -652,9 +672,8 @@ jobs:
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git commit -am "Changelog ${{ needs.publish-release.outputs.version }} - GHA" git commit -am "Changelog ${{ needs.publish-release.outputs.version }} - GHA"
git push origin ${{ needs.publish-release.outputs.version }}-changelog git push origin ${{ needs.publish-release.outputs.version }}-changelog
- - name: Create Pull Request
name: Create Pull Request uses: actions/github-script@v8
uses: actions/github-script@v7
with: with:
script: | script: |
const { repo, owner } = context.repo; const { repo, owner } = context.repo;

View File

@ -4,19 +4,14 @@
# Requires a PAT with the correct scope set in the secrets. # Requires a PAT with the correct scope set in the secrets.
# #
# This workflow will not trigger runs on forked repos. # This workflow will not trigger runs on forked repos.
name: Cleanup Image Tags name: Cleanup Image Tags
on: on:
delete: workflow_dispatch:
push: schedule:
paths: - cron: '0 0 * * 0'
- ".github/workflows/cleanup-tags.yml"
concurrency: concurrency:
group: registry-tags-cleanup group: registry-tags-cleanup
cancel-in-progress: false cancel-in-progress: false
jobs: jobs:
cleanup-images: cleanup-images:
name: Cleanup Image Tags for ${{ matrix.primary-name }} name: Cleanup Image Tags for ${{ matrix.primary-name }}
@ -30,10 +25,9 @@ jobs:
# Requires a personal access token with the OAuth scope delete:packages # Requires a personal access token with the OAuth scope delete:packages
TOKEN: ${{ secrets.GHA_CONTAINER_DELETE_TOKEN }} TOKEN: ${{ secrets.GHA_CONTAINER_DELETE_TOKEN }}
steps: steps:
- - name: Clean temporary images
name: Clean temporary images
if: "${{ env.TOKEN != '' }}" if: "${{ env.TOKEN != '' }}"
uses: stumpylog/image-cleaner-action/ephemeral@v0.10.0 uses: stumpylog/image-cleaner-action/ephemeral@v0.12.0
with: with:
token: "${{ env.TOKEN }}" token: "${{ env.TOKEN }}"
owner: "${{ github.repository_owner }}" owner: "${{ github.repository_owner }}"
@ -43,7 +37,6 @@ jobs:
repo_name: "paperless-ngx" repo_name: "paperless-ngx"
match_regex: "(feature|fix)" match_regex: "(feature|fix)"
do_delete: "true" do_delete: "true"
cleanup-untagged-images: cleanup-untagged-images:
name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }} name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }}
if: github.repository_owner == 'paperless-ngx' if: github.repository_owner == 'paperless-ngx'
@ -58,10 +51,9 @@ jobs:
# Requires a personal access token with the OAuth scope delete:packages # Requires a personal access token with the OAuth scope delete:packages
TOKEN: ${{ secrets.GHA_CONTAINER_DELETE_TOKEN }} TOKEN: ${{ secrets.GHA_CONTAINER_DELETE_TOKEN }}
steps: steps:
- - name: Clean untagged images
name: Clean untagged images
if: "${{ env.TOKEN != '' }}" if: "${{ env.TOKEN != '' }}"
uses: stumpylog/image-cleaner-action/untagged@v0.10.0 uses: stumpylog/image-cleaner-action/untagged@v0.12.0
with: with:
token: "${{ env.TOKEN }}" token: "${{ env.TOKEN }}"
owner: "${{ github.repository_owner }}" owner: "${{ github.repository_owner }}"

View File

@ -10,7 +10,6 @@
# supported CodeQL languages. # supported CodeQL languages.
# #
name: "CodeQL" name: "CodeQL"
on: on:
push: push:
branches: [main, dev] branches: [main, dev]
@ -19,7 +18,6 @@ on:
branches: [dev] branches: [dev]
schedule: schedule:
- cron: '28 13 * * 5' - cron: '28 13 * * 5'
jobs: jobs:
analyze: analyze:
name: Analyze name: Analyze
@ -28,27 +26,23 @@ jobs:
actions: read actions: read
contents: read contents: read
security-events: write security-events: write
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
language: ['javascript', 'python'] language: ['javascript', 'python']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support # Learn more about CodeQL language support at https://git.io/codeql-language-support
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v4
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file. # By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file. # Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main # queries: ./path/to/local/query, your-org/your-repo/queries@main
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v4

View File

@ -1,26 +1,21 @@
name: Crowdin Action name: Crowdin Action
on: on:
workflow_dispatch: workflow_dispatch:
schedule: schedule:
- cron: '2 */12 * * *' - cron: '2 */12 * * *'
push: push:
paths: [ paths: ['src/locale/**', 'src-ui/messages.xlf', 'src-ui/src/locale/**']
'src/locale/**',
'src-ui/messages.xlf',
'src-ui/src/locale/**'
]
branches: [dev] branches: [dev]
jobs: jobs:
synchronize-with-crowdin: synchronize-with-crowdin:
name: Crowdin Sync name: Crowdin Sync
if: github.repository_owner == 'paperless-ngx' if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v6
with:
token: ${{ secrets.PNGX_BOT_PAT }}
- name: crowdin action - name: crowdin action
uses: crowdin/github-action@v2 uses: crowdin/github-action@v2
with: with:

112
.github/workflows/pr-bot.yml vendored Normal file
View File

@ -0,0 +1,112 @@
name: PR Bot
on:
pull_request_target:
types: [opened]
permissions:
contents: read
pull-requests: write
jobs:
pr-bot:
name: Automated PR Bot
runs-on: ubuntu-latest
steps:
- name: Label PR by file path or branch name
# see .github/labeler.yml for the labeler config
uses: actions/labeler@v6
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Label by size
uses: Gascon1/pr-size-labeler@v1.3.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
xs_label: 'small-change'
xs_diff: '9'
s_label: 'non-trivial'
s_diff: '99999'
fail_if_xl: 'false'
excluded_files: /\.lock$/ /\.txt$/ ^src-ui/pnpm-lock\.yaml$ ^src-ui/messages\.xlf$ ^src/locale/en_US/LC_MESSAGES/django\.po$
- name: Label by PR title
uses: actions/github-script@v8
with:
script: |
const pr = context.payload.pull_request;
const title = pr.title.toLowerCase();
const labels = [];
if (/^(fix|bugfix)/i.test(title)) {
labels.push('bug');
} else if (/^feature/i.test(title)) {
labels.push('enhancement');
} else if (!/^(dependabot)/i.test(title) && !/^(chore)/i.test(title)) {
labels.push('enhancement'); // Default fallback
}
if (labels.length) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
labels,
});
core.info(`Added labels based on title: ${labels.join(', ')}`);
}
- name: Label bot-generated PRs
if: ${{ contains(github.actor, 'dependabot') || contains(github.actor, 'crowdin-bot') }}
uses: actions/github-script@v8
with:
script: |
const pr = context.payload.pull_request;
const user = pr.user.login.toLowerCase();
const labels = [];
if (user.includes('dependabot')) {
labels.push('dependencies');
}
if (user.includes('crowdin-bot')) {
labels.push('translation', 'skip-changelog');
}
if (labels.length) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
labels,
});
}
- name: Welcome comment
if: ${{ !contains(github.actor, 'bot') }}
uses: actions/github-script@v8
with:
script: |
const pr = context.payload.pull_request;
const user = pr.user.login;
const { data: members } = await github.rest.orgs.listMembers({
org: 'paperless-ngx',
});
const memberLogins = members.map(m => m.login.toLowerCase());
if (memberLogins.includes(user.toLowerCase())) {
core.info('Skipping comment: user is org member');
return;
}
const body =
"Hello @" + user + ",\n\n" +
"Thank you very much for submitting this PR to us!\n\n" +
"This is what will happen next:\n\n" +
"1. CI tests will run against your PR to ensure quality and consistency.\n" +
"2. Next, human contributors from paperless-ngx review your changes.\n" +
"3. Please address any issues that come up during the review as soon as you are able to.\n" +
"4. If accepted, your pull request will be merged into the `dev` branch and changes there will be tested further.\n" +
"5. Eventually, changes from you and other contributors will be merged into `main` and a new release will be made.\n\n" +
"You'll be hearing from us soon, and thank you again for contributing to our project.";
await github.rest.issues.createComment({
issue_number: pr.number,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});

View File

@ -1,5 +1,4 @@
name: Project Automations name: Project Automations
on: on:
pull_request_target: #_target allows access to secrets pull_request_target: #_target allows access to secrets
types: types:
@ -8,10 +7,8 @@ on:
branches: branches:
- main - main
- dev - dev
permissions: permissions:
contents: read contents: read
jobs: jobs:
pr_opened_or_reopened: pr_opened_or_reopened:
name: pr_opened_or_reopened name: pr_opened_or_reopened

View File

@ -1,35 +1,37 @@
name: 'Repository Maintenance' name: 'Repository Maintenance'
on: on:
schedule: schedule:
- cron: '0 3 * * *' - cron: '0 3 * * *'
workflow_dispatch: workflow_dispatch:
permissions: permissions:
issues: write issues: write
pull-requests: write pull-requests: write
discussions: write discussions: write
concurrency: concurrency:
group: lock group: lock
jobs: jobs:
stale: stale:
name: 'Stale' name: 'Stale'
if: github.repository_owner == 'paperless-ngx' if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@v10
with: with:
days-before-stale: 7 days-before-stale: 7
days-before-close: 14 days-before-close: 14
any-of-labels: 'stale,cant-reproduce,not a bug' any-of-issue-labels: 'cant-reproduce,not a bug'
stale-issue-label: stale stale-issue-label: stale
stale-pr-label: stale
stale-issue-message: > stale-issue-message: >
This issue has been automatically marked as stale because it has not had This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details. days-before-pr-stale: 14
days-before-pr-close: 7
stale-pr-message: ""
stale-pr-label: stale
exempt-pr-labels: 'notable'
close-pr-message: >
This pull request has been automatically closed because it has not had recent activity. Thank you for your contributions. Please open a new pull request or discussion if you would like to continue working on this change.
lock-threads: lock-threads:
name: 'Lock Old Threads' name: 'Lock Old Threads'
if: github.repository_owner == 'paperless-ngx' if: github.repository_owner == 'paperless-ngx'
@ -42,26 +44,20 @@ jobs:
discussion-inactive-days: '30' discussion-inactive-days: '30'
log-output: true log-output: true
issue-comment: > issue-comment: >
This issue has been automatically locked since there This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion or issue for related concerns. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
has not been any recent activity after it was closed.
Please open a new discussion or issue for related concerns.
See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
pr-comment: > pr-comment: >
This pull request has been automatically locked since there This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion or issue for related concerns. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
has not been any recent activity after it was closed.
Please open a new discussion or issue for related concerns.
See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
discussion-comment: > discussion-comment: >
This discussion has been automatically locked since there This discussion has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion for related concerns. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
has not been any recent activity after it was closed.
Please open a new discussion for related concerns.
See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
close-answered-discussions: close-answered-discussions:
name: 'Close Answered Discussions' name: 'Close Answered Discussions'
if: github.repository_owner == 'paperless-ngx' if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/github-script@v7 - uses: actions/github-script@v8
with: with:
script: | script: |
function sleep(ms) { function sleep(ms) {
@ -118,7 +114,7 @@ jobs:
if: github.repository_owner == 'paperless-ngx' if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/github-script@v7 - uses: actions/github-script@v8
with: with:
script: | script: |
function sleep(ms) { function sleep(ms) {
@ -210,7 +206,7 @@ jobs:
if: github.repository_owner == 'paperless-ngx' if: github.repository_owner == 'paperless-ngx'
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/github-script@v7 - uses: actions/github-script@v8
with: with:
script: | script: |
function sleep(ms) { function sleep(ms) {
@ -245,6 +241,7 @@ jobs:
) { ) {
nodes { nodes {
id, id,
createdAt,
number, number,
updatedAt, updatedAt,
upvoteCount, upvoteCount,

69
.github/workflows/translate-strings.yml vendored Normal file
View File

@ -0,0 +1,69 @@
name: Generate Translation Strings
on:
push:
branches:
- dev
jobs:
generate-translate-strings:
name: Generate Translation Strings
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
token: ${{ secrets.PNGX_BOT_PAT }}
ref: ${{ github.head_ref }}
- name: Set up Python
id: setup-python
uses: actions/setup-python@v6
- name: Install system dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -qq --no-install-recommends gettext
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Install backend python dependencies
run: |
uv sync \
--group dev \
--frozen
- name: Generate backend translation strings
run: cd src/ && uv run manage.py makemessages -l en_US -i "samples*"
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Use Node.js 20
uses: actions/setup-node@v6
with:
node-version: 20.x
cache: 'pnpm'
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
- name: Cache frontend dependencies
id: cache-frontend-deps
uses: actions/cache@v4
with:
path: |
~/.pnpm-store
~/.cache
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
- name: Install frontend dependencies
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
run: cd src-ui && pnpm install
- name: Re-link Angular cli
run: cd src-ui && pnpm link @angular/cli
- name: Generate frontend translation strings
run: |
cd src-ui
pnpm run ng extract-i18n
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v7
with:
file_pattern: 'src-ui/messages.xlf src/locale/en_US/LC_MESSAGES/django.po'
commit_message: "Auto translate strings"
commit_user_name: "GitHub Actions"
commit_author: "GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>"

3
.gitignore vendored
View File

@ -107,3 +107,6 @@ celerybeat-schedule*
/.devcontainer/data/ /.devcontainer/data/
/.devcontainer/media/ /.devcontainer/media/
/.devcontainer/redisdata/ /.devcontainer/redisdata/
# ignore pnpm package store folder created when setting up the devcontainer
.pnpm-store/

View File

@ -1,11 +1,10 @@
# This file configures pre-commit hooks. # This file configures pre-commit hooks.
# See https://pre-commit.com/ for general information # See https://pre-commit.com/ for general information
# See https://pre-commit.com/hooks.html for a listing of possible hooks # See https://pre-commit.com/hooks.html for a listing of possible hooks
repos: repos:
# General hooks # General hooks
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0 rev: v6.0.0
hooks: hooks:
- id: check-docstring-first - id: check-docstring-first
- id: check-json - id: check-json
@ -19,7 +18,7 @@ repos:
exclude_types: exclude_types:
- svg - svg
- pofile - pofile
exclude: "(^LICENSE$)" exclude: "(^LICENSE$|^src/documents/static/bootstrap.min.css$)"
- id: mixed-line-ending - id: mixed-line-ending
args: args:
- "--fix=lf" - "--fix=lf"
@ -29,16 +28,16 @@ repos:
- id: check-case-conflict - id: check-case-conflict
- id: detect-private-key - id: detect-private-key
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.4.0 rev: v2.4.1
hooks: hooks:
- id: codespell - id: codespell
exclude: "(^src-ui/src/locale/)|(^src-ui/pnpm-lock.yaml)|(^src-ui/e2e/)|(^src/paperless_mail/tests/samples/)" additional_dependencies: [tomli]
exclude_types: exclude_types:
- pofile - pofile
- json - json
# See https://github.com/prettier/prettier/issues/15742 for the fork reason # See https://github.com/prettier/prettier/issues/15742 for the fork reason
- repo: https://github.com/rbubley/mirrors-prettier - repo: https://github.com/rbubley/mirrors-prettier
rev: 'v3.3.3' rev: 'v3.6.2'
hooks: hooks:
- id: prettier - id: prettier
types_or: types_or:
@ -50,29 +49,36 @@ repos:
- 'prettier-plugin-organize-imports@4.1.0' - 'prettier-plugin-organize-imports@4.1.0'
# Python hooks # Python hooks
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.9 rev: v0.14.5
hooks: hooks:
- id: ruff - id: ruff-check
- id: ruff-format - id: ruff-format
- repo: https://github.com/tox-dev/pyproject-fmt - repo: https://github.com/tox-dev/pyproject-fmt
rev: "v2.5.1" rev: "v2.11.1"
hooks: hooks:
- id: pyproject-fmt - id: pyproject-fmt
# Dockerfile hooks # Dockerfile hooks
- repo: https://github.com/AleksaC/hadolint-py - repo: https://github.com/AleksaC/hadolint-py
rev: v2.12.0.3 rev: v2.14.0
hooks: hooks:
- id: hadolint - id: hadolint
# Shell script hooks # Shell script hooks
- repo: https://github.com/lovesegfault/beautysh - repo: https://github.com/lovesegfault/beautysh
rev: v6.2.1 rev: v6.4.2
hooks: hooks:
- id: beautysh - id: beautysh
additional_dependencies: types: [file]
- setuptools files: (\.sh$|/run$|/finish$)
args: args:
- "--tab" - "--tab"
- repo: https://github.com/shellcheck-py/shellcheck-py - repo: https://github.com/shellcheck-py/shellcheck-py
rev: "v0.10.0.1" rev: "v0.11.0.1"
hooks: hooks:
- id: shellcheck - id: shellcheck
- repo: https://github.com/google/yamlfmt
rev: v0.20.0
hooks:
- id: yamlfmt
exclude: "^src-ui/pnpm-lock.yaml"
types:
- yaml

1
.yamlfmt Normal file
View File

@ -0,0 +1 @@
line_ending: lf

View File

@ -2,9 +2,11 @@
If you feel like contributing to the project, please do! Bug fixes and improvements are always welcome. If you feel like contributing to the project, please do! Bug fixes and improvements are always welcome.
⚠️ Please note: Pull requests that implement a new feature or enhancement _should almost always target an existing feature request_ with evidence of community interest and discussion. This is in order to balance the work of implementing and maintaining new features / enhancements. Pull requests that are opened without meeting this requirement may not be merged.
If you want to implement something big: If you want to implement something big:
- Please start a discussion about that in the issues! Maybe something similar is already in development and we can make it happen together. - As above, please start with a discussion! Maybe something similar is already in development and we can make it happen together.
- When making additions to the project, consider if the majority of users will benefit from your change. If not, you're probably better of forking the project. - When making additions to the project, consider if the majority of users will benefit from your change. If not, you're probably better of forking the project.
- Also consider if your change will get in the way of other users. A good change is a change that enhances the experience of some users who want that change and does not affect users who do not care about the change. - Also consider if your change will get in the way of other users. A good change is a change that enhances the experience of some users who want that change and does not affect users who do not care about the change.
- Please see the [paperless-ngx merge process](#merging-prs) below. - Please see the [paperless-ngx merge process](#merging-prs) below.
@ -37,6 +39,8 @@ Before you can run `pytest`, ensure to [properly set up your local environment](
Once you have submitted a **P**ull **R**equest it will be reviewed, approved, and merged by one or more community members of any team. Automated code tests and formatting checks must be passed. Once you have submitted a **P**ull **R**equest it will be reviewed, approved, and merged by one or more community members of any team. Automated code tests and formatting checks must be passed.
Important: Pull requests that implement a new feature or enhancement _should almost always target an existing feature request_ with evidence of community interest and discussion. This is in order to balance the work of implementing and maintaining new features / enhancements. Instead of opening a PR which does not meet this requirement, please open a feature request instead, to gather feedback from both users and the project maintainers.
## Non-Trivial Requests ## Non-Trivial Requests
PRs deemed `non-trivial` will go through a stricter review process before being merged into `dev`. This is to ensure code quality and complete functionality (free of side effects). PRs deemed `non-trivial` will go through a stricter review process before being merged into `dev`. This is to ensure code quality and complete functionality (free of side effects).
@ -109,28 +113,12 @@ Paperless-ngx is a community project. We do our best to delegate permission and
## Structure ## Structure
As of writing, there are 21 members in paperless-ngx. 4 of these people have complete administrative privileges to the repo: There are currently 2 members in paperless-ngx with complete administrative privileges to the repo:
- [@shamoon](https://github.com/shamoon) - [@shamoon](https://github.com/shamoon)
- [@bauerj](https://github.com/bauerj) - [@stumpylog](https://github.com/stumpylog)
- [@qcasey](https://github.com/qcasey)
- [@FrankStrieter](https://github.com/FrankStrieter)
There are 5 teams collaborating on specific tasks within paperless-ngx: There are other members who occasionally contribute but we are actively seeking more dedicated maintainers of the project. Please reach out if you are interested.
- @paperless-ngx/backend (Python / django)
- @paperless-ngx/frontend (JavaScript / Typescript)
- @paperless-ngx/ci-cd (GitHub Actions / Deployment)
- @paperless-ngx/issues (Issue triage)
- @paperless-ngx/test (General testing for larger PRs)
## Permissions
All team members are notified when mentioned or assigned to a relevant issue or pull request. Additionally, each team has slightly different access to paperless-ngx:
- The **test** team has no special permissions.
- The **issues** team has `triage` access. This means they can organize issues and pull requests.
- The **backend**, **frontend**, and **ci-cd** teams have `write` access. This means they can approve PRs and push code, containers, releases, and more.
## Joining ## Joining
@ -141,13 +129,13 @@ The admins occasionally invite contributors directly if we believe having them o
# Automatic Repository Maintenance # Automatic Repository Maintenance
The Paperless-ngx team appreciates all effort and interest from the community in filing bug reports, creating feature requests, sharing ideas and helping other The Paperless-ngx team appreciates all effort and interest from the community in filing bug reports, creating feature requests, sharing ideas and helping other
community members. That said, in an effort to keep the repository organized and managebale the project uses automatic handling of certain areas: community members. That said, in an effort to keep the repository organized and manageable the project uses automatic handling of certain areas:
- Issues that cannot be reproduced will be marked 'stale' after 7 days of inactivity and closed after 14 further days of inactivity. - Issues that cannot be reproduced will be marked 'stale' after 7 days of inactivity and closed after 14 further days of inactivity.
- Issues, pull requests and discussions that are closed will be locked after 30 days of inactivity. - Issues, pull requests and discussions that are closed will be locked after 30 days of inactivity.
- Discussions with a marked answer will be automatically closed. - Discussions with a marked answer will be automatically closed.
- Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity. - Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity.
- Feature requests that do not meet the following thresholds will be closed: 180 days of inactivity, < 5 "up-votes" after 180 days, < 20 "up-votes" after 1 year or < 80 "up-votes" at 2 years. - Feature requests that do not meet the following thresholds will be closed: 180 days of inactivity with less than 80 "up-votes", < 5 "up-votes" after 180 days, < 20 "up-votes" after 1 year or < 40 "up-votes" at 2 years.
In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns. In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns.
Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features. Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features.

View File

@ -5,7 +5,7 @@
# Purpose: Compiles the frontend # Purpose: Compiles the frontend
# Notes: # Notes:
# - Does PNPM stuff with Typescript and such # - Does PNPM stuff with Typescript and such
FROM --platform=$BUILDPLATFORM docker.io/node:20-bookworm-slim AS compile-frontend FROM --platform=$BUILDPLATFORM docker.io/node:20-trixie-slim AS compile-frontend
COPY ./src-ui /src/src-ui COPY ./src-ui /src/src-ui
@ -21,7 +21,7 @@ ARG PNGX_TAG_VERSION=
RUN set -eux && \ RUN set -eux && \
case "${PNGX_TAG_VERSION}" in \ case "${PNGX_TAG_VERSION}" in \
dev|beta|fix*|feature*) \ dev|beta|fix*|feature*) \
sed -i -E "s/version: '([0-9\.]+)'/version: '\1 #${PNGX_TAG_VERSION}'/g" /src/src-ui/src/environments/environment.prod.ts \ sed -i -E "s/tag: '([a-z\.]+)'/tag: '${PNGX_TAG_VERSION}'/g" /src/src-ui/src/environments/environment.prod.ts \
;; \ ;; \
esac esac
@ -32,7 +32,7 @@ RUN set -eux \
# Purpose: Installs s6-overlay and rootfs # Purpose: Installs s6-overlay and rootfs
# Comments: # Comments:
# - Don't leave anything extra in here either # - Don't leave anything extra in here either
FROM ghcr.io/astral-sh/uv:0.6.13-python3.12-bookworm-slim AS s6-overlay-base FROM ghcr.io/astral-sh/uv:0.9.15-python3.12-trixie-slim AS s6-overlay-base
WORKDIR /usr/src/s6 WORKDIR /usr/src/s6
@ -47,7 +47,7 @@ ENV \
ARG TARGETARCH ARG TARGETARCH
ARG TARGETVARIANT ARG TARGETVARIANT
# Lock this version # Lock this version
ARG S6_OVERLAY_VERSION=3.2.0.2 ARG S6_OVERLAY_VERSION=3.2.1.0
ARG S6_BUILD_TIME_PKGS="curl \ ARG S6_BUILD_TIME_PKGS="curl \
xz-utils" xz-utils"
@ -102,8 +102,6 @@ ARG TARGETARCH
# Can be workflow provided, defaults set for manual building # Can be workflow provided, defaults set for manual building
ARG JBIG2ENC_VERSION=0.30 ARG JBIG2ENC_VERSION=0.30
ARG QPDF_VERSION=11.9.0
ARG GS_VERSION=10.03.1
# Set Python environment variables # Set Python environment variables
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONDONTWRITEBYTECODE=1 \
@ -170,20 +168,8 @@ RUN set -eux \
&& apt-get update \ && apt-get update \
&& apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \ && apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \
&& echo "Installing pre-built updates" \ && echo "Installing pre-built updates" \
&& curl --fail --silent --no-progress-meter --show-error --location --remote-name-all --parallel --parallel-max 4 \ && curl --fail --silent --no-progress-meter --show-error --location --remote-name-all \
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \ https://github.com/paperless-ngx/builder/releases/download/jbig2enc-trixie-v${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
&& echo "Installing qpdf ${QPDF_VERSION}" \
&& dpkg --install ./libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
&& dpkg --install ./qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
&& echo "Installing Ghostscript ${GS_VERSION}" \
&& dpkg --install ./libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
&& dpkg --install ./libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
&& dpkg --install ./ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
&& echo "Installing jbig2enc" \ && echo "Installing jbig2enc" \
&& dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ && dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
&& echo "Configuring imagemagick" \ && echo "Configuring imagemagick" \
@ -254,7 +240,8 @@ RUN set -eux \
&& chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \ && chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \
&& echo "Collecting static files" \ && echo "Collecting static files" \
&& s6-setuidgid paperless python3 manage.py collectstatic --clear --no-input --link \ && s6-setuidgid paperless python3 manage.py collectstatic --clear --no-input --link \
&& s6-setuidgid paperless python3 manage.py compilemessages && s6-setuidgid paperless python3 manage.py compilemessages \
&& /usr/local/bin/deduplicate.py --verbose /usr/src/paperless/static/
VOLUME ["/usr/src/paperless/data", \ VOLUME ["/usr/src/paperless/data", \
"/usr/src/paperless/media", \ "/usr/src/paperless/media", \
@ -265,4 +252,4 @@ ENTRYPOINT ["/init"]
EXPOSE 8000 EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --retries=5 CMD [ "curl", "-fs", "-S", "--max-time", "2", "http://localhost:8000" ] HEALTHCHECK --interval=30s --timeout=10s --retries=5 CMD [ "curl", "-fs", "-S", "-L", "--max-time", "2", "http://localhost:8000" ]

View File

@ -1,11 +1,10 @@
# Docker Compose file for running paperless testing with actual gotenberg # Docker Compose file for running paperless testing with actual Gotenberg
# and Tika containers for a more end to end test of the Tika related functionality # and Tika containers for a more end to end test of the Tika related functionality
# Can be used locally or by the CI to start the necessary containers with the # Can be used locally or by the CI to start the necessary containers with the
# correct networking for the tests # correct networking for the tests
services: services:
gotenberg: gotenberg:
image: docker.io/gotenberg/gotenberg:8.19 image: docker.io/gotenberg/gotenberg:8.25
hostname: gotenberg hostname: gotenberg
container_name: gotenberg container_name: gotenberg
network_mode: host network_mode: host

View File

@ -32,6 +32,6 @@
# Note that this is different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines # Note that this is different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines
# the language used for OCR. # the language used for OCR.
# The container installs English, German, Italian, Spanish and French by default. # The container installs English, German, Italian, Spanish and French by default.
# See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names&suite=buster # See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names
# for available languages. # for available languages.
#PAPERLESS_OCR_LANGUAGES=tur ces #PAPERLESS_OCR_LANGUAGES=tur ces

View File

@ -17,7 +17,7 @@
# - Apache Tika and Gotenberg servers are started with paperless and paperless # - Apache Tika and Gotenberg servers are started with paperless and paperless
# is configured to use these services. These provide support for consuming # is configured to use these services. These provide support for consuming
# Office documents (Word, Excel, PowerPoint and their LibreOffice counter- # Office documents (Word, Excel, PowerPoint and their LibreOffice counter-
# parts. # parts).
# #
# To install and update paperless with this file, do the following: # To install and update paperless with this file, do the following:
# #
@ -25,20 +25,17 @@
# and '.env' into a folder. # and '.env' into a folder.
# - Run 'docker compose pull'. # - Run 'docker compose pull'.
# - Run 'docker compose up -d'. # - Run 'docker compose up -d'.
# #
# For more extensive installation and update instructions, refer to the # For more extensive installation and update instructions, refer to the
# documentation. # documentation.
services: services:
broker: broker:
image: docker.io/library/redis:7 image: docker.io/library/redis:8
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- redisdata:/data - redisdata:/data
db: db:
image: docker.io/library/mariadb:11 image: docker.io/library/mariadb:12
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- dbdata:/var/lib/mysql - dbdata:/var/lib/mysql
@ -48,7 +45,6 @@ services:
MARIADB_USER: paperless MARIADB_USER: paperless
MARIADB_PASSWORD: paperless MARIADB_PASSWORD: paperless
MARIADB_ROOT_PASSWORD: paperless MARIADB_ROOT_PASSWORD: paperless
webserver: webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped restart: unless-stopped
@ -75,9 +71,8 @@ services:
PAPERLESS_TIKA_ENABLED: 1 PAPERLESS_TIKA_ENABLED: 1
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000 PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
PAPERLESS_TIKA_ENDPOINT: http://tika:9998 PAPERLESS_TIKA_ENDPOINT: http://tika:9998
gotenberg: gotenberg:
image: docker.io/gotenberg/gotenberg:8.19 image: docker.io/gotenberg/gotenberg:8.25
restart: unless-stopped restart: unless-stopped
# The gotenberg chromium route is used to convert .eml files. We do not # The gotenberg chromium route is used to convert .eml files. We do not
# want to allow external content like tracking pixels or even javascript. # want to allow external content like tracking pixels or even javascript.
@ -85,11 +80,9 @@ services:
- "gotenberg" - "gotenberg"
- "--chromium-disable-javascript=true" - "--chromium-disable-javascript=true"
- "--chromium-allow-list=file:///tmp/.*" - "--chromium-allow-list=file:///tmp/.*"
tika: tika:
image: docker.io/apache/tika:latest image: docker.io/apache/tika:latest
restart: unless-stopped restart: unless-stopped
volumes: volumes:
data: data:
media: media:

View File

@ -24,16 +24,14 @@
# #
# For more extensive installation and update instructions, refer to the # For more extensive installation and update instructions, refer to the
# documentation. # documentation.
services: services:
broker: broker:
image: docker.io/library/redis:7 image: docker.io/library/redis:8
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- redisdata:/data - redisdata:/data
db: db:
image: docker.io/library/mariadb:11 image: docker.io/library/mariadb:12
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- dbdata:/var/lib/mysql - dbdata:/var/lib/mysql
@ -43,7 +41,6 @@ services:
MARIADB_USER: paperless MARIADB_USER: paperless
MARIADB_PASSWORD: paperless MARIADB_PASSWORD: paperless
MARIADB_ROOT_PASSWORD: paperless MARIADB_ROOT_PASSWORD: paperless
webserver: webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped restart: unless-stopped
@ -65,7 +62,6 @@ services:
PAPERLESS_DBUSER: paperless # only needed if non-default username PAPERLESS_DBUSER: paperless # only needed if non-default username
PAPERLESS_DBPASS: paperless # only needed if non-default password PAPERLESS_DBPASS: paperless # only needed if non-default password
PAPERLESS_DBPORT: 3306 PAPERLESS_DBPORT: 3306
volumes: volumes:
data: data:
media: media:

View File

@ -25,24 +25,21 @@
# #
# For more extensive installation and update instructions, refer to the # For more extensive installation and update instructions, refer to the
# documentation. # documentation.
services: services:
broker: broker:
image: docker.io/library/redis:7 image: docker.io/library/redis:8
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- redisdata:/data - redisdata:/data
db: db:
image: docker.io/library/postgres:17 image: docker.io/library/postgres:18
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- pgdata:/var/lib/postgresql/data - pgdata:/var/lib/postgresql
environment: environment:
POSTGRES_DB: paperless POSTGRES_DB: paperless
POSTGRES_USER: paperless POSTGRES_USER: paperless
POSTGRES_PASSWORD: paperless POSTGRES_PASSWORD: paperless
webserver: webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped restart: unless-stopped
@ -61,7 +58,6 @@ services:
PAPERLESS_DBHOST: db PAPERLESS_DBHOST: db
env_file: env_file:
- stack.env - stack.env
volumes: volumes:
data: data:
media: media:

View File

@ -17,7 +17,7 @@
# - Apache Tika and Gotenberg servers are started with paperless and paperless # - Apache Tika and Gotenberg servers are started with paperless and paperless
# is configured to use these services. These provide support for consuming # is configured to use these services. These provide support for consuming
# Office documents (Word, Excel, PowerPoint and their LibreOffice counter- # Office documents (Word, Excel, PowerPoint and their LibreOffice counter-
# parts. # parts).
# #
# To install and update paperless with this file, do the following: # To install and update paperless with this file, do the following:
# #
@ -28,24 +28,21 @@
# #
# For more extensive installation and update instructions, refer to the # For more extensive installation and update instructions, refer to the
# documentation. # documentation.
services: services:
broker: broker:
image: docker.io/library/redis:7 image: docker.io/library/redis:8
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- redisdata:/data - redisdata:/data
db: db:
image: docker.io/library/postgres:17 image: docker.io/library/postgres:18
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- pgdata:/var/lib/postgresql/data - pgdata:/var/lib/postgresql
environment: environment:
POSTGRES_DB: paperless POSTGRES_DB: paperless
POSTGRES_USER: paperless POSTGRES_USER: paperless
POSTGRES_PASSWORD: paperless POSTGRES_PASSWORD: paperless
webserver: webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped restart: unless-stopped
@ -68,22 +65,18 @@ services:
PAPERLESS_TIKA_ENABLED: 1 PAPERLESS_TIKA_ENABLED: 1
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000 PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
PAPERLESS_TIKA_ENDPOINT: http://tika:9998 PAPERLESS_TIKA_ENDPOINT: http://tika:9998
gotenberg: gotenberg:
image: docker.io/gotenberg/gotenberg:8.19 image: docker.io/gotenberg/gotenberg:8.25
restart: unless-stopped restart: unless-stopped
# The gotenberg chromium route is used to convert .eml files. We do not # The gotenberg chromium route is used to convert .eml files. We do not
# want to allow external content like tracking pixels or even javascript. # want to allow external content like tracking pixels or even javascript.
command: command:
- "gotenberg" - "gotenberg"
- "--chromium-disable-javascript=true" - "--chromium-disable-javascript=true"
- "--chromium-allow-list=file:///tmp/.*" - "--chromium-allow-list=file:///tmp/.*"
tika: tika:
image: docker.io/apache/tika:latest image: docker.io/apache/tika:latest
restart: unless-stopped restart: unless-stopped
volumes: volumes:
data: data:
media: media:

View File

@ -24,24 +24,21 @@
# #
# For more extensive installation and update instructions, refer to the # For more extensive installation and update instructions, refer to the
# documentation. # documentation.
services: services:
broker: broker:
image: docker.io/library/redis:7 image: docker.io/library/redis:8
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- redisdata:/data - redisdata:/data
db: db:
image: docker.io/library/postgres:17 image: docker.io/library/postgres:18
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- pgdata:/var/lib/postgresql/data - pgdata:/var/lib/postgresql
environment: environment:
POSTGRES_DB: paperless POSTGRES_DB: paperless
POSTGRES_USER: paperless POSTGRES_USER: paperless
POSTGRES_PASSWORD: paperless POSTGRES_PASSWORD: paperless
webserver: webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped restart: unless-stopped
@ -59,7 +56,6 @@ services:
environment: environment:
PAPERLESS_REDIS: redis://broker:6379 PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_DBHOST: db PAPERLESS_DBHOST: db
volumes: volumes:
data: data:
media: media:

View File

@ -17,7 +17,7 @@
# - Apache Tika and Gotenberg servers are started with paperless and paperless # - Apache Tika and Gotenberg servers are started with paperless and paperless
# is configured to use these services. These provide support for consuming # is configured to use these services. These provide support for consuming
# Office documents (Word, Excel, PowerPoint and their LibreOffice counter- # Office documents (Word, Excel, PowerPoint and their LibreOffice counter-
# parts. # parts).
# #
# To install and update paperless with this file, do the following: # To install and update paperless with this file, do the following:
# #
@ -28,14 +28,12 @@
# #
# For more extensive installation and update instructions, refer to the # For more extensive installation and update instructions, refer to the
# documentation. # documentation.
services: services:
broker: broker:
image: docker.io/library/redis:7 image: docker.io/library/redis:8
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- redisdata:/data - redisdata:/data
webserver: webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped restart: unless-stopped
@ -56,22 +54,18 @@ services:
PAPERLESS_TIKA_ENABLED: 1 PAPERLESS_TIKA_ENABLED: 1
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000 PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
PAPERLESS_TIKA_ENDPOINT: http://tika:9998 PAPERLESS_TIKA_ENDPOINT: http://tika:9998
gotenberg: gotenberg:
image: docker.io/gotenberg/gotenberg:8.19 image: docker.io/gotenberg/gotenberg:8.25
restart: unless-stopped restart: unless-stopped
# The gotenberg chromium route is used to convert .eml files. We do not # The gotenberg chromium route is used to convert .eml files. We do not
# want to allow external content like tracking pixels or even javascript. # want to allow external content like tracking pixels or even javascript.
command: command:
- "gotenberg" - "gotenberg"
- "--chromium-disable-javascript=true" - "--chromium-disable-javascript=true"
- "--chromium-allow-list=file:///tmp/.*" - "--chromium-allow-list=file:///tmp/.*"
tika: tika:
image: docker.io/apache/tika:latest image: docker.io/apache/tika:latest
restart: unless-stopped restart: unless-stopped
volumes: volumes:
data: data:
media: media:

View File

@ -21,14 +21,12 @@
# #
# For more extensive installation and update instructions, refer to the # For more extensive installation and update instructions, refer to the
# documentation. # documentation.
services: services:
broker: broker:
image: docker.io/library/redis:7 image: docker.io/library/redis:8
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- redisdata:/data - redisdata:/data
webserver: webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped restart: unless-stopped
@ -44,7 +42,6 @@ services:
env_file: docker-compose.env env_file: docker-compose.env
environment: environment:
PAPERLESS_REDIS: redis://broker:6379 PAPERLESS_REDIS: redis://broker:6379
volumes: volumes:
data: data:
media: media:

View File

@ -1,179 +0,0 @@
#!/usr/bin/env bash
set -e
# Source: https://github.com/sameersbn/docker-gitlab/
map_uidgid() {
local -r usermap_original_uid=$(id -u paperless)
local -r usermap_original_gid=$(id -g paperless)
local -r usermap_new_uid=${USERMAP_UID:-$usermap_original_uid}
local -r usermap_new_gid=${USERMAP_GID:-${usermap_original_gid:-$usermap_new_uid}}
if [[ ${usermap_new_uid} != "${usermap_original_uid}" || ${usermap_new_gid} != "${usermap_original_gid}" ]]; then
echo "Mapping UID and GID for paperless:paperless to $usermap_new_uid:$usermap_new_gid"
usermod --non-unique --uid "${usermap_new_uid}" paperless
groupmod --non-unique --gid "${usermap_new_gid}" paperless
fi
}
map_folders() {
# Export these so they can be used in docker-prepare.sh
export DATA_DIR="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}"
export MEDIA_ROOT_DIR="${PAPERLESS_MEDIA_ROOT:-/usr/src/paperless/media}"
export CONSUME_DIR="${PAPERLESS_CONSUMPTION_DIR:-/usr/src/paperless/consume}"
}
custom_container_init() {
# Mostly borrowed from the LinuxServer.io base image
# https://github.com/linuxserver/docker-baseimage-ubuntu/tree/bionic/root/etc/cont-init.d
local -r custom_script_dir="/custom-cont-init.d"
# Tamper checking.
# Don't run files which are owned by anyone except root
# Don't run files which are writeable by others
if [ -d "${custom_script_dir}" ]; then
if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 ! -user root)" ]; then
echo "**** Potential tampering with custom scripts detected ****"
echo "**** The folder '${custom_script_dir}' must be owned by root ****"
return 0
fi
if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 -perm -o+w)" ]; then
echo "**** The folder '${custom_script_dir}' or some of contents have write permissions for others, which is a security risk. ****"
echo "**** Please review the permissions and their contents to make sure they are owned by root, and can only be modified by root. ****"
return 0
fi
# Make sure custom init directory has files in it
if [ -n "$(/bin/ls --almost-all "${custom_script_dir}" 2>/dev/null)" ]; then
echo "[custom-init] files found in ${custom_script_dir} executing"
# Loop over files in the directory
for SCRIPT in "${custom_script_dir}"/*; do
NAME="$(basename "${SCRIPT}")"
if [ -f "${SCRIPT}" ]; then
echo "[custom-init] ${NAME}: executing..."
/bin/bash "${SCRIPT}"
echo "[custom-init] ${NAME}: exited $?"
elif [ ! -f "${SCRIPT}" ]; then
echo "[custom-init] ${NAME}: is not a file"
fi
done
else
echo "[custom-init] no custom files found exiting..."
fi
fi
}
initialize() {
# Setup environment from secrets before anything else
# Check for a version of this var with _FILE appended
# and convert the contents to the env var value
# Source it so export is persistent
# shellcheck disable=SC1091
source /sbin/env-from-file.sh
# Change the user and group IDs if needed
map_uidgid
# Check for overrides of certain folders
map_folders
local -r export_dir="/usr/src/paperless/export"
for dir in \
"${export_dir}" \
"${DATA_DIR}" "${DATA_DIR}/index" \
"${MEDIA_ROOT_DIR}" "${MEDIA_ROOT_DIR}/documents" "${MEDIA_ROOT_DIR}/documents/originals" "${MEDIA_ROOT_DIR}/documents/thumbnails" \
"${CONSUME_DIR}"; do
if [[ ! -d "${dir}" ]]; then
echo "Creating directory ${dir}"
mkdir --parents --verbose "${dir}"
fi
done
local -r tmp_dir="${PAPERLESS_SCRATCH_DIR:=/tmp/paperless}"
echo "Creating directory scratch directory ${tmp_dir}"
mkdir --parents --verbose "${tmp_dir}"
set +e
echo "Adjusting permissions of paperless files. This may take a while."
chown -R paperless:paperless "${tmp_dir}"
for dir in \
"${export_dir}" \
"${DATA_DIR}" \
"${MEDIA_ROOT_DIR}" \
"${CONSUME_DIR}"; do
find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown --changes paperless:paperless {} +
done
set -e
"${gosu_cmd[@]}" /sbin/docker-prepare.sh
# Leave this last thing
custom_container_init
}
install_languages() {
echo "Installing languages..."
read -ra langs <<<"$1"
# Check that it is not empty
if [ ${#langs[@]} -eq 0 ]; then
return
fi
# Build list of packages to install
to_install=()
for lang in "${langs[@]}"; do
pkg="tesseract-ocr-$lang"
if dpkg --status "$pkg" &>/dev/null; then
echo "Package $pkg already installed!"
continue
else
to_install+=("$pkg")
fi
done
# Use apt only when we install packages
if [ ${#to_install[@]} -gt 0 ]; then
apt-get update
for pkg in "${to_install[@]}"; do
if ! apt-cache show "$pkg" &>/dev/null; then
echo "Skipped $pkg: Package not found! :("
continue
fi
echo "Installing package $pkg..."
if ! apt-get --assume-yes install "$pkg" &>/dev/null; then
echo "Could not install $pkg"
exit 1
fi
done
fi
}
echo "Paperless-ngx docker container starting..."
gosu_cmd=(gosu paperless)
if [ "$(id --user)" == "$(id --user paperless)" ]; then
gosu_cmd=()
fi
# Install additional languages if specified
if [[ -n "$PAPERLESS_OCR_LANGUAGES" ]]; then
install_languages "$PAPERLESS_OCR_LANGUAGES"
fi
initialize
if [[ "$1" != "/"* ]]; then
echo Executing management command "$@"
exec "${gosu_cmd[@]}" python3 manage.py "$@"
else
echo Executing "$@"
exec "$@"
fi

View File

@ -9,7 +9,7 @@ if find /run/s6/container_environment/*"_FILE" -maxdepth 1 > /dev/null 2>&1; the
for FILENAME in /run/s6/container_environment/*; do for FILENAME in /run/s6/container_environment/*; do
if [[ "${FILENAME##*/}" == PAPERLESS_*_FILE ]]; then if [[ "${FILENAME##*/}" == PAPERLESS_*_FILE ]]; then
# This should have been named different.. # This should have been named different..
if [[ ${FILENAME} == "PAPERLESS_OCR_SKIP_ARCHIVE_FILE" || ${FILENAME} == "PAPERLESS_MODEL_FILE" ]]; then if [[ "${FILENAME##*/}" == "PAPERLESS_OCR_SKIP_ARCHIVE_FILE" || "${FILENAME##*/}" == "PAPERLESS_MODEL_FILE" ]]; then
continue continue
fi fi
SECRETFILE=$(cat "${FILENAME}") SECRETFILE=$(cat "${FILENAME}")

View File

@ -9,25 +9,57 @@ declare -r media_root_dir="${PAPERLESS_MEDIA_ROOT:-/usr/src/paperless/media}"
declare -r consume_dir="${PAPERLESS_CONSUMPTION_DIR:-/usr/src/paperless/consume}" declare -r consume_dir="${PAPERLESS_CONSUMPTION_DIR:-/usr/src/paperless/consume}"
declare -r tmp_dir="${PAPERLESS_SCRATCH_DIR:=/tmp/paperless}" declare -r tmp_dir="${PAPERLESS_SCRATCH_DIR:=/tmp/paperless}"
echo "${log_prefix} Checking for folder existence" declare -r main_dirs=(
"${export_dir}"
"${data_dir}"
"${media_root_dir}"
"${consume_dir}"
"${tmp_dir}"
)
for dir in \ declare -r extra_dirs=(
"${export_dir}" \ "${main_dirs[@]}"
"${data_dir}" "${data_dir}/index" \ "${data_dir}/index"
"${media_root_dir}" "${media_root_dir}/documents" "${media_root_dir}/documents/originals" "${media_root_dir}/documents/thumbnails" \ "${media_root_dir}/documents"
"${consume_dir}" \ "${media_root_dir}/documents/originals"
"${tmp_dir}"; do "${media_root_dir}/documents/thumbnails"
)
if [[ -n "${USER_IS_NON_ROOT}" ]]; then
# Non-root mode: Create directories as current user, warn about permission issues
echo "${log_prefix} Running in non-root mode, checking directories"
current_uid=$(id --user)
current_gid=$(id --group)
for dir in "${extra_dirs[@]}"; do
if [[ ! -d "${dir}" ]]; then
mkdir --parents --verbose "${dir}" || echo "${log_prefix} WARNING: Could not create ${dir} - permission denied"
fi
# Check permissions on existing directories too
if [[ -d "${dir}" && ! -w "${dir}" ]]; then
echo "${log_prefix} WARNING: No write permission to ${dir}"
fi
done
# Warn about ownership issues
for dir in "${main_dirs[@]}"; do
if [[ -d "${dir}" ]]; then
find "${dir}" -not \( -user ${current_uid} -and -group ${current_gid} \) -exec echo "${log_prefix} WARNING: Permission issue on {}: not owned by current user (${current_uid}:${current_gid})" \; 2>/dev/null || echo "${log_prefix} WARNING: Cannot check permissions on ${dir}"
fi
done
else
# Root mode: Create and fix permissions as needed
echo "${log_prefix} Running with root privileges, adjusting directories and permissions"
# First create directories
for dir in "${extra_dirs[@]}"; do
if [[ ! -d "${dir}" ]]; then if [[ ! -d "${dir}" ]]; then
mkdir --parents --verbose "${dir}" mkdir --parents --verbose "${dir}"
fi fi
done done
echo "${log_prefix} Adjusting file and folder permissions" # Then fix permissions on all directories
for dir in \ for dir in "${main_dirs[@]}"; do
"${export_dir}" \
"${data_dir}" \
"${media_root_dir}" \
"${consume_dir}" \
"${tmp_dir}"; do
find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown --changes paperless:paperless {} + find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown --changes paperless:paperless {} +
done done
fi

View File

@ -1,7 +0,0 @@
#!/command/with-contenv /usr/bin/bash
# shellcheck shell=bash
declare -r data_dir="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}"
# shellcheck disable=SC2164
cd "${PAPERLESS_SRC_DIR}"
exec s6-setlock -n "${data_dir}/migration_lock" python3 manage.py migrate --skip-checks --no-input

View File

@ -2,11 +2,17 @@
# shellcheck shell=bash # shellcheck shell=bash
declare -r log_prefix="[init-migrations]" declare -r log_prefix="[init-migrations]"
declare -r data_dir="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}"
echo "${log_prefix} Apply database migrations..." echo "${log_prefix} Apply database migrations..."
cd "${PAPERLESS_SRC_DIR}"
# The whole migrate, with flock, needs to run as the right user # The whole migrate, with flock, needs to run as the right user
if [[ -n "${USER_IS_NON_ROOT}" ]]; then if [[ -n "${USER_IS_NON_ROOT}" ]]; then
exec /etc/s6-overlay/s6-rc.d/init-migrations/migrate.sh exec s6-setlock -n "${data_dir}/migration_lock" python3 manage.py migrate --skip-checks --no-input
else else
exec s6-setuidgid paperless /etc/s6-overlay/s6-rc.d/init-migrations/migrate.sh exec s6-setuidgid paperless \
s6-setlock -n "${data_dir}/migration_lock" \
python3 manage.py migrate --skip-checks --no-input
fi fi

View File

@ -11,9 +11,10 @@ printf "/usr/src/paperless/src" > /var/run/s6/container_environment/PAPERLESS_SR
echo $(date +%s) > /var/run/s6/container_environment/PAPERLESS_START_TIME_S echo $(date +%s) > /var/run/s6/container_environment/PAPERLESS_START_TIME_S
# Check if we're starting as a non-root user # Check if we're starting as a non-root user
if [ $(id -u) == $(id -u paperless) ]; then if [ "$(id --user)" != "0" ]; then
printf "true" > /var/run/s6/container_environment/USER_IS_NON_ROOT printf "true" > /var/run/s6/container_environment/USER_IS_NON_ROOT
echo "${log_prefix} paperless-ngx docker container running under a user" echo "${log_prefix} paperless-ngx docker container running under a user ($(id --user):$(id --group))"
else else
printf "/usr/src/paperless" > /var/run/s6/container_environment/HOME
echo "${log_prefix} paperless-ngx docker container starting init as root" echo "${log_prefix} paperless-ngx docker container starting init as root"
fi fi

View File

@ -1,70 +1,66 @@
#!/command/with-contenv /usr/bin/bash #!/command/with-contenv /usr/bin/bash
# shellcheck shell=bash # shellcheck shell=bash
# vim: set ft=bash ts=4 sw=4 sts=4 et :
declare -r log_prefix="[init-db-wait]" set -euo pipefail
declare -r LOG_PREFIX="[init-db-wait]"
declare -ri TIMEOUT=60
declare -i ATTEMPT=0
declare -i DELAY=0
declare -i STARTED_AT=${EPOCHSECONDS:?EPOCHSECONDS var unset}
delay_next_attempt() {
local -i elapsed=$(( EPOCHSECONDS - STARTED_AT ))
local -ri remaining=$(( TIMEOUT - elapsed ))
if (( remaining <= 0 )); then
echo "${LOG_PREFIX} Unable to connect after $elapsed seconds."
exit 1
fi
DELAY+=1
# clamp to remaining time
if (( DELAY > remaining )); then
DELAY=$remaining
fi
ATTEMPT+=1
echo "${LOG_PREFIX} Attempt $ATTEMPT failed! Trying again in $DELAY seconds..."
sleep "$DELAY"
}
wait_for_postgres() { wait_for_postgres() {
local attempt_num=1 echo "${LOG_PREFIX} Waiting for PostgreSQL to start..."
local -r max_attempts=5
echo "${log_prefix} Waiting for PostgreSQL to start..."
local -r host="${PAPERLESS_DBHOST:-localhost}" local -r host="${PAPERLESS_DBHOST:-localhost}"
local -r port="${PAPERLESS_DBPORT:-5432}" local -r port="${PAPERLESS_DBPORT:-5432}"
local -r user="${PAPERLESS_DBUSER:-paperless}" local -r user="${PAPERLESS_DBUSER:-paperless}"
# Disable warning, host and port can't have spaces while ! pg_isready -h "${host}" -p "${port}" --username "${user}"; do
# shellcheck disable=SC2086 delay_next_attempt
while [ ! "$(pg_isready -h ${host} -p ${port} --username ${user})" ]; do
if [ $attempt_num -eq $max_attempts ]; then
echo "${log_prefix} Unable to connect to database."
exit 1
else
echo "${log_prefix} Attempt $attempt_num failed! Trying again in 5 seconds..."
fi
attempt_num=$(("$attempt_num" + 1))
sleep 5
done done
# Extra in case this is a first start echo "${LOG_PREFIX} Connected to PostgreSQL"
sleep 5
echo "Connected to PostgreSQL"
} }
wait_for_mariadb() { wait_for_mariadb() {
echo "${log_prefix} Waiting for MariaDB to start..." echo "${LOG_PREFIX} Waiting for MariaDB to start..."
local -r host="${PAPERLESS_DBHOST:=localhost}" local -r host="${PAPERLESS_DBHOST:-localhost}"
local -r port="${PAPERLESS_DBPORT:=3306}" local -r port="${PAPERLESS_DBPORT:-3306}"
local attempt_num=1 while ! mariadb-admin --host="${host}" --port="${port}" --skip-ssl ping --silent >/dev/null 2>&1; do
local -r max_attempts=5 delay_next_attempt
# Disable warning, host and port can't have spaces
# shellcheck disable=SC2086
while ! true > /dev/tcp/$host/$port; do
if [ $attempt_num -eq $max_attempts ]; then
echo "${log_prefix} Unable to connect to database."
exit 1
else
echo "${log_prefix} Attempt $attempt_num failed! Trying again in 5 seconds..."
fi
attempt_num=$(("$attempt_num" + 1))
sleep 5
done done
echo "Connected to MariaDB" echo "${LOG_PREFIX} Connected to MariaDB"
} }
if [[ "${PAPERLESS_DBENGINE}" == "mariadb" ]]; then if [[ "${PAPERLESS_DBENGINE:-}" == "mariadb" ]]; then
echo "${log_prefix} Waiting for MariaDB to report ready"
wait_for_mariadb wait_for_mariadb
elif [[ -n "${PAPERLESS_DBHOST}" ]]; then elif [[ -n "${PAPERLESS_DBHOST:-}" ]]; then
echo "${log_prefix} Waiting for postgresql to report ready"
wait_for_postgres wait_for_postgres
fi fi
echo "${log_prefix} Database is ready" echo "${LOG_PREFIX} Database is ready"

View File

@ -0,0 +1,167 @@
#!/usr/bin/env python3
"""
File deduplication script that replaces identical files with symlinks.
Uses SHA256 hashing to identify duplicate files.
"""
import hashlib
from collections import defaultdict
from pathlib import Path
import click
import humanize
def calculate_sha256(filepath: Path) -> str | None:
sha256_hash = hashlib.sha256()
try:
with filepath.open("rb") as f:
# Read file in chunks to handle large files efficiently
while chunk := f.read(65536): # 64KB chunks
sha256_hash.update(chunk)
return sha256_hash.hexdigest()
except OSError as e:
click.echo(f"Error reading {filepath}: {e}", err=True)
return None
def find_duplicate_files(directory: Path) -> dict[str, list[Path]]:
"""
Recursively scan directory and group files by their SHA256 hash.
Returns a dictionary mapping hash -> list of file paths.
"""
hash_to_files: dict[str, list[Path]] = defaultdict(list)
for filepath in directory.rglob("*"):
# Skip symlinks
if filepath.is_symlink():
continue
# Skip if not a regular file
if not filepath.is_file():
continue
file_hash = calculate_sha256(filepath)
if file_hash:
hash_to_files[file_hash].append(filepath)
# Filter to only return hashes with duplicates
return {h: files for h, files in hash_to_files.items() if len(files) > 1}
def replace_with_symlinks(
duplicate_groups: dict[str, list[Path]],
*,
dry_run: bool = False,
) -> tuple[int, int]:
"""
Replace duplicate files with symlinks to the first occurrence.
Returns (number_of_files_replaced, space_saved_in_bytes).
"""
total_duplicates = 0
space_saved = 0
for file_hash, file_list in duplicate_groups.items():
# Keep the first file as the original, replace others with symlinks
original_file = file_list[0]
duplicates = file_list[1:]
click.echo(f"Found {len(duplicates)} duplicate(s) of: {original_file}")
for duplicate in duplicates:
try:
# Get file size before deletion
file_size = duplicate.stat().st_size
if dry_run:
click.echo(f" [DRY RUN] Would replace: {duplicate}")
else:
# Remove the duplicate file
duplicate.unlink()
# Create relative symlink if possible, otherwise absolute
try:
# Try to create a relative symlink
rel_path = original_file.relative_to(duplicate.parent)
duplicate.symlink_to(rel_path)
click.echo(f" Replaced: {duplicate} -> {rel_path}")
except ValueError:
# Fall back to absolute path
duplicate.symlink_to(original_file.resolve())
click.echo(f" Replaced: {duplicate} -> {original_file}")
space_saved += file_size
total_duplicates += 1
except OSError as e:
click.echo(f" Error replacing {duplicate}: {e}", err=True)
return total_duplicates, space_saved
@click.command()
@click.argument(
"directory",
type=click.Path(
exists=True,
file_okay=False,
dir_okay=True,
readable=True,
path_type=Path,
),
)
@click.option(
"--dry-run",
is_flag=True,
help="Show what would be done without making changes",
)
@click.option("--verbose", "-v", is_flag=True, help="Show verbose output")
def deduplicate(directory: Path, *, dry_run: bool, verbose: bool) -> None:
"""
Recursively search DIRECTORY for identical files and replace them with symlinks.
Uses SHA256 hashing to identify duplicate files. The first occurrence of each
unique file is kept, and all duplicates are replaced with symlinks pointing to it.
"""
directory = directory.resolve()
click.echo(f"Scanning directory: {directory}")
if dry_run:
click.echo("Running in DRY RUN mode - no changes will be made")
# Find all duplicate files
click.echo("Calculating file hashes...")
duplicate_groups = find_duplicate_files(directory)
if not duplicate_groups:
click.echo("No duplicate files found!")
return
total_files = sum(len(files) - 1 for files in duplicate_groups.values())
click.echo(
f"Found {len(duplicate_groups)} group(s) of duplicates "
f"({total_files} files to deduplicate)",
)
if verbose:
for file_hash, files in duplicate_groups.items():
click.echo(f"Hash: {file_hash}")
for f in files:
click.echo(f" - {f}")
# Replace duplicates with symlinks
click.echo("Processing duplicates...")
num_replaced, space_saved = replace_with_symlinks(duplicate_groups, dry_run=dry_run)
# Summary
click.echo(
f"{'Would replace' if dry_run else 'Replaced'} "
f"{num_replaced} duplicate file(s)",
)
if not dry_run:
click.echo(f"Space saved: {humanize.naturalsize(space_saved, binary=True)}")
if __name__ == "__main__":
deduplicate()

View File

@ -179,10 +179,14 @@ following:
### Database Upgrades ### Database Upgrades
In general, paperless does not require a specific version of PostgreSQL or MariaDB and it is Paperless-ngx is compatible with Django-supported versions of PostgreSQL and MariaDB and it is generally
safe to update them to newer versions. However, you should always take a backup and follow safe to update them to newer versions. However, you should always take a backup and follow
the instructions from your database's documentation for how to upgrade between major versions. the instructions from your database's documentation for how to upgrade between major versions.
!!! note
As of Paperless-ngx v2.18, the minimum supported version of PostgreSQL is 14.
For PostgreSQL, refer to [Upgrading a PostgreSQL Cluster](https://www.postgresql.org/docs/current/upgrading.html). For PostgreSQL, refer to [Upgrading a PostgreSQL Cluster](https://www.postgresql.org/docs/current/upgrading.html).
For MariaDB, refer to [Upgrading MariaDB](https://mariadb.com/kb/en/upgrading/) For MariaDB, refer to [Upgrading MariaDB](https://mariadb.com/kb/en/upgrading/)
@ -333,7 +337,7 @@ must be provided to import. If this value is lost, the export cannot be imported
The document importer takes the export produced by the [Document The document importer takes the export produced by the [Document
exporter](#exporter) and imports it into paperless. exporter](#exporter) and imports it into paperless.
The importer works just like the exporter. You point it at a directory, The importer works just like the exporter. You point it at a directory or the generated .zip file,
and the script does the rest of the work: and the script does the rest of the work:
```shell ```shell
@ -351,9 +355,6 @@ When you use the provided docker compose script, put the export inside
the `export` folder in your paperless source directory. Specify the `export` folder in your paperless source directory. Specify
`../export` as the `source`. `../export` as the `source`.
Note that .zip files (as can be generated from the exporter) are not supported. You must unzip them into
the target directory first.
!!! note !!! note
Importing from a previous version of Paperless may work, but for best Importing from a previous version of Paperless may work, but for best
@ -460,6 +461,22 @@ of the index and usually makes queries faster and also ensures that the
autocompletion works properly. This command is regularly invoked by the autocompletion works properly. This command is regularly invoked by the
task scheduler. task scheduler.
### Clearing the database read cache
If the database read cache is enabled, **you must run this command** after making any changes to the database outside the application context.
This includes operations such as restoring a database backup or executing SQL statements like UPDATE, INSERT, DELETE, ALTER, CREATE, or DROP.
Failing to invalidate the cache after such modifications can lead to stale data being served from the cache, and **may cause data corruption** or inconsistent behavior in the application.
Use the following management command to clear the cache:
```
python3 manage.py invalidate_cachalot
```
!!! info
The database read cache is based on Django-Cachalot. You can refer to their [documentation](https://django-cachalot.readthedocs.io/en/latest/quickstart.html#manage-py-command).
### Managing filenames {#renamer} ### Managing filenames {#renamer}
If you use paperless' feature to If you use paperless' feature to

View File

@ -179,6 +179,7 @@ variables:
| ---------------------------- | ---------------------------------------------- | | ---------------------------- | ---------------------------------------------- |
| `DOCUMENT_ID` | Database primary key of the document | | `DOCUMENT_ID` | Database primary key of the document |
| `DOCUMENT_FILE_NAME` | Formatted filename, not including paths | | `DOCUMENT_FILE_NAME` | Formatted filename, not including paths |
| `DOCUMENT_TYPE` | The document type (if any) |
| `DOCUMENT_CREATED` | Date & time when document created | | `DOCUMENT_CREATED` | Date & time when document created |
| `DOCUMENT_MODIFIED` | Date & time when document was last modified | | `DOCUMENT_MODIFIED` | Date & time when document was last modified |
| `DOCUMENT_ADDED` | Date & time when document was added | | `DOCUMENT_ADDED` | Date & time when document was added |
@ -433,6 +434,134 @@ provided. The template is provided as a string, potentially multiline, and rende
In addition, the entire Document instance is available to be utilized in a more advanced way, as well as some variables which only make sense to be accessed In addition, the entire Document instance is available to be utilized in a more advanced way, as well as some variables which only make sense to be accessed
with more complex logic. with more complex logic.
#### Custom Jinja2 Filters
##### Custom Field Access
The `get_cf_value` filter retrieves a value from custom field data with optional default fallback.
###### Syntax
```jinja2
{{ custom_fields | get_cf_value('field_name') }}
{{ custom_fields | get_cf_value('field_name', 'default_value') }}
```
###### Parameters
- `custom_fields`: This _must_ be the provided custom field data
- `name` (str): Name of the custom field to retrieve
- `default` (str, optional): Default value to return if field is not found or has no value
###### Returns
- `str | None`: The field value, default value, or `None` if neither exists
###### Examples
```jinja2
<!-- Basic usage -->
{{ custom_fields | get_cf_value('department') }}
<!-- With default value -->
{{ custom_fields | get_cf_value('phone', 'Not provided') }}
```
##### Datetime Formatting
The `datetime` filter formats a datetime string or datetime object using Python's strftime formatting.
###### Syntax
```jinja2
{{ datetime_value | datetime('%Y-%m-%d %H:%M:%S') }}
```
###### Parameters
- `value` (str | datetime): Date/time value to format (strings will be parsed automatically)
- `format` (str): Python strftime format string
###### Returns
- `str`: Formatted datetime string
###### Examples
```jinja2
<!-- Format datetime object -->
{{ created | datetime('%B %d, %Y at %I:%M %p') }}
<!-- Output: "January 15, 2024 at 02:30 PM" -->
<!-- Custom formatting -->
{{ custom_fields | get_cf_value('Date Field') | datetime('%A, %B %d, %Y') }}
<!-- Output: "Monday, January 15, 2024" -->
```
See the [strftime format code documentation](https://docs.python.org/3.13/library/datetime.html#strftime-and-strptime-format-codes)
for the possible codes and their meanings.
##### Date Localization
The `localize_date` filter formats a date or datetime object into a localized string using Babel internationalization.
This takes into account the provided locale for translation. Since this must be used on a date or datetime object,
you must access the field directly, i.e. `document.created`.
An ISO string can also be provided to control the output format.
###### Syntax
```jinja2
{{ date_value | localize_date('medium', 'en_US') }}
{{ datetime_value | localize_date('short', 'fr_FR') }}
```
###### Parameters
- `value` (date | datetime | str): Date, datetime object or ISO string to format (datetime should be timezone-aware)
- `format` (str): Format type - either a Babel preset ('short', 'medium', 'long', 'full') or custom pattern
- `locale` (str): Locale code for localization (e.g., 'en_US', 'fr_FR', 'de_DE')
###### Returns
- `str`: Localized, formatted date string
###### Examples
```jinja2
<!-- Preset formats -->
{{ document.created | localize_date('short', 'en_US') }}
<!-- Output: "1/15/24" -->
{{ document.created | localize_date('medium', 'en_US') }}
<!-- Output: "Jan 15, 2024" -->
{{ document.created | localize_date('long', 'en_US') }}
<!-- Output: "January 15, 2024" -->
{{ document.created | localize_date('full', 'en_US') }}
<!-- Output: "Monday, January 15, 2024" -->
<!-- Different locales -->
{{ document.created | localize_date('medium', 'fr_FR') }}
<!-- Output: "15 janv. 2024" -->
{{ document.created | localize_date('medium', 'de_DE') }}
<!-- Output: "15.01.2024" -->
<!-- Custom patterns -->
{{ document.created | localize_date('dd/MM/yyyy', 'en_GB') }}
<!-- Output: "15/01/2024" -->
```
See the [supported format codes](https://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns) for more options.
### Format Presets
- **short**: Abbreviated format (e.g., "1/15/24")
- **medium**: Medium-length format (e.g., "Jan 15, 2024")
- **long**: Long format with full month name (e.g., "January 15, 2024")
- **full**: Full format including day of week (e.g., "Monday, January 15, 2024")
#### Additional Variables #### Additional Variables
- `{{ tag_name_list }}`: A list of tag names applied to the document, ordered by the tag name. Note this is a list, not a single string - `{{ tag_name_list }}`: A list of tag names applied to the document, ordered by the tag name. Note this is a list, not a single string

View File

@ -132,7 +132,7 @@ use cases:
5. Documents with a custom field "address" (text) that is empty: 5. Documents with a custom field "address" (text) that is empty:
`?custom_field_query=["OR", ["address", "isnull", true], ["address", "exact", ""]]` `?custom_field_query=["OR", [["address", "isnull", true], ["address", "exact", ""]]]`
6. Documents that don't have a field called "foo": 6. Documents that don't have a field called "foo":
@ -192,8 +192,8 @@ The endpoint supports the following optional form fields:
- `tags`: Similar to correspondent. Specify this multiple times to - `tags`: Similar to correspondent. Specify this multiple times to
have multiple tags added to the document. have multiple tags added to the document.
- `archive_serial_number`: An optional archive serial number to set. - `archive_serial_number`: An optional archive serial number to set.
- `custom_fields`: An array of custom field ids to assign (with an empty - `custom_fields`: Either an array of custom field ids to assign (with an empty
value) to the document. value) to the document or an object mapping field id -> value.
The endpoint will immediately return HTTP 200 if the document consumption The endpoint will immediately return HTTP 200 if the document consumption
process was started successfully, with the UUID of the consumption task process was started successfully, with the UUID of the consumption task
@ -282,6 +282,18 @@ The following methods are supported:
- `"merge": true or false` (defaults to false) - `"merge": true or false` (defaults to false)
- The `merge` flag determines if the supplied permissions will overwrite all existing permissions (including - The `merge` flag determines if the supplied permissions will overwrite all existing permissions (including
removing them) or be merged with existing permissions. removing them) or be merged with existing permissions.
- `edit_pdf`
- Requires `parameters`:
- `"doc_ids": [DOCUMENT_ID]` A list of a single document ID to edit.
- `"operations": [OPERATION, ...]` A list of operations to perform on the documents. Each operation is a dictionary
with the following keys:
- `"page": PAGE_NUMBER` The page number to edit (1-based).
- `"rotate": DEGREES` Optional rotation in degrees (90, 180, 270).
- `"doc": OUTPUT_DOCUMENT_INDEX` Optional index of the output document for split operations.
- Optional `parameters`:
- `"delete_original": true` to delete the original documents after editing.
- `"update_document": true` to update the existing document with the edited PDF.
- `"include_metadata": true` to copy metadata from the original document to the edited document.
- `merge` - `merge`
- No additional `parameters` required. - No additional `parameters` required.
- The ordering of the merged document is determined by the list of IDs. - The ordering of the merged document is determined by the list of IDs.
@ -413,3 +425,14 @@ Initial API version.
list of strings. When creating or updating a custom field value of a list of strings. When creating or updating a custom field value of a
document for a select type custom field, the value should be the `id` of document for a select type custom field, the value should be the `id` of
the option whereas previously was the index of the option. the option whereas previously was the index of the option.
#### Version 8
- The user field of document notes now returns a simplified user object
rather than just the user ID.
#### Version 9
- The document `created` field is now a date, not a datetime. The
`created_date` field is considered deprecated and will be removed in a
future version.

File diff suppressed because it is too large Load Diff

View File

@ -50,47 +50,48 @@ matcher.
### Database ### Database
By default, Paperless uses **SQLite** with a database stored at `data/db.sqlite3`.
To switch to **PostgreSQL** or **MariaDB**, set [`PAPERLESS_DBHOST`](#PAPERLESS_DBHOST) and optionally configure other
database-related environment variables.
#### [`PAPERLESS_DBHOST=<hostname>`](#PAPERLESS_DBHOST) {#PAPERLESS_DBHOST}
: If unset, Paperless uses **SQLite** by default.
Set `PAPERLESS_DBHOST` to switch to PostgreSQL or MariaDB instead.
#### [`PAPERLESS_DBENGINE=<engine_name>`](#PAPERLESS_DBENGINE) {#PAPERLESS_DBENGINE} #### [`PAPERLESS_DBENGINE=<engine_name>`](#PAPERLESS_DBENGINE) {#PAPERLESS_DBENGINE}
: Optional, gives the ability to choose Postgres or MariaDB for : Optional. Specifies the database engine to use when connecting to a remote database.
database engine. Available options are `postgresql` and Available options are `postgresql` and `mariadb`.
`mariadb`.
Default is `postgresql`. Defaults to `postgresql` if `PAPERLESS_DBHOST` is set.
!!! warning !!! warning
Using MariaDB comes with some caveats. See [MySQL Caveats](advanced_usage.md#mysql-caveats). Using MariaDB comes with some caveats. See [MySQL Caveats](advanced_usage.md#mysql-caveats).
#### [`PAPERLESS_DBHOST=<hostname>`](#PAPERLESS_DBHOST) {#PAPERLESS_DBHOST}
: By default, sqlite is used as the database backend. This can be
changed here.
Set PAPERLESS_DBHOST and another database will be used instead of
sqlite.
#### [`PAPERLESS_DBPORT=<port>`](#PAPERLESS_DBPORT) {#PAPERLESS_DBPORT} #### [`PAPERLESS_DBPORT=<port>`](#PAPERLESS_DBPORT) {#PAPERLESS_DBPORT}
: Adjust port if necessary. : Port to use when connecting to PostgreSQL or MariaDB.
Default is 5432. Default is `5432` for PostgreSQL and `3306` for MariaDB.
#### [`PAPERLESS_DBNAME=<name>`](#PAPERLESS_DBNAME) {#PAPERLESS_DBNAME} #### [`PAPERLESS_DBNAME=<name>`](#PAPERLESS_DBNAME) {#PAPERLESS_DBNAME}
: Database name in PostgreSQL or MariaDB. : Name of the database to connect to when using PostgreSQL or MariaDB.
Defaults to "paperless". Defaults to "paperless".
#### [`PAPERLESS_DBUSER=<name>`](#PAPERLESS_DBUSER) {#PAPERLESS_DBUSER} #### [`PAPERLESS_DBUSER=<name>`](#PAPERLESS_DBUSER) {#PAPERLESS_DBUSER}
: Database user in PostgreSQL or MariaDB. : Username for authenticating with the PostgreSQL or MariaDB database.
Defaults to "paperless". Defaults to "paperless".
#### [`PAPERLESS_DBPASS=<password>`](#PAPERLESS_DBPASS) {#PAPERLESS_DBPASS} #### [`PAPERLESS_DBPASS=<password>`](#PAPERLESS_DBPASS) {#PAPERLESS_DBPASS}
: Database password for PostgreSQL or MariaDB. : Password for the PostgreSQL or MariaDB database user.
Defaults to "paperless". Defaults to "paperless".
@ -110,20 +111,20 @@ changed here.
#### [`PAPERLESS_DBSSLROOTCERT=<ca-path>`](#PAPERLESS_DBSSLROOTCERT) {#PAPERLESS_DBSSLROOTCERT} #### [`PAPERLESS_DBSSLROOTCERT=<ca-path>`](#PAPERLESS_DBSSLROOTCERT) {#PAPERLESS_DBSSLROOTCERT}
: SSL root certificate path : Path to the SSL root certificate used to verify the database server.
See [the official documentation about See [the official documentation about
sslmode for PostgreSQL](https://www.postgresql.org/docs/current/libpq-ssl.html). sslmode for PostgreSQL](https://www.postgresql.org/docs/current/libpq-ssl.html).
Changes path of `root.crt`. Changes the location of `root.crt`.
See [the official documentation about See [the official documentation about
sslmode for MySQL and MariaDB](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-ca). sslmode for MySQL and MariaDB](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-ca).
Defaults to unset, using the documented path in the home directory. Defaults to unset, using the standard location in the home directory.
#### [`PAPERLESS_DBSSLCERT=<client-cert-path>`](#PAPERLESS_DBSSLCERT) {#PAPERLESS_DBSSLCERT} #### [`PAPERLESS_DBSSLCERT=<client-cert-path>`](#PAPERLESS_DBSSLCERT) {#PAPERLESS_DBSSLCERT}
: SSL client certificate path : Path to the client SSL certificate used when connecting securely.
See [the official documentation about See [the official documentation about
sslmode for PostgreSQL](https://www.postgresql.org/docs/current/libpq-ssl.html). sslmode for PostgreSQL](https://www.postgresql.org/docs/current/libpq-ssl.html).
@ -131,13 +132,13 @@ changed here.
See [the official documentation about See [the official documentation about
sslmode for MySQL and MariaDB](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-cert). sslmode for MySQL and MariaDB](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-cert).
Changes path of `postgresql.crt`. Changes the location of `postgresql.crt`.
Defaults to unset, using the documented path in the home directory. Defaults to unset, using the standard location in the home directory.
#### [`PAPERLESS_DBSSLKEY=<client-cert-key>`](#PAPERLESS_DBSSLKEY) {#PAPERLESS_DBSSLKEY} #### [`PAPERLESS_DBSSLKEY=<client-cert-key>`](#PAPERLESS_DBSSLKEY) {#PAPERLESS_DBSSLKEY}
: SSL client key path : Path to the client SSL private key used when connecting securely.
See [the official documentation about See [the official documentation about
sslmode for PostgreSQL](https://www.postgresql.org/docs/current/libpq-ssl.html). sslmode for PostgreSQL](https://www.postgresql.org/docs/current/libpq-ssl.html).
@ -145,17 +146,70 @@ changed here.
See [the official documentation about See [the official documentation about
sslmode for MySQL and MariaDB](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-key). sslmode for MySQL and MariaDB](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-key).
Changes path of `postgresql.key`. Changes the location of `postgresql.key`.
Defaults to unset, using the documented path in the home directory. Defaults to unset, using the standard location in the home directory.
#### [`PAPERLESS_DB_TIMEOUT=<int>`](#PAPERLESS_DB_TIMEOUT) {#PAPERLESS_DB_TIMEOUT} #### [`PAPERLESS_DB_TIMEOUT=<int>`](#PAPERLESS_DB_TIMEOUT) {#PAPERLESS_DB_TIMEOUT}
: Amount of time for a database connection to wait for the database to : Sets how long a database connection should wait before timing out.
unlock. Mostly applicable for sqlite based installation. Consider changing
to postgresql if you are having concurrency problems with sqlite.
Defaults to unset, keeping the Django defaults. For SQLite, this sets how long to wait if the database is locked.
For PostgreSQL or MariaDB, this sets the connection timeout.
Defaults to unset, which uses Djangos built-in defaults.
#### [`PAPERLESS_DB_POOLSIZE=<int>`](#PAPERLESS_DB_POOLSIZE) {#PAPERLESS_DB_POOLSIZE}
: Defines the maximum number of database connections to keep in the pool.
Only applies to PostgreSQL. This setting is ignored for other database engines.
The value must be greater than or equal to 1 to be used.
Defaults to unset, which disables connection pooling.
!!! note
A small pool is typically sufficient — for example, a size of 4.
Make sure your PostgreSQL server's max_connections setting is large enough to handle:
```(Paperless workers + Celery workers) × pool size + safety margin```
For example, with 4 Paperless workers and 2 Celery workers, and a pool size of 4:
(4 + 2) × 4 + 10 = 34 connections required.
#### [`PAPERLESS_DB_READ_CACHE_ENABLED=<bool>`](#PAPERLESS_DB_READ_CACHE_ENABLED) {#PAPERLESS_DB_READ_CACHE_ENABLED}
: Caches the database read query results into Redis. This can significantly improve application response times by caching database queries, at the cost of slightly increased memory usage.
Defaults to `false`.
!!! danger
**Do not modify the database outside the application while it is running.**
This includes actions such as restoring a backup, upgrading the database, or performing manual inserts. All external modifications must be done **only when the application is stopped**.
After making any such changes, you **must invalidate the DB read cache** using the `invalidate_cachalot` management command.
#### [`PAPERLESS_READ_CACHE_TTL=<int>`](#PAPERLESS_READ_CACHE_TTL) {#PAPERLESS_READ_CACHE_TTL}
: Specifies how long (in seconds) read data should be cached.
Allowed values are between `1` (one second) and `31536000` (one year). Defaults to `3600` (one hour).
!!! warning
A high TTL increases memory usage over time. Memory may be used until end of TTL, even if the cache is invalidated with the `invalidate_cachalot` command.
In case of an out-of-memory (OOM) situation, Redis may stop accepting new data — including cache entries, scheduled tasks, and documents to consume.
If your system has limited RAM, consider configuring a dedicated Redis instance for the read cache, with a memory limit and the eviction policy set to `allkeys-lru`.
For more details, refer to the [Redis eviction policy documentation](https://redis.io/docs/latest/develop/reference/eviction/), and see the `PAPERLESS_READ_CACHE_REDIS_URL` setting to specify a separate Redis broker.
#### [`PAPERLESS_READ_CACHE_REDIS_URL=<url>`](#PAPERLESS_READ_CACHE_REDIS_URL) {#PAPERLESS_READ_CACHE_REDIS_URL}
: Defines the Redis instance used for the read cache.
Defaults to `None`.
!!! Note
If this value is not set, the same Redis instance used for scheduled tasks will be used for caching as well.
## Optional Services ## Optional Services
@ -200,7 +254,7 @@ and watch out for indentation if editing the YAML file.
### Email Parsing ### Email Parsing
#### [`PAPERLESS_EMAIL_PARSE_DEFAULT_LAYOUT=<int>`(#PAPERLESS_EMAIL_PARSE_DEFAULT_LAYOUT) {#PAPERLESS_EMAIL_PARSE_DEFAULT_LAYOUT} #### [`PAPERLESS_EMAIL_PARSE_DEFAULT_LAYOUT=<int>`](#PAPERLESS_EMAIL_PARSE_DEFAULT_LAYOUT) {#PAPERLESS_EMAIL_PARSE_DEFAULT_LAYOUT}
: The default layout to use for emails that are consumed as documents. Must be one of the integer choices below. Note that mail : The default layout to use for emails that are consumed as documents. Must be one of the integer choices below. Note that mail
rules can specify this setting, thus this fallback is used for the default selection and for .eml files consumed by other means. rules can specify this setting, thus this fallback is used for the default selection and for .eml files consumed by other means.
@ -629,7 +683,13 @@ If both the [PAPERLESS_ACCOUNT_DEFAULT_GROUPS](#PAPERLESS_ACCOUNT_DEFAULT_GROUPS
!!! note !!! note
If you do not have a working email server set up you should set this to 'none'. If you do not have a working email server set up this will be set to 'none'.
#### [`PAPERLESS_ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS=<bool>`](#PAPERLESS_ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS) {#PAPERLESS_ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS}
: See the relevant [django-allauth documentation](https://docs.allauth.org/en/latest/account/configuration.html)
Defaults to True (from allauth)
#### [`PAPERLESS_DISABLE_REGULAR_LOGIN=<bool>`](#PAPERLESS_DISABLE_REGULAR_LOGIN) {#PAPERLESS_DISABLE_REGULAR_LOGIN} #### [`PAPERLESS_DISABLE_REGULAR_LOGIN=<bool>`](#PAPERLESS_DISABLE_REGULAR_LOGIN) {#PAPERLESS_DISABLE_REGULAR_LOGIN}
@ -920,21 +980,10 @@ paperless will process in parallel on a single document.
process very large documents faster, use a higher thread per worker process very large documents faster, use a higher thread per worker
count. count.
The default is a balance between the two, according to your CPU core If unset, paperless uses `max(floor(cpu_count / PAPERLESS_TASK_WORKERS), 1)`
count, with a slight favor towards threads per worker: threads per worker. The idea behind this is that as long as there are enough cores,
the total number of threads should less than or equal to the total number of (logical)
| CPU core count | Workers | Threads | CPU cores.
| -------------- | ------- | ------- |
| > 1 | > 1 | > 1 |
| > 2 | > 2 | > 1 |
| > 4 | > 2 | > 2 |
| > 6 | > 2 | > 3 |
| > 8 | > 2 | > 4 |
| > 12 | > 3 | > 4 |
| > 16 | > 4 | > 4 |
If you only specify PAPERLESS_TASK_WORKERS, paperless will adjust
PAPERLESS_THREADS_PER_WORKER automatically.
#### [`PAPERLESS_WORKER_TIMEOUT=<num>`](#PAPERLESS_WORKER_TIMEOUT) {#PAPERLESS_WORKER_TIMEOUT} #### [`PAPERLESS_WORKER_TIMEOUT=<num>`](#PAPERLESS_WORKER_TIMEOUT) {#PAPERLESS_WORKER_TIMEOUT}
@ -960,6 +1009,22 @@ still perform some basic text pre-processing before matching.
Defaults to 1. Defaults to 1.
#### [`PAPERLESS_DATE_PARSER_LANGUAGES=<lang>`](#PAPERLESS_DATE_PARSER_LANGUAGES) {#PAPERLESS_DATE_PARSER_LANGUAGES}
Specifies which language Paperless should use when parsing dates from documents.
This should be a language code supported by the dateparser library,
for example: "en", or a combination such as "en+de".
Locales are also supported (e.g., "en-AU").
Multiple languages can be combined using "+", for example: "en+de" or "en-AU+de".
For valid values, refer to the list of supported languages and locales in the [dateparser documentation](https://dateparser.readthedocs.io/en/latest/supported_locales.html).
Set this to match the languages in which most of your documents are written.
If not set, Paperless will attempt to infer the language(s) from the OCR configuration (`PAPERLESS_OCR_LANGUAGE`).
!!! note
This format differs from the `PAPERLESS_OCR_LANGUAGE` setting, which uses ISO 639-2 codes (3 letters, e.g., "eng+deu" for Tesseract OCR).
#### [`PAPERLESS_EMAIL_TASK_CRON=<cron expression>`](#PAPERLESS_EMAIL_TASK_CRON) {#PAPERLESS_EMAIL_TASK_CRON} #### [`PAPERLESS_EMAIL_TASK_CRON=<cron expression>`](#PAPERLESS_EMAIL_TASK_CRON) {#PAPERLESS_EMAIL_TASK_CRON}
: Configures the scheduled email fetching frequency. The value : Configures the scheduled email fetching frequency. The value
@ -989,12 +1054,22 @@ should be a valid crontab(5) expression describing when to run.
#### [`PAPERLESS_SANITY_TASK_CRON=<cron expression>`](#PAPERLESS_SANITY_TASK_CRON) {#PAPERLESS_SANITY_TASK_CRON} #### [`PAPERLESS_SANITY_TASK_CRON=<cron expression>`](#PAPERLESS_SANITY_TASK_CRON) {#PAPERLESS_SANITY_TASK_CRON}
: Configures the scheduled sanity checker frequency. : Configures the scheduled sanity checker frequency. The value should be a
valid crontab(5) expression describing when to run.
: If set to the string "disable", the sanity checker will not run automatically. : If set to the string "disable", the sanity checker will not run automatically.
Defaults to `30 0 * * sun` or Sunday at 30 minutes past midnight. Defaults to `30 0 * * sun` or Sunday at 30 minutes past midnight.
#### [`PAPERLESS_WORKFLOW_SCHEDULED_TASK_CRON=<cron expression>`](#PAPERLESS_WORKFLOW_SCHEDULED_TASK_CRON) {#PAPERLESS_WORKFLOW_SCHEDULED_TASK_CRON}
: Configures the scheduled workflow check frequency. The value should be a
valid crontab(5) expression describing when to run.
: If set to the string "disable", scheduled workflows will not run.
Defaults to `5 */1 * * *` or every hour at 5 minutes past the hour.
#### [`PAPERLESS_ENABLE_COMPRESSION=<bool>`](#PAPERLESS_ENABLE_COMPRESSION) {#PAPERLESS_ENABLE_COMPRESSION} #### [`PAPERLESS_ENABLE_COMPRESSION=<bool>`](#PAPERLESS_ENABLE_COMPRESSION) {#PAPERLESS_ENABLE_COMPRESSION}
: Enables compression of the responses from the webserver. : Enables compression of the responses from the webserver.
@ -1057,9 +1132,9 @@ be used with caution!
## Document Consumption {#consume_config} ## Document Consumption {#consume_config}
#### [`PAPERLESS_CONSUMER_DISABLE=<bool>`](#PAPERLESS_CONSUMER_DISABLE) {#PAPERLESS_CONSUMER_DISABLE} #### [`PAPERLESS_CONSUMER_DISABLE`](#PAPERLESS_CONSUMER_DISABLE) {#PAPERLESS_CONSUMER_DISABLE}
: Completely disable the directory-based consumer in docker. If you don't plan to consume documents : If set (to anything), this completely disables the directory-based consumer in docker. If you don't plan to consume documents
via the consumption directory, you can disable the consumer to save resources. via the consumption directory, you can disable the consumer to save resources.
#### [`PAPERLESS_CONSUMER_DELETE_DUPLICATES=<bool>`](#PAPERLESS_CONSUMER_DELETE_DUPLICATES) {#PAPERLESS_CONSUMER_DELETE_DUPLICATES} #### [`PAPERLESS_CONSUMER_DELETE_DUPLICATES=<bool>`](#PAPERLESS_CONSUMER_DELETE_DUPLICATES) {#PAPERLESS_CONSUMER_DELETE_DUPLICATES}
@ -1249,6 +1324,30 @@ consumers working on the same file. Configure this to prevent that.
Defaults to 0.5 seconds. Defaults to 0.5 seconds.
## Workflow webhooks
#### [`PAPERLESS_WEBHOOKS_ALLOWED_SCHEMES=<str>`](#PAPERLESS_WEBHOOKS_ALLOWED_SCHEMES) {#PAPERLESS_WEBHOOKS_ALLOWED_SCHEMES}
: A comma-separated list of allowed schemes for webhooks. This setting
controls which URL schemes are permitted for webhook URLs.
Defaults to `http,https`.
#### [`PAPERLESS_WEBHOOKS_ALLOWED_PORTS=<str>`](#PAPERLESS_WEBHOOKS_ALLOWED_PORTS) {#PAPERLESS_WEBHOOKS_ALLOWED_PORTS}
: A comma-separated list of allowed ports for webhooks. This setting
controls which ports are permitted for webhook URLs. For example, if you
set this to `80,443`, webhooks will only be sent to URLs that use these
ports.
Defaults to empty list, which allows all ports.
#### [`PAPERLESS_WEBHOOKS_ALLOW_INTERNAL_REQUESTS=<bool>`](#PAPERLESS_WEBHOOKS_ALLOW_INTERNAL_REQUESTS) {#PAPERLESS_WEBHOOKS_ALLOW_INTERNAL_REQUESTS}
: If set to false, webhooks cannot be sent to internal URLs (e.g., localhost).
Defaults to true, which allows internal requests.
## Incoming Mail {#incoming_mail} ## Incoming Mail {#incoming_mail}
### Email OAuth {#email_oauth} ### Email OAuth {#email_oauth}
@ -1659,6 +1758,11 @@ started by the container.
: Path to an image file in the /media/logo directory, must include 'logo', e.g. `/logo/Atari_logo.svg` : Path to an image file in the /media/logo directory, must include 'logo', e.g. `/logo/Atari_logo.svg`
!!! note
The logo file will be viewable by anyone with access to the Paperless instance login page,
so consider your choice of logo carefully and removing exif data from images before uploading.
#### [`PAPERLESS_ENABLE_UPDATE_CHECK=<bool>`](#PAPERLESS_ENABLE_UPDATE_CHECK) {#PAPERLESS_ENABLE_UPDATE_CHECK} #### [`PAPERLESS_ENABLE_UPDATE_CHECK=<bool>`](#PAPERLESS_ENABLE_UPDATE_CHECK) {#PAPERLESS_ENABLE_UPDATE_CHECK}
!!! note !!! note
@ -1670,7 +1774,7 @@ started by the container.
## Email sending ## Email sending
Setting an SMTP server for the backend will allow you to reset your Setting an SMTP server for the backend will allow you to use the Email workflow action, send documents from the UI as well as reset your
password. All of these options come from their similarly-named [Django settings](https://docs.djangoproject.com/en/4.2/ref/settings/#email-host) password. All of these options come from their similarly-named [Django settings](https://docs.djangoproject.com/en/4.2/ref/settings/#email-host)
#### [`PAPERLESS_EMAIL_HOST=<str>`](#PAPERLESS_EMAIL_HOST) {#PAPERLESS_EMAIL_HOST} #### [`PAPERLESS_EMAIL_HOST=<str>`](#PAPERLESS_EMAIL_HOST) {#PAPERLESS_EMAIL_HOST}

View File

@ -95,13 +95,13 @@ first-time setup.
7. You can now either ... 7. You can now either ...
- install redis or - install Redis or
- use the included `scripts/start_services.sh` to use docker to fire - use the included `scripts/start_services.sh` to use Docker to fire
up a redis instance (and some other services such as tika, up a Redis instance (and some other services such as Tika,
gotenberg and a database server) or Gotenberg and a database server) or
- spin up a bare redis container - spin up a bare Redis container
``` ```
docker run -d -p 6379:6379 --restart unless-stopped redis:latest docker run -d -p 6379:6379 --restart unless-stopped redis:latest
@ -147,7 +147,7 @@ $ ng build --configuration production
### Testing ### Testing
- Run `pytest` in the `src/` directory to execute all tests. This also - Run `pytest` in the `src/` directory to execute all tests. This also
generates a HTML coverage report. When runnings test, `paperless.conf` generates a HTML coverage report. When running tests, `paperless.conf`
is loaded as well. However, the tests rely on the default is loaded as well. However, the tests rely on the default
configuration. This is not ideal. But for now, make sure no settings configuration. This is not ideal. But for now, make sure no settings
except for DEBUG are overridden when testing. except for DEBUG are overridden when testing.
@ -470,9 +470,14 @@ To get started:
2. VS Code will prompt you with "Reopen in container". Do so and wait for the environment to start. 2. VS Code will prompt you with "Reopen in container". Do so and wait for the environment to start.
3. Initialize the project by running the task **Project Setup: Run all Init Tasks**. This 3. In case your host operating system is Windows:
- The Source Control view in Visual Studio Code might show: "The detected Git repository is potentially unsafe as the folder is owned by someone other than the current user." Use "Manage Unsafe Repositories" to fix this.
- Git might have detecteded modifications for all files, because Windows is using CRLF line endings. Run `git checkout .` in the containers terminal to fix this issue.
4. Initialize the project by running the task **Project Setup: Run all Init Tasks**. This
will initialize the database tables and create a superuser. Then you can compile the front end will initialize the database tables and create a superuser. Then you can compile the front end
for production or run the frontend in debug mode. for production or run the frontend in debug mode.
4. The project is ready for debugging, start either run the fullstack debug or individual debug 5. The project is ready for debugging, start either run the fullstack debug or individual debug
processes. Yo spin up the project without debugging run the task **Project Start: Run all Services** processes. Yo spin up the project without debugging run the task **Project Start: Run all Services**

View File

@ -112,30 +112,6 @@ able to run paperless, you're a bit on your own. If you can't run the
docker image, the documentation has instructions for bare metal docker image, the documentation has instructions for bare metal
installs. installs.
## _How do I proxy this with NGINX?_
**A:** See [the wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Using-a-Reverse-Proxy-with-Paperless-ngx#nginx).
## _How do I get WebSocket support with Apache mod_wsgi_?
**A:** `mod_wsgi` by itself does not support ASGI. Paperless will
continue to work with WSGI, but certain features such as status
notifications about document consumption won't be available.
If you want to continue using `mod_wsgi`, you will have to run an
ASGI-enabled web server as well that processes WebSocket connections,
and configure Apache to redirect WebSocket connections to this server.
Multiple options for ASGI servers exist:
- `gunicorn` with `uvicorn` as the worker implementation (the default
of paperless)
- `daphne` as a standalone server, which is the reference
implementation for ASGI.
- `uvicorn` as a standalone server
You may also find the [Django documentation](https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/) on ASGI
useful to review.
## _What about the Redis licensing change and using one of the open source forks_? ## _What about the Redis licensing change and using one of the open source forks_?
Currently (October 2024), forks of Redis such as Valkey or Redirect are not officially supported by our upstream Currently (October 2024), forks of Redis such as Valkey or Redirect are not officially supported by our upstream

View File

@ -30,7 +30,7 @@ physical documents into a searchable online archive so you can keep, well, _less
- Utilizes the open-source Tesseract engine to recognize more than 100 languages. - Utilizes the open-source Tesseract engine to recognize more than 100 languages.
- Documents are saved as PDF/A format which is designed for long term storage, alongside the unaltered originals. - Documents are saved as PDF/A format which is designed for long term storage, alongside the unaltered originals.
- Uses machine-learning to automatically add tags, correspondents and document types to your documents. - Uses machine-learning to automatically add tags, correspondents and document types to your documents.
- Supports PDF documents, images, plain text files, Office documents (Word, Excel, Powerpoint, and LibreOffice equivalents)[^1] and more. - Supports PDF documents, images, plain text files, Office documents (Word, Excel, PowerPoint, and LibreOffice equivalents)[^1] and more.
- Paperless stores your documents plain on disk. Filenames and folders are managed by paperless and their format can be configured freely with different configurations assigned to different documents. - Paperless stores your documents plain on disk. Filenames and folders are managed by paperless and their format can be configured freely with different configurations assigned to different documents.
- **Beautiful, modern web application** that features: - **Beautiful, modern web application** that features:
- Customizable dashboard with statistics. - Customizable dashboard with statistics.

View File

@ -326,7 +326,7 @@ are released, dependency support is confirmed, etc.
!!! warning !!! warning
Ensure your Redis instance [is secured](https://redis.io/docs/getting-started/#securing-redis). Ensure your Redis instance [is secured](https://redis.io/docs/latest/operate/oss_and_stack/management/security/).
7. Create the following directories if they are missing: 7. Create the following directories if they are missing:
@ -445,7 +445,7 @@ are released, dependency support is confirmed, etc.
13. Configure ImageMagick to allow processing of PDF documents. Most 13. Configure ImageMagick to allow processing of PDF documents. Most
distributions have this disabled by default, since PDF documents can distributions have this disabled by default, since PDF documents can
contain malware. If you don't do this, paperless will fall back to contain malware. If you don't do this, paperless will fall back to
ghostscript for certain steps such as thumbnail generation. Ghostscript for certain steps such as thumbnail generation.
Edit `/etc/ImageMagick-6/policy.xml` and adjust Edit `/etc/ImageMagick-6/policy.xml` and adjust

View File

@ -33,7 +33,7 @@ warns that
`OCR for XX failed, but we're going to stick with what we've got since FORGIVING_OCR is enabled`, `OCR for XX failed, but we're going to stick with what we've got since FORGIVING_OCR is enabled`,
then you might need to install the [Tesseract language then you might need to install the [Tesseract language
files](https://packages.ubuntu.com/search?keywords=tesseract-ocr) files](https://packages.ubuntu.com/search?keywords=tesseract-ocr)
marching your document's languages. matching your document's languages.
As an example, if you are running Paperless-ngx from any Ubuntu or As an example, if you are running Paperless-ngx from any Ubuntu or
Debian box, and your documents are written in Spanish you may need to Debian box, and your documents are written in Spanish you may need to
@ -130,7 +130,7 @@ command:
- 'gotenberg' - 'gotenberg'
- '--chromium-disable-javascript=true' - '--chromium-disable-javascript=true'
- '--chromium-allow-list=file:///tmp/.*' - '--chromium-allow-list=file:///tmp/.*'
- '--api-timeout=60' - '--api-timeout=60s'
``` ```
## Permission denied errors in the consumption directory ## Permission denied errors in the consumption directory
@ -335,7 +335,7 @@ You may see errors when deleting documents like:
Data too long for column 'transaction_id' at row 1 Data too long for column 'transaction_id' at row 1
``` ```
This error can occur in installations which have upgraded from a version of Paperless-ngx that used Django 4 (Paperless-ngx versions prior to v2.13.0) with a MariaDB/MySQL database. Due to the backawards-incompatible change in Django 5, the column "documents_document.transaction_id" will need to be re-created, which can be done with a one-time run of the following management command: This error can occur in installations which have upgraded from a version of Paperless-ngx that used Django 4 (Paperless-ngx versions prior to v2.13.0) with a MariaDB/MySQL database. Due to the backwards-incompatible change in Django 5, the column "documents_document.transaction_id" will need to be re-created, which can be done with a one-time run of the following management command:
```shell-session ```shell-session
$ python3 manage.py convert_mariadb_uuid $ python3 manage.py convert_mariadb_uuid

View File

@ -30,6 +30,9 @@ Each document has data fields that you can assign to them:
- A _document type_ is used to demarcate the type of a document such - A _document type_ is used to demarcate the type of a document such
as letter, bank statement, invoice, contract, etc. It is used to as letter, bank statement, invoice, contract, etc. It is used to
identify what a document is about. identify what a document is about.
- The document _storage path_ is the location where the document files
are stored. See [Storage Paths](advanced_usage.md#storage-paths) for
more information.
- The _date added_ of a document is the date the document was scanned - The _date added_ of a document is the date the document was scanned
into paperless. You cannot and should not change this date. into paperless. You cannot and should not change this date.
- The _date created_ of a document is the date the document was - The _date created_ of a document is the date the document was
@ -89,7 +92,17 @@ and more. These areas allow you to view, add, edit, delete and manage permission
for these objects. You can also manage saved views, mail accounts, mail rules, for these objects. You can also manage saved views, mail accounts, mail rules,
workflows and more from the management sections. workflows and more from the management sections.
## Adding documents to paperless ### Nested Tags
Paperless-ngx v2.19 introduces support for nested tags, allowing you to create a
hierarchy of tags, which may be useful for organizing your documents. Tags can
have a 'parent' tag, creating a tree-like structure, to a maximum depth of 5. When
a tag is added to a document, all of its parent tags are also added automatically
and similarly, when a tag is removed from a document, all of its child tags are
also removed. Additionally, assigning a parent to an existing tag will automatically
update all documents that have this tag assigned, adding the parent tag as well.
## Adding documents to Paperless-ngx
Once you've got Paperless setup, you need to start feeding documents Once you've got Paperless setup, you need to start feeding documents
into it. When adding documents to paperless, it will perform the into it. When adding documents to paperless, it will perform the
@ -115,7 +128,8 @@ following operations on your documents:
No matter which options you choose, Paperless will always store the No matter which options you choose, Paperless will always store the
original document that it found in the consumption directory or in the original document that it found in the consumption directory or in the
mail and will never overwrite that document. Archived versions are mail and will never overwrite that document (except when using certain
document actions, which make that clear). Archived versions are
stored alongside the original versions. Any files found in the stored alongside the original versions. Any files found in the
consumption directory will stored inside the Paperless-ngx file consumption directory will stored inside the Paperless-ngx file
structure and will not be retained in the consumption directory. structure and will not be retained in the consumption directory.
@ -159,7 +173,7 @@ process.
Please see [the wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Related-Projects) for a user-maintained list of related projects and Please see [the wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Related-Projects) for a user-maintained list of related projects and
software (e.g. for mobile devices) that is compatible with Paperless-ngx. software (e.g. for mobile devices) that is compatible with Paperless-ngx.
### Email {#usage-email} ### Incoming Email {#incoming-mail}
You can tell paperless-ngx to consume documents from your email You can tell paperless-ngx to consume documents from your email
accounts. This is a very flexible and powerful feature, if you regularly accounts. This is a very flexible and powerful feature, if you regularly
@ -247,6 +261,10 @@ different means. These are as follows:
Paperless is set up to check your mails every 10 minutes. This can be Paperless is set up to check your mails every 10 minutes. This can be
configured via [`PAPERLESS_EMAIL_TASK_CRON`](configuration.md#PAPERLESS_EMAIL_TASK_CRON) configured via [`PAPERLESS_EMAIL_TASK_CRON`](configuration.md#PAPERLESS_EMAIL_TASK_CRON)
#### Processed Mail
Paperless keeps track of emails it has processed in order to avoid processing the same mail multiple times. This uses the message `UID` provided by the mail server, which should be unique for each message. You can view and manage processed mails from the web UI under Mail > Processed Mails. If you need to re-process a message, you can delete the corresponding processed mail entry, which will allow Paperless-ngx to process the email again the next time the mail fetch task runs.
#### OAuth Email Setup #### OAuth Email Setup
Paperless-ngx supports OAuth2 authentication for Gmail and Outlook email accounts. To set up an email account with OAuth2, you will need to create a 'developer' app with the respective provider and obtain the client ID and client secret and set the appropriate [configuration variables](configuration.md#email_oauth). You will also need to set either [`PAPERLESS_OAUTH_CALLBACK_BASE_URL`](configuration.md#PAPERLESS_OAUTH_CALLBACK_BASE_URL) or [`PAPERLESS_URL`](configuration.md#PAPERLESS_URL) to the correct value for the OAuth2 flow to work correctly. Paperless-ngx supports OAuth2 authentication for Gmail and Outlook email accounts. To set up an email account with OAuth2, you will need to create a 'developer' app with the respective provider and obtain the client ID and client secret and set the appropriate [configuration variables](configuration.md#email_oauth). You will also need to set either [`PAPERLESS_OAUTH_CALLBACK_BASE_URL`](configuration.md#PAPERLESS_OAUTH_CALLBACK_BASE_URL) or [`PAPERLESS_URL`](configuration.md#PAPERLESS_URL) to the correct value for the OAuth2 flow to work correctly.
@ -260,6 +278,31 @@ Once setup, navigating to the email settings page in Paperless-ngx will allow yo
You can also submit a document using the REST API, see [POSTing documents](api.md#file-uploads) You can also submit a document using the REST API, see [POSTing documents](api.md#file-uploads)
for details. for details.
## Sharing documents from Paperless-ngx
Paperless-ngx supports sharing documents with other users by assigning them [permissions](#object-permissions)
to the document. Document files can also be shared externally via [share links](#share-links), [email](#email-sharing)
or using [email](#workflow-action-email) or [webhook](#workflow-action-webhook) actions in workflows.
### Share Links
"Share links" are shareable public links to files and can be created and managed under the 'Send' button on the document detail screen.
- Share links do not require a user to login and thus link directly to a file.
- Links are unique and are of the form `{paperless-url}/share/{randomly-generated-slug}`.
- Links can optionally have an expiration time set.
- After a link expires or is deleted users will be redirected to the regular paperless-ngx login.
!!! tip
If your paperless-ngx instance is behind a reverse-proxy you may want to create an exception to bypass any authentication layers that are part of your setup in order to make links truly publicly-accessible. Of course, do so with caution.
### Email Sharing {#email-sharing}
Paperless-ngx supports directly sending documents via email. If an email server has been [configured](configuration.md#email-sending)
the "Send" button on the document detail page will include an "Email" option. You can also share files via email automatically by using
a [workflow action](#workflow-action-email).
## Permissions ## Permissions
Permissions in Paperless-ngx are based around ['global' permissions](#global-permissions) as well as Permissions in Paperless-ngx are based around ['global' permissions](#global-permissions) as well as
@ -313,7 +356,7 @@ determine if a user can create, edit, delete or view _any_ documents, but indivi
still have "object-level" permissions. still have "object-level" permissions.
| Type | Details | | Type | Details |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| AppConfig | _Change_ or higher permissions grants access to the "Application Configuration" area. | | AppConfig | _Change_ or higher permissions grants access to the "Application Configuration" area. |
| Correspondent | Add, edit, delete or view Correspondents. | | Correspondent | Add, edit, delete or view Correspondents. |
| CustomField | Add, edit, delete or view Custom Fields. | | CustomField | Add, edit, delete or view Custom Fields. |
@ -330,7 +373,7 @@ still have "object-level" permissions.
| Tag | Add, edit, delete or view Tags. | | Tag | Add, edit, delete or view Tags. |
| UISettings | Add, edit, delete or view the UI settings that are used by the web app.<br/>:warning: **Users that will access the web UI must be granted at least _View_ permissions.** | | UISettings | Add, edit, delete or view the UI settings that are used by the web app.<br/>:warning: **Users that will access the web UI must be granted at least _View_ permissions.** |
| User | Add, edit, delete or view Users. | | User | Add, edit, delete or view Users. |
| Workflow | Add, edit, delete or view Workflows.<br/>Note that Workflows are global, in other words all users who can access workflows have access to the same set of them. | | Workflow | Add, edit, delete or view Workflows.<br/>Note that Workflows are global; all users who can access workflows see the same set. Workflows have other permission implications — see [Workflow permissions](#workflow-permissions). |
#### Detailed Explanation of Object Permissions {#object-permissions} #### Detailed Explanation of Object Permissions {#object-permissions}
@ -369,9 +412,9 @@ fields and permissions, which will be merged.
### Workflow Triggers ### Workflow Triggers
#### Types #### Types {#workflow-trigger-types}
Currently, there are three events that correspond to workflow trigger 'types': Currently, there are four events that correspond to workflow trigger 'types':
1. **Consumption Started**: _before_ a document is consumed, so events can include filters by source (mail, consumption 1. **Consumption Started**: _before_ a document is consumed, so events can include filters by source (mail, consumption
folder or API), file path, file name, mail rule folder or API), file path, file name, mail rule
@ -379,11 +422,12 @@ Currently, there are three events that correspond to workflow trigger 'types':
but the document content has been extracted and metadata such as document type, tags, etc. have been set, so these can now but the document content has been extracted and metadata such as document type, tags, etc. have been set, so these can now
be used for filtering. be used for filtering.
3. **Document Updated**: when a document is updated. Similar to 'added' events, triggers can include filtering by content matching, 3. **Document Updated**: when a document is updated. Similar to 'added' events, triggers can include filtering by content matching,
tags, doc type, or correspondent. tags, doc type, correspondent or storage path.
4. **Scheduled**: a scheduled trigger that can be used to run workflows at a specific time. The date used can be either the document 4. **Scheduled**: a scheduled trigger that can be used to run workflows at a specific time. The date used can be either the document
added, created, updated date or you can specify a (date) custom field. You can also specify a day offset from the date. added, created, updated date or you can specify a (date) custom field. You can also specify a day offset from the date (positive
offsets will trigger after the date, negative offsets will trigger before).
The following flow diagram illustrates the three document trigger types: The following flow diagram illustrates the four document trigger types:
```mermaid ```mermaid
flowchart TD flowchart TD
@ -399,6 +443,10 @@ flowchart TD
'Updated' 'Updated'
trigger(s)"} trigger(s)"}
scheduled{"Documents
matching
trigger(s)"}
A[New Document] --> consumption A[New Document] --> consumption
consumption --> |Yes| C[Workflow Actions Run] consumption --> |Yes| C[Workflow Actions Run]
consumption --> |No| D consumption --> |No| D
@ -411,6 +459,11 @@ flowchart TD
updated --> |Yes| J[Workflow Actions Run] updated --> |Yes| J[Workflow Actions Run]
updated --> |No| K updated --> |No| K
J --> K[Document Saved] J --> K[Document Saved]
L[Scheduled Task Check<br/>hourly at :05] --> M[Get All Scheduled Triggers]
M --> scheduled
scheduled --> |Yes| N[Workflow Actions Run]
scheduled --> |No| O[Document Saved]
N --> O
``` ```
#### Filters {#workflow-trigger-filters} #### Filters {#workflow-trigger-filters}
@ -418,22 +471,32 @@ flowchart TD
Workflows allow you to filter by: Workflows allow you to filter by:
- Source, e.g. documents uploaded via consume folder, API (& the web UI) and mail fetch - Source, e.g. documents uploaded via consume folder, API (& the web UI) and mail fetch
- File name, including wildcards e.g. \*.pdf will apply to all pdfs - File name, including wildcards e.g. \*.pdf will apply to all pdfs.
- File path, including wildcards. Note that enabling `PAPERLESS_CONSUMER_RECURSIVE` would allow, for - File path, including wildcards. Note that enabling `PAPERLESS_CONSUMER_RECURSIVE` would allow, for
example, automatically assigning documents to different owners based on the upload directory. example, automatically assigning documents to different owners based on the upload directory.
- Mail rule. Choosing this option will force 'mail fetch' to be the workflow source. - Mail rule. Choosing this option will force 'mail fetch' to be the workflow source.
- Content matching (`Added` and `Updated` triggers only). Filter document content using the matching settings. - Content matching (`Added`, `Updated` and `Scheduled` triggers only). Filter document content using the matching settings.
- Tags (`Added` and `Updated` triggers only). Filter for documents with any of the specified tags
- Document type (`Added` and `Updated` triggers only). Filter documents with this doc type There are also 'advanced' filters available for `Added`, `Updated` and `Scheduled` triggers:
- Correspondent (`Added` and `Updated` triggers only). Filter documents with this correspondent
- Any Tags: Filter for documents with any of the specified tags.
- All Tags: Filter for documents with all of the specified tags.
- No Tags: Filter for documents with none of the specified tags.
- Document type: Filter documents with this document type.
- Not Document types: Filter documents without any of these document types.
- Correspondent: Filter documents with this correspondent.
- Not Correspondents: Filter documents without any of these correspondents.
- Storage path: Filter documents with this storage path.
- Not Storage paths: Filter documents without any of these storage paths.
- Custom field query: Filter documents with a custom field query (the same as used for the document list filters).
### Workflow Actions ### Workflow Actions
#### Types #### Types {#workflow-action-types}
The following workflow action types are available: The following workflow action types are available:
##### Assignment ##### Assignment {#workflow-action-assignment}
"Assignment" actions can assign: "Assignment" actions can assign:
@ -443,7 +506,7 @@ The following workflow action types are available:
- View and / or edit permissions to users or groups - View and / or edit permissions to users or groups
- Custom fields. Note that no value for the field will be set - Custom fields. Note that no value for the field will be set
##### Removal ##### Removal {#workflow-action-removal}
"Removal" actions can remove either all of or specific sets of the following: "Removal" actions can remove either all of or specific sets of the following:
@ -452,7 +515,7 @@ The following workflow action types are available:
- View and / or edit permissions - View and / or edit permissions
- Custom fields - Custom fields
##### Email ##### Email {#workflow-action-email}
"Email" actions can send documents via email. This action requires a mail server to be [configured](configuration.md#email-sending). You can specify: "Email" actions can send documents via email. This action requires a mail server to be [configured](configuration.md#email-sending). You can specify:
@ -460,7 +523,7 @@ The following workflow action types are available:
- The subject and body of the email, which can include placeholders, see [placeholders](usage.md#workflow-placeholders) below - The subject and body of the email, which can include placeholders, see [placeholders](usage.md#workflow-placeholders) below
- Whether to include the document as an attachment - Whether to include the document as an attachment
##### Webhook ##### Webhook {#workflow-action-webhook}
"Webhook" actions send a POST request to a specified URL. You can specify: "Webhook" actions send a POST request to a specified URL. You can specify:
@ -469,44 +532,66 @@ The following workflow action types are available:
- Encoding for the request body, either JSON or form data - Encoding for the request body, either JSON or form data
- The request headers as key-value pairs - The request headers as key-value pairs
For security reasons, webhooks can be limited to specific ports and disallowed from connecting to local URLs. See the relevant
[configuration settings](configuration.md#workflow-webhooks) to change this behavior. If you are allowing non-admins to create workflows,
you may want to adjust these settings to prevent abuse.
#### Workflow placeholders #### Workflow placeholders
Some workflow text can include placeholders but the available options differ depending on the type of Titles can be assigned by workflows using [Jinja templates](https://jinja.palletsprojects.com/en/3.1.x/templates/).
workflow trigger. This is because at the time of consumption (when the text is to be set), no automatic tags etc. have been This allows for complex logic to be used to generate the title, including [logical structures](https://jinja.palletsprojects.com/en/3.1.x/templates/#list-of-control-structures)
applied. You can use the following placeholders with any trigger type: and [filters](https://jinja.palletsprojects.com/en/3.1.x/templates/#id11).
The template is provided as a string.
- `{correspondent}`: assigned correspondent name Using Jinja2 Templates is also useful for [Date localization](advanced_usage.md#Date-Localization) in the title.
- `{document_type}`: assigned document type name
- `{owner_username}`: assigned owner username The available inputs differ depending on the type of workflow trigger.
- `{added}`: added datetime This is because at the time of consumption (when the text is to be set), no automatic tags etc. have been
- `{added_year}`: added year applied. You can use the following placeholders in the template with any trigger type:
- `{added_year_short}`: added year
- `{added_month}`: added month - `{{correspondent}}`: assigned correspondent name
- `{added_month_name}`: added month name - `{{document_type}}`: assigned document type name
- `{added_month_name_short}`: added month short name - `{{owner_username}}`: assigned owner username
- `{added_day}`: added day - `{{added}}`: added datetime
- `{added_time}`: added time in HH:MM format - `{{added_year}}`: added year
- `{original_filename}`: original file name without extension - `{{added_year_short}}`: added year
- `{filename}`: current file name without extension - `{{added_month}}`: added month
- `{{added_month_name}}`: added month name
- `{{added_month_name_short}}`: added month short name
- `{{added_day}}`: added day
- `{{added_time}}`: added time in HH:MM format
- `{{original_filename}}`: original file name without extension
- `{{filename}}`: current file name without extension
- `{{doc_title}}`: current document title
The following placeholders are only available for "added" or "updated" triggers The following placeholders are only available for "added" or "updated" triggers
- `{created}`: created datetime - `{{created}}`: created datetime
- `{created_year}`: created year - `{{created_year}}`: created year
- `{created_year_short}`: created year - `{{created_year_short}}`: created year
- `{created_month}`: created month - `{{created_month}}`: created month
- `{created_month_name}`: created month name - `{{created_month_name}}`: created month name
- `{created_month_name_short}`: created month short name - `{created_month_name_short}}`: created month short name
- `{created_day}`: created day - `{{created_day}}`: created day
- `{created_time}`: created time in HH:MM format - `{{created_time}}`: created time in HH:MM format
- `{doc_url}`: URL to the document in the web UI. Requires the `PAPERLESS_URL` setting to be set. - `{{doc_url}}`: URL to the document in the web UI. Requires the `PAPERLESS_URL` setting to be set.
##### Examples
```jinja2
{{ created | localize_date('MMMM', 'en_US') }}
<!-- Output: "January" -->
{{ added | localize_date('MMMM', 'de_DE') }}
<!-- Output: "Juni" --> # codespell:ignore
```
### Workflow permissions ### Workflow permissions
All users who have application permissions for editing workflows can see the same set All users who have application permissions for editing workflows can see the same set
of workflows. In other words, workflows themselves intentionally do not have an owner or permissions. of workflows. In other words, workflows themselves intentionally do not have an owner or permissions.
Given their potentially far-reaching capabilities, you may want to restrict access to workflows. Given their potentially far-reaching capabilities, including changing the permissions of existing documents, you may want to restrict access to workflows.
Upon migration, existing installs will grant access to workflows to users who can add Upon migration, existing installs will grant access to workflows to users who can add
documents (and superusers who can always access all parts of the app). documents (and superusers who can always access all parts of the app).
@ -544,27 +629,16 @@ The following custom field types are supported:
- `Document Link`: reference(s) to other document(s) displayed as links, automatically creates a symmetrical link in reverse - `Document Link`: reference(s) to other document(s) displayed as links, automatically creates a symmetrical link in reverse
- `Select`: a pre-defined list of strings from which the user can choose - `Select`: a pre-defined list of strings from which the user can choose
## Share Links
Paperless-ngx added the ability to create shareable links to files in version 2.0. You can find the button for this on the document detail screen.
- Share links do not require a user to login and thus link directly to a file.
- Links are unique and are of the form `{paperless-url}/share/{randomly-generated-slug}`.
- Links can optionally have an expiration time set.
- After a link expires or is deleted users will be redirected to the regular paperless-ngx login.
!!! tip
If your paperless-ngx instance is behind a reverse-proxy you may want to create an exception to bypass any authentication layers that are part of your setup in order to make links truly publicly-accessible. Of course, do so with caution.
## PDF Actions ## PDF Actions
Paperless-ngx supports four basic editing operations for PDFs (these operations currently cannot be performed on non-PDF files): Paperless-ngx supports basic editing operations for PDFs (these operations currently cannot be performed on non-PDF files). When viewing an individual document you can
open the 'PDF Editor' to use a simple UI for re-arranging, rotating, deleting pages and splitting documents.
- Merging documents: available when selecting multiple documents for 'bulk editing'. - Merging documents: available when selecting multiple documents for 'bulk editing'.
- Rotating documents: available when selecting multiple documents for 'bulk editing' and from an individual document's details page. - Rotating documents: available when selecting multiple documents for 'bulk editing' and via the pdf editor on an individual document's details page.
- Splitting documents: available from an individual document's details page. - Splitting documents: via the pdf editor on an individual document's details page.
- Deleting pages: available from an individual document's details page. - Deleting pages: via the pdf editor on an individual document's details page.
- Re-arranging pages: via the pdf editor on an individual document's details page.
!!! important !!! important
@ -582,7 +656,7 @@ When you first delete a document it is moved to the 'trash' until either it is e
You can set how long documents remain in the trash before being automatically deleted with [`PAPERLESS_EMPTY_TRASH_DELAY`](configuration.md#PAPERLESS_EMPTY_TRASH_DELAY), which defaults You can set how long documents remain in the trash before being automatically deleted with [`PAPERLESS_EMPTY_TRASH_DELAY`](configuration.md#PAPERLESS_EMPTY_TRASH_DELAY), which defaults
to 30 days. Until the file is actually deleted (e.g. the trash is emptied), all files and database content remains intact and can be restored at any point up until that time. to 30 days. Until the file is actually deleted (e.g. the trash is emptied), all files and database content remains intact and can be restored at any point up until that time.
Additionally you may configure a directory where deleted files are moved to when they the trash is emptied with [`PAPERLESS_EMPTY_TRASH_DIR`](configuration.md#PAPERLESS_EMPTY_TRASH_DIR). Additionally you may configure a directory where deleted files are moved to when the trash is emptied with [`PAPERLESS_EMPTY_TRASH_DIR`](configuration.md#PAPERLESS_EMPTY_TRASH_DIR).
Note that the empty trash directory only stores the original file, the archive file and all database information is permanently removed once a document is fully deleted. Note that the empty trash directory only stores the original file, the archive file and all database information is permanently removed once a document is fully deleted.
## Best practices {#basic-searching} ## Best practices {#basic-searching}

View File

@ -52,12 +52,12 @@ if ! command -v wget &> /dev/null ; then
fi fi
if ! command -v docker &> /dev/null ; then if ! command -v docker &> /dev/null ; then
echo "docker executable not found. Is docker installed?" echo "docker executable not found. Is Docker installed?"
exit 1 exit 1
fi fi
if ! docker compose &> /dev/null ; then if ! docker compose &> /dev/null ; then
echo "docker compose plugin not found. Is docker compose installed?" echo "docker compose plugin not found. Is Docker Compose installed?"
exit 1 exit 1
fi fi
@ -66,7 +66,7 @@ fi
if ! docker stats --no-stream &> /dev/null ; then if ! docker stats --no-stream &> /dev/null ; then
echo "" echo ""
echo "WARN: It look like the current user does not have Docker permissions." echo "WARN: It look like the current user does not have Docker permissions."
echo "WARN: Use 'sudo usermod -aG docker $USER' to assign Docker permissions to the user (may require restarting shell)." echo "WARN: Use 'sudo usermod -aG docker $USER' to assign Docker permissions to the user (may require restarting the shell)."
echo "" echo ""
sleep 3 sleep 3
fi fi
@ -135,7 +135,7 @@ DATABASE_BACKEND=$ask_result
echo "" echo ""
echo "Paperless is able to use Apache Tika to support Office documents such as" echo "Paperless is able to use Apache Tika to support Office documents such as"
echo "Word, Excel, Powerpoint, and Libreoffice equivalents. This feature" echo "Word, Excel, PowerPoint, and LibreOffice equivalents. This feature"
echo "requires more resources due to the required services." echo "requires more resources due to the required services."
echo "" echo ""
@ -157,7 +157,7 @@ echo ""
echo "Specify the user id and group id you wish to run paperless as." echo "Specify the user id and group id you wish to run paperless as."
echo "Paperless will also change ownership on the data, media and consume" echo "Paperless will also change ownership on the data, media and consume"
echo "folder to the specified values, so it's a good idea to supply the user id" echo "folder to the specified values, so it's a good idea to supply the user id"
echo "and group id of your unix user account." echo "and group id of your Unix user account."
echo "If unsure, leave default." echo "If unsure, leave default."
echo "" echo ""
@ -212,7 +212,7 @@ if [[ "$DATABASE_BACKEND" == "sqlite" ]] ; then
echo -n "SQLite database, the " echo -n "SQLite database, the "
fi fi
echo "search index and other data." echo "search index and other data."
echo "As with the media folder, leave empty to have this managed by docker." echo "As with the media folder, leave empty to have this managed by Docker."
echo "" echo ""
echo "CAUTION: If specified, you must specify an absolute path starting with /" echo "CAUTION: If specified, you must specify an absolute path starting with /"
echo "or a relative path starting with ./ here." echo "or a relative path starting with ./ here."
@ -224,7 +224,7 @@ DATA_FOLDER=$ask_result
if [[ "$DATABASE_BACKEND" == "postgres" || "$DATABASE_BACKEND" == "mariadb" ]] ; then if [[ "$DATABASE_BACKEND" == "postgres" || "$DATABASE_BACKEND" == "mariadb" ]] ; then
echo "" echo ""
echo "The database folder, where your database stores its data." echo "The database folder, where your database stores its data."
echo "Leave empty to have this managed by docker." echo "Leave empty to have this managed by Docker."
echo "" echo ""
echo "CAUTION: If specified, you must specify an absolute path starting with /" echo "CAUTION: If specified, you must specify an absolute path starting with /"
echo "or a relative path starting with ./ here." echo "or a relative path starting with ./ here."
@ -276,18 +276,18 @@ echo ""
echo "Target folder: $TARGET_FOLDER" echo "Target folder: $TARGET_FOLDER"
echo "Consume folder: $CONSUME_FOLDER" echo "Consume folder: $CONSUME_FOLDER"
if [[ -z $MEDIA_FOLDER ]] ; then if [[ -z $MEDIA_FOLDER ]] ; then
echo "Media folder: Managed by docker" echo "Media folder: Managed by Docker"
else else
echo "Media folder: $MEDIA_FOLDER" echo "Media folder: $MEDIA_FOLDER"
fi fi
if [[ -z $DATA_FOLDER ]] ; then if [[ -z $DATA_FOLDER ]] ; then
echo "Data folder: Managed by docker" echo "Data folder: Managed by Docker"
else else
echo "Data folder: $DATA_FOLDER" echo "Data folder: $DATA_FOLDER"
fi fi
if [[ "$DATABASE_BACKEND" == "postgres" || "$DATABASE_BACKEND" == "mariadb" ]] ; then if [[ "$DATABASE_BACKEND" == "postgres" || "$DATABASE_BACKEND" == "mariadb" ]] ; then
if [[ -z $DATABASE_FOLDER ]] ; then if [[ -z $DATABASE_FOLDER ]] ; then
echo "Database folder: Managed by docker" echo "Database folder: Managed by Docker"
else else
echo "Database folder: $DATABASE_FOLDER" echo "Database folder: $DATABASE_FOLDER"
fi fi
@ -374,7 +374,7 @@ fi
# of the provided folder # of the provided folder
if [[ -n $DATABASE_FOLDER ]] ; then if [[ -n $DATABASE_FOLDER ]] ; then
if [[ "$DATABASE_BACKEND" == "postgres" ]] ; then if [[ "$DATABASE_BACKEND" == "postgres" ]] ; then
sed -i "s#- pgdata:/var/lib/postgresql/data#- $DATABASE_FOLDER:/var/lib/postgresql/data#g" docker-compose.yml sed -i "s#- pgdata:/var/lib/postgresql#- $DATABASE_FOLDER:/var/lib/postgresql#g" docker-compose.yml
sed -i "/^\s*pgdata:/d" docker-compose.yml sed -i "/^\s*pgdata:/d" docker-compose.yml
elif [[ "$DATABASE_BACKEND" == "mariadb" ]]; then elif [[ "$DATABASE_BACKEND" == "mariadb" ]]; then
sed -i "s#- dbdata:/var/lib/mysql#- $DATABASE_FOLDER:/var/lib/mysql#g" docker-compose.yml sed -i "s#- dbdata:/var/lib/mysql#- $DATABASE_FOLDER:/var/lib/mysql#g" docker-compose.yml

View File

@ -11,14 +11,12 @@ theme:
toggle: toggle:
icon: material/brightness-auto icon: material/brightness-auto
name: Switch to light mode name: Switch to light mode
# Palette toggle for light mode # Palette toggle for light mode
- media: "(prefers-color-scheme: light)" - media: "(prefers-color-scheme: light)"
scheme: default scheme: default
toggle: toggle:
icon: material/brightness-7 icon: material/brightness-7
name: Switch to dark mode name: Switch to dark mode
# Palette toggle for dark mode # Palette toggle for dark mode
- media: "(prefers-color-scheme: dark)" - media: "(prefers-color-scheme: dark)"
scheme: slate scheme: slate
@ -49,6 +47,7 @@ markdown_extensions:
- pymdownx.superfences - pymdownx.superfences
- pymdownx.inlinehilite - pymdownx.inlinehilite
- pymdownx.snippets - pymdownx.snippets
- pymdownx.tilde
- footnotes - footnotes
- pymdownx.superfences: - pymdownx.superfences:
custom_fences: custom_fences:

View File

@ -1,10 +1,6 @@
# Have a look at the docs for documentation. # Have a look at the docs for documentation.
# https://docs.paperless-ngx.com/configuration/ # https://docs.paperless-ngx.com/configuration/
# Debug. Only enable this for development.
#PAPERLESS_DEBUG=false
# Required services # Required services
#PAPERLESS_REDIS=redis://localhost:6379 #PAPERLESS_REDIS=redis://localhost:6379

View File

@ -1,7 +1,7 @@
[project] [project]
name = "paperless-ngx" name = "paperless-ngx"
version = "2.15.1" version = "2.20.3"
description = "A community-supported supercharged version of paperless: scan, index and archive all your physical documents" description = "A community-supported supercharged document management system: scan, index and archive all your physical documents"
readme = "README.md" readme = "README.md"
requires-python = ">=3.10" requires-python = ">=3.10"
classifiers = [ classifiers = [
@ -10,58 +10,63 @@ classifiers = [
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
] ]
# TODO: Move certain things to groups and then utilize that further # TODO: Move certain things to groups and then utilize that further
# This will allow testing to not install a webserver, mysql, etc # This will allow testing to not install a webserver, mysql, etc
dependencies = [ dependencies = [
"bleach~=6.2.0", "babel>=2.17",
"celery[redis]~=5.4.0", "bleach~=6.3.0",
"celery[redis]~=5.5.1",
"channels~=4.2", "channels~=4.2",
"channels-redis~=4.2", "channels-redis~=4.2",
"concurrent-log-handler~=0.9.25", "concurrent-log-handler~=0.9.25",
"dateparser~=1.2", "dateparser~=1.2",
# WARNING: django does not use semver. # WARNING: django does not use semver.
# Only patch versions are guaranteed to not introduce breaking changes. # Only patch versions are guaranteed to not introduce breaking changes.
"django~=5.1.7", "django~=5.2.5",
"django-allauth[socialaccount,mfa]~=65.4.0", "django-allauth[mfa,socialaccount]~=65.12.1",
"django-auditlog~=3.0.0", "django-auditlog~=3.3.0",
"django-celery-results~=2.5.1", "django-cachalot~=2.8.0",
"django-celery-results~=2.6.0",
"django-compression-middleware~=0.5.0", "django-compression-middleware~=0.5.0",
"django-cors-headers~=4.7.0", "django-cors-headers~=4.9.0",
"django-extensions~=3.2.3", "django-extensions~=4.1",
"django-filter~=25.1", "django-filter~=25.1",
"django-guardian~=2.4.0", "django-guardian~=3.2.0",
"django-multiselectfield~=0.1.13", "django-multiselectfield~=1.0.1",
"django-soft-delete~=1.0.18", "django-soft-delete~=1.0.18",
"djangorestframework~=3.15", "django-treenode>=0.23.2",
"djangorestframework-guardian~=0.3.0", "djangorestframework~=3.16",
"djangorestframework-guardian~=0.4.0",
"drf-spectacular~=0.28", "drf-spectacular~=0.28",
"drf-spectacular-sidecar~=2025.3.1", "drf-spectacular-sidecar~=2025.10.1",
"drf-writable-nested~=0.7.1", "drf-writable-nested~=0.7.1",
"filelock~=3.17.0", "filelock~=3.20.0",
"flower~=2.0.1", "flower~=2.0.1",
"gotenberg-client~=0.9.0", "gotenberg-client~=0.12.0",
"httpx-oauth~=0.16", "httpx-oauth~=0.16",
"imap-tools~=1.10.0", "imap-tools~=1.11.0",
"inotifyrecursive~=0.3", "inotifyrecursive~=0.3",
"jinja2~=3.1.5", "jinja2~=3.1.5",
"langdetect~=1.0.9", "langdetect~=1.0.9",
"nltk~=3.9.1", "nltk~=3.9.1",
"ocrmypdf~=16.10.0", "ocrmypdf~=16.12.0",
"pathvalidate~=3.2.3", "pathvalidate~=3.3.1",
"pdf2image~=1.17.0", "pdf2image~=1.17.0",
"python-dateutil~=2.9.0", "python-dateutil~=2.9.0",
"python-dotenv~=1.0.1", "python-dotenv~=1.2.1",
"python-gnupg~=0.5.4", "python-gnupg~=0.5.4",
"python-ipware~=3.0.0", "python-ipware~=3.0.0",
"python-magic~=0.4.27", "python-magic~=0.4.27",
"pyzbar~=0.1.9", "pyzbar~=0.1.9",
"rapidfuzz~=3.12.1", "rapidfuzz~=3.14.0",
"redis[hiredis]~=5.2.1", "redis[hiredis]~=5.2.1",
"scikit-learn~=1.6.1", "regex>=2025.9.18",
"scikit-learn~=1.7.0",
"setproctitle~=1.3.4", "setproctitle~=1.3.4",
"tika-client~=0.9.0", "tika-client~=0.10.0",
"tqdm~=4.67.1", "tqdm~=4.67.1",
"watchdog~=6.0", "watchdog~=6.0",
"whitenoise~=6.9", "whitenoise~=6.9",
@ -73,12 +78,13 @@ optional-dependencies.mariadb = [
"mysqlclient~=2.2.7", "mysqlclient~=2.2.7",
] ]
optional-dependencies.postgres = [ optional-dependencies.postgres = [
"psycopg[c]==3.2.5", "psycopg[c,pool]==3.2.12",
# Direct dependency for proper resolution of the pre-built wheels # Direct dependency for proper resolution of the pre-built wheels
"psycopg-c==3.2.5", "psycopg-c==3.2.12",
"psycopg-pool==3.2.7",
] ]
optional-dependencies.webserver = [ optional-dependencies.webserver = [
"granian[uvloop]~=2.2.0", "granian[uvloop]~=2.5.1",
] ]
[dependency-groups] [dependency-groups]
@ -90,17 +96,17 @@ dev = [
] ]
docs = [ docs = [
"mkdocs-glightbox~=0.4.0", "mkdocs-glightbox~=0.5.1",
"mkdocs-material~=9.6.4", "mkdocs-material~=9.7.0",
] ]
testing = [ testing = [
"daphne", "daphne",
"factory-boy~=3.3.1", "factory-boy~=3.3.1",
"imagehash", "imagehash",
"pytest~=8.3.3", "pytest~=8.4.1",
"pytest-cov~=6.0.0", "pytest-cov~=7.0.0",
"pytest-django~=4.10.0", "pytest-django~=4.11.1",
"pytest-env", "pytest-env",
"pytest-httpx", "pytest-httpx",
"pytest-mock", "pytest-mock",
@ -110,9 +116,9 @@ testing = [
] ]
lint = [ lint = [
"pre-commit~=4.1.0", "pre-commit~=4.4.0",
"pre-commit-uv~=4.1.3", "pre-commit-uv~=4.2.0",
"ruff~=0.9.9", "ruff~=0.14.0",
] ]
typing = [ typing = [
@ -120,6 +126,7 @@ typing = [
"django-filter-stubs", "django-filter-stubs",
"django-stubs[compatible-mypy]", "django-stubs[compatible-mypy]",
"djangorestframework-stubs[compatible-mypy]", "djangorestframework-stubs[compatible-mypy]",
"lxml-stubs",
"mypy", "mypy",
"types-bleach", "types-bleach",
"types-colorama", "types-colorama",
@ -127,11 +134,31 @@ typing = [
"types-markdown", "types-markdown",
"types-pygments", "types-pygments",
"types-python-dateutil", "types-python-dateutil",
"types-pytz",
"types-redis", "types-redis",
"types-setuptools", "types-setuptools",
"types-tqdm", "types-tqdm",
] ]
[tool.uv]
required-version = ">=0.5.14"
package = false
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
]
[tool.uv.sources]
# Markers are chosen to select these almost exclusively when building the Docker image
psycopg-c = [
{ url = "https://github.com/paperless-ngx/builder/releases/download/psycopg-bookworm-3.2.12/psycopg_c-3.2.12-cp312-cp312-linux_x86_64.whl", marker = "sys_platform == 'linux' and platform_machine == 'x86_64' and python_version == '3.12'" },
{ url = "https://github.com/paperless-ngx/builder/releases/download/psycopg-bookworm-3.2.12/psycopg_c-3.2.12-cp312-cp312-linux_aarch64.whl", marker = "sys_platform == 'linux' and platform_machine == 'aarch64' and python_version == '3.12'" },
]
zxing-cpp = [
{ url = "https://github.com/paperless-ngx/builder/releases/download/zxing-2.3.0/zxing_cpp-2.3.0-cp312-cp312-linux_x86_64.whl", marker = "sys_platform == 'linux' and platform_machine == 'x86_64' and python_version == '3.12'" },
{ url = "https://github.com/paperless-ngx/builder/releases/download/zxing-2.3.0/zxing_cpp-2.3.0-cp312-cp312-linux_aarch64.whl", marker = "sys_platform == 'linux' and platform_machine == 'aarch64' and python_version == '3.12'" },
]
[tool.ruff] [tool.ruff]
target-version = "py310" target-version = "py310"
line-length = 88 line-length = 88
@ -172,6 +199,7 @@ lint.extend-select = [
] ]
lint.ignore = [ lint.ignore = [
"DJ001", "DJ001",
"PLC0415",
"RUF012", "RUF012",
"SIM105", "SIM105",
] ]
@ -200,75 +228,19 @@ lint.per-file-ignores."docker/wait-for-redis.py" = [
"INP001", "INP001",
"T201", "T201",
] ]
lint.per-file-ignores."src/documents/file_handling.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/management/commands/document_consumer.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/management/commands/document_exporter.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/migrations/1012_fix_archive_files.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/models.py" = [ lint.per-file-ignores."src/documents/models.py" = [
"SIM115", "SIM115",
] ]
lint.per-file-ignores."src/documents/parsers.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/signals/handlers.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/tests/test_consumer.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/tests/test_file_handling.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/tests/test_management.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/tests/test_management_consumer.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/tests/test_management_exporter.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/tests/test_migration_archive_files.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/tests/test_migration_document_pages_count.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/tests/test_migration_mime_type.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/tests/test_sanity_check.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/documents/views.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/paperless/checks.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/paperless/settings.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/paperless/views.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/paperless_mail/mail.py" = [
"PTH",
] # TODO Enable & remove
lint.per-file-ignores."src/paperless_tesseract/tests/test_parser.py" = [ lint.per-file-ignores."src/paperless_tesseract/tests/test_parser.py" = [
"PTH",
"RUF001", "RUF001",
] # TODO PTH Enable & remove ]
lint.isort.force-single-line = true lint.isort.force-single-line = true
[tool.codespell]
write-changes = true
ignore-words-list = "criterias,afterall,valeu,ureue,equest,ure,assertIn,Oktober"
skip = "src-ui/src/locale/*,src-ui/pnpm-lock.yaml,src-ui/e2e/*,src/paperless_mail/tests/samples/*,src/documents/tests/samples/*,*.po,*.json"
[tool.pytest.ini_options] [tool.pytest.ini_options]
minversion = "8.0" minversion = "8.0"
pythonpath = [ pythonpath = [
@ -280,6 +252,7 @@ testpaths = [
"src/paperless_mail/tests/", "src/paperless_mail/tests/",
"src/paperless_tesseract/tests/", "src/paperless_tesseract/tests/",
"src/paperless_tika/tests", "src/paperless_tika/tests",
"src/paperless_text/tests/",
] ]
addopts = [ addopts = [
"--pythonwarnings=all", "--pythonwarnings=all",
@ -320,10 +293,10 @@ exclude_also = [
] ]
[tool.mypy] [tool.mypy]
mypy_path = "src"
plugins = [ plugins = [
"mypy_django_plugin.main", "mypy_django_plugin.main",
"mypy_drf_plugin.main", "mypy_drf_plugin.main",
"numpy.typing.mypy_plugin",
] ]
check_untyped_defs = true check_untyped_defs = true
disallow_any_generics = true disallow_any_generics = true
@ -332,24 +305,5 @@ disallow_untyped_defs = true
warn_redundant_casts = true warn_redundant_casts = true
warn_unused_ignores = true warn_unused_ignores = true
[tool.uv]
required-version = ">=0.5.14"
package = false
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
]
[tool.uv.sources]
# Markers are chosen to select these almost exclusively when building the Docker image
psycopg-c = [
{ url = "https://github.com/paperless-ngx/builder/releases/download/psycopg-3.2.5/psycopg_c-3.2.5-cp312-cp312-linux_x86_64.whl", marker = "sys_platform == 'linux' and platform_machine == 'x86_64' and python_version == '3.12'" },
{ url = "https://github.com/paperless-ngx/builder/releases/download/psycopg-3.2.5/psycopg_c-3.2.5-cp312-cp312-linux_aarch64.whl", marker = "sys_platform == 'linux' and platform_machine == 'aarch64' and python_version == '3.12'" },
]
zxing-cpp = [
{ url = "https://github.com/paperless-ngx/builder/releases/download/zxing-2.3.0/zxing_cpp-2.3.0-cp312-cp312-linux_x86_64.whl", marker = "sys_platform == 'linux' and platform_machine == 'x86_64' and python_version == '3.12'" },
{ url = "https://github.com/paperless-ngx/builder/releases/download/zxing-2.3.0/zxing_cpp-2.3.0-cp312-cp312-linux_aarch64.whl", marker = "sys_platform == 'linux' and platform_machine == 'aarch64' and python_version == '3.12'" },
]
[tool.django-stubs] [tool.django-stubs]
django_settings_module = "paperless.settings" django_settings_module = "paperless.settings"

View File

@ -6,6 +6,7 @@ A document with an id of ${DOCUMENT_ID} was just consumed. I know the
following additional information about it: following additional information about it:
* Generated File Name: ${DOCUMENT_FILE_NAME} * Generated File Name: ${DOCUMENT_FILE_NAME}
* Document type: ${DOCUMENT_TYPE}
* Archive Path: ${DOCUMENT_ARCHIVE_PATH} * Archive Path: ${DOCUMENT_ARCHIVE_PATH}
* Source Path: ${DOCUMENT_SOURCE_PATH} * Source Path: ${DOCUMENT_SOURCE_PATH}
* Created: ${DOCUMENT_CREATED} * Created: ${DOCUMENT_CREATED}

View File

@ -0,0 +1,13 @@
export const getDocument = jest.fn(() => ({
promise: Promise.resolve({ numPages: 3 }),
}))
export const GlobalWorkerOptions = { workerSrc: '' }
export const VerbosityLevel = { ERRORS: 0 }
globalThis.pdfjsLib = {
getDocument,
GlobalWorkerOptions,
VerbosityLevel,
AbortException: class AbortException extends Error {},
}

View File

@ -27,6 +27,7 @@
"el-GR": "src/locale/messages.el_GR.xlf", "el-GR": "src/locale/messages.el_GR.xlf",
"en-GB": "src/locale/messages.en_GB.xlf", "en-GB": "src/locale/messages.en_GB.xlf",
"es-ES": "src/locale/messages.es_ES.xlf", "es-ES": "src/locale/messages.es_ES.xlf",
"fa-IR": "src/locale/messages.fa_IR.xlf",
"fi-FI": "src/locale/messages.fi_FI.xlf", "fi-FI": "src/locale/messages.fi_FI.xlf",
"fr-FR": "src/locale/messages.fr_FR.xlf", "fr-FR": "src/locale/messages.fr_FR.xlf",
"hu-HU": "src/locale/messages.hu_HU.xlf", "hu-HU": "src/locale/messages.hu_HU.xlf",
@ -47,6 +48,7 @@
"sv-SE": "src/locale/messages.sv_SE.xlf", "sv-SE": "src/locale/messages.sv_SE.xlf",
"tr-TR": "src/locale/messages.tr_TR.xlf", "tr-TR": "src/locale/messages.tr_TR.xlf",
"uk-UA": "src/locale/messages.uk_UA.xlf", "uk-UA": "src/locale/messages.uk_UA.xlf",
"vi-VN": "src/locale/messages.vi_VN.xlf",
"zh-CN": "src/locale/messages.zh_CN.xlf", "zh-CN": "src/locale/messages.zh_CN.xlf",
"zh-TW": "src/locale/messages.zh_TW.xlf" "zh-TW": "src/locale/messages.zh_TW.xlf"
} }
@ -59,10 +61,12 @@
"path": "./extra-webpack.config.ts" "path": "./extra-webpack.config.ts"
}, },
"outputPath": "dist/paperless-ui", "outputPath": "dist/paperless-ui",
"main": "src/main.ts",
"outputHashing": "none", "outputHashing": "none",
"index": "src/index.html", "index": "src/index.html",
"main": "src/main.ts", "polyfills": [
"polyfills": "src/polyfills.ts", "src/polyfills.ts"
],
"tsConfig": "tsconfig.app.json", "tsConfig": "tsconfig.app.json",
"localize": true, "localize": true,
"assets": [ "assets": [
@ -85,12 +89,15 @@
"file-saver", "file-saver",
"utif" "utif"
], ],
"vendorChunk": true,
"extractLicenses": false, "extractLicenses": false,
"buildOptimizer": false,
"sourceMap": true, "sourceMap": true,
"optimization": false, "optimization": false,
"namedChunks": true "namedChunks": true,
"stylePreprocessorOptions": {
"includePaths": [
"."
]
}
}, },
"configurations": { "configurations": {
"production": { "production": {
@ -106,8 +113,6 @@
"sourceMap": false, "sourceMap": false,
"namedChunks": false, "namedChunks": false,
"extractLicenses": true, "extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [ "budgets": [
{ {
"type": "initial", "type": "initial",
@ -187,6 +192,30 @@
}, },
"@angular-eslint/schematics:library": { "@angular-eslint/schematics:library": {
"setParserOptionsProject": true "setParserOptionsProject": true
},
"@schematics/angular:component": {
"type": "component"
},
"@schematics/angular:directive": {
"type": "directive"
},
"@schematics/angular:service": {
"type": "service"
},
"@schematics/angular:guard": {
"typeSeparator": "."
},
"@schematics/angular:interceptor": {
"typeSeparator": "."
},
"@schematics/angular:module": {
"typeSeparator": "."
},
"@schematics/angular:pipe": {
"typeSeparator": "."
},
"@schematics/angular:resolver": {
"typeSeparator": "."
} }
} }
} }

View File

@ -174,7 +174,7 @@ test('bulk edit', async ({ page }) => {
await expect(page.locator('pngx-document-list')).toHaveText( await expect(page.locator('pngx-document-list')).toHaveText(
/Selected 61 of 61 documents/i /Selected 61 of 61 documents/i
) )
await page.getByRole('button', { name: 'Cancel' }).click() await page.getByRole('button', { name: 'None' }).click()
await page.locator('pngx-document-card-small').nth(1).click() await page.locator('pngx-document-card-small').nth(1).click()
await page.locator('pngx-document-card-small').nth(2).click() await page.locator('pngx-document-card-small').nth(2).click()

View File

@ -8,7 +8,7 @@ module.exports = {
'abstract-paperless-service', 'abstract-paperless-service',
], ],
transformIgnorePatterns: [ transformIgnorePatterns: [
`<rootDir>/node_modules/.pnpm/(?!.*\\.mjs$|lodash-es)`, `<rootDir>/node_modules/.pnpm/(?!.*\\.mjs$|lodash-es|@angular\\+common.*locales)`,
], ],
moduleNameMapper: { moduleNameMapper: {
'^src/(.*)': '<rootDir>/src/$1', '^src/(.*)': '<rootDir>/src/$1',

File diff suppressed because it is too large Load Diff

View File

@ -1,77 +1,76 @@
{ {
"name": "paperless-ui", "name": "paperless-ngx-ui",
"version": "0.0.0", "version": "2.20.3",
"scripts": { "scripts": {
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
"ng": "ng", "ng": "ng",
"start": "ng serve", "start": "ng serve",
"build": "ng build", "build": "ng build",
"test": "ng test --no-watch --coverage", "test": "ng test --no-watch --coverage",
"lint": "ng lint", "lint": "ng lint"
"postinstall": "patch-package"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/cdk": "^19.2.7", "@angular/cdk": "^20.2.13",
"@angular/common": "~19.2.4", "@angular/common": "~20.3.15",
"@angular/compiler": "~19.2.4", "@angular/compiler": "~20.3.15",
"@angular/core": "~19.2.4", "@angular/core": "~20.3.15",
"@angular/forms": "~19.2.4", "@angular/forms": "~20.3.15",
"@angular/localize": "~19.2.4", "@angular/localize": "~20.3.15",
"@angular/platform-browser": "~19.2.4", "@angular/platform-browser": "~20.3.15",
"@angular/platform-browser-dynamic": "~19.2.4", "@angular/platform-browser-dynamic": "~20.3.15",
"@angular/router": "~19.2.4", "@angular/router": "~20.3.15",
"@ng-bootstrap/ng-bootstrap": "^18.0.0", "@ng-bootstrap/ng-bootstrap": "^19.0.1",
"@ng-select/ng-select": "^14.2.6", "@ng-select/ng-select": "^20.7.0",
"@ngneat/dirty-check-forms": "^3.0.3", "@ngneat/dirty-check-forms": "^3.0.3",
"@popperjs/core": "^2.11.8", "@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.8",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"mime-names": "^1.0.0", "mime-names": "^1.0.0",
"ng2-pdf-viewer": "^10.4.0", "ng2-pdf-viewer": "^10.4.0",
"ngx-bootstrap-icons": "^1.9.3", "ngx-bootstrap-icons": "^1.9.3",
"ngx-color": "^10.0.0", "ngx-color": "^10.1.0",
"ngx-cookie-service": "^19.1.2", "ngx-cookie-service": "^20.1.1",
"ngx-device-detector": "^9.0.0", "ngx-device-detector": "^10.1.0",
"ngx-file-drop": "^16.0.0", "ngx-ui-tour-ng-bootstrap": "^17.0.1",
"ngx-ui-tour-ng-bootstrap": "^16.0.0",
"rxjs": "^7.8.2", "rxjs": "^7.8.2",
"tslib": "^2.8.1", "tslib": "^2.8.1",
"utif": "^3.1.0", "utif": "^3.1.0",
"uuid": "^11.1.0", "uuid": "^13.0.0",
"zone.js": "^0.15.0" "zone.js": "^0.15.1"
}, },
"devDependencies": { "devDependencies": {
"@angular-builders/custom-webpack": "^19.0.0", "@angular-builders/custom-webpack": "^20.0.0",
"@angular-builders/jest": "^19.0.0", "@angular-builders/jest": "^20.0.0",
"@angular-devkit/build-angular": "^19.2.5", "@angular-devkit/core": "^20.3.13",
"@angular-devkit/core": "^19.2.5", "@angular-devkit/schematics": "^20.3.13",
"@angular-devkit/schematics": "^19.2.5", "@angular-eslint/builder": "20.6.0",
"@angular-eslint/builder": "19.3.0", "@angular-eslint/eslint-plugin": "20.6.0",
"@angular-eslint/eslint-plugin": "19.3.0", "@angular-eslint/eslint-plugin-template": "20.6.0",
"@angular-eslint/eslint-plugin-template": "19.3.0", "@angular-eslint/schematics": "20.6.0",
"@angular-eslint/schematics": "19.3.0", "@angular-eslint/template-parser": "20.6.0",
"@angular-eslint/template-parser": "19.3.0", "@angular/build": "^20.3.13",
"@angular/cli": "~19.2.5", "@angular/cli": "~20.3.13",
"@angular/compiler-cli": "~19.2.4", "@angular/compiler-cli": "~20.3.15",
"@codecov/webpack-plugin": "^1.9.0", "@codecov/webpack-plugin": "^1.9.1",
"@playwright/test": "^1.51.1", "@playwright/test": "^1.57.0",
"@types/jest": "^29.5.14", "@types/jest": "^30.0.0",
"@types/node": "^22.13.17", "@types/node": "^24.10.1",
"@typescript-eslint/eslint-plugin": "^8.29.0", "@typescript-eslint/eslint-plugin": "^8.48.1",
"@typescript-eslint/parser": "^8.29.0", "@typescript-eslint/parser": "^8.48.1",
"@typescript-eslint/utils": "^8.29.0", "@typescript-eslint/utils": "^8.48.1",
"eslint": "^9.23.0", "eslint": "^9.39.1",
"jest": "29.7.0", "jest": "30.2.0",
"jest-environment-jsdom": "^29.7.0", "jest-environment-jsdom": "^30.2.0",
"jest-junit": "^16.0.0", "jest-junit": "^16.0.0",
"jest-preset-angular": "^14.5.4", "jest-preset-angular": "^15.0.3",
"jest-websocket-mock": "^2.5.0", "jest-websocket-mock": "^2.5.0",
"patch-package": "^8.0.0", "prettier-plugin-organize-imports": "^4.3.0",
"prettier-plugin-organize-imports": "^4.1.0",
"ts-node": "~10.9.1", "ts-node": "~10.9.1",
"typescript": "^5.5.4" "typescript": "^5.8.3",
"webpack": "^5.103.0"
}, },
"packageManager": "pnpm@10.17.1",
"pnpm": { "pnpm": {
"onlyBuiltDependencies": [ "onlyBuiltDependencies": [
"@parcel/watcher", "@parcel/watcher",
@ -80,6 +79,5 @@
"lmdb", "lmdb",
"msgpackr-extract" "msgpackr-extract"
] ]
}, }
"typings": "./src/typings.d.ts"
} }

File diff suppressed because one or more lines are too long

9603
src-ui/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,16 @@
import '@angular/localize/init' import '@angular/localize/init'
import { jest } from '@jest/globals' import { jest } from '@jest/globals'
import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone' import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'
import { TextDecoder, TextEncoder } from 'util' import { TextDecoder, TextEncoder } from 'node:util'
if (process.env.NODE_ENV === 'test') { if (process.env.NODE_ENV === 'test') {
setupZoneTestEnv() setupZoneTestEnv()
} }
global.TextEncoder = TextEncoder ;(globalThis as any).TextEncoder = TextEncoder as unknown as {
global.TextDecoder = TextDecoder new (): TextEncoder
}
;(globalThis as any).TextDecoder = TextDecoder as unknown as {
new (): TextDecoder
}
import { registerLocaleData } from '@angular/common' import { registerLocaleData } from '@angular/common'
import localeAf from '@angular/common/locales/af' import localeAf from '@angular/common/locales/af'
@ -20,6 +24,7 @@ import localeDe from '@angular/common/locales/de'
import localeEl from '@angular/common/locales/el' import localeEl from '@angular/common/locales/el'
import localeEnGb from '@angular/common/locales/en-GB' import localeEnGb from '@angular/common/locales/en-GB'
import localeEs from '@angular/common/locales/es' import localeEs from '@angular/common/locales/es'
import localeFa from '@angular/common/locales/fa'
import localeFi from '@angular/common/locales/fi' import localeFi from '@angular/common/locales/fi'
import localeFr from '@angular/common/locales/fr' import localeFr from '@angular/common/locales/fr'
import localeHu from '@angular/common/locales/hu' import localeHu from '@angular/common/locales/hu'
@ -39,6 +44,7 @@ import localeSr from '@angular/common/locales/sr'
import localeSv from '@angular/common/locales/sv' import localeSv from '@angular/common/locales/sv'
import localeTr from '@angular/common/locales/tr' import localeTr from '@angular/common/locales/tr'
import localeUk from '@angular/common/locales/uk' import localeUk from '@angular/common/locales/uk'
import localeVi from '@angular/common/locales/vi'
import localeZh from '@angular/common/locales/zh' import localeZh from '@angular/common/locales/zh'
import localeZhHant from '@angular/common/locales/zh-Hant' import localeZhHant from '@angular/common/locales/zh-Hant'
@ -53,6 +59,7 @@ registerLocaleData(localeDe)
registerLocaleData(localeEl) registerLocaleData(localeEl)
registerLocaleData(localeEnGb) registerLocaleData(localeEnGb)
registerLocaleData(localeEs) registerLocaleData(localeEs)
registerLocaleData(localeFa)
registerLocaleData(localeFi) registerLocaleData(localeFi)
registerLocaleData(localeFr) registerLocaleData(localeFr)
registerLocaleData(localeHu) registerLocaleData(localeHu)
@ -73,6 +80,7 @@ registerLocaleData(localeSr)
registerLocaleData(localeSv) registerLocaleData(localeSv)
registerLocaleData(localeTr) registerLocaleData(localeTr)
registerLocaleData(localeUk) registerLocaleData(localeUk)
registerLocaleData(localeVi)
registerLocaleData(localeZh) registerLocaleData(localeZh)
registerLocaleData(localeZhHant) registerLocaleData(localeZhHant)
@ -112,28 +120,43 @@ if (!URL.revokeObjectURL) {
Object.defineProperty(window.URL, 'revokeObjectURL', { value: jest.fn() }) Object.defineProperty(window.URL, 'revokeObjectURL', { value: jest.fn() })
} }
Object.defineProperty(window, 'ResizeObserver', { value: mock() }) Object.defineProperty(window, 'ResizeObserver', { value: mock() })
Object.defineProperty(window, 'location', {
if (typeof IntersectionObserver === 'undefined') {
class MockIntersectionObserver {
constructor(
public callback: IntersectionObserverCallback,
public options?: IntersectionObserverInit
) {}
observe = jest.fn()
unobserve = jest.fn()
disconnect = jest.fn()
takeRecords = jest.fn()
}
Object.defineProperty(window, 'IntersectionObserver', {
writable: true,
configurable: true, configurable: true,
value: { reload: jest.fn() }, value: MockIntersectionObserver,
}) })
}
HTMLCanvasElement.prototype.getContext = < HTMLCanvasElement.prototype.getContext = <
typeof HTMLCanvasElement.prototype.getContext typeof HTMLCanvasElement.prototype.getContext
>jest.fn() >jest.fn()
// pdfjs if (!HTMLElement.prototype.scrollTo) {
jest.mock('pdfjs-dist', () => ({ HTMLElement.prototype.scrollTo = jest.fn()
getDocument: jest.fn(() => ({ }
promise: Promise.resolve({ numPages: 3 }),
})), jest.mock('uuid', () => ({
GlobalWorkerOptions: { workerSrc: '' }, v4: jest.fn(() =>
VerbosityLevel: { ERRORS: 0 }, 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char: string) => {
globalThis: { const random = Math.floor(Math.random() * 16)
pdfjsLib: { const value = char === 'x' ? random : (random & 0x3) | 0x8
GlobalWorkerOptions: { return value.toString(16)
workerSrc: '', })
}, ),
},
},
})) }))
jest.mock('pdfjs-dist/web/pdf_viewer', () => ({}))
jest.mock('pdfjs-dist')

View File

@ -9,7 +9,6 @@ import {
import { Router, RouterModule } from '@angular/router' import { Router, RouterModule } from '@angular/router'
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap' import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap'
import { allIcons, NgxBootstrapIconsModule } from 'ngx-bootstrap-icons' import { allIcons, NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { NgxFileDropModule } from 'ngx-file-drop'
import { TourNgBootstrapModule, TourService } from 'ngx-ui-tour-ng-bootstrap' import { TourNgBootstrapModule, TourService } from 'ngx-ui-tour-ng-bootstrap'
import { Subject } from 'rxjs' import { Subject } from 'rxjs'
import { routes } from './app-routing.module' import { routes } from './app-routing.module'
@ -43,7 +42,6 @@ describe('AppComponent', () => {
imports: [ imports: [
TourNgBootstrapModule, TourNgBootstrapModule,
RouterModule.forRoot(routes), RouterModule.forRoot(routes),
NgxFileDropModule,
NgbModalModule, NgbModalModule,
AppComponent, AppComponent,
ToastsComponent, ToastsComponent,

View File

@ -1,4 +1,4 @@
import { Component, OnDestroy, OnInit, Renderer2 } from '@angular/core' import { Component, inject, OnDestroy, OnInit, Renderer2 } from '@angular/core'
import { Router, RouterOutlet } from '@angular/router' import { Router, RouterOutlet } from '@angular/router'
import { TourNgBootstrapModule, TourService } from 'ngx-ui-tour-ng-bootstrap' import { TourNgBootstrapModule, TourService } from 'ngx-ui-tour-ng-bootstrap'
import { first, Subscription } from 'rxjs' import { first, Subscription } from 'rxjs'
@ -29,22 +29,22 @@ import { WebsocketStatusService } from './services/websocket-status.service'
], ],
}) })
export class AppComponent implements OnInit, OnDestroy { export class AppComponent implements OnInit, OnDestroy {
private settings = inject(SettingsService)
private websocketStatusService = inject(WebsocketStatusService)
private toastService = inject(ToastService)
private router = inject(Router)
private tasksService = inject(TasksService)
tourService = inject(TourService)
private renderer = inject(Renderer2)
private permissionsService = inject(PermissionsService)
private hotKeyService = inject(HotKeyService)
private componentRouterService = inject(ComponentRouterService)
newDocumentSubscription: Subscription newDocumentSubscription: Subscription
successSubscription: Subscription successSubscription: Subscription
failedSubscription: Subscription failedSubscription: Subscription
constructor( constructor() {
private settings: SettingsService,
private websocketStatusService: WebsocketStatusService,
private toastService: ToastService,
private router: Router,
private tasksService: TasksService,
public tourService: TourService,
private renderer: Renderer2,
private permissionsService: PermissionsService,
private hotKeyService: HotKeyService,
private componentRouterService: ComponentRouterService
) {
let anyWindow = window as any let anyWindow = window as any
anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.mjs' anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.mjs'
this.settings.updateAppearanceSettings() this.settings.updateAppearanceSettings()

View File

@ -50,7 +50,7 @@
<div [ngbNavOutlet]="nav" class="border-start border-end border-bottom p-3 mb-3 shadow-sm"></div> <div [ngbNavOutlet]="nav" class="border-start border-end border-bottom p-3 mb-3 shadow-sm"></div>
<div class="btn-toolbar" role="toolbar"> <div class="btn-toolbar" role="toolbar">
<div class="btn-group me-2"> <div class="btn-group me-2">
<button type="button" (click)="discardChanges()" class="btn btn-secondary" [disabled]="loading || (isDirty$ | async) === false" i18n>Discard</button> <button type="button" (click)="discardChanges()" class="btn btn-outline-secondary" [disabled]="loading || (isDirty$ | async) === false" i18n>Discard</button>
</div> </div>
<div class="btn-group"> <div class="btn-group">
<button type="submit" class="btn btn-primary" [disabled]="loading || !configForm.valid || (isDirty$ | async) === false" i18n>Save</button> <button type="submit" class="btn btn-primary" [disabled]="loading || !configForm.valid || (isDirty$ | async) === false" i18n>Save</button>

View File

@ -105,9 +105,9 @@ describe('ConfigComponent', () => {
it('should support JSON validation for e.g. user_args', () => { it('should support JSON validation for e.g. user_args', () => {
component.configForm.patchValue({ user_args: '{ foo bar }' }) component.configForm.patchValue({ user_args: '{ foo bar }' })
expect(component.errors).toEqual({ user_args: 'Invalid JSON' }) expect(component.errors['user_args']).toEqual('Invalid JSON')
component.configForm.patchValue({ user_args: '{ "foo": "bar" }' }) component.configForm.patchValue({ user_args: '{ "foo": "bar" }' })
expect(component.errors).toEqual({ user_args: null }) expect(component.errors['user_args']).toBeNull()
}) })
it('should upload file, show error if necessary', () => { it('should upload file, show error if necessary', () => {

View File

@ -1,5 +1,5 @@
import { AsyncPipe } from '@angular/common' import { AsyncPipe } from '@angular/common'
import { Component, OnDestroy, OnInit } from '@angular/core' import { Component, OnDestroy, OnInit, inject } from '@angular/core'
import { import {
AbstractControl, AbstractControl,
FormControl, FormControl,
@ -57,6 +57,10 @@ export class ConfigComponent
extends LoadingComponentWithPermissions extends LoadingComponentWithPermissions
implements OnInit, OnDestroy, DirtyComponent implements OnInit, OnDestroy, DirtyComponent
{ {
private configService = inject(ConfigService)
private toastService = inject(ToastService)
private settingsService = inject(SettingsService)
public readonly ConfigOptionType = ConfigOptionType public readonly ConfigOptionType = ConfigOptionType
// generated dynamically // generated dynamically
@ -77,11 +81,7 @@ export class ConfigComponent
storeSub: Subscription storeSub: Subscription
isDirty$: Observable<boolean> isDirty$: Observable<boolean>
constructor( constructor() {
private configService: ConfigService,
private toastService: ToastService,
private settingsService: SettingsService
) {
super() super()
this.configForm.addControl('id', new FormControl()) this.configForm.addControl('id', new FormControl())
PaperlessConfigOptions.forEach((option) => { PaperlessConfigOptions.forEach((option) => {

View File

@ -3,10 +3,24 @@
i18n-title i18n-title
info="Review the log files for the application and for email checking." info="Review the log files for the application and for email checking."
i18n-info> i18n-info>
<div class="form-check form-switch"> <div class="input-group input-group-sm align-items-center">
<div class="input-group input-group-sm me-3">
<span class="input-group-text text-muted" i18n>Show</span>
<input
class="form-control"
type="number"
min="100"
step="100"
[(ngModel)]="limit"
(ngModelChange)="onLimitChange($event)"
style="width: 100px;">
<span class="input-group-text text-muted" i18n>lines</span>
</div>
<div class="form-check form-switch mt-1">
<input class="form-check-input" type="checkbox" role="switch" [(ngModel)]="autoRefreshEnabled"> <input class="form-check-input" type="checkbox" role="switch" [(ngModel)]="autoRefreshEnabled">
<label class="form-check-label" for="autoRefreshSwitch" i18n>Auto refresh</label> <label class="form-check-label" for="autoRefreshSwitch" i18n>Auto refresh</label>
</div> </div>
</div>
</pngx-page-header> </pngx-page-header>
<ul ngbNav #nav="ngbNav" [(activeId)]="activeLog" (activeIdChange)="reloadLogs()" class="nav-tabs"> <ul ngbNav #nav="ngbNav" [(activeId)]="activeLog" (activeIdChange)="reloadLogs()" class="nav-tabs">
@ -27,16 +41,23 @@
} }
</ul> </ul>
<div [ngbNavOutlet]="nav" class="mt-2"></div> <div #logContainer class="bg-dark text-light font-monospace log-container p-3" (scroll)="onScroll()">
@if (loading && !logFiles.length) {
<div class="bg-dark p-3 text-light font-monospace log-container" #logContainer>
@if (loading && logFiles.length) {
<div> <div>
<div class="spinner-border spinner-border-sm me-2" role="status"></div> <div class="spinner-border spinner-border-sm me-2" role="status"></div>
<ng-container i18n>Loading...</ng-container> <ng-container i18n>Loading...</ng-container>
</div> </div>
} @else {
@for (log of logs; track log) {
<p class="m-0 p-0" [ngClass]="'log-entry-' + log.level">{{log.message}}</p>
} }
@for (log of logs; track $index) {
<p class="m-0 p-0 log-entry-{{getLogLevel(log)}}">{{log}}</p>
} }
</div> </div>
<button
type="button"
class="btn btn-sm btn-secondary jump-to-bottom position-fixed bottom-0 end-0 m-5"
[class.visible]="showJumpToBottom"
(click)="scrollToBottom()"
>
<span i18n>Jump to bottom</span>
</button>

View File

@ -16,11 +16,21 @@
} }
.log-container { .log-container {
overflow-y: scroll; height: calc(100vh - 190px);
height: calc(100vh - 200px); overflow-y: auto;
top: 70px;
p { p {
white-space: pre-wrap; white-space: pre-wrap;
} }
} }
.jump-to-bottom {
opacity: 0;
pointer-events: none;
transition: opacity 120ms ease-in-out;
}
.jump-to-bottom.visible {
opacity: 1;
pointer-events: auto;
}

View File

@ -1,3 +1,8 @@
import {
CdkVirtualScrollViewport,
ScrollingModule,
} from '@angular/cdk/scrolling'
import { CommonModule } from '@angular/common'
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
import { provideHttpClientTesting } from '@angular/common/http/testing' import { provideHttpClientTesting } from '@angular/common/http/testing'
import { ComponentFixture, TestBed } from '@angular/core/testing' import { ComponentFixture, TestBed } from '@angular/core/testing'
@ -38,6 +43,9 @@ describe('LogsComponent', () => {
NgxBootstrapIconsModule.pick(allIcons), NgxBootstrapIconsModule.pick(allIcons),
LogsComponent, LogsComponent,
PageHeaderComponent, PageHeaderComponent,
CommonModule,
CdkVirtualScrollViewport,
ScrollingModule,
], ],
providers: [ providers: [
provideHttpClient(withInterceptorsFromDi()), provideHttpClient(withInterceptorsFromDi()),
@ -54,13 +62,12 @@ describe('LogsComponent', () => {
fixture = TestBed.createComponent(LogsComponent) fixture = TestBed.createComponent(LogsComponent)
component = fixture.componentInstance component = fixture.componentInstance
reloadSpy = jest.spyOn(component, 'reloadLogs') reloadSpy = jest.spyOn(component, 'reloadLogs')
window.HTMLElement.prototype.scroll = function () {} // mock scroll
jest.useFakeTimers() jest.useFakeTimers()
fixture.detectChanges() fixture.detectChanges()
}) })
it('should display logs with first log initially', () => { it('should display logs with first log initially', () => {
expect(logSpy).toHaveBeenCalledWith('paperless') expect(logSpy).toHaveBeenCalledWith('paperless', 5000)
fixture.detectChanges() fixture.detectChanges()
expect(fixture.debugElement.nativeElement.textContent).toContain( expect(fixture.debugElement.nativeElement.textContent).toContain(
paperless_logs[0] paperless_logs[0]
@ -71,7 +78,7 @@ describe('LogsComponent', () => {
fixture.debugElement fixture.debugElement
.queryAll(By.directive(NgbNavLink))[1] .queryAll(By.directive(NgbNavLink))[1]
.nativeElement.dispatchEvent(new MouseEvent('click')) .nativeElement.dispatchEvent(new MouseEvent('click'))
expect(logSpy).toHaveBeenCalledWith('mail') expect(logSpy).toHaveBeenCalledWith('mail', 5000)
}) })
it('should handle error with no logs', () => { it('should handle error with no logs', () => {
@ -83,6 +90,10 @@ describe('LogsComponent', () => {
}) })
it('should auto refresh, allow toggle', () => { it('should auto refresh, allow toggle', () => {
jest
.spyOn(CdkVirtualScrollViewport.prototype, 'scrollToIndex')
.mockImplementation(() => undefined)
jest.advanceTimersByTime(6000) jest.advanceTimersByTime(6000)
expect(reloadSpy).toHaveBeenCalledTimes(2) expect(reloadSpy).toHaveBeenCalledTimes(2)
@ -90,4 +101,20 @@ describe('LogsComponent', () => {
jest.advanceTimersByTime(6000) jest.advanceTimersByTime(6000)
expect(reloadSpy).toHaveBeenCalledTimes(2) expect(reloadSpy).toHaveBeenCalledTimes(2)
}) })
it('should debounce limit changes before reloading logs', () => {
const initialCalls = reloadSpy.mock.calls.length
component.onLimitChange(6000)
jest.advanceTimersByTime(299)
expect(reloadSpy).toHaveBeenCalledTimes(initialCalls)
jest.advanceTimersByTime(1)
expect(reloadSpy).toHaveBeenCalledTimes(initialCalls + 1)
})
it('should update jump to bottom visibility on scroll', () => {
component.showJumpToBottom = false
jest.spyOn(component as any, 'isNearBottom').mockReturnValue(false)
component.onScroll()
expect(component.showJumpToBottom).toBe(true)
})
}) })

View File

@ -1,3 +1,4 @@
import { CommonModule } from '@angular/common'
import { import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
@ -5,10 +6,11 @@ import {
OnDestroy, OnDestroy,
OnInit, OnInit,
ViewChild, ViewChild,
inject,
} from '@angular/core' } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap' import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'
import { filter, takeUntil, timer } from 'rxjs' import { Subject, debounceTime, filter, takeUntil, timer } from 'rxjs'
import { LogService } from 'src/app/services/rest/log.service' import { LogService } from 'src/app/services/rest/log.service'
import { PageHeaderComponent } from '../../common/page-header/page-header.component' import { PageHeaderComponent } from '../../common/page-header/page-header.component'
import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
@ -20,6 +22,7 @@ import { LoadingComponentWithPermissions } from '../../loading-component/loading
imports: [ imports: [
PageHeaderComponent, PageHeaderComponent,
NgbNavModule, NgbNavModule,
CommonModule,
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
], ],
@ -28,14 +31,10 @@ export class LogsComponent
extends LoadingComponentWithPermissions extends LoadingComponentWithPermissions
implements OnInit, OnDestroy implements OnInit, OnDestroy
{ {
constructor( private logService = inject(LogService)
private logService: LogService, private changedetectorRef = inject(ChangeDetectorRef)
private changedetectorRef: ChangeDetectorRef
) {
super()
}
public logs: string[] = [] public logs: Array<{ message: string; level: number }> = []
public logFiles: string[] = [] public logFiles: string[] = []
@ -43,9 +42,19 @@ export class LogsComponent
public autoRefreshEnabled: boolean = true public autoRefreshEnabled: boolean = true
@ViewChild('logContainer') logContainer: ElementRef public limit: number = 5000
public showJumpToBottom = false
private readonly limitChange$ = new Subject<number>()
@ViewChild('logContainer') logContainer: ElementRef<HTMLElement>
ngOnInit(): void { ngOnInit(): void {
this.limitChange$
.pipe(debounceTime(300), takeUntil(this.unsubscribeNotifier))
.subscribe(() => this.reloadLogs())
this.logService this.logService
.list() .list()
.pipe(takeUntil(this.unsubscribeNotifier)) .pipe(takeUntil(this.unsubscribeNotifier))
@ -71,16 +80,37 @@ export class LogsComponent
super.ngOnDestroy() super.ngOnDestroy()
} }
onLimitChange(limit: number): void {
this.limitChange$.next(limit)
}
reloadLogs() { reloadLogs() {
this.loading = true this.loading = true
const shouldStickToBottom = this.isNearBottom()
this.logService this.logService
.get(this.activeLog) .get(this.activeLog, this.limit)
.pipe(takeUntil(this.unsubscribeNotifier)) .pipe(takeUntil(this.unsubscribeNotifier))
.subscribe({ .subscribe({
next: (result) => { next: (result) => {
this.logs = result
this.loading = false this.loading = false
const parsed = this.parseLogsWithLevel(result)
const hasChanges =
parsed.length !== this.logs.length ||
parsed.some((log, idx) => {
const current = this.logs[idx]
return (
!current ||
current.message !== log.message ||
current.level !== log.level
)
})
if (hasChanges) {
this.logs = parsed
if (shouldStickToBottom) {
this.scrollToBottom() this.scrollToBottom()
}
this.showJumpToBottom = !shouldStickToBottom
}
}, },
error: () => { error: () => {
this.logs = [] this.logs = []
@ -103,12 +133,35 @@ export class LogsComponent
} }
} }
private parseLogsWithLevel(
logs: string[]
): Array<{ message: string; level: number }> {
return logs.map((log) => ({
message: log,
level: this.getLogLevel(log),
}))
}
scrollToBottom(): void { scrollToBottom(): void {
const viewport = this.logContainer?.nativeElement
if (!viewport) {
return
}
this.changedetectorRef.detectChanges() this.changedetectorRef.detectChanges()
this.logContainer?.nativeElement.scroll({ viewport.scrollTop = viewport.scrollHeight
top: this.logContainer.nativeElement.scrollHeight, this.showJumpToBottom = false
left: 0, }
behavior: 'auto',
}) private isNearBottom(): boolean {
if (!this.logContainer?.nativeElement) return true
const distanceFromBottom =
this.logContainer.nativeElement.scrollHeight -
this.logContainer.nativeElement.scrollTop -
this.logContainer.nativeElement.clientHeight
return distanceFromBottom <= 40
}
onScroll(): void {
this.showJumpToBottom = !this.isNearBottom()
} }
} }

View File

@ -176,6 +176,7 @@
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<pngx-input-check i18n-title title="Show warning when closing saved views with unsaved changes" formControlName="savedViewsWarnOnUnsavedChange"></pngx-input-check> <pngx-input-check i18n-title title="Show warning when closing saved views with unsaved changes" formControlName="savedViewsWarnOnUnsavedChange"></pngx-input-check>
<pngx-input-check i18n-title title="Show document counts in sidebar saved views" formControlName="sidebarViewsShowCount"></pngx-input-check>
</div> </div>
</div> </div>
@ -357,6 +358,6 @@
<div [ngbNavOutlet]="nav" class="border-start border-end border-bottom p-3 mb-3 shadow-sm"></div> <div [ngbNavOutlet]="nav" class="border-start border-end border-bottom p-3 mb-3 shadow-sm"></div>
<button type="submit" class="btn btn-primary mb-2" [disabled]="(isDirty$ | async) === false" i18n>Save</button> <button type="button" (click)="reset()" class="btn btn-outline-secondary mb-2" [disabled]="(isDirty$ | async) === false" i18n>Cancel</button>
<button type="button" (click)="reset()" class="btn btn-secondary ms-2 mb-2" [disabled]="(isDirty$ | async) === false" i18n>Cancel</button> <button type="submit" class="btn btn-primary ms-2 mb-2" [disabled]="(isDirty$ | async) === false" i18n>Save</button>
</form> </form>

View File

@ -28,13 +28,14 @@ import { IfOwnerDirective } from 'src/app/directives/if-owner.directive'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive' import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { PermissionsGuard } from 'src/app/guards/permissions.guard' import { PermissionsGuard } from 'src/app/guards/permissions.guard'
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe' import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
import { SafeHtmlPipe } from 'src/app/pipes/safehtml.pipe'
import { PermissionsService } from 'src/app/services/permissions.service' import { PermissionsService } from 'src/app/services/permissions.service'
import { GroupService } from 'src/app/services/rest/group.service' import { GroupService } from 'src/app/services/rest/group.service'
import { SavedViewService } from 'src/app/services/rest/saved-view.service'
import { UserService } from 'src/app/services/rest/user.service' import { UserService } from 'src/app/services/rest/user.service'
import { SettingsService } from 'src/app/services/settings.service' import { SettingsService } from 'src/app/services/settings.service'
import { SystemStatusService } from 'src/app/services/system-status.service' import { SystemStatusService } from 'src/app/services/system-status.service'
import { Toast, ToastService } from 'src/app/services/toast.service' import { Toast, ToastService } from 'src/app/services/toast.service'
import * as navUtils from 'src/app/utils/navigation'
import { ConfirmButtonComponent } from '../../common/confirm-button/confirm-button.component' import { ConfirmButtonComponent } from '../../common/confirm-button/confirm-button.component'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { CheckComponent } from '../../common/input/check/check.component' import { CheckComponent } from '../../common/input/check/check.component'
@ -59,6 +60,40 @@ const groups = [
{ id: 2, name: 'group2' }, { id: 2, name: 'group2' },
] ]
const status: SystemStatus = {
pngx_version: '2.4.3',
server_os: 'macOS-14.1.1-arm64-arm-64bit',
install_type: InstallType.BareMetal,
storage: { total: 494384795648, available: 13573525504 },
database: {
type: 'sqlite',
url: '/paperless-ngx/data/db.sqlite3',
status: SystemStatusItemStatus.ERROR,
error: null,
migration_status: {
latest_migration: 'socialaccount.0006_alter_socialaccount_extra_data',
unapplied_migrations: [],
},
},
tasks: {
redis_url: 'redis://localhost:6379',
redis_status: SystemStatusItemStatus.ERROR,
redis_error: 'Error 61 connecting to localhost:6379. Connection refused.',
celery_status: SystemStatusItemStatus.ERROR,
celery_url: 'celery@localhost',
celery_error: 'Error connecting to celery@localhost',
index_status: SystemStatusItemStatus.OK,
index_last_modified: new Date().toISOString(),
index_error: null,
classifier_status: SystemStatusItemStatus.OK,
classifier_last_trained: new Date().toISOString(),
classifier_error: null,
sanity_check_status: SystemStatusItemStatus.ERROR,
sanity_check_last_run: new Date().toISOString(),
sanity_check_error: 'Error running sanity check.',
},
}
describe('SettingsComponent', () => { describe('SettingsComponent', () => {
let component: SettingsComponent let component: SettingsComponent
let fixture: ComponentFixture<SettingsComponent> let fixture: ComponentFixture<SettingsComponent>
@ -72,6 +107,7 @@ describe('SettingsComponent', () => {
let groupService: GroupService let groupService: GroupService
let modalService: NgbModal let modalService: NgbModal
let systemStatusService: SystemStatusService let systemStatusService: SystemStatusService
let savedViewsService: SavedViewService
beforeEach(async () => { beforeEach(async () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -92,7 +128,6 @@ describe('SettingsComponent', () => {
ConfirmDialogComponent, ConfirmDialogComponent,
CheckComponent, CheckComponent,
ColorComponent, ColorComponent,
SafeHtmlPipe,
SelectComponent, SelectComponent,
TextComponent, TextComponent,
NumberComponent, NumberComponent,
@ -122,6 +157,7 @@ describe('SettingsComponent', () => {
permissionsService = TestBed.inject(PermissionsService) permissionsService = TestBed.inject(PermissionsService)
modalService = TestBed.inject(NgbModal) modalService = TestBed.inject(NgbModal)
systemStatusService = TestBed.inject(SystemStatusService) systemStatusService = TestBed.inject(SystemStatusService)
savedViewsService = TestBed.inject(SavedViewService)
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true) jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
jest jest
.spyOn(permissionsService, 'currentUserHasObjectPermissions') .spyOn(permissionsService, 'currentUserHasObjectPermissions')
@ -212,7 +248,7 @@ describe('SettingsComponent', () => {
expect(toastErrorSpy).toHaveBeenCalled() expect(toastErrorSpy).toHaveBeenCalled()
expect(storeSpy).toHaveBeenCalled() expect(storeSpy).toHaveBeenCalled()
expect(appearanceSettingsSpy).not.toHaveBeenCalled() expect(appearanceSettingsSpy).not.toHaveBeenCalled()
expect(setSpy).toHaveBeenCalledTimes(29) expect(setSpy).toHaveBeenCalledTimes(30)
// succeed // succeed
storeSpy.mockReturnValueOnce(of(true)) storeSpy.mockReturnValueOnce(of(true))
@ -222,6 +258,9 @@ describe('SettingsComponent', () => {
}) })
it('should offer reload if settings changes require', () => { it('should offer reload if settings changes require', () => {
const reloadSpy = jest
.spyOn(navUtils, 'locationReload')
.mockImplementation(() => {})
completeSetup() completeSetup()
let toast: Toast let toast: Toast
toastService.getToasts().subscribe((t) => (toast = t[0])) toastService.getToasts().subscribe((t) => (toast = t[0]))
@ -238,6 +277,7 @@ describe('SettingsComponent', () => {
expect(toast.actionName).toEqual('Reload now') expect(toast.actionName).toEqual('Reload now')
toast.action() toast.action()
expect(reloadSpy).toHaveBeenCalled()
}) })
it('should allow setting theme color, visually apply change immediately but not save', () => { it('should allow setting theme color, visually apply change immediately but not save', () => {
@ -266,7 +306,7 @@ describe('SettingsComponent', () => {
) )
completeSetup(userService) completeSetup(userService)
fixture.detectChanges() fixture.detectChanges()
expect(toastErrorSpy).toBeCalled() expect(toastErrorSpy).toHaveBeenCalled()
}) })
it('should show errors on load if load groups failure', () => { it('should show errors on load if load groups failure', () => {
@ -278,44 +318,10 @@ describe('SettingsComponent', () => {
) )
completeSetup(groupService) completeSetup(groupService)
fixture.detectChanges() fixture.detectChanges()
expect(toastErrorSpy).toBeCalled() expect(toastErrorSpy).toHaveBeenCalled()
}) })
it('should load system status on initialize, show errors if needed', () => { it('should load system status on initialize, show errors if needed', () => {
const status: SystemStatus = {
pngx_version: '2.4.3',
server_os: 'macOS-14.1.1-arm64-arm-64bit',
install_type: InstallType.BareMetal,
storage: { total: 494384795648, available: 13573525504 },
database: {
type: 'sqlite',
url: '/paperless-ngx/data/db.sqlite3',
status: SystemStatusItemStatus.ERROR,
error: null,
migration_status: {
latest_migration: 'socialaccount.0006_alter_socialaccount_extra_data',
unapplied_migrations: [],
},
},
tasks: {
redis_url: 'redis://localhost:6379',
redis_status: SystemStatusItemStatus.ERROR,
redis_error:
'Error 61 connecting to localhost:6379. Connection refused.',
celery_status: SystemStatusItemStatus.ERROR,
celery_url: 'celery@localhost',
celery_error: 'Error connecting to celery@localhost',
index_status: SystemStatusItemStatus.OK,
index_last_modified: new Date().toISOString(),
index_error: null,
classifier_status: SystemStatusItemStatus.OK,
classifier_last_trained: new Date().toISOString(),
classifier_error: null,
sanity_check_status: SystemStatusItemStatus.ERROR,
sanity_check_last_run: new Date().toISOString(),
sanity_check_error: 'Error running sanity check.',
},
}
jest.spyOn(systemStatusService, 'get').mockReturnValue(of(status)) jest.spyOn(systemStatusService, 'get').mockReturnValue(of(status))
jest.spyOn(permissionsService, 'isAdmin').mockReturnValue(true) jest.spyOn(permissionsService, 'isAdmin').mockReturnValue(true)
completeSetup() completeSetup()
@ -332,6 +338,8 @@ describe('SettingsComponent', () => {
it('should open system status dialog', () => { it('should open system status dialog', () => {
const modalOpenSpy = jest.spyOn(modalService, 'open') const modalOpenSpy = jest.spyOn(modalService, 'open')
jest.spyOn(systemStatusService, 'get').mockReturnValue(of(status))
jest.spyOn(permissionsService, 'isAdmin').mockReturnValue(true)
completeSetup() completeSetup()
component.showSystemStatus() component.showSystemStatus()
expect(modalOpenSpy).toHaveBeenCalledWith(SystemStatusDialogComponent, { expect(modalOpenSpy).toHaveBeenCalledWith(SystemStatusDialogComponent, {
@ -345,4 +353,14 @@ describe('SettingsComponent', () => {
component.reset() component.reset()
expect(component.settingsForm.get('themeColor').value).toEqual('') expect(component.settingsForm.get('themeColor').value).toEqual('')
}) })
it('should trigger maybeRefreshDocumentCounts on settings save', () => {
completeSetup()
const maybeRefreshSpy = jest.spyOn(
savedViewsService,
'maybeRefreshDocumentCounts'
)
settingsService.settingsSaved.emit(true)
expect(maybeRefreshSpy).toHaveBeenCalled()
})
}) })

View File

@ -2,10 +2,10 @@ import { AsyncPipe, ViewportScroller } from '@angular/common'
import { import {
AfterViewInit, AfterViewInit,
Component, Component,
Inject,
LOCALE_ID, LOCALE_ID,
OnDestroy, OnDestroy,
OnInit, OnInit,
inject,
} from '@angular/core' } from '@angular/core'
import { import {
FormControl, FormControl,
@ -49,6 +49,7 @@ import {
PermissionsService, PermissionsService,
} from 'src/app/services/permissions.service' } from 'src/app/services/permissions.service'
import { GroupService } from 'src/app/services/rest/group.service' import { GroupService } from 'src/app/services/rest/group.service'
import { SavedViewService } from 'src/app/services/rest/saved-view.service'
import { UserService } from 'src/app/services/rest/user.service' import { UserService } from 'src/app/services/rest/user.service'
import { import {
LanguageOption, LanguageOption,
@ -56,6 +57,7 @@ import {
} from 'src/app/services/settings.service' } from 'src/app/services/settings.service'
import { SystemStatusService } from 'src/app/services/system-status.service' import { SystemStatusService } from 'src/app/services/system-status.service'
import { Toast, ToastService } from 'src/app/services/toast.service' import { Toast, ToastService } from 'src/app/services/toast.service'
import { locationReload } from 'src/app/utils/navigation'
import { CheckComponent } from '../../common/input/check/check.component' import { CheckComponent } from '../../common/input/check/check.component'
import { ColorComponent } from '../../common/input/color/color.component' import { ColorComponent } from '../../common/input/color/color.component'
import { PermissionsGroupComponent } from '../../common/input/permissions/permissions-group/permissions-group.component' import { PermissionsGroupComponent } from '../../common/input/permissions/permissions-group/permissions-group.component'
@ -104,6 +106,21 @@ export class SettingsComponent
extends ComponentWithPermissions extends ComponentWithPermissions
implements OnInit, AfterViewInit, OnDestroy, DirtyComponent implements OnInit, AfterViewInit, OnDestroy, DirtyComponent
{ {
private documentListViewService = inject(DocumentListViewService)
private toastService = inject(ToastService)
private settings = inject(SettingsService)
currentLocale = inject(LOCALE_ID)
private viewportScroller = inject(ViewportScroller)
private activatedRoute = inject(ActivatedRoute)
readonly tourService = inject(TourService)
private usersService = inject(UserService)
private groupsService = inject(GroupService)
private router = inject(Router)
permissionsService = inject(PermissionsService)
private modalService = inject(NgbModal)
private systemStatusService = inject(SystemStatusService)
private savedViewsService = inject(SavedViewService)
activeNavID: number activeNavID: number
settingsForm = new FormGroup({ settingsForm = new FormGroup({
@ -138,6 +155,7 @@ export class SettingsComponent
notificationsConsumerSuppressOnDashboard: new FormControl(null), notificationsConsumerSuppressOnDashboard: new FormControl(null),
savedViewsWarnOnUnsavedChange: new FormControl(null), savedViewsWarnOnUnsavedChange: new FormControl(null),
sidebarViewsShowCount: new FormControl(null),
}) })
SettingsNavIDs = SettingsNavIDs SettingsNavIDs = SettingsNavIDs
@ -167,7 +185,8 @@ export class SettingsComponent
this.systemStatus.tasks.classifier_status === this.systemStatus.tasks.classifier_status ===
SystemStatusItemStatus.ERROR || SystemStatusItemStatus.ERROR ||
this.systemStatus.tasks.sanity_check_status === this.systemStatus.tasks.sanity_check_status ===
SystemStatusItemStatus.ERROR SystemStatusItemStatus.ERROR ||
this.systemStatus.websocket_connected === SystemStatusItemStatus.ERROR
) )
} }
@ -179,24 +198,11 @@ export class SettingsComponent
) )
} }
constructor( constructor() {
private documentListViewService: DocumentListViewService,
private toastService: ToastService,
private settings: SettingsService,
@Inject(LOCALE_ID) public currentLocale: string,
private viewportScroller: ViewportScroller,
private activatedRoute: ActivatedRoute,
public readonly tourService: TourService,
private usersService: UserService,
private groupsService: GroupService,
private router: Router,
public permissionsService: PermissionsService,
private modalService: NgbModal,
private systemStatusService: SystemStatusService
) {
super() super()
this.settings.settingsSaved.subscribe(() => { this.settings.settingsSaved.subscribe(() => {
if (!this.savePending) this.initialize() if (!this.savePending) this.initialize()
this.savedViewsService.maybeRefreshDocumentCounts()
}) })
} }
@ -308,6 +314,9 @@ export class SettingsComponent
savedViewsWarnOnUnsavedChange: this.settings.get( savedViewsWarnOnUnsavedChange: this.settings.get(
SETTINGS_KEYS.SAVED_VIEWS_WARN_ON_UNSAVED_CHANGE SETTINGS_KEYS.SAVED_VIEWS_WARN_ON_UNSAVED_CHANGE
), ),
sidebarViewsShowCount: this.settings.get(
SETTINGS_KEYS.SIDEBAR_VIEWS_SHOW_COUNT
),
defaultPermsOwner: this.settings.get(SETTINGS_KEYS.DEFAULT_PERMS_OWNER), defaultPermsOwner: this.settings.get(SETTINGS_KEYS.DEFAULT_PERMS_OWNER),
defaultPermsViewUsers: this.settings.get( defaultPermsViewUsers: this.settings.get(
SETTINGS_KEYS.DEFAULT_PERMS_VIEW_USERS SETTINGS_KEYS.DEFAULT_PERMS_VIEW_USERS
@ -485,6 +494,10 @@ export class SettingsComponent
SETTINGS_KEYS.SAVED_VIEWS_WARN_ON_UNSAVED_CHANGE, SETTINGS_KEYS.SAVED_VIEWS_WARN_ON_UNSAVED_CHANGE,
this.settingsForm.value.savedViewsWarnOnUnsavedChange this.settingsForm.value.savedViewsWarnOnUnsavedChange
) )
this.settings.set(
SETTINGS_KEYS.SIDEBAR_VIEWS_SHOW_COUNT,
this.settingsForm.value.sidebarViewsShowCount
)
this.settings.set( this.settings.set(
SETTINGS_KEYS.DEFAULT_PERMS_OWNER, SETTINGS_KEYS.DEFAULT_PERMS_OWNER,
this.settingsForm.value.defaultPermsOwner this.settingsForm.value.defaultPermsOwner
@ -539,7 +552,7 @@ export class SettingsComponent
savedToast.content = $localize`Settings were saved successfully. Reload is required to apply some changes.` savedToast.content = $localize`Settings were saved successfully. Reload is required to apply some changes.`
savedToast.actionName = $localize`Reload now` savedToast.actionName = $localize`Reload now`
savedToast.action = () => { savedToast.action = () => {
location.reload() locationReload()
} }
} }

View File

@ -16,6 +16,7 @@ import {
NgbNavItem, NgbNavItem,
} from '@ng-bootstrap/ng-bootstrap' } from '@ng-bootstrap/ng-bootstrap'
import { allIcons, NgxBootstrapIconsModule } from 'ngx-bootstrap-icons' import { allIcons, NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { throwError } from 'rxjs'
import { routes } from 'src/app/app-routing.module' import { routes } from 'src/app/app-routing.module'
import { import {
PaperlessTask, PaperlessTask,
@ -28,6 +29,7 @@ import { PermissionsGuard } from 'src/app/guards/permissions.guard'
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe' import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
import { PermissionsService } from 'src/app/services/permissions.service' import { PermissionsService } from 'src/app/services/permissions.service'
import { TasksService } from 'src/app/services/tasks.service' import { TasksService } from 'src/app/services/tasks.service'
import { ToastService } from 'src/app/services/toast.service'
import { environment } from 'src/environments/environment' import { environment } from 'src/environments/environment'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { PageHeaderComponent } from '../../common/page-header/page-header.component' import { PageHeaderComponent } from '../../common/page-header/page-header.component'
@ -123,6 +125,7 @@ describe('TasksComponent', () => {
let router: Router let router: Router
let httpTestingController: HttpTestingController let httpTestingController: HttpTestingController
let reloadSpy let reloadSpy
let toastService: ToastService
beforeEach(async () => { beforeEach(async () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -157,6 +160,7 @@ describe('TasksComponent', () => {
httpTestingController = TestBed.inject(HttpTestingController) httpTestingController = TestBed.inject(HttpTestingController)
modalService = TestBed.inject(NgbModal) modalService = TestBed.inject(NgbModal)
router = TestBed.inject(Router) router = TestBed.inject(Router)
toastService = TestBed.inject(ToastService)
fixture = TestBed.createComponent(TasksComponent) fixture = TestBed.createComponent(TasksComponent)
component = fixture.componentInstance component = fixture.componentInstance
jest.useFakeTimers() jest.useFakeTimers()
@ -249,6 +253,42 @@ describe('TasksComponent', () => {
expect(dismissSpy).toHaveBeenCalledWith(selected) expect(dismissSpy).toHaveBeenCalledWith(selected)
}) })
it('should show an error and re-enable modal buttons when dismissing multiple tasks fails', () => {
component.selectedTasks = new Set([tasks[0].id, tasks[1].id])
const error = new Error('dismiss failed')
const toastSpy = jest.spyOn(toastService, 'showError')
const dismissSpy = jest
.spyOn(tasksService, 'dismissTasks')
.mockReturnValue(throwError(() => error))
let modal: NgbModalRef
modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1]))
component.dismissTasks()
expect(modal).not.toBeUndefined()
modal.componentInstance.confirmClicked.emit()
expect(dismissSpy).toHaveBeenCalledWith(new Set([tasks[0].id, tasks[1].id]))
expect(toastSpy).toHaveBeenCalledWith('Error dismissing tasks', error)
expect(modal.componentInstance.buttonsEnabled).toBe(true)
expect(component.selectedTasks.size).toBe(0)
})
it('should show an error when dismissing a single task fails', () => {
const error = new Error('dismiss failed')
const toastSpy = jest.spyOn(toastService, 'showError')
const dismissSpy = jest
.spyOn(tasksService, 'dismissTasks')
.mockReturnValue(throwError(() => error))
component.dismissTask(tasks[0])
expect(dismissSpy).toHaveBeenCalledWith(new Set([tasks[0].id]))
expect(toastSpy).toHaveBeenCalledWith('Error dismissing task', error)
expect(component.selectedTasks.size).toBe(0)
})
it('should support dismiss all tasks', () => { it('should support dismiss all tasks', () => {
let modal: NgbModalRef let modal: NgbModalRef
modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1])) modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1]))

View File

@ -1,5 +1,5 @@
import { NgTemplateOutlet, SlicePipe } from '@angular/common' import { NgTemplateOutlet, SlicePipe } from '@angular/common'
import { Component, OnDestroy, OnInit } from '@angular/core' import { Component, inject, OnDestroy, OnInit } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { import {
@ -24,6 +24,7 @@ import { PaperlessTask } from 'src/app/data/paperless-task'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive' import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe' import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
import { TasksService } from 'src/app/services/tasks.service' import { TasksService } from 'src/app/services/tasks.service'
import { ToastService } from 'src/app/services/toast.service'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { PageHeaderComponent } from '../../common/page-header/page-header.component' import { PageHeaderComponent } from '../../common/page-header/page-header.component'
import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
@ -69,6 +70,11 @@ export class TasksComponent
extends LoadingComponentWithPermissions extends LoadingComponentWithPermissions
implements OnInit, OnDestroy implements OnInit, OnDestroy
{ {
tasksService = inject(TasksService)
private modalService = inject(NgbModal)
private readonly router = inject(Router)
private readonly toastService = inject(ToastService)
public activeTab: TaskTab public activeTab: TaskTab
public selectedTasks: Set<number> = new Set() public selectedTasks: Set<number> = new Set()
public togggleAll: boolean = false public togggleAll: boolean = false
@ -105,14 +111,6 @@ export class TasksComponent
: $localize`Dismiss all` : $localize`Dismiss all`
} }
constructor(
public tasksService: TasksService,
private modalService: NgbModal,
private readonly router: Router
) {
super()
}
ngOnInit() { ngOnInit() {
this.tasksService.reload() this.tasksService.reload()
timer(5000, 5000) timer(5000, 5000)
@ -158,11 +156,19 @@ export class TasksComponent
modal.componentInstance.confirmClicked.pipe(first()).subscribe(() => { modal.componentInstance.confirmClicked.pipe(first()).subscribe(() => {
modal.componentInstance.buttonsEnabled = false modal.componentInstance.buttonsEnabled = false
modal.close() modal.close()
this.tasksService.dismissTasks(tasks) this.tasksService.dismissTasks(tasks).subscribe({
error: (e) => {
this.toastService.showError($localize`Error dismissing tasks`, e)
modal.componentInstance.buttonsEnabled = true
},
})
this.clearSelection() this.clearSelection()
}) })
} else { } else {
this.tasksService.dismissTasks(tasks) this.tasksService.dismissTasks(tasks).subscribe({
error: (e) =>
this.toastService.showError($localize`Error dismissing task`, e),
})
this.clearSelection() this.clearSelection()
} }
} }

View File

@ -11,7 +11,6 @@ import {
} from '@ng-bootstrap/ng-bootstrap' } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons' import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { of, throwError } from 'rxjs' import { of, throwError } from 'rxjs'
import { SafeHtmlPipe } from 'src/app/pipes/safehtml.pipe'
import { ToastService } from 'src/app/services/toast.service' import { ToastService } from 'src/app/services/toast.service'
import { TrashService } from 'src/app/services/trash.service' import { TrashService } from 'src/app/services/trash.service'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
@ -53,7 +52,6 @@ describe('TrashComponent', () => {
TrashComponent, TrashComponent,
PageHeaderComponent, PageHeaderComponent,
ConfirmDialogComponent, ConfirmDialogComponent,
SafeHtmlPipe,
], ],
}).compileComponents() }).compileComponents()

View File

@ -1,4 +1,4 @@
import { Component, OnDestroy } from '@angular/core' import { Component, OnDestroy, inject } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { import {
@ -36,19 +36,19 @@ export class TrashComponent
extends LoadingComponentWithPermissions extends LoadingComponentWithPermissions
implements OnDestroy implements OnDestroy
{ {
private trashService = inject(TrashService)
private toastService = inject(ToastService)
private modalService = inject(NgbModal)
private settingsService = inject(SettingsService)
private router = inject(Router)
public documentsInTrash: Document[] = [] public documentsInTrash: Document[] = []
public selectedDocuments: Set<number> = new Set() public selectedDocuments: Set<number> = new Set()
public allToggled: boolean = false public allToggled: boolean = false
public page: number = 1 public page: number = 1
public totalDocuments: number public totalDocuments: number
constructor( constructor() {
private trashService: TrashService,
private toastService: ToastService,
private modalService: NgbModal,
private settingsService: SettingsService,
private router: Router
) {
super() super()
this.reload() this.reload()
} }

View File

@ -7,7 +7,7 @@
> >
</pngx-page-header> </pngx-page-header>
@if (users) { @if (canViewUsers && users) {
<h4 class="d-flex"> <h4 class="d-flex">
<ng-container i18n>Users</ng-container> <ng-container i18n>Users</ng-container>
<button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editUser()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.User }"> <button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editUser()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.User }">
@ -26,7 +26,7 @@
@for (user of users; track user) { @for (user of users; track user) {
<li class="list-group-item"> <li class="list-group-item">
<div class="row"> <div class="row">
<div class="col d-flex align-items-center"><button class="btn btn-link p-0 text-start" type="button" (click)="editUser(user)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.User)">{{user.username}}</button></div> <div class="col d-flex align-items-center" [class.opacity-50]="!user.is_active"><button class="btn btn-link p-0 text-start" type="button" (click)="editUser(user)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.User)">{{user.username}}</button></div>
<div class="col d-flex align-items-center">{{user.first_name}} {{user.last_name}}</div> <div class="col d-flex align-items-center">{{user.first_name}} {{user.last_name}}</div>
<div class="col d-flex align-items-center">{{user.groups?.map(getGroupName, this).join(', ')}}</div> <div class="col d-flex align-items-center">{{user.groups?.map(getGroupName, this).join(', ')}}</div>
<div class="col"> <div class="col">
@ -45,7 +45,7 @@
</ul> </ul>
} }
@if (groups) { @if (canViewGroups && groups) {
<h4 class="mt-4 d-flex"> <h4 class="mt-4 d-flex">
<ng-container i18n>Groups</ng-container> <ng-container i18n>Groups</ng-container>
<button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editGroup()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.Group }"> <button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editGroup()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.Group }">
@ -86,7 +86,7 @@
</ul> </ul>
} }
@if (!users || !groups) { @if ((canViewUsers && !users) || (canViewGroups && !groups)) {
<div> <div>
<div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div> <div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div>
<div class="visually-hidden" i18n>Loading...</div> <div class="visually-hidden" i18n>Loading...</div>

View File

@ -19,6 +19,7 @@ import { GroupService } from 'src/app/services/rest/group.service'
import { UserService } from 'src/app/services/rest/user.service' import { UserService } from 'src/app/services/rest/user.service'
import { SettingsService } from 'src/app/services/settings.service' import { SettingsService } from 'src/app/services/settings.service'
import { ToastService } from 'src/app/services/toast.service' import { ToastService } from 'src/app/services/toast.service'
import * as navUtils from 'src/app/utils/navigation'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { GroupEditDialogComponent } from '../../common/edit-dialog/group-edit-dialog/group-edit-dialog.component' import { GroupEditDialogComponent } from '../../common/edit-dialog/group-edit-dialog/group-edit-dialog.component'
import { UserEditDialogComponent } from '../../common/edit-dialog/user-edit-dialog/user-edit-dialog.component' import { UserEditDialogComponent } from '../../common/edit-dialog/user-edit-dialog/user-edit-dialog.component'
@ -107,7 +108,7 @@ describe('UsersAndGroupsComponent', () => {
const toastErrorSpy = jest.spyOn(toastService, 'showError') const toastErrorSpy = jest.spyOn(toastService, 'showError')
const toastInfoSpy = jest.spyOn(toastService, 'showInfo') const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
editDialog.failed.emit() editDialog.failed.emit()
expect(toastErrorSpy).toBeCalled() expect(toastErrorSpy).toHaveBeenCalled()
settingsService.currentUser = users[1] // simulate logged in as different user settingsService.currentUser = users[1] // simulate logged in as different user
editDialog.succeeded.emit(users[0]) editDialog.succeeded.emit(users[0])
expect(toastInfoSpy).toHaveBeenCalledWith( expect(toastInfoSpy).toHaveBeenCalledWith(
@ -130,7 +131,7 @@ describe('UsersAndGroupsComponent', () => {
throwError(() => new Error('error deleting user')) throwError(() => new Error('error deleting user'))
) )
deleteDialog.confirm() deleteDialog.confirm()
expect(toastErrorSpy).toBeCalled() expect(toastErrorSpy).toHaveBeenCalled()
deleteSpy.mockReturnValueOnce(of(true)) deleteSpy.mockReturnValueOnce(of(true))
deleteDialog.confirm() deleteDialog.confirm()
expect(listAllSpy).toHaveBeenCalled() expect(listAllSpy).toHaveBeenCalled()
@ -142,19 +143,18 @@ describe('UsersAndGroupsComponent', () => {
let modal: NgbModalRef let modal: NgbModalRef
modalService.activeInstances.subscribe((refs) => (modal = refs[0])) modalService.activeInstances.subscribe((refs) => (modal = refs[0]))
component.editUser(users[0]) component.editUser(users[0])
const navSpy = jest
.spyOn(navUtils, 'setLocationHref')
.mockImplementation(() => {})
const editDialog = modal.componentInstance as UserEditDialogComponent const editDialog = modal.componentInstance as UserEditDialogComponent
editDialog.passwordIsSet = true editDialog.passwordIsSet = true
settingsService.currentUser = users[0] // simulate logged in as same user settingsService.currentUser = users[0] // simulate logged in as same user
editDialog.succeeded.emit(users[0]) editDialog.succeeded.emit(users[0])
fixture.detectChanges() fixture.detectChanges()
Object.defineProperty(window, 'location', {
value: {
href: 'http://localhost/',
},
writable: true, // possibility to override
})
tick(2600) tick(2600)
expect(window.location.href).toContain('logout') expect(navSpy).toHaveBeenCalledWith(
`${window.location.origin}/accounts/logout/?next=/accounts/login/?next=/`
)
})) }))
it('should support edit / create group, show error if needed', () => { it('should support edit / create group, show error if needed', () => {
@ -166,7 +166,7 @@ describe('UsersAndGroupsComponent', () => {
const toastErrorSpy = jest.spyOn(toastService, 'showError') const toastErrorSpy = jest.spyOn(toastService, 'showError')
const toastInfoSpy = jest.spyOn(toastService, 'showInfo') const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
editDialog.failed.emit() editDialog.failed.emit()
expect(toastErrorSpy).toBeCalled() expect(toastErrorSpy).toHaveBeenCalled()
editDialog.succeeded.emit(groups[0]) editDialog.succeeded.emit(groups[0])
expect(toastInfoSpy).toHaveBeenCalledWith( expect(toastInfoSpy).toHaveBeenCalledWith(
`Saved group "${groups[0].name}".` `Saved group "${groups[0].name}".`
@ -188,7 +188,7 @@ describe('UsersAndGroupsComponent', () => {
throwError(() => new Error('error deleting group')) throwError(() => new Error('error deleting group'))
) )
deleteDialog.confirm() deleteDialog.confirm()
expect(toastErrorSpy).toBeCalled() expect(toastErrorSpy).toHaveBeenCalled()
deleteSpy.mockReturnValueOnce(of(true)) deleteSpy.mockReturnValueOnce(of(true))
deleteDialog.confirm() deleteDialog.confirm()
expect(listAllSpy).toHaveBeenCalled() expect(listAllSpy).toHaveBeenCalled()
@ -210,7 +210,7 @@ describe('UsersAndGroupsComponent', () => {
) )
completeSetup(userService) completeSetup(userService)
fixture.detectChanges() fixture.detectChanges()
expect(toastErrorSpy).toBeCalled() expect(toastErrorSpy).toHaveBeenCalled()
}) })
it('should show errors on load if load groups failure', () => { it('should show errors on load if load groups failure', () => {
@ -222,6 +222,6 @@ describe('UsersAndGroupsComponent', () => {
) )
completeSetup(groupService) completeSetup(groupService)
fixture.detectChanges() fixture.detectChanges()
expect(toastErrorSpy).toBeCalled() expect(toastErrorSpy).toHaveBeenCalled()
}) })
}) })

View File

@ -1,15 +1,20 @@
import { Component, OnDestroy, OnInit } from '@angular/core' import { Component, OnDestroy, OnInit, inject } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons' import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { Subject, first, takeUntil } from 'rxjs' import { Subject, first, takeUntil } from 'rxjs'
import { Group } from 'src/app/data/group' import { Group } from 'src/app/data/group'
import { User } from 'src/app/data/user' import { User } from 'src/app/data/user'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive' import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { PermissionsService } from 'src/app/services/permissions.service' import {
PermissionAction,
PermissionType,
PermissionsService,
} from 'src/app/services/permissions.service'
import { GroupService } from 'src/app/services/rest/group.service' import { GroupService } from 'src/app/services/rest/group.service'
import { UserService } from 'src/app/services/rest/user.service' import { UserService } from 'src/app/services/rest/user.service'
import { SettingsService } from 'src/app/services/settings.service' import { SettingsService } from 'src/app/services/settings.service'
import { ToastService } from 'src/app/services/toast.service' import { ToastService } from 'src/app/services/toast.service'
import { setLocationHref } from 'src/app/utils/navigation'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component' import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component'
import { GroupEditDialogComponent } from '../../common/edit-dialog/group-edit-dialog/group-edit-dialog.component' import { GroupEditDialogComponent } from '../../common/edit-dialog/group-edit-dialog/group-edit-dialog.component'
@ -31,23 +36,34 @@ export class UsersAndGroupsComponent
extends ComponentWithPermissions extends ComponentWithPermissions
implements OnInit, OnDestroy implements OnInit, OnDestroy
{ {
private usersService = inject(UserService)
private groupsService = inject(GroupService)
private toastService = inject(ToastService)
private modalService = inject(NgbModal)
permissionsService = inject(PermissionsService)
private settings = inject(SettingsService)
users: User[] users: User[]
groups: Group[] groups: Group[]
unsubscribeNotifier: Subject<any> = new Subject() unsubscribeNotifier: Subject<any> = new Subject()
constructor( public get canViewUsers(): boolean {
private usersService: UserService, return this.permissionsService.currentUserCan(
private groupsService: GroupService, PermissionAction.View,
private toastService: ToastService, PermissionType.User
private modalService: NgbModal, )
public permissionsService: PermissionsService, }
private settings: SettingsService
) { public get canViewGroups(): boolean {
super() return this.permissionsService.currentUserCan(
PermissionAction.View,
PermissionType.Group
)
} }
ngOnInit(): void { ngOnInit(): void {
if (this.canViewUsers) {
this.usersService this.usersService
.listAll(null, null, { full_perms: true }) .listAll(null, null, { full_perms: true })
.pipe(first(), takeUntil(this.unsubscribeNotifier)) .pipe(first(), takeUntil(this.unsubscribeNotifier))
@ -59,7 +75,9 @@ export class UsersAndGroupsComponent
this.toastService.showError($localize`Error retrieving users`, e) this.toastService.showError($localize`Error retrieving users`, e)
}, },
}) })
}
if (this.canViewGroups) {
this.groupsService this.groupsService
.listAll(null, null, { full_perms: true }) .listAll(null, null, { full_perms: true })
.pipe(first(), takeUntil(this.unsubscribeNotifier)) .pipe(first(), takeUntil(this.unsubscribeNotifier))
@ -72,6 +90,7 @@ export class UsersAndGroupsComponent
}, },
}) })
} }
}
ngOnDestroy() { ngOnDestroy() {
this.unsubscribeNotifier.next(true) this.unsubscribeNotifier.next(true)
@ -97,7 +116,9 @@ export class UsersAndGroupsComponent
$localize`Password has been changed, you will be logged out momentarily.` $localize`Password has been changed, you will be logged out momentarily.`
) )
setTimeout(() => { setTimeout(() => {
window.location.href = `${window.location.origin}/accounts/logout/?next=/accounts/login/?next=/` setLocationHref(
`${window.location.origin}/accounts/logout/?next=/accounts/login/?next=/`
)
}, 2500) }, 2500)
} else { } else {
this.toastService.showInfo( this.toastService.showInfo(

View File

@ -68,6 +68,7 @@
<nav id="sidebarMenu" class="d-md-block bg-light sidebar collapse" <nav id="sidebarMenu" class="d-md-block bg-light sidebar collapse"
[ngClass]="slimSidebarEnabled ? 'slim' : 'col-md-3 col-lg-2 col-xxxl-1'" [class.animating]="slimSidebarAnimating" [ngClass]="slimSidebarEnabled ? 'slim' : 'col-md-3 col-lg-2 col-xxxl-1'" [class.animating]="slimSidebarAnimating"
[ngbCollapse]="isMenuCollapsed"> [ngbCollapse]="isMenuCollapsed">
@if (canSaveSettings) {
<button class="btn btn-sm btn-dark sidebar-slim-toggler" (click)="toggleSlimSidebar()"> <button class="btn btn-sm btn-dark sidebar-slim-toggler" (click)="toggleSlimSidebar()">
@if (slimSidebarEnabled) { @if (slimSidebarEnabled) {
<i-bs width="0.9em" height="0.9em" name="chevron-double-right"></i-bs> <i-bs width="0.9em" height="0.9em" name="chevron-double-right"></i-bs>
@ -75,6 +76,7 @@
<i-bs width="0.9em" height="0.9em" name="chevron-double-left"></i-bs> <i-bs width="0.9em" height="0.9em" name="chevron-double-left"></i-bs>
} }
</button> </button>
}
<div class="sidebar-sticky pt-3 d-flex flex-column justify-space-around"> <div class="sidebar-sticky pt-3 d-flex flex-column justify-space-around">
<ul class="nav flex-column"> <ul class="nav flex-column">
<li class="nav-item app-link"> <li class="nav-item app-link">
@ -108,11 +110,19 @@
<li class="nav-item w-100 app-link" cdkDrag [cdkDragDisabled]="!settingsService.organizingSidebarSavedViews" <li class="nav-item w-100 app-link" cdkDrag [cdkDragDisabled]="!settingsService.organizingSidebarSavedViews"
cdkDragPreviewContainer="parent" cdkDragPreviewClass="navItemDrag" (cdkDragStarted)="onDragStart($event)" cdkDragPreviewContainer="parent" cdkDragPreviewClass="navItemDrag" (cdkDragStarted)="onDragStart($event)"
(cdkDragEnded)="onDragEnd($event)"> (cdkDragEnded)="onDragEnd($event)">
<a class="nav-link" [class.text-truncate]="!slimSidebarEnabled" routerLink="view/{{view.id}}" <a class="nav-link" routerLink="view/{{view.id}}"
routerLinkActive="active" (click)="closeMenu()" [ngbPopover]="view.name" routerLinkActive="active" (click)="closeMenu()" [ngbPopover]="view.name"
[disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave"
popoverClass="popover-slim"> popoverClass="popover-slim">
<i-bs class="me-1" name="funnel"></i-bs><span>&nbsp;{{view.name}}</span> <i-bs class="me-1" name="funnel"></i-bs>
<span>&nbsp;<div class="d-inline-flex view-name"><span class="overflow-hidden" [class.text-wrap]="!slimSidebarEnabled">{{view.name}}</span></div>
@if (showSidebarCounts && !slimSidebarEnabled) {
<span class="badge bg-info text-dark ms-2 d-inline">{{ savedViewService.getDocumentCount(view) }}</span>
}
</span>
@if (showSidebarCounts && slimSidebarEnabled) {
<span class="badge bg-info text-dark position-absolute top-0 end-0 d-none d-md-block">{{ savedViewService.getDocumentCount(view) }}</span>
}
</a> </a>
@if (settingsService.organizingSidebarSavedViews) { @if (settingsService.organizingSidebarSavedViews) {
<div class="position-absolute end-0 top-0 px-3 py-2" [class.me-n3]="slimSidebarEnabled" cdkDragHandle> <div class="position-absolute end-0 top-0 px-3 py-2" [class.me-n3]="slimSidebarEnabled" cdkDragHandle>
@ -139,7 +149,7 @@
[disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave"
popoverClass="popover-slim"> popoverClass="popover-slim">
<i-bs class="me-1" name="file-text"></i-bs><span>&nbsp;{{d.title | documentTitle}}</span> <i-bs class="me-1" name="file-text"></i-bs><span>&nbsp;{{d.title | documentTitle}}</span>
<span class="close" (click)="closeDocument(d); $event.preventDefault()"> <span class="close flex-column justify-content-center" (click)="closeDocument(d); $event.preventDefault()">
<i-bs name="x"></i-bs> <i-bs name="x"></i-bs>
</span> </span>
</a> </a>

View File

@ -19,6 +19,10 @@
height: 0.8em; height: 0.8em;
} }
.view-name {
max-width: calc(100% - 50px)
}
.nav-group:not(:has(.app-link)) .sidebar-heading { .nav-group:not(:has(.app-link)) .sidebar-heading {
display: none !important; display: none !important;
} }
@ -187,7 +191,7 @@ main {
list-style-type: none; list-style-type: none;
&:hover .close { &:hover .close {
display: block; display: flex;
} }
.close { .close {

View File

@ -92,6 +92,7 @@ describe('AppFrameComponent', () => {
let router: Router let router: Router
let savedViewSpy let savedViewSpy
let modalService: NgbModal let modalService: NgbModal
let maybeRefreshSpy
beforeEach(async () => { beforeEach(async () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -113,7 +114,11 @@ describe('AppFrameComponent', () => {
{ {
provide: SavedViewService, provide: SavedViewService,
useValue: { useValue: {
reload: () => {}, reload: (fn: any) => {
if (fn) {
fn()
}
},
listAll: () => listAll: () =>
of({ of({
all: [saved_views.map((v) => v.id)], all: [saved_views.map((v) => v.id)],
@ -121,6 +126,8 @@ describe('AppFrameComponent', () => {
results: saved_views, results: saved_views,
}), }),
sidebarViews: saved_views.filter((v) => v.show_in_sidebar), sidebarViews: saved_views.filter((v) => v.show_in_sidebar),
getDocumentCount: (view: SavedView) => 5,
maybeRefreshDocumentCounts: () => {},
}, },
}, },
PermissionsService, PermissionsService,
@ -169,6 +176,7 @@ describe('AppFrameComponent', () => {
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true) jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
savedViewSpy = jest.spyOn(savedViewService, 'reload') savedViewSpy = jest.spyOn(savedViewService, 'reload')
maybeRefreshSpy = jest.spyOn(savedViewService, 'maybeRefreshDocumentCounts')
fixture = TestBed.createComponent(AppFrameComponent) fixture = TestBed.createComponent(AppFrameComponent)
component = fixture.componentInstance component = fixture.componentInstance
@ -359,4 +367,8 @@ describe('AppFrameComponent', () => {
expect(toastErrorSpy).toHaveBeenCalledTimes(2) expect(toastErrorSpy).toHaveBeenCalledTimes(2)
expect(toastInfoSpy).toHaveBeenCalledTimes(3) expect(toastInfoSpy).toHaveBeenCalledTimes(3)
}) })
it('should call maybeRefreshDocumentCounts after saved views reload', () => {
expect(maybeRefreshSpy).toHaveBeenCalled()
})
}) })

View File

@ -6,7 +6,7 @@ import {
moveItemInArray, moveItemInArray,
} from '@angular/cdk/drag-drop' } from '@angular/cdk/drag-drop'
import { NgClass } from '@angular/common' import { NgClass } from '@angular/common'
import { Component, HostListener, OnInit } from '@angular/core' import { Component, HostListener, inject, OnInit } from '@angular/core'
import { ActivatedRoute, Router, RouterModule } from '@angular/router' import { ActivatedRoute, Router, RouterModule } from '@angular/router'
import { import {
NgbCollapseModule, NgbCollapseModule,
@ -74,27 +74,27 @@ export class AppFrameComponent
extends ComponentWithPermissions extends ComponentWithPermissions
implements OnInit, ComponentCanDeactivate implements OnInit, ComponentCanDeactivate
{ {
versionString = `${environment.appTitle} ${environment.version}` router = inject(Router)
private activatedRoute = inject(ActivatedRoute)
private openDocumentsService = inject(OpenDocumentsService)
savedViewService = inject(SavedViewService)
private remoteVersionService = inject(RemoteVersionService)
settingsService = inject(SettingsService)
tasksService = inject(TasksService)
private readonly toastService = inject(ToastService)
private modalService = inject(NgbModal)
permissionsService = inject(PermissionsService)
private djangoMessagesService = inject(DjangoMessagesService)
appRemoteVersion: AppRemoteVersion appRemoteVersion: AppRemoteVersion
isMenuCollapsed: boolean = true isMenuCollapsed: boolean = true
slimSidebarAnimating: boolean = false slimSidebarAnimating: boolean = false
constructor( constructor() {
public router: Router,
private activatedRoute: ActivatedRoute,
private openDocumentsService: OpenDocumentsService,
public savedViewService: SavedViewService,
private remoteVersionService: RemoteVersionService,
public settingsService: SettingsService,
public tasksService: TasksService,
private readonly toastService: ToastService,
private modalService: NgbModal,
public permissionsService: PermissionsService,
private djangoMessagesService: DjangoMessagesService
) {
super() super()
const permissionsService = this.permissionsService
if ( if (
permissionsService.currentUserCan( permissionsService.currentUserCan(
@ -102,7 +102,9 @@ export class AppFrameComponent
PermissionType.SavedView PermissionType.SavedView
) )
) { ) {
this.savedViewService.reload() this.savedViewService.reload(() => {
this.savedViewService.maybeRefreshDocumentCounts()
})
} }
} }
@ -142,10 +144,27 @@ export class AppFrameComponent
}, 200) // slightly longer than css animation for slim sidebar }, 200) // slightly longer than css animation for slim sidebar
} }
get versionString(): string {
return `${environment.appTitle} v${this.settingsService.get(SETTINGS_KEYS.VERSION)}${environment.tag === 'prod' ? '' : ` #${environment.tag}`}`
}
get customAppTitle(): string { get customAppTitle(): string {
return this.settingsService.get(SETTINGS_KEYS.APP_TITLE) return this.settingsService.get(SETTINGS_KEYS.APP_TITLE)
} }
get canSaveSettings(): boolean {
return (
this.permissionsService.currentUserCan(
PermissionAction.Change,
PermissionType.UISettings
) &&
this.permissionsService.currentUserCan(
PermissionAction.Add,
PermissionType.UISettings
)
)
}
get slimSidebarEnabled(): boolean { get slimSidebarEnabled(): boolean {
return this.settingsService.get(SETTINGS_KEYS.SLIM_SIDEBAR) return this.settingsService.get(SETTINGS_KEYS.SLIM_SIDEBAR)
} }
@ -279,4 +298,11 @@ export class AppFrameComponent
onLogout() { onLogout() {
this.openDocumentsService.closeAll() this.openDocumentsService.closeAll()
} }
get showSidebarCounts(): boolean {
return (
this.settingsService.get(SETTINGS_KEYS.SIDEBAR_VIEWS_SHOW_COUNT) &&
!this.settingsService.organizingSidebarSavedViews
)
}
} }

View File

@ -89,7 +89,7 @@
@if (searchResults?.documents.length) { @if (searchResults?.documents.length) {
<h6 class="dropdown-header" i18n="@@searchResults.documents">Documents</h6> <h6 class="dropdown-header" i18n="@@searchResults.documents">Documents</h6>
@for (document of searchResults.documents; track document.id) { @for (document of searchResults.documents; track document.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: document, nameProp: 'title', type: DataType.Document, icon: 'file-text', date: document.added}"></ng-container> <ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: document, nameProp: 'title', type: DataType.Document, icon: 'file-text', date: document.created}"></ng-container>
} }
} }
@if (searchResults?.saved_views.length) { @if (searchResults?.saved_views.length) {

View File

@ -405,7 +405,7 @@ describe('GlobalSearchComponent', () => {
expect(toastErrorSpy).toHaveBeenCalled() expect(toastErrorSpy).toHaveBeenCalled()
// succeed // succeed
editDialog.succeeded.emit(true) editDialog.succeeded.emit(object as any)
expect(toastInfoSpy).toHaveBeenCalled() expect(toastInfoSpy).toHaveBeenCalled()
}) })
@ -456,7 +456,7 @@ describe('GlobalSearchComponent', () => {
expect(toastErrorSpy).toHaveBeenCalled() expect(toastErrorSpy).toHaveBeenCalled()
// succeed // succeed
editDialog.succeeded.emit(true) editDialog.succeeded.emit(searchResults.tags[0] as any)
expect(toastInfoSpy).toHaveBeenCalled() expect(toastInfoSpy).toHaveBeenCalled()
}) })
@ -529,6 +529,17 @@ describe('GlobalSearchComponent', () => {
expect(dispatchSpy).toHaveBeenCalledTimes(2) // once for keydown, second for click expect(dispatchSpy).toHaveBeenCalledTimes(2) // once for keydown, second for click
}) })
it('should support using base href in navigateOrOpenInNewWindow', () => {
jest
.spyOn(component['locationStrategy'], 'getBaseHref')
.mockReturnValue('/base/')
const openSpy = jest.spyOn(window, 'open')
const event = new Event('click')
event['ctrlKey'] = true
component.primaryAction(DataType.Document, { id: 1 }, event as any)
expect(openSpy).toHaveBeenCalledWith('/base/documents/1', '_blank')
})
it('should support title content search and advanced search', () => { it('should support title content search and advanced search', () => {
const qfSpy = jest.spyOn(documentListViewService, 'quickFilter') const qfSpy = jest.spyOn(documentListViewService, 'quickFilter')
component.query = 'test' component.query = 'test'

View File

@ -1,4 +1,4 @@
import { NgTemplateOutlet } from '@angular/common' import { LocationStrategy, NgTemplateOutlet } from '@angular/common'
import { import {
Component, Component,
ElementRef, ElementRef,
@ -6,6 +6,7 @@ import {
QueryList, QueryList,
ViewChild, ViewChild,
ViewChildren, ViewChildren,
inject,
} from '@angular/core' } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { Router } from '@angular/router' import { Router } from '@angular/router'
@ -69,6 +70,17 @@ import { WorkflowEditDialogComponent } from '../../common/edit-dialog/workflow-e
], ],
}) })
export class GlobalSearchComponent implements OnInit { export class GlobalSearchComponent implements OnInit {
searchService = inject(SearchService)
private router = inject(Router)
private modalService = inject(NgbModal)
private documentService = inject(DocumentService)
private documentListViewService = inject(DocumentListViewService)
private permissionsService = inject(PermissionsService)
private toastService = inject(ToastService)
private hotkeyService = inject(HotKeyService)
private settingsService = inject(SettingsService)
private locationStrategy = inject(LocationStrategy)
public DataType = DataType public DataType = DataType
public query: string public query: string
public queryDebounce: Subject<string> public queryDebounce: Subject<string>
@ -90,17 +102,7 @@ export class GlobalSearchComponent implements OnInit {
) )
} }
constructor( constructor() {
public searchService: SearchService,
private router: Router,
private modalService: NgbModal,
private documentService: DocumentService,
private documentListViewService: DocumentListViewService,
private permissionsService: PermissionsService,
private toastService: ToastService,
private hotkeyService: HotKeyService,
private settingsService: SettingsService
) {
this.queryDebounce = new Subject<string>() this.queryDebounce = new Subject<string>()
this.queryDebounce this.queryDebounce
@ -409,6 +411,9 @@ export class GlobalSearchComponent implements OnInit {
const ruleType = this.useAdvancedForFullSearch const ruleType = this.useAdvancedForFullSearch
? FILTER_FULLTEXT_QUERY ? FILTER_FULLTEXT_QUERY
: FILTER_TITLE_CONTENT : FILTER_TITLE_CONTENT
this.documentService.searchQuery = this.useAdvancedForFullSearch
? this.query
: ''
this.documentListViewService.quickFilter([ this.documentListViewService.quickFilter([
{ rule_type: ruleType, value: this.query }, { rule_type: ruleType, value: this.query },
]) ])
@ -421,10 +426,13 @@ export class GlobalSearchComponent implements OnInit {
extras: Object = {} extras: Object = {}
) { ) {
if (newWindow) { if (newWindow) {
const url = this.router.serializeUrl( const serializedUrl = this.router.serializeUrl(
this.router.createUrlTree(commands, extras) this.router.createUrlTree(commands, extras)
) )
window.open(url, '_blank') const baseHref = this.locationStrategy.getBaseHref()
const fullUrl =
baseHref.replace(/\/+$/, '') + '/' + serializedUrl.replace(/^\/+/, '')
window.open(fullUrl, '_blank')
} else { } else {
this.router.navigate(commands, extras) this.router.navigate(commands, extras)
} }

View File

@ -1,4 +1,4 @@
import { Component, OnDestroy, OnInit } from '@angular/core' import { Component, OnDestroy, OnInit, inject } from '@angular/core'
import { import {
NgbDropdownModule, NgbDropdownModule,
NgbProgressbarModule, NgbProgressbarModule,
@ -20,7 +20,7 @@ import { ToastComponent } from '../../common/toast/toast.component'
], ],
}) })
export class ToastsDropdownComponent implements OnInit, OnDestroy { export class ToastsDropdownComponent implements OnInit, OnDestroy {
constructor(public toastService: ToastService) {} toastService = inject(ToastService)
private subscription: Subscription private subscription: Subscription

View File

@ -8,7 +8,7 @@
<p><b>{{messageBold}}</b></p> <p><b>{{messageBold}}</b></p>
} }
@if (message) { @if (message) {
<p class="mb-0" [innerHTML]="message | safeHtml"></p> <p class="mb-0" [innerHTML]="message"></p>
} }
</div> </div>
<div class="modal-footer"> <div class="modal-footer">

View File

@ -1,7 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing' import { ComponentFixture, TestBed } from '@angular/core/testing'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { Subject } from 'rxjs' import { Subject } from 'rxjs'
import { SafeHtmlPipe } from 'src/app/pipes/safehtml.pipe'
import { ConfirmDialogComponent } from './confirm-dialog.component' import { ConfirmDialogComponent } from './confirm-dialog.component'
describe('ConfirmDialogComponent', () => { describe('ConfirmDialogComponent', () => {
@ -11,8 +10,8 @@ describe('ConfirmDialogComponent', () => {
beforeEach(async () => { beforeEach(async () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
providers: [NgbActiveModal, SafeHtmlPipe], providers: [NgbActiveModal],
imports: [ConfirmDialogComponent, SafeHtmlPipe], imports: [ConfirmDialogComponent],
}).compileComponents() }).compileComponents()
modal = TestBed.inject(NgbActiveModal) modal = TestBed.inject(NgbActiveModal)

View File

@ -1,20 +1,17 @@
import { DecimalPipe } from '@angular/common' import { DecimalPipe } from '@angular/common'
import { Component, EventEmitter, Input, Output } from '@angular/core' import { Component, EventEmitter, Input, Output, inject } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { Subject } from 'rxjs' import { Subject } from 'rxjs'
import { SafeHtmlPipe } from 'src/app/pipes/safehtml.pipe'
import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
@Component({ @Component({
selector: 'pngx-confirm-dialog', selector: 'pngx-confirm-dialog',
templateUrl: './confirm-dialog.component.html', templateUrl: './confirm-dialog.component.html',
styleUrls: ['./confirm-dialog.component.scss'], styleUrls: ['./confirm-dialog.component.scss'],
imports: [DecimalPipe, SafeHtmlPipe], imports: [DecimalPipe],
}) })
export class ConfirmDialogComponent extends LoadingComponentWithPermissions { export class ConfirmDialogComponent extends LoadingComponentWithPermissions {
constructor(public activeModal: NgbActiveModal) { activeModal = inject(NgbActiveModal)
super()
}
@Output() @Output()
public confirmClicked = new EventEmitter() public confirmClicked = new EventEmitter()

Some files were not shown because too many files have changed in this diff Show More