From 43ea2878b428b22c76616d8fe0ad52da3aa93694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Agneray?= <francois.agneray@lam.fr> Date: Mon, 3 Oct 2022 17:40:16 +0200 Subject: [PATCH] #82 => WIP --- .../criteria/criteria-by-family.component.html | 1 + .../criteria/criteria-by-family.component.ts | 12 ++++++++++++ .../criteria/criteria-tabs.component.html | 1 + .../components/criteria/criteria-tabs.component.ts | 12 ++++++++++++ .../components/criteria/criterion.component.ts | 9 ++++++++- .../search-type/abstract-search-type.component.ts | 13 +++++++++++-- .../search/containers/criteria.component.html | 1 + .../search/containers/criteria.component.ts | 9 +++++++++ .../app/instance/store/actions/search.actions.ts | 1 + .../app/instance/store/reducers/search.reducer.ts | 6 ++++++ 10 files changed, 62 insertions(+), 3 deletions(-) diff --git a/client/src/app/instance/search/components/criteria/criteria-by-family.component.html b/client/src/app/instance/search/components/criteria/criteria-by-family.component.html index fa4bc082..59dc44c4 100644 --- a/client/src/app/instance/search/components/criteria/criteria-by-family.component.html +++ b/client/src/app/instance/search/components/criteria/criteria-by-family.component.html @@ -4,6 +4,7 @@ [criterion]="getCriterion(attribute.id)" [criteriaList]="criteriaList" (addCriterion)="emitAdd($event)" + (updateCriterion)="emitUpdate($event)" (deleteCriterion)="emitDelete($event)"> </app-criterion> </div> diff --git a/client/src/app/instance/search/components/criteria/criteria-by-family.component.ts b/client/src/app/instance/search/components/criteria/criteria-by-family.component.ts index edc3ae5c..fa8c7617 100644 --- a/client/src/app/instance/search/components/criteria/criteria-by-family.component.ts +++ b/client/src/app/instance/search/components/criteria/criteria-by-family.component.ts @@ -25,6 +25,7 @@ export class CriteriaByFamilyComponent { @Input() attributeList: Attribute[]; @Input() criteriaList: Criterion[]; @Output() addCriterion: EventEmitter<Criterion> = new EventEmitter(); + @Output() updateCriterion: EventEmitter<Criterion> = new EventEmitter(); @Output() deleteCriterion: EventEmitter<number> = new EventEmitter(); /** @@ -60,6 +61,17 @@ export class CriteriaByFamilyComponent { this.addCriterion.emit(criterion); } + /** + * Emits event to update the given criterion to the criteria list. + * + * @param {Criterion} updatedCriterion - The updated criterion. + * + * @fires EventEmitter<Criterion> + */ + emitUpdate(updatedCriterion: Criterion): void { + this.updateCriterion.emit(updatedCriterion); + } + /** * Emits event to remove the given criterion ID from the criteria list. * diff --git a/client/src/app/instance/search/components/criteria/criteria-tabs.component.html b/client/src/app/instance/search/components/criteria/criteria-tabs.component.html index fa9d3aef..da39e682 100644 --- a/client/src/app/instance/search/components/criteria/criteria-tabs.component.html +++ b/client/src/app/instance/search/components/criteria/criteria-tabs.component.html @@ -17,6 +17,7 @@ [attributeList]="attributeList | attributeListByFamily:family.id" [criteriaList]="criteriaList" (addCriterion)="emitAdd($event)" + (updateCriterion)="emitUpdate($event)" (deleteCriterion)="emitDelete($event)"> </app-criteria-by-family> </accordion-group> diff --git a/client/src/app/instance/search/components/criteria/criteria-tabs.component.ts b/client/src/app/instance/search/components/criteria/criteria-tabs.component.ts index f781372a..a11d3b6b 100644 --- a/client/src/app/instance/search/components/criteria/criteria-tabs.component.ts +++ b/client/src/app/instance/search/components/criteria/criteria-tabs.component.ts @@ -26,6 +26,7 @@ export class CriteriaTabsComponent { @Input() criteriaFamilyList: CriteriaFamily[]; @Input() criteriaList: Criterion[]; @Output() addCriterion: EventEmitter<Criterion> = new EventEmitter(); + @Output() updateCriterion: EventEmitter<Criterion> = new EventEmitter(); @Output() deleteCriterion: EventEmitter<number> = new EventEmitter(); /** @@ -39,6 +40,17 @@ export class CriteriaTabsComponent { this.addCriterion.emit(criterion); } + /** + * Emits event to update the given criterion to the criteria list. + * + * @param {Criterion} updatedCriterion - The updated criterion. + * + * @fires EventEmitter<Criterion> + */ + emitUpdate(updatedCriterion: Criterion): void { + this.updateCriterion.emit(updatedCriterion); + } + /** * Emits event to remove the given criterion ID to the criteria list. * diff --git a/client/src/app/instance/search/components/criteria/criterion.component.ts b/client/src/app/instance/search/components/criteria/criterion.component.ts index 245f6fba..599cb54e 100644 --- a/client/src/app/instance/search/components/criteria/criterion.component.ts +++ b/client/src/app/instance/search/components/criteria/criterion.component.ts @@ -22,6 +22,7 @@ export class CriterionComponent implements OnInit, OnChanges { @Input() criterion: Criterion; @Input() criteriaList: Criterion[]; @Output() addCriterion: EventEmitter<Criterion> = new EventEmitter(); + @Output() updateCriterion: EventEmitter<Criterion> = new EventEmitter(); @Output() deleteCriterion: EventEmitter<number> = new EventEmitter(); @ViewChild(SearchTypeLoaderDirective, {static: true}) SearchTypeLoaderDirective!: SearchTypeLoaderDirective; @@ -30,12 +31,14 @@ export class CriterionComponent implements OnInit, OnChanges { ngOnInit() { const viewContainerRef = this.SearchTypeLoaderDirective.viewContainerRef; + viewContainerRef.clear(); const componentRef = viewContainerRef.createComponent<AbstractSearchTypeComponent>( getSearchTypeComponent(this.attribute.search_type) ); componentRef.instance.setAttribute(this.attribute); componentRef.instance.setCriterion(this.criterion); componentRef.instance.setCriteriaList(this.criteriaList); + componentRef.instance.emitAdd.subscribe(() => this.emitAdd()); this.searchTypeComponent = componentRef.instance; } @@ -65,6 +68,10 @@ export class CriterionComponent implements OnInit, OnChanges { } else { criterion = this.searchTypeComponent.getCriterion(); } - this.addCriterion.emit(criterion); + if (this.criteriaList.find(c => c.id === criterion.id)) { + this.updateCriterion.emit(criterion); + } else { + this.addCriterion.emit(criterion); + } } } diff --git a/client/src/app/instance/search/components/criteria/search-type/abstract-search-type.component.ts b/client/src/app/instance/search/components/criteria/search-type/abstract-search-type.component.ts index 2ef2b50d..0cbffda6 100644 --- a/client/src/app/instance/search/components/criteria/search-type/abstract-search-type.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/abstract-search-type.component.ts @@ -7,17 +7,19 @@ * file that was distributed with this source code. */ -import { Directive } from '@angular/core'; +import { Directive, Output, EventEmitter, OnInit } from '@angular/core'; import { UntypedFormGroup } from '@angular/forms'; import { Attribute } from 'src/app/metamodel/models'; import { Criterion } from 'src/app/instance/store/models'; import { searchTypeOperators } from 'src/app/shared/utils'; +import { debounceTime, distinctUntilChanged } from 'rxjs'; @Directive() -export abstract class AbstractSearchTypeComponent { +export abstract class AbstractSearchTypeComponent implements OnInit { attribute: Attribute; criteriaList: Criterion[]; + emitAdd: EventEmitter<{}> = new EventEmitter<{}>(); form: UntypedFormGroup; operators = searchTypeOperators; @@ -25,6 +27,13 @@ export abstract class AbstractSearchTypeComponent { constructor() { } + ngOnInit() { + this.form.valueChanges.pipe( + debounceTime(1000) + ) + .subscribe(() => (this.form.valid) ? this.emitAdd.emit() : null); + } + setAttribute(attribute: Attribute) { this.attribute = attribute; } diff --git a/client/src/app/instance/search/containers/criteria.component.html b/client/src/app/instance/search/containers/criteria.component.html index 41898acc..6b3e0fe3 100644 --- a/client/src/app/instance/search/containers/criteria.component.html +++ b/client/src/app/instance/search/containers/criteria.component.html @@ -34,6 +34,7 @@ [criteriaFamilyList]="criteriaFamilyList | async" [criteriaList]="criteriaList | async" (addCriterion)="addCriterion($event)" + (updateCriterion)="updateCriterion($event)" (deleteCriterion)="deleteCriterion($event)"> </app-criteria-tabs> </div> diff --git a/client/src/app/instance/search/containers/criteria.component.ts b/client/src/app/instance/search/containers/criteria.component.ts index b850069b..1320c1df 100644 --- a/client/src/app/instance/search/containers/criteria.component.ts +++ b/client/src/app/instance/search/containers/criteria.component.ts @@ -71,6 +71,15 @@ export class CriteriaComponent extends AbstractSearchComponent { this.store.dispatch(searchActions.addCriterion({ criterion })); } + /** + * Dispatches action to update the given criterion to the search. + * + * @param {Criterion} updatedCriterion - The updated criterion. + */ + updateCriterion(updatedCriterion: Criterion): void { + this.store.dispatch(searchActions.updateCriterion({ updatedCriterion })) + } + /** * Dispatches action to remove the given criterion ID to the search. * diff --git a/client/src/app/instance/store/actions/search.actions.ts b/client/src/app/instance/store/actions/search.actions.ts index 86333f65..51cd7a03 100644 --- a/client/src/app/instance/store/actions/search.actions.ts +++ b/client/src/app/instance/store/actions/search.actions.ts @@ -24,6 +24,7 @@ export const checkOutput = createAction('[Search] Check Output'); export const checkResult = createAction('[Search] Check Result'); export const updateCriteriaList = createAction('[Search] Update Criteria List', props<{ criteriaList: Criterion[] }>()); export const addCriterion = createAction('[Search] Add Criterion', props<{ criterion: Criterion }>()); +export const updateCriterion = createAction('[Search] Update Criterion', props<{ updatedCriterion: Criterion }>()); export const deleteCriterion = createAction('[Search] Delete Criterion', props<{ idCriterion: number }>()); export const updateOutputList = createAction('[Search] Update Output List', props<{ outputList: number[] }>()); export const retrieveDataLength = createAction('[Search] Retrieve Data Length'); diff --git a/client/src/app/instance/store/reducers/search.reducer.ts b/client/src/app/instance/store/reducers/search.reducer.ts index e81da507..acceaacc 100644 --- a/client/src/app/instance/store/reducers/search.reducer.ts +++ b/client/src/app/instance/store/reducers/search.reducer.ts @@ -93,6 +93,12 @@ export const searchReducer = createReducer( ...state, criteriaList: [...state.criteriaList, criterion] })), + on(searchActions.updateCriterion, (state, { updatedCriterion }) => ({ + ...state, + criteriaList: state.criteriaList.map( + criterion => (criterion.id === updatedCriterion.id) ? updatedCriterion : criterion + ) + })), on(searchActions.deleteCriterion, (state, { idCriterion }) => ({ ...state, criteriaList: [...state.criteriaList.filter(c => c.id !== idCriterion)] -- GitLab