diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 345677c05..c39480421 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,7 +48,7 @@ repos: exclude: "(^Pipfile\\.lock$)" # Python hooks - repo: https://github.com/astral-sh/ruff-pre-commit - rev: 'v0.6.4' + rev: 'v0.6.5' hooks: - id: ruff - id: ruff-format diff --git a/Pipfile.lock b/Pipfile.lock index 48a9ad907..4b94f6dfe 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -3473,12 +3473,12 @@ }, "pytest": { "hashes": [ - "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5", - "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce" + "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181", + "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.3.2" + "version": "==8.3.3" }, "pytest-cov": { "hashes": [ @@ -3760,28 +3760,28 @@ }, "ruff": { "hashes": [ - "sha256:0308610470fcc82969082fc83c76c0d362f562e2f0cdab0586516f03a4e06ec6", - "sha256:0b52387d3289ccd227b62102c24714ed75fbba0b16ecc69a923a37e3b5e0aaaa", - "sha256:0ea086601b22dc5e7693a78f3fcfc460cceabfdf3bdc36dc898792aba48fbad6", - "sha256:34d5efad480193c046c86608dbba2bccdc1c5fd11950fb271f8086e0c763a5d1", - "sha256:50e30b437cebef547bd5c3edf9ce81343e5dd7c737cb36ccb4fe83573f3d392e", - "sha256:549daccee5227282289390b0222d0fbee0275d1db6d514550d65420053021a58", - "sha256:66dbfea86b663baab8fcae56c59f190caba9398df1488164e2df53e216248baa", - "sha256:7862f42fc1a4aca1ea3ffe8a11f67819d183a5693b228f0bb3a531f5e40336fc", - "sha256:803b96dea21795a6c9d5bfa9e96127cc9c31a1987802ca68f35e5c95aed3fc0d", - "sha256:932063a03bac394866683e15710c25b8690ccdca1cf192b9a98260332ca93408", - "sha256:ac3b5bfbee99973f80aa1b7cbd1c9cbce200883bdd067300c22a6cc1c7fba212", - "sha256:ac4b75e898ed189b3708c9ab3fc70b79a433219e1e87193b4f2b77251d058d14", - "sha256:bedff9e4f004dad5f7f76a9d39c4ca98af526c9b1695068198b3bda8c085ef60", - "sha256:c44536df7b93a587de690e124b89bd47306fddd59398a0fb12afd6133c7b3818", - "sha256:c4b153fc152af51855458e79e835fb6b933032921756cec9af7d0ba2aa01a258", - "sha256:d02a4127a86de23002e694d7ff19f905c51e338c72d8e09b56bfb60e1681724f", - "sha256:eebe4ff1967c838a1a9618a5a59a3b0a00406f8d7eefee97c70411fefc353617", - "sha256:f0f8968feea5ce3777c0d8365653d5e91c40c31a81d95824ba61d871a11b8523" + "sha256:005256d977021790cc52aa23d78f06bb5090dc0bfbd42de46d49c201533982ae", + "sha256:09c72a833fd3551135ceddcba5ebdb68ff89225d30758027280968c9acdc7810", + "sha256:381413ec47f71ce1d1c614f7779d88886f406f1fd53d289c77e4e533dc6ea200", + "sha256:3a8d42d11fff8d3143ff4da41742a98f8f233bf8890e9fe23077826818f8d680", + "sha256:3e42a57b58e3612051a636bc1ac4e6b838679530235520e8f095f7c44f706ff9", + "sha256:482c1e6bfeb615eafc5899127b805d28e387bd87db38b2c0c41d271f5e58d8cc", + "sha256:4d32d87fab433c0cf285c3683dd4dae63be05fd7a1d65b3f5bf7cdd05a6b96fb", + "sha256:51935067740773afdf97493ba9b8231279e9beef0f2a8079188c4776c25688e0", + "sha256:52e75a82bbc9b42e63c08d22ad0ac525117e72aee9729a069d7c4f235fc4d276", + "sha256:7291e64d7129f24d1b0c947ec3ec4c0076e958d1475c61202497c6aced35dd19", + "sha256:794ada3400a0d0b89e3015f1a7e01f4c97320ac665b7bc3ade24b50b54cb2972", + "sha256:7e4e308f16e07c95fc7753fc1aaac690a323b2bb9f4ec5e844a97bb7fbebd748", + "sha256:800c50371bdcb99b3c1551d5691e14d16d6f07063a518770254227f7f6e8c178", + "sha256:8e25ddd9cd63ba1f3bd51c1f09903904a6adf8429df34f17d728a8fa11174253", + "sha256:932cd69eefe4daf8c7d92bd6689f7e8182571cb934ea720af218929da7bd7d69", + "sha256:9ad7dfbd138d09d9a7e6931e6a7e797651ce29becd688be8a0d4d5f8177b4b0c", + "sha256:a50af6e828ee692fb10ff2dfe53f05caecf077f4210fae9677e06a808275754f", + "sha256:cf4d3fa53644137f6a4a27a2b397381d16454a1566ae5335855c187fbf67e4f5" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==0.6.4" + "version": "==0.6.5" }, "scipy": { "hashes": [ diff --git a/docs/api.md b/docs/api.md index 94ece85ab..057ccaedb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -235,12 +235,6 @@ results: Pagination works exactly the same as it does for normal requests on this endpoint. -Certain limitations apply to full text queries: - -- Results are always sorted by search score. The results matching the - query best will show up first. -- Only a small subset of filtering parameters are supported. - Furthermore, each returned document has an additional `__search_hit__` attribute with various information about the search results: @@ -280,6 +274,67 @@ attribute with various information about the search results: - `rank` is the index of the search results. The first result will have rank 0. +### Filtering by custom fields + +You can filter documents by their custom field values by specifying the +`custom_field_lookup` query parameter. Here are some recipes for common +use cases: + +1. Documents with a custom field "due" (date) between Aug 1, 2024 and + Sept 1, 2024 (inclusive): + + `?custom_field_lookup=["due", "range", ["2024-08-01", "2024-09-01"]]` + +2. Documents with a custom field "customer" (text) that equals "bob" + (case sensitive): + + `?custom_field_lookup=["customer", "exact", "bob"]` + +3. Documents with a custom field "answered" (boolean) set to `true`: + + `?custom_field_lookup=["answered", "exact", true]` + +4. Documents with a custom field "favorite animal" (select) set to either + "cat" or "dog": + + `?custom_field_lookup=["favorite animal", "in", ["cat", "dog"]]` + +5. Documents with a custom field "address" (text) that is empty: + + `?custom_field_lookup=["OR", ["address", "isnull", true], ["address", "exact", ""]]` + +6. Documents that don't have a field called "foo": + + `?custom_field_lookup=["foo", "exists", false]` + +7. Documents that have document links "references" to both document 3 and 7: + + `?custom_field_lookup=["references", "contains", [3, 7]]` + +All field types support basic operations including `exact`, `in`, `isnull`, +and `exists`. String, URL, and monetary fields support case-insensitive +substring matching operations including `icontains`, `istartswith`, and +`iendswith`. Integer, float, and date fields support arithmetic comparisons +including `gt` (>), `gte` (>=), `lt` (<), `lte` (<=), and `range`. +Lastly, document link fields support a `contains` operator that behaves +like a "is superset of" check. + +!!! warning + + It is possible to do case-insensitive exact match (i.e., `iexact`) and + case-sensitive substring match (i.e., `contains`, `startswith`, + `endswith`) for string, URL, and monetary fields, but + [they may not work as expected on some database backends](https://docs.djangoproject.com/en/5.1/ref/databases/#substring-matching-and-case-sensitivity). + + It is also possible to use regular expressions to match string, URL, and + monetary fields, but the syntax is database-dependent, and accepting + regular expressions from untrusted sources could make your instance + vulnerable to regular expression denial of service attacks. + + For these reasons the above expressions are disabled by default. + If you understand the implications, you may enable them by uncommenting + `PAPERLESS_CUSTOM_FIELD_LOOKUP_OPT_IN` in your configuration file. + ### `/api/search/autocomplete/` Get auto completions for a partial search term. diff --git a/docs/configuration.md b/docs/configuration.md index 3530849dd..57edb7c72 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -608,9 +608,18 @@ You can optionally also automatically redirect users to the SSO login with [PAPE #### [`PAPERLESS_ACCOUNT_SESSION_REMEMBER=`](#PAPERLESS_ACCOUNT_SESSION_REMEMBER) {#PAPERLESS_ACCOUNT_SESSION_REMEMBER} -: Only applies to regular (non-SSO) accounts. See the corresponding +: If false, sessions will expire at browser close, if true will use `PAPERLESS_SESSION_COOKIE_AGE` for expiration. See the corresponding [django-allauth documentation](https://docs.allauth.org/en/latest/account/configuration.html) + Defaults to True + +#### [`PAPERLESS_SESSION_COOKIE_AGE=`](#PAPERLESS_SESSION_COOKIE_AGE) {#PAPERLESS_SESSION_COOKIE_AGE} + +: Login session cookie expiration. Applies if `PAPERLESS_ACCOUNT_SESSION_REMEMBER` is enabled. See the corresponding +[django documentation](https://docs.djangoproject.com/en/5.1/ref/settings/#std-setting-SESSION_COOKIE_AGE) + + Defaults to 1209600 (2 weeks) + ## OCR settings {#ocr} Paperless uses [OCRmyPDF](https://ocrmypdf.readthedocs.io/en/latest/) diff --git a/paperless.conf.example b/paperless.conf.example index 63ee7be22..5fabbf390 100644 --- a/paperless.conf.example +++ b/paperless.conf.example @@ -81,6 +81,7 @@ #PAPERLESS_THUMBNAIL_FONT_NAME= #PAPERLESS_IGNORE_DATES= #PAPERLESS_ENABLE_UPDATE_CHECK= +#PAPERLESS_ALLOW_CUSTOM_FIELD_LOOKUP=iexact,contains,startswith,endswith,regex,iregex # Tika settings diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 18ba85ce4..201cb5faa 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -726,7 +726,7 @@ src/app/components/manage/mail/mail.component.html - 105 + 137 src/app/components/manage/management-list/management-list.component.html @@ -1092,11 +1092,19 @@ src/app/components/manage/mail/mail.component.html - 39 + 41 src/app/components/manage/mail/mail.component.html - 85 + 51 + + + src/app/components/manage/mail/mail.component.html + 99 + + + src/app/components/manage/mail/mail.component.html + 111 src/app/components/manage/management-list/management-list.component.html @@ -1398,7 +1406,7 @@ src/app/components/manage/mail/mail.component.html - 69 + 81 src/app/components/manage/management-list/management-list.component.html @@ -1493,7 +1501,15 @@ src/app/components/manage/mail/mail.component.html - 88 + 54 + + + src/app/components/manage/mail/mail.component.html + 100 + + + src/app/components/manage/mail/mail.component.html + 114 src/app/components/manage/management-list/management-list.component.html @@ -1549,7 +1565,11 @@ src/app/components/manage/workflows/workflows.component.html - 38 + 41 + + + src/app/components/manage/workflows/workflows.component.html + 52 @@ -1879,7 +1899,7 @@ src/app/components/manage/mail/mail.component.html - 66 + 78 src/app/components/manage/management-list/management-list.component.html @@ -2207,7 +2227,7 @@ src/app/components/manage/mail/mail.component.ts - 173 + 179 src/app/components/manage/management-list/management-list.component.ts @@ -2215,7 +2235,7 @@ src/app/components/manage/workflows/workflows.component.ts - 97 + 115 @@ -2402,11 +2422,19 @@ src/app/components/manage/mail/mail.component.html - 36 + 40 src/app/components/manage/mail/mail.component.html - 82 + 48 + + + src/app/components/manage/mail/mail.component.html + 98 + + + src/app/components/manage/mail/mail.component.html + 108 src/app/components/manage/management-list/management-list.component.html @@ -2442,7 +2470,11 @@ src/app/components/manage/workflows/workflows.component.html - 35 + 40 + + + src/app/components/manage/workflows/workflows.component.html + 49 @@ -2546,7 +2578,7 @@ src/app/components/manage/mail/mail.component.ts - 175 + 181 src/app/components/manage/management-list/management-list.component.ts @@ -2554,7 +2586,7 @@ src/app/components/manage/workflows/workflows.component.ts - 99 + 117 @@ -3062,22 +3094,6 @@ src/app/components/common/clearable-badge/clearable-badge.component.html 2 - - src/app/components/common/dates-dropdown/dates-dropdown.component.html - 38 - - - src/app/components/common/dates-dropdown/dates-dropdown.component.html - 59 - - - src/app/components/common/dates-dropdown/dates-dropdown.component.html - 104 - - - src/app/components/common/dates-dropdown/dates-dropdown.component.html - 125 - Are you sure? @@ -3292,36 +3308,36 @@ src/app/components/common/dates-dropdown/dates-dropdown.component.html - 91 + 89 After src/app/components/common/dates-dropdown/dates-dropdown.component.html - 34 + 42 src/app/components/common/dates-dropdown/dates-dropdown.component.html - 100 + 106 Before src/app/components/common/dates-dropdown/dates-dropdown.component.html - 55 + 62 src/app/components/common/dates-dropdown/dates-dropdown.component.html - 121 + 126 Added src/app/components/common/dates-dropdown/dates-dropdown.component.html - 76 + 74 src/app/components/document-list/document-list.component.html @@ -3340,28 +3356,28 @@ Last 7 days src/app/components/common/dates-dropdown/dates-dropdown.component.ts - 45 + 48 Last month src/app/components/common/dates-dropdown/dates-dropdown.component.ts - 50 + 53 Last 3 months src/app/components/common/dates-dropdown/dates-dropdown.component.ts - 55 + 58 Last year src/app/components/common/dates-dropdown/dates-dropdown.component.ts - 60 + 63 @@ -3665,7 +3681,7 @@ src/app/components/manage/mail/mail.component.html - 68 + 80 @@ -4614,7 +4630,7 @@ Not assigned src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts - 340 + 343 Filter drop down element to filter for documents with no correspondent/type/tag assigned @@ -4622,7 +4638,7 @@ Open filter src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts - 452 + 455 @@ -5025,6 +5041,22 @@ src/app/components/common/system-status-dialog/system-status-dialog.component.html 156 + + src/app/components/manage/mail/mail.component.html + 101 + + + src/app/components/manage/mail/mail.component.html + 119 + + + src/app/components/manage/workflows/workflows.component.html + 42 + + + src/app/components/manage/workflows/workflows.component.html + 57 + Regenerate auth token @@ -7420,35 +7452,35 @@ No mail accounts defined. src/app/components/manage/mail/mail.component.html - 50 + 62 Mail rules src/app/components/manage/mail/mail.component.html - 58 + 70 Add Rule src/app/components/manage/mail/mail.component.html - 60 + 72 Sort Order src/app/components/manage/mail/mail.component.html - 67 + 79 No mail rules defined. src/app/components/manage/mail/mail.component.html - 96 + 128 @@ -7511,56 +7543,56 @@ Saved rule "". src/app/components/manage/mail/mail.component.ts - 152 + 151 Error saving rule. src/app/components/manage/mail/mail.component.ts - 163 + 162 Confirm delete mail rule src/app/components/manage/mail/mail.component.ts - 171 + 177 This operation will permanently delete this mail rule. src/app/components/manage/mail/mail.component.ts - 172 + 178 Deleted mail rule src/app/components/manage/mail/mail.component.ts - 181 + 187 Error deleting mail rule. src/app/components/manage/mail/mail.component.ts - 190 + 196 Permissions updated src/app/components/manage/mail/mail.component.ts - 212 + 218 Error updating permissions src/app/components/manage/mail/mail.component.ts - 217 + 223 src/app/components/manage/management-list/management-list.component.ts @@ -7821,49 +7853,49 @@ No workflows defined. src/app/components/manage/workflows/workflows.component.html - 46 + 66 Saved workflow "". src/app/components/manage/workflows/workflows.component.ts - 79 + 78 Error saving workflow. src/app/components/manage/workflows/workflows.component.ts - 87 + 86 Confirm delete workflow src/app/components/manage/workflows/workflows.component.ts - 95 + 113 This operation will permanently delete this workflow. src/app/components/manage/workflows/workflows.component.ts - 96 + 114 Deleted workflow src/app/components/manage/workflows/workflows.component.ts - 105 + 123 Error deleting workflow. src/app/components/manage/workflows/workflows.component.ts - 110 + 128 diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index cdb6e3be5..f5427c713 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -12,6 +12,9 @@ z-index: 995; /* Behind the navbar */ padding: 50px 0 0; /* Height of navbar */ box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1); + overflow-y: auto; + --pngx-sidebar-width: 100%; + max-width: var(--pngx-sidebar-width); .sidebar-heading .spinner-border { width: 0.8em; @@ -24,15 +27,15 @@ // These come from the col-* classes for non-slim sidebar, needed for animation @media (min-width: 768px) { - max-width: 25%; + --pngx-sidebar-width: 25%; } @media (min-width: 992px) { - max-width: 16.66666667%; + --pngx-sidebar-width: 16.66666667%; } @media (min-width: 2400px) { - max-width: 8.33333333%; + --pngx-sidebar-width: 8.33333333%; } transition: all .2s ease; @@ -109,12 +112,17 @@ main { .sidebar-slim-toggler { display: block; - position: absolute; - right: -12px; + position: fixed; + left: calc(var(--pngx-sidebar-width) - 12px); top: 60px; z-index: 996; --bs-btn-padding-x: 0.35rem; --bs-btn-padding-y: 0.125rem; + transition: all .2s ease; + } + + .sidebar.slim .sidebar-slim-toggler { + --pngx-sidebar-width: 50px !important; } } diff --git a/src-ui/src/app/components/common/dates-dropdown/dates-dropdown.component.html b/src-ui/src/app/components/common/dates-dropdown/dates-dropdown.component.html index 8991363d2..dcab4606d 100644 --- a/src-ui/src/app/components/common/dates-dropdown/dates-dropdown.component.html +++ b/src-ui/src/app/components/common/dates-dropdown/dates-dropdown.component.html @@ -1,4 +1,4 @@ -
+
-
+
{{rd.name}}
@@ -28,20 +28,19 @@
} -