mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
This commit is contained in:
commit
990e905a04
1
.github/release-drafter.yml
vendored
1
.github/release-drafter.yml
vendored
@ -30,7 +30,6 @@ replacers: # Changes "Feature: Update checker" to "Update checker"
|
||||
replace: ''
|
||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||
change-title-escapes: '\<*_&#@'
|
||||
tag-prefix: "ngx-"
|
||||
template: |
|
||||
# Changelog
|
||||
|
||||
|
5
.github/scripts/get-build-json.py
vendored
5
.github/scripts/get-build-json.py
vendored
@ -53,10 +53,7 @@ def _main():
|
||||
git_tag = None
|
||||
extra_config = {}
|
||||
|
||||
if args.package == "frontend":
|
||||
# Version is just the branch or tag name
|
||||
version = branch_name
|
||||
elif args.package in pipfile_data["default"]:
|
||||
if args.package in pipfile_data["default"]:
|
||||
# Read the version from Pipfile.lock
|
||||
pkg_data = pipfile_data["default"][args.package]
|
||||
pkg_version = pkg_data["version"].split("==")[-1]
|
||||
|
113
.github/workflows/ci.yml
vendored
113
.github/workflows/ci.yml
vendored
@ -3,8 +3,10 @@ name: ci
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- ngx-*
|
||||
- beta-*
|
||||
# https://semver.org/#spec-item-2
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||
# https://semver.org/#spec-item-9
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+-beta.rc[0-9]+'
|
||||
branches-ignore:
|
||||
- 'translations**'
|
||||
pull_request:
|
||||
@ -53,7 +55,7 @@ jobs:
|
||||
|
||||
prepare-docker-build:
|
||||
name: Prepare Docker Pipeline Data
|
||||
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-'))
|
||||
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || contains(github.ref, 'beta.rc') || startsWith(github.ref, 'refs/tags/v'))
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- documentation
|
||||
@ -104,15 +106,6 @@ jobs:
|
||||
echo ${build_json}
|
||||
|
||||
echo ::set-output name=jbig2enc-json::${build_json}
|
||||
-
|
||||
name: Setup frontend image
|
||||
id: frontend-setup
|
||||
run: |
|
||||
build_json=$(python ${GITHUB_WORKSPACE}/.github/scripts/get-build-json.py frontend)
|
||||
|
||||
echo ${build_json}
|
||||
|
||||
echo ::set-output name=frontend-json::${build_json}
|
||||
|
||||
outputs:
|
||||
|
||||
@ -124,8 +117,6 @@ jobs:
|
||||
|
||||
jbig2enc-json: ${{ steps.jbig2enc-setup.outputs.jbig2enc-json}}
|
||||
|
||||
frontend-json: ${{ steps.frontend-setup.outputs.frontend-json}}
|
||||
|
||||
build-qpdf-debs:
|
||||
name: qpdf
|
||||
needs:
|
||||
@ -175,57 +166,6 @@ jobs:
|
||||
PIKEPDF_GIT_TAG=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).git_tag }}
|
||||
PIKEPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).version }}
|
||||
|
||||
build-frontend:
|
||||
name: Compile frontend
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-build-frontend-${{ github.ref_name }}
|
||||
cancel-in-progress: false
|
||||
needs:
|
||||
- prepare-docker-build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Login to Github Container Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Compile frontend
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./docker-builders/Dockerfile.frontend
|
||||
tags: ${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).image_tag }}
|
||||
# The compilation is identical between different platforms
|
||||
# The buildx and QEMU setup is left, just in case that ever changes
|
||||
# But the platform is set to the runner's native for speedup
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
cache-from: type=registry,ref=${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).cache_tag }}
|
||||
cache-to: type=registry,mode=max,ref=${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).cache_tag }}
|
||||
-
|
||||
name: Export frontend artifact from docker
|
||||
run: |
|
||||
docker create --name frontend-extract ${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).image_tag }}
|
||||
docker cp frontend-extract:/src/src/documents/static/frontend src/documents/static/frontend/
|
||||
-
|
||||
name: Upload frontend artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: frontend-compiled
|
||||
path: src/documents/static/frontend/
|
||||
|
||||
# build and push image to docker hub.
|
||||
build-docker-image:
|
||||
runs-on: ubuntu-20.04
|
||||
@ -238,7 +178,6 @@ jobs:
|
||||
- build-jbig2enc
|
||||
- build-qpdf-debs
|
||||
- build-pikepdf-wheel
|
||||
- build-frontend
|
||||
steps:
|
||||
-
|
||||
name: Check pushing to Docker Hub
|
||||
@ -260,8 +199,12 @@ jobs:
|
||||
ghcr.io/${{ github.repository }}
|
||||
name=paperlessngx/paperless-ngx,enable=${{ steps.docker-hub.outputs.enable }}
|
||||
tags: |
|
||||
# Tag branches with branch name
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
# Process semver tags
|
||||
# For a tag x.y.z or vX.Y.Z, output an x.y.z and x.y image tag
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
@ -297,18 +240,33 @@ jobs:
|
||||
tags: ${{ steps.docker-meta.outputs.tags }}
|
||||
labels: ${{ steps.docker-meta.outputs.labels }}
|
||||
build-args: |
|
||||
REPO=${{ github.repository }}
|
||||
JBIG2ENC_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.jbig2enc-json).version }}
|
||||
QPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.qpdf-json).version }}
|
||||
PIKEPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).version }}
|
||||
PSYCOPG2_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.psycopg2-json).version }}
|
||||
FRONTEND_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).version }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
# Get cache layers from this branch, then dev, then main
|
||||
# This allows new branches to get at least some cache benefits, generally from dev
|
||||
cache-from: |
|
||||
type=registry,ref=ghcr.io/${{ github.repository }}/builder/cache/app:${{ github.ref_name }}
|
||||
type=registry,ref=ghcr.io/${{ github.repository }}/builder/cache/app:dev
|
||||
type=registry,ref=ghcr.io/${{ github.repository }}/builder/cache/app:main
|
||||
cache-to: |
|
||||
type=registry,mode=max,ref=ghcr.io/${{ github.repository }}/builder/cache/app:${{ github.ref_name }}
|
||||
-
|
||||
name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
||||
-
|
||||
name: Export frontend artifact from docker
|
||||
run: |
|
||||
docker create --name frontend-extract ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
||||
docker cp frontend-extract:/usr/src/paperless/src/documents/static/frontend src/documents/static/frontend/
|
||||
-
|
||||
name: Upload frontend artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: frontend-compiled
|
||||
path: src/documents/static/frontend/
|
||||
|
||||
build-release:
|
||||
needs:
|
||||
@ -382,7 +340,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- build-release
|
||||
if: github.ref_type == 'tag' && (startsWith(github.ref_name, 'ngx-') || startsWith(github.ref_name, 'beta-'))
|
||||
if: github.ref_type == 'tag' && (startsWith(github.ref_name, 'v') || contains(github.ref_name, '-beta.rc'))
|
||||
steps:
|
||||
-
|
||||
name: Download release artifact
|
||||
@ -394,12 +352,11 @@ jobs:
|
||||
name: Get version
|
||||
id: get_version
|
||||
run: |
|
||||
if [[ $GITHUB_REF == refs/tags/ngx-* ]]; then
|
||||
echo ::set-output name=version::${GITHUB_REF#refs/tags/ngx-}
|
||||
echo ::set-output name=prerelease::false
|
||||
elif [[ $GITHUB_REF == refs/tags/beta-* ]]; then
|
||||
echo ::set-output name=version::${GITHUB_REF#refs/tags/beta-}
|
||||
echo ::set-output name=version::${{ github.ref_name }}
|
||||
if [[ ${{ contains(github.ref_name, '-beta.rc') }} == 'true' ]]; then
|
||||
echo ::set-output name=prerelease::true
|
||||
else
|
||||
echo ::set-output name=prerelease::false
|
||||
fi
|
||||
-
|
||||
name: Create Release and Changelog
|
||||
@ -407,7 +364,7 @@ jobs:
|
||||
uses: release-drafter/release-drafter@v5
|
||||
with:
|
||||
name: Paperless-ngx ${{ steps.get_version.outputs.version }}
|
||||
tag: ngx-${{ steps.get_version.outputs.version }}
|
||||
tag: ${{ 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
|
||||
|
2
.github/workflows/reusable-ci-backend.yml
vendored
2
.github/workflows/reusable-ci-backend.yml
vendored
@ -87,7 +87,7 @@ jobs:
|
||||
-
|
||||
name: Get changed files
|
||||
id: changed-files-specific
|
||||
uses: tj-actions/changed-files@v18.7
|
||||
uses: tj-actions/changed-files@v19
|
||||
with:
|
||||
files: |
|
||||
src/**
|
||||
|
40
Dockerfile
40
Dockerfile
@ -1,19 +1,32 @@
|
||||
# Default to pulling from the main repo registry when manually building
|
||||
ARG REPO="paperless-ngx/paperless-ngx"
|
||||
# Pull the installer images from the library
|
||||
# These are all built previously
|
||||
# They provide either a .deb or .whl
|
||||
|
||||
# These are all built previously in the pipeline
|
||||
# They provide either a .deb, .whl or whatever npm outputs
|
||||
ARG JBIG2ENC_VERSION
|
||||
ARG QPDF_VERSION
|
||||
ARG PIKEPDF_VERSION
|
||||
ARG PSYCOPG2_VERSION
|
||||
ARG FRONTEND_VERSION
|
||||
|
||||
FROM ghcr.io/${REPO}/builder/jbig2enc:${JBIG2ENC_VERSION} as jbig2enc-builder
|
||||
FROM ghcr.io/${REPO}/builder/qpdf:${QPDF_VERSION} as qpdf-builder
|
||||
FROM ghcr.io/${REPO}/builder/pikepdf:${PIKEPDF_VERSION} as pikepdf-builder
|
||||
FROM ghcr.io/${REPO}/builder/psycopg2:${PSYCOPG2_VERSION} as psycopg2-builder
|
||||
FROM ghcr.io/${REPO}/builder/frontend:${FRONTEND_VERSION} as compile-frontend
|
||||
FROM ghcr.io/paperless-ngx/paperless-ngx/builder/jbig2enc:${JBIG2ENC_VERSION} as jbig2enc-builder
|
||||
FROM ghcr.io/paperless-ngx/paperless-ngx/builder/qpdf:${QPDF_VERSION} as qpdf-builder
|
||||
FROM ghcr.io/paperless-ngx/paperless-ngx/builder/pikepdf:${PIKEPDF_VERSION} as pikepdf-builder
|
||||
FROM ghcr.io/paperless-ngx/paperless-ngx/builder/psycopg2:${PSYCOPG2_VERSION} as psycopg2-builder
|
||||
|
||||
FROM --platform=$BUILDPLATFORM node:16-bullseye-slim AS compile-frontend
|
||||
|
||||
# This stage compiles the frontend
|
||||
# This stage runs once for the native platform, as the outputs are not
|
||||
# dependent on target arch
|
||||
# Inputs: None
|
||||
|
||||
COPY ./src-ui /src/src-ui
|
||||
|
||||
WORKDIR /src/src-ui
|
||||
RUN set -eux \
|
||||
&& npm update npm -g \
|
||||
&& npm ci --no-optional
|
||||
RUN set -eux \
|
||||
&& ./node_modules/.bin/ng build --configuration production
|
||||
|
||||
FROM python:3.9-slim-bullseye as main-app
|
||||
|
||||
@ -156,8 +169,11 @@ COPY gunicorn.conf.py .
|
||||
|
||||
WORKDIR /usr/src/paperless/src/
|
||||
|
||||
# copy app
|
||||
COPY --from=compile-frontend /src/src/ ./
|
||||
# copy backend
|
||||
COPY ./src ./
|
||||
|
||||
# copy frontend
|
||||
COPY --from=compile-frontend /src/src/documents/static/frontend/ ./documents/static/frontend/
|
||||
|
||||
# add users, setup scripts
|
||||
RUN set -eux \
|
||||
|
3
Pipfile
3
Pipfile
@ -19,7 +19,7 @@ djangorestframework = "~=3.13"
|
||||
filelock = "*"
|
||||
fuzzywuzzy = {extras = ["speedup"], version = "*"}
|
||||
gunicorn = "*"
|
||||
imap-tools = "~=0.53.0"
|
||||
imap-tools = "~=0.54.0"
|
||||
langdetect = "*"
|
||||
pathvalidate = "*"
|
||||
pillow = "~=9.1"
|
||||
@ -53,7 +53,6 @@ concurrent-log-handler = "*"
|
||||
zipp = {version = "*", markers = "python_version < '3.9'"}
|
||||
pyzbar = "*"
|
||||
pdf2image = "*"
|
||||
click = "==8.0.4"
|
||||
bleach = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
119
Pipfile.lock
generated
119
Pipfile.lock
generated
@ -44,11 +44,11 @@
|
||||
},
|
||||
"asgiref": {
|
||||
"hashes": [
|
||||
"sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0",
|
||||
"sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9"
|
||||
"sha256:45a429524fba18aba9d512498b19d220c4d628e75b40cf5c627524dbaebc5cc1",
|
||||
"sha256:fddeea3c53fa99d0cdb613c3941cc6e52d822491fc2753fba25768fb5bf4e865"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.5.0"
|
||||
"version": "==3.5.1"
|
||||
},
|
||||
"async-timeout": {
|
||||
"hashes": [
|
||||
@ -99,6 +99,7 @@
|
||||
"sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac",
|
||||
"sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version < '3.9'",
|
||||
"version": "==0.2.1"
|
||||
},
|
||||
@ -206,11 +207,11 @@
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e",
|
||||
"sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"
|
||||
"sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
|
||||
"sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.2"
|
||||
"version": "==8.1.3"
|
||||
},
|
||||
"coloredlogs": {
|
||||
"hashes": [
|
||||
@ -476,7 +477,7 @@
|
||||
"sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
|
||||
"sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"markers": "python_version >= '3'",
|
||||
"version": "==3.3"
|
||||
},
|
||||
"imap-tools": {
|
||||
@ -498,6 +499,7 @@
|
||||
"sha256:b6062987dfc51f0fcb809187cffbd60f35df7acb4589091f154214af6d0d49d3",
|
||||
"sha256:e447dc01619b1e951286f3929be820029d48c75eb25d265c28b92a16548212b8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version < '3.9'",
|
||||
"version": "==5.7.1"
|
||||
},
|
||||
@ -713,36 +715,36 @@
|
||||
},
|
||||
"pikepdf": {
|
||||
"hashes": [
|
||||
"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"
|
||||
"sha256:101ec256a8d312c17decae52226cf32a3e7dc834583134300c2f4e60b70e6e91",
|
||||
"sha256:12b5b3cfc649e2542576a7e55c11e245278f14f727f116904893e54329102867",
|
||||
"sha256:1b8f68a75c0a6f6d4d102d0821365ae2aaa9ab635c6eb6c840569a56b1a266f4",
|
||||
"sha256:1bef3512be59fe0f481375b7eb415ca51ee7c80555031401f5f17ee3392e4add",
|
||||
"sha256:1d3141916dc9efc433fd22beba544f67a53a805800c3ff902baffa398ef4c85e",
|
||||
"sha256:3052df8514d26b676c50e65afc49a1d260c43a08c322c75cc2592c10a9a5b26d",
|
||||
"sha256:356d5554516a295fc10db3f25cfde4e92326f6d015da55d71b84f5ced2a07a5a",
|
||||
"sha256:55330c24b8e04ee09f1bc514c2b6107bb03a5eeb0b74929a61100cd6be22ae29",
|
||||
"sha256:553cf11933fdfe07fdd357ab40b9732db102e921b27c1065239308d42b7b858f",
|
||||
"sha256:5626312990a894c5db3a269455f7eb98df5f59188dde1797c0e352d60fdf89af",
|
||||
"sha256:59c24a65c94693ab4a7e92f4809f847b57461120256c083054e61c99c4952e84",
|
||||
"sha256:607deb1181a7cf5369cf70edfc41574d46c0a17c0cac1f6234272bd4cb3487e4",
|
||||
"sha256:60bdd49e6251f8c99989e6769d4ad29b209c1eaf88090f49d4b30fba98442e40",
|
||||
"sha256:73a7cc3c42609e00393b9d4e1b9ee132f528060254a174bf18ef31a154be0386",
|
||||
"sha256:75f1e2917b4d2d6573fe3d1c3b2ec70829b64515b2f723f5c3bebcdd65761e6c",
|
||||
"sha256:92ca9191680eccc21697e9e9c218e600ab31e7c24f6125749738c10ae2dc7c07",
|
||||
"sha256:9bcaf96e2f571f0fc7e3178cdf1bcca7c13e5c68128e8246031226d47ecf23f1",
|
||||
"sha256:a8f3e2229e2683497fe4ccc4af06050c125160a11bb3562b6c4ddaee4d0cc5c5",
|
||||
"sha256:c277066938ca0ddb2bfe75874ef8dd3aa259936fe15c4cf7d4282f89ba82ab3a",
|
||||
"sha256:c532542a99757d9f41df0cf1fc8f64a044d0eb822822cc069c80be35731df275",
|
||||
"sha256:dfa89bd86e01413531c1d7d201fb01f0e62b52ea926a8e8ca6f99f86ed761e95",
|
||||
"sha256:e064010b733b0a2ec4ec97982cd2887f9025292f2d228c6d5e6eca9d84851e53",
|
||||
"sha256:ea927afe7cb04cc7ade30b961f528ef53e8d9cf467dcc4639cf944fef872a1a1",
|
||||
"sha256:f40703b6267aa43d7f72468fa0a3b505ffff74ece2a4c69cfd3c90e023c41381",
|
||||
"sha256:f45cc4544bbd4c308a525a6bb8e2e29b3f849803ee557c6e35c684447f0a92e5",
|
||||
"sha256:f8ccda5ee992c73f647bcd96c9aa30f5eb9e8a6c5bdd6e3dcb29ebbffbe01a69",
|
||||
"sha256:fe386d93345c9b5a9690f7a7bfb789a5ec5467c34402628e10bda8a4f5bac73e"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.1.1"
|
||||
"version": "==5.1.2"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
@ -1448,6 +1450,7 @@
|
||||
"sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad",
|
||||
"sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version < '3.9'",
|
||||
"version": "==3.8.0"
|
||||
},
|
||||
@ -1587,13 +1590,14 @@
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e",
|
||||
"sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"
|
||||
"sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
|
||||
"sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.2"
|
||||
"version": "==8.1.3"
|
||||
},
|
||||
"coverage": {
|
||||
"extras": [],
|
||||
"hashes": [
|
||||
"sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9",
|
||||
"sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d",
|
||||
@ -1687,11 +1691,11 @@
|
||||
},
|
||||
"faker": {
|
||||
"hashes": [
|
||||
"sha256:0d5425894e098410b64aaade38a81074fa30163076251118523adf5bb44f8346",
|
||||
"sha256:7ab2f741ef1c006ed7274a6ed75695ca8b610f78861566b599ce83c4953bf687"
|
||||
"sha256:0301ace8365d98f3d0bf6e9a40200c8548e845d3812402ae1daf589effe3fb01",
|
||||
"sha256:b1903db92175d78051858128ada397c7dc76f376f6967975419da232b3ebd429"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==13.6.0"
|
||||
"version": "==13.7.0"
|
||||
},
|
||||
"filelock": {
|
||||
"hashes": [
|
||||
@ -1714,7 +1718,7 @@
|
||||
"sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
|
||||
"sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"markers": "python_version >= '3'",
|
||||
"version": "==3.3"
|
||||
},
|
||||
"imagesize": {
|
||||
@ -1725,6 +1729,14 @@
|
||||
"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",
|
||||
@ -1734,11 +1746,11 @@
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:539835f51a74a69f41b848a9645dbdc35b4f20a3b601e2d9a7e22947b15ff119",
|
||||
"sha256:640bed4bb501cbd17194b3cace1dc2126f5b619cf068a726b98192a0fde74ae9"
|
||||
"sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
|
||||
"sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.1.1"
|
||||
"version": "==3.1.2"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
@ -2095,6 +2107,14 @@
|
||||
"index": "pypi",
|
||||
"version": "==3.25.0"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708",
|
||||
"sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==4.2.0"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14",
|
||||
@ -2110,6 +2130,15 @@
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==20.14.1"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad",
|
||||
"sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version < '3.9'",
|
||||
"version": "==3.8.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,13 @@
|
||||
|
||||
# Helper script for building the Docker image locally.
|
||||
# Parses and provides the nessecary versions of other images to Docker
|
||||
# before passing in the rest of script args. A future enhancement
|
||||
# would be to combine this with the CI script
|
||||
# before passing in the rest of script args.
|
||||
|
||||
# First Argument: The Dockerfile to build
|
||||
# Other Arguments: Additional arguments to docker build
|
||||
|
||||
# Example Usage:
|
||||
# ./build-docker-image.sh Dockerfile -t paperless-ngx:my-awesome-feature
|
||||
# ./build-docker-image.sh docker-builders/Dockerfile.qpdf -t paperless-ngx-build-qpdf:x.y.z
|
||||
|
||||
set -eux
|
||||
|
||||
@ -28,23 +26,17 @@ psycopg2_version=$(jq ".default.psycopg2.version" Pipfile.lock | sed 's/=//g' |
|
||||
# Read this from the other config file
|
||||
qpdf_version=$(jq ".qpdf.version" .build-config.json | sed 's/"//g')
|
||||
jbig2enc_version=$(jq ".jbig2enc.version" .build-config.json | sed 's/"//g')
|
||||
# Get the branch name
|
||||
frontend_version=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# Get Git tags for building
|
||||
# psycopg2 uses X_Y_Z git tags
|
||||
psycopg2_git_tag=${psycopg2_version//./_}
|
||||
# pikepdf uses vX.Y.Z
|
||||
pikepdf_git_tag="v${pikepdf_version}"
|
||||
# Get the branch name (used for caching)
|
||||
branch_name=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# https://docs.docker.com/develop/develop-images/build_enhancements/
|
||||
# Required to use cache-from
|
||||
export DOCKER_BUILDKIT=1
|
||||
|
||||
docker build --file "$1" \
|
||||
--cache-from ghcr.io/paperless-ngx/paperless-ngx/builder/cache/app:"${branch_name}" \
|
||||
--cache-from ghcr.io/paperless-ngx/paperless-ngx/builder/cache/app:dev \
|
||||
--build-arg JBIG2ENC_VERSION="${jbig2enc_version}" \
|
||||
--build-arg QPDF_VERSION="${qpdf_version}" \
|
||||
--build-arg PIKEPDF_VERSION="${pikepdf_version}" \
|
||||
--build-arg PIKEPDF_GIT_TAG="${pikepdf_git_tag}" \
|
||||
--build-arg PSYCOPG2_VERSION="${psycopg2_version}" \
|
||||
--build-arg PSYCOPG2_GIT_TAG="${psycopg2_git_tag}" \
|
||||
--build-arg FRONTEND_VERSION="${frontend_version}" "${@:2}" .
|
||||
--build-arg PSYCOPG2_VERSION="${psycopg2_version}" "${@:2}" .
|
||||
|
@ -1,7 +1,6 @@
|
||||
# docker-compose file for running paperless from the docker container registry.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware. The apache/tika image
|
||||
# does not support arm or arm64, however.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
@ -78,14 +77,14 @@ services:
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: gotenberg/gotenberg:7
|
||||
image: gotenberg/gotenberg:7.4
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- "gotenberg"
|
||||
- "--chromium-disable-web-security"
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
image: ghcr.io/paperless-ngx/tika:latest
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
|
@ -1,85 +0,0 @@
|
||||
# docker-compose file for running paperless from the docker container registry.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8000.
|
||||
#
|
||||
# SQLite is used as the database. The SQLite file is stored in the data volume.
|
||||
#
|
||||
# iwishiwasaneagle/apache-tika-arm docker image is used to enable arm64 arch
|
||||
# which apache/tika does not currently support.
|
||||
#
|
||||
# In addition to that, this docker-compose file adds the following optional
|
||||
# configurations:
|
||||
#
|
||||
# - Apache Tika and Gotenberg servers are started with paperless and paperless
|
||||
# is configured to use these services. These provide support for consuming
|
||||
# Office documents (Word, Excel, Power Point and their LibreOffice counter-
|
||||
# parts.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||
# and '.env' into a folder.
|
||||
# - Run 'docker-compose pull'.
|
||||
# - Run 'docker-compose run --rm webserver createsuperuser' to create a user.
|
||||
# - Run 'docker-compose up -d'.
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
|
||||
webserver:
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- broker
|
||||
- gotenberg
|
||||
- tika
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_TIKA_ENABLED: 1
|
||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: gotenberg/gotenberg:7
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- "gotenberg"
|
||||
- "--chromium-disable-web-security"
|
||||
|
||||
tika:
|
||||
image: iwishiwasaneagle/apache-tika-arm@sha256:a78c25ffe57ecb1a194b2859d42a61af46e9e845191512b8f1a4bf90578ffdfd
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
redisdata:
|
@ -1,8 +1,6 @@
|
||||
# docker-compose file for running paperless from the docker container registry.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware. The apache/tika image
|
||||
# does not support arm or arm64, however.
|
||||
#
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
@ -67,14 +65,14 @@ services:
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: gotenberg/gotenberg:7
|
||||
image: gotenberg/gotenberg:7.4
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- "gotenberg"
|
||||
- "--chromium-disable-web-security"
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
image: ghcr.io/paperless-ngx/tika:latest
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
|
@ -117,6 +117,23 @@ Then you can start paperless-ngx with ``-d`` to have it run in the background.
|
||||
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
|
||||
.. note::
|
||||
In version 1.7.1 and onwards, the Docker image can now pinned to a release series.
|
||||
This is often combined with automatic updaters such as Watchtower to allow safer
|
||||
unattended upgrading to new bugfix releases only. It is still recommended to always
|
||||
review release notes before upgrading. To ping your install to a release series, edit
|
||||
the ``docker-compose.yml`` find the line that says
|
||||
|
||||
.. code::
|
||||
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
|
||||
and replace the version with the series you want to track, for example:
|
||||
|
||||
.. code::
|
||||
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:1.7
|
||||
|
||||
Bare Metal Route
|
||||
================
|
||||
|
||||
|
@ -2,6 +2,8 @@ import sphinx_rtd_theme
|
||||
|
||||
|
||||
__version__ = None
|
||||
__full_version_str__ = None
|
||||
__major_minor_version_str__ = None
|
||||
exec(open("../src/paperless/version.py").read())
|
||||
|
||||
|
||||
@ -41,9 +43,9 @@ copyright = "2015-2022, Daniel Quinn, Jonas Winkler, and the paperless-ngx team"
|
||||
#
|
||||
|
||||
# The short X.Y version.
|
||||
version = ".".join([str(_) for _ in __version__[:2]])
|
||||
version = __major_minor_version_str__
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = ".".join([str(_) for _ in __version__[:3]])
|
||||
release = __full_version_str__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -474,7 +474,7 @@ PAPERLESS_TIKA_GOTENBERG_ENDPOINT=<url>
|
||||
Defaults to "http://localhost:3000".
|
||||
|
||||
If you run paperless on docker, you can add those services to the docker-compose
|
||||
file (see the provided ``docker-compose.tika.yml`` file for reference). The changes
|
||||
file (see the provided ``docker-compose.sqlite-tika.yml`` file for reference). The changes
|
||||
requires are as follows:
|
||||
|
||||
.. code:: yaml
|
||||
@ -495,14 +495,14 @@ requires are as follows:
|
||||
# ...
|
||||
|
||||
gotenberg:
|
||||
image: gotenberg/gotenberg:7
|
||||
image: gotenberg/gotenberg:7.4
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- "gotenberg"
|
||||
- "--chromium-disable-web-security"
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
image: ghcr.io/paperless-ngx/tika:latest
|
||||
restart: unless-stopped
|
||||
|
||||
Add the configuration variables to the environment of the webserver (alternatively
|
||||
|
@ -334,11 +334,17 @@ directory.
|
||||
Building the Docker image
|
||||
=========================
|
||||
|
||||
The docker image is primarily built by the GitHub actions workflow, but it can be
|
||||
faster when developing to build and tag an image locally.
|
||||
|
||||
To provide the build arguments automatically, build the image using the helper
|
||||
script ``build-docker-image.sh``.
|
||||
|
||||
Building the docker image from source:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
docker build . -t <your-tag>
|
||||
./build-docker-image.sh Dockerfile -t <your-tag>
|
||||
|
||||
Extending Paperless
|
||||
===================
|
||||
|
@ -347,7 +347,7 @@ 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
|
||||
* ``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
|
||||
@ -728,8 +728,6 @@ configuring some options in paperless can help improve performance immensely:
|
||||
times. Thumbnails will be about 20% larger.
|
||||
* If using docker, consider setting ``PAPERLESS_WEBSERVER_WORKERS`` to
|
||||
1. This will save some memory.
|
||||
* Use the arm compatible docker-compose if you're wanting to use Tika on something like
|
||||
a raspberry pi. The official apache/tika image does not support the arm architecture.
|
||||
|
||||
For details, refer to :ref:`configuration`.
|
||||
|
||||
|
@ -125,7 +125,7 @@ If using docker-compose, this is achieved by the following configuration change
|
||||
.. code:: yaml
|
||||
|
||||
gotenberg:
|
||||
image: gotenberg/gotenberg:7
|
||||
image: gotenberg/gotenberg:7.4
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- "gotenberg"
|
||||
|
@ -5,12 +5,12 @@
|
||||
# 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'
|
||||
asgiref==3.5.1; 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.3.2; python_version >= '3.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.1.2; python_version >= '3.7'
|
||||
click==8.1.3; 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
|
||||
@ -45,7 +45,7 @@ hiredis==2.0.0; python_version >= '3.6'
|
||||
httptools==0.4.0
|
||||
humanfriendly==10.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
hyperlink==21.0.0
|
||||
idna==3.3; python_version >= '3.5'
|
||||
idna==3.3; python_version >= '3'
|
||||
imap-tools==0.54.0
|
||||
img2pdf==0.4.4
|
||||
importlib-resources==5.7.1; python_version < '3.9'
|
||||
@ -62,7 +62,7 @@ packaging==21.3; python_version >= '3.6'
|
||||
pathvalidate==2.5.0
|
||||
pdf2image==1.16.0
|
||||
pdfminer.six==20220319
|
||||
pikepdf==5.1.1
|
||||
pikepdf==5.1.2
|
||||
pillow==9.1.0
|
||||
pluggy==1.0.0; python_version >= '3.6'
|
||||
portalocker==2.4.0; python_version >= '3'
|
||||
|
@ -2,5 +2,5 @@
|
||||
|
||||
docker run -p 5432:5432 -e POSTGRES_PASSWORD=password -v paperless_pgdata:/var/lib/postgresql/data -d postgres:13
|
||||
docker run -d -p 6379:6379 redis:latest
|
||||
docker run -p 3000:3000 -d gotenberg/gotenberg:7 gotenberg --chromium-disable-web-security
|
||||
docker run -p 9998:9998 -d apache/tika
|
||||
docker run -p 3000:3000 -d gotenberg/gotenberg:7.4 gotenberg --chromium-disable-web-security
|
||||
docker run -p 9998:9998 -d ghcr.io/paperless-ngx/tika:latest
|
||||
|
9366
src-ui/package-lock.json
generated
9366
src-ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@
|
||||
"@angular/platform-browser": "~13.3.5",
|
||||
"@angular/platform-browser-dynamic": "~13.3.5",
|
||||
"@angular/router": "~13.3.5",
|
||||
"@ng-bootstrap/ng-bootstrap": "^12.1.0",
|
||||
"@ng-bootstrap/ng-bootstrap": "^12.1.1",
|
||||
"@ng-select/ng-select": "^8.1.1",
|
||||
"@ngneat/dirty-check-forms": "^3.0.2",
|
||||
"@popperjs/core": "^2.11.4",
|
||||
@ -45,14 +45,16 @@
|
||||
"@types/node": "^17.0.30",
|
||||
"codelyzer": "^6.0.2",
|
||||
"concurrently": "7.1.0",
|
||||
"jest": "27.5.1",
|
||||
"jest": "28.0.3",
|
||||
"jest-environment-jsdom": "^28.0.2",
|
||||
"jest-preset-angular": "^12.0.0-next.1",
|
||||
"ts-node": "~10.7.0",
|
||||
"tslint": "~6.1.3",
|
||||
"typescript": "~4.6.3",
|
||||
"wait-on": "~6.0.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"cypress": "~9.6.0",
|
||||
"@cypress/schematic": "^1.6.0"
|
||||
"@cypress/schematic": "^1.6.0",
|
||||
"cypress": "~9.6.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'jest-preset-angular/setup-jest'
|
||||
import { jest } from '@jest/globals'
|
||||
|
||||
/* global mocks for jsdom */
|
||||
const mock = () => {
|
||||
@ -26,5 +26,6 @@ Object.defineProperty(document.body.style, 'transform', {
|
||||
},
|
||||
})
|
||||
|
||||
/* output shorter and more meaningful Zone error stack traces */
|
||||
// Error.stackTraceLimit = 2
|
||||
HTMLCanvasElement.prototype.getContext = <
|
||||
typeof HTMLCanvasElement.prototype.getContext
|
||||
>jest.fn()
|
||||
|
@ -162,8 +162,8 @@
|
||||
<div [ngbNavOutlet]="nav" class="mt-2"></div>
|
||||
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="discard()" i18n [disabled]="networkActive || !(isDirty$ | async)">Discard</button>
|
||||
<button type="button" class="btn btn-outline-primary" (click)="saveEditNext()" *ngIf="hasNext()" i18n [disabled]="networkActive || !(isDirty$ | async)">Save & next</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive || !(isDirty$ | async)">Save</button>
|
||||
<button type="button" class="btn btn-outline-primary" (click)="saveEditNext()" *ngIf="hasNext()" i18n [disabled]="networkActive || !(isDirty$ | async) || error">Save & next</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive || !(isDirty$ | async) || error">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
@ -34,6 +34,7 @@ import {
|
||||
} from 'rxjs/operators'
|
||||
import { PaperlessDocumentSuggestions } from 'src/app/data/paperless-document-suggestions'
|
||||
import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type'
|
||||
import { normalizeDateStr } from 'src/app/utils/date'
|
||||
|
||||
@Component({
|
||||
selector: 'app-document-detail',
|
||||
@ -145,18 +146,24 @@ export class DocumentDetailComponent
|
||||
this.documentForm.valueChanges
|
||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||
.subscribe((changes) => {
|
||||
this.error = null
|
||||
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 }
|
||||
)
|
||||
try {
|
||||
let newDate = new Date(normalizeDateStr(changes['created']))
|
||||
newDate.setHours(
|
||||
this.ogDate.getHours(),
|
||||
this.ogDate.getMinutes(),
|
||||
this.ogDate.getSeconds(),
|
||||
this.ogDate.getMilliseconds()
|
||||
)
|
||||
this.documentForm.patchValue(
|
||||
{ created: newDate.toISOString() },
|
||||
{ emitEvent: false }
|
||||
)
|
||||
} catch (e) {
|
||||
// catch this before we try to save and simulate an api error
|
||||
this.error = { created: e.message }
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(this.document, this.documentForm.value)
|
||||
@ -199,22 +206,22 @@ export class DocumentDetailComponent
|
||||
this.updateComponent(doc)
|
||||
}
|
||||
|
||||
this.ogDate = new Date(doc.created)
|
||||
this.ogDate = new Date(normalizeDateStr(doc.created.toString()))
|
||||
|
||||
// Initialize dirtyCheck
|
||||
this.store = new BehaviorSubject({
|
||||
title: doc.title,
|
||||
content: doc.content,
|
||||
created: this.formatDate(this.ogDate),
|
||||
created: this.ogDate.toISOString(),
|
||||
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
|
||||
// start with ISO8601 string
|
||||
this.documentForm.patchValue(
|
||||
{ created: this.formatDate(this.ogDate) },
|
||||
{ created: this.ogDate.toISOString() },
|
||||
{ emitEvent: false }
|
||||
)
|
||||
|
||||
@ -319,16 +326,17 @@ export class DocumentDetailComponent
|
||||
this.documentsService
|
||||
.get(this.documentId)
|
||||
.pipe(first())
|
||||
.subscribe(
|
||||
(doc) => {
|
||||
.subscribe({
|
||||
next: (doc) => {
|
||||
Object.assign(this.document, doc)
|
||||
this.title = doc.title
|
||||
this.documentForm.patchValue(doc)
|
||||
this.openDocumentService.setDirty(doc.id, false)
|
||||
},
|
||||
(error) => {
|
||||
error: () => {
|
||||
this.router.navigate(['404'])
|
||||
}
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
save() {
|
||||
@ -486,8 +494,4 @@ export class DocumentDetailComponent
|
||||
this.password = (event.target as HTMLInputElement).value
|
||||
}
|
||||
}
|
||||
|
||||
formatDate(date: Date): string {
|
||||
return date.toISOString().split('.')[0] + 'Z'
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { DatePipe } from '@angular/common'
|
||||
import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core'
|
||||
import { SettingsService, SETTINGS_KEYS } from '../services/settings.service'
|
||||
import { normalizeDateStr } from '../utils/date'
|
||||
|
||||
const FORMAT_TO_ISO_FORMAT = {
|
||||
longDate: 'y-MM-dd',
|
||||
@ -33,6 +34,7 @@ export class CustomDatePipe implements PipeTransform {
|
||||
this.settings.get(SETTINGS_KEYS.DATE_LOCALE) ||
|
||||
this.defaultLocale
|
||||
let f = format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT)
|
||||
if (typeof value == 'string') value = normalizeDateStr(value)
|
||||
if (l == 'iso-8601') {
|
||||
return this.datePipe.transform(value, FORMAT_TO_ISO_FORMAT[f], timezone)
|
||||
} else {
|
||||
|
5
src-ui/src/app/utils/date.ts
Normal file
5
src-ui/src/app/utils/date.ts
Normal file
@ -0,0 +1,5 @@
|
||||
// see https://github.com/dateutil/dateutil/issues/878 , JS Date does not
|
||||
// seem to accept these strings as valid dates so we must normalize offset
|
||||
export function normalizeDateStr(dateStr: string): string {
|
||||
return dateStr.replace(/-(\d\d):\d\d:\d\d/gm, `-$1:00`)
|
||||
}
|
@ -51,11 +51,22 @@ export class LocalizedDateParserFormatter extends NgbDateParserFormatter {
|
||||
const dateSeparator = inputFormat.replace(/[dmy]/gi, '').charAt(0)
|
||||
|
||||
if (this.separatorRegExp.test(value)) {
|
||||
// split on separator, pad & re-join without separator
|
||||
value = value
|
||||
.split(this.separatorRegExp)
|
||||
.map((segment) => segment.padStart(2, '0'))
|
||||
.join('')
|
||||
let segments = value.split(this.separatorRegExp)
|
||||
|
||||
// always accept strict yyyy*mm*dd format even if thats not the input format since we can be certain its not yyyy*dd*mm
|
||||
if (
|
||||
value.length == 10 &&
|
||||
segments.length == 3 &&
|
||||
segments[0].length == 4
|
||||
) {
|
||||
return inputFormat
|
||||
.replace('yyyy', segments[0])
|
||||
.replace('mm', segments[1])
|
||||
.replace('dd', segments[2])
|
||||
} else {
|
||||
// otherwise pad & re-join without separator
|
||||
value = segments.map((segment) => segment.padStart(2, '0')).join('')
|
||||
}
|
||||
}
|
||||
|
||||
if (value.length == 4 && inputFormat.substring(0, 4) != 'yyyy') {
|
||||
|
@ -676,28 +676,33 @@ class RemoteVersionView(GenericAPIView):
|
||||
def get(self, request, format=None):
|
||||
remote_version = "0.0.0"
|
||||
is_greater_than_current = False
|
||||
current_version = packaging_version.parse(version.__full_version_str__)
|
||||
# TODO: this can likely be removed when frontend settings are saved to DB
|
||||
feature_is_set = settings.ENABLE_UPDATE_CHECK != "default"
|
||||
if feature_is_set and settings.ENABLE_UPDATE_CHECK:
|
||||
try:
|
||||
with urllib.request.urlopen(
|
||||
"https://api.github.com/repos/"
|
||||
+ "paperless-ngx/paperless-ngx/releases/latest",
|
||||
) as response:
|
||||
req = urllib.request.Request(
|
||||
"https://api.github.com/repos/paperless-ngx/"
|
||||
"paperless-ngx/releases/latest",
|
||||
)
|
||||
# Ensure a JSON response
|
||||
req.add_header("Accept", "application/json")
|
||||
|
||||
with urllib.request.urlopen(req) as response:
|
||||
remote = response.read().decode("utf-8")
|
||||
try:
|
||||
remote_json = json.loads(remote)
|
||||
remote_version = remote_json["tag_name"].replace("ngx-", "")
|
||||
remote_version = remote_json["tag_name"].removeprefix("ngx-")
|
||||
except ValueError:
|
||||
logger.debug("An error occured parsing remote version json")
|
||||
logger.debug("An error occurred parsing remote version json")
|
||||
except urllib.error.URLError:
|
||||
logger.debug("An error occured checking for available updates")
|
||||
logger.debug("An error occurred checking for available updates")
|
||||
|
||||
current_version = ".".join([str(_) for _ in version.__version__[:3]])
|
||||
is_greater_than_current = packaging_version.parse(
|
||||
remote_version,
|
||||
) > packaging_version.parse(
|
||||
current_version,
|
||||
is_greater_than_current = (
|
||||
packaging_version.parse(
|
||||
remote_version,
|
||||
)
|
||||
> current_version
|
||||
)
|
||||
|
||||
return Response(
|
||||
|
@ -11,6 +11,6 @@ class ApiVersionMiddleware:
|
||||
if request.user.is_authenticated:
|
||||
versions = settings.REST_FRAMEWORK["ALLOWED_VERSIONS"]
|
||||
response["X-Api-Version"] = versions[len(versions) - 1]
|
||||
response["X-Version"] = ".".join([str(_) for _ in version.__version__])
|
||||
response["X-Version"] = version.__full_version_str__
|
||||
|
||||
return response
|
||||
|
@ -1 +1,8 @@
|
||||
__version__ = (1, 7, 0)
|
||||
from typing import Final
|
||||
from typing import Tuple
|
||||
|
||||
__version__: Final[Tuple[int, int, int]] = (1, 7, 0)
|
||||
# Version string like X.Y.Z
|
||||
__full_version_str__: Final[str] = ".".join(map(str, __version__))
|
||||
# Version string like X.Y
|
||||
__major_minor_version_str__: Final[str] = ".".join(map(str, __version__[:-1]))
|
||||
|
Loading…
x
Reference in New Issue
Block a user