azkaban-uncached

Skeleton for flow summary.

12/3/2013 5:15:16 PM

Details

build.xml 15(+15 -0)

diff --git a/build.xml b/build.xml
index 86db40b..7287178 100644
--- a/build.xml
+++ b/build.xml
@@ -61,6 +61,21 @@
 			<src path="${java.src.dir}" />
 			<classpath refid="main.classpath" />
 		</javac>
+
+		<!-- Compile dustjs templates -->
+		<!-- Note: Because apply does not support multiple srcfile and targetfile
+				 elements, and for and foreach requires ant-contrib, we use targetfile 
+				 for the template name parameter and then redirect the output of dustc
+				 to the final output file -->
+		<apply dir="${java.src.dir}/tl" executable="dustc" relative="true">
+			<mapper type="glob" from="*.tl" to="*" />
+			<targetfile prefix="--name=" />
+			<srcfile />
+			<fileset dir="${java.src.dir}/tl" includes="*.tl" />
+			<redirector>
+				<outputmapper id="out" type="glob" from="*.tl" to="${dist.dust.dir}/*.js" />
+			</redirector>
+		</apply>
 	</target>
 	
 	<target name="jars" depends="build" description="Create azkaban jar">
diff --git a/src/java/azkaban/webapp/servlet/velocity/flowpage.vm b/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
index cde432c..3e60e3f 100644
--- a/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
@@ -17,7 +17,7 @@
 <!DOCTYPE html> 
 <html>
 	<head>
-#parse( "azkaban/webapp/servlet/velocity/style.vm" )
+#parse("azkaban/webapp/servlet/velocity/style.vm")
 		<script type="text/javascript" src="${context}/js/jquery/jquery-1.9.1.js"></script>    
 		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-1.10.1.custom.js"></script>
 		
@@ -50,18 +50,21 @@
 		<link rel="stylesheet" type="text/css" href="${context}/css/jquery-ui-1.10.1.custom.css" />
 	</head>
 	<body>
+
 #set($current_page="all")
-#parse( "azkaban/webapp/servlet/velocity/nav.vm" )
+#parse("azkaban/webapp/servlet/velocity/nav.vm")
+
 		<div class="messaging"><p id="messageClose">X</p><p id="message"></p></div>  
 		<div class="content">
+
 #if($errorMsg)
 				<div class="box-error-message">$errorMsg</div>
 #else
-#if($error_message != "null")
+	#if($error_message != "null")
 				<div class="box-error-message">$error_message</div>
-#elseif($success_message != "null")
+	#elseif($success_message != "null")
 				<div class="box-success-message">$success_message</div>
-#end
+	#end
 
 				<div id="all-jobs-content">
 					<div class="section-hd flow-header">
@@ -80,8 +83,13 @@
 							<li><a id="graphViewLink" href="#graph">Graph</a></li>
 							<li class="lidivider">|</li>
 							<li><a id="executionsViewLink" href="#executions">Executions</a></li>
+							<li class="lidivider">|</li>
+							<li><a id="summaryViewLink" href="#summary">Summary</a></li>
 						</ul>
 					</div>
+
+	## Graph view.
+
 					<div id="graphView">
 						<div class="relative">
 							<div id="jobList" class="jobList">
@@ -97,7 +105,10 @@
 								</svg>
 							</div>
 						</div>
-					</div>
+					</div><!-- /#graphView -->
+
+	## Executions view.
+
 					<div id="executionsView">
 						<div id="executionDiv" class="all-jobs executionInfo">
 							<table id="execTable">
@@ -129,25 +140,31 @@
 							</ul>
 						</div>
 					</div>
-				</div>
-		<!-- modal content -->
+				</div><!-- /#executionsView -->
+
+	## Summary view.
+
+				<div id="summaryView">
+				</div><!-- /#summaryView -->
+
+	## Invalid session modal.
 
 				<div id="invalid-session" class="modal">
 					<h3>Invalid Session</h3>
-						<p>Session has expired. Please re-login.</p>
-						<div class="actions">
-							<a class="yes btn3" id="login-btn" href="#">Re-login</a>
-						</div>
+					<p>Session has expired. Please re-login.</p>
+					<div class="actions">
+						<a class="yes btn3" id="login-btn" href="#">Re-login</a>
+					</div>
 				</div>
 
-#parse( "azkaban/webapp/servlet/velocity/flowexecutionpanel.vm" )
+	#parse("azkaban/webapp/servlet/velocity/flowexecutionpanel.vm")
 
 #end
 
 		</div>
 		<div id="contextMenu">
 		</div>
-		#parse( "azkaban/webapp/servlet/velocity/messagedialog.vm" )
+#parse("azkaban/webapp/servlet/velocity/messagedialog.vm")
 	</body>
 </html>
 
diff --git a/src/tl/flowsummary.tl b/src/tl/flowsummary.tl
new file mode 100644
index 0000000..b9536c5
--- /dev/null
+++ b/src/tl/flowsummary.tl
@@ -0,0 +1,70 @@
+					<h4>General</h4>
+					<table>
+						<tbody>
+							<tr>
+								<td>Workflow name</td>
+								<td></td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Workflow Purpose/Description</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Project name</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Name of scheduled item</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Workflow Hadoop User Name</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Responsible team</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Responsible manager</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Responsible Developer</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Hadoop APIs Used</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Additional Hadoop APIs Used</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Streaming Languages Used</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Code Repository</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Does this workflow perform any second, third, or higher level connection graph calculations?</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>Can this workflow be run with an empty <strong>/jobs</strong> directory</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>If not, why not?</td>
+								<td></td>
+							</tr>
+							<tr>
+								<td>How does the result get to front-end servers?</td>
+								<td></td>
+							</tr>
+						</tbody>
+					</table>
diff --git a/src/web/js/azkaban.flow.view.js b/src/web/js/azkaban.flow.view.js
index ce01dbc..dfa26bf 100644
--- a/src/web/js/azkaban.flow.view.js
+++ b/src/web/js/azkaban.flow.view.js
@@ -31,22 +31,25 @@ var statusStringMap = {
 
 var handleJobMenuClick = function(action, el, pos) {
 	var jobid = el[0].jobid;
-	var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + flowId + "&job=" + jobid;
+	var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + 
+			flowId + "&job=" + jobid;
 	if (action == "open") {
 		window.location.href = requestURL;
 	}
-	else if(action == "openwindow") {
+	else if (action == "openwindow") {
 		window.open(requestURL);
 	}
 }
 
 var flowTabView;
 azkaban.FlowTabView= Backbone.View.extend({
-	events : {
-		"click #graphViewLink" : "handleGraphLinkClick",
-		"click #executionsViewLink" : "handleExecutionLinkClick"
+	events: {
+		"click #graphViewLink": "handleGraphLinkClick",
+		"click #executionsViewLink": "handleExecutionLinkClick",
+		"click #summaryViewLink": "handleSummaryLinkClick"
 	},
-	initialize : function(settings) {
+	
+	initialize: function(settings) {
 		var selectedView = settings.selectedView;
 		if (selectedView == "executions") {
 			this.handleExecutionLinkClick();
@@ -54,26 +57,39 @@ azkaban.FlowTabView= Backbone.View.extend({
 		else {
 			this.handleGraphLinkClick();
 		}
-
 	},
+	
 	render: function() {
 		console.log("render graph");
 	},
+	
 	handleGraphLinkClick: function(){
 		$("#executionsViewLink").removeClass("selected");
 		$("#graphViewLink").addClass("selected");
-		
+		$('#summaryViewLink').removeClass('selected');
 		$("#executionsView").hide();
 		$("#graphView").show();
+		$('#summaryView').hide();
 	},
+	
 	handleExecutionLinkClick: function() {
 		$("#graphViewLink").removeClass("selected");
 		$("#executionsViewLink").addClass("selected");
-		
-		 $("#graphView").hide();
-		 $("#executionsView").show();
-		 executionModel.trigger("change:view");
-	}
+		$('#summaryViewLink').removeClass('selected');
+		$("#graphView").hide();
+		$("#executionsView").show();
+		$('#summaryView').hide();
+		executionModel.trigger("change:view");
+	},
+
+	handleSummaryLinkClick: function() {
+		$('#graphViewLink').removeClass('selected');
+		$('#executionsViewLink').removeClass('selected');
+		$('#summaryViewLink').addClass('selected');
+		$('#graphView').hide();
+		$('#executionsView').hide();
+		$('#summaryView').show();
+	},
 });
 
 var jobListView;
@@ -84,12 +100,14 @@ azkaban.ExecutionsView = Backbone.View.extend({
 	events: {
 		"click #pageSelection li": "handleChangePageSelection"
 	},
+	
 	initialize: function(settings) {
 		this.model.bind('change:view', this.handleChangeView, this);
 		this.model.bind('render', this.render, this);
 		this.model.set({page: 1, pageSize: 16});
 		this.model.bind('change:page', this.handlePageChange, this);
 	},
+	
 	render: function(evt) {
 		console.log("render");
 		// Render page selections
@@ -155,6 +173,7 @@ azkaban.ExecutionsView = Backbone.View.extend({
 		
 		this.renderPagination(evt);
 	},
+	
 	renderPagination: function(evt) {
 		var total = this.model.get("total");
 		total = total? total : 1;
@@ -228,6 +247,7 @@ azkaban.ExecutionsView = Backbone.View.extend({
 			a.attr("href", "#page" + tpage);
 		}
 	},
+	
 	handleChangePageSelection: function(evt) {
 		if ($(evt.currentTarget).hasClass("disabled")) {
 			return;
@@ -236,6 +256,7 @@ azkaban.ExecutionsView = Backbone.View.extend({
 		
 		this.model.set({"page": page});
 	},
+	
 	handleChangeView: function(evt) {
 		if (this.init) {
 			return;
@@ -245,32 +266,50 @@ azkaban.ExecutionsView = Backbone.View.extend({
 		this.handlePageChange(evt);
 		this.init = true;
 	},
+	
 	handlePageChange: function(evt) {
 		var page = this.model.get("page") - 1;
 		var pageSize = this.model.get("pageSize");
 		var requestURL = contextURL + "/manager";
 		
 		var model = this.model;
-		$.get(
-			requestURL,
-			{"project": projectName, "flow":flowId, "ajax": "fetchFlowExecutions", "start":page * pageSize, "length": pageSize},
-			function(data) {
-				model.set({"executions": data.executions, "total": data.total});
-				model.trigger("render");
-			},
-			"json"
-		);
+		var requestData = {
+			"project": projectName, 
+			"flow": flowId, 
+			"ajax": "fetchFlowExecutions", 
+			"start": page * pageSize, 
+			"length": pageSize
+		};
+		var successHandler = function(data) {
+			model.set({"executions": data.executions, "total": data.total});
+			model.trigger("render");
+		};
+		$.get(requestURL, requestData, successHandler, "json");
+	}
+});
+
+var summaryView;
+azkaban.SummaryView = Backbone.View.extend({
+	events: {
+	},
+	
+	initialize: function(settings) {
+	},
+	
+	render: function(evt) {
+
 	}
 });
 
 var exNodeClickCallback = function(event) {
 	console.log("Node clicked callback");
 	var jobId = event.currentTarget.jobid;
-	var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + flowId + "&job=" + jobId;
+	var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + 
+			flowId + "&job=" + jobId;
 
 	var menu = [	
-			{title: "Open Job...", callback: function() {window.location.href=requestURL;}},
-			{title: "Open Job in New Window...", callback: function() {window.open(requestURL);}}
+		{title: "Open Job...", callback: function() {window.location.href=requestURL;}},
+		{title: "Open Job in New Window...", callback: function() {window.open(requestURL);}}
 	];
 
 	contextMenuView.show(event, menu);
@@ -279,11 +318,12 @@ var exNodeClickCallback = function(event) {
 var exJobClickCallback = function(event) {
 	console.log("Node clicked callback");
 	var jobId = event.currentTarget.jobid;
-	var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + flowId + "&job=" + jobId;
+	var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + 
+			flowId + "&job=" + jobId;
 
 	var menu = [	
-			{title: "Open Job...", callback: function() {window.location.href=requestURL;}},
-			{title: "Open Job in New Window...", callback: function() {window.open(requestURL);}}
+		{title: "Open Job...", callback: function() {window.location.href=requestURL;}},
+		{title: "Open Job in New Window...", callback: function() {window.open(requestURL);}}
 	];
 
 	contextMenuView.show(event, menu);
@@ -318,14 +358,23 @@ $(function() {
 	var selected;
 	// Execution model has to be created before the window switches the tabs.
 	executionModel = new azkaban.ExecutionModel();
-	executionsView = new azkaban.ExecutionsView({el:$('#executionsView'), model: executionModel});
-	flowTabView = new azkaban.FlowTabView({el:$( '#headertabs'), selectedView: selected });
+	executionsView = new azkaban.ExecutionsView({
+		el: $('#executionsView'), 
+		model: executionModel
+	});
+	summaryView = new azkaban.SummaryView({
+		el: $('#summaryView'),
+	});
+	flowTabView = new azkaban.FlowTabView({
+		el: $('#headertabs'), 
+		selectedView: selected 
+	});
 
 	graphModel = new azkaban.GraphModel();
 	mainSvgGraphView = new azkaban.SvgGraphView({
 		el: $('#svgDiv'), 
 		model: graphModel, 
-		rightClick:  { 
+		rightClick: { 
 			"node": exNodeClickCallback, 
 			"edge": exEdgeClickCallback, 
 			"graph": exGraphClickCallback 
@@ -352,61 +401,62 @@ $(function() {
 		flowExecuteDialogView.show(executingData);
 	});
 
-	$.get(
-		requestURL,
-		{"project": projectName, "ajax":"fetchflowgraph", "flow":flowId},
-		function(data) {
-			// Create the nodes
-			var nodes = {};
-			for (var i=0; i < data.nodes.length; ++i) {
-				var node = data.nodes[i];
-				nodes[node.id] = node;
+	var requestData = {
+		"project": projectName, 
+		"ajax": "fetchflowgraph", 
+		"flow":flowId
+	};
+	var successHandler = function(data) {
+		// Create the nodes
+		var nodes = {};
+		for (var i = 0; i < data.nodes.length; ++i) {
+			var node = data.nodes[i];
+			nodes[node.id] = node;
+		}
+		for (var i = 0; i < data.edges.length; ++i) {
+			var edge = data.edges[i];
+			var fromNode = nodes[edge.from];
+			var toNode = nodes[edge.target];
+			
+			if (!fromNode.outNodes) {
+				fromNode.outNodes = {};
 			}
-			for (var i=0; i < data.edges.length; ++i) {
-				var edge = data.edges[i];
-				var fromNode = nodes[edge.from];
-				var toNode = nodes[edge.target];
-				
-				if (!fromNode.outNodes) {
-					fromNode.outNodes = {};
-				}
-				fromNode.outNodes[toNode.id] = toNode;
-				
-				if (!toNode.inNodes) {
-					toNode.inNodes = {};
-				}
-				toNode.inNodes[fromNode.id] = fromNode;
+			fromNode.outNodes[toNode.id] = toNode;
+			
+			if (!toNode.inNodes) {
+				toNode.inNodes = {};
 			}
+			toNode.inNodes[fromNode.id] = fromNode;
+		}
+	
+		console.log("data fetched");
+		graphModel.set({data: data});
+		graphModel.set({nodes: nodes});
+		graphModel.set({disabled: {}});
+		graphModel.trigger("change:graph");
 		
-			console.log("data fetched");
-			graphModel.set({data: data});
-			graphModel.set({nodes: nodes});
-			graphModel.set({disabled: {}});
-			graphModel.trigger("change:graph");
-			
-			// Handle the hash changes here so the graph finishes rendering first.
-			if (window.location.hash) {
-				var hash = window.location.hash;
-				if (hash == "#executions") {
+		// Handle the hash changes here so the graph finishes rendering first.
+		if (window.location.hash) {
+			var hash = window.location.hash;
+			if (hash == "#executions") {
+				flowTabView.handleExecutionLinkClick();
+			}
+			else if (hash == "#graph") {
+				// Redundant, but we may want to change the default. 
+				selected = "graph";
+			}
+			else {
+				if ("#page" == hash.substring(0, "#page".length)) {
+					var page = hash.substring("#page".length, hash.length);
+					console.log("page " + page);
 					flowTabView.handleExecutionLinkClick();
-				}
-				else if (hash == "#graph") {
-					// Redundant, but we may want to change the default. 
-					selected = "graph";
+					executionModel.set({"page": parseInt(page)});
 				}
 				else {
-					if ("#page" == hash.substring(0, "#page".length)) {
-						var page = hash.substring("#page".length, hash.length);
-						console.log("page " + page);
-						flowTabView.handleExecutionLinkClick();
-						executionModel.set({"page": parseInt(page)});
-					}
-					else {
-						selected = "graph";
-					}
+					selected = "graph";
 				}
 			}
-		},
-		"json"
-	);
+		}
+	};
+	$.get(requestURL, requestData, successHandler, "json");
 });