mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
refactored filter service
- I wasn't too happy with that in the end. - The filter editor should not be concerned about managing filter rule state. - Therefore, it should not access a service for filter rules. - The editor should simply be given a set of rules, and edit that rule set. - The only entity that should manage filter state should be the document list service, and the saved view service in the form of filters associated with saved views.
This commit is contained in:
parent
10440ec820
commit
94c07839a4
@ -63,7 +63,7 @@
|
||||
</app-page-header>
|
||||
|
||||
<div class="w-100 mb-4">
|
||||
<app-filter-editor [(filterEditorService)]="filterEditorService" (apply)="applyFilterRules()" (clear)="clearFilterRules()" #filterEditor></app-filter-editor>
|
||||
<app-filter-editor [(filterRules)]="list.filterRules" #filterEditor></app-filter-editor>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
|
@ -2,21 +2,14 @@ import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { cloneFilterRules, FilterRule } from 'src/app/data/filter-rule';
|
||||
import { FILTER_CORRESPONDENT, FILTER_DOCUMENT_TYPE, FILTER_HAS_TAG, FILTER_RULE_TYPES } from 'src/app/data/filter-rule-type';
|
||||
import { SavedViewConfig } from 'src/app/data/saved-view-config';
|
||||
import { DocumentListViewService } from 'src/app/services/document-list-view.service';
|
||||
import { FilterEditorViewService } from 'src/app/services/filter-editor-view.service';
|
||||
import { DOCUMENT_SORT_FIELDS } from 'src/app/services/rest/document.service';
|
||||
import { SavedViewConfigService } from 'src/app/services/saved-view-config.service';
|
||||
import { Toast, ToastService } from 'src/app/services/toast.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { FilterEditorComponent } from '../filter-editor/filter-editor.component';
|
||||
import { SaveViewConfigDialogComponent } from './save-view-config-dialog/save-view-config-dialog.component';
|
||||
import { FilterEditorComponent } from 'src/app/components/filter-editor/filter-editor.component';
|
||||
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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-document-list',
|
||||
templateUrl: './document-list.component.html',
|
||||
@ -27,26 +20,20 @@ export class DocumentListComponent implements OnInit {
|
||||
constructor(
|
||||
public list: DocumentListViewService,
|
||||
public savedViewConfigService: SavedViewConfigService,
|
||||
public filterEditorService: FilterEditorViewService,
|
||||
public route: ActivatedRoute,
|
||||
private toastService: ToastService,
|
||||
public modalService: NgbModal,
|
||||
private titleService: Title) { }
|
||||
|
||||
@ViewChild("filterEditor")
|
||||
private filterEditor: FilterEditorComponent
|
||||
|
||||
displayMode = 'smallCards' // largeCards, smallCards, details
|
||||
|
||||
get isFiltered() {
|
||||
return this.list.filterRules?.length > 0
|
||||
}
|
||||
|
||||
set filterRules(filterRules: FilterRule[]) {
|
||||
this.filterEditorService.filterRules = filterRules
|
||||
}
|
||||
|
||||
get filterRules(): FilterRule[] {
|
||||
return this.filterEditorService.filterRules
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
return this.list.savedViewTitle || "Documents"
|
||||
}
|
||||
@ -66,29 +53,18 @@ export class DocumentListComponent implements OnInit {
|
||||
this.route.paramMap.subscribe(params => {
|
||||
if (params.has('id')) {
|
||||
this.list.savedView = this.savedViewConfigService.getConfig(params.get('id'))
|
||||
this.filterEditorService.filterRules = this.list.filterRules
|
||||
this.titleService.setTitle(`${this.list.savedView.title} - ${environment.appTitle}`)
|
||||
} else {
|
||||
this.list.savedView = null
|
||||
this.filterEditorService.filterRules = this.list.filterRules
|
||||
this.titleService.setTitle(`Documents - ${environment.appTitle}`)
|
||||
}
|
||||
this.list.clear()
|
||||
this.list.reload()
|
||||
})
|
||||
this.filterEditorService.filterRules = this.list.filterRules
|
||||
}
|
||||
|
||||
applyFilterRules() {
|
||||
this.list.filterRules = this.filterEditorService.filterRules
|
||||
}
|
||||
|
||||
clearFilterRules() {
|
||||
this.list.filterRules = this.filterEditorService.filterRules
|
||||
}
|
||||
|
||||
loadViewConfig(config: SavedViewConfig) {
|
||||
this.filterEditorService.filterRules = cloneFilterRules(config.filterRules)
|
||||
this.list.load(config)
|
||||
}
|
||||
|
||||
@ -113,18 +89,15 @@ export class DocumentListComponent implements OnInit {
|
||||
}
|
||||
|
||||
clickTag(tagID: number) {
|
||||
this.filterEditorService.toggleFilterByTag(tagID)
|
||||
this.applyFilterRules()
|
||||
this.filterEditor.toggleTag(tagID)
|
||||
}
|
||||
|
||||
clickCorrespondent(correspondentID: number) {
|
||||
this.filterEditorService.toggleFilterByCorrespondent(correspondentID)
|
||||
this.applyFilterRules()
|
||||
this.filterEditor.toggleCorrespondent(correspondentID)
|
||||
}
|
||||
|
||||
clickDocumentType(documentTypeID: number) {
|
||||
this.filterEditorService.toggleFilterByDocumentType(documentTypeID)
|
||||
this.applyFilterRules()
|
||||
this.filterEditor.toggleDocumentType(documentTypeID)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { Component, EventEmitter, Input, Output, ElementRef, ViewChild, OnChanges, SimpleChange } from '@angular/core';
|
||||
import { FilterRule } from 'src/app/data/filter-rule';
|
||||
import { ObjectWithId } from 'src/app/data/object-with-id';
|
||||
import { Component, EventEmitter, Input, Output, ElementRef, ViewChild, SimpleChange } from '@angular/core';
|
||||
import { NgbDate, NgbDateStruct, NgbDatepicker } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
@Component({
|
||||
|
@ -6,14 +6,14 @@
|
||||
<input class="form-control form-control-sm" type="text" [(ngModel)]="titleFilter" placeholder="Title">
|
||||
</div>
|
||||
|
||||
<app-filter-dropdown class="col-auto" [(items)]="filterEditorService.tags" [itemsSelected]="filterEditorService.selectedTags" [title]="'Tags'" (toggle)="onToggleTag($event)"></app-filter-dropdown>
|
||||
<app-filter-dropdown class="col-auto" [(items)]="filterEditorService.correspondents" [itemsSelected]="filterEditorService.selectedCorrespondents" [title]="'Correspondents'" (toggle)="onToggleCorrespondent($event)"></app-filter-dropdown>
|
||||
<app-filter-dropdown class="col-auto" [(items)]="filterEditorService.documentTypes" [itemsSelected]="filterEditorService.selectedDocumentTypes" [title]="'Document Types'" (toggle)="onToggleDocumentType($event)"></app-filter-dropdown>
|
||||
<app-filter-dropdown class="col-auto" [items]="tags" [itemsSelected]="selectedTags" title="Tags" (toggle)="toggleTag($event.id)"></app-filter-dropdown>
|
||||
<app-filter-dropdown class="col-auto" [items]="correspondents" [itemsSelected]="selectedCorrespondents" title="Correspondents" (toggle)="toggleCorrespondent($event.id)"></app-filter-dropdown>
|
||||
<app-filter-dropdown class="col-auto" [items]="documentTypes" [itemsSelected]="selectedDocumentTypes" title="Document Types" (toggle)="toggleDocumentType($event.id)"></app-filter-dropdown>
|
||||
|
||||
<app-filter-dropdown-date class="col-auto" [dateBefore]="filterEditorService.dateCreatedBefore" [dateAfter]="filterEditorService.dateCreatedAfter" [title]="'Created'" (dateBeforeSet)="onDateCreatedBeforeSet($event)" (dateAfterSet)="onDateCreatedAfterSet($event)"></app-filter-dropdown-date>
|
||||
<app-filter-dropdown-date class="col-auto" [dateBefore]="filterEditorService.dateAddedBefore" [dateAfter]="filterEditorService.dateAddedAfter" [title]="'Added'" (dateBeforeSet)="onDateAddedBeforeSet($event)" (dateAfterSet)="onDateAddedAfterSet($event)"></app-filter-dropdown-date>
|
||||
<app-filter-dropdown-date class="col-auto" [dateBefore]="dateCreatedBefore" [dateAfter]="dateCreatedAfter" title="Created" (dateBeforeSet)="onDateCreatedBeforeSet($event)" (dateAfterSet)="onDateCreatedAfterSet($event)"></app-filter-dropdown-date>
|
||||
<app-filter-dropdown-date class="col-auto" [dateBefore]="dateAddedBefore" [dateAfter]="dateAddedAfter" title="Added" (dateBeforeSet)="onDateAddedBeforeSet($event)" (dateAfterSet)="onDateAddedAfterSet($event)"></app-filter-dropdown-date>
|
||||
|
||||
<button class="btn btn-link btn-sm" [disabled]="!filterEditorService.hasFilters()" (click)="clearSelected()">
|
||||
<button class="btn btn-link btn-sm" [disabled]="!hasFilters()" (click)="clearSelected()">
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
||||
</svg>
|
||||
|
@ -1,11 +1,15 @@
|
||||
import { Component, EventEmitter, Input, Output, OnInit, OnDestroy } from '@angular/core';
|
||||
import { FilterEditorViewService } from 'src/app/services/filter-editor-view.service'
|
||||
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';
|
||||
import { Subject, Subscription } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
||||
import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
|
||||
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_RULE_TYPES, FILTER_TITLE } from 'src/app/data/filter-rule-type';
|
||||
|
||||
@Component({
|
||||
selector: 'app-filter-editor',
|
||||
@ -14,19 +18,44 @@ import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
|
||||
})
|
||||
export class FilterEditorComponent implements OnInit, OnDestroy {
|
||||
|
||||
constructor() { }
|
||||
constructor(
|
||||
private documentTypeService: DocumentTypeService,
|
||||
private tagService: TagService,
|
||||
private correspondentService: CorrespondentService
|
||||
) { }
|
||||
|
||||
tags: PaperlessTag[] = []
|
||||
correspondents: PaperlessCorrespondent[]
|
||||
documentTypes: PaperlessDocumentType[] = []
|
||||
|
||||
@Input()
|
||||
filterEditorService: FilterEditorViewService
|
||||
filterRules: FilterRule[]
|
||||
|
||||
@Output()
|
||||
clear = new EventEmitter()
|
||||
filterRulesChange = new EventEmitter<FilterRule[]>()
|
||||
|
||||
hasFilters() {
|
||||
return this.filterRules.length > 0
|
||||
}
|
||||
|
||||
@Output()
|
||||
apply = new EventEmitter()
|
||||
get selectedTags(): PaperlessTag[] {
|
||||
let tagRules: FilterRule[] = this.filterRules.filter(fr => fr.type.id == FILTER_HAS_TAG)
|
||||
return this.tags?.filter(t => tagRules.find(tr => tr.value == t.id))
|
||||
}
|
||||
|
||||
get selectedCorrespondents(): PaperlessCorrespondent[] {
|
||||
let correspondentRules: FilterRule[] = this.filterRules.filter(fr => fr.type.id == FILTER_CORRESPONDENT)
|
||||
return this.correspondents?.filter(c => correspondentRules.find(cr => cr.value == c.id))
|
||||
}
|
||||
|
||||
get selectedDocumentTypes(): PaperlessDocumentType[] {
|
||||
let documentTypeRules: FilterRule[] = this.filterRules.filter(fr => fr.type.id == FILTER_DOCUMENT_TYPE)
|
||||
return this.documentTypes?.filter(dt => documentTypeRules.find(dtr => dtr.value == dt.id))
|
||||
}
|
||||
|
||||
get titleFilter() {
|
||||
return this.filterEditorService.titleFilter
|
||||
let existingRule = this.filterRules.find(rule => rule.type.id == FILTER_TITLE)
|
||||
return existingRule ? existingRule.value : ''
|
||||
}
|
||||
|
||||
set titleFilter(value) {
|
||||
@ -37,13 +66,18 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
|
||||
subscription: Subscription
|
||||
|
||||
ngOnInit() {
|
||||
this.tagService.listAll().subscribe(result => this.tags = result.results)
|
||||
this.correspondentService.listAll().subscribe(result => this.correspondents = result.results)
|
||||
this.documentTypeService.listAll().subscribe(result => this.documentTypes = result.results)
|
||||
|
||||
this.titleFilterDebounce = new Subject<string>()
|
||||
|
||||
this.subscription = this.titleFilterDebounce.pipe(
|
||||
debounceTime(400),
|
||||
distinctUntilChanged()
|
||||
).subscribe(title => {
|
||||
this.filterEditorService.titleFilter = title
|
||||
this.applyFilters()
|
||||
|
||||
this.setTitleRule(title)
|
||||
})
|
||||
}
|
||||
|
||||
@ -54,46 +88,159 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
applyFilters() {
|
||||
this.apply.next()
|
||||
this.filterRulesChange.next(this.filterRules)
|
||||
}
|
||||
|
||||
clearSelected() {
|
||||
this.filterEditorService.clear()
|
||||
this.clear.next()
|
||||
}
|
||||
|
||||
onToggleTag(tag: PaperlessTag) {
|
||||
this.filterEditorService.toggleFilterByTag(tag)
|
||||
this.filterRules = []
|
||||
this.applyFilters()
|
||||
}
|
||||
|
||||
onToggleCorrespondent(correspondent: PaperlessCorrespondent) {
|
||||
this.filterEditorService.toggleFilterByCorrespondent(correspondent)
|
||||
private toggleFilterRule(filterRuleTypeID: number, value: number) {
|
||||
|
||||
let filterRuleType = FILTER_RULE_TYPES.find(t => t.id == filterRuleTypeID)
|
||||
|
||||
let existingRule = this.filterRules.find(rule => rule.type.id == filterRuleTypeID && rule.value == value)
|
||||
let existingRuleOfSameType = this.filterRules.find(rule => rule.type.id == filterRuleTypeID)
|
||||
|
||||
if (existingRule) {
|
||||
// if this exact rule already exists, remove it in all cases.
|
||||
this.filterRules.splice(this.filterRules.indexOf(existingRule), 1)
|
||||
} else if (filterRuleType.multi || !existingRuleOfSameType) {
|
||||
// if we allow multiple rules per type, or no rule of this type already exists, push a new rule.
|
||||
this.filterRules.push({type: filterRuleType, value: value})
|
||||
} else {
|
||||
// otherwise (i.e., no multi support AND there's already a rule of this type), update the rule.
|
||||
existingRuleOfSameType.value = value
|
||||
}
|
||||
this.applyFilters()
|
||||
}
|
||||
|
||||
onToggleDocumentType(documentType: PaperlessDocumentType) {
|
||||
this.filterEditorService.toggleFilterByDocumentType(documentType)
|
||||
private setTitleRule(title: string) {
|
||||
let existingRule = this.filterRules.find(rule => rule.type.id == FILTER_TITLE)
|
||||
|
||||
if (!existingRule && title) {
|
||||
this.filterRules.push({type: FILTER_RULE_TYPES.find(t => t.id == FILTER_TITLE), value: title})
|
||||
} else if (existingRule && !title) {
|
||||
this.filterRules.splice(this.filterRules.findIndex(rule => rule.type.id == FILTER_TITLE), 1)
|
||||
} else if (existingRule && title) {
|
||||
existingRule.value = title
|
||||
}
|
||||
this.applyFilters()
|
||||
}
|
||||
|
||||
toggleTag(tagId: number) {
|
||||
this.toggleFilterRule(FILTER_HAS_TAG, tagId)
|
||||
}
|
||||
|
||||
toggleCorrespondent(correspondentId: number) {
|
||||
this.toggleFilterRule(FILTER_CORRESPONDENT, correspondentId)
|
||||
}
|
||||
|
||||
toggleDocumentType(documentTypeId: number) {
|
||||
this.toggleFilterRule(FILTER_DOCUMENT_TYPE, documentTypeId)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Date handling
|
||||
|
||||
|
||||
onDateCreatedBeforeSet(date: NgbDateStruct) {
|
||||
this.filterEditorService.setDateCreatedBefore(date)
|
||||
this.setDateCreatedBefore(date)
|
||||
this.applyFilters()
|
||||
}
|
||||
|
||||
onDateCreatedAfterSet(date: NgbDateStruct) {
|
||||
this.filterEditorService.setDateCreatedAfter(date)
|
||||
this.setDateCreatedAfter(date)
|
||||
this.applyFilters()
|
||||
}
|
||||
|
||||
onDateAddedBeforeSet(date: NgbDateStruct) {
|
||||
this.filterEditorService.setDateAddedBefore(date)
|
||||
this.setDateAddedBefore(date)
|
||||
this.applyFilters()
|
||||
}
|
||||
|
||||
onDateAddedAfterSet(date: NgbDateStruct) {
|
||||
this.filterEditorService.setDateAddedAfter(date)
|
||||
this.setDateAddedAfter(date)
|
||||
this.applyFilters()
|
||||
}
|
||||
|
||||
get dateCreatedBefore(): NgbDateStruct {
|
||||
let createdBeforeRule: FilterRule = this.filterRules.find(fr => fr.type.id == FILTER_CREATED_BEFORE)
|
||||
return createdBeforeRule ? {
|
||||
year: createdBeforeRule.value.substring(0,4),
|
||||
month: createdBeforeRule.value.substring(5,7),
|
||||
day: createdBeforeRule.value.substring(8,10)
|
||||
} : undefined
|
||||
}
|
||||
|
||||
get dateCreatedAfter(): NgbDateStruct {
|
||||
let createdAfterRule: FilterRule = this.filterRules.find(fr => fr.type.id == FILTER_CREATED_AFTER)
|
||||
return createdAfterRule ? {
|
||||
year: createdAfterRule.value.substring(0,4),
|
||||
month: createdAfterRule.value.substring(5,7),
|
||||
day: createdAfterRule.value.substring(8,10)
|
||||
} : undefined
|
||||
}
|
||||
|
||||
get dateAddedBefore(): NgbDateStruct {
|
||||
let addedBeforeRule: FilterRule = this.filterRules.find(fr => fr.type.id == FILTER_ADDED_BEFORE)
|
||||
return addedBeforeRule ? {
|
||||
year: addedBeforeRule.value.substring(0,4),
|
||||
month: addedBeforeRule.value.substring(5,7),
|
||||
day: addedBeforeRule.value.substring(8,10)
|
||||
} : undefined
|
||||
}
|
||||
|
||||
get dateAddedAfter(): NgbDateStruct {
|
||||
let addedAfterRule: FilterRule = this.filterRules.find(fr => fr.type.id == FILTER_ADDED_AFTER)
|
||||
return addedAfterRule ? {
|
||||
year: addedAfterRule.value.substring(0,4),
|
||||
month: addedAfterRule.value.substring(5,7),
|
||||
day: addedAfterRule.value.substring(8,10)
|
||||
} : undefined
|
||||
}
|
||||
|
||||
setDateCreatedBefore(date?: NgbDateStruct) {
|
||||
if (date) this.setDateFilter(date, FILTER_CREATED_BEFORE)
|
||||
else this.clearDateFilter(FILTER_CREATED_BEFORE)
|
||||
}
|
||||
|
||||
setDateCreatedAfter(date?: NgbDateStruct) {
|
||||
if (date) this.setDateFilter(date, FILTER_CREATED_AFTER)
|
||||
else this.clearDateFilter(FILTER_CREATED_AFTER)
|
||||
}
|
||||
|
||||
setDateAddedBefore(date?: NgbDateStruct) {
|
||||
if (date) this.setDateFilter(date, FILTER_ADDED_BEFORE)
|
||||
else this.clearDateFilter(FILTER_ADDED_BEFORE)
|
||||
}
|
||||
|
||||
setDateAddedAfter(date?: NgbDateStruct) {
|
||||
if (date) this.setDateFilter(date, FILTER_ADDED_AFTER)
|
||||
else this.clearDateFilter(FILTER_ADDED_AFTER)
|
||||
}
|
||||
|
||||
setDateFilter(date: NgbDateStruct, dateRuleTypeID: number) {
|
||||
let filterRules = this.filterRules
|
||||
let existingRule = filterRules.find(rule => rule.type.id == dateRuleTypeID)
|
||||
let newValue = `${date.year}-${date.month.toString().padStart(2,'0')}-${date.day.toString().padStart(2,'0')}` // YYYY-MM-DD
|
||||
|
||||
if (existingRule) {
|
||||
existingRule.value = newValue
|
||||
} else {
|
||||
filterRules.push({type: FILTER_RULE_TYPES.find(t => t.id == dateRuleTypeID), value: newValue})
|
||||
}
|
||||
|
||||
this.filterRules = filterRules
|
||||
}
|
||||
|
||||
clearDateFilter(dateRuleTypeID: number) {
|
||||
let filterRules = this.filterRules
|
||||
let existingRule = filterRules.find(rule => rule.type.id == dateRuleTypeID)
|
||||
filterRules.splice(filterRules.indexOf(existingRule), 1)
|
||||
this.filterRules = filterRules
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { FilterEditorViewService } from './filter-editor-view.service';
|
||||
|
||||
describe('FilterEditorViewService', () => {
|
||||
let service: FilterEditorViewService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(FilterEditorViewService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
@ -1,182 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TagService } from 'src/app/services/rest/tag.service';
|
||||
import { CorrespondentService } from 'src/app/services/rest/correspondent.service';
|
||||
import { DocumentTypeService } from 'src/app/services/rest/document-type.service';
|
||||
import { ObjectWithId } from 'src/app/data/object-with-id';
|
||||
import { FilterRule } from 'src/app/data/filter-rule';
|
||||
import { FilterRuleType, FILTER_RULE_TYPES, FILTER_CORRESPONDENT, FILTER_DOCUMENT_TYPE, FILTER_HAS_TAG, FILTER_TITLE, FILTER_ADDED_BEFORE, FILTER_ADDED_AFTER, FILTER_CREATED_BEFORE, FILTER_CREATED_AFTER, FILTER_CREATED_YEAR, FILTER_CREATED_MONTH, FILTER_CREATED_DAY } from 'src/app/data/filter-rule-type';
|
||||
import { Results } from 'src/app/data/results'
|
||||
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';
|
||||
import { NgbDate, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FilterEditorViewService {
|
||||
|
||||
tags: PaperlessTag[] = []
|
||||
correspondents: PaperlessCorrespondent[]
|
||||
documentTypes: PaperlessDocumentType[] = []
|
||||
|
||||
filterRules: FilterRule[] = []
|
||||
|
||||
constructor(private tagService: TagService, private documentTypeService: DocumentTypeService, private correspondentService: CorrespondentService) {
|
||||
this.tagService.listAll().subscribe(result => this.tags = result.results)
|
||||
this.correspondentService.listAll().subscribe(result => this.correspondents = result.results)
|
||||
this.documentTypeService.listAll().subscribe(result => this.documentTypes = result.results)
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.filterRules = []
|
||||
}
|
||||
|
||||
hasFilters() {
|
||||
return this.filterRules.length > 0
|
||||
}
|
||||
|
||||
set titleFilter(title: string) {
|
||||
let existingRule = this.filterRules.find(rule => rule.type.id == FILTER_TITLE)
|
||||
|
||||
if (!existingRule && title) {
|
||||
this.filterRules.push({type: FILTER_RULE_TYPES.find(t => t.id == FILTER_TITLE), value: title})
|
||||
} else if (existingRule && !title) {
|
||||
this.filterRules.splice(this.filterRules.findIndex(rule => rule.type.id == FILTER_TITLE), 1)
|
||||
} else if (existingRule && title) {
|
||||
existingRule.value = title
|
||||
}
|
||||
}
|
||||
|
||||
get titleFilter(): string {
|
||||
let existingRule = this.filterRules.find(rule => rule.type.id == FILTER_TITLE)
|
||||
return existingRule ? existingRule.value : ''
|
||||
}
|
||||
|
||||
get selectedTags(): PaperlessTag[] {
|
||||
let tagRules: FilterRule[] = this.filterRules.filter(fr => fr.type.id == FILTER_HAS_TAG)
|
||||
return this.tags?.filter(t => tagRules.find(tr => tr.value == t.id))
|
||||
}
|
||||
|
||||
get selectedCorrespondents(): PaperlessCorrespondent[] {
|
||||
let correspondentRules: FilterRule[] = this.filterRules.filter(fr => fr.type.id == FILTER_CORRESPONDENT)
|
||||
return this.correspondents?.filter(c => correspondentRules.find(cr => cr.value == c.id))
|
||||
}
|
||||
|
||||
get selectedDocumentTypes(): PaperlessDocumentType[] {
|
||||
let documentTypeRules: FilterRule[] = this.filterRules.filter(fr => fr.type.id == FILTER_DOCUMENT_TYPE)
|
||||
return this.documentTypes?.filter(dt => documentTypeRules.find(dtr => dtr.value == dt.id))
|
||||
}
|
||||
|
||||
toggleFilterByTag(tag: PaperlessTag | number) {
|
||||
if (typeof tag == 'number') tag = this.tags?.find(t => t.id == tag)
|
||||
this.toggleFilterByItem(tag, FILTER_HAS_TAG)
|
||||
}
|
||||
|
||||
toggleFilterByCorrespondent(correspondent: PaperlessCorrespondent | number) {
|
||||
if (typeof correspondent == 'number') correspondent = this.correspondents?.find(t => t.id == correspondent)
|
||||
this.toggleFilterByItem(correspondent, FILTER_CORRESPONDENT)
|
||||
}
|
||||
|
||||
toggleFilterByDocumentType(documentType: PaperlessDocumentType | number) {
|
||||
if (typeof documentType == 'number') documentType = this.documentTypes?.find(t => t.id == documentType)
|
||||
this.toggleFilterByItem(documentType, FILTER_DOCUMENT_TYPE)
|
||||
}
|
||||
|
||||
private toggleFilterByItem(item: ObjectWithId, filterRuleTypeID: number) {
|
||||
let filterRules = this.filterRules
|
||||
let filterRuleType: FilterRuleType = FILTER_RULE_TYPES.find(t => t.id == filterRuleTypeID)
|
||||
let existingRules = filterRules.filter(rule => rule.type.id == filterRuleType.id)
|
||||
let existingItemRule = existingRules?.find(rule => rule.value == item.id)
|
||||
|
||||
if (existingRules && existingItemRule) { // if exact rule exists just remove
|
||||
filterRules.splice(filterRules.indexOf(existingItemRule), 1)
|
||||
} else if (existingRules.length > 0 && filterRuleType.multi) { // e.g. tags can have multiple
|
||||
filterRules.push({type: filterRuleType, value: item.id})
|
||||
} else if (existingRules.length > 0) { // correspondents & documentTypes can only be one
|
||||
filterRules.find(rule => rule.type.id == filterRuleType.id).value = item.id
|
||||
} else {
|
||||
filterRules.push({type: filterRuleType, value: item.id})
|
||||
}
|
||||
|
||||
this.filterRules = filterRules
|
||||
}
|
||||
|
||||
get dateCreatedBefore(): NgbDateStruct {
|
||||
let createdBeforeRule: FilterRule = this.filterRules.find(fr => fr.type.id == FILTER_CREATED_BEFORE)
|
||||
return createdBeforeRule ? {
|
||||
year: createdBeforeRule.value.substring(0,4),
|
||||
month: createdBeforeRule.value.substring(5,7),
|
||||
day: createdBeforeRule.value.substring(8,10)
|
||||
} : undefined
|
||||
}
|
||||
|
||||
get dateCreatedAfter(): NgbDateStruct {
|
||||
let createdAfterRule: FilterRule = this.filterRules.find(fr => fr.type.id == FILTER_CREATED_AFTER)
|
||||
return createdAfterRule ? {
|
||||
year: createdAfterRule.value.substring(0,4),
|
||||
month: createdAfterRule.value.substring(5,7),
|
||||
day: createdAfterRule.value.substring(8,10)
|
||||
} : undefined
|
||||
}
|
||||
|
||||
get dateAddedBefore(): NgbDateStruct {
|
||||
let addedBeforeRule: FilterRule = this.filterRules.find(fr => fr.type.id == FILTER_ADDED_BEFORE)
|
||||
return addedBeforeRule ? {
|
||||
year: addedBeforeRule.value.substring(0,4),
|
||||
month: addedBeforeRule.value.substring(5,7),
|
||||
day: addedBeforeRule.value.substring(8,10)
|
||||
} : undefined
|
||||
}
|
||||
|
||||
get dateAddedAfter(): NgbDateStruct {
|
||||
let addedAfterRule: FilterRule = this.filterRules.find(fr => fr.type.id == FILTER_ADDED_AFTER)
|
||||
return addedAfterRule ? {
|
||||
year: addedAfterRule.value.substring(0,4),
|
||||
month: addedAfterRule.value.substring(5,7),
|
||||
day: addedAfterRule.value.substring(8,10)
|
||||
} : undefined
|
||||
}
|
||||
|
||||
setDateCreatedBefore(date?: NgbDateStruct) {
|
||||
if (date) this.setDateFilter(date, FILTER_CREATED_BEFORE)
|
||||
else this.clearDateFilter(FILTER_CREATED_BEFORE)
|
||||
}
|
||||
|
||||
setDateCreatedAfter(date?: NgbDateStruct) {
|
||||
if (date) this.setDateFilter(date, FILTER_CREATED_AFTER)
|
||||
else this.clearDateFilter(FILTER_CREATED_AFTER)
|
||||
}
|
||||
|
||||
setDateAddedBefore(date?: NgbDateStruct) {
|
||||
if (date) this.setDateFilter(date, FILTER_ADDED_BEFORE)
|
||||
else this.clearDateFilter(FILTER_ADDED_BEFORE)
|
||||
}
|
||||
|
||||
setDateAddedAfter(date?: NgbDateStruct) {
|
||||
if (date) this.setDateFilter(date, FILTER_ADDED_AFTER)
|
||||
else this.clearDateFilter(FILTER_ADDED_AFTER)
|
||||
}
|
||||
|
||||
setDateFilter(date: NgbDateStruct, dateRuleTypeID: number) {
|
||||
let filterRules = this.filterRules
|
||||
let existingRule = filterRules.find(rule => rule.type.id == dateRuleTypeID)
|
||||
let newValue = `${date.year}-${date.month.toString().padStart(2,'0')}-${date.day.toString().padStart(2,'0')}` // YYYY-MM-DD
|
||||
|
||||
if (existingRule) {
|
||||
existingRule.value = newValue
|
||||
} else {
|
||||
filterRules.push({type: FILTER_RULE_TYPES.find(t => t.id == dateRuleTypeID), value: newValue})
|
||||
}
|
||||
|
||||
this.filterRules = filterRules
|
||||
}
|
||||
|
||||
clearDateFilter(dateRuleTypeID: number) {
|
||||
let filterRules = this.filterRules
|
||||
let existingRule = filterRules.find(rule => rule.type.id == dateRuleTypeID)
|
||||
filterRules.splice(filterRules.indexOf(existingRule), 1)
|
||||
this.filterRules = filterRules
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user