Skip to content

Commit bd801a8

Browse files
committed
Add system predicates to autocomplete
1 parent 6562b20 commit bd801a8

File tree

3 files changed

+50
-22
lines changed

3 files changed

+50
-22
lines changed

src/app/hydrus-system-predicates.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,3 +410,10 @@ export const ratingOperators: Partial<Record<SystemPredicate, string[]>> = {
410410
'is about'
411411
]
412412
}
413+
414+
export const systemTagsForSearch =
415+
predicateGroups.flatMap(g => 'predicate' in g ? g.predicate : g.predicates)
416+
.map(systemPredicate => ({
417+
systemPredicate,
418+
value: `system:${allSystemPredicates[systemPredicate].name}`
419+
}))

src/app/tag-input/tag-input.component.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,19 @@
4646
>
4747
</mat-chip-grid>
4848
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
49-
@if (filteredTags | async; as tags) {
50-
@if (tags.length > 25) {
49+
@if ((enableSystemPredicates ? filteredTags$ : filteredTagsFromAPI$) | async; as tags) {
50+
@if (tags.length > 100) {
5151
<cdk-virtual-scroll-viewport
5252
class="virtual-scroll-viewport-full-width"
5353
itemSize="48" minBufferPx="256" maxBufferPx="512">
54-
<mat-option *cdkVirtualFor="let tag of tags" [value]="tag.value" [attr.data-tag-namespace]="tag.value | tagNamespace" class="theming tag-color">
55-
{{tag.value}} ({{tag.count | number}})
54+
<mat-option *cdkVirtualFor="let tag of tags" [value]="tag" [attr.data-tag-namespace]="tag.value | tagNamespace" class="theming tag-color">
55+
{{tag.value}} @if(tag.count) { ({{tag.count | number}}) }
5656
</mat-option>
5757
</cdk-virtual-scroll-viewport>
5858
} @else {
5959
@for (tag of tags; track tag.value) {
60-
<mat-option [value]="tag.value" [attr.data-tag-namespace]="tag.value | tagNamespace" class="theming tag-color">
61-
{{tag.value}} ({{tag.count | number}})
60+
<mat-option [value]="tag" [attr.data-tag-namespace]="tag.value | tagNamespace" class="theming tag-color">
61+
{{tag.value}} @if(tag.count) { ({{tag.count | number}}) }
6262
</mat-option>
6363
}
6464
}

src/app/tag-input/tag-input.component.ts

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { HydrusFilesService } from './../hydrus-files.service';
2-
import { Component, OnInit, Output, EventEmitter, ViewChild, ElementRef, Input, Optional, Self } from '@angular/core';
2+
import { Component, OnInit, Output, EventEmitter, ViewChild, ElementRef, Input, Optional, Self, input } from '@angular/core';
33
import {COMMA, ENTER} from '@angular/cdk/keycodes';
44
import { MatChipInputEvent } from '@angular/material/chips';
5-
import { ControlValueAccessor, NgControl, UntypedFormControl } from '@angular/forms';
6-
import { switchMap } from 'rxjs/operators';
7-
import { MatAutocompleteSelectedEvent, MatAutocomplete } from '@angular/material/autocomplete';
8-
import { Observable, firstValueFrom, of } from 'rxjs';
5+
import { ControlValueAccessor, FormControl, NgControl, UntypedFormControl } from '@angular/forms';
6+
import { distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators';
7+
import { MatAutocompleteSelectedEvent, MatAutocomplete, MatOption } from '@angular/material/autocomplete';
8+
import { Observable, combineLatest, firstValueFrom, of } from 'rxjs';
99
import { HydrusTagsService } from '../hydrus-tags.service';
1010
import { HydrusSearchTags, HydrusTagSearchTag, TagDisplayType, isSingleTag } from '../hydrus-tags';
1111
import { MatDialog } from '@angular/material/dialog';
12-
import { allSystemPredicates, predicateGroups, SystemPredicate } from '../hydrus-system-predicates';
12+
import { allSystemPredicates, predicateGroups, SystemPredicate, systemTagsForSearch } from '../hydrus-system-predicates';
1313
import { SystemPredicateDialogComponent } from '../system-predicate-dialog/system-predicate-dialog.component';
1414
import { TagInputDialogComponent } from '../tag-input-dialog/tag-input-dialog.component';
1515
import { SettingsService } from '../settings.service';
@@ -38,6 +38,12 @@ interface ConvertedPredicateGroup {
3838
predicates: ConvertedPredicate[]
3939
}
4040

41+
export interface HydrusTagSearchTagUI {
42+
value: string,
43+
count?: number,
44+
systemPredicate?: SystemPredicate
45+
}
46+
4147
@Component({
4248
selector: 'app-tag-input',
4349
templateUrl: './tag-input.component.html',
@@ -50,9 +56,6 @@ export class TagInputComponent implements OnInit, ControlValueAccessor {
5056
searchTags: HydrusSearchTags = [];
5157
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
5258

53-
tagCtrl = new UntypedFormControl();
54-
filteredTags: Observable<HydrusTagSearchTag[]>;
55-
5659
//inputControl = new FormControl("", this.validators)
5760

5861
@Input() enableOrSearch = true;
@@ -69,6 +72,22 @@ export class TagInputComponent implements OnInit, ControlValueAccessor {
6972

7073
@Input() enableSiblingParentsDialog = true;
7174

75+
showSystemPredicateAutocompleteByDefault = input()
76+
77+
78+
tagCtrl = new FormControl('');
79+
filteredTagsFromAPI$: Observable<HydrusTagSearchTagUI[]> = this.tagCtrl.valueChanges.pipe(
80+
switchMap(search => search && search.length >= 3 ? this.tagsService.searchTags(search, this.displayType) : of([]))
81+
);
82+
83+
filteredSystemPredicates$: Observable<HydrusTagSearchTagUI[]> = this.tagCtrl.valueChanges.pipe(
84+
map((input) => input ? systemTagsForSearch.filter(p => p.value.startsWith(input)) : []),
85+
);
86+
87+
filteredTags$: Observable<HydrusTagSearchTagUI[]> = combineLatest([this.filteredTagsFromAPI$, this.filteredSystemPredicates$, ]).pipe(
88+
map(([api, predicates]) => [...api, ...predicates]),
89+
)
90+
7291
@Output()
7392
tags = new EventEmitter<HydrusSearchTags>();
7493

@@ -87,11 +106,7 @@ export class TagInputComponent implements OnInit, ControlValueAccessor {
87106
if (this.controlDir) {
88107
this.controlDir.valueAccessor = this
89108
}
90-
91-
this.filteredTags = this.tagCtrl.valueChanges.pipe(
92-
switchMap(search => search && search.length >= 3 ? this.tagsService.searchTags(search, this.displayType) : of([]))
93-
);
94-
}
109+
}
95110

96111
favoriteTags = this.settingsService.appSettings.favoriteTags;
97112

@@ -180,8 +195,14 @@ export class TagInputComponent implements OnInit, ControlValueAccessor {
180195
}
181196

182197
selected(event: MatAutocompleteSelectedEvent): void {
183-
const negated = this.tagInput.nativeElement.value.startsWith('-');
184-
this.addSearchTag((negated ? '-' : '') + event.option.value);
198+
const option: MatOption<HydrusTagSearchTagUI> = event.option
199+
console.log(option)
200+
if(option.value.systemPredicate) {
201+
this.systemPredicateButton(option.value.systemPredicate)
202+
} else {
203+
const negated = this.tagInput.nativeElement.value.startsWith('-');
204+
this.addSearchTag((negated ? '-' : '') + option.value.value);
205+
}
185206
this.tagInput.nativeElement.value = '';
186207
this.tagCtrl.setValue(null);
187208
}

0 commit comments

Comments
 (0)