Commit c98a54f4 authored by Iker Hurtado's avatar Iker Hurtado
Browse files

Deep refactoring of the MaterialList component and integration with the new API (unfinished)

parent f7ff10fe
Pipeline #90267 skipped with stage
...@@ -798,14 +798,14 @@ div#specialRows{margin: 30px 40px;} ...@@ -798,14 +798,14 @@ div#specialRows{margin: 30px 40px;}
#matlist .not-found{ font-size: 1.6em; color: #E56400; #matlist .not-found{ font-size: 1.6em; color: #E56400;
text-align: center; padding: 80px 0; } text-align: center; padding: 80px 0; }
#matlist .results-total{text-align: center;}
#matlist .pag-header{ font-size: 1.0em;padding: 10px 12px 24px;text-align: center;} #matlist .pag-header{ font-size: 1.0em;padding: 10px 12px 24px;text-align: center;}
span.prevButton{ display: inline-block; cursor: pointer;} span.prevButton{ display: inline-block; cursor: pointer;}
span.page{ display: inline-block; } span.page{ display: inline-block; }
span.nextButton{ display: inline-block; cursor: pointer;} span.nextButton{ display: inline-block; cursor: pointer;}
.mat-list-container table{
.data-container table{
margin: auto; margin: auto;
width: 96%; width: 96%;
} }
......
...@@ -83,8 +83,8 @@ class FilterPanel { ...@@ -83,8 +83,8 @@ class FilterPanel {
const boolValueFields = new CheckboxesField('Results containing...', undefined, [ const boolValueFields = new CheckboxesField('Results containing...', undefined, [
{value: 'Band structure', text: 'Band structure', id: 'has_band_structure'}, {value: 'Band structure', text: 'Band structure', id: 'has_band_structure'},
{value: 'DOS', text: 'DOS', id: 'has-dos'}, {value: 'DOS', text: 'DOS', id: 'has_dos'},
{value: 'Thermal properties', text: 'Thermal properties', id: 'has-thermal-properties'}, {value: 'Thermal properties', text: 'Thermal properties', id: 'has_thermal_properties'},
]); ]);
this.fields.push(boolValueFields) this.fields.push(boolValueFields)
propertiesGroupBox.append(boolValueFields.element); propertiesGroupBox.append(boolValueFields.element);
......
...@@ -27,7 +27,7 @@ let util = require('../common/util.js'); ...@@ -27,7 +27,7 @@ let util = require('../common/util.js');
let InfoSys = require('../common/InfoSys.js'); let InfoSys = require('../common/InfoSys.js');
let LoadingPopup = require('../common/LoadingPopup.js'); let LoadingPopup = require('../common/LoadingPopup.js');
const RESULTS_PER_PAGE = 20; //const RESULTS_PER_PAGE = 20;
class MaterialList { class MaterialList {
...@@ -35,236 +35,95 @@ class MaterialList { ...@@ -35,236 +35,95 @@ class MaterialList {
constructor(){ constructor(){
this.element = document.createElement('div'); this.element = document.createElement('div');
this.element.setAttribute("id",'matlist'); this.element.setAttribute("id",'matlist');
// map containing an entry per system type (if there are materials for it)
this.matMap = new Map();
this.currentSystemType = 'bulk';
this.esQueryObject = null;
this.element.innerHTML=
`
<div id="system-type-tabs" style=" display: inline-block">
<button id="system-tab-bulk" class="selected">BULK</button>
<button id="system-tab-2D" >2D</button>
<button id="system-tab-1D" >1D</button>
<span class="results-total" >Results<span>
</div>
<div class="pag-header">
<span class="prevButton">
<img src="img/prev.svg" style="display: inline;" width="7px"/> &nbsp; prev
</span> &nbsp;&nbsp;
<span class="page"> X </span> &nbsp;&nbsp;
<span class="nextButton"> next &nbsp;
<img src="img/next.svg" width="7px" />
</span>
</div>
<div class="data-container"> </div>`; // results data container
this.titleBox = this.element.getElementsByClassName("results-total")[0]; this.matMap = new Map();
this.tabsBox = this.element.querySelector("#system-type-tabs"); //this.currentSystemType = 'bulk';
// Pagination components this.optimadeQuery = null;
this.resultsNrTag = this.element.getElementsByClassName("pag-header")[0];
this.prevButton = this.element.getElementsByClassName("prevButton")[0]; this._hide();
this.pageElement = this.element.getElementsByClassName("page")[0];
this.nextButton = this.element.getElementsByClassName("nextButton")[0];
this.resultsContainer = this.element.getElementsByClassName("data-container")[0]; this.pagControl = new PaginationControl();
this.element.append(this.pagControl.element);
this.pagControl.setPrevPageListener( page => {
this._search(page);
});
this.pagControl.setNextPageListener( page => {
this._search(page);
})
this._hide(); this.matListContainer = new MatListContainer();
this.element.append(this.matListContainer.element);
} }
attachAndSetEvents(element){ attachAndSetEvents(element){
element.appendChild(this.element); element.appendChild(this.element);
this._events();
} }
_hide() { _hide() {
this.element.style.display = 'none'; this.element.style.display = 'none';
} }
_show() {
this.element.style.display = 'block';
}
_events() {
this.tabsBox.addEventListener( "click", (e) => {
if (e.target !== e.currentTarget) { // When the event source is a child
let tabId = e.target.id;
let index = tabId.indexOf('system-tab');
if (index >= 0){
let selectingTab = tabId.substring('system-tab'.length+1);
this._updateUI(selectingTab);
// Change the styles of the tabs
this.element.querySelector('#system-tab-'+this.currentSystemType).className = '';
this.element.querySelector('#system-tab-'+selectingTab).className = 'selected';
this.currentSystemType = selectingTab;
}
}
});
this.nextButton.addEventListener('click', e => {
let systemData = this.matMap.get(this.currentSystemType);
if (systemData.page === systemData.totalPages) return;
systemData.page++;
this._paginationSearch();
});
this.prevButton.addEventListener('click', e => {
let systemData = this.matMap.get(this.currentSystemType);
if (systemData.page === 1) return;
systemData.page--;
this._paginationSearch();
});
this.resultsContainer.addEventListener('click', (e) => {
if (e.target !== e.currentTarget) { // When the event source is a child
let element;
if (e.target.className === 'mat-row') element = e.target;
else if (e.target.parentElement.className === 'mat-row')
element = e.target.parentElement;
else if (e.target.parentElement.parentElement.className === 'mat-row')
element = e.target.parentElement.parentElement;
if (element) {
util.setBrowserHashPath('material', element.getAttribute('data-mat-id'));
}
e.stopPropagation();
}
});
_show() {
this.element.style.display = '';
} }
_paginationSearch(){ invalidateSearch(){
this._hide();
let systemTypePosition = this.esQueryObject.bool.must.length-1;
this.esQueryObject.bool.must[systemTypePosition].match.system_type = this.currentSystemType;
let page = this.matMap.get(this.currentSystemType).page;
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);
this.matMap.set(this.currentSystemType, this._createSystemTypeData(data, page, true));
//console.log('this.matMap: ', this.matMap);
this._updateUI(this.currentSystemType);
});
} }
initSearchTest(rootQueryObj){ initSearch(optimadeQuery){
//this.resultsContainer.style.visibility = 'hidden';
this.matMap.clear();
let qqq = { 'bool' : {} };
//qqq.bool.must = {"terms":{"crystal_system":{"operator":"or","query":"cubic"}}};
qqq.bool.must = {"terms":{"crystal_system": ["hexagonal","cubic"]}};
console.log('SENDING: ', JSON.stringify(qqq)); console.log(': ', qqq.bool.must);
let bulkReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
'&per_page='+RESULTS_PER_PAGE, JSON.stringify(qqq), bulke => {
let bulkData = JSON.parse(bulke.target.response); console.log('GETTING: ', bulkData);
this.matMap.set('bulk', this._createSystemTypeData(bulkData, 1, bulke.target.status === 200));
LoadingPopup.hide();
});
this.optimadeQuery = optimadeQuery;
this._search();
} }
initSearch(rootQueryObj){ _search(page){
//this.resultsContainer.style.visibility = 'hidden'; //this.resultsContainer.style.visibility = 'hidden';
this.matMap.clear(); this.matMap.clear();
// rootQueryObj.bool.must.push( { "match": {"system_type" : "bulk"} } );
//console.log('SENDING: ', JSON.stringify(rootQueryObj)); console.log(': ', rootQueryObj.bool.must);
//let systemTypePosition = rootQueryObj.bool.must.length-1;
//this.esQueryObject = rootQueryObj;
LoadingPopup.show(); LoadingPopup.show();
//rootQueryObj = 'elements HAS ALL "Si", "Cl"'; let reqJson = { query: this.optimadeQuery };
console.log('SENDING: ',rootQueryObj); if (page) reqJson.search_by = { page: page}
let bulkReq = util.serverReqPOST(util.getSearchURL(), JSON.stringify({ query: rootQueryObj}) , bulke => {
let bulkData = JSON.parse(bulke.target.response); console.log('GETTING: ', bulkData);
this.matMap.set('bulk', this._createSystemTypeData(bulkData, 1, bulke.target.status === 200));
this._updateUI(this.currentSystemType);
this._show();
LoadingPopup.hide();
this._launchMaterialViewerIfOnlyOne();
});
/*
//let oReq = util.serverReqPOST('http://enc-staging-nomad.esc.rzg.mpg.de/current/v1.0/esmaterials', postQuery, e => {
// Bulk materials request
let bulkReq = util.serverReqPOST(util.getSearchURL()+'?page=1'+
'&per_page='+RESULTS_PER_PAGE, JSON.stringify(rootQueryObj), bulke => {
let bulkData = JSON.parse(bulke.target.response); console.log('GETTING: ', bulkData);
this.matMap.set('bulk', this._createSystemTypeData(bulkData, 1, bulke.target.status === 200));
// 2D materials request
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); console.log('SEARCHING: ', reqJson );
this.matMap.set('2D', this._createSystemTypeData(twoDData, 1, twoDe.target.status === 200)); fetch(util.getSearchURL(), {
method: 'POST',
headers: {'Content-Type': 'application/json;charset=utf-8'},
body: JSON.stringify(reqJson)
})
.then( resp => resp.json() )
.then( result => {
console.log('GETTING: ', result);
// Update
this._setMatList(result.results);
this.pagControl.set(result.pages);
// 1D materials request if (result.results.length === 0){
rootQueryObj.bool.must[systemTypePosition].match.system_type = '1D'; this._hide();
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));
let selectedSystemType = null;
this.matMap.forEach( (materials, systemType) => {
this.element.querySelector('#system-tab-'+systemType).disabled =
(materials.total === 0);
if (selectedSystemType === null && materials.total > 0) {
selectedSystemType = systemType;
this.element.querySelector('#system-tab-'+this.currentSystemType).className = '';
this.element.querySelector('#system-tab-'+selectedSystemType).className = 'selected';
this.currentSystemType = selectedSystemType; }else{
if (result.results.length === 1){
const onlyMat = this.matMap.values().next().value[0];
util.setBrowserHashPath('material', onlyMat.material_id);
} }
}); //else{
rootQueryObj.bool.must[systemTypePosition].match.system_type = this.currentSystemType; this.matListContainer.updateList(this.matMap);
this._updateUI(this.currentSystemType);
//this.resultsContainer.style.visibility = 'visible';
this._show(); this._show();
LoadingPopup.hide(); //}
this._launchMaterialViewerIfOnlyOne(); }
});
}); LoadingPopup.hide();
})
});
*/
/* /*
oReq.addEventListener("error", e => { // Not valid query oReq.addEventListener("error", e => { // Not valid query
...@@ -276,70 +135,94 @@ class MaterialList { ...@@ -276,70 +135,94 @@ class MaterialList {
LoadingPopup.hide(); LoadingPopup.hide();
}); });
*/ */
}
} _setMatList(matList){
if (matList.length > 0){
matList.forEach( mat => {
_launchMaterialViewerIfOnlyOne(){ if (this.matMap.has(mat.formula_reduced)){
let mat; let matArray = this.matMap.get(mat.formula_reduced);
let sum = 0; matArray.push(mat);
this.matMap.forEach( (materials, systemType) => { }else
sum += materials.total; this.matMap.set(mat.formula_reduced, [mat]);
if (materials.total === 1)
mat = materials.materials.values().next().value[0];
}); });
if (sum === 1) util.setBrowserHashPath('material',+(mat.id)); }else this.matMap.clear(); // Right query - results not found
} }
}
_createSystemTypeData(data, page, status){
if (status){
let systemTypeMatMap = new Map();
data.results.forEach( mat => { class PaginationControl{
if (systemTypeMatMap.has(mat.formula_reduced)){
let matArray= systemTypeMatMap.get(mat.formula_reduced); constructor(){
matArray.push(mat); this.element = document.createElement('div');
}else{ //this.element.className = 'pag-header';
let newArray= []; newArray.push(mat); this.element.innerHTML = `
systemTypeMatMap.set(mat.formula_reduced, newArray); <div class="results-total" >Results</div>
}
<div class="pag-header" >
<span class="prevButton">
<img src="img/prev.svg" style="display: inline;" width="7px"/> &nbsp; prev
</span> &nbsp;&nbsp;
<span class="page"> X </span> &nbsp;&nbsp;
<span class="nextButton"> next &nbsp;
<img src="img/next.svg" width="7px" />
</span>
</div>
`;
this.titleBox = this.element.querySelector('.results-total');
this.prevButton = this.element.querySelector('.prevButton');
this.pageElement = this.element.querySelector('.page');
this.nextButton = this.element.querySelector('.nextButton');
this.prevButton.addEventListener('click', e => {
if (this.pagesData.page === 1) return;
this.prevPageListener(this.pagesData.page-1);
}); });
return { 'materials': systemTypeMatMap, this.nextButton.addEventListener('click', e => {
'page': page, console.log('nextButton')
'total': data.total_results, if (this.pagesData.page === this.pagesData.pages) return;
'totalPages': Math.ceil(data.total_results/RESULTS_PER_PAGE) this.nextPageListener(this.pagesData.page+1);
}; });
}else return null; // Right query - results not found
//this.total_results = 0; this.pagesData;
} }
_updateUI(systemType){ set(pagesData){
this.pagesData = pagesData;
this.titleBox.innerHTML= 'Results (total: '+pagesData.total+')';
this.pageElement.innerHTML= 'page '+pagesData.page+' / '+pagesData.pages;
}
setPrevPageListener(listener){
this.prevPageListener = listener;
}
let systemData = this.matMap.get(systemType);
//console.log('_updateUI',systemType, systemData);
this.titleBox.innerHTML= 'Results (total: '+systemData.total+')';
this.pageElement.innerHTML= 'page '+systemData.page+' / '+systemData.totalPages;
let html = ''; setNextPageListener(listener){
this.nextPageListener = listener;
}
}
if (systemData === null) {
this.resultsNrTag.style.display = 'none';
this.titleBox.style.display = 'none';
//if (this.page === 1)
//html+= `<div class="not-found"> No results found </div>`;
// If there is search without results IF PAGE == 0 THERE ISN'T SEARCH
}else{ class MatListContainer{
this.resultsNrTag.style.display = 'block';
this.titleBox.style.display = 'inline';
html +=` constructor(){
this.element = document.createElement('div');
this.element.className = 'mat-list-container';
this.element.innerHTML = `
<table> <table>
<thead> <tr> <thead> <tr>
<th style="width: 24%;"></th> <th style="width: 24%;"></th>
...@@ -355,10 +238,32 @@ class MaterialList { ...@@ -355,10 +238,32 @@ class MaterialList {
</th> </th>
<th style="width: 18%;">Nº calculations</th> <th style="width: 18%;">Nº calculations</th>
</tr> </thead> </tr> </thead>
<tbody>
<tbody> </tbody>
</table>
`; `;
systemData.materials.forEach((mats, formula) => { this.tbody = this.element.querySelector('tbody');
this.tbody.addEventListener('click', e => {
let materialRow = event.target.closest('tr.mat-row');
if (materialRow)
util.setBrowserHashPath('material', materialRow.getAttribute('data-mat-id'));
e.stopPropagation();
});
}
updateList(matMap){
//console.log('matMap', matMap);
if (matMap.size === 0){ this.tbody.innerHTML = ''; return }
let html = ''
matMap.forEach( (mats, formula) => {
let rFormula = util.getSubscriptedFormula(formula); let rFormula = util.getSubscriptedFormula(formula);
html+= '<tr> <td class="formula" colspan="5"><b>'+rFormula+'</b>'; html+= '<tr> <td class="formula" colspan="5"><b>'+rFormula+'</b>';
...@@ -367,10 +272,10 @@ class MaterialList { ...@@ -367,10 +272,10 @@ class MaterialList {
html += '</td></tr>'; html += '</td></tr>';
mats.forEach( mat => { mats.forEach( mat => {
let label= (mat.material_name !== null ? mat.material_name : rFormula); let label = (mat.material_name ? mat.material_name : rFormula);
//console.log("MATERIAL ",mat, mat.system_type); //console.log("MATERIAL ", mat.formula, mat.material_name, rFormula, label);
html+= html +=
`<tr class="mat-row" data-mat-id="${mat.id}"> `<tr class="mat-row" data-mat-id="${mat.material_id}">
<td > ${label} [${mat.formula}] </td> <td > ${label} [${mat.formula}] </td>
<td style="text-align:center" > <td style="text-align:center" >
${mat.space_group_number === null ? '' : mat.space_group_number} ${mat.space_group_number === null ? '' : mat.space_group_number}
...@@ -386,14 +291,13 @@ class MaterialList { ...@@ -386,14 +291,13 @@ class MaterialList {
}); });
}); });
html +=` </tbody> </table>`; this.tbody.innerHTML = html;
}