diff --git a/CHANGELOG b/CHANGELOG index a8ef67f3248b745a13ab77d99645193f99ad2aa0..4e1287a8609cdd05bd11df92736483a4a56f4d34 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,14 +1,14 @@ minerva (14.0.0~alpha.1) unstable; urgency=low * Feature removal: support for tomcat7 removed (#828) * Small improvement: debian package can be installed on debian:buster (#879) - * Bug fix: REST API bioEntities:search method didn't limit results to the + * Bug fix: REST API bioEntities:search method didn't limit results to the submodel id (#860) * Bug fix: Empty Overlay colours were not preserved during export to CellDesigner (#714) - * Bug fix: some project couldn't be accessed due to problem with migration of + * Bug fix: some project couldn't be accessed due to problem with migration of reaction with unknown boolean operator (#880) * Bug fix: problem with unloading plugin is properly handled (#884) - * Bug fix: upload of invalid plugin doesn't add it to plugin tab and list of + * Bug fix: upload of invalid plugin doesn't add it to plugin tab and list of loaded plugins (#885) * Bug fix: link to molart was brokwn (#886) * Bug fix: context menu visualization fixed @@ -17,16 +17,16 @@ minerva (14.0.0~alpha.1) unstable; urgency=low -- Piotr Gawron <piotr.gawron@uni.lu> Mon, 13 Aug 2019 21:00:00 +0200 minerva (14.0.0~alpha.0) unstable; urgency=low - * Feature: security layer redesigned - privilege types and scope changed + * Feature: security layer redesigned - privilege types and scope changed (#636, #624) * Feature: log4j is replaced with log4j2 logging mechanism (#291) * Feature: database installed via debian package is done via dbconfig-commons (#469) * Feature: Replaced connection pool manager C3P0 with better maintained - Hikari - restart of postgresql database doesn't require restart of tomcat + Hikari - restart of postgresql database doesn't require restart of tomcat (#564) * Feature removal: BioCompendium annotator removed (#32) - * Small improvement: anonymous login is no longer required - each API query + * Small improvement: anonymous login is no longer required - each API query outside session is authorized with anonymous user privileges (#629) * Small improvement: bcrypt is used for password encryption (#387) * Small improvement: caching is active by default for new users when @@ -34,14 +34,14 @@ minerva (14.0.0~alpha.0) unstable; urgency=low * Small improvement: when removing overlay in admin panel there is a confirmation dialog (#696) * Small improvement: overlay name is obligatory (#698) - * Small improvement: list of projects in admin panel contains creation date + * Small improvement: list of projects in admin panel contains creation date (#447) * Small improvement: links in list of publications open in new tab (#447) * Small improvement: target gene in search panel contains also information about type of database that identifies the target (#66) - * Small improvement: redundant 'references' field in gene variants data + * Small improvement: redundant 'references' field in gene variants data overlay is now deprecated (#850) - * Small improvement: information about deprecated columns in data overlay is + * Small improvement: information about deprecated columns in data overlay is visible in overlay list (#838) * Small improvement: publication list is resizeable (#740) * Small improvement: user list on project edit dialog is sortable (#808) @@ -60,6 +60,21 @@ minerva (14.0.0~alpha.0) unstable; urgency=low -- Piotr Gawron <piotr.gawron@uni.lu> Fri, 09 Aug 2019 10:00:00 +0200 +minerva (13.1.4) stable; urgency=medium + * Bug fix:search by drugs didn't check synonyms in chembl database + + -- Piotr Gawron <piotr.gawron@uni.lu> Wed, 21 Aug 2019 17:00:00 +0200 + +minerva (13.1.3) stable; urgency=medium + * Bug fix: refreshing list of projects or list of users doesn't change active + page (#870) + * Bug fix: submap list must be selected to export from every submap (#874) + * Bug fix: export map as image properly uses bottom limit (#875) + * Bug fix: reaction info window wasn't closed on CLEAR (#876) + * Bug fix: name of the uploaded file is displayed when adding overlay (#849) + + -- Piotr Gawron <piotr.gawron@uni.lu> Wed, 14 Aug 2019 17:00:00 +0200 + minerva (13.1.2) stable; urgency=medium * Bug fix: Information about problematic zip file is more specific (#865) * Bug fix: Url didn't contain list of opened plugins and they weren't reload @@ -77,7 +92,7 @@ minerva (13.1.1) stable; urgency=medium * Bug fix: user wasn't logged out in all tabs when the log out event appeard in only one of them (#847) - -- Piotr Gawron <piotr.gawron@uni.lu> Tue, 2 Jul 2019 19:00:00 +0200 + -- Piotr Gawron <piotr.gawron@uni.lu> Tue, 2 Jul 2019 19:00:00 +0200 minerva (13.1.0) stable; urgency=medium * Feature: annotators are more flexible - you can define set of input and diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChEMBLParser.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChEMBLParser.java index 37a429c6f0d4c4be1e3d3a0500ec74179f091fea..0f553690da62c7dd3bb5fdcc9298c51120d20ebb 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChEMBLParser.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChEMBLParser.java @@ -52,6 +52,12 @@ public class ChEMBLParser extends DrugAnnotation implements IExternalService { * Url that access data of drug identified by name. */ private static final String DRUG_NAME_API_URL = "https://www.ebi.ac.uk/chembl/api/data/molecule?pref_name__exact="; + + /** + * Url that access data of drug identified by name. + */ + private static final String DRUG_SYNONYM_API_URL = "https://www.ebi.ac.uk/chembl/api/data/molecule?molecule_synonyms__molecule_synonym__iexact="; + /** * Url that access target by identifier. */ @@ -324,29 +330,22 @@ public class ChEMBLParser extends DrugAnnotation implements IExternalService { String page = getWebPageContent(accessUrl); Document document = XmlParser.getXmlDocumentFromString(page); - Node response = XmlParser.getNode("response", document.getChildNodes()); - Node molecules = XmlParser.getNode("molecules", response.getChildNodes()); - - NodeList list = molecules.getChildNodes(); - - for (int i = 0; i < list.getLength(); i++) { - Node node = list.item(i); - if (node.getNodeType() == Node.ELEMENT_NODE) { - if (node.getNodeName().equalsIgnoreCase("molecule")) { - if (drug == null) { - drug = parseDrug(node); - } else { - logger.warn("More drugs than one found for query: " + query); - } - } - } + List<Drug> drugs = extractDrugsFromDocument(document); + if (drugs.size()==0) { + accessUrl = DRUG_SYNONYM_API_URL + name; + page = getWebPageContent(accessUrl); + document = XmlParser.getXmlDocumentFromString(page); + drugs = extractDrugsFromDocument(document); + } + if (drugs.size()>1) { + logger.warn("More drugs than one found for query: " + query); } - if (drug == null) { + if (drugs.size() == 0) { return null; } - setCacheValue(query, getDrugSerializer().objectToString(drug)); - return drug; + setCacheValue(query, getDrugSerializer().objectToString(drugs.get(0))); + return drugs.get(0); } catch (IOException e) { throw new DrugSearchException("Problem with accessing CHEMBL database", e); } catch (InvalidXmlSchemaException e) { @@ -354,6 +353,24 @@ public class ChEMBLParser extends DrugAnnotation implements IExternalService { } } + private List<Drug> extractDrugsFromDocument(Document document) throws DrugSearchException { + List<Drug> result = new ArrayList<>(); + Node response = XmlParser.getNode("response", document.getChildNodes()); + Node molecules = XmlParser.getNode("molecules", response.getChildNodes()); + + NodeList list = molecules.getChildNodes(); + + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + if (node.getNodeName().equalsIgnoreCase("molecule")) { + result.add(parseDrug(node)); + } + } + } + return result; + } + @Override public List<Drug> getDrugListByTarget(MiriamData target, Collection<MiriamData> organisms) throws DrugSearchException { diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChEMBLParserTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChEMBLParserTest.java index dfe8729b8fc362065fc9077d4eec3fe113d3f79a..ff25cddd78eac023de8094f8f4a40b6bf8b80dab 100644 --- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChEMBLParserTest.java +++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChEMBLParserTest.java @@ -877,4 +877,16 @@ public class ChEMBLParserTest extends AnnotationTestFunctions { } } + @Test + public void testFindDrugBryBrandName() throws Exception { + try { + Drug drug = chemblParser.findDrug("picato"); + assertNotNull(drug); + assertEquals("CHEMBL1863513", drug.getSources().get(0).getResource()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + } diff --git a/frontend-js/src/main/js/gui/AddOverlayDialog.js b/frontend-js/src/main/js/gui/AddOverlayDialog.js index c9f0c38d09a9ba606522a135ec7586ded1a2a82a..96d4490165607dfddfa0709bca89c8b7d049f362 100644 --- a/frontend-js/src/main/js/gui/AddOverlayDialog.js +++ b/frontend-js/src/main/js/gui/AddOverlayDialog.js @@ -95,9 +95,7 @@ AddOverlayDialog.prototype.createGui = function () { name: "overlay-file" }); fileInput.addEventListener("change", function () { - return self.processFile(fileInput.files[0]).then(function () { - $(fileInput).val(""); - }).catch(GuiConnector.alert); + return self.processFile(fileInput.files[0]).catch(GuiConnector.alert); }, false); content.appendChild(fileInput); content.appendChild(guiUtils.createNewLine()); @@ -294,9 +292,10 @@ AddOverlayDialog.prototype.open = function () { return self.addOverlay().then(function (result) { $(dialog).dialog("close"); return result; - }, function (error) { + }).catch(function (error) { GuiConnector.hideProcessing(); if (error instanceof NetworkError && error.statusCode === HttpStatus.BAD_REQUEST) { + $("[name='overlay-file']", self.getElement()).val(""); var errorMessage = JSON.parse(error.content); GuiConnector.alert("Problematic input: <br/>" + errorMessage.reason); } else if (error instanceof SecurityError) { diff --git a/frontend-js/src/main/js/gui/admin/MapsAdminPanel.js b/frontend-js/src/main/js/gui/admin/MapsAdminPanel.js index dcac66b096da9038fe252ab6b68368cd2becb53f..c5124c44b01f6c12ce63f0d355e46d56a78f915c 100644 --- a/frontend-js/src/main/js/gui/admin/MapsAdminPanel.js +++ b/frontend-js/src/main/js/gui/admin/MapsAdminPanel.js @@ -346,7 +346,9 @@ MapsAdminPanel.prototype.addUpdateListener = function (project) { var data = row.data(); if (data[0].indexOf(">" + project.getProjectId() + "<") >= 0) { self.projectToTableRow(project, data, user); + var page = dataTable.page(); row.data(data).draw(); + dataTable.page(page); } } }); diff --git a/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js b/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js index 6de9dbcf6e3d527e1099a29bb47de20ba79b5688..735848903e887a4c2cd7383650aa6a2638a857fc 100644 --- a/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js +++ b/frontend-js/src/main/js/gui/admin/UsersAdminPanel.js @@ -303,11 +303,13 @@ UsersAdminPanel.prototype.addUpdateListener = function (user, dataTableRow) { var listener = function () { var login = Functions.escapeSelector(user.getLogin()); self.userToTableRow(user, dataTableRow); - var row = $($("[name='usersTable']", self.getElement())[0]).DataTable().row("#" + login); + var dataTable =$("[name='usersTable']", self.getElement()).DataTable(); + var row = dataTable.row("#" + login); if (row.length > 0) { + var page = dataTable.page(); row.data(dataTableRow).draw(); + dataTable.page(page); } - }; listener.listenerName = listenerName; user.addListener("onreload", listener); diff --git a/frontend-js/src/main/js/gui/export/AbstractExportPanel.js b/frontend-js/src/main/js/gui/export/AbstractExportPanel.js index e22bb9beb066340a497a1d30d156571db2c352de..636e2d2d954f197f158c8814c07711c8784f76af 100644 --- a/frontend-js/src/main/js/gui/export/AbstractExportPanel.js +++ b/frontend-js/src/main/js/gui/export/AbstractExportPanel.js @@ -223,7 +223,7 @@ AbstractExportPanel.prototype._createSelectSubmapDiv = function (models) { var id = model.getId(); var row = Functions.createElement({ type: "li", - content: "<div class=\"checkbox\"><label> <input type=\"checkbox\" name=\"" + name + "\" value=\"" + id + "\" />" + name + "</label></div>", + content: "<div class=\"checkbox\"><label> <input type=\"checkbox\" name=\"" + name + "\" value=\"" + id + "\" checked/>" + name + "</label></div>", xss: false }); choicesContainer.appendChild(row); diff --git a/frontend-js/src/main/js/gui/export/ElementExportPanel.js b/frontend-js/src/main/js/gui/export/ElementExportPanel.js index a1ef96c581466c2b2fe626ee99dfd64c485d1662..54b04e95c464dc31c90243b00a1a537968ca2e64 100644 --- a/frontend-js/src/main/js/gui/export/ElementExportPanel.js +++ b/frontend-js/src/main/js/gui/export/ElementExportPanel.js @@ -95,7 +95,7 @@ ElementExportPanel.prototype.createResponseString = function () { var promises = []; for (var i = 0; i < models.length; i++) { var model = models[i]; - if (submapIds.length === 0 || $.inArray(model.getId(), submapIds) >= 0) { + if ($.inArray(model.getId(), submapIds) >= 0) { promises.push(model.getAliases({ type: types, complete: true, diff --git a/frontend-js/src/main/js/gui/export/NetworkExportPanel.js b/frontend-js/src/main/js/gui/export/NetworkExportPanel.js index 46a728fac879d268378b4817743a8258ac147cf0..bb07cfd58fba8c6fdb9933441ee2cb0c8c20708a 100644 --- a/frontend-js/src/main/js/gui/export/NetworkExportPanel.js +++ b/frontend-js/src/main/js/gui/export/NetworkExportPanel.js @@ -147,10 +147,8 @@ function matchReaction(reaction, elementIds, reactionTypes, submapIds) { if ($.inArray(reaction.getType(), reactionTypes) === -1) { return false; } - if (submapIds.length > 0) { - if ($.inArray(reaction.getModelId(), submapIds) === -1) { - return false; - } + if ($.inArray(reaction.getModelId(), submapIds) === -1) { + return false; } var count = 0; reaction.getElements().forEach(function (element) { diff --git a/frontend-js/src/main/js/map/AbstractCustomMap.js b/frontend-js/src/main/js/map/AbstractCustomMap.js index 1ceef72193d908c7fb5ee6679b08bd3e3f77d3e6..192a87aa79bcb1fd80363f8a003b1a98fa3cd45e 100644 --- a/frontend-js/src/main/js/map/AbstractCustomMap.js +++ b/frontend-js/src/main/js/map/AbstractCustomMap.js @@ -207,7 +207,7 @@ AbstractCustomMap.prototype.registerMapClickEvents = function () { var y1 = Math.max(0, topLeft.y); var x2 = Math.min(self.getModel().getWidth(), rightBottom.x); - var y2 = Math.max(self.getModel().getHeight(), rightBottom.y); + var y2 = Math.min(self.getModel().getHeight(), rightBottom.y); var polygon = ""; polygon += x1 + "," + y1 + ";"; diff --git a/frontend-js/src/main/js/map/canvas/OpenLayers/OpenLayerPolyline.js b/frontend-js/src/main/js/map/canvas/OpenLayers/OpenLayerPolyline.js index 6ee77ee55986f8721bb867c97b5d81b45482e6e7..e4eab7e4c4df3de0c3b83c6ae9d654c6b77ddfa2 100644 --- a/frontend-js/src/main/js/map/canvas/OpenLayers/OpenLayerPolyline.js +++ b/frontend-js/src/main/js/map/canvas/OpenLayers/OpenLayerPolyline.js @@ -12,6 +12,8 @@ function OpenLayerPolyline(options) { var self = this; + self.registerListenerType("onHide"); + if (options.strokeColor === undefined) { options.strokeColor = "#000000"; } @@ -74,7 +76,8 @@ OpenLayerPolyline.prototype.show = function () { }; OpenLayerPolyline.prototype.hide = function () { - return this.getOpenLayersPolyline().setStyle(new ol.style.Style({})); + this.getOpenLayersPolyline().setStyle(new ol.style.Style({})); + return this.callListeners("onHide"); }; OpenLayerPolyline.prototype.isShown = function () { diff --git a/frontend-js/src/main/js/map/marker/MarkerSurfaceCollection.js b/frontend-js/src/main/js/map/marker/MarkerSurfaceCollection.js index c9634456b480961b6dae875c690b872ac8b45370..8ab253ea9171735c35c34b7eaf4bbf5734ca5ce5 100644 --- a/frontend-js/src/main/js/map/marker/MarkerSurfaceCollection.js +++ b/frontend-js/src/main/js/map/marker/MarkerSurfaceCollection.js @@ -228,7 +228,12 @@ MarkerSurfaceCollection.prototype.createSurfaceForDbOverlay = function (element, onClick: onclickFunctions }); result.addListener("onClick", function () { - return map.getTopMap().openInfoWindowForIdentifiedElement(element); + return map.getTopMap().openInfoWindowForIdentifiedElement(element).then(function (infoWindow) { + result.getMapCanvasObjects()[0].addListener("onHide", function () { + return infoWindow._infoWindow.hide(); + }); + return infoWindow; + }); }); self.putSurface({element: element, overlay: dbOverlay}, result); if (self.getMap().isInitialized()) { diff --git a/persist/src/main/resources/db/migration/13.1.4/V13.1.4.20190821__remove_chembl_cache.sql b/persist/src/main/resources/db/migration/13.1.4/V13.1.4.20190821__remove_chembl_cache.sql new file mode 100644 index 0000000000000000000000000000000000000000..6aea6b38443948a2f8999010f401d3a6f41cb16a --- /dev/null +++ b/persist/src/main/resources/db/migration/13.1.4/V13.1.4.20190821__remove_chembl_cache.sql @@ -0,0 +1 @@ +delete from cache_query_table where type in (select id from cache_type_table where class_name ='lcsb.mapviewer.annotation.services.ChEMBLParser'); diff --git a/service/src/main/java/lcsb/mapviewer/services/search/drug/DrugService.java b/service/src/main/java/lcsb/mapviewer/services/search/drug/DrugService.java index 9ea2461a03ab8f64551a0f482ae9a8d522bd82f1..85312d412a9923a8bd8d73a79ab6c47a65b46170 100644 --- a/service/src/main/java/lcsb/mapviewer/services/search/drug/DrugService.java +++ b/service/src/main/java/lcsb/mapviewer/services/search/drug/DrugService.java @@ -174,9 +174,15 @@ public class DrugService extends DbSearchService implements IDrugService { if (name.trim().equals("")) { return null; } + DrugAnnotation secondParser = chEMBLParser; Drug drug = null; try { drug = drugBankParser.findDrug(name); + + if (drug==null) { + drug = chEMBLParser.findDrug(name); + secondParser = drugBankParser; + } if (drug != null) { removeUnknownOrganisms(drug, searchCriteria.getOrganisms()); } @@ -190,13 +196,13 @@ public class DrugService extends DbSearchService implements IDrugService { // * search for name searchNames.add(name); if (drug != null && drug.getName() != null) { - // * search for name of a drug in drugbanke + // * search for name of a drug in drugbank searchNames.add(drug.getName()); // * search for all synonyms found in drugbank // searchNames.addAll(drug.getSynonyms()); } for (String string : searchNames) { - Drug drug2 = chEMBLParser.findDrug(string); + Drug drug2 = secondParser.findDrug(string); if (drug2 != null) { removeUnknownOrganisms(drug2, searchCriteria.getOrganisms()); // don't add drugs that were already found diff --git a/service/src/test/java/lcsb/mapviewer/services/search/drug/DrugServiceTest.java b/service/src/test/java/lcsb/mapviewer/services/search/drug/DrugServiceTest.java index ed04915bfc95cbdb94b8628b3a70b6a0bb6addd7..d7635648ecf2c98ca89313d31b4b90905840ec34 100644 --- a/service/src/test/java/lcsb/mapviewer/services/search/drug/DrugServiceTest.java +++ b/service/src/test/java/lcsb/mapviewer/services/search/drug/DrugServiceTest.java @@ -42,6 +42,17 @@ public class DrugServiceTest extends ServiceTestFunctions { assertNull(drug); } + @Test + public void testGetIstodax() throws Exception { + try { + Drug drug = drugService.getByName("istodax", new DbSearchCriteria()); + assertEquals(2, drug.getSources().size()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + @Test public void testGetTargets() throws Exception { long count = searchHistoryDao.getCount();