diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js index e11954790e770cd4a328c30cc799b7ed8020254c..e8e1ce157c68f9671061a68930e16b57928c6ddc 100644 --- a/frontend-js/src/main/js/ServerConnector.js +++ b/frontend-js/src/main/js/ServerConnector.js @@ -448,6 +448,22 @@ ServerConnector.getReferenceGenomeUrl = function (queryParams, filterParams) { } }; +/** + * + * @param {Object} queryParams + * @param {string} queryParams.genomeId + * @param {string} queryParams.mappingId + * @param {Object} [filterParams] + * + * @returns {string} + */ +ServerConnector.getReferenceGenomeGeneMappingUrl = function (queryParams, filterParams) { + return this.getApiUrl({ + type: "genomics/" + queryParams.genomeId + "/geneMapping/" + queryParams.mappingId + "/", + params: filterParams + }); +}; + /** * * @param {Object} queryParams @@ -1278,8 +1294,6 @@ ServerConnector.getReferenceGenomes = function () { result.push(genome) } return result; - }).catch(function (error) { - return self.processNetworkError(error); }); }; @@ -2071,7 +2085,7 @@ ServerConnector.getPublications = function (params) { * @param {string} [params.version] * @param {string} [params.organism] * @param {string} [params.type] - * @param {string} [params.genomeId] + * @param {string|number} [params.genomeId] * * @returns {Promise} */ @@ -2133,6 +2147,19 @@ ServerConnector.addReferenceGenome = function (genome) { return self.sendPostRequest(self.getReferenceGenomesUrl(), data); }; +/** + * + * @param {Object} params + * @param {string} params.genomeId + * @param {string} params.mappingId + * + * @returns {Promise} + */ +ServerConnector.removeReferenceGenomeGeneMapping = function (params) { + var self = this; + return self.sendDeleteRequest(self.getReferenceGenomeGeneMappingUrl(params)); +}; + /** * diff --git a/frontend-js/src/main/js/gui/admin/EditGenomeDialog.js b/frontend-js/src/main/js/gui/admin/EditGenomeDialog.js index 1987cc9ece115b92207a66061481b9473f6b2a79..f178839c4fc71510381c2c32d96a80c63ebbdb7a 100644 --- a/frontend-js/src/main/js/gui/admin/EditGenomeDialog.js +++ b/frontend-js/src/main/js/gui/admin/EditGenomeDialog.js @@ -92,11 +92,13 @@ EditGenomeDialog.prototype.createGui = function () { tabDiv.appendChild(tabContentDiv); self.createGeneralTab(tabMenuDiv, tabContentDiv); + self.createGeneMappingTab(tabMenuDiv, tabContentDiv); $("a", tabMenuDiv).bind("click", function () { //workaround for some css issues... tabDiv.style.top = "40px"; tabDiv.style.bottom = "10px"; }); + }; /** @@ -115,6 +117,22 @@ EditGenomeDialog.prototype.createGeneralTab = function (tabMenuDiv, tabContentDi }; +/** + * + * @param {HTMLElement} tabMenuDiv + * @param {HTMLElement} tabContentDiv + */ +EditGenomeDialog.prototype.createGeneMappingTab = function (tabMenuDiv, tabContentDiv) { + var self = this; + self.addTab({ + tabMenuDiv: tabMenuDiv, + tabContentDiv: tabContentDiv, + name: "GENE MAPPING", + content: self.createGeneMappingTabContent() + }); + +}; + var id_counter = 0; /** @@ -222,6 +240,66 @@ EditGenomeDialog.prototype.createGeneralTabContent = function () { return result; }; +/** + * + * @returns {HTMLElement} + */ +EditGenomeDialog.prototype.createGeneMappingTabContent = function () { + + var self = this; + + var result = Functions.createElement({ + type: "div", + style: "margin-top:10px;" + }); + + var geneMappingTable = Functions.createElement({ + type: "table", + name: "geneMappingTable", + className: "display", + style: "width:100%" + }); + result.appendChild(geneMappingTable); + + // noinspection JSUnusedGlobalSymbols + $(geneMappingTable).DataTable({ + columns: [{ + title: 'Name' + }, { + title: 'Source' + }, { + title: 'Progress' + }, { + title: 'Remove', + orderable: false + }], + order: [[1, "asc"]] + }); + + $(geneMappingTable).on("click", "[name='removeMapping']", function () { + var button = this; + return self.askConfirmRemoval({ + title: "INFO", + content: "Do you really want to remove this gene mapping?", + input: false + }).then(function (param) { + if (param.status) { + return self.getServerConnector().removeReferenceGenomeGeneMapping({ + mappingId: $(button).attr("data"), + genomeId: self.getReferenceGenome().getId() + }).then(function () { + return self.getServerConnector().getReferenceGenome({genomeId: self.getReferenceGenome().getId()}); + }).then(function (referenceGenome) { + self.setReferenceGenome(referenceGenome); + return self.refresh(); + }); + } + }).catch(GuiConnector.alert); + }); + + return result; +}; + /** * * @returns {Promise|PromiseLike} @@ -397,6 +475,19 @@ EditGenomeDialog.prototype._fillUrl = function (genome, organism, type, version) ; +/** + * + * @param {ReferenceGenomeGeneMapping} geneMapping + * @returns {Array} + */ +EditGenomeDialog.prototype.geneMappingToTableRow = function (geneMapping) { + var row = []; + row[0] = geneMapping.getName(); + row[1] = geneMapping.getSourceUrl(); + row[2] = geneMapping.getProgress(); + row[3] = "<button name='removeMapping' data='" + geneMapping.getId() + "'><i class='fa fa-trash-o' style='font-size:17px'></button>"; + return row; +}; /** * * @returns {Promise} @@ -417,10 +508,18 @@ EditGenomeDialog.prototype.init = function () { searching: false, bInfo: false }); - var data = []; + + return self.refresh(); +}; + +EditGenomeDialog.prototype.refresh = function () { + var self = this; var genome = self.getReferenceGenome(); + var dataTable = $("[name=detailsTable]", self.getElement()).DataTable(); + var data = []; + data.push(['Organism', Functions.createElement({type: "select", name: "genomeOrganismSelect"}).outerHTML]); data.push(['Type', Functions.createElement({type: "select", name: "genomeTypeSelect"}).outerHTML]); data.push(['Version', Functions.createElement({type: "select", name: "genomeVersionSelect"}).outerHTML]); @@ -430,9 +529,22 @@ EditGenomeDialog.prototype.init = function () { dataTable.clear().rows.add(data).draw(); + dataTable = $("[name=geneMappingTable]", self.getElement()).DataTable(); + data = []; + var page = dataTable.page(); + + for (var i = 0; i < genome.getGeneMappings().length; i++) { + var geneMapping = genome.getGeneMappings()[i]; + var rowData = self.geneMappingToTableRow(geneMapping); + data.push(rowData); + } + //it should be simplified, but I couldn't make it work + dataTable.clear().rows.add(data).page(page).draw(false).page(page).draw(false); + return self._fillOrganismSelect(genome); }; + EditGenomeDialog.prototype.destroy = function () { var self = this; var div = self.getElement(); @@ -442,6 +554,10 @@ EditGenomeDialog.prototype.destroy = function () { $(detailsTable).DataTable().destroy(); } + var geneMappingTable = $("[name=geneMappingTable]", div)[0]; + if ($.fn.DataTable.isDataTable(geneMappingTable)) { + $(geneMappingTable).DataTable().destroy(); + } if ($(div).hasClass("ui-dialog-content")) { $(div).dialog("destroy"); diff --git a/frontend-js/src/main/js/map/data/ReferenceGenome.js b/frontend-js/src/main/js/map/data/ReferenceGenome.js index 032563ceb170dd935747b2cec8ef0b4bf5e3bbc2..8ed9b5445016bb0b1a922580129e125079e4c7be 100644 --- a/frontend-js/src/main/js/map/data/ReferenceGenome.js +++ b/frontend-js/src/main/js/map/data/ReferenceGenome.js @@ -23,6 +23,8 @@ function ReferenceGenome(javaObject) { this._geneMapping.push(new ReferenceGenomeGeneMapping(javaObject.geneMapping[i])); } } + } else { + this._geneMapping = []; } } diff --git a/frontend-js/src/main/js/map/data/ReferenceGenomeGeneMapping.js b/frontend-js/src/main/js/map/data/ReferenceGenomeGeneMapping.js index 5b6ad8744b16c438f3150de669ea07540636dffa..b28f702bb5667b2d93d8672502bb26faa1b602a8 100644 --- a/frontend-js/src/main/js/map/data/ReferenceGenomeGeneMapping.js +++ b/frontend-js/src/main/js/map/data/ReferenceGenomeGeneMapping.js @@ -7,19 +7,106 @@ function ReferenceGenomeGeneMapping(javaObject) { } else { this.setUrl(javaObject.sourceUrl); } + this.setLocalUrl(javaObject.localUrl); + this.setSourceUrl(javaObject.sourceUrl); + this.setProgress(javaObject.downloadProgress); + this.setId(javaObject.idObject); } -ReferenceGenomeGeneMapping.prototype.setName = function(name) { +/** + * + * @param {string} name + */ +ReferenceGenomeGeneMapping.prototype.setName = function (name) { this._name = name; }; -ReferenceGenomeGeneMapping.prototype.setUrl = function(url) { - this._url = url; -}; -ReferenceGenomeGeneMapping.prototype.getName = function() { + +/** + * + * @returns {string} + */ +ReferenceGenomeGeneMapping.prototype.getName = function () { return this._name; }; -ReferenceGenomeGeneMapping.prototype.getUrl = function() { + +/** + * + * @param {string} url + */ +ReferenceGenomeGeneMapping.prototype.setUrl = function (url) { + this._url = url; +}; + +/** + * + * @returns {string} + */ +ReferenceGenomeGeneMapping.prototype.getUrl = function () { return this._url; }; +/** + * + * @param {string} url + */ +ReferenceGenomeGeneMapping.prototype.setLocalUrl = function (url) { + this._localUrl = url; +}; + +/** + * + * @returns {string} + */ +ReferenceGenomeGeneMapping.prototype.getLocalUrl = function () { + return this._localUrl; +}; + +/** + * + * @returns {string} + */ +ReferenceGenomeGeneMapping.prototype.getSourceUrl = function () { + return this._sourceUrl; +}; + +/** + * + * @param {string} url + */ +ReferenceGenomeGeneMapping.prototype.setSourceUrl = function (url) { + this._sourceUrl = url; +}; + +/** + * + * @param {number} progress + */ +ReferenceGenomeGeneMapping.prototype.setProgress = function (progress) { + this._progress = progress; +}; + +/** + * + * @returns {number} + */ +ReferenceGenomeGeneMapping.prototype.getProgress = function () { + return this._progress; +}; + +/** + * + * @param {number} id + */ +ReferenceGenomeGeneMapping.prototype.setId = function (id) { + this._id = id; +}; + +/** + * + * @returns {number} + */ +ReferenceGenomeGeneMapping.prototype.getId = function () { + return this._id; +}; + module.exports = ReferenceGenomeGeneMapping; diff --git a/frontend-js/src/test/js/gui/admin/EditGenomeDialog-test.js b/frontend-js/src/test/js/gui/admin/EditGenomeDialog-test.js index c0f889d02d5a7a0bf10bdea58dd71e158d3ce404..36be57ba12a2bba3917ae2b59fa8bdc66bcf0a53 100644 --- a/frontend-js/src/test/js/gui/admin/EditGenomeDialog-test.js +++ b/frontend-js/src/test/js/gui/admin/EditGenomeDialog-test.js @@ -8,6 +8,7 @@ var ValidationError = require('../../../../main/js/ValidationError'); var ServerConnector = require('../../ServerConnector-mock'); var logger = require('../../logger'); +var Promise = require('bluebird'); var chai = require('chai'); var assert = chai.assert; @@ -37,8 +38,38 @@ describe('EditGenomeDialog', function () { return dialog.destroy(); }); }); + it('existing', function () { + helper.loginAsAdmin(); + var dialog; + return ServerConnector.getReferenceGenome({genomeId: 154}).then(function (genome) { + dialog = createDialog(genome); + return dialog.init(); + }).then(function () { + return dialog.destroy(); + }); + }); }); + it('removeMapping', function () { + helper.loginAsAdmin(); + var dialog; + return ServerConnector.getReferenceGenome({genomeId: 154}).then(function (genome) { + dialog = createDialog(genome); + return dialog.init(); + }).then(function () { + dialog.askConfirmRemoval = function () { + return Promise.resolve({status: true}); + }; + assert.equal(0, logger.getWarnings().length); + + var element = $("[name='removeMapping']")[0]; + return helper.triggerJqueryEvent(element, "click"); + }).then(function () { + return dialog.destroy(); + }); + }); + + it('on organism change', function () { var genome = new ReferenceGenome(); var dialog = createDialog(genome); diff --git a/frontend-js/testFiles/apiCalls/genomics/154/DELETE_token=ADMIN_TOKEN_ID& b/frontend-js/testFiles/apiCalls/genomics/154/DELETE_token=ADMIN_TOKEN_ID& new file mode 100644 index 0000000000000000000000000000000000000000..9e26dfeeb6e641a33dae4961196235bdb965b21b --- /dev/null +++ b/frontend-js/testFiles/apiCalls/genomics/154/DELETE_token=ADMIN_TOKEN_ID& @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/frontend-js/testFiles/apiCalls/genomics/154/geneMapping/97/DELETE_token=ADMIN_TOKEN_ID& b/frontend-js/testFiles/apiCalls/genomics/154/geneMapping/97/DELETE_token=ADMIN_TOKEN_ID& new file mode 100644 index 0000000000000000000000000000000000000000..9e26dfeeb6e641a33dae4961196235bdb965b21b --- /dev/null +++ b/frontend-js/testFiles/apiCalls/genomics/154/geneMapping/97/DELETE_token=ADMIN_TOKEN_ID& @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/frontend-js/testFiles/apiCalls/genomics/token=ADMIN_TOKEN_ID& b/frontend-js/testFiles/apiCalls/genomics/token=ADMIN_TOKEN_ID& index e6582c8cbf178d8085874247242f2e05ce70d93c..3d404fc2fc06ba770f05a5ef09943f23cfe110d5 100644 --- a/frontend-js/testFiles/apiCalls/genomics/token=ADMIN_TOKEN_ID& +++ b/frontend-js/testFiles/apiCalls/genomics/token=ADMIN_TOKEN_ID& @@ -1 +1 @@ -[{"downloadProgress":100.0,"geneMapping":[],"idObject":43,"localUrl":null,"organism":{"annotatorClassName":"","descriptionByType":"","descriptionByTypeRelation":"","id":517528,"link":"http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id=8822","resource":"8822","type":"TAXONOMY"},"sourceUrl":"ftp://hgdownload.cse.ucsc.edu/goldenPath/aptMan1/bigZips/aptMan1.2bit","type":"UCSC","version":"aptMan1"},{"downloadProgress":100.0,"geneMapping":[{"downloadProgress":100.0,"localUrl":null,"name":"refGene","sourceUrl":"http://pg-sandbox.uni.lu/data/refGene.txt.bb"}],"idObject":154,"localUrl":null,"organism":{"annotatorClassName":"","descriptionByType":"","descriptionByTypeRelation":"","id":523719,"link":"http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id=9606","resource":"9606","type":"TAXONOMY"},"sourceUrl":"ftp://hgdownload.cse.ucsc.edu/goldenPath/hg19/bigZips/hg19.2bit","type":"UCSC","version":"hg19"},{"downloadProgress":100.0,"geneMapping":[],"idObject":1563,"localUrl":"../minerva-big//5280/hg38.2bit","organism":{"annotatorClassName":"","descriptionByType":"","descriptionByTypeRelation":"","id":927074,"link":"http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id=9606","resource":"9606","type":"TAXONOMY"},"sourceUrl":"ftp://hgdownload.cse.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit","type":"UCSC","version":"hg38"}] \ No newline at end of file +[{"downloadProgress":100.0,"geneMapping":[{"downloadProgress":100.0,"idObject":97,"localUrl":null,"name":"refGene","sourceUrl":"http://pg-sandbox.uni.lu/data/refGene.txt.bb"}],"idObject":154,"localUrl":null,"organism":{"annotatorClassName":"","descriptionByType":"","descriptionByTypeRelation":"","id":523719,"link":"http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id=9606","resource":"9606","type":"TAXONOMY"},"sourceUrl":"ftp://hgdownload.cse.ucsc.edu/goldenPath/hg19/bigZips/hg19.2bit","type":"UCSC","version":"hg19"},{"downloadProgress":100.0,"geneMapping":[],"idObject":1563,"localUrl":"../minerva-big//5280/hg38.2bit","organism":{"annotatorClassName":"","descriptionByType":"","descriptionByTypeRelation":"","id":927074,"link":"http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id=9606","resource":"9606","type":"TAXONOMY"},"sourceUrl":"ftp://hgdownload.cse.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit","type":"UCSC","version":"hg38"},{"downloadProgress":100.0,"geneMapping":[],"idObject":1829,"localUrl":"../minerva-big//9387/hg18.2bit","organism":{"annotatorClassName":"","descriptionByType":"","descriptionByTypeRelation":"","id":1150729,"link":"http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id=9606","resource":"9606","type":"TAXONOMY"},"sourceUrl":"ftp://hgdownload.cse.ucsc.edu/goldenPath/hg18/bigZips/hg18.2bit","type":"UCSC","version":"hg18"}] \ No newline at end of file diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeController.java b/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeController.java index 63b8088bd85f28517307536ebe4f13192dd3cc92..0be38d8fa419779adc7585255b79a5baba045e83 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeController.java @@ -101,4 +101,14 @@ public class ReferenceGenomeController extends BaseController { return referenceGenomeController.removeGenome(genomeId, token); } + @RequestMapping(value = "/genomics/{genomeId}/geneMapping/{mappingId}/", method = { RequestMethod.DELETE }, produces = { + MediaType.APPLICATION_JSON_VALUE }) + public Map<String, Object> removeGeneMapping(// + @PathVariable(value = "genomeId") String genomeId, // + @PathVariable(value = "mappingId") String mappingId, // + @CookieValue(value = Configuration.AUTH_TOKEN) String token // + ) throws SecurityException, IOException, lcsb.mapviewer.api.ObjectNotFoundException { + return referenceGenomeController.removeGeneMapping(genomeId,mappingId, token); + } + } \ No newline at end of file diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeRestImpl.java index cd515a62d53f09f6ea4a2d05d22df192a0322cee..bc71b2447cd7c201b9bdb80b7f61e4e3d2432437 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeRestImpl.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/genomics/ReferenceGenomeRestImpl.java @@ -133,6 +133,7 @@ public class ReferenceGenomeRestImpl extends BaseRestImpl { result.put("localUrl", getLocalUrl(mapping.getSourceUrl())); result.put("sourceUrl", mapping.getSourceUrl()); result.put("name", mapping.getName()); + result.put("idObject", mapping.getId()); return result; } @@ -240,4 +241,27 @@ public class ReferenceGenomeRestImpl extends BaseRestImpl { } } + public Map<String, Object> removeGeneMapping(String genomeId, String mappingId, String token) + throws SecurityException, IOException, ObjectNotFoundException { + if (!getUserService().userHasPrivilege(token, PrivilegeType.MANAGE_GENOMES)) { + throw new SecurityException("Access denied"); + } + ReferenceGenome genome = referenceGenomeService.getReferenceGenomeById(Integer.parseInt(genomeId), token); + if (genome == null) { + throw new ObjectNotFoundException("Genome doesn't exist"); + } + int id = Integer.parseInt(mappingId); + ReferenceGenomeGeneMapping geneMapping = null; + for (ReferenceGenomeGeneMapping mapping : genome.getGeneMapping()) { + if (mapping.getId() == id) { + geneMapping = mapping; + } + } + if (geneMapping == null) { + throw new ObjectNotFoundException("Gene mapping doesn't exist"); + } + referenceGenomeService.removeReferenceGenomeGeneMapping(geneMapping); + return okStatus(); + } + }