diff --git a/src-ui/src/app/app.module.ts b/src-ui/src/app/app.module.ts
index af2c46492..6a847494a 100644
--- a/src-ui/src/app/app.module.ts
+++ b/src-ui/src/app/app.module.ts
@@ -28,6 +28,7 @@ import { PageHeaderComponent } from './components/common/page-header/page-header
import { AppFrameComponent } from './components/app-frame/app-frame.component';
import { ToastsComponent } from './components/common/toasts/toasts.component';
import { FilterEditorComponent } from './components/filter-editor/filter-editor.component';
+import { FilterDropdownComponent } from './components/filter-editor/filter-dropdown/filter-dropdown.component';
import { DocumentCardLargeComponent } from './components/document-list/document-card-large/document-card-large.component';
import { DocumentCardSmallComponent } from './components/document-list/document-card-small/document-card-small.component';
import { NgxFileDropModule } from 'ngx-file-drop';
@@ -74,6 +75,7 @@ import { FilterPipe } from './pipes/filter.pipe';
AppFrameComponent,
ToastsComponent,
FilterEditorComponent,
+ FilterDropdownComponent,
DocumentCardLargeComponent,
DocumentCardSmallComponent,
TextComponent,
diff --git a/src-ui/src/app/components/filter-editor/filter-dropdown/filter-dropdown.component.html b/src-ui/src/app/components/filter-editor/filter-dropdown/filter-dropdown.component.html
new file mode 100644
index 000000000..b135caff0
--- /dev/null
+++ b/src-ui/src/app/components/filter-editor/filter-dropdown/filter-dropdown.component.html
@@ -0,0 +1,19 @@
+
;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ FilterDropodownComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FilterDropodownComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src-ui/src/app/components/filter-editor/filter-dropdown/filter-dropdown.component.ts b/src-ui/src/app/components/filter-editor/filter-dropdown/filter-dropdown.component.ts
new file mode 100644
index 000000000..443fd30e4
--- /dev/null
+++ b/src-ui/src/app/components/filter-editor/filter-dropdown/filter-dropdown.component.ts
@@ -0,0 +1,34 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { FilterRuleType, FILTER_CORRESPONDENT, FILTER_DOCUMENT_TYPE, FILTER_HAS_TAG, FILTER_TITLE, FILTER_RULE_TYPES } from 'src/app/data/filter-rule-type';
+import { ObjectWithId } from 'src/app/data/object-with-id';
+import { MatchingModel } from 'src/app/data/matching-model';
+
+@Component({
+ selector: 'app-filter-dropdown',
+ templateUrl: './filter-dropdown.component.html',
+ styleUrls: ['./filter-dropdown.component.scss']
+})
+export class FilterDropdownComponent implements OnInit {
+
+ constructor() { }
+
+ @Input()
+ filterRuleTypeID: number
+
+ @Output()
+ toggle = new EventEmitter()
+
+ items: MatchingModel[] = []
+ itemsActive: MatchingModel[] = []
+ title: string
+ filterText: string
+
+ ngOnInit(): void {
+ let filterRuleType: FilterRuleType = FILTER_RULE_TYPES.find(t => t.id == this.filterRuleTypeID)
+ this.title = filterRuleType.name
+ }
+
+ toggleItem(item: ObjectWithId) {
+ this.toggle.emit(item, this.filterRuleTypeID)
+ }
+}
diff --git a/src-ui/src/app/components/filter-editor/filter-editor.component.html b/src-ui/src/app/components/filter-editor/filter-editor.component.html
index 5e2077116..153f32644 100644
--- a/src-ui/src/app/components/filter-editor/filter-editor.component.html
+++ b/src-ui/src/app/components/filter-editor/filter-editor.component.html
@@ -6,65 +6,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/src-ui/src/app/components/filter-editor/filter-editor.component.ts b/src-ui/src/app/components/filter-editor/filter-editor.component.ts
index ac89d9b88..b79fbaf12 100644
--- a/src-ui/src/app/components/filter-editor/filter-editor.component.ts
+++ b/src-ui/src/app/components/filter-editor/filter-editor.component.ts
@@ -1,12 +1,15 @@
-import { Component, EventEmitter, Input, OnInit, Output, ElementRef, AfterViewInit, ViewChild } from '@angular/core';
+import { Component, EventEmitter, Input, OnInit, Output, ElementRef, AfterViewInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
import { FilterRule } from 'src/app/data/filter-rule';
-import { FILTER_CORRESPONDENT, FILTER_DOCUMENT_TYPE, FILTER_HAS_TAG, FILTER_TITLE, FILTER_RULE_TYPES } from 'src/app/data/filter-rule-type';
+import { FilterRuleType, FILTER_CORRESPONDENT, FILTER_DOCUMENT_TYPE, FILTER_HAS_TAG, FILTER_TITLE, FILTER_RULE_TYPES } from 'src/app/data/filter-rule-type';
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent';
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type';
import { PaperlessTag } from 'src/app/data/paperless-tag';
+import { AbstractPaperlessService } from 'src/app/services/rest/abstract-paperless-service';
+import { ObjectWithId } from 'src/app/data/object-with-id';
import { CorrespondentService } from 'src/app/services/rest/correspondent.service';
import { DocumentTypeService } from 'src/app/services/rest/document-type.service';
import { TagService } from 'src/app/services/rest/tag.service';
+import { FilterDropdownComponent } from './filter-dropdown/filter-dropdown.component'
import { fromEvent } from 'rxjs';
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
@@ -29,6 +32,9 @@ export class FilterEditorComponent implements OnInit, AfterViewInit {
apply = new EventEmitter()
@ViewChild('filterTextInput') input: ElementRef;
+ @ViewChildren(FilterDropdownComponent) quickFilterDropdowns!: QueryList;
+
+ quickFilterRuleTypeIDs: number[] = [FILTER_HAS_TAG, FILTER_CORRESPONDENT, FILTER_DOCUMENT_TYPE]
correspondents: PaperlessCorrespondent[] = []
tags: PaperlessTag[] = []
@@ -39,25 +45,11 @@ export class FilterEditorComponent implements OnInit, AfterViewInit {
filterCorrespondentsText: string
filterDocumentTypesText: string
- applySelected() {
- this.apply.next()
- }
-
- clearSelected() {
- this.filterRules.splice(0,this.filterRules.length)
- this.updateTextFilterInput()
- this.clear.next()
- }
-
- hasFilters() {
- return this.filterRules.length > 0
- }
-
ngOnInit(): void {
- this.correspondentService.listAll().subscribe(result => {this.correspondents = result.results})
- this.tagService.listAll().subscribe(result => this.tags = result.results)
- this.documentTypeService.listAll().subscribe(result => this.documentTypes = result.results)
this.updateTextFilterInput()
+ this.tagService.listAll().subscribe(result => this.setDropdownItems(result.results, FILTER_HAS_TAG))
+ this.correspondentService.listAll().subscribe(result => this.setDropdownItems(result.results, FILTER_CORRESPONDENT))
+ this.documentTypeService.listAll().subscribe(result => this.setDropdownItems(result.results, FILTER_DOCUMENT_TYPE))
}
ngAfterViewInit() {
@@ -73,8 +65,29 @@ export class FilterEditorComponent implements OnInit, AfterViewInit {
});
}
- findRuleIndex(type_id: number, value: any) {
- return this.filterRules.findIndex(rule => rule.type.id == type_id && rule.value == value)
+ setDropdownItems(items: ObjectWithId[], filterRuleTypeID: number) {
+ let dropdown: FilterDropdownComponent = this.getDropdownByFilterRuleTypeID(filterRuleTypeID)
+ if (dropdown) {
+ dropdown.items = items
+ }
+ }
+
+ getDropdownByFilterRuleTypeID(filterRuleTypeID: number): FilterDropdownComponent {
+ return this.quickFilterDropdowns.find(d => d.filterRuleTypeID == filterRuleTypeID)
+ }
+
+ applySelected() {
+ this.apply.next()
+ }
+
+ clearSelected() {
+ this.filterRules.splice(0,this.filterRules.length)
+ this.updateTextFilterInput()
+ this.clear.next()
+ }
+
+ hasFilters() {
+ return this.filterRules.length > 0
}
updateTextFilterInput() {
@@ -98,60 +111,22 @@ export class FilterEditorComponent implements OnInit, AfterViewInit {
this.applySelected()
}
- toggleFilterByTag(tag_id: number) {
- let existingRuleIndex = this.findRuleIndex(FILTER_HAS_TAG, tag_id)
+ toggleFilterByItem(item: ObjectWithId, filterRuleTypeID: number) {
let filterRules = this.filterRules
- if (existingRuleIndex !== -1) {
- filterRules.splice(existingRuleIndex, 1)
- } else {
- filterRules.push({type: FILTER_RULE_TYPES.find(t => t.id == FILTER_HAS_TAG), value: tag_id})
- }
- this.filterRules = filterRules
- this.applySelected()
- }
+ let filterRuleType: FilterRuleType = FILTER_RULE_TYPES.find(t => t.id == filterRuleTypeID)
+ let existingRule = filterRules.find(rule => rule.type.id == filterRuleType.id)
- toggleFilterByCorrespondent(correspondent_id: number) {
- let filterRules = this.filterRules
- let existingRule = filterRules.find(rule => rule.type.id == FILTER_CORRESPONDENT)
- if (existingRule && existingRule.value == correspondent_id) {
+ if (existingRule && existingRule.value == item.id && filterRuleType.id == FILTER_HAS_TAG) {
+ filterRules.splice(filterRules.indexOf(existingRule), 1)
+ } else if (existingRule && existingRule.value == item.id) {
return
} else if (existingRule) {
- existingRule.value = correspondent_id
+ existingRule.value = item.id
} else {
- filterRules.push({type: FILTER_RULE_TYPES.find(t => t.id == FILTER_CORRESPONDENT), value: correspondent_id})
+ filterRules.push({type: FILTER_RULE_TYPES.find(t => t.id == filterRuleType.id), value: item.id})
}
this.filterRules = filterRules
this.applySelected()
}
- toggleFilterByDocumentType(document_type_id: number) {
- let filterRules = this.filterRules
- let existingRule = filterRules.find(rule => rule.type.id == FILTER_DOCUMENT_TYPE)
- if (existingRule && existingRule.value == document_type_id) {
- return
- } else if (existingRule) {
- existingRule.value = document_type_id
- } else {
- filterRules.push({type: FILTER_RULE_TYPES.find(t => t.id == FILTER_DOCUMENT_TYPE), value: document_type_id})
- }
- this.filterRules = filterRules
- this.applySelected()
- }
-
- currentViewIncludesTag(tag_id: number) {
- return this.findRuleIndex(FILTER_HAS_TAG, tag_id) !== -1
- }
-
- currentViewIncludesCorrespondent(correspondent_id: number) {
- return this.findRuleIndex(FILTER_CORRESPONDENT, correspondent_id) !== -1
- }
-
- currentViewIncludesDocumentType(document_type_id: number) {
- return this.findRuleIndex(FILTER_DOCUMENT_TYPE, document_type_id) !== -1
- }
-
- currentViewIncludesQuickFilter() {
- return this.filterRules.find(rule => rule.type.id == FILTER_HAS_TAG || rule.type.id == FILTER_CORRESPONDENT || rule.type.id == FILTER_DOCUMENT_TYPE) !== undefined
- }
-
}
diff --git a/src-ui/src/app/data/filter-rule-type.ts b/src-ui/src/app/data/filter-rule-type.ts
index a35759f69..1a174ce57 100644
--- a/src-ui/src/app/data/filter-rule-type.ts
+++ b/src-ui/src/app/data/filter-rule-type.ts
@@ -22,15 +22,15 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
{id: FILTER_TITLE, name: "Title contains", filtervar: "title__icontains", datatype: "string", multi: false, default: ""},
{id: FILTER_CONTENT, name: "Content contains", filtervar: "content__icontains", datatype: "string", multi: false, default: ""},
-
- {id: FILTER_ASN, name: "ASN is", filtervar: "archive_serial_number", datatype: "number", multi: false},
-
- {id: FILTER_CORRESPONDENT, name: "Correspondent is", filtervar: "correspondent__id", datatype: "correspondent", multi: false},
- {id: FILTER_DOCUMENT_TYPE, name: "Document type is", filtervar: "document_type__id", datatype: "document_type", multi: false},
- {id: FILTER_IS_IN_INBOX, name: "Is in Inbox", filtervar: "is_in_inbox", datatype: "boolean", multi: false, default: true},
- {id: FILTER_HAS_TAG, name: "Has tag", filtervar: "tags__id__all", datatype: "tag", multi: true},
- {id: FILTER_DOES_NOT_HAVE_TAG, name: "Does not have tag", filtervar: "tags__id__none", datatype: "tag", multi: true},
+ {id: FILTER_ASN, name: "ASN is", filtervar: "archive_serial_number", datatype: "number", multi: false},
+
+ {id: FILTER_CORRESPONDENT, name: "Correspondents", filtervar: "correspondent__id", datatype: "correspondent", multi: false},
+ {id: FILTER_DOCUMENT_TYPE, name: "Document types", filtervar: "document_type__id", datatype: "document_type", multi: false},
+
+ {id: FILTER_IS_IN_INBOX, name: "Is in Inbox", filtervar: "is_in_inbox", datatype: "boolean", multi: false, default: true},
+ {id: FILTER_HAS_TAG, name: "Tags", filtervar: "tags__id__all", datatype: "tag", multi: true},
+ {id: FILTER_DOES_NOT_HAVE_TAG, name: "Does not have tag", filtervar: "tags__id__none", datatype: "tag", multi: true},
{id: FILTER_HAS_ANY_TAG, name: "Has any tag", filtervar: "is_tagged", datatype: "boolean", multi: false, default: true},
{id: FILTER_CREATED_BEFORE, name: "Created before", filtervar: "created__date__lt", datatype: "date", multi: false},
@@ -42,7 +42,7 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
{id: FILTER_ADDED_BEFORE, name: "Added before", filtervar: "added__date__lt", datatype: "date", multi: false},
{id: FILTER_ADDED_AFTER, name: "Added after", filtervar: "added__date__gt", datatype: "date", multi: false},
-
+
{id: FILTER_MODIFIED_BEFORE, name: "Modified before", filtervar: "modified__date__lt", datatype: "date", multi: false},
{id: FILTER_MODIFIED_AFTER, name: "Modified after", filtervar: "modified__date__gt", datatype: "date", multi: false},
]
@@ -54,4 +54,4 @@ export interface FilterRuleType {
datatype: string //number, string, boolean, date
multi: boolean
default?: any
-}
\ No newline at end of file
+}