mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-02 18:47:10 -05:00 
			
		
		
		
	Completely rewrite change detection, add back remove operations
This commit is contained in:
		
							parent
							
								
									4cae338479
								
							
						
					
					
						commit
						360fc081bb
					
				@ -19,6 +19,12 @@
 | 
				
			|||||||
          <input class="form-control" type="text" [(ngModel)]="filterText" placeholder="Filter {{title}}" (keyup.enter)="listFilterEnter()" #listFilterTextInput>
 | 
					          <input class="form-control" type="text" [(ngModel)]="filterText" placeholder="Filter {{title}}" (keyup.enter)="listFilterEnter()" #listFilterTextInput>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					      <button *ngIf="showRemoveAll" role="menuitem" class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-left-0 border-right-0 border-bottom" (click)="removeAll.next()">
 | 
				
			||||||
 | 
					        <svg class="toolbaricon text-danger" fill="currentColor">
 | 
				
			||||||
 | 
					          <use xlink:href="assets/bootstrap-icons.svg#x" />
 | 
				
			||||||
 | 
					        </svg>
 | 
				
			||||||
 | 
					        <small class="my-1">Remove All</small>
 | 
				
			||||||
 | 
					      </button>
 | 
				
			||||||
      <div *ngIf="toggleableItems" class="items">
 | 
					      <div *ngIf="toggleableItems" class="items">
 | 
				
			||||||
        <ng-container *ngFor="let toggleableItem of toggleableItems | filter: filterText">
 | 
					        <ng-container *ngFor="let toggleableItem of toggleableItems | filter: filterText">
 | 
				
			||||||
          <app-toggleable-dropdown-button [toggleableItem]="toggleableItem" [showCounts]="showCounts" (toggle)="toggleItem($event)"></app-toggleable-dropdown-button>
 | 
					          <app-toggleable-dropdown-button [toggleableItem]="toggleableItem" [showCounts]="showCounts" (toggle)="toggleItem($event)"></app-toggleable-dropdown-button>
 | 
				
			||||||
 | 
				
			|||||||
@ -69,12 +69,18 @@ export class FilterableDropdownComponent {
 | 
				
			|||||||
  @Input()
 | 
					  @Input()
 | 
				
			||||||
  singular: boolean = false
 | 
					  singular: boolean = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Input()
 | 
				
			||||||
 | 
					  showRemoveAll: boolean = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Output()
 | 
					  @Output()
 | 
				
			||||||
  toggle = new EventEmitter()
 | 
					  toggle = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Output()
 | 
					  @Output()
 | 
				
			||||||
  open = new EventEmitter()
 | 
					  open = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Output()
 | 
				
			||||||
 | 
					  removeAll = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Output()
 | 
					  @Output()
 | 
				
			||||||
  editingComplete = new EventEmitter()
 | 
					  editingComplete = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -110,7 +116,7 @@ export class FilterableDropdownComponent {
 | 
				
			|||||||
      this.open.next()
 | 
					      this.open.next()
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      this.filterText = ''
 | 
					      this.filterText = ''
 | 
				
			||||||
      if (this.type == FilterableDropdownType.Editing) this.editingComplete.emit(this.itemsSelected)
 | 
					      if (this.type == FilterableDropdownType.Editing) this.editingComplete.emit(this.toggleableItems)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -29,9 +29,33 @@
 | 
				
			|||||||
  <div class="col-auto mb-2 mb-xl-0">
 | 
					  <div class="col-auto mb-2 mb-xl-0">
 | 
				
			||||||
    <div class="d-flex">
 | 
					    <div class="d-flex">
 | 
				
			||||||
      <label class="ml-auto mt-1 mb-0 mr-2">Edit:</label>
 | 
					      <label class="ml-auto mt-1 mb-0 mr-2">Edit:</label>
 | 
				
			||||||
      <app-filterable-dropdown class="mr-2 mr-md-3" title="Tags" icon="tag-fill" [toggleableItems]="tagsToggleableItems" [type]="dropdownTypes.Editing" [showCounts]="!this.selectionSpansPages" (open)="tagsDropdownOpen()" (editingComplete)="applyTags($event)"></app-filterable-dropdown>
 | 
					      <app-filterable-dropdown class="mr-2 mr-md-3" title="Tags" icon="tag-fill"
 | 
				
			||||||
      <app-filterable-dropdown class="mr-2 mr-md-3" title="Correspondent" icon="person-fill" [toggleableItems]="correspondentsToggleableItems" [type]="dropdownTypes.Editing" [showCounts]="!this.selectionSpansPages" singular="true" (open)="correspondentsDropdownOpen()" (editingComplete)="applyCorrespondent($event)"></app-filterable-dropdown>
 | 
					        [toggleableItems]="tagsToggleableItems"
 | 
				
			||||||
      <app-filterable-dropdown class="mr-2 mr-md-3" title="Document Type" icon="file-earmark-fill" [toggleableItems]="documentTypesToggleableItems" [type]="dropdownTypes.Editing" [showCounts]="!this.selectionSpansPages" singular="true" (open)="documentTypesDropdownOpen()" (editingComplete)="applyDocumentType($event)"></app-filterable-dropdown>
 | 
					        [type]="dropdownTypes.Editing"
 | 
				
			||||||
 | 
					        [showCounts]="!this.selectionSpansPages"
 | 
				
			||||||
 | 
					        [showRemoveAll]="this.selectionSpansPages"
 | 
				
			||||||
 | 
					        (open)="tagsDropdownOpen()"
 | 
				
			||||||
 | 
					        (removeAll)="applyTags([], true)"
 | 
				
			||||||
 | 
					        (editingComplete)="applyTags($event)">
 | 
				
			||||||
 | 
					      </app-filterable-dropdown>
 | 
				
			||||||
 | 
					      <app-filterable-dropdown class="mr-2 mr-md-3" title="Correspondent" icon="person-fill" singular="true"
 | 
				
			||||||
 | 
					        [toggleableItems]="correspondentsToggleableItems"
 | 
				
			||||||
 | 
					        [type]="dropdownTypes.Editing"
 | 
				
			||||||
 | 
					        [showCounts]="!this.selectionSpansPages"
 | 
				
			||||||
 | 
					        [showRemoveAll]="this.selectionSpansPages"
 | 
				
			||||||
 | 
					        (open)="correspondentsDropdownOpen()"
 | 
				
			||||||
 | 
					        (removeAll)="applyCorrespondent([], true)"
 | 
				
			||||||
 | 
					        (editingComplete)="applyCorrespondent($event)">
 | 
				
			||||||
 | 
					      </app-filterable-dropdown>
 | 
				
			||||||
 | 
					      <app-filterable-dropdown class="mr-2 mr-md-3" title="Document Type" icon="file-earmark-fill" singular="true"
 | 
				
			||||||
 | 
					        [toggleableItems]="documentTypesToggleableItems"
 | 
				
			||||||
 | 
					        [type]="dropdownTypes.Editing"
 | 
				
			||||||
 | 
					        [showCounts]="!this.selectionSpansPages"
 | 
				
			||||||
 | 
					        [showRemoveAll]="this.selectionSpansPages"
 | 
				
			||||||
 | 
					        (open)="documentTypesDropdownOpen()"
 | 
				
			||||||
 | 
					        (removeAll)="applyDocumentType([], true)"
 | 
				
			||||||
 | 
					        (editingComplete)="applyDocumentType($event)">
 | 
				
			||||||
 | 
					      </app-filterable-dropdown>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  <div class="w-100 d-xl-none"></div>
 | 
					  <div class="w-100 d-xl-none"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,11 @@ 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 {
 | 
				
			||||||
 | 
					  itemsToAdd: any[],
 | 
				
			||||||
 | 
					  itemsToRemove: any[]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'app-bulk-editor',
 | 
					  selector: 'app-bulk-editor',
 | 
				
			||||||
  templateUrl: './bulk-editor.component.html',
 | 
					  templateUrl: './bulk-editor.component.html',
 | 
				
			||||||
@ -33,6 +38,9 @@ export class BulkEditorComponent {
 | 
				
			|||||||
  @Output()
 | 
					  @Output()
 | 
				
			||||||
  selectNone = new EventEmitter()
 | 
					  selectNone = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Output()
 | 
				
			||||||
 | 
					  setTags = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Output()
 | 
					  @Output()
 | 
				
			||||||
  setCorrespondent = new EventEmitter()
 | 
					  setCorrespondent = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -40,18 +48,24 @@ export class BulkEditorComponent {
 | 
				
			|||||||
  setDocumentType = new EventEmitter()
 | 
					  setDocumentType = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Output()
 | 
					  @Output()
 | 
				
			||||||
  setTags = new EventEmitter()
 | 
					  delete = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Output()
 | 
					  @Output()
 | 
				
			||||||
  delete = new EventEmitter()
 | 
					  removeTags = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Output()
 | 
				
			||||||
 | 
					  removeCorrespondents = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Output()
 | 
				
			||||||
 | 
					  removeDocumentTypes = new EventEmitter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  tags: PaperlessTag[]
 | 
					  tags: PaperlessTag[]
 | 
				
			||||||
  correspondents: PaperlessCorrespondent[]
 | 
					  correspondents: PaperlessCorrespondent[]
 | 
				
			||||||
  documentTypes: PaperlessDocumentType[]
 | 
					  documentTypes: PaperlessDocumentType[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private initiallySelectedTagsToggleableItems: ToggleableItem[]
 | 
					  private initialTagsToggleableItems: ToggleableItem[]
 | 
				
			||||||
  private initiallySelectedCorrespondentsToggleableItems: ToggleableItem[]
 | 
					  private initialCorrespondentsToggleableItems: ToggleableItem[]
 | 
				
			||||||
  private initiallySelectedDocumentTypesToggleableItems: ToggleableItem[]
 | 
					  private initialDocumentTypesToggleableItems: ToggleableItem[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  dropdownTypes = FilterableDropdownType
 | 
					  dropdownTypes = FilterableDropdownType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,6 +73,7 @@ export class BulkEditorComponent {
 | 
				
			|||||||
    return this.selectedDocuments.size > this.viewDocuments.length || !Array.from(this.selectedDocuments).every(sd => this.viewDocuments.find(d => d.id == sd))
 | 
					    return this.selectedDocuments.size > this.viewDocuments.length || !Array.from(this.selectedDocuments).every(sd => this.viewDocuments.find(d => d.id == sd))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private _tagsToggleableItems: ToggleableItem[]
 | 
				
			||||||
  get tagsToggleableItems(): ToggleableItem[] {
 | 
					  get tagsToggleableItems(): ToggleableItem[] {
 | 
				
			||||||
    let tagsToggleableItems = []
 | 
					    let tagsToggleableItems = []
 | 
				
			||||||
    let selectedDocuments: PaperlessDocument[] = this.viewDocuments.filter(d => this.selectedDocuments.has(d.id))
 | 
					    let selectedDocuments: PaperlessDocument[] = this.viewDocuments.filter(d => this.selectedDocuments.has(d.id))
 | 
				
			||||||
@ -71,9 +86,11 @@ export class BulkEditorComponent {
 | 
				
			|||||||
      else if (selectedDocumentsWithTag.length > 0 && selectedDocumentsWithTag.length < selectedDocuments.length) state = ToggleableItemState.PartiallySelected
 | 
					      else if (selectedDocumentsWithTag.length > 0 && selectedDocumentsWithTag.length < selectedDocuments.length) state = ToggleableItemState.PartiallySelected
 | 
				
			||||||
      tagsToggleableItems.push({item: t, state: state, count: selectedDocumentsWithTag.length})
 | 
					      tagsToggleableItems.push({item: t, state: state, count: selectedDocumentsWithTag.length})
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					    this._tagsToggleableItems = tagsToggleableItems
 | 
				
			||||||
    return tagsToggleableItems
 | 
					    return tagsToggleableItems
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private _correspondentsToggleableItems: ToggleableItem[]
 | 
				
			||||||
  get correspondentsToggleableItems(): ToggleableItem[] {
 | 
					  get correspondentsToggleableItems(): ToggleableItem[] {
 | 
				
			||||||
    let correspondentsToggleableItems = []
 | 
					    let correspondentsToggleableItems = []
 | 
				
			||||||
    let selectedDocuments: PaperlessDocument[] = this.viewDocuments.filter(d => this.selectedDocuments.has(d.id))
 | 
					    let selectedDocuments: PaperlessDocument[] = this.viewDocuments.filter(d => this.selectedDocuments.has(d.id))
 | 
				
			||||||
@ -86,9 +103,11 @@ export class BulkEditorComponent {
 | 
				
			|||||||
      else if (selectedDocumentsWithCorrespondent.length > 0 && selectedDocumentsWithCorrespondent.length < selectedDocuments.length) state = ToggleableItemState.PartiallySelected
 | 
					      else if (selectedDocumentsWithCorrespondent.length > 0 && selectedDocumentsWithCorrespondent.length < selectedDocuments.length) state = ToggleableItemState.PartiallySelected
 | 
				
			||||||
      correspondentsToggleableItems.push({item: c, state: state, count: selectedDocumentsWithCorrespondent.length})
 | 
					      correspondentsToggleableItems.push({item: c, state: state, count: selectedDocumentsWithCorrespondent.length})
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					    this._correspondentsToggleableItems = correspondentsToggleableItems
 | 
				
			||||||
    return correspondentsToggleableItems
 | 
					    return correspondentsToggleableItems
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private _documentTypesToggleableItems: ToggleableItem[]
 | 
				
			||||||
  get documentTypesToggleableItems(): ToggleableItem[] {
 | 
					  get documentTypesToggleableItems(): ToggleableItem[] {
 | 
				
			||||||
    let documentTypesToggleableItems = []
 | 
					    let documentTypesToggleableItems = []
 | 
				
			||||||
    let selectedDocuments: PaperlessDocument[] = this.viewDocuments.filter(d => this.selectedDocuments.has(d.id))
 | 
					    let selectedDocuments: PaperlessDocument[] = this.viewDocuments.filter(d => this.selectedDocuments.has(d.id))
 | 
				
			||||||
@ -101,6 +120,7 @@ export class BulkEditorComponent {
 | 
				
			|||||||
      else if (selectedDocumentsWithDocumentType.length > 0 && selectedDocumentsWithDocumentType.length < selectedDocuments.length) state = ToggleableItemState.PartiallySelected
 | 
					      else if (selectedDocumentsWithDocumentType.length > 0 && selectedDocumentsWithDocumentType.length < selectedDocuments.length) state = ToggleableItemState.PartiallySelected
 | 
				
			||||||
      documentTypesToggleableItems.push({item: dt, state: state, count: selectedDocumentsWithDocumentType.length})
 | 
					      documentTypesToggleableItems.push({item: dt, state: state, count: selectedDocumentsWithDocumentType.length})
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					    this._documentTypesToggleableItems = documentTypesToggleableItems
 | 
				
			||||||
    return documentTypesToggleableItems
 | 
					    return documentTypesToggleableItems
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -118,39 +138,45 @@ export class BulkEditorComponent {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  tagsDropdownOpen() {
 | 
					  tagsDropdownOpen() {
 | 
				
			||||||
    this.initiallySelectedTagsToggleableItems = this.tagsToggleableItems.filter(tti => tti.state == ToggleableItemState.Selected)
 | 
					    this.initialTagsToggleableItems = this._tagsToggleableItems
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  correspondentsDropdownOpen() {
 | 
					  correspondentsDropdownOpen() {
 | 
				
			||||||
    this.initiallySelectedCorrespondentsToggleableItems = this.correspondentsToggleableItems.filter(cti => cti.state == ToggleableItemState.Selected)
 | 
					    this.initialCorrespondentsToggleableItems = this._correspondentsToggleableItems
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  documentTypesDropdownOpen() {
 | 
					  documentTypesDropdownOpen() {
 | 
				
			||||||
    this.initiallySelectedDocumentTypesToggleableItems = this.documentTypesToggleableItems.filter(dtti => dtti.state == ToggleableItemState.Selected)
 | 
					    this.initialDocumentTypesToggleableItems = this._documentTypesToggleableItems
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  applyTags(selectedTags: PaperlessTag[]) {
 | 
					  applyTags(newTagsToggleableItems: ToggleableItem[], forceApply:boolean = false) {
 | 
				
			||||||
    let unchanged = this.equateItemsToToggleableItems(selectedTags, this.initiallySelectedTagsToggleableItems)
 | 
					    let changedTags = this.checkForChangedItems(this.initialTagsToggleableItems, newTagsToggleableItems)
 | 
				
			||||||
    if (!unchanged) this.setTags.emit(selectedTags)
 | 
					    if (changedTags.itemsToAdd.length > 0) this.setTags.emit(changedTags.itemsToAdd)
 | 
				
			||||||
    this.initiallySelectedTagsToggleableItems = []
 | 
					    if (changedTags.itemsToRemove.length > 0) this.removeTags.emit(changedTags.itemsToRemove)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  applyCorrespondent(selectedCorrespondents: PaperlessCorrespondent[]) {
 | 
					  applyCorrespondent(newCorrespondentsToggleableItems: ToggleableItem[], forceApply:boolean = false) {
 | 
				
			||||||
    let unchanged = this.equateItemsToToggleableItems(selectedCorrespondents, this.initiallySelectedCorrespondentsToggleableItems)
 | 
					    let changedCorrespondents = this.checkForChangedItems(this.initialCorrespondentsToggleableItems, newCorrespondentsToggleableItems)
 | 
				
			||||||
    if (!unchanged) this.setCorrespondent.emit(selectedCorrespondents?.length > 0 ? selectedCorrespondents.shift() : null)
 | 
					    if (changedCorrespondents.itemsToAdd.length > 0) this.setCorrespondent.emit(changedCorrespondents.itemsToAdd)
 | 
				
			||||||
    this.initiallySelectedCorrespondentsToggleableItems = []
 | 
					    else if (changedCorrespondents.itemsToRemove.length > 0) this.removeCorrespondents.emit(changedCorrespondents.itemsToRemove)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  applyDocumentType(selectedDocumentTypes: PaperlessDocumentType[]) {
 | 
					  applyDocumentType(newDocumentTypesToggleableItems: ToggleableItem[], forceApply:boolean = false) {
 | 
				
			||||||
    let unchanged = this.equateItemsToToggleableItems(selectedDocumentTypes, this.initiallySelectedDocumentTypesToggleableItems)
 | 
					    let changedDocumentTypes = this.checkForChangedItems(this.initialDocumentTypesToggleableItems, newDocumentTypesToggleableItems)
 | 
				
			||||||
    if (!unchanged) this.setDocumentType.emit(selectedDocumentTypes.length > 0 ? selectedDocumentTypes.shift() : null)
 | 
					    if (changedDocumentTypes.itemsToAdd.length > 0) this.setDocumentType.emit(changedDocumentTypes.itemsToAdd)
 | 
				
			||||||
    this.initiallySelectedDocumentTypesToggleableItems = []
 | 
					    else if (changedDocumentTypes.itemsToRemove.length > 0) this.removeDocumentTypes.emit(changedDocumentTypes.itemsToRemove)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  equateItemsToToggleableItems(items: ObjectWithId[], toggleableItems: ToggleableItem[]): boolean {
 | 
					  checkForChangedItems(toggleableItemsA: ToggleableItem[], toggleableItemsB: ToggleableItem[]): ChangedItems {
 | 
				
			||||||
    // either both empty or all items must in toggleableItems and vice-versa
 | 
					    let itemsToAdd: any[] = []
 | 
				
			||||||
    return (toggleableItems.length == 0 && items.length == 0) ||
 | 
					    let itemsToRemove: any[] = []
 | 
				
			||||||
           (items.every(i => toggleableItems.find(ti => ti.item.id == i.id) !== undefined) && toggleableItems.every(ti => items.find(i => i.id == ti.item.id) !== undefined))
 | 
					    toggleableItemsA.forEach(oldItem => {
 | 
				
			||||||
 | 
					      let newItem = toggleableItemsB.find(nTTI => nTTI.item.id == oldItem.item.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (newItem.state == ToggleableItemState.Selected && (oldItem.state == ToggleableItemState.PartiallySelected || oldItem.state == ToggleableItemState.NotSelected)) itemsToAdd.push(newItem.item)
 | 
				
			||||||
 | 
					      else if (newItem.state == ToggleableItemState.NotSelected && (oldItem.state == ToggleableItemState.Selected || oldItem.state == ToggleableItemState.PartiallySelected)) itemsToRemove.push(newItem.item)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    return { itemsToAdd: itemsToAdd, itemsToRemove: itemsToRemove }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  applyDelete() {
 | 
					  applyDelete() {
 | 
				
			||||||
 | 
				
			|||||||
@ -87,8 +87,11 @@
 | 
				
			|||||||
    (selectAll)="list.selectAll()"
 | 
					    (selectAll)="list.selectAll()"
 | 
				
			||||||
    (selectNone)="list.selectNone()"
 | 
					    (selectNone)="list.selectNone()"
 | 
				
			||||||
    (setTags)="bulkSetTags($event)"
 | 
					    (setTags)="bulkSetTags($event)"
 | 
				
			||||||
 | 
					    (removeTags)="bulkRemoveTags($event)"
 | 
				
			||||||
    (setCorrespondent)="bulkSetCorrespondent($event)"
 | 
					    (setCorrespondent)="bulkSetCorrespondent($event)"
 | 
				
			||||||
 | 
					    (removeCorrespondents)="bulkRemoveCorrespondents($event)"
 | 
				
			||||||
    (setDocumentType)="bulkSetDocumentType($event)"
 | 
					    (setDocumentType)="bulkSetDocumentType($event)"
 | 
				
			||||||
 | 
					    (removeDocumentTypes)="bulkRemoveDocumentTypes($event)"
 | 
				
			||||||
    (delete)="bulkDelete()">
 | 
					    (delete)="bulkDelete()">
 | 
				
			||||||
</app-bulk-editor>
 | 
					</app-bulk-editor>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -158,7 +158,7 @@ export class DocumentListComponent implements OnInit {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  bulkSetCorrespondent(correspondent: PaperlessCorrespondent) {
 | 
					  bulkSetCorrespondent(correspondent: PaperlessCorrespondent) {
 | 
				
			||||||
    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 Correspondent assignment"
 | 
				
			||||||
    let messageFragment = correspondent ? `assign the correspondent ${correspondent.name} to` : `remove all correspondents from`
 | 
					    let messageFragment = correspondent ? `assign the correspondent ${correspondent.name} to` : `remove all correspondents 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"
 | 
				
			||||||
@ -172,6 +172,22 @@ export class DocumentListComponent implements OnInit {
 | 
				
			|||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bulkRemoveCorrespondents(correspondents: PaperlessCorrespondent[]) {
 | 
				
			||||||
 | 
					    let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
 | 
				
			||||||
 | 
					    modal.componentInstance.title = "Confirm Correspondent Removal"
 | 
				
			||||||
 | 
					    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).`
 | 
				
			||||||
 | 
					    modal.componentInstance.btnClass = "btn-warning"
 | 
				
			||||||
 | 
					    modal.componentInstance.btnCaption = "Confirm"
 | 
				
			||||||
 | 
					    modal.componentInstance.confirmClicked.subscribe(() => {
 | 
				
			||||||
 | 
					      // TODO: API endpoint for remove multiple correspondents
 | 
				
			||||||
 | 
					      this.executeBulkOperation('remove_correspondents', {"correspondents": correspondents.map(t => t.id)}).subscribe(
 | 
				
			||||||
 | 
					        response => {
 | 
				
			||||||
 | 
					          modal.close()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bulkSetDocumentType(documentType: PaperlessDocumentType) {
 | 
					  bulkSetDocumentType(documentType: PaperlessDocumentType) {
 | 
				
			||||||
    let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
 | 
					    let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
 | 
				
			||||||
    modal.componentInstance.title = "Confirm Document Type assignment"
 | 
					    modal.componentInstance.title = "Confirm Document Type assignment"
 | 
				
			||||||
@ -188,6 +204,22 @@ export class DocumentListComponent implements OnInit {
 | 
				
			|||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bulkRemoveDocumentTypes(documentTypes: PaperlessDocumentType[]) {
 | 
				
			||||||
 | 
					    let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
 | 
				
			||||||
 | 
					    modal.componentInstance.title = "Confirm Document Type Removal"
 | 
				
			||||||
 | 
					    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).`
 | 
				
			||||||
 | 
					    modal.componentInstance.btnClass = "btn-warning"
 | 
				
			||||||
 | 
					    modal.componentInstance.btnCaption = "Confirm"
 | 
				
			||||||
 | 
					    modal.componentInstance.confirmClicked.subscribe(() => {
 | 
				
			||||||
 | 
					      // TODO: API endpoint for remove multiple document types
 | 
				
			||||||
 | 
					      this.executeBulkOperation('remove_document_types', {"document_types": documentTypes.map(t => t.id)}).subscribe(
 | 
				
			||||||
 | 
					        response => {
 | 
				
			||||||
 | 
					          modal.close()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bulkSetTags(tags: PaperlessTag[]) {
 | 
					  bulkSetTags(tags: PaperlessTag[]) {
 | 
				
			||||||
    let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
 | 
					    let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
 | 
				
			||||||
    modal.componentInstance.title = "Confirm Tags assignment"
 | 
					    modal.componentInstance.title = "Confirm Tags assignment"
 | 
				
			||||||
@ -197,7 +229,23 @@ export class DocumentListComponent implements OnInit {
 | 
				
			|||||||
    modal.componentInstance.btnCaption = "Confirm"
 | 
					    modal.componentInstance.btnCaption = "Confirm"
 | 
				
			||||||
    modal.componentInstance.confirmClicked.subscribe(() => {
 | 
					    modal.componentInstance.confirmClicked.subscribe(() => {
 | 
				
			||||||
      // TODO: API endpoint for set multiple tags
 | 
					      // TODO: API endpoint for set multiple tags
 | 
				
			||||||
      this.executeBulkOperation('set_tags', {"document_type": tags ? tags.map(t => t.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()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user