Skip to content
Snippets Groups Projects
Commit b6c3bdaf authored by Jaden Diefenbaugh's avatar Jaden Diefenbaugh
Browse files

add report view for readonly

parent 2c6f4451
No related branches found
No related tags found
1 merge request!223Reports overhaul
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/*
* groupItemContainer
* Desc:
* container for an item in the group
*/
angular.module('reportApp')
.directive("groupItemContainer", [function(){
return {
scope: {
group: '=',
reportItem: '='
},
link: function(scope){
scope.item = scope.reportItem;
scope.domId = `${scope.group.name}_${scope.id}`;
},
template: `
<div
group-table-item
ng-if="item.id.includes('table')"
class='panel panel-default'
group='group'
id='item.id'
content='item.content'
>
</div>
<div
group-plot-item
ng-if="item.id.includes('plot')"
class='panel panel-default'
group='group'
id='item.id'
content='item.content'
>
</div>
<div
group-text-item
ng-if="item.id.includes('text')"
class='panel panel-default'
group='group'
report-item='item'
>
</div>
`
};
}]);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/*
* groupsLayout
* Desc:
* controls the layout of the reports content, generating group panels
* using the GroupsService data.
*/
angular.module('reportApp').directive("groupsLayout", ['GroupsService', function(GroupsService){
return {
// isolate scope for modularity & less coupling
scope: {
},
link: function(scope, el, attr){
scope.groups = GroupsService.groups;
},
template: `
<div id='groupsLayout' class='panel-group'>
<div
group-panel-content
class='panel panel-default'
ng-repeat='group in groups'
group='group'
>
</div>
</div>
`
};
}]);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/*
* groupPanelContent
* Desc:
* lays out the content of a group in a panel
*/
angular.module('reportApp').directive("groupPanelContent", ['GroupsService', function(GroupsService){
return {
scope: {
group: '='
},
link: function(scope){
},
template: `
<div id="{{group.name}}-heading" class="panel-heading" role="tab">
<h4 class="panel-title">
<a
role="button"
data-toggle="collapse"
data-parent="#{{group.name}}-heading"
href="#collapse-{{group.name}}"
aria-expanded="true"
aria-controls="collapse-{{group.name}}">
{{ group.name }}
</a>
</h4>
</div>
<div id="collapse-{{group.name}}"
class="panel-collapse collapse in"
role="tabpanel"
aria-labelledby="{{group.name}}-heading">
<div class="panel-body panel-group">
<!--<div group-panel-experiments group='group' class='panel panel-default'></div>!-->
<div
ng-if='group.experiments.length > 0'
group-panel-items
group='group'
>
</div>
</div>
</div>
`
};
}]);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/*
* groupPanelExperiments
* Desc:
* displays the experiments panel of the group
*/
angular.module('reportApp').directive("groupPanelExperiments", ['GroupsService', 'ExperimentsService', 'UrlService', function(GroupsService, ExperimentsService, UrlService){
return {
scope: {
group: '='
},
link: function(scope){
scope.experiments = ExperimentsService.experiments;
scope.expsNotInGroup = () => {
return Object.keys(ExperimentsService.experiments)
// exps not in group
.filter(e => !scope.group.experiments.includes(e))
// exp has compatible analyzer
.filter(e => scope.group.analyzer === '' || ExperimentsService.getAnalyzerFromExpName(e) === scope.group.analyzer)
;
};
scope.getExpDatabases = (expName) => {
let dbs = scope.experiments[expName].declaration.datasets;
return Array.from(new Set(Object.values(dbs).map(db => db.database)));
};
scope.getAnalyzerFromExpName = ExperimentsService.getAnalyzerFromExpName;
scope.getExpUrl = UrlService.getExperimentUrl;
scope.getBlockUrl = UrlService.getBlockUrl;
scope.getDatabaseUrl = UrlService.getDatabaseUrl;
},
template: `
<div id="{{group.name}}-explist-heading" class="panel-heading" role="tab">
<h4 class="panel-title">
<a
role="button"
data-toggle="collapse"
data-parent="#{{group.name}}-explist-heading"
href="#collapse-{{group.name}}-explist"
aria-expanded="true"
aria-controls="collapse-{{group.name}}-explist">
Experiments
</a>
<i style='margin-left: 5px;' ng-if='group.analyzer.length > 0'>
Analyzer: <a href='{{ getBlockUrl(group.analyzer) }}'>{{ group.analyzer }}</a>
</i>
</h4>
</div>
<div id="collapse-{{group.name}}-explist"
class="panel-collapse collapse in"
role="tabpanel"
aria-labelledby="{{group.name}}-explist-heading">
<div class="panel-body">
<table ng-if='group.experiments.length > 0' class="table table-striped table-hover">
<thead>
<tr>
<th>Experiment</th>
<th>Databases</th>
<th>Alias</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='expName in group.experiments' ng-if='experiments[expName]'>
<td><a href='{{ getExpUrl(expName) }}'>{{ expName }}</a></td>
<td>
<span ng-repeat='db in getExpDatabases(expName)'>
<a href='{{ getDatabaseUrl(db) }}'>{{ db }}</a>
&nbsp;
</span>
</td>
<td>{{ group.aliases[expName] }}</td>
</tr>
</tbody>
</table>
</div>
</div>
`
};
}]);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/*
* groupPanelItems
* Desc:
* displays the panel of report items of the group
*/
angular.module('reportApp').directive("groupPanelItems", [function(){
return {
scope: {
group: '='
},
link: function(scope){
},
template: `
<div>
<div
group-item-container
ng-repeat='item in group.reportItems'
group='group'
report-item='item'
style='margin-bottom: 5px;'
>
</div>
</div>
`
};
}]);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/*
* groupPlotItem
* Desc:
* displays a plot report item
*/
angular.module('reportApp')
.directive("groupPlotItem", ['ExperimentsService', function(ExperimentsService){
return {
scope: {
group: '=',
id: '=',
content: '='
},
link: function(scope){
scope.domId = `${scope.group.name}_${scope.id}`;
},
template: `
<div id="{{domId}}-heading" class="panel-heading" role="tab">
<h4 class="panel-title">
<a
class=''
role="button"
data-toggle="collapse"
data-parent="#{{domId}}-heading"
href="#collapse-{{domId}}"
aria-expanded="true"
aria-controls="collapse-{{domId}}">
</a>
</h4>
</div>
<div id="collapse-{{domId}}"
class="panel-collapse collapse in"
role="tabpanel"
aria-labelledby="{{domId}}-heading">
<div class='panel-body'>
<p>{{ id }} content</p>
<strong class='text-danger'>Plot items in reports are not implemented yet.</strong>
</div>
</div>
`
};
}]);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/*
* groupTableItem
* Desc:
* displays a table report item
*/
angular.module('reportApp')
.directive("groupTableItem", ['GroupsService', 'ExperimentsService', function(GroupsService, ExperimentsService){
return {
scope: {
group: '=',
id: '=',
content: '='
},
link: function(scope){
// aliases
scope.fields = scope.content.fields;
// ids
scope.domId = `${scope.group.name}_${scope.id}`;
scope.colSelectorId = `${scope.domId}_columnSelector`;
// add 'expName' to the beginning of the fields to show in the table
// if it isnt already there
if(scope.fields.length === 0 || scope.fields[0] !== 'Experiment'){
scope.fields.unshift('Experiment');
}
// 1 - 10
scope.floatingPointRange = [...(new Array(10)).keys()].map(i => i + 1);
// get possible table entries
scope.tableables = ExperimentsService.tableables || {};
// gets the field type (int, float, string, nothing)
scope.getFieldType = (field) => {
if(field === scope.fields[0]){
return 'string';
}
let hasFieldObj = Object.values(scope.tableables)
.find(o => o[field]);
let fVal = hasFieldObj ? hasFieldObj[field] : {};
let type;
if(fVal.type){
type = fVal.type;
} else if(Number.isSafeInteger(fVal)){
type = 'integer';
} else if(Number.isFinite(fVal)){
type = 'float';
} else if(typeof fVal === 'string'){
type = 'string';
} else {
type = undefined;
}
return type;
};
// gets the field val for the given exp
scope.getFieldVal = (expName, field) => {
let fVal = scope.tableables[expName] ?
scope.tableables[expName][field] : undefined;
let val;
if(field === scope.fields[0]){
val = scope.group.aliases[expName].length > 0 ? scope.group.aliases[expName] : expName;
} else if(!fVal){
val = '-';
} else {
let tmp;
if(fVal.value){
tmp = fVal.value;
} else {
tmp = fVal;
}
let type = scope.getFieldType(field);
if(type && type.startsWith('float')){
val = tmp.toFixed(parseInt(scope.content.precision));
} else {
val = tmp;
}
}
return val;
};
// need to nest actual value in an obj to get angular
// to watch it correctly
scope.sortField = { val: 'Experiment', isReversed: false };
// sort rows (one row per exp)
scope.sortFunc = (expName) => {
return scope.getFieldType(scope.sortField.val) ?
scope.getFieldVal(expName, scope.sortField.val) : expName;
};
// sets the new sort field and direction
scope.setSortField = (field) => {
if(scope.sortField.val === field){
scope.sortField.isReversed = !scope.sortField.isReversed;
} else {
scope.sortField.val = field;
scope.sortField.isReversed = false;
}
};
// a different view of the table
scope.getCSV = () => {
let fields = scope.fields;
let exps = scope.group.experiments
// clone arr
.map(e => `${e}`)
.sort((ea, eb) => (scope.sortField.isReversed ? -1 : 1) * (scope.sortFunc(ea) > scope.sortFunc(eb) ? -1 : 1))
;
let str = '';
let fieldsStr = fields
.map(f => `${f}(${scope.getFieldType(f)})`)
.join(',');
let expsStrs = exps
.map(e => fields.map(f => `${scope.getFieldVal(e, f)}`).join(','))
.join('\n');
str = `${fieldsStr}\n${expsStrs}`;
return str;
};
// toggle val for viewing CSV
scope.isViewingCSV = { val: false };
scope.toggleViewingCSV = () => {
scope.isViewingCSV.val = !scope.isViewingCSV.val;
};
},
template: `
<div id="{{domId}}-heading" class="panel-heading" role="tab">
<h4 class="panel-title">
<a
class=''
role="button"
data-toggle="collapse"
data-parent="#{{domId}}-heading"
href="#collapse-{{domId}}"
aria-expanded="true"
aria-controls="collapse-{{domId}}">
</a>
<div class="btn-group" role="group" role='tab'>
<button class='btn btn-default' ng-click='toggleViewingCSV()'>
Toggle CSV View
</button>
</div>
</h4>
</div>
<div id="collapse-{{domId}}"
class="panel-collapse collapse in"
role="tabpanel"
aria-labelledby="{{domId}}-heading">
<div ng-if='isViewingCSV.val' class='panel-body'>
<pre>{{ getCSV() }}</pre>
</div>
<div ng-if='!isViewingCSV.val' class='panel-body' style='height: 100%; overflow-x: auto;'>
<table class="table table-striped table-hover">
<thead>
<tr>
<th ng-repeat='field in fields'>
<span
ng-if="sortField.val == field"
class='glyphicon'
ng-class="{
'glyphicon-chevron-up': sortField.isReversed,
'glyphicon-chevron-down': !sortField.isReversed
}"
>
</span>
<a role='button' ng-click='setSortField(field)'>
{{ field }} <i>({{ getFieldType(field) }})</i>
</a>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="exp in group.experiments | orderBy:sortFunc:sortField.isReversed">
<td ng-repeat='field in fields'>
{{ getFieldVal(exp, field) }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
`
};
}]);
/*
* Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
*/
/*
* groupTextItem
* Desc:
* displays a text report item
*/
angular.module('reportApp')
.directive("groupTextItem", ['GroupsService', '$sce', 'UrlService', 'reportFactory', function(GroupsService, $sce, UrlService, reportFactory){
return {
scope: {
group: '=',
reportItem: '=',
},
link: function(scope){
// aliases
scope.trustAsHtml = $sce.trustAsHtml;
scope.item = scope.reportItem;
scope.domId = `${scope.group.name}_${scope.item.id}`;
// readonly codemirror options
scope.srccmOptions = {
mode: 'rst',
readOnly: true
};
// handle compiling content
scope.compiledContent = { val: '' };
scope.compileContent = () => {
let url = UrlService.getCompileRstUrl();
let mapToTextBlock = `${scope.group.name}|${scope.group.reportItems.indexOf(scope.reportItem)}`;
console.log(mapToTextBlock);
return reportFactory.compileRST(url, mapToTextBlock)
.then(data => {
scope.compiledContent.val = data.data.html_str;
});
};
// handle toggling between html & rst view
scope.isViewingSrc = { val: false };
// compile the content when loaded
scope.compileContent();
},
template: `
<div id="{{domId}}-heading" class="panel-heading" role="tab">
<h4 class="panel-title">
<a
class=''
role="button"
data-toggle="collapse"
data-parent="#{{domId}}-heading"
href="#collapse-{{domId}}"
aria-expanded="true"
aria-controls="collapse-{{domId}}">
</a>
<div class="btn-group" role="group" role='tab'>
<!-- dont show split view, just toggle between html/rst view !-->
<button class='btn btn-default' ng-click='isViewingSrc.val = !isViewingSrc.val'>
Toggle View
</button>
</div>
</h4>
</div>
<div id="collapse-{{domId}}"
class="panel-collapse collapse in"
role="tabpanel"
aria-labelledby="{{domId}}-heading">
<div class='panel-body'>
<div ng-if='!isViewingSrc.val' class='row'>
<div ng-bind-html='trustAsHtml(compiledContent.val)'></div>
</div>
<div ng-if='isViewingSrc.val'>
<i>Readonly view</i>
<ui-codemirror ng-model='item.content' ui-codemirror-opts='srccmOptions'></ui-codemirror>
</div>
</div>
</div>
`
};
}]);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment