From c1b73c88cd3239e2ebbadaf6132e4b4a79484edb Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Thu, 20 Dec 2018 15:26:23 +0100
Subject: [PATCH] export of reactions allows filtering by reaction type

---
 frontend-js/src/main/js/Configuration.js      | 19 +++++++++
 .../main/js/gui/export/AbstractExportPanel.js | 23 ++++++++---
 .../main/js/gui/export/NetworkExportPanel.js  | 39 ++++++++++++++-----
 .../js/gui/export/ElementExportPanel-test.js  |  8 +++-
 4 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/frontend-js/src/main/js/Configuration.js b/frontend-js/src/main/js/Configuration.js
index 230456ab5f..e0245933d5 100644
--- a/frontend-js/src/main/js/Configuration.js
+++ b/frontend-js/src/main/js/Configuration.js
@@ -322,6 +322,25 @@ Configuration.prototype.getSimpleElementTypeNames = function () {
   return result;
 };
 
+/**
+ *
+ * @return {string[]}
+ */
+Configuration.prototype.getReactionTypeNames = function () {
+  var classesToBeExcluded = {};
+  var i;
+  for (i = 0; i < this._reactionTypes.length; i++) {
+    classesToBeExcluded[this._reactionTypes[i].parentClass] = true;
+  }
+  var result = [];
+  for (i = 0; i < this._reactionTypes.length; i++) {
+    if (classesToBeExcluded[this._reactionTypes[i].className] === undefined) {
+      result.push(this._reactionTypes[i].name);
+    }
+  }
+  return result;
+};
+
 /**
  *
  * @param {BioEntityType[]} reactionTypes
diff --git a/frontend-js/src/main/js/gui/export/AbstractExportPanel.js b/frontend-js/src/main/js/gui/export/AbstractExportPanel.js
index 39cfcd95e1..345bac1d52 100644
--- a/frontend-js/src/main/js/gui/export/AbstractExportPanel.js
+++ b/frontend-js/src/main/js/gui/export/AbstractExportPanel.js
@@ -135,17 +135,21 @@ AbstractExportPanel.prototype.createDualListbox = function (selectElement) {
 /**
  *
  * @param {BioEntityType[]} elementTypes
+ * @param {string} [panelName]
  * @returns {HTMLElement}
  * @protected
  */
-AbstractExportPanel.prototype._createSelectTypeDiv = function (elementTypes) {
+AbstractExportPanel.prototype._createSelectTypeDiv = function (elementTypes, panelName) {
+  if (panelName === undefined) {
+    panelName = " TYPE:";
+  }
   var typeDiv = Functions.createElement({
     type: "div",
     name: "typeSelectDiv"
   });
   typeDiv.appendChild(Functions.createElement({
     type: "h4",
-    content: " TYPE:"
+    content: panelName
   }));
   var choicesContainer = Functions.createElement({
     type: "ul",
@@ -181,12 +185,16 @@ AbstractExportPanel.prototype._createSelectTypeDiv = function (elementTypes) {
 
 /**
  *
+ * @param {HTMLElement} [htmlElement]
  * @returns {Promise<BioEntityType[]>}
  */
-AbstractExportPanel.prototype.getSelectedTypes = function () {
+AbstractExportPanel.prototype.getSelectedTypes = function (htmlElement) {
   var self = this;
+  if (htmlElement === undefined) {
+    htmlElement = self.getElement();
+  }
 
-  var div = $("div[name='typeSelectDiv']", $(self.getElement()))[0];
+  var div = $("div[name='typeSelectDiv']", $(htmlElement))[0];
   var result = [];
   var selectedAll = false;
   $(":checked", $(div)).each(function (index, element) {
@@ -196,8 +204,11 @@ AbstractExportPanel.prototype.getSelectedTypes = function () {
     result.push(element.value);
   });
   if (selectedAll) {
-    return ServerConnector.getConfiguration().then(function (configuration) {
-      return configuration.getSimpleElementTypeNames();
+    result = [];
+    $("input[type='checkbox']", $(div)).each(function (index, element) {
+      if (element.value !== "ALL") {
+        result.push(element.value);
+      }
     });
   }
 
diff --git a/frontend-js/src/main/js/gui/export/NetworkExportPanel.js b/frontend-js/src/main/js/gui/export/NetworkExportPanel.js
index b681dad5c9..cc5941f297 100644
--- a/frontend-js/src/main/js/gui/export/NetworkExportPanel.js
+++ b/frontend-js/src/main/js/gui/export/NetworkExportPanel.js
@@ -7,6 +7,7 @@ var AbstractExportPanel = require('./AbstractExportPanel');
 var Promise = require("bluebird");
 // noinspection JSUnusedLocalSymbols
 var logger = require('../../logger');
+var Functions = require('../../Functions');
 var GuiMessageError = require('../GuiMessageError');
 var Alias = require('../../map/data/Alias');
 
@@ -39,8 +40,12 @@ NetworkExportPanel.prototype.init = function () {
   var self = this;
   var element = self.getElement();
   var configuration = self.getConfiguration();
-  var typeDiv = self._createSelectTypeDiv(configuration.getElementTypes());
-  element.appendChild(typeDiv);
+  var elementTypeDiv = Functions.createElement({type: "div", name: "elementTypes"});
+  elementTypeDiv.appendChild(self._createSelectTypeDiv(configuration.getElementTypes(), "Element type"));
+  element.appendChild(elementTypeDiv);
+  var reactionTypeDiv = Functions.createElement({type: "div", name: "reactionTypes"});
+  reactionTypeDiv.appendChild(self._createSelectTypeDiv(configuration.getReactionTypes(), "Reaction type"));
+  element.appendChild(reactionTypeDiv);
   element.appendChild(self._createSelectColumnDiv(self.getAllColumns()));
   return self.getServerConnector().getProjectStatistics(self.getProject().getProjectId()).then(function (statistics) {
     return self._createMiriamTypeDiv(statistics.getReactionAnnotations());
@@ -118,6 +123,10 @@ NetworkExportPanel.prototype.getAllColumns = function () {
     "columnName": "subsystem",
     "method": "getSubsystem",
     "name": "Subsystem"
+  }, {
+    "columnName": "type",
+    "method": "getType",
+    "name": "Reaction type"
   }]);
 };
 
@@ -125,9 +134,13 @@ NetworkExportPanel.prototype.getAllColumns = function () {
  *
  * @param {Reaction} reaction
  * @param {Object<string,boolean>} elementIds
+ * @param {string[]} reactionTypes
  * @returns {boolean}
  */
-function matchReaction(reaction, elementIds) {
+function matchReaction(reaction, elementIds, reactionTypes) {
+  if ($.inArray(reaction.getType(), reactionTypes) === -1) {
+    return false;
+  }
   var count = 0;
   reaction.getElements().forEach(function (element) {
     if (elementIds[element.getId()]) {
@@ -143,18 +156,26 @@ function matchReaction(reaction, elementIds) {
  */
 NetworkExportPanel.prototype.createResponseString = function () {
   var self = this;
-  var types, miriamTypes;
+  var elementTypes, reactionTypes, miriamTypes;
   var includedCompartmentIds = [];
   var excludedCompartmentIds = [];
   var models = self.getProject().getModels();
 
   var elementIds = [];
   var reactions = [];
-  return self.getSelectedTypes().then(function (result) {
+  var elementTypesDiv = $("[name='elementTypes']", self.getElement())[0];
+  var reactionTypesDiv = $("[name='reactionTypes']", self.getElement())[0];
+  return self.getSelectedTypes(elementTypesDiv).then(function (result) {
+    if (result.length === 0) {
+      return Promise.reject(new GuiMessageError("You must select at least one element type"));
+    }
+    elementTypes = result;
+    return self.getSelectedTypes(reactionTypesDiv);
+  }).then(function (result) {
     if (result.length === 0) {
-      return Promise.reject(new GuiMessageError("You must select at least one type"));
+      return Promise.reject(new GuiMessageError("You must select at least one reaction type"));
     }
-    types = result;
+    reactionTypes = result;
     return self.getSelectedIncludedCompartments();
   }).then(function (result) {
     result.forEach(function (compartment) {
@@ -169,7 +190,7 @@ NetworkExportPanel.prototype.createResponseString = function () {
     var promises = [];
     for (var i = 0; i < models.length; i++) {
       promises.push(models[i].getAliases({
-        type: types,
+        type: elementTypes,
         complete: true,
         includedCompartmentIds: includedCompartmentIds,
         excludedCompartmentIds: excludedCompartmentIds
@@ -189,7 +210,7 @@ NetworkExportPanel.prototype.createResponseString = function () {
     for (var i = 0; i < models.length; i++) {
       for (var j = 0; j < reactionsByModel[i].length; j++) {
         var reaction = reactionsByModel[i][j];
-        if (matchReaction(reaction, elementIds)) {
+        if (matchReaction(reaction, elementIds, reactionTypes)) {
           reactions.push(reaction);
         }
       }
diff --git a/frontend-js/src/test/js/gui/export/ElementExportPanel-test.js b/frontend-js/src/test/js/gui/export/ElementExportPanel-test.js
index be02659da4..65a91982ef 100644
--- a/frontend-js/src/test/js/gui/export/ElementExportPanel-test.js
+++ b/frontend-js/src/test/js/gui/export/ElementExportPanel-test.js
@@ -42,9 +42,13 @@ describe('ElementExportPanel', function () {
     it('select all', function () {
       var exportObject;
       var project;
-      var elementTypes;
 
-      elementTypes = helper.getConfiguration().getSimpleElementTypeNames();
+      function onlyUnique(value, index, self) {
+        return self.indexOf(value) === index;
+      }
+
+      var elementTypes = helper.getConfiguration().getSimpleElementTypeNames().filter(onlyUnique);
+
       return ServerConnector.getProject().then(function (result) {
         project = result;
         exportObject = createExportPanel(project);
-- 
GitLab