Commit 9396e504 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

Merge branch '610-automatic-refresh-it-would-be-nice-to-have' into 'master'

Resolve "automatic Refresh - it would be nice to have"

Closes #610

See merge request minerva/core!736
parents fafb5c40 b1fefbfd
......@@ -20,6 +20,8 @@ minerva (12.3.0~alpha.0) unstable; urgency=low
whitespace, "_" used as separator (#596)
* Small improvement: list of references in drug panel contains PUBMED prefix
(#666)
* Small improvement: list of projects is aut refreshed every 5 seconds if at
least one of the project is uploading/removing (#610)
* Small improvement: passwords to email account and ldap are not sent over
API (#732)
* Small improvement: reactant/product/modifier specific colors are parsed
......
......@@ -30,6 +30,8 @@ function GuiConnector() {
GuiConnector.prototype = Object.create(ObjectWithListeners.prototype);
GuiConnector.prototype.constructor = GuiConnector;
var singleton = new GuiConnector();
/**
*
* @param {GuiConnector} object
......@@ -37,7 +39,7 @@ GuiConnector.prototype.constructor = GuiConnector;
*/
function returnThisOrSingleton(object) {
if (object === undefined || object === null) {
return GuiConnector.singleton;
return singleton;
} else {
return object;
}
......@@ -566,6 +568,5 @@ GuiConnector.prototype.warn = function (message) {
$(self._warnDialog).dialog("open");
};
GuiConnector.singleton = new GuiConnector();
module.exports = GuiConnector.singleton;
module.exports = singleton;
......@@ -58,6 +58,11 @@ ServerConnector.init = function () {
self._configurationParam = [];
self._projects = [];
/**
@name ServerConnector#_projectsById
@type Project[]
*/
self._projectsById = [];
self._users = [];
......@@ -135,7 +140,7 @@ ServerConnector.getNeutralOverlayColorInt = function () {
*
* @param url
* @param description
* @returns {Promise}
* @returns {Promise<string>| PromiseLike<string>}
*/
ServerConnector.sendGetRequest = function (url, description) {
return this.sendRequest({
......@@ -382,6 +387,12 @@ ServerConnector.getApiUrl = function (paramObj) {
return result;
};
/**
*
* @param [queryParams]
* @param [filterParams]
* @return {string}
*/
ServerConnector.getProjectsUrl = function (queryParams, filterParams) {
return this.getApiUrl({
type: "projects/",
......@@ -974,6 +985,10 @@ ServerConnector.getUpdateUserPreferencesUrl = function (queryParams, filterParam
});
};
/**
*
* @return {(PromiseLike<Configuration> | Promise<Configuration>)}
*/
ServerConnector.getConfiguration = function () {
var self = this;
if (this._configuration === undefined) {
......@@ -1039,6 +1054,11 @@ ServerConnector.getModels = function (projectId) {
});
};
/**
*
* @param {string} [projectId]
* @return {Promise<project>| PromiseLike<Project>}
*/
ServerConnector.getProject = function (projectId) {
var queryParams = {};
var filterParams = {};
......@@ -1061,6 +1081,7 @@ ServerConnector.getProject = function (projectId) {
self._projectsById[projectId] = downloadedProject;
}
project = self._projectsById[projectId];
return self.getModels(projectId).then(function (models) {
project.setModels(models);
return self.getOverlays({
......@@ -1117,16 +1138,7 @@ ServerConnector.updateProject = function (project) {
}).then(function () {
return project;
}).catch(function (error) {
if ((error instanceof NetworkError)) {
switch (error.statusCode) {
case HttpStatus.FORBIDDEN:
return Promise.reject(new SecurityError("Access denied."));
default:
return Promise.reject(error);
}
} else {
return Promise.reject(error);
}
return self._processUpdateError(error);
});
};
......@@ -1144,16 +1156,7 @@ ServerConnector.removeProject = function (projectId) {
}
return self._projectsById[project.getProjectId()];
}).then(null, function (error) {
if ((error instanceof NetworkError)) {
switch (error.statusCode) {
case HttpStatus.FORBIDDEN:
return Promise.reject(new SecurityError("Access denied."));
default:
return Promise.reject(error);
}
} else {
return Promise.reject(error);
}
return self._processUpdateError(error);
});
};
......@@ -1171,17 +1174,26 @@ ServerConnector.addProject = function (options) {
}
return project;
}).then(null, function (error) {
if ((error instanceof NetworkError)) {
switch (error.statusCode) {
case HttpStatus.FORBIDDEN:
return Promise.reject(new SecurityError("Access denied."));
default:
return Promise.reject(error);
}
return self._processUpdateError(error);
});
};
/**
*
* @param {Error} error
* @return {Promise}
* @private
*/
ServerConnector._processUpdateError = function (error) {
if (error instanceof NetworkError) {
if (error.statusCode === HttpStatus.FORBIDDEN) {
return Promise.reject(new SecurityError("Access denied."));
} else {
return Promise.reject(error);
}
});
} else {
return Promise.reject(error);
}
};
ServerConnector.serialize = function (object) {
......@@ -1197,6 +1209,11 @@ ServerConnector.serialize = function (object) {
return result;
};
/**
*
* @param {boolean} [reload=false]
* @return {Promise<Project[]>}
*/
ServerConnector.getProjects = function (reload) {
var self = this;
if (self._projects.length > 0 && !reload) {
......@@ -1212,7 +1229,8 @@ ServerConnector.getProjects = function (reload) {
} else {
self._projectsById[project.getProjectId()] = project;
}
self._projects.push(self._projectsById[project.getProjectId()]);
project = self._projectsById[project.getProjectId()];
self._projects.push(project);
}
return self._projects;
});
......@@ -1639,8 +1657,8 @@ ServerConnector.getFullOverlayElement = function (params) {
/**
*
* @param {string} [projectId]
* @returns {Promise}
* @param {string|null} [projectId]
* @returns {Promise<string>| PromiseLike<string>}
*/
ServerConnector.getProjectId = function (projectId) {
var self = this;
......
......@@ -41,6 +41,8 @@ function MapsAdminPanel(params) {
MapsAdminPanel.prototype = Object.create(AbstractAdminPanel.prototype);
MapsAdminPanel.prototype.constructor = MapsAdminPanel;
MapsAdminPanel.AUTO_REFRESH_TIME = 5000;
/**
*
* @private
......@@ -91,7 +93,7 @@ MapsAdminPanel.prototype._createMenuRow = function () {
name: "refreshProject",
content: '<span class="ui-icon ui-icon-refresh"></span>&nbsp;REFRESH',
onclick: function () {
return self.onRefreshClicked().then(null, GuiConnector.alert);
return self.onRefreshClicked().catch(GuiConnector.alert);
},
xss: false
});
......@@ -219,6 +221,9 @@ MapsAdminPanel.prototype.projectToTableRow = function (project, row, user) {
formattedProjectId = projectId;
}
var status = project.getStatus();
if (project.getStatus().toLowerCase() !== "ok" && project.getStatus().toLowerCase() !== "failure") {
status += ' (' + project.getProgress().toFixed(2) + ' %)';
}
if (project.hasErrors()) {
status += "<a name='showErrors' href='#' data='" + project.getProjectId() + "'>" +
"<i class='fa fa-exclamation-triangle' style='font-size:18px; font-weight:400; padding-right:10px;color:red'></i>" +
......@@ -279,6 +284,7 @@ MapsAdminPanel.prototype.setProjects = function (projects) {
var self = this;
return self.getServerConnector().getLoggedUser().then(function (user) {
var requireUpdate = false;
var dataTable = $("[name='projectsTable']", self.getElement()).DataTable();
var data = [];
var page = dataTable.page();
......@@ -288,9 +294,19 @@ MapsAdminPanel.prototype.setProjects = function (projects) {
var rowData = self.projectToTableRow(project, undefined, user);
self.addUpdateListener(project, rowData);
data.push(rowData);
if (project.getStatus().toLowerCase() !== "ok" && project.getStatus().toLowerCase() !== "failure") {
requireUpdate = true;
}
}
//it should be simplified, but I couldn't make it work
dataTable.clear().rows.add(data).page(page).draw(false).page(page).draw(false);
if (requireUpdate) {
setTimeout(function () {
logger.debug("Projects auto refresh");
return self.onRefreshClicked();
}, MapsAdminPanel.AUTO_REFRESH_TIME);
}
});
};
......
......@@ -6,7 +6,8 @@ var MapsAdminPanel = require('../../../../main/js/gui/admin/MapsAdminPanel');
var ServerConnector = require('../../ServerConnector-mock');
var logger = require('../../logger');
var assert = require('assert');
var chai = require('chai');
var assert = chai.assert;
var Promise = require('bluebird');
function createMapsAdminPanel() {
......@@ -19,13 +20,40 @@ function createMapsAdminPanel() {
describe('MapsAdminPanel', function () {
it('refresh', function () {
var mapTab = createMapsAdminPanel();
return mapTab.init().then(function () {
return mapTab.onRefreshClicked();
}).then(function () {
assert.equal(0, logger.getWarnings().length);
return mapTab.destroy();
describe('refresh', function () {
it('default', function () {
var mapTab = createMapsAdminPanel();
return mapTab.init().then(function () {
return mapTab.onRefreshClicked();
}).then(function () {
assert.equal(0, logger.getWarnings().length);
return mapTab.destroy();
});
});
it('with auto refresh', function () {
var mapTab = createMapsAdminPanel();
var originalFunction = ServerConnector.getProjects;
var calls = 0;
MapsAdminPanel.AUTO_REFRESH_TIME=50;
ServerConnector.getProjects = function(){
calls++;
var project = helper.createProject();
project.setStatus("xyz");
return Promise.resolve([project]);
};
return mapTab.init().then(function () {
ServerConnector.getProjects = function(){
calls++;
return Promise.resolve([]);
};
return Promise.delay(60);
}).then(function () {
assert.ok(calls>=2);
}).finally(function(){
ServerConnector.getProjects = originalFunction;
MapsAdminPanel.AUTO_REFRESH_TIME=5000;
return mapTab.destroy();
});
});
});
it('showLogs', function () {
......
......@@ -217,6 +217,8 @@ Helper.prototype.createProject = function (params) {
}
var result = new Project();
result.setProjectId("testId");
result.setName("");
result.setProgress(0);
result.setId(this.idCounter++);
result.addModel(this.createModel());
var overlay = this.createOverlay(result.getModels()[0]);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment