azkaban-uncached

Details

diff --git a/src/java/azkaban/project/Project.java b/src/java/azkaban/project/Project.java
index cdd5edc..5715342 100644
--- a/src/java/azkaban/project/Project.java
+++ b/src/java/azkaban/project/Project.java
@@ -111,6 +111,10 @@ public class Project {
 		return userToPermission.get(userID);
 	}
 	
+	public void removeUserPermission(String userId) {
+		userToPermission.remove(userId);
+	}
+	
 	public long getCreateTimestamp() {
 		return createTimestamp;
 	}
diff --git a/src/java/azkaban/webapp/servlet/HistoryServlet.java b/src/java/azkaban/webapp/servlet/HistoryServlet.java
index 6969ece..78d0258 100644
--- a/src/java/azkaban/webapp/servlet/HistoryServlet.java
+++ b/src/java/azkaban/webapp/servlet/HistoryServlet.java
@@ -12,7 +12,9 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import azkaban.executor.ExecutableFlow;
 import azkaban.executor.ExecutorManager;
+import azkaban.executor.ExecutorManagerException;
 import azkaban.executor.ExecutorManager.ExecutionReference;
 import azkaban.utils.JSONUtils;
 import azkaban.webapp.session.Session;
@@ -32,7 +34,13 @@ public class HistoryServlet extends LoginAbstractAzkabanServlet {
 	protected void handleGet(HttpServletRequest req, HttpServletResponse resp,
 			Session session) throws ServletException, IOException {
 		
-		if (hasParam(req, "timeline")) {
+		if (hasParam(req, "ajax")) {
+			handleAJAXAction(req, resp, session);
+		}
+		else if (hasParam(req, "days")) {
+			handleHistoryDayPage(req, resp, session);
+		}
+		else if (hasParam(req, "timeline")) {
 			handleHistoryTimelinePage(req, resp, session);
 		}
 		else {
@@ -91,9 +99,44 @@ public class HistoryServlet extends LoginAbstractAzkabanServlet {
 		else {
 			resp.sendRedirect(req.getRequestURL().toString());
 		}
+	}
+	
+	private void handleAJAXAction(HttpServletRequest req, HttpServletResponse resp, Session session) throws ServletException, IOException {
+		HashMap<String, Object> ret = new HashMap<String, Object>();
+		String ajaxName = getParam(req, "ajax");
+	
+		if (ajaxName.equals("fetch")) {
+			fetchHistoryData(req, resp, ret);
+		}
 		
+		if (ret != null) {
+			this.writeJSON(resp, ret);
+		}
 	}
-
+	
+	private void fetchHistoryData(HttpServletRequest req, HttpServletResponse resp, HashMap<String, Object> ret) throws ServletException {
+		long start = getLongParam(req, "start");
+		long end = getLongParam(req, "end");
+		
+		ret.put("start", start);
+		ret.put("end", end);
+		
+		List<ExecutionReference> refs = executorManager.getFlowHistory(start, end);
+		ArrayList<Object> refList = new ArrayList<Object>();
+		for (ExecutionReference ref: refs) {
+			
+			HashMap<String,Object> refObj = new HashMap<String,Object>();
+			refObj.put("execId", ref.getExecId());
+			refObj.put("start", ref.getStartTime());
+			refObj.put("end", ref.getEndTime());
+			refObj.put("status", ref.getStatus().toString());
+			
+			refList.add(refObj);
+		}
+		
+		ret.put("data", refList);
+	}
+	
 	private void handleHistoryPage(HttpServletRequest req, HttpServletResponse resp, Session session) {
 		Page page = newPage(req, resp, session, "azkaban/webapp/servlet/velocity/historypage.vm");
 		int pageNum = getIntParam(req, "page", 1);
@@ -158,6 +201,32 @@ public class HistoryServlet extends LoginAbstractAzkabanServlet {
 		page.render();
 	}
 	
+	private void handleHistoryDayPage(HttpServletRequest req, HttpServletResponse resp, Session session) {
+		Page page = newPage(req, resp, session, "azkaban/webapp/servlet/velocity/historydaypage.vm");
+		long currentTime = System.currentTimeMillis();
+		long begin = getLongParam(req, "begin", currentTime - 86400000);
+		long end = getLongParam(req, "end", currentTime);
+		
+		page.add("begin", begin);
+		page.add("end", end);
+		
+		List<ExecutionReference> refs = executorManager.getFlowHistory(begin, end);
+		ArrayList<Object> refList = new ArrayList<Object>();
+		for (ExecutionReference ref: refs) {
+			
+			HashMap<String,Object> refObj = new HashMap<String,Object>();
+			refObj.put("execId", ref.getExecId());
+			refObj.put("start", ref.getStartTime());
+			refObj.put("end", ref.getEndTime());
+			refObj.put("status", ref.getStatus().toString());
+			
+			refList.add(refObj);
+		}
+		
+		page.add("data", JSONUtils.toJSON(refList));
+		page.render();
+	}
+	
 	public class PageSelection {
 		private int page;
 		private int size;
diff --git a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
index 38bdb97..a5d7b64 100644
--- a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
+++ b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
@@ -507,17 +507,28 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 			return;
 		}
 		
-		if (admin) {
-			perm.setPermission(Type.ADMIN, true);
+		if (admin || read || write || execute || schedule) {
+			if (admin) {
+				perm.setPermission(Type.ADMIN, true);
+				perm.setPermission(Type.READ, false);
+				perm.setPermission(Type.WRITE, false);
+				perm.setPermission(Type.EXECUTE, false);
+				perm.setPermission(Type.SCHEDULE, false);
+			}
+			else {
+				perm.setPermission(Type.ADMIN, false);
+				perm.setPermission(Type.READ, read);
+				perm.setPermission(Type.WRITE, write);
+				perm.setPermission(Type.EXECUTE, execute);
+				perm.setPermission(Type.SCHEDULE, schedule);
+			}
+			project.info("User '" + user.getUserId() + "' has changed permissions for '" + username + "' to " + perm.toString());
 		}
 		else {
-			perm.setPermission(Type.READ, read);
-			perm.setPermission(Type.WRITE, write);
-			perm.setPermission(Type.EXECUTE, execute);
-			perm.setPermission(Type.SCHEDULE, schedule);
+			project.removeUserPermission(username);
+			project.info("User '" + user.getUserId() + "' has removed '" + username + "'");
 		}
-		project.info("User '" + user.getUserId() + "' has changed permissions for '" + username + "' to " + perm.toString());
-
+		
 		try {
 			projectManager.commitProject(project.getName());
 		} catch (ProjectManagerException e) {
diff --git a/src/java/azkaban/webapp/servlet/velocity/historydaypage.vm b/src/java/azkaban/webapp/servlet/velocity/historydaypage.vm
new file mode 100644
index 0000000..bf6ccaa
--- /dev/null
+++ b/src/java/azkaban/webapp/servlet/velocity/historydaypage.vm
@@ -0,0 +1,44 @@
+<!DOCTYPE html> 
+<html>
+	<head>
+#parse( "azkaban/webapp/servlet/velocity/style.vm" )
+		<script type="text/javascript" src="${context}/js/jquery/jquery.js"></script>    
+		<script type="text/javascript" src="${context}/js/namespace.js"></script>
+		<script type="text/javascript" src="${context}/js/underscore-1.2.1-min.js"></script>
+		<script type="text/javascript" src="${context}/js/backbone-0.5.3-min.js"></script>
+		<script type="text/javascript" src="${context}/js/jquery.simplemodal.js"></script>
+		<script type="text/javascript" src="${context}/js/azkaban.nav.js"></script>
+		<script type="text/javascript" src="${context}/js/azkaban.historyday.view.js"></script>
+		<script type="text/javascript">
+			var contextURL = "${context}";
+			var currentTime = ${currentTime};
+			var timezone = "${timezone}";
+			var errorMessage = "${error_message}";
+			var successMessage = "${success_message}";
+			
+			var begin = $begin;
+			var end = $end;
+			var data = $data;
+		</script>
+	</head>
+	<body>
+		#set($current_page="history")
+#parse( "azkaban/webapp/servlet/velocity/nav.vm" )
+		<div class="messaging"><p id="messageClose">X</p><p id="message"></p></div>  
+
+		<div class="content history">
+			<div id="all-jobs-content">
+				<div class="section-hd">
+					<h2>History Week</h2>
+				</div>
+			</div>
+			<div id="historyTimeLine">
+				<div id="dayByDayPanel">
+					<svg id="dayGraph">
+						
+					</svg>
+				</div>
+			</div>
+		</div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/src/java/azkaban/webapp/servlet/velocity/historytimelinepage.vm b/src/java/azkaban/webapp/servlet/velocity/historytimelinepage.vm
index 8b726a9..bfdaa74 100644
--- a/src/java/azkaban/webapp/servlet/velocity/historytimelinepage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/historytimelinepage.vm
@@ -8,7 +8,6 @@
 		<script type="text/javascript" src="${context}/js/backbone-0.5.3-min.js"></script>
 		<script type="text/javascript" src="${context}/js/jquery.simplemodal.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.nav.js"></script>
-		<script type="text/javascript" src="${context}/js/azkaban.main.view.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.historytimeline.view.js"></script>
 		<script type="text/javascript">
 			var contextURL = "${context}";
@@ -27,13 +26,19 @@
 #parse( "azkaban/webapp/servlet/velocity/nav.vm" )
 		<div class="messaging"><p id="messageClose">X</p><p id="message"></p></div>  
 
-		<div class="content">
+		<div class="content history">
 			<div id="all-jobs-content">
 				<div class="section-hd">
 					<h2>History Timeline</h2>
 				</div>
 			</div>
-
+			<div id="historyTimeLine">
+				<div id="dayByDayPanel">
+					<svg id="dayGraph">
+						
+					</svg>
+				</div>
+			</div>
 		</div>
 	</body>
 </html>
\ No newline at end of file
diff --git a/src/web/css/azkaban.css b/src/web/css/azkaban.css
index 492768d..7dfc5a7 100644
--- a/src/web/css/azkaban.css
+++ b/src/web/css/azkaban.css
@@ -128,6 +128,10 @@ label.disabled {
   min-height: 150px;
 }
 
+.content.history {
+  min-height: 75px;
+}
+
 .section-ft {
   border-top: 1px solid #cdcdcd;
 }
@@ -2093,6 +2097,24 @@ span .nowrap {
 	margin-bottom: 5px;
 }
 
+#dayByDayPanel {
+	
+}
+
+#dayGraph {
+	background-color: #fff;
+}
+
+#historyTimeLine {
+	position: absolute;
+	top: 160px;
+	bottom: 5px;
+	left: 50px;
+	right: 50px;
+	padding: 10px;
+	background: #E0E0E0;
+}
+
 
 /* old styles */
 .azkaban-charts .hitarea {
diff --git a/src/web/js/azkaban.historyday.view.js b/src/web/js/azkaban.historyday.view.js
new file mode 100644
index 0000000..312ae40
--- /dev/null
+++ b/src/web/js/azkaban.historyday.view.js
@@ -0,0 +1,97 @@
+$.namespace('azkaban');
+
+var dayDataModel;
+azkaban.DayDataModel = Backbone.Model.extend({});
+
+var dayByDayView;
+azkaban.DayByDayView = Backbone.View.extend({
+	events: {
+	},
+	initialize: function(settings) {
+		this.svgns = "http://www.w3.org/2000/svg";
+		this.svg = $(this.el).find('svg')[0];
+		this.columnDayWidth = 100;
+		this.columnHourHeight = 50;
+		this.columnHeight = 50*24;
+		
+		this.render(this);
+	},http://documentcloud.github.com/backbone/#Events-trigger
+	prepareData: function(self) {
+		var response = model.get("data");
+		var start = data.start;
+		var end = data.end;
+		var data = data.data;
+		
+		var daysData = {};
+		
+		var startDate = new Date(start);
+		
+		while (startDate.getTime() < end) {
+			daysData[startDate.getTime()] = new Array();
+			startDate.setDate(startDate.getDate() + 1);
+		}
+		
+		for (var i = 0; i < data.length; ++i) {
+			var flow = data[i];
+			
+		}
+	},
+	render: function(self) {
+		var svg = self.svg;
+		var svgns = self.svgns;
+		var width = $(svg).width();
+		var height = $(svg).height();
+
+		var mainG = document.createElementNS(this.svgns, 'g');
+		$(svg).append(mainG);
+		
+		
+	}
+});
+
+var showDialog = function(title, message) {
+  $('#messageTitle').text(title);
+  $('#messageBox').text(message);
+
+  $('#messageDialog').modal({
+      closeHTML: "<a href='#' title='Close' class='modal-close'>x</a>",
+      position: ["20%",],
+      containerId: 'confirm-container',
+      containerCss: {
+        'height': '220px',
+        'width': '565px'
+      },
+      onShow: function (dialog) {
+      }
+    });
+}
+
+
+$(function() {
+	var requestURL = contextURL + "/history";
+
+	var start = new Date();
+	start.setHours(0);
+	start.setMinutes(0);
+	start.setSeconds(0);
+	start.setMilliseconds(0);
+	var end = new Date(start);
+
+	start.setDate(start.getDate() - 7);
+	console.log(start.getTime());
+
+	end.setDate(end.getDate() + 1);
+	console.log(end.getTime());
+
+	dayDataModel = new azkaban.DayDataModel();
+	dayByDayView = new azkaban.DayByDayView({el:$('#dayByDayPanel'), model: dayDataModel});
+
+	$.get(
+	      requestURL,
+	      {"ajax":"fetch", "start": start.getTime(), "end": end.getTime()},
+	      function(data) {
+			dayDataModel.set({data:data});
+		  },
+	      "json"
+	    );
+});