mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 03:16:10 -06:00 
			
		
		
		
	#186 allow filtering for documents with no correspondents / tags / types
This commit is contained in:
		@@ -21,7 +21,7 @@
 | 
			
		||||
      </div>
 | 
			
		||||
      <div *ngIf="selectionModel.items" class="items">
 | 
			
		||||
        <ng-container *ngFor="let item of selectionModel.items | filter: filterText">
 | 
			
		||||
          <app-toggleable-dropdown-button [item]="item" [state]="selectionModel.get(item.id)" (toggle)="selectionModel.toggle(item.id)"></app-toggleable-dropdown-button>
 | 
			
		||||
          <app-toggleable-dropdown-button *ngIf="allowSelectNone || item.id" [item]="item" [state]="selectionModel.get(item.id)" (toggle)="selectionModel.toggle(item.id)"></app-toggleable-dropdown-button>
 | 
			
		||||
        </ng-container>
 | 
			
		||||
      </div>
 | 
			
		||||
      <button *ngIf="editing" class="list-group-item list-group-item-action bg-light" (click)="applyClicked()" [disabled]="!selectionModel.isDirty()">
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,16 @@ export class FilterableDropdownSelectionModel {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!id) {
 | 
			
		||||
      for (let key of this.temporarySelectionStates.keys()) {
 | 
			
		||||
        if (key) {
 | 
			
		||||
          this.temporarySelectionStates.delete(key)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      this.temporarySelectionStates.delete(null)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (fireEvent) {
 | 
			
		||||
      this.changed.next(this)
 | 
			
		||||
    }
 | 
			
		||||
@@ -84,6 +94,10 @@ export class FilterableDropdownSelectionModel {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isNoneSelected() {
 | 
			
		||||
    return this.selectionSize() == 1 && this.get(null) == ToggleableItemState.Selected
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  init(map) {
 | 
			
		||||
    this.temporarySelectionStates = map
 | 
			
		||||
    this.apply()
 | 
			
		||||
@@ -126,7 +140,11 @@ export class FilterableDropdownComponent {
 | 
			
		||||
  @Input()
 | 
			
		||||
  set items(items: MatchingModel[]) {
 | 
			
		||||
    if (items) {
 | 
			
		||||
      this._selectionModel.items = items
 | 
			
		||||
      this._selectionModel.items = Array.from(items)
 | 
			
		||||
      this._selectionModel.items.unshift({
 | 
			
		||||
        name: "None",
 | 
			
		||||
        id: null
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -171,6 +189,9 @@ export class FilterableDropdownComponent {
 | 
			
		||||
  @Input()
 | 
			
		||||
  icon: string
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  allowSelectNone: boolean = false
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  editing = false
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,9 @@
 | 
			
		||||
  <div class="w-100 d-xl-none"></div>
 | 
			
		||||
   <div class="col col-xl-auto mb-2 mb-xl-0">
 | 
			
		||||
     <div class="d-flex">
 | 
			
		||||
       <app-filterable-dropdown class="mr-2 mr-md-3" [items]="tags" [(selectionModel)]="tagSelectionModel" (selectionModelChange)="updateRules()" [multiple]="true" title="Tags" icon="tag-fill" i18n-title></app-filterable-dropdown>
 | 
			
		||||
       <app-filterable-dropdown class="mr-2 mr-md-3" [items]="correspondents" [(selectionModel)]="correspondentSelectionModel" (selectionModelChange)="updateRules()" title="Correspondents" icon="person-fill" i18n-title></app-filterable-dropdown>
 | 
			
		||||
       <app-filterable-dropdown class="mr-2 mr-md-3" [items]="documentTypes" [(selectionModel)]="documentTypeSelectionModel" (selectionModelChange)="updateRules()" title="Document types" icon="file-earmark-fill" i18n-title></app-filterable-dropdown>
 | 
			
		||||
       <app-filterable-dropdown class="mr-2 mr-md-3" [items]="tags" [(selectionModel)]="tagSelectionModel" (selectionModelChange)="updateRules()" [multiple]="true" [allowSelectNone]="true" title="Tags" icon="tag-fill" i18n-title></app-filterable-dropdown>
 | 
			
		||||
       <app-filterable-dropdown class="mr-2 mr-md-3" [items]="correspondents" [(selectionModel)]="correspondentSelectionModel" (selectionModelChange)="updateRules()" [allowSelectNone]="true" title="Correspondents" icon="person-fill" i18n-title></app-filterable-dropdown>
 | 
			
		||||
       <app-filterable-dropdown class="mr-2 mr-md-3" [items]="documentTypes" [(selectionModel)]="documentTypeSelectionModel" (selectionModelChange)="updateRules()" [allowSelectNone]="true" title="Document types" icon="file-earmark-fill" i18n-title></app-filterable-dropdown>
 | 
			
		||||
       <app-date-dropdown class="mr-2 mr-md-3" [(dateBefore)]="dateCreatedBefore" [(dateAfter)]="dateCreatedAfter" title="Created" (datesSet)="updateRules()" i18n-title></app-date-dropdown>
 | 
			
		||||
       <app-date-dropdown [(dateBefore)]="dateAddedBefore" [(dateAfter)]="dateAddedAfter" title="Added"  (datesSet)="updateRules()" i18n-title></app-date-dropdown>
 | 
			
		||||
     </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ import { DocumentTypeService } from 'src/app/services/rest/document-type.service
 | 
			
		||||
import { TagService } from 'src/app/services/rest/tag.service';
 | 
			
		||||
import { CorrespondentService } from 'src/app/services/rest/correspondent.service';
 | 
			
		||||
import { FilterRule } from 'src/app/data/filter-rule';
 | 
			
		||||
import { FILTER_ADDED_AFTER, FILTER_ADDED_BEFORE, FILTER_CORRESPONDENT, FILTER_CREATED_AFTER, FILTER_CREATED_BEFORE, FILTER_DOCUMENT_TYPE, FILTER_HAS_TAG, FILTER_TITLE } from 'src/app/data/filter-rule-type';
 | 
			
		||||
import { FILTER_ADDED_AFTER, FILTER_ADDED_BEFORE, FILTER_CORRESPONDENT, FILTER_CREATED_AFTER, FILTER_CREATED_BEFORE, FILTER_DOCUMENT_TYPE, FILTER_HAS_ANY_TAG, FILTER_HAS_TAG, FILTER_TITLE } from 'src/app/data/filter-rule-type';
 | 
			
		||||
import { FilterableDropdownSelectionModel } from '../../common/filterable-dropdown/filterable-dropdown.component';
 | 
			
		||||
import { ToggleableItemState } from '../../common/filterable-dropdown/toggleable-dropdown-button/toggleable-dropdown-button.component';
 | 
			
		||||
 | 
			
		||||
@@ -100,14 +100,18 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
 | 
			
		||||
    if (this._titleFilter) {
 | 
			
		||||
      filterRules.push({rule_type: FILTER_TITLE, value: this._titleFilter})
 | 
			
		||||
    }
 | 
			
		||||
    this.tagSelectionModel.getSelectedItems().forEach(tag => {
 | 
			
		||||
      filterRules.push({rule_type: FILTER_HAS_TAG, value: tag.id.toString()})
 | 
			
		||||
    })
 | 
			
		||||
    if (this.tagSelectionModel.isNoneSelected()) {
 | 
			
		||||
      filterRules.push({rule_type: FILTER_HAS_ANY_TAG, value: "false"})
 | 
			
		||||
    } else {
 | 
			
		||||
      this.tagSelectionModel.getSelectedItems().filter(tag => tag.id).forEach(tag => {
 | 
			
		||||
        filterRules.push({rule_type: FILTER_HAS_TAG, value: tag.id?.toString()})
 | 
			
		||||
      })  
 | 
			
		||||
    }
 | 
			
		||||
    this.correspondentSelectionModel.getSelectedItems().forEach(correspondent => {
 | 
			
		||||
      filterRules.push({rule_type: FILTER_CORRESPONDENT, value: correspondent.id.toString()})
 | 
			
		||||
      filterRules.push({rule_type: FILTER_CORRESPONDENT, value: correspondent.id?.toString()})
 | 
			
		||||
    })
 | 
			
		||||
    this.documentTypeSelectionModel.getSelectedItems().forEach(documentType => {
 | 
			
		||||
      filterRules.push({rule_type: FILTER_DOCUMENT_TYPE, value: documentType.id.toString()})
 | 
			
		||||
      filterRules.push({rule_type: FILTER_DOCUMENT_TYPE, value: documentType.id?.toString()})
 | 
			
		||||
    })
 | 
			
		||||
    if (this.dateCreatedBefore) {
 | 
			
		||||
      filterRules.push({rule_type: FILTER_CREATED_BEFORE, value: this.dateCreatedBefore})
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user