diff --git a/frontend-js/src/main/js/Functions.js b/frontend-js/src/main/js/Functions.js index 2eefe04ecdc857e671300418d808b08c6b3da6d3..87849f8e7b8d3c06ea615b6d36023acea0fc4ff0 100644 --- a/frontend-js/src/main/js/Functions.js +++ b/frontend-js/src/main/js/Functions.js @@ -738,6 +738,10 @@ Functions.prototype.computeMD5 = function (s) { return i.toLowerCase() }; +Functions.prototype.isString = function (value) { + return (value instanceof String || typeof value === "string"); +}; + var singleton = new Functions(); module.exports = singleton; diff --git a/frontend-js/src/main/js/GuiConnector.js b/frontend-js/src/main/js/GuiConnector.js index dfaa7c33f62cdb082dfbec39257f5bbededeac9b..2f74cd06ebe9e40ced29e7a03c54e3d9e4b9992e 100644 --- a/frontend-js/src/main/js/GuiConnector.js +++ b/frontend-js/src/main/js/GuiConnector.js @@ -186,7 +186,7 @@ GuiConnector.prototype.updateMouseCoordinates = function (x, y) { /** * - * @param {string} messageText + * @param {string} [messageText] */ GuiConnector.prototype.showProcessing = function (messageText) { var self = returnThisOrSingleton(this); diff --git a/frontend-js/src/main/js/gui/export/AbstractExportPanel.js b/frontend-js/src/main/js/gui/export/AbstractExportPanel.js index 74db8cafbb709dbde80915db6eb5b372fbfec3a7..66d9f6f2a157c5c3753833b67a5721b4df067622 100644 --- a/frontend-js/src/main/js/gui/export/AbstractExportPanel.js +++ b/frontend-js/src/main/js/gui/export/AbstractExportPanel.js @@ -10,6 +10,14 @@ var Functions = require('../../Functions'); var DualListbox = require('dual-listbox').DualListbox; var Promise = require("bluebird"); +/** + * @typedef {Object} ExportColumn + * @property {string} columnName + * @property {string|function(BioEntity):Promise<string>} method + * @property {string} name + * @property {function(Object):string} formatFunction + */ + /** * * @param {Configuration} [params.configuration] @@ -59,7 +67,7 @@ function compareSimple(val1, val2) { * * @param annotations * @returns {HTMLElement} - * @private + * @protected */ AbstractExportPanel.prototype._createMiriamTypeDiv = function (annotations) { var self = this; @@ -128,7 +136,7 @@ AbstractExportPanel.prototype.createDualListbox = function (selectElement) { * * @param {BioEntityType[]} elementTypes * @returns {HTMLElement} - * @private + * @protected */ AbstractExportPanel.prototype._createSelectTypeDiv = function (elementTypes) { var typeDiv = Functions.createElement({ @@ -238,7 +246,7 @@ AbstractExportPanel.prototype._createSelectColumnDiv = function (columnTypes) { var row = Functions.createElement({ type: "li", content: "<div class=\"checkbox\"><label> <input type=\"checkbox\" name=\"column_" + columnType.columnName - + "\" value=\"" + columnType.columnName + "\" />" + columnType.name + "</label></div>", + + "\" value=\"" + columnType.columnName + "\" />" + columnType.name + "</label></div>", xss: false }); choicesContainer.appendChild(row); @@ -270,7 +278,7 @@ AbstractExportPanel.prototype.getSelectedMiriamTypes = function () { /** * - * @returns {Promise} + * @returns {Promise<ExportColumn[]>} */ AbstractExportPanel.prototype.getSelectedColumns = function () { var self = this; @@ -361,7 +369,7 @@ AbstractExportPanel.prototype._getAllCompartments = function () { /** * * @returns {HTMLElement} - * @private + * @protected */ AbstractExportPanel.prototype._createDownloadButton = function () { var self = this; @@ -407,7 +415,7 @@ AbstractExportPanel.prototype.getSaveFilename = function () { /** * * @returns {Promise<HTMLElement>} - * @private + * @protected */ AbstractExportPanel.prototype._createSelectIncludedCompartmentDiv = function () { var self = this; @@ -445,7 +453,7 @@ AbstractExportPanel.prototype._createSelectIncludedCompartmentDiv = function () /** * * @returns {Promise<HTMLElement>} - * @private + * @protected */ AbstractExportPanel.prototype._createSelectExcludedCompartmentDiv = function () { var self = this; @@ -456,7 +464,7 @@ AbstractExportPanel.prototype._createSelectExcludedCompartmentDiv = function () }); typeDiv.appendChild(Functions.createElement({ type: "h4", - content: " Excluded compartment/pathways:" + content: " Excluded compartment/pathway:" })); return self._getCompartmentNames().then(function (compartmentNames) { @@ -562,9 +570,9 @@ AbstractExportPanel.prototype.getSelectedExcludedCompartments = function () { /** * - * @param {{name:string}[]} columns - * @param {MiriamType[]> miriamTypes - * @returns {string} + * @param {ExportColumn[]} columns + * @param {MiriamType[]} miriamTypes + * @returns {Promise<string>} */ AbstractExportPanel.prototype.createResponseHeader = function (columns, miriamTypes) { var stringBuilder = []; @@ -577,7 +585,7 @@ AbstractExportPanel.prototype.createResponseHeader = function (columns, miriamTy var miriamType = miriamTypes[i]; stringBuilder.push(miriamType.getCommonName()); } - return stringBuilder.join("\t"); + return Promise.resolve(stringBuilder.join("\t")); }; diff --git a/frontend-js/src/main/js/gui/export/ElementExportPanel.js b/frontend-js/src/main/js/gui/export/ElementExportPanel.js index ceb0ddd96ddcb1839048ced00be0ef22d054869c..75786dc3c01fd80bcf14952f71ed9cc5fea6c976 100644 --- a/frontend-js/src/main/js/gui/export/ElementExportPanel.js +++ b/frontend-js/src/main/js/gui/export/ElementExportPanel.js @@ -3,7 +3,9 @@ /* exported logger */ var AbstractExportPanel = require('./AbstractExportPanel'); +var Functions = require('../../Functions'); var GuiMessageError = require('../GuiMessageError'); +var IdentifiedElement = require('../../map/data/IdentifiedElement'); var logger = require('../../logger'); @@ -112,38 +114,56 @@ ElementExportPanel.prototype.createResponseString = function () { return Promise.reject(new GuiMessageError("You must select at least one column")); } - var rows = []; - rows.push(self.createResponseHeader(selectedColumns, miriamTypes)); + var rowPromises = []; + rowPromises.push(self.createResponseHeader(selectedColumns, miriamTypes)); for (var i = 0; i < elements.length; i++) { - rows.push(self.createResponseRow(elements[i], selectedColumns, miriamTypes)); + rowPromises.push(self.createResponseRow(elements[i], selectedColumns, miriamTypes)); } - return rows.join("\n"); + return Promise.all(rowPromises).then(function (rows) { + return rows.join("\n"); + }); }); }; /** * - * @param {Alias} alias - * @param {Array} columns - * @param {MiriamType[]} miriamTypes - * @returns {string} + * @param {BioEntity} alias + * @param column + * @returns {Promise<string>} + * @private */ -ElementExportPanel.prototype.createResponseRow = function (alias, columns, miriamTypes) { - var stringBuilder = []; - var i, value; - for (i = 0; i < columns.length; i++) { - var column = columns[i]; - value = alias[column.method](); +ElementExportPanel.prototype._createResponseCell = function (alias, column) { + var valuePromise; + if (Functions.isString(column.method)) { + valuePromise = Promise.resolve(alias[column.method]()); + } else { + valuePromise = Promise.resolve(column.method(alias, this.getProject())); + } + return valuePromise.then(function (value) { if (column.formatFunction !== undefined) { value = column.formatFunction(value); } - if (value instanceof String || typeof value === "string") { + if (Functions.isString(value)) { value = value.replace(/[\n\r]/g, ' '); } - stringBuilder.push(value); + return value; + }); +}; +/** + * + * @param {Alias} alias + * @param {Array} columns + * @param {MiriamType[]} miriamTypes + * @returns {Promise<string>} + */ +ElementExportPanel.prototype.createResponseRow = function (alias, columns, miriamTypes) { + var valuePromises = []; + var i; + for (i = 0; i < columns.length; i++) { + valuePromises.push(this._createResponseCell(alias, columns[i])); } for (i = 0; i < miriamTypes.length; i++) { - value = ""; + var value = ""; var miriamType = miriamTypes[i]; var references = alias.getReferences(); for (var j = 0; j < references.length; j++) { @@ -152,14 +172,16 @@ ElementExportPanel.prototype.createResponseRow = function (alias, columns, miria value += reference.getResource() + ","; } } - stringBuilder.push(value); + valuePromises.push(value); } - return stringBuilder.join("\t"); + return Promise.all(valuePromises).then(function (values) { + return values.join("\t"); + }); }; /** * - * @returns {*[]} + * @returns {ExportColumn[]} */ ElementExportPanel.prototype.getAllColumns = function () { return [{ @@ -177,7 +199,18 @@ ElementExportPanel.prototype.getAllColumns = function () { }, { "columnName": "modelId", "method": "getModelId", - "name": "Model" + "name": "Map id" + }, { + /** + * + * @param {BioEntity} bioEntity + * @param {Project} project + * @returns {string} + */ + "method": function (bioEntity, project) { + return project.getModelById(bioEntity.getModelId()).getName(); + }, + "name": "Map name" }, { "columnName": "type", "method": "getType", @@ -185,11 +218,57 @@ ElementExportPanel.prototype.getAllColumns = function () { }, { "columnName": "complexId", "method": "getComplexId", - "name": "Complex" + "name": "Complex id" + }, { + /** + * + * @param {Alias} bioEntity + * @param {Project} project + * @returns {Promise<string>} + */ + "method": function (bioEntity, project) { + var modelId = bioEntity.getModelId(); + var complexId = bioEntity.getComplexId(); + if (complexId !== undefined) { + return project.getModelById(modelId).getByIdentifiedElement(new IdentifiedElement({ + id: complexId, + modelId: modelId, + type: "ALIAS" + }), true).then(function(complex){ + return complex.getName(); + }); + } else { + return Promise.resolve(""); + } + }, + "name": "Complex name" }, { "columnName": "compartmentId", "method": "getCompartmentId", - "name": "Compartment" + "name": "Compartment/Pathway id" + }, { + /** + * + * @param {Alias} bioEntity + * @param {Project} project + * @returns {Promise<string>} + */ + "method": function (bioEntity, project) { + var modelId = bioEntity.getModelId(); + var compartmentId = bioEntity.getCompartmentId(); + if (compartmentId !== undefined) { + return project.getModelById(modelId).getByIdentifiedElement(new IdentifiedElement({ + id: compartmentId, + modelId: modelId, + type: "ALIAS" + }), true).then(function(complex){ + return complex.getName(); + }); + } else { + return Promise.resolve(""); + } + }, + "name": "Compartment/Pathway name" }, { "columnName": "charge", "method": "getCharge", @@ -233,7 +312,7 @@ ElementExportPanel.prototype.getAllColumns = function () { }, { "columnName": "linkedSubmodelId", "method": "getLinkedSubmodelId", - "name": "Linked submodel" + "name": "Linked submap id" }, { "columnName": "elementId", "method": "getElementId", diff --git a/frontend-js/src/main/js/gui/export/NetworkExportPanel.js b/frontend-js/src/main/js/gui/export/NetworkExportPanel.js index dd90195a70b7e110394d283d92f38fca6ab7cbcc..1d69e3f3cb9ec791b6d1f06b4b0da6540911fb4c 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"); var logger = require('../../logger'); var GuiMessageError = require('../GuiMessageError'); +var Functions = require('../../Functions'); /** * @@ -95,11 +96,22 @@ NetworkExportPanel.prototype.getAllColumns = function () { }, { "columnName": "modelId", "method": "getModelId", - "name": "Model" + "name": "Map id" + }, { + /** + * + * @param {BioEntity} bioEntity + * @param {Project} project + * @returns {string} + */ + "method": function (bioEntity, project) { + return project.getModelById(bioEntity.getModelId()).getName(); + }, + "name": "Map name" }, { "columnName": "type", "method": "getType", - "name": "Type" + "name": "Reaction type" }, { "columnName": "symbol", "method": "getSymbol", @@ -131,7 +143,7 @@ NetworkExportPanel.prototype.getAllColumns = function () { }, { "columnName": "reactionId", "method": "getReactionId", - "name": "Element external id" + "name": "Reaction external id" }, { "columnName": "mechanicalConfidenceScore", "method": "getMechanicalConfidenceScore", @@ -237,11 +249,13 @@ NetworkExportPanel.prototype.createResponseString = function () { return Promise.reject(new GuiMessageError("You must select at least one column")); } - var rows = []; - rows.push(self.createResponseHeader(selectedColumns, miriamTypes)); + var rowPromises = []; + rowPromises.push(self.createResponseHeader(selectedColumns, miriamTypes)); for (var i = 0; i < reactions.length; i++) { - rows.push(self.createResponseRow(reactions[i], selectedColumns, miriamTypes, elementIds)); + rowPromises.push(self.createResponseRow(reactions[i], selectedColumns, miriamTypes, elementIds)); } + return Promise.all(rowPromises); + }).then(function (rows) { return rows.join("\n"); }); }; @@ -252,21 +266,13 @@ NetworkExportPanel.prototype.createResponseString = function () { * @param {Object} columns * @param {MiriamType[]} miriamTypes * @param {Object<string,boolean>} elementIds - * @returns {string} + * @returns {Promise<string>} */ NetworkExportPanel.prototype.createResponseRow = function (reaction, columns, miriamTypes, elementIds) { - var stringBuilder = []; + var valuePromises = []; var i, value; for (i = 0; i < columns.length; i++) { - var column = columns[i]; - value = reaction[column.method](); - if (column.formatFunction !== undefined) { - value = column.formatFunction(value, reaction, elementIds); - } - if (value instanceof String || typeof value === "string") { - value = value.replace(/[\n\r]/g, ' '); - } - stringBuilder.push(value); + valuePromises.push(this._createResponseCell(reaction, columns[i], elementIds)); } for (i = 0; i < miriamTypes.length; i++) { value = ""; @@ -278,9 +284,38 @@ NetworkExportPanel.prototype.createResponseRow = function (reaction, columns, mi value += reference.getResource() + ","; } } - stringBuilder.push(value); + valuePromises.push(value); + } + return Promise.all(valuePromises).then(function (values) { + return values.join("\t"); + }); +}; + +/** + * + * @param {Reaction} reaction + * @param {ExportColumn} column + * @param {Object<string,boolean>} elementIds + * @returns {Promise<string>} + * @private + */ +NetworkExportPanel.prototype._createResponseCell = function (reaction, column, elementIds) { + var valuePromise; + if (Functions.isString(column.method)) { + valuePromise = Promise.resolve(reaction[column.method]()); + } else { + valuePromise = Promise.resolve(column.method(reaction, this.getProject())); } - return stringBuilder.join("\t"); + + return valuePromise.then(function (value) { + if (column.formatFunction !== undefined) { + value = column.formatFunction(value, reaction, elementIds); + } + if (Functions.isString(value)) { + value = value.replace(/[\n\r]/g, ' '); + } + return value; + }); }; module.exports = NetworkExportPanel; diff --git a/frontend-js/src/main/js/map/data/MapModel.js b/frontend-js/src/main/js/map/data/MapModel.js index 0586050a26ec45b08cf8ad0c2ae677cf777a330a..beaa7095556abcd6435849332c19f3290d3ee02e 100644 --- a/frontend-js/src/main/js/map/data/MapModel.js +++ b/frontend-js/src/main/js/map/data/MapModel.js @@ -142,7 +142,7 @@ MapModel.prototype.getAliasById = function (id, complete) { /** * Returns {@link Alias} by identifier. * -* @param {number} id + * @param {number} id * identifier of the {@link Alias} * @returns {Promise<Alias>} by identifier */ @@ -638,7 +638,7 @@ MapModel.prototype.setTileSize = function (tileSize) { * * @param {IdentifiedElement} ie * @param {boolean} complete - * @returns {Promise} + * @returns {Promise<BioEntity|PointData>} */ MapModel.prototype.getByIdentifiedElement = function (ie, complete) { var self = this; 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 011f0beaa28a82ba806010d558b5f7f34040ce0c..7ae054ea43a11b081c926c0f37a498069ece178c 100644 --- a/frontend-js/src/test/js/gui/export/ElementExportPanel-test.js +++ b/frontend-js/src/test/js/gui/export/ElementExportPanel-test.js @@ -280,11 +280,60 @@ describe('ElementExportPanel', function () { project: helper.createProject(), configuration: helper.getConfiguration() }); - var alias = helper.createAlias(); + var alias = helper.createAlias(exportObject.getProject().getModels()[0]); var desc = "test\ntest2\n"; alias.setDescription(desc); - var rowString = exportObject.createResponseRow(alias, exportObject.getAllColumns(), []); - assert.ok(rowString.indexOf("test\ntest2\n") === -1); + return exportObject.createResponseRow(alias, exportObject.getAllColumns(), []).then(function (rowString) { + assert.ok(rowString.indexOf(desc) === -1); + }); + }); + it('complex name', function () { + var complexName = "Complex name2"; + var exportObject = new ElementExportPanel({ + element: testDiv, + project: helper.createProject(), + configuration: helper.getConfiguration() + }); + var alias = helper.createAlias(exportObject.getProject().getModels()[0]); + var complex = helper.createAlias(exportObject.getProject().getModels()[0]); + complex.setName(complexName); + alias.setComplexId(complex.getId()); + return exportObject.createResponseRow(alias, exportObject.getAllColumns(), []).then(function (rowString) { + assert.ok(rowString.indexOf(complexName) >= 0); + }); + }); + it('compartment name', function () { + var compartmentName = "Compartment name2"; + var exportObject = new ElementExportPanel({ + element: testDiv, + project: helper.createProject(), + configuration: helper.getConfiguration() + }); + var alias = helper.createAlias(exportObject.getProject().getModels()[0]); + var compartment = helper.createAlias(exportObject.getProject().getModels()[0]); + compartment.setName(compartmentName); + alias.setCompartmentId(compartment.getId()); + return exportObject.createResponseRow(alias, exportObject.getAllColumns(), []).then(function (rowString) { + assert.ok(rowString.indexOf(compartmentName) >= 0); + }); + }); + it('column with function manipulating data', function () { + var exportObject = new ElementExportPanel({ + element: testDiv, + project: helper.createProject(), + configuration: helper.getConfiguration() + }); + var alias = helper.createAlias(); + return exportObject.createResponseRow(alias, [{ + "columnName": "id", + "method": function (alias) { + return "Alias id: " + alias.getId(); + }, + "name": "Id" + }], []).then(function (rowString) { + assert.ok(rowString.indexOf("Alias id") >= 0); + assert.ok(rowString.indexOf(alias.getId() + "") >= 0); + }); }); }); diff --git a/frontend-js/src/test/js/gui/export/NetworkExportPanel-test.js b/frontend-js/src/test/js/gui/export/NetworkExportPanel-test.js index b7d041d431449944fec9de4b54a7fd1829d2a20f..eb0318e670fc89375ccc56d57ddaf4fec95da59b 100644 --- a/frontend-js/src/test/js/gui/export/NetworkExportPanel-test.js +++ b/frontend-js/src/test/js/gui/export/NetworkExportPanel-test.js @@ -34,4 +34,22 @@ describe('NetworkExportPanel', function () { }); }); + describe('createResponseRow', function () { + it('map name', function () { + var mapName = "map name2"; + var project = helper.createProject(); + var exportObject = new NetworkExportPanel({ + element: testDiv, + project: project, + configuration: helper.getConfiguration() + }); + var alias = helper.createAlias(exportObject.getProject().getModels()[0]); + project.getModels()[0].setName(mapName); + var reaction = helper.createReaction(project.getModels()[0], true); + return exportObject.createResponseRow(reaction, exportObject.getAllColumns(), [], []).then(function (rowString) { + assert.ok(rowString.indexOf(mapName) >= 0); + }); + }); + }); + }); diff --git a/frontend-js/src/test/js/helper.js b/frontend-js/src/test/js/helper.js index a3ee154868a21a0bcab028a081a782d359c0527d..51bca8ac121238feb49d2c031db6864bc98868ca 100644 --- a/frontend-js/src/test/js/helper.js +++ b/frontend-js/src/test/js/helper.js @@ -200,15 +200,17 @@ Helper.prototype.createUser = function () { /** * - * @param {AbstractCustomMap} [map] + * @param {AbstractCustomMap| MapModel} [map] * @returns {Alias} */ Helper.prototype.createAlias = function (map) { var mapId; - if (map === undefined) { - mapId = this.idCounter++; - } else { + if (map instanceof AbstractCustomMap) { + mapId = map.getId(); + } else if (map instanceof Model) { mapId = map.getId(); + } else { + mapId = this.idCounter++; } var result = new Alias({ idObject: this.idCounter++, @@ -223,8 +225,10 @@ Helper.prototype.createAlias = function (map) { }, references: [] }); - if (map !== undefined) { + if (map instanceof AbstractCustomMap) { map.getModel().addAlias(result); + } else if (map instanceof Model) { + map.addAlias(result); } return result; }; @@ -341,6 +345,7 @@ Helper.prototype.createReaction = function (map, complete) { result.setReactants([new Reactant({aliasId: this.createAlias(map)})]); result.setProducts([new Product({aliasId: this.createAlias(map)})]); result.setModifiers([]); + result.setReferences([]); } return result; }; @@ -462,10 +467,10 @@ Helper.prototype.createSbmlFunction = function () { "functionId": "fun", "name": "fun name", "definition": "<lambda>" + - "<bvar><ci> x </ci></bvar>" + - "<bvar><ci> y </ci></bvar>" + - "<apply><plus/><ci> x </ci><ci> y </ci><cn type=\"integer\"> 2 </cn></apply>" + - "</lambda>\n\n", + "<bvar><ci> x </ci></bvar>" + + "<bvar><ci> y </ci></bvar>" + + "<apply><plus/><ci> x </ci><ci> y </ci><cn type=\"integer\"> 2 </cn></apply>" + + "</lambda>\n\n", "arguments": ["x", "y"], "id": this.idCounter++ }); @@ -486,9 +491,9 @@ Helper.prototype.createKineticLaw = function () { return new KineticLaw({ "parameterIds": [], "definition": '<math xmlns="http://www.w3.org/1998/Math/MathML">' + - '<apply xmlns="http://www.w3.org/1998/Math/MathML">' + - '<divide/><apply><times/><ci>ca1</ci><apply><plus/><ci>sa1</ci><ci>sa2</ci></apply></apply><cn type=\"integer\"> 2 </cn>' + - '</apply></math>', + '<apply xmlns="http://www.w3.org/1998/Math/MathML">' + + '<divide/><apply><times/><ci>ca1</ci><apply><plus/><ci>sa1</ci><ci>sa2</ci></apply></apply><cn type=\"integer\"> 2 </cn>' + + '</apply></math>', "functionIds": [] }); };