Compare commits

..

223 Commits

Author SHA1 Message Date
shamoon
026daac77d 2.0.0-beta.1 2023-11-13 19:59:49 -08:00
shamoon
3239c478a5 Merge branch 'main' into dev 2023-11-13 19:57:08 -08:00
Paperless-ngx Bot [bot]
8f2ca5761b New Crowdin updates (#4472) 2023-11-13 19:56:39 -08:00
shamoon
ef9669cdb6 Fix: Miscellaneous v2.0 visual fixes (#4576)
* Fix notes count in tab button wrapping

* Fix position of custom fields dropdown on mobile

* Limit list view title width

* Update messages.xlf
2023-11-13 19:54:01 -08:00
Trenton H
caddcaf807 Forces JSON files to be written as UTF-8, and disables the ensure ASCII option which escapes non-ASCII chars (#4574) 2023-11-13 14:18:21 -08:00
shamoon
90707d661b Feature: compact toasts (#4545) 2023-11-13 21:17:44 +00:00
Trenton H
facb7226fe Chore: Backend bulk updates (#4509) 2023-11-13 17:09:56 +00:00
shamoon
b671f54cb7 Chore: Close answered discussions (#4565) 2023-11-13 16:59:36 +00:00
shamoon
55f26c9c4c Documentation: update docs, screenshots ahead of Paperless-ngx v2.0 (#4542)
* Reformat internal links

* Update screenshots, docs & readme

* Use image lightbox

* Fix nested list on docs index

* Add some visual interest to screenshots layout

* Compress images
2023-11-13 14:56:34 +00:00
shamoon
18995b3561 Fix plain text preview overflow (#4555) 2023-11-13 06:44:07 -08:00
shamoon
8e3fbdddc7 Adds Hungarian translation (#4552) 2023-11-12 16:39:17 -08:00
shamoon
c19df84bef Fix: use ngSwitch for custom fields 2023-11-09 15:07:49 -08:00
Trenton H
e8527ba723 Chore: Cleanup command arguments and standardize process count handling (#4541)
Cleans up some command help text and adds more control over process count for command with a Pool
2023-11-09 11:46:37 -08:00
Jasmin
577b49df9d Documentation: Add link to wiki for SELinux troubleshooting (#4528)
* Add section for SELinux troubleshooting

* Update docs/troubleshooting.md

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-11-09 18:06:51 +00:00
Rock
5b83bd03f5 Documentation: clarify document_exporter includes settings (#4533) 2023-11-09 06:20:27 -08:00
shamoon
73cbf6c33d API support for id args for documents & objects (#4519) 2023-11-06 12:31:10 -08:00
shamoon
95ab3b99f8 Fix: matrix chat link 2023-11-06 11:18:00 -08:00
shamoon
24dbf669a9 Fix: add permissions for custom fields with migration (#4513) 2023-11-06 08:05:35 -08:00
shamoon
8716590cef Chore: Restore codecov commenting to internal PRs (#4508)
Test out changes to code cov config

Co-Authored-By: Trenton H <797416+stumpylog@users.noreply.github.com>
2023-11-05 17:30:04 -08:00
shamoon
10729f0362 Feature: Implement custom fields for documents (#4502)
Adds custom fields of certain data types, attachable to documents and searchable

Co-Authored-By: Trenton H <797416+stumpylog@users.noreply.github.com>
2023-11-05 17:27:23 -08:00
dependabot[bot]
800f54f263 Bump @types/node from 20.8.0 to 20.8.10 in /src-ui (#4482)
Co-Authored-By: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-05 17:26:37 -08:00
dependabot[bot]
e63a543c29 Bump the frontend-eslint-dependencies group in /src-ui with 3 updates (#4479)
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 [eslint](https://github.com/eslint/eslint).


Updates `@typescript-eslint/eslint-plugin` from 6.7.3 to 6.9.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/v6.9.1/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.7.3 to 6.9.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/v6.9.1/packages/parser)

Updates `eslint` from 8.50.0 to 8.52.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/v8.50.0...v8.52.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 21:05:26 +00:00
shamoon
0f08796e1b Allow more dependabot updates at once 2023-11-01 13:53:02 -07:00
dependabot[bot]
d10c32bad6 Bump @playwright/test from 1.38.1 to 1.39.0 in /src-ui (#4480)
Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.38.1 to 1.39.0.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.38.1...v1.39.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 20:36:41 +00:00
dependabot[bot]
813ad6551c Bump concurrently from 8.2.1 to 8.2.2 in /src-ui (#4481)
Bumps [concurrently](https://github.com/open-cli-tools/concurrently) from 8.2.1 to 8.2.2.
- [Release notes](https://github.com/open-cli-tools/concurrently/releases)
- [Commits](https://github.com/open-cli-tools/concurrently/compare/v8.2.1...v8.2.2)

---
updated-dependencies:
- dependency-name: concurrently
  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>
2023-11-01 20:24:14 +00:00
dependabot[bot]
5582b33d40 Bump the frontend-jest-dependencies group in /src-ui with 1 update (#4478)
Bumps the frontend-jest-dependencies group in /src-ui with 1 update: [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest).

- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: "@types/jest"
  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>
2023-11-01 20:10:31 +00:00
dependabot[bot]
79afc236c9 Bump the frontend-angular-dependencies group in /src-ui with 14 updates (#4477)
Bumps the frontend-angular-dependencies group in /src-ui with 14 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/cdk](https://github.com/angular/components) | `16.2.7` | `16.2.11` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `16.2.7` | `16.2.11` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `16.2.7` | `16.2.11` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `16.2.7` | `16.2.11` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `16.2.7` | `16.2.11` |
| [@angular/localize](https://github.com/angular/angular) | `16.2.7` | `16.2.11` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `16.2.7` | `16.2.11` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `16.2.7` | `16.2.11` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `16.2.7` | `16.2.11` |
| [@ng-bootstrap/ng-bootstrap](https://github.com/ng-bootstrap/ng-bootstrap) | `15.1.1` | `15.1.2` |
| [@ng-select/ng-select](https://github.com/ng-select/ng-select) | `11.1.1` | `11.2.0` |
| [ngx-ui-tour-ng-bootstrap](https://github.com/hakimio/ngx-ui-tour) | `13.0.4` | `13.0.6` |
| [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `16.2.4` | `16.2.9` |
| [@angular/cli](https://github.com/angular/angular-cli) | `16.2.4` | `16.2.9` |


Updates `@angular/cdk` from 16.2.7 to 16.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/16.2.7...16.2.11)

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

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

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

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

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

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

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

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

Updates `@ng-bootstrap/ng-bootstrap` from 15.1.1 to 15.1.2
- [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/15.1.1...15.1.2)

Updates `@ng-select/ng-select` from 11.1.1 to 11.2.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/v11.1.1...v11.2.0)

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

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

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

---
updated-dependencies:
- dependency-name: "@angular/cdk"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/common"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-bootstrap/ng-bootstrap"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-select/ng-select"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-ui-tour-ng-bootstrap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/build-angular"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  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>
2023-11-01 12:56:38 -07:00
dependabot[bot]
1f83a75d5f Bump the actions group with 1 update (#4476)
Bumps the actions group with 1 update: [actions/setup-node](https://github.com/actions/setup-node).

- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  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>
2023-11-01 11:22:39 -07:00
shamoon
2a3baf5aec Adds Bulgarian translation (#4470) 2023-11-01 06:49:52 -07:00
Paperless-ngx Bot [bot]
f92ae3b232 New Crowdin updates (#4113) 2023-10-31 15:45:28 -07:00
shamoon
03523244ef Update share-links-dropdown.component.ts 2023-10-31 15:44:53 -07:00
shamoon
55e799b833 Fix: visually hidden text breaks delete button wrap (#4462) 2023-10-30 19:57:11 -07:00
shamoon
10929e9ac8 Fix: API statistics document_file_type_counts return type (#4464) 2023-10-30 16:35:42 -07:00
shamoon
89757609c2 Fix: Always return a list for audit log check (#4463) 2023-10-30 22:47:59 +00:00
shamoon
0f1dea67b7 Chore: upgrade python-ipware dependency (#4446) 2023-10-30 10:16:49 -07:00
nanokatz
38e035b95c Feature: Audit Trail (#4425)
Adds new feature for optionally enabling change tracking for possible audit purposes
---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
Co-authored-by: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
2023-10-30 09:23:22 -07:00
shamoon
f695d4b9da Fix: correct some form typography and styling 2023-10-27 11:41:55 -07:00
Trenton H
4fbe7f16f3 Stops duplicated action runs against internal PRs (#4430) 2023-10-26 01:05:52 +00:00
Trenton H
dcc2cc5001 Only get or create a Correspondent if the email or attachment matches rule filters (#4431) 2023-10-26 00:34:52 +00:00
Trenton H
cb271deb8f Fixes the returning of a set, change to a list instead (#4442) 2023-10-25 16:18:13 -07:00
Trenton H
d480e91196 Feature: Add ahead of time compression of the static files for x86_64 (#4390)
Compressed staticfiles. x86_64 only at this point
2023-10-20 16:22:05 -07:00
shamoon
9880f9ebc7 Feature: support sorting sidebar saved views (#4381) 2023-10-20 02:41:01 +00:00
Trenton H
999ae678c2 Feature: Switches to a new client to handle communication with Gotenberg (#4391)
Switches to a new client to handle communication with Gotenberg for merging and generating PDFs
2023-10-20 00:27:29 +00:00
Sebastian Porombka
5f0eba694c Documentation: note stripping of non-numeric characters from ASN barcode during processing (#4402) 2023-10-19 15:06:48 +00:00
Musa Ahmed
f893ba929a Change: Install script improvements (#4387)
* (1) Made curl command to download installation script silent while allowing erros to be dispalyed. (2) Made `if ! command -v ${DOCKER_COMPOSE_CMD}` silent as the other checks are as well.

* Made curl options more clear
2023-10-19 02:49:37 +00:00
shamoon
d35b0423b6 Update bug-report.yml 2023-10-18 12:12:28 -07:00
shamoon
651a22d056 Update bug-report.yml 2023-10-18 12:09:24 -07:00
shamoon
8dee246854 Update bug-report.yml 2023-10-18 12:08:10 -07:00
Sebastian Porombka
90db397ec6 barcode logic: strip non-numeric characters from detected ASN string (#4379)
* legacy barcodes exist which still contain characters after the number. the current logic did not truncate them. instead, int() was called from the remaining string. this does not work in this case. it is therefore sufficient to continue processing numeric characters.

* lint

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-10-17 03:44:22 +00:00
dependabot[bot]
cf973ff41e Bump @babel/traverse from 7.22.11 to 7.23.2 in /src-ui (#4389)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.22.11 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 20:01:59 -07:00
shamoon
fd8de5b1ea Fix: replace drag drop & clipboard dependencies with Angular CDK (#4362)
* Swap ngx-drag-drop dependency for Angular CDK

* Swap ngx-clipboard dependency for Angular CDK
2023-10-16 19:46:16 -07:00
shamoon
27772257a8 Fix btn-link hover colors per primary color lightness 2023-10-15 13:58:40 -07:00
shamoon
5665db844e Fix: hover colors, empty lists, disable autocomplete, translation strings 2023-10-15 12:00:30 -07:00
shamoon
21a9963a2b Fix: dashboard sidebar sticky, bottom margin 2023-10-15 11:34:59 -07:00
shamoon
99f260225a Fix: update document modified time on note creation / deletion (#4374)
* Update document modified on add or delete notes

* Add document extra endpoints info to docs
2023-10-14 16:24:13 -07:00
shamoon
e4054d684c Fix: correct set owner API location in docs, additional test (#4366)
* Fix location of owner in API documentation

* Add additional test for setting another owner
2023-10-13 09:16:17 -07:00
Trenton H
01af725d79 Remove old information about building the Docker image locally (#4354) 2023-10-11 13:52:28 +00:00
Trenton H
db0f31adea Updates to latest imap_tools which includes fix for the meta charset tag in HTML content of emails (#4355) 2023-10-11 06:32:22 -07:00
shamoon
226c771735 Add AI note 2023-10-10 08:42:31 -07:00
Trenton H
b18b070622 Renames the email certificate so it doesn't get read during Docker startup (#4346) 2023-10-09 14:47:31 -07:00
Trenton H
e52ae28426 Fixes a missing directory pre-create in Docker image (#4347) 2023-10-09 14:33:21 -07:00
shamoon
6acd30eda1 Fix slim sidebar animation on xxxl screens 2023-10-09 10:01:14 -07:00
shamoon
f170cc0354 CI: Install frontend dependencies separately, once (#4336) 2023-10-09 09:44:20 -07:00
shamoon
d9abae51b5 Merge branch 'v2.0-visual-fixes' into dev 2023-10-07 19:42:47 -07:00
Trenton H
ada67bd54e Retry Tika parsing with PUT instead of form data in the event of a 500 error response (#4334) 2023-10-07 18:36:27 -07:00
shamoon
f7f5d0efa6 Fix: get highest ASN regardless of user (#4326) 2023-10-06 17:22:31 -07:00
Trenton H
a2bdd64ad0 Feature: Include more updated base tools in Docker image (#4319)
* New method for installing jbig2enc
* Installs newer qpdf, ghostscript as well as jbig2enc
2023-10-05 10:51:58 -07:00
dependabot[bot]
48f4f21d28 Bump postcss from 8.4.12 to 8.4.31 in /src/paperless_mail/templates (#4318)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.12 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.12...8.4.31)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-05 07:37:59 +00:00
shamoon
57b8ee37ec CI: Shard frontend tests, improve GC, use max workers (#4316) 2023-10-04 19:35:16 -07:00
Trenton H
71bf8eb332 Upgrades all backend libraries and development tools/hooks to latest versions (#4305) 2023-10-02 17:01:16 -07:00
dependabot[bot]
fb1e288580 Bump @types/node from 20.7.0 to 20.8.0 in /src-ui (#4303)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.7.0 to 20.8.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-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>
2023-10-01 21:27:48 +00:00
dependabot[bot]
720c6dd3b0 Bump the frontend-angular-dependencies group in /src-ui with 8 updates (#4302)
Bumps the frontend-angular-dependencies group in /src-ui with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `16.2.6` | `16.2.7` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `16.2.6` | `16.2.7` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `16.2.6` | `16.2.7` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `16.2.6` | `16.2.7` |
| [@angular/localize](https://github.com/angular/angular) | `16.2.6` | `16.2.7` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `16.2.6` | `16.2.7` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `16.2.6` | `16.2.7` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `16.2.6` | `16.2.7` |


Updates `@angular/common` from 16.2.6 to 16.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/16.2.7/packages/common)

Updates `@angular/compiler` from 16.2.6 to 16.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/16.2.7/packages/compiler)

Updates `@angular/core` from 16.2.6 to 16.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/16.2.7/packages/core)

Updates `@angular/forms` from 16.2.6 to 16.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/16.2.7/packages/forms)

Updates `@angular/localize` from 16.2.6 to 16.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/16.2.6...16.2.7)

Updates `@angular/platform-browser` from 16.2.6 to 16.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/16.2.7/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 16.2.6 to 16.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/16.2.7/packages/platform-browser-dynamic)

Updates `@angular/router` from 16.2.6 to 16.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/16.2.7/packages/router)

---
updated-dependencies:
- dependency-name: "@angular/common"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-type: direct:production
  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>
2023-10-01 21:16:33 +00:00
shamoon
be6506da08 Feature: password reset (#4289) 2023-09-30 18:17:42 -07:00
shamoon
4f6698e39f Update mkdocs.yml 2023-09-29 22:40:10 -07:00
shamoon
cdcd22e6a6 Revert #4292 2023-09-28 21:58:40 -07:00
shamoon
b1b3eb4406 Fix removed pull_request event from ci 2023-09-28 21:54:03 -07:00
shamoon
b0c6f5e56b Remove ignore translation branches from ci (#4292) 2023-09-28 20:01:38 -07:00
shamoon
322d8a61c2 Merge branch 'main' into dev 2023-09-28 12:13:43 -07:00
shamoon
d41c4730cd Show docs search shortcut key 2023-09-28 12:02:35 -07:00
shamoon
b38bb47491 Show docs search shortcut key 2023-09-28 11:59:31 -07:00
shamoon
6973691cce Enhancement: dashboard improvements, drag-n-drop reorder dashboard views (#4252)
* Updated dashboard

* Make entire screen dropzone on dashboard too

* Floating upload widget status alerts

* Visual tweaks: spacing, borders

* Better empty view widget

* Support drag + drop reorder of dashboard saved views

* Update messages.xlf

* Disable dashbaord dnd if global dnd active

* Remove ngx-file-drop dep, rebuild file-drop & upload files widget

* Revert custom file drop implementation

* Try patch-package fix

* Simplify dropzone transitions to make more reliable

* Update messages.xlf

* Update dashboard.spec.ts

* Fix coverage
2023-09-28 10:18:12 -07:00
Trenton H
96176589ca Updates the secret key generation to override locale settings and provide more entropy (#4277) 2023-09-28 09:33:41 -07:00
shamoon
a74740877a Fix: remove note max height (#4287) 2023-09-28 09:20:07 -07:00
dependabot[bot]
1de4072a48 Bump the frontend-eslint-dependencies group in /src-ui with 3 updates (#4283)
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 [eslint](https://github.com/eslint/eslint).


Updates `@typescript-eslint/eslint-plugin` from 6.7.2 to 6.7.3
- [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/v6.7.3/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.7.2 to 6.7.3
- [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/v6.7.3/packages/parser)

Updates `eslint` from 8.49.0 to 8.50.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/v8.49.0...v8.50.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-28 03:16:32 +00:00
dependabot[bot]
cf2796b2af Bump the frontend-angular-dependencies group in /src-ui with 10 updates (#4282)
Bumps the frontend-angular-dependencies group in /src-ui with 10 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `16.2.5` | `16.2.6` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `16.2.5` | `16.2.6` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `16.2.5` | `16.2.6` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `16.2.5` | `16.2.6` |
| [@angular/localize](https://github.com/angular/angular) | `16.2.5` | `16.2.6` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `16.2.5` | `16.2.6` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `16.2.5` | `16.2.6` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `16.2.5` | `16.2.6` |
| [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `16.2.3` | `16.2.4` |
| [@angular/cli](https://github.com/angular/angular-cli) | `16.2.3` | `16.2.4` |


Updates `@angular/common` from 16.2.5 to 16.2.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/16.2.6/packages/common)

Updates `@angular/compiler` from 16.2.5 to 16.2.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/16.2.6/packages/compiler)

Updates `@angular/core` from 16.2.5 to 16.2.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/16.2.6/packages/core)

Updates `@angular/forms` from 16.2.5 to 16.2.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/16.2.6/packages/forms)

Updates `@angular/localize` from 16.2.5 to 16.2.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/16.2.5...16.2.6)

Updates `@angular/platform-browser` from 16.2.5 to 16.2.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/16.2.6/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 16.2.5 to 16.2.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/16.2.6/packages/platform-browser-dynamic)

Updates `@angular/router` from 16.2.5 to 16.2.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/16.2.6/packages/router)

Updates `@angular-devkit/build-angular` from 16.2.3 to 16.2.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/16.2.3...16.2.4)

Updates `@angular/cli` from 16.2.3 to 16.2.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/16.2.3...16.2.4)

---
updated-dependencies:
- dependency-name: "@angular/common"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/build-angular"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  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>
2023-09-27 23:12:20 +00:00
Trenton H
85315b768c Updates Django to 4.2.5 (#4278) 2023-09-27 10:45:51 -07:00
dependabot[bot]
76a147e58b Bump @types/node from 20.6.3 to 20.7.0 in /src-ui (#4284)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.6.3 to 20.7.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-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>
2023-09-27 17:07:43 +00:00
dependabot[bot]
de88c6de8c Bump leonsteinhaeuser/project-beta-automations from 2.1.0 to 2.2.1 (#4281)
Bumps [leonsteinhaeuser/project-beta-automations](https://github.com/leonsteinhaeuser/project-beta-automations) from 2.1.0 to 2.2.1.
- [Release notes](https://github.com/leonsteinhaeuser/project-beta-automations/releases)
- [Commits](https://github.com/leonsteinhaeuser/project-beta-automations/compare/v2.1.0...v2.2.1)

---
updated-dependencies:
- dependency-name: leonsteinhaeuser/project-beta-automations
  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>
2023-09-27 16:44:36 +00:00
Trenton H
613b429540 Updates dependabot to group some backend deps and all Github actions updates (#4280) 2023-09-27 09:32:25 -07:00
shamoon
d9abb745a9 Merge branch 'main' into dev 2023-09-26 13:33:27 -07:00
shamoon
702225f535 Update bug-report.yml 2023-09-26 13:33:17 -07:00
Trenton H
612e6341a3 Ensures all old connections are closed in certain longer running locations (#4265) 2023-09-25 12:52:22 -07:00
shamoon
70b566f746 Update translation string for tasks dialog (#4263) 2023-09-25 10:53:36 -07:00
shamoon
6dd69126ae Update messages.xlf 2023-09-25 07:33:40 -07:00
shamoon
f3d6756fba Enhancement: settings reorganization & improvements, separate admin section (#4251)
* Separate admin / manage sections

* Move mail settings to its own component

* Move users and groups to its own component

* Move default permissions to its own settings tab

* Unify list styling, add tour step, refactor components

* Only patch saved views that have changed on settings save

* Update messages.xlf

* Remove unused methods in settings.component.ts

* Drop admin section to bottom of sidebar, cleanup outdated, add docs link to dropdown

* Better visually unify management list & other list pages
2023-09-24 19:24:28 -07:00
Trenton H
8d60506884 Standarizes the imports across all the files and modules (#4248) 2023-09-23 20:17:01 -07:00
shamoon
9712ac109d Feature: consumption templates (#4196)
* Initial implementation of consumption templates

* Frontend implementation of consumption templates

Testing

* Support consumption template source

* order templates, automatically add permissions

* Support title assignment in consumption templates

* Refactoring, filters to and, show sources on list

Show sources on template list, update some translation strings

Make filters and

minor testing

* Update strings

* Only update django-multiselectfield

* Basic docs, document some methods

* Improve testing coverage, template multi-assignment merges
2023-09-22 16:53:13 -07:00
shamoon
379b4f8cd3 Documentation enhancement: add direct links for all config vars (#4237) 2023-09-22 11:12:47 -07:00
shamoon
86d223fd93 Fix mixed rule / owner check, component input / output 2023-09-22 01:20:25 -07:00
shamoon
205106b566 Support edit permissions for mail rules and accounts 2023-09-22 01:01:35 -07:00
shamoon
54099d8441 Fix settings users initialization before groups 2023-09-21 23:35:40 -07:00
shamoon
7c8b501c40 Run npx install playwright in src-ui dir (#4239) 2023-09-21 17:13:19 -07:00
shamoon
02bf0349ca Support default permissions for object creation via frontend (#4233) 2023-09-21 16:28:22 -07:00
shamoon
9d72d1fc81 Update playwright so ci doesnt start failing 2023-09-21 15:12:39 -07:00
Trenton H
085e6da1f2 Handle when INotify fails to import but the polling is set to 0 still (#4230) 2023-09-20 14:04:42 -07:00
Trenton H
1ce0eae931 Creates folders and adjusts permissions before declaring the volumes (#4225) 2023-09-20 11:39:31 -07:00
dependabot[bot]
ff5c25fc8c Bump zone.js from 0.13.1 to 0.13.3 in /src-ui (#4223)
Bumps [zone.js](https://github.com/angular/angular/tree/HEAD/packages/zone.js) from 0.13.1 to 0.13.3.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/packages/zone.js/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/zone.js-0.13.3/packages/zone.js)

---
updated-dependencies:
- dependency-name: zone.js
  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>
2023-09-20 14:39:03 +00:00
dependabot[bot]
ef863bec7c Bump @types/node from 20.5.8 to 20.6.3 in /src-ui (#4224)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.5.8 to 20.6.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-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>
2023-09-20 14:23:33 +00:00
dependabot[bot]
89117da57d Bump the frontend-angular-dependencies group in /src-ui with 2 updates (#4222)
Bumps the frontend-angular-dependencies group in /src-ui with 2 updates: [@angular-devkit/build-angular](https://github.com/angular/angular-cli) and [@angular/cli](https://github.com/angular/angular-cli).


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

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

---
updated-dependencies:
- dependency-name: "@angular-devkit/build-angular"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  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>
2023-09-20 14:08:48 +00:00
dependabot[bot]
6170f4f56a Bump docker/login-action from 2 to 3 (#4221)
Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  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>
2023-09-20 13:34:58 +00:00
dependabot[bot]
0b00f8f4f0 Bump docker/setup-buildx-action from 2 to 3 (#4220)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  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>
2023-09-20 13:24:14 +00:00
dependabot[bot]
a45c128c38 Bump docker/setup-qemu-action from 2 to 3 (#4211)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  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>
2023-09-20 07:31:58 +00:00
dependabot[bot]
fe26655653 Bump bootstrap from 5.3.1 to 5.3.2 in /src-ui (#4217)
Bumps [bootstrap](https://github.com/twbs/bootstrap) from 5.3.1 to 5.3.2.
- [Release notes](https://github.com/twbs/bootstrap/releases)
- [Commits](https://github.com/twbs/bootstrap/compare/v5.3.1...v5.3.2)

---
updated-dependencies:
- dependency-name: bootstrap
  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>
2023-09-20 06:09:25 +00:00
dependabot[bot]
2277fb5a58 Bump the frontend-eslint-dependencies group in /src-ui with 3 updates (#4215)
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 [eslint](https://github.com/eslint/eslint).


Updates `@typescript-eslint/eslint-plugin` from 6.5.0 to 6.7.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/v6.7.2/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.5.0 to 6.7.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/v6.7.2/packages/parser)

Updates `eslint` from 8.48.0 to 8.49.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/v8.48.0...v8.49.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-20 05:57:55 +00:00
dependabot[bot]
b6ab3095ab Bump the frontend-jest-dependencies group in /src-ui with 4 updates (#4218)
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-websocket-mock](https://github.com/romgain/jest-websocket-mock).


Updates `jest` from 29.6.4 to 29.7.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/v29.7.0/packages/jest)

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

Updates `jest-environment-jsdom` from 29.6.4 to 29.7.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/v29.7.0/packages/jest-environment-jsdom)

Updates `jest-websocket-mock` from 2.4.1 to 2.5.0
- [Release notes](https://github.com/romgain/jest-websocket-mock/releases)
- [Commits](https://github.com/romgain/jest-websocket-mock/compare/v2.4.1...v2.5.0)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-jest-dependencies
- dependency-name: "@types/jest"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-jest-dependencies
- dependency-name: jest-environment-jsdom
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-jest-dependencies
- dependency-name: jest-websocket-mock
  dependency-type: direct:development
  update-type: version-update:semver-minor
  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>
2023-09-19 22:40:38 -07:00
dependabot[bot]
591466d16d Bump stumpylog/image-cleaner-action from 0.2.0 to 0.3.0 (#4210)
Bumps [stumpylog/image-cleaner-action](https://github.com/stumpylog/image-cleaner-action) from 0.2.0 to 0.3.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.2.0...v0.3.0)

---
updated-dependencies:
- dependency-name: stumpylog/image-cleaner-action
  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>
2023-09-19 22:12:29 -07:00
dependabot[bot]
666c12f2e8 Bump docker/metadata-action from 4 to 5 (#4209)
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4 to 5.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Upgrade guide](https://github.com/docker/metadata-action/blob/master/UPGRADE.md)
- [Commits](https://github.com/docker/metadata-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  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>
2023-09-19 22:12:14 -07:00
dependabot[bot]
8180226eb7 Bump uuid from 9.0.0 to 9.0.1 in /src-ui (#4216)
Bumps [uuid](https://github.com/uuidjs/uuid) from 9.0.0 to 9.0.1.
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: uuid
  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>
2023-09-20 05:08:46 +00:00
dependabot[bot]
0d5be4a730 Bump the frontend-angular-dependencies group in /src-ui with 16 updates (#4213)
Bumps the frontend-angular-dependencies group in /src-ui with 16 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `16.2.3` | `16.2.5` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `16.2.3` | `16.2.5` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `16.2.3` | `16.2.5` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `16.2.3` | `16.2.5` |
| [@angular/localize](https://github.com/angular/angular) | `16.2.3` | `16.2.5` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `16.2.3` | `16.2.5` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `16.2.3` | `16.2.5` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `16.2.3` | `16.2.5` |
| [ngx-ui-tour-ng-bootstrap](https://github.com/hakimio/ngx-ui-tour) | `13.0.3` | `13.0.4` |
| [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `16.2.1` | `16.2.2` |
| [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) | `16.1.1` | `16.2.0` |
| [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) | `16.1.1` | `16.2.0` |
| [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) | `16.1.1` | `16.2.0` |
| [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) | `16.1.1` | `16.2.0` |
| [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) | `16.1.1` | `16.2.0` |
| [@angular/cli](https://github.com/angular/angular-cli) | `16.2.1` | `16.2.2` |


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

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

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

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

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

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

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

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

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

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

Updates `@angular-eslint/builder` from 16.1.1 to 16.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/v16.2.0/packages/builder)

Updates `@angular-eslint/eslint-plugin` from 16.1.1 to 16.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/v16.2.0/packages/eslint-plugin)

Updates `@angular-eslint/eslint-plugin-template` from 16.1.1 to 16.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/v16.2.0/packages/eslint-plugin-template)

Updates `@angular-eslint/schematics` from 16.1.1 to 16.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/v16.2.0/packages/schematics)

Updates `@angular-eslint/template-parser` from 16.1.1 to 16.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/v16.2.0/packages/template-parser)

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

---
updated-dependencies:
- dependency-name: "@angular/common"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-ui-tour-ng-bootstrap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/build-angular"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/builder"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin-template"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/schematics"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/template-parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-type: direct:development
  update-type: version-update:semver-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>
2023-09-19 21:40:35 -07:00
dependabot[bot]
49a2e2f3fa Bump docker/build-push-action from 4 to 5 (#4212)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  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>
2023-09-20 04:37:16 +00:00
dependabot[bot]
219563146d Bump actions/checkout from 3 to 4 (#4208)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [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/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2023-09-20 03:52:56 +00:00
shamoon
0d01295e79 Update GitHub strings
See #4024
2023-09-19 20:34:27 -07:00
shamoon
b65e195c27 Update translation strings 2023-09-19 14:31:19 -07:00
shamoon
f5717cca1c Enhancement: bulk edit object permissions (#4176)
* bulk_edit_object_perms API endpoint

* Frontend support for bulk object permissions edit
2023-09-19 13:40:21 -07:00
Trenton H
a2c9f6792e Fixes the documentation for fuzzy matching (#4207) 2023-09-19 07:46:13 -07:00
Marwan Khalil
95c12c1840 Fix: completely hide upload widget if user does not have permissions (#4198) 2023-09-17 14:53:20 +00:00
shamoon
4de1cb0a09 Fix application of theme color vars at root (#4193) 2023-09-16 01:08:03 -07:00
Trenton H
ec9ebd3026 Allow the user the specifiy the zip file name (#4189) 2023-09-15 16:33:28 -07:00
shamoon
5ee9ad3e4f Migrate frontend prefix to -pngx 2023-09-14 14:51:02 -07:00
shamoon
9e2135e2c7 Fix bs-theme html attributes 2023-09-14 14:51:02 -07:00
shamoon
116da276c7 Fix form switch checkmark visual bug 2023-09-14 14:51:02 -07:00
shamoon
7c9ab8c0b6 Feature: Share links (#3996)
* Implement share links

Basic implementation of share links

Make certain share link fields not editable, automatically grant permissions on migrate

Updated styling, error messages from expired / deleted links

frontend code linting, reversable sharelink migration

testing coverage

Update translation strings

No links message

* Consolidate file response methods

* improvements to share links on mobile devices

* Refactor share links file_version

* Add docs for share links

* Apply suggestions from code review

* When filtering share links, use the timezone aware now()

* Removes extra call to setup directories for usage in testing

* FIx copied badge display on some browsers

* Move copy to ngx-clipboard library

---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2023-09-14 13:32:43 -07:00
shamoon
3a36d9b1ae Update docker image and ci to node 20 2023-09-14 13:06:14 -07:00
Trenton Holmes
5fce21e269 Trims libraries which are baked into the wheels we use, no need for them on the system 2023-09-14 10:36:15 -07:00
shamoon
a46bfc8b5f Update playwright to 1.38.0 2023-09-14 00:00:27 -07:00
shamoon
a860c29304 Update playwright to 1.38.0 2023-09-13 23:48:26 -07:00
shamoon
cc90b45022 Fix typo in #4179 2023-09-13 23:46:26 -07:00
Dominik Mielcarek
78ae4c42f7 Chore: change dark mode to use Bootstrap's color modes (#4174)
* Change setting dark mode to use Bootstrap's data-bs-theme attribute

* Update dark mode styling to use Bootstrap's color mode attribute

* Update unit tests and lints

* Fix not reflecting custom theme color

* Remove commented-out code

* fix inverted thumbnails in dark mode & card borders

* prettier

* Fix application of dark mode, tests

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-09-13 18:11:44 +00:00
shamoon
d1292c59ea Fix: support doc_pk storage path placeholder (#4179) 2023-09-13 07:43:43 -07:00
Trenton H
1a87c730bc Logs the errors during thumbnail generation, updates default to be WebP 2023-09-12 12:16:22 -07:00
Trenton H
7aa72f768f Uses regex matching against the messages, as ordering and exact matched value don't matter, just the count of matches 2023-09-12 08:59:09 -07:00
Trenton H
81b9f2d4e0 Cleans up the docs, adds validation of the process count, include the test descriptions 2023-09-12 08:17:12 -07:00
Trenton H
a03a745295 Adds multiprocessing to the fuzzy matching for a speedup 2023-09-12 08:17:12 -07:00
shamoon
ce8bf90663 Add progress bar to document_fuzzy_match 2023-09-12 08:17:12 -07:00
Trenton Holmes
e2ae919a84 Implements a new command for fuzzy matching document content and reporting potential duplicates 2023-09-12 08:17:12 -07:00
shamoon
9a0e44a731 Pass saved_view owner as id only (#4158) 2023-09-10 16:37:35 -07:00
Trenton Holmes
650c816a7b Removes support for Python 3.8 and lower from the code base 2023-09-10 11:42:59 -07:00
shamoon
c8bfbb9315 Fix dashboard widget card borders hidden by bkgd color (#4155) 2023-09-10 16:20:02 +00:00
Trenton H
80b32dd392 Updates the underlying image to use Python 3.11 2023-09-10 08:29:11 -07:00
shamoon
e3352ea426 Merge pull request #4055 from paperless-ngx/feature-frontend-handle-slowness
Enhancement: frontend better handle slow backend requests
2023-09-08 19:59:33 -07:00
shamoon
faed7683be Frontend better handle slow backend requests 2023-09-08 19:49:54 -07:00
Trenton H
46a39190a4 Ignores coverage data in the error cases 2023-09-08 19:20:08 -07:00
Trenton H
a2f738772c Fixes handling of exception chains in the util 2023-09-08 19:20:08 -07:00
Trenton H
a1697ff21c Combine and extend the utility for calling the live services to be more robust against failures, reporting, etc 2023-09-08 19:20:08 -07:00
shamoon
b9fdf68be3 Update docker image node to v18 (#4149) 2023-09-08 16:48:02 -07:00
shamoon
ec971d0473 Fix add user / group buttons partially hidden if insufficient permissions (#4133) 2023-09-08 15:14:01 -07:00
shamoon
d462464af9 Merge pull request #4062 from paperless-ngx/feature-improve-error-notifications
Enhancement: Improved error notifications
2023-09-08 12:23:30 -07:00
shamoon
423e0768f9 Improved error notifications 2023-09-08 11:49:56 -07:00
Trenton H
0ef3a141a8 Enables Python 3.11 testing 2023-09-08 11:49:16 -07:00
Trenton H
d532913d56 Unlocks all things which were locked due to ARMv7, etc 2023-09-08 11:21:43 -07:00
Peter
3205bb3bdf Change PWA Manifest to use Standalone Display (#4129) 2023-09-08 17:55:38 +00:00
Kamil Kosek
b238ba054d Enhancement: add --id-range for document_retagger (#4080)
---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2023-09-08 17:33:24 +00:00
shamoon
a8e13df249 Merge pull request #4088 from paperless-ngx/feature-greek-afrikaans-norwegian-translations
Enhancement: Add Afrikaans, Greek & Norwegian languages
2023-09-08 10:10:54 -07:00
shamoon
9dc77d94ed Add Afrikaans, Greek & Norwegian languages 2023-09-08 10:01:01 -07:00
Trenton H
714995877a Merge pull request #4037 from andreheuer/dev
Enhancement: add task id to pre/post consume script as env
2023-09-08 10:00:05 -07:00
shamoon
729d7a11cd Merge pull request #4060 from paperless-ngx/feature-update-backend-bootstrap
Enhancement: update bootstrap to v5.3.1 for backend static pages
2023-09-08 09:20:22 -07:00
shamoon
95cd86a541 Update bootstrap to v5.3.1 for backend static pages 2023-09-08 09:08:23 -07:00
Trenton H
ca1b8344fa Tweaks the FAQ on running with a Raspberry Pi 2023-09-08 09:05:27 -07:00
Trenton H
e797295b82 Drops the building of armv7 and removes most stuff the image does for it 2023-09-08 09:05:27 -07:00
dependabot[bot]
f216b322c2 Bump the frontend-jest-dependencies group in /src-ui with 4 updates (#4112)
* Bump the frontend-jest-dependencies group in /src-ui with 4 updates

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-websocket-mock](https://github.com/romgain/jest-websocket-mock).


Updates `jest` from 29.6.2 to 29.6.4
- [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/v29.6.4/packages/jest)

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

Updates `jest-environment-jsdom` from 29.6.2 to 29.6.4
- [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/v29.6.4/packages/jest-environment-jsdom)

Updates `jest-websocket-mock` from 2.4.0 to 2.4.1
- [Release notes](https://github.com/romgain/jest-websocket-mock/releases)
- [Commits](https://github.com/romgain/jest-websocket-mock/compare/v2.4.0...v2.4.1)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-jest-dependencies
- dependency-name: "@types/jest"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-jest-dependencies
- dependency-name: jest-environment-jsdom
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-jest-dependencies
- dependency-name: jest-websocket-mock
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-jest-dependencies
...

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

* Update toasts.component.spec.ts

---------

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>
2023-09-02 07:08:40 +00:00
github-actions
b97c19ca3c Changelog v1.17.4 - GHA 2023-09-01 19:26:07 -07:00
dependabot[bot]
d54c7ca27c Bump tslib from 2.6.1 to 2.6.2 in /src-ui (#4108)
Bumps [tslib](https://github.com/Microsoft/tslib) from 2.6.1 to 2.6.2.
- [Release notes](https://github.com/Microsoft/tslib/releases)
- [Commits](https://github.com/Microsoft/tslib/compare/v2.6.1...v2.6.2)

---
updated-dependencies:
- dependency-name: tslib
  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>
2023-09-02 01:01:22 +00:00
dependabot[bot]
077de8dcaa Bump the frontend-eslint-dependencies group in /src-ui with 3 updates (#4106)
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 [eslint](https://github.com/eslint/eslint).


Updates `@typescript-eslint/eslint-plugin` from 6.2.1 to 6.5.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/v6.5.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.2.1 to 6.5.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/v6.5.0/packages/parser)

Updates `eslint` from 8.46.0 to 8.48.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/v8.46.0...v8.48.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-02 00:50:14 +00:00
dependabot[bot]
6f50e5671a Bump concurrently from 8.2.0 to 8.2.1 in /src-ui (#4111)
Bumps [concurrently](https://github.com/open-cli-tools/concurrently) from 8.2.0 to 8.2.1.
- [Release notes](https://github.com/open-cli-tools/concurrently/releases)
- [Commits](https://github.com/open-cli-tools/concurrently/compare/v8.2.0...v8.2.1)

---
updated-dependencies:
- dependency-name: concurrently
  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>
2023-09-01 21:54:07 +00:00
dependabot[bot]
bab9bdc832 Bump @types/node from 20.4.5 to 20.5.8 in /src-ui (#4110)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.4.5 to 20.5.8.
- [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-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>
2023-09-01 21:36:50 +00:00
shamoon
8e0adbb0fb Add other jest dependencies to group 2023-09-01 14:17:32 -07:00
dependabot[bot]
6b175ae7e3 Bump the frontend-angular-dependencies group in /src-ui with 19 updates (#4104)
Bumps the frontend-angular-dependencies group in /src-ui with 19 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `16.1.7` | `16.2.3` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `16.1.7` | `16.2.3` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `16.1.7` | `16.2.3` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `16.1.7` | `16.2.3` |
| [@angular/localize](https://github.com/angular/angular) | `16.1.7` | `16.2.3` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `16.1.7` | `16.2.3` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `16.1.7` | `16.2.3` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `16.1.7` | `16.2.3` |
| [@ng-bootstrap/ng-bootstrap](https://github.com/ng-bootstrap/ng-bootstrap) | `15.1.0` | `15.1.1` |
| [ngx-cookie-service](https://github.com/stevermeister/ngx-cookie-service) | `16.0.0` | `16.0.1` |
| [@angular-builders/jest](https://github.com/just-jeb/angular-builders/tree/HEAD/packages/jest) | `16.0.0` | `16.0.1` |
| [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `16.1.6` | `16.2.1` |
| [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) | `16.1.0` | `16.1.1` |
| [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) | `16.1.0` | `16.1.1` |
| [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) | `16.1.0` | `16.1.1` |
| [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) | `16.1.0` | `16.1.1` |
| [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) | `16.1.0` | `16.1.1` |
| [@angular/cli](https://github.com/angular/angular-cli) | `16.1.6` | `16.2.1` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `16.1.7` | `16.2.3` |


Updates `@angular/common` from 16.1.7 to 16.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/16.2.3/packages/common)

Updates `@angular/compiler` from 16.1.7 to 16.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/16.2.3/packages/compiler)

Updates `@angular/core` from 16.1.7 to 16.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/16.2.3/packages/core)

Updates `@angular/forms` from 16.1.7 to 16.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/16.2.3/packages/forms)

Updates `@angular/localize` from 16.1.7 to 16.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/16.1.7...16.2.3)

Updates `@angular/platform-browser` from 16.1.7 to 16.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/16.2.3/packages/platform-browser)

Updates `@angular/platform-browser-dynamic` from 16.1.7 to 16.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/16.2.3/packages/platform-browser-dynamic)

Updates `@angular/router` from 16.1.7 to 16.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/16.2.3/packages/router)

Updates `@ng-bootstrap/ng-bootstrap` from 15.1.0 to 15.1.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/15.1.0...15.1.1)

Updates `ngx-cookie-service` from 16.0.0 to 16.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/v16.0.0...v16.0.1)

Updates `@angular-builders/jest` from 16.0.0 to 16.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@16.0.1/packages/jest)

Updates `@angular-devkit/build-angular` from 16.1.6 to 16.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/16.1.6...16.2.1)

Updates `@angular-eslint/builder` from 16.1.0 to 16.1.1
- [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/v16.1.1/packages/builder)

Updates `@angular-eslint/eslint-plugin` from 16.1.0 to 16.1.1
- [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/v16.1.1/packages/eslint-plugin)

Updates `@angular-eslint/eslint-plugin-template` from 16.1.0 to 16.1.1
- [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/v16.1.1/packages/eslint-plugin-template)

Updates `@angular-eslint/schematics` from 16.1.0 to 16.1.1
- [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/v16.1.1/packages/schematics)

Updates `@angular-eslint/template-parser` from 16.1.0 to 16.1.1
- [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/v16.1.1/packages/template-parser)

Updates `@angular/cli` from 16.1.6 to 16.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/16.1.6...16.2.1)

Updates `@angular/compiler-cli` from 16.1.7 to 16.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/16.2.3/packages/compiler-cli)

---
updated-dependencies:
- dependency-name: "@angular/common"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/forms"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/localize"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/router"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@ng-bootstrap/ng-bootstrap"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: ngx-cookie-service
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-builders/jest"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-devkit/build-angular"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/builder"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/eslint-plugin-template"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/schematics"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular-eslint/template-parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
- dependency-name: "@angular/compiler-cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: frontend-angular-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-01 21:07:47 +00:00
shamoon
9494633da3 Reset to -dev version string 2023-09-01 13:30:54 -07:00
shamoon
c754a5f391 Bumps version to 1.17.4 2023-09-01 13:29:55 -07:00
shamoon
2b692c6fc8 Merge branch 'dev' 2023-09-01 13:29:16 -07:00
Paperless-ngx Bot [bot]
35b6fb1a6d New translations messages.xlf (Greek) (#4095)
[ci skip]
2023-09-01 13:28:41 -07:00
shamoon
61566a34d1 Fix consumer error typo 2023-09-01 00:11:32 -07:00
shamoon
e14f4c94c2 Fix: ghostscript rendering error doesnt trigger frontend failure message (#4092)
* Raise ParseError from gs rendering error

* catch all parser errors as generic exception

* Differentiate generic vs parse errors during consumption
2023-08-31 19:49:00 -07:00
André Heuer
52bdb1a80c Added self type 2023-08-29 23:09:47 -07:00
André Heuer
88ee3bdb6d Removed parameter, added documentation 2023-08-29 23:09:47 -07:00
André Heuer
8f8a99a645 Added task id to pre/post consume script as env 2023-08-29 23:09:47 -07:00
shamoon
8d35f22daf Merge pull request #4085 from paperless-ngx/v1.17.3-changelog
[Documentation] Add v1.17.3 changelog
2023-08-29 15:55:34 -07:00
Trenton H
6f8ef9bbdc Change the category of the pdf-js update 2023-08-29 11:53:59 -07:00
github-actions
e7ddf6ba8f Changelog v1.17.3 - GHA 2023-08-28 21:42:38 -07:00
shamoon
407a119b9a Fix long document names cause overflow on tasks view 2023-08-28 21:32:10 -07:00
shamoon
96aa2451bf Add Ghostscript error to troubleshooting docs 2023-08-28 19:29:36 -07:00
Trenton Holmes
7680aab04d Reset to -dev version string 2023-08-28 18:43:21 -07:00
Trenton Holmes
3aef26b229 Bumps version to 1.17.3 2023-08-28 18:28:40 -07:00
Trenton Holmes
935141adc0 Merge remote-tracking branch 'origin/dev' 2023-08-28 18:27:07 -07:00
Trenton Holmes
4300733d0c Fixes an erroneous raise that prevented the retry logic from going 2023-08-28 18:26:22 -07:00
Paperless-ngx Bot [bot]
c284a091c0 New Crowdin updates (#3997)
* New translations messages.xlf (French)
[ci skip]

* New translations messages.xlf (German)
[ci skip]

* New translations django.po (Slovenian)
[ci skip]

* New translations messages.xlf (Greek)
[ci skip]

* New translations messages.xlf (Spanish)
[ci skip]

* New translations messages.xlf (Arabic)
[ci skip]

* New translations messages.xlf (Catalan)
[ci skip]

* New translations messages.xlf (German)
[ci skip]

* New translations messages.xlf (Dutch)
[ci skip]

* New translations messages.xlf (Slovenian)
[ci skip]

* New translations messages.xlf (Swedish)
[ci skip]

* New translations messages.xlf (Afrikaans)
[ci skip]

* New translations messages.xlf (Slovak)
[ci skip]

* New translations messages.xlf (Greek)
[ci skip]

* New translations messages.xlf (Romanian)
[ci skip]

* New translations messages.xlf (French)
[ci skip]

* New translations messages.xlf (Belarusian)
[ci skip]

* New translations messages.xlf (Czech)
[ci skip]

* New translations messages.xlf (Danish)
[ci skip]

* New translations messages.xlf (Finnish)
[ci skip]

* New translations messages.xlf (Hebrew)
[ci skip]

* New translations messages.xlf (Hungarian)
[ci skip]

* New translations messages.xlf (Italian)
[ci skip]

* New translations messages.xlf (Norwegian)
[ci skip]

* New translations messages.xlf (Polish)
[ci skip]

* New translations messages.xlf (Portuguese)
[ci skip]

* New translations messages.xlf (Russian)
[ci skip]

* New translations messages.xlf (Turkish)
[ci skip]

* New translations messages.xlf (Chinese Simplified)
[ci skip]

* New translations messages.xlf (Portuguese, Brazilian)
[ci skip]

* New translations messages.xlf (Indonesian)
[ci skip]

* New translations messages.xlf (Croatian)
[ci skip]

* New translations messages.xlf (Luxembourgish)
[ci skip]

* New translations messages.xlf (Serbian (Latin))
[ci skip]

* New translations messages.xlf (Ukrainian)
[ci skip]

* New translations messages.xlf (French)
[ci skip]

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-08-28 18:17:51 -07:00
Trenton H
7e768bfe23 When PDF/A rendering fails, add a warning the user may want to allow it to continue 2023-08-28 18:10:11 -07:00
Trenton H
938f388a0b Upload frontend and backend coverage information together so codecov is less wrong with it's initial comment 2023-08-28 18:05:34 -07:00
shamoon
d22a6fb8ea Merge pull request #4065 from paperless-ngx/feature-update-pdf-viewer
Chore: update frontend PDF viewer (including pdf-js)
2023-08-27 13:50:55 -07:00
shamoon
11142e2f05 Update ng2-pdf-viewer (including pdf-js) to 10.0.0 2023-08-27 00:29:23 -07:00
Trenton Holmes
fe7fb488c0 Do some trickery to support Python 3.11 and mocking invalid module names 2023-08-25 08:44:09 -07:00
shamoon
0929c5086a Merge pull request #4064 from paperless-ngx/v1.17.2-changelog
[Documentation] Add v1.17.2 changelog
2023-08-24 12:53:21 -07:00
github-actions
eb3ed7719b Changelog v1.17.2 - GHA 2023-08-24 19:09:28 +00:00
Trenton H
6c19a0f8c7 Reset to -dev versioning string 2023-08-24 11:42:25 -07:00
Trenton H
a0ece589b0 Bumps version to 1.17.2 2023-08-24 11:38:17 -07:00
Trenton H
8165071edf Merge remote-tracking branch 'origin/dev' 2023-08-24 11:35:16 -07:00
shamoon
a667974378 Update settings.component.spec.ts 2023-08-24 00:21:06 -07:00
Trenton Holmes
fe1f88ce5d Sets the http timeouts equal to the task timeout, so it's either done or really done 2023-08-23 18:40:22 -07:00
shamoon
8f2715e437 Merge pull request #4014 from paperless-ngx/ui-perms-tweaks
Enhancement: disable / hide some UI buttons / elements if insufficient permissions, show errors
2023-08-23 10:28:37 -07:00
shamoon
57a3223c77 Merge branch 'dev' into ui-perms-tweaks 2023-08-23 08:48:42 -07:00
Trenton H
df82ac8ac4 Adjusts to use a different loading of certificates and updates the docs for it 2023-08-23 08:22:01 -07:00
Trenton H
16adddc803 Allow users to set a combined certificte and key file for additional certificates in the SSL context 2023-08-23 08:22:01 -07:00
shamoon
d1ae82c5c2 Merge pull request #4038 from paperless-ngx/fix/issue-4036
Fix: tag creation sometimes retained search text
2023-08-21 11:15:15 -07:00
shamoon
0098936347 Fix: tag creation sometimes retained search text 2023-08-20 16:18:34 -07:00
shamoon
17b85f6400 Merge pull request #4035 from brakhane/polling-note
docs: add note about polling when using double-sided collation
2023-08-20 11:04:45 -07:00
Dennis Brakhane
48be9c0fd1 docs: add note about polling when using double-sided collation 2023-08-20 19:51:14 +02:00
shamoon
ce36c2d0ea Merge pull request #4007 from paperless-ngx/fix/issue-4003
Fix: enforce permissions on bulk_edit operations
2023-08-18 06:37:08 -07:00
shamoon
06c63ef4a4 Disable / hide some UI buttons / elements if insufficient permissions 2023-08-17 20:34:19 -07:00
shamoon
03d93a7d6e Fix: enforce permissions on bulk_edit operations 2023-08-17 00:12:46 -07:00
amo13
a0005c8b3e Enhancement: Allow to set a prefix for keys and channels in redis (#3993) 2023-08-16 00:05:01 +00:00
shamoon
2220343c50 Merge pull request #3998 from paperless-ngx/v1.17.1-changelog
[Documentation] Add v1.17.1 changelog
2023-08-15 13:35:50 -07:00
github-actions
68fbed996f Changelog v1.17.1 - GHA 2023-08-15 16:00:47 +00:00
Trenton H
20a4d8949d Reset to -dev version string 2023-08-15 08:42:06 -07:00
502 changed files with 181261 additions and 91121 deletions

View File

@@ -3,8 +3,6 @@ codecov:
# https://docs.codecov.com/docs/flags#recommended-automatic-flag-management
# Require each flag to have 1 upload before notification
flag_management:
default_rules:
after_n_builds: 1
individual_flags:
- name: backend
paths:
@@ -22,12 +20,9 @@ coverage:
default:
# https://docs.codecov.com/docs/commit-status#threshold
threshold: 1%
# https://docs.codecov.com/docs/commit-status#only_pulls
only_pulls: true
patch:
default:
# For the changed lines only, target 75% covered, but
# allow as low as 50%
target: 75%
threshold: 25%
only_pulls: true

View File

@@ -1,21 +1,28 @@
# Tool caches
**/__pycache__
/src-ui/.vscode
/src-ui/node_modules
/src-ui/dist
**/.ruff_cache/
**/.mypy_cache/
# Virtual environment & similar
.venv/
./src-ui/node_modules
./src-ui/dist
# IDE folders
.idea/
.vscode/
./src-ui/.vscode
# VCS
.git
/export
/consume
/media
/data
/docs
.pytest_cache
/dist
/scripts
/resources
# Test related
**/.pytest_cache
**/tests
**/*.spec.ts
**/htmlcov
/src/.pytest_cache
.idea
.venv/
.vscode/
# Local folders
./export
./consume
./media
./data
./docs
./dist
./scripts
./resources

View File

@@ -6,14 +6,21 @@ body:
- type: markdown
attributes:
value: |
Have a question? 👉 [Start a new discussion](https://github.com/paperless-ngx/paperless-ngx/discussions/new) or [ask in chat](https://matrix.to/#/#paperlessngx:matrix.org).
### ⚠️ Please remember: issues are for *bugs*
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.
Before opening an issue, please double check:
Also, note that **Paperless-ngx does not perform OCR itself**, that is handled by other tools. Problems with OCR 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
attributes:
value: |
#### Have a question? 👉 [Start a new discussion](https://github.com/paperless-ngx/paperless-ngx/discussions/new) or [ask in chat](https://matrix.to/#/#paperlessngx:matrix.org).
#### Before opening an issue, please double check:
- [The troubleshooting documentation](https://docs.paperless-ngx.com/troubleshooting/).
- [The installation instructions](https://docs.paperless-ngx.com/setup/#installation).
- [Existing issues and discussions](https://github.com/paperless-ngx/paperless-ngx/search?q=&type=issues).
- Disable any customer container initialization scripts, if using any
- Disable any customer container initialization scripts, if using
If you encounter issues while installing or configuring Paperless-ngx, please post in the ["Support" section of the discussions](https://github.com/paperless-ngx/paperless-ngx/discussions/new?category=support).
- type: textarea

View File

@@ -8,7 +8,7 @@ updates:
target-branch: "dev"
# Look for `package.json` and `lock` files in the `/src-ui` directory
directory: "/src-ui"
# Check the npm registry for updates every month
open-pull-requests-limit: 10
schedule:
interval: "monthly"
labels:
@@ -27,7 +27,7 @@ updates:
frontend-jest-dependencies:
patterns:
- "@types/jest"
- "jest"
- "jest*"
frontend-eslint-dependencies:
patterns:
- "@typescript-eslint*"
@@ -47,8 +47,25 @@ updates:
# Add reviewers
reviewers:
- "paperless-ngx/backend"
groups:
development:
patterns:
- "*pytest*"
- "black"
- "ruff"
- "mkdocs-material"
django:
patterns:
- "*django*"
major-versions:
update-types:
- "major"
small-changes:
update-types:
- "minor"
- "patch"
# Enable updates for Github Actions
# Enable updates for GitHub Actions
- package-ecosystem: "github-actions"
target-branch: "dev"
directory: "/"
@@ -61,3 +78,9 @@ updates:
# Add reviewers
reviewers:
- "paperless-ngx/ci-cd"
groups:
actions:
update-types:
- "major"
- "minor"
- "patch"

View File

@@ -16,19 +16,25 @@ on:
env:
# This is the version of pipenv all the steps will use
# If changing this, change Dockerfile
DEFAULT_PIP_ENV_VERSION: "2023.7.23"
# This is the default version of Python to use in most steps
# If changing this, change Dockerfile
DEFAULT_PYTHON_VERSION: "3.9"
DEFAULT_PIP_ENV_VERSION: "2023.10.24"
# This is the default version of Python to use in most steps which aren't specific
DEFAULT_PYTHON_VERSION: "3.10"
jobs:
pre-commit:
# We want to run on external PRs, but not on our own internal PRs as they'll be run
# by the push to the branch. Without this if check, checks are duplicated since
# internal PRs match both the push and pull_request events.
if:
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
github.repository
name: Linting Checks
runs-on: ubuntu-22.04
steps:
-
name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Install python
uses: actions/setup-python@v4
@@ -46,7 +52,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Set up Python
id: setup-python
@@ -58,7 +64,7 @@ jobs:
-
name: Install pipenv
run: |
pip install --user pipenv==${DEFAULT_PIP_ENV_VERSION}
pip install --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }}
-
name: Install dependencies
run: |
@@ -88,7 +94,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Deploy docs
uses: mhausenblas/mkdocs-deploy-gh-pages@master
@@ -99,18 +105,18 @@ jobs:
EXTRA_PACKAGES: build-base
tests-backend:
name: "Tests (${{ matrix.python-version }})"
name: "Backend Tests (Python ${{ matrix.python-version }})"
runs-on: ubuntu-22.04
needs:
- pre-commit
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10']
python-version: ['3.9', '3.10', '3.11']
fail-fast: false
steps:
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Start containers
run: |
@@ -127,7 +133,7 @@ jobs:
-
name: Install pipenv
run: |
pip install --user pipenv==${DEFAULT_PIP_ENV_VERSION}
pip install --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }}
-
name: Install system dependencies
run: |
@@ -158,14 +164,14 @@ jobs:
cd src/
pipenv --python ${{ steps.setup-python.outputs.python-version }} run pytest -ra
-
name: Upload coverage to Codecov
name: Upload coverage
if: ${{ matrix.python-version == env.DEFAULT_PYTHON_VERSION }}
uses: codecov/codecov-action@v3
uses: actions/upload-artifact@v3
with:
# not required for public repos, but intermittently fails otherwise
token: ${{ secrets.CODECOV_TOKEN }}
# future expansion
flags: backend
name: backend-coverage-report
path: src/coverage.xml
retention-days: 7
if-no-files-found: warn
-
name: Stop containers
if: always()
@@ -173,55 +179,88 @@ jobs:
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
tests-frontend:
name: "Tests Frontend"
install-frontend-depedendencies:
name: "Install Frontend Dependendencies"
runs-on: ubuntu-22.04
needs:
- pre-commit
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
-
name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
node-version: 20.x
cache: 'npm'
cache-dependency-path: 'src-ui/package-lock.json'
- name: Cache frontend depdendencies
id: cache-frontend-deps
uses: actions/cache@v3
with:
path: |
~/.npm
~/.cache
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
-
name: Install dependencies
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
run: cd src-ui && npm ci
-
name: Install Playwright
run: npx playwright install --with-deps
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
run: cd src-ui && npx playwright install --with-deps
tests-frontend:
name: "Frontend Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})"
runs-on: ubuntu-22.04
needs:
- install-frontend-depedendencies
strategy:
fail-fast: false
matrix:
node-version: [20.x]
shard-index: [1, 2, 3, 4]
shard-count: [4]
steps:
- uses: actions/checkout@v4
-
name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'npm'
cache-dependency-path: 'src-ui/package-lock.json'
- name: Cache frontend depdendencies
id: cache-frontend-deps
uses: actions/cache@v3
with:
path: |
~/.npm
~/.cache
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
- name: Re-link Angular cli
run: cd src-ui && npm link @angular/cli
-
name: Linting checks
run: cd src-ui && npm run lint
-
name: Run Jest unit tests
run: cd src-ui && npm run test
run: cd src-ui && npm run test -- --max-workers=2 --shard=${{ matrix.shard-index }}/${{ matrix.shard-count }}
-
name: Upload Jest coverage
if: always()
uses: actions/upload-artifact@v3
with:
name: jest-coverage-report
path: src-ui/coverage
name: jest-coverage-report-${{ matrix.shard-index }}
path: |
src-ui/coverage/coverage-final.json
src-ui/coverage/lcov.info
src-ui/coverage/clover.xml
retention-days: 7
-
name: Upload frontend coverage to Codecov
if: always()
uses: codecov/codecov-action@v3
with:
# not required for public repos, but intermittently fails otherwise
token: ${{ secrets.CODECOV_TOKEN }}
# future expansion
flags: frontend
if-no-files-found: warn
-
name: Run Playwright e2e tests
run: cd src-ui && npx playwright test
run: cd src-ui && npx playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }}
-
name: Upload Playwright test results
if: always()
@@ -231,6 +270,46 @@ jobs:
path: src-ui/playwright-report
retention-days: 7
tests-coverage-upload:
name: "Upload Coverage"
runs-on: ubuntu-22.04
needs:
- tests-backend
- tests-frontend
steps:
-
uses: actions/checkout@v4
-
name: Download frontend coverage
uses: actions/download-artifact@v3
with:
path: src-ui/coverage/
-
name: Upload frontend coverage to Codecov
uses: codecov/codecov-action@v3
with:
# not required for public repos, but intermittently fails otherwise
token: ${{ secrets.CODECOV_TOKEN }}
flags: frontend
directory: src-ui/coverage/
# dont include backend coverage files here
files: '!coverage.xml'
-
name: Download backend coverage
uses: actions/download-artifact@v3
with:
name: backend-coverage-report
path: src/
-
name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
# not required for public repos, but intermittently fails otherwise
token: ${{ secrets.CODECOV_TOKEN }}
# future expansion
flags: backend
directory: src/
build-docker-image:
name: Build Docker image for ${{ github.ref_name }}
runs-on: ubuntu-22.04
@@ -252,7 +331,7 @@ jobs:
# a tag
# Otherwise forks would require a Docker Hub account and secrets setup
run: |
if [[ ${{ github.repository_owner }} == "paperless-ngx" && ( ${{ github.ref_name }} == "main" || ${{ github.ref_name }} == "dev" || ${{ github.ref_name }} == "beta" || ${{ startsWith(github.ref, 'refs/tags/v') }} == "true" ) ]] ; then
if [[ ${{ github.repository_owner }} == "paperless-ngx" && ( ${{ github.ref_name }} == "dev" || ${{ github.ref_name }} == "beta" || ${{ startsWith(github.ref, 'refs/tags/v') }} == "true" ) ]] ; then
echo "Enabling DockerHub image push"
echo "enable=true" >> $GITHUB_OUTPUT
else
@@ -269,7 +348,7 @@ jobs:
-
name: Gather Docker metadata
id: docker-meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}
@@ -284,26 +363,28 @@ jobs:
type=semver,pattern={{major}}.{{minor}}
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
# If https://github.com/docker/buildx/issues/1044 is resolved,
# the append input with a native arm64 arch could be used to
# significantly speed up building
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
-
name: Login to Github Container Registry
uses: docker/login-action@v2
name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
# Don't attempt to login is not pushing to Docker Hub
if: steps.push-other-places.outputs.enable == 'true'
with:
@@ -311,7 +392,7 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Login to Quay.io
uses: docker/login-action@v2
uses: docker/login-action@v3
# Don't attempt to login is not pushing to Quay.io
if: steps.push-other-places.outputs.enable == 'true'
with:
@@ -320,11 +401,11 @@ jobs:
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm/v7,linux/arm64
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker-meta.outputs.labels }}
@@ -353,13 +434,14 @@ jobs:
retention-days: 7
build-release:
name: "Build Release"
needs:
- build-docker-image
runs-on: ubuntu-22.04
steps:
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Set up Python
id: setup-python
@@ -371,11 +453,17 @@ jobs:
-
name: Install pipenv + tools
run: |
pip install --upgrade --user pipenv==${DEFAULT_PIP_ENV_VERSION} setuptools wheel
pip install --upgrade --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }} setuptools wheel
-
name: Install Python dependencies
run: |
pipenv --python ${{ steps.setup-python.outputs.python-version }} sync --dev
-
name: Patch whitenoise
run: |
curl --fail --silent --show-error --location --output 484.patch https://github.com/evansd/whitenoise/pull/484.patch
patch -d $(pipenv --venv)/lib/python3.10/site-packages --verbose -p2 < 484.patch
rm 484.patch
-
name: Install system dependencies
run: |
@@ -462,6 +550,7 @@ jobs:
retention-days: 7
publish-release:
name: "Publish Release"
runs-on: ubuntu-22.04
outputs:
prerelease: ${{ steps.get_version.outputs.prerelease }}
@@ -511,6 +600,7 @@ jobs:
asset_content_type: application/x-xz
append-changelog:
name: "Append Changelog"
runs-on: ubuntu-22.04
needs:
- publish-release
@@ -518,7 +608,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: main
-
@@ -531,7 +621,7 @@ jobs:
-
name: Install pipenv + tools
run: |
pip install --upgrade --user pipenv==${DEFAULT_PIP_ENV_VERSION} setuptools wheel
pip install --upgrade --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }} setuptools wheel
-
name: Append Changelog to docs
id: append-Changelog

View File

@@ -29,7 +29,7 @@ jobs:
-
name: Clean temporary images
if: "${{ env.TOKEN != '' }}"
uses: stumpylog/image-cleaner-action/ephemeral@v0.2.0
uses: stumpylog/image-cleaner-action/ephemeral@v0.3.0
with:
token: "${{ env.TOKEN }}"
owner: "${{ github.repository_owner }}"
@@ -68,7 +68,7 @@ jobs:
-
name: Clean untagged images
if: "${{ env.TOKEN != '' }}"
uses: stumpylog/image-cleaner-action/untagged@v0.2.0
uses: stumpylog/image-cleaner-action/untagged@v0.3.0
with:
token: "${{ env.TOKEN }}"
owner: "${{ github.repository_owner }}"

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

View File

@@ -28,7 +28,7 @@ jobs:
if: github.event_name == 'issues' && (github.event.action == 'opened' || github.event.action == 'reopened')
steps:
- name: Add issue to project and set status to ${{ env.todo }}
uses: leonsteinhaeuser/project-beta-automations@v2.1.0
uses: leonsteinhaeuser/project-beta-automations@v2.2.1
with:
gh_token: ${{ secrets.GH_TOKEN }}
organization: paperless-ngx
@@ -44,7 +44,7 @@ jobs:
if: github.event_name == 'pull_request_target' && (github.event.action == 'opened' || github.event.action == 'reopened') && github.event.pull_request.user.login != 'dependabot'
steps:
- name: Add PR to project and set status to "Needs Review"
uses: leonsteinhaeuser/project-beta-automations@v2.1.0
uses: leonsteinhaeuser/project-beta-automations@v2.2.1
with:
gh_token: ${{ secrets.GH_TOKEN }}
organization: paperless-ngx

View File

@@ -8,6 +8,7 @@ on:
permissions:
issues: write
pull-requests: write
discussions: write
concurrency:
group: lock
@@ -45,3 +46,54 @@ jobs:
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.
close-answered-discussions:
name: 'Close Answered Discussions'
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
with:
script: |
const query = `query($owner:String!, $name:String!) {
repository(owner:$owner, name:$name){
discussions(first:100, answered:true, states:[OPEN]) {
nodes {
id,
number
}
}
}
}`;
const variables = {
owner: context.repo.owner,
name: context.repo.repo,
}
const result = await github.graphql(query, variables)
console.log(`Found ${result.repository.discussions.nodes.length} open answered discussions`)
for (const discussion of result.repository.discussions.nodes) {
console.log(`Closing dicussion #${discussion.number} (${discussion.id})`)
const addCommentMutation = `mutation($discussion:ID!, $body:String!) {
addDiscussionComment(input:{discussionId:$discussion, body:$body}) {
clientMutationId
}
}`;
const commentVariables = {
discussion: discussion.id,
body: 'This discussion has been automatically closed because it was marked as answered.',
}
await github.graphql(addCommentMutation, commentVariables)
const closeDiscussionMutation = `mutation($discussion:ID!, $reason:DiscussionCloseReason!) {
closeDiscussion(input:{discussionId:$discussion, reason:$reason}) {
clientMutationId
}
}`;
const closeVariables = {
discussion: discussion.id,
reason: "RESOLVED",
}
await github.graphql(closeDiscussionMutation, closeVariables)
}

View File

@@ -5,7 +5,7 @@
repos:
# General hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-docstring-first
- id: check-json
@@ -27,7 +27,7 @@ repos:
- id: check-case-conflict
- id: detect-private-key
- repo: https://github.com/pre-commit/mirrors-prettier
rev: 'v3.0.0'
rev: 'v3.1.0'
hooks:
- id: prettier
types_or:
@@ -36,17 +36,17 @@ repos:
- markdown
exclude: "(^Pipfile\\.lock$)"
# Python hooks
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.0.280'
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.1.5'
hooks:
- id: ruff
- repo: https://github.com/psf/black
rev: 23.7.0
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 23.11.0
hooks:
- id: black
# Dockerfile hooks
- repo: https://github.com/AleksaC/hadolint-py
rev: v2.12.0.2
rev: v2.12.0.3
hooks:
- id: hadolint
# Shell script hooks
@@ -57,6 +57,6 @@ repos:
args:
- "--tab"
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: "v0.9.0.5"
rev: "v0.9.0.6"
hooks:
- id: shellcheck

View File

@@ -1,6 +1,16 @@
# https://prettier.io/docs/en/options.html#semicolons
semi: false
# https://prettier.io/docs/en/options.html#quotes
singleQuote: true
# https://prettier.io/docs/en/options.html#trailing-commas
trailingComma: "es5"
{
# https://prettier.io/docs/en/options.html#semicolons
"semi": false,
# https://prettier.io/docs/en/options.html#quotes
"singleQuote": true,
# https://prettier.io/docs/en/options.html#trailing-commas
"trailingComma": "es5",
"overrides": [
{
"files": "index.md",
"options": {
"tabWidth": 4
}
}
]
}

View File

@@ -1 +1 @@
3.8.16
3.9.18

View File

@@ -7,8 +7,8 @@ fix = true
line-length = 88
respect-gitignore = true
src = ["src"]
target-version = "py38"
format = "grouped"
target-version = "py39"
output-format = "grouped"
show-fixes = true
[per-file-ignores]

View File

@@ -11,7 +11,7 @@ If you want to implement something big:
## Python
Paperless supports python 3.8 and 3.9. We format Python code with [Black](https://github.com/psf/black).
Paperless supports python 3.9 - 3.11. We format Python code with [Black](https://github.com/psf/black).
## Branches
@@ -58,6 +58,13 @@ Our community review process for `non-trivial` PRs is the following:
This process might be slow as community members have different schedules and time to dedicate to the Paperless project. However it ensures community code reviews are as brilliantly thorough as they once were with @jonaswinkler.
# AI-Generated Code
This project does not specifically prohibit the use of AI-generated code _during the process_ of creating a PR, however:
1. Any code present in the final PR that was generated using AI sources should be clearly attributed as such and must not violate copyright protections.
2. We will not accept PRs that are entirely or mostly AI-derived.
# Translating Paperless-ngx
Some notes about translation:

View File

@@ -5,7 +5,7 @@
# Purpose: Compiles the frontend
# Notes:
# - Does NPM stuff with Typescript and such
FROM --platform=$BUILDPLATFORM docker.io/node:16-bookworm-slim AS compile-frontend
FROM --platform=$BUILDPLATFORM docker.io/node:20-bookworm-slim AS compile-frontend
COPY ./src-ui /src/src-ui
@@ -21,7 +21,7 @@ RUN set -eux \
# Comments:
# - pipenv dependencies are not left in the final image
# - pipenv can't touch the final image somehow
FROM --platform=$BUILDPLATFORM docker.io/python:3.9-alpine as pipenv-base
FROM --platform=$BUILDPLATFORM docker.io/python:3.11-alpine as pipenv-base
WORKDIR /usr/src/pipenv
@@ -29,7 +29,7 @@ COPY Pipfile* ./
RUN set -eux \
&& echo "Installing pipenv" \
&& python3 -m pip install --no-cache-dir --upgrade pipenv==2023.7.23 \
&& python3 -m pip install --no-cache-dir --upgrade pipenv==2023.10.24 \
&& echo "Generating requirement.txt" \
&& pipenv requirements > requirements.txt
@@ -37,7 +37,7 @@ RUN set -eux \
# Purpose: The final image
# Comments:
# - Don't leave anything extra in here
FROM docker.io/python:3.9-slim-bookworm as main-app
FROM docker.io/python:3.11-slim-bookworm as main-app
LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>"
LABEL org.opencontainers.image.documentation="https://docs.paperless-ngx.com/"
@@ -47,6 +47,14 @@ LABEL org.opencontainers.image.licenses="GPL-3.0-only"
ARG DEBIAN_FRONTEND=noninteractive
# Buildx provided, must be defined to use though
ARG TARGETARCH
# Can be workflow provided, defaults set for manual building
ARG JBIG2ENC_VERSION=0.29
ARG QPDF_VERSION=11.6.3
ARG GS_VERSION=10.02.0
#
# Begin installation and configuration
# Order the steps below from least often changed to most
@@ -67,23 +75,11 @@ ARG RUNTIME_PACKAGES="\
gnupg \
icc-profiles-free \
imagemagick \
# Image processing
liblept5 \
liblcms2-2 \
libtiff6 \
libfreetype6 \
libwebp7 \
libopenjp2-7 \
libimagequant0 \
libraqm0 \
libjpeg62-turbo \
# PostgreSQL
libpq5 \
postgresql-client \
# MySQL / MariaDB
mariadb-client \
# For Numpy
libatlas3-base \
# OCRmyPDF dependencies
tesseract-ocr \
tesseract-ocr-eng \
@@ -93,12 +89,11 @@ ARG RUNTIME_PACKAGES="\
tesseract-ocr-spa \
unpaper \
pngquant \
# pikepdf / qpdf
jbig2dec \
# lxml
libxml2 \
libxslt1.1 \
libgnutls30 \
libqpdf29 \
# itself
qpdf \
# Mime type detection
file \
@@ -107,9 +102,7 @@ ARG RUNTIME_PACKAGES="\
zlib1g \
# Barcode splitter
libzbar0 \
poppler-utils \
# RapidFuzz on armv7
libatomic1"
poppler-utils"
# Install basic runtime packages.
# These change very infrequently
@@ -117,7 +110,37 @@ RUN set -eux \
echo "Installing system packages" \
&& apt-get update \
&& apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \
&& rm -rf /var/lib/apt/lists/* \
&& 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-2_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10_${GS_VERSION}.dfsg-2_${TARGETARCH}.deb \
&& curl --fail --silent --show-error --location \
--output ghostscript_${GS_VERSION}.dfsg-2_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/ghostscript_${GS_VERSION}.dfsg-2_${TARGETARCH}.deb \
&& curl --fail --silent --show-error --location \
--output libgs10-common_${GS_VERSION}.dfsg-2_all.deb \
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10-common_${GS_VERSION}.dfsg-2_all.deb \
&& dpkg --install ./libgs10-common_${GS_VERSION}.dfsg-2_all.deb \
&& dpkg --install ./libgs10_${GS_VERSION}.dfsg-2_${TARGETARCH}.deb \
&& dpkg --install ./ghostscript_${GS_VERSION}.dfsg-2_${TARGETARCH}.deb \
&& echo "Installing jbig2enc" \
&& curl --fail --silent --show-error --location \
--output jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
&& dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
&& echo "Cleaning up image layer" \
&& rm --force --verbose *.deb \
&& rm --recursive --force --verbose /var/lib/apt/lists/* \
&& echo "Installing supervisor" \
&& python3 -m pip install --default-timeout=1000 --upgrade --no-cache-dir supervisor==4.2.5
@@ -168,41 +191,6 @@ RUN set -eux \
&& chmod +x install_management_commands.sh \
&& ./install_management_commands.sh
# Buildx provided, must be defined to use though
ARG TARGETARCH
ARG TARGETVARIANT
# Can be workflow provided, defaults set for manual building
ARG JBIG2ENC_VERSION=0.29
ARG QPDF_VERSION=11.3.0
ARG PIKEPDF_VERSION=7.2.0
ARG PSYCOPG2_VERSION=2.9.6
# Install the built packages from the installer library images
# These change sometimes
RUN set -eux \
&& echo "Getting binaries" \
&& mkdir paperless-ngx \
&& curl --fail --silent --show-error --output paperless-ngx.tar.gz --location https://github.com/paperless-ngx/builder/archive/58bb061b9b3b63009852d6d875f9a305d9ae6ac9.tar.gz \
&& tar -xf paperless-ngx.tar.gz --directory paperless-ngx --strip-components=1 \
&& cd paperless-ngx \
# Setting a specific revision ensures we know what this installed
# and ensures cache breaking on changes
&& echo "Installing jbig2enc" \
&& cp ./jbig2enc/${JBIG2ENC_VERSION}/${TARGETARCH}${TARGETVARIANT}/jbig2 /usr/local/bin/ \
&& cp ./jbig2enc/${JBIG2ENC_VERSION}/${TARGETARCH}${TARGETVARIANT}/libjbig2enc* /usr/local/lib/ \
&& chmod a+x /usr/local/bin/jbig2 \
&& echo "Installing pikepdf and dependencies" \
&& python3 -m pip install --no-cache-dir ./pikepdf/${PIKEPDF_VERSION}/${TARGETARCH}${TARGETVARIANT}/*.whl \
&& python3 -m pip list \
&& echo "Installing psycopg2" \
&& python3 -m pip install --no-cache-dir ./psycopg2/${PSYCOPG2_VERSION}/${TARGETARCH}${TARGETVARIANT}/psycopg2*.whl \
&& python3 -m pip list \
&& echo "Cleaning up image layer" \
&& cd ../ \
&& rm -rf paperless-ngx \
&& rm paperless-ngx.tar.gz
WORKDIR /usr/src/paperless/src/
# Python dependencies
@@ -214,6 +202,9 @@ COPY --from=pipenv-base /usr/src/pipenv/requirements.txt ./
ARG BUILD_PACKAGES="\
build-essential \
git \
# https://www.psycopg.org/docs/install.html#prerequisites
libpq-dev \
# https://github.com/PyMySQL/mysqlclient#linux
default-libmysqlclient-dev \
pkg-config"
@@ -226,34 +217,46 @@ RUN --mount=type=cache,target=/root/.cache/pip/,id=pip-cache \
&& python3 -m pip install --no-cache-dir --upgrade wheel \
&& echo "Installing Python requirements" \
&& python3 -m pip install --default-timeout=1000 --requirement requirements.txt \
&& echo "Patching whitenoise for compression speedup" \
&& curl --fail --silent --show-error --location --output 484.patch https://github.com/evansd/whitenoise/pull/484.patch \
&& patch -d /usr/local/lib/python3.11/site-packages --verbose -p2 < 484.patch \
&& rm 484.patch \
&& echo "Installing NLTK data" \
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" snowball_data \
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" stopwords \
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" punkt \
&& echo "Cleaning up image" \
&& apt-get -y purge ${BUILD_PACKAGES} \
&& apt-get -y autoremove --purge \
&& apt-get --yes purge ${BUILD_PACKAGES} \
&& apt-get --yes autoremove --purge \
&& apt-get clean --yes \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /tmp/* \
&& rm -rf /var/tmp/* \
&& rm -rf /var/cache/apt/archives/* \
&& truncate -s 0 /var/log/*log
&& rm --recursive --force --verbose /var/lib/apt/lists/* \
&& rm --recursive --force --verbose /tmp/* \
&& rm --recursive --force --verbose /var/tmp/* \
&& rm --recursive --force --verbose /var/cache/apt/archives/* \
&& truncate --size 0 /var/log/*log
# copy backend
COPY ./src ./
COPY --chown=1000:1000 ./src ./
# copy frontend
COPY --from=compile-frontend /src/src/documents/static/frontend/ ./documents/static/frontend/
COPY --from=compile-frontend --chown=1000:1000 /src/src/documents/static/frontend/ ./documents/static/frontend/
# add users, setup scripts
# Mount the compiled frontend to expected location
RUN set -eux \
&& addgroup --gid 1000 paperless \
&& useradd --uid 1000 --gid paperless --home-dir /usr/src/paperless paperless \
&& chown -R paperless:paperless /usr/src/paperless \
&& gosu paperless python3 manage.py collectstatic --clear --no-input --link \
&& gosu paperless python3 manage.py compilemessages
&& echo "Setting up user/group" \
&& addgroup --gid 1000 paperless \
&& useradd --uid 1000 --gid paperless --home-dir /usr/src/paperless paperless \
&& echo "Creating volume directories" \
&& mkdir --parents --verbose /usr/src/paperless/data \
&& mkdir --parents --verbose /usr/src/paperless/media \
&& mkdir --parents --verbose /usr/src/paperless/consume \
&& mkdir --parents --verbose /usr/src/paperless/export \
&& echo "Adjusting all permissions" \
&& chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \
&& echo "Collecting static files" \
&& gosu paperless python3 manage.py collectstatic --clear --no-input --link \
&& gosu paperless python3 manage.py compilemessages
VOLUME ["/usr/src/paperless/data", \
"/usr/src/paperless/media", \

78
Pipfile
View File

@@ -3,69 +3,57 @@ url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[[source]]
url = "https://www.piwheels.org/simple"
verify_ssl = true
name = "piwheels"
[packages]
dateparser = "~=1.1"
# WARNING: django does not use semver.
# Only patch versions are guaranteed to not introduce breaking changes.
django = "~=4.1.9"
django-cors-headers = "*"
django = "~=4.2.7"
django-auditlog = "*"
django-celery-results = "*"
django-compression-middleware = "*"
django-guardian = "*"
django-cors-headers = "*"
django-extensions = "*"
django-filter = "~=23.1"
django-filter = "~=23.3"
django-guardian = "*"
django-multiselectfield = "*"
djangorestframework = "~=3.14"
djangorestframework-guardian = "*"
drf-writable-nested = "*"
bleach = "*"
celery = "*"
channels = "~=4.0"
channels-redis = "*"
concurrent-log-handler = "*"
filelock = "*"
flower = "*"
gotenberg-client = "*"
gunicorn = "*"
imap-tools = "*"
inotifyrecursive = "~=0.3"
langdetect = "*"
mysqlclient = "*"
nltk = "*"
ocrmypdf = "~=15.0"
pathvalidate = "*"
python-gnupg = "*"
python-dotenv = "*"
python-dateutil = "*"
python-magic = "*"
python-ipware = "*"
pdf2image = "*"
psycopg2 = "*"
python-dateutil = "*"
python-dotenv = "*"
python-gnupg = "*"
python-ipware = "*"
python-magic = "*"
pyzbar = "*"
rapidfuzz = "*"
redis = {extras = ["hiredis"], version = "*"}
scikit-learn = "~=1.3"
whitenoise = "~=6.5"
watchdog = "~=3.0"
whoosh="~=2.7"
inotifyrecursive = "~=0.3"
ocrmypdf = "~=14.0"
tqdm = "*"
tika-client = "*"
channels = "~=4.0"
channels-redis = "*"
uvicorn = {extras = ["standard"], version = "*"}
concurrent-log-handler = "*"
pyzbar = "*"
mysqlclient = "*"
celery = {extras = ["redis"], version = "*"}
setproctitle = "*"
nltk = "*"
pdf2image = "*"
flower = "*"
bleach = "*"
tika-client = "*"
tqdm = "*"
uvicorn = {extras = ["standard"], version = "*"}
watchdog = "~=3.0"
whitenoise = "~=6.6"
whoosh="~=2.7"
zxing-cpp = {version = "*", platform_machine = "== 'x86_64'"}
#
# Packages locked due to issues (try to check if these are fixed in a release every so often)
#
# Pin this until piwheels is building 1.9 (see https://www.piwheels.org/project/scipy/)
scipy = "==1.8.1"
# v4 brings in extra dependencies for features not used here
reportlab = "==3.6.12"
# Pin these until piwheels is building a newer version (see https://www.piwheels.org/project/{package}/)
cryptography = "==40.0.1"
pikepdf = "==7.2.0"
pillow = "==9.5.0"
[dev-packages]
# Linting
@@ -82,11 +70,11 @@ pytest-env = "*"
pytest-sugar = "*"
pytest-xdist = "*"
pytest-rerunfailures = "*"
"pdfminer.six" = "*"
imagehash = "*"
daphne = "*"
# Documentation
mkdocs-material = "*"
mkdocs-glightbox = "*"
[typing-dev]
mypy = "*"
@@ -98,12 +86,10 @@ celery-types = "*"
django-stubs = {extras= ["compatible-mypy"], version="*"}
types-dateparser = "*"
types-bleach = "*"
types-humanfriendly = "*"
types-redis = "*"
types-tqdm = "*"
types-Markdown = "*"
types-Pygments = "*"
types-backports = "*"
types-colorama = "*"
types-psycopg2 = "*"
types-setuptools = "*"

4553
Pipfile.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -16,8 +16,7 @@
Paperless-ngx is a document management system that transforms your physical documents into a searchable online archive so you can keep, well, _less paper_.
Paperless-ngx forked from [paperless-ng](https://github.com/jonaswinkler/paperless-ng) to continue the great work and distribute responsibility of supporting and advancing the project among a team of people. [Consider joining us!](#community-support) Discussion of this transition can be found in issues
[#1599](https://github.com/jonaswinkler/paperless-ng/issues/1599) and [#1632](https://github.com/jonaswinkler/paperless-ng/issues/1632).
Paperless-ngx is the official successor to the original [Paperless](https://github.com/the-paperless-project/paperless) & [Paperless-ng](https://github.com/jonaswinkler/paperless-ng) projects and is designed to distribute the responsibility of advancing and supporting the project among a team of people. [Consider joining us!](#community-support)
A demo is available at [demo.paperless-ngx.com](https://demo.paperless-ngx.com) using login `demo` / `demo`. _Note: demo content is reset frequently and confidential information should not be uploaded._
@@ -36,32 +35,11 @@ A demo is available at [demo.paperless-ngx.com](https://demo.paperless-ngx.com)
![Dashboard](https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docs/assets/screenshots/documents-smallcards.png#gh-light-mode-only)
![Dashboard](https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docs/assets/screenshots/documents-smallcards-dark.png#gh-dark-mode-only)
- Organize and index your scanned documents with tags, correspondents, types, and more.
- Performs OCR on your documents, adds selectable text to image only documents and adds tags, correspondents and document types to your documents.
- Supports PDF documents, images, plain text files, and Office documents (Word, Excel, Powerpoint, and LibreOffice equivalents).
- Office document support is optional and provided by Apache Tika (see [configuration](https://docs.paperless-ngx.com/configuration/#tika))
- Paperless stores your documents plain on disk. Filenames and folders are managed by paperless and their format can be configured freely.
- Single page application front end.
- Includes a dashboard that shows basic statistics and has document upload.
- Filtering by tags, correspondents, types, and more.
- Customizable views can be saved and displayed on the dashboard.
- Full text search helps you find what you need.
- Auto completion suggests relevant words from your documents.
- Results are sorted by relevance to your search query.
- Highlighting shows you which parts of the document matched the query.
- Searching for similar documents ("More like this")
- Email processing: Paperless adds documents from your email accounts.
- Configure multiple accounts and filters for each account.
- When adding documents from mail, paperless can move these mail to a new folder, mark them as read, flag them as important or delete them.
- Machine learning powered document matching.
- Paperless-ngx learns from your documents and will be able to automatically assign tags, correspondents and types to documents once you've stored a few documents in paperless.
- Optimized for multi core systems: Paperless-ngx consumes multiple documents in parallel.
- The integrated sanity checker makes sure that your document archive is in good health.
- [More screenshots are available in the documentation](https://docs.paperless-ngx.com/#screenshots).
A full list of [features](https://docs.paperless-ngx.com/#features) and [screenshots](https://docs.paperless-ngx.com/#screenshots) are available in the [documentation](https://docs.paperless-ngx.com/).
# Getting started
The easiest way to deploy paperless is docker-compose. The files in the [`/docker/compose` directory](https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose) are configured to pull the image from Github Packages.
The easiest way to deploy paperless is docker-compose. The files in the [`/docker/compose` directory](https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose) are configured to pull the image from GitHub Packages.
If you'd like to jump right in, you can configure a docker-compose environment with our install script:
@@ -85,7 +63,7 @@ If you feel like contributing to the project, please do! Bug fixes, enhancements
## Community Support
People interested in continuing the work on paperless-ngx are encouraged to reach out here on github and in the [Matrix Room](https://matrix.to/#/#paperless:adnidor.de). If you would like to contribute to the project on an ongoing basis there are multiple [teams](https://github.com/orgs/paperless-ngx/people) (frontend, ci/cd, etc) that could use your help so please reach out!
People interested in continuing the work on paperless-ngx are encouraged to reach out here on github and in the [Matrix Room](https://matrix.to/#/#paperless:matrix.org). If you would like to contribute to the project on an ongoing basis there are multiple [teams](https://github.com/orgs/paperless-ngx/people) (frontend, ci/cd, etc) that could use your help so please reach out!
## Translation

View File

@@ -80,7 +80,7 @@ django_checks() {
search_index() {
local -r index_version=6
local -r index_version=7
local -r index_version_file=${DATA_DIR}/.index_version
if [[ (! -f "${index_version_file}") || $(<"${index_version_file}") != "$index_version" ]]; then

View File

@@ -13,6 +13,7 @@ for command in decrypt_documents \
document_retagger \
document_thumbnails \
document_sanity_checker \
document_fuzzy_match \
manage_superuser;
do
echo "installing $command..."

View File

@@ -10,8 +10,8 @@ Before making backups, make sure that paperless is not running.
Options available to any installation of paperless:
- Use the [document exporter](#exporter). The document exporter exports all your documents,
thumbnails and metadata to a specific folder. You may import your
documents into a fresh instance of paperless again or store your
thumbnails, metadata, and database contents to a specific folder. You may import your
documents and settings into a fresh instance of paperless again or store your
documents in another DMS with this export.
- The document exporter is also able to update an already existing
export. Therefore, incremental backups with `rsync` are entirely
@@ -139,7 +139,7 @@ following:
1. Update dependencies. New paperless version may require additional
dependencies. The dependencies required are listed in the section
about
[bare metal installations](/setup#bare_metal).
[bare metal installations](setup.md#bare_metal).
2. Update python requirements. Keep in mind to activate your virtual
environment before that, if you use one.
@@ -239,8 +239,9 @@ with the argument `--help`.
### Document exporter {#exporter}
The document exporter exports all your data from paperless into a folder
for backup or migration to another DMS.
The document exporter exports all your data (including your settings
and database contents) from paperless into a folder for backup or
migration to another DMS.
If you use the document exporter within a cronjob to backup your data
you might use the `-T` flag behind exec to suppress "The input device
@@ -251,14 +252,15 @@ is not a TTY" errors. For example:
document_exporter target [-c] [-d] [-f] [-na] [-nt] [-p] [-sm] [-z]
optional arguments:
-c, --compare-checksums
-d, --delete
-f, --use-filename-format
-c, --compare-checksums
-d, --delete
-f, --use-filename-format
-na, --no-archive
-nt, --no-thumbnail
-p, --use-folder-prefix
-p, --use-folder-prefix
-sm, --split-manifest
-z --zip
-z, --zip
-zn, --zip-name
```
`target` is a folder to which the data gets written. This includes
@@ -286,7 +288,7 @@ other files.
The filenames generated by this command follow the format
`[date created] [correspondent] [title].[extension]`. If you want
paperless to use `PAPERLESS_FILENAME_FORMAT` for exported filenames
paperless to use [`PAPERLESS_FILENAME_FORMAT`](configuration.md#PAPERLESS_FILENAME_FORMAT) for exported filenames
instead, specify `-f` or `--use-filename-format`.
If `-na` or `--no-archive` is provided, no archive files will be exported,
@@ -314,7 +316,8 @@ manifest.json will still contain application wide information (e.g. tags, corres
documenttype, etc)
If `-z` or `--zip` is provided, the export will be a zip file
in the target directory, named according to the current date.
in the target directory, named according to the current local date or the
value set in `-zn` or `--zip-name`.
!!! warning
@@ -351,7 +354,7 @@ currently-imported docs. This problem is common enough that there are
tools for it.
```
document_retagger [-h] [-c] [-T] [-t] [-i] [--use-first] [-f]
document_retagger [-h] [-c] [-T] [-t] [-i] [--id-range] [--use-first] [-f]
optional arguments:
-c, --correspondent
@@ -359,6 +362,7 @@ optional arguments:
-t, --document_type
-s, --storage_path
-i, --inbox-only
--id-range
--use-first
-f, --overwrite
```
@@ -375,6 +379,11 @@ Specify `-i` to have the document retagger work on documents tagged with
inbox tags only. This is useful when you don't want to mess with your
already processed documents.
Specify `--id-range 1 100` to have the document retagger work only on a
specific range of document id´s. This can be useful if you have a lot of
documents and want to test the matching rules only on a subset of
documents.
When multiple document types or correspondents match a single document,
the retagger won't assign these to the document. Specify `--use-first`
to override this behavior and just use the first correspondent or type
@@ -406,6 +415,9 @@ This command takes no arguments.
Use this command to re-create document thumbnails. Optionally include the ` --document {id}` option to generate thumbnails for a specific document only.
You may also specify `--processes` to control the number of processes used to generate new thumbnails. The default is to utilize
a quarter of the available processors.
```
document_thumbnails
```
@@ -433,7 +445,7 @@ task scheduler.
### Managing filenames {#renamer}
If you use paperless' feature to
[assign custom filenames to your documents](/advanced_usage#file-name-handling), you can use this command to move all your files after
[assign custom filenames to your documents](advanced_usage.md#file-name-handling), you can use this command to move all your files after
changing the naming scheme.
!!! warning
@@ -539,7 +551,7 @@ Documents can be stored in Paperless using GnuPG encryption.
!!! warning
Encryption is deprecated since [paperless-ng 0.9](/changelog#paperless-ng-090) and doesn't really
Encryption is deprecated since [paperless-ng 0.9](changelog.md#paperless-ng-090) and doesn't really
provide any additional security, since you have to store the passphrase
in a configuration file on the same system as the encrypted documents
for paperless to work. Furthermore, the entire text content of the
@@ -560,9 +572,30 @@ Enabling encryption is no longer supported.
Basic usage to disable encryption of your document store:
(Note: If `PAPERLESS_PASSPHRASE` isn't set already, you need to specify
(Note: If [`PAPERLESS_PASSPHRASE`](configuration.md#PAPERLESS_PASSPHRASE) isn't set already, you need to specify
it here)
```
decrypt_documents [--passphrase SECR3TP4SSPHRA$E]
```
### Detecting duplicates {#fuzzy_duplicate}
Paperless already catches and prevents upload of exactly matching documents,
however a new scan of an existing document may not produce an exact bit for bit
duplicate. But the content should be exact or close, allowing detection.
This tool does a fuzzy match over document content, looking for
those which look close according to a given ratio.
At this time, other metadata (such as correspondent or type) is not
take into account by the detection.
```
document_fuzzy_match [--ratio] [--processes N]
```
| Option | Required | Default | Description |
| ----------- | -------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| --ratio | No | 85.0 | a number between 0 and 100, setting how similar a document must be for it to be reported. Higher numbers mean more similarity. |
| --processes | No | 1/4 of system cores | Number of processes to use for matching. Setting 1 disables multiple processes |

View File

@@ -35,7 +35,8 @@ The following algorithms are available:
(i.e. preserve ordering) in the PDF.
- **Regular expression:** Parses the match as a regular expression and
tries to find a match within the document.
- **Fuzzy match:** I don't know. Look at [the source](https://github.com/paperless-ngx/paperless-ngx/blob/main/src/documents/matching.py).
- **Fuzzy match:** Uses a partial matching based on locating the tag text
inside the document, using a [partial ratio](https://maxbachmann.github.io/RapidFuzz/Usage/fuzz.html#partial-ratio)
- **Auto:** Tries to automatically match new documents. This does not
require you to set a match. See the [notes below](#automatic-matching).
@@ -106,7 +107,7 @@ document is consumed using a couple of simple hooks.
Just write a script, put it somewhere that Paperless can read & execute,
and then put the path to that script in `paperless.conf` or
`docker-compose.env` with the variable name of either
`PAPERLESS_PRE_CONSUME_SCRIPT` or `PAPERLESS_POST_CONSUME_SCRIPT`.
[`PAPERLESS_PRE_CONSUME_SCRIPT`](configuration.md#PAPERLESS_PRE_CONSUME_SCRIPT) or [`PAPERLESS_POST_CONSUME_SCRIPT`](configuration.md#PAPERLESS_POST_CONSUME_SCRIPT).
!!! info
@@ -126,6 +127,7 @@ script can access the following relevant environment variables set:
| ----------------------- | ------------------------------------------------------------ |
| `DOCUMENT_SOURCE_PATH` | Original path of the consumed document |
| `DOCUMENT_WORKING_PATH` | Path to a copy of the original that consumption will work on |
| `TASK_ID` | UUID of the task used to process the new document (if any) |
!!! note
@@ -168,21 +170,22 @@ Executed after the consumer has successfully processed a document and
has moved it into paperless. It receives the following environment
variables:
| Environment Variable | Description |
| ---------------------------- | --------------------------------------------- |
| `DOCUMENT_ID` | Database primary key of the document |
| `DOCUMENT_FILE_NAME` | Formatted filename, not including paths |
| `DOCUMENT_CREATED` | Date & time when document created |
| `DOCUMENT_MODIFIED` | Date & time when document was last modified |
| `DOCUMENT_ADDED` | Date & time when document was added |
| `DOCUMENT_SOURCE_PATH` | Path to the original document file |
| `DOCUMENT_ARCHIVE_PATH` | Path to the generate archive file (if any) |
| `DOCUMENT_THUMBNAIL_PATH` | Path to the generated thumbnail |
| `DOCUMENT_DOWNLOAD_URL` | URL for document download |
| `DOCUMENT_THUMBNAIL_URL` | URL for the document thumbnail |
| `DOCUMENT_CORRESPONDENT` | Assigned correspondent (if any) |
| `DOCUMENT_TAGS` | Comma separated list of tags applied (if any) |
| `DOCUMENT_ORIGINAL_FILENAME` | Filename of original document |
| Environment Variable | Description |
| ---------------------------- | ---------------------------------------------- |
| `DOCUMENT_ID` | Database primary key of the document |
| `DOCUMENT_FILE_NAME` | Formatted filename, not including paths |
| `DOCUMENT_CREATED` | Date & time when document created |
| `DOCUMENT_MODIFIED` | Date & time when document was last modified |
| `DOCUMENT_ADDED` | Date & time when document was added |
| `DOCUMENT_SOURCE_PATH` | Path to the original document file |
| `DOCUMENT_ARCHIVE_PATH` | Path to the generate archive file (if any) |
| `DOCUMENT_THUMBNAIL_PATH` | Path to the generated thumbnail |
| `DOCUMENT_DOWNLOAD_URL` | URL for document download |
| `DOCUMENT_THUMBNAIL_URL` | URL for the document thumbnail |
| `DOCUMENT_CORRESPONDENT` | Assigned correspondent (if any) |
| `DOCUMENT_TAGS` | Comma separated list of tags applied (if any) |
| `DOCUMENT_ORIGINAL_FILENAME` | Filename of original document |
| `TASK_ID` | Task UUID used to import the document (if any) |
The script can be in any language, A simple shell script example:
@@ -248,7 +251,7 @@ document. You will end up getting files like `0000123.pdf` in your media
directory. This isn't necessarily a bad thing, because you normally
don't have to access these files manually. However, if you wish to name
your files differently, you can do that by adjusting the
`PAPERLESS_FILENAME_FORMAT` configuration option. Paperless adds the
[`PAPERLESS_FILENAME_FORMAT`](configuration.md#PAPERLESS_FILENAME_FORMAT) configuration option. Paperless adds the
correct file extension e.g. `.pdf`, `.jpg` automatically.
This variable allows you to configure the filename (folders are allowed)
@@ -341,7 +344,7 @@ value.
Paperless checks the filename of a document whenever it is saved.
Therefore, you need to update the filenames of your documents and move
them after altering this setting by invoking the
[`document renamer`](/administration#renamer).
[`document renamer`](administration.md#renamer).
!!! warning
@@ -376,7 +379,7 @@ When a single storage layout is not sufficient for your use case,
storage paths come to the rescue. Storage paths allow you to configure
more precisely where each document is stored in the file system.
- Each storage path is a `PAPERLESS_FILENAME_FORMAT` and
- Each storage path is a [`PAPERLESS_FILENAME_FORMAT`](configuration.md#PAPERLESS_FILENAME_FORMAT) and
follows the rules described above
- Each document is assigned a storage path using the matching
algorithms described above, but can be overwritten at any time
@@ -416,7 +419,7 @@ Insurances/ # Insurances
!!! tip
Defining a storage path is optional. If no storage path is defined for a
document, the global `PAPERLESS_FILENAME_FORMAT` is applied.
document, the global [`PAPERLESS_FILENAME_FORMAT`](configuration.md#PAPERLESS_FILENAME_FORMAT) is applied.
## Celery Monitoring {#celery-monitoring}
@@ -525,7 +528,7 @@ At this time, the library utilized for detection of barcodes supports the follow
You may check for updates on the [zbar library homepage](https://github.com/mchehab/zbar).
For usage in Paperless, the type of barcode does not matter, only the contents of it.
For how to enable barcode usage, see [the configuration](/configuration#barcodes).
For how to enable barcode usage, see [the configuration](configuration.md#barcodes).
The two settings may be enabled independently, but do have interactions as explained
below.
@@ -551,7 +554,7 @@ one which holds data to keep in the document.
If your scanner supports double-sided scanning natively, you do not need this feature.
This feature is turned off by default, see [configuration](/configuration#collate) on how to turn it on.
This feature is turned off by default, see [configuration](configuration.md#collate) on how to turn it on.
### Summary
@@ -589,6 +592,12 @@ case, Paperless will remove the staging copy as well as the scan, and give you a
message asking you to restart the process from scratch, by scanning the odd pages again,
followed by the even pages.
It's important that the scan files get consumed in the correct order, and one at a time.
You therefore need to make sure that Paperless is running while you upload the files into
the directory; and if you're using [polling](configuration.md#polling), make sure that
`CONSUMER_POLLING` is set to a value lower than it takes for the second scan to appear,
like 5-10 or even lower.
Another thing that might happen is that you start a double sided scan, but then forget
to upload the second file. To avoid collating the wrong documents if you then come back
a day later to scan a new double-sided document, Paperless will only keep an "odd numbered
@@ -597,11 +606,11 @@ scan a completely new "odd numbered pages" one. The old staging file will get di
### Interaction with "subdirs as tags"
The collation feature can be used together with the "subdirs as tags" feature (but this is not
a requirement). Just create a correctly named double-sided subdir in the hierachy and upload
your scans there. For example, both `double-sided/foo/bar` as well as `foo/bar/double-sided` will
cause the collated document to be treated as if it were uploaded into `foo/bar` and receive both
`foo` and `bar` tags, but not `double-sided`.
The collation feature can be used together with the [subdirs as tags](configuration.md#consume_config)
feature (but this is not a requirement). Just create a correctly named double-sided subdir
in the hierachy and upload your scans there. For example, both `double-sided/foo/bar` as
well as `foo/bar/double-sided` will cause the collated document to be treated as if it
were uploaded into `foo/bar` and receive both `foo` and `bar` tags, but not `double-sided`.
### Interaction with document splitting

View File

@@ -6,7 +6,7 @@ provides a browsable API for most of its endpoints, which you can
inspect at `http://<paperless-host>:<port>/api/`. This also documents
most of the available filters and ordering fields.
The API provides 7 main endpoints:
The API provides the following main endpoints:
- `/api/documents/`: Full CRUD support, except POSTing new documents.
See below.
@@ -19,6 +19,8 @@ The API provides 7 main endpoints:
- `/api/mail_rules/`: Full CRUD support.
- `/api/users/`: Full CRUD support.
- `/api/groups/`: Full CRUD support.
- `/api/share_links/`: Full CRUD support.
- `/api/custom_fields/`: Full CRUD support.
All of these endpoints except for the logging endpoint allow you to
fetch (and edit and delete where appropriate) individual objects by
@@ -47,8 +49,11 @@ fields:
Read-only.
- `archived_file_name`: Verbose filename of the archived document.
Read-only. Null if no archived document is available.
- `notes`: Array of notes associated with the document.
- `set_permissions`: Allows setting document permissions. Optional,
write-only. See [below](#permissions).
- `custom_fields`: Array of custom fields & values, specified as
{ field: CUSTOM_FIELD_ID, value: VALUE }
## Downloading documents
@@ -124,6 +129,11 @@ File metadata is reported as a list of objects in the following form:
depends on the file type and the metadata available in that specific
document. Paperless only reports PDF metadata at this point.
## Documents additional endpoints
- `/api/documents/<id>/notes/`: Retrieve notes for a document.
- `/api/documents/<id>/share_links/`: Retrieve share links for a document.
## Authorization
The REST api provides three different forms of authentication.
@@ -167,7 +177,7 @@ specific query parameters cause the API to return full text search
results:
- `/api/documents/?query=your%20search%20query`: Search for a document
using a full text query. For details on the syntax, see [Basic Usage - Searching](/usage#basic-usage_searching).
using a full text query. For details on the syntax, see [Basic Usage - Searching](usage.md#basic-usage_searching).
- `/api/documents/?more_like=1234`: Search for documents similar to
the document with id 1234.
@@ -272,19 +282,20 @@ consumption including the ID of a created document if consumption succeeded.
## Permissions
All objects (documents, tags, etc.) allow setting object-level permissions
with an optional `set_permissions` parameter which is of the form:
with optional `owner` and / or a `set_permissions` parameters which are of
the form:
```
{
"owner": user_id,
"view": {
"users": [...],
"groups": [...],
},
"change": {
"users": [...],
"groups": [...],
},
"owner": ...,
"set_permissions": {
"view": {
"users": [...],
"groups": [...],
},
"change": {
"users": [...],
"groups": [...],
},
}
```
@@ -292,7 +303,7 @@ with an optional `set_permissions` parameter which is of the form:
Arrays should contain user or group ID numbers.
If this parameter is supplied the object's permissions will be overwritten,
If these parameters are supplied the object's permissions will be overwritten,
assuming the authenticated user has permission to do so (the user must be
the object owner or a superuser).

View File

@@ -20,6 +20,28 @@
margin-left: 4%;
float: left;
}
.grid-flipped-left {
width: 66%;
float: left;
}
.grid-flipped-right {
width: 29%;
margin-left: 4%;
float: left;
}
.grid-half-left {
width: 48%;
float: left;
}
.grid-half-right {
width: 48%;
margin-left: 4%;
float: left;
}
}
.grid-left > p {
@@ -31,6 +53,48 @@
margin: 0;
}
.clear {
clear: both;
margin-bottom: 20px;
display: block;
}
.index-callout {
margin-right: .5rem;
}
/* make code in headers not bold */
h4 code {
font-weight: normal;
}
/* Hide config vars from sidebar, toc and move the border on mobile case their hidden */
.md-nav.md-nav--secondary .md-nav__item .md-nav__link[href*="PAPERLESS_"],
.md-nav.md-nav--secondary .md-nav__item .md-nav__link[href*="USERMAP_"] {
display: none;
}
@media screen and (max-width: 76.1875em) {
.md-nav--primary .md-nav__item {
border-top: none;
}
.md-nav--primary .md-nav__link {
border-top: .05rem solid var(--md-default-fg-color--lightest);
}
}
/* Show search shortcut key */
[data-md-toggle="search"]:not(:checked) ~ .md-header .md-search__form::after {
position: absolute;
top: .3rem;
right: .3rem;
display: block;
padding: .1rem .4rem;
color: var(--md-default-fg-color--lighter);
font-weight: bold;
font-size: .8rem;
border: .05rem solid var(--md-default-fg-color--lighter);
border-radius: .1rem;
content: "/";
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 740 KiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

After

Width:  |  Height:  |  Size: 501 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 KiB

After

Width:  |  Height:  |  Size: 644 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 KiB

After

Width:  |  Height:  |  Size: 667 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 616 KiB

After

Width:  |  Height:  |  Size: 1003 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 KiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 705 KiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 480 KiB

After

Width:  |  Height:  |  Size: 925 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 KiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 685 KiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 KiB

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 706 KiB

After

Width:  |  Height:  |  Size: 726 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 516 KiB

After

Width:  |  Height:  |  Size: 792 KiB

View File

@@ -1,5 +1,100 @@
# Changelog
## paperless-ngx 1.17.4
### Bug Fixes
- Fix: ghostscript rendering error doesnt trigger frontend failure message [@shamoon](https://github.com/shamoon) ([#4092](https://github.com/paperless-ngx/paperless-ngx/pull/4092))
### All App Changes
- Fix: ghostscript rendering error doesnt trigger frontend failure message [@shamoon](https://github.com/shamoon) ([#4092](https://github.com/paperless-ngx/paperless-ngx/pull/4092))
## paperless-ngx 1.17.3
### Bug Fixes
- Fix: When PDF/A rendering fails, add a consideration for the user to add args to override [@stumpylog](https://github.com/stumpylog) ([#4083](https://github.com/paperless-ngx/paperless-ngx/pull/4083))
### Dependencies
- Chore: update frontend PDF viewer (including pdf-js) [@shamoon](https://github.com/shamoon) ([#4065](https://github.com/paperless-ngx/paperless-ngx/pull/4065))
### Maintenance
- Dev: Upload code coverage in the same job [@stumpylog](https://github.com/stumpylog) ([#4084](https://github.com/paperless-ngx/paperless-ngx/pull/4084))
### All App Changes
<details>
<summary>3 changes</summary>
- Fix: When PDF/A rendering fails, add a consideration for the user to add args to override [@stumpylog](https://github.com/stumpylog) ([#4083](https://github.com/paperless-ngx/paperless-ngx/pull/4083))
- Chore: update frontend PDF viewer (including pdf-js) [@shamoon](https://github.com/shamoon) ([#4065](https://github.com/paperless-ngx/paperless-ngx/pull/4065))
- Chore: Prepare for Python 3.11 support [@stumpylog](https://github.com/stumpylog) ([#4066](https://github.com/paperless-ngx/paperless-ngx/pull/4066))
</details>
## paperless-ngx 1.17.2
### Features
- Enhancement: Allow to set a prefix for keys and channels in redis [@amo13](https://github.com/amo13) ([#3993](https://github.com/paperless-ngx/paperless-ngx/pull/3993))
### Bug Fixes
- Fix: Increase the HTTP timeouts for Tika/Gotenberg to maximum task time [@stumpylog](https://github.com/stumpylog) ([#4061](https://github.com/paperless-ngx/paperless-ngx/pull/4061))
- Fix: Allow adding an SSL certificate for IMAP SSL context [@stumpylog](https://github.com/stumpylog) ([#4048](https://github.com/paperless-ngx/paperless-ngx/pull/4048))
- Fix: tag creation sometimes retained search text [@shamoon](https://github.com/shamoon) ([#4038](https://github.com/paperless-ngx/paperless-ngx/pull/4038))
- Fix: enforce permissions on bulk_edit operations [@shamoon](https://github.com/shamoon) ([#4007](https://github.com/paperless-ngx/paperless-ngx/pull/4007))
### All App Changes
<details>
<summary>6 changes</summary>
- Fix: Increase the HTTP timeouts for Tika/Gotenberg to maximum task time [@stumpylog](https://github.com/stumpylog) ([#4061](https://github.com/paperless-ngx/paperless-ngx/pull/4061))
- Enhancement: disable / hide some UI buttons / elements if insufficient permissions, show errors [@shamoon](https://github.com/shamoon) ([#4014](https://github.com/paperless-ngx/paperless-ngx/pull/4014))
- Fix: Allow adding an SSL certificate for IMAP SSL context [@stumpylog](https://github.com/stumpylog) ([#4048](https://github.com/paperless-ngx/paperless-ngx/pull/4048))
- Fix: tag creation sometimes retained search text [@shamoon](https://github.com/shamoon) ([#4038](https://github.com/paperless-ngx/paperless-ngx/pull/4038))
- Fix: enforce permissions on bulk_edit operations [@shamoon](https://github.com/shamoon) ([#4007](https://github.com/paperless-ngx/paperless-ngx/pull/4007))
- Enhancement: Allow to set a prefix for keys and channels in redis [@amo13](https://github.com/amo13) ([#3993](https://github.com/paperless-ngx/paperless-ngx/pull/3993))
</details>
## paperless-ngx 1.17.1
### Features
- Fix / Enhancement: restrict status messages by owner if set \& improve 404 page [@shamoon](https://github.com/shamoon) ([#3959](https://github.com/paperless-ngx/paperless-ngx/pull/3959))
- Feature: Add Ukrainian translation [@shamoon](https://github.com/shamoon) ([#3941](https://github.com/paperless-ngx/paperless-ngx/pull/3941))
### Bug Fixes
- Fix: handle ASN = 0 on frontend cards [@shamoon](https://github.com/shamoon) ([#3988](https://github.com/paperless-ngx/paperless-ngx/pull/3988))
- Fix: improve light color filled primary button text legibility [@shamoon](https://github.com/shamoon) ([#3980](https://github.com/paperless-ngx/paperless-ngx/pull/3980))
- Fix / Enhancement: restrict status messages by owner if set \& improve 404 page [@shamoon](https://github.com/shamoon) ([#3959](https://github.com/paperless-ngx/paperless-ngx/pull/3959))
- Fix: handle very old date strings in correspondent list [@shamoon](https://github.com/shamoon) ([#3953](https://github.com/paperless-ngx/paperless-ngx/pull/3953))
### Documentation
- docs(bare-metal): add new dependency [@bin101](https://github.com/bin101) ([#3931](https://github.com/paperless-ngx/paperless-ngx/pull/3931))
### Dependencies
- Chore: Loosen Pipfile restriction on some packages and update them [@stumpylog](https://github.com/stumpylog) ([#3972](https://github.com/paperless-ngx/paperless-ngx/pull/3972))
### All App Changes
<details>
<summary>6 changes</summary>
- Fix: handle ASN = 0 on frontend cards [@shamoon](https://github.com/shamoon) ([#3988](https://github.com/paperless-ngx/paperless-ngx/pull/3988))
- Fix: improve light color filled primary button text legibility [@shamoon](https://github.com/shamoon) ([#3980](https://github.com/paperless-ngx/paperless-ngx/pull/3980))
- Fix / Enhancement: restrict status messages by owner if set \& improve 404 page [@shamoon](https://github.com/shamoon) ([#3959](https://github.com/paperless-ngx/paperless-ngx/pull/3959))
- Fix: handle very old date strings in correspondent list [@shamoon](https://github.com/shamoon) ([#3953](https://github.com/paperless-ngx/paperless-ngx/pull/3953))
- Chore: Reduces the 2 mail tests flakiness [@stumpylog](https://github.com/stumpylog) ([#3949](https://github.com/paperless-ngx/paperless-ngx/pull/3949))
- Feature: Add Ukrainian translation [@shamoon](https://github.com/shamoon) ([#3941](https://github.com/paperless-ngx/paperless-ngx/pull/3941))
</details>
## paperless-ngx 1.17.0
### Features
@@ -1984,7 +2079,7 @@ This is a maintenance release.
The changed to the full text searching require you to reindex your
documents. _The docker image does this automatically, you don't need to
do anything._ To do this, execute the `document_index reindex`
management command (see [Managing the document search index](/administration#index)).
management command (see [Managing the document search index](administration.md#index)).
### paperless-ng 1.3.2
@@ -2023,7 +2118,7 @@ This release contains new database migrations.
- Changes
- The REST API is versioned from this point onwards. This will
allow me to make changes without breaking existing clients. See
the documentation about [API versioning](/api#api-versioning) for details.
the documentation about [API versioning](api.md#api-versioning) for details.
- Added a color picker for tag colors.
- Added the ability to use the filter for searching the document
content as well.
@@ -2057,7 +2152,7 @@ This release contains new database migrations.
- Changes to the OCRmyPDF integration
- Added support for deskewing and automatic rotation of
incorrectly rotated pages. This is enabled by default, see
[OCR settings](/configuration#ocr).
[OCR settings](configuration.md#ocr).
- Better support for encrypted files.
- Better support for various other PDF files: Paperless will now
attempt to force OCR with safe options when OCR fails with the
@@ -2084,7 +2179,7 @@ This release contains new database migrations.
- Added a docker-specific configuration option to adjust the number of
worker processes of the web server. See
[Docker options](/configuration#docker).
[Docker options](configuration.md#docker).
- Some more memory usage optimizations.
- Don't show inbox statistics if no inbox tag is defined.
@@ -2093,7 +2188,7 @@ This release contains new database migrations.
- Always show top left corner of thumbnails, even for extra wide
documents.
- Added a management command for executing the sanity checker
directly. See [management utilities](/administration#sanity-checker).
directly. See [management utilities](administration.md#sanity-checker).
- The weekly sanity check now reports messages in the log files.
- Fixed an issue with the metadata tab not reporting anything in case
of missing files.
@@ -2127,7 +2222,7 @@ This release contains new database migrations.
management commands, since these also ensure that they're always
executed as the paperless user and you're less likely to run into
permission issues. See
[management commands](/administration#management-commands).
[management commands](administration.md#management-commands).
### paperless-ng 1.1.0
@@ -2169,7 +2264,7 @@ This release contains new database migrations.
status notifications.
Apache `mod_wsgi` users, see
[this note](/faq#how-do-i-get-websocket-support-with-apache-mod_wsgi).
[this note](faq.md#how-do-i-get-websocket-support-with-apache-mod_wsgi).
- Paperless now offers suggestions for tags, correspondents and types
on the document detail page.
@@ -2214,7 +2309,7 @@ bug reports coming in, I think that this is reasonably stable.
- The document exporter locks the media directory and the database
during execution to ensure that the resulting export is
consistent.
- See the [updated documentation](/administration#exporter) for more details.
- See the [updated documentation](administration.md#exporter) for more details.
- Other changes and additions
- Added a language selector to the settings.
- Added date format options to the settings.
@@ -2303,7 +2398,7 @@ paperless.
- Thanks to [Jo Vandeginste](https://github.com/jovandeginste),
Paperless has optional support for Office documents such as .docx,
.doc, .odt and more.
- See the [Tika settings](/configuration#tika) on how to enable this
- See the [Tika settings](configuration.md#tika) on how to enable this
feature. This feature requires two additional services (one for
parsing Office documents and metadata extraction and another for
converting Office documents to PDF), and is therefore not enabled
@@ -2390,7 +2485,7 @@ paperless.
However, this change is not retroactive: If you used the delete method
of the bulk editor, you need to reindex your search index by
[running the management command `document_index` with the argument `reindex`](/administration#index).
[running the management command `document_index` with the argument `reindex`](administration.md#index).
### paperless-ng 0.9.9
@@ -2547,13 +2642,13 @@ primarily.
edit page. If available, a dropdown menu will appear next to the
download button.
- Many of the configuration options regarding OCR have changed.
See [OCR settings](/configuration#ocr) for details.
See [OCR settings](configuration.md#ocr) for details.
- Paperless no longer guesses the language of your documents. It
always uses the language that you specified with
`PAPERLESS_OCR_LANGUAGE`. Be sure to set this to the language
the majority of your documents are in. Multiple languages can be
specified, but that requires more CPU time.
- The management command [`document_archiver`](/administration#archiver)
- The management command [`document_archiver`](administration.md#archiver)
can be used to create archived versions for already existing documents.
- Tags from consumption folder.
- Thanks to [jayme-github](https://github.com/jayme-github),
@@ -2567,7 +2662,7 @@ primarily.
- The endpoint for uploading documents now supports specifying
custom titles, correspondents, tags and types. This can be used
by clients to override the default behavior of paperless. See
[POSTing documents](/api#file-uploads).
[POSTing documents](api.md#file-uploads).
- The document endpoint of API now serves documents in this form:
- correspondents, document types and tags are referenced by
their ID in the fields `correspondent`, `document_type` and
@@ -2601,14 +2696,14 @@ primarily.
- Paperless now supports searching by tags, types and dates and
correspondents. In order to have this applied to your existing
documents, you need to perform a `document_index reindex`
management command (see [document search index](/administration#index))
management command (see [document search index](administration.md#index))
that adds the data to the search index. You only need to do this
once, since the schema of the search index changed. Paperless
keeps the index updated after that whenever something changes.
- Paperless now has spelling corrections ("Did you mean") for
miss-typed queries.
- The documentation contains
[information about the query syntax](/usage#basic-usage_searching).
[information about the query syntax](usage.md#basic-usage_searching).
- Front end:
- Clickable tags, correspondents and types allow quick filtering
for related documents.
@@ -2669,7 +2764,7 @@ primarily.
### paperless-ng 0.9.0
- **Deprecated:** GnuPG. [See this note on the state of GnuPG in paperless-ng.](/administration#encryption)
- **Deprecated:** GnuPG. [See this note on the state of GnuPG in paperless-ng.](administration.md#encryption)
This features will most likely be removed in future versions.
- **Added:** New frontend. Features:
- Single page application: It's much more responsive than the
@@ -2727,7 +2822,7 @@ primarily.
uses PostgreSQL instead of SQLite. Username, database and
password all default to `paperless` if not specified.
- **Modified \[breaking\]:** document_retagger management command
rework. See [Document retagger](/administration#retagger) for
rework. See [Document retagger](administration.md#retagger) for
details. Replaces `document_correspondents` management command.
- **Removed \[breaking\]:** Reminders.
- **Removed:** All customizations made to the django admin pages.
@@ -3196,7 +3291,7 @@ this big change.
wherein Paperless wasn't recognising `.tif` files properly. Thanks
to [ayounggun](https://github.com/ayounggun) for reporting this one
and to [Kusti Skytén](https://github.com/kskyten) for posting the
correct solution in the Github issue.
correct solution in the GitHub issue.
### 0.6.0

View File

@@ -19,7 +19,7 @@ run paperless, these settings have to be defined in different places.
### Redis Broker
`PAPERLESS_REDIS=<url>`
#### [`PAPERLESS_REDIS=<url>`](#PAPERLESS_REDIS) {#PAPERLESS_REDIS}
: This is required for processing scheduled tasks such as email
fetching, index optimization and for training the automatic document
@@ -35,9 +35,15 @@ matcher.
Defaults to `redis://localhost:6379`.
#### [`PAPERLESS_REDIS_PREFIX=<prefix>`](#PAPERLESS_REDIS_PREFIX) {#PAPERLESS_REDIS_PREFIX}
: Prefix to be used in Redis for keys and channels. Useful for sharing one Redis server among multiple Paperless instances.
Defaults to no prefix.
### Database
`PAPERLESS_DBENGINE=<engine_name>`
#### [`PAPERLESS_DBENGINE=<engine_name>`](#PAPERLESS_DBENGINE) {#PAPERLESS_DBENGINE}
: Optional, gives the ability to choose Postgres or MariaDB for
database engine. Available options are `postgresql` and
@@ -47,9 +53,9 @@ database engine. Available options are `postgresql` and
!!! warning
Using MariaDB comes with some caveats. See [MySQL Caveats](/advanced_usage#mysql-caveats).
Using MariaDB comes with some caveats. See [MySQL Caveats](advanced_usage.md#mysql-caveats).
`PAPERLESS_DBHOST=<hostname>`
#### [`PAPERLESS_DBHOST=<hostname>`](#PAPERLESS_DBHOST) {#PAPERLESS_DBHOST}
: By default, sqlite is used as the database backend. This can be
changed here.
@@ -57,31 +63,31 @@ changed here.
Set PAPERLESS_DBHOST and another database will be used instead of
sqlite.
`PAPERLESS_DBPORT=<port>`
#### [`PAPERLESS_DBPORT=<port>`](#PAPERLESS_DBPORT) {#PAPERLESS_DBPORT}
: Adjust port if necessary.
Default is 5432.
`PAPERLESS_DBNAME=<name>`
#### [`PAPERLESS_DBNAME=<name>`](#PAPERLESS_DBNAME) {#PAPERLESS_DBNAME}
: Database name in PostgreSQL or MariaDB.
Defaults to "paperless".
`PAPERLESS_DBUSER=<name>`
#### [`PAPERLESS_DBUSER=<name>`](#PAPERLESS_DBUSER) {#PAPERLESS_DBUSER}
: Database user in PostgreSQL or MariaDB.
Defaults to "paperless".
`PAPERLESS_DBPASS=<password>`
#### [`PAPERLESS_DBPASS=<password>`](#PAPERLESS_DBPASS) {#PAPERLESS_DBPASS}
: Database password for PostgreSQL or MariaDB.
Defaults to "paperless".
`PAPERLESS_DBSSLMODE=<mode>`
#### [`PAPERLESS_DBSSLMODE=<mode>`](#PAPERLESS_DBSSLMODE) {#PAPERLESS_DBSSLMODE}
: SSL mode to use when connecting to PostgreSQL or MariaDB.
@@ -95,7 +101,7 @@ changed here.
Default is `prefer` for PostgreSQL and `PREFERRED` for MariaDB.
`PAPERLESS_DBSSLROOTCERT=<ca-path>`
#### [`PAPERLESS_DBSSLROOTCERT=<ca-path>`](#PAPERLESS_DBSSLROOTCERT) {#PAPERLESS_DBSSLROOTCERT}
: SSL root certificate path
@@ -108,7 +114,7 @@ changed here.
Defaults to unset, using the documented path in the home directory.
`PAPERLESS_DBSSLCERT=<client-cert-path>`
#### [`PAPERLESS_DBSSLCERT=<client-cert-path>`](#PAPERLESS_DBSSLCERT) {#PAPERLESS_DBSSLCERT}
: SSL client certificate path
@@ -122,7 +128,7 @@ changed here.
Defaults to unset, using the documented path in the home directory.
`PAPERLESS_DBSSLKEY=<client-cert-key>`
#### [`PAPERLESS_DBSSLKEY=<client-cert-key>`](#PAPERLESS_DBSSLKEY) {#PAPERLESS_DBSSLKEY}
: SSL client key path
@@ -136,7 +142,7 @@ changed here.
Defaults to unset, using the documented path in the home directory.
`PAPERLESS_DB_TIMEOUT=<int>`
#### [`PAPERLESS_DB_TIMEOUT=<int>`](#PAPERLESS_DB_TIMEOUT) {#PAPERLESS_DB_TIMEOUT}
: Amount of time for a database connection to wait for the database to
unlock. Mostly applicable for sqlite based installation. Consider changing
@@ -156,19 +162,19 @@ Tika and Gotenberg are also needed to allow parsing of E-Mails (.eml).
If you wish to use this, you must provide a Tika server and a Gotenberg server,
configure their endpoints, and enable the feature.
`PAPERLESS_TIKA_ENABLED=<bool>`
#### [`PAPERLESS_TIKA_ENABLED=<bool>`](#PAPERLESS_TIKA_ENABLED) {#PAPERLESS_TIKA_ENABLED}
: Enable (or disable) the Tika parser.
Defaults to false.
`PAPERLESS_TIKA_ENDPOINT=<url>`
#### [`PAPERLESS_TIKA_ENDPOINT=<url>`](#PAPERLESS_TIKA_ENDPOINT) {#PAPERLESS_TIKA_ENDPOINT}
: Set the endpoint URL were Paperless can reach your Tika server.
Defaults to "<http://localhost:9998>".
`PAPERLESS_TIKA_GOTENBERG_ENDPOINT=<url>`
#### [`PAPERLESS_TIKA_GOTENBERG_ENDPOINT=<url>`](#PAPERLESS_TIKA_GOTENBERG_ENDPOINT) {#PAPERLESS_TIKA_GOTENBERG_ENDPOINT}
: Set the endpoint URL were Paperless can reach your Gotenberg server.
@@ -187,7 +193,7 @@ and watch out for indentation if editing the YAML file.
## Paths and folders
`PAPERLESS_CONSUMPTION_DIR=<path>`
#### [`PAPERLESS_CONSUMPTION_DIR=<path>`](#PAPERLESS_CONSUMPTION_DIR) {#PAPERLESS_CONSUMPTION_DIR}
: This where your documents should go to be consumed. Make sure that
it exists and that the user running the paperless service can
@@ -199,14 +205,14 @@ read/write its contents before you start Paperless.
Defaults to "../consume/", relative to the "src" directory.
`PAPERLESS_DATA_DIR=<path>`
#### [`PAPERLESS_DATA_DIR=<path>`](#PAPERLESS_DATA_DIR) {#PAPERLESS_DATA_DIR}
: This is where paperless stores all its data (search index, SQLite
database, classification model, etc).
Defaults to "../data/", relative to the "src" directory.
`PAPERLESS_TRASH_DIR=<path>`
#### [`PAPERLESS_TRASH_DIR=<path>`](#PAPERLESS_TRASH_DIR) {#PAPERLESS_TRASH_DIR}
: Instead of removing deleted documents, they are moved to this
directory.
@@ -217,7 +223,7 @@ directory.
Defaults to empty (i.e. really delete documents).
`PAPERLESS_MEDIA_ROOT=<path>`
#### [`PAPERLESS_MEDIA_ROOT=<path>`](#PAPERLESS_MEDIA_ROOT) {#PAPERLESS_MEDIA_ROOT}
: This is where your documents and thumbnails are stored.
@@ -226,7 +232,7 @@ directory.
Defaults to "../media/", relative to the "src" directory.
`PAPERLESS_STATICDIR=<path>`
#### [`PAPERLESS_STATICDIR=<path>`](#PAPERLESS_STATICDIR) {#PAPERLESS_STATICDIR}
: Override the default STATIC_ROOT here. This is where all static
files created using "collectstatic" manager command are stored.
@@ -237,30 +243,30 @@ files created using "collectstatic" manager command are stored.
Defaults to "../static/", relative to the "src" directory.
`PAPERLESS_FILENAME_FORMAT=<format>`
#### [`PAPERLESS_FILENAME_FORMAT=<format>`](#PAPERLESS_FILENAME_FORMAT) {#PAPERLESS_FILENAME_FORMAT}
: Changes the filenames paperless uses to store documents in the media
directory. See [File name handling](/advanced_usage#file-name-handling) for details.
directory. See [File name handling](advanced_usage.md#file-name-handling) for details.
Default is none, which disables this feature.
`PAPERLESS_FILENAME_FORMAT_REMOVE_NONE=<bool>`
#### [`PAPERLESS_FILENAME_FORMAT_REMOVE_NONE=<bool>`](#PAPERLESS_FILENAME_FORMAT_REMOVE_NONE) {#PAPERLESS_FILENAME_FORMAT_REMOVE_NONE}
: Tells paperless to replace placeholders in
`PAPERLESS_FILENAME_FORMAT` that would resolve to
'none' to be omitted from the resulting filename. This also holds
true for directory names. See [File name handling](/advanced_usage#file-name-handling) for
true for directory names. See [File name handling](advanced_usage.md#file-name-handling) for
details.
Defaults to `false` which disables this feature.
`PAPERLESS_LOGGING_DIR=<path>`
#### [`PAPERLESS_LOGGING_DIR=<path>`](#PAPERLESS_LOGGING_DIR) {#PAPERLESS_LOGGING_DIR}
: This is where paperless will store log files.
Defaults to `PAPERLESS_DATA_DIR/log/`.
`PAPERLESS_NLTK_DIR=<path>`
#### [`PAPERLESS_NLTK_DIR=<path>`](#PAPERLESS_NLTK_DIR) {#PAPERLESS_NLTK_DIR}
: This is where paperless will search for the data required for NLTK
processing, if you are using it. If you are using the Docker image,
@@ -275,13 +281,13 @@ Defaults to `/usr/share/nltk_data`
## Logging
`PAPERLESS_LOGROTATE_MAX_SIZE=<num>`
#### [`PAPERLESS_LOGROTATE_MAX_SIZE=<num>`](#PAPERLESS_LOGROTATE_MAX_SIZE) {#PAPERLESS_LOGROTATE_MAX_SIZE}
: Maximum file size for log files before they are rotated, in bytes.
Defaults to 1 MiB.
`PAPERLESS_LOGROTATE_MAX_BACKUPS=<num>`
#### [`PAPERLESS_LOGROTATE_MAX_BACKUPS=<num>`](#PAPERLESS_LOGROTATE_MAX_BACKUPS) {#PAPERLESS_LOGROTATE_MAX_BACKUPS}
: Number of rotated log files to keep.
@@ -289,7 +295,7 @@ Defaults to `/usr/share/nltk_data`
## Hosting & Security {#hosting-and-security}
`PAPERLESS_SECRET_KEY=<key>`
#### [`PAPERLESS_SECRET_KEY=<key>`](#PAPERLESS_SECRET_KEY) {#PAPERLESS_SECRET_KEY}
: Paperless uses this to make session tokens. If you expose paperless
on the internet, you need to change this, since the default secret
@@ -300,7 +306,7 @@ is well known.
Default is listed in the file `src/paperless/settings.py`.
`PAPERLESS_URL=<url>`
#### [`PAPERLESS_URL=<url>`](#PAPERLESS_URL) {#PAPERLESS_URL}
: This setting can be used to set the three options below
(ALLOWED_HOSTS, CORS_ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS). If the
@@ -314,7 +320,7 @@ not include a trailing slash. E.g. <https://paperless.domain.com>
This value cannot contain a path (e.g. domain.com/path), even if
you are installing paperless-ngx at a subpath.
`PAPERLESS_CSRF_TRUSTED_ORIGINS=<comma-separated-list>`
#### [`PAPERLESS_CSRF_TRUSTED_ORIGINS=<comma-separated-list>`](#PAPERLESS_CSRF_TRUSTED_ORIGINS) {#PAPERLESS_CSRF_TRUSTED_ORIGINS}
: A list of trusted origins for unsafe requests (e.g. POST). As of
Django 4.0 this is required to access the Django admin via the web.
@@ -325,7 +331,7 @@ See the [Django project documentation on the settings](https://docs.djangoprojec
Defaults to empty string, which does not add any origins to the
trusted list.
`PAPERLESS_ALLOWED_HOSTS=<comma-separated-list>`
#### [`PAPERLESS_ALLOWED_HOSTS=<comma-separated-list>`](#PAPERLESS_ALLOWED_HOSTS) {#PAPERLESS_ALLOWED_HOSTS}
: If you're planning on putting Paperless on the open internet, then
you really should set this value to the domain name you're using.
@@ -342,7 +348,7 @@ You can read more about this in [the Django project's documentation](https://doc
Defaults to "\*", which is all hosts.
`PAPERLESS_CORS_ALLOWED_HOSTS=<comma-separated-list>`
#### [`PAPERLESS_CORS_ALLOWED_HOSTS=<comma-separated-list>`](#PAPERLESS_CORS_ALLOWED_HOSTS) {#PAPERLESS_CORS_ALLOWED_HOSTS}
: You need to add your servers to the list of allowed hosts that can
do CORS calls. Set this to your public domain name.
@@ -351,7 +357,7 @@ do CORS calls. Set this to your public domain name.
Defaults to "<http://localhost:8000>".
`PAPERLESS_TRUSTED_PROXIES=<comma-separated-list>`
#### [`PAPERLESS_TRUSTED_PROXIES=<comma-separated-list>`](#PAPERLESS_TRUSTED_PROXIES) {#PAPERLESS_TRUSTED_PROXIES}
: This may be needed to prevent IP address spoofing if you are using e.g.
fail2ban with log entries for failed authorization attempts. Value should be
@@ -359,14 +365,14 @@ IP address(es).
Defaults to empty string.
`PAPERLESS_FORCE_SCRIPT_NAME=<path>`
#### [`PAPERLESS_FORCE_SCRIPT_NAME=<path>`](#PAPERLESS_FORCE_SCRIPT_NAME) {#PAPERLESS_FORCE_SCRIPT_NAME}
: To host paperless under a subpath url like example.com/paperless you
set this value to /paperless. No trailing slash!
Defaults to none, which hosts paperless at "/".
`PAPERLESS_STATIC_URL=<path>`
#### [`PAPERLESS_STATIC_URL=<path>`](#PAPERLESS_STATIC_URL) {#PAPERLESS_STATIC_URL}
: Override the STATIC_URL here. Unless you're hosting Paperless off a
subdomain like /paperless/, you probably don't need to change this.
@@ -380,7 +386,7 @@ If you do change it, be sure to include the trailing slash.
at a subpath e.g. example.com/paperlessngx you will also need to set
`PAPERLESS_FORCE_SCRIPT_NAME` (see above).
`PAPERLESS_AUTO_LOGIN_USERNAME=<username>`
#### [`PAPERLESS_AUTO_LOGIN_USERNAME=<username>`](#PAPERLESS_AUTO_LOGIN_USERNAME) {#PAPERLESS_AUTO_LOGIN_USERNAME}
: Specify a username here so that paperless will automatically perform
login with the selected user.
@@ -392,7 +398,7 @@ login with the selected user.
Defaults to none, which disables this feature.
`PAPERLESS_ADMIN_USER=<username>`
#### [`PAPERLESS_ADMIN_USER=<username>`](#PAPERLESS_ADMIN_USER) {#PAPERLESS_ADMIN_USER}
: If this environment variable is specified, Paperless automatically
creates a superuser with the provided username at start. This is
@@ -408,19 +414,19 @@ or AWS ECS.
it recreate a user that already exists. You can leave this
throughout the lifecycle of the containers.
`PAPERLESS_ADMIN_MAIL=<email>`
#### [`PAPERLESS_ADMIN_MAIL=<email>`](#PAPERLESS_ADMIN_MAIL) {#PAPERLESS_ADMIN_MAIL}
: (Optional) Specify superuser email address. Only used when
PAPERLESS_ADMIN_USER is set.
Defaults to `root@localhost`.
`PAPERLESS_ADMIN_PASSWORD=<password>`
#### [`PAPERLESS_ADMIN_PASSWORD=<password>`](#PAPERLESS_ADMIN_PASSWORD) {#PAPERLESS_ADMIN_PASSWORD}
: Only used when PAPERLESS_ADMIN_USER is set. This will
be the password of the automatically created superuser.
`PAPERLESS_COOKIE_PREFIX=<str>`
#### [`PAPERLESS_COOKIE_PREFIX=<str>`](#PAPERLESS_COOKIE_PREFIX) {#PAPERLESS_COOKIE_PREFIX}
: Specify a prefix that is added to the cookies used by paperless to
identify the currently logged in user. This is useful for when
@@ -430,7 +436,7 @@ you're running two instances of paperless on the same host.
Defaults to `""`, which does not alter the cookie names.
`PAPERLESS_ENABLE_HTTP_REMOTE_USER=<bool>`
#### [`PAPERLESS_ENABLE_HTTP_REMOTE_USER=<bool>`](#PAPERLESS_ENABLE_HTTP_REMOTE_USER) {#PAPERLESS_ENABLE_HTTP_REMOTE_USER}
: Allows authentication via HTTP_REMOTE_USER which is used by some SSO
applications.
@@ -449,7 +455,7 @@ applications.
Defaults to "false" which disables this feature.
`PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME=<str>`
#### [`PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME=<str>`](#PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME) {#PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME}
: If "PAPERLESS_ENABLE_HTTP_REMOTE_USER" is enabled, this
property allows to customize the name of the HTTP header from which
@@ -460,7 +466,7 @@ followed by the normalized actual header name.
Defaults to "HTTP_REMOTE_USER".
`PAPERLESS_LOGOUT_REDIRECT_URL=<str>`
#### [`PAPERLESS_LOGOUT_REDIRECT_URL=<str>`](#PAPERLESS_LOGOUT_REDIRECT_URL) {#PAPERLESS_LOGOUT_REDIRECT_URL}
: URL to redirect the user to after a logout. This can be used
together with PAPERLESS_ENABLE_HTTP_REMOTE_USER to
@@ -468,21 +474,21 @@ redirect the user back to the SSO application's logout page.
Defaults to None, which disables this feature.
`PAPERLESS_USE_X_FORWARD_HOST=<bool>`
#### [`PAPERLESS_USE_X_FORWARD_HOST=<bool>`](#PAPERLESS_USE_X_FORWARD_HOST) {#PAPERLESS_USE_X_FORWARD_HOST}
: Configures the Django setting [USE_X_FORWARDED_HOST](https://docs.djangoproject.com/en/4.2/ref/settings/#use-x-forwarded-host)
which may be needed for hosting behind a proxy.
Defaults to False
`PAPERLESS_USE_X_FORWARD_PORT=<bool>`
#### [`PAPERLESS_USE_X_FORWARD_PORT=<bool>`](#PAPERLESS_USE_X_FORWARD_PORT) {#PAPERLESS_USE_X_FORWARD_PORT}
: Configures the Django setting [USE_X_FORWARDED_PORT](https://docs.djangoproject.com/en/4.2/ref/settings/#use-x-forwarded-port)
which may be needed for hosting behind a proxy.
Defaults to False
`PAPERLESS_PROXY_SSL_HEADER=<json-list>`
#### [`PAPERLESS_PROXY_SSL_HEADER=<json-list>`](#PAPERLESS_PROXY_SSL_HEADER) {#PAPERLESS_PROXY_SSL_HEADER}
: Configures the Django setting [SECURE_PROXY_SSL_HEADER](https://docs.djangoproject.com/en/4.2/ref/settings/#secure-proxy-ssl-header)
which may be needed for hosting behind a proxy. The two values in the list will form the tuple of
@@ -495,6 +501,19 @@ HTTP header/value expected by Django, eg `'["HTTP_X_FORWARDED_PROTO", "https"]'`
Settings this value has security implications. Read the Django documentation
and be sure you understand its usage before setting it.
#### [`PAPERLESS_EMAIL_CERTIFICATE_LOCATION=<path>`](#PAPERLESS_EMAIL_CERTIFICATE_LOCATION) {#PAPERLESS_EMAIL_CERTIFICATE_LOCATION}
: Configures an additional SSL certificate file containing a [certificate](https://docs.python.org/3/library/ssl.html#certificates)
or certificate chain which should be trusted for validating SSL connections against mail providers.
This is for use with self-signed certificates against local IMAP servers.
Defaults to None.
!!! warning
Settings this value has security implications for the security of your email.
Understand what it does and be sure you need to before setting.
## OCR settings {#ocr}
Paperless uses [OCRmyPDF](https://ocrmypdf.readthedocs.io/en/latest/)
@@ -502,7 +521,7 @@ for performing OCR on documents and images. Paperless uses sensible
defaults for most settings, but all of them can be configured to your
needs.
`PAPERLESS_OCR_LANGUAGE=<lang>`
#### [`PAPERLESS_OCR_LANGUAGE=<lang>`](#PAPERLESS_OCR_LANGUAGE) {#PAPERLESS_OCR_LANGUAGE}
: Customize the language that paperless will attempt to use when
parsing documents.
@@ -522,7 +541,7 @@ parsing documents.
If your language contains a '-' such as chi-sim, you must use `chi_sim`.
`PAPERLESS_OCR_MODE=<mode>`
#### [`PAPERLESS_OCR_MODE=<mode>`](#PAPERLESS_OCR_MODE) {#PAPERLESS_OCR_MODE}
: Tell paperless when and how to perform ocr on your documents. Three
modes are available:
@@ -552,7 +571,7 @@ modes are available:
Read more about this in the [OCRmyPDF
documentation](https://ocrmypdf.readthedocs.io/en/latest/advanced.html#when-ocr-is-skipped).
`PAPERLESS_OCR_SKIP_ARCHIVE_FILE=<mode>`
#### [`PAPERLESS_OCR_SKIP_ARCHIVE_FILE=<mode>`](#PAPERLESS_OCR_SKIP_ARCHIVE_FILE) {#PAPERLESS_OCR_SKIP_ARCHIVE_FILE}
: Specify when you would like paperless to skip creating an archived
version of your documents. This is useful if you don't want to have two
@@ -565,7 +584,7 @@ almost-identical versions of your documents in the media folder.
The default is `never`.
`PAPERLESS_OCR_CLEAN=<mode>`
#### [`PAPERLESS_OCR_CLEAN=<mode>`](#PAPERLESS_OCR_CLEAN) {#PAPERLESS_OCR_CLEAN}
: Tells paperless to use `unpaper` to clean any input document before
sending it to tesseract. This uses more resources, but generally
@@ -584,7 +603,7 @@ results in better OCR results. The following modes are available:
`clean-final` and the ocr mode `redo` is configured, `clean` is used
instead.
`PAPERLESS_OCR_DESKEW=<bool>`
#### [`PAPERLESS_OCR_DESKEW=<bool>`](#PAPERLESS_OCR_DESKEW) {#PAPERLESS_OCR_DESKEW}
: Tells paperless to correct skewing (slight rotation of input images
mainly due to improper scanning)
@@ -596,7 +615,7 @@ mainly due to improper scanning)
Deskewing is incompatible with ocr mode `redo`. Deskewing will get
disabled automatically if `redo` is used as the ocr mode.
`PAPERLESS_OCR_ROTATE_PAGES=<bool>`
#### [`PAPERLESS_OCR_ROTATE_PAGES=<bool>`](#PAPERLESS_OCR_ROTATE_PAGES) {#PAPERLESS_OCR_ROTATE_PAGES}
: Tells paperless to correct page rotation (90°, 180° and 270°
rotation).
@@ -607,7 +626,7 @@ rotation).
Defaults to `true`, which enables this feature.
`PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD=<num>`
#### [`PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD=<num>`](#PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD) {#PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD}
: Adjust the threshold for automatic page rotation by
`PAPERLESS_OCR_ROTATE_PAGES`. This is an arbitrary value reported by
@@ -617,7 +636,7 @@ pages being rotated as well.
Defaults to "12".
`PAPERLESS_OCR_OUTPUT_TYPE=<type>`
#### [`PAPERLESS_OCR_OUTPUT_TYPE=<type>`](#PAPERLESS_OCR_OUTPUT_TYPE) {#PAPERLESS_OCR_OUTPUT_TYPE}
: Specify the the type of PDF documents that paperless should produce.
@@ -631,7 +650,7 @@ pages being rotated as well.
If not specified, `pdfa` is used. Remember that paperless also keeps
the original input file as well as the archived version.
`PAPERLESS_OCR_PAGES=<num>`
#### [`PAPERLESS_OCR_PAGES=<num>`](#PAPERLESS_OCR_PAGES) {#PAPERLESS_OCR_PAGES}
: Tells paperless to use only the specified amount of pages for OCR.
Documents with less than the specified amount of pages get OCR'ed
@@ -646,7 +665,7 @@ completely.
Defaults to 0, which disables this feature and always uses all
pages.
`PAPERLESS_OCR_IMAGE_DPI=<num>`
#### [`PAPERLESS_OCR_IMAGE_DPI=<num>`](#PAPERLESS_OCR_IMAGE_DPI) {#PAPERLESS_OCR_IMAGE_DPI}
: Paperless will OCR any images you put into the system and convert
them into PDF documents. This is useful if your scanner produces
@@ -660,7 +679,7 @@ fails, it uses this value as a fallback.
Default is none, which will automatically calculate image DPI so
that the produced PDF documents are A4 sized.
`PAPERLESS_OCR_MAX_IMAGE_PIXELS=<num>`
#### [`PAPERLESS_OCR_MAX_IMAGE_PIXELS=<num>`](#PAPERLESS_OCR_MAX_IMAGE_PIXELS) {#PAPERLESS_OCR_MAX_IMAGE_PIXELS}
: Paperless will raise a warning when OCRing images which are over
this limit and will not OCR images which are more than twice this
@@ -683,7 +702,7 @@ but could result in missing text content.
this value if you are certain your documents are not malicious and
you need the text which was not OCRed
`PAPERLESS_OCR_USER_ARGS=<json>`
#### [`PAPERLESS_OCR_USER_ARGS=<json>`](#PAPERLESS_OCR_USER_ARGS) {#PAPERLESS_OCR_USER_ARGS}
: OCRmyPDF offers many more options. Use this parameter to specify any
additional arguments you wish to pass to OCRmyPDF. Since Paperless
@@ -709,7 +728,7 @@ they use underscores instead of dashes.
## Software tweaks {#software_tweaks}
`PAPERLESS_TASK_WORKERS=<num>`
#### [`PAPERLESS_TASK_WORKERS=<num>`](#PAPERLESS_TASK_WORKERS) {#PAPERLESS_TASK_WORKERS}
: Paperless does multiple things in the background: Maintain the
search index, maintain the automatic matching algorithm, check
@@ -718,7 +737,7 @@ things it will do in parallel.
Defaults to 1
`PAPERLESS_THREADS_PER_WORKER=<num>`
#### [`PAPERLESS_THREADS_PER_WORKER=<num>`](#PAPERLESS_THREADS_PER_WORKER) {#PAPERLESS_THREADS_PER_WORKER}
: Furthermore, paperless uses multiple threads when consuming
documents to speed up OCR. This variable specifies how many pages
@@ -752,13 +771,13 @@ paperless will process in parallel on a single document.
If you only specify PAPERLESS_TASK_WORKERS, paperless will adjust
PAPERLESS_THREADS_PER_WORKER automatically.
`PAPERLESS_WORKER_TIMEOUT=<num>`
#### [`PAPERLESS_WORKER_TIMEOUT=<num>`](#PAPERLESS_WORKER_TIMEOUT) {#PAPERLESS_WORKER_TIMEOUT}
: Machines with few cores or weak ones might not be able to finish OCR
on large documents within the default 1800 seconds. So extending
this timeout may prove to be useful on weak hardware setups.
`PAPERLESS_TIME_ZONE=<timezone>`
#### [`PAPERLESS_TIME_ZONE=<timezone>`](#PAPERLESS_TIME_ZONE) {#PAPERLESS_TIME_ZONE}
: Set the time zone here. See more details on
why and how to set it [in the Django project documentation](https://docs.djangoproject.com/en/4.1/ref/settings/#std:setting-TIME_ZONE)
@@ -766,7 +785,7 @@ for details on how to set it.
Defaults to UTC.
`PAPERLESS_ENABLE_NLTK=<bool>`
#### [`PAPERLESS_ENABLE_NLTK=<bool>`](#PAPERLESS_ENABLE_NLTK) {#PAPERLESS_ENABLE_NLTK}
: Enables or disables the advanced natural language processing
used during automatic classification. If disabled, paperless will
@@ -776,7 +795,7 @@ still perform some basic text pre-processing before matching.
Defaults to 1.
`PAPERLESS_EMAIL_TASK_CRON=<cron expression>`
#### [`PAPERLESS_EMAIL_TASK_CRON=<cron expression>`](#PAPERLESS_EMAIL_TASK_CRON) {#PAPERLESS_EMAIL_TASK_CRON}
: Configures the scheduled email fetching frequency. The value
should be a valid crontab(5) expression describing when to run.
@@ -785,7 +804,7 @@ should be a valid crontab(5) expression describing when to run.
Defaults to `*/10 * * * *` or every ten minutes.
`PAPERLESS_TRAIN_TASK_CRON=<cron expression>`
#### [`PAPERLESS_TRAIN_TASK_CRON=<cron expression>`](#PAPERLESS_TRAIN_TASK_CRON) {#PAPERLESS_TRAIN_TASK_CRON}
: Configures the scheduled automatic classifier training frequency. The value
should be a valid crontab(5) expression describing when to run.
@@ -794,7 +813,7 @@ should be a valid crontab(5) expression describing when to run.
Defaults to `5 */1 * * *` or every hour at 5 minutes past the hour.
`PAPERLESS_INDEX_TASK_CRON=<cron expression>`
#### [`PAPERLESS_INDEX_TASK_CRON=<cron expression>`](#PAPERLESS_INDEX_TASK_CRON) {#PAPERLESS_INDEX_TASK_CRON}
: Configures the scheduled search index update frequency. The value
should be a valid crontab(5) expression describing when to run.
@@ -803,7 +822,7 @@ should be a valid crontab(5) expression describing when to run.
Defaults to `0 0 * * *` or daily at midnight.
`PAPERLESS_SANITY_TASK_CRON=<cron expression>`
#### [`PAPERLESS_SANITY_TASK_CRON=<cron expression>`](#PAPERLESS_SANITY_TASK_CRON) {#PAPERLESS_SANITY_TASK_CRON}
: Configures the scheduled sanity checker frequency.
@@ -811,7 +830,7 @@ should be a valid crontab(5) expression describing when to run.
Defaults to `30 0 * * sun` or Sunday at 30 minutes past midnight.
`PAPERLESS_ENABLE_COMPRESSION=<bool>`
#### [`PAPERLESS_ENABLE_COMPRESSION=<bool>`](#PAPERLESS_ENABLE_COMPRESSION) {#PAPERLESS_ENABLE_COMPRESSION}
: Enables compression of the responses from the webserver.
@@ -823,7 +842,7 @@ should be a valid crontab(5) expression describing when to run.
to enable compression in your proxy configuration rather than
the webserver
`PAPERLESS_CONVERT_MEMORY_LIMIT=<num>`
#### [`PAPERLESS_CONVERT_MEMORY_LIMIT=<num>`](#PAPERLESS_CONVERT_MEMORY_LIMIT) {#PAPERLESS_CONVERT_MEMORY_LIMIT}
: On smaller systems, or even in the case of Very Large Documents, the
consumer may explode, complaining about how it's "unable to extend
@@ -836,7 +855,7 @@ everything without writing to disk, and units are in megabytes.
Defaults to 0, which disables the limit.
`PAPERLESS_CONVERT_TMPDIR=<path>`
#### [`PAPERLESS_CONVERT_TMPDIR=<path>`](#PAPERLESS_CONVERT_TMPDIR) {#PAPERLESS_CONVERT_TMPDIR}
: Similar to the memory limit, if you've got a small system and your
OS mounts /tmp as tmpfs, you should set this to a path that's on a
@@ -851,14 +870,14 @@ documents.
## Document Consumption {#consume_config}
`PAPERLESS_CONSUMER_DELETE_DUPLICATES=<bool>`
#### [`PAPERLESS_CONSUMER_DELETE_DUPLICATES=<bool>`](#PAPERLESS_CONSUMER_DELETE_DUPLICATES) {#PAPERLESS_CONSUMER_DELETE_DUPLICATES}
: When the consumer detects a duplicate document, it will not touch
the original document. This default behavior can be changed here.
Defaults to false.
`PAPERLESS_CONSUMER_RECURSIVE=<bool>`
#### [`PAPERLESS_CONSUMER_RECURSIVE=<bool>`](#PAPERLESS_CONSUMER_RECURSIVE) {#PAPERLESS_CONSUMER_RECURSIVE}
: Enable recursive watching of the consumption directory. Paperless
will then pickup files from files in subdirectories within your
@@ -866,7 +885,7 @@ consumption directory as well.
Defaults to false.
`PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=<bool>`
#### [`PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=<bool>`](#PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS) {#PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS}
: Set the names of subdirectories as tags for consumed files. E.g.
`<CONSUMPTION_DIR>/foo/bar/file.pdf` will add the tags "foo" and
@@ -880,7 +899,7 @@ don't exist yet.
Defaults to false.
`PAPERLESS_CONSUMER_IGNORE_PATTERNS=<json>`
#### [`PAPERLESS_CONSUMER_IGNORE_PATTERNS=<json>`](#PAPERLESS_CONSUMER_IGNORE_PATTERNS) {#PAPERLESS_CONSUMER_IGNORE_PATTERNS}
: By default, paperless ignores certain files and folders in the
consumption directory, such as system files created by the Mac OS
@@ -898,7 +917,7 @@ or hidden folders some tools use to store data.
Defaults to
`[".DS_STORE/*", "._*", ".stfolder/*", ".stversions/*", ".localized/*", "desktop.ini", "@eaDir/*"]`.
`PAPERLESS_CONSUMER_BARCODE_SCANNER=<string>`
#### [`PAPERLESS_CONSUMER_BARCODE_SCANNER=<string>`](#PAPERLESS_CONSUMER_BARCODE_SCANNER) {#PAPERLESS_CONSUMER_BARCODE_SCANNER}
: Sets the barcode scanner used for barcode functionality.
@@ -908,27 +927,27 @@ or hidden folders some tools use to store data.
zxing is not available on all platforms.
`PAPERLESS_PRE_CONSUME_SCRIPT=<filename>`
#### [`PAPERLESS_PRE_CONSUME_SCRIPT=<filename>`](#PAPERLESS_PRE_CONSUME_SCRIPT) {#PAPERLESS_PRE_CONSUME_SCRIPT}
: After some initial validation, Paperless can trigger an arbitrary
script if you like before beginning consumption. This script will be provided
data for it to work with via the environment.
For more information, take a look at [pre-consumption script](/advanced_usage#pre-consume-script).
For more information, take a look at [pre-consumption script](advanced_usage.md#pre-consume-script).
The default is blank, which means nothing will be executed.
`PAPERLESS_POST_CONSUME_SCRIPT=<filename>`
#### [`PAPERLESS_POST_CONSUME_SCRIPT=<filename>`](#PAPERLESS_POST_CONSUME_SCRIPT) {#PAPERLESS_POST_CONSUME_SCRIPT}
: After a document is consumed, Paperless can trigger an arbitrary
script if you like. This script will be provided
data for it to work with via the environment.
For more information, take a look at [Post-consumption script](/advanced_usage#post-consume-script).
For more information, take a look at [Post-consumption script](advanced_usage.md#post-consume-script).
The default is blank, which means nothing will be executed.
`PAPERLESS_FILENAME_DATE_ORDER=<format>`
#### [`PAPERLESS_FILENAME_DATE_ORDER=<format>`](#PAPERLESS_FILENAME_DATE_ORDER) {#PAPERLESS_FILENAME_DATE_ORDER}
: Paperless will check the document text for document date
information. Use this setting to enable checking the document
@@ -942,7 +961,7 @@ document text will be checked as normal.
Defaults to none, which disables this feature.
`PAPERLESS_NUMBER_OF_SUGGESTED_DATES=<num>`
#### [`PAPERLESS_NUMBER_OF_SUGGESTED_DATES=<num>`](#PAPERLESS_NUMBER_OF_SUGGESTED_DATES) {#PAPERLESS_NUMBER_OF_SUGGESTED_DATES}
: Paperless searches an entire document for dates. The first date
found will be used as the initial value for the created date. When
@@ -957,7 +976,7 @@ setting value.
Defaults to 3. Set to 0 to disable this feature.
`PAPERLESS_THUMBNAIL_FONT_NAME=<filename>`
#### [`PAPERLESS_THUMBNAIL_FONT_NAME=<filename>`](#PAPERLESS_THUMBNAIL_FONT_NAME) {#PAPERLESS_THUMBNAIL_FONT_NAME}
: Paperless creates thumbnails for plain text files by rendering the
content of the file on an image and uses a predefined font for that.
@@ -969,7 +988,7 @@ This font can be changed here.
Defaults to
`/usr/share/fonts/liberation/LiberationSerif-Regular.ttf`.
`PAPERLESS_IGNORE_DATES=<string>`
#### [`PAPERLESS_IGNORE_DATES=<string>`](#PAPERLESS_IGNORE_DATES) {#PAPERLESS_IGNORE_DATES}
: Paperless parses a documents creation date from filename and file
content. You may specify a comma separated list of dates that should
@@ -981,7 +1000,7 @@ unlikely to be the documents creation date.
Defaults to an empty string to not ignore any dates.
`PAPERLESS_DATE_ORDER=<format>`
#### [`PAPERLESS_DATE_ORDER=<format>`](#PAPERLESS_DATE_ORDER) {#PAPERLESS_DATE_ORDER}
: Paperless will try to determine the document creation date from its
contents. Specify the date format Paperless should expect to see
@@ -993,7 +1012,7 @@ within your documents.
### Polling {#polling}
`PAPERLESS_CONSUMER_POLLING=<num>`
#### [`PAPERLESS_CONSUMER_POLLING=<num>`](#PAPERLESS_CONSUMER_POLLING) {#PAPERLESS_CONSUMER_POLLING}
: If paperless won't find documents added to your consume folder, it
might not be able to automatically detect filesystem changes. In
@@ -1005,14 +1024,14 @@ system changes with `inotify`.
Defaults to 0, which disables polling and uses filesystem
notifications.
`PAPERLESS_CONSUMER_POLLING_RETRY_COUNT=<num>`
#### [`PAPERLESS_CONSUMER_POLLING_RETRY_COUNT=<num>`](#PAPERLESS_CONSUMER_POLLING_RETRY_COUNT) {#PAPERLESS_CONSUMER_POLLING_RETRY_COUNT}
: If consumer polling is enabled, sets the number of times paperless
will check for a file to remain unmodified.
Defaults to 5.
`PAPERLESS_CONSUMER_POLLING_DELAY=<num>`
#### [`PAPERLESS_CONSUMER_POLLING_DELAY=<num>`](#PAPERLESS_CONSUMER_POLLING_DELAY) {#PAPERLESS_CONSUMER_POLLING_DELAY}
: If consumer polling is enabled, sets the delay in seconds between
each check (above) paperless will do while waiting for a file to
@@ -1022,7 +1041,7 @@ remain unmodified.
### iNotify {#inotify}
`PAPERLESS_CONSUMER_INOTIFY_DELAY=<num>`
#### [`PAPERLESS_CONSUMER_INOTIFY_DELAY=<num>`](#PAPERLESS_CONSUMER_INOTIFY_DELAY) {#PAPERLESS_CONSUMER_INOTIFY_DELAY}
: Sets the time in seconds the consumer will wait for additional
events from inotify before the consumer will consider a file ready
@@ -1034,7 +1053,7 @@ consumers working on the same file. Configure this to prevent that.
## Barcodes {#barcodes}
`PAPERLESS_CONSUMER_ENABLE_BARCODES=<bool>`
#### [`PAPERLESS_CONSUMER_ENABLE_BARCODES=<bool>`](#PAPERLESS_CONSUMER_ENABLE_BARCODES) {#PAPERLESS_CONSUMER_ENABLE_BARCODES}
: Enables the scanning and page separation based on detected barcodes.
This allows for scanning and adding multiple documents per uploaded
@@ -1049,11 +1068,11 @@ file, which are separated by one or multiple barcode pages.
The original document will be removed and the separated pages will
be saved as pdf.
See additional information in the [advanced usage documentation](/advanced_usage#barcodes)
See additional information in the [advanced usage documentation](advanced_usage.md#barcodes)
Defaults to false.
`PAPERLESS_CONSUMER_BARCODE_TIFF_SUPPORT=<bool>`
#### [`PAPERLESS_CONSUMER_BARCODE_TIFF_SUPPORT=<bool>`](#PAPERLESS_CONSUMER_BARCODE_TIFF_SUPPORT) {#PAPERLESS_CONSUMER_BARCODE_TIFF_SUPPORT}
: Whether TIFF image files should be scanned for barcodes. This will
automatically convert any TIFF image(s) to pdfs for later
@@ -1062,7 +1081,7 @@ PAPERLESS_CONSUMER_ENABLE_BARCODES has been enabled.
Defaults to false.
`PAPERLESS_CONSUMER_BARCODE_STRING=<string>`
#### [`PAPERLESS_CONSUMER_BARCODE_STRING=<string>`](#PAPERLESS_CONSUMER_BARCODE_STRING) {#PAPERLESS_CONSUMER_BARCODE_STRING}
: Defines the string to be detected as a separator barcode. If
paperless is used with the PATCH-T separator pages, users shouldn't
@@ -1070,14 +1089,15 @@ change this.
Defaults to "PATCHT"
`PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE=<bool>`
#### [`PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE=<bool>`](#PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE) {#PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE}
: Enables the detection of barcodes in the scanned document and
setting the ASN (archive serial number) if a properly formatted
barcode is detected.
The barcode must consist of a (configurable) prefix and the ASN
to be set, for instance `ASN00123`.
to be set, for instance `ASN00123`. The content after the prefix
is cleaned of non-numeric characters.
This option is compatible with barcode page separation, since
pages will be split up before reading the ASN.
@@ -1088,14 +1108,14 @@ barcode is detected.
Defaults to false.
`PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX=<string>`
#### [`PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX=<string>`](#PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX) {#PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX}
: Defines the prefix that is used to identify a barcode as an ASN
barcode.
Defaults to "ASN"
`PAPERLESS_CONSUMER_BARCODE_UPSCALE=<float>`
#### [`PAPERLESS_CONSUMER_BARCODE_UPSCALE=<float>`](#PAPERLESS_CONSUMER_BARCODE_UPSCALE) {#PAPERLESS_CONSUMER_BARCODE_UPSCALE}
: Defines the upscale factor used in barcode detection.
Improves the detection of small barcodes, i.e. with a value of 1.5 by
@@ -1106,7 +1126,7 @@ PAPERLESS_CONSUMER_BARCODE_DPI set to a value higher than default.
Defaults to 0.0
`PAPERLESS_CONSUMER_BARCODE_DPI=<int>`
#### [`PAPERLESS_CONSUMER_BARCODE_DPI=<int>`](#PAPERLESS_CONSUMER_BARCODE_DPI) {#PAPERLESS_CONSUMER_BARCODE_DPI}
: During barcode detection every page from a PDF document needs
to be converted to an image. A dpi value can be specified in the
@@ -1116,9 +1136,18 @@ combination with PAPERLESS_CONSUMER_BARCODE_UPSCALE bigger than 1.0.
Defaults to "300"
## Audit Trail
#### [`PAPERLESS_AUDIT_LOG_ENABLED=<bool>`](#PAPERLESS_AUDIT_LOG_ENABLED){#PAPERLESS_AUDIT_LOG_ENABLED}
: Enables an audit trail for documents, document types, correspondents, and tags. Log entries can be viewed in the Django backend only.
!!! warning
Once enabled cannot be disabled
## Collate Double-Sided Documents {#collate}
`PAPERLESS_CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED=<bool>`
#### [`PAPERLESS_CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED=<bool>`](#PAPERLESS_CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED) {#PAPERLESS_CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED}
: Enables automatic collation of two single-sided scans into a double-sided
document.
@@ -1130,11 +1159,11 @@ document.
`PAPERLESS_CONSUMER_RECURSIVE` must be enabled for this to work.
For more information, read the [corresponding section in the advanced
documentation](/advanced_usage#collate).
documentation](advanced_usage.md#collate).
Defaults to false.
`PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_SUBDIR_NAME=<str>`
#### [`PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_SUBDIR_NAME=<str>`](#PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_SUBDIR_NAME) {#PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_SUBDIR_NAME}
: The name of the subdirectory that the collate feature expects documents to
arrive.
@@ -1145,7 +1174,8 @@ arrive.
Defaults to "double-sided".
`PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_TIFF_SUPPORT=<bool>`
#### [`PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_TIFF_SUPPORT=<bool>`](#PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_TIFF_SUPPORT) {#PAPERLESS_CONSUMER_COLLATE_DOUBLE_SIDED_TIFF_SUPPORT}
: Whether TIFF image files should be supported when collating documents.
This will automatically convert any TIFF image(s) to pdfs for later
processing. This only has an effect if
@@ -1163,11 +1193,11 @@ simply typing the name of the program doesn't automatically execute it
(ie. the program isn't in your $PATH), then you'll need to specify
the literal path for that program.
`PAPERLESS_CONVERT_BINARY=<path>`
#### [`PAPERLESS_CONVERT_BINARY=<path>`](#PAPERLESS_CONVERT_BINARY) {#PAPERLESS_CONVERT_BINARY}
: Defaults to "convert".
`PAPERLESS_GS_BINARY=<path>`
#### [`PAPERLESS_GS_BINARY=<path>`](#PAPERLESS_GS_BINARY) {#PAPERLESS_GS_BINARY}
: Defaults to "gs".
@@ -1177,7 +1207,7 @@ These options don't have any effect in `paperless.conf`. These options
adjust the behavior of the docker container. Configure these in
`docker-compose.env`.
`PAPERLESS_WEBSERVER_WORKERS=<num>`
#### [`PAPERLESS_WEBSERVER_WORKERS=<num>`](#PAPERLESS_WEBSERVER_WORKERS) {#PAPERLESS_WEBSERVER_WORKERS}
: The number of worker processes the webserver should spawn. More
worker processes usually result in the front end to load data much
@@ -1187,7 +1217,7 @@ increase RAM usage.
Defaults to 1.
`PAPERLESS_BIND_ADDR=<ip address>`
#### [`PAPERLESS_BIND_ADDR=<ip address>`](#PAPERLESS_BIND_ADDR) {#PAPERLESS_BIND_ADDR}
: The IP address the webserver will listen on inside the container.
There are special setups where you may need to configure this value
@@ -1195,7 +1225,7 @@ to restrict the Ip address or interface the webserver listens on.
Defaults to `[::]`, meaning all interfaces, including IPv6.
`PAPERLESS_PORT=<port>`
#### [`PAPERLESS_PORT=<port>`](#PAPERLESS_PORT) {#PAPERLESS_PORT}
: The port number the webserver will listen on inside the container.
There are special setups where you may need this to avoid collisions
@@ -1208,7 +1238,7 @@ one pod).
Defaults to 8000.
`USERMAP_UID=<uid>`
#### [`USERMAP_UID=<uid>`](#USERMAP_UID) {#USERMAP_UID}
: The ID of the paperless user in the container. Set this to your
actual user ID on the host system, which you can get by executing
@@ -1223,7 +1253,7 @@ actual user ID on the host system, which you can get by executing
Defaults to 1000.
`USERMAP_GID=<gid>`
#### [`USERMAP_GID=<gid>`](#USERMAP_GID) {#USERMAP_GID}
: The ID of the paperless Group in the container. Set this to your
actual group ID on the host system, which you can get by executing
@@ -1238,7 +1268,7 @@ actual group ID on the host system, which you can get by executing
Defaults to 1000.
`PAPERLESS_OCR_LANGUAGES=<list>`
#### [`PAPERLESS_OCR_LANGUAGES=<list>`](#PAPERLESS_OCR_LANGUAGES) {#PAPERLESS_OCR_LANGUAGES}
: Additional OCR languages to install. By default, paperless comes
with English, German, Italian, Spanish and French. If your language
@@ -1263,17 +1293,17 @@ specified as "chi-tra".
Defaults to none, which does not install any additional languages.
`PAPERLESS_ENABLE_FLOWER=<defined>`
#### [`PAPERLESS_ENABLE_FLOWER=<defined>`](#PAPERLESS_ENABLE_FLOWER) {#PAPERLESS_ENABLE_FLOWER}
: If this environment variable is defined, the Celery monitoring tool
[Flower](https://flower.readthedocs.io/en/latest/index.html) will be
started by the container.
You can read more about this in the [advanced documentation](/advanced_usage#celery-monitoring).
You can read more about this in the [advanced documentation](advanced_usage.md#celery-monitoring).
## Update Checking {#update-checking}
`PAPERLESS_ENABLE_UPDATE_CHECK=<bool>`
#### [`PAPERLESS_ENABLE_UPDATE_CHECK=<bool>`](#PAPERLESS_ENABLE_UPDATE_CHECK) {#PAPERLESS_ENABLE_UPDATE_CHECK}
!!! note
@@ -1281,3 +1311,32 @@ started by the container.
v1.9.2. A one-time migration is performed for users who have this
setting set. This setting is always ignored if the corresponding
frontend setting has been set.
## Email sending
Setting an SMTP server for the backend will allow you to 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)
#### [`PAPERLESS_EMAIL_HOST=<str>`](#PAPERLESS_EMAIL_HOST) {#PAPERLESS_EMAIL_HOST}
: Defaults to 'localhost'.
#### [`PAPERLESS_EMAIL_PORT=<int>`](#PAPERLESS_EMAIL_PORT) {#PAPERLESS_EMAIL_PORT}
: Defaults to port 25.
#### [`PAPERLESS_EMAIL_HOST_USER=<str>`](#PAPERLESS_EMAIL_HOST_USER) {#PAPERLESS_EMAIL_HOST_USER}
: Defaults to ''.
#### [`PAPERLESS_EMAIL_HOST_PASSWORD=<str>`](#PAPERLESS_EMAIL_HOST_PASSWORD) {#PAPERLESS_EMAIL_HOST_PASSWORD}
: Defaults to ''.
#### [`PAPERLESS_EMAIL_USE_TLS=<bool>`](#PAPERLESS_EMAIL_USE_TLS) {#PAPERLESS_EMAIL_USE_TLS}
: Defaults to false.
#### [`PAPERLESS_EMAIL_USE_SSL=<bool>`](#PAPERLESS_EMAIL_USE_SSL) {#PAPERLESS_EMAIL_USE_SSL}
: Defaults to false.

View File

@@ -61,7 +61,7 @@ first-time setup.
Every command is executed directly from the root folder of the project unless specified otherwise.
1. Install prerequisites + pipenv as mentioned in
[Bare metal route](/setup#bare_metal).
[Bare metal route](setup.md#bare_metal).
2. Copy `paperless.conf.example` to `paperless.conf` and enable debug
mode within the file via `PAPERLESS_DEBUG=true`.

View File

@@ -12,7 +12,7 @@ open to collaboration in the form of PRs, ideas etc.
## _I'm using docker. Where are my documents?_
**A:** Your documents are stored inside the docker volume
**A:** By default, your documents are stored inside the docker volume
`paperless_media`. Docker manages this volume automatically for you. It
is a persistent storage and will persist as long as you don't
explicitly delete it. The actual location depends on your host operating
@@ -46,8 +46,8 @@ elsewhere. Here are a couple notes about that.
- By default, paperless uses the internal ID of each document as its
filename. This might not be very convenient for export. However, you
can adjust the way files are stored in paperless by
[configuring the filename format](/advanced_usage#file-name-handling).
- [The exporter](/administration#exporter) is
[configuring the filename format](advanced_usage.md#file-name-handling).
- [The exporter](administration.md#exporter) is
another easy way to get your files out of paperless with reasonable
file names.
@@ -78,11 +78,11 @@ has to do much less work to serve the data.
!!! note
You can adjust some of the settings so that paperless uses less
processing power. See [setup](/setup#less-powerful-devices) for details.
processing power. See [setup](setup.md#less-powerful-devices) for details.
## _How do I install paperless-ngx on Raspberry Pi?_
**A:** Docker images are available for armv7 and arm64 hardware, so just
**A:** Docker images are available for arm64 hardware, so just
follow the [docker-compose instructions](https://docs.paperless-ngx.com/setup/#installation). Apart from more required disk
space compared to a bare metal installation, docker comes with close to
zero overhead, even on Raspberry Pi.
@@ -92,6 +92,13 @@ the python requirements do not have precompiled packages for ARM /
ARM64. Installation of these will require additional development
libraries and compilation will take a long time.
!!! note
For ARMv7 (32-bit) systems, paperless may still function, but it could require
modifications to the Dockerfile (if using Docker) or additional
tools for installing bare metal. It is suggested to upgrade to arm64
instead.
## _How do I run this on Unraid?_
**A:** Paperless-ngx is available as [community
@@ -103,10 +110,7 @@ Fahrer](https://github.com/Tooa) created a container template for that.
**A:** I honestly don't know! As for all other devices that might be
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
installs. I'm running paperless on an i3 processor from 2015 or so.
This is also what I use to test new releases with. Apart from that, I
also have a Raspberry Pi, which I occasionally build the image on and
see if it works.
installs.
## _How do I proxy this with NGINX?_

View File

@@ -5,7 +5,7 @@
**Paperless-ngx** is a _community-supported_ open-source document management system that transforms your
physical documents into a searchable online archive so you can keep, well, _less paper_.
[Get started](/setup){ .md-button .md-button--primary .index-callout }
[Get started](setup.md){ .md-button .md-button--primary .index-callout }
[Demo](https://demo.paperless-ngx.com){ .md-button .md-button--secondary target=\_blank }
</div>
@@ -15,103 +15,159 @@ physical documents into a searchable online archive so you can keep, well, _less
</div>
<div class="clear"></div>
## Why This Exists
## Features
Paper is a nightmare. Environmental issues aside, there's no excuse for
it in the 21st century. It takes up space, collects dust, doesn't
support any form of a search feature, indexing is tedious, it's heavy
and prone to damage & loss.
- **Organize and index** your scanned documents with tags, correspondents, types, and more.
- Performs **OCR** on your documents, adding selectable text to image-only 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.
- 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:
- Customizable dashboard with statistics.
- Filtering by tags, correspondents, types, and more.
- Bulk editing of tags, correspondents, types and more.
- Drag-and-drop uploading of documents throughout the app.
- Customizable views can be saved and displayed on the dashboard and / or sidebar.
- Support for custom fields of various data types.
- Shareable public links with optional expiration.
- **Full text search** helps you find what you need:
- Auto completion suggests relevant words from your documents.
- Results are sorted by relevance to your search query.
- Highlighting shows you which parts of the document matched the query.
- Searching for similar documents ("More like this")
- **Email processing**[^1]: import documents from your email accounts:
- Configure multiple accounts and rules for each account.
- After processing, paperless can perform actions on the messages such as marking as read, deleting and more.
- A built-in robust **multi-user permissions** system that supports 'global' permissions as well as per document or object.
- A powerful templating system that gives you more control over the consumption pipeline.
- **Optimized** for multi core systems: Paperless-ngx consumes multiple documents in parallel.
- The integrated sanity checker makes sure that your document archive is in good health.
This software is designed to make "going paperless" easier. No more worrying
about finding stuff again, feed documents right from the post box into
the scanner and then shred them. Perhaps you might find it useful too.
[^1]: Office document and email consumption support is optional and provided by Apache Tika (see [configuration](https://docs.paperless-ngx.com/configuration/#tika))
## Paperless, a history
Paperless is a simple Django application running in two parts: a
_Consumer_ (the thing that does the indexing) and the _Web server_ (the
part that lets you search & download already-indexed documents). If you
want to learn more about its functions keep on reading after the
installation section.
Paperless-ngx is the official successor to the original [Paperless](https://github.com/the-paperless-project/paperless) & [Paperless-ng](https://github.com/jonaswinkler/paperless-ng) projects and is designed to distribute the responsibility of advancing and supporting the project among a team of people. [Consider joining us!](https://github.com/paperless-ngx/paperless-ngx#community-support)
Paperless-ngx is a document management system that transforms your
physical documents into a searchable online archive so you can keep,
well, _less paper_.
Paperless-ngx forked from paperless-ng to continue the great work and
distribute responsibility of supporting and advancing the project among
a team of people.
NG stands for both Angular (the framework used for the Frontend) and
next-gen. Publishing this project under a different name also avoids
confusion between paperless and paperless-ngx.
If you want to learn about what's different in paperless-ngx from
Paperless, check out these resources in the documentation:
- [Some screenshots](#screenshots) of the new UI are available.
- Read [this section](/advanced_usage#automatic-matching) if you want to learn about how paperless automates all
tagging using machine learning.
- Paperless now comes with a [proper email consumer](/usage#usage-email) that's fully tested and production ready.
- Paperless creates searchable PDF/A documents from whatever you put into the consumption directory. This means
that you can select text in image-only documents coming from your scanner.
- See [this note](/administration#encryption) about GnuPG encryption in paperless-ngx.
- Paperless is now integrated with a
[task processing queue](/setup#task_processor) that tells you at a glance when and why something is not working.
- The [changelog](/changelog) contains a detailed list of all changes in paperless-ngx.
Further discussion of the transition between these projects can be found at
[ng#1599](https://github.com/jonaswinkler/paperless-ng/issues/1599) and [ng#1632](https://github.com/jonaswinkler/paperless-ng/issues/1632).
## Screenshots
This is what Paperless-ngx looks like.
Paperless-ngx aims to be as nice to use as it is useful. Check out some screenshots below.
The dashboard shows customizable views on your document and allows
document uploads:
<div class="grid-flipped-left" markdown>
![image](assets/screenshots/dashboard.png)
</div>
<div class="grid-flipped-right" markdown>
The dashboard shows saved views which can be sorted. Documents can be uploaded with the button or dropped anywhere in the application.
</div>
<div class="clear"></div>
[![image](assets/screenshots/dashboard.png)](assets/screenshots/dashboard.png)
The document list provides three different styles to browse your documents.
The document list provides three different styles to scroll through your
documents:
![image](assets/screenshots/documents-table.png){: style="width:32%"}
![image](assets/screenshots/documents-smallcards.png){: style="width:32%"}
![image](assets/screenshots/documents-largecards.png){: style="width:32%"}
[![image](assets/screenshots/documents-table.png)](assets/screenshots/documents-table.png)
<div class="clear"></div>
[![image](assets/screenshots/documents-smallcards.png)](assets/screenshots/documents-smallcards.png)
<div class="grid-left" markdown>
Use the 'slim' sidebar to focus on your docs and minimize the UI.
</div>
<div class="grid-right" markdown>
![image](assets/screenshots/documents-smallcards-slimsidebar.png)
</div>
<div class="clear"></div>
[![image](assets/screenshots/documents-largecards.png)](assets/screenshots/documents-largecards.png)
Of course, Paperless-ngx also supports dark mode:
Paperless-ngx also supports dark mode:
![image](assets/screenshots/documents-smallcards-dark.png)
[![image](assets/screenshots/documents-smallcards-dark.png)](assets/screenshots/documents-smallcards-dark.png)
<div class="clear"></div>
Extensive filtering mechanisms:
<div class="grid-left" markdown>
Quickly find documents with extensive filtering mechanisms.
</div>
<div class="grid-right" markdown>
![image](assets/screenshots/documents-filter.png)
</div>
<div class="clear"></div>
<div class="grid-left" markdown>
And perform bulk edit operations to set tags, correspondents, etc. as well as permissions.
</div>
<div class="grid-right" markdown>
![image](assets/screenshots/bulk-edit.png)
</div>
<div class="clear"></div>
[![image](assets/screenshots/documents-filter.png)](assets/screenshots/documents-filter.png)
Side-by-side editing of documents.
Bulk editing of document tags, correspondents, etc.:
![image](assets/screenshots/editing.png)
[![image](assets/screenshots/bulk-edit.png)](assets/screenshots/bulk-edit.png)
<div class="grid-left" markdown>
Support for custom fields.
Side-by-side editing of documents:
![image](assets/screenshots/custom_field1.png)
[![image](assets/screenshots/editing.png)](assets/screenshots/editing.png)
</div>
<div class="grid-right" markdown>
![image](assets/screenshots/custom_field2.png)
</div>
<div class="clear"></div>
Tag editing. This looks about the same for correspondents and document
types.
<div class="grid-left" markdown>
A robust permissions system with support for 'global' and document / object permissions.
[![image](assets/screenshots/new-tag.png)](assets/screenshots/new-tag.png)
![image](assets/screenshots/permissions_global.png)
Searching provides auto complete and highlights the results.
</div>
<div class="grid-right" markdown>
![image](assets/screenshots/permissions_document.png)
</div>
<div class="clear"></div>
[![image](assets/screenshots/search-preview.png)](assets/screenshots/search-preview.png)
<div class="grid-left" markdown>
Searching provides auto complete and highlights the results.
[![image](assets/screenshots/search-results.png)](assets/screenshots/search-results.png)
![image](assets/screenshots/search-preview.png)
Fancy mail filters!
</div>
<div class="grid-right" markdown>
![image](assets/screenshots/search-results.png)
</div>
<div class="clear"></div>
[![image](assets/screenshots/mail-rules-edited.png)](assets/screenshots/mail-rules-edited.png)
Tag, correspondent, document type and storage path editing.
![image](assets/screenshots/new-tag.png){: style="width:21%; float: left"}
![image](assets/screenshots/new-correspondent.png){: style="width:21%; margin-left: 4%; float: left"}
![image](assets/screenshots/new-document_type.png){: style="width:21%; margin-left: 4%; float: left"}
![image](assets/screenshots/new-storage_path.png){: style="width:21%; margin-left: 4%; float: left"}
<div class="clear"></div>
<div class="grid-half-left" markdown>
Mail rules support various filters and actions for incoming e-mails.
![image](assets/screenshots/mail-rules-edited.png)
</div>
<div class="grid-half-right" markdown>
Consumption templates provide finer control over the document pipeline.
![image](assets/screenshots/consumption_template.png)
</div>
<div class="clear"></div>
<div class="clear"></div>
Mobile devices are supported.
[![image](assets/screenshots/mobile.png)](assets/screenshots/mobile.png)
![image](assets/screenshots/mobile1.png){: style="width:32%"}
![image](assets/screenshots/mobile2.png){: style="width:32%"}
![image](assets/screenshots/mobile3.png){: style="width:32%"}
## Support
@@ -131,7 +187,7 @@ People interested in continuing the work on paperless-ngx are encouraged to reac
### Translation
Paperless-ngx is available in many languages that are coordinated on [Crowdin](https://crwd.in/paperless-ngx). If you want to help out by translating paperless-ngx into your language, please head over to https://crwd.in/paperless-ngx, and thank you!
Paperless-ngx is available in many languages that are coordinated on [Crowdin](https://crwd.in/paperless-ngx). If you want to help out by translating paperless-ngx into your language, please head over to the [Paperless-ngx project at Crowdin](https://crwd.in/paperless-ngx), and thank you!
## Scanners & Software

View File

@@ -30,7 +30,7 @@ steps described in [Docker setup](#docker_hub) automatically.
2. Download and run the installation script:
```shell-session
$ bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)"
$ bash -c "$(curl --location --silent --show-error https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)"
```
!!! note
@@ -124,7 +124,7 @@ steps described in [Docker setup](#docker_hub) automatically.
user in the container. This value (`user_id` below), should be
the same id that `USERMAP_UID` and `USERMAP_GID` are set to in
the next step. See `USERMAP_UID` and `USERMAP_GID`
[here](/configuration#docker).
[here](configuration.md#docker).
Your entry for Paperless should contain something like:
@@ -148,12 +148,12 @@ steps described in [Docker setup](#docker_hub) automatically.
!!! note
You can copy any setting from the file `paperless.conf.example` and
paste it here. Have a look at [configuration](/configuration) to see what's available.
paste it here. Have a look at [configuration](configuration.md) to see what's available.
!!! note
You can utilize Docker secrets for configuration settings by
appending `_FILE` to configuration values. For example `PAPERLESS_DBUSER`
appending `_FILE` to configuration values. For example [`PAPERLESS_DBUSER`](configuration.md#PAPERLESS_DBUSER)
can be set using `PAPERLESS_DBUSER_FILE=/var/run/secrets/password.txt`.
!!! warning
@@ -162,8 +162,8 @@ steps described in [Docker setup](#docker_hub) automatically.
system notifications with `inotify`. When storing the consumption
directory on such a file system, paperless will not pick up new
files with the default configuration. You will need to use
`PAPERLESS_CONSUMER_POLLING`, which will disable inotify. See
[here](/configuration#polling).
[`PAPERLESS_CONSUMER_POLLING`](configuration.md#PAPERLESS_CONSUMER_POLLING), which will disable inotify. See
[here](configuration.md#polling).
6. Run `docker-compose pull`. This will pull the image.
@@ -223,20 +223,8 @@ steps described in [Docker setup](#docker_hub) automatically.
webserver:
build:
context: .
args:
QPDF_VERSION: x.y.x
PIKEPDF_VERSION: x.y.z
PSYCOPG2_VERSION: x.y.z
JBIG2ENC_VERSION: 0.29
```
!!! note
You should match the build argument versions to the version for the
release you have checked out. These are pre-built images with
certain, more updated software. If you want to build these images
your self, that is possible, but beyond the scope of these steps.
4. Follow steps 3 to 8 of [Docker Setup](#docker_hub). When asked to run
`docker-compose pull` to pull the image, do
@@ -255,7 +243,7 @@ supported.
1. Install dependencies. Paperless requires the following packages.
- `python3` 3.8, 3.9
- `python3` - 3.9 - 3.11 are supported
- `python3-pip`
- `python3-dev`
- `default-libmysqlclient-dev` for MariaDB
@@ -342,41 +330,41 @@ supported.
home folder of the user you created before (`/opt/paperless`).
Optional: If you cloned the git repo, you will have to
compile the frontend yourself, see [here](/development#front-end-development)
compile the frontend yourself, see [here](development.md#front-end-development)
and use the `build` step, not `serve`.
6. Configure paperless. See [configuration](/configuration) for details.
6. Configure paperless. See [configuration](configuration.md) for details.
Edit the included `paperless.conf` and adjust the settings to your
needs. Required settings for getting
paperless running are:
- `PAPERLESS_REDIS` should point to your redis server, such as
- [`PAPERLESS_REDIS`](configuration.md#PAPERLESS_REDIS) should point to your redis server, such as
<redis://localhost:6379>.
- `PAPERLESS_DBENGINE` optional, and should be one of `postgres`,
- [`PAPERLESS_DBENGINE`](configuration.md#PAPERLESS_DBENGINE) optional, and should be one of `postgres`,
`mariadb`, or `sqlite`
- `PAPERLESS_DBHOST` should be the hostname on which your
- [`PAPERLESS_DBHOST`](configuration.md#PAPERLESS_DBHOST) should be the hostname on which your
PostgreSQL server is running. Do not configure this to use
SQLite instead. Also configure port, database name, user and
password as necessary.
- `PAPERLESS_CONSUMPTION_DIR` should point to a folder which
- [`PAPERLESS_CONSUMPTION_DIR`](configuration.md#PAPERLESS_CONSUMPTION_DIR) should point to a folder which
paperless should watch for documents. You might want to have
this somewhere else. Likewise, `PAPERLESS_DATA_DIR` and
`PAPERLESS_MEDIA_ROOT` define where paperless stores its data.
this somewhere else. Likewise, [`PAPERLESS_DATA_DIR`](configuration.md#PAPERLESS_DATA_DIR) and
[`PAPERLESS_MEDIA_ROOT`](configuration.md#PAPERLESS_MEDIA_ROOT) define where paperless stores its data.
If you like, you can point both to the same directory.
- `PAPERLESS_SECRET_KEY` should be a random sequence of
- [`PAPERLESS_SECRET_KEY`](configuration.md#PAPERLESS_SECRET_KEY) should be a random sequence of
characters. It's used for authentication. Failure to do so
allows third parties to forge authentication credentials.
- `PAPERLESS_URL` if you are behind a reverse proxy. This should
- [`PAPERLESS_URL`](configuration.md#PAPERLESS_URL) if you are behind a reverse proxy. This should
point to your domain. Please see
[configuration](/configuration) for more
[configuration](configuration.md) for more
information.
Many more adjustments can be made to paperless, especially the OCR
part. The following options are recommended for everyone:
- Set `PAPERLESS_OCR_LANGUAGE` to the language most of your
- Set [`PAPERLESS_OCR_LANGUAGE`](configuration.md#PAPERLESS_OCR_LANGUAGE) to the language most of your
documents are written in.
- Set `PAPERLESS_TIME_ZONE` to your local time zone.
- Set [`PAPERLESS_TIME_ZONE`](configuration.md#PAPERLESS_TIME_ZONE) to your local time zone.
!!! warning
@@ -522,7 +510,7 @@ supported.
not available for most distributions.
15. Optional: If using the NLTK machine learning processing (see
`PAPERLESS_ENABLE_NLTK` in [configuration](/configuration#software_tweaks) for details),
[`PAPERLESS_ENABLE_NLTK`](configuration.md#PAPERLESS_ENABLE_NLTK) for details),
download the NLTK data for the Snowball
Stemmer, Stopwords and Punkt tokenizer to your
`PAPERLESS_DATA_DIR/nltk`. Refer to the [NLTK
@@ -571,7 +559,7 @@ your setup depending on how you installed paperless.
This setup describes how to update an existing paperless Docker
installation. The important things to keep in mind are as follows:
- Read the [changelog](/changelog) and
- Read the [changelog](changelog.md) and
take note of breaking changes.
- You should decide if you want to stick with SQLite or want to
migrate your database to PostgreSQL. See [documentation](#sqlite_to_psql)
@@ -631,7 +619,7 @@ Migration to paperless-ngx is then performed in a few simple steps:
See [Docker setup](#docker_hub) details on
which edits are advised.
6. [Update paperless.](/administration#updating)
6. [Update paperless.](administration.md#updating)
7. In order to find your existing documents with the new search
feature, you need to invoke a one-time operation that will create
@@ -670,23 +658,23 @@ commands as well.
1. Stop and remove the paperless container
2. If using an external database, stop the container
3. Update Redis configuration
a) If `REDIS_URL` is already set, change it to `PAPERLESS_REDIS`
a) If `REDIS_URL` is already set, change it to [`PAPERLESS_REDIS`](configuration.md#PAPERLESS_REDIS)
and continue to step 4.
b) Otherwise, in the `docker-compose.yml` add a new service for
Redis, following [the example compose
files](https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose)
c) Set the environment variable `PAPERLESS_REDIS` so it points to
c) Set the environment variable [`PAPERLESS_REDIS`](configuration.md#PAPERLESS_REDIS) so it points to
the new Redis container
4. Update user mapping
a) If set, change the environment variable `PUID` to `USERMAP_UID`
b) If set, change the environment variable `PGID` to `USERMAP_GID`
5. Update configuration paths
a) Set the environment variable `PAPERLESS_DATA_DIR` to `/config`
a) Set the environment variable [`PAPERLESS_DATA_DIR`](configuration.md#PAPERLESS_DATA_DIR) to `/config`
6. Update media paths
a) Set the environment variable `PAPERLESS_MEDIA_ROOT` to
a) Set the environment variable [`PAPERLESS_MEDIA_ROOT`](configuration.md#PAPERLESS_MEDIA_ROOT) to
`/data/media`
7. Update timezone
a) Set the environment variable `PAPERLESS_TIME_ZONE` to the same
a) Set the environment variable [`PAPERLESS_TIME_ZONE`](configuration.md#PAPERLESS_TIME_ZONE) to the same
value as `TZ`
8. Modify the `image:` to point to
`ghcr.io/paperless-ngx/paperless-ngx:latest` or a specific version
@@ -718,7 +706,7 @@ below use PostgreSQL, but are applicable to MySQL/MariaDB with the
!!! warning
MySQL is case insensitive by default, treating values like "Name" and
"NAME" as identical. See [MySQL caveats](/advanced_usage#mysql-caveats) for details.
"NAME" as identical. See [MySQL caveats](advanced_usage.md#mysql-caveats) for details.
!!! warning
@@ -739,7 +727,7 @@ below use PostgreSQL, but are applicable to MySQL/MariaDB with the
file to `docker-compose.yml`. Remember to adjust the consumption
directory, if necessary.
b) Without docker, configure the database in your `paperless.conf`
file. See [configuration](/configuration) for
file. See [configuration](configuration.md) for
details.
3. Open a shell and initialize the database:
@@ -823,36 +811,36 @@ the Pi and configuring some options in paperless can help improve
performance immensely:
- Stick with SQLite to save some resources.
- Consider setting `PAPERLESS_OCR_PAGES` to 1, so that paperless will
- Consider setting [`PAPERLESS_OCR_PAGES`](configuration.md#PAPERLESS_OCR_PAGES) to 1, so that paperless will
only OCR the first page of your documents. In most cases, this page
contains enough information to be able to find it.
- `PAPERLESS_TASK_WORKERS` and `PAPERLESS_THREADS_PER_WORKER` are
- [`PAPERLESS_TASK_WORKERS`](configuration.md#PAPERLESS_TASK_WORKERS) and [`PAPERLESS_THREADS_PER_WORKER`](configuration.md#PAPERLESS_THREADS_PER_WORKER) are
configured to use all cores. The Raspberry Pi models 3 and up have 4
cores, meaning that paperless will use 2 workers and 2 threads per
worker. This may result in sluggish response times during
consumption, so you might want to lower these settings (example: 2
workers and 1 thread to always have some computing power left for
other tasks).
- Keep `PAPERLESS_OCR_MODE` at its default value `skip` and consider
- Keep [`PAPERLESS_OCR_MODE`](configuration.md#PAPERLESS_OCR_MODE) at its default value `skip` and consider
OCR'ing your documents before feeding them into paperless. Some
scanners are able to do this!
- Set `PAPERLESS_OCR_SKIP_ARCHIVE_FILE` to `with_text` to skip archive
- Set [`PAPERLESS_OCR_SKIP_ARCHIVE_FILE`](configuration.md#PAPERLESS_OCR_SKIP_ARCHIVE_FILE) to `with_text` to skip archive
file generation for already ocr'ed documents, or `always` to skip it
for all documents.
- If you want to perform OCR on the device, consider using
`PAPERLESS_OCR_CLEAN=none`. This will speed up OCR times and use
less memory at the expense of slightly worse OCR results.
- If using docker, consider setting `PAPERLESS_WEBSERVER_WORKERS` to 1. This will save some memory.
- Consider setting `PAPERLESS_ENABLE_NLTK` to false, to disable the
- If using docker, consider setting [`PAPERLESS_WEBSERVER_WORKERS`](configuration.md#PAPERLESS_WEBSERVER_WORKERS) to 1. This will save some memory.
- Consider setting [`PAPERLESS_ENABLE_NLTK`](configuration.md#PAPERLESS_ENABLE_NLTK) to false, to disable the
more advanced language processing, which can take more memory and
processing time.
For details, refer to [configuration](/configuration).
For details, refer to [configuration](configuration.md).
!!! note
Updating the
[automatic matching algorithm](/advanced_usage#automatic-matching) takes quite a bit of time. However, the update mechanism
[automatic matching algorithm](advanced_usage.md#automatic-matching) takes quite a bit of time. However, the update mechanism
checks if your data has changed before doing the heavy lifting. If you
experience the algorithm taking too much cpu time, consider changing the
schedule in the admin interface to daily. You can also manually invoke

View File

@@ -46,8 +46,7 @@ run:
If you notice that the consumer will only pickup files in the
consumption directory at startup, but won't find any other files added
later, you will need to enable filesystem polling with the configuration
option `PAPERLESS_CONSUMER_POLLING`, see
`[here](/configuration#polling).
option [`PAPERLESS_CONSUMER_POLLING`](configuration.md#PAPERLESS_CONSUMER_POLLING).
This will disable listening to filesystem changes with inotify and
paperless will manually check the consumption directory for changes
@@ -145,7 +144,7 @@ The following error occured while consuming document.pdf: [Errno 13] Permission
This happens when paperless does not have permission to delete files
inside the consumption directory. Ensure that `USERMAP_UID` and
`USERMAP_GID` are set to the user id and group id you use on the host
operating system, if these are different from `1000`. See [Docker setup](/setup#docker_hub).
operating system, if these are different from `1000`. See [Docker setup](setup.md#docker_hub).
Also ensure that you are able to read and write to the consumption
directory on the host.
@@ -265,8 +264,8 @@ This probably indicates paperless tried to consume the same file twice.
This can happen for a number of reasons, depending on how documents are
placed into the consume folder. If paperless is using inotify (the
default) to check for documents, try adjusting the
[inotify configuration](/configuration#inotify). If polling is enabled, try adjusting the
[polling configuration](/configuration#polling).
[inotify configuration](configuration.md#inotify). If polling is enabled, try adjusting the
[polling configuration](configuration.md#polling).
## Consumer fails waiting for file to remain unmodified.
@@ -278,7 +277,7 @@ You might find messages like these in your log files:
This indicates paperless timed out while waiting for the file to be
completely written to the consume folder. Adjusting
[polling configuration](/configuration#polling) values should resolve the issue.
[polling configuration](configuration.md#polling) values should resolve the issue.
!!! note
@@ -297,8 +296,8 @@ This indicates paperless was unable to open the file, as the OS reported
the file as still being in use. To prevent a crash, paperless did not
try to consume the file. If paperless is using inotify (the default) to
check for documents, try adjusting the
[inotify configuration](/configuration#inotify). If polling is enabled, try adjusting the
[polling configuration](/configuration#polling).
[inotify configuration](configuration.md#inotify). If polling is enabled, try adjusting the
[polling configuration](configuration.md#polling).
!!! note
@@ -320,7 +319,7 @@ many workers attempting to access the database simultaneously.
Consider changing to the PostgreSQL database if you will be processing
many documents at once often. Otherwise, try tweaking the
`PAPERLESS_DB_TIMEOUT` setting to allow more time for the database to
[`PAPERLESS_DB_TIMEOUT`](configuration.md#PAPERLESS_DB_TIMEOUT) setting to allow more time for the database to
unlock. This may have minor performance implications.
## gunicorn fails to start with "is not a valid port number"
@@ -330,7 +329,7 @@ environment variable named `${serviceName}_PORT`. This is
the same environment variable which is used by Paperless to optionally
change the port gunicorn listens on.
To fix this, set `PAPERLESS_PORT` again to your desired port, or the
To fix this, set [`PAPERLESS_PORT`](configuration.md#PAPERLESS_PORT) again to your desired port, or the
default of 8000.
## Database Warns about unique constraint "documents_tag_name_uniq
@@ -345,3 +344,15 @@ STATEMENT: INSERT INTO "documents_tag" ("owner_id", "name", "match", "matching_
This can happen during heavy consumption when using polling. Paperless will handle it correctly and the file
will still be consumed
## Consumption fails with "Ghostscript PDF/A rendering failed"
Newer versions of OCRmyPDF will fail if it encounters errors during processing.
This is intentional as the output archive file may differ in unexpected or undesired
ways from the original. As the logs indicate, if you encounter this error you can set
`PAPERLESS_OCR_USER_ARGS: '{"continue_on_soft_render_error": true}'` to try to 'force'
processing documents with this issue.
## Platform-Specific Deployment Troubleshooting
A user-maintained wiki page is available to help troubleshoot issues that may arise when trying to deploy Paperless-ngx on specific platforms, for example SELinux. Please see [the wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Platform%E2%80%90Specific-Troubleshooting).

View File

@@ -62,7 +62,7 @@ following operations on your documents:
paperless to create archived versions for digital documents, you can
configure that by configuring
`PAPERLESS_OCR_SKIP_ARCHIVE_FILE=with_text`. Please read the
[relevant section in the documentation](/configuration#ocr).
[relevant section in the documentation](configuration.md#ocr).
!!! note
@@ -103,25 +103,14 @@ Typically, you're looking at an FTP server like
### Web UI Upload
The dashboard has a file drop field to upload documents to paperless.
Simply drag a file onto this field or select a file with the file
dialog. Multiple files are supported.
You can also upload documents on any other page of the web UI by
dragging-and-dropping files into your browser window.
The dashboard has a button to upload documents to paperless or you
can simply drag a file anywhere into the app to initiate the consumption
process.
### Mobile upload {#usage-mobile_upload}
The mobile app over at [https://github.com/qcasey/paperless_share](https://github.com/qcasey/paperless_share)
allows Android users to share any documents with paperless. This can be
combined with any of the mobile scanning apps out there, such as Office
Lens.
Furthermore, there is the [Paperless
App](https://github.com/bauerj/paperless_app) as well, which not only
has document upload, but also document browsing and download features.
Another option is [Paperless Mobile](https://github.com/astubenbord/paperless-mobile), an Android app that supports document upload, scanning, management of labels and more.
Please see [the wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Affiliated-Projects) for a user-maintained list of affiliated projects and
software (e.g. for mobile devices) that is compatible with Paperless-ngx.
### IMAP (Email) {#usage-email}
@@ -145,9 +134,9 @@ These rules perform the following:
5. If documents were consumed from a mail, the rule action is performed
on that mail.
Paperless will completely ignore mails that do not match your filters.
It will also only perform the action on mails that it has consumed
documents from.
Paperless will check all emails only once and completely ignore messages
that do not match your filters. It will also only perform the rule action
on e-mails that it has consumed documents from.
The actions all ensure that the same mail is not consumed twice by
different means. These are as follows:
@@ -208,11 +197,11 @@ different means. These are as follows:
them further.
Paperless is set up to check your mails every 10 minutes. This can be
configured via `PAPERLESS_EMAIL_TASK_CRON` (see [software tweaks](/configuration#software_tweaks))
configured via [`PAPERLESS_EMAIL_TASK_CRON`](configuration.md#PAPERLESS_EMAIL_TASK_CRON)
### REST API
You can also submit a document using the REST API, see [POSTing documents](/api#file-uploads)
You can also submit a document using the REST API, see [POSTing documents](api.md#file-uploads)
for details.
## Permissions
@@ -247,6 +236,13 @@ do not have an owner set.
Note that superusers have access to all objects.
### Default permissions
Default permissions for documents can be set using consumption templates.
For objects created via the web UI (tags, doc types, etc.) the default is to set the current user
as owner and no extra permissions, but you explicitly set these under Settings > Permissions.
### Users and Groups
Paperless-ngx versions after 1.14.0 allow creating and editing users and groups via the 'frontend' UI.
@@ -254,6 +250,112 @@ These can be found under Settings > Users & Groups, assuming the user has access
as a member of a group those permissions will be inherited and this is reflected in the UI. Explicit
permissions can be granted to limit access to certain parts of the UI (and corresponding API endpoints).
### Password reset
In order to enable the password reset feature you will need to setup an SMTP backend, see
[`PAPERLESS_EMAIL_HOST`](configuration.md#PAPERLESS_EMAIL_HOST)
## Consumption templates
Consumption templates were introduced in v2.0 and allow for finer control over what metadata (tags, doc
types) and permissions (owner, privileges) are assigned to documents during consumption. In general,
templates are applied sequentially (by sort order) but subsequent templates will never override an
assignment from a preceding template. The same is true for mail rules, e.g. if you set the correspondent
in a mail rule any subsequent consumption templates that are applied _will not_ overwrite this. The
exception to this is assignments that can be multiple e.g. tags and permissions, which will be merged.
Consumption templates allow you to filter by:
- 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 path, including wildcards. Note that enabling `PAPERLESS_CONSUMER_RECURSIVE` would allow, for
example, automatically assigning documents to different owners based on the upload directory.
- Mail rule. Choosing this option will force 'mail fetch' to be the template source.
!!! note
You must include a file name filter, a path filter or a mail rule filter. Use * for either to apply
to all files.
Consumption templates can assign:
- Title, see [title placeholders](usage.md#title_placeholders) below
- Tags, correspondent, document types
- Document owner
- View and / or edit permissions to users or groups
### Consumption template permissions
All users who have application permissions for editing consumption templates can see the same set
of templates. In other words, templates themselves intentionally do not have an owner or permissions.
Given their potentially far-reaching capabilities, you may want to restrict access to templates.
Upon migration, existing installs will grant access to consumption templates to users who can add
documents (and superusers who can always access all parts of the app).
### Title placeholders
Consumption template titles can include placeholders, _only for items that are assigned within the template_.
This is because at the time of consumption (when the title is to be set), no automatic tags etc. have been
applied. You can use the following placeholders:
- `{correspondent}`: assigned correspondent name
- `{document_type}`: assigned document type name
- `{owner_username}`: assigned owner username
- `{added}`: added datetime
- `{added_year}`: added year
- `{added_year_short}`: added year
- `{added_month}`: added month
- `{added_month_name}`: added month name
- `{added_month_name_short}`: added month short name
- `{added_day}`: added day
## Custom Fields {#custom-fields}
Paperless-ngx supports the use of custom fields for documents as of v2.0, allowing a user
to optionally attach data to documents which does not fit in the existing set of fields
Paperless-ngx provides.
1. First, create a custom field (under "Manage"), with a given name and data type. This could be something like "Invoice Number" or "Date Paid", with a data type of "Number", "Date", "String", etc.
2. Once created, a field can be used with documents and data stored. To do so, use the "Custom Fields" menu on the document detail page, choose your existing field and click "Add". Once the field is visible in the form you can enter the appropriate
data which will be validated according to the custom field "data type".
3. Fields can be removed by hovering over the field name revealing a "Remove" button.
!!! important
Added / removed fields, as well as any data is not saved to the document until you
actually hit the "Save" button, similar to other changes on the document details page.
!!! note
Once the data type for a field is set, it cannot be changed.
Multiple fields may be attached to a document but the same field name cannot be assigned multiple times to the a single document.
The following custom field types are supported:
- `Text`: any text
- `Boolean`: true / false (check / unchecked) field
- `Date`: date
- `URL`: a valid url
- `Integer`: integer number e.g. 12
- `Number`: float number e.g. 12.3456
- `Monetary`: float number with exactly two decimals, e.g. 12.30
## Share Links
Paperless-ngx added the abiltiy 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.
## Best practices {#basic-searching}
Paperless offers a couple tools that help you organize your document
@@ -462,7 +564,7 @@ Once you have scanned in a document, proceed in paperless as follows.
paperless will assign them automatically. After consuming a couple
documents, you can even ask paperless to *learn* when to assign tags and
correspondents by itself. For details on this feature, see
[advanced matching](/advanced_usage#matching).
[advanced matching](advanced_usage.md#matching).
### Task management

View File

@@ -38,7 +38,6 @@ ask_docker_folder() {
echo "Invalid folder: $result"
fi
done
}
@@ -58,7 +57,7 @@ if ! command -v docker &> /dev/null ; then
fi
DOCKER_COMPOSE_CMD="docker-compose"
if ! command -v ${DOCKER_COMPOSE_CMD} ; then
if ! command -v ${DOCKER_COMPOSE_CMD} &> /dev/null ; then
if docker compose version &> /dev/null ; then
DOCKER_COMPOSE_CMD="docker compose"
else
@@ -321,7 +320,8 @@ fi
wget "https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.$DOCKER_COMPOSE_VERSION.yml" -O docker-compose.yml
wget "https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/.env" -O .env
SECRET_KEY=$(tr --delete --complement 'a-zA-Z0-9' < /dev/urandom 2>/dev/null | head --bytes 64)
SECRET_KEY=$(LC_ALL=C tr -dc 'a-zA-Z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' < /dev/urandom | head --bytes 64)
DEFAULT_LANGUAGES=("deu eng fra ita spa")

View File

@@ -28,6 +28,7 @@ theme:
repo: fontawesome/brands/github
favicon: assets/favicon.png
repo_url: https://github.com/paperless-ngx/paperless-ngx
repo_name: paperless-ngx/paperless-ngx
edit_uri: blob/main/docs/
extra_css:
- assets/extra.css
@@ -42,6 +43,7 @@ markdown_extensions:
- pymdownx.superfences
- pymdownx.inlinehilite
- pymdownx.snippets
- footnotes
strict: true
nav:
- index.md
@@ -64,3 +66,5 @@ extra:
link: https://hub.docker.com/r/paperlessngx/paperless-ngx
- icon: material/chat
link: https://matrix.to/#/#paperless:matrix.org
plugins:
- glightbox

View File

@@ -24,7 +24,7 @@
"error",
{
"type": "attribute",
"prefix": "app",
"prefix": "pngx",
"style": "camelCase"
}
],
@@ -32,7 +32,7 @@
"error",
{
"type": "element",
"prefix": "app",
"prefix": "pngx",
"style": "kebab-case"
}
]

View File

@@ -12,23 +12,28 @@
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"prefix": "pngx",
"i18n": {
"sourceLocale": "en-US",
"locales": {
"ar-AR": "src/locale/messages.ar_AR.xlf",
"af-ZA": "src/locale/messages.af_ZA.xlf",
"bg-BG": "src/locale/messages.bg_BG.xlf",
"be-BY": "src/locale/messages.be_BY.xlf",
"ca-ES": "src/locale/messages.ca_ES.xlf",
"cs-CZ": "src/locale/messages.cs_CZ.xlf",
"da-DK": "src/locale/messages.da_DK.xlf",
"de-DE": "src/locale/messages.de_DE.xlf",
"el-GR": "src/locale/messages.el_GR.xlf",
"en-GB": "src/locale/messages.en_GB.xlf",
"es-ES": "src/locale/messages.es_ES.xlf",
"fi-FI": "src/locale/messages.fi_FI.xlf",
"fr-FR": "src/locale/messages.fr_FR.xlf",
"hu-HU": "src/locale/messages.hu_HU.xlf",
"it-IT": "src/locale/messages.it_IT.xlf",
"lb-LU": "src/locale/messages.lb_LU.xlf",
"nl-NL": "src/locale/messages.nl_NL.xlf",
"no-NO": "src/locale/messages.no_NO.xlf",
"pl-PL": "src/locale/messages.pl_PL.xlf",
"pt-BR": "src/locale/messages.pt_BR.xlf",
"pt-PT": "src/locale/messages.pt_PT.xlf",

View File

@@ -1,24 +1,6 @@
import { test, expect } from '@playwright/test'
const REQUESTS_HAR = 'e2e/settings/requests/api-settings.har'
test('should post settings on save', async ({ page }) => {
await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
await page.goto('/settings')
await page.getByLabel('Use system setting').click()
await page.getByRole('button', { name: 'Save' }).scrollIntoViewIfNeeded()
const updatePromise = page.waitForRequest((request) => {
const data = request.postDataJSON()
const isValid = data['settings'] != null
return (
isValid &&
request.method() === 'POST' &&
request.url().includes('/api/ui_settings/')
)
})
await page.getByRole('button', { name: 'Save' }).click()
await updatePromise
})
const REQUESTS_HAR = 'e2e/admin/requests/api-settings.har'
test('should activate / deactivate save button when settings change', async ({
page,
@@ -46,10 +28,10 @@ test('should warn on unsaved changes', async ({ page }) => {
test('should apply appearance changes when set', async ({ page }) => {
await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
await page.goto('/settings')
await expect(page.locator('body')).toHaveClass(/color-scheme-system/)
await expect(page.locator('html')).toHaveAttribute('data-bs-theme', /auto/)
await page.getByLabel('Use system setting').click()
await page.getByLabel('Enable dark mode').click()
await expect(page.locator('body')).toHaveClass(/color-scheme-dark/)
await expect(page.locator('html')).toHaveAttribute('data-bs-theme', /dark/)
})
test('should toggle saved view options when set & saved', async ({ page }) => {
@@ -72,30 +54,3 @@ test('should toggle saved view options when set & saved', async ({ page }) => {
await page.getByRole('button', { name: 'Save' }).click()
await updatePromise
})
test('should support tab direct navigation', async ({ page }) => {
await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
await page.goto('/settings/general')
await expect(page.getByRole('tab', { name: 'General' })).toHaveAttribute(
'aria-selected',
'true'
)
await page.goto('/settings/notifications')
await expect(
page.getByRole('tab', { name: 'Notifications' })
).toHaveAttribute('aria-selected', 'true')
await page.goto('/settings/savedviews')
await expect(page.getByRole('tab', { name: 'Saved Views' })).toHaveAttribute(
'aria-selected',
'true'
)
await page.goto('/settings/mail')
await expect(page.getByRole('tab', { name: 'Mail' })).toHaveAttribute(
'aria-selected',
'true'
)
await page.goto('/settings/usersgroups')
await expect(
page.getByRole('tab', { name: 'Users & Groups' })
).toHaveAttribute('aria-selected', 'true')
})

View File

@@ -10,7 +10,7 @@ test('dashboard inbox link', async ({ page }) => {
await page.goto('/dashboard')
await page.getByRole('link', { name: 'Documents in inbox' }).click()
await expect(page).toHaveURL(/tags__id__all=9/)
await expect(page.locator('app-document-list')).toHaveText(/8 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/8 documents/)
})
test('dashboard total documents link', async ({ page }) => {
@@ -18,7 +18,7 @@ test('dashboard total documents link', async ({ page }) => {
await page.goto('/dashboard')
await page.getByRole('link').filter({ hasText: 'Total documents' }).click()
await expect(page).toHaveURL(/documents/)
await expect(page.locator('app-document-list')).toHaveText(/61 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/61 documents/)
await page.getByRole('button', { name: 'Reset filters' })
})
@@ -26,19 +26,20 @@ test('dashboard saved view show all', async ({ page }) => {
await page.routeFromHAR(REQUESTS_HAR3, { notFound: 'fallback' })
await page.goto('/dashboard')
await page
.locator('app-widget-frame')
.locator('pngx-widget-frame')
.filter({ hasText: 'Inbox' })
.getByRole('link', { name: 'Show all' })
.first()
.click()
await expect(page).toHaveURL(/view\/7/)
await expect(page.locator('app-document-list')).toHaveText(/8 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/8 documents/)
})
test('dashboard saved view document links', async ({ page }) => {
await page.routeFromHAR(REQUESTS_HAR4, { notFound: 'fallback' })
await page.goto('/dashboard')
await page
.locator('app-widget-frame')
.locator('pngx-widget-frame')
.filter({ hasText: 'Inbox' })
.locator('table')
.getByRole('link', { name: /test/ })

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -8,7 +8,7 @@ test('should activate / deactivate save button when changes are saved', async ({
}) => {
await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
await page.goto('/documents/175/')
await page.waitForSelector('app-document-detail app-input-text:first-child')
await page.waitForSelector('pngx-document-detail pngx-input-text:first-child')
await expect(page.getByTitle('Storage path', { exact: true })).toHaveText(
/\w+/
)
@@ -85,7 +85,7 @@ test('should show a mobile preview', async ({ page }) => {
test('should show a list of notes', async ({ page }) => {
await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
await page.goto('/documents/175/notes')
await expect(page.locator('app-document-notes')).toBeVisible()
await expect(page.locator('pngx-document-notes')).toBeVisible()
await expect(
await page.getByRole('button', {
name: /delete note/i,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -13,33 +13,33 @@ test('basic filtering', async ({ page }) => {
await page.getByRole('button', { name: 'Tags' }).click()
await page.getByRole('menuitem', { name: 'Inbox' }).click()
await expect(page).toHaveURL(/tags__id__all=9/)
await expect(page.locator('app-document-list')).toHaveText(/8 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/8 documents/)
await page.getByRole('button', { name: 'Document type' }).click()
await page.getByRole('menuitem', { name: 'Invoice Test 3' }).click()
await expect(page).toHaveURL(/document_type__id__in=1/)
await expect(page.locator('app-document-list')).toHaveText(/3 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/3 documents/)
await page.getByRole('button', { name: 'Reset filters' }).first().click()
await page.getByRole('button', { name: 'Correspondent' }).click()
await page.getByRole('menuitem', { name: 'Test Correspondent 1' }).click()
await page.getByRole('menuitem', { name: 'Correspondent 9' }).click()
await expect(page).toHaveURL(/correspondent__id__in=12,1/)
await expect(page.locator('app-document-list')).toHaveText(/7 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/7 documents/)
await page
.locator('app-filter-editor')
.locator('pngx-filter-editor')
.getByTitle('Correspondent')
.getByText('Exclude')
.click()
await expect(page).toHaveURL(/correspondent__id__none=12,1/)
await expect(page.locator('app-document-list')).toHaveText(/54 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/54 documents/)
// clear button
await page.getByRole('button', { name: '2 selected', exact: true }).click()
await expect(page.locator('app-document-list')).toHaveText(/61 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/61 documents/)
await page.getByRole('button', { name: 'Storage path' }).click()
await page.getByRole('menuitem', { name: 'Testing 12' }).click()
await expect(page).toHaveURL(/storage_path__id__in=5/)
await expect(page.locator('app-document-list')).toHaveText(/8 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/8 documents/)
await page.getByRole('button', { name: 'Reset filters' }).first().click()
await expect(page.locator('app-document-list')).toHaveText(/61 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/61 documents/)
})
test('text filtering', async ({ page }) => {
@@ -47,35 +47,35 @@ test('text filtering', async ({ page }) => {
await page.goto('/documents')
await page.getByRole('textbox').click()
await page.getByRole('textbox').fill('test')
await expect(page.locator('app-document-list')).toHaveText(/32 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/32 documents/)
await expect(page).toHaveURL(/title_content=test/)
await page.getByRole('button', { name: 'Title & content' }).click()
await page.getByRole('button', { name: 'Title', exact: true }).click()
await expect(page.locator('app-document-list')).toHaveText(/9 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/9 documents/)
await expect(page).toHaveURL(/title__icontains=test/)
await page.getByRole('button', { name: 'Title', exact: true }).click()
await page.getByRole('button', { name: 'Advanced search' }).click()
await expect(page).toHaveURL(/query=test/)
await expect(page.locator('app-document-list')).toHaveText(/26 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/26 documents/)
await page.getByRole('button', { name: 'Advanced search' }).click()
await page.getByRole('button', { name: 'ASN' }).click()
await page.getByRole('textbox').fill('1123')
await expect(page).toHaveURL(/archive_serial_number=1123/)
await expect(page.locator('app-document-list')).toHaveText(/one document/i)
await expect(page.locator('pngx-document-list')).toHaveText(/one document/i)
await page.locator('select').selectOption('greater')
await page.getByRole('textbox').click()
await page.getByRole('textbox').fill('1123')
await expect(page).toHaveURL(/archive_serial_number__gt=1123/)
await expect(page.locator('app-document-list')).toHaveText(/5 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/5 documents/)
await page.locator('select').selectOption('less')
await expect(page).toHaveURL(/archive_serial_number__lt=1123/)
await expect(page.locator('app-document-list')).toHaveText(/0 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/0 documents/)
await page.locator('select').selectOption('is null')
await expect(page).toHaveURL(/archive_serial_number__isnull=1/)
await expect(page.locator('app-document-list')).toHaveText(/55 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/55 documents/)
await page.locator('select').selectOption('not null')
await expect(page).toHaveURL(/archive_serial_number__isnull=0/)
await expect(page.locator('app-document-list')).toHaveText(/6 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/6 documents/)
})
test('date filtering', async ({ page }) => {
@@ -83,7 +83,7 @@ test('date filtering', async ({ page }) => {
await page.goto('/documents')
await page.getByRole('button', { name: 'Created' }).click()
await page.getByRole('menuitem', { name: 'Last 3 months' }).click()
await expect(page.locator('app-document-list')).toHaveText(/one document/i)
await expect(page.locator('pngx-document-list')).toHaveText(/one document/i)
await page.getByRole('button', { name: 'Created Clear selected' }).click()
await page.getByRole('button', { name: 'Created' }).click()
await page
@@ -94,7 +94,7 @@ test('date filtering', async ({ page }) => {
await page.getByRole('combobox', { name: 'Select year' }).selectOption('2022')
await page.getByText('11', { exact: true }).click()
await page.getByRole('button', { name: 'Title & content' }).click()
await expect(page.locator('app-document-list')).toHaveText(/2 documents/)
await expect(page.locator('pngx-document-list')).toHaveText(/2 documents/)
})
test('sorting', async ({ page }) => {
@@ -105,7 +105,7 @@ test('sorting', async ({ page }) => {
await expect(page).toHaveURL(/sort=archive_serial_number/)
await page.getByRole('button', { name: 'Sort' }).click()
await page
.locator('app-page-header')
.locator('pngx-page-header')
.getByRole('button', { name: 'Correspondent' })
.click()
await expect(page).toHaveURL(/sort=correspondent__name/)
@@ -114,7 +114,7 @@ test('sorting', async ({ page }) => {
await expect(page).toHaveURL(/sort=title/)
await page.getByRole('button', { name: 'Sort' }).click()
await page
.locator('app-page-header')
.locator('pngx-page-header')
.getByRole('button', { name: 'Document type' })
.click()
await expect(page).toHaveURL(/sort=document_type__name/)
@@ -138,42 +138,42 @@ test('sorting', async ({ page }) => {
test('change views', async ({ page }) => {
await page.routeFromHAR(REQUESTS_HAR5, { notFound: 'fallback' })
await page.goto('/documents')
await page.locator('app-page-header label').first().click()
await expect(page.locator('app-document-list table')).toBeVisible()
await page.locator('app-page-header label').nth(1).click()
await expect(page.locator('app-document-card-small').first()).toBeAttached()
await page.locator('app-page-header label').nth(2).click()
await expect(page.locator('app-document-card-large').first()).toBeAttached()
await page.locator('pngx-page-header label').first().click()
await expect(page.locator('pngx-document-list table')).toBeVisible()
await page.locator('pngx-page-header label').nth(1).click()
await expect(page.locator('pngx-document-card-small').first()).toBeAttached()
await page.locator('pngx-page-header label').nth(2).click()
await expect(page.locator('pngx-document-card-large').first()).toBeAttached()
})
test('bulk edit', async ({ page }) => {
await page.routeFromHAR(REQUESTS_HAR6, { notFound: 'fallback' })
await page.goto('/documents')
await page.locator('app-document-card-small').nth(0).click()
await page.locator('pngx-document-card-small').nth(0).click()
await page
.locator('app-document-card-small')
.locator('pngx-document-card-small')
.nth(3)
.click({
modifiers: ['Shift'],
})
await expect(page.locator('app-document-list')).toHaveText(
await expect(page.locator('pngx-document-list')).toHaveText(
/Selected 4 of 61 documents/i
)
await page.getByRole('button', { name: 'Page' }).click()
await expect(page.locator('app-document-list')).toHaveText(
await expect(page.locator('pngx-document-list')).toHaveText(
/Selected 50 of 61 documents/i
)
await page.getByRole('button', { name: 'All' }).click()
await expect(page.locator('app-document-list')).toHaveText(
await expect(page.locator('pngx-document-list')).toHaveText(
/Selected 61 of 61 documents/i
)
await page.getByRole('button', { name: 'Cancel' }).click()
await page.locator('app-document-card-small').nth(1).click()
await page.locator('app-document-card-small').nth(2).click()
await page.locator('pngx-document-card-small').nth(1).click()
await page.locator('pngx-document-card-small').nth(2).click()
await page.getByRole('button', { name: 'Tags' }).click()
await page.getByRole('menuitem', { name: 'TagWithPartial' }).click()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -11,4 +11,5 @@ module.exports = {
moduleNameMapper: {
'^src/(.*)': '<rootDir>/src/$1',
},
workerIdleMemoryLimit: '512MB',
}

File diff suppressed because it is too large Load Diff

4578
src-ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,56 +6,59 @@
"start": "ng serve",
"build": "ng build",
"test": "ng test --no-watch --coverage",
"lint": "ng lint"
"lint": "ng lint",
"postinstall": "patch-package"
},
"private": true,
"dependencies": {
"@angular/common": "~16.1.7",
"@angular/compiler": "~16.1.7",
"@angular/core": "~16.1.7",
"@angular/forms": "~16.1.7",
"@angular/localize": "~16.1.7",
"@angular/platform-browser": "~16.1.7",
"@angular/platform-browser-dynamic": "~16.1.7",
"@angular/router": "~16.1.7",
"@ng-bootstrap/ng-bootstrap": "^15.1.0",
"@ng-select/ng-select": "^11.1.1",
"@angular/cdk": "^16.2.11",
"@angular/common": "~16.2.11",
"@angular/compiler": "~16.2.11",
"@angular/core": "~16.2.11",
"@angular/forms": "~16.2.11",
"@angular/localize": "~16.2.11",
"@angular/platform-browser": "~16.2.11",
"@angular/platform-browser-dynamic": "~16.2.11",
"@angular/router": "~16.2.11",
"@ng-bootstrap/ng-bootstrap": "^15.1.2",
"@ng-select/ng-select": "^11.2.0",
"@ngneat/dirty-check-forms": "^3.0.3",
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.1",
"bootstrap": "^5.3.2",
"file-saver": "^2.0.5",
"mime-names": "^1.0.0",
"ng2-pdf-viewer": "^9.1.5",
"ng2-pdf-viewer": "^10.0.0",
"ngx-color": "^9.0.0",
"ngx-cookie-service": "^16.0.0",
"ngx-cookie-service": "^16.0.1",
"ngx-file-drop": "^16.0.0",
"ngx-ui-tour-ng-bootstrap": "^13.0.3",
"ngx-ui-tour-ng-bootstrap": "^13.0.6",
"rxjs": "^7.8.1",
"tslib": "^2.6.1",
"uuid": "^9.0.0",
"zone.js": "^0.13.0"
"tslib": "^2.6.2",
"uuid": "^9.0.1",
"zone.js": "^0.13.3"
},
"devDependencies": {
"@angular-builders/jest": "16.0.0",
"@angular-devkit/build-angular": "~16.1.6",
"@angular-eslint/builder": "16.1.0",
"@angular-eslint/eslint-plugin": "16.1.0",
"@angular-eslint/eslint-plugin-template": "16.1.0",
"@angular-eslint/schematics": "16.1.0",
"@angular-eslint/template-parser": "16.1.0",
"@angular/cli": "~16.1.6",
"@angular/compiler-cli": "~16.1.3",
"@playwright/test": "^1.36.2",
"@types/jest": "^29.5.3",
"@types/node": "^20.4.5",
"@typescript-eslint/eslint-plugin": "^6.2.1",
"@typescript-eslint/parser": "^6.2.1",
"concurrently": "^8.1.0",
"eslint": "^8.46.0",
"jest": "29.6.2",
"jest-environment-jsdom": "^29.6.2",
"@angular-builders/jest": "16.0.1",
"@angular-devkit/build-angular": "~16.2.9",
"@angular-eslint/builder": "16.2.0",
"@angular-eslint/eslint-plugin": "16.2.0",
"@angular-eslint/eslint-plugin-template": "16.2.0",
"@angular-eslint/schematics": "16.2.0",
"@angular-eslint/template-parser": "16.2.0",
"@angular/cli": "~16.2.9",
"@angular/compiler-cli": "~16.2.3",
"@playwright/test": "^1.39.0",
"@types/jest": "^29.5.7",
"@types/node": "^20.8.10",
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1",
"concurrently": "^8.2.2",
"eslint": "^8.52.0",
"jest": "29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-preset-angular": "^13.1.1",
"jest-websocket-mock": "^2.4.0",
"jest-websocket-mock": "^2.5.0",
"patch-package": "^8.0.0",
"ts-node": "~10.9.1",
"typescript": "^5.1.6",
"wait-on": "^7.0.1"

File diff suppressed because one or more lines are too long

View File

@@ -8,19 +8,24 @@ global.TextEncoder = TextEncoder
global.TextDecoder = TextDecoder
import { registerLocaleData } from '@angular/common'
import localeAf from '@angular/common/locales/af'
import localeAr from '@angular/common/locales/ar'
import localeBe from '@angular/common/locales/be'
import localeBg from '@angular/common/locales/bg'
import localeCa from '@angular/common/locales/ca'
import localeCs from '@angular/common/locales/cs'
import localeDa from '@angular/common/locales/da'
import localeDe from '@angular/common/locales/de'
import localeEl from '@angular/common/locales/el'
import localeEnGb from '@angular/common/locales/en-GB'
import localeEs from '@angular/common/locales/es'
import localeFi from '@angular/common/locales/fi'
import localeFr from '@angular/common/locales/fr'
import localeHu from '@angular/common/locales/hu'
import localeIt from '@angular/common/locales/it'
import localeLb from '@angular/common/locales/lb'
import localeNl from '@angular/common/locales/nl'
import localeNo from '@angular/common/locales/no'
import localePl from '@angular/common/locales/pl'
import localePt from '@angular/common/locales/pt'
import localeRo from '@angular/common/locales/ro'
@@ -33,19 +38,24 @@ import localeTr from '@angular/common/locales/tr'
import localeUk from '@angular/common/locales/uk'
import localeZh from '@angular/common/locales/zh'
registerLocaleData(localeAf)
registerLocaleData(localeAr)
registerLocaleData(localeBe)
registerLocaleData(localeBg)
registerLocaleData(localeCa)
registerLocaleData(localeCs)
registerLocaleData(localeDa)
registerLocaleData(localeDe)
registerLocaleData(localeEl)
registerLocaleData(localeEnGb)
registerLocaleData(localeEs)
registerLocaleData(localeFi)
registerLocaleData(localeFr)
registerLocaleData(localeHu)
registerLocaleData(localeIt)
registerLocaleData(localeLb)
registerLocaleData(localeNl)
registerLocaleData(localeNo)
registerLocaleData(localePl)
registerLocaleData(localePt, 'pt-BR')
registerLocaleData(localePt, 'pt-PT')
@@ -75,7 +85,12 @@ Object.defineProperty(window, 'sessionStorage', { value: mock() })
Object.defineProperty(window, 'getComputedStyle', {
value: () => ['-webkit-appearance'],
})
Object.defineProperty(navigator, 'clipboard', {
value: {
writeText: async () => {},
},
})
Object.defineProperty(navigator, 'canShare', { value: () => true })
Object.defineProperty(window, 'ResizeObserver', { value: mock() })
HTMLCanvasElement.prototype.getContext = <

View File

@@ -6,14 +6,14 @@ import { DocumentDetailComponent } from './components/document-detail/document-d
import { DocumentListComponent } from './components/document-list/document-list.component'
import { CorrespondentListComponent } from './components/manage/correspondent-list/correspondent-list.component'
import { DocumentTypeListComponent } from './components/manage/document-type-list/document-type-list.component'
import { LogsComponent } from './components/manage/logs/logs.component'
import { SettingsComponent } from './components/manage/settings/settings.component'
import { LogsComponent } from './components/admin/logs/logs.component'
import { SettingsComponent } from './components/admin/settings/settings.component'
import { TagListComponent } from './components/manage/tag-list/tag-list.component'
import { NotFoundComponent } from './components/not-found/not-found.component'
import { DocumentAsnComponent } from './components/document-asn/document-asn.component'
import { DirtyFormGuard } from './guards/dirty-form.guard'
import { StoragePathListComponent } from './components/manage/storage-path-list/storage-path-list.component'
import { TasksComponent } from './components/manage/tasks/tasks.component'
import { TasksComponent } from './components/admin/tasks/tasks.component'
import { PermissionsGuard } from './guards/permissions.guard'
import { DirtyDocGuard } from './guards/dirty-doc.guard'
import { DirtySavedViewGuard } from './guards/dirty-saved-view.guard'
@@ -21,6 +21,10 @@ import {
PermissionAction,
PermissionType,
} from './services/permissions.service'
import { ConsumptionTemplatesComponent } from './components/manage/consumption-templates/consumption-templates.component'
import { MailComponent } from './components/manage/mail/mail.component'
import { UsersAndGroupsComponent } from './components/admin/users-groups/users-groups.component'
import { CustomFieldsComponent } from './components/manage/custom-fields/custom-fields.component'
export const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
@@ -142,6 +146,15 @@ export const routes: Routes = [
},
},
},
// redirect old paths
{
path: 'settings/mail',
redirectTo: '/mail',
},
{
path: 'settings/usersgroups',
redirectTo: '/usersgroups',
},
{
path: 'settings',
component: SettingsComponent,
@@ -166,11 +179,6 @@ export const routes: Routes = [
},
},
},
{
path: 'settings/:section',
component: SettingsComponent,
canDeactivate: [DirtyFormGuard],
},
{
path: 'tasks',
component: TasksComponent,
@@ -182,7 +190,50 @@ export const routes: Routes = [
},
},
},
{ path: 'tasks', component: TasksComponent },
{
path: 'customfields',
component: CustomFieldsComponent,
canActivate: [PermissionsGuard],
data: {
requiredPermission: {
action: PermissionAction.View,
type: PermissionType.CustomField,
},
},
},
{
path: 'templates',
component: ConsumptionTemplatesComponent,
canActivate: [PermissionsGuard],
data: {
requiredPermission: {
action: PermissionAction.View,
type: PermissionType.ConsumptionTemplate,
},
},
},
{
path: 'mail',
component: MailComponent,
canActivate: [PermissionsGuard],
data: {
requiredPermission: {
action: PermissionAction.View,
type: PermissionType.MailAccount,
},
},
},
{
path: 'usersgroups',
component: UsersAndGroupsComponent,
canActivate: [PermissionsGuard],
data: {
requiredPermission: {
action: PermissionAction.View,
type: PermissionType.User,
},
},
},
],
},

View File

@@ -1,16 +1,10 @@
<app-toasts></app-toasts>
<pngx-toasts></pngx-toasts>
<ngx-file-drop dropZoneClassName="main-dropzone" contentClassName="main-content" [disabled]="!dragDropEnabled"
(onFileDrop)="dropped($event)" (onFileOver)="fileOver()" (onFileLeave)="fileLeave()">
<ng-template ngx-file-drop-content-tmp>
<div class="global-dropzone-overlay fade" [class.show]="fileIsOver" [class.hide]="hidden">
<h2 i18n>Drop files to begin upload</h2>
</div>
<div [class.inert]="fileIsOver">
<router-outlet></router-outlet>
</div>
</ng-template>
</ngx-file-drop>
<pngx-file-drop>
<ng-container content>
<router-outlet></router-outlet>
</ng-container>
</pngx-file-drop>
<tour-step-template>
<ng-template #tourStep let-step="step">

View File

@@ -2,14 +2,11 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'
import {
ComponentFixture,
TestBed,
discardPeriodicTasks,
fakeAsync,
tick,
} from '@angular/core/testing'
import { By } from '@angular/platform-browser'
import { Router } from '@angular/router'
import { RouterTestingModule } from '@angular/router/testing'
import { NgxFileDropModule } from 'ngx-file-drop'
import { TourService, TourNgBootstrapModule } from 'ngx-ui-tour-ng-bootstrap'
import { Subject } from 'rxjs'
import { routes } from './app-routing.module'
@@ -21,8 +18,9 @@ import {
} from './services/consumer-status.service'
import { PermissionsService } from './services/permissions.service'
import { ToastService, Toast } from './services/toast.service'
import { UploadDocumentsService } from './services/upload-documents.service'
import { SettingsService } from './services/settings.service'
import { FileDropComponent } from './components/file-drop/file-drop.component'
import { NgxFileDropModule } from 'ngx-file-drop'
describe('AppComponent', () => {
let component: AppComponent
@@ -33,11 +31,10 @@ describe('AppComponent', () => {
let toastService: ToastService
let router: Router
let settingsService: SettingsService
let uploadDocumentsService: UploadDocumentsService
beforeEach(async () => {
TestBed.configureTestingModule({
declarations: [AppComponent, ToastsComponent],
declarations: [AppComponent, ToastsComponent, FileDropComponent],
providers: [],
imports: [
HttpClientTestingModule,
@@ -53,7 +50,6 @@ describe('AppComponent', () => {
settingsService = TestBed.inject(SettingsService)
toastService = TestBed.inject(ToastService)
router = TestBed.inject(Router)
uploadDocumentsService = TestBed.inject(UploadDocumentsService)
fixture = TestBed.createComponent(AppComponent)
component = fixture.componentInstance
})
@@ -72,6 +68,7 @@ describe('AppComponent', () => {
}))
it('should display toast on document consumed with link if user has access', () => {
const navigateSpy = jest.spyOn(router, 'navigate')
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
let toast: Toast
toastService.getToasts().subscribe((toasts) => (toast = toasts[0]))
@@ -81,9 +78,13 @@ describe('AppComponent', () => {
.spyOn(consumerStatusService, 'onDocumentConsumptionFinished')
.mockReturnValue(fileStatusSubject)
component.ngOnInit()
fileStatusSubject.next(new FileStatus())
const status = new FileStatus()
status.documentId = 1
fileStatusSubject.next(status)
expect(toastSpy).toHaveBeenCalled()
expect(toast.action).not.toBeUndefined()
toast.action()
expect(navigateSpy).toHaveBeenCalledWith(['documents', status.documentId])
})
it('should display toast on document consumed without link if user does not have access', () => {
@@ -138,45 +139,4 @@ describe('AppComponent', () => {
fileStatusSubject.next(new FileStatus())
expect(toastSpy).toHaveBeenCalled()
})
it('should disable drag-drop if on dashboard', () => {
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
jest.spyOn(router, 'url', 'get').mockReturnValueOnce('/dashboard')
expect(component.dragDropEnabled).toBeFalsy()
jest.spyOn(router, 'url', 'get').mockReturnValueOnce('/documents')
expect(component.dragDropEnabled).toBeTruthy()
})
it('should enable drag-drop if user has permissions', () => {
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
expect(component.dragDropEnabled).toBeTruthy()
})
it('should disable drag-drop if user does not have permissions', () => {
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(false)
expect(component.dragDropEnabled).toBeFalsy()
})
it('should support drag drop', fakeAsync(() => {
expect(component.fileIsOver).toBeFalsy()
component.fileOver()
tick(1)
fixture.detectChanges()
expect(component.fileIsOver).toBeTruthy()
const dropzone = fixture.debugElement.query(
By.css('.global-dropzone-overlay')
)
expect(dropzone).not.toBeNull()
component.fileLeave()
tick(700)
fixture.detectChanges()
expect(dropzone.classes['hide']).toBeTruthy()
// drop
const toastSpy = jest.spyOn(toastService, 'show')
const uploadSpy = jest.spyOn(uploadDocumentsService, 'uploadFiles')
component.dropped([])
tick(3000)
expect(toastSpy).toHaveBeenCalled()
expect(uploadSpy).toHaveBeenCalled()
}))
})

View File

@@ -5,8 +5,6 @@ import { Router } from '@angular/router'
import { Subscription, first } from 'rxjs'
import { ConsumerStatusService } from './services/consumer-status.service'
import { ToastService } from './services/toast.service'
import { NgxFileDropEntry } from 'ngx-file-drop'
import { UploadDocumentsService } from './services/upload-documents.service'
import { TasksService } from './services/tasks.service'
import { TourService } from 'ngx-ui-tour-ng-bootstrap'
import {
@@ -16,7 +14,7 @@ import {
} from './services/permissions.service'
@Component({
selector: 'app-root',
selector: 'pngx-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
@@ -25,16 +23,11 @@ export class AppComponent implements OnInit, OnDestroy {
successSubscription: Subscription
failedSubscription: Subscription
private fileLeaveTimeoutID: any
fileIsOver: boolean = false
hidden: boolean = true
constructor(
private settings: SettingsService,
private consumerStatusService: ConsumerStatusService,
private toastService: ToastService,
private router: Router,
private uploadDocumentsService: UploadDocumentsService,
private tasksService: TasksService,
public tourService: TourService,
private renderer: Renderer2,
@@ -87,9 +80,8 @@ export class AppComponent implements OnInit, OnDestroy {
)
) {
this.toastService.show({
title: $localize`Document added`,
content: $localize`Document ${status.filename} was added to Paperless-ngx.`,
delay: 10000,
content: $localize`Document ${status.filename} was added to paperless.`,
actionName: $localize`Open document`,
action: () => {
this.router.navigate(['documents', status.documentId])
@@ -97,9 +89,8 @@ export class AppComponent implements OnInit, OnDestroy {
})
} else {
this.toastService.show({
title: $localize`Document added`,
content: $localize`Document ${status.filename} was added to Paperless-ngx.`,
delay: 10000,
content: $localize`Document ${status.filename} was added to paperless.`,
})
}
}
@@ -128,9 +119,8 @@ export class AppComponent implements OnInit, OnDestroy {
)
) {
this.toastService.show({
title: $localize`New document detected`,
content: $localize`Document ${status.filename} is being processed by Paperless-ngx.`,
delay: 5000,
content: $localize`Document ${status.filename} is being processed by paperless.`,
})
}
})
@@ -179,6 +169,22 @@ export class AppComponent implements OnInit, OnDestroy {
offset: 0,
},
},
{
anchorId: 'tour.mail',
content: $localize`Manage e-mail accounts and rules for automatically importing documents.`,
route: '/mail',
backdropConfig: {
offset: 0,
},
},
{
anchorId: 'tour.consumption-templates',
content: $localize`Consumption templates give you finer control over the document ingestion process.`,
route: '/templates',
backdropConfig: {
offset: 0,
},
},
{
anchorId: 'tour.file-tasks',
content: $localize`File Tasks shows you documents that have been consumed, are waiting to be, or may have failed during the process.`,
@@ -189,7 +195,7 @@ export class AppComponent implements OnInit, OnDestroy {
},
{
anchorId: 'tour.settings',
content: $localize`Check out the settings for various tweaks to the web app, toggle settings for saved views or setup e-mail checking.`,
content: $localize`Check out the settings for various tweaks to the web app and toggle settings for saved views.`,
route: '/settings',
backdropConfig: {
offset: 0,
@@ -234,42 +240,4 @@ export class AppComponent implements OnInit, OnDestroy {
})
})
}
public get dragDropEnabled(): boolean {
return (
!this.router.url.includes('dashboard') &&
this.permissionsService.currentUserCan(
PermissionAction.Add,
PermissionType.Document
)
)
}
public fileOver() {
// allows transition
setTimeout(() => {
this.fileIsOver = true
}, 1)
this.hidden = false
// stop fileLeave timeout
clearTimeout(this.fileLeaveTimeoutID)
}
public fileLeave(immediate: boolean = false) {
const ms = immediate ? 0 : 500
this.fileLeaveTimeoutID = setTimeout(() => {
this.fileIsOver = false
// await transition completed
setTimeout(() => {
this.hidden = true
}, 150)
}, ms)
}
public dropped(files: NgxFileDropEntry[]) {
this.fileLeave(true)
this.uploadDocumentsService.uploadFiles(files)
this.toastService.showInfo($localize`Initiating upload...`, 3000)
}
}

View File

@@ -14,8 +14,8 @@ import { DashboardComponent } from './components/dashboard/dashboard.component'
import { TagListComponent } from './components/manage/tag-list/tag-list.component'
import { DocumentTypeListComponent } from './components/manage/document-type-list/document-type-list.component'
import { CorrespondentListComponent } from './components/manage/correspondent-list/correspondent-list.component'
import { LogsComponent } from './components/manage/logs/logs.component'
import { SettingsComponent } from './components/manage/settings/settings.component'
import { LogsComponent } from './components/admin/logs/logs.component'
import { SettingsComponent } from './components/admin/settings/settings.component'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { DatePipe, registerLocaleData } from '@angular/common'
import { NotFoundComponent } from './components/not-found/not-found.component'
@@ -39,6 +39,7 @@ import { NgxFileDropModule } from 'ngx-file-drop'
import { TextComponent } from './components/common/input/text/text.component'
import { SelectComponent } from './components/common/input/select/select.component'
import { CheckComponent } from './components/common/input/check/check.component'
import { UrlComponent } from './components/common/input/url/url.component'
import { PasswordComponent } from './components/common/input/password/password.component'
import { SaveViewConfigDialogComponent } from './components/document-list/save-view-config-dialog/save-view-config-dialog.component'
import { TagsComponent } from './components/common/input/tags/tags.component'
@@ -77,7 +78,7 @@ import { DirtySavedViewGuard } from './guards/dirty-saved-view.guard'
import { StoragePathListComponent } from './components/manage/storage-path-list/storage-path-list.component'
import { StoragePathEditDialogComponent } from './components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component'
import { SettingsService } from './services/settings.service'
import { TasksComponent } from './components/manage/tasks/tasks.component'
import { TasksComponent } from './components/admin/tasks/tasks.component'
import { TourNgBootstrapModule } from 'ngx-ui-tour-ng-bootstrap'
import { UserEditDialogComponent } from './components/common/edit-dialog/user-edit-dialog/user-edit-dialog.component'
import { GroupEditDialogComponent } from './components/common/edit-dialog/group-edit-dialog/group-edit-dialog.component'
@@ -94,20 +95,35 @@ import { PermissionsFilterDropdownComponent } from './components/common/permissi
import { UsernamePipe } from './pipes/username.pipe'
import { LogoComponent } from './components/common/logo/logo.component'
import { IsNumberPipe } from './pipes/is-number.pipe'
import { ShareLinksDropdownComponent } from './components/common/share-links-dropdown/share-links-dropdown.component'
import { ConsumptionTemplatesComponent } from './components/manage/consumption-templates/consumption-templates.component'
import { ConsumptionTemplateEditDialogComponent } from './components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component'
import { MailComponent } from './components/manage/mail/mail.component'
import { UsersAndGroupsComponent } from './components/admin/users-groups/users-groups.component'
import { DragDropModule } from '@angular/cdk/drag-drop'
import { FileDropComponent } from './components/file-drop/file-drop.component'
import { CustomFieldsComponent } from './components/manage/custom-fields/custom-fields.component'
import { CustomFieldEditDialogComponent } from './components/common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component'
import { CustomFieldsDropdownComponent } from './components/common/custom-fields-dropdown/custom-fields-dropdown.component'
import localeAf from '@angular/common/locales/af'
import localeAr from '@angular/common/locales/ar'
import localeBe from '@angular/common/locales/be'
import localeBg from '@angular/common/locales/bg'
import localeCa from '@angular/common/locales/ca'
import localeCs from '@angular/common/locales/cs'
import localeDa from '@angular/common/locales/da'
import localeDe from '@angular/common/locales/de'
import localeEl from '@angular/common/locales/el'
import localeEnGb from '@angular/common/locales/en-GB'
import localeEs from '@angular/common/locales/es'
import localeFi from '@angular/common/locales/fi'
import localeFr from '@angular/common/locales/fr'
import localeHu from '@angular/common/locales/hu'
import localeIt from '@angular/common/locales/it'
import localeLb from '@angular/common/locales/lb'
import localeNl from '@angular/common/locales/nl'
import localeNo from '@angular/common/locales/no'
import localePl from '@angular/common/locales/pl'
import localePt from '@angular/common/locales/pt'
import localeRo from '@angular/common/locales/ro'
@@ -120,19 +136,24 @@ import localeTr from '@angular/common/locales/tr'
import localeUk from '@angular/common/locales/uk'
import localeZh from '@angular/common/locales/zh'
registerLocaleData(localeAf)
registerLocaleData(localeAr)
registerLocaleData(localeBe)
registerLocaleData(localeBg)
registerLocaleData(localeCa)
registerLocaleData(localeCs)
registerLocaleData(localeDa)
registerLocaleData(localeDe)
registerLocaleData(localeEl)
registerLocaleData(localeEnGb)
registerLocaleData(localeEs)
registerLocaleData(localeFi)
registerLocaleData(localeFr)
registerLocaleData(localeHu)
registerLocaleData(localeIt)
registerLocaleData(localeLb)
registerLocaleData(localeNl)
registerLocaleData(localeNo)
registerLocaleData(localePl)
registerLocaleData(localePt, 'pt-BR')
registerLocaleData(localePt, 'pt-PT')
@@ -185,6 +206,7 @@ function initializeApp(settings: SettingsService) {
TextComponent,
SelectComponent,
CheckComponent,
UrlComponent,
PasswordComponent,
SaveViewConfigDialogComponent,
TagsComponent,
@@ -225,6 +247,15 @@ function initializeApp(settings: SettingsService) {
UsernamePipe,
LogoComponent,
IsNumberPipe,
ShareLinksDropdownComponent,
ConsumptionTemplatesComponent,
ConsumptionTemplateEditDialogComponent,
MailComponent,
UsersAndGroupsComponent,
FileDropComponent,
CustomFieldsComponent,
CustomFieldEditDialogComponent,
CustomFieldsDropdownComponent,
],
imports: [
BrowserModule,
@@ -238,6 +269,7 @@ function initializeApp(settings: SettingsService) {
NgSelectModule,
ColorSliderModule,
TourNgBootstrapModule,
DragDropModule,
],
providers: [
{

View File

@@ -1,17 +1,24 @@
<app-page-header title="Logs" i18n-title>
</app-page-header>
<pngx-page-header title="Logs" i18n-title>
</pngx-page-header>
<ul ngbNav #nav="ngbNav" [(activeId)]="activeLog" (activeIdChange)="reloadLogs()" class="nav-tabs">
<li *ngFor="let logFile of logFiles" [ngbNavItem]="logFile">
<a ngbNavLink>{{logFile}}.log</a>
</li>
<div *ngIf="isLoading && !logFiles.length" class="pb-2">
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
<ng-container i18n>Loading...</ng-container>
</div>
</ul>
<div [ngbNavOutlet]="nav" class="mt-2"></div>
<div class="bg-dark p-3 text-light font-monospace log-container" #logContainer>
<div *ngIf="isLoading && logFiles.length">
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
<ng-container i18n>Loading...</ng-container>
</div>
<p
class="m-0 p-0 log-entry-{{getLogLevel(log)}}"
*ngFor="let log of logs">{{log}}</p>

View File

@@ -0,0 +1,94 @@
import {
Component,
ElementRef,
OnInit,
AfterViewChecked,
ViewChild,
OnDestroy,
} from '@angular/core'
import { Subject, takeUntil } from 'rxjs'
import { LogService } from 'src/app/services/rest/log.service'
@Component({
selector: 'pngx-logs',
templateUrl: './logs.component.html',
styleUrls: ['./logs.component.scss'],
})
export class LogsComponent implements OnInit, AfterViewChecked, OnDestroy {
constructor(private logService: LogService) {}
public logs: string[] = []
public logFiles: string[] = []
public activeLog: string
private unsubscribeNotifier: Subject<any> = new Subject()
public isLoading: boolean = false
@ViewChild('logContainer') logContainer: ElementRef
ngOnInit(): void {
this.isLoading = true
this.logService
.list()
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe((result) => {
this.logFiles = result
this.isLoading = false
if (this.logFiles.length > 0) {
this.activeLog = this.logFiles[0]
this.reloadLogs()
}
})
}
ngAfterViewChecked() {
this.scrollToBottom()
}
ngOnDestroy(): void {
this.unsubscribeNotifier.next(true)
this.unsubscribeNotifier.complete()
}
reloadLogs() {
this.isLoading = true
this.logService
.get(this.activeLog)
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (result) => {
this.logs = result
this.isLoading = false
},
error: () => {
this.logs = []
this.isLoading = false
},
})
}
getLogLevel(log: string) {
if (log.indexOf('[DEBUG]') != -1) {
return 10
} else if (log.indexOf('[WARNING]') != -1) {
return 30
} else if (log.indexOf('[ERROR]') != -1) {
return 40
} else if (log.indexOf('[CRITICAL]') != -1) {
return 50
} else {
return 20
}
}
scrollToBottom(): void {
this.logContainer?.nativeElement.scroll({
top: this.logContainer.nativeElement.scrollHeight,
left: 0,
behavior: 'auto',
})
}
}

View File

@@ -0,0 +1,324 @@
<pngx-page-header title="Settings" i18n-title>
<button class="btn btn-sm btn-outline-primary" (click)="tourService.start()"><ng-container i18n>Start tour</ng-container></button>
<a *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Admin }" class="btn btn-sm btn-primary ms-3" href="admin/" target="_blank">
<ng-container i18n>Open Django Admin</ng-container>
<svg class="sidebaricon ms-1" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#arrow-up-right"/>
</svg>
</a>
</pngx-page-header>
<form [formGroup]="settingsForm" (ngSubmit)="saveSettings()">
<ul ngbNav #nav="ngbNav" (navChange)="onNavChange($event)" [(activeId)]="activeNavID" class="nav-tabs">
<li [ngbNavItem]="SettingsNavIDs.General">
<a ngbNavLink i18n>General</a>
<ng-template ngbNavContent>
<h4 i18n>Appearance</h4>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Display language</span>
</div>
<div class="col">
<select class="form-select" formControlName="displayLanguage">
<option *ngFor="let lang of displayLanguageOptions" [ngValue]="lang.code">{{lang.name}}<span *ngIf="lang.code && currentLocale !== 'en-US'"> - {{lang.englishName}}</span></option>
</select>
<small *ngIf="displayLanguageIsDirty" class="form-text text-primary" i18n>You need to reload the page after applying a new language.</small>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Date display</span>
</div>
<div class="col">
<select class="form-select" formControlName="dateLocale">
<option *ngFor="let lang of dateLocaleOptions" [ngValue]="lang.code">{{lang.name}}<span *ngIf="lang.code"> - {{today | customDate:'shortDate':null:lang.code}}</span></option>
</select>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Date format</span>
</div>
<div class="col">
<div class="form-check">
<input type="radio" id="dateFormatShort" name="dateFormat" class="form-check-input" formControlName="dateFormat" value="shortDate">
<label class="form-check-label" for="dateFormatShort" i18n>Short: {{today | customDate:'shortDate':null:computedDateLocale}}</label>
</div>
<div class="form-check">
<input type="radio" id="dateFormatMedium" name="dateFormat" class="form-check-input" formControlName="dateFormat" value="mediumDate">
<label class="form-check-label" for="dateFormatMedium" i18n>Medium: {{today | customDate:'mediumDate':null:computedDateLocale}}</label>
</div>
<div class="form-check">
<input type="radio" id="dateFormatLong" name="dateFormat" class="form-check-input" formControlName="dateFormat" value="longDate">
<label class="form-check-label" for="dateFormatLong" i18n>Long: {{today | customDate:'longDate':null:computedDateLocale}}</label>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Items per page</span>
</div>
<div class="col">
<select class="form-select" formControlName="documentListItemPerPage">
<option [ngValue]="10">10</option>
<option [ngValue]="25">25</option>
<option [ngValue]="50">50</option>
<option [ngValue]="100">100</option>
</select>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Document editor</span>
</div>
<div class="col">
<pngx-input-check i18n-title title="Use PDF viewer provided by the browser" i18n-hint hint="This is usually faster for displaying large PDF documents, but it might not work on some browsers." formControlName="useNativePdfViewer"></pngx-input-check>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Sidebar</span>
</div>
<div class="col">
<pngx-input-check i18n-title title="Use 'slim' sidebar (icons only)" formControlName="slimSidebarEnabled"></pngx-input-check>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Dark mode</span>
</div>
<div class="col">
<pngx-input-check i18n-title title="Use system settings" formControlName="darkModeUseSystem"></pngx-input-check>
<pngx-input-check [hidden]="settingsForm.value.darkModeUseSystem" i18n-title title="Enable dark mode" formControlName="darkModeEnabled"></pngx-input-check>
<pngx-input-check i18n-title title="Invert thumbnails in dark mode" formControlName="darkModeInvertThumbs"></pngx-input-check>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Theme Color</span>
</div>
<div class="col col-md-3">
<pngx-input-color i18n-title formControlName="themeColor" [error]="error?.color"></pngx-input-color>
</div>
<div class="col-2">
<button class="btn btn-link btn-sm pt-2 ps-0" [disabled]="!this.settingsForm.get('themeColor').value" (click)="clearThemeColor()">
<svg fill="currentColor" class="buttonicon-sm me-1">
<use xlink:href="assets/bootstrap-icons.svg#x"/>
</svg><ng-container i18n>Reset</ng-container>
</button>
</div>
</div>
<h4 class="mt-4" id="update-checking" i18n>Update checking</h4>
<div class="row mb-3">
<div class="offset-md-3 col">
<p i18n>
Update checking works by pinging the public <a href="https://api.github.com/repos/paperless-ngx/paperless-ngx/releases/latest" target="_blank" rel="noopener noreferrer">GitHub API</a> for the latest release to determine whether a new version is available.<br/>
Actual updating of the app must still be performed manually.
</p>
<p i18n>
<em>No tracking data is collected by the app in any way.</em>
</p>
<pngx-input-check i18n-title title="Enable update checking" formControlName="updateCheckingEnabled"></pngx-input-check>
</div>
</div>
<h4 class="mt-4" i18n>Bulk editing</h4>
<div class="row mb-3">
<div class="offset-md-3 col">
<pngx-input-check i18n-title title="Show confirmation dialogs" formControlName="bulkEditConfirmationDialogs" i18n-hint hint="Deleting documents will always ask for confirmation."></pngx-input-check>
<pngx-input-check i18n-title title="Apply on close" formControlName="bulkEditApplyOnClose"></pngx-input-check>
</div>
</div>
<h4 class="mt-4" i18n>Notes</h4>
<div class="row mb-3">
<div class="offset-md-3 col">
<pngx-input-check i18n-title title="Enable notes" formControlName="notesEnabled"></pngx-input-check>
</div>
</div>
</ng-template>
</li>
<li [ngbNavItem]="SettingsNavIDs.Permissions">
<a ngbNavLink i18n>Permissions</a>
<ng-template ngbNavContent>
<h4 i18n>Default Permissions</h4>
<div class="row mb-3">
<div class="offset-md-3 col">
<p i18n>
Settings apply to this user account for objects (Tags, Mail Rules, etc.) created via the web UI
</p>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Default Owner</span>
</div>
<div class="col-md-4">
<pngx-input-select [items]="users" bindLabel="username" formControlName="defaultPermsOwner" [allowNull]="true"></pngx-input-select>
<small class="form-text text-muted text-end d-block mt-n2" i18n>Objects without an owner can be viewed and edited by all users</small>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Default View Permissions</span>
</div>
<div class="col-md-4">
<div class="row">
<div class="col-2">
<span class="d-block pt-1" i18n>Users:</span>
</div>
<div class="col">
<ng-container *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.User }">
<pngx-permissions-user type="view" formControlName="defaultPermsViewUsers"></pngx-permissions-user>
</ng-container>
</div>
</div>
<div class="row">
<div class="col-2">
<span class="d-block pt-1" i18n>Groups:</span>
</div>
<div class="col">
<ng-container *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Group }">
<pngx-permissions-group type="view" formControlName="defaultPermsViewGroups"></pngx-permissions-group>
</ng-container>
</div>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 col-form-label pt-0">
<span i18n>Default Edit Permissions</span>
</div>
<div class="col-md-4">
<div class="row">
<div class="col-2">
<span class="d-block pt-1" i18n>Users:</span>
</div>
<div class="col">
<ng-container *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.User }">
<pngx-permissions-user type="view" formControlName="defaultPermsEditUsers"></pngx-permissions-user>
</ng-container>
</div>
</div>
<div class="row">
<div class="col-2">
<span class="d-block pt-1" i18n>Groups:</span>
</div>
<div class="col">
<ng-container *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Group }">
<pngx-permissions-group type="view" formControlName="defaultPermsEditGroups"></pngx-permissions-group>
</ng-container>
</div>
</div>
<div class="row">
<small class="form-text text-muted text-end d-block" i18n>Edit permissions also grant viewing permissions</small>
</div>
</div>
</div>
</ng-template>
</li>
<li [ngbNavItem]="SettingsNavIDs.Notifications">
<a ngbNavLink i18n>Notifications</a>
<ng-template ngbNavContent>
<h4 i18n>Document processing</h4>
<div class="row mb-3">
<div class="offset-md-3 col">
<pngx-input-check i18n-title title="Show notifications when new documents are detected" formControlName="notificationsConsumerNewDocument"></pngx-input-check>
<pngx-input-check i18n-title title="Show notifications when document processing completes successfully" formControlName="notificationsConsumerSuccess"></pngx-input-check>
<pngx-input-check i18n-title title="Show notifications when document processing fails" formControlName="notificationsConsumerFailed"></pngx-input-check>
<pngx-input-check i18n-title title="Suppress notifications on dashboard" formControlName="notificationsConsumerSuppressOnDashboard" i18n-hint hint="This will suppress all messages about document processing status on the dashboard."></pngx-input-check>
</div>
</div>
</ng-template>
</li>
<li [ngbNavItem]="SettingsNavIDs.SavedViews">
<a ngbNavLink i18n>Saved views</a>
<ng-template ngbNavContent>
<h4 i18n>Settings</h4>
<div class="row mb-3">
<div class="offset-md-3 col">
<pngx-input-check i18n-title title="Show warning when closing saved views with unsaved changes" formControlName="savedViewsWarnOnUnsavedChange"></pngx-input-check>
</div>
</div>
<h4 i18n>Views</h4>
<div formGroupName="savedViews">
<div *ngFor="let view of savedViews" [formGroupName]="view.id" class="row">
<div class="mb-3 col">
<label class="form-label" for="name_{{view.id}}" i18n>Name</label>
<input type="text" class="form-control" formControlName="name" id="name_{{view.id}}">
</div>
<div class="mb-2 col">
<label class="form-label" for="show_on_dashboard_{{view.id}}" i18n>&nbsp;<span class="visually-hidden">Appears on</span></label>
<div class="form-check form-switch">
<input type="checkbox" class="form-check-input" id="show_on_dashboard_{{view.id}}" formControlName="show_on_dashboard">
<label class="form-check-label" for="show_on_dashboard_{{view.id}}" i18n>Show on dashboard</label>
</div>
<div class="form-check form-switch">
<input type="checkbox" class="form-check-input" id="show_in_sidebar_{{view.id}}" formControlName="show_in_sidebar">
<label class="form-check-label" for="show_in_sidebar_{{view.id}}" i18n>Show in sidebar</label>
</div>
</div>
<div class="mb-2 col-auto">
<label class="form-label" for="name_{{view.id}}" i18n>Actions</label>
<button type="button" class="btn btn-sm btn-outline-danger form-control" (click)="deleteSavedView(view)" *pngxIfPermissions="{ action: PermissionAction.Delete, type: PermissionType.SavedView }" i18n>Delete</button>
</div>
</div>
<div *ngIf="savedViews && savedViews.length === 0" i18n>No saved views defined.</div>
<div *ngIf="!savedViews">
<div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div>
<div class="visually-hidden" i18n>Loading...</div>
</div>
</div>
</ng-template>
</li>
</ul>
<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" *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.UISettings }" [disabled]="(isDirty$ | async) === false" i18n>Save</button>
</form>

View File

@@ -0,0 +1,368 @@
import { ViewportScroller, DatePipe } from '@angular/common'
import { HttpClientTestingModule } from '@angular/common/http/testing'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { By } from '@angular/platform-browser'
import { Router, ActivatedRoute, convertToParamMap } from '@angular/router'
import { RouterTestingModule } from '@angular/router/testing'
import {
NgbModule,
NgbAlertModule,
NgbNavLink,
} from '@ng-bootstrap/ng-bootstrap'
import { NgSelectModule } from '@ng-select/ng-select'
import { of, throwError } from 'rxjs'
import { routes } from 'src/app/app-routing.module'
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'
import { SETTINGS_KEYS } from 'src/app/data/paperless-uisettings'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { PermissionsGuard } from 'src/app/guards/permissions.guard'
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 { 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 { SettingsService } from 'src/app/services/settings.service'
import { ToastService, Toast } from 'src/app/services/toast.service'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { CheckComponent } from '../../common/input/check/check.component'
import { ColorComponent } from '../../common/input/color/color.component'
import { NumberComponent } from '../../common/input/number/number.component'
import { PermissionsGroupComponent } from '../../common/input/permissions/permissions-group/permissions-group.component'
import { PermissionsUserComponent } from '../../common/input/permissions/permissions-user/permissions-user.component'
import { SelectComponent } from '../../common/input/select/select.component'
import { TagsComponent } from '../../common/input/tags/tags.component'
import { TextComponent } from '../../common/input/text/text.component'
import { PageHeaderComponent } from '../../common/page-header/page-header.component'
import { SettingsComponent } from './settings.component'
import { IfOwnerDirective } from 'src/app/directives/if-owner.directive'
const savedViews = [
{ id: 1, name: 'view1', show_in_sidebar: true, show_on_dashboard: true },
{ id: 2, name: 'view2', show_in_sidebar: false, show_on_dashboard: false },
]
const users = [
{ id: 1, username: 'user1', is_superuser: false },
{ id: 2, username: 'user2', is_superuser: false },
]
const groups = [
{ id: 1, name: 'group1' },
{ id: 2, name: 'group2' },
]
describe('SettingsComponent', () => {
let component: SettingsComponent
let fixture: ComponentFixture<SettingsComponent>
let router: Router
let settingsService: SettingsService
let savedViewService: SavedViewService
let activatedRoute: ActivatedRoute
let viewportScroller: ViewportScroller
let toastService: ToastService
let userService: UserService
let permissionsService: PermissionsService
let groupService: GroupService
beforeEach(async () => {
TestBed.configureTestingModule({
declarations: [
SettingsComponent,
PageHeaderComponent,
IfPermissionsDirective,
CustomDatePipe,
ConfirmDialogComponent,
CheckComponent,
ColorComponent,
SafeHtmlPipe,
SelectComponent,
TextComponent,
NumberComponent,
TagsComponent,
PermissionsUserComponent,
PermissionsGroupComponent,
IfOwnerDirective,
],
providers: [CustomDatePipe, DatePipe, PermissionsGuard],
imports: [
NgbModule,
HttpClientTestingModule,
RouterTestingModule.withRoutes(routes),
FormsModule,
ReactiveFormsModule,
NgbAlertModule,
NgSelectModule,
],
}).compileComponents()
router = TestBed.inject(Router)
activatedRoute = TestBed.inject(ActivatedRoute)
viewportScroller = TestBed.inject(ViewportScroller)
toastService = TestBed.inject(ToastService)
settingsService = TestBed.inject(SettingsService)
settingsService.currentUser = users[0]
userService = TestBed.inject(UserService)
permissionsService = TestBed.inject(PermissionsService)
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
jest
.spyOn(permissionsService, 'currentUserHasObjectPermissions')
.mockReturnValue(true)
jest
.spyOn(permissionsService, 'currentUserOwnsObject')
.mockReturnValue(true)
groupService = TestBed.inject(GroupService)
savedViewService = TestBed.inject(SavedViewService)
})
function completeSetup(excludeService = null) {
if (excludeService !== userService) {
jest.spyOn(userService, 'listAll').mockReturnValue(
of({
all: users.map((u) => u.id),
count: users.length,
results: users.concat([]),
})
)
}
if (excludeService !== groupService) {
jest.spyOn(groupService, 'listAll').mockReturnValue(
of({
all: groups.map((g) => g.id),
count: groups.length,
results: groups.concat([]),
})
)
}
if (excludeService !== savedViewService) {
jest.spyOn(savedViewService, 'listAll').mockReturnValue(
of({
all: savedViews.map((v) => v.id),
count: savedViews.length,
results: (savedViews as PaperlessSavedView[]).concat([]),
})
)
}
fixture = TestBed.createComponent(SettingsComponent)
component = fixture.componentInstance
fixture.detectChanges()
}
it('should support tabbed settings & change URL, prevent navigation if dirty confirmation rejected', () => {
completeSetup()
const navigateSpy = jest.spyOn(router, 'navigate')
const tabButtons = fixture.debugElement.queryAll(By.directive(NgbNavLink))
tabButtons[1].nativeElement.dispatchEvent(new MouseEvent('click'))
expect(navigateSpy).toHaveBeenCalledWith(['settings', 'permissions'])
tabButtons[2].nativeElement.dispatchEvent(new MouseEvent('click'))
expect(navigateSpy).toHaveBeenCalledWith(['settings', 'notifications'])
tabButtons[3].nativeElement.dispatchEvent(new MouseEvent('click'))
expect(navigateSpy).toHaveBeenCalledWith(['settings', 'savedviews'])
const initSpy = jest.spyOn(component, 'initialize')
component.isDirty = true // mock dirty
navigateSpy.mockResolvedValueOnce(false) // nav rejected cause dirty
tabButtons[0].nativeElement.dispatchEvent(new MouseEvent('click'))
expect(navigateSpy).toHaveBeenCalledWith(['settings', 'general'])
expect(initSpy).not.toHaveBeenCalled()
navigateSpy.mockResolvedValueOnce(true) // nav accepted even though dirty
tabButtons[1].nativeElement.dispatchEvent(new MouseEvent('click'))
expect(navigateSpy).toHaveBeenCalledWith(['settings', 'notifications'])
expect(initSpy).toHaveBeenCalled()
})
it('should support direct link to tab by URL, scroll if needed', () => {
completeSetup()
jest
.spyOn(activatedRoute, 'paramMap', 'get')
.mockReturnValue(of(convertToParamMap({ section: 'notifications' })))
activatedRoute.snapshot.fragment = '#notifications'
const scrollSpy = jest.spyOn(viewportScroller, 'scrollToAnchor')
component.ngOnInit()
expect(component.activeNavID).toEqual(3) // Notifications
component.ngAfterViewInit()
expect(scrollSpy).toHaveBeenCalledWith('#notifications')
})
it('should enable organizing of sidebar saved views even on direct navigation', () => {
completeSetup()
jest
.spyOn(activatedRoute, 'paramMap', 'get')
.mockReturnValue(of(convertToParamMap({ section: 'savedviews' })))
activatedRoute.snapshot.fragment = '#savedviews'
component.ngOnInit()
expect(component.activeNavID).toEqual(4) // Saved Views
component.ngAfterViewInit()
expect(settingsService.organizingSidebarSavedViews).toBeTruthy()
})
it('should support save saved views, show error', () => {
completeSetup()
const tabButtons = fixture.debugElement.queryAll(By.directive(NgbNavLink))
tabButtons[3].nativeElement.dispatchEvent(new MouseEvent('click'))
fixture.detectChanges()
const toastErrorSpy = jest.spyOn(toastService, 'showError')
const toastSpy = jest.spyOn(toastService, 'show')
const savedViewPatchSpy = jest.spyOn(savedViewService, 'patchMany')
const toggle = fixture.debugElement.query(
By.css('.form-check.form-switch input')
)
toggle.nativeElement.checked = true
toggle.nativeElement.dispatchEvent(new Event('change'))
// saved views error first
savedViewPatchSpy.mockReturnValueOnce(
throwError(() => new Error('unable to save saved views'))
)
component.saveSettings()
expect(toastErrorSpy).toHaveBeenCalled()
expect(savedViewPatchSpy).toHaveBeenCalled()
toastSpy.mockClear()
toastErrorSpy.mockClear()
savedViewPatchSpy.mockClear()
// succeed saved views
savedViewPatchSpy.mockReturnValueOnce(
of(savedViews as PaperlessSavedView[])
)
component.saveSettings()
expect(toastErrorSpy).not.toHaveBeenCalled()
expect(savedViewPatchSpy).toHaveBeenCalled()
})
it('should update only patch saved views that have changed', () => {
completeSetup()
const tabButtons = fixture.debugElement.queryAll(By.directive(NgbNavLink))
tabButtons[3].nativeElement.dispatchEvent(new MouseEvent('click'))
fixture.detectChanges()
const patchSpy = jest.spyOn(savedViewService, 'patchMany')
component.saveSettings()
expect(patchSpy).not.toHaveBeenCalled()
const view = savedViews[0]
const toggle = fixture.debugElement.query(
By.css('.form-check.form-switch input')
)
toggle.nativeElement.checked = true
toggle.nativeElement.dispatchEvent(new Event('change'))
// register change
component.savedViewGroup.get(view.id.toString()).value[
'show_on_dashboard'
] = !view.show_on_dashboard
fixture.detectChanges()
component.saveSettings()
expect(patchSpy).toHaveBeenCalledWith([
{
id: view.id,
name: view.name,
show_in_sidebar: view.show_in_sidebar,
show_on_dashboard: !view.show_on_dashboard,
},
])
})
it('should support save local settings updating appearance settings and calling API, show error', () => {
completeSetup()
jest.spyOn(savedViewService, 'patchMany').mockReturnValue(of([]))
const toastErrorSpy = jest.spyOn(toastService, 'showError')
const toastSpy = jest.spyOn(toastService, 'show')
const storeSpy = jest.spyOn(settingsService, 'storeSettings')
const appearanceSettingsSpy = jest.spyOn(
settingsService,
'updateAppearanceSettings'
)
const setSpy = jest.spyOn(settingsService, 'set')
// error first
storeSpy.mockReturnValueOnce(
throwError(() => new Error('unable to save settings'))
)
component.saveSettings()
expect(toastErrorSpy).toHaveBeenCalled()
expect(storeSpy).toHaveBeenCalled()
expect(appearanceSettingsSpy).not.toHaveBeenCalled()
expect(setSpy).toHaveBeenCalledTimes(24)
// succeed
storeSpy.mockReturnValueOnce(of(true))
component.saveSettings()
expect(toastSpy).toHaveBeenCalled()
expect(appearanceSettingsSpy).toHaveBeenCalled()
})
it('should offer reload if settings changes require', () => {
completeSetup()
jest.spyOn(savedViewService, 'patchMany').mockReturnValue(of([]))
let toast: Toast
toastService.getToasts().subscribe((t) => (toast = t[0]))
component.initialize(true) // reset
component.store.getValue()['displayLanguage'] = 'en-US'
component.store.getValue()['updateCheckingEnabled'] = false
component.settingsForm.value.displayLanguage = 'en-GB'
component.settingsForm.value.updateCheckingEnabled = true
jest.spyOn(settingsService, 'storeSettings').mockReturnValueOnce(of(true))
component.saveSettings()
expect(toast.actionName).toEqual('Reload now')
})
it('should allow setting theme color, visually apply change immediately but not save', () => {
completeSetup()
const appearanceSpy = jest.spyOn(
settingsService,
'updateAppearanceSettings'
)
const colorInput = fixture.debugElement.query(By.directive(ColorComponent))
colorInput.query(By.css('input')).nativeElement.value = '#ff0000'
colorInput
.query(By.css('input'))
.nativeElement.dispatchEvent(new Event('change'))
fixture.detectChanges()
expect(appearanceSpy).toHaveBeenCalled()
expect(settingsService.get(SETTINGS_KEYS.THEME_COLOR)).toEqual('')
component.clearThemeColor()
})
it('should support delete saved view', () => {
completeSetup()
const toastSpy = jest.spyOn(toastService, 'showInfo')
const deleteSpy = jest.spyOn(savedViewService, 'delete')
deleteSpy.mockReturnValue(of(true))
component.deleteSavedView(savedViews[0] as PaperlessSavedView)
expect(deleteSpy).toHaveBeenCalled()
expect(toastSpy).toHaveBeenCalledWith(
`Saved view "${savedViews[0].name}" deleted.`
)
})
it('should show errors on load if load users failure', () => {
const toastErrorSpy = jest.spyOn(toastService, 'showError')
jest
.spyOn(userService, 'listAll')
.mockImplementation(() =>
throwError(() => new Error('failed to load users'))
)
completeSetup(userService)
fixture.detectChanges()
expect(toastErrorSpy).toBeCalled()
})
it('should show errors on load if load groups failure', () => {
const toastErrorSpy = jest.spyOn(toastService, 'showError')
jest
.spyOn(groupService, 'listAll')
.mockImplementation(() =>
throwError(() => new Error('failed to load groups'))
)
completeSetup(groupService)
fixture.detectChanges()
expect(toastErrorSpy).toBeCalled()
})
})

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