diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index 903d578da..b8687dc56 100755 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -122,27 +122,38 @@ install_languages() { if [ ${#langs[@]} -eq 0 ]; then return fi - apt-get update + # Build list of packages to install + to_install=() for lang in "${langs[@]}"; do pkg="tesseract-ocr-$lang" if dpkg --status "$pkg" &>/dev/null; then echo "Package $pkg already installed!" continue - fi - - if ! apt-cache show "$pkg" &>/dev/null; then - echo "Package $pkg not found! :(" - continue - fi - - echo "Installing package $pkg..." - if ! apt-get --assume-yes install "$pkg" &>/dev/null; then - echo "Could not install $pkg" - exit 1 + else + to_install+=("$pkg") fi done + + # Use apt only when we install packages + if [ ${#to_install[@]} -gt 0 ]; then + apt-get update + + for pkg in "${to_install[@]}"; do + + if ! apt-cache show "$pkg" &>/dev/null; then + echo "Skipped $pkg: Package not found! :(" + continue + fi + + echo "Installing package $pkg..." + if ! apt-get --assume-yes install "$pkg" &>/dev/null; then + echo "Could not install $pkg" + exit 1 + fi + done + fi } echo "Paperless-ngx docker container starting..." diff --git a/docs/api.md b/docs/api.md index 7e27f65d1..10b6799ab 100644 --- a/docs/api.md +++ b/docs/api.md @@ -236,12 +236,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: @@ -281,6 +275,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/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 7c0ec396d..c64cef921 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -3094,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? @@ -3324,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 @@ -3372,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 @@ -4646,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 @@ -4654,7 +4638,7 @@ Open filter src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts - 452 + 455 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 7f9871b97..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 @@ -13,7 +13,7 @@ padding: 50px 0 0; /* Height of navbar */ box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1); overflow-y: auto; - --pngx-sidebar-width: 25%; + --pngx-sidebar-width: 100%; max-width: var(--pngx-sidebar-width); .sidebar-heading .spinner-border { 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 @@
} -