From 3a0d8daa48e4fa33c7455491e5e34f6feb78921a Mon Sep 17 00:00:00 2001
From: felmer <franz-josef.elmer@id.ethz.ch>
Date: Fri, 14 Apr 2023 11:26:41 +0200
Subject: [PATCH] SSDM-13120: Show property semantic annotations

---
 .../eln-lims/html/js/server/ServerFacade.js   | 20 ++++++-
 .../webapps/eln-lims/html/js/util/FormUtil.js | 50 +++++++++++------
 .../js/views/SampleForm/SampleFormView.js     | 54 ++++++++++++++-----
 3 files changed, 92 insertions(+), 32 deletions(-)

diff --git a/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js b/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js
index f10c7d33963..32377af9d1e 100644
--- a/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js
+++ b/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js
@@ -2410,6 +2410,17 @@ function ServerFacade(openbisServer) {
         v1Sample["experimentTypeCode"] = v3Sample.experiment && v3Sample.experiment.type ? v3Sample.experiment.type.code : null;
 		v1Sample["sampleTypeCode"] = (v3Sample.type)?v3Sample.type.code:null;
         v1Sample["semanticAnnotations"] = (v3Sample.type)?v3Sample.type.semanticAnnotations:null;
+        if (v3Sample.type && v3Sample.type.propertyAssignments) {
+            v1Sample["propertyTypesSemanticAnnotations"] = {}
+            v3Sample.type.propertyAssignments.forEach(function(assignment) {
+                var propertyType = assignment.getPropertyType();
+                var annotations = [].concat(assignment.getSemanticAnnotations());
+                if (propertyType && propertyType.getSemanticAnnotations()) {
+                    annotations = annotations.concat(propertyType.getSemanticAnnotations());
+                }
+                v1Sample["propertyTypesSemanticAnnotations"][propertyType.getCode()] = annotations;
+            });
+        }
 		v1Sample["properties"] = v3Sample.properties;
 
 		v1Sample["registrationDetails"] = {};
@@ -2742,7 +2753,12 @@ function ServerFacade(openbisServer) {
             //
             var fetchOptions = new SampleFetchOptions();
             fetchOptions.withSpace();
-            fetchOptions.withType().withSemanticAnnotations();
+            fetchOptions.withType();
+            if (fechOptions["withSemanticAnnotations"]) {
+                fetchOptions.withType().withSemanticAnnotations();
+                fetchOptions.withType().withPropertyAssignments().withSemanticAnnotations();
+                fetchOptions.withType().withPropertyAssignments().withPropertyType().withSemanticAnnotations();
+            }
             fetchOptions.withRegistrator();
             fetchOptions.withModifier();
             fetchOptions.withProject();
@@ -2803,6 +2819,7 @@ function ServerFacade(openbisServer) {
 			"samplePermId" : samplePermId,
 			"withProperties" : true,
 			"withParents" : true,
+            "withSemanticAnnotations" : true,
 			"withChildren" : true
 		}, callbackFunction);
 	}
@@ -2899,6 +2916,7 @@ function ServerFacade(openbisServer) {
 				"withProperties" : true,
 				"withParents" : true,
 				"withChildren" : true,
+                "withSemanticAnnotations" : true,
 				"sampleIdentifier" : sampleIdentifier
 			}, function(samples) {
 				samples.forEach(function(sample) {
diff --git a/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/util/FormUtil.js b/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/util/FormUtil.js
index 99898c52ea0..97eb6e2ddef 100644
--- a/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/util/FormUtil.js
+++ b/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/util/FormUtil.js
@@ -757,7 +757,7 @@ var FormUtil = new function() {
 	//
 	// Get Field with container to obtain a correct layout
 	//
-	this.getFieldForComponentWithLabel = function($component, label, postComponent, isInline) {
+	this.getFieldForComponentWithLabel = function($component, label, postComponent, isInline, $info) {
 		var $fieldset = $('<div>');
 		
 		var $controlGroup = $('<div>', {class : 'form-group'});
@@ -768,13 +768,9 @@ var FormUtil = new function() {
 		
 		var labelText = "";
 		if(label) {
-			labelText = label + requiredText + ":";
-		}
-		var labelColumnClass = ""
-		if(!isInline) {
-			labelColumnClass = this.labelColumnClass;
-		}
-		var $controlLabel = $('<label>', { class : 'control-label' }).html(labelText);
+            labelText = label + requiredText;
+        }
+        var $controlLabel = this.createLabel(labelText, $info);
 		
 		var controlColumnClass = ""
 		if(!isInline) {
@@ -804,8 +800,32 @@ var FormUtil = new function() {
 			return $fieldset;
 		}
 	}
-	
-	this.createPropertyField = function(propertyType, propertyValue) {
+
+    this.createLabel = function(label, $info) {
+        var $controlLabel = $('<label>', {class : 'control-label' });
+        
+        if(label) {
+            if ($info) {
+                var $line = $("<div>");
+                $line.append(label);
+                $infoIcon = $("<span>", { 'class' : 'glyphicon glyphicon-info-sign', 'style' : 'padding:2px' });
+                $infoIcon.tooltipster({
+                    content: $info,
+                    theme: 'tooltipster-shadow',
+                    interactive: true
+                });
+                $line.append($infoIcon);
+                $line.append(":");
+                $controlLabel.append($line);
+            } else
+            {
+                $controlLabel.text(label + ":");
+            }
+        }
+        return $controlLabel;
+    }
+
+    this.createPropertyField = function(propertyType, propertyValue, $info) {
 	    var isLink = propertyType.dataType === "HYPERLINK";
 	    var hyperlinkLabel = null;
 		if (propertyType.dataType === "CONTROLLEDVOCABULARY") {
@@ -816,23 +836,19 @@ var FormUtil = new function() {
 			    isLink = true;
 			}
 		}
-		return this._createField(isLink, propertyType.label, propertyValue, propertyType.code, null, null, hyperlinkLabel);
+        return this._createField(isLink, propertyType.label, propertyValue, propertyType.code, null, null, hyperlinkLabel, $info);
 	}
 	
 	this.getFieldForLabelWithText = function(label, text, id, postComponent, cssForText) {
 		return this._createField(false, label, text, id, postComponent, cssForText);
 	}
 	
-	this._createField = function(hyperlink, label, text, id, postComponent, cssForText, hyperlinkLabel) {
+    this._createField = function(hyperlink, label, text, id, postComponent, cssForText, hyperlinkLabel, $info) {
 		var $fieldset = $('<div>');
 		
 		var $controlGroup = $('<div>', {class : 'form-group'});
 		
-		var $controlLabel = $('<label>', {class : 'control-label' });
-		
-		if(label) {
-			$controlLabel.text(label + ":");
-		}
+        var $controlLabel = this.createLabel(label, $info);
 		
 		var $controls = $('<div>', {class : 'controls' });
 		
diff --git a/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SampleForm/SampleFormView.js b/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SampleForm/SampleFormView.js
index 896e08c16e8..8cbea659f91 100644
--- a/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SampleForm/SampleFormView.js
+++ b/ui-eln-lims/src/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SampleForm/SampleFormView.js
@@ -679,6 +679,7 @@ function SampleFormView(sampleFormController, sampleFormModel) {
 		for(var j = 0; j < propertyTypeGroup.propertyTypes.length; j++) {
 		    var propertyType = propertyTypeGroup.propertyTypes[j];
 			var propertyTypeV3 = profile.getPropertyTypeFromSampleTypeV3(this._sampleFormModel.sampleType, propertyType.code);
+            var semanticAnnotations = this._renderPropertyTypeSemanticAnnotations(this._sampleFormModel.sample.propertyTypesSemanticAnnotations[propertyTypeV3.code]);
 			FormUtil.fixStringPropertiesForForm(propertyTypeV3, this._sampleFormModel.sample);
 			if(!propertyType.showInEditViews && (this._sampleFormModel.mode === FormMode.EDIT || this._sampleFormModel.mode === FormMode.CREATE) && propertyType.code !== "$XMLCOMMENTS") { //Skip
 				continue;
@@ -720,17 +721,17 @@ function SampleFormView(sampleFormController, sampleFormModel) {
                             if (customWidget === 'Spreadsheet') {
                                 var $jexcelContainer = $("<div>");
                                 JExcelEditorManager.createField($jexcelContainer, this._sampleFormModel.mode, propertyType.code, this._sampleFormModel.sample);
-                                $controlGroup = FormUtil.getFieldForComponentWithLabel($jexcelContainer, propertyType.label);
+                                $controlGroup = FormUtil.getFieldForComponentWithLabel($jexcelContainer, propertyType.label, null, null, semanticAnnotations);
                             } else if (customWidget === 'Word Processor') {
                                 var $component = FormUtil.getFieldForPropertyType(propertyType, value);
                                 $component = FormUtil.activateRichTextProperties($component, undefined, propertyType, value, true);
-                                $controlGroup = FormUtil.getFieldForComponentWithLabel($component, propertyType.label);
+                                $controlGroup = FormUtil.getFieldForComponentWithLabel($component, propertyType.label, null, null, semanticAnnotations);
                             }
                         } else if(propertyType.dataType === "SAMPLE") {
                             var $component = new SampleField(false, '', false, value, true);
-                            $controlGroup = FormUtil.getFieldForComponentWithLabel($component, propertyType.label);
+                            $controlGroup = FormUtil.getFieldForComponentWithLabel($component, propertyType.label, null, null, semanticAnnotations);
                         } else { // The base case paints the property value as a label
-                            $controlGroup = FormUtil.createPropertyField(propertyType, value);
+                            $controlGroup = FormUtil.createPropertyField(propertyType, value, semanticAnnotations);
                         }
 					} else {
 						continue;
@@ -811,7 +812,7 @@ function SampleFormView(sampleFormController, sampleFormModel) {
 						$component.change(changeEvent(propertyType));
 					}
 
-					$controlGroup = FormUtil.getFieldForComponentWithLabel($component, propertyType.label);
+                    $controlGroup = FormUtil.getFieldForComponentWithLabel($component, propertyType.label, null, null, semanticAnnotations);
 				}
 				$fieldset.append($controlGroup);
 			}
@@ -830,6 +831,23 @@ function SampleFormView(sampleFormController, sampleFormModel) {
 
 		return false;
 	}
+	
+    this._renderPropertyTypeSemanticAnnotations = function(annotations) {
+        if (annotations && annotations.length > 0) {
+            var $group = $("<div>", {class : "form-group"});
+            $group.append($("<label>", {class : "control-label"}).text("Semantic Annotations:"));
+            var $lines = $("<div>", {class : "controls" });
+            var _this = this;
+            annotations.forEach(function(annotation) {
+                $lines.append(_this._renderSemanticAnnotation(annotation.getPredicateAccessionId(),
+                        annotation.getPredicateOntologyId(),
+                        annotation.getPredicateOntologyVersion()));
+            });
+            $group.append($lines);
+            return $group;
+        }
+        return null;
+    }
 
 	this._createIdentificationInfoSection = function(hideShowOptionsModel, sampleType, entityPath) {
 		hideShowOptionsModel.push({
@@ -927,21 +945,29 @@ function SampleFormView(sampleFormController, sampleFormModel) {
             var $controls = $("<div>", {class : "controls" });
             var _this = this;
             this._sampleFormModel.sample.semanticAnnotations.forEach(function(annotation) {
-                var $line = $("<div>");
-                $line.append(_this.asHyperLinkOrText(annotation.getDescriptorAccessionId()));
-                $line.append(" (Ontology: ");
-                $line.append(_this.asHyperLinkOrText(annotation.getDescriptorOntologyId()));
-                $line.append(", Version: ");
-                $line.append(_this.asHyperLinkOrText(annotation.getDescriptorOntologyVersion()));
-                $line.append(")");
-                $controls.append($line);
+                $controls.append(_this._renderSemanticAnnotation(annotation.getDescriptorAccessionId(),
+                        annotation.getDescriptorOntologyId(),
+                        annotation.getDescriptorOntologyVersion()));
             });
             $group.append($controls);
             $fieldset.append($("<div>").append($group));
         }
     }
 
-    this.asHyperLinkOrText = function(text) {
+    this._renderSemanticAnnotation = function(accessionId, ontologyId, ontologyVersion) {
+        var $line = $("<div>");
+        $line.append(this._asHyperLinkOrText(accessionId));
+        $line.append(" (Ontology: ");
+        $line.append(this._asHyperLinkOrText(ontologyId));
+        if (ontologyVersion && ontologyVersion.length > 0) {
+            $line.append(", Version: ");
+            $line.append(this._asHyperLinkOrText(ontologyVersion));
+        }
+        $line.append(")");
+        return $line;
+    }
+
+    this._asHyperLinkOrText = function(text) {
         return text.startsWith("http") ? FormUtil.asHyperlink(text) : text;
     }
 
-- 
GitLab