From 93d13d981ef233c5bc21a3427ac1965c47a2a47f Mon Sep 17 00:00:00 2001
From: "mathias.chouet" <mathias.chouet@irstea.fr>
Date: Tue, 25 Aug 2020 09:40:32 +0200
Subject: [PATCH] Fix #428 - search engine above calculators list

---
 .../calculator-list.component.html            | 16 ++++++--
 .../calculator-list.component.scss            | 13 +++++++
 .../calculator-list.component.ts              | 39 +++++++++++++++++--
 3 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/src/app/components/calculator-list/calculator-list.component.html b/src/app/components/calculator-list/calculator-list.component.html
index 904c6d994..755776307 100644
--- a/src/app/components/calculator-list/calculator-list.component.html
+++ b/src/app/components/calculator-list/calculator-list.component.html
@@ -1,6 +1,16 @@
+<div id="header-search">
+    <form id="search-modules">
+        <mat-form-field>
+            <mat-icon matPrefix>search</mat-icon>
+            <input type="search" matInput name="searchTerms" [(ngModel)]="searchTerms" (input)="filterItems()"
+                (keydown.escape)="resetSearch()">
+        </mat-form-field>
+    </form>
+</div>
+
 <div class="container" fxLayout="row wrap" fxLayoutAlign="space-evenly stretch" (konami)="onKC()">
 
-    <mat-card class="welcome-card" *ngIf="nbOpenCalculators === 0">
+    <mat-card class="welcome-card" *ngIf="nbOpenCalculators === 0 && searchTerms === ''">
 
         <mat-card-header>
             <mat-card-title>{{ uitextWelcomeTitle }}</mat-card-title>
@@ -16,7 +26,7 @@
 
     </mat-card>
 
-    <mat-card *ngFor="let theme of items" class="compute-nodes-theme">
+    <mat-card *ngFor="let theme of filteredItems" class="compute-nodes-theme">
 
         <mat-card-header>
             <mat-card-title>{{ theme.title }}</mat-card-title>
@@ -44,7 +54,7 @@
 
     </mat-card>
 
-    <mat-card class="examples-card" *ngIf="nbOpenCalculators === 0">
+    <mat-card class="examples-card" *ngIf="nbOpenCalculators === 0 && searchTerms === ''">
 
         <mat-card-header>
             <mat-card-title>{{ uitextExamplesTitle }}</mat-card-title>
diff --git a/src/app/components/calculator-list/calculator-list.component.scss b/src/app/components/calculator-list/calculator-list.component.scss
index 0ad0e0313..665a2b38c 100644
--- a/src/app/components/calculator-list/calculator-list.component.scss
+++ b/src/app/components/calculator-list/calculator-list.component.scss
@@ -60,3 +60,16 @@ a.load-example {
     cursor: pointer;
     padding-top: 1px;
 }
+
+#header-search {
+    width: 100%;
+    text-align: center;
+
+    mat-form-field {
+        width: 280px;
+
+        mat-icon {
+            vertical-align: bottom;
+        }
+    }
+}
diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts
index e3c286fbe..51c7563a5 100644
--- a/src/app/components/calculator-list/calculator-list.component.ts
+++ b/src/app/components/calculator-list/calculator-list.component.ts
@@ -22,8 +22,14 @@ import { ApplicationSetupService } from "../../services/app-setup.service";
     styleUrls: ["./calculator-list.component.scss"]
 })
 export class CalculatorListComponent implements OnInit {
+
     private _items: any[];
 
+    public filteredItems: any[];
+
+    /** what is typed into the search field in the nav bar */
+    public searchTerms: string;
+
     constructor(
         @Inject(forwardRef(() => AppComponent)) private appComponent: AppComponent,
         private router: Router,
@@ -33,6 +39,8 @@ export class CalculatorListComponent implements OnInit {
     ) {
         ServiceFactory.i18nService.addObserver(this);
         ServiceFactory.applicationSetupService.addObserver(this);
+
+        this.searchTerms = "";
     }
 
     /** triggered on init */
@@ -104,6 +112,9 @@ export class CalculatorListComponent implements OnInit {
                 } // else the only remaining calculator was "Structure", the one we don't want
             }
         }
+
+        // at first there is no filter, initialize anyway
+        this.filterItems();
     }
 
     public create(t: CalculatorType) {
@@ -159,8 +170,30 @@ export class CalculatorListComponent implements OnInit {
         return Session.getInstance().getNumberOfNubs();
     }
 
-    public get items() {
-        return this._items;
+    public resetSearch() {
+        this.searchTerms = "";
+        this.filterItems();
+    }
+
+    /**
+     * Returns calculators grouped by themes, filtered by the search
+     * terms entered in the navbar's search field in AppComponent
+     */
+    public filterItems() {
+        if (this.searchTerms === "") {
+            this.filteredItems = this._items;
+        } else {
+            this.filteredItems = JSON.parse(JSON.stringify(this._items));
+            // filter items based on parent component's search field
+            for (const i of this.filteredItems) {
+                i.calculators = i.calculators.filter((c) => {
+                    return (c.label.toLowerCase().includes(this.searchTerms.toLowerCase()));
+                });
+            }
+            this.filteredItems = this.filteredItems.filter((i) => {
+                return (i.calculators.length > 0);
+            });
+        }
     }
 
     /**
@@ -226,7 +259,7 @@ export class CalculatorListComponent implements OnInit {
     }
 
     public onKC() {
-        for (const i of this.items) {
+        for (const i of this._items) {
             const img = [ "assets/images/themes/sp.jpg", "assets/images/themes/autres.jpg" ];
             const idx = Math.floor(Math.random() * 2);
             i.image.path = img[idx];
-- 
GitLab