diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4fadf260e..425243163 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -208,7 +208,7 @@ jobs: tag_name: ng-${{ steps.get_version.outputs.version }} release_name: Paperless-ng ${{ steps.get_version.outputs.version }} draft: false - prerelease: true + prerelease: false body: | For a complete list of changes, see the changelog at https://paperless-ng.readthedocs.io/en/latest/changelog.html. - diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 000000000..f5a7765dd --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,5 @@ +files: + - source: /src/locale/en-us/LC_MESSAGES/django.po + translation: /src/locale/%two_letters_code%/LC_MESSAGES/django.po + - source: /src-ui/messages.xlf + translation: /src-ui/src/locale/messages.%two_letters_code%.xlf diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index 8e1a21757..5919b14aa 100644 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -79,7 +79,11 @@ initialize() { fi done + echo "creating directory /tmp/paperless" + mkdir -p /tmp/paperless + chown -R paperless:paperless ../ + chown -R paperless:paperless /tmp/paperless migrations diff --git a/docs/administration.rst b/docs/administration.rst index 1690d49e2..14b986e82 100644 --- a/docs/administration.rst +++ b/docs/administration.rst @@ -20,6 +20,8 @@ Options available to any installation of paperless: metadata to a specific folder. You may import your documents into a fresh instance of paperless again or store your documents in another DMS with this export. +* The document exporter is also able to update an already existing export. + Therefore, incremental backups with ``rsync`` are entirely possible. Options available to docker installations: @@ -88,10 +90,28 @@ B. If you built the image yourself, do the following: $ docker-compose build $ docker-compose up -Running `docker-compose up` will also apply any new database migrations. +Running ``docker-compose up`` will also apply any new database migrations. If you see everything working, press CTRL+C once to gracefully stop paperless. Then you can start paperless-ng with ``-d`` to have it run in the background. + .. note:: + + In version 0.9.14, the update process was changed. In 0.9.13 and earlier, the + docker-compose files specified exact versions and pull won't automatically + update to newer versions. In order to enable updates as described above, either + get the new ``docker-compose.yml`` file from `here `_ + or edit the ``docker-compose.yml`` file, find the line that says + + .. code:: + + image: jonaswinkler/paperless-ng:0.9.x + + and replace the version with ``latest``: + + .. code:: + + image: jonaswinkler/paperless-ng:latest + Bare Metal Route ================ @@ -192,8 +212,13 @@ backup or migration to another DMS. .. code:: - document_exporter target + document_exporter target [-c] [-f] [-d] + optional arguments: + -c, --compare-checksums + -f, --use-filename-format + -d, --delete + ``target`` is a folder to which the data gets written. This includes documents, thumbnails and a ``manifest.json`` file. The manifest contains all metadata from the database (correspondents, tags, etc). @@ -202,6 +227,24 @@ When you use the provided docker compose script, specify ``../export`` as the target. This path inside the container is automatically mounted on your host on the folder ``export``. +If the target directory already exists and contains files, paperless will assume +that the contents of the export directory are a previous export and will attempt +to update the previous export. Paperless will only export changed and added files. +Paperless determines whether a file has changed by inspecting the file attributes +"date/time modified" and "size". If that does not work out for you, specify +``--compare-checksums`` and paperless will attempt to compare file checksums instead. +This is slower. + +Paperless will not remove any existing files in the export directory. If you want +paperless to also remove files that do not belong to the current export such as files +from deleted documents, specify ``--delete``. Be careful when pointing paperless to +a directory that already contains other files. + +The filenames generated by this command follow the format +``[date created] [correspondent] [title].[extension]``. +If you want paperless to use ``PAPERLESS_FILENAME_FORMAT`` for exported filenames +instead, specify ``--use-filename-format``. + .. _utilities-importer: diff --git a/docs/changelog.rst b/docs/changelog.rst index 498c53301..28bcc00e6 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,29 @@ Changelog ********* +paperless-ng 1.0.0 +################## + +Nothing special about this release, but since there are relatively few bug reports coming in, I think that this is reasonably stable. + +* Document export + + * The document exporter has been rewritten to support updating an already existing export in place. + This enables incremental backups with ``rsync``. + * The document exporter supports naming exported files according to ``PAPERLESS_FILENAME_FORMAT``. + * The document exporter locks the media directory and the database during execution to ensure that + the resulting export is consistent. + * See the :ref:`updated documentation ` for more details. + +* Other changes and additions + + * Added a language selector to the settings. + * Added date format options to the settings. + * Range selection with shift clicking is now possible in the document list. + * Filtering correspondent, type and tag management pages by name. + * Focus "Name" field in dialogs by default. + + paperless-ng 0.9.14 ################### @@ -116,7 +139,7 @@ paperless-ng 0.9.10 * There are some configuration options in the settings to alter the behavior. * Other changes and additions - + * Thanks to `zjean`_, paperless now publishes a webmanifest, which is useful for adding the application to home screens on mobile devices. * The Paperless-ng logo now navigates to the dashboard. * Filter for documents that don't have any correspondents, types or tags assigned. @@ -136,7 +159,7 @@ paperless-ng 0.9.10 The bulk delete operations did not update the search index. Therefore, documents that you deleted remained in the index and caused the search to return messages about missing documents when searching. Further bulk operations will properly update the index. - + However, this change is not retroactive: If you used the delete method of the bulk editor, you need to reindex your search index by :ref:`running the management command document_index with the argument reindex `. @@ -191,12 +214,12 @@ paperless-ng 0.9.7 * Thanks to the hard work of `Michael Shamoon`_, paperless now comes with a much more streamlined UI for filtering documents. - + * `Michael Shamoon`_ replaced the document preview with another component. This should fix compatibility with Safari browsers. * Added buttons to the management pages to quickly show all documents with one specific tag, correspondent, or title. - - * Paperless now stores your saved views on the server and associates them with your user account. + + * Paperless now stores your saved views on the server and associates them with your user account. This means that you can access your views on multiple devices and have separate views for different users. You will have to recreate your views. @@ -214,7 +237,7 @@ paperless-ng 0.9.7 This option enables you to be logged in into multiple instances by specifying different cookie names for each instance. * Fixes - + * Sometimes paperless would assign dates in the future to newly consumed documents. * The filename format fields ``{created_month}`` and ``{created_day}`` now use a leading zero for single digit values. * The filename format field ``{tags}`` can no longer be used without arguments. diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 9b6324a76..6175cf700 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -394,53 +394,60 @@ 2 + + Filter by: + + src/app/components/manage/tag-list/tag-list.component.html + 8 + + Name src/app/components/manage/tag-list/tag-list.component.html - 13 + 9 Color src/app/components/manage/tag-list/tag-list.component.html - 14 + 20 Matching src/app/components/manage/tag-list/tag-list.component.html - 15 + 21 Document count src/app/components/manage/tag-list/tag-list.component.html - 16 + 22 Actions src/app/components/manage/tag-list/tag-list.component.html - 17 + 23 Documents src/app/components/manage/tag-list/tag-list.component.html - 32 + 38 Edit src/app/components/manage/tag-list/tag-list.component.html - 37 + 43 @@ -475,21 +482,35 @@ Saved view "" deleted. src/app/components/manage/settings/settings.component.ts - 55 + 63 Settings saved successfully. src/app/components/manage/settings/settings.component.ts - 68 + 79 + + + + Use system language + + src/app/components/manage/settings/settings.component.ts + 83 + + + + Use date format of display language + + src/app/components/manage/settings/settings.component.ts + 87 Error while storing settings on server: src/app/components/manage/settings/settings.component.ts - 80 + 103 @@ -510,7 +531,7 @@ Saved views src/app/components/manage/settings/settings.component.html - 64 + 114 @@ -520,109 +541,158 @@ 13 + + Display language + + src/app/components/manage/settings/settings.component.html + 17 + + + + You need to reload the page after applying a new language. + + src/app/components/manage/settings/settings.component.html + 25 + + + + Date display + + src/app/components/manage/settings/settings.component.html + 32 + + + + Date format + + src/app/components/manage/settings/settings.component.html + 45 + + + + Short: + + src/app/components/manage/settings/settings.component.html + 51 + + + + Medium: + + src/app/components/manage/settings/settings.component.html + 55 + + + + Long: + + src/app/components/manage/settings/settings.component.html + 59 + + Items per page src/app/components/manage/settings/settings.component.html - 17 + 67 Document editor src/app/components/manage/settings/settings.component.html - 33 + 83 Use PDF viewer provided by the browser src/app/components/manage/settings/settings.component.html - 37 + 87 This is usually faster for displaying large PDF documents, but it might not work on some browsers. src/app/components/manage/settings/settings.component.html - 37 + 87 Dark mode src/app/components/manage/settings/settings.component.html - 44 + 94 Use system settings src/app/components/manage/settings/settings.component.html - 47 + 97 Enable dark mode src/app/components/manage/settings/settings.component.html - 48 + 98 Bulk editing src/app/components/manage/settings/settings.component.html - 52 + 102 Show confirmation dialogs src/app/components/manage/settings/settings.component.html - 56 + 106 Deleting documents will always ask for confirmation. src/app/components/manage/settings/settings.component.html - 56 + 106 Apply on close src/app/components/manage/settings/settings.component.html - 57 + 107 Appears on src/app/components/manage/settings/settings.component.html - 76 + 126 Show on dashboard src/app/components/manage/settings/settings.component.html - 79 + 129 Show in sidebar src/app/components/manage/settings/settings.component.html - 83 + 133 No saved views defined. src/app/components/manage/settings/settings.component.html - 93 + 143 @@ -650,7 +720,7 @@ Last correspondence src/app/components/manage/correspondent-list/correspondent-list.component.html - 15 + 22 @@ -692,21 +762,21 @@ Matching algorithm src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html - 11 + 10 Matching pattern src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html - 12 + 11 Case insensitive src/app/components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component.html - 13 + 12 @@ -913,13 +983,6 @@ 46 - - Filter by: - - src/app/components/document-list/filter-editor/filter-editor.component.html - 4 - - Filter tags @@ -1019,8 +1082,8 @@ 50 - - Created: + + Created: src/app/components/document-list/document-card-large/document-card-large.component.html 67 @@ -1400,6 +1463,34 @@ 12 + + English (US) + + src/app/services/settings.service.ts + 74 + + + + German + + src/app/services/settings.service.ts + 75 + + + + Dutch + + src/app/services/settings.service.ts + 76 + + + + French + + src/app/services/settings.service.ts + 77 + + Error @@ -1558,56 +1649,56 @@ Create new item src/app/components/common/edit-dialog/edit-dialog.component.ts - 43 + 50 Edit item src/app/components/common/edit-dialog/edit-dialog.component.ts - 47 + 54 Could not save element: src/app/components/common/edit-dialog/edit-dialog.component.ts - 51 + 58 Automatic src/app/components/manage/generic-list/generic-list.component.ts - 33 + 39 Do you really want to delete this element? src/app/components/manage/generic-list/generic-list.component.ts - 76 + 97 Associated documents will not be deleted. src/app/components/manage/generic-list/generic-list.component.ts - 83 + 104 Delete src/app/components/manage/generic-list/generic-list.component.ts - 85 + 106 Error while deleting element: src/app/components/manage/generic-list/generic-list.component.ts - 93 + 114 diff --git a/src-ui/src/app/app.module.ts b/src-ui/src/app/app.module.ts index 30411c980..49e937c0b 100644 --- a/src-ui/src/app/app.module.ts +++ b/src-ui/src/app/app.module.ts @@ -13,7 +13,7 @@ import { DocumentTypeListComponent } from './components/manage/document-type-lis import { LogsComponent } from './components/manage/logs/logs.component'; import { SettingsComponent } from './components/manage/settings/settings.component'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { DatePipe } from '@angular/common'; +import { DatePipe, registerLocaleData } from '@angular/common'; import { NotFoundComponent } from './components/not-found/not-found.component'; import { CorrespondentListComponent } from './components/manage/correspondent-list/correspondent-list.component'; import { ConfirmDialogComponent } from './components/common/confirm-dialog/confirm-dialog.component'; @@ -59,6 +59,15 @@ import { SelectDialogComponent } from './components/common/select-dialog/select- import { NgSelectModule } from '@ng-select/ng-select'; import { NumberComponent } from './components/common/input/number/number.component'; import { SafePipe } from './pipes/safe.pipe'; +import { CustomDatePipe } from './pipes/custom-date.pipe'; + +import localeFr from '@angular/common/locales/fr'; +import localeNl from '@angular/common/locales/nl'; +import localeDe from '@angular/common/locales/de'; + +registerLocaleData(localeFr) +registerLocaleData(localeNl) +registerLocaleData(localeDe) @NgModule({ declarations: [ @@ -108,7 +117,8 @@ import { SafePipe } from './pipes/safe.pipe'; MetadataCollapseComponent, SelectDialogComponent, NumberComponent, - SafePipe + SafePipe, + CustomDatePipe ], imports: [ BrowserModule, diff --git a/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts b/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts index 46f486167..3faf18dbb 100644 --- a/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts +++ b/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts @@ -27,6 +27,8 @@ export abstract class EditDialogComponent implements OnI networkActive = false + closeEnabled = false + error = null abstract getForm(): FormGroup @@ -37,6 +39,11 @@ export abstract class EditDialogComponent implements OnI if (this.object != null) { this.objectForm.patchValue(this.object) } + + // wait to enable close button so it doesnt steal focus from input since its the first clickable element in the DOM + setTimeout(() => { + this.closeEnabled = true + }); } getCreateTitle() { diff --git a/src-ui/src/app/components/dashboard/dashboard.component.html b/src-ui/src/app/components/dashboard/dashboard.component.html index 47751fe8b..c10b8ea04 100644 --- a/src-ui/src/app/components/dashboard/dashboard.component.html +++ b/src-ui/src/app/components/dashboard/dashboard.component.html @@ -1,5 +1,5 @@ -
-
- +
+
- +
@@ -17,11 +17,11 @@
- {{(document.correspondent$ | async)?.name}} + {{(document.correspondent$ | async)?.name}} {{(document.correspondent$ | async)?.name}}: {{document.title | documentTitle}} - +
#{{document.archive_serial_number}}
@@ -64,7 +64,7 @@
#{{document.archiv
- Created: {{document.created | date}} + Created: {{document.created | customDate}}
diff --git a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts index e3bd4b7f7..f8bb9f518 100644 --- a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts +++ b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts @@ -15,16 +15,11 @@ export class DocumentCardLargeComponent implements OnInit { @Input() selected = false - setSelected(value: boolean) { - this.selected = value - this.selectedChange.emit(value) - } - @Output() - selectedChange = new EventEmitter() + toggleSelected = new EventEmitter() get selectable() { - return this.selectedChange.observers.length > 0 + return this.toggleSelected.observers.length > 0 } @Input() diff --git a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html index c951bf281..882de71ed 100644 --- a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html +++ b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html @@ -1,18 +1,18 @@
-
- +
+
- +
- +
+ {{moreTags}} @@ -23,7 +23,7 @@

- {{(document.correspondent$ | async)?.name}}: + {{(document.correspondent$ | async)?.name}}: {{document.title | documentTitle}} (#{{document.archive_serial_number}})

@@ -43,14 +43,14 @@ - +
- {{document.created | date}} + {{document.created | customDate:'shortDate'}}
diff --git a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.ts b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.ts index ed69c5c50..5db0e30c0 100644 --- a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.ts +++ b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.ts @@ -14,14 +14,9 @@ export class DocumentCardSmallComponent implements OnInit { @Input() selected = false - - setSelected(value: boolean) { - this.selected = value - this.selectedChange.emit(value) - } - + @Output() - selectedChange = new EventEmitter() + toggleSelected = new EventEmitter() @Input() document: PaperlessDocument diff --git a/src-ui/src/app/components/document-list/document-list.component.html b/src-ui/src/app/components/document-list/document-list.component.html index 612238215..cfc2e655d 100644 --- a/src-ui/src/app/components/document-list/document-list.component.html +++ b/src-ui/src/app/components/document-list/document-list.component.html @@ -90,7 +90,7 @@
- +
@@ -135,10 +135,10 @@ i18n>Added - +
- +
@@ -147,28 +147,28 @@ - {{(d.correspondent$ | async)?.name}} + {{(d.correspondent$ | async)?.name}} {{d.title | documentTitle}} - + - {{(d.document_type$ | async)?.name}} + {{(d.document_type$ | async)?.name}} - {{d.created | date}} + {{d.created | customDate}} - {{d.added | date}} + {{d.added | customDate}}
- +
diff --git a/src-ui/src/app/components/document-list/document-list.component.scss b/src-ui/src/app/components/document-list/document-list.component.scss index f90a94be4..28f765e29 100644 --- a/src-ui/src/app/components/document-list/document-list.component.scss +++ b/src-ui/src/app/components/document-list/document-list.component.scss @@ -1,5 +1,9 @@ @import "/src/theme"; +tr { + user-select: none; +} + .table-row-selected { background-color: $primaryFaded; } diff --git a/src-ui/src/app/components/document-list/document-list.component.ts b/src-ui/src/app/components/document-list/document-list.component.ts index fda99eb8d..509c0a735 100644 --- a/src-ui/src/app/components/document-list/document-list.component.ts +++ b/src-ui/src/app/components/document-list/document-list.component.ts @@ -160,6 +160,11 @@ export class DocumentListComponent implements OnInit { this.filterRulesModified = modified } + toggleSelected(document: PaperlessDocument, event: MouseEvent): void { + if (!event.shiftKey) this.list.toggleSelected(document) + else this.list.selectRangeTo(document) + } + clickTag(tagID: number) { this.list.selectNone() setTimeout(() => { diff --git a/src-ui/src/app/components/document-list/save-view-config-dialog/save-view-config-dialog.component.html b/src-ui/src/app/components/document-list/save-view-config-dialog/save-view-config-dialog.component.html index f2063df7e..7f1d39859 100644 --- a/src-ui/src/app/components/document-list/save-view-config-dialog/save-view-config-dialog.component.html +++ b/src-ui/src/app/components/document-list/save-view-config-dialog/save-view-config-dialog.component.html @@ -1,7 +1,7 @@
diff --git a/src-ui/src/app/components/document-list/save-view-config-dialog/save-view-config-dialog.component.ts b/src-ui/src/app/components/document-list/save-view-config-dialog/save-view-config-dialog.component.ts index e930ffaed..4f70941dd 100644 --- a/src-ui/src/app/components/document-list/save-view-config-dialog/save-view-config-dialog.component.ts +++ b/src-ui/src/app/components/document-list/save-view-config-dialog/save-view-config-dialog.component.ts @@ -20,6 +20,8 @@ export class SaveViewConfigDialogComponent implements OnInit { @Input() buttonsEnabled = true + closeEnabled = false + _defaultName = "" get defaultName() { @@ -31,7 +33,7 @@ export class SaveViewConfigDialogComponent implements OnInit { this._defaultName = value this.saveViewConfigForm.patchValue({name: value}) } - + saveViewConfigForm = new FormGroup({ name: new FormControl(''), showInSideBar: new FormControl(false), @@ -39,6 +41,10 @@ export class SaveViewConfigDialogComponent implements OnInit { }) ngOnInit(): void { + // wait to enable close button so it doesnt steal focus from input since its the first clickable element in the DOM + setTimeout(() => { + this.closeEnabled = true + }); } save() { 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 3544aeed0..bbc2c8453 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 @@ -1,12 +1,11 @@