diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/etc/config.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/etc/config.js index 589cda418e56d12632df7b22e665c188806fcab4..549b910bf1cfacc3167c41bb6a856fbcb365f5a3 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/etc/config.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/etc/config.js @@ -30,7 +30,7 @@ loadJSResorce("./etc/InstanceProfile.js", onLoadInstanceProfileResorceFunc); //</PROFILE_PLACEHOLDER> var PLUGINS_CONFIGURATION = { - extraPlugins : ["life-sciences", "flow", "microscopy"] + extraPlugins : ["life-sciences", "flow", "microscopy", "bbb-hub"] }; var options = { diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/BBBServerFacade.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/BBBServerFacade.js new file mode 100644 index 0000000000000000000000000000000000000000..32c4989cf99266320443d5c48729e6440a8e559e --- /dev/null +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/BBBServerFacade.js @@ -0,0 +1,142 @@ +var BBBServerFacade = new function() { + this.getExperiment = function($container, model) { + require(["openbis", + "as/dto/sample/fetchoptions/SampleFetchOptions", + "as/dto/experiment/fetchoptions/ExperimentFetchOptions", + "as/dto/experiment/id/ExperimentIdentifier", + "as/dto/dataset/fetchoptions/DataSetFetchOptions"], + function(openbis, SampleFetchOptions, + ExperimentFetchOptions, + ExperimentIdentifier, + DataSetFetchOptions) { + + var v3 = new openbis(null); + v3._private.sessionToken = mainController.openbisV1._internal.sessionToken; + + var webAppContext = v3.getWebAppContext(); + + var dataSetFetchOptions = new DataSetFetchOptions(); + dataSetFetchOptions.withType(); + dataSetFetchOptions.withPhysicalData(); + + var experimentId = new ExperimentIdentifier(model.experiment.identifier); + var fetchOptions = new ExperimentFetchOptions(); + fetchOptions.withDataSetsUsing(dataSetFetchOptions); + fetchOptions.withType(); + + var sampleFetchOptions = new SampleFetchOptions(); + sampleFetchOptions.withType().withPropertyAssignments().withPropertyType(); + sampleFetchOptions.withProperties(); + fetchOptions.withSamplesUsing(sampleFetchOptions); + v3.getExperiments([experimentId], fetchOptions).done(function(result) { + var experiment = result[model.experiment.identifier]; + if (experiment.type.code == "BBB") { + SnakemakeTrigger.paintTriggerContainers($container, model, experiment); + } + }); + }); + } + + this.getExperiments = function($content) { + require(["openbis", "as/dto/sample/fetchoptions/SampleFetchOptions", + "as/dto/experiment/fetchoptions/ExperimentFetchOptions", + "as/dto/experiment/id/ExperimentIdentifier", + "as/dto/dataset/fetchoptions/DataSetFetchOptions", + "as/dto/experiment/search/ExperimentSearchCriteria", + "as/dto/project/fetchoptions/ProjectFetchOptions"], + function(openbis, SampleFetchOptions, + ExperimentFetchOptions, + ExperimentIdentifier, + DataSetFetchOptions, + ExperimentSearchCriteria, + ProjectFetchOptions) { + + var v3 = new openbis(); + + v3.loginAsAnonymousUser().done(function(sessionToken) { + v3._private.sessionToken = sessionToken; + var webAppContext = v3.getWebAppContext(); + + var fetchOptions = new ExperimentFetchOptions(); + fetchOptions.withType(); + fetchOptions.withProperties(); + fetchOptions.withRegistrator(); + + var projectFetchOptions = new ProjectFetchOptions(); + projectFetchOptions.withSpace(); + + fetchOptions.withProjectUsing(projectFetchOptions); + + var searchCriteria = new ExperimentSearchCriteria(); + searchCriteria.withType(); + + v3.searchExperiments(searchCriteria, fetchOptions).done(function(result) { + BBBServerFacade.getRoleAssignment($content, result.objects); + }); + }).fail(function(result) { + console.log("Call failed to server: " + JSON.stringify(result)); + }); + }); + } + + this.getRoleAssignment = function ($content, experiments) { + require(["openbis", "as/dto/roleassignment/fetchoptions/RoleAssignmentFetchOptions", + "as/dto/roleassignment/search/RoleAssignmentSearchCriteria"], + function(openbis, RoleAssignmentFetchOptions, RoleAssignmentSearchCriteria) { + + var v3 = new openbis(); + + v3.loginAsAnonymousUser().done(function(sessionToken) { + v3._private.sessionToken = sessionToken; + var webAppContext = v3.getWebAppContext(); + + var criteria = new RoleAssignmentSearchCriteria(); + criteria.withOrOperator(); + criteria.withProject(); + criteria.withSpace(); + + var fetchOptions = new RoleAssignmentFetchOptions(); + fetchOptions.withSpace(); + fetchOptions.withProject(); + fetchOptions.withUser(); + fetchOptions.withAuthorizationGroup(); + + v3.searchRoleAssignments(criteria, fetchOptions).done(function(result) { + SnakemakeTable.paintTable($content, experiments, result.objects); + }); + }).fail(function(result) { + console.log("Call failed to server: " + JSON.stringify(result)); + }); + }); + } + + this.callCustomASService = function(params, $model, action) { + var result_div = $('#callback_message'); + + require(["openbis", + "as/dto/service/id/CustomASServiceCode", + "as/dto/service/CustomASServiceExecutionOptions", + "as/dto/experiment/id/ExperimentIdentifier"], + function(openbis, CustomASServiceCode, CustomASServiceExecutionOptions, ExperimentIdentifier) { + + var v3 = new openbis(null); + v3._private.sessionToken = mainController.openbisV1._internal.sessionToken; + var webAppContext = mainController.openbisV3.getWebAppContext(); + webAppContext['entityIdentifier'] = $model.experiment.identifier; + + var serviceCode = new CustomASServiceCode("snakemake_service"); + var options = new CustomASServiceExecutionOptions(); + + options.withParameter("webapp_context", webAppContext) + Object.keys(params).forEach(function(key) { + options.withParameter(key, params[key]); + }); + + v3.executeCustomASService(serviceCode, options).done(function(result) { + result_json = JSON.parse(result); + action(result_json) + }); + }); + return false; + } +} \ No newline at end of file diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/UiComponents.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/UiComponents.js new file mode 100644 index 0000000000000000000000000000000000000000..36e1f12a6404c1896e609c4d8c3292b65b86335e --- /dev/null +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/UiComponents.js @@ -0,0 +1,104 @@ +var UiComponents = new function() { + + this.addDropdown = function(label, options, $container, selectAction) { + var $dropdown = UiComponents.getDropdown(options); + $inputGroup = UiComponents.getInputGroup($dropdown, label); + $inputGroup.css("margin-top", "3px"); + $container.append($inputGroup); + $dropdown.select2({ width : "100%", theme : "bootstrap", minimumResultsForSearch: 10 }); + if (selectAction) { + $dropdown.on('select2:select', function (e) { + selectAction(e.params.data.id); + }); + } + $inputGroup.getValue = function() { + return $dropdown.val(); + } + return $inputGroup; + } + + this.getDropdown = function(options, value) { + var $input = $("<select>", { class : "form-control", type : "text" }); + $input.append($("<option>", { "disabled" : true, "selected" : true, "value" : true }).text(" -- select an option -- ")); + for (option of options) { + var $option = $("<option>"); + $option.text(option.label); + $option.attr("value", option.value); + $input.append($option); + } + if (value) { + $input.val(value); + } + return $input; + } + + this.getInputGroup = function($input, label) { + var $inputGroup = $("<div>", { class : "input-group" }); + $inputGroup.append($("<span>", { class : "input-group-addon" }).text(label).css({ 'min-width' : '150px' })); + $inputGroup.append($input); + return $inputGroup; + } + + this.getButton = function($html, action, size, icon) { + var buttonSize = size ? size : 'md'; + var $button = $('<button>', { + type : 'button', + class : 'btn btn-default btn-' + buttonSize, + 'aria-label' : 'Left Align' + }); + if(icon) { + var $icon = $('<span>', { class : 'glyphicon ' + icon }); + $icon.css("margin-right", "0.5rem"); + $button.append($icon); + } + if($html) { + $button.append($("<span>").text($html)); + } + if(action) { + $button.click(action); + } + return $button; + } + + this.getFieldset = function(legendText) { + var $fieldset = $('<fieldset>'); + if (legendText) { + var $legend = $('<legend>', { class : 'section-legend' }).append(legendText) + $fieldset.append($legend); + } + return $fieldset; + } + + this.getLoader = function() { + return $('<div>').attr('class', 'loader col-centered'); + } + + // blocks given $component or whole screen of none given + this.startLoading = function($component) { + var params = { + message : this.getLoader(), + css: { + border: 'none', + padding: '15px', + backgroundColor: 'transparent', + }, + overlayCSS: { + opacity : 0.1, + } + }; + if ($component) { + $component.block(params); + } else { + $.blockUI(params); + } + } + + // unblocks given $component or whole screen of none given + this.stopLoading = function($component) { + if ($component) { + $component.unblock(); + } else { + $.unblockUI(); + } + } +} \ No newline at end of file diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/plugin.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..b6803e35362dff0ecd780bb4c5a171bc4d21425d --- /dev/null +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/plugin.js @@ -0,0 +1,37 @@ +function BBBHubTechnology() { + this.init(); +} + +$.extend(BBBHubTechnology.prototype, ELNLIMSPlugin.prototype, { + // This code is copy of openBis plugin. It was taken from here: + // https://sissource.ethz.ch/sis/bbb-hub/tree/master/openbis/core-plugins/bbb-hub/1/as/webapps/snakemake/html/js + // Now it is a ELN plugin. + + init: function() { + loadJSResorce("./plugins/bbb-hub/UiComponents.js"); + loadJSResorce("./plugins/bbb-hub/BBBServerFacade.js"); + loadJSResorce("./plugins/bbb-hub/snakemake-table.js"); + loadJSResorce("./plugins/bbb-hub/snakemake-trigger.js"); + }, + + experimentFormTop : function($container, model) { + BBBServerFacade.getExperiment($container, model); + }, + + experimentFormBottom : function($container, model) { + }, + + getExtraUtilities : function() { + return [{ + icon : "fa fa-table", + uniqueViewName : "BBB_VIEW_NAME_TEST", + label : "Snakemake", + paintView : function($header, $content) { + $header.append($("<h1>").append("Public Index Page")); + BBBServerFacade.getExperiments($content); + } + }]; + } +}); + +profile.plugins.push(new BBBHubTechnology()); \ No newline at end of file diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/snakemake-table.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/snakemake-table.js new file mode 100644 index 0000000000000000000000000000000000000000..a6add5714f1bd889e0379b02921fe668b826fe0a --- /dev/null +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/snakemake-table.js @@ -0,0 +1,169 @@ +var SnakemakeTable = new function() { + + this.paintTable = function(container, experiments, roles) { + var columns = []; + + columns.push({ + label : 'Code', + property : 'code', + isExportable: false, + sortable : true + }); + + columns.push({ + label : 'Description', + property : 'description', + isExportable: false, + sortable : true + }); + + columns.push({ + label : 'Group', + property : 'group', + isExportable: false, + sortable : true + }); + + columns.push({ + label : 'E-mail', + property : 'email', + isExportable: false, + sortable : true + }); + + columns.push({ + label : 'Special access', + property : 'specialAccess', + isExportable: false, + sortable : true + }); + + var getDataList = function(callback) { + var entities = []; + + var rolesMap = SnakemakeTable.rolesMap(roles); + + var dataList = []; + + for (i = 0; i < experiments.length; i++) { + if (experiments[i].type === undefined || experiments[i].type.code !== "BBB") { + continue; + } + + var desc = experiments[i].properties["BBB.DESCRIPTION"]; + var group = experiments[i].properties["BBB.GROUP"]; + var registrator = experiments[i].registrator; + var projectCode = experiments[i].project.code; + var spaceCode = experiments[i].project.space.code; + + var model = { 'code' : experiments[i].code, + 'description' : desc === undefined ? "" : desc, + 'group' : group === undefined ? "" : group, + 'email' : registrator === null ? "" : registrator.email, + 'specialAccess' : SnakemakeTable.getSpecialAccess(rolesMap, projectCode, spaceCode) + }; + + dataList.push(model); + } + callback(dataList); + }; + + var dataGridController = new DataGridController(null, columns, [], null, getDataList, null, true, "ENTITY_TABLE_BBB", null, 90); + dataGridController.init(container); + } + + this.prepareData = function(experiments, roles) { + var data = []; + + var rolesMap = SnakemakeTable.rolesMap(roles); + + for (i = 0; i < experiments.length; i++) { + var row = []; + + if (experiments[i].type === undefined || experiments[i].type.code !== "BBB") { + continue; + } + + var desc = experiments[i].properties["BBB.DESCRIPTION"]; + var group = experiments[i].properties["BBB.GROUP"]; + var registrator = experiments[i].registrator; + var projectCode = experiments[i].project.code; + var spaceCode = experiments[i].project.space.code; + + row.push(experiments[i].code); + row.push(desc === undefined ? "" : desc); + row.push(group === undefined ? "" : group); + row.push(registrator === null ? "" : registrator.email); + row.push(SnakemakeTable.getSpecialAccess(rolesMap, projectCode, spaceCode)); + + data.push(row); + } + + return data; + } + + this.getSpecialAccess = function(rolesMap, projectCode, spaceCode) { + var projectUsers = rolesMap["projects"][projectCode] === undefined ? "" : rolesMap["projects"][projectCode]["users"].join(", "); + var projectGroups = rolesMap["projects"][projectCode] === undefined ? "" : rolesMap["projects"][projectCode]["groups"].join(", "); + + var spaceUsers = rolesMap["space"][spaceCode] === undefined ? "" : rolesMap["space"][spaceCode]["users"].join(", "); + var spaceGroups = rolesMap["space"][spaceCode] === undefined ? "" : rolesMap["space"][spaceCode]["groups"].join(", "); + + var users = projectUsers + (projectUsers !== "" && spaceUsers !== "" ? ", " : "") + spaceUsers; + var groups = projectGroups + (projectGroups !== "" && spaceGroups !== "" ? ", " : "") + spaceGroups; + + var access = ""; + if (users !== "") { + access += "<span style='font-weight:bold'>Users: </span>" + users; + } + + if (groups !== "") { + if (access !== "") { + access += "<br/>"; + } + access += "<span style='font-weight:bold'>Groups: </span>" + groups; + } + + return access; + } + + this.rolesMap = function(roles) { + var rolesMap = new Map(); + + var projects = new Map(); + var spaces = new Map(); + + rolesMap["projects"] = projects; + rolesMap["space"] = spaces; + + for (i = 0; i < roles.length; i++) { + var user = roles[i].user == null ? null : roles[i].user.userId; + var group = roles[i].authorizationGroup == null ? null : roles[i].authorizationGroup.code; + + if (roles[i].project !== null) { + var value = projects[roles[i].project.code]; + projects[roles[i].project.code] = SnakemakeTable.appendValue(value, user, group); + } else { + var value = spaces[roles[i].space.code]; + spaces[roles[i].space.code] = SnakemakeTable.appendValue(value, user, group); + } + } + + return rolesMap; + } + + this.appendValue = function(value, user, group) { + if (value === undefined) { + value = new Map(); + value["users"] = new Array(); + value["groups"] = new Array(); + } + + if (user !== null) { + value["users"].push(user); + } else { + value["groups"].push(group); + } + return value; + } +} \ No newline at end of file diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/snakemake-trigger.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/snakemake-trigger.js new file mode 100644 index 0000000000000000000000000000000000000000..a3756fdfc4a20c0d1432b9973209524ad2dbe27b --- /dev/null +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/plugins/bbb-hub/snakemake-trigger.js @@ -0,0 +1,161 @@ +var SnakemakeTrigger = new function() { + + var groups; + var propTypeCodeToLabelMap = {}; + var dataSetPaths; + var $formContainerAll; + var $formContainerGroups; + var $dropdownGroupBy; + var $dropdownGroup1; + var $dropdownGroup2; + var $button; + var $model; + + this.paintTriggerContainers = function($container, model, experiment) { + $model = model; + SnakemakeTrigger.paintFormContainers($container); + SnakemakeTrigger.paintProcessAll(); + SnakemakeTrigger.paintGroupBy(experiment); + SnakemakeTrigger.paintGroupValues(); + groups = SnakemakeTrigger.getGroups(experiment); + files = SnakemakeTrigger.getFiles(experiment); + } + + this.paintFormContainers = function($container) { + var $fieldsetAll = UiComponents.getFieldset("Process all comparisons"); + var $fieldsetGroups = UiComponents.getFieldset("Pick groups to compare"); + $formContainerAll = $('<div>').addClass('form-group'); + $formContainerGroups = $('<div>').addClass('form-group'); + $fieldsetAll.append($formContainerAll); + $fieldsetGroups.append($formContainerGroups); + $container.append($fieldsetAll).append($fieldsetGroups); + } + + this.paintProcessAll = function() { + var $buttonAll = UiComponents.getButton("Start processing", SnakemakeTrigger.startProcessingAll); + $formContainerAll.append($buttonAll); + } + + this.paintGroupBy = function(experiment) { + var groupByOptions = []; + if (experiment.samples.length > 0) { + var sample = experiment.samples[0]; + for (var i = 0; i < sample.type.propertyAssignments.length; i++) { + var propertyAssignment = sample.type.propertyAssignments[i]; + groupByOptions.push({ + label: propertyAssignment.propertyType.label, + value: propertyAssignment.propertyType.code, + }); + propTypeCodeToLabelMap[propertyAssignment.propertyType.code] = propertyAssignment.propertyType.label; + } + } + + $dropdownGroupBy = UiComponents.addDropdown("Group by", groupByOptions, $formContainerGroups, SnakemakeTrigger.paintGroupValues); + } + + this.paintGroupValues = function(propertyType) { + if (propertyType) { + var groupOptions = groups[propertyType].map(function(value) { return { + label: value, + value: value, + }}); + } else { + var groupOptions = []; + } + + if ($dropdownGroup1) { + $dropdownGroup1.remove(); + } + if ($dropdownGroup2) { + $dropdownGroup2.remove(); + } + if ($button) { + $button.remove(); + } + + $dropdownGroup1 = UiComponents.addDropdown("Group 1", groupOptions, $formContainerGroups); + $dropdownGroup2 = UiComponents.addDropdown("Group 2", groupOptions, $formContainerGroups); + + $button = UiComponents.getButton("Start processing", SnakemakeTrigger.startProcessing); + $button.css("margin-top", "20px"); + $formContainerGroups.append($button); + } + + this.getGroups = function(experiment) { + var groups = {}; + for (var i = 0; i < experiment.samples.length; i++) { + var sample = experiment.samples[i]; + // collect groups + for (var propertyKey in sample.properties) { + if (sample.properties.hasOwnProperty(propertyKey)) { + var propertyValue = sample.properties[propertyKey]; + if (groups.hasOwnProperty(propertyKey) == false) { + groups[propertyKey] = []; + } + if (groups[propertyKey].indexOf(propertyValue) == -1) { + groups[propertyKey].push(propertyValue); + } + } + } + } + return groups; + } + + this.getFiles = function(experiment) { + dataSetPaths = []; + for (var i = 0; i < experiment.dataSets.length; i++) { + var dataSet = experiment.dataSets[i]; + if (dataSet.type.code == "FASTQ" || dataSet.type.code == "METADATA") { + var path = dataSet.physicalData.shareId + "/" + dataSet.physicalData.location; + dataSetPaths.push(path); + } + } + } + + this.startProcessingAll = function() { + UiComponents.startLoading(); + var jsonrpc = { + "method": "start_processing_all", + "params": { + "data_set_paths": dataSetPaths + } + }; + BBBServerFacade.callCustomASService(jsonrpc, $model, function(result) { + UiComponents.stopLoading(); + if (result.success) { + alert("Processing started."); + } else { + alert("Error: " + result.data); + } + }); + } + + this.startProcessing = function() { + var groupSelection = { + groupBy: propTypeCodeToLabelMap[$dropdownGroupBy.getValue()], + group1: $dropdownGroup1.getValue(), + group2: $dropdownGroup2.getValue(), + } + if (!groupSelection.groupBy || !groupSelection.group1 || !groupSelection.group2) { + alert("Select both groups first."); + return; + } + UiComponents.startLoading(); + + var jsonrpc = { + "method": "start_processing", + "params": { + "group_selection": groupSelection, + "data_set_paths": dataSetPaths + } + }; + BBBServerFacade.callCustomASService(jsonrpc, $model, function(result) { + UiComponents.stopLoading(); + if (result.success) { + alert("Processing started."); + } else { + alert("Error: " + result.data); + } + }); + } +} \ No newline at end of file