diff --git a/frontend-js/src/main/js/Functions.js b/frontend-js/src/main/js/Functions.js index bf016d2f577ff11e7b0ce9b22375d1aa5c9006b3..9fc811c193ad498b7de77357be40ad692ef259e4 100644 --- a/frontend-js/src/main/js/Functions.js +++ b/frontend-js/src/main/js/Functions.js @@ -264,9 +264,11 @@ Functions.getElementByName = function (element, name) { * * @param {Object} params * @param {string} params.type type of the {HTMLElement} to be created + * @param {string} [params.inputType] type of the input to be created * @param {string} [params.className] css class of the element * @param {string} [params.style] css styling * @param {string} [params.value] + * @param {string|HTMLElement} [params.content] * * @returns {HTMLElement} */ @@ -285,7 +287,9 @@ Functions.createElement = function (params) { result.type = params.inputType; } if (params.content !== null && params.content !== undefined) { - if (params.xss !== false) { + if (Functions.isDomElement(params.content)) { + result.appendChild(params.content); + } else if (params.xss !== false) { var content = xss(params.content); if (content !== params.content) { logger.warn("XSS changed content: " + params.content); diff --git a/frontend-js/src/main/js/ObjectWithListeners.js b/frontend-js/src/main/js/ObjectWithListeners.js index df0dfa815cbd5683ab8b935cf46dd8456cb99ba4..5b54f6f37f2900ab379ec623995364b282f2339d 100644 --- a/frontend-js/src/main/js/ObjectWithListeners.js +++ b/frontend-js/src/main/js/ObjectWithListeners.js @@ -143,7 +143,7 @@ ObjectWithListeners.prototype.removePropertyListener = function (name, fun) { * @param arg * argument data passed to the handler * - * @returns {Promise} + * @returns {PromiseLike} */ ObjectWithListeners.prototype.callListeners = function (type, arg) { if (this._validListeners[type] === undefined) { diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js index 422f046f7c72e745c6f9fc2632b94c905991fb78..58058cf16cfcd17dbb36bccd5c0851fbffeaad7d 100644 --- a/frontend-js/src/main/js/ServerConnector.js +++ b/frontend-js/src/main/js/ServerConnector.js @@ -150,6 +150,11 @@ function isSessionExpiredError(error) { return false; } +/** + * + * @param params + * @returns {PromiseLike} + */ ServerConnector.sendRequest = function (params) { var self = this; if (arguments.length > 1) { @@ -236,6 +241,12 @@ ServerConnector.sendDeleteRequest = function (url, json) { }); }; +/** + * + * @param url + * @param json + * @returns {PromiseLike} + */ ServerConnector.sendPatchRequest = function (url, json) { return this.sendRequest({ method: "PATCH", @@ -279,7 +290,7 @@ ServerConnector.createGetParams = function (params, prefix) { if (prefix !== undefined) { key = prefix + "." + key; } - if (value instanceof Point ) { + if (value instanceof Point) { value = this.pointToString(value); } else if (Object.prototype.toString.call(value) === '[object Array]') { value = this.idsToString(value); @@ -829,6 +840,11 @@ ServerConnector.getProject = function (projectId) { }); }; +/** + * + * @param {Project} project + * @returns {PromiseLike|Promise} + */ ServerConnector.updateProject = function (project) { var self = this; var queryParams = { @@ -840,14 +856,16 @@ ServerConnector.updateProject = function (project) { version: project.getVersion(), notifyEmail: project.getNotifyEmail(), organism: self.serialize(project.getOrganism()), - disease: self.serialize(project.getDisease()) + disease: self.serialize(project.getDisease()), + mapCanvasType: project.getMapCanvasType() } }; return self.sendPatchRequest(self.getProjectUrl(queryParams), filterParams).then(function (content) { var downloadedProject = new Project(content); - project.update(downloadedProject); + return project.update(downloadedProject); + }).then(function () { return project; - }).then(null, function (error) { + }).catch(function (error) { if ((error instanceof NetworkError)) { switch (error.statusCode) { case HttpStatus.FORBIDDEN: diff --git a/frontend-js/src/main/js/gui/AbstractGuiElement.js b/frontend-js/src/main/js/gui/AbstractGuiElement.js index 59af4fa59929b15570ddaf0b93214e1e805d1252..f2817d3a395badbdaf3103c8d5c39cbeb3974f00 100644 --- a/frontend-js/src/main/js/gui/AbstractGuiElement.js +++ b/frontend-js/src/main/js/gui/AbstractGuiElement.js @@ -54,6 +54,10 @@ AbstractGuiElement.prototype.setProject = function (project) { this._project = project; }; +/** + * + * @returns {Project} + */ AbstractGuiElement.prototype.getProject = function () { if (this._project === undefined || this._project === null) { return this.getMap().getProject(); @@ -97,6 +101,10 @@ AbstractGuiElement.prototype.setConfiguration = function (configuration) { this._configuration = configuration; }; +/** + * + * @returns {Configuration} + */ AbstractGuiElement.prototype.getConfiguration = function () { return this._configuration; }; diff --git a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js index 963c02464c218224b94a584a01ab9825f29865ec..99f09eba27e999cc0923825799decaee9f05b29f 100644 --- a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js +++ b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js @@ -323,7 +323,7 @@ AddProjectDialog.prototype.createGeneralTabContent = function () { onclick: function () { return self.onSaveClicked().then(function () { return self.close(); - }, GuiConnector.alert); + }).catch(GuiConnector.alert); }, xss: false }); @@ -429,8 +429,8 @@ AddProjectDialog.prototype.createRow = function (elements) { result.appendChild(element); } return result; - }; + AddProjectDialog.prototype.createOverlaysTab = function (tabMenuDiv, tabContentDiv) { var self = this; self.addTab({ @@ -792,7 +792,7 @@ AddProjectDialog.prototype._fillMapCanvasTypeSelectOptions = function (select, c } $(licenceCheckbox).prop('checked', false); }); - }) + }); }; diff --git a/frontend-js/src/main/js/gui/admin/EditProjectDialog.js b/frontend-js/src/main/js/gui/admin/EditProjectDialog.js index b65a1d542b9a1646f678488c5a9d5f7930a03f54..e43b1160d326762bf05246cd50fcffffd93b029b 100644 --- a/frontend-js/src/main/js/gui/admin/EditProjectDialog.js +++ b/frontend-js/src/main/js/gui/admin/EditProjectDialog.js @@ -9,6 +9,7 @@ var Annotation = require('../../map/data/Annotation'); var CommentsTab = require('./CommentsAdminPanel'); var GuiConnector = require('../../GuiConnector'); var PrivilegeType = require('../../map/data/PrivilegeType'); +var ValidationError = require("../../ValidationError"); var Functions = require('../../Functions'); // noinspection JSUnusedLocalSymbols @@ -157,12 +158,52 @@ EditProjectDialog.prototype.createGeneralTabContent = function () { style: "display:table-cell", content: "ProjectId" })); - projectIdRow.appendChild(new Functions.createElement({ + projectIdRow.appendChild(Functions.createElement({ type: "div", style: "display:table-cell", content: project.getProjectId() })); + var mapCanvasTypeRow = Functions.createElement({ + type: "div", + style: "display:table-row" + }); + table.appendChild(mapCanvasTypeRow); + mapCanvasTypeRow.appendChild(Functions.createElement({ + type: "div", + style: "display:table-cell", + content: "Map canvas type: " + })); + mapCanvasTypeRow.appendChild(Functions.createElement({ + type: "div", + style: "display:table-cell", + content: Functions.createElement({ + type: "select", + name: "project-map-canvas-type" + }) + })); + + var googleLicenseRow = Functions.createElement({ + type: "div", + style: "display:table-row" + }); + table.appendChild(googleLicenseRow); + googleLicenseRow.appendChild(Functions.createElement({ + type: "div", + style: "display:table-cell", + content: "I agree to <a href='https://developers.google.com/maps/terms'>Google Maps APIs Terms of Service</a>: ", + xss: false + })); + googleLicenseRow.appendChild(Functions.createElement({ + type: "div", + style: "display:table-cell", + content: Functions.createElement({ + type: "input", + inputType: "checkbox", + name: "project-google-maps-license" + }) + })); + var nameRow = new Functions.createElement({ type: "div", style: "display:table-row" @@ -548,6 +589,42 @@ EditProjectDialog.prototype.init = function () { }).then(function () { return self.refreshComments(); }).then(function () { + var configuration = self.getConfiguration(); + var mapCanvasTypes = configuration.getMapCanvasTypes(); + var select = $("[name='project-map-canvas-type']", self.getElement())[0]; + var licenceCheckbox = $("[name='project-google-maps-license']", self.getElement())[0]; + var licenceDiv = licenceCheckbox.parentElement.parentElement; + + for (var i = 0; i < mapCanvasTypes.length; i++) { + var mapCanvasType = mapCanvasTypes[i]; + var option = Functions.createElement({ + type: "option", + content: mapCanvasType.name, + value: mapCanvasType.id + }); + if (mapCanvasType.id === self.getProject().getMapCanvasType()) { + option.selected = true; + if (mapCanvasType.id === "GOOGLE_MAPS_API") { + $(licenceDiv).css("display", "table-row"); + self.setLicenseAccepted(true); + } else { + $(licenceDiv).css("display", "none"); + self.setLicenseAccepted(false); + } + } + select.appendChild(option); + } + $(select).change(function () { + $("option:selected", select).each(function () { + if ($(this).val() === "GOOGLE_MAPS_API") { + $(licenceDiv).css("display", "table-row"); + } else { + $(licenceDiv).css("display", "none"); + } + self.setLicenseAccepted(false); + }); + }); + $(window).trigger('resize'); }); }; @@ -784,18 +861,45 @@ var prepareMiriamData = function (type, resource) { } }; +/** + * + * @returns {PromiseLike} + */ EditProjectDialog.prototype.onSaveClicked = function () { var self = this; var project = self.getProject(); var element = self.getElement(); - project.setName($("[name='projectName']", element)[0].value); - project.setVersion($("[name='projectVersion']", element)[0].value); - project.setNotifyEmail($("[name='projectNotifyEmail']", element)[0].value); - var organism = prepareMiriamData("TAXONOMY", $("[name='projectOrganism']", element)[0].value); - project.setOrganism(organism); - var disease = prepareMiriamData("MESH_2012", $("[name='projectDisease']", element)[0].value); - project.setDisease(disease); - return ServerConnector.updateProject(project); + return self.checkValidity().then(function () { + project.setName($("[name='projectName']", element)[0].value); + project.setVersion($("[name='projectVersion']", element)[0].value); + project.setNotifyEmail($("[name='projectNotifyEmail']", element)[0].value); + var organism = prepareMiriamData("TAXONOMY", $("[name='projectOrganism']", element)[0].value); + project.setOrganism(organism); + var disease = prepareMiriamData("MESH_2012", $("[name='projectDisease']", element)[0].value); + project.setDisease(disease); + project.setMapCanvasType(self.getMapCanvasTypeId()); + return ServerConnector.updateProject(project); + }); +}; + +EditProjectDialog.prototype.checkValidity = function () { + var self = this; + var isValid = true; + var error = "<b>Some data is missing.</b><ul>"; + + var mapCanvasTypeId = self.getMapCanvasTypeId(); + if (mapCanvasTypeId === "GOOGLE_MAPS_API") { + if (!self.isLicenseAccepted()) { + isValid = false; + error += "<li>Please accept Google Maps License when choosing Google Maps API engine</li>"; + } + } + + if (isValid) { + return Promise.resolve(true); + } else { + return Promise.reject(new ValidationError(error)); + } }; EditProjectDialog.prototype.close = function () { var self = this; @@ -905,5 +1009,35 @@ EditProjectDialog.prototype.destroy = function () { } }; +/** + * + * @param {string} mapCanvasTypeId + */ +EditProjectDialog.prototype.setMapCanvasTypeId = function (mapCanvasTypeId) { + var select = $("[name='project-map-canvas-type']", this.getElement()); + select.val(mapCanvasTypeId); + select.change(); +}; + +/** + * + * @returns {string} + */ +EditProjectDialog.prototype.getMapCanvasTypeId = function () { + return $("[name='project-map-canvas-type']", this.getElement()).val(); +}; + + +EditProjectDialog.prototype.setLicenseAccepted = function (isLicenseAccepted) { + $("[name='project-google-maps-license']", this.getElement()).prop("checked", isLicenseAccepted); +}; + +/** + * + * @returns {boolean} + */ +EditProjectDialog.prototype.isLicenseAccepted = function () { + return $("[name='project-google-maps-license']", this.getElement()).is(":checked"); +}; module.exports = EditProjectDialog; diff --git a/frontend-js/src/main/js/map/data/Project.js b/frontend-js/src/main/js/map/data/Project.js index da5e7eff2cd479ccc02b1ba58ab7d9b8a5ebb043..43dbd5051a0f9f81186931f70ff8a84369b2eb2c 100644 --- a/frontend-js/src/main/js/map/data/Project.js +++ b/frontend-js/src/main/js/map/data/Project.js @@ -72,7 +72,7 @@ Project.prototype.loadFromData = function (data) { /** * * @param {Project} data - * @returns {Promise} + * @returns {PromiseLike} */ Project.prototype.update = function (data) { this._update(data); diff --git a/frontend-js/src/test/js/gui/admin/EditProjectDialog-test.js b/frontend-js/src/test/js/gui/admin/EditProjectDialog-test.js index 0d808a00081fa7f1f4eb5c3f5215e0f6dbc08654..63d4373df80bd07df6c12f83d71b2db608de3eb7 100644 --- a/frontend-js/src/test/js/gui/admin/EditProjectDialog-test.js +++ b/frontend-js/src/test/js/gui/admin/EditProjectDialog-test.js @@ -96,6 +96,8 @@ describe('EditProjectDialog', function () { customMap: null, configuration: helper.getConfiguration() }); + return dialog.init(); + }).then(function () { return dialog.onSaveClicked(); }).then(function (result) { assert.ok(project === result); diff --git a/frontend-js/testFiles/apiCalls/projects/sample/PATCH_project.disease.resource=D010300&project.disease.type=MESH_2012&project.name=UNKNOWN DISEASE MAP&project.organism.resource=9606&project.organism.type=TAXONOMY&project.version=2.01&token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/projects/sample/PATCH_project.disease.resource=D010300&project.disease.type=MESH_2012&project.mapCanvasType=OPEN_LAYERS&project.name=UNKNOWN DISEASE MAP&project.organism.resource=9606&project.organism.type=TAXONOMY&project.version=2.01&token=MOCK_TOKEN_ID& similarity index 100% rename from frontend-js/testFiles/apiCalls/projects/sample/PATCH_project.disease.resource=D010300&project.disease.type=MESH_2012&project.name=UNKNOWN DISEASE MAP&project.organism.resource=9606&project.organism.type=TAXONOMY&project.version=2.01&token=MOCK_TOKEN_ID& rename to frontend-js/testFiles/apiCalls/projects/sample/PATCH_project.disease.resource=D010300&project.disease.type=MESH_2012&project.mapCanvasType=OPEN_LAYERS&project.name=UNKNOWN DISEASE MAP&project.organism.resource=9606&project.organism.type=TAXONOMY&project.version=2.01&token=MOCK_TOKEN_ID&