From da299c053507a35a8067ff76ccf04a7ccb983b00 Mon Sep 17 00:00:00 2001 From: "nise.moe" Date: Sat, 24 Feb 2024 17:58:10 +0100 Subject: [PATCH] Operators refactor (added boolean), handling errors in frontend, improved export/import settings --- .../nise/controller/SearchController.kt | 20 ++++++-- nise-frontend/src/app/app.component.html | 2 +- .../src/app/search/search.component.html | 25 +++++---- .../src/app/search/search.component.ts | 51 ++++++++++++------- nise-frontend/src/assets/style.css | 4 ++ .../query-builder/query-builder.component.ts | 8 ++- .../components/query/query.component.html | 26 ++++++++-- .../components/query/query.component.ts | 26 +++++++--- 8 files changed, 118 insertions(+), 44 deletions(-) diff --git a/nise-backend/src/main/kotlin/com/nisemoe/nise/controller/SearchController.kt b/nise-backend/src/main/kotlin/com/nisemoe/nise/controller/SearchController.kt index 9ffc526..5da9ba9 100644 --- a/nise-backend/src/main/kotlin/com/nisemoe/nise/controller/SearchController.kt +++ b/nise-backend/src/main/kotlin/com/nisemoe/nise/controller/SearchController.kt @@ -129,10 +129,15 @@ class SearchController( data class SearchPredicate( val field: SearchField, - val operator: String, + val operator: SearchPredicateOperator, val value: String ) + data class SearchPredicateOperator( + val operatorType: String, + val acceptsValues: String + ) + data class SearchField( val name: String, val type: String @@ -352,8 +357,9 @@ class SearchController( private fun buildPredicateCondition(predicate: SearchPredicate): Condition { val field = mapPredicateFieldToDatabaseField(predicate.field.name) return when (predicate.field.type.lowercase()) { - "number" -> buildNumberCondition(field as Field, predicate.operator, predicate.value.toDouble()) - "string" -> buildStringCondition(field as Field, predicate.operator, predicate.value) + "number" -> buildNumberCondition(field as Field, predicate.operator.operatorType, predicate.value.toDouble()) + "string" -> buildStringCondition(field as Field, predicate.operator.operatorType, predicate.value) + "boolean" -> buildBooleanCondition(field as Field, predicate.operator.operatorType, predicate.value.toBoolean()) else -> throw IllegalArgumentException("Invalid field type") } } @@ -423,6 +429,14 @@ class SearchController( } } + private fun buildBooleanCondition(field: Field, operator: String, value: Boolean): Condition { + return when (operator) { + "=" -> field.eq(value) + "!=" -> field.ne(value) + else -> throw IllegalArgumentException("Invalid operator") + } + } + private fun buildNumberCondition(field: Field, operator: String, value: Double): Condition { return when (operator) { "=" -> field.eq(value) diff --git a/nise-frontend/src/app/app.component.html b/nise-frontend/src/app/app.component.html index f2cb6a2..4a41834 100644 --- a/nise-frontend/src/app/app.component.html +++ b/nise-frontend/src/app/app.component.html @@ -26,5 +26,5 @@
- v20240222 + v20240224
diff --git a/nise-frontend/src/app/search/search.component.html b/nise-frontend/src/app/search/search.component.html index 9aec323..d93342d 100644 --- a/nise-frontend/src/app/search/search.component.html +++ b/nise-frontend/src/app/search/search.component.html @@ -4,8 +4,8 @@
Table columns -
- {{ category }} +
+ {{ category }}
-
-
- - - -
- - +
+ + + +
+
@@ -60,13 +58,18 @@
+
+

Looks like something went wrong... :(

+

I'll look into what caused the error - but feel free to get in touch.

+
+
tools
- +
diff --git a/nise-frontend/src/app/search/search.component.ts b/nise-frontend/src/app/search/search.component.ts index 49dfd3b..6d165d0 100644 --- a/nise-frontend/src/app/search/search.component.ts +++ b/nise-frontend/src/app/search/search.component.ts @@ -9,7 +9,6 @@ import {Field, Query, QueryBuilderComponent} from "../../corelib/components/quer import {RouterLink} from "@angular/router"; import {CalculatePageRangePipe} from "../../corelib/calculate-page-range.pipe"; import {DownloadFilesService} from "../../corelib/service/download-files.service"; -import {catchError, throwError} from "rxjs"; interface SchemaField { name: string; @@ -96,6 +95,7 @@ export class SearchComponent implements OnInit { constructor(private httpClient: HttpClient, public downloadFilesService: DownloadFilesService) { } + isError = false; isLoading = false; response: SearchResponse | null = null; @@ -189,6 +189,24 @@ export class SearchComponent implements OnInit { }; } + deselectEntireFieldCategory(categoryName: string): void { + this.fields.forEach(field => { + if (field.category === categoryName) { + field.active = false; + } + }); + this.saveColumnsStatusToLocalStorage(); + } + + selectEntireFieldCategory(categoryName: string): void { + this.fields.forEach(field => { + if (field.category === categoryName) { + field.active = true; + } + }); + this.saveColumnsStatusToLocalStorage(); + } + mapSchemaFieldsToFields(): Field[] { return this.fields.map(field => { return { @@ -248,28 +266,25 @@ export class SearchComponent implements OnInit { search(pageNumber: number = 1): void { this.isLoading = true; + this.isError = false; + this.response = null; + const body = { queries: this.queries, sorting: this.sortingOrder, page: pageNumber } - this.httpClient.post(`${environment.apiUrl}/search`, body).pipe( - catchError(error => { - // Handle the error or rethrow - console.error('An error occurred:', error); - return throwError(() => new Error('An error occurred')); // Rethrow or return a new observable - }) - ).subscribe({ - next: (response) => { - this.response = response; - this.isLoading = false; - }, - error: (error) => { - // Handle subscription error - console.error('Subscription error:', error); - this.isLoading = false; - } - }); + this.httpClient.post(`${environment.apiUrl}/search`, body) + .subscribe({ + next: (response) => { + this.response = response; + this.isLoading = false; + }, + error: (error) => { + this.isError = true; + this.isLoading = false; + } + }); this.updateLocalStorage(); } diff --git a/nise-frontend/src/assets/style.css b/nise-frontend/src/assets/style.css index 17597b0..f7b6571 100644 --- a/nise-frontend/src/assets/style.css +++ b/nise-frontend/src/assets/style.css @@ -202,6 +202,10 @@ a.btn-success:hover { margin-bottom: 40px; } +.mt-1 { + margin-top: 10px; +} + .mt-2 { margin-top: 20px; } diff --git a/nise-frontend/src/corelib/components/query-builder/query-builder.component.ts b/nise-frontend/src/corelib/components/query-builder/query-builder.component.ts index ade06bb..7403412 100644 --- a/nise-frontend/src/corelib/components/query-builder/query-builder.component.ts +++ b/nise-frontend/src/corelib/components/query-builder/query-builder.component.ts @@ -5,6 +5,7 @@ import {QueryComponent} from "../query/query.component"; export type FieldType = 'number' | 'string' | 'flag' | 'grade' | 'boolean'; export type OperatorType = '=' | '>' | '<' | 'contains' | 'like' | '>=' | '<=' | '!='; +export type ValueType = 'any' | 'boolean'; export interface Field { name: string; @@ -13,10 +14,15 @@ export interface Field { export interface Predicate { field: Field | null; - operator: OperatorType | null; + operator: Operator | null; value: string | number | null; } +export interface Operator { + operatorType: OperatorType; + acceptsValues: ValueType; +} + export interface Query { predicates: Predicate[]; logicalOperator: 'AND' | 'OR'; diff --git a/nise-frontend/src/corelib/components/query/query.component.html b/nise-frontend/src/corelib/components/query/query.component.html index 03ad5a4..72def22 100644 --- a/nise-frontend/src/corelib/components/query/query.component.html +++ b/nise-frontend/src/corelib/components/query/query.component.html @@ -18,13 +18,31 @@ - + - + + + + + + + + + + + + + +
diff --git a/nise-frontend/src/corelib/components/query/query.component.ts b/nise-frontend/src/corelib/components/query/query.component.ts index fb72403..d76ef65 100644 --- a/nise-frontend/src/corelib/components/query/query.component.ts +++ b/nise-frontend/src/corelib/components/query/query.component.ts @@ -1,6 +1,6 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; -import {Field, FieldType, OperatorType, Predicate, Query} from "../query-builder/query-builder.component"; -import {NgForOf} from "@angular/common"; +import {Field, FieldType, Operator, OperatorType, Predicate, Query} from "../query-builder/query-builder.component"; +import {JsonPipe, NgForOf, NgIf} from "@angular/common"; import {FormsModule, ReactiveFormsModule} from "@angular/forms"; import { v4 as uuidv4 } from 'uuid'; @@ -10,7 +10,9 @@ import { v4 as uuidv4 } from 'uuid'; imports: [ NgForOf, ReactiveFormsModule, - FormsModule + FormsModule, + NgIf, + JsonPipe ], templateUrl: './query.component.html', styleUrl: './query.component.css' @@ -32,17 +34,29 @@ export class QueryComponent { predicate.operator = this.getOperators(selectedField.type)[0]; } - getOperators(fieldType: FieldType | undefined): OperatorType[] { + getOperators(fieldType: FieldType | undefined): Operator[] { switch (fieldType) { case 'number': - return ['=', '>', '<', '>=', '<=', '!=']; + return ['=', '>', '<', '>=', '<=', '!='] + .map((operatorType: String) => ({ operatorType: operatorType, acceptsValues: 'any'}) as Operator); case 'string': - return ['=', 'contains', 'like']; + return ['=', 'contains', 'like'] + .map((operatorType: String) => ({ operatorType: operatorType, acceptsValues: 'any'}) as Operator); + case 'boolean': + return ['=', '!='] + .map((operatorType: String) => ({ operatorType: operatorType, acceptsValues: 'boolean'}) as Operator); default: return []; } } + compare(a: any, b: any): boolean { + console.warn('compare', a, b); + console.warn('compare', a === b) + console.error(); + return a === b; + } + addPredicate(): void { this.query.predicates.push({ field: null, operator: null, value: null }); this.queryChanged.emit();