mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
This commit is contained in:
		
							
								
								
									
										8
									
								
								.github/scripts/cleanup-tags.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/scripts/cleanup-tags.py
									
									
									
									
										vendored
									
									
								
							| @@ -249,10 +249,12 @@ class MainImageTagsCleaner(RegistryTagsCleaner): | ||||
|         will be removed, if the corresponding branch no longer exists. | ||||
|         """ | ||||
|  | ||||
|         # Default to everything gets kept still | ||||
|         super().decide_what_tags_to_keep() | ||||
|  | ||||
|         # Locate the feature branches | ||||
|         feature_branches = {} | ||||
|         for branch in self.branch_api.get_branches( | ||||
|             owner=self.repo_owner, | ||||
|             repo=self.repo_name, | ||||
|         ): | ||||
|             if branch.name.startswith("feature-"): | ||||
| @@ -261,6 +263,10 @@ class MainImageTagsCleaner(RegistryTagsCleaner): | ||||
|  | ||||
|         logger.info(f"Located {len(feature_branches)} feature branches") | ||||
|  | ||||
|         if not len(feature_branches): | ||||
|             # Our work here is done, delete nothing | ||||
|             return | ||||
|  | ||||
|         # Filter to packages which are tagged with feature-* | ||||
|         packages_tagged_feature: List[ContainerPackage] = [] | ||||
|         for package in self.all_package_versions: | ||||
|   | ||||
							
								
								
									
										35
									
								
								.github/scripts/github.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								.github/scripts/github.py
									
									
									
									
										vendored
									
									
								
							| @@ -15,7 +15,7 @@ from typing import Dict | ||||
| from typing import List | ||||
| from typing import Optional | ||||
|  | ||||
| import requests | ||||
| import httpx | ||||
|  | ||||
| logger = logging.getLogger("github-api") | ||||
|  | ||||
| @@ -28,15 +28,15 @@ class _GithubApiBase: | ||||
|  | ||||
|     def __init__(self, token: str) -> None: | ||||
|         self._token = token | ||||
|         self._session: Optional[requests.Session] = None | ||||
|         self._client: Optional[httpx.Client] = None | ||||
|  | ||||
|     def __enter__(self) -> "_GithubApiBase": | ||||
|         """ | ||||
|         Sets up the required headers for auth and response | ||||
|         type from the API | ||||
|         """ | ||||
|         self._session = requests.Session() | ||||
|         self._session.headers.update( | ||||
|         self._client = httpx.Client() | ||||
|         self._client.headers.update( | ||||
|             { | ||||
|                 "Accept": "application/vnd.github.v3+json", | ||||
|                 "Authorization": f"token {self._token}", | ||||
| @@ -49,14 +49,14 @@ class _GithubApiBase: | ||||
|         Ensures the authorization token is cleaned up no matter | ||||
|         the reason for the exit | ||||
|         """ | ||||
|         if "Accept" in self._session.headers: | ||||
|             del self._session.headers["Accept"] | ||||
|         if "Authorization" in self._session.headers: | ||||
|             del self._session.headers["Authorization"] | ||||
|         if "Accept" in self._client.headers: | ||||
|             del self._client.headers["Accept"] | ||||
|         if "Authorization" in self._client.headers: | ||||
|             del self._client.headers["Authorization"] | ||||
|  | ||||
|         # Close the session as well | ||||
|         self._session.close() | ||||
|         self._session = None | ||||
|         self._client.close() | ||||
|         self._client = None | ||||
|  | ||||
|     def _read_all_pages(self, endpoint): | ||||
|         """ | ||||
| @@ -66,7 +66,7 @@ class _GithubApiBase: | ||||
|         internal_data = [] | ||||
|  | ||||
|         while True: | ||||
|             resp = self._session.get(endpoint) | ||||
|             resp = self._client.get(endpoint) | ||||
|             if resp.status_code == 200: | ||||
|                 internal_data += resp.json() | ||||
|                 if "next" in resp.links: | ||||
| @@ -76,7 +76,7 @@ class _GithubApiBase: | ||||
|                     break | ||||
|             else: | ||||
|                 logger.warning(f"Request to {endpoint} return HTTP {resp.status_code}") | ||||
|                 break | ||||
|                 resp.raise_for_status() | ||||
|  | ||||
|         return internal_data | ||||
|  | ||||
| @@ -113,14 +113,15 @@ class GithubBranchApi(_GithubApiBase): | ||||
|     def __init__(self, token: str) -> None: | ||||
|         super().__init__(token) | ||||
|  | ||||
|         self._ENDPOINT = "https://api.github.com/repos/{OWNER}/{REPO}/branches" | ||||
|         self._ENDPOINT = "https://api.github.com/repos/{REPO}/branches" | ||||
|  | ||||
|     def get_branches(self, owner: str, repo: str) -> List[GithubBranch]: | ||||
|     def get_branches(self, repo: str) -> List[GithubBranch]: | ||||
|         """ | ||||
|         Returns all current branches of the given repository owned by the given | ||||
|         owner or organization. | ||||
|         """ | ||||
|         endpoint = self._ENDPOINT.format(OWNER=owner, REPO=repo) | ||||
|         # The environment GITHUB_REPOSITORY already contains the owner in the correct location | ||||
|         endpoint = self._ENDPOINT.format(REPO=repo) | ||||
|         internal_data = self._read_all_pages(endpoint) | ||||
|         return [GithubBranch(branch) for branch in internal_data] | ||||
|  | ||||
| @@ -247,7 +248,7 @@ class GithubContainerRegistryApi(_GithubApiBase): | ||||
|         """ | ||||
|         Deletes the given package version from the GHCR | ||||
|         """ | ||||
|         resp = self._session.delete(package_data.url) | ||||
|         resp = self._client.delete(package_data.url) | ||||
|         if resp.status_code != 204: | ||||
|             logger.warning( | ||||
|                 f"Request to delete {package_data.url} returned HTTP {resp.status_code}", | ||||
| @@ -266,7 +267,7 @@ class GithubContainerRegistryApi(_GithubApiBase): | ||||
|             PACKAGE_VERSION_ID=package_data.id, | ||||
|         ) | ||||
|  | ||||
|         resp = self._session.post(endpoint) | ||||
|         resp = self._client.post(endpoint) | ||||
|         if resp.status_code != 204: | ||||
|             logger.warning( | ||||
|                 f"Request to delete {endpoint} returned HTTP {resp.status_code}", | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -139,7 +139,7 @@ jobs: | ||||
|       - | ||||
|         name: Get changed files | ||||
|         id: changed-files-specific | ||||
|         uses: tj-actions/changed-files@v32 | ||||
|         uses: tj-actions/changed-files@v34 | ||||
|         with: | ||||
|           files: | | ||||
|             src/** | ||||
|   | ||||
							
								
								
									
										4
									
								
								.github/workflows/cleanup-tags.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/cleanup-tags.yml
									
									
									
									
										vendored
									
									
								
							| @@ -64,9 +64,9 @@ jobs: | ||||
|         with: | ||||
|           python-version: "3.10" | ||||
|       - | ||||
|         name: Install requests | ||||
|         name: Install httpx | ||||
|         run: | | ||||
|           python -m pip install requests | ||||
|           python -m pip install httpx | ||||
|       # | ||||
|       # Clean up primary package | ||||
|       # | ||||
|   | ||||
							
								
								
									
										23
									
								
								.github/workflows/installer-library.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								.github/workflows/installer-library.yml
									
									
									
									
										vendored
									
									
								
							| @@ -50,6 +50,11 @@ jobs: | ||||
|         uses: actions/setup-python@v4 | ||||
|         with: | ||||
|           python-version: "3.9" | ||||
|       - | ||||
|         name: Install jq | ||||
|         run: | | ||||
|           sudo apt-get update | ||||
|           sudo apt-get install jq | ||||
|       - | ||||
|         name: Setup qpdf image | ||||
|         id: qpdf-setup | ||||
| @@ -86,6 +91,18 @@ jobs: | ||||
|           echo ${build_json} | ||||
|  | ||||
|           echo "jbig2enc-json=${build_json}" >> $GITHUB_OUTPUT | ||||
|       - | ||||
|         name: Setup other versions | ||||
|         id: cache-bust-setup | ||||
|         run: | | ||||
|           pillow_version=$(jq ".default.pillow.version" Pipfile.lock | sed 's/=//g' | sed 's/"//g') | ||||
|           lxml_version=$(jq ".default.lxml.version" Pipfile.lock | sed 's/=//g' | sed 's/"//g') | ||||
|  | ||||
|           echo "Pillow is ${pillow_version}" | ||||
|           echo "lxml is ${lxml_version}" | ||||
|  | ||||
|           echo "pillow-version=${pillow_version}" >> $GITHUB_OUTPUT | ||||
|           echo "lxml-version=${lxml_version}" >> $GITHUB_OUTPUT | ||||
|  | ||||
|     outputs: | ||||
|  | ||||
| @@ -99,6 +116,10 @@ jobs: | ||||
|  | ||||
|       jbig2enc-json: ${{ steps.jbig2enc-setup.outputs.jbig2enc-json }} | ||||
|  | ||||
|       pillow-version: ${{ steps.cache-bust-setup.outputs.pillow-version }} | ||||
|  | ||||
|       lxml-version: ${{ steps.cache-bust-setup.outputs.lxml-version }} | ||||
|  | ||||
|   build-qpdf-debs: | ||||
|     name: qpdf | ||||
|     needs: | ||||
| @@ -145,3 +166,5 @@ jobs: | ||||
|         REPO=${{ needs.prepare-docker-build.outputs.ghcr-repository }} | ||||
|         QPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.qpdf-json).version }} | ||||
|         PIKEPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).version }} | ||||
|         PILLOW_VERSION=${{ needs.prepare-docker-build.outputs.pillow-version }} | ||||
|         LXML_VERSION=${{ needs.prepare-docker-build.outputs.lxml-version }} | ||||
|   | ||||
							
								
								
									
										4
									
								
								Pipfile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Pipfile
									
									
									
									
									
								
							| @@ -16,18 +16,18 @@ django-extensions = "*" | ||||
| django-filter = "~=22.1" | ||||
| djangorestframework = "~=3.13" | ||||
| filelock = "*" | ||||
| fuzzywuzzy = {extras = ["speedup"], version = "*"} | ||||
| gunicorn = "*" | ||||
| imap-tools = "*" | ||||
| langdetect = "*" | ||||
| pathvalidate = "*" | ||||
| pillow = "~=9.2" | ||||
| pillow = "~=9.3" | ||||
| pikepdf = "*" | ||||
| python-gnupg = "*" | ||||
| python-dotenv = "*" | ||||
| python-dateutil = "*" | ||||
| python-magic = "*" | ||||
| psycopg2 = "*" | ||||
| rapidfuzz = "*" | ||||
| redis = {extras = ["hiredis"], version = "*"} | ||||
| scikit-learn = "~=1.1" | ||||
| # Pin this until piwheels is building 1.9 (see https://www.piwheels.org/project/scipy/) | ||||
|   | ||||
							
								
								
									
										806
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										806
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|     "_meta": { | ||||
|         "hash": { | ||||
|             "sha256": "5558c489e948de1779e547beae0dd36a2e551aa6be8505c26b651fd87eac2834" | ||||
|             "sha256": "f8bdb4da9007a887c66a7e0243c486419676aa1a053c9a78e3760abb1f60e0a0" | ||||
|         }, | ||||
|         "pipfile-spec": 6, | ||||
|         "requires": {}, | ||||
| @@ -75,10 +75,10 @@ | ||||
|         }, | ||||
|         "automat": { | ||||
|             "hashes": [ | ||||
|                 "sha256:7979803c74610e11ef0c0d68a2942b152df52da55336e0c9d58daf1831cbdf33", | ||||
|                 "sha256:b6feb6455337df834f6c9962d6ccf771515b7d939bca142b29c20c2376bc6111" | ||||
|                 "sha256:c3164f8742b9dc440f3682482d32aaff7bb53f71740dd018533f9de286b64180", | ||||
|                 "sha256:e56beb84edad19dcc11d30e8d9b895f75deeb5ef5e96b84a467066b3b84bb04e" | ||||
|             ], | ||||
|             "version": "==20.2.0" | ||||
|             "version": "==22.10.0" | ||||
|         }, | ||||
|         "backports.zoneinfo": { | ||||
|             "hashes": [ | ||||
| @@ -109,14 +109,6 @@ | ||||
|             ], | ||||
|             "version": "==3.6.4.0" | ||||
|         }, | ||||
|         "bleach": { | ||||
|             "hashes": [ | ||||
|                 "sha256:085f7f33c15bd408dd9b17a4ad77c577db66d76203e5984b1bd59baeee948b2a", | ||||
|                 "sha256:0d03255c47eb9bd2f26aa9bb7f2107732e7e8fe195ca2f64709fcf3b0a4a085c" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==5.0.1" | ||||
|         }, | ||||
|         "celery": { | ||||
|             "extras": [ | ||||
|                 "redis" | ||||
| @@ -409,17 +401,6 @@ | ||||
|             "index": "pypi", | ||||
|             "version": "==1.2.0" | ||||
|         }, | ||||
|         "fuzzywuzzy": { | ||||
|             "extras": [ | ||||
|                 "speedup" | ||||
|             ], | ||||
|             "hashes": [ | ||||
|                 "sha256:45016e92264780e58972dca1b3d939ac864b78437422beecebb3095f8efd00e8", | ||||
|                 "sha256:928244b28db720d1e0ee7587acf660ea49d7e4c632569cad4f1cd7e68a5f0993" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==0.18.0" | ||||
|         }, | ||||
|         "gunicorn": { | ||||
|             "hashes": [ | ||||
|                 "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e", | ||||
| @@ -630,114 +611,6 @@ | ||||
|             "index": "pypi", | ||||
|             "version": "==1.0.9" | ||||
|         }, | ||||
|         "levenshtein": { | ||||
|             "hashes": [ | ||||
|                 "sha256:019ae21de930d6077efa1eac746de4df5234e7c6c11ab10080c0935fc5abbecf", | ||||
|                 "sha256:02688fff6d256afdd57da5359144ddab8e054b2ba98ddcf147fe191bdf996e88", | ||||
|                 "sha256:0274b87df89d1dda8dce77cf05a9dfab7bd30045a09e0d9435ec8be622e374e6", | ||||
|                 "sha256:0323e8dbeec4d63c27111796baa7e8a89b391c32d90e67d78f9404d0c8edeab4", | ||||
|                 "sha256:053edbb52fe8b8a1a6698c4fee39590c9e44a602ace807291eb87e3b17f85f48", | ||||
|                 "sha256:059027f5dd2aafb916301f46a619c7fe03ff5761cdb2d091cf80bf6dbc24bc29", | ||||
|                 "sha256:05f11a4be4f668974238cff21208fbd9f629cab8a68b444b7d4a4cfd8081b1d6", | ||||
|                 "sha256:0ab71cc5ea86f6685a7b2235edad65f1f2a4b6341109af259d758973d96eece5", | ||||
|                 "sha256:0b439f4fb0b615bc0443cc83eaf5835bd480f680c69ed1be963bdb401b8159f8", | ||||
|                 "sha256:0ec50d24a12e50857e94ac9035d3c06fd0827bb477b9ebcd83a2a49dd89e5e23", | ||||
|                 "sha256:131fc50d52a52acc367ea8bccb028447b734243d00ba1cfc7d9ff8d0dc37fa38", | ||||
|                 "sha256:17b5f1d1a4a5ac536283298c98cafc5632ae3897c8601fb2ec8babc6f47a1be9", | ||||
|                 "sha256:183b8da9b870ad171a11a629c43e0587a228aea9d595a969231d59bf530b6c77", | ||||
|                 "sha256:18888d50813b9df9b8dc8c1506ec40c783db25f130a6101eb89896b27076f751", | ||||
|                 "sha256:25b88277832eb558305c3bb986ad61f19b5cb5a87aced289bce4a1701a92aa31", | ||||
|                 "sha256:266cdab48e2242b6c010beb8b7af4164aa87f4ad8d6fbd9f4f531214f8ddb234", | ||||
|                 "sha256:281bffb09b2e1620db4e99a9df96e38d939c341c7c43cd5191326fbdb4d42275", | ||||
|                 "sha256:28cd002cf5a499e6e9bd69d992ffd501b8473948f3e97d6e075b774df1901e8e", | ||||
|                 "sha256:2972c6c6a806e0c788f6ec39510abdb61b3a648fd141a5fa77becd2cc05ff551", | ||||
|                 "sha256:2b4027b370cc46c4802ba32a979729209c0407d548723e809f19a50a9df27405", | ||||
|                 "sha256:318c924e218be754427ce6bb4c630d9dcb5478eb00a8a3f8a0972086adc763b1", | ||||
|                 "sha256:380accae56f8c9df99f34bc7e79d286fee37c3dd06b362c394b08ea96371b7c5", | ||||
|                 "sha256:3c7784f9936292c9d3f92fc772d874edc071a16cd883ea0d997e5c4318f6362c", | ||||
|                 "sha256:3ebd85fd6253abe89f852fc008294d490eb7a5f66913703148b8d263b048cc90", | ||||
|                 "sha256:4126c8fe9d817ac3ab223ee5db41a09d0fa82dbd6bb59d207b6f7313d733f19b", | ||||
|                 "sha256:4155f0ab246b6892110960f25989ab91073cd708b974f4732dca4d219a8be3e1", | ||||
|                 "sha256:41f16267d8e6d916e06a6a1a0e151f643a6bab1277945a4bd494f359d4185dd2", | ||||
|                 "sha256:4522f5d662d3ee55a072fad18e2af5dae480658d4e23b04b455c4b7542ce4327", | ||||
|                 "sha256:46c900c807b0614c454ba89271ec6f59212403c54dc68ea493ab1ece2c510618", | ||||
|                 "sha256:48291b25a904243f37c9aabbfed3eaba466c9a993f5f5946fe647163b7face07", | ||||
|                 "sha256:5038a5e9e106087c117f0a7d6fd9d8a382b228da24bbd085b9f2b5d54ab11c3a", | ||||
|                 "sha256:594a26bcf0cb720c16ac6db3fd4b3f411be756f9da7682f2f629089ff15aef18", | ||||
|                 "sha256:59706135d3107939effe9f9263bd78c507f4abd7bfb96acc5a7f4176aa0a90d2", | ||||
|                 "sha256:5a327d7581696c7a392a8f85cce7e54fa1303f5b79b3b2983abaab309b56cfd6", | ||||
|                 "sha256:5eca8a45d38c916783c44e5da06a367b77234efa51d84dda8804654b99efecc9", | ||||
|                 "sha256:5fa85f6789178ede5333568cbee5bac5fa9718d5f02406b65545e83368fa8fe9", | ||||
|                 "sha256:65097e45ef7a942a9b92999b81d2e91fe80cbd0616215e625af39d2166692018", | ||||
|                 "sha256:65cc9938cb9bd8862fc220e0719fd7f9c291d788f0a62bb8840820c46fa5a4d0", | ||||
|                 "sha256:6a4c3607e2a0e66337d8ddf95ca7efe9b30ebf944119a4fb86503ea66f777263", | ||||
|                 "sha256:72f11a136f148eb1218e7d1492749b8b5594302010db0cebd47423c4ac8c79ee", | ||||
|                 "sha256:78b5a71de59e30c697a64c69fc48b032bb99c43b7437091b808a9ba20bb0235c", | ||||
|                 "sha256:7b212edc9bf9d0c25cc3117483289b9e1a49a1ed134a02635baa987e9f0d89db", | ||||
|                 "sha256:7e0f7045c420abdea249a28384baa846b87bad5c9f42af1957dc50c6e337fa1a", | ||||
|                 "sha256:7e83cfec424f546dc3f0cc71896f8cc384a711f4116bc1abb0598302a9af3240", | ||||
|                 "sha256:80c55bcc31d21bd07f7d1589e11f2ac1faf3359cf9f93026a1944ee76a40f954", | ||||
|                 "sha256:863740d7f45adfd29b95658a680b16113721eaa89857c67e7e9573c61e87bbd8", | ||||
|                 "sha256:88484b8c3f71dc9205d0d36da541e2cdcf4bc74474a2ee8d99c2e6411b659b89", | ||||
|                 "sha256:8a08810e0bcc606d10cf1c5389c96fc92362244c0cf761358c495c2eb29df3dc", | ||||
|                 "sha256:8c0637ae4fcb54d5c7fc9af24d348003b6f9dbaf7a06bf13f769d7b85903af39", | ||||
|                 "sha256:8e9e3409338a42e3d4c30c224fdb678364542c77994f089fd6cc8131969eff48", | ||||
|                 "sha256:902ea10ba85e014dc5d23a7bbb3ab70722349561e73783dd71571359e8867244", | ||||
|                 "sha256:9533db74a2685169380db3db3ab59643453e7c486fffa9bf3ab60b73c4e174be", | ||||
|                 "sha256:97f02ff49d1fa21308207a7743bec4fdd7aa90e8dd091539da660fc51e624c4d", | ||||
|                 "sha256:9ea9a2a154dc7d8658930fa87cda0e6094235b5e130f037d9894eaf8722119a5", | ||||
|                 "sha256:a0440d847b2c9986e4d27e8a59164714e5198530c69a5f9fb2e4620f9136d653", | ||||
|                 "sha256:a6d39a27b542a781d691827b955d685d496fb6cccfc6eecc336a78b399032062", | ||||
|                 "sha256:a7f4d3c478b1fcf412bf6c82914b02fed33ab359120df9172dda7bc855227461", | ||||
|                 "sha256:ad297807bbdffce61b04e5e0c22f3c5d9e1905c1ee186f1f6d029f83bf0f18b8", | ||||
|                 "sha256:add6778bb51efb80174937543754d2dfa0f4e504e7302d97896006a642c14f95", | ||||
|                 "sha256:ae075ebf7bb5f48b3bd2fc9cd53346e4ff43e2515a4f822914bbc62a3cbd6e7e", | ||||
|                 "sha256:b26fb439a7fbb522af63bbd781fbf51ec0c0659134a93f5bc8e9e68641df811e", | ||||
|                 "sha256:b2bac59721d246939b21274229b9923aeae3db97b6118da739c658c17e110dd6", | ||||
|                 "sha256:b314ad1f0667715e8d1b6197d5336ab579b13e801172721d62331bd40034a30c", | ||||
|                 "sha256:b7317035875bd7c4705e2566848b2043b78e18f2f5675ea651f9f7805b5589eb", | ||||
|                 "sha256:b8e936e620e5f336a207e08c0da9dace5d4dbcc8e64743ab1acaa77a64bbf060", | ||||
|                 "sha256:b906da4e9a7ba4ec33ed2f7238343866932c1a6f84944c804252b2922708d0ee", | ||||
|                 "sha256:ba690e4e33c360fcf0b8411ca90f8b9cc595e8deddd6a25a9a75a725b698cd6a", | ||||
|                 "sha256:bb14da3d63da994c34cfa47cde469df8013ddf5f575455a22530c8c4a0ed8616", | ||||
|                 "sha256:bbc2e1632f4a61fa171ddab3bc8368fb8475e7ce68733ca92fec862fdd8e0f60", | ||||
|                 "sha256:bbdd3c896db09993b7879cd35e56da6ed8918d161d6e80f9d9c40d78d34e4784", | ||||
|                 "sha256:bcaaa8e542cb7e1962d0a58ce6a25f6b4b6ca2e5ce743155fc1f6eb2fea52574", | ||||
|                 "sha256:bee682ab1005aff597946234e47c95fcf0f44d2b1f38075f0aba26bbc4e7545a", | ||||
|                 "sha256:bfec6543d60c57e7543d9cbccdd5dfcf562f2c05cd6b814df68108a20794e254", | ||||
|                 "sha256:c2e50baf7be8831524a87beec6c1873539519a1948f907dc3d4b9be27ebacb80", | ||||
|                 "sha256:c6c79a6138be017d85f3bab1df735669b669a38f9b3ff646a1f179afbacb7b63", | ||||
|                 "sha256:c702fb7c8bfd87c9ce9c8bddfc9a5796a492bab35a52b1693adee413721e32f2", | ||||
|                 "sha256:c9ba1725826f6571a6e4c1561bb1613711f0058b91927a147dc42c637ba087d9", | ||||
|                 "sha256:cf205ac52cb6b45745c0a4891cdb6e709c10ad5b034aa736aff561fc4ce9828c", | ||||
|                 "sha256:d0d03fc67499ee90feedfa2add4aaa1c091a7bf333535d847b10fffe390e58fe", | ||||
|                 "sha256:d118d63f08fd6ac285cb8166e96c992a6ed0e7a1644e8790c39070b18779e688", | ||||
|                 "sha256:d24c09f397c3ce55f20e0250da7ba5b0e5249cb5d21465e71ec15154a3a7e8e0", | ||||
|                 "sha256:d41735c7a646dae8612e0552dfc53f45807eeb54364dfb1f0a65ac274bc56b3a", | ||||
|                 "sha256:dd1696d91f2a37cece9bd22e507e7be7c37c59ecc61fd15f0d0f31e3b6888957", | ||||
|                 "sha256:dfcad9c63a893c95ba1149481b9680ce68dd71211f08df0073ee62700790bc97", | ||||
|                 "sha256:e384782608837d9aaf123e413679883091744664a2cd76f0ad0e0a1f12facc57", | ||||
|                 "sha256:e5ea0abea338c617b753082f36f64c70ade853d88e91ab5732b301ae8ed16e3f", | ||||
|                 "sha256:e6ff81c570413bcc35f1c16850eb66e2493a3259e68efe8672376533d2c82d38", | ||||
|                 "sha256:e88951ad2831880405f3f055ab12a6aa72696c20a2815128eeccdc3bf914cd78", | ||||
|                 "sha256:e98e16b6ce531b12100c01daac922e8ec5b991832a5f58003f13b7d45ea82dc0", | ||||
|                 "sha256:eb0fd32e8e433797499571447d9f975b4744be79c0a3339413868d79517231ed", | ||||
|                 "sha256:ee74a73e1f9e16b71f67329e99bb58aa4af9a2c3c4b3a5db9f26e92e7c39e161", | ||||
|                 "sha256:f15ec5f825c283a5aa427d78759ab8f84e7b5441d15cfff476b548bce3764666", | ||||
|                 "sha256:f296c7fe928ce0e29e313f85c43a5ab80542e096e1163c2605b8cc18aa2aff2b", | ||||
|                 "sha256:f32df1b19f773bb41382e8b215955d248c9766e3d6ff5a1dd89709e7d96e4685", | ||||
|                 "sha256:f3ed67279a4b317a808ac743d3a915f74187530c5f3d9c859e5d04d475b8c174", | ||||
|                 "sha256:f5b972ca514898fb7131671c425a62ca38fdae2a8d6296e4b605ec8202349f8c", | ||||
|                 "sha256:f961086c0dbba6c00cbd5c5b5646247efd0d0a4044444bfaa9efc7a6ba5e96a5", | ||||
|                 "sha256:f9bd7d7a449667d6f17edd9045ec82a4ed2767afb91743d3d0b18c376a56dfe2", | ||||
|                 "sha256:fbac4c8ffadb685189efa92fafdb2f5392e9cbd262eae3818bcdb1bd19acaaf2", | ||||
|                 "sha256:fc43c8276d0a7c7b76f31d4f3f80f9eb820673628f1411770a70029c1d5f6a75", | ||||
|                 "sha256:fcfded324f0710632e22050a2fd7b56b1cbcb2d21001630bcc26d536f54bffec", | ||||
|                 "sha256:ff435abdcbfdf4a070f488830cd53aef77cf8649d0fd8ed76bf27d9566e80e78" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==0.20.7" | ||||
|         }, | ||||
|         "lxml": { | ||||
|             "hashes": [ | ||||
|                 "sha256:04da965dfebb5dac2619cb90fcf93efdb35b3c6994fea58a157a834f2f94b318", | ||||
| @@ -1028,69 +901,68 @@ | ||||
|         }, | ||||
|         "pillow": { | ||||
|             "hashes": [ | ||||
|                 "sha256:0030fdbd926fb85844b8b92e2f9449ba89607231d3dd597a21ae72dc7fe26927", | ||||
|                 "sha256:030e3460861488e249731c3e7ab59b07c7853838ff3b8e16aac9561bb345da14", | ||||
|                 "sha256:0ed2c4ef2451de908c90436d6e8092e13a43992f1860275b4d8082667fbb2ffc", | ||||
|                 "sha256:136659638f61a251e8ed3b331fc6ccd124590eeff539de57c5f80ef3a9594e58", | ||||
|                 "sha256:13b725463f32df1bfeacbf3dd197fb358ae8ebcd8c5548faa75126ea425ccb60", | ||||
|                 "sha256:1536ad017a9f789430fb6b8be8bf99d2f214c76502becc196c6f2d9a75b01b76", | ||||
|                 "sha256:15928f824870535c85dbf949c09d6ae7d3d6ac2d6efec80f3227f73eefba741c", | ||||
|                 "sha256:17d4cafe22f050b46d983b71c707162d63d796a1235cdf8b9d7a112e97b15bac", | ||||
|                 "sha256:1802f34298f5ba11d55e5bb09c31997dc0c6aed919658dfdf0198a2fe75d5490", | ||||
|                 "sha256:1cc1d2451e8a3b4bfdb9caf745b58e6c7a77d2e469159b0d527a4554d73694d1", | ||||
|                 "sha256:1fd6f5e3c0e4697fa7eb45b6e93996299f3feee73a3175fa451f49a74d092b9f", | ||||
|                 "sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d", | ||||
|                 "sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f", | ||||
|                 "sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069", | ||||
|                 "sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402", | ||||
|                 "sha256:336b9036127eab855beec9662ac3ea13a4544a523ae273cbf108b228ecac8437", | ||||
|                 "sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885", | ||||
|                 "sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e", | ||||
|                 "sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be", | ||||
|                 "sha256:408673ed75594933714482501fe97e055a42996087eeca7e5d06e33218d05aa8", | ||||
|                 "sha256:4134d3f1ba5f15027ff5c04296f13328fecd46921424084516bdb1b2548e66ff", | ||||
|                 "sha256:4ad2f835e0ad81d1689f1b7e3fbac7b01bb8777d5a985c8962bedee0cc6d43da", | ||||
|                 "sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004", | ||||
|                 "sha256:510cef4a3f401c246cfd8227b300828715dd055463cdca6176c2e4036df8bd4f", | ||||
|                 "sha256:5aed7dde98403cd91d86a1115c78d8145c83078e864c1de1064f52e6feb61b20", | ||||
|                 "sha256:69bd1a15d7ba3694631e00df8de65a8cb031911ca11f44929c97fe05eb9b6c1d", | ||||
|                 "sha256:6bf088c1ce160f50ea40764f825ec9b72ed9da25346216b91361eef8ad1b8f8c", | ||||
|                 "sha256:6e8c66f70fb539301e064f6478d7453e820d8a2c631da948a23384865cd95544", | ||||
|                 "sha256:727dd1389bc5cb9827cbd1f9d40d2c2a1a0c9b32dd2261db522d22a604a6eec9", | ||||
|                 "sha256:74a04183e6e64930b667d321524e3c5361094bb4af9083db5c301db64cd341f3", | ||||
|                 "sha256:75e636fd3e0fb872693f23ccb8a5ff2cd578801251f3a4f6854c6a5d437d3c04", | ||||
|                 "sha256:7761afe0126d046974a01e030ae7529ed0ca6a196de3ec6937c11df0df1bc91c", | ||||
|                 "sha256:7888310f6214f19ab2b6df90f3f06afa3df7ef7355fc025e78a3044737fab1f5", | ||||
|                 "sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4", | ||||
|                 "sha256:7c7b502bc34f6e32ba022b4a209638f9e097d7a9098104ae420eb8186217ebbb", | ||||
|                 "sha256:808add66ea764ed97d44dda1ac4f2cfec4c1867d9efb16a33d158be79f32b8a4", | ||||
|                 "sha256:831e648102c82f152e14c1a0938689dbb22480c548c8d4b8b248b3e50967b88c", | ||||
|                 "sha256:93689632949aff41199090eff5474f3990b6823404e45d66a5d44304e9cdc467", | ||||
|                 "sha256:96b5e6874431df16aee0c1ba237574cb6dff1dcb173798faa6a9d8b399a05d0e", | ||||
|                 "sha256:9a54614049a18a2d6fe156e68e188da02a046a4a93cf24f373bffd977e943421", | ||||
|                 "sha256:a138441e95562b3c078746a22f8fca8ff1c22c014f856278bdbdd89ca36cff1b", | ||||
|                 "sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8", | ||||
|                 "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb", | ||||
|                 "sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3", | ||||
|                 "sha256:adabc0bce035467fb537ef3e5e74f2847c8af217ee0be0455d4fec8adc0462fc", | ||||
|                 "sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf", | ||||
|                 "sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1", | ||||
|                 "sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a", | ||||
|                 "sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28", | ||||
|                 "sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0", | ||||
|                 "sha256:d5b87da55a08acb586bad5c3aa3b86505f559b84f39035b233d5bf844b0834b1", | ||||
|                 "sha256:dcd7b9c7139dc8258d164b55696ecd16c04607f1cc33ba7af86613881ffe4ac8", | ||||
|                 "sha256:dfe4c1fedfde4e2fbc009d5ad420647f7730d719786388b7de0999bf32c0d9fd", | ||||
|                 "sha256:ea98f633d45f7e815db648fd7ff0f19e328302ac36427343e4432c84432e7ff4", | ||||
|                 "sha256:ec52c351b35ca269cb1f8069d610fc45c5bd38c3e91f9ab4cbbf0aebc136d9c8", | ||||
|                 "sha256:eef7592281f7c174d3d6cbfbb7ee5984a671fcd77e3fc78e973d492e9bf0eb3f", | ||||
|                 "sha256:f07f1f00e22b231dd3d9b9208692042e29792d6bd4f6639415d2f23158a80013", | ||||
|                 "sha256:f3fac744f9b540148fa7715a435d2283b71f68bfb6d4aae24482a890aed18b59", | ||||
|                 "sha256:fa768eff5f9f958270b081bb33581b4b569faabf8774726b283edb06617101dc", | ||||
|                 "sha256:fac2d65901fb0fdf20363fbd345c01958a742f2dc62a8dd4495af66e3ff502a4" | ||||
|                 "sha256:03150abd92771742d4a8cd6f2fa6246d847dcd2e332a18d0c15cc75bf6703040", | ||||
|                 "sha256:073adb2ae23431d3b9bcbcff3fe698b62ed47211d0716b067385538a1b0f28b8", | ||||
|                 "sha256:0b07fffc13f474264c336298d1b4ce01d9c5a011415b79d4ee5527bb69ae6f65", | ||||
|                 "sha256:0b7257127d646ff8676ec8a15520013a698d1fdc48bc2a79ba4e53df792526f2", | ||||
|                 "sha256:12ce4932caf2ddf3e41d17fc9c02d67126935a44b86df6a206cf0d7161548627", | ||||
|                 "sha256:15c42fb9dea42465dfd902fb0ecf584b8848ceb28b41ee2b58f866411be33f07", | ||||
|                 "sha256:18498994b29e1cf86d505edcb7edbe814d133d2232d256db8c7a8ceb34d18cef", | ||||
|                 "sha256:1c7c8ae3864846fc95f4611c78129301e203aaa2af813b703c55d10cc1628535", | ||||
|                 "sha256:22b012ea2d065fd163ca096f4e37e47cd8b59cf4b0fd47bfca6abb93df70b34c", | ||||
|                 "sha256:276a5ca930c913f714e372b2591a22c4bd3b81a418c0f6635ba832daec1cbcfc", | ||||
|                 "sha256:2e0918e03aa0c72ea56edbb00d4d664294815aa11291a11504a377ea018330d3", | ||||
|                 "sha256:3033fbe1feb1b59394615a1cafaee85e49d01b51d54de0cbf6aa8e64182518a1", | ||||
|                 "sha256:3168434d303babf495d4ba58fc22d6604f6e2afb97adc6a423e917dab828939c", | ||||
|                 "sha256:3dd6caf940756101205dffc5367babf288a30043d35f80936f9bfb37f8355b32", | ||||
|                 "sha256:40e1ce476a7804b0fb74bcfa80b0a2206ea6a882938eaba917f7a0f004b42502", | ||||
|                 "sha256:41e0051336807468be450d52b8edd12ac60bebaa97fe10c8b660f116e50b30e4", | ||||
|                 "sha256:4390e9ce199fc1951fcfa65795f239a8a4944117b5935a9317fb320e7767b40f", | ||||
|                 "sha256:502526a2cbfa431d9fc2a079bdd9061a2397b842bb6bc4239bb176da00993812", | ||||
|                 "sha256:51e0e543a33ed92db9f5ef69a0356e0b1a7a6b6a71b80df99f1d181ae5875636", | ||||
|                 "sha256:57751894f6618fd4308ed8e0c36c333e2f5469744c34729a27532b3db106ee20", | ||||
|                 "sha256:5d77adcd56a42d00cc1be30843d3426aa4e660cab4a61021dc84467123f7a00c", | ||||
|                 "sha256:655a83b0058ba47c7c52e4e2df5ecf484c1b0b0349805896dd350cbc416bdd91", | ||||
|                 "sha256:68943d632f1f9e3dce98908e873b3a090f6cba1cbb1b892a9e8d97c938871fbe", | ||||
|                 "sha256:6c738585d7a9961d8c2821a1eb3dcb978d14e238be3d70f0a706f7fa9316946b", | ||||
|                 "sha256:73bd195e43f3fadecfc50c682f5055ec32ee2c933243cafbfdec69ab1aa87cad", | ||||
|                 "sha256:772a91fc0e03eaf922c63badeca75e91baa80fe2f5f87bdaed4280662aad25c9", | ||||
|                 "sha256:77ec3e7be99629898c9a6d24a09de089fa5356ee408cdffffe62d67bb75fdd72", | ||||
|                 "sha256:7db8b751ad307d7cf238f02101e8e36a128a6cb199326e867d1398067381bff4", | ||||
|                 "sha256:801ec82e4188e935c7f5e22e006d01611d6b41661bba9fe45b60e7ac1a8f84de", | ||||
|                 "sha256:82409ffe29d70fd733ff3c1025a602abb3e67405d41b9403b00b01debc4c9a29", | ||||
|                 "sha256:828989c45c245518065a110434246c44a56a8b2b2f6347d1409c787e6e4651ee", | ||||
|                 "sha256:829f97c8e258593b9daa80638aee3789b7df9da5cf1336035016d76f03b8860c", | ||||
|                 "sha256:871b72c3643e516db4ecf20efe735deb27fe30ca17800e661d769faab45a18d7", | ||||
|                 "sha256:89dca0ce00a2b49024df6325925555d406b14aa3efc2f752dbb5940c52c56b11", | ||||
|                 "sha256:90fb88843d3902fe7c9586d439d1e8c05258f41da473952aa8b328d8b907498c", | ||||
|                 "sha256:97aabc5c50312afa5e0a2b07c17d4ac5e865b250986f8afe2b02d772567a380c", | ||||
|                 "sha256:9aaa107275d8527e9d6e7670b64aabaaa36e5b6bd71a1015ddd21da0d4e06448", | ||||
|                 "sha256:9f47eabcd2ded7698106b05c2c338672d16a6f2a485e74481f524e2a23c2794b", | ||||
|                 "sha256:a0a06a052c5f37b4ed81c613a455a81f9a3a69429b4fd7bb913c3fa98abefc20", | ||||
|                 "sha256:ab388aaa3f6ce52ac1cb8e122c4bd46657c15905904b3120a6248b5b8b0bc228", | ||||
|                 "sha256:ad58d27a5b0262c0c19b47d54c5802db9b34d38bbf886665b626aff83c74bacd", | ||||
|                 "sha256:ae5331c23ce118c53b172fa64a4c037eb83c9165aba3a7ba9ddd3ec9fa64a699", | ||||
|                 "sha256:af0372acb5d3598f36ec0914deed2a63f6bcdb7b606da04dc19a88d31bf0c05b", | ||||
|                 "sha256:afa4107d1b306cdf8953edde0534562607fe8811b6c4d9a486298ad31de733b2", | ||||
|                 "sha256:b03ae6f1a1878233ac620c98f3459f79fd77c7e3c2b20d460284e1fb370557d4", | ||||
|                 "sha256:b0915e734b33a474d76c28e07292f196cdf2a590a0d25bcc06e64e545f2d146c", | ||||
|                 "sha256:b4012d06c846dc2b80651b120e2cdd787b013deb39c09f407727ba90015c684f", | ||||
|                 "sha256:b472b5ea442148d1c3e2209f20f1e0bb0eb556538690fa70b5e1f79fa0ba8dc2", | ||||
|                 "sha256:b59430236b8e58840a0dfb4099a0e8717ffb779c952426a69ae435ca1f57210c", | ||||
|                 "sha256:b90f7616ea170e92820775ed47e136208e04c967271c9ef615b6fbd08d9af0e3", | ||||
|                 "sha256:b9a65733d103311331875c1dca05cb4606997fd33d6acfed695b1232ba1df193", | ||||
|                 "sha256:bac18ab8d2d1e6b4ce25e3424f709aceef668347db8637c2296bcf41acb7cf48", | ||||
|                 "sha256:bca31dd6014cb8b0b2db1e46081b0ca7d936f856da3b39744aef499db5d84d02", | ||||
|                 "sha256:be55f8457cd1eac957af0c3f5ece7bc3f033f89b114ef30f710882717670b2a8", | ||||
|                 "sha256:c7025dce65566eb6e89f56c9509d4f628fddcedb131d9465cacd3d8bac337e7e", | ||||
|                 "sha256:c935a22a557a560108d780f9a0fc426dd7459940dc54faa49d83249c8d3e760f", | ||||
|                 "sha256:dbb8e7f2abee51cef77673be97760abff1674ed32847ce04b4af90f610144c7b", | ||||
|                 "sha256:ebf2029c1f464c59b8bdbe5143c79fa2045a581ac53679733d3a91d400ff9efb", | ||||
|                 "sha256:f1ff2ee69f10f13a9596480335f406dd1f70c3650349e2be67ca3139280cade0" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==9.2.0" | ||||
|             "version": "==9.3.0" | ||||
|         }, | ||||
|         "pluggy": { | ||||
|             "hashes": [ | ||||
| @@ -1223,13 +1095,6 @@ | ||||
|             "index": "pypi", | ||||
|             "version": "==0.5.0" | ||||
|         }, | ||||
|         "python-levenshtein": { | ||||
|             "hashes": [ | ||||
|                 "sha256:88a58b95e3340a918489dac0c78f731323c0a4d8f5564f839ffea80155574e77", | ||||
|                 "sha256:9228af5523f797f0798f045dc4a95ed1f46df72bc2186e52b530a33998a51b37" | ||||
|             ], | ||||
|             "version": "==0.20.7" | ||||
|         }, | ||||
|         "python-magic": { | ||||
|             "hashes": [ | ||||
|                 "sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b", | ||||
| @@ -1240,10 +1105,10 @@ | ||||
|         }, | ||||
|         "pytz": { | ||||
|             "hashes": [ | ||||
|                 "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22", | ||||
|                 "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914" | ||||
|                 "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427", | ||||
|                 "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2" | ||||
|             ], | ||||
|             "version": "==2022.5" | ||||
|             "version": "==2022.6" | ||||
|         }, | ||||
|         "pytz-deprecation-shim": { | ||||
|             "hashes": [ | ||||
| @@ -1309,111 +1174,98 @@ | ||||
|         }, | ||||
|         "rapidfuzz": { | ||||
|             "hashes": [ | ||||
|                 "sha256:036f904bcac16d726273eee7ec0636978af31d151f30c95b611240e22592ab79", | ||||
|                 "sha256:0429a7a51d1372afaca969ee3170f9975f2fe6e187b485aeef55d3e8d7d934e0", | ||||
|                 "sha256:09de4fd3dbcc73f61b85af006372f48fee7d4324de227702b9da0d2572445d26", | ||||
|                 "sha256:0c8a5e65cab629ca5bb4b1d2b410f8444384b60364ab528508200acfdf9e659d", | ||||
|                 "sha256:0e64ab58b19866ad3df53e651a429871d744f8794cca25c553396b25d679a1ac", | ||||
|                 "sha256:0f09ff49b28e557615a9ad4d5eedbfd5b886fccb3ec35d85dd34c51348c4bf98", | ||||
|                 "sha256:12e14b0c43e3bc0c679ef09bfcbcaf9397534e03b8854c417086779a79e08bb2", | ||||
|                 "sha256:134a467692216e05a8806efe40e3bcae9aa81b9e051b209a4244b639a168c78e", | ||||
|                 "sha256:13ce1019ddce7419502fac43b62ac166d3d6d290b727050e3de5bda79a6beb59", | ||||
|                 "sha256:16a2edf3ea888c9d3582761a2bbaa734e03f6db25d96e73edd4dcef6883897ee", | ||||
|                 "sha256:17ba5fb474515356608cdb8d750f95c12f3e4dc9a0e2c9d7caca3d4cee55048e", | ||||
|                 "sha256:2183fc91971c0853f6170225577d24d81b865d416104b433de53e55a6d2a476a", | ||||
|                 "sha256:24569412e1aac1ac008548cdcd40da771e14467f4bacab9f9abfe5bbb5dfe8be", | ||||
|                 "sha256:254d5a800de54c416fa9b220e442a4861b272c1223139ae3dee0aea1c9f27c9c", | ||||
|                 "sha256:2bc3ec87df5eaad59e6e02e6517047fb268a48866f3531c4b8b59c2c78069fe5", | ||||
|                 "sha256:2d3652804ae17920eaa965b1e057ee0ea32d5bb02f50147c82a1d350a86fc3f1", | ||||
|                 "sha256:30773e23bebe27ddcf7644d6ebb143bf7c9adeb18019a963172174ef522c0831", | ||||
|                 "sha256:3b6573607568438dfc3d4341b0b00d326ac2cf86281df97e7f8c0348e2f89b5e", | ||||
|                 "sha256:3d50a2ca8cd1cea13afd2ff8e052ba49860c64cc3e617398670fd6a8d11e450f", | ||||
|                 "sha256:3f1c030e2d61d77cb14814640618e29cf13e4554340a3baa9191d162a4dfcd9e", | ||||
|                 "sha256:40e8d37d67a6e4713ddb6053eb3007a3ca15eddd23f2e4a5039c39e666c10b3a", | ||||
|                 "sha256:41c9e2acfa25c7667b70913d63887f76e981badc1e95a2878257d28b96f5a10c", | ||||
|                 "sha256:42d18db6f7e1e6ef85a8e673b2fa3352727cc56e60e48e7c9268fe0286ab9f91", | ||||
|                 "sha256:475aacad5d5c4f9ad920b4232cc196d79a1777fe1eada9122103c30154d18af4", | ||||
|                 "sha256:47e163d6a6676be9a3a7e93d5a2c3c65a43c1530b680903ebdba951e07ee7999", | ||||
|                 "sha256:5080ad715e39b8a2d82339cf4170785e9092c7625ec2095ff3590fdb0a532a41", | ||||
|                 "sha256:52639268dffc8900892a5e57964228fb187512b0f249de9a45ba37c6f2bc52a5", | ||||
|                 "sha256:54264d70af59224d6874fcc5828da50d99668055574fe254849cab96f3b80e43", | ||||
|                 "sha256:553e8e3dce321ed33e8b437586e7765d78e6d8fbb236b02768b46e1b2b91b41e", | ||||
|                 "sha256:56aa67bf938e8dcc5e940f183538f09041441f1c4c5a86abe748416950db9d27", | ||||
|                 "sha256:578934d7524f8378175295e6411b737d35d393d91d4661c739daa8ea2b185836", | ||||
|                 "sha256:588dd5f520683af53a9d9d0cabde0987788c0ea9adfda3b058a9c27f448b2b3f", | ||||
|                 "sha256:5aff0ac1723f7c8d751869a51e6b12d703fd6e6153228d68d8773f19bd5bd968", | ||||
|                 "sha256:5e3164736ed071dc743994b9228ead52b63010aba24b1621de81b3ac39d490b9", | ||||
|                 "sha256:5e89f50f5f3be2b851e9714015e1a26c6546e6b42f3df69b86200af8eacf9d8c", | ||||
|                 "sha256:61152fa1e3df04b4e748f09338f36ca32f7953829f4e630d26f7f564f4cb527b", | ||||
|                 "sha256:64133c9f45cb88b508d52427339b796c76e1790300c7ea4d2ed210f224e0698d", | ||||
|                 "sha256:65b8611c9f5385a2986e11e85137cdecf40610e5d5f250d96a9ed32b7e995c4a", | ||||
|                 "sha256:6803ef01f4056d61120e37acba8953e6b3149363e85caaba40ee8d49753fe7bd", | ||||
|                 "sha256:68d46ad148c9cb8be532b5dd7bc246b067e81d4cfabad19b4cb6ac4031cab124", | ||||
|                 "sha256:6b12420d5b769cd7e1478a8085aeea1ad0ffc8f7fedc86c48b8d598e1602f5ad", | ||||
|                 "sha256:705ccd8de2b7b5295c6a230a3919fc9db8da9d2a6347c15c871fcb2202abd237", | ||||
|                 "sha256:7478341137e65a0227fda4f3e39b3d50e6ec7dd4f767077dd435b412c2f2c129", | ||||
|                 "sha256:769cf4099f53507231ba04cbf9ee16bea3c193767efc9bdf5e6c59e67e6b5cea", | ||||
|                 "sha256:7750b950a6987bce114b9f36413399712422f4f49b2ad43f4b4ee3af34968b99", | ||||
|                 "sha256:7c457f779992a0f5527455cdc17c387268ae9f712d4e29d691704c83c6e58c2d", | ||||
|                 "sha256:7dd6a439fb09dc9ba463de3f5c8e20f097225816b33a66380b68c8561a08045c", | ||||
|                 "sha256:804c7c67dc316f77b01b9bef5e75f727b73ff1015ff0514972b59dc05eec4d81", | ||||
|                 "sha256:86038b9777b2aa0ebf8c586b81cba166ccde7e6d744aad576cd98c1a07be4c53", | ||||
|                 "sha256:86c34175830cacac1c16d2182a0f725afbd40042955b7572c8475e3b6a5d8ada", | ||||
|                 "sha256:8a11b70ebb2d7317d69bdb1f692a0eda292a4cddfe9ccb760a8d1a9e763811dd", | ||||
|                 "sha256:8b402e99593483a8b05a09fb2a20379ecaa9b0d1f1cf32957b42134bd3305731", | ||||
|                 "sha256:8b480a78227457a0b65e0b23afbda9c152dee4e1b41ccc058db8c41ea7a82ab0", | ||||
|                 "sha256:8bc00bd6b6407dc7a8eb31964bcc38862c25e7f5f5982f912f265eb3c4d83140", | ||||
|                 "sha256:8d6fa1d009fcb9a9169548c29d65a1f05c0fcf1ac966f40e35035307d6a17050", | ||||
|                 "sha256:9081542fea2baeebda8caa43a54ecd8a152a05ff3271c38ac8eae447377cef54", | ||||
|                 "sha256:931a939ba5e5574f769507038fdf400dbbc46aab2866d4e5e96d83a29f081712", | ||||
|                 "sha256:984d40ecda0bc0109c4239d782dfe87362d02b286548672f8a2468eabbf48a69", | ||||
|                 "sha256:9924497dec6a30b5158ef7cc9c60a87c6c46d9f7b7bb7254d4f157b57b531fb8", | ||||
|                 "sha256:a48ff6b6258a32f50f876a6c74fa2f506c1de3b11773d6bf31b6715255807a48", | ||||
|                 "sha256:a7f5a77466c4701062469bce29358ca0797db2bc6d8f6c3cd4e13f418cca10bc", | ||||
|                 "sha256:a98c63d1f5ec2c15adf5dc81c461c8d88c16395956f4518b78e2e04b3285b1e5", | ||||
|                 "sha256:adc7c6cb3dde5c284d84c7c6f4602b1545ba89c6ebb857b337d0428befb344e5", | ||||
|                 "sha256:b4f577ded3e40695d5e0796e8b7f4fa78577d873627e0d0692f7060ad73af314", | ||||
|                 "sha256:b5c7b0a4929bfd3945d9c2022cff0b683a39accf5594897fa9004cee4f402b06", | ||||
|                 "sha256:b5cd1ea9fa396243d34f7bac5bb5787f89310f13fd2b092d11940c6cd7bd0bd8", | ||||
|                 "sha256:bafd18a27dbe3197e460809468a7c47d9d29d1ebab6a878d5bb5a71fda2056d6", | ||||
|                 "sha256:bd595bd23a4e1c72d5f5ac416ea49b9a3d87e11fb2db4b960378038ce9bb12f7", | ||||
|                 "sha256:bd7a1992e91c90197c34ccc674bd64262262627083c99896b79e2c9f5fe28075", | ||||
|                 "sha256:bd8f36d8bd399c7d695182e467b4428adb940a157014ab605bbe4d0ab0a1976e", | ||||
|                 "sha256:bf5277ff74c9980245697ea227057d0f05b31c96bc73bae2697c1a48d4980e45", | ||||
|                 "sha256:bfabc6130752f4f77584b2ecbba2adf6fe469b06c52cb974ba8304f1f63bb24f", | ||||
|                 "sha256:c10724490b87fcb86161e5ceb17893626d13363e31efee77aa8e251ee16dcdd5", | ||||
|                 "sha256:c1477455b82d6db7336ef769f507a55bba9fe9f1c96dc531d7c2c510630307d6", | ||||
|                 "sha256:c288e239fc3aaae3865e43e1f35b606f92ee687a0801e4d46c45d7849aebbe35", | ||||
|                 "sha256:c305ea5405f8615e6ecd39cb28acc7a362713ba3c17c7737b591b377d1afd9ec", | ||||
|                 "sha256:c77cec595dc80f97a1b32413fb1b618e4da8ba132697e075ad8e4025c4058575", | ||||
|                 "sha256:c822853e9d54979eb5fcf9e54c1f90e5c18eeb399571383ac768cff47d6d6ada", | ||||
|                 "sha256:cad5088f1adb9161f2def653908328cfa1dc9bc57e7e41ccdc9339d31cc576d1", | ||||
|                 "sha256:cc3103e31d27352afe4c5a71702e09185850187d299145d5e98f9fb99a3be498", | ||||
|                 "sha256:ced719fcae6f2a348ac596b67f6d7c26ff3d9d2b7378237953ac5e162d8a4e2e", | ||||
|                 "sha256:d181889218d80f6beb5ae3838bc23e201d2a1fae688baaa40d82ef9080594315", | ||||
|                 "sha256:d1d8192820d8489a8e3ef160cbe38f5ff974db5263c76438cf44e7574743353b", | ||||
|                 "sha256:d24181dfdfcc3d9b37333fea2f5bf9f51e034bd9e0ba67a871f18686b797c739", | ||||
|                 "sha256:d51b9183ebce60d4795ceaef24b8db2df3ed04307ee787d6adafcc196330a47c", | ||||
|                 "sha256:dad6697c6b9e02dd45f73e22646913daad743afd27dadb0b6a430a1573fb4566", | ||||
|                 "sha256:dafe8c6e74fea0fdcfec002bc77aee40b4891b14ea513e6092402609ac8dac00", | ||||
|                 "sha256:dc0f695b32700b14f404cccaebc25eea6db323418385568297995aee8b5278f8", | ||||
|                 "sha256:e2fe220d4b100b00734d9388e33296ac8f585c763548c372ca17b24affa178e0", | ||||
|                 "sha256:e459287f0daaee3ee0108123d7e9a1c1c136e94d4382533a93cb509d54dc1ea3", | ||||
|                 "sha256:ea4107a5cc00a05c92be47047662000296d2ccc7ba93aaa030cd5ecab8d5ffaf", | ||||
|                 "sha256:ea4f0d056a95cfdabde667a1796f9ba5296d2776bce2fd4d4cb5674e0e10671f", | ||||
|                 "sha256:ea5bc5bae1cf447b79be04f05e73b6ea39a5df63374f70cc5d6862337462d4d9", | ||||
|                 "sha256:ecfe2fe942edabcd1553701237710de296d3eb45472f9128662c95da98e9ed43", | ||||
|                 "sha256:eec5ad2f06701e57a2cb483c849704bdf8ea76195918550ab2fc4287970f1c76", | ||||
|                 "sha256:f2f91b867d7eca3b99c25e06e7e3a6f84cd4ccb99f390721670ba956f79167c9", | ||||
|                 "sha256:f5ed8d4e1545f08bd3745cc47742b3689f1a652b00590caeb32caf3297d01e06", | ||||
|                 "sha256:f6e6395404b0239cff7873a18a94839343a44429624f2a70a27b914cc5059580", | ||||
|                 "sha256:f71edc8503d08bc5d35187eb72f13b7ec78647f1c14bb90a758ae795b049f788", | ||||
|                 "sha256:f72d33b0d76a658d8b692b3e42c45539939bac26ff5b71b516cb20fa6d8ff7f6", | ||||
|                 "sha256:f9226824c132d38f2337d2c76e3009acc036f0b05f20e95e82f8195400e1e366", | ||||
|                 "sha256:faba219b270b78e9494cfe3d955d7b45c10799c18ee47ec24b1ada93978d491b" | ||||
|                 "sha256:028aa9edfa044629a0a9e924a168a01f61c8f570c9ea919e2ed214826ba1cdfb", | ||||
|                 "sha256:02a5c8b780af49a4e5f08033450d3f7c696f6c04e57c67ecbb19c9944ea3ce20", | ||||
|                 "sha256:07c623741958dd49d8c2c51f7c2e62472f41b8d795cc9c734e441e30de3f8330", | ||||
|                 "sha256:0ae8c0c2f51f618d54579341c44ba198849d9cd845bb0dc85d1711fd8de9a159", | ||||
|                 "sha256:129c93a76c4fed176b4eaaf78fecd290932971bca10315dee9feaf94a7b443b1", | ||||
|                 "sha256:13ad87a539b13794292fb661b8c4f4c19e6c066400d9db991e3a1441f55fc29b", | ||||
|                 "sha256:16426b441d28efb3b1fe10f2b81aa469020655cef068a32de6ec24433590ee5b", | ||||
|                 "sha256:1a600b037a56a61111c01809b5e4c4b5aac12edf2769c094fefab02d496a95a4", | ||||
|                 "sha256:1e0f6f878c20454a7e7ea2ed30970ae0334852c5e422e7014757821fa33c1588", | ||||
|                 "sha256:20f2f0f0746ffc165168ca160c5b1a1485076bdde5b656cf3dbe532ef2ac57ff", | ||||
|                 "sha256:2207927f42ae7b7fbcc1a4ff86f202647776200f3d8723603e7acf96af924e9f", | ||||
|                 "sha256:22487992f4811c8aef449736f483514f0294d5593f5f9c95cbfb2474dbc363b9", | ||||
|                 "sha256:22646f54d44d98d6f462fb3f1ac997ea53aaebdd1344039e8f75090f43e47a89", | ||||
|                 "sha256:22e8b127abcf0b10ebf8a9b3351c3c980e5c27cb60a865632d90d6a698060a9a", | ||||
|                 "sha256:238fddfb90fab858ced88d064608bff9aed83cec11a7630a4e95b7e49734d8b1", | ||||
|                 "sha256:241912c4f7f232c7518384f8cea719cf2ff290f80735355a217e9c690d274f62", | ||||
|                 "sha256:25db060ba8082c38f75da482ff15d3b60a4bc59f158b6d29a2c5bccadd2b71b0", | ||||
|                 "sha256:2676f7ccd22a67638baff054a8e13924f20d87efb3a873f6ea248a395a80e2c8", | ||||
|                 "sha256:27fa0e7d5e5291dc3e48c6512524f2f8e7ba3d397fa712a85a97639e3d6597e9", | ||||
|                 "sha256:2c2cd1e01e8aef2bd1b5152e66e0b865f31eb2d00a8d28cbbbb802f42e2dbe43", | ||||
|                 "sha256:2e9709a163ec3b890f9a4173261e9ef586046feee74bbece62595bf103421178", | ||||
|                 "sha256:2fda8c003d9ae4f3674c783887b31ecb76f4ab58670a8f01b93efd0917c1e503", | ||||
|                 "sha256:33cfd01cb7f8a48c8e057198e3814a120323c0360017dd5c4eba07d097b43b39", | ||||
|                 "sha256:35737fd5766ca212d98e0598fb4d302f509e1cbf7b6dc42e2eddefd956150815", | ||||
|                 "sha256:35b34f33a9f0a86fdba39053b203d8d517da76f3553230a55867c51f0d802b67", | ||||
|                 "sha256:3abe9c25f9ba260a6828d24002a15112c5f21c6877c5f8c294ffe4b9d197c6d2", | ||||
|                 "sha256:3c7f3c61e2d1530cf7e1647bdbb466f0f83fa30d2c579b6d75e444f88ff47913", | ||||
|                 "sha256:3e8707e98b645f80834e24103e7cd67f1b772999bb979da6d61ca1fcdc07672a", | ||||
|                 "sha256:3eae4c6880dbabee9f363950510c09d7e12dea8dbc6ebcd2ff58e594a78d9370", | ||||
|                 "sha256:3f7b798807ac9c5f632e8f359adf1393f81d9211e4961eedb5e2d4ce311e0078", | ||||
|                 "sha256:43398361d54fed476ccfdb52dc34d88c64461f0ec35f8abf10dd0413a3f19d8c", | ||||
|                 "sha256:4581600ded8f37e8387d0eef93520fb33dafab6ccb37d005e20d05cd3fbdd9db", | ||||
|                 "sha256:45def44f1140c6f5c7a5389645d02e8011d27a6e64f529f33cee687e7c25af07", | ||||
|                 "sha256:475a551c43ba23b4ca328c9bbcae39205729f4751280eb9763da08d97d328953", | ||||
|                 "sha256:4787d8e9f4b184d383ad000cdd48330ae75ec927c5832067a6b3617c5f6fb677", | ||||
|                 "sha256:48539221026b0a84b6d2c2665c3dde784e3c0fac28975658c03fed352f8e1d7e", | ||||
|                 "sha256:4f3f0ddfe3176e19c0a3cf6ad29e9ff216ff5fdec035b001ebabad91ef155107", | ||||
|                 "sha256:4fc958b21416825c599e228278c69efb480169cd99d1a21787a54f53fbff026c", | ||||
|                 "sha256:589464c49a332c644b750f2ebc3737d444427669323ace623bd4948e414a641a", | ||||
|                 "sha256:5c6a9ada752149e23051852867596b35afc79015760e23676ac287bcad58e0b6", | ||||
|                 "sha256:5dcd7bd175d870338fc9ae43d0184ecd45958f5ca2ee7ea0a7953eedc4d9718e", | ||||
|                 "sha256:5e2c0a5a0346ce95a965ed6fa941edcf129cac22bf63314b684a3fe64078c95b", | ||||
|                 "sha256:5fa88543c5744d725fc989afd79926c226e1c5f5c00904834851997f367da2b5", | ||||
|                 "sha256:626eaa1b52a9dafa9bf377bcdcfdf1ea867dd51b5bb5dab1a05938c3303f317f", | ||||
|                 "sha256:651664023726f28f7447e40fa2b8a015514f9db4b58654e9bf7d3729e2606eab", | ||||
|                 "sha256:74f821370ac01f677b5a26e0606084f2eb671f7bb4f3e2e82d94a100b1c28457", | ||||
|                 "sha256:7a67d93fd2e6e5a4e278eade2bbef16ba88d4efcb4eed106f075b0b21427a92f", | ||||
|                 "sha256:7e34c996cc245a21f376c3b8eede1296339845f039c8c270297a455d3a1ad71b", | ||||
|                 "sha256:7f2db0c684d9999c81084aa370e2e6b266b694e76c7e356bbeb3b282ca524475", | ||||
|                 "sha256:7febf074f7de7ebc374100be0036fc592659af911b6efbc1135cdebfe939c57d", | ||||
|                 "sha256:800b1498989bfb64118b219eeb42957b3d93ec7d6955dfc742a3cbf3be738f2f", | ||||
|                 "sha256:8eadfb5394ab5b9c6e3d4bb00ef49e19f60a4e431190c103e647d4e4bff3332e", | ||||
|                 "sha256:917e3e2ffc0e078cce4a632f65d32a339f18cad22b5536a32c641bf1900e7f96", | ||||
|                 "sha256:96fe7da85d8721c3a5c362f6b1e7fd26ad74a76bebc369fb7ae62907cf069940", | ||||
|                 "sha256:9836bea98f25a67c296f57cf6de420c88f46e430ee85d25ae5f397968c7adcdf", | ||||
|                 "sha256:9c8295dd49582dfb6a29e5f9dfa1691a0edd2e0512377ceb2c8dd11e7fabd38a", | ||||
|                 "sha256:9ceb8d6f1bd18a058cb8472c6e8cc84802413a65b029a7832589ba7b76c0eb11", | ||||
|                 "sha256:9e239e404dbb9fec308409e174710b5e53ff8bd9647e8875e2ca245b1f762f89", | ||||
|                 "sha256:9f849d4889a0f1bc2260b981b1ae8393938e8a2c92666e1757e69f947c6ce868", | ||||
|                 "sha256:a6d78f967b7b162013fc85821a74cc7cd021fbf045f166629c9bd523799d8e51", | ||||
|                 "sha256:a8d5787f5c52c00991032b976b69f5c1e181a3bddce76fd43c91b2c4901c96ce", | ||||
|                 "sha256:a9a90ab26b12218d10d5f148e84e8facd62f562bc25d32e2c3cf3c743f7e0e67", | ||||
|                 "sha256:ac6ce417174a086a496aefc7caa614640dc33d418a922ee0a184b093d84f2f6c", | ||||
|                 "sha256:ac95a2ca4add04f349f8f5c05269d8b194a72ebdfc4f86a725c15d79a420d429", | ||||
|                 "sha256:ad279e4892652583671a7ece977dd9b1eb17ae9752fbc9013c950095b044a315", | ||||
|                 "sha256:ad5935f4a0ec3a2c3d19021fcd27addce4892ae00f71cc4180009bc4bed930ac", | ||||
|                 "sha256:ae0519d01a05c6204c2d27ae49b2231787d9a6efc801d5dbf131b20065fd21e3", | ||||
|                 "sha256:b1114da71974c86e64a98afff8d88cf3a3351b289d07f0218e67d56b506cb9e2", | ||||
|                 "sha256:b2b81c6cb59b955b82a4853e3fbef7231da87c5522a69daaf9b01bd81d137ec3", | ||||
|                 "sha256:b63402c5af2ad744c2c1ab2e7265eb317e75257fd27eb6f087fea76464b065db", | ||||
|                 "sha256:b75fe7abf55e7da6d32174b5ac207a465d1bc69d777049c277776472c0b7d82c", | ||||
|                 "sha256:c0006c6450d02efdfef8d3f81e6a87790572486046676fe29f4c5da8708ea11b", | ||||
|                 "sha256:c1191a1c9f24134c6048770aabaa2f7def8d6d4c919da857d5e7dabdf63308f2", | ||||
|                 "sha256:c43579c7a64f21c9b4d4c3106ace46a8ebfb8e704372e6c8cc45807d1b86462f", | ||||
|                 "sha256:c62472a70c7f22f1ae9864c02554dbc234a1dfbac24388542bf87437a4169379", | ||||
|                 "sha256:c6c4064b2324b86f7a035379928fe1f3aca4ca5ba75ebedc9ea0d821b0e05606", | ||||
|                 "sha256:c6fa81c8d3c901d9f174482185f23b02052e71da015da3a613be98f28fd2672b", | ||||
|                 "sha256:c74b960a1b93ac22e6cbf268ce509fb2c2338a29180c3d844df4a57bfff73273", | ||||
|                 "sha256:c9c2b3b00033afdb745cc77b8c2ed858b08bb9a773c9a81a1160ece59a361545", | ||||
|                 "sha256:c9fdbe8b1b32a731ee48a21a161358e55067c9cabd36ba0b8d844e5106056920", | ||||
|                 "sha256:d0fc1e32353afef426488d2e19cd295f1f504323215275ec0871bdae2b052a70", | ||||
|                 "sha256:d5b65d9f2860210087739adadc075bd9215b363d00c3c8e68369560683a4c3df", | ||||
|                 "sha256:d6e6972c5bd1ee4f532029616dfe0f5133f7cc688ebc05dbbc03e19b4ec12199", | ||||
|                 "sha256:e333bb6a69c515a1fce149002aaf7d8902fddab54db14fe14c89c6da402410d2", | ||||
|                 "sha256:ef812c73fff460678defaab3a95ec9b7551ef14d424eb6af7b75e376050119d2", | ||||
|                 "sha256:f030223aa618a48d2f8339fd674c4c03db88649313e2c65107e9c04e09edc7f2", | ||||
|                 "sha256:f371453d0c1109e93ef569741a27171e602ef1fbea5c27a8f190f403234fd36b", | ||||
|                 "sha256:f74636ca4a3ce700f4fe2dbe10d224ee4fb52ecab12ea3007a2bc2fcd0d53888", | ||||
|                 "sha256:f96973d42caf0e4566882b6e7acbba753199d7acb4db486f14ab553c7b395cd5" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==2.11.1" | ||||
|             "index": "pypi", | ||||
|             "version": "==2.12.0" | ||||
|         }, | ||||
|         "redis": { | ||||
|             "extras": [ | ||||
| @@ -1508,45 +1360,54 @@ | ||||
|         }, | ||||
|         "reportlab": { | ||||
|             "hashes": [ | ||||
|                 "sha256:03501aa3cffb93ec35ca01d66a70d38090e88080b16eb4efb015a0fdc94a48c9", | ||||
|                 "sha256:04fc4420f0548815d0623e031c86a1f7f3f3003e699d9af7148742e2d72b024a", | ||||
|                 "sha256:06a9a9b04083529e4204e0c0f4574b7795cc8364a49e66dac25d94588fdaf24a", | ||||
|                 "sha256:32b3e10acdbbd2b91a8bb94134ed011af8e5c32ef5fe69f5481f83bbc89fd40e", | ||||
|                 "sha256:384e51906d710cec7721ee4f074bc59131dbed9ef3b8e45408432caa752c1d5d", | ||||
|                 "sha256:3e53e8222afc535cfdad3d73786c570ec6567b48e3e09bfadca606b170f3f46d", | ||||
|                 "sha256:456b9e245dacfa0f676f2864b8981a61bb50aa3fe690fe54885dc41b2b2b402c", | ||||
|                 "sha256:4c183a28a44bc03c0ab825fceab4a07a8b36d7f67a208dcf9e561dc4e343aec9", | ||||
|                 "sha256:4e97028ea070199955cb50dd1e321177f7fd2fefe89fb328d016e510d60bfc9e", | ||||
|                 "sha256:5104000c1f84066c452022316faecb7382eae23a878547cacfa6511f9fddfe02", | ||||
|                 "sha256:55df316e227f876e88ba5979c2456e3be47988056e0053d1139f9fbaff968d24", | ||||
|                 "sha256:60bcdefa9246e9dd26708d53fe4a51dcef74f9a387b8daa557804adf856a4fd5", | ||||
|                 "sha256:689ecf2eea098afb4bba39c97994c6e9ab65a1cf8e5ca7f897942f8692af9932", | ||||
|                 "sha256:68d118d8f4dabfde284237901a24b22e7827695cc74c8184b57828eb10e28090", | ||||
|                 "sha256:74ca4e4221bb68403753a595a9d24899b2a559d42fd573d00d8884e6a54d0ba1", | ||||
|                 "sha256:89c9ba175f72a2fd91836c414a09f91459f2e53b648f69300de6f8e0709a2de2", | ||||
|                 "sha256:89f486c48a06655a7aec92b593be60f70d4cfed0b205038acc0c3263df3d8b4a", | ||||
|                 "sha256:8e4d4133a2be465aae0826ae8e11319e6411e3119d16b4d6f40079fa89835c43", | ||||
|                 "sha256:93864be3ae1dabfa66607734113cc08ac9f839e2b49632df60ede1f0893864ee", | ||||
|                 "sha256:a62a856d5c6168f07d2c18e725f577bda5d4bbd4bf535d5c7c99d03b335effe1", | ||||
|                 "sha256:a71f6f231e94f2e543a255aa98bf8db2936f7b132be456c70ccf3c98cd60c160", | ||||
|                 "sha256:abb5d98541fc89c0d94627d82c83bdd464120c3422333e0f9f37a236ca1c44c8", | ||||
|                 "sha256:ad2d649197971c52a8c074739b3aae3cf3db99971561a371a54d429c19a49050", | ||||
|                 "sha256:b36e27adeb36fcf2854f8d9951e5e99fa655b4f03d2d15ba321bae42d65e2535", | ||||
|                 "sha256:b5f30124b0f5dab69fa56d12b94a50656f030e547bb09ab03936fd8708f04afc", | ||||
|                 "sha256:b6450ebf6fbbe826dd4e4837e7cc906a256e1383883ef21a143a5d39c7ce35cc", | ||||
|                 "sha256:b6d8979e7769cb860dfffd8d1c303501fea4820f592b5e6836cba1b64aa82f10", | ||||
|                 "sha256:c3988595e57c114c2cc93dd21b08f917c3d868bf57fd52bbb20008e3c26f023e", | ||||
|                 "sha256:c3a4bdb586e6649bd2b7d452b79c09a819bcb848ac408f1f4b00155c91469ffd", | ||||
|                 "sha256:c3d774f1d522579398ebfb5ad9129cc4a409c35a14f412e1ae20c0a7d42561f0", | ||||
|                 "sha256:c894990d87b0c8eae1f60a747c5180f9abcc525f1c71435cbdcb1f5ee420d675", | ||||
|                 "sha256:ca40c72a6c07ebd35a1b85d8cb3069b43587a589fe2ff2d16e33ea53b1ffe40f", | ||||
|                 "sha256:cf0e362917ca2c00627828fce077fe364b7e0f70e795fb98e97c8befe8f96289", | ||||
|                 "sha256:ea3dc427b6be0eb0966732e9e30bccec1c8b395aba0484430bc72d811a9e84ea", | ||||
|                 "sha256:f73970f8c4ccb2c32cf350f1b86171af27ed7df79dc0cc529875bc40610b6bbd", | ||||
|                 "sha256:fe5c2fcbe8f130c8913dad56d2513afb809491ad8a17b5c49b3951cfa070d4a3" | ||||
|                 "sha256:07fdd968df7941c2bfb67b9bb4532f424992dfafc71b72a4e4b291ff707e6b0e", | ||||
|                 "sha256:090ea99ff829d918f7b6140594373b1340a34e1e6876eddae5aa06662ec10d64", | ||||
|                 "sha256:109009b02fc225882ea766a5ed8be0ef473fa1356e252a3f651a6aa89b4a195f", | ||||
|                 "sha256:1dd0307b2b13b0482ac8314fd793fbbce263a428b189371addf0466784e1d597", | ||||
|                 "sha256:236a6483210049205f6180d7a7595d0ca2e4ce343d83cc94ca719a4145809c6f", | ||||
|                 "sha256:26c25ea4afa8b92a2c14f4edc41c8fc30505745ce84cae86538e80cacadd7ae2", | ||||
|                 "sha256:2a0bc7a1d64fe754b62e175ba0cf47a630b529c0488ec9ac4e4c7655e295ea4d", | ||||
|                 "sha256:2c9b0861d8f40d7a24b094b8834f6a489b9e8c70bceaa7fa98237eed229671ce", | ||||
|                 "sha256:39e92fa4ab2a8f0f2cc051d9c1e3acb881340c07ef59c0c8b627861343d653c0", | ||||
|                 "sha256:3a62e51a4a47616896bd0f1e9cc3fbfb174b713794a5031a34b84f69dbe01775", | ||||
|                 "sha256:3fd1ffdd5204301eb4c290a5752ac62f44d2d0b262e02e35a1e5234c13e14662", | ||||
|                 "sha256:498b4ec7e73426de64c6bf6ec03c5b3f10dedf5db8a9e13fdf195f95a3d065aa", | ||||
|                 "sha256:4c599645af9b5b2241a23e977a82c965a59c24cd94b2600b8d34373c66cad763", | ||||
|                 "sha256:4fa3cdf490f3828b055381e8c7dc7819b3e5f7a442d7af7a8f90e9806a7fff51", | ||||
|                 "sha256:55a070206580e161b6bbe1a96abf816c18d4c2c225d49916654714c93d842835", | ||||
|                 "sha256:666bdba4958b348460a765c48b8c0640e7085540846ed9494f47d8651604b33c", | ||||
|                 "sha256:69f41295d696c822224334f0994f1f107df7efed72211d45a1118696f1427c84", | ||||
|                 "sha256:6dfcf7bd6db5d80711cbbd0996b6e7a79cc414ca81457960367df11d2860f92a", | ||||
|                 "sha256:71cf73f9907c444ef663ea653dbac24af07c307079572c3ff8f20ad1463af3b7", | ||||
|                 "sha256:72ec333f089b4fce5a6d740ed0a1963a3994146be195722da0d8e14d4a7e1600", | ||||
|                 "sha256:759495c2b8c15cb0d6b539c246896029e4cde42a896c3956f77e311c5f6b0807", | ||||
|                 "sha256:7a7c3369fa618eca79f9554ce06c618a5e738e592d61d96aa09b2457ca3ea410", | ||||
|                 "sha256:8b1215facead57cc5325aef4229ef886e85d270b2ba02080fb5809ce9d2b81b4", | ||||
|                 "sha256:907f7cd4832bb295d0c1573de15cc5aab5988282caf2ee7a2b1276fb6cdf502b", | ||||
|                 "sha256:93e229519d046491b798f2c12dbbf2f3e237e89589aa5cbb5e1d8c1a978816db", | ||||
|                 "sha256:a12049314497d872f6788f811e2b331654db207937f8a2fb34ff3e3cd9897faa", | ||||
|                 "sha256:a8dddc52e0e486291be0ad39184da0607fae9cc665fdba1881211de9cfc0b332", | ||||
|                 "sha256:adf78ccb2defad5b6ecb2e2e9f2a672719b0a8e2278592a7d77f6c220a042388", | ||||
|                 "sha256:b13cebf4e397bba14542bcd023338b6ff2c151a3a12aabca89eecbf972cb361a", | ||||
|                 "sha256:b3648f3c340b6b6aabf9352341478c708cee6f00c5cd5c902311fcf4ce870f3c", | ||||
|                 "sha256:b6a1b685da0b9a8000bb980e02d9d5be202d0cc539af113b661c76c051fca6f1", | ||||
|                 "sha256:b777ddc57b2d3366cbc540616034cdc1089ca0a31fefc907028e1dd62a6bf16c", | ||||
|                 "sha256:bb83df8f7840321d34cb5b24c972c617a8c1716c8a36e5050fff56adf5891b8c", | ||||
|                 "sha256:c07ec796a2a5d44bf787f2b623b6e668a389b0cafb78af34cf74554ff3bc532b", | ||||
|                 "sha256:c40e108072379ff83dd7442159ebc249d12eb8eec15b70614953fecd2c403792", | ||||
|                 "sha256:c4863c49602722237e35cbce5aa91af4539cc63a671f59504d2b3f3767d898cf", | ||||
|                 "sha256:c56d701f7dc662e1d3d7fe364e66fa1339eafce54a488c2d16ec0ea49dc213c2", | ||||
|                 "sha256:c84afd5bef6e407c80ba9f99b6abbe3ea78e8243b0f19897a871a7bcad1f749d", | ||||
|                 "sha256:cdd206883e999278d2af656f988dfcc89eb0c175ce6d75e87b713cf1e792c0c4", | ||||
|                 "sha256:ce85a204f46c871c8af6fa64b9bbed165456935c1d0bfb2f570a3194f6723ddb", | ||||
|                 "sha256:cee3b6ebef5e4a8654ec5f0effeb1a2bb157ad87b0ac856871d25a805c0f2f90", | ||||
|                 "sha256:d4cecfb48a6cfbfe2caf0fc280cecea999699e63bc98cb02254bd87b39eff677", | ||||
|                 "sha256:db62bed0774778fdf82c609cb9efd0062f2fdcd285be527d01f6be9fd9755888", | ||||
|                 "sha256:f51dcb39e910a853749250c0f82aced80bca3f7315e9c4ee14349eb7cab6a3f8", | ||||
|                 "sha256:f5808e1dac6b66c109d6205ce2aebf84bb89e1a1493b7e6df38932df5ebfb9cf" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.7' and python_version < '4'", | ||||
|             "version": "==3.6.11" | ||||
|             "version": "==3.6.12" | ||||
|         }, | ||||
|         "requests": { | ||||
|             "hashes": [ | ||||
| @@ -1558,27 +1419,30 @@ | ||||
|         }, | ||||
|         "scikit-learn": { | ||||
|             "hashes": [ | ||||
|                 "sha256:1c8fecb7c9984d9ec2ea48898229f98aad681a0873e0935f2b7f724fbce4a047", | ||||
|                 "sha256:2b8db962360c93554cab7bb3c096c4a24695da394dd4b3c3f13409f409b425bc", | ||||
|                 "sha256:2f46c6e3ff1054a5ec701646dcfd61d43b8ecac4d416014daed8843cf4c33d4d", | ||||
|                 "sha256:3e7d1fc817867a350133f937aaebcafbc06192517cbdf0cf7e5774ad4d1adb9f", | ||||
|                 "sha256:407e9a1cb9e6ba458a539986a9bd25546a757088095b3aab91d465b79a760d37", | ||||
|                 "sha256:567417dbbe6a6278399c3e6daf1654414a5a1a4d818d28f251fa7fc28730a1bf", | ||||
|                 "sha256:589d46f28460469f444b898223b13d99db9463e1038dc581ba698111f612264b", | ||||
|                 "sha256:5ec3ea40d467966821843210c02117d82b097b54276fdcfb50f4dfb5c60dbe39", | ||||
|                 "sha256:6c840f662b5d3377c4ccb8be1fc21bb52cb5d8b8790f8d6bf021739f84e543cf", | ||||
|                 "sha256:76800652fb6d6bf527bce36ecc2cc25738b28fe1a17bd294a218fff8e8bd6d50", | ||||
|                 "sha256:7c22d1305b16f08d57751a4ea36071e2215efb4c09cb79183faa4e8e82a3dbf8", | ||||
|                 "sha256:a682ec0f82b6f30fb07486daed1c8001b6683cc66b51877644dfc532bece6a18", | ||||
|                 "sha256:a90ca42fe8242fd6ff56cda2fecc5fca586a88a24ab602d275d2d0dcc0b928fb", | ||||
|                 "sha256:b1e706deca9b2ad87ae27dafd5ac4e8eff01b6db492ed5c12cef4735ec5f21ea", | ||||
|                 "sha256:bbef6ea1c012ff9f3e6f6e9ca006b8772d8383e177b898091e68fbd9b3f840f9", | ||||
|                 "sha256:c33e16e9a165af6012f5be530ccfbb672e2bc5f9b840238a05eb7f6694304e3f", | ||||
|                 "sha256:d6f232779023c3b060b80b5c82e5823723bc424dcac1d1a148aa2492c54d245d", | ||||
|                 "sha256:f94c0146bad51daef919c402a3da8c1c6162619653e1c00c92baa168fda292f2" | ||||
|                 "sha256:23fb9e74b813cc2528b5167d82ed08950b11106ccf50297161875e45152fb311", | ||||
|                 "sha256:250da993701da88bf475e7c5746abf1285ea0ae47e4d0917cd13afd6600bb162", | ||||
|                 "sha256:28b2bd6a1419acd522ff45d282c8ba23dbccb5338802ab0ee12baa4ade0aba4c", | ||||
|                 "sha256:2ee2c649f2231b68511aabb0dc827edd8936aad682acc6263c34aed11bc95dac", | ||||
|                 "sha256:30e27721adc308e8fd9f419f43068e43490005f911edf4476a9e585059fa8a83", | ||||
|                 "sha256:38814f66285318f2e241305cca545eaa9b4126c65aa5dd78c69371f235f78e2b", | ||||
|                 "sha256:4d3a19166d4e1cdfcab975c68f471e046ce01e74c42a9a33fa89a14c2fcedf60", | ||||
|                 "sha256:5699cded6c0685426433c7e5afe0fecad80ec831ec7fa264940e50c796775cc5", | ||||
|                 "sha256:6785b8a3093329bf90ac01801be5525551728ae73edb11baa175df660820add4", | ||||
|                 "sha256:6d1c1394e38a3319ace620381f6f23cc807d8780e9915c152449a86fc8f1db21", | ||||
|                 "sha256:701181792a28c82fecae12adb5d15d0ecf57bffab7cf4bdbb52c7b3fd428d540", | ||||
|                 "sha256:748f2bd632d6993e8918d43f1a26c380aeda4e122a88840d4c3a9af99d4239fe", | ||||
|                 "sha256:8e9dd76c7274055d1acf4526b8efb16a3531c26dcda714a0c16da99bf9d41900", | ||||
|                 "sha256:bef51978a51ec19977700fe7b86aecea49c825884f3811756b74a3b152bb4e35", | ||||
|                 "sha256:cd55c6fbef7608dbce1f22baf289dfcc6eb323247daa3c3542f73d389c724786", | ||||
|                 "sha256:da5a2e95fef9805b1750e4abda4e834bf8835d26fc709a391543b53feee7bd0e", | ||||
|                 "sha256:ee47f68d973cee7009f06edb956f2f5588a0f230f24a2a70175fd0ecf36e2653", | ||||
|                 "sha256:f4931f2a6c06e02c6c17a05f8ae397e2545965bc7a0a6cb38c8cd7d4fba8624d", | ||||
|                 "sha256:f5644663987ee221f5d1f47a593271b966c271c236fe05634e6bdc06041b5a2b", | ||||
|                 "sha256:f5d4231af7199531e77da1b78a4cc6b3d960a00b1ec672578ac818aae2b9c35d", | ||||
|                 "sha256:fd3ee69d36d42a7dcbb17e355a5653af5fd241a7dfd9133080b3dde8d9e2aafb" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==1.1.2" | ||||
|             "version": "==1.1.3" | ||||
|         }, | ||||
|         "scipy": { | ||||
|             "hashes": [ | ||||
| @@ -1759,11 +1623,11 @@ | ||||
|                 "tls" | ||||
|             ], | ||||
|             "hashes": [ | ||||
|                 "sha256:8d4718d1e48dcc28933f8beb48dc71cfe77a125e37ad1eb7a3d0acc49baf6c99", | ||||
|                 "sha256:e5b60de39f2d1da153fbe1874d885fe3fcbdb21fcc446fa759a53e8fc3513bed" | ||||
|                 "sha256:32acbd40a94f5f46e7b42c109bfae2b302250945561783a8b7a059048f2d4d31", | ||||
|                 "sha256:86c55f712cc5ab6f6d64e02503352464f0400f66d4f079096d744080afcccbd0" | ||||
|             ], | ||||
|             "markers": "python_full_version >= '3.7.1'", | ||||
|             "version": "==22.8.0" | ||||
|             "version": "==22.10.0" | ||||
|         }, | ||||
|         "txaio": { | ||||
|             "hashes": [ | ||||
| @@ -1778,16 +1642,16 @@ | ||||
|                 "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", | ||||
|                 "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" | ||||
|             ], | ||||
|             "markers": "python_version < '3.10'", | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==4.4.0" | ||||
|         }, | ||||
|         "tzdata": { | ||||
|             "hashes": [ | ||||
|                 "sha256:323161b22b7802fdc78f20ca5f6073639c64f1a7227c40cd3e19fd1d0ce6650a", | ||||
|                 "sha256:e15b2b3005e2546108af42a0eb4ccab4d9e225e2dfbf4f77aad50c70a4b1f3ab" | ||||
|                 "sha256:04a680bdc5b15750c39c12a448885a51134a27ec9af83667663f0b3a1bf3f342", | ||||
|                 "sha256:91f11db4503385928c15598c98573e3af07e7229181bee5375bd30f1695ddcae" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==2022.5" | ||||
|             "version": "==2022.6" | ||||
|         }, | ||||
|         "tzlocal": { | ||||
|             "hashes": [ | ||||
| @@ -1920,65 +1784,79 @@ | ||||
|             ], | ||||
|             "version": "==0.2.5" | ||||
|         }, | ||||
|         "webencodings": { | ||||
|             "hashes": [ | ||||
|                 "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", | ||||
|                 "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" | ||||
|             ], | ||||
|             "version": "==0.5.1" | ||||
|         }, | ||||
|         "websockets": { | ||||
|             "hashes": [ | ||||
|                 "sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af", | ||||
|                 "sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c", | ||||
|                 "sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76", | ||||
|                 "sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47", | ||||
|                 "sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69", | ||||
|                 "sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079", | ||||
|                 "sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c", | ||||
|                 "sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55", | ||||
|                 "sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02", | ||||
|                 "sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559", | ||||
|                 "sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3", | ||||
|                 "sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e", | ||||
|                 "sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978", | ||||
|                 "sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98", | ||||
|                 "sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae", | ||||
|                 "sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755", | ||||
|                 "sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d", | ||||
|                 "sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991", | ||||
|                 "sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1", | ||||
|                 "sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680", | ||||
|                 "sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247", | ||||
|                 "sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f", | ||||
|                 "sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2", | ||||
|                 "sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7", | ||||
|                 "sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4", | ||||
|                 "sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667", | ||||
|                 "sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb", | ||||
|                 "sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094", | ||||
|                 "sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36", | ||||
|                 "sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79", | ||||
|                 "sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500", | ||||
|                 "sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e", | ||||
|                 "sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582", | ||||
|                 "sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442", | ||||
|                 "sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd", | ||||
|                 "sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6", | ||||
|                 "sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731", | ||||
|                 "sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4", | ||||
|                 "sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d", | ||||
|                 "sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8", | ||||
|                 "sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f", | ||||
|                 "sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677", | ||||
|                 "sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8", | ||||
|                 "sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9", | ||||
|                 "sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e", | ||||
|                 "sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b", | ||||
|                 "sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916", | ||||
|                 "sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4" | ||||
|                 "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41", | ||||
|                 "sha256:00c870522cdb69cd625b93f002961ffb0c095394f06ba8c48f17eef7c1541f96", | ||||
|                 "sha256:0154f7691e4fe6c2b2bc275b5701e8b158dae92a1ab229e2b940efe11905dff4", | ||||
|                 "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72", | ||||
|                 "sha256:09a1814bb15eff7069e51fed0826df0bc0702652b5cb8f87697d469d79c23576", | ||||
|                 "sha256:0cff816f51fb33c26d6e2b16b5c7d48eaa31dae5488ace6aae468b361f422b63", | ||||
|                 "sha256:185929b4808b36a79c65b7865783b87b6841e852ef5407a2fb0c03381092fa3b", | ||||
|                 "sha256:2fc8709c00704194213d45e455adc106ff9e87658297f72d544220e32029cd3d", | ||||
|                 "sha256:33d69ca7612f0ddff3316b0c7b33ca180d464ecac2d115805c044bf0a3b0d032", | ||||
|                 "sha256:389f8dbb5c489e305fb113ca1b6bdcdaa130923f77485db5b189de343a179393", | ||||
|                 "sha256:38ea7b82bfcae927eeffc55d2ffa31665dc7fec7b8dc654506b8e5a518eb4d50", | ||||
|                 "sha256:3d3cac3e32b2c8414f4f87c1b2ab686fa6284a980ba283617404377cd448f631", | ||||
|                 "sha256:40e826de3085721dabc7cf9bfd41682dadc02286d8cf149b3ad05bff89311e4f", | ||||
|                 "sha256:4239b6027e3d66a89446908ff3027d2737afc1a375f8fd3eea630a4842ec9a0c", | ||||
|                 "sha256:45ec8e75b7dbc9539cbfafa570742fe4f676eb8b0d3694b67dabe2f2ceed8aa6", | ||||
|                 "sha256:47a2964021f2110116cc1125b3e6d87ab5ad16dea161949e7244ec583b905bb4", | ||||
|                 "sha256:48c08473563323f9c9debac781ecf66f94ad5a3680a38fe84dee5388cf5acaf6", | ||||
|                 "sha256:4c6d2264f485f0b53adf22697ac11e261ce84805c232ed5dbe6b1bcb84b00ff0", | ||||
|                 "sha256:4f72e5cd0f18f262f5da20efa9e241699e0cf3a766317a17392550c9ad7b37d8", | ||||
|                 "sha256:56029457f219ade1f2fc12a6504ea61e14ee227a815531f9738e41203a429112", | ||||
|                 "sha256:5c1289596042fad2cdceb05e1ebf7aadf9995c928e0da2b7a4e99494953b1b94", | ||||
|                 "sha256:62e627f6b6d4aed919a2052efc408da7a545c606268d5ab5bfab4432734b82b4", | ||||
|                 "sha256:74de2b894b47f1d21cbd0b37a5e2b2392ad95d17ae983e64727e18eb281fe7cb", | ||||
|                 "sha256:7c584f366f46ba667cfa66020344886cf47088e79c9b9d39c84ce9ea98aaa331", | ||||
|                 "sha256:7d27a7e34c313b3a7f91adcd05134315002aaf8540d7b4f90336beafaea6217c", | ||||
|                 "sha256:7d3f0b61c45c3fa9a349cf484962c559a8a1d80dae6977276df8fd1fa5e3cb8c", | ||||
|                 "sha256:82ff5e1cae4e855147fd57a2863376ed7454134c2bf49ec604dfe71e446e2193", | ||||
|                 "sha256:84bc2a7d075f32f6ed98652db3a680a17a4edb21ca7f80fe42e38753a58ee02b", | ||||
|                 "sha256:884be66c76a444c59f801ac13f40c76f176f1bfa815ef5b8ed44321e74f1600b", | ||||
|                 "sha256:8a5cc00546e0a701da4639aa0bbcb0ae2bb678c87f46da01ac2d789e1f2d2038", | ||||
|                 "sha256:8dc96f64ae43dde92530775e9cb169979f414dcf5cff670455d81a6823b42089", | ||||
|                 "sha256:8f38706e0b15d3c20ef6259fd4bc1700cd133b06c3c1bb108ffe3f8947be15fa", | ||||
|                 "sha256:90fcf8929836d4a0e964d799a58823547df5a5e9afa83081761630553be731f9", | ||||
|                 "sha256:931c039af54fc195fe6ad536fde4b0de04da9d5916e78e55405436348cfb0e56", | ||||
|                 "sha256:932af322458da7e4e35df32f050389e13d3d96b09d274b22a7aa1808f292fee4", | ||||
|                 "sha256:942de28af58f352a6f588bc72490ae0f4ccd6dfc2bd3de5945b882a078e4e179", | ||||
|                 "sha256:9bc42e8402dc5e9905fb8b9649f57efcb2056693b7e88faa8fb029256ba9c68c", | ||||
|                 "sha256:a7a240d7a74bf8d5cb3bfe6be7f21697a28ec4b1a437607bae08ac7acf5b4882", | ||||
|                 "sha256:a9f9a735deaf9a0cadc2d8c50d1a5bcdbae8b6e539c6e08237bc4082d7c13f28", | ||||
|                 "sha256:ae5e95cfb53ab1da62185e23b3130e11d64431179debac6dc3c6acf08760e9b1", | ||||
|                 "sha256:b029fb2032ae4724d8ae8d4f6b363f2cc39e4c7b12454df8df7f0f563ed3e61a", | ||||
|                 "sha256:b0d15c968ea7a65211e084f523151dbf8ae44634de03c801b8bd070b74e85033", | ||||
|                 "sha256:b343f521b047493dc4022dd338fc6db9d9282658862756b4f6fd0e996c1380e1", | ||||
|                 "sha256:b627c266f295de9dea86bd1112ed3d5fafb69a348af30a2422e16590a8ecba13", | ||||
|                 "sha256:b9968694c5f467bf67ef97ae7ad4d56d14be2751000c1207d31bf3bb8860bae8", | ||||
|                 "sha256:ba089c499e1f4155d2a3c2a05d2878a3428cf321c848f2b5a45ce55f0d7d310c", | ||||
|                 "sha256:bbccd847aa0c3a69b5f691a84d2341a4f8a629c6922558f2a70611305f902d74", | ||||
|                 "sha256:bc0b82d728fe21a0d03e65f81980abbbcb13b5387f733a1a870672c5be26edab", | ||||
|                 "sha256:c57e4c1349fbe0e446c9fa7b19ed2f8a4417233b6984277cce392819123142d3", | ||||
|                 "sha256:c94ae4faf2d09f7c81847c63843f84fe47bf6253c9d60b20f25edfd30fb12588", | ||||
|                 "sha256:c9b27d6c1c6cd53dc93614967e9ce00ae7f864a2d9f99fe5ed86706e1ecbf485", | ||||
|                 "sha256:d210abe51b5da0ffdbf7b43eed0cfdff8a55a1ab17abbec4301c9ff077dd0342", | ||||
|                 "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48", | ||||
|                 "sha256:d6a4162139374a49eb18ef5b2f4da1dd95c994588f5033d64e0bbfda4b6b6fcf", | ||||
|                 "sha256:da39dd03d130162deb63da51f6e66ed73032ae62e74aaccc4236e30edccddbb0", | ||||
|                 "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a", | ||||
|                 "sha256:dd500e0a5e11969cdd3320935ca2ff1e936f2358f9c2e61f100a1660933320ea", | ||||
|                 "sha256:dd9becd5fe29773d140d68d607d66a38f60e31b86df75332703757ee645b6faf", | ||||
|                 "sha256:e0cb5cc6ece6ffa75baccfd5c02cffe776f3f5c8bf486811f9d3ea3453676ce8", | ||||
|                 "sha256:e23173580d740bf8822fd0379e4bf30aa1d5a92a4f252d34e893070c081050df", | ||||
|                 "sha256:e3a686ecb4aa0d64ae60c9c9f1a7d5d46cab9bfb5d91a2d303d00e2cd4c4c5cc", | ||||
|                 "sha256:e789376b52c295c4946403bd0efecf27ab98f05319df4583d3c48e43c7342c2f", | ||||
|                 "sha256:edc344de4dac1d89300a053ac973299e82d3db56330f3494905643bb68801269", | ||||
|                 "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3", | ||||
|                 "sha256:f2c38d588887a609191d30e902df2a32711f708abfd85d318ca9b367258cfd0c", | ||||
|                 "sha256:f55b5905705725af31ccef50e55391621532cd64fbf0bc6f4bac935f0fccec46", | ||||
|                 "sha256:f5fc088b7a32f244c519a048c170f14cf2251b849ef0e20cbbb0fdf0fdaf556f", | ||||
|                 "sha256:fe10ddc59b304cb19a1bdf5bd0a7719cbbc9fbdd57ac80ed436b709fcf889106", | ||||
|                 "sha256:ff64a1d38d156d429404aaa84b27305e957fd10c30e5880d1765c9480bea490f" | ||||
|             ], | ||||
|             "version": "==10.3" | ||||
|             "version": "==10.4" | ||||
|         }, | ||||
|         "whitenoise": { | ||||
|             "hashes": [ | ||||
| @@ -2137,11 +2015,11 @@ | ||||
|         }, | ||||
|         "babel": { | ||||
|             "hashes": [ | ||||
|                 "sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51", | ||||
|                 "sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb" | ||||
|                 "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe", | ||||
|                 "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==2.10.3" | ||||
|             "version": "==2.11.0" | ||||
|         }, | ||||
|         "black": { | ||||
|             "hashes": [ | ||||
| @@ -2204,11 +2082,11 @@ | ||||
|         }, | ||||
|         "colorama": { | ||||
|             "hashes": [ | ||||
|                 "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da", | ||||
|                 "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4" | ||||
|                 "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", | ||||
|                 "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" | ||||
|             ], | ||||
|             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", | ||||
|             "version": "==0.4.5" | ||||
|             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", | ||||
|             "version": "==0.4.6" | ||||
|         }, | ||||
|         "coverage": { | ||||
|             "extras": [ | ||||
| @@ -2298,6 +2176,14 @@ | ||||
|             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", | ||||
|             "version": "==0.17.1" | ||||
|         }, | ||||
|         "exceptiongroup": { | ||||
|             "hashes": [ | ||||
|                 "sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41", | ||||
|                 "sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad" | ||||
|             ], | ||||
|             "markers": "python_version < '3.11'", | ||||
|             "version": "==1.0.0" | ||||
|         }, | ||||
|         "execnet": { | ||||
|             "hashes": [ | ||||
|                 "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5", | ||||
| @@ -2332,11 +2218,11 @@ | ||||
|         }, | ||||
|         "identify": { | ||||
|             "hashes": [ | ||||
|                 "sha256:6c32dbd747aa4ceee1df33f25fed0b0f6e0d65721b15bd151307ff7056d50245", | ||||
|                 "sha256:b276db7ec52d7e89f5bc4653380e33054ddc803d25875952ad90b0f012cbcdaa" | ||||
|                 "sha256:48b7925fe122720088aeb7a6c34f17b27e706b72c61070f27fe3789094233440", | ||||
|                 "sha256:7a214a10313b9489a0d61467db2856ae8d0b8306fc923e03a9effa53d8aedc58" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==2.5.6" | ||||
|             "version": "==2.5.8" | ||||
|         }, | ||||
|         "idna": { | ||||
|             "hashes": [ | ||||
| @@ -2354,14 +2240,6 @@ | ||||
|             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", | ||||
|             "version": "==1.4.1" | ||||
|         }, | ||||
|         "importlib-metadata": { | ||||
|             "hashes": [ | ||||
|                 "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab", | ||||
|                 "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43" | ||||
|             ], | ||||
|             "markers": "python_version < '3.10'", | ||||
|             "version": "==5.0.0" | ||||
|         }, | ||||
|         "iniconfig": { | ||||
|             "hashes": [ | ||||
|                 "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", | ||||
| @@ -2550,11 +2428,11 @@ | ||||
|         }, | ||||
|         "pytest": { | ||||
|             "hashes": [ | ||||
|                 "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7", | ||||
|                 "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39" | ||||
|                 "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71", | ||||
|                 "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==7.1.3" | ||||
|             "version": "==7.2.0" | ||||
|         }, | ||||
|         "pytest-cov": { | ||||
|             "hashes": [ | ||||
| @@ -2614,10 +2492,10 @@ | ||||
|         }, | ||||
|         "pytz": { | ||||
|             "hashes": [ | ||||
|                 "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22", | ||||
|                 "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914" | ||||
|                 "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427", | ||||
|                 "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2" | ||||
|             ], | ||||
|             "version": "==2022.5" | ||||
|             "version": "==2022.6" | ||||
|         }, | ||||
|         "pyyaml": { | ||||
|             "hashes": [ | ||||
| @@ -2769,11 +2647,11 @@ | ||||
|         }, | ||||
|         "termcolor": { | ||||
|             "hashes": [ | ||||
|                 "sha256:6b2cf769e93364a2676e1de56a7c0cff2cf5bd07f37e9cc80b0dd6320ebfe388", | ||||
|                 "sha256:7e597f9de8e001a3208c4132938597413b9da45382b6f1d150cff8d062b7aaa3" | ||||
|                 "sha256:91dd04fdf661b89d7169cefd35f609b19ca931eb033687eaa647cef1ff177c49", | ||||
|                 "sha256:b80df54667ce4f48c03fe35df194f052dc27a541ebbf2544e4d6b47b5d6949c4" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==2.0.1" | ||||
|             "version": "==2.1.0" | ||||
|         }, | ||||
|         "toml": { | ||||
|             "hashes": [ | ||||
| @@ -2788,7 +2666,7 @@ | ||||
|                 "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", | ||||
|                 "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "markers": "python_version < '3.11'", | ||||
|             "version": "==2.0.1" | ||||
|         }, | ||||
|         "tornado": { | ||||
| @@ -2810,18 +2688,18 @@ | ||||
|         }, | ||||
|         "tox": { | ||||
|             "hashes": [ | ||||
|                 "sha256:44f3c347c68c2c68799d7d44f1808f9d396fc8a1a500cbc624253375c7ae107e", | ||||
|                 "sha256:bf037662d7c740d15c9924ba23bb3e587df20598697bb985ac2b49bdc2d847f6" | ||||
|                 "sha256:89e4bc6df3854e9fc5582462e328dd3660d7d865ba625ae5881bbc63836a6324", | ||||
|                 "sha256:d2c945f02a03d4501374a3d5430877380deb69b218b1df9b7f1d2f2a10befaf9" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==3.26.0" | ||||
|             "version": "==3.27.0" | ||||
|         }, | ||||
|         "typing-extensions": { | ||||
|             "hashes": [ | ||||
|                 "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", | ||||
|                 "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" | ||||
|             ], | ||||
|             "markers": "python_version < '3.10'", | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==4.4.0" | ||||
|         }, | ||||
|         "urllib3": { | ||||
| @@ -2834,19 +2712,11 @@ | ||||
|         }, | ||||
|         "virtualenv": { | ||||
|             "hashes": [ | ||||
|                 "sha256:227ea1b9994fdc5ea31977ba3383ef296d7472ea85be9d6732e42a91c04e80da", | ||||
|                 "sha256:d07dfc5df5e4e0dbc92862350ad87a36ed505b978f6c39609dc489eadd5b0d27" | ||||
|                 "sha256:186ca84254abcbde98180fd17092f9628c5fe742273c02724972a1d8a2035108", | ||||
|                 "sha256:530b850b523c6449406dfba859d6345e48ef19b8439606c5d74d7d3c9e14d76e" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==20.16.5" | ||||
|         }, | ||||
|         "zipp": { | ||||
|             "hashes": [ | ||||
|                 "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1", | ||||
|                 "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8" | ||||
|             ], | ||||
|             "markers": "python_version < '3.9'", | ||||
|             "version": "==3.10.0" | ||||
|             "version": "==20.16.6" | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -23,6 +23,8 @@ fi | ||||
| # Parse what we can from Pipfile.lock | ||||
| pikepdf_version=$(jq ".default.pikepdf.version" Pipfile.lock  | sed 's/=//g' | sed 's/"//g') | ||||
| psycopg2_version=$(jq ".default.psycopg2.version" Pipfile.lock | sed 's/=//g' | sed 's/"//g') | ||||
| pillow_version=$(jq ".default.pillow.version" Pipfile.lock | sed 's/=//g' | sed 's/"//g') | ||||
| lxml_version=$(jq ".default.lxml.version" Pipfile.lock | sed 's/=//g' | 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') | ||||
| @@ -40,4 +42,6 @@ docker build --file "$1" \ | ||||
| 	--build-arg JBIG2ENC_VERSION="${jbig2enc_version}" \ | ||||
| 	--build-arg QPDF_VERSION="${qpdf_version}" \ | ||||
| 	--build-arg PIKEPDF_VERSION="${pikepdf_version}" \ | ||||
| 	--build-arg PILLOW_VERSION="${pillow_version}" \ | ||||
| 	--build-arg LXML_VERSION="${lxml_version}" \ | ||||
| 	--build-arg PSYCOPG2_VERSION="${psycopg2_version}" "${@:2}" . | ||||
|   | ||||
| @@ -1,14 +0,0 @@ | ||||
| # This Dockerfile compiles the frontend | ||||
| # Inputs: None | ||||
|  | ||||
| FROM node:16-bullseye-slim AS compile-frontend | ||||
|  | ||||
| COPY ./src /src/src | ||||
| COPY ./src-ui /src/src-ui | ||||
|  | ||||
| WORKDIR /src/src-ui | ||||
| RUN set -eux \ | ||||
|   && npm update npm -g \ | ||||
|   && npm ci --omit=optional | ||||
| RUN set -eux \ | ||||
|   && ./node_modules/.bin/ng build --configuration production | ||||
| @@ -18,6 +18,10 @@ LABEL org.opencontainers.image.description="A intermediate image with pikepdf wh | ||||
|  | ||||
| ARG DEBIAN_FRONTEND=noninteractive | ||||
| ARG PIKEPDF_VERSION | ||||
| # These are not used, but will still bust the cache if one changes | ||||
| # Otherwise, the main image will try to build thing (and fail) | ||||
| ARG PILLOW_VERSION | ||||
| ARG LXML_VERSION | ||||
|  | ||||
| ARG BUILD_PACKAGES="\ | ||||
|   build-essential \ | ||||
|   | ||||
| @@ -258,12 +258,18 @@ Paperless provides the following placeholders within filenames: | ||||
| * ``{tag_list}``: A comma separated list of all tags assigned to the document. | ||||
| * ``{title}``: The title of the document. | ||||
| * ``{created}``: The full date (ISO format) the document was created. | ||||
| * ``{created_year}``: Year created only. | ||||
| * ``{created_year}``: Year created only, formatted as the year with century. | ||||
| * ``{created_year_short}``: Year created only, formatted as the year without century, zero padded. | ||||
| * ``{created_month}``: Month created only (number 01-12). | ||||
| * ``{created_month_name}``: Month created name, as per locale | ||||
| * ``{created_month_name_short}``: Month created abbreviated name, as per locale | ||||
| * ``{created_day}``: Day created only (number 01-31). | ||||
| * ``{added}``: The full date (ISO format) the document was added to paperless. | ||||
| * ``{added_year}``: Year added only. | ||||
| * ``{added_year_short}``: Year added only, formatted as the year without century, zero padded. | ||||
| * ``{added_month}``: Month added only (number 01-12). | ||||
| * ``{added_month_name}``: Month added name, as per locale | ||||
| * ``{added_month_name_short}``: Month added abbreviated name, as per locale | ||||
| * ``{added_day}``: Day added only (number 01-31). | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -464,7 +464,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context> | ||||
|           <context context-type="linenumber">65</context> | ||||
|           <context context-type="linenumber">88</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context> | ||||
| @@ -727,14 +727,14 @@ | ||||
|         <source>Confirmation</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/confirm-dialog/confirm-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">17</context> | ||||
|           <context context-type="linenumber">20</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="9178182467454450952" datatype="html"> | ||||
|         <source>Confirm</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/confirm-dialog/confirm-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">29</context> | ||||
|           <context context-type="linenumber">32</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> | ||||
| @@ -757,53 +757,53 @@ | ||||
|         <source>After</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/date-dropdown/date-dropdown.component.html</context> | ||||
|           <context context-type="linenumber">13</context> | ||||
|           <context context-type="linenumber">21</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8700121026680200191" datatype="html"> | ||||
|         <source>Clear</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/date-dropdown/date-dropdown.component.html</context> | ||||
|           <context context-type="linenumber">18</context> | ||||
|           <context context-type="linenumber">26</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/date-dropdown/date-dropdown.component.html</context> | ||||
|           <context context-type="linenumber">41</context> | ||||
|           <context context-type="linenumber">49</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1218334388194408974" datatype="html"> | ||||
|         <source>Before</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/date-dropdown/date-dropdown.component.html</context> | ||||
|           <context context-type="linenumber">36</context> | ||||
|           <context context-type="linenumber">44</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4873149362496451858" datatype="html"> | ||||
|         <source>Last 7 days</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/date-dropdown/date-dropdown.component.ts</context> | ||||
|           <context context-type="linenumber">38</context> | ||||
|           <context context-type="linenumber">43</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4463380307954693363" datatype="html"> | ||||
|         <source>Last month</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/date-dropdown/date-dropdown.component.ts</context> | ||||
|           <context context-type="linenumber">39</context> | ||||
|           <context context-type="linenumber">47</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8697368973702409683" datatype="html"> | ||||
|         <source>Last 3 months</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/date-dropdown/date-dropdown.component.ts</context> | ||||
|           <context context-type="linenumber">40</context> | ||||
|           <context context-type="linenumber">51</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3566342898065860218" datatype="html"> | ||||
|         <source>Last year</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/date-dropdown/date-dropdown.component.ts</context> | ||||
|           <context context-type="linenumber">41</context> | ||||
|           <context context-type="linenumber">55</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8953033926734869941" datatype="html"> | ||||
| @@ -1240,7 +1240,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">88</context> | ||||
|           <context context-type="linenumber">93</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/tasks/tasks.component.html</context> | ||||
| @@ -1284,7 +1284,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">152</context> | ||||
|           <context context-type="linenumber">157</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> | ||||
| @@ -1311,11 +1311,11 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">134</context> | ||||
|           <context context-type="linenumber">139</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">131</context> | ||||
|           <context context-type="linenumber">153</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/services/rest/document.service.ts</context> | ||||
| @@ -1609,6 +1609,10 @@ | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">43</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context> | ||||
|           <context context-type="linenumber">32</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4452427314943113135" datatype="html"> | ||||
|         <source>Previous</source> | ||||
| @@ -1657,7 +1661,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">128</context> | ||||
|           <context context-type="linenumber">133</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> | ||||
| @@ -1680,7 +1684,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">140</context> | ||||
|           <context context-type="linenumber">145</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> | ||||
| @@ -1703,7 +1707,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">146</context> | ||||
|           <context context-type="linenumber">151</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> | ||||
| @@ -2235,7 +2239,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">173</context> | ||||
|           <context context-type="linenumber">178</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2784168796433474565" datatype="html"> | ||||
| @@ -2246,7 +2250,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">178</context> | ||||
|           <context context-type="linenumber">183</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7585826646011739428" datatype="html"> | ||||
| @@ -2307,7 +2311,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">182</context> | ||||
|           <context context-type="linenumber">187</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="157572966557284263" datatype="html"> | ||||
| @@ -2318,7 +2322,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">187</context> | ||||
|           <context context-type="linenumber">192</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3727324658595204357" datatype="html"> | ||||
| @@ -2421,60 +2425,60 @@ | ||||
|         <source>Views</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">63</context> | ||||
|           <context context-type="linenumber">64</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1233494216161906927" datatype="html"> | ||||
|         <source>Save "<x id="INTERPOLATION" equiv-text="{{list.activeSavedViewTitle}}"/>"</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">70</context> | ||||
|           <context context-type="linenumber">75</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2276119452079372898" datatype="html"> | ||||
|         <source>Save as...</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">71</context> | ||||
|           <context context-type="linenumber">76</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8786996283897742947" datatype="html"> | ||||
|         <source>{VAR_PLURAL, plural, =1 {Selected <x id="INTERPOLATION"/> of one document} other {Selected <x id="INTERPOLATION"/> of <x id="INTERPOLATION_1"/> documents}}</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">90</context> | ||||
|           <context context-type="linenumber">95</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6600548268163632449" datatype="html"> | ||||
|         <source>{VAR_PLURAL, plural, =1 {One document} other {<x id="INTERPOLATION"/> documents}}</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">92</context> | ||||
|           <context context-type="linenumber">97</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2243770355958919528" datatype="html"> | ||||
|         <source>(filtered)</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">92</context> | ||||
|           <context context-type="linenumber">97</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1559883523769732271" datatype="html"> | ||||
|         <source>Error while loading documents</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">105</context> | ||||
|           <context context-type="linenumber">110</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7517688192215738656" datatype="html"> | ||||
|         <source>ASN</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">122</context> | ||||
|           <context context-type="linenumber">127</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">136</context> | ||||
|           <context context-type="linenumber">158</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/services/rest/document.service.ts</context> | ||||
| @@ -2485,11 +2489,11 @@ | ||||
|         <source>Added</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">158</context> | ||||
|           <context context-type="linenumber">163</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> | ||||
|           <context context-type="linenumber">61</context> | ||||
|           <context context-type="linenumber">60</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/services/rest/document.service.ts</context> | ||||
| @@ -2500,140 +2504,140 @@ | ||||
|         <source>Edit document</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">177</context> | ||||
|           <context context-type="linenumber">182</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2155249406916744630" datatype="html"> | ||||
|         <source>View "<x id="PH" equiv-text="this.list.activeSavedViewTitle"/>" saved successfully.</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context> | ||||
|           <context context-type="linenumber">170</context> | ||||
|           <context context-type="linenumber">196</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6837554170707123455" datatype="html"> | ||||
|         <source>View "<x id="PH" equiv-text="savedView.name"/>" created successfully.</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context> | ||||
|           <context context-type="linenumber">210</context> | ||||
|           <context context-type="linenumber">237</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6849725902312323996" datatype="html"> | ||||
|         <source>Reset filters</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context> | ||||
|           <context context-type="linenumber">71</context> | ||||
|           <context context-type="linenumber">73</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5195932016807797291" datatype="html"> | ||||
|         <source>Correspondent: <x id="PH" equiv-text="this.correspondents.find((c) => c.id == +rule.value)?.name"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">72,74</context> | ||||
|           <context context-type="linenumber">94,96</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8170755470576301659" datatype="html"> | ||||
|         <source>Without correspondent</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">76</context> | ||||
|           <context context-type="linenumber">98</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8705701325879965907" datatype="html"> | ||||
|         <source>Type: <x id="PH" equiv-text="this.documentTypes.find((dt) => dt.id == +rule.value)?.name"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">81,83</context> | ||||
|           <context context-type="linenumber">103,105</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4362173610367509215" datatype="html"> | ||||
|         <source>Without document type</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">85</context> | ||||
|           <context context-type="linenumber">107</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8180755793012580465" datatype="html"> | ||||
|         <source>Tag: <x id="PH" equiv-text="this.tags.find((t) => t.id == +rule.value)?.name"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">89,91</context> | ||||
|           <context context-type="linenumber">111,113</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6494566478302448576" datatype="html"> | ||||
|         <source>Without any tag</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">95</context> | ||||
|           <context context-type="linenumber">117</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6523384805359286307" datatype="html"> | ||||
|         <source>Title: <x id="PH" equiv-text="rule.value"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">99</context> | ||||
|           <context context-type="linenumber">121</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1872523635812236432" datatype="html"> | ||||
|         <source>ASN: <x id="PH" equiv-text="rule.value"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">102</context> | ||||
|           <context context-type="linenumber">124</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3100631071441658964" datatype="html"> | ||||
|         <source>Title & content</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">134</context> | ||||
|           <context context-type="linenumber">156</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1010505078885609376" datatype="html"> | ||||
|         <source>Advanced search</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">139</context> | ||||
|           <context context-type="linenumber">161</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2649431021108393503" datatype="html"> | ||||
|         <source>More like</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">145</context> | ||||
|           <context context-type="linenumber">167</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3697582909018473071" datatype="html"> | ||||
|         <source>equals</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">164</context> | ||||
|           <context context-type="linenumber">186</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5325481293405718739" datatype="html"> | ||||
|         <source>is empty</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">168</context> | ||||
|           <context context-type="linenumber">190</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6166785695326182482" datatype="html"> | ||||
|         <source>is not empty</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">172</context> | ||||
|           <context context-type="linenumber">194</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4686622206659266699" datatype="html"> | ||||
|         <source>greater than</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">176</context> | ||||
|           <context context-type="linenumber">198</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8014012170270529279" datatype="html"> | ||||
|         <source>less than</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context> | ||||
|           <context context-type="linenumber">180</context> | ||||
|           <context context-type="linenumber">202</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7210076240260527720" datatype="html"> | ||||
| @@ -3473,6 +3477,10 @@ | ||||
|           <context context-type="sourcefile">src/app/guards/dirty-form.guard.ts</context> | ||||
|           <context context-type="linenumber">18</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context> | ||||
|           <context context-type="linenumber">24</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/services/open-documents.service.ts</context> | ||||
|           <context context-type="linenumber">116</context> | ||||
| @@ -3507,6 +3515,27 @@ | ||||
|           <context context-type="linenumber">22</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1649285023712919370" datatype="html"> | ||||
|         <source>You have unsaved changes to the saved view</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context> | ||||
|           <context context-type="linenumber">26</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7282050913165342352" datatype="html"> | ||||
|         <source>Are you sure you want to close this saved view?</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context> | ||||
|           <context context-type="linenumber">30</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="856284624775342512" datatype="html"> | ||||
|         <source>Save and close</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context> | ||||
|           <context context-type="linenumber">34</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7536524521722799066" datatype="html"> | ||||
|         <source>(no title)</source> | ||||
|         <context-group purpose="location"> | ||||
|   | ||||
							
								
								
									
										624
									
								
								src-ui/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										624
									
								
								src-ui/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -13,14 +13,14 @@ | ||||
|   }, | ||||
|   "private": true, | ||||
|   "dependencies": { | ||||
|     "@angular/common": "~14.2.4", | ||||
|     "@angular/compiler": "~14.2.4", | ||||
|     "@angular/core": "~14.2.4", | ||||
|     "@angular/forms": "~14.2.4", | ||||
|     "@angular/localize": "~14.2.4", | ||||
|     "@angular/platform-browser": "~14.2.4", | ||||
|     "@angular/platform-browser-dynamic": "~14.2.4", | ||||
|     "@angular/router": "~14.2.4", | ||||
|     "@angular/common": "~14.2.8", | ||||
|     "@angular/compiler": "~14.2.8", | ||||
|     "@angular/core": "~14.2.8", | ||||
|     "@angular/forms": "~14.2.8", | ||||
|     "@angular/localize": "~14.2.8", | ||||
|     "@angular/platform-browser": "~14.2.8", | ||||
|     "@angular/platform-browser-dynamic": "~14.2.8", | ||||
|     "@angular/router": "~14.2.8", | ||||
|     "@ng-bootstrap/ng-bootstrap": "^13.0.0", | ||||
|     "@ng-select/ng-select": "^9.0.2", | ||||
|     "@ngneat/dirty-check-forms": "^3.0.2", | ||||
| @@ -31,7 +31,7 @@ | ||||
|     "ngx-color": "^8.0.3", | ||||
|     "ngx-cookie-service": "^14.0.1", | ||||
|     "ngx-file-drop": "^14.0.1", | ||||
|     "ngx-ui-tour-ng-bootstrap": "^11.0.0", | ||||
|     "ngx-ui-tour-ng-bootstrap": "^11.1.0", | ||||
|     "rxjs": "~7.5.7", | ||||
|     "tslib": "^2.3.1", | ||||
|     "uuid": "^9.0.0", | ||||
| @@ -39,15 +39,15 @@ | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@angular-builders/jest": "14.0.1", | ||||
|     "@angular-devkit/build-angular": "~14.2.4", | ||||
|     "@angular/cli": "~14.2.4", | ||||
|     "@angular/compiler-cli": "~14.2.4", | ||||
|     "@angular-devkit/build-angular": "~14.2.7", | ||||
|     "@angular/cli": "~14.2.7", | ||||
|     "@angular/compiler-cli": "~14.2.8", | ||||
|     "@types/jest": "28.1.6", | ||||
|     "@types/node": "^18.7.23", | ||||
|     "codelyzer": "^6.0.2", | ||||
|     "concurrently": "7.4.0", | ||||
|     "jest": "28.1.3", | ||||
|     "jest-environment-jsdom": "^29.1.2", | ||||
|     "jest-environment-jsdom": "^29.2.2", | ||||
|     "jest-preset-angular": "^12.2.2", | ||||
|     "ts-node": "~10.9.1", | ||||
|     "tslint": "~6.1.3", | ||||
|   | ||||
| @@ -15,6 +15,7 @@ import { DirtyFormGuard } from './guards/dirty-form.guard' | ||||
| import { StoragePathListComponent } from './components/manage/storage-path-list/storage-path-list.component' | ||||
| import { TasksComponent } from './components/manage/tasks/tasks.component' | ||||
| import { DirtyDocGuard } from './guards/dirty-doc.guard' | ||||
| import { DirtySavedViewGuard } from './guards/dirty-saved-view.guard' | ||||
|  | ||||
| const routes: Routes = [ | ||||
|   { path: '', redirectTo: 'dashboard', pathMatch: 'full' }, | ||||
| @@ -24,8 +25,16 @@ const routes: Routes = [ | ||||
|     canDeactivate: [DirtyDocGuard], | ||||
|     children: [ | ||||
|       { path: 'dashboard', component: DashboardComponent }, | ||||
|       { path: 'documents', component: DocumentListComponent }, | ||||
|       { path: 'view/:id', component: DocumentListComponent }, | ||||
|       { | ||||
|         path: 'documents', | ||||
|         component: DocumentListComponent, | ||||
|         canDeactivate: [DirtySavedViewGuard], | ||||
|       }, | ||||
|       { | ||||
|         path: 'view/:id', | ||||
|         component: DocumentListComponent, | ||||
|         canDeactivate: [DirtySavedViewGuard], | ||||
|       }, | ||||
|       { path: 'documents/:id', component: DocumentDetailComponent }, | ||||
|       { path: 'asn/:id', component: DocumentAsnComponent }, | ||||
|       { path: 'tags', component: TagListComponent }, | ||||
|   | ||||
| @@ -24,6 +24,7 @@ import { CorrespondentEditDialogComponent } from './components/common/edit-dialo | ||||
| import { TagEditDialogComponent } from './components/common/edit-dialog/tag-edit-dialog/tag-edit-dialog.component' | ||||
| import { DocumentTypeEditDialogComponent } from './components/common/edit-dialog/document-type-edit-dialog/document-type-edit-dialog.component' | ||||
| import { TagComponent } from './components/common/tag/tag.component' | ||||
| import { ClearableBadge } from './components/common/clearable-badge/clearable-badge.component' | ||||
| import { PageHeaderComponent } from './components/common/page-header/page-header.component' | ||||
| import { AppFrameComponent } from './components/app-frame/app-frame.component' | ||||
| import { ToastsComponent } from './components/common/toasts/toasts.component' | ||||
| @@ -69,6 +70,7 @@ import { ColorComponent } from './components/common/input/color/color.component' | ||||
| import { DocumentAsnComponent } from './components/document-asn/document-asn.component' | ||||
| import { DocumentCommentsComponent } from './components/document-comments/document-comments.component' | ||||
| import { DirtyDocGuard } from './guards/dirty-doc.guard' | ||||
| import { DirtySavedViewGuard } from './guards/dirty-saved-view.guard' | ||||
| import { StoragePathListComponent } from './components/manage/storage-path-list/storage-path-list.component' | ||||
| import { StoragePathEditDialogComponent } from './components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component' | ||||
| import { SettingsService } from './services/settings.service' | ||||
| @@ -141,6 +143,7 @@ function initializeApp(settings: SettingsService) { | ||||
|     DocumentTypeEditDialogComponent, | ||||
|     StoragePathEditDialogComponent, | ||||
|     TagComponent, | ||||
|     ClearableBadge, | ||||
|     PageHeaderComponent, | ||||
|     AppFrameComponent, | ||||
|     ToastsComponent, | ||||
| @@ -215,6 +218,7 @@ function initializeApp(settings: SettingsService) { | ||||
|     { provide: NgbDateAdapter, useClass: ISODateAdapter }, | ||||
|     { provide: NgbDateParserFormatter, useClass: LocalizedDateParserFormatter }, | ||||
|     DirtyDocGuard, | ||||
|     DirtySavedViewGuard, | ||||
|   ], | ||||
|   bootstrap: [AppComponent], | ||||
| }) | ||||
|   | ||||
| @@ -16,7 +16,12 @@ | ||||
|         <use xlink:href="assets/bootstrap-icons.svg#search"/> | ||||
|       </svg> | ||||
|       <input class="form-control form-control-sm" type="text" placeholder="Search documents" aria-label="Search" | ||||
|         [formControl]="searchField" [ngbTypeahead]="searchAutoComplete" (selectItem)="itemSelected($event)" i18n-placeholder> | ||||
|         [formControl]="searchField" [ngbTypeahead]="searchAutoComplete" (keyup)="searchFieldKeyup($event)" (selectItem)="itemSelected($event)" i18n-placeholder> | ||||
|       <button *ngIf="!searchFieldEmpty" class="btn btn-link btn-sm px-0 position-absolute top-0 end-0" (click)="resetSearchField()"> | ||||
|         <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"/> | ||||
|         </svg> | ||||
|       </button> | ||||
|     </form> | ||||
|   </div> | ||||
|   <ul ngbNav class="order-sm-3"> | ||||
|   | ||||
| @@ -243,17 +243,18 @@ main { | ||||
|  | ||||
|   form { | ||||
|     position: relative; | ||||
|   } | ||||
|  | ||||
|   svg { | ||||
|     > svg { | ||||
|       position: absolute; | ||||
|       left: 0.6rem; | ||||
|       top: 0.5rem; | ||||
|       color: rgba(255, 255, 255, 0.6); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   &:focus-within { | ||||
|     svg { | ||||
|     form > svg { | ||||
|       display: none; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -93,6 +93,20 @@ export class AppFrameComponent implements OnInit, ComponentCanDeactivate { | ||||
|  | ||||
|   searchField = new FormControl('') | ||||
|  | ||||
|   get searchFieldEmpty(): boolean { | ||||
|     return this.searchField.value.trim().length == 0 | ||||
|   } | ||||
|  | ||||
|   resetSearchField() { | ||||
|     this.searchField.reset('') | ||||
|   } | ||||
|  | ||||
|   searchFieldKeyup(event: KeyboardEvent) { | ||||
|     if (event.key == 'Escape') { | ||||
|       this.resetSearchField() | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   get openDocuments(): PaperlessDocument[] { | ||||
|     return this.openDocumentsService.getOpenDocuments() | ||||
|   } | ||||
|   | ||||
| @@ -0,0 +1,9 @@ | ||||
| <button *ngIf="active" class="position-absolute top-0 start-100 translate-middle badge bg-secondary border border-light rounded-pill p-1" title="Clear" i18n-title (click)="onClick($event)"> | ||||
|     <svg *ngIf="!isNumbered && selected" width="1em" height="1em" class="check m-0 p-0 opacity-75" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> | ||||
|         <use xlink:href="assets/bootstrap-icons.svg#check-lg"/> | ||||
|     </svg> | ||||
|     <div *ngIf="isNumbered" class="number">{{number}}<span class="visually-hidden">selected</span></div> | ||||
|     <svg width=".9em" height="1em" class="x m-0 p-0 opacity-75" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> | ||||
|         <use xlink:href="assets/bootstrap-icons.svg#x-lg"/> | ||||
|     </svg> | ||||
| </button> | ||||
| @@ -0,0 +1,28 @@ | ||||
| .badge { | ||||
|     min-width: 20px; | ||||
|     min-height: 20px; | ||||
| } | ||||
|  | ||||
| .x { | ||||
|     display: none; | ||||
| } | ||||
|  | ||||
| .number { | ||||
|     min-width: 1em; | ||||
|     min-height: 1em; | ||||
|     display: inline-block; | ||||
| } | ||||
|  | ||||
| button:hover { | ||||
|     .check, | ||||
|     .number { | ||||
|         opacity: 0 !important; | ||||
|     } | ||||
|  | ||||
|     .x { | ||||
|         display: inline-block; | ||||
|         position: absolute; | ||||
|         top: 5px; | ||||
|         left: calc(50% - 4px); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,33 @@ | ||||
| import { Component, Input, Output, EventEmitter } from '@angular/core' | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-clearable-badge', | ||||
|   templateUrl: './clearable-badge.component.html', | ||||
|   styleUrls: ['./clearable-badge.component.scss'], | ||||
| }) | ||||
| export class ClearableBadge { | ||||
|   constructor() {} | ||||
|  | ||||
|   @Input() | ||||
|   number: number | ||||
|  | ||||
|   @Input() | ||||
|   selected: boolean | ||||
|  | ||||
|   @Output() | ||||
|   cleared: EventEmitter<boolean> = new EventEmitter() | ||||
|  | ||||
|   get active(): boolean { | ||||
|     return this.selected || this.number > -1 | ||||
|   } | ||||
|  | ||||
|   get isNumbered(): boolean { | ||||
|     return this.number > -1 | ||||
|   } | ||||
|  | ||||
|   onClick(event: PointerEvent) { | ||||
|     this.cleared.emit(true) | ||||
|     event.stopImmediatePropagation() | ||||
|     event.preventDefault() | ||||
|   } | ||||
| } | ||||
| @@ -16,4 +16,7 @@ | ||||
|         <ngb-progressbar *ngIf="!confirmButtonEnabled" style="height: 1px;" type="dark" [max]="secondsTotal" [value]="seconds"></ngb-progressbar> | ||||
|         <span class="visually-hidden">{{ seconds | number: '1.0-0' }} seconds</span> | ||||
|       </button> | ||||
|       <button *ngIf="alternativeBtnCaption" type="button" class="btn" [class]="alternativeBtnClass" (click)="alternative()" [disabled]="!alternativeButtonEnabled || !buttonsEnabled"> | ||||
|         {{alternativeBtnCaption}} | ||||
|       </button> | ||||
|     </div> | ||||
|   | ||||
| @@ -13,6 +13,9 @@ export class ConfirmDialogComponent { | ||||
|   @Output() | ||||
|   public confirmClicked = new EventEmitter() | ||||
|  | ||||
|   @Output() | ||||
|   public alternativeClicked = new EventEmitter() | ||||
|  | ||||
|   @Input() | ||||
|   title = $localize`Confirmation` | ||||
|  | ||||
| @@ -28,14 +31,22 @@ export class ConfirmDialogComponent { | ||||
|   @Input() | ||||
|   btnCaption = $localize`Confirm` | ||||
|  | ||||
|   @Input() | ||||
|   alternativeBtnClass = 'btn-secondary' | ||||
|  | ||||
|   @Input() | ||||
|   alternativeBtnCaption | ||||
|  | ||||
|   @Input() | ||||
|   buttonsEnabled = true | ||||
|  | ||||
|   confirmButtonEnabled = true | ||||
|   alternativeButtonEnabled = true | ||||
|   seconds = 0 | ||||
|   secondsTotal = 0 | ||||
|  | ||||
|   confirmSubject: Subject<boolean> | ||||
|   alternativeSubject: Subject<boolean> | ||||
|  | ||||
|   delayConfirm(seconds: number) { | ||||
|     const refreshInterval = 0.15 // s | ||||
| @@ -68,4 +79,10 @@ export class ConfirmDialogComponent { | ||||
|     this.confirmSubject?.next(true) | ||||
|     this.confirmSubject?.complete() | ||||
|   } | ||||
|  | ||||
|   alternative() { | ||||
|     this.alternativeClicked.emit() | ||||
|     this.alternativeSubject?.next(true) | ||||
|     this.alternativeSubject?.complete() | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,11 +1,17 @@ | ||||
|   <div class="btn-group w-100" ngbDropdown role="group"> | ||||
|   <button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="dateBefore || dateAfter ? 'btn-primary' : 'btn-outline-primary'"> | ||||
|     {{title}} | ||||
|     <app-clearable-badge [selected]="isActive" (cleared)="reset()"></app-clearable-badge><span class="visually-hidden">selected</span> | ||||
|   </button> | ||||
|   <div class="dropdown-menu date-dropdown shadow pt-0" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}"> | ||||
|     <div class="list-group list-group-flush"> | ||||
|         <button *ngFor="let qf of quickFilters" class="list-group-item small list-goup list-group-item-action d-flex p-2 ps-3" role="menuitem" (click)="setDateQuickFilter(qf.id)"> | ||||
|           {{qf.name}} | ||||
|         <button *ngFor="let rd of relativeDates" class="list-group-item small list-goup list-group-item-action d-flex p-2" role="menuitem" (click)="setRelativeDate(rd.date)"> | ||||
|           <div _ngcontent-hga-c166="" class="selected-icon me-1"> | ||||
|             <svg *ngIf="relativeDate === rd.date" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" class="bi bi-check" viewBox="0 0 16 16"> | ||||
|               <path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z"/> | ||||
|             </svg> | ||||
|           </div> | ||||
|           {{rd.name}} | ||||
|         </button> | ||||
|         <div class="list-group-item d-flex flex-column align-items-start" role="menuitem"> | ||||
|  | ||||
|   | ||||
| @@ -5,3 +5,8 @@ | ||||
|     line-height: 1; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .selected-icon { | ||||
|   min-width: 1em; | ||||
|   min-height: 1em; | ||||
| } | ||||
|   | ||||
| @@ -16,12 +16,15 @@ import { ISODateAdapter } from 'src/app/utils/ngb-iso-date-adapter' | ||||
| export interface DateSelection { | ||||
|   before?: string | ||||
|   after?: string | ||||
|   relativeDateID?: number | ||||
| } | ||||
|  | ||||
| const LAST_7_DAYS = 0 | ||||
| const LAST_MONTH = 1 | ||||
| const LAST_3_MONTHS = 2 | ||||
| const LAST_YEAR = 3 | ||||
| export enum RelativeDate { | ||||
|   LAST_7_DAYS = 0, | ||||
|   LAST_MONTH = 1, | ||||
|   LAST_3_MONTHS = 2, | ||||
|   LAST_YEAR = 3, | ||||
| } | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-date-dropdown', | ||||
| @@ -34,11 +37,23 @@ export class DateDropdownComponent implements OnInit, OnDestroy { | ||||
|     this.datePlaceHolder = settings.getLocalizedDateInputFormat() | ||||
|   } | ||||
|  | ||||
|   quickFilters = [ | ||||
|     { id: LAST_7_DAYS, name: $localize`Last 7 days` }, | ||||
|     { id: LAST_MONTH, name: $localize`Last month` }, | ||||
|     { id: LAST_3_MONTHS, name: $localize`Last 3 months` }, | ||||
|     { id: LAST_YEAR, name: $localize`Last year` }, | ||||
|   relativeDates = [ | ||||
|     { | ||||
|       date: RelativeDate.LAST_7_DAYS, | ||||
|       name: $localize`Last 7 days`, | ||||
|     }, | ||||
|     { | ||||
|       date: RelativeDate.LAST_MONTH, | ||||
|       name: $localize`Last month`, | ||||
|     }, | ||||
|     { | ||||
|       date: RelativeDate.LAST_3_MONTHS, | ||||
|       name: $localize`Last 3 months`, | ||||
|     }, | ||||
|     { | ||||
|       date: RelativeDate.LAST_YEAR, | ||||
|       name: $localize`Last year`, | ||||
|     }, | ||||
|   ] | ||||
|  | ||||
|   datePlaceHolder: string | ||||
| @@ -55,12 +70,26 @@ export class DateDropdownComponent implements OnInit, OnDestroy { | ||||
|   @Output() | ||||
|   dateAfterChange = new EventEmitter<string>() | ||||
|  | ||||
|   @Input() | ||||
|   relativeDate: RelativeDate | ||||
|  | ||||
|   @Output() | ||||
|   relativeDateChange = new EventEmitter<number>() | ||||
|  | ||||
|   @Input() | ||||
|   title: string | ||||
|  | ||||
|   @Output() | ||||
|   datesSet = new EventEmitter<DateSelection>() | ||||
|  | ||||
|   get isActive(): boolean { | ||||
|     return ( | ||||
|       this.relativeDate !== null || | ||||
|       this.dateAfter?.length > 0 || | ||||
|       this.dateBefore?.length > 0 | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   private datesSetDebounce$ = new Subject() | ||||
|  | ||||
|   private sub: Subscription | ||||
| @@ -77,37 +106,33 @@ export class DateDropdownComponent implements OnInit, OnDestroy { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   setDateQuickFilter(qf: number) { | ||||
|   reset() { | ||||
|     this.dateBefore = null | ||||
|     let date = new Date() | ||||
|     switch (qf) { | ||||
|       case LAST_7_DAYS: | ||||
|         date.setDate(date.getDate() - 7) | ||||
|         break | ||||
|  | ||||
|       case LAST_MONTH: | ||||
|         date.setMonth(date.getMonth() - 1) | ||||
|         break | ||||
|  | ||||
|       case LAST_3_MONTHS: | ||||
|         date.setMonth(date.getMonth() - 3) | ||||
|         break | ||||
|  | ||||
|       case LAST_YEAR: | ||||
|         date.setFullYear(date.getFullYear() - 1) | ||||
|         break | ||||
|     this.dateAfter = null | ||||
|     this.relativeDate = null | ||||
|     this.onChange() | ||||
|   } | ||||
|     this.dateAfter = formatDate(date, 'yyyy-MM-dd', 'en-us', 'UTC') | ||||
|  | ||||
|   setRelativeDate(rd: RelativeDate) { | ||||
|     this.dateBefore = null | ||||
|     this.dateAfter = null | ||||
|     this.relativeDate = this.relativeDate == rd ? null : rd | ||||
|     this.onChange() | ||||
|   } | ||||
|  | ||||
|   onChange() { | ||||
|     this.dateAfterChange.emit(this.dateAfter) | ||||
|     this.dateBeforeChange.emit(this.dateBefore) | ||||
|     this.datesSet.emit({ after: this.dateAfter, before: this.dateBefore }) | ||||
|     this.dateAfterChange.emit(this.dateAfter) | ||||
|     this.relativeDateChange.emit(this.relativeDate) | ||||
|     this.datesSet.emit({ | ||||
|       after: this.dateAfter, | ||||
|       before: this.dateBefore, | ||||
|       relativeDateID: this.relativeDate, | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   onChangeDebounce() { | ||||
|     this.relativeDate = null | ||||
|     this.datesSetDebounce$.next({ | ||||
|       after: this.dateAfter, | ||||
|       before: this.dateBefore, | ||||
|   | ||||
| @@ -5,12 +5,7 @@ | ||||
|     </svg> | ||||
|     <div class="d-none d-sm-inline"> {{title}}</div> | ||||
|     <ng-container *ngIf="!editing && selectionModel.selectionSize() > 0"> | ||||
|       <div *ngIf="multiple" class="position-absolute top-0 start-100 translate-middle badge bg-secondary border border-light text-light rounded-pill"> | ||||
|         {{selectionModel.totalCount}}<span class="visually-hidden">selected</span> | ||||
|       </div> | ||||
|       <div *ngIf="!multiple" class="position-absolute top-0 start-100 p-2 translate-middle badge bg-secondary border border-light rounded-circle"> | ||||
|         <span class="visually-hidden">selected</span> | ||||
|       </div> | ||||
|       <app-clearable-badge [number]="multiple ? selectionModel.totalCount : undefined" [selected]="!multiple && selectionModel.selectionSize() > 0" (cleared)="reset()"></app-clearable-badge> | ||||
|     </ng-container> | ||||
|   </button> | ||||
|   <div class="dropdown-menu py-0 shadow" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}"> | ||||
|   | ||||
| @@ -384,4 +384,9 @@ export class FilterableDropdownComponent { | ||||
|       this.selectionModel.exclude(itemID) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   reset() { | ||||
|     this.selectionModel.reset() | ||||
|     this.selectionModelChange.emit(this.selectionModel) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -60,14 +60,19 @@ | ||||
|   </div> | ||||
|  | ||||
|   <div class="btn-group ms-2 flex-fill" ngbDropdown role="group"> | ||||
|     <button class="btn btn-sm btn-outline-primary dropdown-toggle flex-fill" tourAnchor="tour.documents-views" ngbDropdownToggle i18n>Views</button> | ||||
|     <button class="btn btn-sm btn-outline-primary dropdown-toggle flex-fill" tourAnchor="tour.documents-views" ngbDropdownToggle> | ||||
|       <ng-container i18n>Views</ng-container> | ||||
|       <div *ngIf="savedViewIsModified" class="position-absolute top-0 start-100 p-2 translate-middle badge bg-secondary border border-light rounded-circle"> | ||||
|         <span class="visually-hidden">selected</span> | ||||
|       </div> | ||||
|     </button> | ||||
|     <div class="dropdown-menu shadow dropdown-menu-right" ngbDropdownMenu> | ||||
|       <ng-container *ngIf="!list.activeSavedViewId"> | ||||
|         <button ngbDropdownItem *ngFor="let view of savedViewService.allViews" (click)="loadViewConfig(view.id)">{{view.name}}</button> | ||||
|         <div class="dropdown-divider" *ngIf="savedViewService.allViews.length > 0"></div> | ||||
|       </ng-container> | ||||
|  | ||||
|       <button ngbDropdownItem (click)="saveViewConfig()" *ngIf="list.activeSavedViewId" i18n>Save "{{list.activeSavedViewTitle}}"</button> | ||||
|       <button ngbDropdownItem (click)="saveViewConfig()" *ngIf="list.activeSavedViewId" [disabled]="!savedViewIsModified" i18n>Save "{{list.activeSavedViewTitle}}"</button> | ||||
|       <button ngbDropdownItem (click)="saveViewConfigAs()" i18n>Save as...</button> | ||||
|     </div> | ||||
|   </div> | ||||
|   | ||||
| @@ -9,7 +9,11 @@ import { | ||||
| import { ActivatedRoute, convertToParamMap, Router } from '@angular/router' | ||||
| import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | ||||
| import { filter, first, map, Subject, switchMap, takeUntil } from 'rxjs' | ||||
| import { FilterRule, isFullTextFilterRule } from 'src/app/data/filter-rule' | ||||
| import { | ||||
|   FilterRule, | ||||
|   filterRulesDiffer, | ||||
|   isFullTextFilterRule, | ||||
| } from 'src/app/data/filter-rule' | ||||
| import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type' | ||||
| import { PaperlessDocument } from 'src/app/data/paperless-document' | ||||
| import { PaperlessSavedView } from 'src/app/data/paperless-saved-view' | ||||
| @@ -54,15 +58,36 @@ export class DocumentListComponent implements OnInit, OnDestroy { | ||||
|   displayMode = 'smallCards' // largeCards, smallCards, details | ||||
|  | ||||
|   unmodifiedFilterRules: FilterRule[] = [] | ||||
|   private unmodifiedSavedView: PaperlessSavedView | ||||
|  | ||||
|   private unsubscribeNotifier: Subject<any> = new Subject() | ||||
|  | ||||
|   get savedViewIsModified(): boolean { | ||||
|     if (!this.list.activeSavedViewId || !this.unmodifiedSavedView) return false | ||||
|     else { | ||||
|       return ( | ||||
|         this.unmodifiedSavedView.sort_field !== this.list.sortField || | ||||
|         this.unmodifiedSavedView.sort_reverse !== this.list.sortReverse || | ||||
|         filterRulesDiffer( | ||||
|           this.unmodifiedSavedView.filter_rules, | ||||
|           this.list.filterRules | ||||
|         ) | ||||
|       ) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   get isFiltered() { | ||||
|     return this.list.filterRules?.length > 0 | ||||
|   } | ||||
|  | ||||
|   getTitle() { | ||||
|     return this.list.activeSavedViewTitle || $localize`Documents` | ||||
|     let title = this.list.activeSavedViewTitle | ||||
|     if (title && this.savedViewIsModified) { | ||||
|       title += '*' | ||||
|     } else if (!title) { | ||||
|       title = $localize`Documents` | ||||
|     } | ||||
|     return title | ||||
|   } | ||||
|  | ||||
|   getSortFields() { | ||||
| @@ -122,7 +147,7 @@ export class DocumentListComponent implements OnInit, OnDestroy { | ||||
|           this.router.navigate(['404']) | ||||
|           return | ||||
|         } | ||||
|  | ||||
|         this.unmodifiedSavedView = view | ||||
|         this.list.activateSavedViewWithQueryParams( | ||||
|           view, | ||||
|           convertToParamMap(this.route.snapshot.queryParams) | ||||
| @@ -165,7 +190,8 @@ export class DocumentListComponent implements OnInit, OnDestroy { | ||||
|       this.savedViewService | ||||
|         .patch(savedView) | ||||
|         .pipe(first()) | ||||
|         .subscribe((result) => { | ||||
|         .subscribe((view) => { | ||||
|           this.unmodifiedSavedView = view | ||||
|           this.toastService.showInfo( | ||||
|             $localize`View "${this.list.activeSavedViewTitle}" saved successfully.` | ||||
|           ) | ||||
| @@ -179,6 +205,7 @@ export class DocumentListComponent implements OnInit, OnDestroy { | ||||
|       .getCached(viewID) | ||||
|       .pipe(first()) | ||||
|       .subscribe((view) => { | ||||
|         this.unmodifiedSavedView = view | ||||
|         this.list.activateSavedView(view) | ||||
|         this.list.reload() | ||||
|       }) | ||||
|   | ||||
| @@ -11,7 +11,12 @@ | ||||
|           <select *ngIf="textFilterTarget == 'asn'" class="form-select flex-grow-0 w-auto" [(ngModel)]="textFilterModifier" (change)="textFilterModifierChange()"> | ||||
|             <option *ngFor="let m of textFilterModifiers" ngbDropdownItem [value]="m.id">{{m.label}}</option> | ||||
|           </select> | ||||
|           <input #textFilterInput class="form-control form-control-sm" type="text" [disabled]="textFilterModifierIsNull" [(ngModel)]="textFilter" (keyup.enter)="textFilterEnter()" [readonly]="textFilterTarget == 'fulltext-morelike'"> | ||||
|           <button *ngIf="_textFilter" class="btn btn-link btn-sm px-0 position-absolute top-0 end-0 z-10" (click)="resetTextField()"> | ||||
|             <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"/> | ||||
|             </svg> | ||||
|           </button> | ||||
|           <input #textFilterInput class="form-control form-control-sm" type="text" [disabled]="textFilterModifierIsNull" [(ngModel)]="textFilter" (keyup)="textFilterKeyup($event)" [readonly]="textFilterTarget == 'fulltext-morelike'"> | ||||
|          </div> | ||||
|      </div> | ||||
|   </div> | ||||
| @@ -54,12 +59,14 @@ | ||||
|             title="Created" i18n-title | ||||
|             (datesSet)="updateRules()" | ||||
|             [(dateBefore)]="dateCreatedBefore" | ||||
|             [(dateAfter)]="dateCreatedAfter"></app-date-dropdown> | ||||
|             [(dateAfter)]="dateCreatedAfter" | ||||
|             [(relativeDate)]="dateCreatedRelativeDate"></app-date-dropdown> | ||||
|           <app-date-dropdown class="mb-2 mb-xl-0" | ||||
|             title="Added" i18n-title | ||||
|             (datesSet)="updateRules()" | ||||
|             [(dateBefore)]="dateAddedBefore" | ||||
|             [(dateAfter)]="dateAddedAfter" | ||||
|             title="Added" i18n-title | ||||
|             (datesSet)="updateRules()"></app-date-dropdown> | ||||
|             [(relativeDate)]="dateAddedRelativeDate"></app-date-dropdown> | ||||
|         </div> | ||||
|      </div> | ||||
|    </div> | ||||
|   | ||||
| @@ -21,3 +21,7 @@ | ||||
| input[type="text"] { | ||||
|   min-width: 120px; | ||||
| } | ||||
|  | ||||
| .z-10 { | ||||
|   z-index: 10; | ||||
| } | ||||
|   | ||||
| @@ -44,6 +44,7 @@ import { DocumentService } from 'src/app/services/rest/document.service' | ||||
| import { PaperlessDocument } from 'src/app/data/paperless-document' | ||||
| import { PaperlessStoragePath } from 'src/app/data/paperless-storage-path' | ||||
| import { StoragePathService } from 'src/app/services/rest/storage-path.service' | ||||
| import { RelativeDate } from '../../common/date-dropdown/date-dropdown.component' | ||||
|  | ||||
| const TEXT_FILTER_TARGET_TITLE = 'title' | ||||
| const TEXT_FILTER_TARGET_TITLE_CONTENT = 'title-content' | ||||
| @@ -57,6 +58,27 @@ const TEXT_FILTER_MODIFIER_NOTNULL = 'not null' | ||||
| const TEXT_FILTER_MODIFIER_GT = 'greater' | ||||
| const TEXT_FILTER_MODIFIER_LT = 'less' | ||||
|  | ||||
| const RELATIVE_DATE_QUERY_REGEXP_CREATED = /created:\[([^\]]+)\]/g | ||||
| const RELATIVE_DATE_QUERY_REGEXP_ADDED = /added:\[([^\]]+)\]/g | ||||
| const RELATIVE_DATE_QUERYSTRINGS = [ | ||||
|   { | ||||
|     relativeDate: RelativeDate.LAST_7_DAYS, | ||||
|     dateQuery: '-1 week to now', | ||||
|   }, | ||||
|   { | ||||
|     relativeDate: RelativeDate.LAST_MONTH, | ||||
|     dateQuery: '-1 month to now', | ||||
|   }, | ||||
|   { | ||||
|     relativeDate: RelativeDate.LAST_3_MONTHS, | ||||
|     dateQuery: '-3 month to now', | ||||
|   }, | ||||
|   { | ||||
|     relativeDate: RelativeDate.LAST_YEAR, | ||||
|     dateQuery: '-1 year to now', | ||||
|   }, | ||||
| ] | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-filter-editor', | ||||
|   templateUrl: './filter-editor.component.html', | ||||
| @@ -197,6 +219,8 @@ export class FilterEditorComponent implements OnInit, OnDestroy { | ||||
|   dateCreatedAfter: string | ||||
|   dateAddedBefore: string | ||||
|   dateAddedAfter: string | ||||
|   dateCreatedRelativeDate: RelativeDate | ||||
|   dateAddedRelativeDate: RelativeDate | ||||
|  | ||||
|   _unmodifiedFilterRules: FilterRule[] = [] | ||||
|   _filterRules: FilterRule[] = [] | ||||
| @@ -228,6 +252,8 @@ export class FilterEditorComponent implements OnInit, OnDestroy { | ||||
|     this.dateAddedAfter = null | ||||
|     this.dateCreatedBefore = null | ||||
|     this.dateCreatedAfter = null | ||||
|     this.dateCreatedRelativeDate = null | ||||
|     this.dateAddedRelativeDate = null | ||||
|     this.textFilterModifier = TEXT_FILTER_MODIFIER_EQUALS | ||||
|  | ||||
|     value.forEach((rule) => { | ||||
| @@ -245,8 +271,39 @@ export class FilterEditorComponent implements OnInit, OnDestroy { | ||||
|           this.textFilterTarget = TEXT_FILTER_TARGET_ASN | ||||
|           break | ||||
|         case FILTER_FULLTEXT_QUERY: | ||||
|           this._textFilter = rule.value | ||||
|           let allQueryArgs = rule.value.split(',') | ||||
|           let textQueryArgs = [] | ||||
|           allQueryArgs.forEach((arg) => { | ||||
|             if (arg.match(RELATIVE_DATE_QUERY_REGEXP_CREATED)) { | ||||
|               ;[...arg.matchAll(RELATIVE_DATE_QUERY_REGEXP_CREATED)].forEach( | ||||
|                 (match) => { | ||||
|                   if (match[1]?.length) { | ||||
|                     this.dateCreatedRelativeDate = | ||||
|                       RELATIVE_DATE_QUERYSTRINGS.find( | ||||
|                         (qS) => qS.dateQuery == match[1] | ||||
|                       )?.relativeDate | ||||
|                   } | ||||
|                 } | ||||
|               ) | ||||
|             } else if (arg.match(RELATIVE_DATE_QUERY_REGEXP_ADDED)) { | ||||
|               ;[...arg.matchAll(RELATIVE_DATE_QUERY_REGEXP_ADDED)].forEach( | ||||
|                 (match) => { | ||||
|                   if (match[1]?.length) { | ||||
|                     this.dateAddedRelativeDate = | ||||
|                       RELATIVE_DATE_QUERYSTRINGS.find( | ||||
|                         (qS) => qS.dateQuery == match[1] | ||||
|                       )?.relativeDate | ||||
|                   } | ||||
|                 } | ||||
|               ) | ||||
|             } else { | ||||
|               textQueryArgs.push(arg) | ||||
|             } | ||||
|           }) | ||||
|           if (textQueryArgs.length) { | ||||
|             this._textFilter = textQueryArgs.join(',') | ||||
|             this.textFilterTarget = TEXT_FILTER_TARGET_FULLTEXT_QUERY | ||||
|           } | ||||
|           break | ||||
|         case FILTER_FULLTEXT_MORELIKE: | ||||
|           this._moreLikeId = +rule.value | ||||
| @@ -471,6 +528,89 @@ export class FilterEditorComponent implements OnInit, OnDestroy { | ||||
|         value: this.dateAddedAfter, | ||||
|       }) | ||||
|     } | ||||
|     if ( | ||||
|       this.dateAddedRelativeDate !== null || | ||||
|       this.dateCreatedRelativeDate !== null | ||||
|     ) { | ||||
|       let queryArgs: Array<string> = [] | ||||
|       let existingRule = filterRules.find( | ||||
|         (fr) => fr.rule_type == FILTER_FULLTEXT_QUERY | ||||
|       ) | ||||
|  | ||||
|       // if had a title / content search and added a relative date we need to carry it over... | ||||
|       if ( | ||||
|         !existingRule && | ||||
|         this._textFilter?.length > 0 && | ||||
|         (this.textFilterTarget == TEXT_FILTER_TARGET_TITLE_CONTENT || | ||||
|           this.textFilterTarget == TEXT_FILTER_TARGET_TITLE) | ||||
|       ) { | ||||
|         existingRule = filterRules.find( | ||||
|           (fr) => | ||||
|             fr.rule_type == FILTER_TITLE_CONTENT || fr.rule_type == FILTER_TITLE | ||||
|         ) | ||||
|         existingRule.rule_type = FILTER_FULLTEXT_QUERY | ||||
|       } | ||||
|  | ||||
|       let existingRuleArgs = existingRule?.value.split(',') | ||||
|       if (this.dateCreatedRelativeDate !== null) { | ||||
|         queryArgs.push( | ||||
|           `created:[${ | ||||
|             RELATIVE_DATE_QUERYSTRINGS.find( | ||||
|               (qS) => qS.relativeDate == this.dateCreatedRelativeDate | ||||
|             ).dateQuery | ||||
|           }]` | ||||
|         ) | ||||
|         if (existingRule) { | ||||
|           queryArgs = existingRuleArgs | ||||
|             .filter((arg) => !arg.match(RELATIVE_DATE_QUERY_REGEXP_CREATED)) | ||||
|             .concat(queryArgs) | ||||
|         } | ||||
|       } | ||||
|       if (this.dateAddedRelativeDate !== null) { | ||||
|         queryArgs.push( | ||||
|           `added:[${ | ||||
|             RELATIVE_DATE_QUERYSTRINGS.find( | ||||
|               (qS) => qS.relativeDate == this.dateAddedRelativeDate | ||||
|             ).dateQuery | ||||
|           }]` | ||||
|         ) | ||||
|         if (existingRule) { | ||||
|           queryArgs = existingRuleArgs | ||||
|             .filter((arg) => !arg.match(RELATIVE_DATE_QUERY_REGEXP_ADDED)) | ||||
|             .concat(queryArgs) | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (existingRule) { | ||||
|         existingRule.value = queryArgs.join(',') | ||||
|       } else { | ||||
|         filterRules.push({ | ||||
|           rule_type: FILTER_FULLTEXT_QUERY, | ||||
|           value: queryArgs.join(','), | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|     if ( | ||||
|       this.dateCreatedRelativeDate == null && | ||||
|       this.dateAddedRelativeDate == null | ||||
|     ) { | ||||
|       const existingRule = filterRules.find( | ||||
|         (fr) => fr.rule_type == FILTER_FULLTEXT_QUERY | ||||
|       ) | ||||
|       if ( | ||||
|         existingRule?.value.match(RELATIVE_DATE_QUERY_REGEXP_CREATED) || | ||||
|         existingRule?.value.match(RELATIVE_DATE_QUERY_REGEXP_ADDED) | ||||
|       ) { | ||||
|         // remove any existing date query | ||||
|         existingRule.value = existingRule.value | ||||
|           .replace(RELATIVE_DATE_QUERY_REGEXP_CREATED, '') | ||||
|           .replace(RELATIVE_DATE_QUERY_REGEXP_ADDED, '') | ||||
|         if (existingRule.value.replace(',', '').trim() === '') { | ||||
|           // if its empty now, remove it entirely | ||||
|           filterRules.splice(filterRules.indexOf(existingRule), 1) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     return filterRules | ||||
|   } | ||||
|  | ||||
| @@ -569,13 +709,21 @@ export class FilterEditorComponent implements OnInit, OnDestroy { | ||||
|     this.updateRules() | ||||
|   } | ||||
|  | ||||
|   textFilterEnter() { | ||||
|   textFilterKeyup(event: KeyboardEvent) { | ||||
|     if (event.key == 'Enter') { | ||||
|       const filterString = ( | ||||
|         this.textFilterInput.nativeElement as HTMLInputElement | ||||
|       ).value | ||||
|       if (filterString.length) { | ||||
|         this.updateTextFilter(filterString) | ||||
|       } | ||||
|     } else if (event.key == 'Escape') { | ||||
|       this.resetTextField() | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   resetTextField() { | ||||
|     this.updateTextFilter('') | ||||
|   } | ||||
|  | ||||
|   changeTextFilterTarget(target) { | ||||
|   | ||||
							
								
								
									
										51
									
								
								src-ui/src/app/guards/dirty-saved-view.guard.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src-ui/src/app/guards/dirty-saved-view.guard.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| import { CanDeactivate } from '@angular/router' | ||||
| import { Injectable } from '@angular/core' | ||||
| import { first, Observable, Subject } from 'rxjs' | ||||
| import { DocumentListComponent } from '../components/document-list/document-list.component' | ||||
| import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | ||||
| import { ConfirmDialogComponent } from '../components/common/confirm-dialog/confirm-dialog.component' | ||||
|  | ||||
| @Injectable() | ||||
| export class DirtySavedViewGuard | ||||
|   implements CanDeactivate<DocumentListComponent> | ||||
| { | ||||
|   constructor(private modalService: NgbModal) {} | ||||
|  | ||||
|   canDeactivate( | ||||
|     component: DocumentListComponent | ||||
|   ): boolean | Observable<boolean> { | ||||
|     return component.savedViewIsModified ? this.warn(component) : true | ||||
|   } | ||||
|  | ||||
|   warn(component: DocumentListComponent) { | ||||
|     let modal = this.modalService.open(ConfirmDialogComponent, { | ||||
|       backdrop: 'static', | ||||
|     }) | ||||
|     modal.componentInstance.title = $localize`Unsaved Changes` | ||||
|     modal.componentInstance.messageBold = | ||||
|       $localize`You have unsaved changes to the saved view` + | ||||
|       ' "' + | ||||
|       component.getTitle() | ||||
|     ;('".') | ||||
|     modal.componentInstance.message = $localize`Are you sure you want to close this saved view?` | ||||
|     modal.componentInstance.btnClass = 'btn-secondary' | ||||
|     modal.componentInstance.btnCaption = $localize`Close` | ||||
|     modal.componentInstance.alternativeBtnClass = 'btn-primary' | ||||
|     modal.componentInstance.alternativeBtnCaption = $localize`Save and close` | ||||
|     modal.componentInstance.alternativeClicked.pipe(first()).subscribe(() => { | ||||
|       modal.componentInstance.buttonsEnabled = false | ||||
|       component.saveViewConfig() | ||||
|       modal.close() | ||||
|     }) | ||||
|     modal.componentInstance.confirmClicked.pipe(first()).subscribe(() => { | ||||
|       modal.componentInstance.buttonsEnabled = false | ||||
|       modal.close() | ||||
|     }) | ||||
|  | ||||
|     const subject = new Subject<boolean>() | ||||
|     modal.componentInstance.confirmSubject = subject | ||||
|     modal.componentInstance.alternativeSubject = subject | ||||
|  | ||||
|     return subject | ||||
|   } | ||||
| } | ||||
| @@ -171,15 +171,15 @@ export class DocumentListViewService { | ||||
|     this.reduceSelectionToFilter() | ||||
|  | ||||
|     if (!this.router.routerState.snapshot.url.includes('/view/')) { | ||||
|       this.router.navigate([], { | ||||
|         queryParams: { view: view.id }, | ||||
|       }) | ||||
|       this.router.navigate(['view', view.id]) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   loadFromQueryParams(queryParams: ParamMap) { | ||||
|     const paramsEmpty: boolean = queryParams.keys.length == 0 | ||||
|     let newState: ListViewState = this.listViewStates.get(null) | ||||
|     let newState: ListViewState = this.listViewStates.get( | ||||
|       this._activeSavedViewId | ||||
|     ) | ||||
|     if (!paramsEmpty) newState = paramsToViewState(queryParams) | ||||
|     if (newState == undefined) newState = this.defaultListViewState() // if nothing in local storage | ||||
|  | ||||
| @@ -276,7 +276,6 @@ export class DocumentListViewService { | ||||
|     ) { | ||||
|       this.activeListViewState.sortField = 'created' | ||||
|     } | ||||
|     this._activeSavedViewId = null | ||||
|     this.activeListViewState.filterRules = filterRules | ||||
|     this.reload() | ||||
|     this.reduceSelectionToFilter() | ||||
| @@ -288,7 +287,6 @@ export class DocumentListViewService { | ||||
|   } | ||||
|  | ||||
|   set sortField(field: string) { | ||||
|     this._activeSavedViewId = null | ||||
|     this.activeListViewState.sortField = field | ||||
|     this.reload() | ||||
|     this.saveDocumentListView() | ||||
| @@ -299,7 +297,6 @@ export class DocumentListViewService { | ||||
|   } | ||||
|  | ||||
|   set sortReverse(reverse: boolean) { | ||||
|     this._activeSavedViewId = null | ||||
|     this.activeListViewState.sortReverse = reverse | ||||
|     this.reload() | ||||
|     this.saveDocumentListView() | ||||
|   | ||||
| @@ -372,6 +372,10 @@ textarea, | ||||
|   &:hover, &:focus { | ||||
|     background-color: var(--bs-body-bg); | ||||
|   } | ||||
|  | ||||
|   &:focus { | ||||
|     color: var(--bs-body-color); | ||||
|   } | ||||
| } | ||||
|  | ||||
| .dropdown-menu { | ||||
| @@ -393,6 +397,10 @@ textarea, | ||||
|       background-color: var(--bs-primary); | ||||
|       color: var(--pngx-primary-text-contrast); | ||||
|     } | ||||
|  | ||||
|     &.disabled, &:disabled { | ||||
|       opacity: 50%; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -579,7 +587,7 @@ a.badge { | ||||
|     border-radius: 0.15rem; | ||||
|   } | ||||
|  | ||||
|   > .btn:not(:first-child) { | ||||
|   > .btn:not(:first-child):not(:nth-child(2)) { | ||||
|     border-top-left-radius: 0; | ||||
|     border-bottom-left-radius: 0; | ||||
|   } | ||||
|   | ||||
| @@ -405,6 +405,7 @@ class Consumer(LoggingMixin): | ||||
|  | ||||
|                 # Don't save with the lock active. Saving will cause the file | ||||
|                 # renaming logic to acquire the lock as well. | ||||
|                 # This triggers things like file renaming | ||||
|                 document.save() | ||||
|  | ||||
|                 # Delete the file only if it was successfully consumed | ||||
| @@ -438,6 +439,9 @@ class Consumer(LoggingMixin): | ||||
|  | ||||
|         self._send_progress(100, 100, "SUCCESS", MESSAGE_FINISHED, document.id) | ||||
|  | ||||
|         # Return the most up to date fields | ||||
|         document.refresh_from_db() | ||||
|  | ||||
|         return document | ||||
|  | ||||
|     def _store(self, text, date, mime_type) -> Document: | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| import datetime | ||||
| import logging | ||||
| import os | ||||
| from collections import defaultdict | ||||
| @@ -172,7 +171,7 @@ def generate_filename(doc, counter=0, append_gpg=True, archive_filename=False): | ||||
|             else: | ||||
|                 asn = "-none-" | ||||
|  | ||||
|             # Convert UTC database date to localized date | ||||
|             # Convert UTC database datetime to localized date | ||||
|             local_added = timezone.localdate(doc.added) | ||||
|             local_created = timezone.localdate(doc.created) | ||||
|  | ||||
| @@ -180,14 +179,20 @@ def generate_filename(doc, counter=0, append_gpg=True, archive_filename=False): | ||||
|                 title=pathvalidate.sanitize_filename(doc.title, replacement_text="-"), | ||||
|                 correspondent=correspondent, | ||||
|                 document_type=document_type, | ||||
|                 created=datetime.date.isoformat(local_created), | ||||
|                 created_year=local_created.year, | ||||
|                 created_month=f"{local_created.month:02}", | ||||
|                 created_day=f"{local_created.day:02}", | ||||
|                 added=datetime.date.isoformat(local_added), | ||||
|                 added_year=local_added.year, | ||||
|                 added_month=f"{local_added.month:02}", | ||||
|                 added_day=f"{local_added.day:02}", | ||||
|                 created=local_created.isoformat(), | ||||
|                 created_year=local_created.strftime("%Y"), | ||||
|                 created_year_short=local_created.strftime("%y"), | ||||
|                 created_month=local_created.strftime("%m"), | ||||
|                 created_month_name=local_created.strftime("%B"), | ||||
|                 created_month_name_short=local_created.strftime("%b"), | ||||
|                 created_day=local_created.strftime("%d"), | ||||
|                 added=local_added.isoformat(), | ||||
|                 added_year=local_added.strftime("%Y"), | ||||
|                 added_year_short=local_added.strftime("%y"), | ||||
|                 added_month=local_added.strftime("%m"), | ||||
|                 added_month_name=local_added.strftime("%B"), | ||||
|                 added_month_name_short=local_added.strftime("%b"), | ||||
|                 added_day=local_added.strftime("%d"), | ||||
|                 asn=asn, | ||||
|                 tags=tags, | ||||
|                 tag_list=tag_list, | ||||
|   | ||||
| @@ -142,14 +142,14 @@ def matches(matching_model, document): | ||||
|         return bool(match) | ||||
|  | ||||
|     elif matching_model.matching_algorithm == MatchingModel.MATCH_FUZZY: | ||||
|         from fuzzywuzzy import fuzz | ||||
|         from rapidfuzz import fuzz | ||||
|  | ||||
|         match = re.sub(r"[^\w\s]", "", matching_model.match) | ||||
|         text = re.sub(r"[^\w\s]", "", document_content) | ||||
|         if matching_model.is_insensitive: | ||||
|             match = match.lower() | ||||
|             text = text.lower() | ||||
|         if fuzz.partial_ratio(match, text) >= 90: | ||||
|         if fuzz.partial_ratio(match, text, score_cutoff=90): | ||||
|             # TODO: make this better | ||||
|             log_reason( | ||||
|                 matching_model, | ||||
|   | ||||
| @@ -400,6 +400,13 @@ def update_filename_and_move_files(sender, instance, **kwargs): | ||||
|  | ||||
|     with FileLock(settings.MEDIA_LOCK): | ||||
|         try: | ||||
|  | ||||
|             # If this was waiting for the lock, the filename or archive_filename | ||||
|             # of this document may have been updated.  This happens if multiple updates | ||||
|             # get queued from the UI for the same document | ||||
|             # So freshen up the data before doing anything | ||||
|             instance.refresh_from_db() | ||||
|  | ||||
|             old_filename = instance.filename | ||||
|             old_source_path = instance.source_path | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,7 @@ except ImportError: | ||||
|     import backports.zoneinfo as zoneinfo | ||||
|  | ||||
| from django.conf import settings | ||||
| from django.utils import timezone | ||||
| from django.test import override_settings | ||||
| from django.test import TestCase | ||||
|  | ||||
| @@ -326,6 +327,12 @@ class TestConsumer(DirectoriesMixin, TestCase): | ||||
|     def testNormalOperation(self): | ||||
|  | ||||
|         filename = self.get_test_file() | ||||
|  | ||||
|         # Get the local time, as an aware datetime | ||||
|         # Roughly equal to file modification time | ||||
|         rough_create_date_local = timezone.localtime(timezone.now()) | ||||
|  | ||||
|         # Consume the file | ||||
|         document = self.consumer.try_consume_file(filename) | ||||
|  | ||||
|         self.assertEqual(document.content, "The Text") | ||||
| @@ -351,7 +358,20 @@ class TestConsumer(DirectoriesMixin, TestCase): | ||||
|  | ||||
|         self._assert_first_last_send_progress() | ||||
|  | ||||
|         self.assertEqual(document.created.tzinfo, zoneinfo.ZoneInfo("America/Chicago")) | ||||
|         # Convert UTC time from DB to local time | ||||
|         document_date_local = timezone.localtime(document.created) | ||||
|  | ||||
|         self.assertEqual( | ||||
|             document_date_local.tzinfo, | ||||
|             zoneinfo.ZoneInfo("America/Chicago"), | ||||
|         ) | ||||
|         self.assertEqual(document_date_local.tzinfo, rough_create_date_local.tzinfo) | ||||
|         self.assertEqual(document_date_local.year, rough_create_date_local.year) | ||||
|         self.assertEqual(document_date_local.month, rough_create_date_local.month) | ||||
|         self.assertEqual(document_date_local.day, rough_create_date_local.day) | ||||
|         self.assertEqual(document_date_local.hour, rough_create_date_local.hour) | ||||
|         self.assertEqual(document_date_local.minute, rough_create_date_local.minute) | ||||
|         # Skipping seconds and more precise | ||||
|  | ||||
|     @override_settings(FILENAME_FORMAT=None) | ||||
|     def testDeleteMacFiles(self): | ||||
|   | ||||
| @@ -1036,6 +1036,34 @@ class TestFilenameGeneration(TestCase): | ||||
|         self.assertEqual(generate_filename(doc_a), "0000002.pdf") | ||||
|         self.assertEqual(generate_filename(doc_b), "SomeImportantNone/2020-07-25.pdf") | ||||
|  | ||||
|     @override_settings( | ||||
|         FILENAME_FORMAT="{created_year_short}/{created_month_name_short}/{created_month_name}/{title}", | ||||
|     ) | ||||
|     def test_short_names_created(self): | ||||
|         doc = Document.objects.create( | ||||
|             title="The Title", | ||||
|             created=timezone.make_aware( | ||||
|                 datetime.datetime(1989, 12, 21, 7, 36, 51, 153), | ||||
|             ), | ||||
|             mime_type="application/pdf", | ||||
|             pk=2, | ||||
|             checksum="2", | ||||
|         ) | ||||
|         self.assertEqual(generate_filename(doc), "89/Dec/December/The Title.pdf") | ||||
|  | ||||
|     @override_settings( | ||||
|         FILENAME_FORMAT="{added_year_short}/{added_month_name}/{added_month_name_short}/{title}", | ||||
|     ) | ||||
|     def test_short_names_added(self): | ||||
|         doc = Document.objects.create( | ||||
|             title="The Title", | ||||
|             added=timezone.make_aware(datetime.datetime(1984, 8, 21, 7, 36, 51, 153)), | ||||
|             mime_type="application/pdf", | ||||
|             pk=2, | ||||
|             checksum="2", | ||||
|         ) | ||||
|         self.assertEqual(generate_filename(doc), "84/August/Aug/The Title.pdf") | ||||
|  | ||||
|  | ||||
| def run(): | ||||
|     doc = Document.objects.create( | ||||
|   | ||||
| @@ -347,6 +347,13 @@ if os.getenv("PAPERLESS_DBHOST"): | ||||
|     if os.getenv("PAPERLESS_DBENGINE") == "mariadb": | ||||
|         engine = "django.db.backends.mysql" | ||||
|         options = {"read_default_file": "/etc/mysql/my.cnf", "charset": "utf8mb4"} | ||||
|  | ||||
|         # Silence Django error on old MariaDB versions. | ||||
|         # VARCHAR can support > 255 in modern versions | ||||
|         # https://docs.djangoproject.com/en/4.1/ref/checks/#database | ||||
|         # https://mariadb.com/kb/en/innodb-system-variables/#innodb_large_prefix | ||||
|         SILENCED_SYSTEM_CHECKS = ["mysql.W003"] | ||||
|  | ||||
|     else:  # Default to PostgresDB | ||||
|         engine = "django.db.backends.postgresql_psycopg2" | ||||
|         options = {"sslmode": os.getenv("PAPERLESS_DBSSLMODE", "prefer")} | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| import datetime | ||||
| import os | ||||
| import time | ||||
| from pathlib import Path | ||||
| from typing import Final | ||||
|  | ||||
| import pytest | ||||
| from django.test import TestCase | ||||
| from documents.parsers import ParseError | ||||
| from paperless_tika.parsers import TikaDocumentParser | ||||
|  | ||||
|  | ||||
| @@ -24,6 +25,44 @@ class TestTikaParserAgainstServer(TestCase): | ||||
|     def tearDown(self) -> None: | ||||
|         self.parser.cleanup() | ||||
|  | ||||
|     def try_parse_with_wait(self, test_file, mime_type): | ||||
|         """ | ||||
|         For whatever reason, the image started during the test pipeline likes to | ||||
|         segfault sometimes, when run with the exact files that usually pass. | ||||
|  | ||||
|         So, this function will retry the parsing up to 3 times, with larger backoff | ||||
|         periods between each attempt, in hopes the issue resolves itself during | ||||
|         one attempt to parse. | ||||
|  | ||||
|         This will wait the following: | ||||
|             - Attempt 1 - 20s following failure | ||||
|             - Attempt 2 - 40s following failure | ||||
|             - Attempt 3 - 80s following failure | ||||
|  | ||||
|         """ | ||||
|         succeeded = False | ||||
|         retry_time = 20.0 | ||||
|         retry_count = 0 | ||||
|         max_retry_count = 3 | ||||
|  | ||||
|         while retry_count < max_retry_count and not succeeded: | ||||
|             try: | ||||
|                 self.parser.parse(test_file, mime_type) | ||||
|  | ||||
|                 succeeded = True | ||||
|             except Exception as e: | ||||
|                 print(f"{e} during try #{retry_count}", flush=True) | ||||
|  | ||||
|                 retry_count = retry_count + 1 | ||||
|  | ||||
|                 time.sleep(retry_time) | ||||
|                 retry_time = retry_time * 2.0 | ||||
|  | ||||
|         self.assertTrue( | ||||
|             succeeded, | ||||
|             "Continued Tika server errors after multiple retries", | ||||
|         ) | ||||
|  | ||||
|     def test_basic_parse_odt(self): | ||||
|         """ | ||||
|         GIVEN: | ||||
| @@ -36,7 +75,7 @@ class TestTikaParserAgainstServer(TestCase): | ||||
|         """ | ||||
|         test_file = self.SAMPLE_DIR / Path("sample.odt") | ||||
|  | ||||
|         self.parser.parse(test_file, "application/vnd.oasis.opendocument.text") | ||||
|         self.try_parse_with_wait(test_file, "application/vnd.oasis.opendocument.text") | ||||
|  | ||||
|         self.assertEqual( | ||||
|             self.parser.text, | ||||
| @@ -62,7 +101,7 @@ class TestTikaParserAgainstServer(TestCase): | ||||
|         """ | ||||
|         test_file = self.SAMPLE_DIR / Path("sample.docx") | ||||
|  | ||||
|         self.parser.parse( | ||||
|         self.try_parse_with_wait( | ||||
|             test_file, | ||||
|             "application/vnd.openxmlformats-officedocument.wordprocessingml.document", | ||||
|         ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 phail
					phail