mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05: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
	 jonaswinkler
					jonaswinkler