From 8df73da41e63bcfe35d76026fae11d18b97c3bca Mon Sep 17 00:00:00 2001
From: yvesn <yvesn>
Date: Mon, 29 May 2017 09:29:11 +0000
Subject: [PATCH] SSDM-5068 : ELN config on GUI - loading settings and applying
 to profile on startup

SVN: 38223
---
 .../1/as/webapps/eln-lims/html/index.html     |   1 +
 .../eln-lims/html/js/config/Profile.js        |  15 +-
 .../html/js/config/SettingsManager.js         | 255 ++++++++++++++++++
 .../html/js/controllers/MainController.js     |   3 +-
 .../eln-lims/html/js/server/ServerFacade.js   |  23 ++
 .../SettingsForm/SettingsFormController.js    | 227 ++--------------
 .../js/views/SettingsForm/SettingsFormView.js |  36 +--
 .../js/views/SideMenu/SideMenuWidgetView.js   |  25 +-
 8 files changed, 343 insertions(+), 242 deletions(-)
 create mode 100644 openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/config/SettingsManager.js

diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/index.html b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/index.html
index 2f91865d9bc..809361e9b71 100644
--- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/index.html
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/index.html
@@ -85,6 +85,7 @@
 	<script type="text/javascript" src="./js/config/ELNDictionary.js"></script>
 	<script type="text/javascript" src="./js/config/Profile.js"></script>
 	<script type="text/javascript" src="./js/config/StandardProfile.js"></script>
+	<script type="text/javascript" src="./js/config/SettingsManager.js"></script>
 	<script type="text/javascript" src="./js/server/ServerFacade.js"></script>
 	
 	<script type="text/javascript" src="./js/util/Util.js"></script>
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/config/Profile.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/config/Profile.js
index 037d2ce4645..4b97aa48b00 100644
--- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/config/Profile.js
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/config/Profile.js
@@ -48,7 +48,7 @@ $.extend(DefaultProfile.prototype, {
 				showTrashcan : true,
 				showSettings : true,
 				showVocabularyViewer : true,
-				showUserManager : true
+				showUserManager : true,
 		}
 		
 		this.orderLabInfo = {
@@ -801,7 +801,14 @@ $.extend(DefaultProfile.prototype, {
 				callback();
 			});
 		}
-		
+
+		this.initSettings = function(callback) {
+			var settingsManager = new SettingsManager(this.serverFacade);
+			settingsManager.loadSettingsAndApplyToProfile((function() {
+				callback();
+			}));
+		}
+
 		//
 		// Initializes
 		//
@@ -813,7 +820,9 @@ $.extend(DefaultProfile.prototype, {
 						_this.initDirectLinkURL(function() {
 							_this.initIsAdmin(function() {
 								_this.initDatasetTypeCodes(function() {
-									callbackWhenDone();
+									_this.initSettings(function() {
+										callbackWhenDone();
+									});
 								});
 							});
 						});
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/config/SettingsManager.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/config/SettingsManager.js
new file mode 100644
index 00000000000..4b7fcf8419e
--- /dev/null
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/config/SettingsManager.js
@@ -0,0 +1,255 @@
+function SettingsManager(serverFacade) {
+
+    this._serverFacade = serverFacade;
+
+	this.validateAndsave = function(settingsSample, settings, doneCallback) {
+		console.log(settings);
+		var _this = this;
+		var errors = this._validateSettings(settings);
+		if (errors.length > 0) {
+			Util.showError(this._getSanitizedErrorString(errors));
+		} else {
+			settingsSample.properties = { "ELN_SETTINGS" : JSON.stringify(settings) };
+			this._serverFacade.updateSample(settingsSample, function(ok) {
+				if(ok) {
+					_this.applySettingsToProfile(settings, profile);
+					doneCallback();
+				}
+			});
+		}
+	}
+
+	this.loadSettings = function(callback) {
+		this._serverFacade.searchSamples({ "sampleIdentifier" : "/ELN_SETTINGS/GENERAL_ELN_SETTINGS", "withProperties" : true }, (function(data) {
+			if(!data[0]) {
+				window.alert("The item is no longer available, refresh the page, if the problem persists tell your admin that the Lucene index is probably corrupted.");
+			} else {
+				var settings = JSON.parse(data[0].properties.ELN_SETTINGS);
+				callback(settings);
+			}
+		}).bind(this))
+	}
+
+	// Loads settings and logs validation errors to console.
+	// Applies the settings to the profile even if they are invalid.
+    this.loadSettingsAndApplyToProfile = function(doneCallback) {
+		this.loadSettings((function(settings) {
+			var errors = this._validateSettings(settings);
+			if (errors.length > 0) {
+				console.log("The settings contain the following errors:");
+				console.log(errors);
+			}
+			this.applySettingsToProfile(settings, profile);
+			doneCallback();
+		}).bind(this));
+    }
+
+	this._getSanitizedErrorString = function(errors) {
+		var $container = $("<div>");
+        $container.append($("<h3>").text("Settings validation errors:"));
+		var $ul = $("<ul>");
+		for (var error of errors) {
+			$ul.append($("<li>").text(error));
+		}
+		$container.append($ul);
+		return $container.html();
+	}
+
+	this.getAllDatasetTypeCodeOptions = function() {
+		return profile.allDatasetTypeCodes;
+	}
+
+	this.getForcedDisableRTFOptions = function() {
+		return profile.allPropertyTypes.map(function(_) { return _.code; });
+	}
+
+	this.getForcedMonospaceFontOptions = function() {
+		return profile.allPropertyTypes.map(function(_) { return _.code; });
+	}
+
+	this.getSampleTypeProtocolsOptions = function() {
+		return profile.allSampleTypes.map((sampleType) => {return sampleType.code})
+	}
+
+	this.getInventorySpacesOptions = function() {
+		return profile.allSpaces;
+	}
+
+	this.getSampleTypeOptions = function() {
+		return profile.getAllSampleTypes().map( function(_) { return _.code; } )
+	}
+
+	this.getAnnotationPropertyTypeOptions = function() {
+		return profile.allPropertyTypes.map( function(_) { return _.code; } );
+	}
+
+	this.applySettingsToProfile = function(settings, targetProfile) {
+		// fields to be overwritten
+		var fields = [
+			"dataSetTypeForFileNameMap",
+			"forcedDisableRTF",
+			"forceMonospaceFont",
+			"inventorySpaces",
+			"sampleTypeProtocols",
+		];
+		for (var field of fields) {
+			if (settings[field]) {
+				targetProfile[field] = settings[field];
+			}
+		}
+		// main menu
+		for (var menuItem of Object.keys(settings.mainMenu)) {
+			targetProfile.mainMenu[menuItem] = settings.mainMenu[menuItem];
+		}
+		// sampleTypeDefinitionsExtension
+		for (var sampleType of Object.keys(settings.sampleTypeDefinitionsExtension)) {
+			profile.sampleTypeDefinitionsExtension[sampleType] = settings.sampleTypeDefinitionsExtension[sampleType];
+		}
+	}
+
+    this._validateSettings = function(settings) {
+		var errors = [];
+		this._validateMainMenu(settings, errors);
+		this._validateForcedDisableRTF(settings, errors);
+		this._validateForcedMonospaceFont(settings, errors);
+		this._validateInventorySpaces(settings, errors);
+		this._validateDataSetTypeForFileNameMap(settings, errors);
+		this._validateSampleTypeProtocols(settings, errors);
+		this._validateSampleTypeDefinitionsExtension(settings, errors);
+		return errors;
+	}
+
+	this._validateSampleTypeDefinitionsExtension = function(settings, errors) {
+		if (settings.sampleTypeDefinitionsExtension) {
+			for (var sampleType of Object.keys(settings.sampleTypeDefinitionsExtension)) {
+				// not checking for valid sample type
+				// config can contain entries which are not yet defined
+				// but if sample type exists, more strict validation is used
+				var sampleTypeExists = this.getSampleTypeOptions().indexOf(sampleType) !== -1;
+				var hints = settings.sampleTypeDefinitionsExtension[sampleType];
+				var errorPrefix = "Error in definitions extension for sample type " + sampleType + ": ";
+				for (var hintType of Object.keys(hints)) {
+					if (hintType == "undefined") {
+						errors.push(errorPrefix + "Hint type (children/parents) is undefined");
+					}
+					if (hintType === "SAMPLE_CHILDREN_HINT" || hintType === "SAMPLE_PARENTS_HINT") {
+						var hintArray = hints[hintType];
+						for (var hint of hintArray) {
+							if (hint.LABEL == null || hint.LABEL.length === 0) {
+								errors.push(errorPrefix + "Sample type definitions hint labels can't be empty.");
+							}
+							if (typeof(hint.TYPE) !== "string") {
+								errors.push(errorPrefix + "Sample type definitions hint type (" +
+											hint.TYPE +
+											 ") must be a string.");
+							} else if (sampleTypeExists && this.getSampleTypeOptions().indexOf(hint.TYPE) === -1) {
+								errors.push(errorPrefix + "Sample type definitions hint type (" +
+											hint.TYPE +
+											 ") must be an existing property type.");
+							}
+							if (hint.MIN_COUNT != null && (typeof(hint.MIN_COUNT) !== "number" || isNaN(hint.MIN_COUNT))) {
+								errors.push(errorPrefix + "Sample type definitions hint MIN_COUNT must be a number.");
+							}
+							if (hint.MAX_COUNT != null && (typeof(hint.MAX_COUNT) !== "number" || isNaN(hint.MAX_COUNT))) {
+								errors.push(errorPrefix + "Sample type definitions hint MAX_COUNT must be a number.");
+							}
+							if (hint.ANNOTATION_PROPERTIES) {
+								var propertyTypeOptions = this.getAnnotationPropertyTypeOptions();
+								for (var annotationProperty of hint.ANNOTATION_PROPERTIES) {
+									// debugger;
+									if (sampleTypeExists && (annotationProperty.TYPE == null || propertyTypeOptions.indexOf(annotationProperty.TYPE) === -1)) {
+										errors.push(errorPrefix + "Annotation properties must have an existing property type but is: " +
+													annotationProperty.TYPE);
+									}
+									if (annotationProperty.MANDATORY == null || typeof(annotationProperty.MANDATORY) !== "boolean") {
+										errors.push(errorPrefix + "Annotation properties must have a boolean MANDATORY field but is: "
+													+ annotationProperty.MANDATORY);
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	this._validateMainMenu = function(settings, errors) {
+		if (settings.mainMenu) {
+			var availableMenuItems = Object.keys(profile.mainMenu);
+			for (var menuItem of Object.keys(settings.mainMenu)) {
+				if (availableMenuItems.indexOf(menuItem) === -1) {
+					errors.push(menuItem + 
+								" is not a Main Menu Item. Available items: " +
+								availableMenuItems.join(", " +
+								"."));
+				}
+				if (typeof(settings.mainMenu[menuItem]) !== "boolean") {
+					errors.push(menuItem + ": " + settings.mainMenu[menuItem] + " is not of type 'boolean'.");
+				}
+			}
+		}
+	}
+
+	this._validateForcedDisableRTF = function(settings, errors) {
+		if (settings.forcedDisableRTF) {
+			for (var item of settings.forcedDisableRTF) {
+				if (this.getForcedDisableRTFOptions().indexOf(item) === -1) {
+					errors.push(item + " is not a property type.");
+				}
+			}
+		}
+	}
+
+	this._validateForcedMonospaceFont = function(settings, errors) {
+		if (settings.forceMonospaceFont) {
+			for (var item of settings.forceMonospaceFont) {
+				if (this.getForcedMonospaceFontOptions().indexOf(item) === -1) {
+					errors.push(item + " is not a property type.");
+				}
+			}
+		}
+	}
+
+	this._validateInventorySpaces = function(settings, errors) {
+		if (settings.inventorySpaces) {
+			for (var item of settings.inventorySpaces) {
+				if (this.getInventorySpacesOptions().indexOf(item) === -1) {
+					errors.push(item + " is not space.");
+				}
+			}
+		}
+	}
+
+	this._validateSampleTypeProtocols = function(settings, errors) {
+		if (settings.sampleTypeProtocols) {
+			for (var item of settings.sampleTypeProtocols) {
+				if (this.getSampleTypeProtocolsOptions().indexOf(item) === -1) {
+					errors.push(item + " is not a sample type protocol.");
+				}
+			}
+		}		
+	}
+
+	this._validateDataSetTypeForFileNameMap = function(settings, errors) {
+		if (settings.dataSetTypeForFileNameMap) {
+			for (var dataSetTypeForFileName of settings.dataSetTypeForFileNameMap) {
+				if (dataSetTypeForFileName.dataSetType == null) {
+					errors.push("dataSetTypeForFileNameMap must contain a field named dataSetType.");
+				} else if (this.getAllDatasetTypeCodeOptions().indexOf(dataSetTypeForFileName.dataSetType) === -1) {
+					errors.push("Dataset type " + 
+								dataSetTypeForFileName.dataSetType + 
+								" is not allowed. Available types: " +
+								this.getAllDatasetTypeCodeOptions().join(", ") +
+								".");
+				}
+				if (dataSetTypeForFileName.fileNameExtension == null) {
+					errors.push("dataSetTypeForFileNameMap must contain a field named fileNameExtension.");
+				} else if (dataSetTypeForFileName.fileNameExtension.length == 0) {
+					errors.push("Filename extension can't be empty.");
+				}
+			}
+		}
+	}
+
+}
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/controllers/MainController.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/controllers/MainController.js
index 9f8bad7a10a..3c10ceb3b6c 100644
--- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/controllers/MainController.js
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/controllers/MainController.js
@@ -650,7 +650,7 @@ function MainController(profile) {
 	
 	this._showSettingsPage = function(mode) {
 		var _this = this;
-		this.serverFacade.searchSamples({ "sampleIdentifier" : "/ELN_SETTINGS/GENERAL_ELN_SETTINGS" }, function(data) {
+		this.serverFacade.searchSamples({ "sampleIdentifier" : "/ELN_SETTINGS/GENERAL_ELN_SETTINGS", "withProperties" : true }, function(data) {
 			if(!data[0]) {
 				window.alert("The item is no longer available, refresh the page, if the problem persists tell your admin that the Lucene index is probably corrupted.");
 			} else {
@@ -658,7 +658,6 @@ function MainController(profile) {
 				var views = _this._getNewViewModel(true, true, false);
 				newView.init(views);
 				_this.currentView = newView;
-				//window.scrollTo(0,0);
 			}
 		});
 	}
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js
index f48356bafb7..546a42777e4 100644
--- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js
@@ -1738,4 +1738,27 @@ function ServerFacade(openbisServer) {
 		
 		this.openbisServer.searchOnSearchDomain(preferredSearchDomainOrNull, searchText, null, callbackFunction);
 	}
+
+	//
+	// V3 Save Functions
+	//
+
+	this.updateSample = function(sampleV1, callbackFunction) {
+		require([ "as/dto/sample/update/SampleUpdate", "as/dto/sample/id/SamplePermId"], 
+        function(SampleUpdate, SamplePermId) {
+			var sampleUpdate = new SampleUpdate();
+            sampleUpdate.setSampleId(new SamplePermId(sampleV1.permId));
+			
+			for(var propertyCode in sampleV1.properties) {
+				sampleUpdate.setProperty(propertyCode, sampleV1.properties[propertyCode]);
+			}
+
+            mainController.openbisV3.updateSamples([ sampleUpdate ]).done(function() {
+                callbackFunction(true);
+            }).fail(function(result) {
+				Util.showError("Call failed to server: " + JSON.stringify(result));
+				callbackFunction(false);
+			});
+        });
+	}
 }
\ No newline at end of file
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SettingsForm/SettingsFormController.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SettingsForm/SettingsFormController.js
index ce2e79397ec..54559081453 100644
--- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SettingsForm/SettingsFormController.js
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SettingsForm/SettingsFormController.js
@@ -18,222 +18,29 @@ function SettingsFormController(mainController, settingsSample, mode) {
 	this._mainController = mainController;
 	this._settingsFormModel = new SettingsFormModel(settingsSample, mode);
 	this._settingsFormView = new SettingsFormView(this, this._settingsFormModel);
-	
+	this._settingsManager = new SettingsManager(this._mainController.serverFacade);
+
 	this.init = function(views) {
-		this._settingsFormView.repaint(views);
+		// apply settings to copy of profile, even if invalid, for editing
+		var profileToEdit = jQuery.extend(true, {}, profile);
+		this._settingsManager.loadSettings((function(settings) {
+			this._settingsManager.applySettingsToProfile(settings, profileToEdit);
+			this._settingsFormView.repaint(views, profileToEdit);
+		}).bind(this));
 	}
 
 	this.save = function(settings) {
-		var _this = this;
-		var errors = this._validateSettings(settings);
-		if (errors.length > 0) {
-			Util.showError(this._getSanitizedErrorString(errors));
-		} else {
-			// TODO store settings
-			this._applySettingsToProfile(settings);
+		this._settingsManager.validateAndsave(this._settingsFormModel.settingsSample, settings, (function() {
 			this._mainController.changeView("showSettingsPage");
-		}
-	}
-
-	this._getSanitizedErrorString = function(errors) {
-		var $container = $("<div>");
-		var $ul = $("<ul>");
-		for (var error of errors) {
-			$ul.append($("<li>").text(error));
-		}
-		$container.append($ul);
-		return $container.html();
-	}
-
-	this.getAllDatasetTypeCodeOptions = function() {
-		return profile.allDatasetTypeCodes;
-	}
-
-	this.getForcedDisableRTFOptions = function() {
-		return profile.allPropertyTypes.map(function(_) { return _.code; });
-	}
-
-	this.getForcedMonospaceFontOptions = function() {
-		return profile.allPropertyTypes.map(function(_) { return _.code; });
-	}
-
-	this.getSampleTypeProtocolsOptions = function() {
-		return profile.allSampleTypes.map((sampleType) => {return sampleType.code})
-	}
-
-	this.getInventorySpacesOptions = function() {
-		return profile.allSpaces;
-	}
-
-	this.getSampleTypeOptions = function() {
-		return profile.getAllSampleTypes().map( function(_) { return _.code; } )
-	}
-
-	this.getAnnotationPropertyTypeOptions = function() {
-		return profile.allPropertyTypes.map( function(_) { return _.code; } );
+		}).bind(this));
 	}
 
-	this._applySettingsToProfile = function(settings) {
-		var fields = [
-			"dataSetTypeForFileNameMap",
-			"mainMenu",
-			"forcedDisableRTF",
-			"forceMonospaceFont",
-			"inventorySpaces",
-			"sampleTypeProtocols",
-			"sampleTypeDefinitionsExtension",
-		];
-		for (var field of fields) {
-			if (settings[field]) {
-				profile[field] = settings[field];
-			}
-		}
-	}
-
-	// TODO move validation to some place where it can be called on application startup as well
-	this._validateSettings = function(settings) {
-		var errors = [];
-		this._validateMainMenu(settings, errors);
-		this._validateForcedDisableRTF(settings, errors);
-		this._validateForcedMonospaceFont(settings, errors);
-		this._validateInventorySpaces(settings, errors);
-		this._validateDataSetTypeForFileNameMap(settings, errors);
-		this._validateSampleTypeProtocols(settings, errors);
-		this._validateSampleTypeDefinitionsExtension(settings, errors);
-		return errors;
-	}
-
-	this._validateSampleTypeDefinitionsExtension = function(settings, errors) {
-		if (settings.sampleTypeDefinitionsExtension) {
-			for (var sampleType of Object.keys(settings.sampleTypeDefinitionsExtension)) {
-				// not checking for valid sample type
-				// config can contain entries which are not yet defined
-				// but if sample type exists, more strict validation is used
-				var sampleTypeExists = this.getSampleTypeOptions().indexOf(sampleType) !== -1;
-				var hints = settings.sampleTypeDefinitionsExtension[sampleType];
-				var errorPrefix = "Error in definitions extension for sample type " + sampleType + ": ";
-				for (var hintType of Object.keys(hints)) {
-					if (hintType == "undefined") {
-						errors.push(errorPrefix + "Hint type (children/parents) is undefined");
-					}
-					if (hintType === "SAMPLE_CHILDREN_HINT" || hintType === "SAMPLE_PARENTS_HINT") {
-						var hintArray = hints[hintType];
-						for (var hint of hintArray) {
-							if (hint.LABEL == null || hint.LABEL.length === 0) {
-								errors.push(errorPrefix + "Sample type definitions hint labels can't be empty.");
-							}
-							if (typeof(hint.TYPE) !== "string") {
-								errors.push(errorPrefix + "Sample type definitions hint type (" +
-											hint.TYPE +
-											 ") must be a string.");
-							} else if (sampleTypeExists && this.getSampleTypeOptions().indexOf(hint.TYPE) === -1) {
-								errors.push(errorPrefix + "Sample type definitions hint type (" +
-											hint.TYPE +
-											 ") must be an existing property type.");
-							}
-							if (hint.MIN_COUNT != null && (typeof(hint.MIN_COUNT) !== "number" || isNaN(hint.MIN_COUNT))) {
-								errors.push(errorPrefix + "Sample type definitions hint MIN_COUNT must be a number.");
-							}
-							if (hint.MAX_COUNT != null && (typeof(hint.MAX_COUNT) !== "number" || isNaN(hint.MAX_COUNT))) {
-								errors.push(errorPrefix + "Sample type definitions hint MAX_COUNT must be a number.");
-							}
-							if (hint.ANNOTATION_PROPERTIES) {
-								var propertyTypeOptions = this.getAnnotationPropertyTypeOptions();
-								for (var annotationProperty of hint.ANNOTATION_PROPERTIES) {
-									// debugger;
-									if (sampleTypeExists && (annotationProperty.TYPE == null || propertyTypeOptions.indexOf(annotationProperty.TYPE) === -1)) {
-										errors.push(errorPrefix + "Annotation properties must have an existing property type but is: " +
-													annotationProperty.TYPE);
-									}
-									if (annotationProperty.MANDATORY == null || typeof(annotationProperty.MANDATORY) !== "boolean") {
-										errors.push(errorPrefix + "Annotation properties must have a boolean MANDATORY field but is: "
-													+ annotationProperty.MANDATORY);
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-
-	this._validateMainMenu = function(settings, errors) {
-		if (settings.mainMenu) {
-			var availableMenuItems = Object.keys(profile.mainMenu);
-			for (var menuItem of Object.keys(settings.mainMenu)) {
-				if (availableMenuItems.indexOf(menuItem) === -1) {
-					errors.push(menuItem + 
-								" is not a Main Menu Item. Available items: " +
-								availableMenuItems.join(", " +
-								"."));
-				}
-				if (typeof(settings.mainMenu[menuItem]) !== "boolean") {
-					errors.push(menuItem + ": " + settings.mainMenu[menuItem] + " is not of type 'boolean'.");
-				}
-			}
-		}
-	}
-
-	this._validateForcedDisableRTF = function(settings, errors) {
-		if (settings.forcedDisableRTF) {
-			for (var item of settings.forcedDisableRTF) {
-				if (this.getForcedDisableRTFOptions().indexOf(item) === -1) {
-					errors.push(item + " is not a property type.");
-				}
-			}
-		}
-	}
-
-	this._validateForcedMonospaceFont = function(settings, errors) {
-		if (settings.forceMonospaceFont) {
-			for (var item of settings.forceMonospaceFont) {
-				if (this.getForcedMonospaceFontOptions().indexOf(item) === -1) {
-					errors.push(item + " is not a property type.");
-				}
-			}
-		}
-	}
-
-	this._validateInventorySpaces = function(settings, errors) {
-		if (settings.inventorySpaces) {
-			for (var item of settings.inventorySpaces) {
-				if (this.getInventorySpacesOptions().indexOf(item) === -1) {
-					errors.push(item + " is not space.");
-				}
-			}
-		}
-	}
-
-	this._validateSampleTypeProtocols = function(settings, errors) {
-		if (settings.sampleTypeProtocols) {
-			for (var item of settings.sampleTypeProtocols) {
-				if (this.getSampleTypeProtocolsOptions().indexOf(item) === -1) {
-					errors.push(item + " is not a sample type protocol.");
-				}
-			}
-		}		
-	}
-
-	this._validateDataSetTypeForFileNameMap = function(settings, errors) {
-		if (settings.dataSetTypeForFileNameMap) {
-			for (var dataSetTypeForFileName of settings.dataSetTypeForFileNameMap) {
-				if (dataSetTypeForFileName.dataSetType == null) {
-					errors.push("dataSetTypeForFileNameMap must contain a field named dataSetType.");
-				} else if (this.getAllDatasetTypeCodeOptions().indexOf(dataSetTypeForFileName.dataSetType) === -1) {
-					errors.push("Dataset type " + 
-								dataSetTypeForFileName.dataSetType + 
-								" is not allowed. Available types: " +
-								this.getAllDatasetTypeCodeOptions().join(", ") +
-								".");
-				}
-				if (dataSetTypeForFileName.fileNameExtension == null) {
-					errors.push("dataSetTypeForFileNameMap must contain a field named fileNameExtension.");
-				} else if (dataSetTypeForFileName.fileNameExtension.length == 0) {
-					errors.push("Filename extension can't be empty.");
-				}
-			}
-		}
-	}
+	this.getAllDatasetTypeCodeOptions = this._settingsManager.getAllDatasetTypeCodeOptions;
+	this.getForcedDisableRTFOptions = this._settingsManager.getForcedDisableRTFOptions;
+	this.getForcedMonospaceFontOptions = this._settingsManager.getForcedMonospaceFontOptions;
+	this.getSampleTypeProtocolsOptions = this._settingsManager.getSampleTypeProtocolsOptions;
+	this.getInventorySpacesOptions = this._settingsManager.getInventorySpacesOptions;
+	this.getSampleTypeOptions = this._settingsManager.getSampleTypeOptions;
+	this.getAnnotationPropertyTypeOptions = this._settingsManager.getAnnotationPropertyTypeOptions;
 
 }
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SettingsForm/SettingsFormView.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SettingsForm/SettingsFormView.js
index cb4101c92c5..f13a5788bd5 100644
--- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SettingsForm/SettingsFormView.js
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SettingsForm/SettingsFormView.js
@@ -27,8 +27,9 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 	this._sampleTypeProtocolsTableModel = null;
 	this._sampleTypeDefinitionsTableModels = {}; // key: sample type; value: table model
 
-	this.repaint = function(views) {
+	this.repaint = function(views, profileToEdit) {
 
+		this._profileToEdit = profileToEdit;
 		var $container = views.content;
 
 		Util.blockUI(null, null, true);
@@ -99,9 +100,7 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 		for (sampleType of sampleTypes) {
 			var tableModel = this._sampleTypeDefinitionsTableModels[sampleType];
 			var values = tableModel.getValues();
-			if (Object.keys(values).length !== 0) {
-				sampleTypeDefinitionsSettings[sampleType] = tableModel.getValues();
-			}
+			sampleTypeDefinitionsSettings[sampleType] = tableModel.getValues();
 		}
 		return sampleTypeDefinitionsSettings;
 	}
@@ -145,10 +144,13 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 			}
 		};
 		// add data
-		for (var menuItemName of Object.keys(profile.mainMenu)) {
-			tableModel.addRow({
-				menuItemName : menuItemName,
-				enabled : profile.mainMenu[menuItemName] });
+		for (var menuItemName of Object.keys(this._profileToEdit.mainMenu)) {
+			if (menuItemName !== "showSettings") {
+				tableModel.addRow({
+					menuItemName : menuItemName,
+					enabled : this._profileToEdit.mainMenu[menuItemName]
+				});
+			}
 		}
 		// transform output
 		tableModel.valuesTransformer = function(values) {
@@ -166,7 +168,7 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 			columnName : "Forced Disable RTF",
 			placeholder : "select property type",
 			options : this._settingsFormController.getForcedDisableRTFOptions(),
-			initialValues : profile.forcedDisableRTF,
+			initialValues : this._profileToEdit.forcedDisableRTF,
 		});
 	}
 
@@ -175,7 +177,7 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 			columnName : "Forced Monospace Font",
 			placeholder : "select property type",
 			options : this._settingsFormController.getForcedMonospaceFontOptions(),
-			initialValues : profile.forceMonospaceFont,
+			initialValues : this._profileToEdit.forceMonospaceFont,
 		});
 	}
 
@@ -184,7 +186,7 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 			columnName : "Inventory Spaces",
 			placeholder : "select space",
 			options : this._settingsFormController.getInventorySpacesOptions(),
-			initialValues : profile.inventorySpaces,
+			initialValues : this._profileToEdit.inventorySpaces,
 		});
 	}
 
@@ -193,7 +195,7 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 			columnName : "Sample Type Protocols",
 			placeholder : "select protocol",
 			options : this._settingsFormController.getSampleTypeProtocolsOptions(),
-			initialValues : profile.sampleTypeProtocols,
+			initialValues : this._profileToEdit.sampleTypeProtocols,
 		});
 	}
 
@@ -210,14 +212,14 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 
 	// 	this._appendSlider({
 	// 		$container : $fieldset,
-	// 		value : profile.storagesConfiguration.storageSpaceLowWarning,
+	// 		value : this._profileToEdit.storagesConfiguration.storageSpaceLowWarning,
 	// 		labelText : "Low storage space warning:",
 	// 		id : "settings-slider-low-storage",
 	// 	});
 
 	// 	this._appendSlider({
 	// 		$container : $fieldset,
-	// 		value : profile.storagesConfiguration.boxSpaceLowWarning,
+	// 		value : this._profileToEdit.storagesConfiguration.boxSpaceLowWarning,
 	// 		labelText : "Low box space warning:",
 	// 		id : "settings-slider-low-box",
 	// 	});
@@ -299,7 +301,7 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 			}).bind(this),
 		};
 		// add data
-		for (var dataSetTypeForFileName of profile.dataSetTypeForFileNameMap) {
+		for (var dataSetTypeForFileName of this._profileToEdit.dataSetTypeForFileNameMap) {
 			tableModel.addRow(dataSetTypeForFileName);
 		}
 		// transform output
@@ -319,13 +321,13 @@ function SettingsFormView(settingsFormController, settingsFormModel) {
 	//
 	this._paintSampleTypesDefinition = function($container) {
 		var $fieldset = this._getFieldset($container, "Sample type definitions", "settings-section-sampletype-definitions");
-		for (var sampleType of profile.getAllSampleTypes()) {
+		for (var sampleType of this._profileToEdit.getAllSampleTypes()) {
 			// layout
 			var $div = $("<div>").css("padding-left", "15px");
 			var $sampleTypeFieldset = this._getFieldset($div, sampleType.code, "settings-section-sampletype-" + sampleType.code);
 			$fieldset.append($div);
 			// table for sample type
-			var sampleTypeSettings = profile.sampleTypeDefinitionsExtension[sampleType.code];
+			var sampleTypeSettings = this._profileToEdit.sampleTypeDefinitionsExtension[sampleType.code];
 			var tableModel = this._getSampleTypeDefinitionTableModel(sampleTypeSettings);
 			$sampleTypeFieldset.append(this._getTable(tableModel));
 			this._sampleTypeDefinitionsTableModels[sampleType.code] = tableModel;
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetView.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetView.js
index f6bac713ff4..4a16ca23e0e 100644
--- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetView.js
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SideMenu/SideMenuWidgetView.js
@@ -528,16 +528,21 @@ function SideMenuWidgetView(sideMenuWidgetController, sideMenuWidgetModel) {
         this._sideMenuWidgetModel.menuDOMBody.append($tree);
         this._sideMenuWidgetModel.tree = $tree;
         
-        $tree.fancytree("getTree").getNodeByKey("LAB_NOTEBOOK").setExpanded(true);
+		var labNotebook = $tree.fancytree("getTree").getNodeByKey("LAB_NOTEBOOK");
+		if (labNotebook) {
+	        labNotebook.setExpanded(true);
+		}
         var inventoryNode = $tree.fancytree("getTree").getNodeByKey("INVENTORY");
-        inventoryNode.setExpanded(true).done(function(){
-            inventoryNode.visit(function(node){
-                node.setExpanded(true).done(function(){
-                    node.visit(function(node2){
-                        node2.setExpanded(true);
-                    })
-                });
-            })
-        });
+		if (inventoryNode) {
+			inventoryNode.setExpanded(true).done(function(){
+				inventoryNode.visit(function(node){
+					node.setExpanded(true).done(function(){
+						node.visit(function(node2){
+							node2.setExpanded(true);
+						})
+					});
+				})
+			});
+		}
     }
 }
\ No newline at end of file
-- 
GitLab