Commit 52a9a187 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

Merge branch '333-plugin-api-should-allow-to-store-user-data' into 'master'

Resolve "plugin API should allow to store user data"

Closes #333

See merge request piotr.gawron/minerva!221
parents 981d9a9f 0266d7cc
Pipeline #4101 passed with stage
in 1 minute and 10 seconds
......@@ -361,4 +361,209 @@ Functions.loadScript = function (url) {
});
};
Functions.computeMD5 = function (s) {
function L(k, d) {
return (k << d) | (k >>> (32 - d))
}
function K(G, k) {
var I, d, F, H, x;
F = (G & 2147483648);
H = (k & 2147483648);
I = (G & 1073741824);
d = (k & 1073741824);
x = (G & 1073741823) + (k & 1073741823);
if (I & d) {
return (x ^ 2147483648 ^ F ^ H)
}
if (I | d) {
if (x & 1073741824) {
return (x ^ 3221225472 ^ F ^ H)
} else {
return (x ^ 1073741824 ^ F ^ H)
}
} else {
return (x ^ F ^ H)
}
}
function r(d, F, k) {
return (d & F) | ((~d) & k)
}
function q(d, F, k) {
return (d & k) | (F & (~k))
}
function p(d, F, k) {
return (d ^ F ^ k)
}
function n(d, F, k) {
return (F ^ (d | (~k)))
}
function u(G, F, aa, Z, k, H, I) {
G = K(G, K(K(r(F, aa, Z), k), I));
return K(L(G, H), F)
}
function f(G, F, aa, Z, k, H, I) {
G = K(G, K(K(q(F, aa, Z), k), I));
return K(L(G, H), F)
}
function D(G, F, aa, Z, k, H, I) {
G = K(G, K(K(p(F, aa, Z), k), I));
return K(L(G, H), F)
}
function t(G, F, aa, Z, k, H, I) {
G = K(G, K(K(n(F, aa, Z), k), I));
return K(L(G, H), F)
}
function e(G) {
var Z;
var F = G.length;
var x = F + 8;
var k = (x - (x % 64)) / 64;
var I = (k + 1) * 16;
var aa = Array(I - 1);
var d = 0;
var H = 0;
while (H < F) {
Z = (H - (H % 4)) / 4;
d = (H % 4) * 8;
aa[Z] = (aa[Z] | (G.charCodeAt(H) << d));
H++
}
Z = (H - (H % 4)) / 4;
d = (H % 4) * 8;
aa[Z] = aa[Z] | (128 << d);
aa[I - 2] = F << 3;
aa[I - 1] = F >>> 29;
return aa
}
function B(x) {
var k = "", F = "", G, d;
for (d = 0; d <= 3; d++) {
G = (x >>> (d * 8)) & 255;
F = "0" + G.toString(16);
k = k + F.substr(F.length - 2, 2)
}
return k
}
function J(k) {
k = k.replace(/rn/g, "n");
var d = "";
for (var F = 0; F < k.length; F++) {
var x = k.charCodeAt(F);
if (x < 128) {
d += String.fromCharCode(x)
} else {
if ((x > 127) && (x < 2048)) {
d += String.fromCharCode((x >> 6) | 192);
d += String.fromCharCode((x & 63) | 128)
} else {
d += String.fromCharCode((x >> 12) | 224);
d += String.fromCharCode(((x >> 6) & 63) | 128);
d += String.fromCharCode((x & 63) | 128)
}
}
}
return d
}
var C = Array();
var P, h, E, v, g, Y, X, W, V;
var S = 7, Q = 12, N = 17, M = 22;
var A = 5, z = 9, y = 14, w = 20;
var o = 4, m = 11, l = 16, j = 23;
var U = 6, T = 10, R = 15, O = 21;
s = J(s);
C = e(s);
Y = 1732584193;
X = 4023233417;
W = 2562383102;
V = 271733878;
for (P = 0; P < C.length; P += 16) {
h = Y;
E = X;
v = W;
g = V;
Y = u(Y, X, W, V, C[P + 0], S, 3614090360);
V = u(V, Y, X, W, C[P + 1], Q, 3905402710);
W = u(W, V, Y, X, C[P + 2], N, 606105819);
X = u(X, W, V, Y, C[P + 3], M, 3250441966);
Y = u(Y, X, W, V, C[P + 4], S, 4118548399);
V = u(V, Y, X, W, C[P + 5], Q, 1200080426);
W = u(W, V, Y, X, C[P + 6], N, 2821735955);
X = u(X, W, V, Y, C[P + 7], M, 4249261313);
Y = u(Y, X, W, V, C[P + 8], S, 1770035416);
V = u(V, Y, X, W, C[P + 9], Q, 2336552879);
W = u(W, V, Y, X, C[P + 10], N, 4294925233);
X = u(X, W, V, Y, C[P + 11], M, 2304563134);
Y = u(Y, X, W, V, C[P + 12], S, 1804603682);
V = u(V, Y, X, W, C[P + 13], Q, 4254626195);
W = u(W, V, Y, X, C[P + 14], N, 2792965006);
X = u(X, W, V, Y, C[P + 15], M, 1236535329);
Y = f(Y, X, W, V, C[P + 1], A, 4129170786);
V = f(V, Y, X, W, C[P + 6], z, 3225465664);
W = f(W, V, Y, X, C[P + 11], y, 643717713);
X = f(X, W, V, Y, C[P + 0], w, 3921069994);
Y = f(Y, X, W, V, C[P + 5], A, 3593408605);
V = f(V, Y, X, W, C[P + 10], z, 38016083);
W = f(W, V, Y, X, C[P + 15], y, 3634488961);
X = f(X, W, V, Y, C[P + 4], w, 3889429448);
Y = f(Y, X, W, V, C[P + 9], A, 568446438);
V = f(V, Y, X, W, C[P + 14], z, 3275163606);
W = f(W, V, Y, X, C[P + 3], y, 4107603335);
X = f(X, W, V, Y, C[P + 8], w, 1163531501);
Y = f(Y, X, W, V, C[P + 13], A, 2850285829);
V = f(V, Y, X, W, C[P + 2], z, 4243563512);
W = f(W, V, Y, X, C[P + 7], y, 1735328473);
X = f(X, W, V, Y, C[P + 12], w, 2368359562);
Y = D(Y, X, W, V, C[P + 5], o, 4294588738);
V = D(V, Y, X, W, C[P + 8], m, 2272392833);
W = D(W, V, Y, X, C[P + 11], l, 1839030562);
X = D(X, W, V, Y, C[P + 14], j, 4259657740);
Y = D(Y, X, W, V, C[P + 1], o, 2763975236);
V = D(V, Y, X, W, C[P + 4], m, 1272893353);
W = D(W, V, Y, X, C[P + 7], l, 4139469664);
X = D(X, W, V, Y, C[P + 10], j, 3200236656);
Y = D(Y, X, W, V, C[P + 13], o, 681279174);
V = D(V, Y, X, W, C[P + 0], m, 3936430074);
W = D(W, V, Y, X, C[P + 3], l, 3572445317);
X = D(X, W, V, Y, C[P + 6], j, 76029189);
Y = D(Y, X, W, V, C[P + 9], o, 3654602809);
V = D(V, Y, X, W, C[P + 12], m, 3873151461);
W = D(W, V, Y, X, C[P + 15], l, 530742520);
X = D(X, W, V, Y, C[P + 2], j, 3299628645);
Y = t(Y, X, W, V, C[P + 0], U, 4096336452);
V = t(V, Y, X, W, C[P + 7], T, 1126891415);
W = t(W, V, Y, X, C[P + 14], R, 2878612391);
X = t(X, W, V, Y, C[P + 5], O, 4237533241);
Y = t(Y, X, W, V, C[P + 12], U, 1700485571);
V = t(V, Y, X, W, C[P + 3], T, 2399980690);
W = t(W, V, Y, X, C[P + 10], R, 4293915773);
X = t(X, W, V, Y, C[P + 1], O, 2240044497);
Y = t(Y, X, W, V, C[P + 8], U, 1873313359);
V = t(V, Y, X, W, C[P + 15], T, 4264355552);
W = t(W, V, Y, X, C[P + 6], R, 2734768916);
X = t(X, W, V, Y, C[P + 13], O, 1309151649);
Y = t(Y, X, W, V, C[P + 4], U, 4149444226);
V = t(V, Y, X, W, C[P + 11], T, 3174756917);
W = t(W, V, Y, X, C[P + 2], R, 718787259);
X = t(X, W, V, Y, C[P + 9], O, 3951481745);
Y = K(Y, h);
X = K(X, E);
W = K(W, v);
V = K(V, g)
}
var i = B(Y) + B(X) + B(W) + B(V);
return i.toLowerCase()
};
module.exports = Functions;
......@@ -313,6 +313,27 @@ ServerConnector.getProjectsUrl = function (queryParams, filterParams) {
});
};
ServerConnector.getRegisterPluginUrl = function (queryParams, filterParams) {
return this.getApiUrl({
type: "plugins/",
params: filterParams
});
};
ServerConnector.getPluginGlobalParamUrl = function (queryParams, filterParams) {
return this.getApiUrl({
url: this.getRegisterPluginUrl(queryParams) + queryParams.hash + "/data/global/" + queryParams.key + "/",
params: filterParams
});
};
ServerConnector.getPluginUserParamUrl = function (queryParams, filterParams) {
return this.getApiUrl({
url: this.getRegisterPluginUrl(queryParams) + queryParams.hash + "/data/users/" + queryParams.login + "/" + queryParams.key + "/",
params: filterParams
});
};
ServerConnector.getProjectUrl = function (queryParams, filterParams) {
var id = this.getIdOrAsterisk(queryParams.projectId);
return this.getApiUrl({
......@@ -1897,4 +1918,57 @@ ServerConnector.getSbmlParameter = function (params) {
});
};
ServerConnector.registerPlugin = function (params) {
var self = this;
if (params === undefined) {
params = {};
}
return self.sendPostRequest(self.getRegisterPluginUrl(), params);
};
ServerConnector.getPluginGlobalParam = function (params) {
var self = this;
if (params === undefined) {
params = {};
}
return self.sendGetRequest(self.getPluginGlobalParamUrl(params));
};
ServerConnector.setPluginGlobalParam = function (params) {
var self = this;
if (params === undefined) {
params = {};
}
var filterParams = {
value: params.value
};
return self.sendPostRequest(self.getPluginGlobalParamUrl(params), filterParams);
};
ServerConnector.getPluginUserParam = function (params) {
var self = this;
if (params === undefined) {
params = {};
}
return self.getLoggedUser().then(function (user) {
params.login = user.getLogin();
return self.sendGetRequest(self.getPluginUserParamUrl(params));
})
};
ServerConnector.setPluginUserParam = function (params) {
var self = this;
if (params === undefined) {
params = {};
}
var filterParams = {
value: params.value
};
return self.getLoggedUser().then(function (user) {
params.login = user.getLogin();
return self.sendPostRequest(self.getPluginUserParamUrl(params), filterParams);
});
};
module.exports = ServerConnector;
......@@ -26,6 +26,8 @@ function AbstractCustomMap(model, options) {
if (model === undefined) {
throw Error("Model must be defined");
}
this.registerListenerType("onZoomChanged");
this.registerListenerType("onCenterChanged");
this.setElement(options.getElement());
this.setConfiguration(options.getConfiguration());
......@@ -884,12 +886,20 @@ AbstractCustomMap.prototype._createMapChangedCallbacks = function () {
google.maps.event.addListener(this.getGoogleMap(), 'zoom_changed', function () {
sessionData.setZoomLevel(self.getModel(), self.getGoogleMap().getZoom());
});
google.maps.event.addListener(this.getGoogleMap(), 'zoom_changed', function () {
return self.callListeners("onZoomChanged", self.getGoogleMap().getZoom());
});
// listener for changing location of the map (moving left/right/top/bottom
google.maps.event.addListener(this.getGoogleMap(), 'center_changed', function () {
var coord = self.getGoogleMap().getCenter();
var point = self.fromLatLngToPoint(coord);
sessionData.setCenter(self.getModel(), point);
});
google.maps.event.addListener(this.getGoogleMap(), 'center_changed', function () {
return self.callListeners("onCenterChanged", self.getCenter());
});
};
AbstractCustomMap.prototype.addCenterButton = function () {
......@@ -1063,6 +1073,28 @@ AbstractCustomMap.prototype.setCenter = function (coordinates) {
}
};
AbstractCustomMap.prototype.getCenter = function () {
var coordinates = this.getGoogleMap().getCenter();
return this.fromLatLngToPoint(coordinates);
};
AbstractCustomMap.prototype.getBounds = function () {
var self = this;
var bounds = self.getGoogleMap().getBounds();
var ne = bounds.getNorthEast();
var sw = bounds.getSouthWest();
var result = {
p1: this.fromLatLngToPoint(ne),
p2: this.fromLatLngToPoint(sw)
};
if (result.p2.x > result.p1.x) {
result.p2.x -= 360 * self.pixelsPerLonDegree_*self.zoomFactor;
}
return result;
};
/**
* Sets zoom level for google maps.
*
......@@ -1075,11 +1107,15 @@ AbstractCustomMap.prototype.setZoom = function (zoom) {
if (this.initialized) {
return Promise.resolve(this.getGoogleMap().setZoom(zoom));
} else {
logger.warn("cannot center map that is not opened yet");
logger.warn("cannot change zoom for map that is not opened yet");
return Promise.resolve();
}
};
AbstractCustomMap.prototype.getZoom = function () {
return this.getGoogleMap().getZoom()
};
AbstractCustomMap.prototype.fitBounds = function (markers) {
var self = this;
var map = self.getGoogleMap();
......
......@@ -36,6 +36,8 @@ function CustomMap(options) {
AbstractCustomMap.call(this, options.getProject().getModel(), options);
this.registerListenerType("onBioEntityClick");
this.registerListenerType("onShowOverlay");
this.registerListenerType("onHideOverlay");
this._selectedOverlays = [];
......@@ -242,6 +244,8 @@ CustomMap.prototype.openDataOverlay = function (param) {
}
return Promise.resolve();
}
}).then(function () {
return self.callListeners("onShowOverlay", overlayToOpen);
});
}
};
......@@ -538,6 +542,10 @@ CustomMap.prototype.hideDataOverlay = function (identifier) {
}
ServerConnector.getSessionData(self.getProject()).setVisibleOverlays(ids);
return self.redrawSelectedDataOverlays();
}).then(function () {
return self.getProject().getDataOverlayById(identifier);
}).then(function (overlay) {
return self.callListeners("onHideOverlay", overlay);
});
}
};
......
......@@ -5,6 +5,8 @@ var IdentifiedElement = require('../map/data/IdentifiedElement');
var UserDbOverlay = require('../map/overlay/UserDbOverlay');
var Configuration = require('../Configuration');
var logger = require('../logger');
var Promise = require("bluebird");
function getOverlayByName(customMap, dbOverlayName) {
......@@ -244,6 +246,7 @@ function createProjectMap(options) {
addListener: function (param) {
var object = null;
var listenerWrapper = null;
var listenerType = param.type;
if (param.dbOverlayName !== undefined) {
object = getOverlayByName(map, param.dbOverlayName);
listenerWrapper = function (e) {
......@@ -256,12 +259,45 @@ function createProjectMap(options) {
listenerWrapper = function () {
return param.callback();
};
} else if (param.object === "overlay") {
object = map;
if (param.type === "onShow") {
listenerType = "onShowOverlay";
} else if (param.type === "onHide") {
listenerType = "onHideOverlay";
} else {
throw new Error("Unknown listener type: " + param.type);
}
listenerWrapper = function (e) {
return param.callback(e.arg);
};
} else if (param.object === "map") {
object = map;
if (param.type === "onZoomChanged") {
listenerWrapper = function (e) {
return param.callback({modelId: e.object.getId(), zoom: e.arg});
};
} else if (param.type === "onCenterChanged") {
listenerWrapper = function (e) {
return param.callback({modelId: e.object.getId(), center: e.arg});
};
} else {
throw new Error("Unknown listener type: " + param.type);
}
} else {
throw new Error("Invalid argument");
}
object.addListener(param.type, listenerWrapper);
listenersData.push({listener: param.callback, wrapper: listenerWrapper, object: object, type: param.type});
object.addListener(listenerType, listenerWrapper);
listenersData.push({listener: param.callback, wrapper: listenerWrapper, object: object, type: listenerType});
if (object === map) {
var submaps = map.getSubmaps();
for (var i = 0; i < submaps.length; i++) {
var submap = submaps[i];
submap.addListener(listenerType, listenerWrapper);
listenersData.push({listener: param.callback, wrapper: listenerWrapper, object: submap, type: listenerType});
}
}
},
removeListener: function (param) {
var dbOverlay = getOverlayByName(map, param.dbOverlayName);
......@@ -371,6 +407,20 @@ function createProjectMap(options) {
}
return submap.setCenter(new google.maps.Point(params.x, params.y));
},
getCenter: function (params) {
var submap = map.getSubmapById(params.modelId);
if (submap === null) {
throw new Error("Unknown modelId: " + params.modelId);
}
return submap.getCenter();
},
getBounds: function (params) {
var submap = map.getSubmapById(params.modelId);
if (submap === null) {
throw new Error("Unknown modelId: " + params.modelId);
}
return submap.getBounds();
},
fitBounds: function (params) {
var submap = map.getSubmapById(params.modelId);
if (submap === null) {
......@@ -392,6 +442,13 @@ function createProjectMap(options) {
}
return submap.setZoom(params.zoom);
},
getZoom: function (params) {
var submap = map.getSubmapById(params.modelId);
if (submap === null) {
throw new Error("Unknown modelId: " + params.modelId);
}
return submap.getZoom();
},
openMap: function (params) {
return map.openSubmap(params.id);
}
......@@ -422,12 +479,30 @@ function createConfiguration(options) {
};
}
function createPluginData(options) {
return {
setGlobalParam: function (key, value) {
return ServerConnector.setPluginGlobalParam({hash: options.hash, key: key, value: value});
},
getGlobalParam: function (key) {
return ServerConnector.getPluginGlobalParam({hash: options.hash, key: key});
},
setUserParam: function (key, value) {
return ServerConnector.setPluginUserParam({hash: options.hash, key: key, value: value});
},
getUserParam: function (key) {
return ServerConnector.getPluginUserParam({hash: options.hash, key: key});
}
};
}
function MinervaPluginProxy(options) {
return {
pluginId: options.pluginId,
element: options.element,
project: createProject(options),
configuration: createConfiguration(options)
configuration: createConfiguration(options),
pluginData: createPluginData(options)
};
}
......
......@@ -6,6 +6,7 @@ var ObjectWithListeners = require('../ObjectWithListeners');
var Promise = require("bluebird");
var logger = require('../logger');
var Functions = require('../Functions');
var pluginId = 0;
......@@ -49,16 +50,18 @@ Plugin.prototype.load = function () {
var self = this;
var options = self.getOptions();
var hash;
var error = false;
var registerPromise = null;
return ServerConnector.sendRequest({
url: options.url,
description: "Loading plugin: " + options.url,
method: "GET"
}).then(function (content) {
hash = Functions.computeMD5(content);
var pluginData = undefined;
var error = false;
try {
var registerPromise = null;
// noinspection JSUnusedLocalSymbols
var minervaDefine = function (pluginFunction) {
try {
......@@ -69,6 +72,7 @@ Plugin.prototype.load = function () {
}
var minervaPluginProxy = new MinervaPluginProxy({