From aa9bb74fc60d8ac6f1851d735cf9ec23d96f26ed Mon Sep 17 00:00:00 2001
From: "Hurtado, Iker (ikerh)" <iker.hurtado@bsc.es>
Date: Sat, 27 Oct 2018 20:45:25 +0200
Subject: [PATCH] Properties search filter integration

---
 client/bundle.js                           | 114 +++++++++------------
 client/css/styles.css                      |   4 +-
 client/src/search-mod/MaterialList.view.js |  48 +++++----
 client/src/search-mod/NewSearchMod.js      |  66 ++++--------
 4 files changed, 99 insertions(+), 133 deletions(-)

diff --git a/client/bundle.js b/client/bundle.js
index dcd3298f..a908f867 100644
--- a/client/bundle.js
+++ b/client/bundle.js
@@ -7796,11 +7796,7 @@
 	        this.materialNameBox.disable(true);
 	      }
 	    });
-	    /*
-	        this.propertiesBox= new PropertiesBox();
-	        this.propertiesBox.setAddPropertiesListener(propsMap => {
-	          this.addPropertiesInSearchQuery(propsMap);
-	        });*/
+
 
 	    this.filterPanel = new FilterPanel();
 	    this.filterSidePanel.appendChild(this.filterPanel.element);
@@ -7826,7 +7822,7 @@
 	      if (this.searchQuery.lenght === 0){
 	        util.showUserMsg('No query');
 	      }else{
-	        let rootQueryObj;
+	        let searchExpressionQuery;
 
 	        //************** Material name or complex search expression
 	        //if (this.queryTypes[i] === 'MN'){
@@ -7834,18 +7830,15 @@
 
 
 	        if (this.element.querySelector('#allow-other-elements').checked)
-	          rootQueryObj = this._getESQueryFromSearchQuery_otherElements(
+	          searchExpressionQuery = this._getESQueryFromSearchQuery_otherElements(
 	            this.searchQuery, this.queryTypes);
 	        // Regular case: search containing only the elements in the search expression
-	        else rootQueryObj =
+	        else searchExpressionQuery =
 	            this._getESQueryFromSearchQuery(this.searchQuery, this.queryTypes);
 
-
-	        /* Pending to ADD *************/
-	        //let filterMap = this.filterPanel.getValues();
-	        //this._addFiltersInSearchQuery(filterMap, queryObj);
-
-	        this.materialList.initSearch(rootQueryObj);
+	        this.materialList.initSearch(
+	          this._addFiltersInSearchQuery( this.filterPanel.getValues(),
+	            searchExpressionQuery));
 	        //util.setBrowserHashPath('search','results');
 
 	        this.element.querySelector('.add-box').style.display = 'none';
@@ -7877,7 +7870,7 @@
 	          if (selectingTab === 'element')
 	            selectingElement = this.elementTable.element;
 	          else if (selectingTab === 'name')
-	            selectingElement = this.materialNameBox.element;//this.propertiesBox.element;
+	            selectingElement = this.materialNameBox.element;
 	          else if (selectingTab === 'formula')
 	            selectingElement = this.formulaBox.element;
 
@@ -8081,30 +8074,37 @@
 
 
 
-	  _addFiltersInSearchQuery(filterMap, queryFilterArray){
-	    //let filters = [];
+	  _addFiltersInSearchQuery(filterMap, searchExpressionQuery){
+	    let rootQueryObj = { 'bool' : {} };
+	    rootQueryObj.bool.must = [];
+	    rootQueryObj.bool.must.push( searchExpressionQuery );
+
+
 	    filterMap.forEach((values/*Array*/, filterName) => {
 
 	      let filterNameDef = replaceDashes(filterName);
 
 	      if (filterName === 'mass-density' || filterName === 'band-gap'){
 	        //***** util.eV2J() apply?
-	        queryFilterArray.push( this._getFieldESRange(filterNameDef, values) );
+	        rootQueryObj.bool.must.push( this._getFieldESRange(filterNameDef, values) );
 
 	      }else if (filterName === 'band-gap-type'){ // special case
 	        if ( values !== 'both')
-	          queryFilterArray.push( this._getESSimpleMatch('band_gap_direct',
+	          rootQueryObj.bool.must.push( this._getESSimpleMatch('band_gap_direct',
 	            ( values === 'direct' ? true : false ) ) );
 
 	      }else if (filterName.startsWith('has')){ // has- filters
-	        queryFilterArray.push( this._getESSimpleMatch(filterNameDef, values, false) );
+	        rootQueryObj.bool.must.push( this._getESSimpleMatch(filterNameDef, values, false) );
 
 	      }else{ // normal case
-	        queryFilterArray.push( this._getESOperatorMatch(filterNameDef, values, false) );
+	        rootQueryObj.bool.must.push( this._getESOperatorMatch(filterNameDef, values, false) );
+	        console.log(this._getESOperatorMatch(filterNameDef, values, false) );
 	      }
 
 	    });
-	    //return filters;
+
+
+	    return rootQueryObj;
 	  }
 
 
@@ -8201,28 +8201,6 @@
 	    //this._showSearchBox();
 	  }
 
-	/*
-	  addPropertiesInSearchQuery(propsMap){
-	    propsMap.forEach((values, propName) => {
-	      let i = this.queryTypes.indexOf(propName);
-	      if (i < 0)
-	        this.addTagInSearchQuery(values.join(' | '), propName);
-	      else{
-	        let currentValues = this.searchQuery[i].split(' | ');
-	        //console.log('Current VAlues: ',currentValues);
-	        values.forEach(value => {
-	          if (currentValues.indexOf(value) < 0) currentValues.push(value);
-	        });
-	        this.searchQuery[i] = currentValues.join(' | ');
-	        this.updateSearchQuery();
-	        //this._showSearchBox();
-	      }
-	    });
-	  }*/
-
-
-
-
 
 	  removeElementORFormulaInSearchQuery(item){
 	    //console.log(" removeElementORFormulaInSearchQuery item: ",item, this.searchQuery.indexOf(item));
@@ -9285,7 +9263,6 @@
 	      let systemData = this.matMap.get(this.currentSystemType);
 	      if (systemData.page === systemData.totalPages) return;
 	      systemData.page++;
-	      console.log('nextButton page:', systemData.page);
 	      this._paginationSearch();
 	    });
 
@@ -9293,7 +9270,6 @@
 	      let systemData = this.matMap.get(this.currentSystemType);
 	      if (systemData.page === 1) return;
 	      systemData.page--;
-	      console.log('nextButton page:', systemData.page);
 	      this._paginationSearch();
 	    });
 
@@ -9325,7 +9301,7 @@
 	    let req = util.serverReqPOST(util.getSearchURL()+'?page='+page+
 	            '&per_page='+RESULTS_PER_PAGE, JSON.stringify(this.esQueryObject), e => {
 
-	      let data = JSON.parse(e.target.response);  console.log('GETTING: ', data);
+	      let data = JSON.parse(e.target.response);
 
 	      this.matMap.set(this.currentSystemType, this._createSystemTypeData(data, page, true));
 	      //console.log('this.matMap: ', this.matMap);
@@ -9335,17 +9311,21 @@
 	  }
 
 
-	  initSearch(searchJson){
+	  initSearch(rootQueryObj){
 	    //this.resultsContainer.style.visibility = 'hidden';
 	    this.matMap.clear();
-
+	    this.currentSystemType = 'bulk';
+	/*
 	    let rootQueryObj = { 'bool' : {} };
 	    rootQueryObj.bool.must = [];
 	    rootQueryObj.bool.must.push( searchJson );
 	    rootQueryObj.bool.must.push( { "match": {"system_type" : "bulk"} } );
+	    */
+	    rootQueryObj.bool.must.push( { "match": {"system_type" : "bulk"} } );
+	    let systemTypePosition = rootQueryObj.bool.must.length-1;
 	    this.esQueryObject = rootQueryObj;
 
-	    console.log('SENDING: ', JSON.stringify(rootQueryObj));
+	    console.log('SENDING: ', JSON.stringify(rootQueryObj)); console.log(': ', rootQueryObj.bool.must);
 
 
 	    LoadingPopup.show();
@@ -9358,33 +9338,33 @@
 	      let bulkData = JSON.parse(bulke.target.response);  console.log('GETTING: ', bulkData);
 
 	      this.matMap.set('bulk', this._createSystemTypeData(bulkData, 1, bulke.target.status === 200));
-	      console.log('this.matMap: ', this.matMap);
 
 
 	      // 2D materials request
-	      rootQueryObj.bool.must[1].match.system_type = '2D';
-	      console.log('SENDING: ', JSON.stringify(rootQueryObj));
+	      rootQueryObj.bool.must[systemTypePosition].match.system_type = '2D';
 	      let twoDReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
 	              '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), twoDe => {
 
 	        let twoDData = JSON.parse(twoDe.target.response);
 
 	        this.matMap.set('2D', this._createSystemTypeData(twoDData, 1, twoDe.target.status === 200));
-	        console.log('this.matMap: ', this.matMap);
 
 
 	        // 1D materials request
-	        rootQueryObj.bool.must[1].match.system_type = '1D';
-	        console.log('SENDING: ', JSON.stringify(rootQueryObj));
+	        rootQueryObj.bool.must[systemTypePosition].match.system_type = '1D';
 	        let oneDReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
 	                '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), oneDe => {
 
 	          let oneDData = JSON.parse(oneDe.target.response);
 
 	          this.matMap.set('1D', this._createSystemTypeData(oneDData, 1, oneDe.target.status === 200));
-	          console.log('this.matMap: ', this.matMap);
 
-	          this._updateUI('bulk');
+	          this._updateUI(this.currentSystemType);
+	          this.matMap.forEach( (materials, systemType) => {
+	            this.element.querySelector('#system-tab-'+systemType).disabled =
+	              (materials.total === 0);
+	          });
+
 	          //this.resultsContainer.style.visibility = 'visible';
 	          LoadingPopup.hide();
 	          this._launchMaterialViewerIfOnlyOne();
@@ -9449,8 +9429,7 @@
 	  _updateUI(systemType){
 
 	    let systemData = this.matMap.get(systemType);
-	    console.log('_updateUI',systemType, systemData);
-
+	    //console.log('_updateUI',systemType, systemData);
 	    this.titleBox.innerHTML= 'Results (total: '+systemData.total+')';
 	    this.pageElement.innerHTML= 'page '+systemData.page+' / '+systemData.totalPages;
 
@@ -9472,12 +9451,13 @@
 	        <table>
 	          <thead> <tr>
 	            <th style="width: 24%;"></th>
-	            <th style="width: 20%;">
-	              <span info-sys-data="system-type">System type</span>
-	            </th>
 	            <th style="width: 16%;">
 	              <span info-sys-data="space-group">Space group</span>
 	            </th>
+	            <th style="width: 20%;">
+	              <span >Space gr. int. symbol</span>
+	            </th>
+
 	            <th style="width: 22%;">
 	              <span info-sys-data="structure-type">Structure type</span>
 	            </th>
@@ -9500,12 +9480,14 @@
 	          html+=
 	          `<tr class="mat-row" data-mat-id="${mat.id}">
 	            <td  > ${label} [${mat.formula}] </td>
-	            <td style="text-align:center" >
-	              <!--<span info-sys-data="system-type">-->${mat.system_type} <!--</span>-->
-	            </td>
 	            <td style="text-align:center" >
 	              ${mat.space_group_number === null ? '' : mat.space_group_number}
 	            </td>
+	            <td>
+	              ${mat.space_group_international_short_symbol === null ? '' :
+	                mat.space_group_international_short_symbol}
+	            </td>
+
 	            <td> ${mat.structure_type === null ? '' : mat.structure_type } </td>
 	            <td style="text-align:center" > ${mat.nr_of_calculations} </td>
 	          </tr>`;
diff --git a/client/css/styles.css b/client/css/styles.css
index ef01996f..1e551bc6 100644
--- a/client/css/styles.css
+++ b/client/css/styles.css
@@ -635,9 +635,11 @@ div#specialRows{margin: 30px 40px;}
 
 #matlist{ width: 742px; margin: 40px auto 40px;}
 
-#system-type-tabs{width: 100%; }
+#system-type-tabs{ width: 100%; }
 #system-type-tabs button{ font-size: 1.2em; }
 #system-type-tabs button.selected { color: #E56400;}
+#system-type-tabs button:disabled { color: #BBB; cursor: default}
+
 span.results-total { float: right;}
 
 /* #paginationWg erased*/
diff --git a/client/src/search-mod/MaterialList.view.js b/client/src/search-mod/MaterialList.view.js
index 22145c60..3c8eb209 100644
--- a/client/src/search-mod/MaterialList.view.js
+++ b/client/src/search-mod/MaterialList.view.js
@@ -103,7 +103,6 @@ class MaterialList {
       let systemData = this.matMap.get(this.currentSystemType);
       if (systemData.page === systemData.totalPages) return;
       systemData.page++;
-      console.log('nextButton page:', systemData.page);
       this._paginationSearch();
     });
 
@@ -111,7 +110,6 @@ class MaterialList {
       let systemData = this.matMap.get(this.currentSystemType);
       if (systemData.page === 1) return;
       systemData.page--;
-      console.log('nextButton page:', systemData.page);
       this._paginationSearch();
     });
 
@@ -143,7 +141,7 @@ class MaterialList {
     let req = util.serverReqPOST(util.getSearchURL()+'?page='+page+
             '&per_page='+RESULTS_PER_PAGE, JSON.stringify(this.esQueryObject), e => {
 
-      let data = JSON.parse(e.target.response);  console.log('GETTING: ', data);
+      let data = JSON.parse(e.target.response);
 
       this.matMap.set(this.currentSystemType, this._createSystemTypeData(data, page, true));
       //console.log('this.matMap: ', this.matMap);
@@ -153,17 +151,21 @@ class MaterialList {
   }
 
 
-  initSearch(searchJson){
+  initSearch(rootQueryObj){
     //this.resultsContainer.style.visibility = 'hidden';
     this.matMap.clear();
-
+    this.currentSystemType = 'bulk';
+/*
     let rootQueryObj = { 'bool' : {} };
     rootQueryObj.bool.must = [];
     rootQueryObj.bool.must.push( searchJson );
     rootQueryObj.bool.must.push( { "match": {"system_type" : "bulk"} } );
+    */
+    rootQueryObj.bool.must.push( { "match": {"system_type" : "bulk"} } );
+    let systemTypePosition = rootQueryObj.bool.must.length-1;
     this.esQueryObject = rootQueryObj;
 
-    console.log('SENDING: ', JSON.stringify(rootQueryObj));
+    console.log('SENDING: ', JSON.stringify(rootQueryObj)); console.log(': ', rootQueryObj.bool.must);
 
 
     LoadingPopup.show();
@@ -176,33 +178,33 @@ class MaterialList {
       let bulkData = JSON.parse(bulke.target.response);  console.log('GETTING: ', bulkData);
 
       this.matMap.set('bulk', this._createSystemTypeData(bulkData, 1, bulke.target.status === 200));
-      console.log('this.matMap: ', this.matMap);
 
 
       // 2D materials request
-      rootQueryObj.bool.must[1].match.system_type = '2D';
-      console.log('SENDING: ', JSON.stringify(rootQueryObj));
+      rootQueryObj.bool.must[systemTypePosition].match.system_type = '2D';
       let twoDReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
               '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), twoDe => {
 
         let twoDData = JSON.parse(twoDe.target.response);
 
         this.matMap.set('2D', this._createSystemTypeData(twoDData, 1, twoDe.target.status === 200));
-        console.log('this.matMap: ', this.matMap);
 
 
         // 1D materials request
-        rootQueryObj.bool.must[1].match.system_type = '1D';
-        console.log('SENDING: ', JSON.stringify(rootQueryObj));
+        rootQueryObj.bool.must[systemTypePosition].match.system_type = '1D';
         let oneDReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
                 '&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), oneDe => {
 
           let oneDData = JSON.parse(oneDe.target.response);
 
           this.matMap.set('1D', this._createSystemTypeData(oneDData, 1, oneDe.target.status === 200));
-          console.log('this.matMap: ', this.matMap);
 
-          this._updateUI('bulk');
+          this._updateUI(this.currentSystemType);
+          this.matMap.forEach( (materials, systemType) => {
+            this.element.querySelector('#system-tab-'+systemType).disabled =
+              (materials.total === 0);
+          });
+
           //this.resultsContainer.style.visibility = 'visible';
           LoadingPopup.hide();
           this._launchMaterialViewerIfOnlyOne();
@@ -267,8 +269,7 @@ class MaterialList {
   _updateUI(systemType){
 
     let systemData = this.matMap.get(systemType);
-    console.log('_updateUI',systemType, systemData);
-
+    //console.log('_updateUI',systemType, systemData);
     this.titleBox.innerHTML= 'Results (total: '+systemData.total+')';
     this.pageElement.innerHTML= 'page '+systemData.page+' / '+systemData.totalPages;
 
@@ -290,12 +291,13 @@ class MaterialList {
         <table>
           <thead> <tr>
             <th style="width: 24%;"></th>
-            <th style="width: 20%;">
-              <span info-sys-data="system-type">System type</span>
-            </th>
             <th style="width: 16%;">
               <span info-sys-data="space-group">Space group</span>
             </th>
+            <th style="width: 20%;">
+              <span >Space gr. int. symbol</span>
+            </th>
+
             <th style="width: 22%;">
               <span info-sys-data="structure-type">Structure type</span>
             </th>
@@ -318,12 +320,14 @@ class MaterialList {
           html+=
           `<tr class="mat-row" data-mat-id="${mat.id}">
             <td  > ${label} [${mat.formula}] </td>
-            <td style="text-align:center" >
-              <!--<span info-sys-data="system-type">-->${mat.system_type} <!--</span>-->
-            </td>
             <td style="text-align:center" >
               ${mat.space_group_number === null ? '' : mat.space_group_number}
             </td>
+            <td>
+              ${mat.space_group_international_short_symbol === null ? '' :
+                mat.space_group_international_short_symbol}
+            </td>
+
             <td> ${mat.structure_type === null ? '' : mat.structure_type } </td>
             <td style="text-align:center" > ${mat.nr_of_calculations} </td>
           </tr>`;
diff --git a/client/src/search-mod/NewSearchMod.js b/client/src/search-mod/NewSearchMod.js
index b7018bdd..800132d2 100644
--- a/client/src/search-mod/NewSearchMod.js
+++ b/client/src/search-mod/NewSearchMod.js
@@ -191,11 +191,7 @@ class NewSearchMod {
         this.materialNameBox.disable(true);
       }
     });
-    /*
-        this.propertiesBox= new PropertiesBox();
-        this.propertiesBox.setAddPropertiesListener(propsMap => {
-          this.addPropertiesInSearchQuery(propsMap);
-        });*/
+
 
     this.filterPanel = new FilterPanel();
     this.filterSidePanel.appendChild(this.filterPanel.element);
@@ -221,7 +217,7 @@ class NewSearchMod {
       if (this.searchQuery.lenght === 0){
         util.showUserMsg('No query');
       }else{
-        let rootQueryObj;
+        let searchExpressionQuery;
 
         //************** Material name or complex search expression
         //if (this.queryTypes[i] === 'MN'){
@@ -229,18 +225,15 @@ class NewSearchMod {
 
 
         if (this.element.querySelector('#allow-other-elements').checked)
-          rootQueryObj = this._getESQueryFromSearchQuery_otherElements(
+          searchExpressionQuery = this._getESQueryFromSearchQuery_otherElements(
             this.searchQuery, this.queryTypes);
         // Regular case: search containing only the elements in the search expression
-        else rootQueryObj =
+        else searchExpressionQuery =
             this._getESQueryFromSearchQuery(this.searchQuery, this.queryTypes);
 
-
-        /* Pending to ADD *************/
-        //let filterMap = this.filterPanel.getValues();
-        //this._addFiltersInSearchQuery(filterMap, queryObj);
-
-        this.materialList.initSearch(rootQueryObj);
+        this.materialList.initSearch(
+          this._addFiltersInSearchQuery( this.filterPanel.getValues(),
+            searchExpressionQuery));
         //util.setBrowserHashPath('search','results');
 
         this.element.querySelector('.add-box').style.display = 'none';
@@ -272,7 +265,7 @@ class NewSearchMod {
           if (selectingTab === 'element')
             selectingElement = this.elementTable.element;
           else if (selectingTab === 'name')
-            selectingElement = this.materialNameBox.element;//this.propertiesBox.element;
+            selectingElement = this.materialNameBox.element;
           else if (selectingTab === 'formula')
             selectingElement = this.formulaBox.element;
 
@@ -476,30 +469,37 @@ class NewSearchMod {
 
 
 
-  _addFiltersInSearchQuery(filterMap, queryFilterArray){
-    //let filters = [];
+  _addFiltersInSearchQuery(filterMap, searchExpressionQuery){
+    let rootQueryObj = { 'bool' : {} };
+    rootQueryObj.bool.must = [];
+    rootQueryObj.bool.must.push( searchExpressionQuery );
+
+
     filterMap.forEach((values/*Array*/, filterName) => {
 
       let filterNameDef = replaceDashes(filterName);
 
       if (filterName === 'mass-density' || filterName === 'band-gap'){
         //***** util.eV2J() apply?
-        queryFilterArray.push( this._getFieldESRange(filterNameDef, values) );
+        rootQueryObj.bool.must.push( this._getFieldESRange(filterNameDef, values) );
 
       }else if (filterName === 'band-gap-type'){ // special case
         if ( values !== 'both')
-          queryFilterArray.push( this._getESSimpleMatch('band_gap_direct',
+          rootQueryObj.bool.must.push( this._getESSimpleMatch('band_gap_direct',
             ( values === 'direct' ? true : false ) ) );
 
       }else if (filterName.startsWith('has')){ // has- filters
-        queryFilterArray.push( this._getESSimpleMatch(filterNameDef, values, false) );
+        rootQueryObj.bool.must.push( this._getESSimpleMatch(filterNameDef, values, false) );
 
       }else{ // normal case
-        queryFilterArray.push( this._getESOperatorMatch(filterNameDef, values, false) );
+        rootQueryObj.bool.must.push( this._getESOperatorMatch(filterNameDef, values, false) );
+        console.log(this._getESOperatorMatch(filterNameDef, values, false) );
       }
 
     });
-    //return filters;
+
+
+    return rootQueryObj;
   }
 
 
@@ -596,28 +596,6 @@ class NewSearchMod {
     //this._showSearchBox();
   }
 
-/*
-  addPropertiesInSearchQuery(propsMap){
-    propsMap.forEach((values, propName) => {
-      let i = this.queryTypes.indexOf(propName);
-      if (i < 0)
-        this.addTagInSearchQuery(values.join(' | '), propName);
-      else{
-        let currentValues = this.searchQuery[i].split(' | ');
-        //console.log('Current VAlues: ',currentValues);
-        values.forEach(value => {
-          if (currentValues.indexOf(value) < 0) currentValues.push(value);
-        });
-        this.searchQuery[i] = currentValues.join(' | ');
-        this.updateSearchQuery();
-        //this._showSearchBox();
-      }
-    });
-  }*/
-
-
-
-
 
   removeElementORFormulaInSearchQuery(item){
     //console.log(" removeElementORFormulaInSearchQuery item: ",item, this.searchQuery.indexOf(item));
-- 
GitLab