diff --git a/frontend-js/src/main/js/gui/leftPanel/GenericSearchPanel.js b/frontend-js/src/main/js/gui/leftPanel/GenericSearchPanel.js index 30faa341b633ce1991ada5dc038ed710a36f6b43..931d88743cb4d3bbbc23cc1ed577d39d26de896d 100644 --- a/frontend-js/src/main/js/gui/leftPanel/GenericSearchPanel.js +++ b/frontend-js/src/main/js/gui/leftPanel/GenericSearchPanel.js @@ -9,6 +9,7 @@ var Alias = require('../../map/data/Alias'); var InvalidArgumentError = require('../../InvalidArgumentError'); var PanelControlElementType = require('../PanelControlElementType'); var Reaction = require('../../map/data/Reaction'); +var SearchBioEntityGroup = require('../../map/data/SearchBioEntityGroup'); // noinspection JSUnusedLocalSymbols var logger = require('../../logger'); @@ -52,6 +53,8 @@ GenericSearchPanel.prototype.createTableElement = function (element, icon) { return this.createAliasElement(element, icon); } else if (element instanceof Reaction) { return this.createReactionElement(element); + } else if (element instanceof SearchBioEntityGroup) { + return this.createSearchBioEntityGroupElement(element); } else { throw new Error("Unknown element type: " + element.constructor.name); } @@ -95,6 +98,21 @@ GenericSearchPanel.prototype.createAliasElement = function (alias, icon) { return result; }; +GenericSearchPanel.prototype.createSearchBioEntityGroupElement = function (group, icon) { + var self = this; + var guiUtils = self.getGuiUtils(); + + var result = document.createElement("tr"); + var td = document.createElement("td"); + result.appendChild(td); + var div = guiUtils.createSearchBioEntityGroupElement(group); + + div.appendChild(guiUtils.createSeparator()); + td.appendChild(div); + + return result; +}; + GenericSearchPanel.prototype.searchByQuery = function () { var self = this; var query = this.getControlElement(PanelControlElementType.SEARCH_INPUT).value; @@ -123,7 +141,7 @@ GenericSearchPanel.prototype.refreshSearchAutocomplete = function () { GenericSearchPanel.prototype.init = function () { var query = ServerConnector.getSessionData().getSearchQuery(); if (query !== undefined) { - return this.getOverlayDb().searchByEncodedQuery(query, false).catch(function(error){ + return this.getOverlayDb().searchByEncodedQuery(query, false).catch(function (error) { if (error instanceof InvalidArgumentError) { logger.warn(error.message); } else { diff --git a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js index 09fc55fa0769c2beab7a7cb6ced8db7b91a92841..f677c943f01e13bba742df4afb0fdadf9afef67c 100644 --- a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js +++ b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js @@ -2,6 +2,8 @@ /* exported logger */ +var Alias = require('../../map/data/Alias'); + var GuiConnector = require('../../GuiConnector'); var AbstractGuiElement = require('../AbstractGuiElement'); var Functions = require('../../Functions'); @@ -185,7 +187,7 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) { var annotators = this.getConfiguration().getAnnotators(); var annotatorsClassMapping = {}; for (var i = 0; i < annotators.length; i++) { - annotatorsClassMapping[annotators[i].getClassName()] = annotators[i]; + annotatorsClassMapping[annotators[i].getClassName()] = annotators[i]; } var grouppedAnnotations = {}; @@ -198,8 +200,8 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) { // = annotatorClasName ? annotatorsClassMapping[annotatorClasName].getName() : "Annotated by curator"; var cntAnnotations = 0; - - Object.keys(grouppedAnnotations).sort().forEach(function(annotatorClass){ + + Object.keys(grouppedAnnotations).sort().forEach(function (annotatorClass) { // var desc = grouppedAnnotations.keys()[i]; var groupContainer = (inline ? document.createElement("span") : document.createElement("div")); @@ -210,16 +212,16 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) { if (inline) { descContainer.innerHTML = annotatorName + ': '; } else { - descContainer.innerHTML = annotatorName; - + descContainer.innerHTML = annotatorName; + if (annotatorClass) { var annotatorDescription = annotatorsClassMapping[annotatorClass].getDescription(); if (annotatorDescription) { var tooltipContainer = Functions.createElement({ - type: "span" + type: "span" }); tooltipContainer.appendChild(Functions.createElement({ - type: "span", + type: "span", className: "glyphicon glyphicon-question-sign tooltip-icon" })); tooltipContainer.appendChild(Functions.createElement({ @@ -230,19 +232,19 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) { descContainer.appendChild(tooltipContainer); } - } - } + } + } descContainer.className = "minerva-annotation-group-header"; if (!inline) groupContainer.className = "minerva-annotation-group"; groupContainer.appendChild(descContainer); - if (inline){ + if (inline) { var par = document.createElement("span"); par.innerHTML = "("; groupContainer.appendChild(par); } - grouppedAnnotations[annotatorClass] = grouppedAnnotations[annotatorClass].sort(function(a, b) { + grouppedAnnotations[annotatorClass] = grouppedAnnotations[annotatorClass].sort(function (a, b) { const aType = a.getType().toUpperCase(); const bType = b.getType().toUpperCase(); if (aType < bType) return -1; @@ -258,9 +260,9 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) { var link = self.createAnnotationLink(element, showType); if (inline) { if (j > 0) { - var coma = document.createElement("span"); - coma.innerHTML = ", "; - groupContainer.appendChild(coma); + var coma = document.createElement("span"); + coma.innerHTML = ", "; + groupContainer.appendChild(coma); } groupContainer.appendChild(link); } else { @@ -268,9 +270,9 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) { var row = document.createElement("div"); row.style.height = "26px"; if (j % 2 === 0) { - row.className = "minerva-annotation-row-odd"; + row.className = "minerva-annotation-row-odd"; } else { - row.className = "minerva-annotation-row-even"; + row.className = "minerva-annotation-row-even"; } var header = document.createElement("div"); @@ -287,15 +289,15 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) { } } - if (inline){ - var par = document.createElement("span"); - par.innerHTML = ")"; - groupContainer.appendChild(par); + if (inline) { + var par = document.createElement("span"); + par.innerHTML = ")"; + groupContainer.appendChild(par); } result.appendChild(groupContainer); }); - + return result; }; @@ -441,7 +443,6 @@ GuiUtils.prototype.createReactionElement = function (params) { div.appendChild(self.createReactantsLine(reaction.getReactants())); div.appendChild(self.createProductsLine(reaction.getProducts())); div.appendChild(self.createModifiersLine(reaction.getModifiers())); - div.appendChild(self.createCandidates("Candidates: ", reaction.getOther('dataMining'))); div.appendChild(self.createAnnotations("Annotations: ", reaction.getReferences())); return div; }; @@ -480,11 +481,17 @@ GuiUtils.prototype.createAliasElement = function (params) { div.appendChild(self.createParamLine("Charge: ", alias.getCharge())); div.appendChild(self.createArrayParamLine("Synonyms: ", alias.getSynonyms())); div.appendChild(self.createLabelText(alias.getDescription())); - div.appendChild(self.createCandidates("Candidates: ", alias.getOther('dataMining'))); - div.appendChild(self.createChebiTree("Chebi ontology: ", alias.getOther('chebiTree'))); + // div.appendChild(self.createChebiTree("Chebi ontology: ", alias.getOther('chebiTree'))); div.appendChild(self.createAnnotations("Annotations: ", alias.getReferences())); return div; }; +GuiUtils.prototype.createSearchBioEntityGroupElement = function (group) { + if (group.getBioEntities()[0] instanceof Alias) { + return this.createAliasElement({alias:group, icon:group.getIcon()}); + } else { + return this.createReactionElement({reaction:group, icon:group.getIcon()}); + } +}; GuiUtils.prototype.createReactantsLine = function (label, value) { var result = document.createElement("div"); diff --git a/frontend-js/src/main/js/map/data/SearchBioEntityGroup.js b/frontend-js/src/main/js/map/data/SearchBioEntityGroup.js index f444b4e1deff425472a0590f45fa098b9f2917d5..cfb18a2d9050a4cb68cd59b36bb67b0c2b89d03e 100644 --- a/frontend-js/src/main/js/map/data/SearchBioEntityGroup.js +++ b/frontend-js/src/main/js/map/data/SearchBioEntityGroup.js @@ -100,5 +100,124 @@ SearchAliasGroup.prototype.getIcon = function () { return this._icon; }; +//aggregated data +SearchAliasGroup.prototype.getType = function () { + return this._bioEntites[0].getType(); +}; + +SearchAliasGroup.prototype.getName = function () { + return this._bioEntites[0].getName(); +}; + +SearchAliasGroup.prototype.getModelId = function () { + return this._bioEntites[0].getModelId(); +}; + +SearchAliasGroup.prototype.getReactants = function () { + return this._bioEntites[0].getReactants(); +}; +SearchAliasGroup.prototype.getProducts = function () { + return this._bioEntites[0].getProducts(); +}; +SearchAliasGroup.prototype.getModifiers = function () { + return this._bioEntites[0].getModifiers(); +}; + +SearchAliasGroup.prototype.getFullName = function () { + return this.getMergedParameterByFunction("getFullName"); +}; + +SearchAliasGroup.prototype.getReactionId = function () { + return this.getMergedParameterByFunction("getReactionId"); +}; +SearchAliasGroup.prototype.getLinkedSubmodelId = function () { + return this.getMergedParameterByFunction("getLinkedSubmodelId"); +}; +SearchAliasGroup.prototype.getSymbol = function () { + return this.getMergedParameterByFunction("getSymbol"); +}; +SearchAliasGroup.prototype.getAbbreviation = function () { + return this.getMergedParameterByFunction("getAbbreviation"); +}; +SearchAliasGroup.prototype.getFormula = function () { + return this.getMergedParameterByFunction("getFormula"); +}; +SearchAliasGroup.prototype.getMechanicalConfidenceScore = function () { + return this.getMergedParameterByFunction("getMechanicalConfidenceScore"); +}; +SearchAliasGroup.prototype.getLowerBound = function () { + return this.getMergedParameterByFunction("getLowerBound"); +}; +SearchAliasGroup.prototype.getUpperBound = function () { + return this.getMergedParameterByFunction("getUpperBound"); +}; +SearchAliasGroup.prototype.getGeneProteinReaction = function () { + return this.getMergedParameterByFunction("getGeneProteinReaction"); +}; +SearchAliasGroup.prototype.getSubsystem = function () { + return this.getMergedParameterByFunction("getSubsystem"); +}; +SearchAliasGroup.prototype.getDescription = function () { + return this.getMergedParameterByFunction("getDescription"); +}; +SearchAliasGroup.prototype.getCharge = function () { + return this.getMergedParameterByFunction("getCharge"); +}; +SearchAliasGroup.prototype.getSynonyms = function () { + return this.getIntersectionListByFunction("getSynonyms"); +}; +SearchAliasGroup.prototype.getFormerSymbols = function () { + return this.getIntersectionListByFunction("getFormerSymbols"); +}; + +SearchAliasGroup.prototype.getReferences = function () { + return this.getIntersectionListByFunction("getReferences"); +}; + +SearchAliasGroup.prototype.getOther = function (param) { + if (param === "modifications") { + return this.getIntersectionListByFunction(function (alias) { + return alias.getOther(param) + }); + } else { + throw new Error("Don't now how to handle: " + param); + } +}; + +SearchAliasGroup.prototype.getMergedParameterByFunction = function (functionName) { + var bioEntities = this.getBioEntities(); + var result = bioEntities[0][functionName](); + for (var i = 1; i < bioEntities.length; i++) { + var newEntry = bioEntities[i][functionName](); + if (newEntry !== result) { + result = "Value different among merged elements"; + } + } + return result; +}; + +SearchAliasGroup.prototype.getIntersectionListByFunction = function (functionName, comparator) { + var bioEntities = this.getBioEntities(); + var result; + if (typeof functionName === "function") { + result = functionName(bioEntities[0]); + } else { + result = bioEntities[0][functionName](); + } + for (var i = 1; i < bioEntities.length; i++) { + var newList; + if (typeof functionName === "function") { + newList = functionName(bioEntities[i]); + } else { + newList = bioEntities[0][functionName](); + } + //intersection of two arrays + result = result.filter(function (n) { + return newList.indexOf(n) !== -1; + }); + } + return result; +}; + module.exports = SearchAliasGroup; diff --git a/frontend-js/src/main/js/map/overlay/SearchDbOverlay.js b/frontend-js/src/main/js/map/overlay/SearchDbOverlay.js index a642c3ff7e67b3c14178b19717a47218ea158319..915480fce82e8b40214c74172748461598a4fe89 100644 --- a/frontend-js/src/main/js/map/overlay/SearchDbOverlay.js +++ b/frontend-js/src/main/js/map/overlay/SearchDbOverlay.js @@ -46,21 +46,35 @@ SearchDbOverlay.prototype.getElementsByQuery = function (query) { var model = self.getMap().getSubmapById(elements[0].getModelId()).getModel(); promises.push(model.getByIdentifiedElement(elements[i], true)); } - return Promise.all(promises).then(function (fullElements) { + return Promise.all(promises).then(function (elements) { var result = []; var iconCounter = 1; - for (var i = 0; i < fullElements.length; i++) { - var element = fullElements[i]; - var icon; - if (element instanceof Alias) { - icon = self.getIcon(queryId, iconCounter++); - } else if (!(element instanceof Reaction)) { - throw new Error("Unknown element type: " + element.getType()); + var groups = []; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + var alreadyExists = false; + var group; + for (var j = 0; j < groups.length; j++) { + group = groups[j]; + if (group.bioEntityMatch(element)) { + alreadyExists = true; + group.addBioEntity(element); + } + } + + if (!alreadyExists) { + var icon; + if (element instanceof Alias) { + icon = self.getIcon(queryId, iconCounter++) + } + group = new SearchBioEntityGroup(element); + group.setIcon(icon); + groups.push(group); + result.push({ + element: group, + icon: icon + }); } - result.push({ - element: element, - icon: icon - }); } return result; });