diff --git a/beat/web/reports/static/reports/app/controllers/groupsController.js b/beat/web/reports/static/reports/app/controllers/groupsController.js index f1ff33c4c9638093d49f242be7814a1e725f9e11..75650e0ca22f6a91c0c8d2702542ff39e918d704 100644 --- a/beat/web/reports/static/reports/app/controllers/groupsController.js +++ b/beat/web/reports/static/reports/app/controllers/groupsController.js @@ -23,17 +23,8 @@ angular.module('reportApp').controller('GroupsController', ['$scope', 'GroupsService', function ($scope, GroupsService){ let vm = this; - // testing stuffs - vm.test = 'test'; vm.report = $scope.report; - const getAnalyzerFromExpName = (expName) => { - let analyzers = vm.report.all_experiments[expName].declaration.analyzers; - let analyzer_block = analyzers[Object.keys(analyzers)[0]]; - - return analyzer_block.algorithm; - }; - // GroupsService stuff to be used directly in ui vm.groups = GroupsService.groups; @@ -45,5 +36,9 @@ angular.module('reportApp').controller('GroupsController', ['$scope', 'GroupsSer // createGroup input val vm.newGroupName = ''; + vm.removeExperiment = (experiment_name) => { + beat.ui.report.remove_experiment('report_remove_experiment', experiment_name, $scope); + }; + console.log(vm); }]); diff --git a/beat/web/reports/static/reports/app/services/experimentsService.js b/beat/web/reports/static/reports/app/services/experimentsService.js index 8b2bf785e2d4dcaddc3176ca37a2f1a0d22f95dc..b52e6250530f0ac90bfa961f85359cec8268eef7 100644 --- a/beat/web/reports/static/reports/app/services/experimentsService.js +++ b/beat/web/reports/static/reports/app/services/experimentsService.js @@ -145,6 +145,17 @@ angular.module('reportApp').factory('ExperimentsService', ['experimentFactory', .map(([res_name, obj]) => obj); }; + // make sure there are no invalid experiments in the report's groups + const cleanGroups = (validExpNames) => { + GroupsService.groups.forEach(g => { + g.experiments.forEach(e => { + if(!validExpNames.includes(e)){ + g.removeExperiment(e); + } + }); + }); + }; + const loadExperiments = (...args) => { let expFetch; if(args.length === 2){ @@ -165,6 +176,8 @@ angular.module('reportApp').factory('ExperimentsService', ['experimentFactory', plotData[expName] = getPlottablesFromExpName(expName); }); + cleanGroups(Object.keys(expData)); + console.log(expData); console.log(tableData); console.log(plotData); diff --git a/beat/web/reports/templates/reports/panels/experiment_table.html b/beat/web/reports/templates/reports/panels/experiment_table.html new file mode 100644 index 0000000000000000000000000000000000000000..62149942cc859bda74396dd6f4de7848f5a4f790 --- /dev/null +++ b/beat/web/reports/templates/reports/panels/experiment_table.html @@ -0,0 +1,167 @@ +{# NOTE: This is a modified version of the experiments app's "table" panel #} +{% comment %} +* 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/. +{% endcomment %} +{% load experiment_tags %} + +{% if objects %} +<div class="col-sm-10 vertical-center"> + <div id="filters" class="form-inline"> + <div class="form-group form-group-sm"> + <div class="input-group input-group-sm"> + <span class="input-group-addon" id="basic-addon1"><i class="fa fa-search"></i></span> + <input type="text" tabindex="2" id="text-filter" class="form-control" placeholder="Filter rows..." aria-describedby="basic-addon1"> + </div> + </div> + + <div class="form-group form-group-sm"> + <label for="attestation-filter" class="control-label">Attestation:</label> + <select id="attestation-filter" class="form-control"> + <option selected>All</option> + <option>Attested</option> + <option>Locked</option> + </select> + </div> + + <div class="form-group form-group-sm"> + <label for="privacy-filter" class="control-label">Privacy:</label> + <select id="privacy-filter" class="form-control"> + <option selected>All</option> + <option>Public</option> + <option>Shared</option> + <option>Private</option> + </select> + </div> + + <div class="form-group form-group-sm"> + <label for="status-filter" class="control-label">Status:</label> + <select id="status-filter" class="form-control"> + <option selected>All</option> + <option>Done</option> + <option>Running</option> + <option>Scheduled</option> + <option>Pending</option> + <option>Failed</option> + </select> + </div> + </div> +</div><!-- row --> + +<div class="row"> + <div class="col-sm-12"> + <div class="scrollable table-responsive"> + <table id="{{ panel_id }}" class="table table-hover table-condensed object-list experiment-list"> + <thead> + <tr> + <th class='delete'></th> + <th class="attestation"></th> + <th class="privacy"></th> + <th class="status"></th> + <th class="date">Updated</th> + <th>Name</th> + <th class="datasets">Databases/Protocols</th> + <th class="analyzers">Analyzers</th> + </tr> + </thead> + <tbody> + {% for obj in objects %} + {% with obj.get_status_display as status %} + <tr class="{{ status }}"> + {% if owner %} + <td class="delete" ng-controller='GroupsController as ctrl'> + <a + title="Delete Experiment" + data-toggle="tooltip" + data-placement="top"> + <span ng-click="ctrl.removeExperiment('{{ obj.fullname }}')"> + <i class='fa fa-times fa-2x'></i> + </span> + </a> + </td> + {% endif %} + <td class="attestation"> + {% if obj.attestation %} + <a class="icon-link" href="{% url 'attestations:view' obj.attestation.number %}" title="{% if obj.attestation.locked %}Locked{% else %}Attested{% endif %} (click to view)" data-toggle="tooltip" data-placement="top"> + {% if obj.attestation.locked %} + <span class="icon-locked fa-stack"> + <i class="fa fa-certificate fa-stack-2x"></i> + <i class="fa fa-lock fa-stack-1x fa-inverse"></i> + </span> + {% else %} + <i class="icon-attested fa fa-certificate"></i> + {% endif %} + </a> + {% endif %} + </td> + <td class="privacy"> + <a title="{{ obj.get_sharing_display }}" data-toggle="tooltip" data-placement="top"> + {% if obj.get_sharing_display == 'Private' %} + <i class="fa fa-user fa-2x"></i> + {% elif obj.get_sharing_display == 'Shared' %} + <i class="fa fa-users fa-2x"></i> + {% else %} + <i class="fa fa-globe fa-2x"></i> + {% endif %} + </a> + </td> + <td class="status"> + <a title="{{ status }}" data-toggle="tooltip" data-placement="top"> + {% if status == 'Done' %} + <i class="icon-done fa fa-check fa-2x"></i> + {% elif status == 'Scheduled' %} + <i class="icon-scheduled fa fa-calendar-check-o fa-2x"></i> + {% elif status == 'Pending' %} + <i class="icon-pending fa fa-play fa-2x"></i> + {% elif status == 'Failed' %} + <i class="icon-failed fa fa-bug fa-2x"></i> + {% elif status == 'Canceling' %} + <i class="icon-canceling fa fa-power-off fa-2x"></i> + {% else %} + <i class="icon-running fa fa-refresh fa-spin fa-2x"></i> + {% endif %} + </a> + </td> + <td class="date">{{ obj.updated|date }}</td> + <td class="name"><a href="{{ obj.get_absolute_url }}" data-toggle="tooltip" data-placement="top" title="Click to view">{{ obj.fullname }}</a></td> + <td class="datasets">{{ obj.databases_and_protocols|join:"," }}</td> + <td class="analyzers">{{ obj.analyzers|join:"," }}</td> + </tr> + {% endwith %} + {% endfor %} + </tbody> + </table> + </div> + </div><!-- col --> +</div><!-- row --> +{% else %} <!-- if objects --> +<div class="row"> + <div class="col-sm-12 not-found"> + No experiment found + </div> +</div><!-- row --> +{% endif %} <!-- if objects --> + +{% csrf_token %} + +{% filter_script panel_id "text-filter" "attestation-filter" "privacy-filter" "status-filter" %} +{% if not request.user.is_anonymous %} +{% report_script panel_id "master-report-checkbox" "report-checkbox" "add-to-report" %} +{% endif %} diff --git a/beat/web/reports/templates/reports/panels/viewer.html b/beat/web/reports/templates/reports/panels/viewer.html index adefaff89be1691242e04c37cf6aea02065f6c78..ab68e5c6573881b3399dd7c0d23473fe43be8edc 100644 --- a/beat/web/reports/templates/reports/panels/viewer.html +++ b/beat/web/reports/templates/reports/panels/viewer.html @@ -20,8 +20,8 @@ * 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/. {% endcomment %} -{% load experiment_tags %} {% load ui_tags %} +{% load report_tags %} {% with object.get_status_display as status %} <div class="row"> diff --git a/beat/web/reports/templatetags/report_tags.py b/beat/web/reports/templatetags/report_tags.py index 5b0e0b6996e614a82e8534aea85600765cc995cb..29b93c20fb311d3820daa8416d41d09869c2e509 100644 --- a/beat/web/reports/templatetags/report_tags.py +++ b/beat/web/reports/templatetags/report_tags.py @@ -247,3 +247,16 @@ def report_saved(id): register.inclusion_tag('reports/dialogs/report_saved.html')(report_saved) + + +#-------------------------------------------------- + + +@register.inclusion_tag('reports/panels/experiment_table.html', takes_context=True) +def experiment_table(context, objects, owner, id): + return dict( + request=context['request'], + objects=objects, + owner=owner, + panel_id=id, + )