From c238ee6cfb9c6d03dc1b017a5de9a3be4c78ff47 Mon Sep 17 00:00:00 2001 From: Paul Friederichsen Date: Fri, 18 Aug 2023 07:08:01 -0500 Subject: [PATCH] Add ratings system predicates --- src/app/app.module.ts | 12 ++- .../file-info-sheet.component.html | 24 +---- .../file-info-sheet.component.ts | 28 ++---- src/app/hydrus-file.ts | 30 +++--- src/app/hydrus-rating.ts | 71 ++++++++++++++ src/app/hydrus-services.ts | 45 +++------ src/app/hydrus-system-predicates.ts | 71 ++++++++++++-- .../note-edit-dialog.component.ts | 1 - .../rating-inc-dec.component.html | 3 + .../rating-inc-dec.component.scss | 0 .../rating-inc-dec.component.spec.ts | 23 +++++ .../rating-inc-dec.component.ts | 21 +++++ .../rating-like/rating-like.component.html | 5 + .../rating-like/rating-like.component.scss | 0 .../rating-like/rating-like.component.spec.ts | 23 +++++ src/app/rating-like/rating-like.component.ts | 24 +++++ .../rating-numerical.component.html | 8 ++ .../rating-numerical.component.scss | 0 .../rating-numerical.component.spec.ts | 23 +++++ .../rating-numerical.component.ts | 24 +++++ .../service-select-dialog.component.html | 17 ++++ .../service-select-dialog.component.scss | 0 .../service-select-dialog.component.spec.ts | 23 +++++ .../service-select-dialog.component.ts | 60 ++++++++++++ .../services-info-dialog.component.ts | 2 +- .../system-predicate-dialog.component.html | 6 ++ .../system-predicate-dialog.component.scss | 14 +-- .../system-predicate-dialog.component.ts | 30 +++++- ...em-predicate-ratings-dialog.component.html | 37 ++++++++ ...em-predicate-ratings-dialog.component.scss | 23 +++++ ...predicate-ratings-dialog.component.spec.ts | 23 +++++ ...stem-predicate-ratings-dialog.component.ts | 93 +++++++++++++++++++ src/app/tag-input/tag-input.component.ts | 62 ++++++++++--- 33 files changed, 705 insertions(+), 121 deletions(-) create mode 100644 src/app/hydrus-rating.ts create mode 100644 src/app/rating-inc-dec/rating-inc-dec.component.html create mode 100644 src/app/rating-inc-dec/rating-inc-dec.component.scss create mode 100644 src/app/rating-inc-dec/rating-inc-dec.component.spec.ts create mode 100644 src/app/rating-inc-dec/rating-inc-dec.component.ts create mode 100644 src/app/rating-like/rating-like.component.html create mode 100644 src/app/rating-like/rating-like.component.scss create mode 100644 src/app/rating-like/rating-like.component.spec.ts create mode 100644 src/app/rating-like/rating-like.component.ts create mode 100644 src/app/rating-numerical/rating-numerical.component.html create mode 100644 src/app/rating-numerical/rating-numerical.component.scss create mode 100644 src/app/rating-numerical/rating-numerical.component.spec.ts create mode 100644 src/app/rating-numerical/rating-numerical.component.ts create mode 100644 src/app/service-select-dialog/service-select-dialog.component.html create mode 100644 src/app/service-select-dialog/service-select-dialog.component.scss create mode 100644 src/app/service-select-dialog/service-select-dialog.component.spec.ts create mode 100644 src/app/service-select-dialog/service-select-dialog.component.ts create mode 100644 src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.html create mode 100644 src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.scss create mode 100644 src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.spec.ts create mode 100644 src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 275ca48..630a261 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -88,6 +88,11 @@ import { ApiSettingsComponent } from './api-settings/api-settings.component'; import { AppSettingsComponent } from './app-settings/app-settings.component'; import { JsonViewDialogComponent } from './json-view-dialog/json-view-dialog.component'; import { FileMetadataDialogComponent } from './file-metadata-dialog/file-metadata-dialog.component'; +import { SystemPredicateRatingsDialogComponent } from './system-predicate-ratings-dialog/system-predicate-ratings-dialog.component'; +import { ServiceSelectDialogComponent } from './service-select-dialog/service-select-dialog.component'; +import { RatingNumericalComponent } from './rating-numerical/rating-numerical.component'; +import { RatingLikeComponent } from './rating-like/rating-like.component'; +import { RatingIncDecComponent } from './rating-inc-dec/rating-inc-dec.component'; const MAT_MODULES = [ @@ -153,7 +158,12 @@ const MAT_MODULES = [ ApiSettingsComponent, AppSettingsComponent, JsonViewDialogComponent, - FileMetadataDialogComponent + FileMetadataDialogComponent, + SystemPredicateRatingsDialogComponent, + ServiceSelectDialogComponent, + RatingNumericalComponent, + RatingLikeComponent, + RatingIncDecComponent ], imports: [ BrowserModule, diff --git a/src/app/file-info-sheet/file-info-sheet.component.html b/src/app/file-info-sheet/file-info-sheet.component.html index a0d4382..9176776 100644 --- a/src/app/file-info-sheet/file-info-sheet.component.html +++ b/src/app/file-info-sheet/file-info-sheet.component.html @@ -107,14 +107,7 @@

File Info

{{rating.name}} ({{rating.value ?? 'not set'}})

- - - - - - - - +

+

- {{rating.value}} - +

+{{rating.value}} + diff --git a/src/app/rating-inc-dec/rating-inc-dec.component.scss b/src/app/rating-inc-dec/rating-inc-dec.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/rating-inc-dec/rating-inc-dec.component.spec.ts b/src/app/rating-inc-dec/rating-inc-dec.component.spec.ts new file mode 100644 index 0000000..29a8782 --- /dev/null +++ b/src/app/rating-inc-dec/rating-inc-dec.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RatingIncDecComponent } from './rating-inc-dec.component'; + +describe('RatingIncDecComponent', () => { + let component: RatingIncDecComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RatingIncDecComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(RatingIncDecComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/rating-inc-dec/rating-inc-dec.component.ts b/src/app/rating-inc-dec/rating-inc-dec.component.ts new file mode 100644 index 0000000..c60adee --- /dev/null +++ b/src/app/rating-inc-dec/rating-inc-dec.component.ts @@ -0,0 +1,21 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { HydrusIncDecRating, HydrusIncDecRatingValue } from '../hydrus-rating'; + +@Component({ + selector: 'app-rating-inc-dec', + templateUrl: './rating-inc-dec.component.html', + styleUrls: ['./rating-inc-dec.component.scss'] +}) +export class RatingIncDecComponent { + + @Input() rating: HydrusIncDecRating + + @Output() ratingSet = new EventEmitter() + + constructor() { } + + setRating(value: HydrusIncDecRatingValue) { + this.ratingSet.emit(value); + } + +} diff --git a/src/app/rating-like/rating-like.component.html b/src/app/rating-like/rating-like.component.html new file mode 100644 index 0000000..7d0547d --- /dev/null +++ b/src/app/rating-like/rating-like.component.html @@ -0,0 +1,5 @@ + diff --git a/src/app/rating-like/rating-like.component.scss b/src/app/rating-like/rating-like.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/rating-like/rating-like.component.spec.ts b/src/app/rating-like/rating-like.component.spec.ts new file mode 100644 index 0000000..10d0317 --- /dev/null +++ b/src/app/rating-like/rating-like.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RatingLikeComponent } from './rating-like.component'; + +describe('RatingLikeComponent', () => { + let component: RatingLikeComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RatingLikeComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(RatingLikeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/rating-like/rating-like.component.ts b/src/app/rating-like/rating-like.component.ts new file mode 100644 index 0000000..3d565b5 --- /dev/null +++ b/src/app/rating-like/rating-like.component.ts @@ -0,0 +1,24 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { HydrusLikeRating, HydrusLikeRatingValue, ratingIcons, ratingIconsOutline } from '../hydrus-rating'; + +@Component({ + selector: 'app-rating-like', + templateUrl: './rating-like.component.html', + styleUrls: ['./rating-like.component.scss'] +}) +export class RatingLikeComponent { + + @Input() rating: HydrusLikeRating + + @Output() ratingSet = new EventEmitter() + + ratingIcons = ratingIcons; + ratingIconsOutline = ratingIconsOutline; + + constructor() { } + + setRating(value: HydrusLikeRatingValue) { + this.ratingSet.emit(value); + } + +} diff --git a/src/app/rating-numerical/rating-numerical.component.html b/src/app/rating-numerical/rating-numerical.component.html new file mode 100644 index 0000000..82b5473 --- /dev/null +++ b/src/app/rating-numerical/rating-numerical.component.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/app/rating-numerical/rating-numerical.component.scss b/src/app/rating-numerical/rating-numerical.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/rating-numerical/rating-numerical.component.spec.ts b/src/app/rating-numerical/rating-numerical.component.spec.ts new file mode 100644 index 0000000..69ac070 --- /dev/null +++ b/src/app/rating-numerical/rating-numerical.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RatingNumericalComponent } from './rating-numerical.component'; + +describe('RatingNumericalComponent', () => { + let component: RatingNumericalComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RatingNumericalComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(RatingNumericalComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/rating-numerical/rating-numerical.component.ts b/src/app/rating-numerical/rating-numerical.component.ts new file mode 100644 index 0000000..1043b4e --- /dev/null +++ b/src/app/rating-numerical/rating-numerical.component.ts @@ -0,0 +1,24 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { HydrusNumericalRating, HydrusNumericalRatingValue, ratingIcons, ratingIconsOutline } from '../hydrus-rating'; + +@Component({ + selector: 'app-rating-numerical', + templateUrl: './rating-numerical.component.html', + styleUrls: ['./rating-numerical.component.scss'] +}) +export class RatingNumericalComponent { + + @Input() rating: HydrusNumericalRating + + @Output() ratingSet = new EventEmitter() + + ratingIcons = ratingIcons; + ratingIconsOutline = ratingIconsOutline; + + constructor() { } + + setRating(value: HydrusNumericalRatingValue) { + this.ratingSet.emit(value); + } + +} diff --git a/src/app/service-select-dialog/service-select-dialog.component.html b/src/app/service-select-dialog/service-select-dialog.component.html new file mode 100644 index 0000000..eb3a60e --- /dev/null +++ b/src/app/service-select-dialog/service-select-dialog.component.html @@ -0,0 +1,17 @@ +

{{this.data.title}}

+
+
+ + Service + + + {{service.name}} + + + +
+
+
+ + +
diff --git a/src/app/service-select-dialog/service-select-dialog.component.scss b/src/app/service-select-dialog/service-select-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/service-select-dialog/service-select-dialog.component.spec.ts b/src/app/service-select-dialog/service-select-dialog.component.spec.ts new file mode 100644 index 0000000..0b64e0c --- /dev/null +++ b/src/app/service-select-dialog/service-select-dialog.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ServiceSelectDialogComponent } from './service-select-dialog.component'; + +describe('ServiceSelectDialogComponent', () => { + let component: ServiceSelectDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ServiceSelectDialogComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ServiceSelectDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/service-select-dialog/service-select-dialog.component.ts b/src/app/service-select-dialog/service-select-dialog.component.ts new file mode 100644 index 0000000..32ba3c5 --- /dev/null +++ b/src/app/service-select-dialog/service-select-dialog.component.ts @@ -0,0 +1,60 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { HydrusService } from '../hydrus-services'; +import { MatDialogRef, MAT_DIALOG_DATA, MatDialog, MatDialogConfig } from '@angular/material/dialog'; +import { HydrusServicesService } from '../hydrus-services.service'; +import { map } from 'rxjs'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; + +interface ServiceSelectDialogData { + title: string; + serviceFilter: (services: HydrusService[]) => HydrusService[]; +} + +const defaultData: ServiceSelectDialogData = { + title: 'Select service', + serviceFilter: (services: HydrusService[]) => services, +} + + +@Component({ + selector: 'app-service-select-dialog', + templateUrl: './service-select-dialog.component.html', + styleUrls: ['./service-select-dialog.component.scss'] +}) +export class ServiceSelectDialogComponent implements OnInit { + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: ServiceSelectDialogData, + private servicesService: HydrusServicesService + ) { + if(!data) { + this.data = defaultData; + } + } + + ngOnInit(): void { + } + + services$ = this.servicesService.hydrusServicesArray$.pipe( + map(s => this.data.serviceFilter(s)) + ) + + currentService: HydrusService = null; + + static open(dialog: MatDialog, data?: Partial, config?: MatDialogConfig) { + return dialog.open( + ServiceSelectDialogComponent, + { + maxWidth: '648px', + width: '90vw', + data: { + ...defaultData, + ...data + }, + ...config + } + ); + } + +} diff --git a/src/app/services-info-dialog/services-info-dialog.component.ts b/src/app/services-info-dialog/services-info-dialog.component.ts index 6111364..249c849 100644 --- a/src/app/services-info-dialog/services-info-dialog.component.ts +++ b/src/app/services-info-dialog/services-info-dialog.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { HydrusServicesService } from '../hydrus-services.service'; -import { isNumericalRatingService, isLikeRatingService, isIncDecRatingService } from '../hydrus-services'; +import { isNumericalRatingService, isLikeRatingService, isIncDecRatingService } from '../hydrus-rating'; @Component({ selector: 'app-services-info-dialog', diff --git a/src/app/system-predicate-dialog/system-predicate-dialog.component.html b/src/app/system-predicate-dialog/system-predicate-dialog.component.html index 3a1e3cb..160666a 100644 --- a/src/app/system-predicate-dialog/system-predicate-dialog.component.html +++ b/src/app/system-predicate-dialog/system-predicate-dialog.component.html @@ -140,6 +140,12 @@

system:{{predicate.name}}

+ + Service + + {{service.name}} + +
diff --git a/src/app/system-predicate-dialog/system-predicate-dialog.component.scss b/src/app/system-predicate-dialog/system-predicate-dialog.component.scss index 9bccd09..84e62d7 100644 --- a/src/app/system-predicate-dialog/system-predicate-dialog.component.scss +++ b/src/app/system-predicate-dialog/system-predicate-dialog.component.scss @@ -1,13 +1,13 @@ -@use '../../variables' as *; +//@use '../../variables' as *; //@use '@angular/material/core/typography/typography-utils'; //@use 'sass:math'; -.form-section + .form-section { - //margin-left: 8px; -} -.form-section > * + * { - //margin-left: 8px; -} +// .form-section + .form-section { +// //margin-left: 8px; +// } +// .form-section > * + * { +// //margin-left: 8px; +// } .form-section { display: flex; diff --git a/src/app/system-predicate-dialog/system-predicate-dialog.component.ts b/src/app/system-predicate-dialog/system-predicate-dialog.component.ts index 8133965..8438114 100644 --- a/src/app/system-predicate-dialog/system-predicate-dialog.component.ts +++ b/src/app/system-predicate-dialog/system-predicate-dialog.component.ts @@ -4,6 +4,10 @@ import { FormControl, FormGroup, Validators } from '@angular/forms'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { searchFiletypes } from '../hydrus-file-mimes'; import { allSystemPredicates, hashAlgorithms, operatorDefaults, operatorOptions, Operators, Predicate, SystemPredicate, unitDefaults, Units, unitsOptions, Value, valueLabels } from '../hydrus-system-predicates'; +import { HydrusServicesService } from '../hydrus-services.service'; +import { map, of, switchMap } from 'rxjs'; +import { isFileService } from '../hydrus-services'; +import { isRatingService } from '../hydrus-rating'; @Component({ @@ -16,7 +20,8 @@ export class SystemPredicateDialogComponent implements OnInit { constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) private data: {predicate: SystemPredicate}, - @Inject(LOCALE_ID) private locale + @Inject(LOCALE_ID) private locale, + private services: HydrusServicesService ) { } @@ -35,6 +40,23 @@ export class SystemPredicateDialogComponent implements OnInit { public predicateEnum = this.data.predicate; public predicate: Predicate = allSystemPredicates[this.data.predicate]; + services$ = of(this.data.predicate).pipe( + switchMap(predicate => { + if(predicate === SystemPredicate.FILE_SERVICE) { + return this.services.hydrusServicesArray$.pipe( + map(services => services.filter(isFileService)) + ) + } else if (predicate === SystemPredicate.HAS_RATING || predicate === SystemPredicate.NO_RATING) { + return this.services.hydrusServicesArray$.pipe( + map(services => services.filter(isRatingService)) + ) + } else { + return of([]) + } + }) + ) + + predicateForm = new FormGroup({ value: new FormGroup({ [this.predicate.value]: this.valueForm() @@ -105,6 +127,9 @@ export class SystemPredicateDialogComponent implements OnInit { right: new FormControl(1, Validators.required) }) } + case Value.SERVICE_NAME: { + return new FormControl(null, Validators.required) + } default: { return null } @@ -177,6 +202,9 @@ export class SystemPredicateDialogComponent implements OnInit { case Value.RATIO: { return `${v.left}:${v.right}` } + case Value.SERVICE_NAME: { + return `${v}` + } default: { return null } diff --git a/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.html b/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.html new file mode 100644 index 0000000..4ced7c8 --- /dev/null +++ b/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.html @@ -0,0 +1,37 @@ +

system:rating for {{data.service.name}}

+
+
+ + + Status + + + {{op}} + + + + + + + + + + + + Rating + + + +
+
+
+ + +
diff --git a/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.scss b/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.scss new file mode 100644 index 0000000..67c4ce0 --- /dev/null +++ b/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.scss @@ -0,0 +1,23 @@ +.form-section { + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: center; + gap: 8px; +} + +.outer-form-section { + justify-content: center; + width: 100%; +} + +.wide-form { + flex-grow: 1; + width: 600px; +} +.wide-field { + flex-grow: 1; +} +.string-field { + width: 300px; +} diff --git a/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.spec.ts b/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.spec.ts new file mode 100644 index 0000000..101949d --- /dev/null +++ b/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SystemPredicateRatingsDialogComponent } from './system-predicate-ratings-dialog.component'; + +describe('SystemPredicateRatingsDialogComponent', () => { + let component: SystemPredicateRatingsDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SystemPredicateRatingsDialogComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SystemPredicateRatingsDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.ts b/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.ts new file mode 100644 index 0000000..01b5769 --- /dev/null +++ b/src/app/system-predicate-ratings-dialog/system-predicate-ratings-dialog.component.ts @@ -0,0 +1,93 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { HydrusServicesService } from '../hydrus-services.service'; +import { map, shareReplay } from 'rxjs'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { FormControl, Validators } from '@angular/forms'; +import { isNumericalRatingService, isLikeRatingService, isIncDecRatingService, HydrusRatingValue, ratingsServiceToRatingPredicate, HydrusNumericalRatingValue, HydrusIncDecRatingValue, HydrusLikeRatingValue } from '../hydrus-rating'; +import { HydrusService } from '../hydrus-services'; +import { ratingOperators } from '../hydrus-system-predicates'; + +function generateRating(service: HydrusService) { + if (isNumericalRatingService(service)) { + return { + ...service, + value: null as HydrusNumericalRatingValue + } + } else if (isLikeRatingService(service)) { + return { + ...service, + value: null as HydrusLikeRatingValue + } + } else if (isIncDecRatingService(service)) { + return { + ...service, + value: 0 as HydrusIncDecRatingValue + } + } +} + +@Component({ + selector: 'app-system-predicate-ratings-dialog', + templateUrl: './system-predicate-ratings-dialog.component.html', + styleUrls: ['./system-predicate-ratings-dialog.component.scss'] +}) +export class SystemPredicateRatingsDialogComponent implements OnInit { + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: {service: HydrusService}, + //private services: HydrusServicesService + ) { } + + ngOnInit(): void { + } + + rating = generateRating(this.data.service); + predicate = ratingsServiceToRatingPredicate(this.data.service); + operators = ratingOperators[this.predicate] + + isNumericalRatingService = isNumericalRatingService; + isLikeRatingService = isLikeRatingService; + isIncDecRatingService = isIncDecRatingService; + + setRating(value: HydrusRatingValue) { + this.rating.value = value; + } + + operatorForm = new FormControl('is', Validators.required) + + getValue() { + if(isNumericalRatingService(this.rating)) { + return `${this.rating.value}/${this.rating.max_stars}` + } else if(isLikeRatingService(this.rating)) { + return this.rating.value ? 'liked' : 'disliked' + } else if(isIncDecRatingService(this.rating)) { + return `${this.rating.value}` + } else { + return '' + } + } + + getPredicateString() { + if(this.rating.value === null) { + return `system:no rating for ${this.data.service.name}` + } + const value = this.getValue(); + return `system:rating for ${this.data.service.name} ${this.operatorForm.value} ${value}` + } + + addButton() { + this.dialogRef.close(this.getPredicateString()) + } + + // ratingsServices$ = this.services.hydrusServicesArray$.pipe( + // map(services => getRatingsServices(services)) + // ) + + // serviceInput = new FormControl(null); + + // selectedService$ = this.serviceInput.valueChanges.pipe( + // shareReplay(1), + // ) + +} diff --git a/src/app/tag-input/tag-input.component.ts b/src/app/tag-input/tag-input.component.ts index 6b3c2d5..7fd9329 100644 --- a/src/app/tag-input/tag-input.component.ts +++ b/src/app/tag-input/tag-input.component.ts @@ -5,7 +5,7 @@ import { MatChipInputEvent } from '@angular/material/chips'; import { ControlValueAccessor, NgControl, UntypedFormControl } from '@angular/forms'; import { switchMap } from 'rxjs/operators'; import { MatAutocompleteSelectedEvent, MatAutocomplete } from '@angular/material/autocomplete'; -import { Observable, of } from 'rxjs'; +import { Observable, firstValueFrom, of } from 'rxjs'; import { HydrusTagsService } from '../hydrus-tags.service'; import { HydrusSearchTags, HydrusTagSearchTag, TagDisplayType } from '../hydrus-tags'; import { MatDialog } from '@angular/material/dialog'; @@ -13,6 +13,11 @@ import { allSystemPredicates, predicateGroups, SystemPredicate } from '../hydrus import { SystemPredicateDialogComponent } from '../system-predicate-dialog/system-predicate-dialog.component'; import { TagInputDialogComponent } from '../tag-input-dialog/tag-input-dialog.component'; import { SettingsService } from '../settings.service'; +import { ServiceSelectDialogComponent } from '../service-select-dialog/service-select-dialog.component'; +import { SystemPredicateRatingsDialogComponent } from '../system-predicate-ratings-dialog/system-predicate-ratings-dialog.component'; +import { isRatingService } from '../hydrus-rating'; +import { HydrusService } from '../hydrus-services'; +import { searchTagsContainsSystemPredicate } from '../utils/tag-utils'; function convertPredicate(p: SystemPredicate): ConvertedPredicate { const pred = allSystemPredicates[p]; @@ -212,26 +217,55 @@ export class TagInputComponent implements OnInit, ControlValueAccessor { return 'predicate' in p; } - systemPredicateButton(pred: SystemPredicate) { + async systemPredicateButton(pred: SystemPredicate) { + if(pred === SystemPredicate.RATING_GENERAL) { + const result = await this.ratingPredicateDialog(); + if(result) { + this.addSearchTag(result); + } + return; + } const predicate = allSystemPredicates[pred]; if(!predicate.operator && !predicate.units && !predicate.value) { this.addSearchTag(`system:${predicate.name}`); } else { - const dialogRef = this.dialog.open( - SystemPredicateDialogComponent, - { - //width: '80vw', - data: {predicate: pred}, - } - ); - dialogRef.afterClosed().subscribe(result => { - if(result) { - this.addSearchTag(result); - } - }); + const result = await this.predicateDialog(pred); + if(result) { + this.addSearchTag(result); + } } } + async predicateDialog(pred: SystemPredicate) { + const dialogRef = this.dialog.open( + SystemPredicateDialogComponent, + { + //width: '80vw', + data: {predicate: pred}, + } + ) + return firstValueFrom(dialogRef.afterClosed()); + } + + async ratingPredicateDialog() { + const serviceDialog = ServiceSelectDialogComponent.open(this.dialog, { + title: 'Select rating service', + serviceFilter: services => services.filter(isRatingService), + }) + const service = await firstValueFrom(serviceDialog.afterClosed()); + const dialogRef = this.dialog.open( + SystemPredicateRatingsDialogComponent, + { + data: { + service + }, + // maxWidth: '648px', + // width: '90vw', + } + ); + return firstValueFrom(dialogRef.afterClosed()); + } + predicateButtons: (ConvertedPredicateGroup | ConvertedPredicate)[] = predicateGroups.map(p => { const isGroup = 'predicates' in p;