Compare commits

...

241 Commits

Author SHA1 Message Date
Michael Shamoon
4df065d8d5 v1.7.0 2022-04-25 10:26:49 -07:00
shamoon
a358477cda Merge pull request #695 from paperless-ngx/beta
[Beta] Paperless-ngx v1.7.0 Release Candidate 1
2022-04-25 10:24:27 -07:00
shamoon
44d6db8c47 Merge pull request #772 from paperless-ngx/fix-dark-mode-delay-btn-progress
Fix dark mode delay button progress bar not visible
2022-04-22 08:15:30 -07:00
Quinn Casey
49e627d2fd Merge pull request #785 from paperless-ngx/fix-docs-darkmode-toggle
Fix docs dark mode toggle blocks menu button
2022-04-22 07:24:28 -07:00
shamoon
c3a8d93eb4 fix docs dark mode toggle blocks menu button 2022-04-22 01:00:19 -07:00
Paperless-ngx Translation Bot [bot]
7a648c6465 New Crowdin updates (#781)
* New translations messages.xlf (Russian)
[ci skip]

* New translations messages.xlf (Russian)
[ci skip]
2022-04-21 20:33:16 -07:00
Michael Shamoon
23b2fbef45 Fix dark mode delay button progress bar not visible 2022-04-19 19:25:24 -07:00
Paperless-ngx Translation Bot [bot]
b63f87a5b5 New translations messages.xlf (French) (#764)
[ci skip]
2022-04-18 19:48:23 -07:00
shamoon
68e3612d36 Merge pull request #765 from p-h-a-i-l/fix-mail-action-mixup
fix Mail actions mixup
2022-04-18 16:23:34 -07:00
phail
616a826b8a fix Mail actions mixup 2022-04-19 00:59:57 +02:00
shamoon
09d62d76b2 Merge pull request #745 from paperless-ngx/1.7.0-rc1-css-fixes-1
Beta 1.7.0 rc1 CSS Fixes #1
2022-04-18 12:02:14 -07:00
Quinn Casey
deab7794d6 Merge pull request #751 from paperless-ngx/feature-ci-concurrency
Adds workflow level concurrency group
2022-04-17 17:17:28 -07:00
Trenton Holmes
bc892059a1 Adds workflow level concurrency group with cancelling of in progress jobs to the CI 2022-04-17 15:29:50 -07:00
Michael Shamoon
dd1d4b86d2 use var in input check / radio svgs 2022-04-17 00:49:34 -07:00
Michael Shamoon
65eeea9453 toasts should respect close button coloring 2022-04-17 00:48:57 -07:00
Michael Shamoon
b2b202586c fix settings mobile display bugs 2022-04-17 00:36:47 -07:00
Michael Shamoon
49341260dc fix popover carats 2022-04-17 00:25:39 -07:00
Michael Shamoon
dfcef81001 fix dark mode progress showing in light mode 2022-04-17 00:25:28 -07:00
Michael Shamoon
a834a6c874 remove single-use css vars 2022-04-17 00:25:10 -07:00
Paperless-ngx Translation Bot [bot]
53c2a0c724 New translations messages.xlf (Serbian (Latin)) (#735)
[ci skip]
2022-04-16 00:39:08 -07:00
Michael Shamoon
3a8cc31f1b fix some css specificity issues, unused vars 2022-04-16 00:23:15 -07:00
Quinn Casey
0f6b452d17 Merge pull request #737 from paperless-ngx/add-missing-packages-to-doc
add barcode packages to setup.rst
2022-04-15 06:32:47 -07:00
Florian Brandes
e994bcf737 add barcode packages to setup.rst
fixes #730

Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-15 08:32:53 +02:00
Michael Shamoon
5432700b0d Add note for malformed package-lock in 1.6.0 2022-04-13 20:43:42 -07:00
Paperless-ngx Translation Bot [bot]
7b7534c952 New Crowdin updates (#699)
* New translations django.po (Polish)
[ci skip]

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

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

* New translations messages.xlf (Danish)
[ci skip]
2022-04-13 20:33:15 -07:00
shamoon
b4570545ef Merge pull request #717 from paperless-ngx/fix-custom-theme-color-contrast
Fix custom theme color contrast
2022-04-13 13:31:24 -07:00
Michael Shamoon
6478db13e6 miscellaneous css fixes / reorganization 2022-04-13 13:30:02 -07:00
Michael Shamoon
1d7ddcc10d Remove unneeded imports since change to css vars 2022-04-13 08:43:35 -07:00
shamoon
30508c6c2c Merge pull request #702 from paperless-ngx/stalebot-unconfirmed
Chore: Only stale unconfirmed issues
2022-04-13 08:35:31 -07:00
Quinn Casey
18f43c5757 Merge pull request #722 from paperless-ngx/fix-gotenberg
Fix: use correct gotenberg image for sqlite-tika.arm.yml
2022-04-13 08:34:40 -07:00
shamoon
52498efd14 Merge pull request #723 from paperless-ngx/bugfix-remove-tag-match
Fix docker/metadata-action creation of latest tag
2022-04-13 08:28:44 -07:00
Trenton Holmes
40cb721d16 Removes the matching regex from the docker/metadata-action as it will create a new :latest even for release candidates 2022-04-13 08:20:30 -07:00
Michael Shamoon
1c2699b16e Refactor contrast to use luminance function 2022-04-13 08:18:10 -07:00
Michael Shamoon
d98a016087 Initial build of primary color contrast 2022-04-13 08:18:09 -07:00
Quinn Casey
bc5b6db031 Fix gotenberg image 2022-04-13 08:16:35 -07:00
Quinn Casey
4a4f252ad8 Merge branch 'main' into beta 2022-04-13 08:13:32 -07:00
Quinn Casey
c81dd1a478 Merge pull request #720 from alumpe/docs-typo-fixes
Corrects some spelling mistakes in docs
2022-04-13 07:11:36 -07:00
Adrian Lumpe
31016156be corrects some spelling mistakes in docs 2022-04-13 15:39:49 +02:00
shamoon
dad352f05e Update changelog.rst
[ci skip]
2022-04-13 03:14:43 -07:00
shamoon
95e94618d8 Merge pull request #270 from jonasc/dev
Allow setting more than one tag in mail rules
2022-04-13 03:11:38 -07:00
shamoon
045a401cd7 Merge pull request #705 from paperless-ngx/fix-startls
bugfix for imap using starttls
2022-04-12 18:51:46 -07:00
Quinn Casey
d5d7e2edbc Merge pull request #715 from paperless-ngx/nginx-proxy-config-variable
Add required PAPERLESS_URL to nginx proxy docs
2022-04-12 15:17:22 -07:00
Quinn Casey
64e1a6ec7e Merge pull request #713 from paperless-ngx/fix-1.7.0-rc1-tags-input-color
Fix: v1.7.0-rc1 Tags input should use body color
2022-04-12 15:11:05 -07:00
Quinn Casey
2221b425ad Add required PAPERLESS_URL to nginx proxy docs 2022-04-12 15:06:32 -07:00
Michael Shamoon
86b2ccae94 Tags input should use body color 2022-04-12 14:45:47 -07:00
shamoon
0bd67a54ab Merge pull request #704 from paperless-ngx/breaking-changes-changelog
Chore: Add Breaking Changes to release notes
2022-04-12 10:19:15 -07:00
Quinn Casey
306f254218 Add Breaking Changes 2022-04-12 07:37:49 -07:00
Quinn Casey
449add88a6 Bump header level 2022-04-12 07:37:02 -07:00
Quinn Casey
941ba8d689 Only stale unconfirmed issues 2022-04-12 07:31:14 -07:00
shamoon
813335f8eb Update changelog.rst
[ci skip]
2022-04-12 07:30:16 -07:00
shamoon
f0cef2f42f Update changelog.rst
[ci skip]
2022-04-12 07:29:07 -07:00
shamoon
e767eb38f4 Merge pull request #700 from paperless-ngx/fix-healthcheck
add "localhost" to ALLOWED_HOSTS
2022-04-12 07:25:09 -07:00
Florian Brandes
71cbef4c13 fixes #697
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-12 15:54:18 +02:00
jonasc
834ad1ef84 reformat migration with black 2022-04-12 15:06:38 +02:00
Florian Brandes
753e6661bc add "localhost" to ALLOWED_HOSTS
if PAPERLESS_URL is set and ALLOWED_HOSTS is NOT set

Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-12 14:39:08 +02:00
jonasc
1ce19f5444 merge migrations 2022-04-12 10:51:19 +02:00
jonasc
0de1230a1a Reset related_name (was set to prevent duplicate) 2022-04-12 10:45:56 +02:00
jonasc
5ff304324d Add backwards data migration
The documents.tests.test_migration_mime_type test suite failes if no
backwards migration is provided. This simple backwards migration sets
the old assign_tag field with a tag if exactly one is set in
assign_tags.
2022-04-12 10:45:56 +02:00
jonasc
37f7ef41f2 Save MailRule and MailAccount objects in tests
This fixes the errors in the tests that the new many-to-many
assign_tags property cannot be accessed due to MailRule not having an
id. In one case it it necessary to give additional names to both objects
as several are created.
2022-04-12 10:45:52 +02:00
jonasc
4022284059 Allow setting more than one tag in mail rules
The three migrations do the following to preserve existing data in
assign_tag:
1. Add the new many-to-many field assign_tags.
2. Copy existing data from the assign_tag field to the assign_tags.
3. Delete the existing assign_tag field.
2022-04-12 10:41:08 +02:00
shamoon
dde6a2eb7d Merge branch 'main' into beta 2022-04-11 23:37:21 -07:00
Michael Shamoon
1083ed4e40 Update .pre-commit-config.yaml
[ci skip]
2022-04-11 23:32:37 -07:00
Michael Shamoon
c111825b1e Minor merge conflicts
[ci skip]
2022-04-11 23:31:20 -07:00
Michael Shamoon
e36c22d29a Update changelog.rst
[ci skip]
2022-04-11 23:05:16 -07:00
Michael Shamoon
c192931015 Update changelog.rst
[ci skip]
2022-04-11 22:58:08 -07:00
Michael Shamoon
ae895a4aec Create release-drafter.yml
[ci skip]
2022-04-11 22:05:55 -07:00
Michael Shamoon
301ad7e07d v1.7.0-rc1 2022-04-11 21:03:02 -07:00
Trenton Holmes
cc93616019 Merge pull request #691 from paperless-ngx/dependabot/pip/dev/django-4.0.4
Bump django from 4.0.3 to 4.0.4
2022-04-11 16:04:44 -07:00
Michael Shamoon
493d9875d4 tiny docs css fix
[ci skip]
2022-04-11 14:14:15 -07:00
shamoon
3fb8d05f0d Merge pull request #684 from paperless-ngx/docs-dark-mode
Documentation dark mode
2022-04-11 14:10:23 -07:00
dependabot[bot]
88066563d3 Bump django from 4.0.3 to 4.0.4
Bumps [django](https://github.com/django/django) from 4.0.3 to 4.0.4.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/4.0.3...4.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-11 20:37:09 +00:00
shamoon
9e3590352c Merge pull request #690 from paperless-ngx/fix-scanners-table
Fix: scanners table
2022-04-11 12:56:45 -07:00
Quinn Casey
86ad52639f Fix name 2022-04-11 12:34:37 -07:00
Quinn Casey
c00be946a5 Remove explicit "no" as was done in f303a1c 2022-04-11 12:32:32 -07:00
Quinn Casey
322aeeb552 Add 994d502 2022-04-11 12:23:27 -07:00
Quinn Casey
501d4cafa9 Add f303a1c 2022-04-11 12:21:52 -07:00
Quinn Casey
e556fb3e3a Add f2f7b71 2022-04-11 12:17:44 -07:00
Quinn Casey
bb930297d6 Reset table to b318c0a 2022-04-11 12:12:01 -07:00
shamoon
83f10167e5 Merge pull request #483 from stumpylog/check-if-file-busy
Adds wait for file before consuming
2022-04-11 11:56:05 -07:00
Quinn Casey
d47bb21389 Merge pull request #654 from paperless-ngx/fix-doc-detail-time
Fix: frontend document editing erases time data
2022-04-11 11:54:24 -07:00
Florian
4dedff00b8 Merge pull request #532 from paperless-ngx/feature-barcode-splitter
Feature barcode splitter
2022-04-11 08:51:48 +02:00
Trenton Holmes
2414dad656 Adds additional checking for both inotify and polling around document still being busy before consuming it 2022-04-10 12:21:34 -07:00
shamoon
8f98cb4860 Merge pull request #550 from stumpylog/feature-mail-consume-improve-docs
Feature mail consume improve docs
2022-04-10 08:46:45 -07:00
shamoon
6e96b7e00a Merge pull request #612 from stumpylog/bug-fix-filter-len
Increase length of SavedViewFilterRule
2022-04-10 08:46:25 -07:00
Michael Shamoon
04acce4916 dark mode toggle, css vars 2022-04-09 22:10:03 -07:00
Michael Shamoon
1b7a304149 initial docs dark mode css 2022-04-08 22:49:45 -07:00
shamoon
00287b27ab Merge pull request #680 from paperless-ngx/bug-fix-fnmatch
[bug] - Fixes attachment filename matching during mail fetching
2022-04-08 13:59:22 -07:00
Trenton Holmes
8f18b7fd6c Fixes the matching of attachment files names to patterns 2022-04-08 13:42:42 -07:00
Felix E
dde7771dc6 Merge pull request #674 from paperless-ngx/feature-django4-csrf
Add `PAPERLESS_URL` env variable & CSRF var
2022-04-08 21:00:57 +02:00
Quinn Casey
4165184e42 Chore: Implement release-drafter action for Changelogs (#669)
* Add inital release-drafter config

* Replace release action

* Add collapse-after 3 to dependencies
2022-04-08 11:12:19 -07:00
shamoon
f3c8211ba4 Merge pull request #672 from paperless-ngx/update-screenshots 2022-04-08 10:25:51 -07:00
Michael Shamoon
e4953a756a docs for PAPERLESS_URL + PAPERLESS_CSRF_TRUSTED_ORIGINS 2022-04-08 09:59:59 -07:00
Trenton Holmes
471ac63a3a Increases SavedViewFilterRule value to the maximum length 2022-04-08 08:55:58 -07:00
Trenton Holmes
f358eda5c5 Updates the mail db model to use the built-in enum capabilities and runs the migrations 2022-04-08 08:55:40 -07:00
Trenton Holmes
035130ecdc Updates the folder input text and adds docs note for how to figure out the folder separator value 2022-04-08 08:55:40 -07:00
Michael Shamoon
908fc8573a Merge dev changes to PULL_REQUEST_TEMPLATE.md
[ci skip]
2022-04-08 00:41:55 -07:00
Michael Shamoon
ca0e86757b add PAPERLESS_URL env variable for CSRF 2022-04-08 00:27:53 -07:00
Michael Shamoon
d4153607c9 reorganizing scss for clarity
[ci skip]
2022-04-07 23:23:28 -07:00
Michael Shamoon
99d0a0845d fix scss organization
[ci skip]
2022-04-07 23:15:27 -07:00
Florian Brandes
5fae5a9ee0 fix conditional in separate_pages
add additional test for separate_pages

Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-08 08:09:48 +02:00
Michael Shamoon
b5a75be1db fix error case
[ci skip]
2022-04-07 23:06:46 -07:00
Michael Shamoon
93ad5433e4 Updated screenshots 2022-04-07 15:28:54 -07:00
Trenton Holmes
eb5e0e0b9b Merge pull request #501 from stumpylog/configure-worker-retry
Adds settings for worker retry time
2022-04-07 15:24:53 -07:00
Michael Shamoon
5ead8de0bb Add global drag-n-drop note
[ci skip]
2022-04-07 15:21:49 -07:00
Trenton Holmes
dc90f58391 Merge pull request #641 from paperless-ngx/dependabot/pip/dev/pre-commit-2.18.1
Bump pre-commit from 2.17.0 to 2.18.1
2022-04-07 14:29:08 -07:00
Michael Shamoon
ca43c71cf5 fix some broken css vars 2022-04-07 14:27:49 -07:00
dependabot[bot]
931a311c48 Bump pre-commit from 2.17.0 to 2.18.1
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.17.0 to 2.18.1.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.17.0...v2.18.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-07 20:54:33 +00:00
Michael Shamoon
9f9d7da1ce minor css hover + focus state fixes
[ci skip]
2022-04-07 13:51:36 -07:00
Trenton Holmes
d00e8d3b0f Merge pull request #649 from paperless-ngx/dependabot/pip/dev/zipp-3.8.0
Bump zipp from 3.7.0 to 3.8.0
2022-04-07 13:49:50 -07:00
Trenton Holmes
d4124bae0c Merge pull request #653 from paperless-ngx/dependabot/pip/dev/tqdm-4.64.0
Bump tqdm from 4.63.1 to 4.64.0
2022-04-07 13:37:46 -07:00
Michael Shamoon
c062eb751e another tiny doc style fix
[ci skip]
2022-04-07 12:47:48 -07:00
Michael Shamoon
e273a594ba tiny doc style fixes for rtd tools
[ci skip]
2022-04-07 12:44:08 -07:00
shamoon
ebb724e687 Merge pull request #652 from paperless-ngx/documentation-style
Documentation style
2022-04-07 12:35:06 -07:00
shamoon
58eb2d6f63 Merge pull request #283 from paperless-ngx/feature-global-dragdrop
Feature: global drag'n'drop
2022-04-07 12:14:59 -07:00
Michael Shamoon
b14bf8a96d prettier docs 2022-04-07 11:38:48 -07:00
Quinn Casey
01987f1b51 Merge pull request #667 from paperless-ngx/codeowners
Feature: Add CODEOWNERS
2022-04-07 08:31:48 -07:00
shamoon
0a35358e8d Merge pull request #666 from paperless-ngx/feature-update-base-image 2022-04-07 08:30:59 -07:00
Quinn Casey
5bacb85c33 Fix typo 2022-04-07 08:13:25 -07:00
Quinn Casey
6933ac523f Remove explicit team tagging from PR template 2022-04-07 08:13:12 -07:00
Quinn Casey
ba9120b417 Add CODEOWNERS 2022-04-07 08:12:05 -07:00
dependabot[bot]
3e71f5810f Bump tqdm from 4.63.1 to 4.64.0
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.63.1 to 4.64.0.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.63.1...v4.64.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-07 15:02:57 +00:00
Trenton Holmes
296a0edae4 Updates the base image tag to use the :dev tag from the base image dev branch 2022-04-07 08:00:22 -07:00
Florian Brandes
cdf5602dfb update documentation
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
e214f719c9 add more tests
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
08fbcf5158 use imported List
fail test if non-existing dir exists

Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
10ca515ac5 addes tests:
- barcode-39
- barcode-128
- qr barcodes
- test for consumption

Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
e59a14852b code formatting
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
c696b4f2f2 set barcode reader default to disabled
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
553153ba92 put code under CONSUMER_ENABLE_BARCODES
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
9d2bcf807e add more type hinting
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
422ac9befe decode bytecode in string
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
793f641af6 make list checks consistent
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
0ea5f5d584 use append method for lists
Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
florian on nixos (Florian Brandes)
c024b846c3 add config options and documentation
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
florian on nixos (Florian Brandes)
37b3fde4e1 pre-commit hooks
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
florian on nixos (Florian Brandes)
e89ef5de25 renaming of documents to align with front end
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
florian on nixos (Florian Brandes)
06cac44d02 update ci.yml to include new dependency
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
florian on nixos (Florian Brandes)
488fe28ad3 flake8
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
florian on nixos (Florian Brandes)
50f474ae92 run black
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
florian on nixos (Florian Brandes)
78ca2ffaba add trailing commas
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
florian on nixos (Florian Brandes)
911f5bc78e reorder imports
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-07 11:14:29 +02:00
Florian Brandes
b227427916 add split logic to consume_file
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-07 11:14:17 +02:00
florian on nixos (Florian Brandes)
b5f77fd6e7 skip test if dir exists
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-06 21:16:41 +02:00
florian on nixos (Florian Brandes)
4fe966f534 more work on barcode
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-06 21:16:41 +02:00
florian on nixos (Florian Brandes)
bcce0838dd working split pages
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-06 21:16:41 +02:00
florian on nixos (Florian Brandes)
76e43bcb89 add first tests for barcode reader
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-06 21:16:41 +02:00
florian on nixos (Florian Brandes)
c666be32f4 add barcode packages
Signed-off-by: florian on nixos (Florian Brandes) <florian.brandes@posteo.de>
2022-04-06 21:16:41 +02:00
Trenton Holmes
2d850795d8 Merge pull request #642 from paperless-ngx/dependabot/pip/dev/ocrmypdf-13.4.2
Bump ocrmypdf from 13.4.1 to 13.4.2
2022-04-06 12:13:03 -07:00
Michael Shamoon
784982718e retain document time / tz in detail form 2022-04-05 22:11:09 -07:00
shamoon
2f8d263c9c Merge pull request #630 from paperless-ngx/fix-disableable-download-buttons
Fix: download buttons should disable while waiting
2022-04-05 19:44:43 -07:00
dependabot[bot]
b214163af3 Bump ocrmypdf from 13.4.1 to 13.4.2
Bumps [ocrmypdf](https://github.com/jbarlow83/ocrmypdf) from 13.4.1 to 13.4.2.
- [Release notes](https://github.com/jbarlow83/ocrmypdf/releases)
- [Changelog](https://github.com/ocrmypdf/OCRmyPDF/blob/master/docs/release_notes.rst)
- [Commits](https://github.com/jbarlow83/ocrmypdf/compare/v13.4.1...v13.4.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-06 02:04:09 +00:00
dependabot[bot]
a4fe1000c2 Bump zipp from 3.7.0 to 3.8.0
Bumps [zipp](https://github.com/jaraco/zipp) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/jaraco/zipp/releases)
- [Changelog](https://github.com/jaraco/zipp/blob/main/CHANGES.rst)
- [Commits](https://github.com/jaraco/zipp/compare/v3.7.0...v3.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-06 02:03:28 +00:00
Trenton Holmes
9a275fa4ed Merge pull request #619 from paperless-ngx/dependabot/pip/dev/pillow-9.1.0
Bump pillow from 9.0.1 to 9.1.0
2022-04-05 18:57:52 -07:00
Michael Shamoon
f2c83f51de Cleanup file upload susbcriptions 2022-04-05 13:33:24 -07:00
Michael Shamoon
fb76b72787 Delete upload-documents.service.spec.ts 2022-04-05 13:33:24 -07:00
Michael Shamoon
bec6c4511c Cleaner activation with Angular directives 2022-04-05 13:33:24 -07:00
Michael Shamoon
77b9988d05 Refactor uploads to service, working global dd 2022-04-05 13:33:24 -07:00
Michael Shamoon
3e49f93816 100vh body height, fix filter editor horizontal overflow 2022-04-05 13:33:24 -07:00
Michael Shamoon
32f6932faf fix overlay background color in dark mode 2022-04-05 13:16:13 -07:00
Michael Shamoon
db76e1d65f code formatting 2022-04-05 13:16:13 -07:00
Michael Shamoon
0136ba504b Delete upload-documents.service.spec.ts 2022-04-05 13:16:13 -07:00
Michael Shamoon
459e026f16 Add translation directive for upload message 2022-04-05 13:16:13 -07:00
Michael Shamoon
b03a723c3e Fix dark mode alert close button 2022-04-05 13:16:13 -07:00
Michael Shamoon
7562636151 Cleaner activation with Angular directives 2022-04-05 13:16:13 -07:00
Michael Shamoon
3acc65ca0d Fix broken toast animations & DOM removal 2022-04-05 13:16:13 -07:00
Michael Shamoon
fde0f4ca0a Add initiating toast 2022-04-05 13:16:13 -07:00
Michael Shamoon
73cab2af2d Refactor uploads to service, working global dd 2022-04-05 13:16:12 -07:00
dependabot[bot]
94d2198b30 Bump pillow from 9.0.1 to 9.1.0
Bumps [pillow](https://github.com/python-pillow/Pillow) from 9.0.1 to 9.1.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/9.0.1...9.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-05 18:20:14 +00:00
Trenton Holmes
88a67c8703 Merge pull request #618 from paperless-ngx/dependabot/pip/dev/pikepdf-5.1.1
Bump pikepdf from 5.1.0 to 5.1.1
2022-04-05 11:14:21 -07:00
Felix E
ccf9b1291e Merge pull request #591 from paperless-ngx/feature-version-checker
Feature: Update checker
2022-04-05 20:11:21 +02:00
Quinn Casey
47dae716ae Merge pull request #599 from stumpylog/minor-bug-fixes
Fixes downloaded filename, add more consumer ignore settings
2022-04-05 09:56:54 -07:00
Quinn Casey
ea26e1c72f Merge pull request #576 from fantasticle/dev
Update regex date match patterns
2022-04-05 09:52:27 -07:00
Quinn Casey
e6d79f0673 Update docs, examples with new ignore settings 2022-04-05 09:21:18 -07:00
Quinn Casey
bf7002d0ae Merge pull request #616 from paperless-ngx/fix-save-vew-modal-errors
fix some api error displaying
2022-04-05 09:10:15 -07:00
Quinn Casey
cbae145da5 Merge pull request #564 from paperless-ngx/feature-password-protected-pdfs
Feature: Show prompt on password-protected pdfs
2022-04-05 08:59:29 -07:00
shamoon
a728502988 Update bug-report.yml 2022-04-04 15:30:40 -07:00
shamoon
9419f74d13 Update bug-report.yml 2022-04-04 15:30:15 -07:00
shamoon
50523c1566 Update bug-report.yml 2022-04-04 15:18:59 -07:00
shamoon
e9ef3e270d Update bug-report.yml 2022-04-04 15:18:12 -07:00
shamoon
9078f7beef Update bug-report.yml 2022-04-04 15:03:35 -07:00
shamoon
ac2c5abb09 Create config.yml 2022-04-04 15:02:41 -07:00
shamoon
a02235eb2b Delete other.md 2022-04-04 14:59:09 -07:00
shamoon
7658761940 Update bug-report.yml 2022-04-04 14:57:58 -07:00
shamoon
3f03f076cf Create bug-report.yml 2022-04-04 14:56:55 -07:00
shamoon
141e6de88f Delete bug_report.md 2022-04-04 14:56:21 -07:00
Trenton Holmes
88bbfe5961 Merge pull request #594 from danielBreitlauch/dev
FIX BUG: case-sensitive matching was not possible
2022-04-04 09:24:59 -07:00
Trenton Holmes
d60569b6d6 Quiets the pytest output 2022-04-04 17:59:37 +02:00
Michael Shamoon
91165e80ba Remove unused default 2022-04-04 07:05:00 -07:00
dependabot[bot]
a15f9552eb Bump pikepdf from 5.1.0 to 5.1.1
Bumps [pikepdf](https://github.com/pikepdf/pikepdf) from 5.1.0 to 5.1.1.
- [Release notes](https://github.com/pikepdf/pikepdf/releases)
- [Changelog](https://github.com/pikepdf/pikepdf/blob/master/docs/release_notes.rst)
- [Commits](https://github.com/pikepdf/pikepdf/compare/v5.1.0...v5.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-03 22:20:33 +00:00
Trenton Holmes
501d225f93 Merge pull request #557 from paperless-ngx/dependabot/pip/dev/sphinx-4.5.0
Bump sphinx from 4.4.0 to 4.5.0
2022-04-03 15:08:38 -07:00
dependabot[bot]
4942f244da Bump sphinx from 4.4.0 to 4.5.0
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.4.0...v4.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-03 20:35:06 +00:00
Trenton Holmes
1be5c9af56 Merge pull request #554 from paperless-ngx/dependabot/pip/dev/black-22.3.0
Bump black from 22.1.0 to 22.3.0
2022-04-03 13:14:03 -07:00
Trenton Holmes
fab7abb85b Merge pull request #622 from fantasticle/patch-2
fix 404 for post-consumption-example
2022-04-03 08:45:13 -07:00
fantasticle
818d383f2e Merge branch 'paperless-ngx:dev' into dev 2022-04-03 16:42:51 +02:00
shamoon
5fffa32630 disable download buttons while awaiting zip 2022-04-02 22:23:42 -07:00
Michael Shamoon
19d5feb483 Fix save view error for filter_rules
see #601
2022-04-02 19:49:58 -07:00
Michael Shamoon
199fc6be94 Properly display api errors on list filter & translate error message 2022-04-02 19:45:54 -07:00
Trenton Holmes
865729c033 Merge pull request #611 from stumpylog/bug-fix-install-script
Support docker-compose v2 in install
2022-04-02 15:36:52 -07:00
Trenton Holmes
6aa9071e24 Converts the docker compose check to use if statement 2022-04-02 14:34:19 -07:00
Trenton Holmes
6db3fc2eea Fixes an issue where the install script wouldn't recognize docker compose v2 command 2022-04-02 14:34:19 -07:00
shamoon
65ffaaa67c Merge pull request #623 from paperless-ngx/feature-fix-docker-tags
Fixes the Docker image tags
2022-04-02 13:46:23 -07:00
Michael Shamoon
440467e304 Allow notify user if update checking not explicitly set 2022-04-02 10:10:49 -07:00
fantasticle
07f2c9c1c6 Update docs/advanced_usage.rst
Co-authored-by: Felix E <felix@eckhofer.com>
2022-04-02 18:25:56 +02:00
Fantasticle
74422dd000 update name from master to main 2022-04-02 18:19:11 +02:00
Trenton Holmes
78d663bbb4 Fixes the Docker image tags 2022-04-02 08:48:58 -07:00
fantasticle
6cc2fa5306 fix 404 for post-consumption-example
still pointed to jonas' repository
2022-04-02 15:56:03 +02:00
Fantasticle
db0a58ea04 fix link for post-consumption-example, 404d to jonas 2022-04-02 15:52:32 +02:00
fantasticle
eba1e69e64 Merge branch 'paperless-ngx:dev' into dev 2022-04-02 15:49:35 +02:00
shamoon
a4e7877033 Update docs/configuration.rst for consistency
Co-authored-by: Quinn Casey <quinn@quinncasey.com>
2022-04-02 01:37:37 -07:00
Michael Shamoon
c62260ab02 Use GH api URL
Update configuration.rst
2022-04-02 01:36:37 -07:00
Michael Shamoon
b58550bb79 refactor to update_available 2022-04-02 01:36:19 -07:00
Michael Shamoon
d02c7df75c json parse version string 2022-04-02 01:36:19 -07:00
Michael Shamoon
6dbebf4806 Fix version string regex 2022-04-02 01:33:51 -07:00
Michael Shamoon
1019660f6a Add config variable for update check 2022-04-02 01:33:51 -07:00
Michael Shamoon
bfd11060ec Add version check to app frame 2022-04-02 01:33:51 -07:00
Michael Shamoon
7b6dccf5ef RemoteVersionService 2022-04-02 01:33:51 -07:00
Michael Shamoon
d76eccad1c remote_version API endpoint 2022-04-02 01:33:51 -07:00
Michael Shamoon
6f0ac7ae45 Update bootstrap-icons.svg 2022-04-02 01:33:50 -07:00
dependabot[bot]
8f17ed1eb9 Bump black from 22.1.0 to 22.3.0
Bumps [black](https://github.com/psf/black) from 22.1.0 to 22.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.1.0...22.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-02 08:29:39 +00:00
Daniel Breitlauch
2b5562e376 adding case-sensitive tests 2022-04-01 21:15:30 +02:00
Trenton Holmes
35b3216fee Fixes a couple of minor bugs in the downloading of documents and additional consumer ignore items 2022-04-01 11:12:18 -07:00
Daniel Breitlauch
6f8020e30d removing transformation to lowercase since it is not needed at all. 2022-04-01 18:26:01 +02:00
Daniel Breitlauch
0bee3901b6 Merge branch 'paperless-ngx:dev' into dev 2022-04-01 12:04:51 +02:00
Daniel Breitlauch
7106c68032 FIX BUG: case-sensitive matching was not possible 2022-04-01 12:03:05 +02:00
fantasticle
be707536bd Merge branch 'paperless-ngx:dev' into dev 2022-04-01 11:35:00 +02:00
Fantasticle
4754ac2bd1 remove unnecessary import 2022-03-31 21:25:58 +02:00
Fantasticle
3cca77e748 add more tests for regex date parser, remove duplicate name 2022-03-31 21:24:57 +02:00
Trenton Holmes
4ec1aaabe6 Adds settings for worker retry time, with what should be sensible default 2022-03-31 10:24:46 -07:00
Fantasticle
0baacbef98 update new regex pattern for second boundary 2022-03-31 09:37:15 +02:00
fantasticle
d8261b3359 add test for new regex 2022-03-30 23:18:03 +02:00
shamoon
ed2524cbbb Merge pull request #582 from paperless-ngx/fix-black-main-branch
[ci skip]
2022-03-30 10:44:33 -07:00
Trenton Holmes
76a4ae2aae Merge pull request #552 from stumpylog/bugfix-black
Bump version of black in CI/pre-commit

Revert "Merge pull request #552 from stumpylog/bugfix-black"

This reverts commit 9e8ac05f72.

Merge pull request #552 from stumpylog/bugfix-black

Bump version of black in CI/pre-commit
2022-03-30 10:35:02 -07:00
shamoon
f3d1bd25ad Merge pull request #577 from Prominence/patch-1
add ocr fails for XX to troubleshooting.rst
2022-03-30 06:42:19 -07:00
Alexey Zinchenko
3ed6d4bc7a Update troubleshooting.rst 2022-03-30 13:27:09 +03:00
fantasticle
1ecb26a3fb Update regex date match patterns 2022-03-30 12:19:30 +02:00
shamoon
15488fbfd0 Add note for target branch
[ci skip]
2022-03-30 00:03:48 -07:00
Michael Shamoon
85bf92ad2f Show prompt on password-protected pdfs 2022-03-29 15:38:09 -07:00
shamoon
94afd4f1e2 Merge pull request #561 from MichaelYochpaz/main
Fix reference from Paperless-ngx to Paperless-ng [ci skip]
2022-03-29 11:15:56 -07:00
Michael
1218944680 Fix reference from Paperless-ngx to Paperless-ng 2022-03-29 21:09:09 +03:00
shamoon
eda69dc881 Merge pull request #537 from Stormheg/patch-1
Fix typo in api documentation
2022-03-26 14:42:34 -07:00
Storm Heg
500e5c41ff Fix typo in api.rst 2022-03-26 22:34:50 +01:00
130 changed files with 3801 additions and 1121 deletions

91
.github/ISSUE_TEMPLATE/bug-report.yml vendored Normal file
View File

@@ -0,0 +1,91 @@
name: Bug report
description: Something is not working
title: "[BUG] Concise description of the issue"
labels: ["bug", "unconfirmed"]
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/#/#paperless:adnidor.de).
Before opening an issue, please check [the documentation](https://paperless-ngx.readthedocs.io/en/latest/troubleshooting.html) and see if it helps you resolve your issue. Please also make sure that you followed the installation instructions.
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). Remember that Paperless successfully runs on a variety of different systems. If Paperless-ngx does not start, it's likely an issue with your system, not an issue of Paperless-ngx.
Finally, please search issues and discussions before opening a new bug report.
- type: textarea
id: description
attributes:
label: Description
description: A clear and concise description of what the bug is.
placeholder: Currently...
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
placeholder: In this situation...
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Steps to reproduce
description: Steps to reproduce the behavior
placeholder: "1. Go to '...', 2. Click on '....', 3. See error"
validations:
required: true
- type: textarea
id: logs
attributes:
label: Webserver logs
description: If available, post any logs from the web server related to your issue.
render: bash
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem.
- type: input
id: version
attributes:
label: Paperless-ngx version
placeholder: e.g. 1.6.0
validations:
required: true
- type: input
id: host-os
attributes:
label: Host OS
description: Host OS of the machine running paperless-ngx
placeholder: e.g. Archlinux / Ubuntu 20.04
validations:
required: true
- type: dropdown
id: install-method
attributes:
label: Installation method
options:
- Docker
- Bare metal
- Other (please describe above)
validations:
required: true
- type: input
id: browser
attributes:
label: Browser
description: Which browser you are using, if relevant
placeholder: e.g. Chrome, Safari
- type: input
id: config-changes
attributes:
label: Configuration changes
description: Any configuration changes you made in `docker-compose.yml`, `docker-compose.env` or `paperless.conf`.
- type: input
id: other
attributes:
label: Other
description: Any other relevant details

View File

@@ -1,50 +0,0 @@
---
name: Bug report
about: Something is not working
title: '[BUG] Concise description of the issue'
labels: ''
assignees: ''
---
<!---
=> Before opening an issue, please check the documentation and see if it helps you resolve your issue: https://paperless-ngx.readthedocs.io/en/latest/troubleshooting.html
=> Please also make sure that you followed the installation instructions.
=> Please search the issues and look for similar issues before opening a bug report.
=> If you would like to submit a feature request please submit one under https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests
=> If you encounter issues while installing of configuring Paperless-ngx, please post that in the "Support" section of the discussions. Remember that Paperless successfully runs on a variety of different systems. If paperless does not start, it's probably an issue with your system, and not an issue of paperless.
=> Don't remove the [BUG] prefix from the title.
-->
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Webserver logs**
```
If available, post any logs from the web server related to your issue.
```
**Relevant information**
- Host OS of the machine running paperless: [e.g. Archlinux / Ubuntu 20.04]
- Browser [e.g. chrome, safari]
- Version [e.g. 1.0.0]
- Installation method: [docker / bare metal]
- Any configuration changes you made in `docker-compose.yml`, `docker-compose.env` or `paperless.conf`.

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: 🤔 Questions and Help
url: https://github.com/paperless-ngx/paperless-ngx/discussions
about: This issue tracker is not for support questions. Please refer to our Discussions.
- name: 💬 Chat
url: https://matrix.to/#/#paperless:adnidor.de
about: Want to discuss Paperless-ngx with others? Check out our chat.
- name: 🚀 Feature Request
url: https://github.com/paperless-ngx/paperless-ngx/discussions/new?category=feature-requests
about: Remember to search for existing feature requests and "up-vote" any you like

View File

@@ -1,19 +0,0 @@
---
name: Other
about: Anything that is not a feature request or bug.
title: '[Other] Title of your issue'
labels: ''
assignees: ''
---
<!--
=> Discussions, Feedback and other suggestions belong in the "Discussion" section and not on the issue tracker.
=> If you would like to submit a feature request please submit one under https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests
=> If you encounter issues while installing of configuring Paperless-ngx, please post that in the "Support" section of the discussions. Remember that Paperless successfully runs on a variety of different systems. If paperless does not start, it's probably is an issue with your system, and not an issue of paperless.
=> Don't remove the [Other] prefix from the title.
-->

View File

@@ -1,23 +1,15 @@
<!--
<!--
Note: All PRs with code changes should be targeted to the `dev` branch, pure documentation changes can target `main`
-->
## Proposed change
<!--
Please include a summary of the change and which issue is fixed (if any) and any relevant motivation / context. List any dependencies that are required for this change. If appropriate, please include an explanation of how your poposed change can be tested. Screenshots and / or videos can also be helpful if appropriate.
Please include a summary of the change and which issue is fixed (if any) and any relevant motivation / context. List any dependencies that are required for this change. If appropriate, please include an explanation of how your proposed change can be tested. Screenshots and / or videos can also be helpful if appropriate.
-->
Fixes # (issue)
<!--
Please also tag the relevant team to help with review. You can tag any of the following:
@paperless-ngx/backend (Python / django, database, etc.)
@paperless-ngx/frontend (JavaScript/Typescript, HTML, CSS, etc.)
@paperless-ngx/ci-cd (GitHub Actions, deployment)
@paperless-ngx/test (General testing for larger PRs)
-->
## Type of change
<!--

37
.github/release-drafter.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
categories:
- title: 'Breaking Changes'
labels:
- 'breaking-change'
- title: 'Features'
labels:
- 'enhancement'
- title: 'Bug Fixes'
labels:
- 'bug'
- title: 'Documentation'
label: 'documentation'
- title: 'Maintenance'
labels:
- 'chore'
- 'deployment'
- 'translation'
- title: 'Dependencies'
collapse-after: 3
label: 'dependencies'
include-labels:
- 'enhancement'
- 'bug'
- 'chore'
- 'deployment'
- 'translation'
- 'dependencies'
replacers: # Changes "Feature: Update checker" to "Update checker"
- search: '/Feature:|Feat:|\[feature\]/gi'
replace: ''
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&#@'
tag-prefix: "ngx-"
template: |
# Changelog
$CHANGES

7
.github/stale.yml vendored
View File

@@ -2,11 +2,8 @@
daysUntilStale: 30
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- fixpending
onlyLabels:
- unconfirmed
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable

View File

@@ -132,7 +132,7 @@ jobs:
name: Install system dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript optipng
sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript optipng libzbar0 poppler-utils
-
name: Install Python dependencies
run: |
@@ -185,6 +185,9 @@ jobs:
# build and push image to docker hub.
build-docker-image:
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || startsWith(github.ref, 'refs/tags/ngx-') || startsWith(github.ref, 'refs/tags/beta-'))
concurrency:
group: ${{ github.workflow }}-build-docker-image-${{ github.ref }}
cancel-in-progress: true
runs-on: ubuntu-20.04
needs: [tests-backend, tests-frontend]
steps:
@@ -195,10 +198,8 @@ jobs:
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=match,pattern=ngx-(\d.\d.\d),group=1
type=semver,pattern=ngx-{{version}}
type=semver,pattern=ngx-{{major}}.{{minor}}
type=ref
type=ref,event=branch
type=ref,event=tag
-
name: Checkout
uses: actions/checkout@v3
@@ -328,24 +329,22 @@ jobs:
if [[ $GITHUB_REF == refs/tags/ngx-* ]]; then
echo ::set-output name=version::${GITHUB_REF#refs/tags/ngx-}
echo ::set-output name=prerelease::false
echo ::set-output name=body::"For a complete list of changes, see the changelog at https://paperless-ngx.readthedocs.io/en/latest/changelog.html"
elif [[ $GITHUB_REF == refs/tags/beta-* ]]; then
echo ::set-output name=version::${GITHUB_REF#refs/tags/beta-}
echo ::set-output name=prerelease::true
echo ::set-output name=body::"For a complete list of changes, see the changelog at https://github.com/paperless-ngx/paperless-ngx/blob/beta/docs/changelog.rst"
fi
-
name: Create release
id: create_release
uses: actions/create-release@v1
name: Create Release and Changelog
id: create-release
uses: release-drafter/release-drafter@v5
with:
name: Paperless-ngx ${{ steps.get_version.outputs.version }}
tag: ngx-${{ steps.get_version.outputs.version }}
version: ${{ steps.get_version.outputs.version }}
prerelease: ${{ steps.get_version.outputs.prerelease }}
publish: true # ensures release is not marked as draft
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ngx-${{ steps.get_version.outputs.version }}
release_name: Paperless-ngx ${{ steps.get_version.outputs.version }}
draft: false
prerelease: ${{ steps.get_version.outputs.prerelease }}
body: ${{ steps.get_version.outputs.body }}
-
name: Upload release archive
id: upload-release-asset
@@ -353,7 +352,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
upload_url: ${{ steps.create-release.outputs.upload_url }}
asset_path: ./paperless-ngx.tar.xz
asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz
asset_content_type: application/x-xz

View File

@@ -5,7 +5,7 @@
repos:
# General hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
rev: v4.2.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: "v2.6.1"
rev: "v2.6.2"
hooks:
- id: prettier
types_or:
@@ -47,7 +47,7 @@ repos:
- id: yesqa
exclude: "(migrations)"
- repo: https://github.com/asottile/add-trailing-comma
rev: "v2.2.1"
rev: "v2.2.2"
hooks:
- id: add-trailing-comma
exclude: "(migrations)"

10
CODEOWNERS Normal file
View File

@@ -0,0 +1,10 @@
/.github/workflows/ @paperless-ngx/ci-cd
/docker/ @paperless-ngx/ci-cd
/scripts/ @paperless-ngx/ci-cd
/src-ui/ @paperless-ngx/frontend
/src/ @paperless-ngx/backend
Pipfile* @paperless-ngx/backend
*.py @paperless-ngx/backend
requirements.txt @paperless-ngx/backend

View File

@@ -6,7 +6,7 @@ WORKDIR /src/src-ui
RUN npm update npm -g && npm ci --no-optional
RUN ./node_modules/.bin/ng build --configuration production
FROM ghcr.io/paperless-ngx/builder/ngx-base:1.0 as main-app
FROM ghcr.io/paperless-ngx/builder/ngx-base:1.7.0 as main-app
LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>"
LABEL org.opencontainers.image.documentation="https://paperless-ngx.readthedocs.io/en/latest/"

View File

@@ -22,7 +22,7 @@ gunicorn = "*"
imap-tools = "*"
langdetect = "*"
pathvalidate = "*"
pillow = "~=9.0"
pillow = "~=9.1"
# Any version update to pikepdf requires a base image update
pikepdf = "~=5.1"
python-gnupg = "*"
@@ -51,6 +51,8 @@ concurrent-log-handler = "*"
"backports.zoneinfo" = {version = "*", markers = "python_version < '3.9'"}
"importlib-resources" = {version = "*", markers = "python_version < '3.9'"}
zipp = {version = "*", markers = "python_version < '3.9'"}
pyzbar = "*"
pdf2image = "*"
[dev-packages]
coveralls = "*"
@@ -62,7 +64,7 @@ pytest-django = "*"
pytest-env = "*"
pytest-sugar = "*"
pytest-xdist = "*"
sphinx = "~=4.4.0"
sphinx = "~=4.5.0"
sphinx_rtd_theme = "*"
tox = "*"
black = "*"

348
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "f33c0aeb0cb880b444efd367ad5b47358dde2a9b18b55dcd6943dd81f6c7e2a6"
"sha256": "9573af313c811561d467d814c52c6bd1439bc48e3b31d7f56afed5f0ebe4b648"
},
"pipfile-spec": 6,
"requires": {},
@@ -68,10 +68,10 @@
},
"autobahn": {
"hashes": [
"sha256:60e1f4c602aacd052ffe3d46ae40b6b75f8286b3c46922c213b523162e58c17e"
"sha256:58a887c7a196bb08d8b6624cb3695f493a9e5c9f00fd350d8d6f829b47ff9036"
],
"markers": "python_version >= '3.7'",
"version": "==22.2.2"
"version": "==22.3.2"
},
"automat": {
"hashes": [
@@ -99,7 +99,6 @@
"sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac",
"sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"
],
"index": "pypi",
"markers": "python_version < '3.9'",
"version": "==0.2.1"
},
@@ -207,11 +206,11 @@
},
"click": {
"hashes": [
"sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1",
"sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"
"sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e",
"sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"
],
"markers": "python_version >= '3.6'",
"version": "==8.0.4"
"markers": "python_version >= '3.7'",
"version": "==8.1.2"
},
"coloredlogs": {
"hashes": [
@@ -280,11 +279,11 @@
},
"django": {
"hashes": [
"sha256:1239218849e922033a35d2a2f777cb8bee18bd725416744074f455f34ff50d0c",
"sha256:77ff2e7050e3324c9b67e29b6707754566f58514112a9ac73310f60cd5261930"
"sha256:07c8638e7a7f548dc0acaaa7825d84b7bd42b10e8d22268b3d572946f1e9b687",
"sha256:4e8177858524417563cc0430f29ea249946d831eacb0068a1455686587df40b5"
],
"index": "pypi",
"version": "==4.0.3"
"version": "==4.0.4"
},
"django-cors-headers": {
"hashes": [
@@ -488,16 +487,15 @@
},
"img2pdf": {
"hashes": [
"sha256:8e51c5043efa95d751481b516071a006f87c2a4059961a9ac43ec238915de09f"
"sha256:8ec898a9646523fd3862b154f3f47cd52609c24cc3e2dc1fb5f0168f0cbe793c"
],
"version": "==0.4.3"
"version": "==0.4.4"
},
"importlib-resources": {
"hashes": [
"sha256:1b93238cbf23b4cde34240dd8321d99e9bf2eb4bc91c0c99b2886283e7baad85",
"sha256:a9dd72f6cc106aeb50f6e66b86b69b454766dd6e39b69ac68450253058706bcc"
],
"index": "pypi",
"markers": "python_version < '3.9'",
"version": "==5.6.0"
},
@@ -673,11 +671,11 @@
},
"ocrmypdf": {
"hashes": [
"sha256:201ed2f589f851be73908fce35fbb6fb05e4739289d3cd8765f9519f49ea1cd9",
"sha256:f42e60bc2b6534634dd08928584275b1c556dc875c849650afcc38f7da9e2856"
"sha256:7f0a6165b80ba1b37ce5943cf5b4faf93bf98c04c8f5157ef83c5f292491485f",
"sha256:d52410bc38cf5b66da27668e38c66ac41fd3136457c1ec388b311f0a78ee213c"
],
"index": "pypi",
"version": "==13.4.1"
"version": "==13.4.2"
},
"packaging": {
"hashes": [
@@ -695,87 +693,98 @@
"index": "pypi",
"version": "==2.5.0"
},
"pdfminer.six": {
"pdf2image": {
"hashes": [
"sha256:0351f17d362ee2d48b158be52bcde6576d96460efd038a3e89a043fba6d634d7",
"sha256:d3efb75c0249b51c1bf795e3a8bddf1726b276c77bf75fb136adea471ee2825b"
"sha256:84f79f2b8fad943e36323ea4e937fcb05f26ded0caa0a01181df66049e42fb65",
"sha256:d58ed94d978a70c73c2bb7fdf8acbaf2a7089c29ff8141be5f45433c0c4293bb"
],
"index": "pypi",
"version": "==20211012"
"version": "==1.16.0"
},
"pdfminer.six": {
"hashes": [
"sha256:af0630f98a292bad4170f54e80f82ca81b916dd0b2c996437ec45c02f11d8762",
"sha256:eff2ce0abeaa4df94dc3461f70eab104487c7b4a2b3c7e9fd0aeec6c5f44d6a6"
],
"index": "pypi",
"version": "==20220319"
},
"pikepdf": {
"hashes": [
"sha256:1567b74d15c16d1bef56a6d5f56fb6a35f4cc022ae252d35f33f56bb16b87966",
"sha256:179f24b4a4d0e89c7f592d85ba4daf7d34c709eb0a691425b881413fdce70734",
"sha256:22201b06db627a86cc91c1b76491dd9c57fce2df4e3bc8ba700ff66f7f7da04a",
"sha256:3e1a0b9ecf5d4aa106c3c0db558952f9a15f343f812c3bba6d6e1a56e25224ed",
"sha256:45ce2479e5ba74896ef389abf92831d7fbb34f25e6557adb9115710223a0bb13",
"sha256:4fa5c8494b011b19bd198dd9c3cd94676b905360b2231ad35171ae586644b823",
"sha256:559b3d502cc1a6813cbcb0766b0797fec034303f8f9b0734cf938fb1734e2b74",
"sha256:61731fceaab99850bc7045232301c2332bba727f78b53f7038fcbdcaf3d64309",
"sha256:6460d489341e7f8dc3f6b0dbf1f5a75a918ebd1e0ecb4c2b00877264a68ee1f4",
"sha256:716ca6fc8947502cb73a517c884066afa132ca998e085a309b8fb8c5796d6277",
"sha256:726450eb9baaad5697687c2621d481c80f868b68c06d2cff4be3f6a7ce28cfee",
"sha256:7e9c247ca384ad1606281eda4d841bc8cbff90875979ac3b520bcc5404bf9b26",
"sha256:8333d813b452daa4a066e135fd7ab6f7c07ccc02cb8381455d61d74f0a0ad0fe",
"sha256:83d0af374b103934de033f096205143fa9d6f78e789ba78c8aa6dfb0e5b73bc3",
"sha256:878c1c95298486d8cea7e8236c70613e7eae1426cbf362c3883ecd06e8f9c2d9",
"sha256:9abef24d929c4a08292dc4be4d6c4e5bf93832e747eef5f39e854348a332f46a",
"sha256:a474241dbeda246356b6448f607f4fb9fee5b9f5cb19511a768b88b471325865",
"sha256:a553fd06e5f6e78c5e840d066e7c8b1a988e16489fe0bd4a143ca601809ea4dd",
"sha256:a6154c6bb7606ef534444f54271a410a6337cee54dcdef20f0fa0686f622cf50",
"sha256:ac0082379cf6aa6c0c682bee4a3d2adbe6d60b9125e3632876d7c5e9665c07ab",
"sha256:c22e3fbfb76ad7838dde82c8d9fafd4c09fd419cee531b31d1b48a07344ac2b4",
"sha256:d42c52ff2e8fb00fad14182f67a8f076f38c75a874123b6776aa5c6af09e1126",
"sha256:d6ef14b722f80351e15c9163e0aa1f1df84f065c080765f8232ec51af6bd3368",
"sha256:d71a38445c80972572248815ebe61f9c814c53925a6b83b6596f3482a98a5f25",
"sha256:e81ebbdd53257f411827bbb301900cdbdca34ca60b4f7248f80c6e6980062498",
"sha256:f52f4ed655c25c408e8454cbcf0e7223b62f635d1e8ab738fd0c2d46531d28ed",
"sha256:fb407ae5820ee0bf71022d5a8f539d709dac590443270a13baf6a8872c76d46f"
"sha256:01be838a44430c4be84b748a33950fed09892472934a8041596c11189f365f7f",
"sha256:0cc95ef470169dfa5acc9196299bdba236716234a0d8b2746e2a563bc6f1f456",
"sha256:13e72d0aeeb3fc452569a3f7994acdd007de9aad804ced734d57cec269261b8b",
"sha256:2873503522ef26a09a6020c29c2efd221fa2ddc31e83bd902be27d317144cf63",
"sha256:2d5d6d3248b33ca5961d84bc3121a299cd27237fad56868d815e381c9a98d3d1",
"sha256:2f62e6c7bcf5d631e6ea74cf861f3e816f587c6ccb4ecbf6ac862e088ba2e4ac",
"sha256:51694d3d2f90510da6a8d7a4d07313ca868b373fffec6de270d9bbff1ce37180",
"sha256:5c23cbd7ae71f08fb5b5d9660eb0bc61abf345ada01bea6e1b6884c4261e17d6",
"sha256:6371bf02a436be2b7c63322b83a8e47523f2cd16438b2e93d546c7caf9ae308d",
"sha256:657293b74af8c7cf03f9905218a7935b26a4f3006803016b40b3db78e04cb35c",
"sha256:680d47377bb9fd6a36b6a81464ee269b4b29cbf29a84ae4f2ab8f6ea3665bf69",
"sha256:710535c679ab0d7b8249f72247832773e7a9a121dfbe9cad7f6465bd9bb45fae",
"sha256:7b4d7c09036d863915cb01007ca183d6fe64e2d57c0472453097bc9e029a58fb",
"sha256:978b6388ae99a024bdcae5a322c68e90c187cb568d09d43e6586b3479267121d",
"sha256:9917a03d500aab72715a9236136af7a5c8c7b26c034bf71ebdf028e177f0d25f",
"sha256:996faa6b119488f96d7271672a22af86e56e5544ec6b8eae6cd7d4432c70ae2d",
"sha256:9bac9e9d6b28dc0cc5a554051f183fbd070d0f9fe63c4e9aca939b8c44a5bb4d",
"sha256:aac14061de06843759ea6f5777fd8d7b71af808ed9264f57483a3311a09788ab",
"sha256:ad5361c3669fc0c8dbaf8fa0a590bddf59fad256bb2c527d5ce5cf991743a240",
"sha256:bc40b30c37f8f7c5bef873eca1f04e91ce34b6b74507d8d0019238a17d281fdc",
"sha256:bd9faae19787a5d05b9fcbe84d7cfe4d44e318068e06eca18906b9dba45425b6",
"sha256:c64e7905ec438b7a6c12626f2859df87f471892fab75b65b1441d9e1b38b4dde",
"sha256:d4db409b21a8ec0d3a79d2bbd894b997b13223c9ccf341cdc31b64360f1ee4c7",
"sha256:e0b635d6d9faefb4d0d32722279b8eb4e4d5d7b596c426f3433343de65e0c772",
"sha256:e62e9e8afe77fe2f06715faf10f38a4810d282d66f1e9e05208bb8d9723e6acf",
"sha256:f85d309bcfeeb3e2d344346a5050bfc41e332f19d390f79c20e4fc7de4b10a17",
"sha256:fe3fc2efe498aba6204b85c17c6a5d54ab7303354ecc5c3da624a6b6af0b3406"
],
"index": "pypi",
"version": "==5.1.0"
"version": "==5.1.1"
},
"pillow": {
"hashes": [
"sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97",
"sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049",
"sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c",
"sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae",
"sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28",
"sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030",
"sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56",
"sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976",
"sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e",
"sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e",
"sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f",
"sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b",
"sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a",
"sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e",
"sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa",
"sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7",
"sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00",
"sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838",
"sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360",
"sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b",
"sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a",
"sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd",
"sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4",
"sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70",
"sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204",
"sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc",
"sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b",
"sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669",
"sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7",
"sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e",
"sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c",
"sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092",
"sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c",
"sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5",
"sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"
"sha256:01ce45deec9df310cbbee11104bae1a2a43308dd9c317f99235b6d3080ddd66e",
"sha256:0c51cb9edac8a5abd069fd0758ac0a8bfe52c261ee0e330f363548aca6893595",
"sha256:17869489de2fce6c36690a0c721bd3db176194af5f39249c1ac56d0bb0fcc512",
"sha256:21dee8466b42912335151d24c1665fcf44dc2ee47e021d233a40c3ca5adae59c",
"sha256:25023a6209a4d7c42154073144608c9a71d3512b648a2f5d4465182cb93d3477",
"sha256:255c9d69754a4c90b0ee484967fc8818c7ff8311c6dddcc43a4340e10cd1636a",
"sha256:35be4a9f65441d9982240e6966c1eaa1c654c4e5e931eaf580130409e31804d4",
"sha256:3f42364485bfdab19c1373b5cd62f7c5ab7cc052e19644862ec8f15bb8af289e",
"sha256:3fddcdb619ba04491e8f771636583a7cc5a5051cd193ff1aa1ee8616d2a692c5",
"sha256:463acf531f5d0925ca55904fa668bb3461c3ef6bc779e1d6d8a488092bdee378",
"sha256:4fe29a070de394e449fd88ebe1624d1e2d7ddeed4c12e0b31624561b58948d9a",
"sha256:55dd1cf09a1fd7c7b78425967aacae9b0d70125f7d3ab973fadc7b5abc3de652",
"sha256:5a3ecc026ea0e14d0ad7cd990ea7f48bfcb3eb4271034657dc9d06933c6629a7",
"sha256:5cfca31ab4c13552a0f354c87fbd7f162a4fafd25e6b521bba93a57fe6a3700a",
"sha256:66822d01e82506a19407d1afc104c3fcea3b81d5eb11485e593ad6b8492f995a",
"sha256:69e5ddc609230d4408277af135c5b5c8fe7a54b2bdb8ad7c5100b86b3aab04c6",
"sha256:6b6d4050b208c8ff886fd3db6690bf04f9a48749d78b41b7a5bf24c236ab0165",
"sha256:7a053bd4d65a3294b153bdd7724dce864a1d548416a5ef61f6d03bf149205160",
"sha256:82283af99c1c3a5ba1da44c67296d5aad19f11c535b551a5ae55328a317ce331",
"sha256:8782189c796eff29dbb37dd87afa4ad4d40fc90b2742704f94812851b725964b",
"sha256:8d79c6f468215d1a8415aa53d9868a6b40c4682165b8cb62a221b1baa47db458",
"sha256:97bda660702a856c2c9e12ec26fc6d187631ddfd896ff685814ab21ef0597033",
"sha256:a325ac71914c5c043fa50441b36606e64a10cd262de12f7a179620f579752ff8",
"sha256:a336a4f74baf67e26f3acc4d61c913e378e931817cd1e2ef4dfb79d3e051b481",
"sha256:a598d8830f6ef5501002ae85c7dbfcd9c27cc4efc02a1989369303ba85573e58",
"sha256:a5eaf3b42df2bcda61c53a742ee2c6e63f777d0e085bbc6b2ab7ed57deb13db7",
"sha256:aea7ce61328e15943d7b9eaca87e81f7c62ff90f669116f857262e9da4057ba3",
"sha256:af79d3fde1fc2e33561166d62e3b63f0cc3e47b5a3a2e5fea40d4917754734ea",
"sha256:c24f718f9dd73bb2b31a6201e6db5ea4a61fdd1d1c200f43ee585fc6dcd21b34",
"sha256:c5b0ff59785d93b3437c3703e3c64c178aabada51dea2a7f2c5eccf1bcf565a3",
"sha256:c7110ec1701b0bf8df569a7592a196c9d07c764a0a74f65471ea56816f10e2c8",
"sha256:c870193cce4b76713a2b29be5d8327c8ccbe0d4a49bc22968aa1e680930f5581",
"sha256:c9efef876c21788366ea1f50ecb39d5d6f65febe25ad1d4c0b8dff98843ac244",
"sha256:de344bcf6e2463bb25179d74d6e7989e375f906bcec8cb86edb8b12acbc7dfef",
"sha256:eb1b89b11256b5b6cad5e7593f9061ac4624f7651f7a8eb4dfa37caa1dfaa4d0",
"sha256:ed742214068efa95e9844c2d9129e209ed63f61baa4d54dbf4cf8b5e2d30ccf2",
"sha256:f401ed2bbb155e1ade150ccc63db1a4f6c1909d3d378f7d1235a44e90d75fb97",
"sha256:fb89397013cf302f282f0fc998bb7abf11d49dcff72c8ecb320f76ea6e2c5717"
],
"index": "pypi",
"version": "==9.0.1"
"version": "==9.1.0"
},
"pluggy": {
"hashes": [
@@ -862,11 +871,11 @@
},
"pyparsing": {
"hashes": [
"sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea",
"sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"
"sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954",
"sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"
],
"markers": "python_version >= '3.6'",
"version": "==3.0.7"
"markers": "python_full_version >= '3.6.8'",
"version": "==3.0.8"
},
"python-dateutil": {
"hashes": [
@@ -959,6 +968,15 @@
],
"version": "==6.0"
},
"pyzbar": {
"hashes": [
"sha256:13e3ee5a2f3a545204a285f41814d5c0db571967e8d4af8699a03afc55182a9c",
"sha256:4559628b8192feb25766d954b36a3753baaf5c97c03135aec7e4a026036b475d",
"sha256:8f4c5264c9c7c6b9f20d01efc52a4eba1ded47d9ba857a94130afe33703eb518"
],
"index": "pypi",
"version": "==0.1.9"
},
"redis": {
"hashes": [
"sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2",
@@ -1173,11 +1191,11 @@
},
"setuptools": {
"hashes": [
"sha256:89eef7b71423ab7fccc7dfafdc145410ef170c4a89567427f932448135e08cdf",
"sha256:92b15f45ab164eb0c410d2bf661a6e9d15e3b78c0dffb0325f2bf0f313071cae"
"sha256:26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8",
"sha256:47c7b0c0f8fc10eec4cf1e71c6fdadf8decaa74ffa087e68cd1c20db7ad6a592"
],
"markers": "python_version >= '3.7'",
"version": "==61.1.1"
"version": "==62.1.0"
},
"six": {
"hashes": [
@@ -1220,22 +1238,22 @@
},
"tqdm": {
"hashes": [
"sha256:4230a49119a416c88cc47d0d2d32d5d90f1a282d5e497d49801950704e49863d",
"sha256:6461b009d6792008d0000e1b0c7ca50195ec78c0e808a3a6b668a56a3236c3a5"
"sha256:40be55d30e200777a307a7585aee69e4eabb46b4ec6a4b4a5f2d9f11e7d5408d",
"sha256:74a2cdefe14d11442cedf3ba4e21a3b84ff9a2dbdc6cfae2c34addb2a14a5ea6"
],
"index": "pypi",
"version": "==4.63.1"
"version": "==4.64.0"
},
"twisted": {
"extras": [
"tls"
],
"hashes": [
"sha256:57f32b1f6838facb8c004c89467840367ad38e9e535f8252091345dba500b4f2",
"sha256:5c63c149eb6b8fe1e32a0215b1cef96fabdba04f705d8efb9174b1ccf5b49d49"
"sha256:a047990f57dfae1e0bd2b7df2526d4f16dcdc843774dc108b78c52f2a5f13680",
"sha256:f9f7a91f94932477a9fc3b169d57f54f96c6e74a23d78d9ce54039a7f48928a2"
],
"markers": "python_full_version >= '3.6.7'",
"version": "==22.2.0"
"version": "==22.4.0"
},
"txaio": {
"hashes": [
@@ -1263,11 +1281,11 @@
},
"tzlocal": {
"hashes": [
"sha256:0f28015ac68a5c067210400a9197fc5d36ba9bc3f8eaf1da3cbd59acdfed9e09",
"sha256:28ba8d9fcb6c9a782d6e0078b4f6627af1ea26aeaa32b4eab5324abc7df4149f"
"sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745",
"sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"
],
"markers": "python_version >= '3.6'",
"version": "==4.1"
"version": "==4.2"
},
"urllib3": {
"hashes": [
@@ -1341,10 +1359,10 @@
},
"watchgod": {
"hashes": [
"sha256:4ba20c2fa3e63df706ab50e694b9453b05395fadb7cbbfd984d71fb1547d485d",
"sha256:c12d15f3df7d11e740704e45398277f75f1d78f46ad59ca9d7505bfd8b8d3086"
"sha256:2f3e8137d98f493ff58af54ea00f4d1433a6afe2ed08ab331a657df468c6bfce",
"sha256:cb11ff66657befba94d828e3b622d5fb76f22fbda1376f355f3e6e51e97d9450"
],
"version": "==0.8.1"
"version": "==0.8.2"
},
"wcwidth": {
"hashes": [
@@ -1425,12 +1443,11 @@
},
"zipp": {
"hashes": [
"sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d",
"sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"
"sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad",
"sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"
],
"index": "pypi",
"markers": "python_version < '3.9'",
"version": "==3.7.0"
"version": "==3.8.0"
},
"zope.interface": {
"hashes": [
@@ -1516,32 +1533,32 @@
},
"black": {
"hashes": [
"sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2",
"sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71",
"sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6",
"sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5",
"sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912",
"sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866",
"sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d",
"sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0",
"sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321",
"sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8",
"sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd",
"sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3",
"sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba",
"sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0",
"sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5",
"sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a",
"sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28",
"sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c",
"sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1",
"sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab",
"sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f",
"sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61",
"sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3"
"sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b",
"sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176",
"sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09",
"sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a",
"sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015",
"sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79",
"sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb",
"sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20",
"sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464",
"sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968",
"sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82",
"sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21",
"sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0",
"sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265",
"sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b",
"sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a",
"sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72",
"sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce",
"sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0",
"sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a",
"sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163",
"sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad",
"sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"
],
"index": "pypi",
"version": "==22.1.0"
"version": "==22.3.0"
},
"certifi": {
"hashes": [
@@ -1568,15 +1585,15 @@
},
"click": {
"hashes": [
"sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1",
"sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"
"sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e",
"sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"
],
"markers": "python_version >= '3.6'",
"version": "==8.0.4"
"markers": "python_version >= '3.7'",
"version": "==8.1.2"
},
"coverage": {
"extras": [
"toml"
],
"hashes": [
"sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9",
@@ -1671,11 +1688,11 @@
},
"faker": {
"hashes": [
"sha256:5536ceb63380f0d598c026b7c330c17d719a19d1a495e9397ee8f5259420a696",
"sha256:85ed0cb379e3b7414bdb6b484994beaf9bddc74472c8c35f743c16cf5fc0c314"
"sha256:188961065fb5c78ea639f42176f55100f72c90c3a3179ac6c955c4bd712b0511",
"sha256:7758ece2593ce603db117db3d27393c31f4af03f783e176f3f0e14839a4f3426"
],
"markers": "python_version >= '3.6'",
"version": "==13.3.3"
"version": "==13.3.4"
},
"filelock": {
"hashes": [
@@ -1709,14 +1726,6 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.3.0"
},
"importlib-metadata": {
"hashes": [
"sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6",
"sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"
],
"markers": "python_version < '3.10'",
"version": "==4.11.3"
},
"iniconfig": {
"hashes": [
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
@@ -1825,11 +1834,11 @@
},
"pre-commit": {
"hashes": [
"sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616",
"sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"
"sha256:02226e69564ebca1a070bd1f046af866aa1c318dbc430027c50ab832ed2b73f2",
"sha256:5d445ee1fa8738d506881c5d84f83c62bb5be6b2838e32207433647e8e5ebe10"
],
"index": "pypi",
"version": "==2.17.0"
"version": "==2.18.1"
},
"py": {
"hashes": [
@@ -1857,11 +1866,11 @@
},
"pyparsing": {
"hashes": [
"sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea",
"sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"
"sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954",
"sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"
],
"markers": "python_version >= '3.6'",
"version": "==3.0.7"
"markers": "python_full_version >= '3.6.8'",
"version": "==3.0.8"
},
"pytest": {
"hashes": [
@@ -1995,11 +2004,11 @@
},
"sphinx": {
"hashes": [
"sha256:5da895959511473857b6d0200f56865ed62c31e8f82dd338063b84ec022701fe",
"sha256:6caad9786055cb1fa22b4a365c1775816b876f91966481765d7d50e9f0dd35cc"
"sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6",
"sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226"
],
"index": "pypi",
"version": "==4.4.0"
"version": "==4.5.0"
},
"sphinx-rtd-theme": {
"hashes": [
@@ -2087,14 +2096,6 @@
"index": "pypi",
"version": "==3.24.5"
},
"typing-extensions": {
"hashes": [
"sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42",
"sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"
],
"markers": "python_version >= '3.6'",
"version": "==4.1.1"
},
"urllib3": {
"hashes": [
"sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14",
@@ -2105,20 +2106,11 @@
},
"virtualenv": {
"hashes": [
"sha256:1e8588f35e8b42c6ec6841a13c5e88239de1e6e4e4cedfd3916b306dc826ec66",
"sha256:8e5b402037287126e81ccde9432b95a8be5b19d36584f64957060a3488c11ca8"
"sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a",
"sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==20.14.0"
},
"zipp": {
"hashes": [
"sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d",
"sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"
],
"index": "pypi",
"markers": "python_version < '3.9'",
"version": "==3.7.0"
"version": "==20.14.1"
}
}
}

View File

@@ -22,6 +22,10 @@
# Docker setup does not use the configuration file.
# A few commonly adjusted settings are provided below.
# This is required if you will be exposing Paperless-ngx on a public domain
# (if doing so please consider security measures such as reverse proxy)
#PAPERLESS_URL=https://paperless.example.com
# Adjust this key if you plan to make paperless available publicly. It should
# be a very long sequence of random characters. You don't need to remember it.
#PAPERLESS_SECRET_KEY=change-me

View File

@@ -69,10 +69,11 @@ services:
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
gotenberg:
image: thecodingmachine/gotenberg
image: gotenberg/gotenberg:7
restart: unless-stopped
environment:
DISABLE_GOOGLE_CHROME: 1
command:
- "gotenberg"
- "--chromium-disable-routes=true"
tika:
image: iwishiwasaneagle/apache-tika-arm@sha256:a78c25ffe57ecb1a194b2859d42a61af46e9e845191512b8f1a4bf90578ffdfd

592
docs/_static/css/custom.css vendored Normal file
View File

@@ -0,0 +1,592 @@
/* Variables */
:root {
--color-text-body: #5c5962;
--color-text-body-light: #fcfcfc;
--color-text-anchor: #7253ed;
--color-text-alt: rgba(0, 0, 0, 0.3);
--color-text-title: #27262b;
--color-text-code-inline: #e74c3c;
--color-text-code-nt: #062873;
--color-text-selection: #b19eff;
--color-bg-body: #fcfcfc;
--color-bg-body-alt: #f3f6f6;
--color-bg-side-nav: #f5f6fa;
--color-bg-side-nav-hover: #ebedf5;
--color-bg-code-block: var(--color-bg-side-nav);
--color-border: #eeebee;
--color-btn-neutral-bg: #f3f6f6;
--color-btn-neutral-bg-hover: #e5ebeb;
--color-success-title: #1abc9c;
--color-success-body: #dbfaf4;
--color-warning-title: #f0b37e;
--color-warning-body: #ffedcc;
--color-danger-title: #f29f97;
--color-danger-body: #fdf3f2;
--color-info-title: #6ab0de;
--color-info-body: #e7f2fa;
}
.dark-mode {
--color-text-body: #abb2bf;
--color-text-body-light: #9499a2;
--color-text-alt: rgba(0255, 255, 255, 0.5);
--color-text-title: var(--color-text-anchor);
--color-text-code-inline: #abb2bf;
--color-text-code-nt: #2063f3;
--color-text-selection: #030303;
--color-bg-body: #1d1d20 !important;
--color-bg-body-alt: #131315;
--color-bg-side-nav: #18181a;
--color-bg-side-nav-hover: #101216;
--color-bg-code-block: #101216;
--color-border: #47494f;
--color-btn-neutral-bg: #242529;
--color-btn-neutral-bg-hover: #101216;
--color-success-title: #02120f;
--color-success-body: #041b17;
--color-warning-title: #1b0e03;
--color-warning-body: #371d06;
--color-danger-title: #120902;
--color-danger-body: #1b0503;
--color-info-title: #020608;
--color-info-body: #06141e;
}
* {
transition: background-color 0.3s ease, border-color 0.3s ease;
}
/* Typography */
body {
font-family: system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
font-size: inherit;
line-height: 1.4;
color: var(--color-text-body);
}
h1, h2, h3, h4, h5, h6 {
font-family: inherit;
}
.rst-content .toctree-wrapper>p.caption, .rst-content h1, .rst-content h2, .rst-content h3, .rst-content h4, .rst-content h5, .rst-content h6 {
padding-top: .5em;
}
p, .main-content-wrap, .rst-content .section ul, .rst-content .toctree-wrapper ul, .rst-content section ul, .wy-plain-list-disc, article ul {
line-height: 1.6;
}
pre, .code, .rst-content .linenodiv pre, .rst-content div[class^=highlight] pre, .rst-content pre.literal-block {
font-family: "SFMono-Regular", Menlo,Consolas, Monospace;
font-size: 0.75em;
line-height: 1.8;
}
.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4 {
font-size: 1rem
}
.rst-versions {
font-family: inherit;
line-height: 1;
}
footer, footer p {
font-size: .8rem;
}
footer .rst-footer-buttons {
font-size: 1rem;
}
@media (max-width: 400px) {
/* break code lines on mobile */
pre, code {
word-break: break-word;
}
}
/* Layout */
.wy-side-nav-search, .wy-menu-vertical {
width: auto;
}
.wy-nav-side {
z-index: 0;
display: flex;
flex-wrap: wrap;
background-color: var(--color-bg-side-nav);
}
.wy-side-scroll {
width: 100%;
overflow-y: auto;
}
@media (min-width: 66.5rem) {
.wy-side-scroll {
width:264px
}
}
@media (min-width: 50rem) {
.wy-nav-side {
flex-wrap: nowrap;
position: fixed;
width: 248px;
height: 100%;
flex-direction: column;
border-right: 1px solid var(--color-border);
align-items:flex-end
}
}
@media (min-width: 66.5rem) {
.wy-nav-side {
width: calc((100% - 1064px) / 2 + 264px);
min-width:264px
}
}
@media (min-width: 50rem) {
.wy-nav-content-wrap {
position: relative;
max-width: 800px;
margin-left:248px
}
}
@media (min-width: 66.5rem) {
.wy-nav-content-wrap {
margin-left:calc((100% - 1064px) / 2 + 264px)
}
}
/* Colors */
body.wy-body-for-nav,
.wy-nav-content {
background: var(--color-bg-body);
}
.wy-nav-side {
border-right: 1px solid var(--color-border);
}
.wy-side-nav-search, .wy-nav-top {
background: var(--color-bg-side-nav);
border-bottom: 1px solid var(--color-border);
}
.wy-nav-content-wrap {
background: inherit;
}
.wy-side-nav-search > a, .wy-nav-top a, .wy-nav-top i {
color: var(--color-text-title);
}
.wy-side-nav-search > a:hover, .wy-nav-top a:hover {
background: transparent;
}
.wy-side-nav-search > div.version {
color: var(--color-text-alt)
}
.wy-side-nav-search > div[role="search"] {
border-top: 1px solid var(--color-border);
}
.wy-menu-vertical li.toctree-l2.current>a, .wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,
.wy-menu-vertical li.toctree-l3.current>a, .wy-menu-vertical li.toctree-l3.current li.toctree-l4>a {
background: var(--color-bg-side-nav);
}
.rst-content .highlighted {
background: #eedd85;
box-shadow: 0 0 0 2px #eedd85;
font-weight: 600;
}
.wy-side-nav-search input[type=text],
html.writer-html5 .rst-content table.docutils th {
color: var(--color-text-body);
}
.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,
.wy-table-backed,
.wy-table-odd td,
.wy-table-striped tr:nth-child(2n-1) td {
background-color: var(--color-bg-body-alt);
}
.rst-content table.docutils,
.wy-table-bordered-all,
html.writer-html5 .rst-content table.docutils th,
.rst-content table.docutils td,
.wy-table-bordered-all td,
hr {
border-color: var(--color-border) !important;
}
::selection {
background: var(--color-text-selection);
}
/* Ridiculous rules are taken from sphinx_rtd */
.rst-content .admonition-title,
.wy-alert-title {
color: var(--color-text-body-light);
}
.rst-content .hint,
.rst-content .important,
.rst-content .tip,
.rst-content .wy-alert-success,
.wy-alert.wy-alert-success {
background: var(--color-success-body);
}
.rst-content .hint .admonition-title,
.rst-content .hint .wy-alert-title,
.rst-content .important .admonition-title,
.rst-content .important .wy-alert-title,
.rst-content .tip .admonition-title,
.rst-content .tip .wy-alert-title,
.rst-content .wy-alert-success .admonition-title,
.rst-content .wy-alert-success .wy-alert-title,
.wy-alert.wy-alert-success .rst-content .admonition-title,
.wy-alert.wy-alert-success .wy-alert-title {
background-color: var(--color-success-title);
}
.rst-content .admonition-todo,
.rst-content .attention,
.rst-content .caution,
.rst-content .warning,
.rst-content .wy-alert-warning,
.wy-alert.wy-alert-warning {
background: var(--color-warning-body);
}
.rst-content .admonition-todo .admonition-title,
.rst-content .admonition-todo .wy-alert-title,
.rst-content .attention .admonition-title,
.rst-content .attention .wy-alert-title,
.rst-content .caution .admonition-title,
.rst-content .caution .wy-alert-title,
.rst-content .warning .admonition-title,
.rst-content .warning .wy-alert-title,
.rst-content .wy-alert-warning .admonition-title,
.rst-content .wy-alert-warning .wy-alert-title,
.rst-content .wy-alert.wy-alert-warning .admonition-title,
.wy-alert.wy-alert-warning .rst-content .admonition-title,
.wy-alert.wy-alert-warning .wy-alert-title {
background: var(--color-warning-title);
}
.rst-content .danger,
.rst-content .error,
.rst-content .wy-alert-danger,
.wy-alert.wy-alert-danger {
background: var(--color-danger-body);
}
.rst-content .danger .admonition-title,
.rst-content .danger .wy-alert-title,
.rst-content .error .admonition-title,
.rst-content .error .wy-alert-title,
.rst-content .wy-alert-danger .admonition-title,
.rst-content .wy-alert-danger .wy-alert-title,
.wy-alert.wy-alert-danger .rst-content .admonition-title,
.wy-alert.wy-alert-danger .wy-alert-title {
background: var(--color-danger-title);
}
.rst-content .note,
.rst-content .seealso,
.rst-content .wy-alert-info,
.wy-alert.wy-alert-info {
background: var(--color-info-body);
}
.rst-content .note .admonition-title,
.rst-content .note .wy-alert-title,
.rst-content .seealso .admonition-title,
.rst-content .seealso .wy-alert-title,
.rst-content .wy-alert-info .admonition-title,
.rst-content .wy-alert-info .wy-alert-title,
.wy-alert.wy-alert-info .rst-content .admonition-title,
.wy-alert.wy-alert-info .wy-alert-title {
background: var(--color-info-title);
}
/* Links */
a, a:visited,
.wy-menu-vertical a,
a.icon.icon-home,
.wy-menu-vertical li.toctree-l1.current > a.current {
color: var(--color-text-anchor);
text-decoration: none;
}
a:hover, .wy-breadcrumbs-aside a {
color: var(--color-text-anchor); /* reset */
}
.rst-versions a, .rst-versions .rst-current-version {
color: #var(--color-text-anchor);
}
.wy-nav-content a.reference, .wy-nav-content a:not([class]) {
background-image: linear-gradient(var(--color-border) 0%, var(--color-border) 100%);
background-repeat: repeat-x;
background-position: 0 100%;
background-size: 1px 1px;
}
.wy-nav-content a.reference:hover, .wy-nav-content a:not([class]):hover {
background-image: linear-gradient(rgba(114,83,237,0.45) 0%, rgba(114,83,237,0.45) 100%);
background-size: 1px 1px;
}
.wy-menu-vertical a:hover,
.wy-menu-vertical li.current a:hover,
.wy-menu-vertical a:active {
background: var(--color-bg-side-nav-hover) !important;
color: var(--color-text-body);
}
.wy-menu-vertical li.toctree-l1.current>a,
.wy-menu-vertical li.current>a,
.wy-menu-vertical li.on a {
background-color: var(--color-bg-side-nav-hover);
border: none;
font-weight: normal;
}
.wy-menu-vertical li.current {
background-color: inherit;
}
.wy-menu-vertical li.current a {
border-right: none;
}
.wy-menu-vertical li.toctree-l2 a,
.wy-menu-vertical li.toctree-l3 a,
.wy-menu-vertical li.toctree-l4 a,
.wy-menu-vertical li.toctree-l5 a,
.wy-menu-vertical li.toctree-l6 a,
.wy-menu-vertical li.toctree-l7 a,
.wy-menu-vertical li.toctree-l8 a,
.wy-menu-vertical li.toctree-l9 a,
.wy-menu-vertical li.toctree-l10 a {
color: var(--color-text-body);
}
a.image-reference, a.image-reference:hover {
background: none !important;
}
a.image-reference img {
cursor: zoom-in;
}
/* Code blocks */
.rst-content code, .rst-content tt, code {
padding: 0.25em;
font-weight: 400;
background-color: var(--color-bg-code-block);
border: 1px solid var(--color-border);
border-radius: 4px;
}
.rst-content div[class^=highlight], .rst-content pre.literal-block {
padding: 0.7rem;
margin-top: 0;
margin-bottom: 0.75rem;
overflow-x: auto;
background-color: var(--color-bg-side-nav);
border-color: var(--color-border);
border-radius: 4px;
box-shadow: none;
}
.rst-content .admonition-title,
.rst-content div.admonition,
.wy-alert-title {
padding: 10px 12px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.highlight .go {
color: inherit;
}
.highlight .nt {
color: var(--color-text-code-nt);
}
.rst-content code.literal,
.rst-content tt.literal {
border-color: var(--color-border);
background-color: var(--color-border);
color: var(--color-text-code-inline)
}
/* Search */
.wy-side-nav-search input[type=text] {
border: none;
border-radius: 0;
background-color: transparent;
font-family: inherit;
font-size: .85rem;
box-shadow: none;
padding: .7rem 1rem .7rem 2.8rem;
margin: 0;
}
#rtd-search-form {
position: relative;
}
#rtd-search-form:before {
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
content: "\f002";
color: var(--color-text-alt);
position: absolute;
left: 1.5rem;
top: .7rem;
}
/* Side nav */
.wy-side-nav-search {
padding: 1rem 0 0 0;
}
.wy-menu-vertical li a button.toctree-expand {
float: right;
margin-right: -1.5em;
padding: 0 .5em;
}
.wy-menu-vertical a,
.wy-menu-vertical li.current>a,
.wy-menu-vertical li.current li>a {
padding-right: 1.5em !important;
}
.wy-menu-vertical li.current li>a.current {
font-weight: 600;
}
/* Misc spacing */
.rst-content .admonition-title, .wy-alert-title {
padding: 10px 12px;
}
/* Buttons */
.btn {
display: inline-block;
box-sizing: border-box;
padding: 0.3em 1em;
margin: 0;
font-family: inherit;
font-size: inherit;
font-weight: 500;
line-height: 1.5;
color: #var(--color-text-anchor);
text-decoration: none;
vertical-align: baseline;
background-color: #f7f7f7;
border-width: 0;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0,0,0,0.12),0 3px 10px rgba(0,0,0,0.08);
appearance: none;
}
.btn:active {
padding: 0.3em 1em;
}
.rst-content .btn:focus {
outline: 1px solid #ccc;
}
.rst-content .btn-neutral, .rst-content .btn span.fa {
color: var(--color-text-body) !important;
}
.btn-neutral {
background-color: var(--color-btn-neutral-bg) !important;
color: var(--color-btn-neutral-text) !important;
border: 1px solid var(--color-btn-neutral-bg);
}
.btn:hover, .btn-neutral:hover {
background-color: var(--color-btn-neutral-bg-hover) !important;
}
/* Icon overrides */
.wy-side-nav-search a.icon-home:before {
display: none;
}
.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before {
content: "\f106"; /* fa-angle-up */
}
.fa-plus-square-o:before, .wy-menu-vertical li button.toctree-expand:before {
content: "\f107"; /* fa-angle-down */
}
/* Misc */
.wy-nav-top {
line-height: 36px;
}
.wy-nav-top > i {
font-size: 24px;
padding: 8px 0 0 2px;
color:#var(--color-text-anchor);
}
.rst-content table.docutils td,
.rst-content table.docutils th,
.rst-content table.field-list td,
.rst-content table.field-list th,
.wy-table td,
.wy-table th {
padding: 8px 14px;
}
.dark-mode-toggle {
position: absolute;
top: 14px;
right: 12px;
height: 20px;
width: 24px;
z-index: 10;
border: none;
background-color: transparent;
color: inherit;
opacity: 0.7;
}
.wy-nav-content-wrap {
z-index: 20;
}

View File

@@ -1,14 +0,0 @@
/* override table width restrictions */
@media screen and (min-width: 767px) {
.wy-table-responsive table td {
/* !important prevents the common CSS stylesheets from
overriding this as on RTD they are loaded after this stylesheet */
white-space: normal !important;
}
.wy-table-responsive {
overflow: visible !important;
}
}

47
docs/_static/js/darkmode.js vendored Normal file
View File

@@ -0,0 +1,47 @@
let toggleButton;
let icon;
function load() {
"use strict";
toggleButton = document.createElement("button");
toggleButton.setAttribute("title", "Toggle dark mode");
toggleButton.classList.add("dark-mode-toggle");
icon = document.createElement("i");
icon.classList.add("fa", darkModeState ? "fa-sun-o" : "fa-moon-o");
toggleButton.appendChild(icon);
document.body.prepend(toggleButton);
// Listen for changes in the OS settings
// addListener is used because older versions of Safari don't support addEventListener
// prefersDarkQuery set in <head>
if (prefersDarkQuery) {
prefersDarkQuery.addListener(function (evt) {
toggleDarkMode(evt.matches);
});
}
// Initial setting depending on the prefers-color-mode or localstorage
// darkModeState should be set in the document <head> to prevent flash
if (darkModeState == undefined) darkModeState = false;
toggleDarkMode(darkModeState);
// Toggles the "dark-mode" class on click and sets localStorage state
toggleButton.addEventListener("click", () => {
darkModeState = !darkModeState;
toggleDarkMode(darkModeState);
localStorage.setItem("dark-mode", darkModeState);
});
}
function toggleDarkMode(state) {
document.documentElement.classList.toggle("dark-mode", state);
document.documentElement.classList.toggle("light-mode", !state);
icon.classList.remove("fa-sun-o");
icon.classList.remove("fa-moon-o");
icon.classList.add(state ? "fa-sun-o" : "fa-moon-o");
darkModeState = state;
}
document.addEventListener("DOMContentLoaded", load);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 445 KiB

BIN
docs/_static/screenshots/bulk-edit.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 608 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 KiB

After

Width:  |  Height:  |  Size: 706 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 480 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 KiB

After

Width:  |  Height:  |  Size: 848 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 KiB

After

Width:  |  Height:  |  Size: 703 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 KiB

After

Width:  |  Height:  |  Size: 517 KiB

13
docs/_templates/layout.html vendored Normal file
View File

@@ -0,0 +1,13 @@
{% extends "!layout.html" %}
{% block extrahead %}
<script>
// MediaQueryList object
const prefersDarkQuery = window.matchMedia("(prefers-color-scheme: dark)");
const lsDark = localStorage.getItem("dark-mode");
let darkModeState = lsDark !== null ? lsDark == "true" : prefersDarkQuery.matches;
document.documentElement.classList.toggle("dark-mode", darkModeState);
document.documentElement.classList.toggle("light-mode", !darkModeState);
</script>
{{ super() }}
{% endblock %}

View File

@@ -369,7 +369,7 @@ the naming scheme.
.. warning::
Since this command moves you documents around alot, it is advised to to
Since this command moves you documents around a lot, it is advised to to
a backup before. The renaming logic is robust and will never overwrite
or delete a file, but you can't ever be careful enough.

View File

@@ -200,7 +200,7 @@ Troubleshooting:
- Check your script's permission e.g. in case of permission error ``sudo chmod 755 post-consumption-example.sh``
- Pipe your scripts's output to a log file e.g. ``echo "${DOCUMENT_ID}" | tee --append /usr/src/paperless/scripts/post-consumption-example.log``
.. _post-consumption-example.sh: https://github.com/jonaswinkler/paperless-ngx/blob/master/scripts/post-consumption-example.sh
.. _post-consumption-example.sh: https://github.com/paperless-ngx/paperless-ngx/blob/main/scripts/post-consumption-example.sh
.. _advanced-file_name_handling:
@@ -243,7 +243,7 @@ will create a directory structure as follows:
last filename a document was stored as. If you do rename a file, paperless will
report your files as missing and won't be able to find them.
Paperless provides the following placeholders withing filenames:
Paperless provides the following placeholders within filenames:
* ``{asn}``: The archive serial number of the document, or "none".
* ``{correspondent}``: The name of the correspondent, or "none".

View File

@@ -5,6 +5,87 @@
Changelog
*********
paperless-ngx 1.7.0
###################
Breaking Changes
* ``PAPERLESS_URL`` is now required when using a reverse proxy. See `#674`_.
Features
* Allow setting more than one tag in mail rules `@jonasc`_ (#270)
* global drag'n'drop `@shamoon`_ (#283).
* Fix: download buttons should disable while waiting `@shamoon`_ (#630).
* Update checker `@shamoon`_ (#591).
* Show prompt on password-protected pdfs `@shamoon`_ (#564).
* Filtering query params aka browser navigation for filtering `@shamoon`_ (#540).
* Clickable tags in dashboard widgets `@shamoon`_ (#515).
* Add bottom pagination `@shamoon`_ (#372).
* Feature barcode splitter `@gador`_ (#532).
* App loading screen `@shamoon`_ (#298).
* Use progress bar for delayed buttons `@shamoon`_ (#415).
* Add minimum length for documents text filter `@shamoon`_ (#401).
* Added nav buttons in the document detail view `@GruberViktor`_ (#273).
* Improve date keyboard input `@shamoon`_ (#253).
* Color theming `@shamoon`_ (#243).
* Parse dates when entered without separators `@GruberViktor`_ (#250).
Bug Fixes
* add "localhost" to ALLOWED_HOSTS `@gador`_ (#700).
* Fix: scanners table `@qcasey`_ (#690).
* Adds wait for file before consuming `@stumpylog`_ (#483).
* Fix: frontend document editing erases time data `@shamoon`_ (#654).
* Increase length of SavedViewFilterRule `@stumpylog`_ (#612).
* Fixes attachment filename matching during mail fetching `@stumpylog`_ (#680).
* Add ``PAPERLESS_URL`` env variable & CSRF var `@shamoon`_ (#674).
* Fix: download buttons should disable while waiting `@shamoon`_ (#630).
* Fixes downloaded filename, add more consumer ignore settings `@stumpylog`_ (#599).
* FIX BUG: case-sensitive matching was not possible `@danielBreitlauch`_ (#594).
* uses shutil.move instead of rename `@gador`_ (#617).
* Fix npm deps 01.02.22 2 `@shamoon`_ (#610).
* Fix npm dependencies 01.02.22 `@shamoon`_ (#600).
* fix issue 416: implement PAPERLESS_OCR_MAX_IMAGE_PIXELS `@hacker-h`_ (#441).
* fix: exclude cypress from build in Dockerfile `@FrankStrieter`_ (#526).
* Corrections to pass pre-commit hooks `@schnuffle`_ (#454).
* Fix 311 unable to click checkboxes in document list `@shamoon`_ (#313).
* Fix imap tools bug `@stumpylog`_ (#393).
* Fix filterable dropdown buttons arent translated `@shamoon`_ (#366).
* Fix 224: "Auto-detected date is day before receipt date" `@a17t`_ (#246).
* Fix minor sphinx errors `@shamoon`_ (#322).
* Fix page links hidden `@shamoon`_ (#314).
* Fix: Include excluded items in dropdown count `@shamoon`_ (#263).
Translation
* `@miku323`_ contributed to Slovenian translation.
* `@FaintGhost`_ contributed to Chinese Simplified translation.
* `@DarkoBG79`_ contributed to Serbian translation.
* `Kemal Secer`_ contributed to Turkish translation.
* `@Prominence`_ contributed to Belarusian translation.
Documentation
* Fix: scanners table `@qcasey`_ (#690).
* Add `PAPERLESS_URL` env variable & CSRF var `@shamoon`_ (#674).
* Fixes downloaded filename, add more consumer ignore settings `@stumpylog`_ (#599).
* fix issue 416: implement ``PAPERLESS_OCR_MAX_IMAGE_PIXELS`` `@hacker-h`_ (#441).
* Fix minor sphinx errors `@shamoon`_ (#322).
Maintenance
* Add ``PAPERLESS_URL`` env variable & CSRF var `@shamoon`_ (#674).
* Chore: Implement release-drafter action for Changelogs `@qcasey`_ (#669).
* Chore: Add CODEOWNERS `@qcasey`_ (#667).
* Support docker-compose v2 in install `@stumpylog`_ (#611).
* Add Belarusian localization `@shamoon`_ (#588).
* Add Turkish localization `@shamoon`_ (#536).
* Add Serbian localization `@shamoon`_ (#504).
* Create PULL_REQUEST_TEMPLATE.md `@shamoon`_ (#304).
* Add Chinese localization `@shamoon`_ (#247).
* Add Slovenian language for frontend `@shamoon`_ (#315).
paperless-ngx 1.6.0
###################
@@ -35,6 +116,10 @@ Version 1.6.0 merges several pending PRs from jonaswinkler's repo and includes n
* `@shamoon`_ created a slick new logo (#165).
* `@tim-vogel`_ fixed exports missing groups (#193).
Known issues:
* 1.6.0 included a malformed package-lock.json, as a result users who want to build the docker image themselves need to change line 6 of the ``Dockerfile`` to ``RUN npm update npm -g && npm install --legacy-peer-deps``.
Thank you to the following people for their documentation updates, fixes, and comprehensive testing:
`@m0veax`_, `@a17t`_, `@fignew`_, `@muued`_, `@bauerj`_, `@isigmund`_, `@denilsonsa`_, `@mweimerskirch`_, `@alexander-bauer`_, `@apeltzer`_, `@tribut`_, `@yschroeder`_, `@gador`_, `@sAksham-Ar`_, `@sbrunner`_, `@philpagel`_, `@davemachado`_, `@2600box`_, `@qcasey`_, `@Nicarim`_, `@kpj`_, `@filcuk`_, `@Timoms`_, `@mattlamb99`_, `@padraigkitterick`_, `@ajkavanagh`_, `@Tooa`_, `@Unkn0wnCat`_, `@pewter77`_, `@stumpylog`_, `@Toxix`_, `@azapater`_, `@jschpp`_
@@ -140,7 +225,7 @@ paperless-ng 1.4.0
* New URL pattern for accessing documents by ASN directly (http://<paperless>/asn/123)
* Added logging when executing pre- and post-consume scripts.
* Added logging when executing pre* and post-consume scripts.
* Better error logging during document consumption.
@@ -1576,6 +1661,16 @@ bulk of the work on this big change.
.. _@azapater: https://github.com/azapater
.. _@tim-vogel: https://github.com/tim-vogel
.. _@jschpp: https://github.com/jschpp
.. _@schnuffle: https://github.com/schnuffle
.. _@GruberViktor: https://github.com/gruberviktor
.. _@hacker-h: https://github.com/hacker-h
.. _@danielBreitlauch: https://github.com/danielbreitlauch
.. _@miku323: https://github.com/miku323
.. _@FaintGhost: https://github.com/FaintGhost
.. _@DarkoBG79: https://github.com/DarkoBG79
.. _Kemal Secer: https://crowdin.com/profile/kemal.secer
.. _@Prominence: https://github.com/Prominence
.. _@jonasc: https://github.com/jonasc
.. _#20: https://github.com/the-paperless-project/paperless/issues/20
.. _#44: https://github.com/the-paperless-project/paperless/issues/44
@@ -1684,6 +1779,7 @@ bulk of the work on this big change.
.. _#488: https://github.com/the-paperless-project/paperless/pull/488
.. _#489: https://github.com/the-paperless-project/paperless/pull/489
.. _#492: https://github.com/the-paperless-project/paperless/pull/492
.. _#674: https://github.com/paperless-ngx/paperless-ngx/pull/674
.. _a new home on Docker Hub: https://hub.docker.com/r/danielquinn/paperless/
.. _optipng: http://optipng.sourceforge.net/

View File

@@ -15,7 +15,7 @@ extensions = [
]
# Add any paths that contain templates here, relative to this directory.
# templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix of source filenames.
source_suffix = ".rst"
@@ -119,6 +119,16 @@ html_theme_path = []
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
# These paths are either relative to html_static_path
# or fully qualified paths (eg. https://...)
html_css_files = [
"css/custom.css",
]
html_js_files = [
"js/darkmode.js",
]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.

View File

@@ -130,6 +130,8 @@ PAPERLESS_LOGROTATE_MAX_BACKUPS=<num>
Defaults to 20.
.. _hosting-and-security:
Hosting & Security
##################
@@ -142,7 +144,24 @@ PAPERLESS_SECRET_KEY=<key>
Default is listed in the file ``src/paperless/settings.py``.
PAPERLESS_ALLOWED_HOSTS<comma-separated-list>
PAPERLESS_URL=<url>
This setting can be used to set the three options below (ALLOWED_HOSTS,
CORS_ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS). If the other options are
set the values will be combined with this one. Do not include a trailing
slash. E.g. https://paperless.domain.com
Defaults to empty string, leaving the other settings unaffected.
PAPERLESS_CSRF_TRUSTED_ORIGINS=<comma-separated-list>
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.
See https://docs.djangoproject.com/en/4.0/ref/settings/#csrf-trusted-origins
Can also be set using PAPERLESS_URL (see above).
Defaults to empty string, which does not add any origins to the trusted list.
PAPERLESS_ALLOWED_HOSTS=<comma-separated-list>
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. Failing to do
so leaves you open to HTTP host header attacks:
@@ -151,12 +170,19 @@ PAPERLESS_ALLOWED_HOSTS<comma-separated-list>
Just remember that this is a comma-separated list, so "example.com" is fine,
as is "example.com,www.example.com", but NOT " example.com" or "example.com,"
Can also be set using PAPERLESS_URL (see above).
If manually set, please remember to include "localhost". Otherwise docker
healthcheck will fail.
Defaults to "*", which is all hosts.
PAPERLESS_CORS_ALLOWED_HOSTS<comma-separated-list>
PAPERLESS_CORS_ALLOWED_HOSTS=<comma-separated-list>
You need to add your servers to the list of allowed hosts that can do CORS
calls. Set this to your public domain name.
Can also be set using PAPERLESS_URL (see above).
Defaults to "http://localhost:8000".
PAPERLESS_FORCE_SCRIPT_NAME=<path>
@@ -185,7 +211,7 @@ PAPERLESS_AUTO_LOGIN_USERNAME=<username>
PAPERLESS_ADMIN_USER=<username>
If this environment variable is specified, Paperless automatically creates
a superuser with the provided username at start. This is useful in cases
where you can not run the `createsuperuser` command seperately, such as Kubernetes
where you can not run the `createsuperuser` command separately, such as Kubernetes
or AWS ECS.
Requires `PAPERLESS_ADMIN_PASSWORD` to be set.
@@ -540,6 +566,10 @@ PAPERLESS_WORKER_TIMEOUT=<num>
large documents within the default 1800 seconds. So extending this timeout
may prove to be useful on weak hardware setups.
PAPERLESS_WORKER_RETRY=<num>
If PAPERLESS_WORKER_TIMEOUT has been configured, the retry time for a task can
also be configured. By default, this value will be set to 10s more than the
worker timeout. This value should never be set less than the worker timeout.
PAPERLESS_TIME_ZONE=<timezone>
Set the time zone here.
@@ -588,6 +618,27 @@ PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=<bool>
Defaults to false.
PAPERLESS_CONSUMER_ENABLE_BARCODES=<bool>
Enables the scanning and page separation based on detected barcodes.
This allows for scanning and adding multiple documents per uploaded
file, which are separated by one or multiple barcode pages.
For ease of use, it is suggested to use a standardized separation page,
e.g. `here <https://www.alliancegroup.co.uk/patch-codes.htm>`_.
If no barcodes are detected in the uploaded file, no page separation
will happen.
Defaults to false.
PAPERLESS_CONSUMER_BARCODE_STRING=PATCHT
Defines the string to be detected as a separator barcode.
If paperless is used with the PATCH-T separator pages, users
shouldn't change this.
Defaults to "PATCHT"
PAPERLESS_CONVERT_MEMORY_LIMIT=<num>
On smaller systems, or even in the case of Very Large Documents, the consumer
@@ -671,7 +722,7 @@ PAPERLESS_CONSUMER_IGNORE_PATTERNS=<json>
This can be adjusted by configuring a custom json array with patterns to exclude.
Defautls to ``[".DS_STORE/*", "._*", ".stfolder/*"]``.
Defaults to ``[".DS_STORE/*", "._*", ".stfolder/*", ".stversions/*", ".localized/*", "desktop.ini"]``.
Binaries
########
@@ -764,3 +815,26 @@ PAPERLESS_OCR_LANGUAGES=<list>
PAPERLESS_OCR_LANGUAGE=tur
Defaults to none, which does not install any additional languages.
.. _configuration-update-checking:
Update Checking
###############
PAPERLESS_ENABLE_UPDATE_CHECK=<bool>
Enable (or disable) the automatic check for available updates. This feature is disabled
by default but if it is not explicitly set Paperless-ngx will show a message about this.
If enabled, the feature works by pinging the the Github API for the latest release e.g.
https://api.github.com/repos/paperless-ngx/paperless-ngx/releases/latest
to determine whether a new version is available.
Actual updating of the app must still be performed manually.
Note that for users of thirdy-party containers e.g. linuxserver.io this notification
may be 'ahead' of a new release from the third-party maintainers.
In either case, no tracking data is collected by the app in any way.
Defaults to none, which disables the feature.

View File

@@ -7,7 +7,7 @@ Frequently asked questions
**A:** While Paperless-ngx is already considered largely "feature-complete" it is a community-driven
project and development will be guided in this way. New features can be submitted via
GitHub discussions and "up-voted" by the community but this is not a garauntee the feature
GitHub discussions and "up-voted" by the community but this is not a guarantee the feature
will be implemented. This project will always be open to collaboration in the form of PRs,
ideas etc.

View File

@@ -13,43 +13,43 @@ that works right for you based on recommendations from other Paperless users.
Physical scanners
=================
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brand | Model | Supports | Recommended By |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| | | FTP | NFS | SMB | SMTP | API [1]_ | |
+=========+================+=====+=====+=====+======+==========+================+
| Brother | `ADS-1700W`_ | yes | | yes | yes | |`holzhannes`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `ADS-1600W`_ | yes | | yes | yes | |`holzhannes`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `ADS-1500W`_ | yes | | yes | yes | |`danielquinn`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `ADS-1100W`_ | yes | | | | |`ytzelf`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `ADS-2800W`_ | yes | yes | | yes | yes |`philpagel`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-J6930DW`_ | yes | | | | |`ayounggun`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-L5850DW`_ | yes | | | yes | |`holzhannes`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-L2750DW`_ | yes | | yes | yes | |`muued`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-J5910DW`_ | yes | | | | |`bmsleight`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-8950DW`_ | yes | | | yes | yes |`philpagel`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-9142CDN`_ | yes | | yes | | |`REOLDEV`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Fujitsu | `ix500`_ | yes | | yes | | |`eonist`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Epson | `ES-580W`_ | yes | | yes | yes | |`fignew`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Epson | `WF-7710DWF`_ | yes | | yes | | |`Skylinar`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Fujitsu | `S1300i`_ | yes | | yes | | |`jonaswinkler`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Doxie | `Q2`_ | | | | | yes |`Unkn0wnCat`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brand | Model | Supports | Recommended By |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| | | FTP | SFTP | NFS | SMB | SMTP | API [1]_ | |
+=========+================+=====+======+=====+=====+======+==========+================+
| Brother | `ADS-1700W`_ | yes | | | yes | yes | |`holzhannes`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `ADS-1600W`_ | yes | | | yes | yes | |`holzhannes`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `ADS-1500W`_ | yes | | | yes | yes | |`danielquinn`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `ADS-1100W`_ | yes | | | | | |`ytzelf`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `ADS-2800W`_ | yes | yes | | yes | yes | |`philpagel`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `MFC-J6930DW`_ | yes | | | | | |`ayounggun`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `MFC-L5850DW`_ | yes | | | | yes | |`holzhannes`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `MFC-L2750DW`_ | yes | | | yes | yes | |`muued`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `MFC-J5910DW`_ | yes | | | | | |`bmsleight`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `MFC-8950DW`_ | yes | | | yes | yes | |`philpagel`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Brother | `MFC-9142CDN`_ | yes | | | yes | | |`REOLDEV`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Fujitsu | `ix500`_ | yes | | | yes | | |`eonist`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Epson | `ES-580W`_ | yes | | | yes | yes | |`fignew`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Epson | `WF-7710DWF`_ | yes | | | yes | | |`Skylinar`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Fujitsu | `S1300i`_ | yes | | | yes | | |`jonaswinkler`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
| Doxie | `Q2`_ | | | | | | yes |`Unkn0wnCat`_ |
+---------+----------------+-----+------+-----+-----+------+----------+----------------+
.. _MFC-L5850DW: https://www.brother-usa.com/products/mfcl5850dw
.. _MFC-L2750DW: https://www.brother.de/drucker/laserdrucker/mfc-l2750dw
@@ -131,4 +131,3 @@ This part assumes your Doxie is connected to WiFi and you know its IP.
6. Click *Submit* at the bottom of the page
Congrats, you can now scan directly from your Doxie to your Paperless-ngx instance!

View File

@@ -4,41 +4,60 @@
Screenshots
***********
This is what paperless-ngx looks like. You shouldn't use paperless to index
research papers though, its a horrible tool for that job.
This is what Paperless-ngx looks like.
The dashboard shows customizable views on your document and allows document uploads:
.. image:: _static/screenshots/dashboard.png
:target: _static/screenshots/dashboard.png
The document list provides three different styles to scroll through your documents:
.. image:: _static/screenshots/documents-table.png
:target: _static/screenshots/documents-table.png
.. image:: _static/screenshots/documents-smallcards.png
:target: _static/screenshots/documents-smallcards.png
.. image:: _static/screenshots/documents-largecards.png
:target: _static/screenshots/documents-largecards.png
Paperless-ngx also supports "dark mode":
.. image:: _static/screenshots/documents-smallcards-dark.png
:target: _static/screenshots/documents-smallcards-dark.png
Extensive filtering mechanisms:
.. image:: _static/screenshots/documents-filter.png
:target: _static/screenshots/documents-filter.png
Side-by-side editing of documents. Optimized for 1080p.
Bulk editing of document tags, correspondents, etc.:
.. image:: _static/screenshots/bulk-edit.png
:target: _static/screenshots/bulk-edit.png
Side-by-side editing of documents:
.. image:: _static/screenshots/editing.png
:target: _static/screenshots/editing.png
Tag editing. This looks about the same for correspondents and document types.
.. image:: _static/screenshots/new-tag.png
:target: _static/screenshots/new-tag.png
Searching provides auto complete and highlights the results.
.. image:: _static/screenshots/search-preview.png
:target: _static/screenshots/search-preview.png
.. image:: _static/screenshots/search-results.png
:target: _static/screenshots/search-results.png
Fancy mail filters!
.. image:: _static/screenshots/mail-rules-edited.png
:target: _static/screenshots/mail-rules-edited.png
Mobile support in the future? This kinda works, however some layouts are still
too wide.
Mobile devices are supported.
.. image:: _static/screenshots/mobile.png
:target: _static/screenshots/mobile.png

View File

@@ -291,12 +291,14 @@ writing. Windows is not and will never be supported.
* ``libpq-dev`` for PostgreSQL
* ``libmagic-dev`` for mime type detection
* ``mime-support`` for mime type detection
* ``libzbar0`` for barcode detection
* ``poppler-utils`` for barcode detection
Use this list for your preferred package management:
.. code::
python3 python3-pip python3-dev imagemagick fonts-liberation optipng gnupg libpq-dev libmagic-dev mime-support
python3 python3-pip python3-dev imagemagick fonts-liberation optipng gnupg libpq-dev libmagic-dev mime-support libzbar0 poppler-utils
These dependencies are required for OCRmyPDF, which is used for text recognition.
@@ -345,6 +347,8 @@ writing. Windows is not and will never be supported.
paperless stores its data. If you like, you can point both to the same directory.
* ``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 point to your domain. Please see
:ref:`configuration` for more information.
Many more adjustments can be made to paperless, especially the OCR part. The following options are recommended
for everyone:
@@ -784,4 +788,6 @@ the following configuration is required for paperless to operate:
}
}
The ``PAPERLESS_URL`` configuration variable is also required when using a reverse proxy. Please refer to the :ref:`hosting-and-security` docs.
Also read `this <https://channels.readthedocs.io/en/stable/deploying.html#nginx-supervisor-ubuntu>`__, towards the end of the section.

View File

@@ -62,7 +62,7 @@ your documents:
1. OCR the document, if it has no text. Digital documents usually have text,
and this step will be skipped for those documents.
2. Paperless will create an archiveable PDF/A document from your document.
2. Paperless will create an archivable PDF/A document from your document.
If this document is coming from your scanner, it will have embedded selectable text.
3. Paperless performs automatic matching of tags, correspondents and types on the
document before storing it in the database.
@@ -102,12 +102,14 @@ files from the scanner. Typically, you're looking at an FTP server like
.. TODO: hyperref to configuration of the location of this magic folder.
Dashboard upload
================
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.
.. _usage-mobile_upload:
@@ -178,6 +180,14 @@ These are as follows:
automatically or manually and tell paperless to move them to yet another folder
after consumption. It's up to you.
.. note::
When defining a mail rule with a folder, you may need to try different characters to
define how the sub-folders are separated. Common values include ".", "/" or "|", but
this varies by the mail server. Unfortunately, this isn't a value we can determine
automatically. Either check the documentation for your mail server, or check for
errors in the logs and try different folder separator values.
.. note::
Paperless will process the rules in the order defined in the admin page.

View File

@@ -47,24 +47,29 @@ if [[ $(id -u) == "0" ]] ; then
exit 1
fi
if [[ -z $(which wget) ]] ; then
if ! command -v wget &> /dev/null ; then
echo "wget executable not found. Is wget installed?"
exit 1
fi
if [[ -z $(which docker) ]] ; then
if ! command -v docker &> /dev/null ; then
echo "docker executable not found. Is docker installed?"
exit 1
fi
if [[ -z $(which docker-compose) ]] ; then
echo "docker-compose executable not found. Is docker-compose installed?"
exit 1
DOCKER_COMPOSE_CMD="docker-compose"
if ! command -v ${DOCKER_COMPOSE_CMD} ; then
if docker compose version &> /dev/null ; then
DOCKER_COMPOSE_CMD="docker compose"
else
echo "docker-compose executable not found. Is docker-compose installed?"
exit 1
fi
fi
# Check if user has permissions to run Docker by trying to get the status of Docker (docker status).
# If this fails, the user probably does not have permissions for Docker.
if [ ! "$(docker stats --no-stream 2>/dev/null 1>&2)" ] ; then
if ! docker stats --no-stream &> /dev/null ; then
echo ""
echo "WARN: It look like the current user does not have Docker permissions."
echo "WARN: Use 'sudo usermod -aG docker $USER' to assign Docker permissions to the user."
@@ -87,6 +92,14 @@ echo ""
echo "1. Application configuration"
echo "============================"
echo ""
echo "The URL paperless will be available at. This is required if the"
echo "installation will be accessible via the web, otherwise can be left blank."
echo ""
ask "URL" ""
URL=$ask_result
echo ""
echo "The port on which the paperless webserver will listen for incoming"
echo "connections."
@@ -273,6 +286,7 @@ if [[ "$DATABASE_BACKEND" == "postgres" ]] ; then
fi
fi
echo ""
echo "URL: $URL"
echo "Port: $PORT"
echo "Database: $DATABASE_BACKEND"
echo "Tika enabled: $TIKA_ENABLED"
@@ -308,6 +322,9 @@ SECRET_KEY=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 64 | head -n 1)
DEFAULT_LANGUAGES="deu eng fra ita spa"
{
if [[ ! $URL == "" ]] ; then
echo "PAPERLESS_URL=$URL"
fi
if [[ ! $USERMAP_UID == "1000" ]] ; then
echo "USERMAP_UID=$USERMAP_UID"
fi
@@ -351,8 +368,8 @@ if [ "$l1" -eq "$l2" ] ; then
fi
docker-compose pull
${DOCKER_COMPOSE_CMD} pull
docker-compose run --rm -e DJANGO_SUPERUSER_PASSWORD="$PASSWORD" webserver createsuperuser --noinput --username "$USERNAME" --email "$EMAIL"
${DOCKER_COMPOSE_CMD} run --rm -e DJANGO_SUPERUSER_PASSWORD="$PASSWORD" webserver createsuperuser --noinput --username "$USERNAME" --email "$EMAIL"
docker-compose up -d
${DOCKER_COMPOSE_CMD} up -d

View File

@@ -27,8 +27,10 @@
# Security and hosting
#PAPERLESS_SECRET_KEY=change-me
#PAPERLESS_ALLOWED_HOSTS=example.com,www.example.com
#PAPERLESS_CORS_ALLOWED_HOSTS=http://example.com,http://localhost:8000
#PAPERLESS_URL=https://example.com
#PAPERLESS_CSRF_TRUSTED_ORIGINS=https://example.com # can be set using PAPERLESS_URL
#PAPERLESS_ALLOWED_HOSTS=example.com,www.example.com # can be set using PAPERLESS_URL
#PAPERLESS_CORS_ALLOWED_HOSTS=https://localhost:8080,https://example.com # can be set using PAPERLESS_URL
#PAPERLESS_FORCE_SCRIPT_NAME=
#PAPERLESS_STATIC_URL=/static/
#PAPERLESS_AUTO_LOGIN_USERNAME=
@@ -58,8 +60,10 @@
#PAPERLESS_CONSUMER_POLLING=10
#PAPERLESS_CONSUMER_DELETE_DUPLICATES=false
#PAPERLESS_CONSUMER_RECURSIVE=false
#PAPERLESS_CONSUMER_IGNORE_PATTERNS=[".DS_STORE/*", "._*", ".stfolder/*"]
#PAPERLESS_CONSUMER_IGNORE_PATTERNS=[".DS_STORE/*", "._*", ".stfolder/*", ".stversions/*", ".localized/*", "desktop.ini"]
#PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=false
#PAPERLESS_CONSUMER_ENABLE_BARCODES=false
#PAPERLESS_CONSUMER_ENABLE_BARCODES=PATCHT
#PAPERLESS_OPTIMIZE_THUMBNAILS=true
#PAPERLESS_PRE_CONSUME_SCRIPT=/path/to/an/arbitrary/script.sh
#PAPERLESS_POST_CONSUME_SCRIPT=/path/to/an/arbitrary/script.sh
@@ -67,6 +71,7 @@
#PAPERLESS_FILENAME_PARSE_TRANSFORMS=[]
#PAPERLESS_THUMBNAIL_FONT_NAME=
#PAPERLESS_IGNORE_DATES=
#PAPERLESS_ENABLE_UPDATE_CHECK=
# Tika settings

View File

@@ -5,15 +5,15 @@
# pipenv lock --requirements
#
-i https://pypi.python.org/simple
--extra-index-url https://www.piwheels.org/simple
-i https://pypi.python.org/simple/
--extra-index-url https://www.piwheels.org/simple/
aioredis==1.3.1
anyio==3.5.0; python_full_version >= '3.6.2'
arrow==1.2.2; python_version >= '3.6'
asgiref==3.5.0; python_version >= '3.7'
async-timeout==4.0.2; python_version >= '3.6'
attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
autobahn==22.2.2; python_version >= '3.7'
autobahn==22.3.2; python_version >= '3.7'
automat==20.2.0
backports.zoneinfo==0.2.1; python_version < '3.9'
blessed==1.19.1; python_version >= '2.7'
@@ -23,7 +23,7 @@ channels-redis==3.4.0
channels==3.0.4
chardet==4.0.0; python_version >= '3.1'
charset-normalizer==2.0.12; python_version >= '3'
click==8.0.4; python_version >= '3.6'
click==8.1.2; python_version >= '3.7'
coloredlogs==15.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
concurrent-log-handler==0.9.20
constantly==15.1.0
@@ -35,7 +35,7 @@ django-extensions==3.1.5
django-filter==21.1
django-picklefield==3.0.1; python_version >= '3'
django-q==1.3.9
django==4.0.3
django==4.0.4
djangorestframework==3.13.1
filelock==3.6.0
fuzzywuzzy[speedup]==0.18.0
@@ -47,7 +47,7 @@ humanfriendly==10.0; python_version >= '2.7' and python_version not in '3.0, 3.1
hyperlink==21.0.0
idna==3.3; python_version >= '3.5'
imap-tools==0.53.0
img2pdf==0.4.3
img2pdf==0.4.4
importlib-resources==5.6.0; python_version < '3.9'
incremental==21.3.0
inotify-simple==1.3.5; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
@@ -57,12 +57,13 @@ langdetect==1.0.9
lxml==4.8.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
msgpack==1.0.3
numpy==1.22.3; python_version >= '3.8'
ocrmypdf==13.4.1
ocrmypdf==13.4.2
packaging==21.3; python_version >= '3.6'
pathvalidate==2.5.0
pdfminer.six==20211012
pikepdf==5.1.0
pillow==9.0.1
pdf2image==1.16.0
pdfminer.six==20220319
pikepdf==5.1.1
pillow==9.1.0
pluggy==1.0.0; python_version >= '3.6'
portalocker==2.4.0; python_version >= '3'
psycopg2==2.9.3
@@ -70,7 +71,7 @@ pyasn1-modules==0.2.8
pyasn1==0.4.8
pycparser==2.21
pyopenssl==22.0.0
pyparsing==3.0.7; python_version >= '3.6'
pyparsing==3.0.8; python_full_version >= '3.6.8'
python-dateutil==2.8.2
python-dotenv==0.20.0
python-gnupg==0.4.8
@@ -79,6 +80,7 @@ python-magic==0.4.25
pytz-deprecation-shim==0.1.0.post0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
pytz==2022.1
pyyaml==6.0
pyzbar==0.1.9
redis==3.5.3
regex==2022.3.2; python_version >= '3.6'
reportlab==3.6.9; python_version >= '3.7' and python_version < '4'
@@ -86,26 +88,26 @@ requests==2.27.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3
scikit-learn==1.0.2
scipy==1.8.0; python_version < '3.11' and python_version >= '3.8'
service-identity==21.1.0
setuptools==61.1.1; python_version >= '3.7'
setuptools==62.1.0; python_version >= '3.7'
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
sniffio==1.2.0; python_version >= '3.5'
sqlparse==0.4.2; python_version >= '3.5'
threadpoolctl==3.1.0; python_version >= '3.6'
tika==1.24
tqdm==4.63.1
twisted[tls]==22.2.0; python_full_version >= '3.6.7'
tqdm==4.64.0
twisted[tls]==22.4.0; python_full_version >= '3.6.7'
txaio==22.2.1; python_version >= '3.6'
typing-extensions==4.1.1; python_version >= '3.6'
tzdata==2022.1; python_version >= '3.6'
tzlocal==4.1; python_version >= '3.6'
tzlocal==4.2; python_version >= '3.6'
urllib3==1.26.9; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'
uvicorn[standard]==0.17.6
uvloop==0.16.0
watchdog==2.1.7
watchgod==0.8.1
watchgod==0.8.2
wcwidth==0.2.5
websockets==10.2
whitenoise==6.0.0
whoosh==2.7.4
zipp==3.7.0; python_version < '3.9'
zipp==3.8.0; python_version < '3.9'
zope.interface==5.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'

View File

@@ -1,3 +1,13 @@
<app-toasts></app-toasts>
<router-outlet></router-outlet>
<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>

View File

@@ -4,6 +4,8 @@ import { Router } from '@angular/router'
import { Subscription } 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'
@Component({
selector: 'app-root',
@@ -15,11 +17,16 @@ 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 router: Router,
private uploadDocumentsService: UploadDocumentsService
) {
let anyWindow = window as any
anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.js'
@@ -100,4 +107,36 @@ export class AppComponent implements OnInit, OnDestroy {
}
})
}
public get dragDropEnabled(): boolean {
return !this.router.url.includes('dashboard')
}
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

@@ -12,7 +12,7 @@
</a>
<div class="search-form-container flex-grow-1 py-2 pb-3 pb-sm-2 px-3 ps-md-4 me-sm-auto order-3 order-sm-1">
<form (ngSubmit)="search()" class="form-inline flex-grow-1">
<svg width="1em" height="1em">
<svg width="1em" height="1em" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#search"/>
</svg>
<input class="form-control form-control-sm" type="text" placeholder="Search documents" aria-label="Search"
@@ -25,7 +25,7 @@
<span *ngIf="displayName" class="navbar-text small me-2 text-light d-none d-sm-inline">
{{displayName}}
</span>
<svg width="1.3em" height="1.3em">
<svg width="1.3em" height="1.3em" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#person-circle"/>
</svg>
</button>
@@ -170,21 +170,46 @@
<li class="nav-item">
<div class="d-flex w-100 flex-wrap">
<a class="nav-link pe-2 pb-1" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx">
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="sidebaricon bi bi-github" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="sidebaricon" viewBox="0 0 16 16">
<use xlink:href="assets/bootstrap-icons.svg#github" />
</svg>&nbsp;<ng-container i18n>GitHub</ng-container>
</a>
<a class="nav-link-additional small text-muted ms-3" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests" title="Suggest an idea">
<svg xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" fill="currentColor" class="bi bi-lightbulb pe-1" viewBox="0 0 16 16">
<path d="M2 6a6 6 0 1 1 10.174 4.31c-.203.196-.359.4-.453.619l-.762 1.769A.5.5 0 0 1 10.5 13a.5.5 0 0 1 0 1 .5.5 0 0 1 0 1l-.224.447a1 1 0 0 1-.894.553H6.618a1 1 0 0 1-.894-.553L5.5 15a.5.5 0 0 1 0-1 .5.5 0 0 1 0-1 .5.5 0 0 1-.46-.302l-.761-1.77a1.964 1.964 0 0 0-.453-.618A5.984 5.984 0 0 1 2 6zm6-5a5 5 0 0 0-3.479 8.592c.263.254.514.564.676.941L5.83 12h4.342l.632-1.467c.162-.377.413-.687.676-.941A5 5 0 0 0 8 1z"/>
<svg xmlns="http://www.w3.org/2000/svg" width="1.1em" height="1.1em" fill="currentColor" class="me-1" viewBox="0 0 16 16">
<use xlink:href="assets/bootstrap-icons.svg#lightbulb" />
</svg>
<ng-container i18n>Suggest an idea</ng-container>
</a>
</div>
</li>
<li class="nav-item mt-2">
<div class="px-3 py-2 text-muted small">
{{versionString}}
<div class="px-3 py-2 text-muted small d-flex align-items-center flex-wrap">
<div class="me-3">{{ versionString }}</div>
<div *ngIf="appRemoteVersion" class="version-check">
<ng-template #updateAvailablePopContent>
<span class="small">Paperless-ngx v{{ appRemoteVersion.version }} <ng-container i18n>is available.</ng-container><br/><ng-container i18n>Click to view.</ng-container></span>
</ng-template>
<ng-template #updateCheckingNotEnabledPopContent>
<span class="small"><ng-container i18n>Checking for updates is disabled.</ng-container><br/><ng-container i18n>Click for more information.</ng-container></span>
</ng-template>
<ng-container *ngIf="appRemoteVersion.feature_is_set; else updateCheckNotSet">
<a *ngIf="appRemoteVersion.update_available" class="small text-decoration-none" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx/releases"
[ngbPopover]="updateAvailablePopContent" popoverClass="shadow" triggers="mouseenter:mouseleave" container="body">
<svg fill="currentColor" class="me-1" width="1.2em" height="1.2em" style="vertical-align: text-top;" viewBox="0 0 16 16">
<use xlink:href="assets/bootstrap-icons.svg#info-circle" />
</svg>
<ng-container *ngIf="appRemoteVersion?.update_available" i18n>Update available</ng-container>
</a>
</ng-container>
<ng-template #updateCheckNotSet>
<a class="small text-decoration-none" target="_blank" rel="noopener noreferrer" href="https://paperless-ngx.readthedocs.io/en/latest/configuration.html#update-checking"
[ngbPopover]="updateCheckingNotEnabledPopContent" popoverClass="shadow" triggers="mouseenter:mouseleave" container="body">
<svg fill="currentColor" class="me-1" width="1.2em" height="1.2em" style="vertical-align: text-top;" viewBox="0 0 16 16">
<use xlink:href="assets/bootstrap-icons.svg#info-circle" />
</svg>
</a>
</ng-template>
</div>
</div>
</li>
</ul>

View File

@@ -1,4 +1,3 @@
@import "/src/theme";
/*
* Sidebar
*/
@@ -35,20 +34,24 @@
.sidebar .nav-link {
font-weight: 500;
}
.sidebar .nav-link .sidebaricon {
margin-right: 4px;
}
&:hover, &.active, &:focus {
color: var(--bs-primary);
}
.sidebar .nav-link.active {
color: var(--bs-primary);
font-weight: bold;
}
&:focus-visible {
outline: none;
background-color: var(--bs-body-bg);
}
.sidebar .nav-link.active .sidebaricon,
.sidebar .nav-link:hover .sidebaricon {
color: inherit;
&.active {
font-weight: bold;
}
.sidebaricon {
margin-right: 4px;
color: inherit;
}
}
.sidebar-heading {
@@ -171,8 +174,28 @@
&:focus {
background-color: rgba(0, 0, 0, 0.3);
color: var(--bs-light);
flex-grow: 1;
padding-left: 0.5rem;
}
}
}
.version-check {
animation: pulse 2s ease-in-out 0s 1;
}
@keyframes pulse {
0% {
opacity: 0;
}
25% {
opacity: 100%;
}
75% {
opacity: 0;
}
100% {
opacity: 100%;
}
}

View File

@@ -18,6 +18,10 @@ import { DocumentDetailComponent } from '../document-detail/document-detail.comp
import { Meta } from '@angular/platform-browser'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import { FILTER_FULLTEXT_QUERY } from 'src/app/data/filter-rule-type'
import {
RemoteVersionService,
AppRemoteVersion,
} from 'src/app/services/rest/remote-version.service'
@Component({
selector: 'app-app-frame',
@@ -32,10 +36,18 @@ export class AppFrameComponent {
private searchService: SearchService,
public savedViewService: SavedViewService,
private list: DocumentListViewService,
private meta: Meta
) {}
private meta: Meta,
private remoteVersionService: RemoteVersionService
) {
this.remoteVersionService
.checkForUpdates()
.subscribe((appRemoteVersion: AppRemoteVersion) => {
this.appRemoteVersion = appRemoteVersion
})
}
versionString = `${environment.appTitle} ${environment.version}`
appRemoteVersion
isMenuCollapsed: boolean = true

View File

@@ -1,5 +1,3 @@
@import "/src/theme";
.badge-corner {
position: absolute;
top: -8px;
@@ -42,7 +40,7 @@
filter: brightness(0.5);
&.active {
background-color: var(--ngx-primary-lighten-30);
background-color: var(--pngx-primary-lighten-30);
}
}

View File

@@ -2,7 +2,7 @@
*ngFor="let toast of toasts"
[header]="toast.title" [autohide]="true" [delay]="toast.delay"
[class]="toast.classname"
(hide)="toastService.closeToast(toast)">
(hidden)="toastService.closeToast(toast)">
<p>{{toast.content}}</p>
<p *ngIf="toast.action"><button class="btn btn-sm btn-outline-secondary" (click)="toastService.closeToast(toast); toast.action()">{{toast.actionName}}</button></p>
</ngb-toast>

View File

@@ -5,3 +5,7 @@
margin: 0.5em;
z-index: 1200;
}
.toast:not(.show) {
display: block; // this corrects an ng-bootstrap bug that prevented animations
}

View File

@@ -1,5 +1,3 @@
@import "/src/theme";
form {
position: relative;
}
@@ -33,3 +31,7 @@ form {
mix-blend-mode: soft-light;
pointer-events: none;
}
::ng-deep .ngx-file-drop__drop-zone--over {
background-color: var(--pngx-primary-faded) !important;
}

View File

@@ -6,7 +6,7 @@ import {
FileStatus,
FileStatusPhase,
} from 'src/app/services/consumer-status.service'
import { DocumentService } from 'src/app/services/rest/document.service'
import { UploadDocumentsService } from 'src/app/services/upload-documents.service'
const MAX_ALERTS = 5
@@ -19,8 +19,8 @@ export class UploadFileWidgetComponent implements OnInit {
alertsExpanded = false
constructor(
private documentService: DocumentService,
private consumerStatusService: ConsumerStatusService
private consumerStatusService: ConsumerStatusService,
private uploadDocumentsService: UploadDocumentsService
) {}
getStatus() {
@@ -116,48 +116,6 @@ export class UploadFileWidgetComponent implements OnInit {
public fileLeave(event) {}
public dropped(files: NgxFileDropEntry[]) {
for (const droppedFile of files) {
if (droppedFile.fileEntry.isFile) {
const fileEntry = droppedFile.fileEntry as FileSystemFileEntry
fileEntry.file((file: File) => {
let formData = new FormData()
formData.append('document', file, file.name)
let status = this.consumerStatusService.newFileUpload(file.name)
status.message = $localize`Connecting...`
this.documentService.uploadDocument(formData).subscribe(
(event) => {
if (event.type == HttpEventType.UploadProgress) {
status.updateProgress(
FileStatusPhase.UPLOADING,
event.loaded,
event.total
)
status.message = $localize`Uploading...`
} else if (event.type == HttpEventType.Response) {
status.taskId = event.body['task_id']
status.message = $localize`Upload complete, waiting...`
}
},
(error) => {
switch (error.status) {
case 400: {
this.consumerStatusService.fail(status, error.error.document)
break
}
default: {
this.consumerStatusService.fail(
status,
$localize`HTTP error: ${error.status} ${error.statusText}`
)
break
}
}
}
)
})
}
}
this.uploadDocumentsService.uploadFiles(files)
}
}

View File

@@ -135,20 +135,27 @@
</li>
<li [ngbNavItem]="4" class="d-md-none">
<a ngbNavLink>Preview</a>
<ng-template ngbNavContent *ngIf="pdfPreview.offsetParent == undefined">
<ng-container *ngIf="getContentType() == 'application/pdf'">
<div class="preview-sticky pdf-viewer-container" *ngIf="!useNativePdfViewer ; else nativePdfViewer">
<pdf-viewer [src]="previewUrl" [original-size]="false" [show-borders]="true" [show-all]="true" [render-text-mode]="2"></pdf-viewer>
<a ngbNavLink>Preview</a>
<ng-template ngbNavContent *ngIf="pdfPreview.offsetParent == undefined">
<div class="position-relative">
<ng-container *ngIf="getContentType() == 'application/pdf'">
<div class="preview-sticky pdf-viewer-container" *ngIf="!useNativePdfViewer ; else nativePdfViewer">
<pdf-viewer [src]="{ url: previewUrl, password: password }" [original-size]="false" [show-borders]="true" [show-all]="true" [(page)]="previewCurrentPage" [render-text-mode]="2" (error)="onError($event)" (after-load-complete)="pdfPreviewLoaded($event)"></pdf-viewer>
</div>
<ng-template #nativePdfViewer>
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
</ng-template>
</ng-container>
<ng-container *ngIf="getContentType() == 'text/plain'">
<object [data]="previewUrl | safeUrl" type="text/plain" class="preview-sticky bg-white" width="100%"></object>
</ng-container>
<div *ngIf="requiresPassword" class="password-prompt">
<form>
<input autocomplete="" class="form-control" i18n-placeholder placeholder="Enter Password" type="password" (keyup)="onPasswordKeyUp($event)" />
</form>
</div>
</div>
<ng-template #nativePdfViewer>
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
</ng-template>
</ng-container>
<ng-container *ngIf="getContentType() == 'text/plain'">
<object [data]="previewUrl | safeUrl" type="text/plain" class="preview-sticky bg-white" width="100%"></object>
</ng-container>
</ng-template>
</ng-template>
</li>
</ul>
@@ -160,10 +167,10 @@
</form>
</div>
<div class="col-md-6 col-xl-8 mb-3 d-none d-md-block" #pdfPreview>
<div class="col-md-6 col-xl-8 mb-3 d-none d-md-block position-relative" #pdfPreview>
<ng-container *ngIf="getContentType() == 'application/pdf'">
<div class="preview-sticky pdf-viewer-container" *ngIf="!useNativePdfViewer ; else nativePdfViewer">
<pdf-viewer [src]="previewUrl" [original-size]="false" [show-borders]="true" [show-all]="true" [(page)]="previewCurrentPage" [render-text-mode]="2" (after-load-complete)="pdfPreviewLoaded($event)"></pdf-viewer>
<pdf-viewer [src]="{ url: previewUrl, password: password }" [original-size]="false" [show-borders]="true" [show-all]="true" [(page)]="previewCurrentPage" [render-text-mode]="2" (error)="onError($event)" (after-load-complete)="pdfPreviewLoaded($event)"></pdf-viewer>
</div>
<ng-template #nativePdfViewer>
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
@@ -172,5 +179,11 @@
<ng-container *ngIf="getContentType() == 'text/plain'">
<object [data]="previewUrl | safeUrl" type="text/plain" class="preview-sticky bg-white" width="100%"></object>
</ng-container>
<div *ngIf="requiresPassword" class="password-prompt">
<form>
<input autocomplete="" class="form-control" i18n-placeholder placeholder="Enter Password" type="password" (keyup)="onPasswordKeyUp($event)" />
</form>
</div>
</div>
</div>

View File

@@ -17,3 +17,10 @@
--page-margin: 1px 0 -8px;
width: 100% !important;
}
.password-prompt {
position: absolute;
top: 30%;
left: 30%;
right: 30%;
}

View File

@@ -1,10 +1,4 @@
import {
Component,
OnInit,
OnDestroy,
ViewChild,
ElementRef,
} from '@angular/core'
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { ActivatedRoute, Router } from '@angular/router'
import { NgbModal, NgbNav } from '@ng-bootstrap/ng-bootstrap'
@@ -90,6 +84,11 @@ export class DocumentDetailComponent
isDirty$: Observable<boolean>
unsubscribeNotifier: Subject<any> = new Subject()
requiresPassword: boolean = false
password: string
ogDate: Date
@ViewChild('nav') nav: NgbNav
@ViewChild('pdfPreview') set pdfPreview(element) {
// this gets called when compontent added or removed from DOM
@@ -145,7 +144,21 @@ export class DocumentDetailComponent
ngOnInit(): void {
this.documentForm.valueChanges
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe((wow) => {
.subscribe((changes) => {
if (this.ogDate) {
let newDate = new Date(changes['created'])
newDate.setHours(
this.ogDate.getHours(),
this.ogDate.getMinutes(),
this.ogDate.getSeconds(),
this.ogDate.getMilliseconds()
)
this.documentForm.patchValue(
{ created: this.formatDate(newDate) },
{ emitEvent: false }
)
}
Object.assign(this.document, this.documentForm.value)
})
@@ -186,17 +199,25 @@ export class DocumentDetailComponent
this.updateComponent(doc)
}
this.ogDate = new Date(doc.created)
// Initialize dirtyCheck
this.store = new BehaviorSubject({
title: doc.title,
content: doc.content,
created: doc.created,
created: this.formatDate(this.ogDate),
correspondent: doc.correspondent,
document_type: doc.document_type,
archive_serial_number: doc.archive_serial_number,
tags: [...doc.tags],
})
// ensure we're always starting with 24-char ISO8601 string
this.documentForm.patchValue(
{ created: this.formatDate(this.ogDate) },
{ emitEvent: false }
)
this.isDirty$ = dirtyCheck(
this.documentForm,
this.store.asObservable()
@@ -450,5 +471,22 @@ export class DocumentDetailComponent
pdfPreviewLoaded(pdf: PDFDocumentProxy) {
this.previewNumPages = pdf.numPages
if (this.password) this.requiresPassword = false
}
onError(event) {
if (event.name == 'PasswordException') {
this.requiresPassword = true
}
}
onPasswordKeyUp(event: KeyboardEvent) {
if ('Enter' == event.key) {
this.password = (event.target as HTMLInputElement).value
}
}
formatDate(date: Date): string {
return date.toISOString().split('.')[0] + 'Z'
}
}

View File

@@ -57,13 +57,18 @@
</div>
<div class="col-auto ms-auto mb-2 mb-xl-0 d-flex">
<div class="btn-group btn-group-sm me-2">
<button type="button" class="btn btn-outline-primary btn-sm" (click)="downloadSelected()">
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
<button type="button" [disabled]="awaitingDownload" class="btn btn-outline-primary btn-sm" (click)="downloadSelected()">
<svg *ngIf="!awaitingDownload" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#download" />
</svg>&nbsp;<ng-container i18n>Download</ng-container>
</svg>
<div *ngIf="awaitingDownload" class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">Preparing download...</span>
</div>
&nbsp;
<ng-container i18n>Download</ng-container>
</button>
<div class="btn-group" ngbDropdown role="group" aria-label="Button group with nested dropdown">
<button class="btn btn-outline-primary btn-sm dropdown-toggle-split" ngbDropdownToggle></button>
<button [disabled]="awaitingDownload" class="btn btn-outline-primary btn-sm dropdown-toggle-split" ngbDropdownToggle></button>
<div class="dropdown-menu shadow" ngbDropdownMenu>
<button ngbDropdownItem i18n (click)="downloadSelected('originals')">Download originals</button>
</div>

View File

@@ -39,6 +39,7 @@ export class BulkEditorComponent {
tagSelectionModel = new FilterableDropdownSelectionModel()
correspondentSelectionModel = new FilterableDropdownSelectionModel()
documentTypeSelectionModel = new FilterableDropdownSelectionModel()
awaitingDownload: boolean
constructor(
private documentTypeService: DocumentTypeService,
@@ -317,10 +318,12 @@ export class BulkEditorComponent {
}
downloadSelected(content = 'archive') {
this.awaitingDownload = true
this.documentService
.bulkDownload(Array.from(this.list.selected), content)
.subscribe((result: any) => {
saveAs(result, 'documents.zip')
this.awaitingDownload = false
})
}
}

View File

@@ -1,5 +1,3 @@
@import "/src/theme";
.result-content {
overflow-wrap: anywhere;
}
@@ -60,7 +58,7 @@
}
.doc-img-background-selected {
background-color: var(--ngx-primary-faded);
background-color: var(--pngx-primary-faded);
}
.card-info {

View File

@@ -1,5 +1,3 @@
@import "/src/theme";
.card-text {
font-size: 90%;
}
@@ -45,7 +43,7 @@
}
.doc-img-background-selected {
background-color: var(--ngx-primary-faded);
background-color: var(--pngx-primary-faded);
}
.card-info {

View File

@@ -75,7 +75,7 @@
</app-page-header>
<div class="sticky-top py-2 mt-n2 mt-sm-n3 py-sm-4 bg-body mx-n3 px-3">
<div class="row sticky-top pt-4 pb-2 pb-lg-4 bg-body">
<app-filter-editor [hidden]="isBulkEditing" [(filterRules)]="list.filterRules" [unmodifiedFilterRules]="unmodifiedFilterRules" #filterEditor></app-filter-editor>
<app-bulk-editor [hidden]="!isBulkEditing"></app-bulk-editor>
</div>
@@ -100,7 +100,7 @@
<ng-container *ngTemplateOutlet="pagination"></ng-container>
<ng-container *ngIf="list.error ; else documentListNoError">
<div class="alert alert-danger" role="alert">Error while loading documents: {{list.error}}</div>
<div class="alert alert-danger" role="alert"><ng-container i18n>Error while loading documents</ng-container>: {{list.error}}</div>
</ng-container>
<ng-template #documentListNoError>
@@ -185,7 +185,7 @@
</tbody>
</table>
<div class="m-n2 row row-cols-paperless-cards" *ngIf="displayMode == 'smallCards'">
<div class="row row-cols-paperless-cards" *ngIf="displayMode == 'smallCards'">
<app-document-card-small class="p-0" [selected]="list.isSelected(d)" (toggleSelected)="toggleSelected(d, $event)" [document]="d" *ngFor="let d of list.documents; trackBy: trackByDocumentId" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)" (clickDocumentType)="clickDocumentType($event)"></app-document-card-small>
</div>
<div *ngIf="list.documents?.length > 15" class="mt-3">

View File

@@ -1,11 +1,13 @@
@import "/src/theme";
::ng-deep app-document-list app-page-header > div.mb-3 {
margin-bottom: 0 !important;
}
tr {
user-select: none;
}
.table-row-selected {
background-color: var(--ngx-primary-faded);
background-color: var(--pngx-primary-faded);
}
$paperless-card-breakpoints: (

View File

@@ -243,8 +243,12 @@ export class DocumentListComponent implements OnInit, OnDestroy, AfterViewInit {
$localize`View "${savedView.name}" created successfully.`
)
},
error: (error) => {
modal.componentInstance.error = error.error
error: (httpError) => {
let error = httpError.error
if (error.filter_rules) {
error.filter_rules = error.filter_rules.map((r) => r.value)
}
modal.componentInstance.error = error
modal.componentInstance.buttonsEnabled = true
},
})

View File

@@ -50,7 +50,7 @@
</div>
</div>
<div class="w-100 d-xl-none"></div>
<div class="col col-xl-auto mb-2 mb-xl-0">
<div class="col col-xl-auto">
<button class="btn btn-link btn-sm px-0 mx-0 ms-xl-n3" [disabled]="!rulesModified" (click)="resetSelected()">
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x me-1" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>

View File

@@ -8,6 +8,11 @@
<app-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></app-input-text>
<app-input-check i18n-title title="Show in sidebar" formControlName="showInSideBar"></app-input-check>
<app-input-check i18n-title title="Show on dashboard" formControlName="showOnDashboard"></app-input-check>
<div *ngIf="error?.filter_rules" class="alert alert-danger" role="alert">
<h6 class="alert-heading" i18n>Filter rules error occurred while saving this view</h6>
<ng-container i18n>The error returned was</ng-container>:<br/>
{{ error.filter_rules }}
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="cancel()" i18n [disabled]="!buttonsEnabled">Cancel</button>

View File

@@ -7,7 +7,7 @@
<ul ngbNav #nav="ngbNav" class="nav-tabs">
<li [ngbNavItem]="1">
<a ngbNavLink i18n>General settings</a>
<a ngbNavLink i18n>General</a>
<ng-template ngbNavContent>
<h4 i18n>Appearance</h4>
@@ -104,7 +104,7 @@
<div class="col-md-3 col-form-label">
<span i18n>Theme Color</span>
</div>
<div class="col-3">
<div class="col col-md-3">
<app-input-color i18n-title formControlName="themeColor" [error]="error?.color"></app-input-color>
</div>
<div class="col-2">

View File

@@ -9,7 +9,7 @@ import {
import { PaperlessDocument } from '../data/paperless-document'
import { PaperlessSavedView } from '../data/paperless-saved-view'
import { DOCUMENT_LIST_SERVICE } from '../data/storage-keys'
import { DocumentService } from './rest/document.service'
import { DocumentService, DOCUMENT_SORT_FIELDS } from './rest/document.service'
import { SettingsService, SETTINGS_KEYS } from './settings.service'
/**
@@ -160,7 +160,24 @@ export class DocumentListViewService {
activeListViewState.currentPage = 1
this.reload()
} else {
this.error = error.error
let errorMessage
if (
typeof error.error !== 'string' &&
Object.keys(error.error).length > 0
) {
// e.g. { archive_serial_number: Array<string> }
errorMessage = Object.keys(error.error)
.map((fieldName) => {
const fieldError: Array<string> = error.error[fieldName]
return `${
DOCUMENT_SORT_FIELDS.find((f) => f.field == fieldName)?.name
}: ${fieldError[0]}`
})
.join(', ')
} else {
errorMessage = error.error
}
this.error = errorMessage
}
},
})

View File

@@ -0,0 +1,23 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { map, Observable } from 'rxjs'
import { environment } from 'src/environments/environment'
export interface AppRemoteVersion {
version: string
update_available: boolean
feature_is_set: boolean
}
@Injectable({
providedIn: 'root',
})
export class RemoteVersionService {
constructor(private http: HttpClient) {}
public checkForUpdates(): Observable<AppRemoteVersion> {
return this.http.get<AppRemoteVersion>(
`${environment.apiBaseUrl}remote_version/`
)
}
}

View File

@@ -9,7 +9,11 @@ import {
} from '@angular/core'
import { Meta } from '@angular/platform-browser'
import { CookieService } from 'ngx-cookie-service'
import { hexToHsl } from 'src/app/utils/color'
import {
BRIGHTNESS,
estimateBrightnessForColor,
hexToHsl,
} from 'src/app/utils/color'
export interface PaperlessSettings {
key: string
@@ -132,28 +136,41 @@ export class SettingsService {
: this.renderer.removeClass(this.document.body, 'color-scheme-dark')
}
// remove these in case they were there
this.renderer.removeClass(this.document.body, 'primary-dark')
this.renderer.removeClass(this.document.body, 'primary-light')
if (themeColor) {
const hsl = hexToHsl(themeColor)
const bgBrightnessEstimate = estimateBrightnessForColor(themeColor)
if (bgBrightnessEstimate == BRIGHTNESS.DARK) {
this.renderer.addClass(this.document.body, 'primary-dark')
this.renderer.removeClass(this.document.body, 'primary-light')
} else {
this.renderer.addClass(this.document.body, 'primary-light')
this.renderer.removeClass(this.document.body, 'primary-dark')
}
this.renderer.setStyle(
document.documentElement,
document.body,
'--pngx-primary',
`${+hsl.h * 360},${hsl.s * 100}%`,
RendererStyleFlags2.DashCase
)
this.renderer.setStyle(
document.documentElement,
document.body,
'--pngx-primary-lightness',
`${hsl.l * 100}%`,
RendererStyleFlags2.DashCase
)
} else {
this.renderer.removeStyle(
document.documentElement,
document.body,
'--pngx-primary',
RendererStyleFlags2.DashCase
)
this.renderer.removeStyle(
document.documentElement,
document.body,
'--pngx-primary-lightness',
RendererStyleFlags2.DashCase
)

View File

@@ -0,0 +1,74 @@
import { Injectable } from '@angular/core'
import { HttpEventType } from '@angular/common/http'
import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop'
import {
ConsumerStatusService,
FileStatusPhase,
} from './consumer-status.service'
import { DocumentService } from './rest/document.service'
import { Subscription } from 'rxjs'
@Injectable({
providedIn: 'root',
})
export class UploadDocumentsService {
private uploadSubscriptions: Array<Subscription> = []
constructor(
private documentService: DocumentService,
private consumerStatusService: ConsumerStatusService
) {}
uploadFiles(files: NgxFileDropEntry[]) {
for (const droppedFile of files) {
if (droppedFile.fileEntry.isFile) {
const fileEntry = droppedFile.fileEntry as FileSystemFileEntry
fileEntry.file((file: File) => {
let formData = new FormData()
formData.append('document', file, file.name)
let status = this.consumerStatusService.newFileUpload(file.name)
status.message = $localize`Connecting...`
this.uploadSubscriptions[file.name] = this.documentService
.uploadDocument(formData)
.subscribe({
next: (event) => {
if (event.type == HttpEventType.UploadProgress) {
status.updateProgress(
FileStatusPhase.UPLOADING,
event.loaded,
event.total
)
status.message = $localize`Uploading...`
} else if (event.type == HttpEventType.Response) {
status.taskId = event.body['task_id']
status.message = $localize`Upload complete, waiting...`
this.uploadSubscriptions[file.name]?.complete()
}
},
error: (error) => {
switch (error.status) {
case 400: {
this.consumerStatusService.fail(
status,
error.error.document
)
break
}
default: {
this.consumerStatusService.fail(
status,
$localize`HTTP error: ${error.status} ${error.statusText}`
)
break
}
}
this.uploadSubscriptions[file.name]?.complete()
},
})
})
}
}
}
}

View File

@@ -1,4 +1,9 @@
import { HSL } from 'ngx-color'
import { HSL, RGB } from 'ngx-color'
export const BRIGHTNESS = {
LIGHT: 'light',
DARK: 'dark',
}
function componentToHex(c) {
var hex = Math.floor(c).toString(16)
@@ -86,14 +91,42 @@ export function rgbToHsl(r, g, b) {
}
export function hexToHsl(hex: string): HSL {
const rgb = hexToRGB(hex)
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b)
return { h: hsl[0], s: hsl[1], l: hsl[2] }
}
export function hexToRGB(hex: string): RGB {
hex = hex.replace('#', '')
let aRgbHex = hex.match(/.{1,2}/g)
const hsl = rgbToHsl(
parseInt(aRgbHex[0], 16),
parseInt(aRgbHex[1], 16),
parseInt(aRgbHex[2], 16)
)
return { h: hsl[0], s: hsl[1], l: hsl[2] }
return {
r: parseInt(aRgbHex[0], 16),
g: parseInt(aRgbHex[1], 16),
b: parseInt(aRgbHex[2], 16),
}
}
export function computeLuminance(color: RGB) {
// Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
const colorKeys = Object.keys(color)
for (var i = 0; i < 3; i++) {
var rgb = color[colorKeys[i]]
rgb /= 255
rgb = rgb < 0.03928 ? rgb / 12.92 : Math.pow((rgb + 0.055) / 1.055, 2.4)
color[i] = rgb
}
return 0.2126 * color[0] + 0.7152 * color[1] + 0.0722 * color[2]
}
export function estimateBrightnessForColor(colorHex: string) {
// See <https://www.w3.org/TR/WCAG20/#contrast-ratiodef>
// Adapted from https://api.flutter.dev/flutter/material/ThemeData/estimateBrightnessForColor.html
const rgb = hexToRGB(colorHex)
const luminance = computeLuminance(rgb)
const kThreshold = 0.15
return (luminance + 0.05) * (luminance + 0.05) > kThreshold
? BRIGHTNESS.LIGHT
: BRIGHTNESS.DARK
}
export function randomColor() {

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 579 KiB

After

Width:  |  Height:  |  Size: 861 KiB

View File

@@ -5,7 +5,7 @@ export const environment = {
apiBaseUrl: document.baseURI + 'api/',
apiVersion: '2',
appTitle: 'Paperless-ngx',
version: '1.6.0',
version: '1.7.0',
webSocketHost: window.location.host,
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
webSocketBaseUrl: base_url.pathname + 'ws/',

View File

@@ -616,7 +616,7 @@
<context context-type="linenumber">4</context>
</context-group>
<note priority="1" from="description">This button dismisses all status messages about processed documents on the dashboard (failed and successful)</note>
<target state="translated">Afskedig afsluttede</target>
<target state="translated">Ryd afsluttede</target>
</trans-unit>
<trans-unit id="118343233500414755" datatype="html">
<source>Drop documents here or</source>
@@ -2016,7 +2016,7 @@
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context>
</context-group>
<target state="translated">Visning sprog</target>
<target state="translated">Visningssprog</target>
</trans-unit>
<trans-unit id="53523152145406584" datatype="html">
<source>You need to reload the page after applying a new language.</source>
@@ -2232,7 +2232,7 @@
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">163</context>
</context-group>
<target state="translated">Ingen gemte visninger angivet.</target>
<target state="translated">Ingen gemte visninger.</target>
</trans-unit>
<trans-unit id="5610279464668232148" datatype="html" approved="yes">
<source>Saved view &quot;<x id="PH" equiv-text="savedView.name"/>&quot; deleted.</source>

View File

@@ -2136,7 +2136,7 @@
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">103</context>
</context-group>
<target state="final">Edition en masse</target>
<target state="final">Édition en masse</target>
</trans-unit>
<trans-unit id="8158899674926420054" datatype="html" approved="yes">
<source>Show confirmation dialogs</source>

View File

@@ -2452,7 +2452,7 @@
<context context-type="sourcefile">src/app/services/open-documents.service.ts</context>
<context context-type="linenumber">97</context>
</context-group>
<target state="translated">Istnieją niezapisane zmiany.</target>
<target state="translated">Masz niezapisane zmiany.</target>
</trans-unit>
<trans-unit id="3305084982600522070" datatype="html">
<source>Are you sure you want to leave?</source>

View File

@@ -54,14 +54,14 @@
</context-group>
<target state="final">Документ <x id="PH" equiv-text="status.filename"/> обрабатывается paperless</target>
</trans-unit>
<trans-unit id="2173456130768795374" datatype="html">
<trans-unit id="2173456130768795374" datatype="html" approved="yes">
<source>Paperless-ngx</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">app title</note>
<target state="translated">Paperless-ngx</target>
<target state="final">Paperless-ngx</target>
</trans-unit>
<trans-unit id="7100953725264790651" datatype="html" approved="yes">
<source>Search documents</source>
@@ -433,7 +433,7 @@
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
<context context-type="linenumber">45</context>
</context-group>
<target state="translated">Нажмите снова, чтобы исключить элементы.</target>
<target state="translated">Нажмите еще раз, чтобы исключить элементы.</target>
</trans-unit>
<trans-unit id="7593728289020204896" datatype="html" approved="yes">
<source>Not assigned</source>

View File

@@ -1352,7 +1352,7 @@
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">202</context>
</context-group>
<target state="translated">Ova radnja će trajno obrisati <x id="PH" equiv-text="this.list.selected.size"/> selektovane dokumente.</target>
<target state="translated">Ova radnja će trajno obrisati <x id="PH" equiv-text="this.list.selected.size"/> selektovan(a) dokument(a).</target>
</trans-unit>
<trans-unit id="5641451190833696892" datatype="html">
<source>This operation cannot be undone.</source>

View File

@@ -4,27 +4,146 @@ $enable-negative-margins: true;
@import "node_modules/bootstrap/scss/bootstrap";
@import "~@ng-select/ng-select/themes/default.theme.css";
@import "theme";
@import "theme_dark";
@import "print";
.toolbaricon {
width: 1.2em;
height: 1.2em;
}
.buttonicon {
width: 1.2em;
height: 1.2em;
}
.sidebaricon {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
// Paperless-ngx styles
body {
font-size: 0.875rem;
height: 100vh;
}
* {
transition: background-color 0.3s ease, border-color 0.3s ease;
}
svg.logo {
.leaf {
fill: var(--bs-primary) !important;
}
.text {
fill: var(--bs-body-color) !important;
}
}
.navbar.bg-primary {
--bs-primary: hsl(var(--pngx-primary),var(--pngx-primary-lightness));
--bs-primary-rgb: var(--bs-primary);
}
.border {
border-color: var(--bs-border-color) !important;
}
.border-end {
border-right: 1px solid var(--bs-border-color) !important;
}
.border-start {
border-left: 1px solid var(--bs-border-color) !important;
}
.border-bottom {
border-bottom: 1px solid var(--bs-border-color) !important;
}
.nav-link, .list-group-item {
color: var(--bs-body-color);
}
.bg-body {
background-color: var(--bs-body-bg);
}
.bg-primary {
background-color: var(--bs-primary) !important;
color: var(--pngx-primary-text-contrast);
}
.navbar-brand {
color: var(--pngx-primary-text-contrast) !important;
}
.navbar .dropdown .btn {
color: var(--pngx-primary-text-contrast) !important;
}
.btn-primary {
color: var(--pngx-primary-text-contrast);
background-color: var(--bs-primary);
border-color: var(--bs-primary);
&:hover, &:focus {
background-color: var(--pngx-primary-darken-5);
border-color: var(--pngx-primary-darken-5);
}
&:disabled, &.disabled {
color: var(--pngx-primary-text-contrast);
background-color: var(--pngx-primary-darken-5) !important;
border-color: var(--pngx-primary-darken-5) !important;
}
}
.btn-outline-primary {
border-color: var(--bs-primary) !important;
color: var(--bs-primary) !important;
&:hover, &:focus, &.active, &:active {
background-color: var(--bs-primary) !important;
color: var(--bs-light) !important;
}
}
.btn-outline-secondary {
color: var(--bs-secondary);
&:hover {
color: var(--bs-light);
}
}
.nav-item .sidebaricon {
color: var(--bs-secondary);
}
.btn:focus,
.btn:active:focus,
.dropdown-item:focus,
.btn-check:focus + .btn,
.form-control:focus,
.form-check-input:focus,
.form-check-radio:focus,
.form-select:focus {
box-shadow: 0 0 0 0.25rem hsla(var(--pngx-primary), var(--pngx-primary-lightness), var(--pngx-focus-alpha));
}
.form-switch .form-check-input:focus {
background-image: escape-svg(url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#bbb'/></svg>"));
}
.nav-item a:focus-visible {
outline: none;
background-color: var(--bs-body-bg);
}
a.navbar-brand:focus-visible {
outline: none;
color: var(--pngx-primary-darken-5);
}
.dropdown.show {
> .btn-primary {
background-color: var(--bs-primary);
border-color: var(--bs-primary);
}
> .btn-outline-primary {
color: var(--pngx-primary-text-contrast) !important;
}
}
a, a:hover, .btn-link, .btn-link:hover {
color: var(--bs-primary);
}
.form-control-dark {
@@ -116,6 +235,251 @@ body {
}
}
.form-control:not(.btn),
input,
select,
textarea,
.form-select:not(.is-invalid):not(:disabled),
.form-check-input,
.ng-select .ng-select-container .ng-value-container .ng-input > input {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
&:focus {
background-color: var(--pngx-bg-darker);
color: var(--bs-body-color);
}
}
.form-check-input:checked {
background-color: var(--bs-primary);
border-color: var(--bs-primary);
}
.form-check-input:focus {
border-color: var(--bs-primary);
}
.page-link {
color: var(--bs-secondary);
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color) !important;
&:hover, &:focus {
background-color: var(--bs-primary) !important;
color: var(--bs-light) !important;
}
}
.page-item.active .page-link {
background-color: var(--bs-primary);
border-color: var(--bs-primary) !important;
color: var(--bs-light);
}
.page-item.disabled .page-link {
background-color: var(--pngx-bg-darker);
}
.nav-tabs {
border-bottom: 1px solid var(--bs-border-color);
.nav-link {
color: var(--bs-primary);
&.active, &:hover {
border-color: var(--bs-border-color);
background-color: var(--bs-body-bg);
color: var(--bs-body-color);
border-bottom: 1px solid transparent;
}
&:focus {
border-color: var(--bs-border-color);
}
&.active:focus, &:active {
border-bottom: 1px solid transparent;
}
}
}
.ng-select-container,
.ng-select.ng-select-opened > .ng-select-container,
.ng-dropdown-panel,
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option {
background-color: var(--bs-body-bg) !important;
color: var(--bs-body-color) !important;
border-color: var(--bs-border-color) !important;
input:focus {
background-color: transparent !important;
}
}
.input-group-text {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
}
.list-group-item {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
&:hover, &:focus {
background-color: var(--bs-body-bg);
}
}
.dropdown-menu {
background-color: var(--bs-body-bg);
.dropdown-divider {
border-color: var(--bs-border-color);
}
.dropdown-item {
color: var(--bs-body-color);
&:hover, &:focus {
background-color: var(--pngx-bg-darker);
color: var(--bs-body-color);
}
&.active {
background-color: var(--bs-primary);
color: var(--pngx-primary-text-contrast);
}
}
}
.doc-img-container {
border: none !important;
border-top-left-radius: .25rem;
border-top-right-radius: .25rem;
overflow: hidden;
}
// icons
.toolbaricon {
width: 1.2em;
height: 1.2em;
}
.buttonicon {
width: 1.2em;
height: 1.2em;
}
.sidebaricon {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
table.table {
color: var(--bs-body-color);
.des,.asc {
background-color: var(--bs-body-bg) !important;
}
}
.close {
color: var(--bs-body-color);
}
.modal .btn-close {
color: var(--bs-body-color);
}
.main-dropzone {
height: 100%;
width: 100%;
&.ngx-file-drop__drop-zone--over {
background-color: transparent !important;
}
}
.global-dropzone-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(23, 84, 31, .8);
z-index: 1055; // $zindex-modal
pointer-events: none !important;
user-select: none !important;
text-align: center;
padding-top: 25%;
&.show {
opacity: 1 !important;
}
&.hide {
display: none;
}
}
.ngx-file-drop__drop-zone--over .global-dropzone-overlay {
opacity: 0;
}
.inert {
pointer-events: none !important;
user-select: none !important;
}
.alert-danger {
color: var(--bs-body-color);
background-color: var(--bs-danger);
border-color: var(--bs-danger);
}
.progress {
background-color: var(--bs-body-bg);
}
.ngb-dp-header,
.ngb-dp-weekdays,
.ngb-dp-month {
background-color: var(--bs-body-bg);
}
.popover {
.popover-header,
.popover-body {
background-color: var(--pngx-bg-alt);
border-color: var(--bs-border-color);
color: var(--bs-body-color);
}
}
// fix popover carat colors
.bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="left"] {
border-left-color: var(--pngx-bg-alt);
}
.bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="right"] {
border-right-color: var(--pngx-bg-alt);
}
.bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="top"] {
border-top-color: var(--pngx-bg-alt);
}
.bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="bottom"] {
border-bottom-color: var(--pngx-bg-alt);
}
.bs-popover-bottom .popover-header::before,
.bs-popover-auto[x-placement^=bottom] .popover-header::before {
border-bottom-color: var(--pngx-bg-alt);
}
// Bootstrap 5 tweaks
a.badge {
text-decoration: none;

View File

@@ -1,294 +1,222 @@
:root {
@mixin paperless-green {
// base color e.g. #17541f = hsl(128, 57%, 21%)
--pngx-primary: 128, 57%;
--pngx-primary-lightness: 21%;
}
body {
@include paperless-green;
--pngx-primary-text-contrast: var(--bs-light);
--bs-primary: hsl(var(--pngx-primary), var(--pngx-primary-lightness));
--bs-border-color: var(--bs-gray-400);
--ngx-primary-faded: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 72%));
--ngx-primary-lighten-10: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 10%));
--ngx-primary-lighten-30: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 30%));
--ngx-primary-darken-10: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 10%));
--ngx-primary-darken-15: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 15%));
--ngx-primary-darken-18: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%));
--ngx-bg-darker: var(--bs-gray-100);
--ngx-focus-alpha: 0.3;
--pngx-primary-faded: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 72%));
--pngx-primary-lighten-30: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 30%));
--pngx-primary-darken-5: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 5%));
--pngx-primary-darken-15: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 15%));
--pngx-primary-darken-18: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%));
--pngx-bg-alt: #fff;
--pngx-bg-darker: var(--bs-gray-100);
--pngx-focus-alpha: 0.3;
}
svg.logo {
.leaf {
fill: var(--bs-primary) !important;
// Dark text colors allow for maintain contrast with theme color changes
$text-color-light-bg: #212529;
$text-color-dark-bg: #abb2bf;
$text-color-dark-bg-accent: lighten($text-color-dark-bg, 10%);
// Taken from bootstrap
$form-check-input-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><path fill='none' stroke='#{$text-color-light-bg}' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/></svg>");
$form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='2' fill='#{$text-color-light-bg}'/></svg>");
.primary-light {
--pngx-primary-text-contrast: #{$text-color-light-bg} !important;
.form-check-input:checked[type=checkbox] {
background-image: escape-svg($form-check-input-checked-bg-image-dark);
}
.text {
fill: var(--bs-body-color) !important;
.form-check-input:checked[type=radio] {
background-image: escape-svg($form-check-radio-checked-bg-image-dark);
}
.btn-close {
filter: none !important;
}
}
.nav-link, .list-group-item {
color: var(--bs-body-color);
.primary-dark {
--pngx-primary-text-contrast: #{$text-color-dark-bg} !important;
}
.bg-body {
background-color: var(--bs-body-bg);
// Dark mode
@mixin paperless-green-dark-mode {
--pngx-primary-lightness: 31%;
}
.bg-primary {
background-color: var(--bs-primary) !important;
}
@mixin dark-mode {
--bs-body-color: #{$text-color-dark-bg};
--pngx-body-color-accent: #{$text-color-dark-bg-accent};
--bs-danger: #b71631;
--bs-danger-rgb: 183, 22, 49;
--bs-body-bg: #161618;
--bs-body-bg-rgb: 22, 22, 24;
--bs-light: #1c1c1f;
--bs-light-rgb: 28, 28, 31;
--bs-border-color: #47494f;
--pngx-bg-darker: #101216;
--pngx-bg-alt: #242529;
--pngx-focus-alpha: 0.6;
--pngx-primary-faded: var(--pngx-primary-darken-15);
--pngx-primary-text-contrast: var(--bs-body-color);
.btn-primary {
background-color: var(--bs-primary);
border-color: var(--bs-primary);
&:hover, &:focus {
background-color: var(--ngx-primary-darken-10);
border-color: var(--ngx-primary-darken-10);
}
&:disabled, &.disabled {
background-color: var(--ngx-primary-darken-10) !important;
border-color: var(--ngx-primary-darken-10) !important;
}
}
.btn-outline-primary {
border-color: var(--bs-primary) !important;
color: var(--bs-primary) !important;
&:hover, &:focus, &.active, &:active {
background-color: var(--bs-primary) !important;
color: var(--bs-light) !important;
}
}
.btn-outline-secondary {
color: var(--bs-secondary);
}
.nav-item .sidebaricon {
color: var(--bs-secondary);
}
.btn:focus,
.btn:active:focus,
.dropdown-item:focus,
.btn-check:focus + .btn,
.form-control:focus,
.form-check-input:focus,
.form-check-radio:focus,
.form-select:focus {
box-shadow: 0 0 0 0.25rem hsla(var(--pngx-primary), var(--pngx-primary-lightness), var(--ngx-focus-alpha));
}
.form-switch .form-check-input:focus {
background-image: escape-svg(url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#bbb'/></svg>"));
}
.nav-link:focus-visible, .nav-item a:focus-visible {
outline: none;
background-color: var(--ngx-bg-darker);
}
a.navbar-brand:focus-visible {
outline: none;
color: var(--ngx-primary-darken-10);
}
.dropdown.show {
> .btn-primary {
background-color: var(--bs-primary);
border-color: var(--bs-primary);
}
> .btn-outline-primary {
.text-dark, .text-light {
color: var(--bs-body-color) !important;
}
}
a, a:hover, .btn-link, .btn-link:hover {
color: var(--bs-primary);
}
.form-control:not(.btn),
input,
select,
textarea,
.form-select:not(.is-invalid):not(:disabled),
.form-check-input {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
&:focus {
background-color: var(--ngx-bg-darker);
color: var(--bs-body-color) !important;
}
}
.form-check-input:checked {
background-color: var(--bs-primary);
border-color: var(--bs-primary);
}
.form-check-input:focus {
border-color: var(--bs-primary);
}
.page-link {
color: var(--bs-secondary);
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color) !important;
&:hover, &:focus {
background-color: var(--bs-primary) !important;
color: var(--bs-light) !important;
}
}
.page-item.active .page-link {
background-color: var(--bs-primary);
border-color: var(--bs-primary) !important;
color: var(--bs-light);
}
.page-item.disabled .page-link {
background-color: var(--ngx-bg-darker);
}
.nav-tabs {
border-bottom: 1px solid var(--bs-border-color);
.nav-link {
color: var(--bs-primary);
&.active, &:hover {
border-color: var(--bs-border-color);
background-color: var(--bs-body-bg);
color: var(--bs-body-color);
border-bottom: 1px solid transparent;
}
&:focus {
border-color: var(--bs-border-color);
}
&.active:focus, &:active {
border-bottom: 1px solid transparent;
.btn-primary {
&:hover, &:focus, &.active, &:active {
color: var(--bs-body-color) !important;
}
}
}
.ng-select-container,
.ng-select.ng-select-opened > .ng-select-container,
.ng-dropdown-panel,
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option {
background-color: var(--bs-body-bg) !important;
color: var(--bs-body-color) !important;
border-color: var(--bs-border-color) !important;
input:focus {
background-color: transparent !important;
}
}
.input-group-text {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
}
.list-group-item {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
&:hover, &:focus {
background-color: var(--bs-body-bg);
}
}
.dropdown-menu {
background-color: var(--bs-body-bg);
.dropdown-divider {
border-color: var(--bs-border-color);
.btn-outline-primary {
&:hover, &:focus, &.active, &:active {
color: var(--bs-light) !important;
}
}
.dropdown-item {
.btn-outline-secondary {
&:hover, &:focus, &.active, &:active {
background-color: var(--pngx-bg-darker);
color: var(--bs-primary);
}
}
.btn-light {
color: var(--bs-body-color);
}
&:hover {
background-color: var(--ngx-bg-darker);
color: var(--bs-body-color);
}
.btn .progress {
background-color: var(--pngx-body-color-accent);
}
&.active {
background-color: var(--bs-primary);
.search-form-container {
input, input:focus {
color: var(--bs-body-color) !important;
}
}
}
table.table {
color: var(--bs-body-color);
.card {
background-color: var(--bs-body-bg);
.des,.asc {
background-color: var(--bs-body-bg) !important;
.card-header {
background-color: rgba(0, 0, 0, 0.12);
}
}
}
.close {
color: var(--bs-body-color);
}
.modal .btn-close {
color: var(--bs-body-color);
}
.ngx-file-drop__drop-zone--over {
background-color: var(--ngx-primary-faded) !important;
}
.alert-danger {
color: var(--bs-body-color);
background-color: var(--bs-danger);
border-color: var(--bs-danger);
}
.alert-secondary {
background-color: var(--ngx-primary-darken-18);
border-color: var(--ngx-primary-darken-15);
color: var(--bs-body-color);
}
.ngb-dp-header,
.ngb-dp-weekdays,
.ngb-dp-month {
background-color: var(--bs-body-bg);
}
.popover {
.popover-header,
.popover-body {
background-color: var(--ngx-bg-alt);
.modal-content, .modal-header, .modal-body, .modal-footer {
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
}
app-tag .badge {
filter: brightness(.8);
}
.doc-img {
mix-blend-mode: normal;
border-radius: 0;
border-color: var(--bs-border-color);
filter: invert(10%);
&.border-end {
border-right: none !important;
}
}
.doc-img.inverted {
filter: invert(95%) hue-rotate(180deg);
}
.card-selected .doc-img {
mix-blend-mode: luminosity;
}
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option:hover,
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {
background-color: var(--bs-light);
}
table {
.des,
.asc {
&::after {
filter: invert(0.8); /* arrow is a black inline png bkgd image (!) so use filter */
}
}
&.table-hover > tbody > tr:hover > * {
background-color: var(--bs-light);
color: var(--pngx-body-color-accent);
}
}
.alert-secondary {
background-color: var(--bs-light);
border-color: var(--pngx-bg-darker);
color: var(--bs-body-color);
}
.table-striped > tbody > tr:nth-of-type(odd) > * {
color: var(--pngx-body-color-accent);
}
.close, .modal .btn-close, .alert .btn-close {
text-shadow: 0 1px 0 #666;
}
.modal .btn-close, .alert .btn-close, .toast .btn-close {
filter: invert(1) grayscale(100%) brightness(200%);
}
.toast, .toast-header {
background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 15%), 0.8);
}
.toast,
.toast .toast-header,
.toast .btn-close {
color: var(--pngx-primary-text-contrast);
}
}
// fix popover carat colors
.bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="left"] {
border-left-color: var(--ngx-bg-alt);
}
.bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="right"] {
border-right-color: var(--ngx-bg-alt);
}
.bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="top"] {
border-top-color: var(--ngx-bg-alt);
}
.bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="bottom"] {
border-bottom-color: var(--ngx-bg-alt);
body.color-scheme-dark {
// no custom theme color
&:not(.primary-light):not(.primary-dark) {
@include paperless-green-dark-mode;
.navbar.bg-primary {
// navbar is og green in dark mode
@include paperless-green;
}
}
@include dark-mode;
}
.bs-popover-bottom .popover-header::before,
.bs-popover-auto[x-placement^=bottom] .popover-header::before {
border-bottom-color: var(--ngx-bg-alt);
@media (prefers-color-scheme: dark) {
body.color-scheme-system {
// no custom theme color
&:not(.primary-light):not(.primary-dark) {
@include paperless-green-dark-mode;
.navbar.bg-primary {
// navbar is og green in dark mode
@include paperless-green;
}
}
@include dark-mode;
}
}

View File

@@ -1,168 +0,0 @@
$primary-dark-mode: #45973a;
$primary-dark-mode-rgb: 69, 151, 58;
$primary-dark-mode-darken-10: darken($primary-dark-mode, 10%);
$danger-dark-mode: #b71631;
$danger-dark-mode-rgb: 183, 22, 49;
$bg-dark-mode: #161618;
$bg-dark-mode-rgb: 22, 22, 24;
$bg-dark-mode-accent: #101216;
$bg-dark-mode-alt: #242529;
$bg-light-dark-mode: #1c1c1f;
$bg-light-dark-mode-rgb: 28, 28, 31;
$text-color-dark-mode: #abb2bf;
$text-color-dark-mode-accent: lighten($text-color-dark-mode, 10%);
$border-color-dark-mode: #47494f;
* {
transition: background-color 0.3s ease, border-color 0.3s ease;
}
@mixin dark-mode {
--bs-primary: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 10%));
--bs-danger: #{$danger-dark-mode};
--bs-danger-rgb: #{$danger-dark-mode-rgb};
--bs-body-bg: #{$bg-dark-mode};
--bs-body-bg-rgb: #{$bg-dark-mode-rgb};
--bs-body-color: #{$text-color-dark-mode};
--bs-light: #{$bg-light-dark-mode};
--bs-light-rgb: #{$bg-light-dark-mode-rgb};
--bs-border-color: #{$border-color-dark-mode};
--ngx-bg-darker: #{$bg-dark-mode-accent};
--ngx-bg-alt: #{$bg-dark-mode-alt};
--ngx-body-color-accent: #{$text-color-dark-mode-accent};
--ngx-focus-alpha: 0.7;
--ngx-primary-faded: var(--ngx-primary-darken-15);
.navbar.bg-primary{
--bs-primary: hsl(var(--pngx-primary),var(--pngx-primary-lightness));
--bs-primary-rgb: var(--bs-primary);
}
.navbar-brand {
color: var(--bs-body-color);
}
.border {
border-color: var(--bs-border-color) !important;
}
.border-end {
border-right: 1px solid var(--bs-border-color) !important;
}
.border-start {
border-left: 1px solid var(--bs-border-color) !important;
}
.border-bottom {
border-bottom: 1px solid var(--bs-border-color) !important;
}
.text-dark, .text-light {
color: var(--bs-body-color) !important;
}
.btn-outline-primary, .btn-primary {
&:hover, &:focus, &.active, &:active {
color: var(--ngx-body-color-accent) !important;
}
}
.btn-outline-secondary {
&:hover, &:focus, &.active, &:active {
background-color: var(--ngx-bg-darker);
color: var(--bs-primary);
}
}
.card {
background-color: var(--bs-body-bg);
.card-header {
background-color: rgba(0, 0, 0, 0.12);
}
}
.modal-content, .modal-header, .modal-body, .modal-footer {
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
}
app-tag .badge {
filter: brightness(.8);
}
.doc-img-container {
border: none !important;
border-top-left-radius: .25rem;
border-top-right-radius: .25rem;
overflow: hidden;
}
.doc-img {
mix-blend-mode: normal;
border-radius: 0;
border-color: var(--bs-border-color);
filter: invert(10%);
&.border-end {
border-right: none !important;
}
}
.doc-img.inverted {
filter: invert(95%) hue-rotate(180deg);
}
.card-selected .doc-img {
mix-blend-mode: luminosity;
}
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option:hover,
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {
background-color: $bg-light-dark-mode;
}
table {
.des,
.asc {
&::after {
filter: invert(0.8); /* arrow is a black inline png bkgd image (!) so use filter */
}
}
&.table-hover > tbody > tr:hover > * {
background-color: $bg-light-dark-mode;
color: $text-color-dark-mode-accent;
}
}
.table-striped > tbody > tr:nth-of-type(odd) > * {
color: $text-color-dark-mode-accent;
}
.close, .modal .btn-close {
text-shadow: 0 1px 0 #666;
}
.modal .btn-close {
filter: invert(1) grayscale(100%) brightness(200%);
}
.toast {
background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%), 0.9);
}
.toast-header {
background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 10%), 0.9);
}
}
body.color-scheme-dark {
@include dark-mode;
}
body.color-scheme-system {
@media (prefers-color-scheme: dark) {
@include dark-mode;
}
}

View File

@@ -3,7 +3,9 @@ import os
from pathlib import Path
from pathlib import PurePath
from threading import Thread
from time import monotonic
from time import sleep
from typing import Final
from django.conf import settings
from django.core.management.base import BaseCommand
@@ -53,6 +55,25 @@ def _consume(filepath):
logger.warning(f"Not consuming file {filepath}: Unknown file extension.")
return
# Total wait time: up to 500ms
os_error_retry_count: Final[int] = 50
os_error_retry_wait: Final[float] = 0.01
read_try_count = 0
file_open_ok = False
while (read_try_count < os_error_retry_count) and not file_open_ok:
try:
with open(filepath, "rb"):
file_open_ok = True
except OSError:
read_try_count += 1
sleep(os_error_retry_wait)
if read_try_count >= os_error_retry_count:
logger.warning(f"Not consuming file {filepath}: OS reports file as busy still")
return
tag_ids = None
try:
if settings.CONSUMER_SUBDIRS_AS_TAGS:
@@ -81,19 +102,23 @@ def _consume_wait_unmodified(file):
logger.debug(f"Waiting for file {file} to remain unmodified")
mtime = -1
size = -1
current_try = 0
while current_try < settings.CONSUMER_POLLING_RETRY_COUNT:
try:
new_mtime = os.stat(file).st_mtime
stat_data = os.stat(file)
new_mtime = stat_data.st_mtime
new_size = stat_data.st_size
except FileNotFoundError:
logger.debug(
f"File {file} moved while waiting for it to remain " f"unmodified.",
)
return
if new_mtime == mtime:
if new_mtime == mtime and new_size == size:
_consume(file)
return
mtime = new_mtime
size = new_size
sleep(settings.CONSUMER_POLLING_DELAY)
current_try += 1
@@ -182,14 +207,32 @@ class Command(BaseCommand):
descriptor = inotify.add_watch(directory, inotify_flags)
try:
inotify_debounce: Final[float] = 0.5
notified_files = {}
while not self.stop_flag:
for event in inotify.read(timeout=1000):
if recursive:
path = inotify.get_path(event.wd)
else:
path = directory
filepath = os.path.join(path, event.name)
_consume(filepath)
notified_files[filepath] = monotonic()
# Check the files against the timeout
still_waiting = {}
for filepath in notified_files:
# Time of the last inotify event for this file
last_event_time = notified_files[filepath]
if (monotonic() - last_event_time) > inotify_debounce:
_consume(filepath)
else:
still_waiting[filepath] = last_event_time
# These files are still waiting to hit the timeout
notified_files = still_waiting
except KeyboardInterrupt:
pass

View File

@@ -60,7 +60,7 @@ def match_tags(document, classifier):
def matches(matching_model, document):
search_kwargs = {}
document_content = document.content.lower()
document_content = document.content
# Check that match is not empty
if matching_model.match.strip() == "":

View File

@@ -0,0 +1,20 @@
# Generated by Django 4.0.3 on 2022-04-01 22:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("documents", "1017_alter_savedviewfilterrule_rule_type"),
]
operations = [
migrations.AlterField(
model_name="savedviewfilterrule",
name="value",
field=models.CharField(
blank=True, max_length=255, null=True, verbose_name="value"
),
),
]

View File

@@ -375,7 +375,7 @@ class SavedViewFilterRule(models.Model):
rule_type = models.PositiveIntegerField(_("rule type"), choices=RULE_TYPES)
value = models.CharField(_("value"), max_length=128, blank=True, null=True)
value = models.CharField(_("value"), max_length=255, blank=True, null=True)
class Meta:
verbose_name = _("filter rule")

View File

@@ -23,6 +23,7 @@ from documents.signals import document_consumer_declaration
# - XX. MONTH ZZZZ with XX being 1 or 2 and ZZZZ being 2 or 4 digits
# - MONTH ZZZZ, with ZZZZ being 4 digits
# - MONTH XX, ZZZZ with XX being 1 or 2 and ZZZZ being 4 digits
# - XX MON ZZZZ with XX being 1 or 2 and ZZZZ being 4 digits. MONTH is 3 letters
# TODO: isnt there a date parsing library for this?
@@ -31,7 +32,8 @@ DATE_REGEX = re.compile(
r"(\b|(?!=([_-])))([0-9]{4}|[0-9]{2})[\.\/-]([0-9]{1,2})[\.\/-]([0-9]{1,2})(\b|(?=([_-])))|" # noqa: E501
r"(\b|(?!=([_-])))([0-9]{1,2}[\. ]+[^ ]{3,9} ([0-9]{4}|[0-9]{2}))(\b|(?=([_-])))|" # noqa: E501
r"(\b|(?!=([_-])))([^\W\d_]{3,9} [0-9]{1,2}, ([0-9]{4}))(\b|(?=([_-])))|"
r"(\b|(?!=([_-])))([^\W\d_]{3,9} [0-9]{4})(\b|(?=([_-])))",
r"(\b|(?!=([_-])))([^\W\d_]{3,9} [0-9]{4})(\b|(?=([_-])))|"
r"(\b|(?!=([_-])))(\b[0-9]{1,2}[ \.\/-][A-Z]{3}[ \.\/-][0-9]{4})(\b|(?=([_-])))", # noqa: E501
)

View File

@@ -1,6 +1,12 @@
import logging
import os
import shutil
import tempfile
from typing import List # for type hinting. Can be removed, if only Python >3.8 is used
import tqdm
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django.conf import settings
from django.db.models.signals import post_save
from documents import index
@@ -14,8 +20,12 @@ from documents.models import Document
from documents.models import DocumentType
from documents.models import Tag
from documents.sanity_checker import SanityCheckFailedException
from pdf2image import convert_from_path
from pikepdf import Pdf
from pyzbar import pyzbar
from whoosh.writing import AsyncWriter
logger = logging.getLogger("paperless.tasks")
@@ -62,6 +72,115 @@ def train_classifier():
logger.warning("Classifier error: " + str(e))
def barcode_reader(image) -> List[str]:
"""
Read any barcodes contained in image
Returns a list containing all found barcodes
"""
barcodes = []
# Decode the barcode image
detected_barcodes = pyzbar.decode(image)
if detected_barcodes:
# Traverse through all the detected barcodes in image
for barcode in detected_barcodes:
if barcode.data:
decoded_barcode = barcode.data.decode("utf-8")
barcodes.append(decoded_barcode)
logger.debug(
f"Barcode of type {str(barcode.type)} found: {decoded_barcode}",
)
return barcodes
def scan_file_for_separating_barcodes(filepath: str) -> List[int]:
"""
Scan the provided file for page separating barcodes
Returns a list of pagenumbers, which separate the file
"""
separator_page_numbers = []
separator_barcode = str(settings.CONSUMER_BARCODE_STRING)
# use a temporary directory in case the file os too big to handle in memory
with tempfile.TemporaryDirectory() as path:
pages_from_path = convert_from_path(filepath, output_folder=path)
for current_page_number, page in enumerate(pages_from_path):
current_barcodes = barcode_reader(page)
if separator_barcode in current_barcodes:
separator_page_numbers.append(current_page_number)
return separator_page_numbers
def separate_pages(filepath: str, pages_to_split_on: List[int]) -> List[str]:
"""
Separate the provided file on the pages_to_split_on.
The pages which are defined by page_numbers will be removed.
Returns a list of (temporary) filepaths to consume.
These will need to be deleted later.
"""
os.makedirs(settings.SCRATCH_DIR, exist_ok=True)
tempdir = tempfile.mkdtemp(prefix="paperless-", dir=settings.SCRATCH_DIR)
fname = os.path.splitext(os.path.basename(filepath))[0]
pdf = Pdf.open(filepath)
document_paths = []
logger.debug(f"Temp dir is {str(tempdir)}")
if not pages_to_split_on:
logger.warning("No pages to split on!")
else:
# go from the first page to the first separator page
dst = Pdf.new()
for n, page in enumerate(pdf.pages):
if n < pages_to_split_on[0]:
dst.pages.append(page)
output_filename = "{}_document_0.pdf".format(fname)
savepath = os.path.join(tempdir, output_filename)
with open(savepath, "wb") as out:
dst.save(out)
document_paths = [savepath]
# iterate through the rest of the document
for count, page_number in enumerate(pages_to_split_on):
logger.debug(f"Count: {str(count)} page_number: {str(page_number)}")
dst = Pdf.new()
try:
next_page = pages_to_split_on[count + 1]
except IndexError:
next_page = len(pdf.pages)
# skip the first page_number. This contains the barcode page
for page in range(page_number + 1, next_page):
logger.debug(
f"page_number: {str(page_number)} next_page: {str(next_page)}",
)
dst.pages.append(pdf.pages[page])
output_filename = "{}_document_{}.pdf".format(fname, str(count + 1))
logger.debug(f"pdf no:{str(count)} has {str(len(dst.pages))} pages")
savepath = os.path.join(tempdir, output_filename)
with open(savepath, "wb") as out:
dst.save(out)
document_paths.append(savepath)
logger.debug(f"Temp files are {str(document_paths)}")
return document_paths
def save_to_dir(
filepath: str,
newname: str = None,
target_dir: str = settings.CONSUMPTION_DIR,
):
"""
Copies filepath to target_dir.
Optionally rename the file.
"""
if os.path.isfile(filepath) and os.path.isdir(target_dir):
dst = shutil.copy(filepath, target_dir)
logging.debug(f"saved {str(filepath)} to {str(dst)}")
if newname:
dst_new = os.path.join(target_dir, newname)
logger.debug(f"moving {str(dst)} to {str(dst_new)}")
os.rename(dst, dst_new)
else:
logger.warning(f"{str(filepath)} or {str(target_dir)} don't exist.")
def consume_file(
path,
override_filename=None,
@@ -72,6 +191,48 @@ def consume_file(
task_id=None,
):
# check for separators in current document
if settings.CONSUMER_ENABLE_BARCODES:
separators = []
document_list = []
separators = scan_file_for_separating_barcodes(path)
if separators:
logger.debug(f"Pages with separators found in: {str(path)}")
document_list = separate_pages(path, separators)
if document_list:
for n, document in enumerate(document_list):
# save to consumption dir
# rename it to the original filename with number prefix
if override_filename:
newname = f"{str(n)}_" + override_filename
else:
newname = None
save_to_dir(document, newname=newname)
# if we got here, the document was successfully split
# and can safely be deleted
logger.debug("Deleting file {}".format(path))
os.unlink(path)
# notify the sender, otherwise the progress bar
# in the UI stays stuck
payload = {
"filename": override_filename,
"task_id": task_id,
"current_progress": 100,
"max_progress": 100,
"status": "SUCCESS",
"message": "finished",
}
try:
async_to_sync(get_channel_layer().group_send)(
"status_updates",
{"type": "status_update", "data": payload},
)
except OSError as e:
logger.warning("OSError. It could be, the broker cannot be reached.")
logger.warning(str(e))
return "File successfully split"
# continue with consumption if no barcode was found
document = Consumer().try_consume_file(
path,
override_filename=override_filename,

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

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