mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Only apply edits when something has changed
This commit is contained in:
		| @@ -37,7 +37,7 @@ export class FilterableDropdownComponent { | ||||
|   @Input() | ||||
|   set items(items: ObjectWithId[]) { | ||||
|     if (items) { | ||||
|       this.selectableItems = items.map(i => { | ||||
|       this._selectableItems = items.map(i => { | ||||
|         return {item: i, state: SelectableItemState.NotSelected} | ||||
|       }) | ||||
|     } | ||||
| @@ -84,15 +84,16 @@ export class FilterableDropdownComponent { | ||||
|   toggle = new EventEmitter() | ||||
|  | ||||
|   @Output() | ||||
|   close = new EventEmitter() | ||||
|   open = new EventEmitter() | ||||
|  | ||||
|   @Output() | ||||
|   editingComplete = new EventEmitter() | ||||
|  | ||||
|   constructor(private filterPipe: FilterPipe) { } | ||||
|  | ||||
|   toggleItem(selectableItem: SelectableItem): void { | ||||
|     if (this.singular && selectableItem.state == SelectableItemState.Selected) { | ||||
|       this._selectableItems.forEach(si => { | ||||
|         if (si.state == SelectableItemState.Selected && si.item.id !== selectableItem.item.id) si.state = SelectableItemState.NotSelected | ||||
|       }) | ||||
|       this._selectableItems.filter(si => si.item.id !== selectableItem.item.id).forEach(si => si.state = SelectableItemState.NotSelected) | ||||
|     } | ||||
|     this.toggle.emit(selectableItem.item) | ||||
|   } | ||||
| @@ -101,10 +102,11 @@ export class FilterableDropdownComponent { | ||||
|     if (open) { | ||||
|       setTimeout(() => { | ||||
|         this.listFilterTextInput.nativeElement.focus(); | ||||
|       }, 0); | ||||
|       }, 0) | ||||
|       this.open.next() | ||||
|     } else { | ||||
|       this.filterText = '' | ||||
|       this.close.emit(this.itemsSelected) | ||||
|       if (this.type == FilterableDropdownType.Editing) this.editingComplete.emit(this.itemsSelected) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -26,9 +26,9 @@ | ||||
|   <div class="col mb-2 mb-xl-0"> | ||||
|     <div class="d-flex"> | ||||
|       <label class="ml-auto mt-1 mr-2">Apply:</label> | ||||
|       <app-filterable-dropdown class="mr-2 mr-md-3" title="Tags" icon="tag-fill" [selectableItems]="tagsSelectableItems" [type]="dropdownTypes.Editing" (close)="applyTags($event)"></app-filterable-dropdown> | ||||
|       <app-filterable-dropdown class="mr-2 mr-md-3" title="Correspondent" icon="person-fill" [selectableItems]="correspondentsSelectableItems" [type]="dropdownTypes.Editing" singular="true" (close)="applyCorrespondent($event)"></app-filterable-dropdown> | ||||
|       <app-filterable-dropdown class="mr-2 mr-md-3" title="Document Type" icon="file-earmark-fill" [selectableItems]="documentTypesSelectableItems" [type]="dropdownTypes.Editing" singular="true" (close)="applyDocumentType($event)"></app-filterable-dropdown> | ||||
|       <app-filterable-dropdown class="mr-2 mr-md-3" title="Tags" icon="tag-fill" [selectableItems]="tagsSelectableItems" [type]="dropdownTypes.Editing" (open)="tagsDropdownOpen()" (editingComplete)="applyTags($event)"></app-filterable-dropdown> | ||||
|       <app-filterable-dropdown class="mr-2 mr-md-3" title="Correspondent" icon="person-fill" [selectableItems]="correspondentsSelectableItems" [type]="dropdownTypes.Editing" singular="true" (open)="correspondentsDropdownOpen()" (editingComplete)="applyCorrespondent($event)"></app-filterable-dropdown> | ||||
|       <app-filterable-dropdown class="mr-2 mr-md-3" title="Document Type" icon="file-earmark-fill" [selectableItems]="documentTypesSelectableItems" [type]="dropdownTypes.Editing" singular="true" (open)="documentTypesDropdownOpen()" (editingComplete)="applyDocumentType($event)"></app-filterable-dropdown> | ||||
|     </div> | ||||
|   </div> | ||||
|   <div class="w-100 d-xl-none"></div> | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import { Component, EventEmitter, Input, Output } from '@angular/core'; | ||||
| import { ObjectWithId } from 'src/app/data/object-with-id'; | ||||
| import { PaperlessTag } from 'src/app/data/paperless-tag'; | ||||
| import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'; | ||||
| import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'; | ||||
| @@ -47,7 +48,12 @@ export class BulkEditorComponent { | ||||
|   correspondents: PaperlessCorrespondent[] | ||||
|   documentTypes: PaperlessDocumentType[] | ||||
|  | ||||
|   private _initialTagsSelectableItems: SelectableItem[] | ||||
|   private _initialCorrespondentsSelectableItems: SelectableItem[] | ||||
|   private _initialDocumentTypesSelectableItems: SelectableItem[] | ||||
|  | ||||
|   dropdownTypes = FilterableDropdownType | ||||
|  | ||||
|   get tagsSelectableItems(): SelectableItem[] { | ||||
|     let tagsSelectableItems = [] | ||||
|     let selectedDocuments: PaperlessDocument[] = this.allDocuments.filter(d => this.selectedDocuments.has(d.id)) | ||||
| @@ -72,7 +78,6 @@ export class BulkEditorComponent { | ||||
|       else if (selectedDocumentsWithCorrespondent.length > 0 && selectedDocumentsWithCorrespondent.length < selectedDocuments.length) state = SelectableItemState.PartiallySelected | ||||
|       correspondentsSelectableItems.push( { item: c, state: state } ) | ||||
|     }) | ||||
|  | ||||
|     return correspondentsSelectableItems | ||||
|   } | ||||
|  | ||||
| @@ -87,7 +92,6 @@ export class BulkEditorComponent { | ||||
|       else if (selectedDocumentsWithDocumentType.length > 0 && selectedDocumentsWithDocumentType.length < selectedDocuments.length) state = SelectableItemState.PartiallySelected | ||||
|       documentTypesSelectableItems.push( { item: dt, state: state } ) | ||||
|     }) | ||||
|  | ||||
|     return documentTypesSelectableItems | ||||
|   } | ||||
|  | ||||
| @@ -104,16 +108,43 @@ export class BulkEditorComponent { | ||||
|     this.documentTypeService.listAll().subscribe(result => this.documentTypes = result.results) | ||||
|   } | ||||
|  | ||||
|   applyTags(tags: PaperlessTag[]) { | ||||
|     this.setTags.emit(tags) | ||||
|   tagsDropdownOpen() { | ||||
|     this._initialTagsSelectableItems = this.tagsSelectableItems | ||||
|   } | ||||
|  | ||||
|   applyCorrespondent(selectedCorrespondent: PaperlessCorrespondent[]) { | ||||
|     this.setCorrespondent.emit(selectedCorrespondent.length > 0 ? selectedCorrespondent.shift() : null) | ||||
|   correspondentsDropdownOpen() { | ||||
|     this._initialCorrespondentsSelectableItems = this.correspondentsSelectableItems | ||||
|   } | ||||
|  | ||||
|   applyDocumentType(selectedDocumentType: PaperlessDocumentType[]) { | ||||
|     this.setDocumentType.emit(selectedDocumentType.length > 0 ? selectedDocumentType.shift() : null) | ||||
|   documentTypesDropdownOpen() { | ||||
|     this._initialDocumentTypesSelectableItems = this.documentTypesSelectableItems | ||||
|   } | ||||
|  | ||||
|   applyTags(selectedTags: PaperlessTag[]) { | ||||
|     let initiallySelectedSelectableTags = this._initialTagsSelectableItems.filter(tsi => tsi.state == SelectableItemState.Selected) | ||||
|     let unchanged = this.equateItemsToSelectableItems(selectedTags, initiallySelectedSelectableTags) | ||||
|     if (!unchanged) this.setTags.emit(selectedTags) | ||||
|     this._initialTagsSelectableItems = null | ||||
|   } | ||||
|  | ||||
|   applyCorrespondent(selectedCorrespondents: PaperlessCorrespondent[]) { | ||||
|     let initiallySelectedSelectableCorrespondents = this._initialCorrespondentsSelectableItems.filter(csi => csi.state == SelectableItemState.Selected) | ||||
|     let unchanged = this.equateItemsToSelectableItems(selectedCorrespondents, initiallySelectedSelectableCorrespondents) | ||||
|     if (!unchanged) this.setCorrespondent.emit(selectedCorrespondents?.length > 0 ? selectedCorrespondents.shift() : null) | ||||
|     this._initialCorrespondentsSelectableItems = null | ||||
|   } | ||||
|  | ||||
|   applyDocumentType(selectedDocumentTypes: PaperlessDocumentType[]) { | ||||
|     let initiallySelectedSelectableDocumentTypes = this._initialDocumentTypesSelectableItems.filter(dtsi => dtsi.state == SelectableItemState.Selected) | ||||
|     let unchanged = this.equateItemsToSelectableItems(selectedDocumentTypes, initiallySelectedSelectableDocumentTypes) | ||||
|     if (!unchanged) this.setDocumentType.emit(selectedDocumentTypes.length > 0 ? selectedDocumentTypes.shift() : null) | ||||
|     this._initialDocumentTypesSelectableItems = null | ||||
|   } | ||||
|  | ||||
|   equateItemsToSelectableItems(items: ObjectWithId[], selectableItems: SelectableItem[]): boolean { | ||||
|     // either both empty or all items must in selectableItems and vice-versa | ||||
|     return (selectableItems.length == 0 && items.length == 0) || | ||||
|            (items.every(i => selectableItems.find(si => si.item.id == i.id) !== undefined) && selectableItems.every(si => items.find(i => i.id == si.item.id) !== undefined)) | ||||
|   } | ||||
|  | ||||
|   applyDelete() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Michael Shamoon
					Michael Shamoon