diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/genome/AbstractReferenceGenomeConnector.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/genome/AbstractReferenceGenomeConnector.java index 385b8c2ae7ed1765ba3621f774bee40231fbe403..2a39d1aaa82d7c747f37b9da7965e0623e19a6bd 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/genome/AbstractReferenceGenomeConnector.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/genome/AbstractReferenceGenomeConnector.java @@ -159,8 +159,9 @@ public abstract class AbstractReferenceGenomeConnector extends CachableInterface * {@link #referenceGenome} * @param name * {@link #name} + * @throws ReferenceGenomeConnectorException */ - private DownloadGeneMappingGenomeVersionTask(ReferenceGenome referenceGenome, String name, String url, IProgressUpdater updater) { + private DownloadGeneMappingGenomeVersionTask(ReferenceGenome referenceGenome, String name, String url, IProgressUpdater updater) throws ReferenceGenomeConnectorException { this.url = url; this.referenceGenome = referenceGenome; this.name = name; @@ -173,36 +174,36 @@ public abstract class AbstractReferenceGenomeConnector extends CachableInterface } }; } + } @Override public Void call() throws Exception { getDbUtils().createSessionForCurrentThread(); try { - ReferenceGenome referenceGenome = getReferenceGenomeDao().getById(this.referenceGenome.getId()); - for (ReferenceGenomeGeneMapping mapping : referenceGenome.getGeneMapping()) { - if (mapping.getName().equals(name)) { - throw new ReferenceGenomeConnectorException("Gene mapping with name: \"" + name + "\" already exists."); - } - } - if (!url.toLowerCase().endsWith("bb")) { - throw new ReferenceGenomeConnectorException("Only big bed format files are supported but found: \"" + url + "\"."); - } + ReferenceGenome referenceGenome = getReferenceGenomeDao().getById(this.referenceGenome.getId()); + for (ReferenceGenomeGeneMapping mapping : referenceGenome.getGeneMapping()) { + if (mapping.getName().equals(name)) { + throw new ReferenceGenomeConnectorException("Gene mapping with name: \"" + name + "\" already exists."); + } + } + if (!url.toLowerCase().endsWith("bb")) { + throw new ReferenceGenomeConnectorException("Only big bed format files are supported but found: \"" + url + "\"."); + } ReferenceGenomeGeneMapping mapping = new ReferenceGenomeGeneMapping(); - mapping.setReferenceGenome(referenceGenome); mapping.setName(name); mapping.setSourceUrl(url); referenceGenome.addReferenceGenomeGeneMapping(mapping); - getReferenceGenomeGeneMappingDao().add(mapping); - getReferenceGenomeGeneMappingDao().flush(); + getReferenceGenomeDao().update(referenceGenome); getReferenceGenomeDao().commit(); + getReferenceGenomeDao().flush(); getBigFileCache().downloadFile(url, false, new IProgressUpdater() { @Override public void setProgress(double progress) { if (updater != null) { updater.setProgress(progress); } - // we have to get the object because it's in separate thred + // we have to get the object because it's in separate thread ReferenceGenomeGeneMapping temp = getReferenceGenomeGeneMappingDao().getById(mapping.getId()); temp.setDownloadProgress(progress); getReferenceGenomeGeneMappingDao().update(temp); diff --git a/frontend-js/src/main/css/global.css b/frontend-js/src/main/css/global.css index e6ae7e3baaefc2db36fba1de9f8afbc399e94c82..61174790bda4d2a654ac21c8b3646e69a351d7ae 100644 --- a/frontend-js/src/main/css/global.css +++ b/frontend-js/src/main/css/global.css @@ -643,7 +643,8 @@ h1 { .minerva-plugin-tab .minerva-menu-row button, .minerva-edit-project-dialog .minerva-menu-row button, .minerva-users-tab .minerva-menu-row button, -.minerva-genome-tab .minerva-menu-row button { +.minerva-genome-tab .minerva-menu-row button, +.minerva-edit-genome-dialog .minerva-menu-row button { margin: 5px; } @@ -1104,6 +1105,7 @@ input[type=file] { background: #f5f5f5; cursor: pointer; } + #minervaAppDiv table.dataTable.hover tbody tr:hover, #minervaAppDiv table.dataTable.display tbody tr:hover, #minervaAppDiv table.dataTable.display tbody tr:hover > .sorting_1, diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js index 3163015862ba479d7b783a5e691ce8cb83aaf438..ed52d611712915b61ae5c970919e4f573fe19449 100644 --- a/frontend-js/src/main/js/ServerConnector.js +++ b/frontend-js/src/main/js/ServerConnector.js @@ -38,6 +38,7 @@ var SbmlParameter = require('./map/data/SbmlParameter'); var SecurityError = require('./SecurityError'); var SessionData = require('./SessionData'); var User = require('./map/data/User'); +var ValidationError = require('./ValidationError'); var PrivilegeType = require('./map/data/PrivilegeType'); var GuiConnector = require('./GuiConnector'); @@ -2433,7 +2434,14 @@ ServerConnector.addGeneMapping = function (params) { name: params.mappingName, url: params.mappingUrl }; - return self.sendPostRequest(self.getReferenceGenomeGeneMappingsUrl(params), data); + return self.sendPostRequest(self.getReferenceGenomeGeneMappingsUrl(params), data).catch(function (e) { + if (e instanceof NetworkError && e.statusCode === HttpStatus.BAD_REQUEST) { + var content = JSON.parse(e.content); + throw new ValidationError(content.reason); + } else { + return self.processNetworkError(e); + } + }); }; /** * diff --git a/frontend-js/src/main/js/gui/admin/EditGenomeDialog.js b/frontend-js/src/main/js/gui/admin/EditGenomeDialog.js index 60cb158713b861c8ebd85eb479d55e753fc3c4a5..cff98ee83e7a361e23f7d0b1215c0c043097afc0 100644 --- a/frontend-js/src/main/js/gui/admin/EditGenomeDialog.js +++ b/frontend-js/src/main/js/gui/admin/EditGenomeDialog.js @@ -32,6 +32,7 @@ function EditGenomeDialog(params) { self.setReferenceGenome(params.referenceGenome); $(self.getElement()).css({overflow: "hidden"}); + $(self.getElement()).addClass("minerva-edit-genome-dialog"); self.createGui(); self.registerListenerType("onSave"); @@ -240,6 +241,18 @@ EditGenomeDialog.prototype.createGeneMappingTabContent = function () { menuRow.appendChild(addGeneMappingButton); + var refreshButton = Functions.createElement({ + type: "button", + name: "saveGenome", + content: ' REFRESH', + onclick: function () { + return self.refresh(); + }, + xss: false + }); + + menuRow.appendChild(refreshButton); + return result; }; @@ -259,7 +272,7 @@ EditGenomeDialog.prototype.onSaveClicked = function () { genome.setVersion(self.getSelectedVersion()); return self.getServerConnector().addReferenceGenome(genome).then(function () { return self.callListeners("onSave"); - }).catch(function(e){ + }).catch(function (e) { if (e instanceof ObjectExistsError) { GuiConnector.alert("Reference genome already exists"); } else { @@ -433,7 +446,7 @@ EditGenomeDialog.prototype.geneMappingToTableRow = function (geneMapping) { var row = []; row[0] = geneMapping.getName(); row[1] = geneMapping.getSourceUrl(); - row[2] = geneMapping.getProgress(); + row[2] = geneMapping.getProgressStatus(); row[3] = "<button name='removeMapping' data='" + geneMapping.getId() + "'><i class='fa fa-trash-o' style='font-size:17px'></button>"; return row; }; @@ -468,34 +481,40 @@ EditGenomeDialog.prototype.init = function () { */ 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]); - data.push(['Source url', Functions.createElement({type: "input", name: "genomeSourceUrl"}).outerHTML]); - data.push(['Local url', Functions.createElement({type: "input", name: "genomeLocalUrl"}).outerHTML]); - data.push(['Progress', Functions.createElement({type: "input", name: "genomeProgress"}).outerHTML]); - - 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); + var refreshReferenceGenomePromise = Promise.resolve(); + if (!self.isNew()) { + refreshReferenceGenomePromise = self.getServerConnector().getReferenceGenome({genomeId: self.getReferenceGenome().getId()}).then(function (genome) { + self.setReferenceGenome(genome); + }); } - //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 refreshReferenceGenomePromise.then(function () { + 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]); + data.push(['Source url', Functions.createElement({type: "input", name: "genomeSourceUrl"}).outerHTML]); + data.push(['Local url', Functions.createElement({type: "input", name: "genomeLocalUrl"}).outerHTML]); + data.push(['Progress', Functions.createElement({type: "input", name: "genomeProgress"}).outerHTML]); + + 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); + return self._fillOrganismSelect(genome); + }); }; /** @@ -522,6 +541,7 @@ EditGenomeDialog.prototype.destroy = function () { /** * + * @return {Promise} */ EditGenomeDialog.prototype.open = function () { var self = this; @@ -541,6 +561,8 @@ EditGenomeDialog.prototype.open = function () { }); } $(div).dialog("open"); + + return self.refresh(); }; /** @@ -621,7 +643,7 @@ EditGenomeDialog.prototype.openAddGeneMapping = function () { return self.refresh(); }).then(function () { $(dialog).dialog('destroy').remove(); - }); + }).catch(GuiConnector.alert); }, 'Cancel': function () { $(this).dialog('destroy').remove(); diff --git a/frontend-js/src/main/js/gui/admin/GenomeAdminPanel.js b/frontend-js/src/main/js/gui/admin/GenomeAdminPanel.js index afece10d70d1c7d0ee1dcb3574f75b270ccf6c8b..a6ed06d2aee54057ab17d2d929c6c7056ea90c5d 100644 --- a/frontend-js/src/main/js/gui/admin/GenomeAdminPanel.js +++ b/frontend-js/src/main/js/gui/admin/GenomeAdminPanel.js @@ -297,11 +297,9 @@ GenomeAdminPanel.prototype.showEditDialog = function (id) { } return self.getDialog(referenceGenome); }).then(function (dialog) { - dialog.open(); + return dialog.open(); + }).finally(function () { GuiConnector.hideProcessing(); - }).catch(function (error) { - GuiConnector.hideProcessing(); - return Promise.reject(error); }); }; @@ -314,11 +312,9 @@ GenomeAdminPanel.prototype.onAddClicked = function () { GuiConnector.showProcessing(); var referenceGenome = new ReferenceGenome(); return self.getDialog(referenceGenome).then(function (dialog) { - dialog.open(); - GuiConnector.hideProcessing(); - }).catch(function (error) { + return dialog.open(); + }).finally(function () { GuiConnector.hideProcessing(); - return Promise.reject(error); }); }; diff --git a/frontend-js/src/main/js/map/data/ReferenceGenomeGeneMapping.js b/frontend-js/src/main/js/map/data/ReferenceGenomeGeneMapping.js index 1d5ec11c43558133f767b1aae3c2ec4e5a33f7db..3f765a66793971ea03d71699112df696057c7f2e 100644 --- a/frontend-js/src/main/js/map/data/ReferenceGenomeGeneMapping.js +++ b/frontend-js/src/main/js/map/data/ReferenceGenomeGeneMapping.js @@ -84,6 +84,27 @@ ReferenceGenomeGeneMapping.prototype.getSourceUrl = function () { return this._sourceUrl; }; +/** + * + * @returns {string} + */ +ReferenceGenomeGeneMapping.prototype.getProgressStatus = function () { + var progress = this.getProgress(); + if (progress === 100) { + if (this.getLocalUrl() !== undefined) { + return "READY"; + } else { + return "ERROR"; + } + } else { + if (progress === undefined) { + return "N/A"; + } else { + return progress.toFixed(2) + ' %'; + } + } +}; + /** * * @param {string} url 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 84af369f43914b2b33e1256b69d63d30fb2cda8c..bcc6152d61139ae1b1d5d9f3734ad6016864a259 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 @@ -244,7 +244,7 @@ public class ReferenceGenomeRestImpl extends BaseRestImpl { try { referenceGenomeService.addReferenceGenome(genomeType, organism, version, url); return okStatus(); - } catch(ReferenceGenomeExistsException e) { + } catch (ReferenceGenomeExistsException e) { throw new ObjectExistsException(e); } catch (URISyntaxException e) { throw new QueryException("Problem wih given uri", e); @@ -262,6 +262,10 @@ public class ReferenceGenomeRestImpl extends BaseRestImpl { ReferenceGenome genome = referenceGenomeService.getReferenceGenomeById(id, token); String name = getFirstValue(formData.get("name")); String url = getFirstValue(formData.get("url")); + if (!url.toLowerCase().endsWith("bb")) { + throw new QueryException("Only big bed format files are supported but found: \"" + url + "\"."); + } + referenceGenomeService.addReferenceGenomeGeneMapping(genome, name, url); return okStatus(); } catch (URISyntaxException e) {