From 75c8cd9967970a562d6e8fd41bedf39df1c5de94 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Sun, 27 Dec 2020 23:05:19 -0800 Subject: [PATCH 001/105] Dark mode settings logic --- src-ui/src/app/app.component.ts | 6 ++-- .../manage/settings/settings.component.html | 27 ++++++++++++----- .../manage/settings/settings.component.ts | 27 ++++++++++++++--- src-ui/src/app/data/storage-keys.ts | 8 +++-- .../src/app/services/app-view.service.spec.ts | 16 ++++++++++ src-ui/src/app/services/app-view.service.ts | 29 +++++++++++++++++++ 6 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 src-ui/src/app/services/app-view.service.spec.ts create mode 100644 src-ui/src/app/services/app-view.service.ts diff --git a/src-ui/src/app/app.component.ts b/src-ui/src/app/app.component.ts index 84c173a18..9cd9fb3ec 100644 --- a/src-ui/src/app/app.component.ts +++ b/src-ui/src/app/app.component.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core'; +import { AppViewService } from './services/app-view.service'; @Component({ selector: 'app-root', @@ -6,8 +7,9 @@ import { Component } from '@angular/core'; styleUrls: ['./app.component.scss'] }) export class AppComponent { - - constructor () { + + constructor (appViewService: AppViewService) { + appViewService.updateDarkModeSettings() } diff --git a/src-ui/src/app/components/manage/settings/settings.component.html b/src-ui/src/app/components/manage/settings/settings.component.html index 6c16cfaa8..9b999c0dc 100644 --- a/src-ui/src/app/components/manage/settings/settings.component.html +++ b/src-ui/src/app/components/manage/settings/settings.component.html @@ -10,21 +10,34 @@ General settings -

Document list

- +

Appearance

+
Items per page
- + - + +
+
+ +
+
+ Dark mode +
+
+ +
+ + +
@@ -35,7 +48,7 @@
- +
@@ -61,7 +74,7 @@
No saved views defined.
- +
@@ -71,4 +84,4 @@
- \ No newline at end of file + diff --git a/src-ui/src/app/components/manage/settings/settings.component.ts b/src-ui/src/app/components/manage/settings/settings.component.ts index bec85e039..acb456f1c 100644 --- a/src-ui/src/app/components/manage/settings/settings.component.ts +++ b/src-ui/src/app/components/manage/settings/settings.component.ts @@ -1,10 +1,11 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, Renderer2 } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'; import { GENERAL_SETTINGS } from 'src/app/data/storage-keys'; import { DocumentListViewService } from 'src/app/services/document-list-view.service'; import { SavedViewService } from 'src/app/services/rest/saved-view.service'; import { Toast, ToastService } from 'src/app/services/toast.service'; +import { AppViewService } from 'src/app/services/app-view.service'; @Component({ selector: 'app-settings', @@ -17,17 +18,24 @@ export class SettingsComponent implements OnInit { settingsForm = new FormGroup({ 'documentListItemPerPage': new FormControl(+localStorage.getItem(GENERAL_SETTINGS.DOCUMENT_LIST_SIZE) || GENERAL_SETTINGS.DOCUMENT_LIST_SIZE_DEFAULT), + 'darkModeUseSystem': new FormControl( + localStorage.getItem(GENERAL_SETTINGS.DARK_MODE_USE_SYSTEM) == undefined ? GENERAL_SETTINGS.DARK_MODE_USE_SYSTEM_DEFAULT : JSON.parse(localStorage.getItem(GENERAL_SETTINGS.DARK_MODE_USE_SYSTEM)) + ), + 'darkModeEnabled': new FormControl( + localStorage.getItem(GENERAL_SETTINGS.DARK_MODE_ENABLED) == undefined ? GENERAL_SETTINGS.DARK_MODE_ENABLED_DEFAULT : JSON.parse(localStorage.getItem(GENERAL_SETTINGS.DARK_MODE_ENABLED)) + ), 'savedViews': this.savedViewGroup }) + savedViews: PaperlessSavedView[] + constructor( public savedViewService: SavedViewService, private documentListViewService: DocumentListViewService, - private toastService: ToastService + private toastService: ToastService, + private appViewService: AppViewService ) { } - savedViews: PaperlessSavedView[] - ngOnInit() { this.savedViewService.listAll().subscribe(r => { this.savedViews = r.results @@ -50,9 +58,20 @@ export class SettingsComponent implements OnInit { }) } + toggleDarkModeSetting() { + if (this.settingsForm.value.darkModeUseSystem) { + (this.settingsForm.controls.darkModeEnabled as FormControl).disable() + } else { + (this.settingsForm.controls.darkModeEnabled as FormControl).enable() + } + } + private saveLocalSettings() { localStorage.setItem(GENERAL_SETTINGS.DOCUMENT_LIST_SIZE, this.settingsForm.value.documentListItemPerPage) + localStorage.setItem(GENERAL_SETTINGS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem) + localStorage.setItem(GENERAL_SETTINGS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString()) this.documentListViewService.updatePageSize() + this.appViewService.updateDarkModeSettings() this.toastService.showToast(Toast.make("Information", $localize`Settings saved successfully.`)) } diff --git a/src-ui/src/app/data/storage-keys.ts b/src-ui/src/app/data/storage-keys.ts index 13b41d4a7..057d68d70 100644 --- a/src-ui/src/app/data/storage-keys.ts +++ b/src-ui/src/app/data/storage-keys.ts @@ -8,5 +8,9 @@ export const DOCUMENT_LIST_SERVICE = { export const GENERAL_SETTINGS = { DOCUMENT_LIST_SIZE: 'general-settings:documentListSize', - DOCUMENT_LIST_SIZE_DEFAULT: 50 -} \ No newline at end of file + DOCUMENT_LIST_SIZE_DEFAULT: 50, + DARK_MODE_USE_SYSTEM: 'general-settings:darkModeUseSystem', + DARK_MODE_USE_SYSTEM_DEFAULT: true, + DARK_MODE_ENABLED: 'general-settings:darkModeEnabled', + DARK_MODE_ENABLED_DEFAULT: false +} diff --git a/src-ui/src/app/services/app-view.service.spec.ts b/src-ui/src/app/services/app-view.service.spec.ts new file mode 100644 index 000000000..fc44ed3a4 --- /dev/null +++ b/src-ui/src/app/services/app-view.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AppViewService } from './app-view.service'; + +describe('AppViewService', () => { + let service: AppViewService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AppViewService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src-ui/src/app/services/app-view.service.ts b/src-ui/src/app/services/app-view.service.ts new file mode 100644 index 000000000..c6faa5603 --- /dev/null +++ b/src-ui/src/app/services/app-view.service.ts @@ -0,0 +1,29 @@ +import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core'; +import { DOCUMENT } from '@angular/common'; +import { GENERAL_SETTINGS } from 'src/app/data/storage-keys'; + +@Injectable({ + providedIn: 'root' +}) +export class AppViewService { + private renderer: Renderer2; + + constructor(rendererFactory: RendererFactory2, @Inject(DOCUMENT) private document) { + this.renderer = rendererFactory.createRenderer(null, null); + } + + updateDarkModeSettings() { + let darkModeUseSystem = JSON.parse(localStorage.getItem(GENERAL_SETTINGS.DARK_MODE_USE_SYSTEM)) && GENERAL_SETTINGS.DARK_MODE_USE_SYSTEM_DEFAULT + let darkModeEnabled = JSON.parse(localStorage.getItem(GENERAL_SETTINGS.DARK_MODE_ENABLED)) || GENERAL_SETTINGS.DARK_MODE_ENABLED_DEFAULT + + if (darkModeUseSystem) { + this.renderer.addClass(this.document.body, 'dark-mode-preferred') + this.renderer.removeClass(this.document.body, 'dark-mode') + } else { + this.renderer.removeClass(this.document.body, 'dark-mode-preferred') + darkModeEnabled ? this.renderer.addClass(this.document.body, 'dark-mode') : this.renderer.removeClass(this.document.body, 'dark-mode') + } + + } + +} From 28b7c3c20867e97eae9a3d9ff4fc04a66d1cef7a Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Sun, 27 Dec 2020 23:05:34 -0800 Subject: [PATCH 002/105] Logo svg inline --- .../app-frame/app-frame.component.html | 4 +- src-ui/src/assets/logo-dark-notext.svg | 86 ++++--------------- src-ui/src/assets/logo-white-notext.svg | 69 +++++++++++++++ 3 files changed, 90 insertions(+), 69 deletions(-) create mode 100644 src-ui/src/assets/logo-white-notext.svg diff --git a/src-ui/src/app/components/app-frame/app-frame.component.html b/src-ui/src/app/components/app-frame/app-frame.component.html index d191ec0de..6fd2a579e 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.html +++ b/src-ui/src/app/components/app-frame/app-frame.component.html @@ -1,6 +1,8 @@ diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index 5ace8a2ff..433fe3054 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -72,17 +72,42 @@ padding-top: .75rem; padding-bottom: .75rem; font-size: 1rem; - background-color: rgba(0, 0, 0, .25); - box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25); } -.navbar .navbar-toggler { - top: .25rem; - right: 1rem; -} +.navbar .search-form-container { + max-width: 550px; + position: relative; -.navbar .form-control { - padding: .75rem 1rem; - border-width: 0; - border-radius: 0; + svg { + position: absolute; + left: 1.8em; + color: rgba(255, 255, 255, 0.6); + } + + &:focus-within { + svg { + display: none; + } + } + + .form-control { + color: rgba(255, 255, 255, 0.5); + background-color: rgba(0, 0, 0, 0.2); + padding-left: 1.8rem; + border-color: rgba(255, 255, 255, 0.5); + transition: flex 0.3s ease; + max-width: 600px; + min-width: 300px; // 1/2 max + + &::placeholder { + color: rgba(255, 255, 255, 0.5); + } + + &:focus { + background-color: #fff; + color: initial; + flex-grow: 1; + padding-left: 0.5rem; + } + } } From 2e544326e57fadd108c8473e3c6b6c0ec3ff9b4e Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Thu, 31 Dec 2020 00:35:54 -0800 Subject: [PATCH 047/105] Toggle caret tweaks --- .../app-frame/app-frame.component.scss | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index 433fe3054..44b1531b1 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -1,23 +1,19 @@ - @import "/src/theme"; - - /* +/* * Sidebar */ - - .sidebar { +.sidebar { position: fixed; top: 0; bottom: 0; left: 0; z-index: 100; /* Behind the navbar */ - padding: 48px 0 0; /* Height of navbar */ + padding: 50px 0 0; /* Height of navbar */ box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1); } - @media (max-width: 767.98px) { .sidebar { - top: 3rem; + top: 3.5rem; } } @@ -26,11 +22,11 @@ top: 0; /* height: calc(100vh - 48px); */ height: 100%; - padding-top: .5rem; + padding-top: 0.5rem; overflow-x: hidden; - overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ + overflow-y: auto; + /* Scrollable contents if viewport is shorter than content. */ } - @supports ((position: -webkit-sticky) or (position: sticky)) { .sidebar-sticky { position: -webkit-sticky; @@ -53,27 +49,33 @@ font-weight: bold; } -.sidebar .nav-link:hover .sidebaricon, -.sidebar .nav-link.active .sidebaricon { +.sidebar .nav-link.active .sidebaricon, +.sidebar .nav-link:hover .sidebaricon { color: inherit; } .sidebar-heading { - font-size: .75rem; + font-size: 0.75rem; text-transform: uppercase; } - /* * Navbar */ - - .navbar-brand { - padding-top: .75rem; - padding-bottom: .75rem; +.navbar-brand { + padding-top: 0.75rem; + padding-bottom: 0.75rem; font-size: 1rem; } +.navbar-toggler { +} + +.dropdown-toggle::after { + margin-left: 0.4em; + vertical-align: 0.155em; +} + .navbar .search-form-container { max-width: 550px; position: relative; @@ -91,16 +93,16 @@ } .form-control { - color: rgba(255, 255, 255, 0.5); - background-color: rgba(0, 0, 0, 0.2); + color: rgba(255, 255, 255, 0.3); + background-color: rgba(0, 0, 0, 0.15); padding-left: 1.8rem; - border-color: rgba(255, 255, 255, 0.5); + border-color: rgba(255, 255, 255, 0.2); transition: flex 0.3s ease; max-width: 600px; min-width: 300px; // 1/2 max &::placeholder { - color: rgba(255, 255, 255, 0.5); + color: rgba(255, 255, 255, 0.4); } &:focus { From 2a744a3a83cab33d37458bdb79c996c3ee040cf2 Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Thu, 31 Dec 2020 11:12:46 +0100 Subject: [PATCH 048/105] roll back changes #184 #227 --- docker/gunicorn.conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/gunicorn.conf.py b/docker/gunicorn.conf.py index 5c9c0eb37..edfb362d9 100644 --- a/docker/gunicorn.conf.py +++ b/docker/gunicorn.conf.py @@ -1,4 +1,4 @@ -bind = ['[::]:8000', 'localhost:8000'] +bind = '0.0.0.0:8000' backlog = 2048 workers = 3 worker_class = 'sync' From 70cb27bf0a04eab157bc1d91d7084f1a29a6bbc3 Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Thu, 31 Dec 2020 11:23:03 +0100 Subject: [PATCH 049/105] bump versions --- docker/hub/docker-compose.postgres.yml | 2 +- docker/hub/docker-compose.sqlite.yml | 2 +- docs/changelog.rst | 7 +++++++ src-ui/src/environments/environment.prod.ts | 2 +- src/paperless/version.py | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docker/hub/docker-compose.postgres.yml b/docker/hub/docker-compose.postgres.yml index c2b599e52..0779cea22 100644 --- a/docker/hub/docker-compose.postgres.yml +++ b/docker/hub/docker-compose.postgres.yml @@ -15,7 +15,7 @@ services: POSTGRES_PASSWORD: paperless webserver: - image: jonaswinkler/paperless-ng:0.9.10 + image: jonaswinkler/paperless-ng:0.9.11 restart: always depends_on: - db diff --git a/docker/hub/docker-compose.sqlite.yml b/docker/hub/docker-compose.sqlite.yml index 429d42c06..3eed96cc3 100644 --- a/docker/hub/docker-compose.sqlite.yml +++ b/docker/hub/docker-compose.sqlite.yml @@ -5,7 +5,7 @@ services: restart: always webserver: - image: jonaswinkler/paperless-ng:0.9.10 + image: jonaswinkler/paperless-ng:0.9.11 restart: always depends_on: - broker diff --git a/docs/changelog.rst b/docs/changelog.rst index fe4d89a55..70f5cf683 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,13 @@ Changelog ********* + +paperless-ng 0.9.11 +################### + +* Fixed an issue with the docker image not starting at all due to a configuration change of the web server. + + paperless-ng 0.9.10 ################### diff --git a/src-ui/src/environments/environment.prod.ts b/src-ui/src/environments/environment.prod.ts index 7b707f014..1ac69bc39 100644 --- a/src-ui/src/environments/environment.prod.ts +++ b/src-ui/src/environments/environment.prod.ts @@ -2,5 +2,5 @@ export const environment = { production: true, apiBaseUrl: "/api/", appTitle: "Paperless-ng", - version: "0.9.10" + version: "0.9.11" }; diff --git a/src/paperless/version.py b/src/paperless/version.py index facb097fc..e1ba14cb4 100644 --- a/src/paperless/version.py +++ b/src/paperless/version.py @@ -1 +1 @@ -__version__ = (0, 9, 10) +__version__ = (0, 9, 11) From 5236f4e58d26508a4c4d06c1b2e8a4a18822fc2f Mon Sep 17 00:00:00 2001 From: Jo Vandeginste Date: Thu, 31 Dec 2020 14:41:47 +0100 Subject: [PATCH 050/105] Refactor after feedback: - rename PAPERLESS_TIKA to PAPERLESS_TIKA_ENABLED - all other env params now start with PAPERLESS_TIKA - convert_to_pdf as class instance method - smaller details Signed-off-by: Jo Vandeginste --- docker/hub/docker-compose.tika.yml | 6 +-- docker/local/docker-compose.tika.yml | 6 +-- docs/configuration.rst | 6 +-- src/paperless/settings.py | 7 ++- src/paperless_tika/apps.py | 2 +- src/paperless_tika/parsers.py | 65 +++++++++++++--------------- src/paperless_tika/test.py | 3 -- 7 files changed, 46 insertions(+), 49 deletions(-) delete mode 100644 src/paperless_tika/test.py diff --git a/docker/hub/docker-compose.tika.yml b/docker/hub/docker-compose.tika.yml index 04dd3260e..af8f575a0 100644 --- a/docker/hub/docker-compose.tika.yml +++ b/docker/hub/docker-compose.tika.yml @@ -24,9 +24,9 @@ services: env_file: docker-compose.env environment: PAPERLESS_REDIS: redis://broker:6379 - PAPERLESS_TIKA: 1 - GOTENBERG_SERVER_ENDPOINT: http://gotenberg:3000 - TIKA_SERVER_ENDPOINT: http://tika:9998 + PAPERLESS_TIKA_ENABLED: 1 + PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000 + PAPERLESS_TIKA_ENDPOINT: http://tika:9998 gotenberg: image: thecodingmachine/gotenberg diff --git a/docker/local/docker-compose.tika.yml b/docker/local/docker-compose.tika.yml index ab901f306..889713908 100644 --- a/docker/local/docker-compose.tika.yml +++ b/docker/local/docker-compose.tika.yml @@ -24,9 +24,9 @@ services: env_file: docker-compose.env environment: PAPERLESS_REDIS: redis://broker:6379 - PAPERLESS_TIKA: 1 - GOTENBERG_SERVER_ENDPOINT: http://gotenberg:3000 - TIKA_SERVER_ENDPOINT: http://tika:9998 + PAPERLESS_TIKA_ENABLED: 1 + PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000 + PAPERLESS_TIKA_ENDPOINT: http://tika:9998 gotenberg: image: thecodingmachine/gotenberg diff --git a/docs/configuration.rst b/docs/configuration.rst index f53acb633..49c95bff1 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -291,17 +291,17 @@ configure their endpoints, and enable the feature. If you run paperless on docker, you can add those services to the docker-compose file (see the examples provided). -PAPERLESS_TIKA= +PAPERLESS_TIKA_ENABLED= Enable (or disable) the Tika parser. Defaults to false. -TIKA_SERVER_ENDPOINT= +PAPERLESS_TIKA_ENDPOINT= Set the endpoint URL were Paperless can reach your Tika server. Defaults to "http://localhost:9998". -GOTENBERG_SERVER_ENDPOINT= +PAPERLESS_TIKA_GOTENBERG_ENDPOINT= Set the endpoint URL were Paperless can reach your Gotenberg server. Defaults to "http://localhost:3000". diff --git a/src/paperless/settings.py b/src/paperless/settings.py index 219166cf5..caa1b9b18 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -427,5 +427,8 @@ PAPERLESS_FILENAME_FORMAT = os.getenv("PAPERLESS_FILENAME_FORMAT") THUMBNAIL_FONT_NAME = os.getenv("PAPERLESS_THUMBNAIL_FONT_NAME", "/usr/share/fonts/liberation/LiberationSerif-Regular.ttf") # Tika settings -PAPERLESS_TIKA = __get_boolean("PAPERLESS_TIKA", "NO") -GOTENBERG_SERVER_ENDPOINT = os.getenv("GOTENBERG_SERVER_ENDPOINT", "http://localhost:3000") +PAPERLESS_TIKA_ENABLED = __get_boolean("PAPERLESS_TIKA_ENABLED", "NO") +PAPERLESS_TIKA_ENDPOINT = os.getenv("PAPERLESS_TIKA_ENDPOINT", "http://localhost:9998") +PAPERLESS_TIKA_GOTENBERG_ENDPOINT = os.getenv( + "PAPERLESS_TIKA_GOTENBERG_ENDPOINT", "http://localhost:3000" +) diff --git a/src/paperless_tika/apps.py b/src/paperless_tika/apps.py index c29586d6a..5cab21427 100644 --- a/src/paperless_tika/apps.py +++ b/src/paperless_tika/apps.py @@ -9,6 +9,6 @@ class PaperlessTikaConfig(AppConfig): def ready(self): from documents.signals import document_consumer_declaration - if settings.PAPERLESS_TIKA: + if settings.PAPERLESS_TIKA_ENABLED: document_consumer_declaration.connect(tika_consumer_declaration) AppConfig.ready(self) diff --git a/src/paperless_tika/parsers.py b/src/paperless_tika/parsers.py index 5a77681f2..81f213a6b 100644 --- a/src/paperless_tika/parsers.py +++ b/src/paperless_tika/parsers.py @@ -70,49 +70,46 @@ class TikaDocumentParser(DocumentParser): def parse(self, document_path, mime_type): self.log("info", f"[TIKA_PARSE] Sending {document_path} to Tika server") + tika_server = settings.PAPERLESS_TIKA_ENDPOINT try: - parsed = parser.from_file(document_path) + parsed = parser.from_file(document_path, tika_server) except requests.exceptions.HTTPError as err: - raise ParseError(f"Could not parse {document_path} with tika server: {err}") - - try: - content = parsed["content"].strip() - except: - content = "" - - try: - creation_date = dateutil.parser.isoparse( - parsed["metadata"]["Creation-Date"] + raise ParseError( + f"Could not parse {document_path} with tika server at {tika_server}: {err}" ) + + try: + self.text = parsed["content"].strip() except: - creation_date = None + pass + + try: + self.date = dateutil.parser.isoparse(parsed["metadata"]["Creation-Date"]) + except: + pass archive_path = os.path.join(self.tempdir, "convert.pdf") - convert_to_pdf(self, document_path, archive_path) - + convert_to_pdf(document_path, archive_path) self.archive_path = archive_path - self.date = creation_date - self.text = content + def convert_to_pdf(document_path, pdf_path): + pdf_path = os.path.join(self.tempdir, "convert.pdf") + gotenberg_server = settings.PAPERLESS_TIKA_GOTENBERG_ENDPOINT + url = gotenberg_server + "/convert/office" -def convert_to_pdf(self, document_path, pdf_path): - pdf_path = os.path.join(self.tempdir, "convert.pdf") - gotenberg_server = settings.GOTENBERG_SERVER_ENDPOINT - url = gotenberg_server + "/convert/office" + self.log("info", f"[TIKA] Converting {document_path} to PDF as {pdf_path}") + files = {"files": open(document_path, "rb")} + headers = {} - self.log("info", f"[TIKA] Converting {document_path} to PDF as {pdf_path}") - files = {"files": open(document_path, "rb")} - headers = {} + try: + response = requests.post(url, files=files, headers=headers) + response.raise_for_status() # ensure we notice bad responses + except requests.exceptions.HTTPError as err: + raise ParseError( + f"Could not contact gotenberg server at {gotenberg_server}: {err}" + ) - try: - response = requests.post(url, files=files, headers=headers) - response.raise_for_status() # ensure we notice bad responses - except requests.exceptions.HTTPError as err: - raise ParseError( - f"Could not contact gotenberg server at {gotenberg_server}: {err}" - ) - - file = open(pdf_path, "wb") - file.write(response.content) - file.close() + file = open(pdf_path, "wb") + file.write(response.content) + file.close() diff --git a/src/paperless_tika/test.py b/src/paperless_tika/test.py deleted file mode 100644 index 0a2885226..000000000 --- a/src/paperless_tika/test.py +++ /dev/null @@ -1,3 +0,0 @@ -import magic -m = magic.from_file("/nfsstorage/jo/syncthing/Documenten/20R-309.153.052.pdf") -print(m) From aa7e2594e2c747dedefd113e88ad28464c5a3747 Mon Sep 17 00:00:00 2001 From: Stefan Date: Thu, 31 Dec 2020 15:07:35 +0100 Subject: [PATCH 051/105] self serve pdf.worker.min.js --- src-ui/angular.json | 6 +++++- src-ui/src/app/app.component.ts | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src-ui/angular.json b/src-ui/angular.json index ce2dd82f7..db8c66b19 100644 --- a/src-ui/angular.json +++ b/src-ui/angular.json @@ -27,7 +27,11 @@ "assets": [ "src/favicon.ico", "src/assets", - "src/manifest.webmanifest" + "src/manifest.webmanifest", { + "glob": "pdf.worker.min.js", + "input": "node_modules/pdfjs-dist/build/", + "output": "/assets/js/" + } ], "styles": [ "src/styles.scss" diff --git a/src-ui/src/app/app.component.ts b/src-ui/src/app/app.component.ts index 84c173a18..330f8f157 100644 --- a/src-ui/src/app/app.component.ts +++ b/src-ui/src/app/app.component.ts @@ -6,8 +6,9 @@ import { Component } from '@angular/core'; styleUrls: ['./app.component.scss'] }) export class AppComponent { - + constructor () { + (window as any).pdfWorkerSrc = '/assets/js/pdf.worker.min.js'; } From fddda75f75e6ae207d91d252c2ac3195c29aef9a Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Thu, 31 Dec 2020 15:59:12 +0100 Subject: [PATCH 052/105] more translation --- src/documents/models.py | 5 +- src/paperless_mail/admin.py | 26 +++++----- src/paperless_mail/models.py | 96 ++++++++++++++++++++++++------------ 3 files changed, 81 insertions(+), 46 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 6395d66aa..2349dacd1 100755 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -122,7 +122,6 @@ class DocumentType(MatchingModel): verbose_name_plural = _("document types") - class Document(models.Model): STORAGE_TYPE_UNENCRYPTED = "unencrypted" @@ -230,8 +229,8 @@ class Document(models.Model): class Meta: ordering = ("-created",) - verbose_name = _("Document") - verbose_name_plural = _("Documents") + verbose_name = _("document") + verbose_name_plural = _("documents") def __str__(self): created = datetime.date.isoformat(self.created) diff --git a/src/paperless_mail/admin.py b/src/paperless_mail/admin.py index 0440234b7..4c63c2b29 100644 --- a/src/paperless_mail/admin.py +++ b/src/paperless_mail/admin.py @@ -1,6 +1,8 @@ from django.contrib import admin from paperless_mail.models import MailAccount, MailRule +from django.utils.translation import gettext_lazy as _ + class MailAccountAdmin(admin.ModelAdmin): @@ -19,31 +21,31 @@ class MailRuleAdmin(admin.ModelAdmin): (None, { 'fields': ('name', 'order', 'account', 'folder') }), - ("Filter", { + (_("Filter"), { 'description': - "Paperless will only process mails that match ALL of the " - "filters given below.", + _("Paperless will only process mails that match ALL of the " + "filters given below."), 'fields': ('filter_from', 'filter_subject', 'filter_body', 'maximum_age') }), - ("Actions", { + (_("Actions"), { 'description': - "The action applied to the mail. This action is only " - "performed when documents were consumed from the mail. Mails " - "without attachments will remain entirely untouched.", + _("The action applied to the mail. This action is only " + "performed when documents were consumed from the mail. " + "Mails without attachments will remain entirely untouched."), 'fields': ( 'action', 'action_parameter') }), - ("Metadata", { + (_("Metadata"), { 'description': - "Assign metadata to documents consumed from this rule " - "automatically. If you do not assign tags, types or " - "correspondents here, paperless will still process all " - "matching rules that you have defined.", + _("Assign metadata to documents consumed from this rule " + "automatically. If you do not assign tags, types or " + "correspondents here, paperless will still process all " + "matching rules that you have defined."), "fields": ( 'assign_title_from', 'assign_tag', diff --git a/src/paperless_mail/models.py b/src/paperless_mail/models.py index aa1ac5684..d585d7c1c 100644 --- a/src/paperless_mail/models.py +++ b/src/paperless_mail/models.py @@ -2,6 +2,8 @@ from django.db import models import documents.models as document_models +from django.utils.translation import gettext_lazy as _ + class MailAccount(models.Model): @@ -10,29 +12,39 @@ class MailAccount(models.Model): IMAP_SECURITY_STARTTLS = 3 IMAP_SECURITY_OPTIONS = ( - (IMAP_SECURITY_NONE, "No encryption"), - (IMAP_SECURITY_SSL, "Use SSL"), - (IMAP_SECURITY_STARTTLS, "Use STARTTLS"), + (IMAP_SECURITY_NONE, _("No encryption")), + (IMAP_SECURITY_SSL, _("Use SSL")), + (IMAP_SECURITY_STARTTLS, _("Use STARTTLS")), ) - name = models.CharField(max_length=256, unique=True) + name = models.CharField( + _("name"), + max_length=256, unique=True) - imap_server = models.CharField(max_length=256) + imap_server = models.CharField( + _("imap server"), + max_length=256) imap_port = models.IntegerField( + _("imap port"), blank=True, null=True, - help_text="This is usually 143 for unencrypted and STARTTLS " - "connections, and 993 for SSL connections.") + help_text=_("This is usually 143 for unencrypted and STARTTLS " + "connections, and 993 for SSL connections.")) imap_security = models.PositiveIntegerField( + _("imap security"), choices=IMAP_SECURITY_OPTIONS, default=IMAP_SECURITY_SSL ) - username = models.CharField(max_length=256) + username = models.CharField( + _("username"), + max_length=256) - password = models.CharField(max_length=256) + password = models.CharField( + _("password"), + max_length=256) def __str__(self): return self.name @@ -46,18 +58,18 @@ class MailRule(models.Model): ACTION_FLAG = 4 ACTIONS = ( - (ACTION_MARK_READ, "Mark as read, don't process read mails"), - (ACTION_FLAG, "Flag the mail, don't process flagged mails"), - (ACTION_MOVE, "Move to specified folder"), - (ACTION_DELETE, "Delete"), + (ACTION_MARK_READ, _("Mark as read, don't process read mails")), + (ACTION_FLAG, _("Flag the mail, don't process flagged mails")), + (ACTION_MOVE, _("Move to specified folder")), + (ACTION_DELETE, _("Delete")), ) TITLE_FROM_SUBJECT = 1 TITLE_FROM_FILENAME = 2 TITLE_SELECTOR = ( - (TITLE_FROM_SUBJECT, "Use subject as title"), - (TITLE_FROM_FILENAME, "Use attachment filename as title") + (TITLE_FROM_SUBJECT, _("Use subject as title")), + (TITLE_FROM_FILENAME, _("Use attachment filename as title")) ) CORRESPONDENT_FROM_NOTHING = 1 @@ -67,47 +79,65 @@ class MailRule(models.Model): CORRESPONDENT_SELECTOR = ( (CORRESPONDENT_FROM_NOTHING, - "Do not assign a correspondent"), + _("Do not assign a correspondent")), (CORRESPONDENT_FROM_EMAIL, "Use mail address"), (CORRESPONDENT_FROM_NAME, - "Use name (or mail address if not available)"), + _("Use name (or mail address if not available)")), (CORRESPONDENT_FROM_CUSTOM, - "Use correspondent selected below") + _("Use correspondent selected below")) ) - name = models.CharField(max_length=256, unique=True) + name = models.CharField( + _("name"), + max_length=256, unique=True) - order = models.IntegerField(default=0) + order = models.IntegerField( + _("order"), + default=0) account = models.ForeignKey( MailAccount, related_name="rules", - on_delete=models.CASCADE + on_delete=models.CASCADE, + verbose_name=_("account") ) - folder = models.CharField(default='INBOX', max_length=256) + folder = models.CharField( + _("folder"), + default='INBOX', max_length=256) - filter_from = models.CharField(max_length=256, null=True, blank=True) - filter_subject = models.CharField(max_length=256, null=True, blank=True) - filter_body = models.CharField(max_length=256, null=True, blank=True) + filter_from = models.CharField( + _("filter from"), + max_length=256, null=True, blank=True) + filter_subject = models.CharField( + _("filter subject"), + max_length=256, null=True, blank=True) + filter_body = models.CharField( + _("filter body"), + max_length=256, null=True, blank=True) maximum_age = models.PositiveIntegerField( + _("maximum age"), default=30, - help_text="Specified in days.") + help_text=_("Specified in days.")) action = models.PositiveIntegerField( + _("action"), choices=ACTIONS, default=ACTION_MARK_READ, ) action_parameter = models.CharField( + _("action parameter"), max_length=256, blank=True, null=True, - help_text="Additional parameter for the action selected above, i.e., " - "the target folder of the move to folder action." + help_text=_("Additional parameter for the action selected above, " + "i.e., " + "the target folder of the move to folder action.") ) assign_title_from = models.PositiveIntegerField( + _("assign title from"), choices=TITLE_SELECTOR, default=TITLE_FROM_SUBJECT ) @@ -116,17 +146,20 @@ class MailRule(models.Model): document_models.Tag, null=True, blank=True, - on_delete=models.SET_NULL + on_delete=models.SET_NULL, + verbose_name=_("assign this tag"), ) assign_document_type = models.ForeignKey( document_models.DocumentType, null=True, blank=True, - on_delete=models.SET_NULL + on_delete=models.SET_NULL, + verbose_name=_("assign this document type"), ) assign_correspondent_from = models.PositiveIntegerField( + _("assign correspondent from"), choices=CORRESPONDENT_SELECTOR, default=CORRESPONDENT_FROM_NOTHING ) @@ -135,7 +168,8 @@ class MailRule(models.Model): document_models.Correspondent, null=True, blank=True, - on_delete=models.SET_NULL + on_delete=models.SET_NULL, + verbose_name=_("assign this correspondent") ) def __str__(self): From 71d7aa3fb25544df35e4156d2162aca245abff90 Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Thu, 31 Dec 2020 16:00:24 +0100 Subject: [PATCH 053/105] update message file --- src/locale/en-us/LC_MESSAGES/django.po | 296 +++++++++++++++++++------ 1 file changed, 234 insertions(+), 62 deletions(-) diff --git a/src/locale/en-us/LC_MESSAGES/django.po b/src/locale/en-us/LC_MESSAGES/django.po index c3c76c5a4..0af8b7217 100644 --- a/src/locale/en-us/LC_MESSAGES/django.po +++ b/src/locale/en-us/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-30 19:20+0000\n" +"POT-Creation-Date: 2020-12-31 14:39+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -41,7 +41,8 @@ msgstr "" msgid "Automatic Classification" msgstr "" -#: documents/models.py:41 documents/models.py:355 +#: documents/models.py:41 documents/models.py:354 paperless_mail/models.py:21 +#: paperless_mail/models.py:92 msgid "name" msgstr "" @@ -57,7 +58,7 @@ msgstr "" msgid "is insensitive" msgstr "" -#: documents/models.py:80 documents/models.py:141 +#: documents/models.py:80 documents/models.py:140 msgid "correspondent" msgstr "" @@ -83,11 +84,11 @@ msgstr "" msgid "tag" msgstr "" -#: documents/models.py:115 documents/models.py:172 +#: documents/models.py:115 documents/models.py:171 msgid "tags" msgstr "" -#: documents/models.py:121 documents/models.py:154 +#: documents/models.py:121 documents/models.py:153 msgid "document type" msgstr "" @@ -95,221 +96,221 @@ msgstr "" msgid "document types" msgstr "" -#: documents/models.py:131 +#: documents/models.py:130 msgid "Unencrypted" msgstr "" -#: documents/models.py:132 +#: documents/models.py:131 msgid "Encrypted with GNU Privacy Guard" msgstr "" -#: documents/models.py:145 +#: documents/models.py:144 msgid "title" msgstr "" -#: documents/models.py:158 +#: documents/models.py:157 msgid "content" msgstr "" -#: documents/models.py:160 +#: documents/models.py:159 msgid "" "The raw, text-only data of the document. This field is primarily used for " "searching." msgstr "" -#: documents/models.py:165 +#: documents/models.py:164 msgid "mime type" msgstr "" -#: documents/models.py:176 +#: documents/models.py:175 msgid "checksum" msgstr "" -#: documents/models.py:180 +#: documents/models.py:179 msgid "The checksum of the original document." msgstr "" -#: documents/models.py:184 +#: documents/models.py:183 msgid "archive checksum" msgstr "" -#: documents/models.py:189 +#: documents/models.py:188 msgid "The checksum of the archived document." msgstr "" -#: documents/models.py:193 documents/models.py:333 +#: documents/models.py:192 documents/models.py:332 msgid "created" msgstr "" -#: documents/models.py:197 +#: documents/models.py:196 msgid "modified" msgstr "" -#: documents/models.py:201 +#: documents/models.py:200 msgid "storage type" msgstr "" -#: documents/models.py:209 +#: documents/models.py:208 msgid "added" msgstr "" -#: documents/models.py:213 +#: documents/models.py:212 msgid "filename" msgstr "" -#: documents/models.py:218 +#: documents/models.py:217 msgid "Current filename in storage" msgstr "" -#: documents/models.py:222 +#: documents/models.py:221 msgid "archive serial number" msgstr "" -#: documents/models.py:227 +#: documents/models.py:226 msgid "The position of this document in your physical document archive." msgstr "" +#: documents/models.py:232 +msgid "document" +msgstr "" + #: documents/models.py:233 -msgid "Document" +msgid "documents" msgstr "" -#: documents/models.py:234 -msgid "Documents" -msgstr "" - -#: documents/models.py:324 +#: documents/models.py:323 msgid "group" msgstr "" -#: documents/models.py:327 +#: documents/models.py:326 msgid "message" msgstr "" -#: documents/models.py:330 +#: documents/models.py:329 msgid "level" msgstr "" -#: documents/models.py:337 +#: documents/models.py:336 msgid "log" msgstr "" -#: documents/models.py:338 +#: documents/models.py:337 msgid "logs" msgstr "" -#: documents/models.py:349 documents/models.py:399 +#: documents/models.py:348 documents/models.py:398 msgid "saved view" msgstr "" -#: documents/models.py:350 +#: documents/models.py:349 msgid "saved views" msgstr "" -#: documents/models.py:353 +#: documents/models.py:352 msgid "user" msgstr "" -#: documents/models.py:359 +#: documents/models.py:358 msgid "show on dashboard" msgstr "" -#: documents/models.py:362 +#: documents/models.py:361 msgid "show in sidebar" msgstr "" -#: documents/models.py:366 +#: documents/models.py:365 msgid "sort field" msgstr "" -#: documents/models.py:369 +#: documents/models.py:368 msgid "sort reverse" msgstr "" -#: documents/models.py:375 +#: documents/models.py:374 msgid "title contains" msgstr "" -#: documents/models.py:376 +#: documents/models.py:375 msgid "content contains" msgstr "" -#: documents/models.py:377 +#: documents/models.py:376 msgid "ASN is" msgstr "" -#: documents/models.py:378 +#: documents/models.py:377 msgid "correspondent is" msgstr "" -#: documents/models.py:379 +#: documents/models.py:378 msgid "document type is" msgstr "" -#: documents/models.py:380 +#: documents/models.py:379 msgid "is in inbox" msgstr "" -#: documents/models.py:381 +#: documents/models.py:380 msgid "has tag" msgstr "" -#: documents/models.py:382 +#: documents/models.py:381 msgid "has any tag" msgstr "" -#: documents/models.py:383 +#: documents/models.py:382 msgid "created before" msgstr "" -#: documents/models.py:384 +#: documents/models.py:383 msgid "created after" msgstr "" -#: documents/models.py:385 +#: documents/models.py:384 msgid "created year is" msgstr "" -#: documents/models.py:386 +#: documents/models.py:385 msgid "created month is" msgstr "" -#: documents/models.py:387 +#: documents/models.py:386 msgid "created day is" msgstr "" -#: documents/models.py:388 +#: documents/models.py:387 msgid "added before" msgstr "" -#: documents/models.py:389 +#: documents/models.py:388 msgid "added after" msgstr "" -#: documents/models.py:390 +#: documents/models.py:389 msgid "modified before" msgstr "" -#: documents/models.py:391 +#: documents/models.py:390 msgid "modified after" msgstr "" -#: documents/models.py:392 +#: documents/models.py:391 msgid "does not have tag" msgstr "" -#: documents/models.py:403 +#: documents/models.py:402 msgid "rule type" msgstr "" -#: documents/models.py:407 +#: documents/models.py:406 msgid "value" msgstr "" -#: documents/models.py:411 +#: documents/models.py:410 msgid "filter rule" msgstr "" -#: documents/models.py:412 +#: documents/models.py:411 msgid "filter rules" msgstr "" @@ -320,3 +321,174 @@ msgstr "" #: paperless/settings.py:254 msgid "German" msgstr "" + +#: paperless_mail/admin.py:24 +msgid "Filter" +msgstr "" + +#: paperless_mail/admin.py:26 +msgid "" +"Paperless will only process mails that match ALL of the filters given below." +msgstr "" + +#: paperless_mail/admin.py:34 +msgid "Actions" +msgstr "" + +#: paperless_mail/admin.py:36 +msgid "" +"The action applied to the mail. This action is only performed when documents " +"were consumed from the mail. Mails without attachments will remain entirely " +"untouched." +msgstr "" + +#: paperless_mail/admin.py:43 +msgid "Metadata" +msgstr "" + +#: paperless_mail/admin.py:45 +msgid "" +"Assign metadata to documents consumed from this rule automatically. If you " +"do not assign tags, types or correspondents here, paperless will still " +"process all matching rules that you have defined." +msgstr "" + +#: paperless_mail/models.py:15 +msgid "No encryption" +msgstr "" + +#: paperless_mail/models.py:16 +msgid "Use SSL" +msgstr "" + +#: paperless_mail/models.py:17 +msgid "Use STARTTLS" +msgstr "" + +#: paperless_mail/models.py:25 +msgid "imap server" +msgstr "" + +#: paperless_mail/models.py:29 +msgid "imap port" +msgstr "" + +#: paperless_mail/models.py:32 +msgid "" +"This is usually 143 for unencrypted and STARTTLS connections, and 993 for " +"SSL connections." +msgstr "" + +#: paperless_mail/models.py:36 +msgid "imap security" +msgstr "" + +#: paperless_mail/models.py:42 +msgid "username" +msgstr "" + +#: paperless_mail/models.py:46 +msgid "password" +msgstr "" + +#: paperless_mail/models.py:61 +msgid "Mark as read, don't process read mails" +msgstr "" + +#: paperless_mail/models.py:62 +msgid "Flag the mail, don't process flagged mails" +msgstr "" + +#: paperless_mail/models.py:63 +msgid "Move to specified folder" +msgstr "" + +#: paperless_mail/models.py:64 +msgid "Delete" +msgstr "" + +#: paperless_mail/models.py:71 +msgid "Use subject as title" +msgstr "" + +#: paperless_mail/models.py:72 +msgid "Use attachment filename as title" +msgstr "" + +#: paperless_mail/models.py:82 +msgid "Do not assign a correspondent" +msgstr "" + +#: paperless_mail/models.py:86 +msgid "Use name (or mail address if not available)" +msgstr "" + +#: paperless_mail/models.py:88 +msgid "Use correspondent selected below" +msgstr "" + +#: paperless_mail/models.py:96 +msgid "order" +msgstr "" + +#: paperless_mail/models.py:103 +msgid "account" +msgstr "" + +#: paperless_mail/models.py:107 +msgid "folder" +msgstr "" + +#: paperless_mail/models.py:111 +msgid "filter from" +msgstr "" + +#: paperless_mail/models.py:114 +msgid "filter subject" +msgstr "" + +#: paperless_mail/models.py:117 +msgid "filter body" +msgstr "" + +#: paperless_mail/models.py:121 +msgid "maximum age" +msgstr "" + +#: paperless_mail/models.py:123 +msgid "Specified in days." +msgstr "" + +#: paperless_mail/models.py:126 +msgid "action" +msgstr "" + +#: paperless_mail/models.py:132 +msgid "action parameter" +msgstr "" + +#: paperless_mail/models.py:134 +msgid "" +"Additional parameter for the action selected above, i.e., the target folder " +"of the move to folder action." +msgstr "" + +#: paperless_mail/models.py:140 +msgid "assign title from" +msgstr "" + +#: paperless_mail/models.py:150 +msgid "assign this tag" +msgstr "" + +#: paperless_mail/models.py:158 +msgid "assign this document type" +msgstr "" + +#: paperless_mail/models.py:162 +msgid "assign correspondent from" +msgstr "" + +#: paperless_mail/models.py:172 +msgid "assign this correspondent" +msgstr "" From be7bf5288b698359849552469a3114c13a44104e Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Thu, 31 Dec 2020 07:52:14 -0800 Subject: [PATCH 054/105] Fix alignment --- src-ui/src/app/components/app-frame/app-frame.component.html | 2 +- src-ui/src/app/components/app-frame/app-frame.component.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.html b/src-ui/src/app/components/app-frame/app-frame.component.html index 9d6c4924f..8029edc98 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.html +++ b/src-ui/src/app/components/app-frame/app-frame.component.html @@ -8,7 +8,7 @@ Paperless-ng -
+
diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index 44b1531b1..f62eccf96 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -82,7 +82,7 @@ svg { position: absolute; - left: 1.8em; + left: 2rem; color: rgba(255, 255, 255, 0.6); } From f090537ef4c5650277b2b7f00fc29173e827f64f Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Thu, 31 Dec 2020 16:23:08 -0800 Subject: [PATCH 055/105] tweak username display, dropdown size + spacing --- .../app-frame/app-frame.component.html | 27 ++++++++++++------- .../app-frame/app-frame.component.scss | 13 ++++++++- .../app-frame/app-frame.component.ts | 23 +++++++++++++--- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.html b/src-ui/src/app/components/app-frame/app-frame.component.html index 8029edc98..a05b691af 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.html +++ b/src-ui/src/app/components/app-frame/app-frame.component.html @@ -20,21 +20,28 @@ diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index f62eccf96..f2abb80f9 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -62,13 +62,16 @@ /* * Navbar */ + .navbar-brand { padding-top: 0.75rem; padding-bottom: 0.75rem; font-size: 1rem; } -.navbar-toggler { +.dropdown.show .dropdown-toggle, +.dropdown-toggle:hover { + opacity: 0.7; } .dropdown-toggle::after { @@ -76,6 +79,14 @@ vertical-align: 0.155em; } +.navbar .dropdown-menu { + font-size: 0.875rem; // body size + + a svg { + opacity: 0.6; + } +} + .navbar .search-form-container { max-width: 550px; position: relative; diff --git a/src-ui/src/app/components/app-frame/app-frame.component.ts b/src-ui/src/app/components/app-frame/app-frame.component.ts index c4c00843d..dca0d9106 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.ts +++ b/src-ui/src/app/components/app-frame/app-frame.component.ts @@ -9,7 +9,8 @@ import { SavedViewService } from 'src/app/services/rest/saved-view.service'; import { SearchService } from 'src/app/services/rest/search.service'; import { environment } from 'src/environments/environment'; import { DocumentDetailComponent } from '../document-detail/document-detail.component'; - +import { Meta } from '@angular/platform-browser'; + @Component({ selector: 'app-app-frame', templateUrl: './app-frame.component.html', @@ -22,8 +23,11 @@ export class AppFrameComponent implements OnInit, OnDestroy { private activatedRoute: ActivatedRoute, private openDocumentsService: OpenDocumentsService, private searchService: SearchService, - public savedViewService: SavedViewService + public savedViewService: SavedViewService, + private meta: Meta ) { + console.log(meta); + } versionString = `${environment.appTitle} ${environment.version}` @@ -55,7 +59,7 @@ export class AppFrameComponent implements OnInit, OnDestroy { term.length < 2 ? from([[]]) : this.searchService.autocomplete(term) ) ) - + itemSelected(event) { event.preventDefault() let currentSearch: string = this.searchField.value @@ -98,4 +102,17 @@ export class AppFrameComponent implements OnInit, OnDestroy { } } + get displayName() { + // TODO: taken from dashboard component, is this the best way to pass around username? + let tagFullName = this.meta.getTag('name=full_name') + let tagUsername = this.meta.getTag('name=username') + if (tagFullName && tagFullName.content) { + return tagFullName.content + } else if (tagUsername && tagUsername.content) { + return tagUsername.content + } else { + return null + } + } + } From 564f3b9170c68edc94f187320797a3b61c747cfd Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 20:23:32 +0100 Subject: [PATCH 056/105] fix some messages --- src/locale/en-us/LC_MESSAGES/django.po | 12 ++++++++---- src/paperless_mail/models.py | 8 ++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/locale/en-us/LC_MESSAGES/django.po b/src/locale/en-us/LC_MESSAGES/django.po index 0af8b7217..7b9435883 100644 --- a/src/locale/en-us/LC_MESSAGES/django.po +++ b/src/locale/en-us/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-31 14:39+0000\n" +"POT-Creation-Date: 2021-01-01 19:09+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -366,11 +366,11 @@ msgid "Use STARTTLS" msgstr "" #: paperless_mail/models.py:25 -msgid "imap server" +msgid "IMAP server" msgstr "" #: paperless_mail/models.py:29 -msgid "imap port" +msgid "IMAP port" msgstr "" #: paperless_mail/models.py:32 @@ -380,7 +380,7 @@ msgid "" msgstr "" #: paperless_mail/models.py:36 -msgid "imap security" +msgid "IMAP security" msgstr "" #: paperless_mail/models.py:42 @@ -419,6 +419,10 @@ msgstr "" msgid "Do not assign a correspondent" msgstr "" +#: paperless_mail/models.py:84 +msgid "Use mail address" +msgstr "" + #: paperless_mail/models.py:86 msgid "Use name (or mail address if not available)" msgstr "" diff --git a/src/paperless_mail/models.py b/src/paperless_mail/models.py index d585d7c1c..44682cfbf 100644 --- a/src/paperless_mail/models.py +++ b/src/paperless_mail/models.py @@ -22,18 +22,18 @@ class MailAccount(models.Model): max_length=256, unique=True) imap_server = models.CharField( - _("imap server"), + _("IMAP server"), max_length=256) imap_port = models.IntegerField( - _("imap port"), + _("IMAP port"), blank=True, null=True, help_text=_("This is usually 143 for unencrypted and STARTTLS " "connections, and 993 for SSL connections.")) imap_security = models.PositiveIntegerField( - _("imap security"), + _("IMAP security"), choices=IMAP_SECURITY_OPTIONS, default=IMAP_SECURITY_SSL ) @@ -81,7 +81,7 @@ class MailRule(models.Model): (CORRESPONDENT_FROM_NOTHING, _("Do not assign a correspondent")), (CORRESPONDENT_FROM_EMAIL, - "Use mail address"), + _("Use mail address")), (CORRESPONDENT_FROM_NAME, _("Use name (or mail address if not available)")), (CORRESPONDENT_FROM_CUSTOM, From dc525783ee396cd43f961d9e1a8d8a985afa58e8 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Fri, 1 Jan 2021 12:25:16 -0800 Subject: [PATCH 057/105] search icon position --- .../src/app/components/app-frame/app-frame.component.scss | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index f2abb80f9..473e6f85b 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -89,11 +89,14 @@ .navbar .search-form-container { max-width: 550px; - position: relative; + + form { + position: relative; + } svg { position: absolute; - left: 2rem; + left: 0.6rem; color: rgba(255, 255, 255, 0.6); } From 54a0da8151995d0182665d6e58535ef9d5276c44 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Fri, 1 Jan 2021 12:29:52 -0800 Subject: [PATCH 058/105] Dark mode compatability --- .../src/app/components/app-frame/app-frame.component.scss | 6 +++++- src-ui/src/theme_dark.scss | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index 473e6f85b..2d3cc5f04 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -104,6 +104,10 @@ svg { display: none; } + + .form-control::placeholder { + color: rgba(255, 255, 255, 0); + } } .form-control { @@ -121,7 +125,7 @@ &:focus { background-color: #fff; - color: initial; + color: #212529; flex-grow: 1; padding-left: 0.5rem; } diff --git a/src-ui/src/theme_dark.scss b/src-ui/src/theme_dark.scss index a122f1d86..5f08583e8 100644 --- a/src-ui/src/theme_dark.scss +++ b/src-ui/src/theme_dark.scss @@ -36,6 +36,10 @@ $border-color-dark-mode: #47494f; } } + .text-light { + color: $text-color-dark-mode !important; + } + .border { border-color: $border-color-dark-mode !important; } From a4e5d36a021440c86c65b32db512e85eee118d08 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Fri, 1 Jan 2021 12:36:19 -0800 Subject: [PATCH 059/105] Linting --- .../src/app/components/app-frame/app-frame.component.scss | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index 2d3cc5f04..26c4db273 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -19,13 +19,11 @@ .sidebar-sticky { position: relative; - top: 0; - /* height: calc(100vh - 48px); */ + top: 0; /* height: calc(100vh - 48px); */ height: 100%; padding-top: 0.5rem; overflow-x: hidden; - overflow-y: auto; - /* Scrollable contents if viewport is shorter than content. */ + overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ } @supports ((position: -webkit-sticky) or (position: sticky)) { .sidebar-sticky { From 6566e36141a6268ab294efb1f6f883678faf028b Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Fri, 1 Jan 2021 12:41:05 -0800 Subject: [PATCH 060/105] Mistakenly overwritten files from merge of dev branch --- src-ui/angular.json | 275 +++++++++++++------------ src-ui/src/environments/environment.ts | 2 +- 2 files changed, 139 insertions(+), 138 deletions(-) diff --git a/src-ui/angular.json b/src-ui/angular.json index f081430c7..db8c66b19 100644 --- a/src-ui/angular.json +++ b/src-ui/angular.json @@ -1,138 +1,139 @@ { - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "paperless-ui": { - "projectType": "application", - "schematics": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:browser", - "options": { - "outputPath": "dist/paperless-ui", - "outputHashing": "none", - "index": "src/index.html", - "main": "src/main.ts", - "polyfills": "src/polyfills.ts", - "tsConfig": "tsconfig.app.json", - "aot": true, - "assets": [ - "src/favicon.ico", - "src/assets", - "src/manifest.webmanifest" - ], - "styles": [ - "src/styles.scss" - ], - "scripts": [], - "allowedCommonJsDependencies": [ - "ng2-pdf-viewer" - ] - }, - "configurations": { - "production": { - "fileReplacements": [ - { - "replace": "src/environments/environment.ts", - "with": "src/environments/environment.prod.ts" - } - ], - "optimization": true, - "outputHashing": "none", - "sourceMap": false, - "extractCss": true, - "namedChunks": false, - "extractLicenses": true, - "vendorChunk": false, - "buildOptimizer": true, - "budgets": [ - { - "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" - } - ] - } - } - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "options": { - "browserTarget": "paperless-ui:build" - }, - "configurations": { - "production": { - "browserTarget": "paperless-ui:build:production" - } - } - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "paperless-ui:build" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "main": "src/test.ts", - "polyfills": "src/polyfills.ts", - "tsConfig": "tsconfig.spec.json", - "karmaConfig": "karma.conf.js", - "assets": [ - "src/favicon.ico", - "src/assets", - "src/manifest.webmanifest" - ], - "styles": [ - "src/styles.scss" - ], - "scripts": [] - } - }, - "lint": { - "builder": "@angular-devkit/build-angular:tslint", - "options": { - "tsConfig": [ - "tsconfig.app.json", - "tsconfig.spec.json", - "e2e/tsconfig.json" - ], - "exclude": [ - "**/node_modules/**" - ] - } - }, - "e2e": { - "builder": "@angular-devkit/build-angular:protractor", - "options": { - "protractorConfig": "e2e/protractor.conf.js", - "devServerTarget": "paperless-ui:serve" - }, - "configurations": { - "production": { - "devServerTarget": "paperless-ui:serve:production" - } - } - } - } - } - }, - "defaultProject": "paperless-ui", - "cli": { - "analytics": "7c47c2bc-b97e-4014-85ae-b0c99b5750b4" - } -} \ No newline at end of file + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "paperless-ui": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/paperless-ui", + "outputHashing": "none", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "tsconfig.app.json", + "aot": true, + "assets": [ + "src/favicon.ico", + "src/assets", + "src/manifest.webmanifest", { + "glob": "pdf.worker.min.js", + "input": "node_modules/pdfjs-dist/build/", + "output": "/assets/js/" + } + ], + "styles": [ + "src/styles.scss" + ], + "scripts": [], + "allowedCommonJsDependencies": [ + "ng2-pdf-viewer" + ] + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "none", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "paperless-ui:build" + }, + "configurations": { + "production": { + "browserTarget": "paperless-ui:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "paperless-ui:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "tsconfig.spec.json", + "karmaConfig": "karma.conf.js", + "assets": [ + "src/favicon.ico", + "src/assets", + "src/manifest.webmanifest" + ], + "styles": [ + "src/styles.scss" + ], + "scripts": [] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "tsconfig.app.json", + "tsconfig.spec.json", + "e2e/tsconfig.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + }, + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "paperless-ui:serve" + }, + "configurations": { + "production": { + "devServerTarget": "paperless-ui:serve:production" + } + } + } + } + } + }, + "defaultProject": "paperless-ui" +} diff --git a/src-ui/src/environments/environment.ts b/src-ui/src/environments/environment.ts index 7c5b29e82..29a8f3af6 100644 --- a/src-ui/src/environments/environment.ts +++ b/src-ui/src/environments/environment.ts @@ -4,7 +4,7 @@ export const environment = { production: false, - apiBaseUrl: "http://10.0.1.26:8000/api/", + apiBaseUrl: "http://localhost:8000/api/", appTitle: "Paperless-ng", version: "DEVELOPMENT" }; From 77409616974f5c59cd3a7af253ea108bf074e0b9 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Fri, 1 Jan 2021 12:42:58 -0800 Subject: [PATCH 061/105] Spaces --- src-ui/src/app/components/app-frame/app-frame.component.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index 26c4db273..d23ee8141 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -19,11 +19,11 @@ .sidebar-sticky { position: relative; - top: 0; /* height: calc(100vh - 48px); */ + top: 0; /* height: calc(100vh - 48px); */ height: 100%; padding-top: 0.5rem; overflow-x: hidden; - overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ + overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ } @supports ((position: -webkit-sticky) or (position: sticky)) { .sidebar-sticky { From 3d2d9cb3a2e00052b0390e1f09ba55fd1b4d4374 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Fri, 1 Jan 2021 12:43:19 -0800 Subject: [PATCH 062/105] Remove unused line --- src-ui/src/app/components/app-frame/app-frame.component.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index d23ee8141..6809875eb 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -19,7 +19,7 @@ .sidebar-sticky { position: relative; - top: 0; /* height: calc(100vh - 48px); */ + top: 0; height: 100%; padding-top: 0.5rem; overflow-x: hidden; From 1234634ba3a301394aa5816affb7e70bd17ba563 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Fri, 1 Jan 2021 12:49:48 -0800 Subject: [PATCH 063/105] Not sure why Typescript complained about this --- src-ui/src/app/app.component.ts | 2 +- src-ui/src/app/services/app-view.service.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-ui/src/app/app.component.ts b/src-ui/src/app/app.component.ts index 1c2001043..30ecb40d0 100644 --- a/src-ui/src/app/app.component.ts +++ b/src-ui/src/app/app.component.ts @@ -9,8 +9,8 @@ import { AppViewService } from './services/app-view.service'; export class AppComponent { constructor (appViewService: AppViewService) { - appViewService.updateDarkModeSettings() (window as any).pdfWorkerSrc = '/assets/js/pdf.worker.min.js'; + appViewService.updateDarkModeSettings() } diff --git a/src-ui/src/app/services/app-view.service.ts b/src-ui/src/app/services/app-view.service.ts index 6af2e43af..67a429ffe 100644 --- a/src-ui/src/app/services/app-view.service.ts +++ b/src-ui/src/app/services/app-view.service.ts @@ -18,7 +18,7 @@ export class AppViewService { this.updateDarkModeSettings() } - updateDarkModeSettings() { + updateDarkModeSettings(): void { let darkModeUseSystem = this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM) let darkModeEnabled = this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED) From 8490b65bcc81130052863577d9511cad546347ee Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 21:50:23 +0100 Subject: [PATCH 064/105] update lockfile --- Pipfile.lock | 57 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 1cfccb8ff..c6621b543 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "3d576f289958226a7583e4c471c7f8c11bff6933bf093185f623cfb381a92412" + "sha256": "993e362c31af6b8094693075f614270a820cf0b557369d66d674e1a107b7bd31" }, "pipfile-spec": 6, "requires": { @@ -44,6 +44,13 @@ ], "version": "==1.17.12" }, + "certifi": { + "hashes": [ + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" + ], + "version": "==2020.12.5" + }, "cffi": { "hashes": [ "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", @@ -229,6 +236,15 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==9.0" }, + "idna": { + "hashes": [ + "sha256:4a57a6379512ade94fa99e2fa46d3cd0f2f553040548d0e2958c6ed90ee48226", + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, "imap-tools": { "hashes": [ "sha256:72bf46dc135b039a5d5b59f4e079242ac15eac02a30038e8cb2dec7b153cab65", @@ -683,6 +699,14 @@ ], "version": "==3.5.56" }, + "requests": { + "hashes": [ + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.25.1" + }, "scikit-learn": { "hashes": [ "sha256:090bbf144fd5823c1f2efa3e1a9bf180295b24294ca8f478e75b40ed54f8036e", @@ -769,6 +793,14 @@ "markers": "python_version >= '3.5'", "version": "==2.1.0" }, + "tika": { + "hashes": [ + "sha256:c2c50f405622f74531841104f9e85c17511aede11de8e5385eab1a29a31f191b", + "sha256:d1f2eddb93caa9a2857569486aa2bc0320d0bf1796cdbe03066954cbc4b4bf62" + ], + "index": "pypi", + "version": "==1.24" + }, "tqdm": { "hashes": [ "sha256:38b658a3e4ecf9b4f6f8ff75ca16221ae3378b2e175d846b6b33ea3a20852cf5", @@ -777,6 +809,15 @@ "index": "pypi", "version": "==4.54.1" }, + "typing-extensions": { + "hashes": [ + "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", + "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", + "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" + ], + "markers": "python_version < '3.8'", + "version": "==3.7.4.3" + }, "tzlocal": { "hashes": [ "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44", @@ -784,6 +825,14 @@ ], "version": "==2.1" }, + "urllib3": { + "hashes": [ + "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", + "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.26.2" + }, "watchdog": { "hashes": [ "sha256:3caefdcc8f06a57fdc5ef2d22aa7c0bfda4f55e71a0bee74cbf3176d97536ef3", @@ -1197,11 +1246,11 @@ }, "requests": { "hashes": [ - "sha256:7f1a0b932f4a60a1a65caa4263921bb7d9ee911957e0ae4a23a6dd08185ad5f8", - "sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998" + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.25.0" + "version": "==2.25.1" }, "six": { "hashes": [ From 279e269a66f9e929089fc05e5426eac6b4d42e76 Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 21:50:32 +0100 Subject: [PATCH 065/105] update start_services.sh script --- scripts/start_services.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/start_services.sh b/scripts/start_services.sh index e566f59b3..cbab7ac9e 100755 --- a/scripts/start_services.sh +++ b/scripts/start_services.sh @@ -1,2 +1,4 @@ docker run -p 5432:5432 -v paperless_pgdata:/var/lib/postgresql/data -d postgres:13 docker run -d -p 6379:6379 redis:latest +docker run -p 3000:3000 -d thecodingmachine/gotenberg +docker run -p 9998:9998 -d apache/tika From c05bfb894ae5fad60760a47cf44bb34510274808 Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 21:50:45 +0100 Subject: [PATCH 066/105] remove duplicate code --- src/documents/parsers.py | 46 ++++++++++++++++++++ src/paperless_tesseract/parsers.py | 50 ++-------------------- src/paperless_tika/parsers.py | 67 +++++------------------------- 3 files changed, 60 insertions(+), 103 deletions(-) diff --git a/src/documents/parsers.py b/src/documents/parsers.py index 725e605a2..65d321ce5 100644 --- a/src/documents/parsers.py +++ b/src/documents/parsers.py @@ -144,6 +144,52 @@ def run_convert(input_file, raise ParseError("Convert failed at {}".format(args)) +def make_thumbnail_from_pdf(in_path, temp_dir, logging_group=None): + """ + The thumbnail of a PDF is just a 500px wide image of the first page. + """ + out_path = os.path.join(temp_dir, "convert.png") + + # Run convert to get a decent thumbnail + try: + run_convert(density=300, + scale="500x5000>", + alpha="remove", + strip=True, + trim=False, + auto_orient=True, + input_file="{}[0]".format(in_path), + output_file=out_path, + logging_group=logging_group) + except ParseError: + # if convert fails, fall back to extracting + # the first PDF page as a PNG using Ghostscript + logger.warning( + "Thumbnail generation with ImageMagick failed, falling back " + "to ghostscript. Check your /etc/ImageMagick-x/policy.xml!", + extra={'group': logging_group} + ) + gs_out_path = os.path.join(temp_dir, "gs_out.png") + cmd = [settings.GS_BINARY, + "-q", + "-sDEVICE=pngalpha", + "-o", gs_out_path, + in_path] + if not subprocess.Popen(cmd).wait() == 0: + raise ParseError("Thumbnail (gs) failed at {}".format(cmd)) + # then run convert on the output from gs + run_convert(density=300, + scale="500x5000>", + alpha="remove", + strip=True, + trim=False, + auto_orient=True, + input_file=gs_out_path, + output_file=out_path, + logging_group=logging_group) + + return out_path + def parse_date(filename, text): """ Returns the date of the document. diff --git a/src/paperless_tesseract/parsers.py b/src/paperless_tesseract/parsers.py index 4da5af2c0..fc8702eac 100644 --- a/src/paperless_tesseract/parsers.py +++ b/src/paperless_tesseract/parsers.py @@ -1,7 +1,6 @@ import json import os import re -import subprocess import ocrmypdf import pdftotext @@ -10,7 +9,8 @@ from PIL import Image from django.conf import settings from ocrmypdf import InputFileError, EncryptedPdfError -from documents.parsers import DocumentParser, ParseError, run_convert +from documents.parsers import DocumentParser, ParseError, \ + make_thumbnail_from_pdf class RasterisedDocumentParser(DocumentParser): @@ -47,50 +47,8 @@ class RasterisedDocumentParser(DocumentParser): return result def get_thumbnail(self, document_path, mime_type): - """ - The thumbnail of a PDF is just a 500px wide image of the first page. - """ - - out_path = os.path.join(self.tempdir, "convert.png") - - # Run convert to get a decent thumbnail - try: - run_convert(density=300, - scale="500x5000>", - alpha="remove", - strip=True, - trim=False, - auto_orient=True, - input_file="{}[0]".format(document_path), - output_file=out_path, - logging_group=self.logging_group) - except ParseError: - # if convert fails, fall back to extracting - # the first PDF page as a PNG using Ghostscript - self.log( - 'warning', - "Thumbnail generation with ImageMagick failed, falling back " - "to ghostscript. Check your /etc/ImageMagick-x/policy.xml!") - gs_out_path = os.path.join(self.tempdir, "gs_out.png") - cmd = [settings.GS_BINARY, - "-q", - "-sDEVICE=pngalpha", - "-o", gs_out_path, - document_path] - if not subprocess.Popen(cmd).wait() == 0: - raise ParseError("Thumbnail (gs) failed at {}".format(cmd)) - # then run convert on the output from gs - run_convert(density=300, - scale="500x5000>", - alpha="remove", - strip=True, - trim=False, - auto_orient=True, - input_file=gs_out_path, - output_file=out_path, - logging_group=self.logging_group) - - return out_path + return make_thumbnail_from_pdf( + document_path, self.tempdir, self.logging_group) def is_image(self, mime_type): return mime_type in [ diff --git a/src/paperless_tika/parsers.py b/src/paperless_tika/parsers.py index 81f213a6b..8ee10632f 100644 --- a/src/paperless_tika/parsers.py +++ b/src/paperless_tika/parsers.py @@ -1,14 +1,11 @@ import os -import subprocess -import tika import requests import dateutil.parser -from PIL import ImageDraw, ImageFont, Image from django.conf import settings -from documents.parsers import DocumentParser, ParseError, run_convert -from paperless_tesseract.parsers import RasterisedDocumentParser +from documents.parsers import DocumentParser, ParseError, \ + make_thumbnail_from_pdf from tika import parser @@ -18,55 +15,11 @@ class TikaDocumentParser(DocumentParser): """ def get_thumbnail(self, document_path, mime_type): - self.log("info", f"[TIKA_THUMB] Generating thumbnail for{document_path}") - archive_path = self.archive_path + if not self.archive_path: + self.archive_path = self.convert_to_pdf(document_path) - out_path = os.path.join(self.tempdir, "convert.png") - - # Run convert to get a decent thumbnail - try: - run_convert( - density=300, - scale="500x5000>", - alpha="remove", - strip=True, - trim=False, - input_file="{}[0]".format(archive_path), - output_file=out_path, - logging_group=self.logging_group, - ) - except ParseError: - # if convert fails, fall back to extracting - # the first PDF page as a PNG using Ghostscript - self.log( - "warning", - "Thumbnail generation with ImageMagick failed, falling back " - "to ghostscript. Check your /etc/ImageMagick-x/policy.xml!", - ) - gs_out_path = os.path.join(self.tempdir, "gs_out.png") - cmd = [ - settings.GS_BINARY, - "-q", - "-sDEVICE=pngalpha", - "-o", - gs_out_path, - archive_path, - ] - if not subprocess.Popen(cmd).wait() == 0: - raise ParseError("Thumbnail (gs) failed at {}".format(cmd)) - # then run convert on the output from gs - run_convert( - density=300, - scale="500x5000>", - alpha="remove", - strip=True, - trim=False, - input_file=gs_out_path, - output_file=out_path, - logging_group=self.logging_group, - ) - - return out_path + return make_thumbnail_from_pdf( + self.archive_path, self.tempdir, self.logging_group) def parse(self, document_path, mime_type): self.log("info", f"[TIKA_PARSE] Sending {document_path} to Tika server") @@ -89,11 +42,9 @@ class TikaDocumentParser(DocumentParser): except: pass - archive_path = os.path.join(self.tempdir, "convert.pdf") - convert_to_pdf(document_path, archive_path) - self.archive_path = archive_path + self.archive_path = self.convert_to_pdf(document_path) - def convert_to_pdf(document_path, pdf_path): + def convert_to_pdf(self, document_path): pdf_path = os.path.join(self.tempdir, "convert.pdf") gotenberg_server = settings.PAPERLESS_TIKA_GOTENBERG_ENDPOINT url = gotenberg_server + "/convert/office" @@ -113,3 +64,5 @@ class TikaDocumentParser(DocumentParser): file = open(pdf_path, "wb") file.write(response.content) file.close() + + return pdf_path From 1e541b688ddd5dc3f85a739a9acf51554d5ca31b Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+nikonratm@users.noreply.github.com> Date: Fri, 1 Jan 2021 12:52:35 -0800 Subject: [PATCH 067/105] brand width rem --- src-ui/src/app/components/app-frame/app-frame.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.html b/src-ui/src/app/components/app-frame/app-frame.component.html index 36408dce5..46065a102 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.html +++ b/src-ui/src/app/components/app-frame/app-frame.component.html @@ -5,7 +5,7 @@ - + Paperless-ng From de32addf76f8e041808a3551998e3de847ef0c5c Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 21:59:21 +0100 Subject: [PATCH 068/105] fix up the tika parser --- src/paperless_tika/parsers.py | 44 ++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/paperless_tika/parsers.py b/src/paperless_tika/parsers.py index 8ee10632f..56792fb51 100644 --- a/src/paperless_tika/parsers.py +++ b/src/paperless_tika/parsers.py @@ -21,26 +21,44 @@ class TikaDocumentParser(DocumentParser): return make_thumbnail_from_pdf( self.archive_path, self.tempdir, self.logging_group) + def extract_metadata(self, document_path, mime_type): + tika_server = settings.PAPERLESS_TIKA_ENDPOINT + try: + parsed = parser.from_file(document_path, tika_server) + except Exception as e: + self.log("warning", f"Error while fetching document metadata for " + f"{document_path}: {e}") + return [] + + return [ + { + "namespace": "", + "prefix": "", + "key": key, + "value": parsed['metadata'][key] + } for key in parsed['metadata'] + ] + def parse(self, document_path, mime_type): - self.log("info", f"[TIKA_PARSE] Sending {document_path} to Tika server") + self.log("info", f"Sending {document_path} to Tika server") tika_server = settings.PAPERLESS_TIKA_ENDPOINT try: parsed = parser.from_file(document_path, tika_server) - except requests.exceptions.HTTPError as err: + except Exception as err: raise ParseError( - f"Could not parse {document_path} with tika server at {tika_server}: {err}" + f"Could not parse {document_path} with tika server at " + f"{tika_server}: {err}" ) - try: - self.text = parsed["content"].strip() - except: - pass + self.text = parsed["content"].strip() try: - self.date = dateutil.parser.isoparse(parsed["metadata"]["Creation-Date"]) - except: - pass + self.date = dateutil.parser.isoparse( + parsed["metadata"]["Creation-Date"]) + except Exception as e: + self.log("warning", f"Unable to extract date for document " + f"{document_path}: {e}") self.archive_path = self.convert_to_pdf(document_path) @@ -49,16 +67,16 @@ class TikaDocumentParser(DocumentParser): gotenberg_server = settings.PAPERLESS_TIKA_GOTENBERG_ENDPOINT url = gotenberg_server + "/convert/office" - self.log("info", f"[TIKA] Converting {document_path} to PDF as {pdf_path}") + self.log("info", f"Converting {document_path} to PDF as {pdf_path}") files = {"files": open(document_path, "rb")} headers = {} try: response = requests.post(url, files=files, headers=headers) response.raise_for_status() # ensure we notice bad responses - except requests.exceptions.HTTPError as err: + except Exception as err: raise ParseError( - f"Could not contact gotenberg server at {gotenberg_server}: {err}" + f"Error while converting document to PDF: {err}" ) file = open(pdf_path, "wb") From 40ef375c15c319d18ab81c6bc265f352f52de52f Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 22:19:43 +0100 Subject: [PATCH 069/105] supply file_name for tika parser --- src/documents/consumer.py | 3 +-- src/documents/parsers.py | 2 +- src/documents/tests/test_consumer.py | 4 ++-- src/paperless_tesseract/parsers.py | 2 +- src/paperless_text/parsers.py | 2 +- src/paperless_tika/parsers.py | 8 ++++---- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/documents/consumer.py b/src/documents/consumer.py index 5a06194b7..abd12d802 100755 --- a/src/documents/consumer.py +++ b/src/documents/consumer.py @@ -1,6 +1,5 @@ import datetime import hashlib -import logging import os import magic @@ -130,7 +129,7 @@ class Consumer(LoggingMixin): try: self.log("debug", "Parsing {}...".format(self.filename)) - document_parser.parse(self.path, mime_type) + document_parser.parse(self.path, mime_type, self.filename) self.log("debug", f"Generating thumbnail for {self.filename}...") thumbnail = document_parser.get_optimised_thumbnail( diff --git a/src/documents/parsers.py b/src/documents/parsers.py index 65d321ce5..e14607bd0 100644 --- a/src/documents/parsers.py +++ b/src/documents/parsers.py @@ -267,7 +267,7 @@ class DocumentParser(LoggingMixin): def extract_metadata(self, document_path, mime_type): return [] - def parse(self, document_path, mime_type): + def parse(self, document_path, mime_type, file_name=None): raise NotImplementedError() def get_archive_path(self): diff --git a/src/documents/tests/test_consumer.py b/src/documents/tests/test_consumer.py index 795ca7f95..90c034f9e 100644 --- a/src/documents/tests/test_consumer.py +++ b/src/documents/tests/test_consumer.py @@ -177,7 +177,7 @@ class DummyParser(DocumentParser): def get_optimised_thumbnail(self, document_path, mime_type): return self.fake_thumb - def parse(self, document_path, mime_type): + def parse(self, document_path, mime_type, file_name=None): self.text = "The Text" @@ -194,7 +194,7 @@ class FaultyParser(DocumentParser): def get_optimised_thumbnail(self, document_path, mime_type): return self.fake_thumb - def parse(self, document_path, mime_type): + def parse(self, document_path, mime_type, file_name=None): raise ParseError("Does not compute.") diff --git a/src/paperless_tesseract/parsers.py b/src/paperless_tesseract/parsers.py index fc8702eac..31e956284 100644 --- a/src/paperless_tesseract/parsers.py +++ b/src/paperless_tesseract/parsers.py @@ -88,7 +88,7 @@ class RasterisedDocumentParser(DocumentParser): f"Error while calculating DPI for image {image}: {e}") return None - def parse(self, document_path, mime_type): + def parse(self, document_path, mime_type, file_name=None): mode = settings.OCR_MODE text_original = get_text_from_pdf(document_path) diff --git a/src/paperless_text/parsers.py b/src/paperless_text/parsers.py index a38bd7a91..c1afe07fc 100644 --- a/src/paperless_text/parsers.py +++ b/src/paperless_text/parsers.py @@ -32,6 +32,6 @@ class TextDocumentParser(DocumentParser): return out_path - def parse(self, document_path, mime_type): + def parse(self, document_path, mime_type, file_name=None): with open(document_path, 'r') as f: self.text = f.read() diff --git a/src/paperless_tika/parsers.py b/src/paperless_tika/parsers.py index 56792fb51..13e937daa 100644 --- a/src/paperless_tika/parsers.py +++ b/src/paperless_tika/parsers.py @@ -39,7 +39,7 @@ class TikaDocumentParser(DocumentParser): } for key in parsed['metadata'] ] - def parse(self, document_path, mime_type): + def parse(self, document_path, mime_type, file_name=None): self.log("info", f"Sending {document_path} to Tika server") tika_server = settings.PAPERLESS_TIKA_ENDPOINT @@ -60,15 +60,15 @@ class TikaDocumentParser(DocumentParser): self.log("warning", f"Unable to extract date for document " f"{document_path}: {e}") - self.archive_path = self.convert_to_pdf(document_path) + self.archive_path = self.convert_to_pdf(document_path, file_name) - def convert_to_pdf(self, document_path): + def convert_to_pdf(self, document_path, file_name): pdf_path = os.path.join(self.tempdir, "convert.pdf") gotenberg_server = settings.PAPERLESS_TIKA_GOTENBERG_ENDPOINT url = gotenberg_server + "/convert/office" self.log("info", f"Converting {document_path} to PDF as {pdf_path}") - files = {"files": open(document_path, "rb")} + files = {"files": (file_name, open(document_path, "rb"))} headers = {} try: From d5601b7ec0efe0d5af92da224c30d5d650522c8c Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 22:29:25 +0100 Subject: [PATCH 070/105] remove active class from user menu --- src-ui/src/app/components/app-frame/app-frame.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-ui/src/app/components/app-frame/app-frame.component.html b/src-ui/src/app/components/app-frame/app-frame.component.html index 46065a102..42273ca3a 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.html +++ b/src-ui/src/app/components/app-frame/app-frame.component.html @@ -34,7 +34,7 @@

Logged in as {{displayName}}

- + Settings From 0a7412424d988bc606e8fcfffefaaec4cce7c023 Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 22:38:26 +0100 Subject: [PATCH 071/105] refactored app-view service --- src-ui/src/app/app.component.ts | 10 +++--- .../app-frame/app-frame.component.ts | 3 +- .../manage/settings/settings.component.ts | 6 ++-- .../src/app/services/app-view.service.spec.ts | 16 --------- src-ui/src/app/services/app-view.service.ts | 35 ------------------- src-ui/src/app/services/settings.service.ts | 28 +++++++++++++-- 6 files changed, 34 insertions(+), 64 deletions(-) delete mode 100644 src-ui/src/app/services/app-view.service.spec.ts delete mode 100644 src-ui/src/app/services/app-view.service.ts diff --git a/src-ui/src/app/app.component.ts b/src-ui/src/app/app.component.ts index 30ecb40d0..73c5fc861 100644 --- a/src-ui/src/app/app.component.ts +++ b/src-ui/src/app/app.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { AppViewService } from './services/app-view.service'; +import { SettingsService } from './services/settings.service'; @Component({ selector: 'app-root', @@ -8,10 +8,10 @@ import { AppViewService } from './services/app-view.service'; }) export class AppComponent { - constructor (appViewService: AppViewService) { - (window as any).pdfWorkerSrc = '/assets/js/pdf.worker.min.js'; - appViewService.updateDarkModeSettings() + constructor (private settings: SettingsService) { + let anyWindow = (window as any) + anyWindow.pdfWorkerSrc = '/assets/js/pdf.worker.min.js'; + this.settings.updateDarkModeSettings() } - } diff --git a/src-ui/src/app/components/app-frame/app-frame.component.ts b/src-ui/src/app/components/app-frame/app-frame.component.ts index dca0d9106..ad4460f16 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.ts +++ b/src-ui/src/app/components/app-frame/app-frame.component.ts @@ -26,8 +26,7 @@ export class AppFrameComponent implements OnInit, OnDestroy { public savedViewService: SavedViewService, private meta: Meta ) { - console.log(meta); - + } versionString = `${environment.appTitle} ${environment.version}` diff --git a/src-ui/src/app/components/manage/settings/settings.component.ts b/src-ui/src/app/components/manage/settings/settings.component.ts index df3015e21..0b0646157 100644 --- a/src-ui/src/app/components/manage/settings/settings.component.ts +++ b/src-ui/src/app/components/manage/settings/settings.component.ts @@ -5,7 +5,6 @@ import { DocumentListViewService } from 'src/app/services/document-list-view.ser import { SavedViewService } from 'src/app/services/rest/saved-view.service'; import { SettingsService, SETTINGS_KEYS } from 'src/app/services/settings.service'; import { ToastService } from 'src/app/services/toast.service'; -import { AppViewService } from 'src/app/services/app-view.service'; @Component({ selector: 'app-settings', @@ -31,8 +30,7 @@ export class SettingsComponent implements OnInit { public savedViewService: SavedViewService, private documentListViewService: DocumentListViewService, private toastService: ToastService, - private settings: SettingsService, - private appViewService: AppViewService + private settings: SettingsService ) { } ngOnInit() { @@ -72,7 +70,7 @@ export class SettingsComponent implements OnInit { this.settings.set(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem) this.settings.set(SETTINGS_KEYS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString()) this.documentListViewService.updatePageSize() - this.appViewService.updateDarkModeSettings() + this.settings.updateDarkModeSettings() this.toastService.showInfo($localize`Settings saved successfully.`) } diff --git a/src-ui/src/app/services/app-view.service.spec.ts b/src-ui/src/app/services/app-view.service.spec.ts deleted file mode 100644 index fc44ed3a4..000000000 --- a/src-ui/src/app/services/app-view.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AppViewService } from './app-view.service'; - -describe('AppViewService', () => { - let service: AppViewService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(AppViewService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src-ui/src/app/services/app-view.service.ts b/src-ui/src/app/services/app-view.service.ts deleted file mode 100644 index 67a429ffe..000000000 --- a/src-ui/src/app/services/app-view.service.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core'; -import { DOCUMENT } from '@angular/common'; -import { SettingsService, SETTINGS_KEYS } from './settings.service'; - -@Injectable({ - providedIn: 'root' -}) -export class AppViewService { - private renderer: Renderer2; - - constructor( - private settings: SettingsService, - private rendererFactory: RendererFactory2, - @Inject(DOCUMENT) private document - ) { - this.renderer = rendererFactory.createRenderer(null, null); - - this.updateDarkModeSettings() - } - - updateDarkModeSettings(): void { - let darkModeUseSystem = this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM) - let darkModeEnabled = this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED) - - if (darkModeUseSystem) { - this.renderer.addClass(this.document.body, 'color-scheme-system') - this.renderer.removeClass(this.document.body, 'color-scheme-dark') - } else { - this.renderer.removeClass(this.document.body, 'color-scheme-system') - darkModeEnabled ? this.renderer.addClass(this.document.body, 'color-scheme-dark') : this.renderer.removeClass(this.document.body, 'color-scheme-dark') - } - - } - -} diff --git a/src-ui/src/app/services/settings.service.ts b/src-ui/src/app/services/settings.service.ts index 7b1cfe9e3..a8f85972d 100644 --- a/src-ui/src/app/services/settings.service.ts +++ b/src-ui/src/app/services/settings.service.ts @@ -1,4 +1,5 @@ -import { Injectable } from '@angular/core'; +import { DOCUMENT } from '@angular/common'; +import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core'; export interface PaperlessSettings { key: string @@ -27,7 +28,30 @@ const SETTINGS: PaperlessSettings[] = [ }) export class SettingsService { - constructor() { } + private renderer: Renderer2; + + constructor( + private rendererFactory: RendererFactory2, + @Inject(DOCUMENT) private document + ) { + this.renderer = rendererFactory.createRenderer(null, null); + + this.updateDarkModeSettings() + } + + updateDarkModeSettings(): void { + let darkModeUseSystem = this.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM) + let darkModeEnabled = this.get(SETTINGS_KEYS.DARK_MODE_ENABLED) + + if (darkModeUseSystem) { + this.renderer.addClass(this.document.body, 'color-scheme-system') + this.renderer.removeClass(this.document.body, 'color-scheme-dark') + } else { + this.renderer.removeClass(this.document.body, 'color-scheme-system') + darkModeEnabled ? this.renderer.addClass(this.document.body, 'color-scheme-dark') : this.renderer.removeClass(this.document.body, 'color-scheme-dark') + } + + } get(key: string): any { let setting = SETTINGS.find(s => s.key == key) From bac0dbb70b6ceb925888db33882a5e3774a3239c Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 22:38:33 +0100 Subject: [PATCH 072/105] messages --- src-ui/messages.xlf | 97 +++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 38 deletions(-) diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 5f12c504c..133d1ae96 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -377,7 +377,7 @@ Do you really want to delete the tag ""? src/app/components/manage/tag-list/tag-list.component.ts - 31 + 28 @@ -440,7 +440,7 @@ Do you really want to delete the document type ""? src/app/components/manage/document-type-list/document-type-list.component.ts - 26 + 24 @@ -468,21 +468,21 @@ Saved view " deleted. src/app/components/manage/settings/settings.component.ts - 52 + 54 Settings saved successfully. src/app/components/manage/settings/settings.component.ts - 61 + 74 Error while storing settings on server: src/app/components/manage/settings/settings.component.ts - 73 + 86 @@ -496,11 +496,11 @@ Saved views src/app/components/manage/settings/settings.component.html - 41 + 56 - - Document list + + Appearance src/app/components/manage/settings/settings.component.html 13 @@ -513,60 +513,74 @@ 17 + + Dark mode + + src/app/components/manage/settings/settings.component.html + 33 + + + + Use system settings + + src/app/components/manage/settings/settings.component.html + 36 + + Bulk editing src/app/components/manage/settings/settings.component.html - 33 + 44 Show confirmation dialogs src/app/components/manage/settings/settings.component.html - 35 + 48 Deleting documents will always ask for confirmation. src/app/components/manage/settings/settings.component.html - 35 + 48 Apply on close src/app/components/manage/settings/settings.component.html - 36 + 49 Appears on src/app/components/manage/settings/settings.component.html - 53 + 68 Show on dashboard src/app/components/manage/settings/settings.component.html - 56 + 71 Show in sidebar src/app/components/manage/settings/settings.component.html - 60 + 75 No saved views defined. src/app/components/manage/settings/settings.component.html - 70 + 85 @@ -580,7 +594,7 @@ Do you really want to delete the correspondent ""? src/app/components/manage/correspondent-list/correspondent-list.component.ts - 26 + 24 @@ -776,26 +790,33 @@ Paperless-ng src/app/components/app-frame/app-frame.component.html - 4 + 11 app title - - Search for documents + + Search documents src/app/components/app-frame/app-frame.component.html - 12 - - - - Manage - - src/app/components/app-frame/app-frame.component.html - 77 + 15 Settings + + src/app/components/app-frame/app-frame.component.html + 40 + + + + Logout + + src/app/components/app-frame/app-frame.component.html + 45 + + + + Manage src/app/components/app-frame/app-frame.component.html 112 @@ -805,49 +826,49 @@ Admin src/app/components/app-frame/app-frame.component.html - 119 + 147 Misc src/app/components/app-frame/app-frame.component.html - 125 + 153 Documentation src/app/components/app-frame/app-frame.component.html - 132 + 160 GitHub src/app/components/app-frame/app-frame.component.html - 139 + 167 - - Logout + + Logged in as src/app/components/app-frame/app-frame.component.html - 146 + 34 Open documents src/app/components/app-frame/app-frame.component.html - 57 + 92 Close all src/app/components/app-frame/app-frame.component.html - 71 + 106 @@ -910,7 +931,7 @@ Not assigned src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts - 145 + 161 Filter drop down element to filter for documents with no correspondent/type/tag assigned From ebdddc4fe4ee98e35cab3ffe1867c12048e401a9 Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 22:44:10 +0100 Subject: [PATCH 073/105] fix metadata column --- .../metadata-collapse/metadata-collapse.component.html | 2 +- .../metadata-collapse/metadata-collapse.component.scss | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src-ui/src/app/components/document-detail/metadata-collapse/metadata-collapse.component.html b/src-ui/src/app/components/document-detail/metadata-collapse/metadata-collapse.component.html index e8fda1d0b..ac42860c9 100644 --- a/src-ui/src/app/components/document-detail/metadata-collapse/metadata-collapse.component.html +++ b/src-ui/src/app/components/document-detail/metadata-collapse/metadata-collapse.component.html @@ -16,7 +16,7 @@ {{m.prefix}}:{{m.key}} - {{m.value}} + {{m.value}} diff --git a/src-ui/src/app/components/document-detail/metadata-collapse/metadata-collapse.component.scss b/src-ui/src/app/components/document-detail/metadata-collapse/metadata-collapse.component.scss index e69de29bb..b946da146 100644 --- a/src-ui/src/app/components/document-detail/metadata-collapse/metadata-collapse.component.scss +++ b/src-ui/src/app/components/document-detail/metadata-collapse/metadata-collapse.component.scss @@ -0,0 +1,3 @@ +.metadata-column { + overflow-wrap: anywhere; +} \ No newline at end of file From c4367818b73100f00d68469c81c1531ae9548b05 Mon Sep 17 00:00:00 2001 From: jonaswinkler Date: Fri, 1 Jan 2021 23:08:02 +0100 Subject: [PATCH 074/105] better matching algorithm descriptions --- .../correspondent-edit-dialog.component.html | 2 +- .../document-type-edit-dialog.component.html | 2 +- .../manage/generic-list/generic-list.component.ts | 2 +- .../tag-edit-dialog/tag-edit-dialog.component.html | 2 +- src-ui/src/app/data/matching-model.ts | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src-ui/src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html b/src-ui/src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html index e35c57e26..fd6b01de9 100644 --- a/src-ui/src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html +++ b/src-ui/src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html @@ -9,7 +9,7 @@ - +
diff --git a/src-ui/src/app/components/manage/generic-list/generic-list.component.ts b/src-ui/src/app/components/manage/generic-list/generic-list.component.ts index 1f9cc65f9..b31231bc8 100644 --- a/src-ui/src/app/components/manage/generic-list/generic-list.component.ts +++ b/src-ui/src/app/components/manage/generic-list/generic-list.component.ts @@ -30,7 +30,7 @@ export abstract class GenericListComponent implements On if (o.matching_algorithm == MATCH_AUTO) { return $localize`Automatic` } else if (o.match && o.match.length > 0) { - return `${o.match} (${MATCHING_ALGORITHMS.find(a => a.id == o.matching_algorithm).name})` + return `${MATCHING_ALGORITHMS.find(a => a.id == o.matching_algorithm).shortName}: ${o.match}` } else { return "-" } diff --git a/src-ui/src/app/components/manage/tag-list/tag-edit-dialog/tag-edit-dialog.component.html b/src-ui/src/app/components/manage/tag-list/tag-edit-dialog/tag-edit-dialog.component.html index bbb96fb6b..7efaac4b9 100644 --- a/src-ui/src/app/components/manage/tag-list/tag-edit-dialog/tag-edit-dialog.component.html +++ b/src-ui/src/app/components/manage/tag-list/tag-edit-dialog/tag-edit-dialog.component.html @@ -20,7 +20,7 @@ - +