mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-28 03:46:06 -05:00 
			
		
		
		
	Unify bulk operations logic, working tags assignment and removal
This commit is contained in:
		| @@ -11,7 +11,7 @@ import { DocumentService } from 'src/app/services/rest/document.service'; | |||||||
| import { FilterableDropdownType } from 'src/app/components/common/filterable-dropdown/filterable-dropdown.component'; | import { FilterableDropdownType } from 'src/app/components/common/filterable-dropdown/filterable-dropdown.component'; | ||||||
| import { ToggleableItem, ToggleableItemState } from 'src/app/components/common/filterable-dropdown/toggleable-dropdown-button/toggleable-dropdown-button.component'; | import { ToggleableItem, ToggleableItemState } from 'src/app/components/common/filterable-dropdown/toggleable-dropdown-button/toggleable-dropdown-button.component'; | ||||||
|  |  | ||||||
| interface ChangedItems { | export interface ChangedItems { | ||||||
|   itemsToAdd: any[], |   itemsToAdd: any[], | ||||||
|   itemsToRemove: any[] |   itemsToRemove: any[] | ||||||
| } | } | ||||||
| @@ -42,23 +42,14 @@ export class BulkEditorComponent { | |||||||
|   setTags = new EventEmitter() |   setTags = new EventEmitter() | ||||||
|  |  | ||||||
|   @Output() |   @Output() | ||||||
|   setCorrespondent = new EventEmitter() |   setCorrespondents = new EventEmitter() | ||||||
|  |  | ||||||
|   @Output() |   @Output() | ||||||
|   setDocumentType = new EventEmitter() |   setDocumentTypes = new EventEmitter() | ||||||
|  |  | ||||||
|   @Output() |   @Output() | ||||||
|   delete = new EventEmitter() |   delete = new EventEmitter() | ||||||
|  |  | ||||||
|   @Output() |  | ||||||
|   removeTags = new EventEmitter() |  | ||||||
|  |  | ||||||
|   @Output() |  | ||||||
|   removeCorrespondents = new EventEmitter() |  | ||||||
|  |  | ||||||
|   @Output() |  | ||||||
|   removeDocumentTypes = new EventEmitter() |  | ||||||
|  |  | ||||||
|   tags: PaperlessTag[] |   tags: PaperlessTag[] | ||||||
|   correspondents: PaperlessCorrespondent[] |   correspondents: PaperlessCorrespondent[] | ||||||
|   documentTypes: PaperlessDocumentType[] |   documentTypes: PaperlessDocumentType[] | ||||||
| @@ -151,8 +142,7 @@ export class BulkEditorComponent { | |||||||
|  |  | ||||||
|   applyTags(newTagsToggleableItems: ToggleableItem[]) { |   applyTags(newTagsToggleableItems: ToggleableItem[]) { | ||||||
|     let changedTags = this.checkForChangedItems(this.initialTagsToggleableItems, newTagsToggleableItems) |     let changedTags = this.checkForChangedItems(this.initialTagsToggleableItems, newTagsToggleableItems) | ||||||
|     if (changedTags.itemsToAdd.length > 0) this.setTags.emit(changedTags.itemsToAdd) |     if (changedTags.itemsToAdd.length > 0 || changedTags.itemsToRemove.length > 0) this.setTags.emit(changedTags) | ||||||
|     if (changedTags.itemsToRemove.length > 0) this.removeTags.emit(changedTags.itemsToRemove) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   removeAllTags() { |   removeAllTags() { | ||||||
| @@ -161,22 +151,20 @@ export class BulkEditorComponent { | |||||||
|  |  | ||||||
|   applyCorrespondent(newCorrespondentsToggleableItems: ToggleableItem[]) { |   applyCorrespondent(newCorrespondentsToggleableItems: ToggleableItem[]) { | ||||||
|     let changedCorrespondents = this.checkForChangedItems(this.initialCorrespondentsToggleableItems, newCorrespondentsToggleableItems) |     let changedCorrespondents = this.checkForChangedItems(this.initialCorrespondentsToggleableItems, newCorrespondentsToggleableItems) | ||||||
|     if (changedCorrespondents.itemsToAdd.length > 0) this.setCorrespondent.emit(changedCorrespondents.itemsToAdd[0]) |     if (changedCorrespondents.itemsToAdd.length > 0 || changedCorrespondents.itemsToRemove.length > 0) this.setCorrespondents.emit(changedCorrespondents) | ||||||
|     else if (changedCorrespondents.itemsToRemove.length > 0) this.removeCorrespondents.emit(changedCorrespondents.itemsToRemove) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   removeAllCorrespondents() { |   removeAllCorrespondents() { | ||||||
|     this.setDocumentType.emit(null) |     this.setDocumentTypes.emit(null) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   applyDocumentType(newDocumentTypesToggleableItems: ToggleableItem[]) { |   applyDocumentType(newDocumentTypesToggleableItems: ToggleableItem[]) { | ||||||
|     let changedDocumentTypes = this.checkForChangedItems(this.initialDocumentTypesToggleableItems, newDocumentTypesToggleableItems) |     let changedDocumentTypes = this.checkForChangedItems(this.initialDocumentTypesToggleableItems, newDocumentTypesToggleableItems) | ||||||
|     if (changedDocumentTypes.itemsToAdd.length > 0) this.setDocumentType.emit(changedDocumentTypes.itemsToAdd[0]) |     if (changedDocumentTypes.itemsToAdd.length > 0 || changedDocumentTypes.itemsToRemove.length > 0) this.setDocumentTypes.emit(changedDocumentTypes) | ||||||
|     else if (changedDocumentTypes.itemsToRemove.length > 0) this.removeDocumentTypes.emit(changedDocumentTypes.itemsToRemove) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   removeAllDocumentTypes() { |   removeAllDocumentTypes() { | ||||||
|     this.setDocumentType.emit(null) |     this.setDocumentTypes.emit(null) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   checkForChangedItems(toggleableItemsA: ToggleableItem[], toggleableItemsB: ToggleableItem[]): ChangedItems { |   checkForChangedItems(toggleableItemsA: ToggleableItem[], toggleableItemsB: ToggleableItem[]): ChangedItems { | ||||||
|   | |||||||
| @@ -87,11 +87,8 @@ | |||||||
|     (selectAll)="list.selectAll()" |     (selectAll)="list.selectAll()" | ||||||
|     (selectNone)="list.selectNone()" |     (selectNone)="list.selectNone()" | ||||||
|     (setTags)="bulkSetTags($event)" |     (setTags)="bulkSetTags($event)" | ||||||
|     (removeTags)="bulkRemoveTags($event)" |     (setCorrespondents)="bulkSetCorrespondents($event)" | ||||||
|     (setCorrespondent)="bulkSetCorrespondent($event)" |     (setDocumentTypes)="bulkSetDocumentTypes($event)" | ||||||
|     (removeCorrespondents)="bulkRemoveCorrespondents($event)" |  | ||||||
|     (setDocumentType)="bulkSetDocumentType($event)" |  | ||||||
|     (removeDocumentTypes)="bulkRemoveDocumentTypes($event)" |  | ||||||
|     (delete)="bulkDelete()"> |     (delete)="bulkDelete()"> | ||||||
| </app-bulk-editor> | </app-bulk-editor> | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ import { SaveViewConfigDialogComponent } from './save-view-config-dialog/save-vi | |||||||
| import { PaperlessTag } from 'src/app/data/paperless-tag'; | import { PaperlessTag } from 'src/app/data/paperless-tag'; | ||||||
| import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'; | import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'; | ||||||
| import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'; | import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'; | ||||||
|  | import { ChangedItems } from './bulk-editor/bulk-editor.component'; | ||||||
|  |  | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-document-list', |   selector: 'app-document-list', | ||||||
| @@ -156,47 +157,71 @@ export class DocumentListComponent implements OnInit { | |||||||
|     ) |     ) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bulkSetCorrespondent(correspondent: PaperlessCorrespondent) { |   bulkSetTags(changedTags: ChangedItems) { | ||||||
|     let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'}) |     let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'}) | ||||||
|     modal.componentInstance.title = "Confirm Correspondent assignment" |     modal.componentInstance.title = "Confirm Tags Assignment" | ||||||
|     let messageFragment = correspondent ? `assign the correspondent ${correspondent.name} to` : `remove all correspondents from` |     let action = 'set_tags' | ||||||
|  |     let tags | ||||||
|  |     let messageFragment = '' | ||||||
|  |     let both = changedTags && changedTags.itemsToAdd.length > 0 && changedTags.itemsToRemove.length > 0 | ||||||
|  |     if (!changedTags) { | ||||||
|  |       messageFragment = `remove all tags from` | ||||||
|  |     } else { | ||||||
|  |       if (changedTags.itemsToAdd.length > 0) { | ||||||
|  |         tags = changedTags.itemsToAdd | ||||||
|  |         messageFragment = `assign the tag(s) ${changedTags.itemsToAdd.map(t => t.name).join(', ')} to` | ||||||
|  |       } | ||||||
|  |       if (changedTags.itemsToRemove.length > 0) { | ||||||
|  |         if (!both) { | ||||||
|  |           // TODO: API endpoint for remove multiple tags | ||||||
|  |           action = 'remove_tags' | ||||||
|  |           tags = changedTags.itemsToRemove | ||||||
|  |         } else { | ||||||
|  |           messageFragment += ' and ' | ||||||
|  |         } | ||||||
|  |         messageFragment += `remove the correspondent(s) ${changedTags.itemsToRemove.map(t => t.name).join(', ')} from` | ||||||
|  |       } | ||||||
|  |     } | ||||||
|     modal.componentInstance.message = `This operation will ${messageFragment} all ${this.list.selected.size} selected document(s).` |     modal.componentInstance.message = `This operation will ${messageFragment} all ${this.list.selected.size} selected document(s).` | ||||||
|     modal.componentInstance.btnClass = "btn-warning" |     modal.componentInstance.btnClass = "btn-warning" | ||||||
|     modal.componentInstance.btnCaption = "Confirm" |     modal.componentInstance.btnCaption = "Confirm" | ||||||
|     modal.componentInstance.confirmClicked.subscribe(() => { |     modal.componentInstance.confirmClicked.subscribe(() => { | ||||||
|       this.executeBulkOperation('set_correspondent', {"correspondent": correspondent ? correspondent.id : null}).subscribe( |       this.executeBulkOperation(action, {"tags": tags ? tags.map(t => t.id) : null}).subscribe( | ||||||
|         response => { |         response => { | ||||||
|           modal.close() |           if (!both) modal.close() | ||||||
|  |           else { | ||||||
|  |             this.executeBulkOperation('remove_tags', {"tags": changedTags.itemsToRemove.map(t => t.id)}).subscribe( | ||||||
|  |               response => { | ||||||
|  |                 modal.close() | ||||||
|  |               }) | ||||||
|  |           } | ||||||
|         } |         } | ||||||
|       ) |       ) | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bulkRemoveCorrespondents(correspondents: PaperlessCorrespondent[]) { |   bulkSetCorrespondents(changedCorrespondents: ChangedItems) { | ||||||
|     let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'}) |     let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'}) | ||||||
|     modal.componentInstance.title = "Confirm Correspondent Removal" |     modal.componentInstance.title = "Confirm Correspondent Assignment" | ||||||
|     modal.componentInstance.message = `This operation will remove the correspondent(s) ${correspondents.map(t => t.name).join(', ')} from all ${this.list.selected.size} selected document(s).` |     let action = 'set_correspondent' | ||||||
|     modal.componentInstance.btnClass = "btn-warning" |     let correspondents | ||||||
|     modal.componentInstance.btnCaption = "Confirm" |     let messageFragment | ||||||
|     modal.componentInstance.confirmClicked.subscribe(() => { |     if (!changedCorrespondents) { | ||||||
|  |       messageFragment = `remove all correspondents from` | ||||||
|  |     } else if (changedCorrespondents.itemsToAdd.length > 0) { | ||||||
|  |       correspondents = changedCorrespondents.itemsToAdd[0] | ||||||
|  |       messageFragment = `assign the correspondent ${correspondents.name} to` | ||||||
|  |     } else { | ||||||
|       // TODO: API endpoint for remove multiple correspondents |       // TODO: API endpoint for remove multiple correspondents | ||||||
|       this.executeBulkOperation('remove_correspondents', {"correspondents": correspondents.map(t => t.id)}).subscribe( |       action = 'remove_correspondents' | ||||||
|         response => { |       correspondents = changedCorrespondents.itemsToRemove | ||||||
|           modal.close() |       messageFragment = `remove the correspondent(s) ${correspondents.map(c => c.name).join(', ')} from` | ||||||
|         } |     } | ||||||
|       ) |  | ||||||
|     }) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bulkSetDocumentType(documentType: PaperlessDocumentType) { |  | ||||||
|     let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'}) |  | ||||||
|     modal.componentInstance.title = "Confirm Document Type assignment" |  | ||||||
|     let messageFragment = documentType ? `assign the document type ${documentType.name} to` : `remove all document types from` |  | ||||||
|     modal.componentInstance.message = `This operation will ${messageFragment} all ${this.list.selected.size} selected document(s).` |     modal.componentInstance.message = `This operation will ${messageFragment} all ${this.list.selected.size} selected document(s).` | ||||||
|     modal.componentInstance.btnClass = "btn-warning" |     modal.componentInstance.btnClass = "btn-warning" | ||||||
|     modal.componentInstance.btnCaption = "Confirm" |     modal.componentInstance.btnCaption = "Confirm" | ||||||
|     modal.componentInstance.confirmClicked.subscribe(() => { |     modal.componentInstance.confirmClicked.subscribe(() => { | ||||||
|       this.executeBulkOperation('set_document_type', {"document_type": documentType ? documentType.id : null}).subscribe( |       this.executeBulkOperation(action, {"correspondents": correspondents ? correspondents.map(c => c.id) : null}).subscribe( | ||||||
|         response => { |         response => { | ||||||
|           modal.close() |           modal.close() | ||||||
|         } |         } | ||||||
| @@ -204,48 +229,27 @@ export class DocumentListComponent implements OnInit { | |||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bulkRemoveDocumentTypes(documentTypes: PaperlessDocumentType[]) { |   bulkSetDocumentTypes(changedDocumentTypes: ChangedItems) { | ||||||
|     let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'}) |     let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'}) | ||||||
|     modal.componentInstance.title = "Confirm Document Type Removal" |     let action = 'set_document_type' | ||||||
|     modal.componentInstance.message = `This operation will remove the document type(s) ${documentTypes.map(t => t.name).join(', ')} all ${this.list.selected.size} selected document(s).` |     let documentTypes | ||||||
|     modal.componentInstance.btnClass = "btn-warning" |     let messageFragment | ||||||
|     modal.componentInstance.btnCaption = "Confirm" |     if (!changedDocumentTypes) { | ||||||
|     modal.componentInstance.confirmClicked.subscribe(() => { |       messageFragment = `remove all document types from` | ||||||
|       // TODO: API endpoint for remove multiple document types |     } else if (changedDocumentTypes.itemsToAdd.length > 0) { | ||||||
|       this.executeBulkOperation('remove_document_types', {"document_types": documentTypes.map(t => t.id)}).subscribe( |       documentTypes = changedDocumentTypes.itemsToAdd[0] | ||||||
|         response => { |       messageFragment = `assign the document type ${documentTypes.name} to` | ||||||
|           modal.close() |     } else { | ||||||
|         } |       // TODO: API endpoint for remove multiple doc types | ||||||
|       ) |       action = 'remove_document_types' | ||||||
|     }) |       documentTypes = changedDocumentTypes.itemsToRemove | ||||||
|   } |       messageFragment = `remove the document type(s) ${documentTypes.map(dt => dt.name).join(', ')} from` | ||||||
|  |     } | ||||||
|   bulkSetTags(tags: PaperlessTag[]) { |  | ||||||
|     let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'}) |  | ||||||
|     modal.componentInstance.title = "Confirm Tags assignment" |  | ||||||
|     let messageFragment = tags ? `assign the tag(s) ${tags.map(t => t.name).join(', ')} to` : `remove all tags from` |  | ||||||
|     modal.componentInstance.message = `This operation will ${messageFragment} all ${this.list.selected.size} selected document(s).` |     modal.componentInstance.message = `This operation will ${messageFragment} all ${this.list.selected.size} selected document(s).` | ||||||
|     modal.componentInstance.btnClass = "btn-warning" |     modal.componentInstance.btnClass = "btn-warning" | ||||||
|     modal.componentInstance.btnCaption = "Confirm" |     modal.componentInstance.btnCaption = "Confirm" | ||||||
|     modal.componentInstance.confirmClicked.subscribe(() => { |     modal.componentInstance.confirmClicked.subscribe(() => { | ||||||
|       // TODO: API endpoint for set multiple tags |       this.executeBulkOperation(action, {"document_types": documentTypes ? documentTypes.map(dt => dt.id) : null}).subscribe( | ||||||
|       this.executeBulkOperation('set_tags', {"tags": tags ? tags.map(t => t.id) : null}).subscribe( |  | ||||||
|         response => { |  | ||||||
|           modal.close() |  | ||||||
|         } |  | ||||||
|       ) |  | ||||||
|     }) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bulkRemoveTags(tags: PaperlessTag[]) { |  | ||||||
|     let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'}) |  | ||||||
|     modal.componentInstance.title = "Confirm Tags Removal" |  | ||||||
|     modal.componentInstance.message = `This operation will remove the tags ${tags.map(t => t.name).join(', ')} from all ${this.list.selected.size} selected document(s).` |  | ||||||
|     modal.componentInstance.btnClass = "btn-warning" |  | ||||||
|     modal.componentInstance.btnCaption = "Confirm" |  | ||||||
|     modal.componentInstance.confirmClicked.subscribe(() => { |  | ||||||
|       // TODO: API endpoint for remove multiple tags |  | ||||||
|       this.executeBulkOperation('remove_tags', {"tags": tags.map(t => t.id)}).subscribe( |  | ||||||
|         response => { |         response => { | ||||||
|           modal.close() |           modal.close() | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Michael Shamoon
					Michael Shamoon