Commit 522086be authored by Iker Hurtado's avatar Iker Hurtado
Browse files

First implementation of table row sorting in new Methodology details page

parent f27cab02
......@@ -3122,8 +3122,6 @@
this.element.addEventListener('click', e => {
this.off = !this.off;
//this.element.className = (this.off ? this.classNameBase+'-off' :
//this.classNameBase);
let imagePath = (this.off ? imageBasePath+'_off' : imageBasePath);
this.image.setAttribute('src',imagePath+'.png');
this.listener(this.off);
......@@ -5978,8 +5976,10 @@
let DetailsViewBase = __webpack_require__(19);
let util = __webpack_require__(1);
let InfoSys = __webpack_require__(11);
let FilterInGroupsComponent = __webpack_require__(36);
let FilterInGroupsComponent = __webpack_require__(26);
let DataStore = __webpack_require__(2);
let SortingButton = __webpack_require__(36);
const REPOSITORY_LINK =
'https://repository.nomad-coe.eu/NomadRepository-1.1/views/calculation.zul?pid=';
......@@ -6000,7 +6000,7 @@
constructor() {
super('Methodology');
this.sortedLeafs = [];
this.sortedCalcs = [];
this.markedCalc = null;
this.element.innerHTML+=`
......@@ -6025,24 +6025,33 @@
<table id="methodology-data">
<thead>
<tr>
<th style="width: 13%;"><span>Calculation ID</span></th>
<th style="width: 13%;">
<span>Calculation ID</span>
<span class="sorting-button"></span>
</th>
<th style="width: 15%;">
<span>Type</span>
<span class="sorting-button"></span>
</th>
<th style="width: 19%;">
<span info-sys-data="functional-type">Density functional</span>
<span class="sorting-button"></span>
</th>
<th style="width: 15%;">
<span info-sys-data="code-name">Code</span>
<span class="sorting-button"></span>
</th>
<th style="width: 17%;">
<span info-sys-data="pseudopotential-type">Potential</span>
<span class="sorting-button"></span>
</th>
<th style="width: 12%;">
<span info-sys-data="basis-set-type">Basis set</span>
<span class="sorting-button"></span>
</th>
<th style="width: 9%;">
<span info-sys-data="basis-set-type">Link</span>
</th>
</tr>
</thead>
......@@ -6056,6 +6065,7 @@
this.moreInfoRow.className= 'moreinfo';
this.moreInfoCalcId = null;
// filtering feature initialitation
this.filterComponent = new FilterInGroupsComponent('meth-filter-component');
this.element.querySelector('.filter-placeholder').
appendChild(this.filterComponent.element);
......@@ -6074,7 +6084,30 @@
if (propsPresent) rows[i].style.display = 'table-row';
else rows[i].style.display = 'none';
}
});
// row sorting feature initialitation
this.sortingButtonWrappers =
this.dataTableWrapper.querySelectorAll('.sorting-button');
this.sortingButtonsMap = new Map([
[ 'id', undefined ],
[ 'type', undefined ],
[ 'functional', undefined ],
[ 'code', undefined ],
[ 'potential', undefined ],
[ 'basisSet', undefined ] ]);
let keysIter = this.sortingButtonsMap.keys();
this.sortingButtonWrappers.forEach( e => {
let field = keysIter.next().value;
let component = new SortingButton(field);
e.appendChild(component.element);
component.setListener( (descendingOrder, field) => {
this.sortRowsCalcDataBy(descendingOrder, field);
this._render();
});
});
// For static ones
......@@ -6105,7 +6138,7 @@
}
this.moreInfoCalcId = id;
let moreInfoCalc, calcGroupType;
this.sortedLeafs.forEach( leafId => { //console.log(leafId, id);
this.sortedCalcs.forEach( leafId => { //console.log(leafId, id);
if (leafId === id){
moreInfoCalc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
calcGroupType = DataStore.getGroupType(leafId);
......@@ -6169,43 +6202,85 @@
updateSelection( leafIds ){
/*
this.moreInfoCalcId = null; // Reset the unfolded more info
//console.log('MethodologyDetails UPDATING ',calcs); console.log(calcs);
this.sortedLeafs.length = 0;
this.sortedCalcs.length = 0;
leafIds.forEach( leafId => {
let calc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
this.sortedLeafs.push(leafId);
//let calc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
this.sortedCalcs.push(leafId);
});
this.sortedCalcs.sort();
*/
//this.sortedCalcs = DataStore.getCalculations();
DataStore.getCalculations().forEach( c => {
let calcType = c.run_type;
if (DataStore.getGroups().has(c.id)){//leafId)){
calcType = DataStore.getGroupType(c.id);//leafId);
if (calcType === 'convergence') calcType = 'parameter variation';
//console.log('Group',DataStore.getGroupType(leafId));
}
this.sortedCalcs.push({
id: c.id,
type: calcType,
functional: c.functional_type,
code: c.code_name,
potential: c.core_electron_treatment,
basisSet: c.basis_set_type
});
});
this.sortedLeafs.sort();
/*
this.sortedCalcs.sort( (a, b) => {
return a.id - b.id;
});*/
this.sortRowsCalcDataBy(true, 'id');
//console.log('sortedCalcs:', this.sortedCalcs);
this._render();
}
sortRowsCalcDataBy(descendingOrder, field){
this.sortedCalcs.sort( (a, b) => {
if(a[field] < b[field]) return (descendingOrder ? -1 : 1);
if(a[field] > b[field]) return (descendingOrder ? 1 : -1);
return 0;
});
}
updateMarkedLeaf(leafId){ }
_render(){
let html = '';
this.sortedLeafs.forEach( leafId => {
let calc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
this.sortedCalcs.forEach( rowCalcData => { //leafId => {
/*let calc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
let calcType = calc.run_type;
if (DataStore.getGroups().has(leafId)){
calcType = DataStore.getGroupType(leafId);
if (DataStore.getGroups().has(calc.id)){//leafId)){
calcType = DataStore.getGroupType(calc.id);//leafId);
if (calcType === 'convergence') calcType = 'parameter variation';
//console.log('Group',DataStore.getGroupType(leafId));
}
}*/
html+= getRowHtml(leafId, calc, calcType);
//html+= getRowHtml(leafId, calc, calcType);
html+= getRowHtml(rowCalcData);
});
this.tbody.innerHTML = html;
InfoSys.addToInfoSystem(this.tbody);
function getRowHtml(leafId, calc, calcType){
function getRowHtml(rowCalcData/*leafId, calc, calcType*/){
let calc = DataStore.getCalc( /*DataStore.getCalcReprIntId(*/rowCalcData.id);
let calcType = rowCalcData.type;
let calcProps = calcType+','+calc.functional_type+','+calc.code_name+
','+calc.core_electron_treatment+','+calc.basis_set_type;
......@@ -6216,8 +6291,8 @@
+'<img src="img/download.svg" height="20px" /> </a>';
//***** InfoSys.setTooltip(this.spaceGroup, 'space-group.value:'+data.space_group);
return `
<tr data-calc-id="${leafId}" data-calc-props="${calcProps}" class="data-row">
<td>${leafId}</td>
<tr data-calc-id="${calc.id/*leafId*/}" data-calc-props="${calcProps}" class="data-row">
<td>${calc.id/*leafId*/}</td>
<td>
<span info-sys-data="calculation-type.value:${calcType}">
${calcType}</span>
......@@ -6282,7 +6357,125 @@
/***/ },
/* 26 */,
/* 26 */
/***/ function(module, exports, __webpack_require__) {
let util = __webpack_require__(1);
let calcTypesMap = new Map();
calcTypesMap.set('Single point', 'single point');
calcTypesMap.set('GW', 'GW calculation');
calcTypesMap.set('Geometry optimization', 'geometry optimization');
calcTypesMap.set('Molecular dynamics', 'molecular dynamics');
calcTypesMap.set('Phonon', 'phonon calculation');
calcTypesMap.set('Equation of state', 'equation of state');
calcTypesMap.set('Parameter variation', 'parameter variation');//calcTypesMap.set('Convergence', 'convergence');
calcTypesMap.set('QHA', 'QHA calculation');
let densityFunctionalMap = new Map();
densityFunctionalMap.set('LDA', 'LDA');
densityFunctionalMap.set('GGA', 'GGA');
densityFunctionalMap.set('meta-GGA', 'meta-GGA');
densityFunctionalMap.set('hybrid-GGA', 'hybrid-GGA');
densityFunctionalMap.set('meta-hybrid-GGA', 'meta-hybrid-GGA');
densityFunctionalMap.set('HF', 'HF');
let codeMap = new Map();
codeMap.set('exciting', 'exciting');
codeMap.set('VASP', 'VASP');
codeMap.set('FHI-aims', 'FHI-aims');
let potentialMap = new Map();
potentialMap.set('Full potential', 'full all electron');
potentialMap.set('Pseudo potential', 'pseudopotential');
let basicSetMap = new Map();
basicSetMap.set('Numeric AOs', 'numeric AOs');
basicSetMap.set('Gaussians', 'gaussians');
basicSetMap.set('(L)APW+lo', '(L)APW+lo');
basicSetMap.set('Plane waves', 'plane waves');
class FilterInGroupsComponent {
constructor(className) {
this.element = document.createElement('div');
this.element.className = className;
this.filtersOn = [];
this.folded = true;
this.element.innerHTML+=`
<div style="float: left; width: 97%;" >
<div class="filter-groups-c-folded" >
<span style="vertical-align: top;">Filtering</span>
</div>
<div class="filter-groups-c-unfolded" style="display: none">
</div>
</div>
<div class="filter-c-btn" style="float: right; width: 3%;">
<img src="${util.IMAGE_DIR}folded.png" />
<!--<button class="on">filter</button> -->
</div>
<div style="clear: both;"></div>
`;
this.foldedPanel = this.element.querySelector('.filter-groups-c-folded');
this.unfoldedPanel = this.element.querySelector('.filter-groups-c-unfolded');
this.foldBtn = this.element.querySelector('img');
this.foldBtn.addEventListener('click', e => {
this.folded = !this.folded;
this.foldBtn.src = (this.folded ? util.IMAGE_DIR+'folded.png' :
util.IMAGE_DIR+'unfolded.png');
//this.foldBtn.className = (this.folded ? 'on' : 'off');
this.foldedPanel.style.display = (this.folded ? 'block' : 'none');
this.unfoldedPanel.style.display = (this.folded ? 'none' : 'flex');
});
this.addGroupItems('Calculation type', calcTypesMap);
this.addGroupItems('Density functional', densityFunctionalMap);
this.addGroupItems('Code', codeMap);
this.addGroupItems('Potential', potentialMap);
this.addGroupItems('Basic set', basicSetMap);
// Add listener for checkboxes events
this.element.addEventListener('click', (e) => {
if (e.target.tagName === 'INPUT'){
let index = this.filtersOn.indexOf(e.target.value);
if (index >= 0) this.filtersOn.splice( index, 1 );
else this.filtersOn.push(e.target.value);
this.itemListener(this.filtersOn);
//console.log('this.filtersOn',this.filtersOn);
}
});
}
addGroupItems(group, groupItemsMap){
let html = '<div> <div style="font-weight: bold; padding: 6px 0;">'+group+'</div>';
groupItemsMap.forEach( (itemId, itemName) => {
this.filtersOn.push(itemId);
html += '<input type="checkbox" value="'+itemId+'" checked>'+
'<span style="vertical-align: 20%">'+itemName+'</span> &nbsp;&nbsp; <br> ';
});
this.unfoldedPanel.innerHTML += html+ '</div>';
}
setItemListener(listener){
this.itemListener = listener;
}
}
// EXPORTS
module.exports = FilterInGroupsComponent;
/***/ },
/* 27 */
/***/ function(module, exports, __webpack_require__) {
......@@ -8563,116 +8756,36 @@
let util = __webpack_require__(1);
let calcTypesMap = new Map();
calcTypesMap.set('Single point', 'single point');
calcTypesMap.set('GW', 'GW calculation');
calcTypesMap.set('Geometry optimization', 'geometry optimization');
calcTypesMap.set('Molecular dynamics', 'molecular dynamics');
calcTypesMap.set('Phonon', 'phonon calculation');
calcTypesMap.set('Equation of state', 'equation of state');
calcTypesMap.set('Parameter variation', 'parameter variation');//calcTypesMap.set('Convergence', 'convergence');
calcTypesMap.set('QHA', 'QHA calculation');
let densityFunctionalMap = new Map();
densityFunctionalMap.set('LDA', 'LDA');
densityFunctionalMap.set('GGA', 'GGA');
densityFunctionalMap.set('meta-GGA', 'meta-GGA');
densityFunctionalMap.set('hybrid-GGA', 'hybrid-GGA');
densityFunctionalMap.set('meta-hybrid-GGA', 'meta-hybrid-GGA');
densityFunctionalMap.set('HF', 'HF');
let codeMap = new Map();
codeMap.set('exciting', 'exciting');
codeMap.set('VASP', 'VASP');
codeMap.set('FHI-aims', 'FHI-aims');
let potentialMap = new Map();
potentialMap.set('Full potencial', 'full all electron');
potentialMap.set('Pseudo potencial', 'pseudopotential');
let basicSetMap = new Map();
basicSetMap.set('Numeric AOs', 'numeric AOs');
basicSetMap.set('Gaussians', 'gaussians');
basicSetMap.set('(L)APW+lo', '(L)APW+lo');
basicSetMap.set('Plane waves', 'plane waves');
class SortingButton {
constructor(id) {
class FilterInGroupsComponent {
this.id = id;
this.off = true;
constructor(className) {
this.element = document.createElement('div');
this.element.className = className;
this.filtersOn = [];
this.folded = true;
this.element = document.createElement('span');
this.element.innerHTML+=`
<div style="float: left; width: 97%;" >
<div class="filter-groups-c-folded" >
<span style="vertical-align: top;">Filtering</span>
</div>
<div class="filter-groups-c-unfolded" style="display: none">
</div>
</div>
<div class="filter-c-btn" style="float: right; width: 3%;">
<img src="${util.IMAGE_DIR}folded.png" />
<!--<button class="on">filter</button> -->
</div>
<div style="clear: both;"></div>
<img src="img/sorting_off.png" width="24px"
style="margin-bottom: -1px; cursor: pointer"/>
`;
this.foldedPanel = this.element.querySelector('.filter-groups-c-folded');
this.unfoldedPanel = this.element.querySelector('.filter-groups-c-unfolded');
this.foldBtn = this.element.querySelector('img');
this.foldBtn.addEventListener('click', e => {
this.folded = !this.folded;
this.foldBtn.src = (this.folded ? util.IMAGE_DIR+'folded.png' :
util.IMAGE_DIR+'unfolded.png');
//this.foldBtn.className = (this.folded ? 'on' : 'off');
this.foldedPanel.style.display = (this.folded ? 'block' : 'none');
this.unfoldedPanel.style.display = (this.folded ? 'none' : 'flex');
});
this.addGroupItems('Calculation type', calcTypesMap);
this.addGroupItems('Density functional', densityFunctionalMap);
this.addGroupItems('Code', codeMap);
this.addGroupItems('Potential', potentialMap);
this.addGroupItems('Basic set', basicSetMap);
// Add listener for checkboxes events
this.element.addEventListener('click', (e) => {
if (e.target.tagName === 'INPUT'){
let index = this.filtersOn.indexOf(e.target.value);
if (index >= 0) this.filtersOn.splice( index, 1 );
else this.filtersOn.push(e.target.value);
this.itemListener(this.filtersOn);
//console.log('this.filtersOn',this.filtersOn);
}
});
}
this.image = this.element.querySelector('img');
addGroupItems(group, groupItemsMap){
let html = '<div> <div style="font-weight: bold; padding: 6px 0;">'+group+'</div>';
groupItemsMap.forEach( (itemId, itemName) => {
this.filtersOn.push(itemId);
html += '<input type="checkbox" value="'+itemId+'" checked>'+
'<span style="vertical-align: 20%">'+itemName+'</span> &nbsp;&nbsp; <br> ';
this.element.addEventListener('click', e => {
this.off = !this.off;
let imagePath = (this.off ? 'img/sorting_off' : 'img/sorting');
this.image.setAttribute('src',imagePath+'.png');
this.listener(this.off, this.id);
});
this.unfoldedPanel.innerHTML += html+ '</div>';
}
setItemListener(listener){
this.itemListener = listener;
setListener(listener){
this.listener = listener;
}
}
// EXPORTS
module.exports = FilterInGroupsComponent;
module.exports = SortingButton;
/***/ }
......
......@@ -16,8 +16,6 @@ class SwitchComponent {
this.element.addEventListener('click', e => {
this.off = !this.off;
//this.element.className = (this.off ? this.classNameBase+'-off' :
//this.classNameBase);
let imagePath = (this.off ? imageBasePath+'_off' : imageBasePath);
this.image.setAttribute('src',imagePath+'.png');
this.listener(this.off);
......
......@@ -25,8 +25,8 @@ codeMap.set('VASP', 'VASP');
codeMap.set('FHI-aims', 'FHI-aims');
let potentialMap = new Map();
potentialMap.set('Full potencial', 'full all electron');
potentialMap.set('Pseudo potencial', 'pseudopotential');
potentialMap.set('Full potential', 'full all electron');
potentialMap.set('Pseudo potential', 'pseudopotential');
let basicSetMap = new Map();
basicSetMap.set('Numeric AOs', 'numeric AOs');
......
......@@ -6,6 +6,8 @@ let util = require('../common/util.js');
let InfoSys = require('../common/InfoSys.js');
let FilterInGroupsComponent = require('./FilterInGroupsComponent.js');
let DataStore = require('./DataStore.js');
let SortingButton = require('./SortingButton.js');
const REPOSITORY_LINK =
'https://repository.nomad-coe.eu/NomadRepository-1.1/views/calculation.zul?pid=';
......@@ -26,7 +28,7 @@ class MethodologyDetails extends DetailsViewBase {
constructor() {
super('Methodology');
this.sortedLeafs = [];
this.sortedCalcs = [];
this.markedCalc = null;
this.element.innerHTML+=`
......@@ -51,24 +53,33 @@ class MethodologyDetails extends DetailsViewBase {
<table id="methodology-data">
<thead>
<tr>
<th style="width: 13%;"><span>Calculation ID</span></th>
<th style="width: 13%;">
<span>Calculation ID</span>
<span class="sorting-button"></span>
</th>
<th style="width: 15%;">
<span>Type</span>
<span class="sorting-button"></span>
</th>
<th style="width: 19%;">
<span info-sys-data="functional-type">Density functional</span>
<span class="sorting-button"></span>
</th>
<th style="width: 15%;">
<span info-sys-data="code-name">Code</span>
<span class="sorting-button"></span>
</th>
<th style="width: 17%;">
<span info-sys-data="pseudopotential-type">Potential</span>
<span class="sorting-button"></span>
</th>
<th style="width: 12%;">
<span info-sys-data="basis-set-type">Basis set</span>
<span class="sorting-button"></span>
</th>
<th style="width: 9%;">
<span info-sys-data="basis-set-type">Link</span>
</th>
</tr>
</thead>
......@@ -82,6 +93,7 @@ class MethodologyDetails extends DetailsViewBase {
this.moreInfoRow.className= 'moreinfo';
this.moreInfoCalcId = null;
// filtering feature initialitation
this.filterComponent = new FilterInGroupsComponent('meth-filter-component');
this.element.querySelector('.filter-placeholder').
appendChild(this.filterComponent.element);
......@@ -100,7 +112,30 @@ class MethodologyDetails extends DetailsViewBase {
if (propsPresent) rows[i].style.display = 'table-row';
else rows[i].style.display = 'none';
}
});
// row sorting feature initialitation
this.sortingButtonWrappers =
this.dataTableWrapper.querySelectorAll('.sorting-button');
this.sortingButtonsMap = new Map([
[ 'id', undefined ],
[ 'type', undefined ],
[ 'functional', undefined ],
[ 'code', undefined ],
[ 'potential', undefined ],
[ 'basisSet', undefined ] ]);
let keysIter = this.sortingButtonsMap.keys();
this.sortingButtonWrappers.forEach( e => {
let field = keysIter.next().value;
let component = new SortingButton(field);
e.appendChild(component.element);
component.setListener( (descendingOrder, field) => {
this.sortRowsCalcDataBy(descendingOrder, field);
this._render();
});
});
// For static ones
......@@ -131,7 +166,7 @@ class MethodologyDetails extends DetailsViewBase {
}
this.moreInfoCalcId = id;
let moreInfoCalc, calcGroupType;
this.sortedLeafs.forEach( leafId => { //console.log(leafId, id);
this.sortedCalcs.forEach( leafId => { //console.log(leafId, id);
if (leafId === id){
moreInfoCalc = DataStore.getCalc(DataStore.getCalcReprIntId(leafId));
calcGroupType = DataStore.getGroupType(leafId);
......@@ -195,43 +230,85 @@ class MethodologyDetails extends DetailsViewBase {