From cfdd39df2feecabf66965c3aab84f0ec75709b21 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <piotr.gawron@uni.lu> Date: Fri, 8 Sep 2017 13:05:20 +0200 Subject: [PATCH] work in progress --- frontend-js/src/main/js/Configuration.js | 12 + .../src/main/js/gui/admin/AddProjectDialog.js | 30 ++- .../js/gui/admin/ChooseValidatorsDialog.js | 220 ++++++++++++++++++ .../src/main/js/map/data/UserPreferences.js | 1 + .../gui/admin/ChooseValidatorsDialog-test.js | 47 ++++ web/src/main/webapp/admin-new.xhtml | 4 +- web/src/main/webapp/export-new.xhtml | 4 +- 7 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 frontend-js/src/main/js/gui/admin/ChooseValidatorsDialog.js create mode 100644 frontend-js/src/test/js/gui/admin/ChooseValidatorsDialog-test.js diff --git a/frontend-js/src/main/js/Configuration.js b/frontend-js/src/main/js/Configuration.js index 783461f2e2..f8bf26513b 100644 --- a/frontend-js/src/main/js/Configuration.js +++ b/frontend-js/src/main/js/Configuration.js @@ -142,6 +142,14 @@ Configuration.prototype.setMiriamTypes = function (miriamTypes) { this._miriamTypes.push(new MiriamType(typeData, key)); } } + this._miriamTypes.sort(function compare(a, b) { + if (a.getCommonName() < b.getCommonName()) + return -1; + if (a.getCommonName() > b.getCommonName()) + return 1; + return 0; + } + ); }; Configuration.prototype.setPrivilegeTypes = function (privilegeTypes) { @@ -169,6 +177,10 @@ Configuration.prototype.getMiriamTypeByName = function (name) { return null; }; +Configuration.prototype.getMiriamTypes = function () { + return this._miriamTypes; +}; + Configuration.prototype.setModificationStateTypes = function (modificationStateTypes) { this._modificationStateTypes = []; for (var key in modificationStateTypes) { diff --git a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js index cf51867179..5f03de0349 100644 --- a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js +++ b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js @@ -5,6 +5,7 @@ var Promise = require("bluebird"); var AbstractGuiElement = require('../AbstractGuiElement'); var ChooseAnnotatorsDialog = require('./ChooseAnnotatorsDialog'); +var ChooseValidatorsDialog = require('./ChooseValidatorsDialog'); var GuiConnector = require('../../GuiConnector'); var UserPreferences = require("../../map/data/UserPreferences"); @@ -106,6 +107,22 @@ AddProjectDialog.prototype.showAnnotatorsDialog = function () { return self._annotatorsDialog.open(); }); }; +AddProjectDialog.prototype.showValidatorsDialog = function () { + var self = this; + var promise; + if (self._validatorsDialog === undefined) { + self._validatorsDialog = new ChooseValidatorsDialog({ + element: Functions.createElement({type: "div"}), + customMap: null + }); + promise = self._validatorsDialog.init(); + } else { + promise = Promise.resolve(); + } + return promise.then(function () { + return self._validatorsDialog.open(); + }); +}; AddProjectDialog.prototype.createGeneralTabContent = function () { var self = this; @@ -167,9 +184,17 @@ AddProjectDialog.prototype.createGeneralTabContent = function () { return self.showAnnotatorsDialog().then(null, GuiConnector.alert); } }); + var showValidatorsButton = Functions.createElement({ + type: "button", + name: "project-show-validators", + content: "Advanced", + onclick: function () { + return self.showValidatorsDialog().then(null, GuiConnector.alert); + } + }); table.appendChild(self.createCheckboxRow("Annotate model automatically:", false, "project-annotate-automatically", [showAnnotatorsButton])); - table.appendChild(self.createCheckboxRow("Verify manual annotations:", false, "project-verify-annotations")); + table.appendChild(self.createCheckboxRow("Verify manual annotations:", false, "project-verify-annotations", [showValidatorsButton])); table.appendChild(self.createCheckboxRow("Cache data:", false, "project-cache-data")); table.appendChild(self.createCheckboxRow("Auto margin:", true, "project-auto-margin")); table.appendChild(self.createCheckboxRow("Display as SBGN:", false, "project-sbgn-visualization")); @@ -384,6 +409,9 @@ AddProjectDialog.prototype.destroy = function () { if (self._annotatorsDialog !== undefined) { self._annotatorsDialog.destroy(); } + if (self._validatorsDialog !== undefined) { + self._validatorsDialog.destroy(); + } }; AddProjectDialog.prototype.open = function () { diff --git a/frontend-js/src/main/js/gui/admin/ChooseValidatorsDialog.js b/frontend-js/src/main/js/gui/admin/ChooseValidatorsDialog.js new file mode 100644 index 0000000000..74913e85f2 --- /dev/null +++ b/frontend-js/src/main/js/gui/admin/ChooseValidatorsDialog.js @@ -0,0 +1,220 @@ +"use strict"; + +/* exported logger */ + +var AbstractGuiElement = require('../AbstractGuiElement'); +var DualListbox = require('dual-listbox').DualListbox; +var GuiConnector = require("../../GuiConnector"); +var UserPreferences = require("../../map/data/UserPreferences"); + +var Functions = require('../../functions'); +var logger = require('../../logger'); + +var Promise = require("bluebird"); + +function ChooseValidatorsDialog(params) { + AbstractGuiElement.call(this, params); + var self = this; + self.createGui(); +} + +ChooseValidatorsDialog.prototype = Object.create(AbstractGuiElement.prototype); +ChooseValidatorsDialog.prototype.constructor = ChooseValidatorsDialog; + +ChooseValidatorsDialog.prototype.createGui = function () { + var self = this; + var content = Functions.createElement({ + type: "div", + style: "display:table" + }); + content.appendChild(Functions.createElement({ + type: "div", + style: "display:table-cell", + content: "<div name='elementTree'/>" + })); + + content.appendChild(Functions.createElement({ + type: "div", + style: "display:table-cell", + content: "<div name='annotatorListBox'/>" + })); + + self.getElement().appendChild(content); +}; + +ChooseValidatorsDialog.prototype.setElementType = function (elementType) { + var self = this; + + var configuration; + + return ServerConnector.getConfiguration().then(function (result) { + configuration = result; + return ServerConnector.getLoggedUser(); + }).then(function (user) { + var element = $("[name='annotatorListBox']", self.getElement())[0]; + Functions.removeChildren(element); + + var validAnnotationSelect = Functions.createElement({ + type: "select", + className: "minerva-multi-select" + }); + + var miriamTypes = configuration.getMiriamTypes(); + + var validAnnotations = user.getPreferences().getElementValidAnnotations(elementType.className); + + for (var i = 0; i < miriamTypes.length; i++) { + var miriamType = miriamTypes[i]; + var selected = false; + for (var j = 0; j < validAnnotations.length; j++) { + if (miriamType.getName() === validAnnotations[j]) { + selected = true; + } + } + var option = new Option(); + option.value = miriamType.getName(); + option.attributes.selected = selected; + option.innerHTML = "<div>" + miriamType.getCommonName() + "</div>"; + validAnnotationSelect.appendChild(option); + } + + element.appendChild(validAnnotationSelect); + new DualListbox(validAnnotationSelect, { + addEvent: function (value) { + var miriamTypes = configuration.getMiriamTypes(); + var miriamType; + for (var i = 0; i < miriamTypes.length; i++) { + if (value === miriamTypes[i].getName()) { + miriamType = miriamTypes[i]; + } + } + validAnnotations.push(miriamType.getName()); + + var data = new UserPreferences(); + + var elementAnnotators = {}; + elementAnnotators[elementType.className] = validAnnotations; + data.setElementValidAnnotations(elementAnnotators); + return ServerConnector.updateUserPreferences({user: user, preferences: data}).then(null, GuiConnector.alert); + }, + removeEvent: function (value) { + var miriamTypes = configuration.getMiriamTypes(); + var miriamType; + for (var i = 0; i < miriamTypes.length; i++) { + if (value === miriamTypes[i].getName()) { + miriamType = miriamTypes[i]; + } + } + var index = validAnnotations.indexOf(miriamType.getName()); + if (index > -1) { + validAnnotations.splice(index, 1); + } + + var data = new UserPreferences(); + + var elementAnnotators = {}; + elementAnnotators[elementType.className] = validAnnotations; + data.setElementValidAnnotations(elementAnnotators); + return ServerConnector.updateUserPreferences({user: user, preferences: data}).then(null, GuiConnector.alert); + }, + availableTitle: 'Available', + selectedTitle: 'Used', + addButtonText: '>', + removeButtonText: '<', + addAllButtonText: '>>', + removeAllButtonText: '<<' + }); + }); + +}; + +ChooseValidatorsDialog.prototype.init = function () { + var self = this; + return ServerConnector.getConfiguration().then(function (configuration) { + + var treeData = self.createElementTree(configuration); + + var element = $('[name="elementTree"]', self.getElement()); + element.jstree({ + core: { + data: treeData + } + }).on('ready.jstree', function () { + element.jstree("open_all"); + }).on("select_node.jstree", + function (evt, data) { + return self.setElementType(data.node.data); + } + ); + }); +}; + +ChooseValidatorsDialog.prototype.createElementTree = function (configuration) { + + var elementTypes = configuration.getElementTypes(); + var reactionTypes = configuration.getReactionTypes(); + + var treeNodes = { + "lcsb.mapviewer.model.map.BioEntity": { + text: "BioEntity", + children: [] + } + }; + + var i; + for (i = 0; i < elementTypes.length; i++) { + var type = elementTypes[i]; + var name = type.className; + if (name.indexOf(".") > 0) { + name = name.substr(name.lastIndexOf(".") + 1); + } + treeNodes[type.className] = { + text: name, + data: type, + children: [] + }; + } + + for (i = 0; i < reactionTypes.length; i++) { + var type = reactionTypes[i]; + treeNodes[type.className] = { + text: type.name, + data: type, + children: [] + }; + } + + for (var treeNodeName in treeNodes) { + if (treeNodes.hasOwnProperty(treeNodeName)) { + var treeNode = treeNodes[treeNodeName]; + if (treeNode.data !== undefined) { + var parentNode = treeNodes[treeNode.data.parentClass]; + parentNode.children.push(treeNode); + } + } + } + + return treeNodes["lcsb.mapviewer.model.map.BioEntity"]; +}; + +ChooseValidatorsDialog.prototype.destroy = function () { + $(this.getElement()).dialog("destroy"); +}; + +ChooseValidatorsDialog.prototype.open = function () { + var self = this; + var div = self.getElement(); + if (!$(div).hasClass("ui-dialog-content")) { + $(div).dialog({ + title: "Select valid annotations", + modal: true, + width: window.innerWidth / 2, + height: window.innerHeight / 2 + + }); + } + + $(div).dialog("open"); +}; + +module.exports = ChooseValidatorsDialog; diff --git a/frontend-js/src/main/js/map/data/UserPreferences.js b/frontend-js/src/main/js/map/data/UserPreferences.js index e4b36b9b84..e4591977b2 100644 --- a/frontend-js/src/main/js/map/data/UserPreferences.js +++ b/frontend-js/src/main/js/map/data/UserPreferences.js @@ -70,6 +70,7 @@ UserPreferences.prototype.toExport = function () { "semantic-zooming": this._projectUpload.semanticZooming }, "element-annotators": this._elementAnnotators, + "element-valid-annotations": this._elementValidAnnotations }; }; diff --git a/frontend-js/src/test/js/gui/admin/ChooseValidatorsDialog-test.js b/frontend-js/src/test/js/gui/admin/ChooseValidatorsDialog-test.js new file mode 100644 index 0000000000..9ed8f4cbef --- /dev/null +++ b/frontend-js/src/test/js/gui/admin/ChooseValidatorsDialog-test.js @@ -0,0 +1,47 @@ +"use strict"; + +/* exported assert */ +/* exported logger */ +require("../../mocha-config"); + +var ChooseValidatorsDialog = require('../../../../main/js/gui/admin/ChooseValidatorsDialog'); +var logger = require('../../logger'); + +var chai = require('chai'); +var assert = chai.assert; + +describe('ChooseValidatorsDialog', function () { + it('init', function () { + var dialog = new ChooseValidatorsDialog({ + element: testDiv, + customMap: null + }); + return dialog.init(); + }); + + it('createElementTree', function () { + var dialog = new ChooseValidatorsDialog({ + element: testDiv, + customMap: null + }); + return ServerConnector.getConfiguration().then(function (configuration) { + var treeData = dialog.createElementTree(configuration); + + assert.ok(treeData); + assert.ok(treeData.text); + assert.ok(treeData.children); + assert.equal(2, treeData.children.length); + }) + }); + + it('setElementType', function () { + var dialog = new ChooseValidatorsDialog({ + element: testDiv, + customMap: null + }); + return ServerConnector.getConfiguration().then(function (configuration) { + return dialog.setElementType(configuration.getReactionTypes()[0]); + }) + }); + +}); diff --git a/web/src/main/webapp/admin-new.xhtml b/web/src/main/webapp/admin-new.xhtml index c3c23487b7..e243418bcb 100644 --- a/web/src/main/webapp/admin-new.xhtml +++ b/web/src/main/webapp/admin-new.xhtml @@ -15,9 +15,11 @@ <script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.min.js" type="text/javascript"/> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> - <script src="https://cdn.datatables.net/1.10.13/js/jquery.dataTables.min.js"></script> + <script src="https://cdn.datatables.net/1.10.13/js/jquery.dataTables.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script> <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.13/css/jquery.dataTables.min.css"/> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" /> <link rel="shortcut icon" href="./resources/images/favicon.png" type="image/png" /> diff --git a/web/src/main/webapp/export-new.xhtml b/web/src/main/webapp/export-new.xhtml index e84a149b5e..41c263b3d4 100644 --- a/web/src/main/webapp/export-new.xhtml +++ b/web/src/main/webapp/export-new.xhtml @@ -16,11 +16,13 @@ <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <script src="https://cdn.datatables.net/1.10.13/js/jquery.dataTables.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script> <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.13/css/jquery.dataTables.min.css"/> <link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"/> - + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" /> + <link rel="shortcut icon" href="./resources/images/favicon.png" type="image/png" /> <h:outputScript library="js" name="minerva.js" /> -- GitLab