From b6c3bdaf64983fbd8c58d798cef697d531ec061a Mon Sep 17 00:00:00 2001
From: Jaden Diefenbaugh <blakcap@users.noreply.github.com>
Date: Mon, 13 Mar 2017 16:41:37 +0100
Subject: [PATCH] add report view for readonly

---
 .../app/directives/view/itemContainer.js      |  68 ++++++
 .../reports/app/directives/view/layout.js     |  49 ++++
 .../app/directives/view/panelContent.js       |  66 ++++++
 .../app/directives/view/panelExperiments.js   |  99 ++++++++
 .../reports/app/directives/view/panelItems.js |  48 ++++
 .../reports/app/directives/view/plotItem.js   |  64 ++++++
 .../reports/app/directives/view/tableItem.js  | 213 ++++++++++++++++++
 .../reports/app/directives/view/textItem.js   | 102 +++++++++
 8 files changed, 709 insertions(+)
 create mode 100644 beat/web/reports/static/reports/app/directives/view/itemContainer.js
 create mode 100644 beat/web/reports/static/reports/app/directives/view/layout.js
 create mode 100644 beat/web/reports/static/reports/app/directives/view/panelContent.js
 create mode 100644 beat/web/reports/static/reports/app/directives/view/panelExperiments.js
 create mode 100644 beat/web/reports/static/reports/app/directives/view/panelItems.js
 create mode 100644 beat/web/reports/static/reports/app/directives/view/plotItem.js
 create mode 100644 beat/web/reports/static/reports/app/directives/view/tableItem.js
 create mode 100644 beat/web/reports/static/reports/app/directives/view/textItem.js

diff --git a/beat/web/reports/static/reports/app/directives/view/itemContainer.js b/beat/web/reports/static/reports/app/directives/view/itemContainer.js
new file mode 100644
index 000000000..3aed999c4
--- /dev/null
+++ b/beat/web/reports/static/reports/app/directives/view/itemContainer.js
@@ -0,0 +1,68 @@
+/*
+ * 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>
+`
+	};
+}]);
diff --git a/beat/web/reports/static/reports/app/directives/view/layout.js b/beat/web/reports/static/reports/app/directives/view/layout.js
new file mode 100644
index 000000000..fe1d3750f
--- /dev/null
+++ b/beat/web/reports/static/reports/app/directives/view/layout.js
@@ -0,0 +1,49 @@
+/*
+ * 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>
+`
+	};
+}]);
diff --git a/beat/web/reports/static/reports/app/directives/view/panelContent.js b/beat/web/reports/static/reports/app/directives/view/panelContent.js
new file mode 100644
index 000000000..89158ec44
--- /dev/null
+++ b/beat/web/reports/static/reports/app/directives/view/panelContent.js
@@ -0,0 +1,66 @@
+/*
+ * 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>
+`
+	};
+}]);
+
diff --git a/beat/web/reports/static/reports/app/directives/view/panelExperiments.js b/beat/web/reports/static/reports/app/directives/view/panelExperiments.js
new file mode 100644
index 000000000..df8bd1632
--- /dev/null
+++ b/beat/web/reports/static/reports/app/directives/view/panelExperiments.js
@@ -0,0 +1,99 @@
+/*
+ * 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>
+`
+	};
+}]);
diff --git a/beat/web/reports/static/reports/app/directives/view/panelItems.js b/beat/web/reports/static/reports/app/directives/view/panelItems.js
new file mode 100644
index 000000000..6ff325d43
--- /dev/null
+++ b/beat/web/reports/static/reports/app/directives/view/panelItems.js
@@ -0,0 +1,48 @@
+/*
+ * 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>
+`
+	};
+}]);
diff --git a/beat/web/reports/static/reports/app/directives/view/plotItem.js b/beat/web/reports/static/reports/app/directives/view/plotItem.js
new file mode 100644
index 000000000..78570e388
--- /dev/null
+++ b/beat/web/reports/static/reports/app/directives/view/plotItem.js
@@ -0,0 +1,64 @@
+/*
+ * 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>
+`
+	};
+}]);
diff --git a/beat/web/reports/static/reports/app/directives/view/tableItem.js b/beat/web/reports/static/reports/app/directives/view/tableItem.js
new file mode 100644
index 000000000..bed05cf76
--- /dev/null
+++ b/beat/web/reports/static/reports/app/directives/view/tableItem.js
@@ -0,0 +1,213 @@
+/*
+ * 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>
+`
+	};
+}]);
diff --git a/beat/web/reports/static/reports/app/directives/view/textItem.js b/beat/web/reports/static/reports/app/directives/view/textItem.js
new file mode 100644
index 000000000..113cc4b2f
--- /dev/null
+++ b/beat/web/reports/static/reports/app/directives/view/textItem.js
@@ -0,0 +1,102 @@
+/*
+ * 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>
+`
+	};
+}]);
-- 
GitLab