Feature: Dynamic document storage pathes (#916)

* Added devcontainer

* Add feature storage pathes

* Exclude tests and add versioning

* Check escaping

* Check escaping

* Check quoting

* Echo

* Escape

* Escape :

* Double escape \

* Escaping

* Remove if

* Escape colon

* Missing \

* Esacpe :

* Escape all

* test

* Remove sed

* Fix exclude

* Remove SED command

* Add LD_LIBRARY_PATH

* Adjusted to v1.7

* Updated test-cases

* Remove devcontainer

* Removed internal build-file

* Run pre-commit

* Corrected flak8 error

* Adjusted to v1.7

* Updated test-cases

* Corrected flak8 error

* Adjusted to new plural translations

* Small adjustments due to code-review backend

* Adjusted line-break

* Removed PAPERLESS prefix from settings variables

* Corrected style change due to search+replace

* First documentation draft

* Revert changes to Pipfile

* Add sphinx-autobuild with keep-outdated

* Revert merge error that results in wrong storage path is evaluated

* Adjust styles of generated files ...

* Adds additional testing to cover dynamic storage path functionality

* Remove unnecessary condition

* Add hint to edit storage path dialog

* Correct spelling of pathes to paths

* Minor documentation tweaks

* Minor typo

* improving wrapping of filter editor buttons with new storage path button

* Update .gitignore

* Fix select border radius in non input-groups

* Better storage path edit hint

* Add note to edit storage path dialog re document_renamer

* Add note to bulk edit storage path re document_renamer

* Rename FILTER_STORAGE_DIRECTORY to PATH

* Fix broken filter rule parsing

* Show default storage if unspecified

* Remove note re storage path on bulk edit

* Add basic validation of filename variables

Co-authored-by: Markus Kling <markus@markus-kling.net>
Co-authored-by: Trenton Holmes <holmes.trenton@gmail.com>
Co-authored-by: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Co-authored-by: Quinn Casey <quinn@quinncasey.com>
This commit is contained in:
Markus
2022-05-19 23:42:25 +02:00
committed by GitHub
parent c5e03c7f28
commit dd3b5c129c
67 changed files with 1427 additions and 203 deletions

View File

@@ -53,6 +53,15 @@
[(selectionModel)]="documentTypeSelectionModel"
(apply)="setDocumentTypes($event)">
</app-filterable-dropdown>
<app-filterable-dropdown class="me-2 me-md-3" title="Storage path" icon="folder-fill" i18n-title
filterPlaceholder="Filter storage paths" i18n-filterPlaceholder
[items]="storagePaths"
[editing]="true"
[applyOnClose]="applyOnClose"
(open)="openStoragePathDropdown()"
[(selectionModel)]="storagePathsSelectionModel"
(apply)="setStoragePaths($event)">
</app-filterable-dropdown>
</div>
</div>
<div class="col-auto ms-auto mb-2 mb-xl-0 d-flex">

View File

@@ -22,6 +22,8 @@ import { MatchingModel } from 'src/app/data/matching-model'
import { SettingsService } from 'src/app/services/settings.service'
import { ToastService } from 'src/app/services/toast.service'
import { saveAs } from 'file-saver'
import { StoragePathService } from 'src/app/services/rest/storage-path.service'
import { PaperlessStoragePath } from 'src/app/data/paperless-storage-path'
import { SETTINGS_KEYS } from 'src/app/data/paperless-uisettings'
@Component({
@@ -33,10 +35,12 @@ export class BulkEditorComponent {
tags: PaperlessTag[]
correspondents: PaperlessCorrespondent[]
documentTypes: PaperlessDocumentType[]
storagePaths: PaperlessStoragePath[]
tagSelectionModel = new FilterableDropdownSelectionModel()
correspondentSelectionModel = new FilterableDropdownSelectionModel()
documentTypeSelectionModel = new FilterableDropdownSelectionModel()
storagePathsSelectionModel = new FilterableDropdownSelectionModel()
awaitingDownload: boolean
constructor(
@@ -48,7 +52,8 @@ export class BulkEditorComponent {
private modalService: NgbModal,
private openDocumentService: OpenDocumentsService,
private settings: SettingsService,
private toastService: ToastService
private toastService: ToastService,
private storagePathService: StoragePathService
) {}
applyOnClose: boolean = this.settings.get(
@@ -68,6 +73,9 @@ export class BulkEditorComponent {
this.documentTypeService
.listAll()
.subscribe((result) => (this.documentTypes = result.results))
this.storagePathService
.listAll()
.subscribe((result) => (this.storagePaths = result.results))
}
private executeBulkOperation(modal, method: string, args) {
@@ -145,6 +153,17 @@ export class BulkEditorComponent {
})
}
openStoragePathDropdown() {
this.documentService
.getSelectionData(Array.from(this.list.selected))
.subscribe((s) => {
this.applySelectionData(
s.selected_storage_paths,
this.storagePathsSelectionModel
)
})
}
private _localizeList(items: MatchingModel[]) {
if (items.length == 0) {
return ''
@@ -299,6 +318,42 @@ export class BulkEditorComponent {
}
}
setStoragePaths(changedDocumentPaths: ChangedItems) {
if (
changedDocumentPaths.itemsToAdd.length == 0 &&
changedDocumentPaths.itemsToRemove.length == 0
)
return
let storagePath =
changedDocumentPaths.itemsToAdd.length > 0
? changedDocumentPaths.itemsToAdd[0]
: null
if (this.showConfirmationDialogs) {
let modal = this.modalService.open(ConfirmDialogComponent, {
backdrop: 'static',
})
modal.componentInstance.title = $localize`Confirm storage path assignment`
if (storagePath) {
modal.componentInstance.message = $localize`This operation will assign the storage path "${storagePath.name}" to ${this.list.selected.size} selected document(s).`
} else {
modal.componentInstance.message = $localize`This operation will remove the storage path from ${this.list.selected.size} selected document(s).`
}
modal.componentInstance.btnClass = 'btn-warning'
modal.componentInstance.btnCaption = $localize`Confirm`
modal.componentInstance.confirmClicked.subscribe(() => {
this.executeBulkOperation(modal, 'set_storage_path', {
storage_path: storagePath ? storagePath.id : null,
})
})
} else {
this.executeBulkOperation(null, 'set_storage_path', {
storage_path: storagePath ? storagePath.id : null,
})
}
}
applyDelete() {
let modal = this.modalService.open(ConfirmDialogComponent, {
backdrop: 'static',