Fixed <select> flickering

This commit is contained in:
nise.moe 2024-02-25 20:12:50 +01:00
parent a055e88063
commit 6129257a3b
4 changed files with 46 additions and 39 deletions

View File

@ -5,17 +5,24 @@ import {HttpClient} from "@angular/common/http";
import {environment} from "../../environments/environment";
import {countryCodeToFlag, formatDuration} from "../format";
import {OsuGradeComponent} from "../../corelib/components/osu-grade/osu-grade.component";
import {Field, Query, QueryBuilderComponent} from "../../corelib/components/query-builder/query-builder.component";
import {
FieldType,
Operator,
Query,
QueryBuilderComponent
} from "../../corelib/components/query-builder/query-builder.component";
import {RouterLink} from "@angular/router";
import {CalculatePageRangePipe} from "../../corelib/calculate-page-range.pipe";
import {DownloadFilesService} from "../../corelib/service/download-files.service";
import {CuteLoadingComponent} from "../../corelib/components/cute-loading/cute-loading.component";
import {Title} from "@angular/platform-browser";
export interface SchemaField {
name: string;
shortName: string;
category: 'user' | 'score' | 'beatmap' | 'metrics';
type: 'number' | 'string' | 'flag' | 'grade' | 'boolean' | 'datetime' | 'playtime';
validOperators: Operator[];
active: boolean;
description: string;
}
@ -63,6 +70,7 @@ interface Sorting {
export class SearchComponent implements OnInit {
constructor(private httpClient: HttpClient,
private title: Title,
public downloadFilesService: DownloadFilesService) { }
isError = false;
@ -76,10 +84,14 @@ export class SearchComponent implements OnInit {
queries: Query[] | null = null;
ngOnInit(): void {
this.title.setTitle("/k/ - advanced search");
this.isLoadingSchema = true;
this.httpClient.get<SchemaResponse>(`${environment.apiUrl}/search/schema`,).subscribe({
next: (response) => {
this.fields = response.fields;
this.fields.forEach(field => {
field.validOperators = this.getOperators(field.type);
})
this.loadPreviousFromLocalStorage();
this.isLoadingSchema = false;
},
@ -89,6 +101,34 @@ export class SearchComponent implements OnInit {
});
}
getOperators(fieldType: FieldType | undefined): Operator[] {
switch (fieldType) {
case 'number':
return ['=', '>', '<', '>=', '<=', '!=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'any'}) as Operator);
case 'string':
return ['=', 'contains', 'like']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'any'}) as Operator);
case 'boolean':
return ['=', '!=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'boolean'}) as Operator);
case 'flag':
return ['=', '!=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'flag'}) as Operator);
case 'grade':
return ['=', '!=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'grade'}) as Operator);
case 'datetime':
return ['before', 'after']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'datetime'}) as Operator);
case 'playtime':
return ['>', '<', '>=', '<=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'any'}) as Operator);
default:
return [];
}
}
private loadPreviousFromLocalStorage() {
const storedQueries = localStorage.getItem('search_settings');
if (storedQueries) {
@ -227,6 +267,6 @@ export class SearchComponent implements OnInit {
protected readonly countryCodeToFlag = countryCodeToFlag;
protected readonly Math = Math;
protected readonly formatDuration = formatDuration;
}

View File

@ -8,13 +8,8 @@ export type FieldType = 'number' | 'string' | 'flag' | 'grade' | 'boolean' | 'da
export type OperatorType = '=' | '>' | '<' | 'contains' | 'like' | '>=' | '<=' | '!=';
export type ValueType = 'any' | 'boolean' | 'flag' | 'grade' | 'datetime';
export interface Field {
name: string;
type: FieldType;
}
export interface Predicate {
field: Field | null;
field: SchemaField | null;
operator: Operator | null;
value: string | number | null;
}
@ -27,7 +22,7 @@ export interface Operator {
export interface Query {
predicates: Predicate[];
logicalOperator: 'AND' | 'OR';
childQueries?: Query[]; // Optional property for sub-queries
childQueries?: Query[];
}
@Component({

View File

@ -30,7 +30,7 @@
<select [disabled]="!predicate.field">
<option *ngFor="let operator of getOperators(predicate.field?.type)"
<option *ngFor="let operator of predicate.field?.validOperators"
[selected]="operator.operatorType === predicate.operator?.operatorType"
(click)="predicate.operator = operator; this.queryChanged.emit()">
{{ operator.operatorType }}

View File

@ -32,35 +32,7 @@ export class QueryComponent {
onFieldChange(predicate: Predicate, selectedField: any): void {
predicate.field = selectedField;
predicate.operator = this.getOperators(selectedField.type)[0];
}
getOperators(fieldType: FieldType | undefined): Operator[] {
switch (fieldType) {
case 'number':
return ['=', '>', '<', '>=', '<=', '!=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'any'}) as Operator);
case 'string':
return ['=', 'contains', 'like']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'any'}) as Operator);
case 'boolean':
return ['=', '!=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'boolean'}) as Operator);
case 'flag':
return ['=', '!=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'flag'}) as Operator);
case 'grade':
return ['=', '!=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'grade'}) as Operator);
case 'datetime':
return ['before', 'after']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'datetime'}) as Operator);
case 'playtime':
return ['>', '<', '>=', '<=']
.map((operatorType: String) => ({operatorType: operatorType, acceptsValues: 'any'}) as Operator);
default:
return [];
}
predicate.operator = selectedField.validOperators[0];
}
addPredicate(): void {