From 1b0b4e6c9285775e0253b6d5877f8814f46cc02c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Agneray?= <francois.agneray@lam.fr>
Date: Thu, 12 May 2022 18:04:39 +0200
Subject: [PATCH] Refactor search_types

---
 .../abstract-search-type.component.ts         |   3 +
 .../criteria-by-family.component.html         | 127 +-----------------
 .../criteria/criterion.component.html         |  16 +++
 .../criteria/criterion.component.ts           |  44 ++++++
 .../search/components/criteria/index.ts       |   6 +
 .../criteria/search-type-loader.directive.ts  |   8 ++
 .../criteria/search-type/field.component.html |  46 ++-----
 .../criteria/test-search-type.component.ts    |  10 ++
 8 files changed, 105 insertions(+), 155 deletions(-)
 create mode 100644 client/src/app/instance/search/components/criteria/abstract-search-type.component.ts
 create mode 100644 client/src/app/instance/search/components/criteria/criterion.component.html
 create mode 100644 client/src/app/instance/search/components/criteria/criterion.component.ts
 create mode 100644 client/src/app/instance/search/components/criteria/search-type-loader.directive.ts
 create mode 100644 client/src/app/instance/search/components/criteria/test-search-type.component.ts

diff --git a/client/src/app/instance/search/components/criteria/abstract-search-type.component.ts b/client/src/app/instance/search/components/criteria/abstract-search-type.component.ts
new file mode 100644
index 00000000..3f2f3168
--- /dev/null
+++ b/client/src/app/instance/search/components/criteria/abstract-search-type.component.ts
@@ -0,0 +1,3 @@
+export interface AbstractSearchTypeComponent {
+    data: any;
+}
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 72eba5b8..cdf6dbf0 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
@@ -1,123 +1,8 @@
 <div *ngFor="let attribute of attributeList">
-    <div [ngSwitch]="attribute.search_type">
-        <div *ngSwitchCase="'field'">
-            <app-field 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-field>
-        </div>
-        <div *ngSwitchCase="'between'">
-            <app-between 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-between>
-        </div>
-        <div *ngSwitchCase="'select'">
-            <app-select 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-select>
-        </div>
-        <div *ngSwitchCase="'select-multiple'">
-            <app-select-multiple 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-select-multiple>
-        </div>
-        <div *ngSwitchCase="'datalist'">
-            <app-datalist 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-datalist>
-        </div>
-        <div *ngSwitchCase="'list'">
-            <app-list 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-list>
-        </div>
-        <div *ngSwitchCase="'radio'">
-            <app-radio 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-radio>
-        </div>
-        <div *ngSwitchCase="'checkbox'">
-            <app-checkbox 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-checkbox>
-        </div>
-        <div *ngSwitchCase="'date'">
-            <app-date 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-date>
-        </div>
-        <div *ngSwitchCase="'between-date'">
-            <app-between-date 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-between-date>
-        </div>
-        <div *ngSwitchCase="'time'">
-            <app-time 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-time>
-        </div>
-        <div *ngSwitchCase="'date-time'">
-            <app-datetime 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-datetime>
-        </div>
-        <div *ngSwitchCase="'json'">
-            <app-json-criteria 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-json-criteria>
-        </div>
-        <div *ngSwitchCase="'svom_json_kw'">
-            <app-svom-json-kw-criteria 
-                [attribute]="attribute"
-                [criterion]="getCriterion(attribute.id)"
-                [criteriaList]="criteriaList"
-                [svomKeywords]="svomKeywords"
-                (selectSvomAcronym)=selectSvomAcronym.emit($event)
-                (resetSvomKeywords)="resetSvomKeywords.emit()"
-                (addCriterion)="emitAdd($event)"
-                (deleteCriterion)="emitDelete($event)">
-            </app-svom-json-kw-criteria>
-        </div>
-        <div *ngSwitchDefault>
-            {{ attribute.search_type }} search type not supported
-        </div>
-    </div>
+    <app-criterion 
+        [attribute]="attribute"
+        [criterion]="getCriterion(attribute.id)"
+        (addCriterion)="emitAdd($event)"
+        (deleteCriterion)="emitDelete($event)">
+    </app-criterion>
 </div>
diff --git a/client/src/app/instance/search/components/criteria/criterion.component.html b/client/src/app/instance/search/components/criteria/criterion.component.html
new file mode 100644
index 00000000..3a9c1c00
--- /dev/null
+++ b/client/src/app/instance/search/components/criteria/criterion.component.html
@@ -0,0 +1,16 @@
+<div class="row">
+    <div class="col form-group">
+        <label>
+            <app-attribute-label [label]="attribute.label" [description]="attribute.description"></app-attribute-label>
+        </label>
+        <ng-template searchType></ng-template>
+    </div>
+    <div class="col-2 text-center align-self-end pb-3">
+        <!-- <button class="btn btn-outline-success" *ngIf="!criterion" [hidden]="!form.valid && form.controls.operator.value != 'nl' && form.controls.operator.value != 'nnl'" (click)="emitAdd()">
+            <span class="fas fa-plus fa-fw"></span>
+        </button>
+        <button class="btn btn-outline-danger" *ngIf="criterion" (click)="deleteCriterion.emit(attribute.id)">
+            <span class="fa fa-times fa-fw"></span>
+        </button> -->
+    </div>
+</div>
diff --git a/client/src/app/instance/search/components/criteria/criterion.component.ts b/client/src/app/instance/search/components/criteria/criterion.component.ts
new file mode 100644
index 00000000..fc2f97fd
--- /dev/null
+++ b/client/src/app/instance/search/components/criteria/criterion.component.ts
@@ -0,0 +1,44 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, ContentChild } from '@angular/core';
+
+import { Attribute } from 'src/app/metamodel/models';
+import { Criterion } from 'src/app/instance/store/models';
+import { SearchTypeLoaderDirective } from './search-type-loader.directive';
+import { AbstractSearchTypeComponent } from './abstract-search-type.component';
+import { TestSearchTypeComponent } from './test-search-type.component';
+import { FieldComponent } from './search-type/field.component';
+
+@Component({
+    selector: 'app-criterion',
+    templateUrl: 'criterion.component.html'
+})
+export class CriterionComponent {
+    @Input() attribute: Attribute;
+    @Input() criterion: Criterion;
+    @Output() addCriterion: EventEmitter<Criterion> = new EventEmitter();
+    @Output() deleteCriterion: EventEmitter<number> = new EventEmitter();
+
+    @ViewChild(SearchTypeLoaderDirective, {static: true}) searchType!: SearchTypeLoaderDirective;
+
+    ngOnInit() {
+        const componentRef = this.searchType.viewContainerRef.createComponent<AbstractSearchTypeComponent>(TestSearchTypeComponent);
+        componentRef.instance.data = { text: 'Bonjour Yannick !' };
+    }
+
+    /**
+     * Emits event to add criterion to the criteria list.
+     *
+     * @fires EventEmitter<Criterion>
+     */
+    emitAdd(criterion: Criterion): void {
+        this.addCriterion.emit(criterion);
+    }
+}
diff --git a/client/src/app/instance/search/components/criteria/index.ts b/client/src/app/instance/search/components/criteria/index.ts
index 88656ad3..7dd250f7 100644
--- a/client/src/app/instance/search/components/criteria/index.ts
+++ b/client/src/app/instance/search/components/criteria/index.ts
@@ -1,11 +1,17 @@
 import { ConeSearchTabComponent } from './cone-search-tab.component';
 import { CriteriaTabsComponent } from './criteria-tabs.component';
 import { CriteriaByFamilyComponent } from './criteria-by-family.component';
+import { SearchTypeLoaderDirective } from './search-type-loader.directive';
+import { TestSearchTypeComponent } from './test-search-type.component';
+import { CriterionComponent } from './criterion.component';
 import { searchTypeComponents } from './search-type';
 
 export const criteriaComponents = [
     ConeSearchTabComponent,
     CriteriaTabsComponent,
     CriteriaByFamilyComponent,
+    SearchTypeLoaderDirective,
+    TestSearchTypeComponent,
+    CriterionComponent,
     searchTypeComponents
 ];
diff --git a/client/src/app/instance/search/components/criteria/search-type-loader.directive.ts b/client/src/app/instance/search/components/criteria/search-type-loader.directive.ts
new file mode 100644
index 00000000..74d000d5
--- /dev/null
+++ b/client/src/app/instance/search/components/criteria/search-type-loader.directive.ts
@@ -0,0 +1,8 @@
+import { Directive, ViewContainerRef } from '@angular/core';
+
+@Directive({
+    selector: '[searchType]',
+})
+export class SearchTypeLoaderDirective {
+    constructor(public viewContainerRef: ViewContainerRef) { }
+}
diff --git a/client/src/app/instance/search/components/criteria/search-type/field.component.html b/client/src/app/instance/search/components/criteria/search-type/field.component.html
index 99e3af2e..84260fca 100644
--- a/client/src/app/instance/search/components/criteria/search-type/field.component.html
+++ b/client/src/app/instance/search/components/criteria/search-type/field.component.html
@@ -1,39 +1,17 @@
 <form [formGroup]="form" novalidate>
-    <div class="row">
-        <div class="col form-group">
-            <label>
-                <app-attribute-label [label]="attribute.label" [description]="attribute.description"></app-attribute-label>
-            </label>
-            <span *ngIf="attribute.operator === 'lk'" class="pl-1" [tooltip]="helpLike" placement="right" containerClass="custom-tooltip right-tooltip">
-                <span class="far fa-question-circle fa-sm"></span>
-            </span>
-            <div class="row">
-                <div class="col col-sm-auto pr-sm-1 mb-1 mb-sm-0">
-                    <select class="custom-select" formControlName="operator" (change)="operatorOnChange()">
-                        <option *ngFor="let o of operators" [ngValue]="o.value">{{ o.label }}</option>
-                    </select>
-                </div>
-                <div class="w-100 d-block d-sm-none"></div>
-                <div class="col pl-sm-1">
-                    <input [type]="getType()" 
-                        class="form-control" 
-                        [placeholder]="getPlaceholder()" 
-                        formControlName="value"
-                        autocomplete="off">
-                </div>
-            </div>
+    <div class="row form-group">
+        <div class="col col-sm-auto pr-sm-1 mb-1 mb-sm-0">
+            <select class="custom-select" formControlName="operator" (change)="operatorOnChange()">
+                <option *ngFor="let o of operators" [ngValue]="o.value">{{ o.label }}</option>
+            </select>
         </div>
-        <div class="col-2 text-center align-self-end pb-3">
-            <button class="btn btn-outline-success" *ngIf="!criterion" [hidden]="!form.valid && form.controls.operator.value != 'nl' && form.controls.operator.value != 'nnl'" (click)="emitAdd()">
-                <span class="fas fa-plus fa-fw"></span>
-            </button>
-            <button class="btn btn-outline-danger" *ngIf="criterion" (click)="deleteCriterion.emit(attribute.id)">
-                <span class="fa fa-times fa-fw"></span>
-            </button>
+        <div class="w-100 d-block d-sm-none"></div>
+        <div class="col pl-sm-1">
+            <input [type]="getType()" 
+                class="form-control" 
+                [placeholder]="getPlaceholder()" 
+                formControlName="value"
+                autocomplete="off">
         </div>
     </div>
 </form>
-
-<ng-template #helpLike>
-    <app-help-like></app-help-like>
-</ng-template>
\ No newline at end of file
diff --git a/client/src/app/instance/search/components/criteria/test-search-type.component.ts b/client/src/app/instance/search/components/criteria/test-search-type.component.ts
new file mode 100644
index 00000000..72d3aefa
--- /dev/null
+++ b/client/src/app/instance/search/components/criteria/test-search-type.component.ts
@@ -0,0 +1,10 @@
+import { Component, Input } from '@angular/core';
+import { AbstractSearchTypeComponent } from './abstract-search-type.component';
+
+@Component({
+    selector: 'app-test-search-type',
+    template: '<p>{{ data.text }}</p>'
+})
+export class TestSearchTypeComponent implements AbstractSearchTypeComponent {
+    @Input() data: any;
+}
-- 
GitLab