From ad6b3df44d0f3f3ceb59776752ef0e02d8d25ae2 Mon Sep 17 00:00:00 2001
From: cramakri <cramakri>
Date: Tue, 11 Dec 2012 10:09:51 +0000
Subject: [PATCH] BIS-229 SP-419 : Implemented bottom-up and top-down display.

SVN: 27906
---
 .../1/as/webapps/sample-graph/html/webapp.js  | 132 +++++++++++++-----
 1 file changed, 94 insertions(+), 38 deletions(-)

diff --git a/deep_sequencing_unit/source/core-plugins/ngs-sample-overview-graph/1/as/webapps/sample-graph/html/webapp.js b/deep_sequencing_unit/source/core-plugins/ngs-sample-overview-graph/1/as/webapps/sample-graph/html/webapp.js
index e1f1c561b0a..084cdc18468 100644
--- a/deep_sequencing_unit/source/core-plugins/ngs-sample-overview-graph/1/as/webapps/sample-graph/html/webapp.js
+++ b/deep_sequencing_unit/source/core-plugins/ngs-sample-overview-graph/1/as/webapps/sample-graph/html/webapp.js
@@ -73,53 +73,50 @@ function SampleGraphLink(sourceNode, targetNode) {
 	this.targetNode = targetNode;
 }
 
+/** Break an identifier into a code and space */
+function codeAndSpaceFromIdentifier(identifier) {
+	var identifierTokens = identifier.split("/");
+	var space, code;
+	if (identifierTokens.length > 2) {
+		space = identifierTokens[1];
+		code = identifierTokens[2];
+	} else {
+		space = null;
+		code = identifierTokens[1];
+	}
+	return {space : space, code : code};
+}
+
+
 /**
- * The model that manages state and implements the operations for the sample graph. This model is specific to the Flowcell type.
+ * The model that manages state and implements the operations for the sample graph.
  */
-function FlowcellGraphModel() {
+function SampleGraphModel() {
 	this.initializeModel();
 }
 
-FlowcellGraphModel.prototype.initializeModel = function() {
+SampleGraphModel.prototype.initializeModel = function() {
 	this.sampleIdentifier = webappContext.getEntityIdentifier();
-	var identifierTokens = this.sampleIdentifier.split("/");
-	if (identifierTokens.length > 2) {
-		this.sampleSpace = identifierTokens[1];
-		this.sampleCode = identifierTokens[2];
-	} else {
-		this.sampleSpace = null;
-		this.sampleCode = identifierTokens[1];
-	}
+	var codeAndSpace = codeAndSpaceFromIdentifier(this.sampleIdentifier);
+	this.sampleSpace = codeAndSpace.space;
+	this.sampleCode = codeAndSpace.code;
 	this.samplePermId = webappContext.getEntityPermId();
 	this.sampleType = webappContext.getEntityType();
 	var samplesByType = {};
 	COLUMNS.forEach(function(column) { samplesByType[column.type] = [] });
 	this.samplesByType = samplesByType;
+	this.flowcellsByIdentifier = {};
 }
 
 /**
  * Request the data necessary to display the graph.
  */
-FlowcellGraphModel.prototype.requestGraphData = function(callback)
+SampleGraphModel.prototype.requestGraphData = function(callback)
 {
-	var containerCriteria = {
-		matchClauses : 
-			[ {"@type" : "AttributeMatchClause",
-				fieldType : "ATTRIBUTE",			
-				attribute : "CODE",
-				desiredValue : this.sampleCode
-			}, {"@type" : "AttributeMatchClause",
-				fieldType : "ATTRIBUTE",			
-				attribute : "SPACE",
-				desiredValue : this.sampleSpace
-			} ],
-		operator : "MATCH_ALL_CLAUSES"		
-	};
-
 	var matchClauses = [ {"@type" : "AttributeMatchClause",
 		fieldType : "ATTRIBUTE",
 		attribute : "CODE",
-		desiredValue : this.sampleCode + "*"
+		desiredValue : (FLOWCELL_SAMPLE_TYPE == this.sampleType) ? this.sampleCode + "*" : this.sampleCode
 	}];
 
 	if (this.sampleSpace) {
@@ -139,16 +136,58 @@ FlowcellGraphModel.prototype.requestGraphData = function(callback)
 	var lexicalParent = this;
 	function coalesceResult(data) {
 		lexicalParent.coalesceGraphData(data);
-		callback();
+		lexicalParent.requestFlowcellData(callback)
 	}
 
 	openbisServer.searchForSamplesWithFetchOptions(sampleCriteria, ["PROPERTIES", "ANCESTORS", "DESCENDANTS"], coalesceResult);
 }
 
+/**
+ * In most cases, we need an additional server request to get the flowcell data. Make that call here.
+ */
+SampleGraphModel.prototype.requestFlowcellData = function(callback) {
+	if (FLOWCELL_SAMPLE_TYPE == this.sampleType) {
+		callback();
+		return;
+	}
+
+	// Collect the Flowcell code and spaces
+	var flowlaneIds = [];
+	this.samplesByType[FLOWLANE_SAMPLE_TYPE].forEach(function(flowlane) {
+		var flowcellId = flowlane.identifier.split(":")[0];
+		var codeAndSpace = codeAndSpaceFromIdentifier(flowcellId);
+		flowlaneIds.push(codeAndSpace);
+	});
+
+	var matchClauses = [];
+	flowlaneIds.forEach(function(cs) {
+		matchClauses.push({"@type" : "AttributeMatchClause",
+			fieldType : "ATTRIBUTE",
+			attribute : "CODE",
+			desiredValue : cs.code
+		})
+	})
+
+	var sampleCriteria = {
+		matchClauses : matchClauses,
+		operator : "MATCH_ANY_CLAUSES"
+	};
+
+	var lexicalParent = this;
+	function coalesceResult(data) {
+		lexicalParent.coalesceGraphData(data);
+		callback();
+	}
+
+	openbisServer.searchForSamplesWithFetchOptions(sampleCriteria, ["PROPERTIES"], coalesceResult);
+
+};
+
+
 /**
  * Request the data necessary to display the graph.
  */
-FlowcellGraphModel.prototype.coalesceGraphData = function(data, callback) {
+SampleGraphModel.prototype.coalesceGraphData = function(data, callback) {
 	var samples = data.result;
 	var nodesById = {};
 
@@ -170,6 +209,9 @@ FlowcellGraphModel.prototype.coalesceGraphData = function(data, callback) {
 			node.arrayIndex = sampleTypeArray.length;
 			sampleTypeArray.push(node);
 		}
+		if (FLOWCELL_SAMPLE_TYPE == node.sampleType) {
+			lexicalParent.flowcellsByIdentifier[node.identifier] = node;
+		}
 
 		if (sample.parents) sample.parents.forEach(convertSampleToNode);
 		if (sample.children) sample.children.forEach(convertSampleToNode);
@@ -178,35 +220,49 @@ FlowcellGraphModel.prototype.coalesceGraphData = function(data, callback) {
 	function resolveParents(sample) {
 		// This is just a nodeId, it will be resolved elsewhere
 		if (isPureId(sample)) return;
+		if (!sample.parents) return;
 
 		sample.parents.forEach(resolveParents);
 
 		var node = nodeForSample(sample);
 		node.parents = sample.parents.map(nodeForSample);
+		node.parents.forEach(function(p) { p.children = [node]});
 	}
 
 	function resolveChildren(sample) {
 		// This is just a nodeId, it will be resolved elsewhere
 		if (isPureId(sample)) return;
+		if (!sample.children) return;
 
 		sample.children.forEach(resolveChildren);
 
 		var node = nodeForSample(sample);
 		node.children = sample.children.map(nodeForSample);
+		node.children.forEach(function(p) { p.parents = [node]});
 	}
 
 	samples.forEach(convertSampleToNode);
 	samples.forEach(resolveParents);
 	samples.forEach(resolveChildren);
 
-	// The parents of the flowlanes should become the parents of the flow cell
-	var flowcell = this.samplesByType[FLOWCELL_SAMPLE_TYPE][0];
-	if (flowcell) {
-		var flowlaneParents = []
-		this.samplesByType[FLOWLANE_SAMPLE_TYPE].forEach(function(d) { flowlaneParents = flowlaneParents.concat(d.parents); });
-		this.samplesByType[FLOWCELL_SAMPLE_TYPE][0].parents = flowlaneParents;
-		this.samplesByType[FLOWLANE_SAMPLE_TYPE].forEach(function(d) { d.parents = [flowcell]});
-	}
+	// The parents of the flowlanes should become the parents of the flowcell and the
+	// flowcell should become the parent of the flowlanes.
+	var flowcellsByIdentifier = this.flowcellsByIdentifier;
+	this.samplesByType[FLOWLANE_SAMPLE_TYPE].forEach(function(flowlane) {
+		var flowcellId = flowlane.identifier.split(":")[0];
+		var flowcell = flowcellsByIdentifier[flowcellId];
+		if (flowcell) {
+			var parents = flowcell.parents;
+			parents = parents.concat(flowlane.parents);
+			flowcell.parents = parents;
+			flowcell.children.push(flowlane);
+			flowlane.parents.forEach(function(parent) {
+				var children = parent.children;
+				children.splice(children.indexOf(flowlane), 1, flowcell);
+			})
+			flowlane.parents = [flowcell];
+		}
+	});
 }
 
 
@@ -563,7 +619,7 @@ function clickedTopDown() {
 
 /// The model that manages state and implements the operations
 var model;
-model = new FlowcellGraphModel();
+model = new SampleGraphModel();
 
 // The presenter tranlsates the model into visual elements
 var presenter;
-- 
GitLab