diff --git a/frontend-js/.idea/jsLinters/jshint.xml b/frontend-js/.idea/jsLinters/jshint.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d81b34316962a9dac27738599f2ef19c3f27a046
--- /dev/null
+++ b/frontend-js/.idea/jsLinters/jshint.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JSHintConfiguration" version="2.9.5" use-config-file="true" use-custom-config-file="true" custom-config-file-path="$PROJECT_DIR$/.jshintrc">
+    <option asi="false" />
+    <option bitwise="true" />
+    <option boss="false" />
+    <option browser="true" />
+    <option browserify="false" />
+    <option camelcase="false" />
+    <option couch="false" />
+    <option curly="true" />
+    <option debug="false" />
+    <option devel="false" />
+    <option dojo="false" />
+    <option elision="false" />
+    <option enforceall="false" />
+    <option eqeqeq="true" />
+    <option eqnull="false" />
+    <option es3="false" />
+    <option es5="false" />
+    <option esnext="false" />
+    <option evil="false" />
+    <option expr="false" />
+    <option forin="true" />
+    <option freeze="false" />
+    <option funcscope="false" />
+    <option futurehostile="false" />
+    <option gcl="false" />
+    <option globalstrict="false" />
+    <option immed="false" />
+    <option iterator="false" />
+    <option jasmine="false" />
+    <option jquery="false" />
+    <option lastsemic="false" />
+    <option latedef="false" />
+    <option laxbreak="false" />
+    <option laxcomma="false" />
+    <option loopfunc="false" />
+    <option maxerr="50" />
+    <option mocha="false" />
+    <option module="false" />
+    <option mootools="false" />
+    <option moz="false" />
+    <option multistr="false" />
+    <option newcap="false" />
+    <option noarg="true" />
+    <option nocomma="false" />
+    <option node="false" />
+    <option noempty="true" />
+    <option nomen="false" />
+    <option nonbsp="false" />
+    <option nonew="true" />
+    <option nonstandard="false" />
+    <option notypeof="false" />
+    <option noyield="false" />
+    <option onevar="false" />
+    <option passfail="false" />
+    <option phantom="false" />
+    <option plusplus="false" />
+    <option proto="false" />
+    <option prototypejs="false" />
+    <option qunit="false" />
+    <option quotmark="false" />
+    <option rhino="false" />
+    <option scripturl="false" />
+    <option shadow="false" />
+    <option shelljs="false" />
+    <option singleGroups="false" />
+    <option smarttabs="false" />
+    <option strict="true" />
+    <option sub="false" />
+    <option supernew="false" />
+    <option trailing="false" />
+    <option typed="false" />
+    <option undef="true" />
+    <option unused="false" />
+    <option validthis="false" />
+    <option varstmt="false" />
+    <option white="false" />
+    <option withstmt="false" />
+    <option worker="false" />
+    <option wsh="false" />
+    <option yui="false" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/frontend-js/.jshintrc b/frontend-js/.jshintrc
index f4cf0adf392e6f0e75a3c844a0116af4c9e9b232..a37287075c9c28818b9a538f9096fe01464f1913 100644
--- a/frontend-js/.jshintrc
+++ b/frontend-js/.jshintrc
@@ -22,11 +22,11 @@
     "sub": true,
     "trailing": true,
     "smarttabs": true,
-    
+
   "globals"   : {
-    
+
     "alert" : false,
-    
+
     /*
      * custom test params
      */
@@ -40,7 +40,7 @@
     "beforeEach" : false,
     "after"      : false,
     "afterEach"  : false,
-    
+
     /* minerva globals */
     "GuiConnector"  : false,
     "ServerConnector"  : false,
@@ -56,5 +56,5 @@
 
   },
   "predef": [ "-Promise" ]
-    
+
 }
diff --git a/frontend-js/src/main/js/GuiConnector.js b/frontend-js/src/main/js/GuiConnector.js
index f88e1fac215aef206f54858073a9e1009409cf8d..1f68d4408c65b530a4a2b8a135638ed4bfc62cf3 100644
--- a/frontend-js/src/main/js/GuiConnector.js
+++ b/frontend-js/src/main/js/GuiConnector.js
@@ -4,6 +4,7 @@ var logger = require('./logger');
 
 var Functions = require('./Functions');
 var SecurityError = require('./SecurityError');
+var ValidationError = require('./ValidationError');
 var GuiMessageError = require('./gui/GuiMessageError');
 var NetworkError = require('./NetworkError');
 
@@ -18,12 +19,20 @@ function GuiConnector() {
   this.yPos = 0;
 }
 
+function returnThisOrSingleton(object) {
+  if (object === undefined || object === null) {
+    return GuiConnector.singleton;
+  } else {
+    return object;
+  }
+}
+
 /**
  * List of GET params passed via url.
  */
 
 GuiConnector.prototype.init = function () {
-  var self = this;
+  var self = returnThisOrSingleton(this);
 
   if (!String.prototype.endsWith) {
     String.prototype.endsWith = function (pattern) {
@@ -53,10 +62,10 @@ GuiConnector.prototype.init = function () {
     self.getParams[decode(arguments[1])] = decode(arguments[2]);
   });
 
-  // forser browser to update mouse coordinates whenever mouse move
+  // force browser to update mouse coordinates whenever mouse move
   jQuery(document).ready(function () {
     $(document).mousemove(function (e) {
-      this.updateMouseCoordinates(e.pageX, e.pageY);
+      self.updateMouseCoordinates(e.pageX, e.pageY);
     });
   });
 
@@ -113,12 +122,13 @@ GuiConnector.prototype.getImgPrefix = function () {
  * Updates coordinates of the mouse in the browser.
  */
 GuiConnector.prototype.updateMouseCoordinates = function (x, y) {
-  this.xPos = x;
-  this.yPos = y;
+  var self = returnThisOrSingleton(this);
+  self.xPos = x;
+  self.yPos = y;
 };
 
 GuiConnector.prototype.showProcessing = function (messageText) {
-  var self = this;
+  var self = returnThisOrSingleton(this);
   if (self._processingDialog === undefined) {
     self._processingDialog = document.createElement("div");
     self._processingDialogContent = document.createElement("div");
@@ -129,7 +139,7 @@ GuiConnector.prototype.showProcessing = function (messageText) {
       title: "PROCESSING",
       width: "150px",
       closeOnEscape: false,
-      dialogClass: 'minerva-no-close',
+      dialogClass: 'minerva-no-close'
     });
   }
   if (messageText === undefined) {
@@ -137,7 +147,7 @@ GuiConnector.prototype.showProcessing = function (messageText) {
   }
   var messageImg = Functions.createElement({
     type: "img",
-    src: 'resources/images/icons/ajax-loader.gif',
+    src: 'resources/images/icons/ajax-loader.gif'
   });
   self._processingDialogContent.innerHTML = "";
   self._processingDialogContent.style.textAlign = "center";
@@ -149,12 +159,12 @@ GuiConnector.prototype.showProcessing = function (messageText) {
 };
 
 GuiConnector.prototype.hideProcessing = function () {
-  var self = this;
+  var self = returnThisOrSingleton(this);
   $(self._processingDialog).dialog("close");
 };
 
 GuiConnector.prototype.alert = function (error) {
-  var self = this;
+  var self = returnThisOrSingleton(this);
   logger.error(error);
   if (self._errorDialog === undefined) {
     self._errorDialog = document.createElement("div");
@@ -172,6 +182,8 @@ GuiConnector.prototype.alert = function (error) {
   var message = error;
   if (message instanceof SecurityError) {
     message = error.message + "<p>Please <a href=\"login.xhtml?from="+encodeURI(window.location.href)+"\">login</a> to access this resource</p>";
+  } else if (message instanceof ValidationError) {
+    message = error.message;
   } else if (message instanceof GuiMessageError) {
     message = error.message;
   } else if (message instanceof NetworkError && (error.message === "XHR error" || error.message === "Failed to fetch")) {
@@ -185,7 +197,7 @@ GuiConnector.prototype.alert = function (error) {
 };
 
 GuiConnector.prototype.info = function (message) {
-  var self = this;
+  var self = returnThisOrSingleton(this);
   if (self._infoDialog === undefined) {
     self._infoDialog = document.createElement("div");
     self._infoDialogContent = document.createElement("div");
@@ -205,7 +217,7 @@ GuiConnector.prototype.info = function (message) {
 };
 
 GuiConnector.prototype.destroy = function () {
-  var self = this;
+  var self = returnThisOrSingleton(this);
 
   if (self._infoDialog !== undefined) {
     $(self._infoDialog).dialog("destroy").remove();
@@ -219,4 +231,7 @@ GuiConnector.prototype.destroy = function () {
   }
 };
 
-module.exports = new GuiConnector();
+GuiConnector.singleton = new GuiConnector();
+
+
+module.exports = GuiConnector.singleton;
diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js
index ce4c81d45a7a3574d8e4aaac285aa92b6f2406eb..530faf20efbb8c5746de8798f544bcbb58d4b6a2 100644
--- a/frontend-js/src/main/js/ServerConnector.js
+++ b/frontend-js/src/main/js/ServerConnector.js
@@ -57,13 +57,14 @@ ServerConnector.init = function() {
   self._loggedUser = undefined;
   self._serverBaseUrl = undefined;
 
+  var i;
   var listeners = self.getListeners("onDataLoadStart");
-  for (var i = 0; i < listeners.length; i++) {
+  for (i = 0; i < listeners.length; i++) {
     self.removeListener("onDataLoadStart", listeners[i]);
   }
 
-  var listeners = self.getListeners("onDataLoadStop");
-  for (var i = 0; i < listeners.length; i++) {
+  listeners = self.getListeners("onDataLoadStop");
+  for (i = 0; i < listeners.length; i++) {
     self.removeListener("onDataLoadStop", listeners[i]);
   }
 
@@ -689,10 +690,37 @@ ServerConnector.updateProject = function(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);
+        case HttpStatus.FORBIDDEN:
+          return Promise.reject(new SecurityError("Access denied."));
+        default:
+          return Promise.reject(error);
+      }
+    } else {
+      return Promise.reject(error);
+    }
+  });
+};
+
+ServerConnector.addProject = function(options) {
+  var self = this;
+  var queryParams = {
+    projectId : options.projectId
+  };
+  return self.sendPostRequest(self.getProjectUrl(queryParams), options).then(function(content) {
+    var project = new Project(content);
+    if (self._projectsById[project.getProjectId()] !== undefined) {
+      self._projectsById[project.getProjectId()].update(project);
+    } else {
+      self._projectsById[project.getProjectId()] = project;
+    }
+    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);
       }
     } else {
       return Promise.reject(error);
diff --git a/frontend-js/src/main/js/ValidationError.js b/frontend-js/src/main/js/ValidationError.js
new file mode 100644
index 0000000000000000000000000000000000000000..e23e2abe0257e48d6f75528bbc63074c921e1819
--- /dev/null
+++ b/frontend-js/src/main/js/ValidationError.js
@@ -0,0 +1,15 @@
+"use strict";
+
+/* exported logger */
+
+var logger = require('./logger');
+
+function ValidationError(message) {
+  this.message = message;
+  this.stack = (new Error()).stack;
+}
+
+ValidationError.prototype = Object.create(Error.prototype);
+ValidationError.prototype.constructor = ValidationError;
+
+module.exports = ValidationError;
diff --git a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js
index 8abb8cd323817b0f3c44f084a043d50cf3fe16d0..08dac1d77e70a0eb84c68703b8d926464911a7eb 100644
--- a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js
+++ b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js
@@ -11,6 +11,8 @@ var logger = require('../../logger');
 
 var guiUtils = new (require('../leftPanel/GuiUtils'))();
 
+var ValidationError = require("../../ValidationError");
+
 function AddProjectDialog(params) {
   AbstractGuiElement.call(this, params);
   var self = this;
@@ -23,26 +25,26 @@ function AddProjectDialog(params) {
 AddProjectDialog.prototype = Object.create(AbstractGuiElement.prototype);
 AddProjectDialog.prototype.constructor = AddProjectDialog;
 
-AddProjectDialog.prototype.createGui = function() {
+AddProjectDialog.prototype.createGui = function () {
   var self = this;
   var element = self.getElement();
 
   var tabDiv = Functions.createElement({
-    type : "div",
-    name : "tabView",
-    className : "tabbable boxed parentTabs"
+    type: "div",
+    name: "tabView",
+    className: "tabbable boxed parentTabs"
   });
   element.appendChild(tabDiv);
 
   var tabMenuDiv = Functions.createElement({
-    type : "ul",
-    className : "nav nav-tabs"
+    type: "ul",
+    className: "nav nav-tabs"
   });
   tabDiv.appendChild(tabMenuDiv);
 
   var tabContentDiv = Functions.createElement({
-    type : "div",
-    className : "tab-content"
+    type: "div",
+    className: "tab-content"
   });
   tabDiv.appendChild(tabContentDiv);
 
@@ -52,30 +54,30 @@ AddProjectDialog.prototype.createGui = function() {
   self.createOverviewImagesTab(tabMenuDiv, tabContentDiv);
 };
 
-AddProjectDialog.prototype.createGeneralTab = function(tabMenuDiv, tabContentDiv) {
+AddProjectDialog.prototype.createGeneralTab = function (tabMenuDiv, tabContentDiv) {
   var self = this;
   self.addTab({
-    tabMenuDiv : tabMenuDiv,
-    tabContentDiv : tabContentDiv,
-    name : "GENERAL",
-    id : "add_project_general_tab",
-    content : self.createGeneralTabContent(),
+    tabMenuDiv: tabMenuDiv,
+    tabContentDiv: tabContentDiv,
+    name: "GENERAL",
+    id: "add_project_general_tab",
+    content: self.createGeneralTabContent(),
   });
 
 };
 
-AddProjectDialog.prototype.addTab = function(params) {
+AddProjectDialog.prototype.addTab = function (params) {
   var navLi = guiUtils.createTabMenuObject({
-    id : params.id,
-    name : params.name,
-    navigationBar : params.tabMenuDiv
+    id: params.id,
+    name: params.name,
+    navigationBar: params.tabMenuDiv
   });
   params.tabMenuDiv.appendChild(navLi);
 
   var contentDiv = guiUtils.createTabContentObject({
-    id : params.id,
-    navigationObject : navLi,
-    navigationBar : params.tabMenuDiv
+    id: params.id,
+    navigationObject: navLi,
+    navigationBar: params.tabMenuDiv
   });
 
   if (params.content !== undefined) {
@@ -85,32 +87,32 @@ AddProjectDialog.prototype.addTab = function(params) {
   params.tabContentDiv.appendChild(contentDiv);
 };
 
-AddProjectDialog.prototype.createGeneralTabContent = function() {
+AddProjectDialog.prototype.createGeneralTabContent = function () {
   var self = this;
 
   var result = new Functions.createElement({
-    type : "div",
+    type: "div",
   });
 
   var table = new Functions.createElement({
-    type : "div",
-    style : "display:table"
+    type: "div",
+    style: "display:table"
   });
   result.appendChild(table);
 
   var fileInput = Functions.createElement({
-    type : "input",
-    inputType : "file",
-    name : "project-file",
+    type: "input",
+    inputType: "file",
+    name: "project-file",
   });
-  fileInput.addEventListener("change", function() {
+  fileInput.addEventListener("change", function () {
     return self.callListeners("onFileUpload", fileInput.files[0]);
   }, false);
-  self.addListener("onFileUpload", function(e) {
+  self.addListener("onFileUpload", function (e) {
     var file = e.arg;
     return self.processFile(file);
   });
-  self.addListener("onFileUpload", function(e) {
+  self.addListener("onFileUpload", function (e) {
     var file = e.arg;
     if (file.name.lastIndexOf('.') > 0) {
       return self.setProjectId(file.name.substring(0, file.name.lastIndexOf('.')));
@@ -118,15 +120,15 @@ AddProjectDialog.prototype.createGeneralTabContent = function() {
       return file.name;
     }
   });
-  self.addListener("onFileUpload", function(e) {
+  self.addListener("onFileUpload", function (e) {
     var file = e.arg;
     return self.setFileParserForFilename(file.name);
   });
   table.appendChild(self.createRow(guiUtils.createLabel("Upload file: "), fileInput));
 
   var fileFormatSelect = Functions.createElement({
-    type : "select",
-    name : "project-format",
+    type: "select",
+    name: "project-format",
   });
 
   table.appendChild(self.createRow(guiUtils.createLabel("File format: "), fileFormatSelect));
@@ -136,6 +138,7 @@ AddProjectDialog.prototype.createGeneralTabContent = function() {
   table.appendChild(self.createInputRow("Project Disease:", "", "project-disease"));
   table.appendChild(self.createInputRow("Organism:", "", "project-organism"));
   table.appendChild(self.createInputRow("Version:", "", "project-version"));
+  table.appendChild(self.createInputRow("Notify email:", "", "project-notify-email"));
 
   table.appendChild(self.createCheckboxRow("Annotate model automatically:", false, "project-annotate-automatically"));
   table.appendChild(self.createCheckboxRow("Verify manual annotations:", false, "project-verify-annotations"));
@@ -145,27 +148,27 @@ AddProjectDialog.prototype.createGeneralTabContent = function() {
   table.appendChild(self.createCheckboxRow("Semantic zooming:", false, "project-semantic-zooming"));
 
   var saveProjectButton = Functions.createElement({
-    type : "button",
-    name : "saveProject",
-    content : '<span class="ui-icon ui-icon-disk"></span>&nbsp;SAVE',
-    onclick : function() {
-      return self.onSaveClicked().then(function() {
+    type: "button",
+    name: "saveProject",
+    content: '<span class="ui-icon ui-icon-disk"></span>&nbsp;SAVE',
+    onclick: function () {
+      return self.onSaveClicked().then(function () {
         return self.close();
       }, GuiConnector.alert);
     },
   });
   var cancelButton = Functions.createElement({
-    type : "button",
-    name : "cancelProject",
-    content : '<span class="ui-icon ui-icon-cancel"></span>&nbsp;CANCEL',
-    onclick : function() {
+    type: "button",
+    name: "cancelProject",
+    content: '<span class="ui-icon ui-icon-cancel"></span>&nbsp;CANCEL',
+    onclick: function () {
       return self.close();
     },
   });
   var menuRow = Functions.createElement({
-    type : "div",
-    className : "minerva-menu-row",
-    style : "display:table-row; margin:10px",
+    type: "div",
+    className: "minerva-menu-row",
+    style: "display:table-row; margin:10px",
   });
   result.appendChild(menuRow);
   menuRow.appendChild(saveProjectButton);
@@ -173,47 +176,47 @@ AddProjectDialog.prototype.createGeneralTabContent = function() {
 
   return result;
 };
-AddProjectDialog.prototype.createInputRow = function(labelName, defaultValue, inputName) {
+AddProjectDialog.prototype.createInputRow = function (labelName, defaultValue, inputName) {
   var label = new Functions.createElement({
-    type : "div",
-    style : "display:table-cell",
-    content : labelName,
+    type: "div",
+    style: "display:table-cell",
+    content: labelName,
   });
   var input = new Functions.createElement({
-    type : "div",
-    style : "display:table-cell",
-    content : "<input name='" + inputName + "' value='" + defaultValue + "'/>",
+    type: "div",
+    style: "display:table-cell",
+    content: "<input name='" + inputName + "' value='" + defaultValue + "'/>",
   });
   return this.createRow(label, input);
 };
 
-AddProjectDialog.prototype.createCheckboxRow = function(labelName, defaultValue, inputName) {
+AddProjectDialog.prototype.createCheckboxRow = function (labelName, defaultValue, inputName) {
   var label = new Functions.createElement({
-    type : "div",
-    style : "display:table-cell",
-    content : labelName,
+    type: "div",
+    style: "display:table-cell",
+    content: labelName,
   });
   var checked = "";
   if (defaultValue) {
     checked = "checked";
   }
   var checkbox = new Functions.createElement({
-    type : "div",
-    style : "display:table-cell",
-    content : "<input type='checkbox' name='" + inputName + "' " + checked + "/>",
+    type: "div",
+    style: "display:table-cell",
+    content: "<input type='checkbox' name='" + inputName + "' " + checked + "/>",
   });
   return this.createRow(label, checkbox);
 };
 
-AddProjectDialog.prototype.createRow = function(label, value) {
+AddProjectDialog.prototype.createRow = function (label, value) {
   var result = new Functions.createElement({
-    type : "div",
-    style : "display:table-row"
+    type: "div",
+    style: "display:table-row"
   });
   if (label.tagName.toLowerCase() !== 'div') {
     var labelContainer = new Functions.createElement({
-      type : "div",
-      style : "display:table-cell",
+      type: "div",
+      style: "display:table-cell",
     });
     labelContainer.appendChild(label);
     label = labelContainer;
@@ -221,8 +224,8 @@ AddProjectDialog.prototype.createRow = function(label, value) {
   result.appendChild(label);
   if (value.tagName.toLowerCase() !== 'div') {
     var valueContainer = new Functions.createElement({
-      type : "div",
-      style : "display:table-cell",
+      type: "div",
+      style: "display:table-cell",
     });
     valueContainer.appendChild(value);
     value = valueContainer;
@@ -231,80 +234,80 @@ AddProjectDialog.prototype.createRow = function(label, value) {
   return result;
 
 };
-AddProjectDialog.prototype.createOverlaysTab = function(tabMenuDiv, tabContentDiv) {
+AddProjectDialog.prototype.createOverlaysTab = function (tabMenuDiv, tabContentDiv) {
   var self = this;
   self.addTab({
-    tabMenuDiv : tabMenuDiv,
-    tabContentDiv : tabContentDiv,
-    name : "OVERLAYS",
-    id : "project_overlays_tab",
-    content : self.createOverlaysTabContent(),
+    tabMenuDiv: tabMenuDiv,
+    tabContentDiv: tabContentDiv,
+    name: "OVERLAYS",
+    id: "project_overlays_tab",
+    content: self.createOverlaysTabContent(),
   });
 };
 
-AddProjectDialog.prototype.createOverlaysTabContent = function() {
+AddProjectDialog.prototype.createOverlaysTabContent = function () {
   var self = this;
   var result = Functions.createElement({
-    type : "div",
+    type: "div",
   });
   result.appendChild(self._createOverlayTable());
   return result;
 };
 
-AddProjectDialog.prototype._createOverlayTable = function() {
+AddProjectDialog.prototype._createOverlayTable = function () {
   var result = Functions.createElement({
-    type : "div",
-    style : "margin-top:10px;",
+    type: "div",
+    style: "margin-top:10px;",
   });
 
   return result;
 };
 
-AddProjectDialog.prototype.createSubmapsTab = function(tabMenuDiv, tabContentDiv) {
+AddProjectDialog.prototype.createSubmapsTab = function (tabMenuDiv, tabContentDiv) {
   var self = this;
   self.addTab({
-    tabMenuDiv : tabMenuDiv,
-    tabContentDiv : tabContentDiv,
-    name : "USERS",
-    id : "project_submaps_tab",
-    content : self.createSubmapsTabContent(),
+    tabMenuDiv: tabMenuDiv,
+    tabContentDiv: tabContentDiv,
+    name: "USERS",
+    id: "project_submaps_tab",
+    content: self.createSubmapsTabContent(),
   });
 };
 
-AddProjectDialog.prototype.createSubmapsTabContent = function() {
+AddProjectDialog.prototype.createSubmapsTabContent = function () {
   var result = Functions.createElement({
-    type : "div",
-    style : "margin-top:10px;",
+    type: "div",
+    style: "margin-top:10px;",
   });
   return result;
 };
 
-AddProjectDialog.prototype.createOverviewImagesTab = function(tabMenuDiv, tabContentDiv) {
+AddProjectDialog.prototype.createOverviewImagesTab = function (tabMenuDiv, tabContentDiv) {
   var self = this;
   self.addTab({
-    tabMenuDiv : tabMenuDiv,
-    tabContentDiv : tabContentDiv,
-    name : "USERS",
-    id : "project_overview_images_tab",
-    content : self.createOverviewImagesTabContent(),
+    tabMenuDiv: tabMenuDiv,
+    tabContentDiv: tabContentDiv,
+    name: "USERS",
+    id: "project_overview_images_tab",
+    content: self.createOverviewImagesTabContent(),
   });
 };
 
-AddProjectDialog.prototype.createOverviewImagesTabContent = function() {
+AddProjectDialog.prototype.createOverviewImagesTabContent = function () {
   var result = Functions.createElement({
-    type : "div",
-    style : "margin-top:10px;",
+    type: "div",
+    style: "margin-top:10px;",
   });
   return result;
 };
 
-AddProjectDialog.prototype.init = function() {
+AddProjectDialog.prototype.init = function () {
   var self = this;
-  return ServerConnector.getConfiguration().then(function(configuration) {
+  return ServerConnector.getConfiguration().then(function (configuration) {
     var select = $("[name='project-format']", self.getElement())[0];
     var option = Functions.createElement({
-      type : "option",
-      content : "---",
+      type: "option",
+      content: "---",
     });
     option.selected = true;
     select.appendChild(option);
@@ -312,53 +315,56 @@ AddProjectDialog.prototype.init = function() {
     for (var i = 0; i < converters.length; i++) {
       var converter = converters[i];
       option = Functions.createElement({
-        type : "option",
-        content : converter.name,
+        type: "option",
+        content: converter.name,
       });
       option.data = converter.extension;
       option.value = converter.handler;
       select.appendChild(option);
     }
+    return ServerConnector.getLoggedUser();
+  }).then(function (user) {
+    self.setNotifyEmail(user.getEmail());
   });
 };
 
-AddProjectDialog.prototype.destroy = function() {
+AddProjectDialog.prototype.destroy = function () {
   $(this.getElement()).dialog("destroy");
 };
 
-AddProjectDialog.prototype.open = function() {
+AddProjectDialog.prototype.open = function () {
   var self = this;
   var div = self.getElement();
   if (!$(div).hasClass("ui-dialog-content")) {
     $(div).dialog({
-      title : "ADD PROJECT",
-      width : window.innerWidth / 2,
-      height : window.innerHeight / 2,
+      title: "ADD PROJECT",
+      width: window.innerWidth / 2,
+      height: window.innerHeight / 2,
     });
   }
   $(div).dialog("open");
 };
 
-AddProjectDialog.prototype.close = function() {
+AddProjectDialog.prototype.close = function () {
   var self = this;
   $(self.getElement()).dialog("close");
 };
 
-AddProjectDialog.prototype.clear = function() {
+AddProjectDialog.prototype.clear = function () {
   var self = this;
   $("input", self.getElement()).val("");
   self.setFileContent(undefined);
   return Promise.resolve();
 };
 
-AddProjectDialog.prototype.processFile = function(file) {
+AddProjectDialog.prototype.processFile = function (file) {
   var self = this;
   self.setFileContent(null);
   if (file) {
-    return new Promise(function(resolve, reject) {
+    return new Promise(function (resolve, reject) {
       var reader = new FileReader();
       reader.readAsText(file, "UTF-8");
-      reader.onload = function(evt) {
+      reader.onload = function (evt) {
         try {
           self.setFileContent(evt.target.result);
           resolve(self.getFileContent());
@@ -366,7 +372,7 @@ AddProjectDialog.prototype.processFile = function(file) {
           reject(error);
         }
       };
-      reader.onerror = function() {
+      reader.onerror = function () {
         reject(new Error("Problem reading file"));
       };
     });
@@ -375,22 +381,64 @@ AddProjectDialog.prototype.processFile = function(file) {
   }
 };
 
-AddProjectDialog.prototype.setFileContent = function(fileContent) {
+AddProjectDialog.prototype.setFileContent = function (fileContent) {
   this._fileContent = fileContent;
 };
-AddProjectDialog.prototype.getFileContent = function() {
+AddProjectDialog.prototype.getFileContent = function () {
   return this._fileContent;
 };
 
-AddProjectDialog.prototype.setProjectId = function(projectId) {
+AddProjectDialog.prototype.setProjectId = function (projectId) {
   $("[name='project-id']", this.getElement()).val(projectId);
 };
 
-AddProjectDialog.prototype.getProjectId = function() {
+AddProjectDialog.prototype.getProjectId = function () {
   return $("[name='project-id']", this.getElement()).val();
 };
 
-AddProjectDialog.prototype.setFileParserForFilename = function(filename) {
+AddProjectDialog.prototype.setName = function (name) {
+  $("[name='project-name']", this.getElement()).val(name);
+};
+AddProjectDialog.prototype.setNotifyEmail = function (email) {
+  $("[name='project-notify-email']", this.getElement()).val(email);
+};
+
+AddProjectDialog.prototype.getName = function () {
+  return $("[name='project-name']", this.getElement()).val();
+};
+
+AddProjectDialog.prototype.getDisease = function () {
+  return $("[name='project-disease']", this.getElement()).val();
+};
+AddProjectDialog.prototype.getOrganism = function () {
+  return $("[name='project-organism']", this.getElement()).val();
+};
+AddProjectDialog.prototype.getOrganism = function () {
+  return $("[name='project-version']", this.getElement()).val();
+};
+AddProjectDialog.prototype.getNotifyEmail = function () {
+  return $("[name='project-notify-email']", this.getElement()).val();
+};
+AddProjectDialog.prototype.isAnnotateAutomatically = function () {
+  return $("[name='project-annotate-automatically']", this.getElement()).is(':checked');
+};
+AddProjectDialog.prototype.isVerifyAnnotations = function () {
+  return $("[name='project-verify-annotations']", this.getElement()).is(':checked');
+};
+AddProjectDialog.prototype.isCache = function () {
+  return $("[name='project-cache']", this.getElement()).is(':checked');
+};
+AddProjectDialog.prototype.isAutoMargin = function () {
+  return $("[name='project-auto-margin']", this.getElement()).is(':checked');
+};
+AddProjectDialog.prototype.isSbgn = function () {
+  return $("[name='project-sbgn-visualization']", this.getElement()).is(':checked');
+};
+AddProjectDialog.prototype.isSemanticZooming = function () {
+  return $("[name='project-semantic-zooming']", this.getElement()).is(':checked');
+};
+
+AddProjectDialog.prototype.setFileParserForFilename = function (filename) {
   var self = this;
   var select = $("[name='project-format']", self.getElement)[0];
   var options = select.options;
@@ -406,11 +454,10 @@ AddProjectDialog.prototype.setFileParserForFilename = function(filename) {
   }
   options[optionId].selected = true;
 };
-AddProjectDialog.prototype.getConverter = function() {
+AddProjectDialog.prototype.getConverter = function () {
   var self = this;
   var select = $("[name='project-format']", self.getElement)[0];
-  return ServerConnector.getConfiguration().then(function(configuration) {
-    var options = select.options;
+  return ServerConnector.getConfiguration().then(function (configuration) {
     var handler = select.options[select.selectedIndex].value;
     var converters = configuration.getModelConverters();
     for (var i = 0; i < converters.length; i++) {
@@ -423,4 +470,58 @@ AddProjectDialog.prototype.getConverter = function() {
   });
 };
 
+AddProjectDialog.prototype.onSaveClicked = function () {
+  var self = this;
+  return self.checkValidity().then(function () {
+    return self.getConverter();
+  }).then(function (converter) {
+    var parserClass;
+    if (converter !== null) {
+      parserClass = converter.handler;
+    }
+    var options = {
+      "projectId": self.getProjectId(),
+      "name": self.getName(),
+      "parser": parserClass,
+      "file-content": self.getFileContent(),
+      "auto-resize": self.isAutoMargin(),
+      "cache": self.isCache(),
+      "notify-email": self.getNotifyEmail(),
+      "disease": self.getDisease(),
+      "organism": self.getOrganism(),
+      "sbgn": self.isSbgn(),
+      "semantic-zoom": self.isSemanticZooming(),
+    };
+    return ServerConnector.addProject(options);
+  });
+};
+
+AddProjectDialog.prototype.checkValidity = function () {
+  var self = this;
+  var isValid = true;
+  var error = "<b>Some data is missing.</b><ul>";
+  if (self.getFileContent() === null || self.getFileContent() === undefined) {
+    error += "<li>Please select file before uploading</li>";
+    isValid = false;
+  }
+  return self.getConverter().then(function (converter) {
+    if (converter === null) {
+      error += "<li>Please select converter before uploading</li>";
+      isValid = false;
+    }
+    return ServerConnector.getProject(self.getProjectId());
+  }).then(function (project) {
+    if (project !== null) {
+      error += "<li>Project with given id already exists</li>";
+      isValid = false;
+    }
+    error += "</ul>";
+    if (isValid) {
+      return Promise.resolve(true);
+    } else {
+      return Promise.reject(new ValidationError(error));
+    }
+  });
+};
+
 module.exports = AddProjectDialog;
diff --git a/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js b/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js
index 64259fe14b260a6fb512c5be354ce1df1fa648ed..53de4d5b1d5ad86a1c740f1b0822eb7ebdf63fbb 100644
--- a/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js
+++ b/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js
@@ -10,26 +10,28 @@ var GuiConnector = require('../../GuiConnector');
 var logger = require('../../logger');
 var Functions = require('../../Functions');
 
+var Promise = require('bluebird');
+
 function OverlayPanel(params) {
-    params.panelName = "overlays";
-    params.scrollable = true;
-    params.helpTip = "<p>Overlays tab allows to display or generate custom coloring of elements and interactions in the map.</p>"
-        + "<p>General overlays are overlays accessible for every user viewing the content.</p>"
-        + "<p>Custom overlays are user-provided overlays, this menu becomes available upon login (see below).</p>";
-    Panel.call(this, params);
+  params.panelName = "overlays";
+  params.scrollable = true;
+  params.helpTip = "<p>Overlays tab allows to display or generate custom coloring of elements and interactions in the map.</p>"
+    + "<p>General overlays are overlays accessible for every user viewing the content.</p>"
+    + "<p>Custom overlays are user-provided overlays, this menu becomes available upon login (see below).</p>";
+  Panel.call(this, params);
 
-    var self = this;
+  var self = this;
 
-    self._createOverlayPanelGui();
+  self._createOverlayPanelGui();
 
-    var addButton = this.getControlElement(PanelControlElementType.OVERLAY_ADD_OVERLAY_BUTTON);
+  var addButton = this.getControlElement(PanelControlElementType.OVERLAY_ADD_OVERLAY_BUTTON);
 
-    addButton.onclick = function () {
-        return self.openAddOverlayDialog();
-    };
+  addButton.onclick = function () {
+    return self.openAddOverlayDialog();
+  };
 
-    var titleElement = this.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TITLE);
-    self.setCustomOverlaysMessage(titleElement.innerHTML);
+  var titleElement = this.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TITLE);
+  self.setCustomOverlaysMessage(titleElement.innerHTML);
 
 }
 
@@ -37,352 +39,352 @@ OverlayPanel.prototype = Object.create(Panel.prototype);
 OverlayPanel.prototype.constructor = OverlayPanel;
 
 OverlayPanel.prototype._createOverlayPanelGui = function () {
-    var generalOverlaysDiv = Functions.createElement({
-        type: "div",
-        name: "generalOverlays",
-        className: "searchPanel"
-    });
-    this.getElement().appendChild(generalOverlaysDiv);
-    this.setControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_DIV, generalOverlaysDiv);
-
-    var generalOverlaysTitle = Functions.createElement({
-        type: "h5",
-        content: "GENERAL OVERLAYS:"
-    });
-    generalOverlaysDiv.appendChild(generalOverlaysTitle);
-
-    var generalOverlaysTableDiv = Functions.createElement({
-        type: "table",
-        name: "generalOverlaysTab",
-        className: "table table-bordered",
-        style: "width:100%"
-    });
-    generalOverlaysDiv.appendChild(generalOverlaysTableDiv);
-    this.setControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_TABLE, generalOverlaysTableDiv);
-
-    var customOverlaysDiv = Functions.createElement({
-        type: "div",
-        name: "customOverlays",
-        className: "searchPanel"
-    });
-    this.getElement().appendChild(customOverlaysDiv);
-    this.setControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_DIV, customOverlaysDiv);
-
-    var customOverlaysTitle = Functions.createElement({
-        type: "h5",
-        name: "customOverlaysTitle",
-        content: "USER-PROVIDED OVERLAYS:"
-    });
-    customOverlaysDiv.appendChild(customOverlaysTitle);
-    this.setControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TITLE, customOverlaysTitle);
-
-    var customOverlaysTableDiv = Functions.createElement({
-        type: "table",
-        name: "customOverlaysTab",
-        className: "table table-bordered",
-        style: "width:100%"
-    });
-    customOverlaysDiv.appendChild(customOverlaysTableDiv);
-    this.setControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TABLE, customOverlaysTableDiv);
-
-    var centerTag = Functions.createElement({
-        type: "center"
-    });
-    customOverlaysDiv.appendChild(centerTag);
-
-    var addOverlayButton = Functions.createElement({
-        type: "button",
-        name: "addOverlay",
-        content: "Add overlay"
-    });
-    centerTag.appendChild(addOverlayButton);
-    this.setControlElement(PanelControlElementType.OVERLAY_ADD_OVERLAY_BUTTON, addOverlayButton);
+  var generalOverlaysDiv = Functions.createElement({
+    type: "div",
+    name: "generalOverlays",
+    className: "searchPanel"
+  });
+  this.getElement().appendChild(generalOverlaysDiv);
+  this.setControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_DIV, generalOverlaysDiv);
+
+  var generalOverlaysTitle = Functions.createElement({
+    type: "h5",
+    content: "GENERAL OVERLAYS:"
+  });
+  generalOverlaysDiv.appendChild(generalOverlaysTitle);
+
+  var generalOverlaysTableDiv = Functions.createElement({
+    type: "table",
+    name: "generalOverlaysTab",
+    className: "table table-bordered",
+    style: "width:100%"
+  });
+  generalOverlaysDiv.appendChild(generalOverlaysTableDiv);
+  this.setControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_TABLE, generalOverlaysTableDiv);
+
+  var customOverlaysDiv = Functions.createElement({
+    type: "div",
+    name: "customOverlays",
+    className: "searchPanel"
+  });
+  this.getElement().appendChild(customOverlaysDiv);
+  this.setControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_DIV, customOverlaysDiv);
+
+  var customOverlaysTitle = Functions.createElement({
+    type: "h5",
+    name: "customOverlaysTitle",
+    content: "USER-PROVIDED OVERLAYS:"
+  });
+  customOverlaysDiv.appendChild(customOverlaysTitle);
+  this.setControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TITLE, customOverlaysTitle);
+
+  var customOverlaysTableDiv = Functions.createElement({
+    type: "table",
+    name: "customOverlaysTab",
+    className: "table table-bordered",
+    style: "width:100%"
+  });
+  customOverlaysDiv.appendChild(customOverlaysTableDiv);
+  this.setControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TABLE, customOverlaysTableDiv);
+
+  var centerTag = Functions.createElement({
+    type: "center"
+  });
+  customOverlaysDiv.appendChild(centerTag);
+
+  var addOverlayButton = Functions.createElement({
+    type: "button",
+    name: "addOverlay",
+    content: "Add overlay"
+  });
+  centerTag.appendChild(addOverlayButton);
+  this.setControlElement(PanelControlElementType.OVERLAY_ADD_OVERLAY_BUTTON, addOverlayButton);
 };
 
 OverlayPanel.prototype.clear = function () {
-    var table = this.getControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_TABLE);
-    while (table.firstChild) {
-        table.removeChild(table.firstChild);
-    }
+  var table = this.getControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_TABLE);
+  while (table.firstChild) {
+    table.removeChild(table.firstChild);
+  }
 
-    table = this.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TABLE);
-    while (table.firstChild) {
-        table.removeChild(table.firstChild);
-    }
+  table = this.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TABLE);
+  while (table.firstChild) {
+    table.removeChild(table.firstChild);
+  }
 
 };
 
 OverlayPanel.prototype.createTableHeader = function (edit) {
-    var result = document.createElement("thead");
+  var result = document.createElement("thead");
 
-    var row = document.createElement("tr");
+  var row = document.createElement("tr");
 
-    var nameTd = document.createElement("th");
-    nameTd.innerHTML = "Name";
-    row.appendChild(nameTd);
+  var nameTd = document.createElement("th");
+  nameTd.innerHTML = "Name";
+  row.appendChild(nameTd);
 
-    var viewTd = document.createElement("th");
-    viewTd.innerHTML = "View";
-    row.appendChild(viewTd);
+  var viewTd = document.createElement("th");
+  viewTd.innerHTML = "View";
+  row.appendChild(viewTd);
 
-    var dataTd = document.createElement("th");
-    dataTd.innerHTML = "Data";
-    row.appendChild(dataTd);
+  var dataTd = document.createElement("th");
+  dataTd.innerHTML = "Data";
+  row.appendChild(dataTd);
 
-    if (edit) {
-        var editTd = document.createElement("th");
-        editTd.innerHTML = "Edit";
-        row.appendChild(editTd);
-    }
+  if (edit) {
+    var editTd = document.createElement("th");
+    editTd.innerHTML = "Edit";
+    row.appendChild(editTd);
+  }
 
-    result.appendChild(row);
-    return result;
+  result.appendChild(row);
+  return result;
 };
 
 OverlayPanel.prototype.createOverlayRow = function (overlay, checked) {
-    var self = this;
-    var guiUtils = self.getGuiUtils();
-    var result = document.createElement("tr");
+  var self = this;
+  var guiUtils = self.getGuiUtils();
+  var result = document.createElement("tr");
+
+  if (checked) {
+    result.className = "active";
+  }
+
+  var nameTd = document.createElement("td");
+  nameTd.innerHTML = overlay.getName();
+  result.appendChild(nameTd);
+
+  var viewTd = document.createElement("td");
+  if (overlay.getInputDataAvailable()) {
+    var checkbox = document.createElement("input");
+    checkbox.type = "checkbox";
+    checkbox.checked = checked;
+    checkbox.onclick = function () {
+      if (this.checked) {
+        return self.getMap().openDataOverlay(overlay.getId()).then(null, GuiConnector.alert);
+      } else {
+        return self.getMap().removeSelectedLayout(overlay.getId()).then(null, GuiConnector.alert);
+      }
+    };
+    viewTd.appendChild(checkbox);
+  } else {
+    var img = guiUtils.createIcon("icons/search.png");
+    var link = document.createElement("a");
+    link.href = "#";
+    link.onclick = function () {
+      self.getMap().openDataOverlay(overlay.getId());
+      $(result).addClass('active').siblings().removeClass('active');
+    };
+    link.appendChild(img);
+    viewTd.appendChild(link);
+  }
+  result.appendChild(viewTd);
+
+  var dataTd = document.createElement("td");
+  if (overlay.getInputDataAvailable()) {
+    var button = document.createElement("button");
+    button.setAttribute("name", "download-overlay-" + overlay.getId());
+    button.onclick = function () {
+      return ServerConnector.getOverlaySourceDownloadUrl({
+        overlayId: overlay.getId()
+      }).then(function (url) {
+        return self.downloadFile(url);
+      }).then(null, GuiConnector.alert);
+    };
+    button.innerHTML = "<span class='ui-icon ui-icon-arrowthickstop-1-s'></span>";
+    dataTd.appendChild(button);
+  }
+
+  result.appendChild(dataTd);
+
+  if (overlay.getCreator() !== "" && overlay.getCreator() !== undefined) {
+    var editTd = document.createElement("td");
+    var editButton = document.createElement("button");
+    editButton.setAttribute("name", "editButton");
+    editButton.onclick = function () {
+      return self.openEditOverlayDialog(overlay);
+    };
+    editButton.innerHTML = "<span class='ui-icon ui-icon-document'></span>";
+    editTd.appendChild(editButton);
+    result.appendChild(editTd);
+  }
+  result.title = overlay.getDescription();
+  return result;
+};
 
-    if (checked) {
-        result.className = "active";
+OverlayPanel.prototype.openEditOverlayDialog = function (overlay) {
+  var self = this;
+  var guiUtils = self.getGuiUtils();
+  var content = document.createElement("fieldset");
+  var nameInput = guiUtils.createInputText(overlay.getName());
+  var row = guiUtils.createTableRow([guiUtils.createLabel("Name: "), nameInput]);
+  content.appendChild(row);
+
+  var descriptionInput = guiUtils.createTextArea(overlay.getDescription());
+  row = guiUtils.createTableRow([guiUtils.createLabel("Description: "), descriptionInput]);
+  content.appendChild(row);
+
+  var buttons = [{
+    text: "SAVE",
+    click: function () {
+      var windowSelf = this;
+      overlay.setName(nameInput.value);
+      overlay.setDescription(descriptionInput.value);
+      return ServerConnector.updateOverlay(overlay).then(function () {
+        return self.refresh();
+      }).then(function () {
+        $(windowSelf).dialog("close");
+      }).then(null, GuiConnector.alert);
     }
-
-    var nameTd = document.createElement("td");
-    nameTd.innerHTML = overlay.getName();
-    result.appendChild(nameTd);
-
-    var viewTd = document.createElement("td");
-    if (overlay.getInputDataAvailable()) {
-        var checkbox = document.createElement("input");
-        checkbox.type = "checkbox";
-        checkbox.checked = checked;
-        checkbox.onclick = function () {
-            if (this.checked) {
-                return self.getMap().openDataOverlay(overlay.getId()).then(null, GuiConnector.alert);
-            } else {
-                return self.getMap().removeSelectedLayout(overlay.getId()).then(null, GuiConnector.alert);
-            }
-        };
-        viewTd.appendChild(checkbox);
-    } else {
-        var img = guiUtils.createIcon("icons/search.png");
-        var link = document.createElement("a");
-        link.href = "#";
-        link.onclick = function () {
-            self.getMap().openDataOverlay(overlay.getId());
-            $(result).addClass('active').siblings().removeClass('active');
-        };
-        link.appendChild(img);
-        viewTd.appendChild(link);
+  }, {
+    text: "REMOVE",
+    click: function () {
+      self.getMap().removeSelectedLayout(overlay.getId());
+
+      var windowSelf = this;
+      return ServerConnector.removeOverlay({
+        overlayId: overlay.getId()
+      }).then(function () {
+        return self.refresh();
+      }).then(function () {
+        $(windowSelf).dialog("close");
+      }).then(null, GuiConnector.alert);
     }
-    result.appendChild(viewTd);
-
-    var dataTd = document.createElement("td");
-    if (overlay.getInputDataAvailable()) {
-        var button = document.createElement("button");
-        button.setAttribute("name", "download-overlay-" + overlay.getId());
-        button.onclick = function () {
-            return ServerConnector.getOverlaySourceDownloadUrl({
-                overlayId: overlay.getId()
-            }).then(function (url) {
-                return self.downloadFile(url);
-            }).then(null, GuiConnector.alert);
-        };
-        button.innerHTML = "<span class='ui-icon ui-icon-arrowthickstop-1-s'></span>";
-        dataTd.appendChild(button);
+  }, {
+    text: "CANCEL",
+    click: function () {
+      $(this).dialog("close");
     }
+  }];
+  self.openDialog(content, {
+    id: overlay.getId(),
+    buttons: buttons,
+    title: "Data overlay: " + overlay.getName(),
+    className: "minerva-overlay-dialog",
+  });
+};
 
-    result.appendChild(dataTd);
-
-    if (overlay.getCreator() !== "" && overlay.getCreator() !== undefined) {
-        var editTd = document.createElement("td");
-        var editButton = document.createElement("button");
-        editButton.setAttribute("name", "editButton");
-        editButton.onclick = function () {
-            return self.openEditOverlayDialog(overlay);
-        };
-        editButton.innerHTML = "<span class='ui-icon ui-icon-document'></span>";
-        editTd.appendChild(editButton);
-        result.appendChild(editTd);
+OverlayPanel.prototype.refresh = function () {
+  var self = this;
+  var user = null;
+
+  var overlayTypes = [];
+  var selectedOverlay = [];
+
+  return ServerConnector.getOverlayTypes().then(function (types) {
+    overlayTypes = types;
+    return ServerConnector.getLoggedUser();
+  }).then(function (loggedUser) {
+    user = loggedUser;
+    return self.getMap().getVisibleDataOverlays();
+  }).then(function (visibleDataOverlays) {
+    for (var j = 0; j < visibleDataOverlays.length; j++) {
+      selectedOverlay[visibleDataOverlays[j].getId()] = true;
     }
-    result.title = overlay.getDescription();
-    return result;
-};
 
-OverlayPanel.prototype.openEditOverlayDialog = function (overlay) {
-    var self = this;
-    var guiUtils = self.getGuiUtils();
-    var content = document.createElement("fieldset");
-    var nameInput = guiUtils.createInputText(overlay.getName());
-    var row = guiUtils.createTableRow([guiUtils.createLabel("Name: "), nameInput]);
-    content.appendChild(row);
-
-    var descriptionInput = guiUtils.createTextArea(overlay.getDescription());
-    row = guiUtils.createTableRow([guiUtils.createLabel("Description: "), descriptionInput]);
-    content.appendChild(row);
-
-    var buttons = [{
-        text: "SAVE",
-        click: function () {
-            var windowSelf = this;
-            overlay.setName(nameInput.value);
-            overlay.setDescription(descriptionInput.value);
-            return ServerConnector.updateOverlay(overlay).then(function () {
-                return self.refresh();
-            }).then(function () {
-                $(windowSelf).dialog("close");
-            }).then(null, GuiConnector.alert);
-        }
-    }, {
-        text: "REMOVE",
-        click: function () {
-            self.getMap().removeSelectedLayout(overlay.getId());
-
-            var windowSelf = this;
-            return ServerConnector.removeOverlay({
-                overlayId: overlay.getId()
-            }).then(function () {
-                return self.refresh();
-            }).then(function () {
-                $(windowSelf).dialog("close");
-            }).then(null, GuiConnector.alert);
-        }
-    }, {
-        text: "CANCEL",
-        click: function () {
-            $(this).dialog("close");
-        }
-    }];
-    self.openDialog(content, {
-        id: overlay.getId(),
-        buttons: buttons,
-        title: "Data overlay: " + overlay.getName(),
-        className: "minerva-overlay-dialog",
+    return ServerConnector.getOverlays({
+      publicOverlay: false,
+      creator: user.getLogin(),
     });
-};
+  }).then(
+    function (customOverlays) {
 
-OverlayPanel.prototype.refresh = function () {
-    var self = this;
-    var user = null;
-
-    var overlayTypes = [];
-    var selectedOverlay = [];
-
-    return ServerConnector.getOverlayTypes().then(function (types) {
-        overlayTypes = types;
-        return ServerConnector.getLoggedUser();
-    }).then(function (loggedUser) {
-        user = loggedUser;
-        return self.getMap().getVisibleDataOverlays();
-    }).then(function (visibleDataOverlays) {
-        for (var j = 0; j < visibleDataOverlays.length; j++) {
-            selectedOverlay[visibleDataOverlays[j].getId()] = true;
+      var id = self.getMap().getGoogleMap().getMapTypeId().substring(2);
+      selectedOverlay[id] = true;
+
+      self.clear();
+
+      var generalOverlays = [];
+      var overlay;
+
+      var overlays = self.getMap().getLayouts();
+      for (var i = 0; i < overlays.length; i++) {
+        overlay = overlays[i];
+        if (overlay.getCreator() === undefined || overlay.getCreator() === "") {
+          generalOverlays.push(overlay);
         }
+      }
+
+      var table = self.getControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_TABLE);
+      table.appendChild(self.createTableHeader());
+
+      var body = document.createElement("tbody");
+      table.appendChild(body);
+      for (i = 0; i < generalOverlays.length; i++) {
+        overlay = generalOverlays[i];
+        body.appendChild(self.createOverlayRow(overlay, selectedOverlay[overlay.getId()]));
+      }
+
+      var title = self.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TITLE);
+      var addButton = self.getControlElement(PanelControlElementType.OVERLAY_ADD_OVERLAY_BUTTON);
+      if (user.getLogin() === "anonymous") {
+        title.innerHTML = 'YOU ARE NOT LOGGED IN. PLEASE, <a href="#">LOG IN</a>'
+          + 'TO UPLOAD AND VIEW CUSTOM OVERLAYS<br/><center><button>LOGIN</button></center>';
+        var openLoginDialog = function () {
+          return self.getParent().getLoginDialog().open();
+        };
+        $(title).find("a")[0].onclick = openLoginDialog;
+        $(title).find("button")[0].onclick = openLoginDialog;
+        addButton.style.display = "none";
+      } else {
+        title.innerHTML = self.getCustomOverlaysMessage();
+        addButton.style.display = "block";
+
+        table = self.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TABLE);
+        table.appendChild(self.createTableHeader(true));
+
+        body = document.createElement("tbody");
+        table.appendChild(body);
+        for (i = 0; i < customOverlays.length; i++) {
+          overlay = customOverlays[i];
+          body.appendChild(self.createOverlayRow(overlay, selectedOverlay[overlay.getId()]));
+        }
+      }
 
-        return ServerConnector.getOverlays({
-            publicOverlay: false,
-            creator: user.getLogin(),
-        });
-    }).then(
-        function (customOverlays) {
-
-            var id = self.getMap().getGoogleMap().getMapTypeId().substring(2);
-            selectedOverlay[id] = true;
-
-            self.clear();
-
-            var generalOverlays = [];
-            var overlay;
-
-            var overlays = self.getMap().getLayouts();
-            for (var i = 0; i < overlays.length; i++) {
-                overlay = overlays[i];
-                if (overlay.getCreator() === undefined || overlay.getCreator() === "") {
-                    generalOverlays.push(overlay);
-                }
-            }
-
-            var table = self.getControlElement(PanelControlElementType.OVERLAY_GENERAL_OVERLAY_TABLE);
-            table.appendChild(self.createTableHeader());
-
-            var body = document.createElement("tbody");
-            table.appendChild(body);
-            for (i = 0; i < generalOverlays.length; i++) {
-                overlay = generalOverlays[i];
-                body.appendChild(self.createOverlayRow(overlay, selectedOverlay[overlay.getId()]));
-            }
-
-            var title = self.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TITLE);
-            var addButton = self.getControlElement(PanelControlElementType.OVERLAY_ADD_OVERLAY_BUTTON);
-            if (user.getLogin() === "anonymous") {
-                title.innerHTML = 'YOU ARE NOT LOGGED IN. PLEASE, <a href="#">LOG IN</a>'
-                    + 'TO UPLOAD AND VIEW CUSTOM OVERLAYS<br/><center><button>LOGIN</button></center>';
-                var openLoginDialog = function () {
-                    return self.getParent().getLoginDialog().open();
-                };
-                $(title).find("a")[0].onclick = openLoginDialog;
-                $(title).find("button")[0].onclick = openLoginDialog;
-                addButton.style.display = "none";
-            } else {
-                title.innerHTML = self.getCustomOverlaysMessage();
-                addButton.style.display = "block";
-
-                table = self.getControlElement(PanelControlElementType.OVERLAY_CUSTOM_OVERLAY_TABLE);
-                table.appendChild(self.createTableHeader(true));
-
-                body = document.createElement("tbody");
-                table.appendChild(body);
-                for (i = 0; i < customOverlays.length; i++) {
-                    overlay = customOverlays[i];
-                    body.appendChild(self.createOverlayRow(overlay, selectedOverlay[overlay.getId()]));
-                }
-            }
-
-            self.onresize();
-        });
+      self.onresize();
+    });
 };
 
 OverlayPanel.prototype.setCustomOverlaysMessage = function (customOverlaysMessage) {
-    this._customOverlaysMessage = customOverlaysMessage;
+  this._customOverlaysMessage = customOverlaysMessage;
 };
 
 OverlayPanel.prototype.getCustomOverlaysMessage = function () {
-    return this._customOverlaysMessage;
+  return this._customOverlaysMessage;
 };
 
 
 OverlayPanel.prototype.openAddOverlayDialog = function () {
-    var self = this;
-    if (self._addOverlayDialog !== undefined) {
-        self._addOverlayDialog.destroy();
-    }
-    self._addOverlayDialog = new AddOverlayDialog({
-        project: self.getProject(),
-        customMap: self.getMap(),
-        element: document.createElement("div"),
-    });
-    self._addOverlayDialog.addListener("onAddOverlay", function (e) {
-        self.getMap().getModel().addLayout(e.arg);
-        return self.refresh();
-    });
-    return self._addOverlayDialog.init().then(function () {
-        return self._addOverlayDialog.open();
-    });
+  var self = this;
+  if (self._addOverlayDialog !== undefined) {
+    self._addOverlayDialog.destroy();
+  }
+  self._addOverlayDialog = new AddOverlayDialog({
+    project: self.getProject(),
+    customMap: self.getMap(),
+    element: document.createElement("div"),
+  });
+  self._addOverlayDialog.addListener("onAddOverlay", function (e) {
+    self.getMap().getModel().addLayout(e.arg);
+    return self.refresh();
+  });
+  return self._addOverlayDialog.init().then(function () {
+    return self._addOverlayDialog.open();
+  });
 };
 
 OverlayPanel.prototype.init = function () {
-    return this.refresh();
+  return this.refresh();
 };
 
 OverlayPanel.prototype.destroy = function () {
-    var self = this;
-    Panel.prototype.destroy.call(this);
-    if (self._addOverlayDialog !== undefined) {
-        return self._addOverlayDialog.destroy();
-    } else {
-        return Promise.resolve();
-    }
+  var self = this;
+  Panel.prototype.destroy.call(this);
+  if (self._addOverlayDialog !== undefined) {
+    return self._addOverlayDialog.destroy();
+  } else {
+    return Promise.resolve();
+  }
 };
 
 module.exports = OverlayPanel;
diff --git a/frontend-js/src/main/js/minerva.js b/frontend-js/src/main/js/minerva.js
index f512561d040d154d2c9e98ac897d54fa4911efb7..aff5e13e93300e90eea0d951c75c26fbb0d67a4d 100644
--- a/frontend-js/src/main/js/minerva.js
+++ b/frontend-js/src/main/js/minerva.js
@@ -329,11 +329,12 @@ function createResult(customMap) {
     getAllBioEntities: function () {
       var models = [customMap.getModel()];
       var result = [];
-      for (var i = 0; i < customMap.getModel().getSubmodels().length; i++) {
+      var i;
+      for (i = 0; i < customMap.getModel().getSubmodels().length; i++) {
         models.push(customMap.getModel().getSubmodels()[i]);
       }
       var promises = [];
-      for (var i = 0; i < models.length; i++) {
+      for (i = 0; i < models.length; i++) {
         promises.push(models[i].getAliases({
           type: customMap.getConfiguration().getElementTypes(),
           complete: true,
diff --git a/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js b/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js
index dcb98ffb1ef73ca12643844469f2dfa00210121c..644bec605eb44e465e6a2a3f13b7869a78c9580e 100644
--- a/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js
+++ b/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js
@@ -2,40 +2,86 @@
 
 /* exported assert */
 /* exported logger */
+require("../../mocha-config");
 
 var AddProjectDialog = require('../../../../main/js/gui/admin/AddProjectDialog');
 var logger = require('../../logger');
 
 var assert = require('assert');
 
-describe('AddProjectDialog', function() {
-  it('init', function() {
+describe('AddProjectDialog', function () {
+  it('init', function () {
     var dialog = new AddProjectDialog({
-      element : testDiv,
-      customMap : null,
+      element: testDiv,
+      customMap: null
+    });
+    return ServerConnector.login("admin", "admin").then(function(){
+      return dialog.init();
+    }).then(function () {
+      assert.ok(dialog.getNotifyEmail() !== "");
     });
-    return dialog.init();
   });
 
-  describe('onFileUpload', function() {
-    it('default', function() {
+  describe('onFileUpload', function () {
+    it('default', function () {
       var dialog = new AddProjectDialog({
-        element : testDiv,
-        customMap : null
+        element: testDiv,
+        customMap: null
       });
 
-      var file = new Blob([ "<node></node>" ]);
+      var file = new Blob(["<node></node>"]);
       file.name = "test.xml";
-      return dialog.init().then(function() {
+      return dialog.init().then(function () {
         return dialog.callListeners("onFileUpload", file);
-      }).then(function() {
+      }).then(function () {
         assert.ok(dialog.getFileContent());
         assert.equal("test", dialog.getProjectId());
         return dialog.getConverter();
-      }).then(function(converter) {
+      }).then(function (converter) {
         assert.equal("xml", converter.extension);
       });
     });
   });
 
+  describe('onSaveClicked', function () {
+    var originalAddProject;
+    beforeEach(function () {
+      originalAddProject = ServerConnector.addProject;
+    });
+    afterEach(function () {
+      ServerConnector.addProject = originalAddProject;
+    });
+    it('default', function () {
+      var options;
+      ServerConnector.addProject = function (params) {
+        options = params;
+      };
+
+      var dialog = new AddProjectDialog({
+        element: testDiv,
+        customMap: null
+      });
+
+      var file = new Blob(["<node></node>"]);
+      file.name = "test.xml";
+      return dialog.init().then(function () {
+        return dialog.callListeners("onFileUpload", file);
+      }).then(function () {
+        return dialog.onSaveClicked();
+      }).then(function () {
+        assert.ok(options["name"] !== undefined);
+        assert.ok(options["projectId"] !== undefined);
+        assert.ok(options["file-content"] !== undefined);
+        assert.ok(options["parser"] !== undefined);
+        assert.ok(options["auto-resize"] !== undefined);
+        assert.ok(options["cache"] !== undefined);
+        assert.ok(options["notify-email"] !== undefined);
+        assert.ok(options["disease"] !== undefined);
+        assert.ok(options["organism"] !== undefined);
+        assert.ok(options["sbgn"] !== undefined);
+        assert.ok(options["semantic-zoom"] !== undefined);
+      });
+    });
+  });
+
 });
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 7d3c7d14229f22f8230ad8bb2492a2687d63cce6..fa6e53a4b1c8ed5877c2cb20e31bfd16c02b1dd3 100644
--- a/frontend-js/src/test/js/gui/admin/EditProjectDialog-test.js
+++ b/frontend-js/src/test/js/gui/admin/EditProjectDialog-test.js
@@ -2,6 +2,7 @@
 
 /* exported assert */
 /* exported logger */
+require("../../mocha-config");
 
 var EditProjectDialog = require('../../../../main/js/gui/admin/EditProjectDialog');
 var logger = require('../../logger');
diff --git a/frontend-js/src/test/js/map/TouchMap-test.js b/frontend-js/src/test/js/map/TouchMap-test.js
index fecc0a813d03d6ab9ee6eedeb5fc145015d5e63a..975a0865f3c465c5a32919a1f15bc33cb20e41ae 100644
--- a/frontend-js/src/test/js/map/TouchMap-test.js
+++ b/frontend-js/src/test/js/map/TouchMap-test.js
@@ -89,7 +89,7 @@ describe('TouchMap', function () {
         var clicked = false;
         google.maps.event.addListener(map.getGoogleMap(), "click", function () {
           clicked = true;
-        })
+        });
         evt = document.createEvent('UIEvent');
         evt.initUIEvent('touchend', true, true, window, null);
         evt.changedTouches = [evtLocation];
@@ -105,7 +105,7 @@ describe('TouchMap', function () {
     it("default", function () {
       var map = helper.createCustomMap();
       var coordinates = map.getGoogleMap().getCenter();
-      var touchMap = new TouchMap(map);
+      new TouchMap(map);
 
       var evtLocation = {
         pageX: 10,
@@ -131,8 +131,8 @@ describe('TouchMap', function () {
 
       var coordinates2 = map.getGoogleMap().getCenter();
 
-      assert.ok(coordinates.x != coordinates2.x);
-      assert.ok(coordinates.y != coordinates2.y);
+      assert.ok(coordinates.x !== coordinates2.x);
+      assert.ok(coordinates.y !== coordinates2.y);
 
     });
   });
diff --git a/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js b/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js
index e48b205a9f9620f97b2532804187a536dba4a459..190e315a162473236eb95b89c2efaf9c2d399a07 100644
--- a/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js
+++ b/frontend-js/src/test/js/map/window/AliasInfoWindow-test.js
@@ -6,7 +6,6 @@ var Promise = require("bluebird");
 var functions = require('../../../../main/js/Functions');
 
 var Alias = require('../../../../main/js/map/data/Alias');
-var LayoutAlias = require('../../../../main/js/map/data/LayoutAlias');
 var Drug = require('../../../../main/js/map/data/Drug');
 var AliasInfoWindow = require('../../../../main/js/map/window/AliasInfoWindow');
 var IdentifiedElement = require('../../../../main/js/map/data/IdentifiedElement');
diff --git a/frontend-js/src/test/js/minerva-test.js b/frontend-js/src/test/js/minerva-test.js
index 5131c6b2af3d5a68dc6df9a023d058e1c5b4b275..c3cc8f9f9d4e97f10c5345d767045b1b99acd4bd 100644
--- a/frontend-js/src/test/js/minerva-test.js
+++ b/frontend-js/src/test/js/minerva-test.js
@@ -113,7 +113,6 @@ describe('minerva global', function () {
   it('create with layout', function () {
     var layout;
     var project;
-    var customMap;
     return ServerConnectorMock.getProject().then(function (result) {
       project = result;
       var options = helper.createCustomMapOptions(project);
diff --git a/frontend-js/src/test/js/mocha-config.js b/frontend-js/src/test/js/mocha-config.js
index a22a4f79ecc3a7dcf963c20ce8a2c65a8ee757e5..be219d23ced51a2b01c91998f64a04a5c3f4a354 100644
--- a/frontend-js/src/test/js/mocha-config.js
+++ b/frontend-js/src/test/js/mocha-config.js
@@ -3,9 +3,6 @@
 var Promise = require("bluebird");
 var Cookies = require('js-cookie');
 
-var chai = require('chai');
-var assert = chai.assert;
-
 var Helper = require('./helper');
 
 // -----------------------------
@@ -39,7 +36,7 @@ before(function () {
   global.window = global.dom.window;
   global.document = window.document;
   global.document.elementFromPoint = function () {
-  }
+  };
 
 global.$ = require('jquery');
 global.jQuery = $;