azkaban-uncached

Merge pull request #82 from davidzchen/bootstrap_ui Improve

12/18/2013 7:10:25 PM

Changes

src/tl/flowsummary.tl 293(+98 -195)

src/web/css/bootstrap-datetimepicker.min.css 9(+0 -9)

Details

diff --git a/src/java/azkaban/scheduler/ScheduleManager.java b/src/java/azkaban/scheduler/ScheduleManager.java
index 81c5c29..f0325af 100644
--- a/src/java/azkaban/scheduler/ScheduleManager.java
+++ b/src/java/azkaban/scheduler/ScheduleManager.java
@@ -104,7 +104,6 @@ public class ScheduleManager implements TriggerAgent {
 	
 	// only do this when using external runner
 	public synchronized void updateLocal() throws ScheduleManagerException {
-
 		List<Schedule> updates = loader.loadUpdatedSchedules();
 		for(Schedule s : updates) {
 			if(s.getStatus().equals(TriggerStatus.EXPIRED.toString())) {
@@ -157,15 +156,15 @@ public class ScheduleManager implements TriggerAgent {
 	 * @param id
 	 * @return
 	 * @throws ScheduleManagerException 
-	*/
+	 */
 //	public Set<Schedule> getSchedules(int projectId, String flowId) throws ScheduleManagerException {
 //		updateLocal();
 //		return scheduleIdentityPairMap.get(new Pair<Integer,String>(projectId, flowId));
 //	}
 	public Schedule getSchedule(int projectId, String flowId) throws ScheduleManagerException {
-	updateLocal();
-	return scheduleIdentityPairMap.get(new Pair<Integer,String>(projectId, flowId));
-}
+		updateLocal();
+		return scheduleIdentityPairMap.get(new Pair<Integer,String>(projectId, flowId));
+	}
 
 	/**
 	 * Returns the scheduled flow for the scheduleId
diff --git a/src/java/azkaban/webapp/AzkabanWebServer.java b/src/java/azkaban/webapp/AzkabanWebServer.java
index df2c02a..c24ea11 100644
--- a/src/java/azkaban/webapp/AzkabanWebServer.java
+++ b/src/java/azkaban/webapp/AzkabanWebServer.java
@@ -758,6 +758,7 @@ public class AzkabanWebServer extends AzkabanServer {
 		root.addServlet(staticServlet, "/css/*");
 		root.addServlet(staticServlet, "/js/*");
 		root.addServlet(staticServlet, "/images/*");
+		root.addServlet(staticServlet, "/fonts/*");
 		root.addServlet(staticServlet, "/favicon.ico");
 		
 		root.addServlet(new ServletHolder(new ProjectManagerServlet()),"/manager");
diff --git a/src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java b/src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java
index f7a5184..8ac470e 100644
--- a/src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java
+++ b/src/java/azkaban/webapp/servlet/AbstractAzkabanServlet.java
@@ -55,7 +55,7 @@ public abstract class AbstractAzkabanServlet extends HttpServlet {
 	public static final String XML_MIME_TYPE = "application/xhtml+xml";
 	public static final String JSON_MIME_TYPE = "application/json";
 
-	private static final WebUtils utils = new WebUtils();
+	protected static final WebUtils utils = new WebUtils();
 	
 	private AzkabanServer application;
 	private String name;
diff --git a/src/java/azkaban/webapp/servlet/LoginAbstractAzkabanServlet.java b/src/java/azkaban/webapp/servlet/LoginAbstractAzkabanServlet.java
index 5e0c67e..b48e2c9 100644
--- a/src/java/azkaban/webapp/servlet/LoginAbstractAzkabanServlet.java
+++ b/src/java/azkaban/webapp/servlet/LoginAbstractAzkabanServlet.java
@@ -64,6 +64,10 @@ public abstract class LoginAbstractAzkabanServlet extends AbstractAzkabanServlet
 		contextType.put(".jpeg", "image/jpeg");
 		contextType.put(".gif", "image/gif");
 		contextType.put(".jpg", "image/jpeg");
+		contextType.put(".eot", "application/vnd.ms-fontobject");
+		contextType.put(".svg", "image/svg+xml");
+		contextType.put(".ttf", "application/octet-stream");
+		contextType.put(".woff", "application/x-font-woff");
 	}
 	
 	private File webResourceDirectory = null;
@@ -121,10 +125,10 @@ public abstract class LoginAbstractAzkabanServlet extends AbstractAzkabanServlet
 		String prefix = req.getContextPath() + req.getServletPath();
 		String path = req.getRequestURI().substring(prefix.length());
 		int index = path.lastIndexOf('.');
-		if (index == -1 ) {
+		if (index == -1) {
 			return false;
 		}
-		
+
 		String extension = path.substring(index);
 		if (contextType.containsKey(extension)) {
 			File file = new File(webResourceDirectory, path);
diff --git a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
index ba37274..6099b5c 100644
--- a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
+++ b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
@@ -366,7 +366,8 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 					break;
 				}
 			}
-		} catch (ScheduleManagerException e) {
+		} 
+    catch (ScheduleManagerException e) {
 			// TODO Auto-generated catch block
 			throw new ServletException(e);
 		}
@@ -395,7 +396,8 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 		//project.info("Project removing by '" + user.getUserId() + "'");
 		try {
 			projectManager.removeProject(project, user);
-		} catch (ProjectManagerException e) {
+		} 
+    catch (ProjectManagerException e) {
 			this.setErrorMessageInCookie(resp, e.getMessage());
 			resp.sendRedirect(req.getRequestURI() + "?project=" + projectName);
 			return;
diff --git a/src/java/azkaban/webapp/servlet/ScheduleServlet.java b/src/java/azkaban/webapp/servlet/ScheduleServlet.java
index 566437d..c373608 100644
--- a/src/java/azkaban/webapp/servlet/ScheduleServlet.java
+++ b/src/java/azkaban/webapp/servlet/ScheduleServlet.java
@@ -102,19 +102,21 @@ public class ScheduleServlet extends LoginAbstractAzkabanServlet {
 		if (ajaxName.equals("slaInfo")) {
 			ajaxSlaInfo(req, ret, session.getUser());
 		}
-		else if(ajaxName.equals("setSla")) {
+		else if (ajaxName.equals("setSla")) {
 			ajaxSetSla(req, ret, session.getUser());
-		} else
-		if(ajaxName.equals("loadFlow")) {
+		} else if(ajaxName.equals("loadFlow")) {
 			ajaxLoadFlows(req, ret, session.getUser());
 		}
-		else if(ajaxName.equals("loadHistory")) {
+		else if (ajaxName.equals("loadHistory")) {
 			ajaxLoadHistory(req, resp, session.getUser());
 			ret = null;
 		}
-		else if(ajaxName.equals("scheduleFlow")) {
+		else if (ajaxName.equals("scheduleFlow")) {
 			ajaxScheduleFlow(req, ret, session.getUser());
 		}
+    else if (ajaxName.equals("fetchSchedule")) {
+      ajaxFetchSchedule(req, ret, session.getUser());
+    }
 
 		if (ret != null) {
 			this.writeJSON(resp, ret);
@@ -123,9 +125,7 @@ public class ScheduleServlet extends LoginAbstractAzkabanServlet {
 
 	private void ajaxSetSla(HttpServletRequest req, HashMap<String, Object> ret, User user) {
 		try {
-			
 			int scheduleId = getIntParam(req, "scheduleId");
-			
 			Schedule sched = scheduleManager.getSchedule(scheduleId);
 			
 			Project project = projectManager.getProject(sched.getProjectId());
@@ -231,14 +231,38 @@ public class ScheduleServlet extends LoginAbstractAzkabanServlet {
 		int min = Integer.parseInt(duration.split(":")[1]);
 		return Minutes.minutes(min+hour*60).toPeriod();
 	}
-
+  
+  private void ajaxFetchSchedule(HttpServletRequest req, 
+      HashMap<String, Object> ret, User user) throws ServletException {
+		
+		int projectId = getIntParam(req, "projectId");
+	  String flowId = getParam(req, "flowId");	
+		try {
+      Schedule schedule = scheduleManager.getSchedule(
+					projectId, flowId);
+    
+			if (schedule != null) {
+				Map<String, String> jsonObj = new HashMap<String, String>();
+				jsonObj.put("scheduleId", Integer.toString(schedule.getScheduleId()));
+				jsonObj.put("submitUser", schedule.getSubmitUser());
+				jsonObj.put("firstSchedTime", 
+						utils.formatDateTime(schedule.getFirstSchedTime()));
+				jsonObj.put("nextExecTime", 
+						utils.formatDateTime(schedule.getNextExecTime()));
+				jsonObj.put("period", utils.formatPeriod(schedule.getPeriod()));
+				ret.put("schedule", jsonObj);
+			}
+		}
+    catch (ScheduleManagerException e) {
+      ret.put("error", e);
+		}
+	}
+	
 	private void ajaxSlaInfo(HttpServletRequest req, HashMap<String, Object> ret, User user) {
 		int scheduleId;
 		try {
 			scheduleId = getIntParam(req, "scheduleId");
-			
 			Schedule sched = scheduleManager.getSchedule(scheduleId);
-			
 			Project project = getProjectAjaxByPermission(ret, sched.getProjectId(), user, Type.READ);
 			if (project == null) {
 				ret.put("error", "Error loading project. Project " + sched.getProjectId() + " doesn't exist");
@@ -300,7 +324,6 @@ public class ScheduleServlet extends LoginAbstractAzkabanServlet {
 		} catch (ScheduleManagerException e) {
 			ret.put("error", e);
 		}
-		
 	}
 
 	protected Project getProjectAjaxByPermission(Map<String, Object> ret, int projectId, User user, Permission.Type type) {
@@ -318,7 +341,7 @@ public class ScheduleServlet extends LoginAbstractAzkabanServlet {
 		
 		return null;
 	}
-	
+
 	private void handleGetAllSchedules(HttpServletRequest req, HttpServletResponse resp,
 			Session session) throws ServletException, IOException{
 		
@@ -371,7 +394,7 @@ public class ScheduleServlet extends LoginAbstractAzkabanServlet {
 				if (action.equals("scheduleFlow")) {
 					ajaxScheduleFlow(req, ret, session.getUser());
 				}
-				else if(action.equals("removeSched")){
+				else if (action.equals("removeSched")){
 					ajaxRemoveSched(req, ret, session.getUser());
 				}
 			}
@@ -384,9 +407,8 @@ public class ScheduleServlet extends LoginAbstractAzkabanServlet {
 			this.writeJSON(resp, ret);
 		}
 	}
-
+	
 	private void ajaxLoadFlows(HttpServletRequest req, HashMap<String, Object> ret, User user) throws ServletException {
-		
 		List<Schedule> schedules;
 		try {
 			schedules = scheduleManager.getSchedules();
diff --git a/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm b/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
index 891f19c..17c197f 100644
--- a/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
@@ -21,7 +21,8 @@
 #parse("azkaban/webapp/servlet/velocity/style.vm")
 #parse("azkaban/webapp/servlet/velocity/javascript.vm")
 
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-1.10.1.custom.js"></script>
+		<script type="text/javascript" src="${context}/js/moment.min.js"></script>
+		<script type="text/javascript" src="${context}/js/bootstrap-datetimepicker.min.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.common.utils.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.date.utils.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.context.menu.js"></script>
@@ -44,7 +45,7 @@
 			var execId = "${execid}";
 		</script>
 		<link rel="stylesheet" type="text/css" href="${context}/css/azkaban-svg.css">
-		<link rel="stylesheet" type="text/css" href="${context}/css/jquery-ui-1.10.1.custom.css">
+		<link rel="stylesheet" type="text/css" href="${context}/css/bootstrap-datetimepicker.css" />
 	</head>
 	<body>
 
@@ -79,59 +80,54 @@
 	## Page header
 
 		<div class="az-page-header">
-			<div class="container">
-				<h1>
-					<a href="${context}/executor?execid=${execid}">Flow Execution <small>$execid</small></a>
-				</h1>
+			<div class="container" id="flow-status">
+        <div class="row">
+          <div class="col-lg-7">
+            <h1>
+              <a href="${context}/executor?execid=${execid}">
+                Flow Execution <small>$execid <span id="flowStatus">-</span></small>
+              </a>
+            </h1>
+          </div>
+          <div class="col-lg-5">
+            <div class="az-exflow-stats">
+              <div class="col-md-5">
+                <p><strong>Submit User</strong> <span id="submitUser">-</span></p>
+                <p><strong>Duration</strong> <span id="duration">-</span></p>
+              </div>
+              <div class="col-md-7">
+                <p><strong>Start Time</strong> <span id="startTime">-</span></p>
+                <p><strong>End Time</strong> <span id="endTime">-</span></p>
+              </div>
+            </div>
+            <div class="clearfix"></div>
+          </div>
+        </div>
 			</div>
 		</div>
 
 		<div class="container">
 
 	## Breadcrumb
+
 			<ol class="breadcrumb">
 				<li><a href="${context}/manager?project=${projectName}"><strong>Project</strong> $projectName</a></li>
 				<li><a href="${context}/manager?project=${projectName}&flow=${flowid}"><strong>Flow</strong> $flowid</a></li>
 				<li class="active"><strong>Execution</strong> $execid</li>
 			</ol>
 		
-	## Flow status
-			
-			<div class="well">
-				<div class="row" id="flow-status">
-					<div class="col-lg-6">
-						<p><strong>Status</strong> <span id="flowStatus">-</span></p>
-						<p><strong>Submit User</strong> <span id="submitUser">-</span></p>
-					</div>
-					<div class="col-lg-6">
-						<p><strong>Start Time</strong> <span id="startTime">-</span></p>
-						<p><strong>End Time</strong> <span id="endTime">-</span></p>
-						<p><strong>Duration</strong> <span id="duration">-</span></p>
-					</div>
-				</div>
-			</div>
-
 	## Tabs and buttons.
 
-			<div class="row" id="headertabs">
-				<div class="col-lg-8">
-					<ul class="nav nav-pills">
-						<li id="graphViewLink"><a href="#graph">Graph</a></li>
-						<li id="jobslistViewLink"><a href="#jobslist">Job List</a></li>
-						<li id="flowLogViewLink"><a href="#log">Flow Log</a></li>
-					</ul>
-				</div>
-				<div class="col-lg-4">
-					<div class="pull-right">
-						<button type="button" id="pausebtn" class="btn btn-primary">Pause</button>
-						<button type="button" id="resumebtn" class="btn btn-primary">Resume</button>
-						<button type="button" id="cancelbtn" class="btn btn-danger">Cancel</button>
-						<button type="button" id="retrybtn" class="btn btn-success">Retry Failed</button>
-						<button type="button" id="executebtn" class="btn btn-success">Prepare Execution</button>
-					</div>
-					<div class="clearfix"></div>
-				</div>
-			</div>
+			<ul class="nav nav-tabs" id="headertabs">
+				<li id="graphViewLink"><a href="#graph">Graph</a></li>
+				<li id="jobslistViewLink"><a href="#jobslist">Job List</a></li>
+				<li id="flowLogViewLink"><a href="#log">Flow Log</a></li>
+				<li class="nav-button pull-right"><button type="button" id="pausebtn" class="btn btn-primary">Pause</button></li>
+				<li class="nav-button pull-right"><button type="button" id="resumebtn" class="btn btn-primary">Resume</button></li>
+				<li class="nav-button pull-right"><button type="button" id="cancelbtn" class="btn btn-danger">Cancel</button></li>
+				<li class="nav-button pull-right"><button type="button" id="retrybtn" class="btn btn-success">Retry Failed</button></li>
+				<li class="nav-button pull-right"><button type="button" id="executebtn" class="btn btn-success">Prepare Execution</button></li>
+			</ul>
 
 	## Graph View
 
diff --git a/src/java/azkaban/webapp/servlet/velocity/executionspage.vm b/src/java/azkaban/webapp/servlet/velocity/executionspage.vm
index 883344b..8f69701 100644
--- a/src/java/azkaban/webapp/servlet/velocity/executionspage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/executionspage.vm
@@ -21,6 +21,7 @@
 #parse("azkaban/webapp/servlet/velocity/style.vm")
 #parse("azkaban/webapp/servlet/velocity/javascript.vm")
 	
+		<script type="text/javascript" src="${context}/js/azkaban.executions.view.js"></script>
 		<script type="text/javascript">
 			var contextURL = "${context}";
 			var currentTime = ${currentTime};
@@ -55,104 +56,102 @@
 ## Page Content
 
 		<div class="container">
-			<div class="row">
+      <ul class="nav nav-tabs" id="header-tabs">
+        <li id="currently-running-view-link"><a href="#currently-running">Currently Running</a></li>
+        <li id="recently-finished-view-link"><a href="#recently-finished">Recently Finished</a></li>
+      </ul>
+
+			<div class="row" id="currently-running-view">
 				<div class="col-lg-12">
-					<div class="panel panel-default">
-						<div class="panel-heading">Currently Running Jobs</div>
-						<table id="executingJobs" class="table table-striped table-bordered table-hover table-condensed executions-table">
-							<thead>
-								<tr>
-									<th class="execid">Execution Id</th>
-									<th>Flow</th>
-									<th>Project</th>
-									<th class="user">User</th>
-									<th class="user">Proxy User</th>
-									<th class="date">Start Time</th>
-									<th class="date">End Time</th>
-									<th class="elapse">Elapsed</th>
-									<th class="status">Status</th>
-									<th class="action">Action</th>
-								</tr>
-							</thead>
-							<tbody>
+          <table id="executingJobs" class="table table-striped table-bordered table-hover table-condensed executions-table">
+            <thead>
+              <tr>
+                <th class="execid">Execution Id</th>
+                <th>Flow</th>
+                <th>Project</th>
+                <th class="user">User</th>
+                <th class="user">Proxy User</th>
+                <th class="date">Start Time</th>
+                <th class="date">End Time</th>
+                <th class="elapse">Elapsed</th>
+                <th class="status">Status</th>
+                <th class="action">Action</th>
+              </tr>
+            </thead>
+            <tbody>
 #if ($runningFlows)
 	#foreach ($flow in $runningFlows)
-								<tr class="row" >
-									<td class="tb-name">
-										<a href="${context}/executor?execid=${flow.executionId}">${flow.executionId}</a>
-									</td>
-									<td><a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})&flow=${flow.flowId}">${flow.flowId}</a></td>
-									<td>
-										<a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})">$vmutils.getProjectName(${flow.projectId})</a>
-									</td>
-									<td>${flow.submitUser}</td>
-									<td>${flow.proxyUsers}</td>
-									<td>$utils.formatDate(${flow.startTime})</td>
-									<td>$utils.formatDate(${flow.endTime})</td>
-									<td>$utils.formatDuration(${flow.startTime}, ${flow.endTime})</td>
-									<td><div class="status ${flow.status}">$utils.formatStatus(${flow.status})</div></td>
-									<td></td>
-								</tr>
+              <tr>
+                <td class="tb-name">
+                  <a href="${context}/executor?execid=${flow.executionId}">${flow.executionId}</a>
+                </td>
+                <td><a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})&flow=${flow.flowId}">${flow.flowId}</a></td>
+                <td>
+                  <a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})">$vmutils.getProjectName(${flow.projectId})</a>
+                </td>
+                <td>${flow.submitUser}</td>
+                <td>${flow.proxyUsers}</td>
+                <td>$utils.formatDate(${flow.startTime})</td>
+                <td>$utils.formatDate(${flow.endTime})</td>
+                <td>$utils.formatDuration(${flow.startTime}, ${flow.endTime})</td>
+                <td><div class="status ${flow.status}">$utils.formatStatus(${flow.status})</div></td>
+                <td></td>
+              </tr>
 	#end
 #else
-								<tr>
-									<td colspan="10">No Executing Flows</td>
-								</tr>
+              <tr>
+                <td colspan="10">No Executing Flows</td>
+              </tr>
 #end
-							</tbody>
-						</table>
-					</div><!-- /panel -->
+            </tbody>
+          </table>
 				</div><!-- /col-lg-12 -->
 			</div><!-- /row -->
 
-			<div class="row">
+			<div class="row" id="recently-finished-view">
 				<div class="col-lg-12">
-					<div class="panel panel-default">
-						<div class="panel-heading">Recently Finished Jobs</div>
-						<table id="recentlyFinished" class="table table-striped table-bordered table-hover table-condensed executions-table">
-							<thead>
-								<tr>
-									<th class="execid">Execution Id</th>
-									<th>Flow</th>
-									<th>Project</th>
-									<th class="user">User</th>
-									<th class="user">Proxy User</th>
-									<th class="date">Start Time</th>
-									<th class="date">End Time</th>
-									<th class="elapse">Elapsed</th>
-									<th class="status">Status</th>
-									<th class="action">Action</th>
-								</tr>
-							</thead>
-							<tbody>
+          <table id="recentlyFinished" class="table table-striped table-bordered table-hover table-condensed executions-table">
+            <thead>
+              <tr>
+                <th class="execid">Execution Id</th>
+                <th>Flow</th>
+                <th>Project</th>
+                <th class="user">User</th>
+                <th class="user">Proxy User</th>
+                <th class="date">Start Time</th>
+                <th class="date">End Time</th>
+                <th class="elapse">Elapsed</th>
+                <th class="status">Status</th>
+                <th class="action">Action</th>
+              </tr>
+            </thead>
+            <tbody>
 #if ($recentlyFinished.isEmpty())
 	#foreach ($flow in $recentlyFinished)
-								<tr class="row" >
-									<td class="tb-name execId">
-										<a href="${context}/executor?execid=${flow.executionId}">${flow.executionId}</a>
-									</td>
-									<td><a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})&flow=${flow.flowId}">${flow.flowId}</a></td>
-									<td>
-										<a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})">$vmutils.getProjectName(${flow.projectId})</a>
-									</td>
-									<td>${flow.submitUser}</td>
-									<td>${flow.proxyUsers}</td>
-									<td>$utils.formatDate(${flow.startTime})</td>
-									<td>$utils.formatDate(${flow.endTime})</td>
-									<td>$utils.formatDuration(${flow.startTime}, ${flow.endTime})</td>
-									<td><div class="status ${flow.status}">$utils.formatStatus(${flow.status})</div></td>
-									<td></td>
-								</tr>
+              <tr>
+                <td class="tb-name execId">
+                  <a href="${context}/executor?execid=${flow.executionId}">${flow.executionId}</a>
+                </td>
+                <td><a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})&flow=${flow.flowId}">${flow.flowId}</a></td>
+                <td>
+                  <a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})">$vmutils.getProjectName(${flow.projectId})</a>
+                </td>
+                <td>${flow.submitUser}</td>
+                <td>${flow.proxyUsers}</td>
+                <td>$utils.formatDate(${flow.startTime})</td>
+                <td>$utils.formatDate(${flow.endTime})</td>
+                <td>$utils.formatDuration(${flow.startTime}, ${flow.endTime})</td>
+                <td><div class="status ${flow.status}">$utils.formatStatus(${flow.status})</div></td>
+                <td></td>
+              </tr>
 	#end
 #else
-								<tr>
-									<td colspan="10">No Recently Finished</td>
-								</tr>
+              <tr>
+                <td colspan="10">No Recently Finished</td>
+              </tr>
 #end	
-							</tbody>
-						</table>
-					</div><!-- /panel -->
-
+            </tbody>
+          </table>
 				</div><!-- /col-lg-12 -->
 			</div><!-- /row -->
 		
diff --git a/src/java/azkaban/webapp/servlet/velocity/flowpage.vm b/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
index cb48fbc..376d30c 100644
--- a/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
@@ -21,10 +21,12 @@
 #parse("azkaban/webapp/servlet/velocity/style.vm")
 #parse("azkaban/webapp/servlet/velocity/javascript.vm")
 
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-1.10.1.custom.js"></script>
+		<script type="text/javascript" src="${context}/js/moment.min.js"></script>
+		<script type="text/javascript" src="${context}/js/bootstrap-datetimepicker.min.js"></script>
 		
-		<script type="text/javascript" src="${context}/js/dust-core-2.2.2.min.js"></script>
+    <script type="text/javascript" src="${context}/js/dust-core-2.2.2.min.js"></script>
 		<script type="text/javascript" src="${context}/js/flowsummary.js"></script>
+
 		<script type="text/javascript" src="${context}/js/azkaban.date.utils.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.ajax.utils.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.common.utils.js"></script>
@@ -46,7 +48,7 @@
 			var execId = null;
 		</script>
 		<link rel="stylesheet" type="text/css" href="${context}/css/azkaban-svg.css" />
-		<link rel="stylesheet" type="text/css" href="${context}/css/jquery-ui-1.10.1.custom.css" />
+		<link rel="stylesheet" type="text/css" href="${context}/css/bootstrap-datetimepicker.css" />
 	</head>
 	<body>
 
@@ -83,8 +85,17 @@
 
 		<div class="az-page-header">
 			<div class="container">
-        <h1><a href="${context}/manager?project=${project.name}&flow=${flowid}">Flow <small>$flowid</small></a></h1>
-				<p>$project.description</p>
+				<div class="row">
+					<div class="col-lg-6">
+						<h1><a href="${context}/manager?project=${project.name}&flow=${flowid}">Flow <small>$flowid</small></a></h1>
+					</div>
+					<div class="col-lg-6">
+						<div class="pull-right az-page-header-form">
+							<button type="button" class="btn btn-success" id="executebtn">Schedule / Execute Flow</button>
+						</div>
+						<div class="clearfix"></div>
+					</div>
+				</div>
 			</div>
 		</div>
 
@@ -96,21 +107,11 @@
         <li class="active"><strong>Flow</strong> $flowid</li>
       </ol>
 
-			<div class="row">
-				<div class="col-lg-8">
-					<ul class="nav nav-pills" id="headertabs">
-						<li id="graphViewLink"><a href="#graph">Graph</a></li>
-						<li id="executionsViewLink"><a href="#executions">Executions</a></li>
-						<li id="summaryViewLink"><a href="#summary">Summary</a></li>
-					</ul>
-				</div>
-				<div class="col-lg-4">
-					<div class="pull-right">
-						<button type="button" class="btn btn-success" id="executebtn">Schedule / Execute Flow</button>
-					</div>
-					<div class="clearfix"></div>
-				</div>
-			</div>
+			<ul class="nav nav-tabs" id="headertabs">
+				<li id="graphViewLink"><a href="#graph">Graph</a></li>
+				<li id="executionsViewLink"><a href="#executions">Executions</a></li>
+				<li id="summaryViewLink"><a href="#summary">Summary</a></li>
+			</ul>
 					
 	## Graph view.
 
@@ -120,7 +121,7 @@
 
 			<div class="row" id="executionsView">
 				<div class="col-lg-12">
-					<table class="table table-striped table-bordered" id="execTable">
+					<table class="table table-striped table-bordered table-condensed table-hover" id="execTable">
 						<thead>
 							<tr>
 								<th>Execution Id</th>
@@ -146,12 +147,10 @@
 					</ul>
 				</div>
 			</div>
-		
+
 	## Summary view.
 
-			<div class="row">
-				<div class="col-lg-12" id="summaryView">
-				</div>
+			<div class="row" id="summaryView">
 			</div><!-- /#summaryView -->
 
 			<div id="contextMenu">
diff --git a/src/java/azkaban/webapp/servlet/velocity/historypage.vm b/src/java/azkaban/webapp/servlet/velocity/historypage.vm
index bb85769..a0fe2b9 100644
--- a/src/java/azkaban/webapp/servlet/velocity/historypage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/historypage.vm
@@ -21,12 +21,10 @@
 #parse("azkaban/webapp/servlet/velocity/style.vm")
 #parse("azkaban/webapp/servlet/velocity/javascript.vm")
 
-		<link rel="stylesheet" type="text/css" href="${context}/css/jquery-ui-1.10.1.custom.css" />
-		<link rel="stylesheet" type="text/css" href="${context}/css/jquery-ui-timepicker-addon.css" />
+		<link rel="stylesheet" type="text/css" href="${context}/css/bootstrap-datetimepicker.css" />
 
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-1.10.1.custom.js"></script>
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-timepicker-addon.js"></script> 
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-sliderAccess.js"></script>
+		<script type="text/javascript" src="${context}/js/moment.min.js"></script>
+		<script type="text/javascript" src="${context}/js/bootstrap-datetimepicker.min.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.history.view.js"></script>
 		<script type="text/javascript">
 			var contextURL = "${context}";
@@ -70,74 +68,76 @@
 ## Page header.
 
 		<div class="az-page-header">
-			<div class="container">
-				<h1>History</h1>
+      <div class="container">
+        <div class="row">
+          <div class="col-lg-6">
+            <h1>History</h1>
+          </div>
+          <div class="col-lg-6">
+            <form id="search-form" method="get" class="form-inline az-page-header-form" role="form">
+              <input type="hidden" name="search" value="true">
+              <div class="form-group">
+                <div class="input-group">
+                  <input type="text" id="searchtextbox" placeholder="flow name containing ..." value=#if($search_term) ${search_term} #else "" #end class="form-control input-sm" name="searchterm">
+                  <span class="input-group-btn">
+                    <button class="btn btn-primary btn-sm">Quick Search</button>
+                    <button type="button" class="btn btn-success btn-sm" id="adv-filter-btn">Advanced Filter</button>
+                  </span>
+                </div>
+              </div>
+            </form>
+          </div>
+        </div>
 			</div>
 		</div>
 
 		<div class="container">
 			<div class="row">
 				<div class="col-lg-12">
-					<div class="panel panel-default">
-						<div class="panel-heading">
-							<form id="search-form" method="get" class="form-inline" role="form">
-								<input type="hidden" name="search" value="true">
-								<div class="form-group">
-									<div class="input-group">
-										<input type="text" id="searchtextbox" placeholder="flow name containing ..." value=#if($search_term) ${search_term} #else "" #end class="form-control" name="searchterm">
-										<span class="input-group-btn">
-											<button class="btn btn-primary">Quick Search</button>
-											<button type="button" class="btn btn-success" id="adv-filter-btn">Advanced Filter</button>
-										</span>
-									</div>
-								</div>
-							</form>
-						</div>
-						<table id="executingJobs" class="table table-striped table-bordered table-hover table-condensed executions-table">
-							<thead>
-								<tr>
-									<th class="execid">Execution Id</th>
-									<th>Flow</th>
-									<th>Project</th>
-									<th>User</th>
-									<th class="date">Start Time</th>
-									<th class="date">End Time</th>
-									<th class="elapse">Elapsed</th>
-									<th class="status">Status</th>
-									<th class="action">Action</th>
-								</tr>
-							</thead>
-							<tbody>
+          <table id="executingJobs" class="table table-striped table-bordered table-hover table-condensed executions-table">
+            <thead>
+              <tr>
+                <th class="execid">Execution Id</th>
+                <th>Flow</th>
+                <th>Project</th>
+                <th>User</th>
+                <th class="date">Start Time</th>
+                <th class="date">End Time</th>
+                <th class="elapse">Elapsed</th>
+                <th class="status">Status</th>
+                <th class="action">Action</th>
+              </tr>
+            </thead>
+            <tbody>
 #if (!$flowHistory.isEmpty())
 	#foreach ($flow in $flowHistory)
-								<tr>
-									<td class="tb-name execId">
-										<a href="${context}/executor?execid=${flow.executionId}">${flow.executionId}</a>
-									</td>
-									<td class="tb-name">
-										<a href="${context}/executor?execid=${flow.executionId}">${flow.flowId}</a>
-									</td>
-									<td>
-										<a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})">$vmutils.getProjectName(${flow.projectId})</a>
-									</td>
-									<td>${flow.submitUser}</td>
-									<td>$utils.formatDate(${flow.startTime})</td>
-									<td>$utils.formatDate(${flow.endTime})</td>
-									<td>$utils.formatDuration(${flow.startTime}, ${flow.endTime})</td>
-									<td>
-										<div class="status ${flow.status}">$utils.formatStatus(${flow.status})</div>
-									</td>
-									<td></td>
-								</tr>
+              <tr>
+                <td class="tb-name execId">
+                  <a href="${context}/executor?execid=${flow.executionId}">${flow.executionId}</a>
+                </td>
+                <td class="tb-name">
+                  <a href="${context}/executor?execid=${flow.executionId}">${flow.flowId}</a>
+                </td>
+                <td>
+                  <a href="${context}/manager?project=$vmutils.getProjectName(${flow.projectId})">$vmutils.getProjectName(${flow.projectId})</a>
+                </td>
+                <td>${flow.submitUser}</td>
+                <td>$utils.formatDate(${flow.startTime})</td>
+                <td>$utils.formatDate(${flow.endTime})</td>
+                <td>$utils.formatDuration(${flow.startTime}, ${flow.endTime})</td>
+                <td>
+                  <div class="status ${flow.status}">$utils.formatStatus(${flow.status})</div>
+                </td>
+                <td></td>
+              </tr>
 	#end
 #else
-								<tr>
-									<td class="last" colspan="9">No History Results Found</td>
-								</tr>
+              <tr>
+                <td class="last" colspan="9">No History Results Found</td>
+              </tr>
 #end
-							</tbody>
-						</table>
-					</div><!-- /panel -->
+            </tbody>
+          </table>
 					<ul class="pagination" id="pageSelection">
 #if ($search)
 						<li id="previous" class="first"><a href="${context}/history?page=${previous.page}&size=${previous.size}&search=true&searchterm=${search_term}"><span class="arrow">&larr;</span>Previous</a></li>
diff --git a/src/java/azkaban/webapp/servlet/velocity/index.vm b/src/java/azkaban/webapp/servlet/velocity/index.vm
index 3b99772..768f6ea 100644
--- a/src/java/azkaban/webapp/servlet/velocity/index.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/index.vm
@@ -59,12 +59,41 @@
 ## Page Header and project search form.
 
 		<div class="az-page-header">
-			<div class="container">
+      <div class="container">
+        <div class="row">
+          <div class="col-lg-6">
 #if ($allProjects)
-				<h1>All Projects</h1>
+            <h1>All Projects</h1>
 #else
-				<h1>My Projects</h1>
+            <h1>My Projects</h1>
 #end
+          </div>
+          <div class="col-lg-6">
+            <form id="search-form" method="get" class="form-inline az-page-header-form" role="form">
+              <input type="hidden" name="doaction" value="search">
+#if ($allProjects)
+              <input type="hidden" name="all" value="true">				
+#end
+              <div class="form-group col-md-9">
+                <div class="input-group">
+                  <input id="search-textbox" type="text" placeholder="Project name containing..." value=#if($search_term) ${search_term} #else "" #end class="form-control input-sm" name="searchterm">
+                  <span class="input-group-btn">
+                    <button class="btn btn-sm btn-primary">Quick Search</button>
+                  </span>
+                </div>
+              </div>
+#if (!$hideCreateProject)
+              <div class="form-group col-md-3" id="create-project">
+## Note: The Create Project button is not completely flush to the right because
+## form-group has padding.
+                <div class="pull-right">
+                  <button type="button" id="create-project-btn" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-plus"></span> Create Project</button>
+                </div>
+              </div>
+#end
+            </form>
+          </div>
+        </div>
 			</div>
 		</div>
 
@@ -73,71 +102,46 @@
 		<div class="container">
 			<div class="row">
 				<div class="col-lg-12">
-					<div class="panel panel-default">
-						<div class="panel-heading">
-							<form id="search-form" method="get" class="form-inline" role="form">
-								<fieldset>
-									<input type="hidden" name="doaction" value="search">
-#if ($allProjects)
-									<input type="hidden" name="all" value="true">				
-#end
-									<div class="form-group col-md-10">
-										<div class="input-group">
-											<input id="search-textbox" type="text" placeholder="Project name containing..." value=#if($search_term) ${search_term} #else "" #end class="form-control" name="searchterm">
-											<span class="input-group-btn">
-												<button class="btn btn-primary">Quick Search</button>
-											</span>
-										</div>
-									</div>
-#if (!$hideCreateProject)
-									<div class="form-group col-md-2" id="create-project">
-										<button type="button" id="create-project-btn" class="btn btn-success"><span class="glyphicon glyphicon-plus"></span> Create Project</button>
-									</div>
-#end
-								</fieldset>
-							</form>
-						</div>
-						<table class="table table-striped table-bordered table-hover" id="all-jobs">
-							<thead>
-								<tr>
-									<th class="tb-name">Name</th>
-									<th class="tb-up-date">Modified Date</th>
-									<th class="tb-owner">Modified By</th>
-								</tr>
-							</thead>
-							<tbody>
+          <table class="table table-condensed table-striped table-bordered table-hover" id="all-jobs">
+            <thead>
+              <tr>
+                <th class="tb-name">Name</th>
+                <th class="tb-up-date">Modified Date</th>
+                <th class="tb-owner">Modified By</th>
+              </tr>
+            </thead>
+            <tbody>
 #if(!$projects.isEmpty())
 	#foreach($project in $projects)
-								<tr>
-									<td id="${project.name}" class="tb-name project-expand expanded">
-										<span class="glyphicon glyphicon-plus"></span>
-										<a href="${context}/manager?project=${project.name}">$project.name</a>
-									</td>
-									<td class="tb-up-date">$utils.formatDate($project.lastModifiedTimestamp)</td>
-									<td class="tb-owner">$project.lastModifiedUser</td>
-								</tr>
-								<tr class="childrow collapse" id="${project.name}-child">
-									<td colspan="3">
-										<table class="table table-bordered">
-											<thead>
-												<tr>
-													<th class="tb-name">Flows</th>
-												</tr>
-											</thead>
-											<tbody id="${project.name}-tbody">
-											</tbody>
-										</table>
-									</td>
-								</tr>
+              <tr class="az-project-row">
+                <td id="${project.name}" class="tb-name project-expand expanded">
+                  <span class="glyphicon glyphicon-chevron-down az-expander"></span>
+                  <a href="${context}/manager?project=${project.name}">$project.name</a>
+                </td>
+                <td class="tb-up-date">$utils.formatDate($project.lastModifiedTimestamp)</td>
+                <td class="tb-owner">$project.lastModifiedUser</td>
+              </tr>
+              <tr class="childrow collapse" id="${project.name}-child">
+                <td colspan="3">
+                  <table class="table table-bordered">
+                    <thead>
+                      <tr>
+                        <th class="tb-name">Flows</th>
+                      </tr>
+                    </thead>
+                    <tbody id="${project.name}-tbody">
+                    </tbody>
+                  </table>
+                </td>
+              </tr>
 	#end
 #else
-								<tr>
-									<td colspan="3">No viewable projects found.</td>
-								</tr>
+              <tr>
+                <td colspan="3">No viewable projects found.</td>
+              </tr>
 #end
-							</tbody>
-						</table>
-					</div>
+            </tbody>
+          </table>
 				</div>
 			</div>
 
diff --git a/src/java/azkaban/webapp/servlet/velocity/jobdetailspage.vm b/src/java/azkaban/webapp/servlet/velocity/jobdetailspage.vm
index 639a70e..8977276 100644
--- a/src/java/azkaban/webapp/servlet/velocity/jobdetailspage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/jobdetailspage.vm
@@ -66,7 +66,16 @@
 
 		<div class="az-page-header">
 			<div class="container">
-				<h1><a href="${context}/executor?execid=${execid}&job=${jobid}">Job Execution <small>$jobid</small></a></h1>
+				<div class="row">
+					<div class="col-lg-6">
+						<h1><a href="${context}/executor?execid=${execid}&job=${jobid}">Job Execution <small>$jobid</small></a></h1>
+					</div>
+					<div class="col-lg-6">
+						<div class="pull-right az-page-header-form">
+							<a href="${context}/manager?project=${projectName}&flow=${flowid}&job=$jobid" class="btn btn-default">Job Properties</a>
+						</div>
+					</div>
+				</div>
 			</div>
 		</div>
 	
@@ -80,21 +89,11 @@
         <li class="active"><strong>Job</strong> $jobid</li>
 			</ol>
 			
-      <div class="row">
-				<div class="col-lg-8">
-					<ul class="nav nav-pills" id="headertabs">
-            <li id="jobSummaryViewLink"><a href="#jobsummary">Summary</a></li>
-            <li id="jobLogViewLink"><a href="#joblog">Log</a></li>
-            <li><a href="${context}/pigvisualizer?execid=${execid}&jobid=${jobid}">Visualization</a></li>
-					</ul>
-				</div>
-				<div class="col-lg-4">
-					<div class="pull-right">
-            <a href="${context}/manager?project=${projectName}&flow=${flowid}&job=$jobid" class="btn btn-default">Job Properties</a>
-					</div>
-					<div class="clearfix"></div>
-				</div>
-			</div>
+			<ul class="nav nav-tabs" id="headertabs">
+				<li id="jobSummaryViewLink"><a href="#jobsummary">Summary</a></li>
+				<li id="jobLogViewLink"><a href="#joblog">Log</a></li>
+				<li><a href="${context}/pigvisualizer?execid=${execid}&jobid=${jobid}">Visualization</a></li>
+			</ul>
 
 	## Log content.
 
@@ -115,6 +114,7 @@
 			</div>
 
 	## Job Summary
+
 			<div id="jobSummaryView" class="row">
 				<div class="col-lg-12">
 					<table id="commandTable" class="table table-striped table-bordered table-hover">
diff --git a/src/java/azkaban/webapp/servlet/velocity/jobnav.vm b/src/java/azkaban/webapp/servlet/velocity/jobnav.vm
index bb27f16..70f974e 100644
--- a/src/java/azkaban/webapp/servlet/velocity/jobnav.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/jobnav.vm
@@ -14,7 +14,7 @@
  * the License.
 *#
 	
-					<ul class="nav nav-pills">
+					<ul class="nav nav-tabs">
 						<li#if($job_page == 'properties') class="active"#end><a href="${context}/manager?project=${project.name}&flow=${flowid}&job=${jobid}">Job</a></li>
 						<li#if($job_page == 'history') class="active"#end><a id="jobs-logs-btn" href="${context}/manager?project=${project.name}&job=$jobid&history">History</a></li>
 					</ul>
diff --git a/src/java/azkaban/webapp/servlet/velocity/jobpage.vm b/src/java/azkaban/webapp/servlet/velocity/jobpage.vm
index fc2c378..0326037 100644
--- a/src/java/azkaban/webapp/servlet/velocity/jobpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/jobpage.vm
@@ -21,8 +21,6 @@
 #parse ("azkaban/webapp/servlet/velocity/style.vm")
 #parse ("azkaban/webapp/servlet/velocity/javascript.vm")
 
-		<link rel="stylesheet" type="text/css" href="${context}/css/jquery-ui-1.10.1.custom.css" />
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-1.10.1.custom.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.jobedit.view.js"></script>
 		<script type="text/javascript">
 			var contextURL = "${context}";
diff --git a/src/java/azkaban/webapp/servlet/velocity/login.vm b/src/java/azkaban/webapp/servlet/velocity/login.vm
index 84b5e89..bb8968b 100644
--- a/src/java/azkaban/webapp/servlet/velocity/login.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/login.vm
@@ -28,12 +28,12 @@
   </head>
   <body>
 
-#set ($current_page="all")
-#set ($navbar_disabled=1)
+#set ($current_page = "all")
+#set ($navbar_disabled = 1)
 #parse ("azkaban/webapp/servlet/velocity/nav.vm")
 
 		<div class="container">
-			<div class="row">
+			<div class="row az-login">
 				<div class="col-lg-4">
 				</div>
 				<div class="col-lg-4">
diff --git a/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm b/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm
index 1106a2b..edd848d 100644
--- a/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm
@@ -22,6 +22,7 @@
 #parse ("azkaban/webapp/servlet/velocity/javascript.vm")
 
 		<script type="text/javascript" src="${context}/js/azkaban.permission.view.js"></script>
+		<script type="text/javascript" src="${context}/js/azkaban.projectmodals.view.js"></script>
 		<script type="text/javascript">
 			var contextURL = "${context}";
 			var currentTime = ${currentTime};
@@ -63,192 +64,193 @@
 			</div>
 		</div>
 
-		<div class="az-page-header">
-			<div class="container">
-				<h1><a href="${context}/manager?project=${project.name}">Project <small>$project.name</small></a></h1>
-				<p>$project.description</p>
-			</div>
-		</div>
+	## Page header.
+	
+  #parse ("azkaban/webapp/servlet/velocity/projectpageheader.vm")
+
+  ## Page content.
 
 		<div class="container">
 			<div class="row">
 				<div class="col-lg-8">
 	
-	## Breadcrumb
-
-					<ol class="breadcrumb">
-						<li><a href="${context}/manager?project=${project.name}"><strong>Project</strong> $project.name</a></li>
-					</ol>
-
 	#set ($project_page = "permissions")
 	#parse ("azkaban/webapp/servlet/velocity/projectnav.vm")
 
-					<div class="panel panel-default">
-						<div class="panel-heading">
-							Permissions
-							<div class="pull-right">
-	#if ($isAdmin)
-								<button id="addUser" class="btn btn-xs btn-success">Add User</button>
-								<button id="addGroup" class="btn btn-xs btn-warning">Add Group</button>
-								<button id="addProxyUser" class="btn btn-xs btn-info">Add Proxy User</button>
-	#end
-							</div>
-						</div>
-						<div class="panel-body">
-
 	## User permissions table.
 
-							<div class="panel panel-success">
-								<div class="panel-heading">User</div>
-								<table class="table table-striped permission-table" id="permissions-table">
-									<thead>
-										<th class="tb-username">User</th>
-										<th class="tb-perm">Admin</th>
-										<th class="tb-read">Read</th>
-										<th class="tb-write">Write</th>
-										<th class="tb-execute">Execute</th>
-										<th class="tb-schedule">Schedule</th>					
+          <div class="panel panel-success">
+            <div class="panel-heading">
+              User
+  #if ($isAdmin)
+              <div class="pull-right">
+                <button id="addUser" class="btn btn-xs btn-success">Add</button>
+              </div>
+  #end
+            </div>
+            <table class="table table-striped permission-table" id="permissions-table">
+              <thead>
+                <tr>
+                  <th class="tb-username">User</th>
+                  <th class="tb-perm">Admin</th>
+                  <th class="tb-read">Read</th>
+                  <th class="tb-write">Write</th>
+                  <th class="tb-execute">Execute</th>
+                  <th class="tb-schedule">Schedule</th>					
 	#if ($isAdmin)
-											<th class="tb-action"></th>
-	#end
-									</thead>
-									<tbody>
+                  <th class="tb-action"></th>
+  #end
+                </tr>
+              </thead>
+              <tbody>
 
 	#if ($permissions)
 		#foreach ($perm in $permissions)
-										<tr>
-											<td class="tb-username">
+                <tr>
+                  <td class="tb-username">
 			#if ($perm.first == $username) 
-												${perm.first} <span class="sublabel">(you)</span> 
+                    ${perm.first} <span class="sublabel">(you)</span> 
 			#else 
-												$perm.first 
+                    $perm.first 
 			#end
-											</td>
+                  </td>
 			#if ($perm.second.isPermissionNameSet("ADMIN")) 
-											<td><input id="${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled" checked="true"></input></td>
-											<td><input id="${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled" checked="true"></input></td>
-											<td><input id="${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" checked="true"></input></td>
-											<td><input id="${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" checked="true"></input></td>
-											<td><input id="${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" checked="true"></input></td>
+                  <td><input id="${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled" checked="true"></input></td>
+                  <td><input id="${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled" checked="true"></input></td>
+                  <td><input id="${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" checked="true"></input></td>
+                  <td><input id="${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" checked="true"></input></td>
+                  <td><input id="${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" checked="true"></input></td>
 			#else
-											<td><input id="${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled"></input></td>
-											<td><input id="${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled"  #if ($perm.second.isPermissionNameSet("READ")) checked="true" #end></input></td>
-											<td><input id="${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" #if ($perm.second.isPermissionNameSet("WRITE")) checked="true" #end></input></td>
-											<td><input id="${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" #if ($perm.second.isPermissionNameSet("EXECUTE")) checked="true" #end></input></td>
-											<td><input id="${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" #if ($perm.second.isPermissionNameSet("SCHEDULE")) checked="true" #end></input></td>
+                  <td><input id="${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled"></input></td>
+                  <td><input id="${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled"  #if ($perm.second.isPermissionNameSet("READ")) checked="true" #end></input></td>
+                  <td><input id="${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" #if ($perm.second.isPermissionNameSet("WRITE")) checked="true" #end></input></td>
+                  <td><input id="${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" #if ($perm.second.isPermissionNameSet("EXECUTE")) checked="true" #end></input></td>
+                  <td><input id="${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" #if ($perm.second.isPermissionNameSet("SCHEDULE")) checked="true" #end></input></td>
 			#end
 
 			#if ($isAdmin)
-											<td><button id="$perm.first" #if($perm.first == $username) disabled="disabled" class="btn btn-xs btn-disabled" #else class="btn btn-xs btn-default" #end >Change</button></td>
+                  <td><button id="$perm.first" #if($perm.first == $username) disabled="disabled" class="btn btn-xs btn-disabled" #else class="btn btn-xs btn-default" #end >Change</button></td>
 			#end
-										</tr>
+                </tr>
 		#end
 	#else
     #if ($isAdmin)
-										<tr><td colspan="7">No Users Found.</td></tr>
+                <tr><td colspan="7">No Users Found.</td></tr>
     #else
-										<tr><td colspan="6">No Users Found.</td></tr>
+                <tr><td colspan="6">No Users Found.</td></tr>
     #end
 	#end
-									</tbody>
-								</table>
-							</div>
+              </tbody>
+            </table>
+          </div>
 
 	## Group permissions table.
 							
-							<div class="panel panel-warning">
-								<div class="panel-heading">Group</div>
-								<table class="table table-striped permission-table" id="group-permissions-table">
-									<thead>
-										<tr>
-											<th class="tb-username">Group</th>
-											<th class="tb-perm">Admin</th>
-											<th class="tb-read">Read</th>
-											<th class="tb-write">Write</th>
-											<th class="tb-execute">Execute</th>
-											<th class="tb-schedule">Schedule</th>
+          <div class="panel panel-warning">
+            <div class="panel-heading">
+              Group
+  #if ($isAdmin)
+              <div class="pull-right">
+                <button id="addGroup" class="btn btn-xs btn-warning">Add</button>
+              </div>
+  #end
+            </div>
+            <table class="table table-striped permission-table" id="group-permissions-table">
+              <thead>
+                <tr>
+                  <th class="tb-username">Group</th>
+                  <th class="tb-perm">Admin</th>
+                  <th class="tb-read">Read</th>
+                  <th class="tb-write">Write</th>
+                  <th class="tb-execute">Execute</th>
+                  <th class="tb-schedule">Schedule</th>
 	#if ($isAdmin)
-											<th class="tb-action"></th>
+                  <th class="tb-action"></th>
 	#end
-										</tr>
-									</thead>
-									<tbody>
+                </tr>
+              </thead>
+              <tbody>
 	#if ($groupPermissions)
 		#foreach ($perm in $groupPermissions)
-										<tr>
-											<td class="tb-username">
+                <tr>
+                  <td class="tb-username">
 			#if ($perm.first == $username) 
-												${perm.first} <span class="sublabel">(you)</span> 
+                    ${perm.first} <span class="sublabel">(you)</span> 
 			#else 
-												$perm.first 
+                    $perm.first 
 			#end
-											</td>
+                  </td>
 			#if ($perm.second.isPermissionNameSet("ADMIN")) 
-											<td><input id="group-${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled" checked="true"></input></td>
-											<td><input id="group-${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled" checked="true"></input></td>
-											<td><input id="group-${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" checked="true"></input></td>
-											<td><input id="group-${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" checked="true"></input></td>
-											<td><input id="group-${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" checked="true"></input></td>
+                  <td><input id="group-${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled" checked="true"></input></td>
+                  <td><input id="group-${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled" checked="true"></input></td>
+                  <td><input id="group-${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" checked="true"></input></td>
+                  <td><input id="group-${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" checked="true"></input></td>
+                  <td><input id="group-${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" checked="true"></input></td>
 			#else
-											<td><input id="group-${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled"></input></td>
-											<td><input id="group-${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled"  #if ($perm.second.isPermissionNameSet("READ")) checked="true" #end></input></td>
-											<td><input id="group-${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" #if ($perm.second.isPermissionNameSet("WRITE")) checked="true" #end></input></td>
-											<td><input id="group-${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" #if ($perm.second.isPermissionNameSet("EXECUTE")) checked="true" #end></input></td>
-											<td><input id="group-${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" #if ($perm.second.isPermissionNameSet("SCHEDULE")) checked="true" #end></input></td>
+                  <td><input id="group-${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled"></input></td>
+                  <td><input id="group-${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled"  #if ($perm.second.isPermissionNameSet("READ")) checked="true" #end></input></td>
+                  <td><input id="group-${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" #if ($perm.second.isPermissionNameSet("WRITE")) checked="true" #end></input></td>
+                  <td><input id="group-${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" #if ($perm.second.isPermissionNameSet("EXECUTE")) checked="true" #end></input></td>
+                  <td><input id="group-${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" #if ($perm.second.isPermissionNameSet("SCHEDULE")) checked="true" #end></input></td>
 			#end
 
 			#if ($isAdmin)
-											<td><button id="group-$perm.first" class="btn btn-xs btn-default">Change</button></td>
+                  <td><button id="group-$perm.first" class="btn btn-xs btn-default">Change</button></td>
 			#end
-										</tr>
+                </tr>
 		#end
 	#else
     #if ($isAdmin)
-										<tr><td colspan="7">No Groups Found.</td></tr>
+                <tr><td colspan="7">No Groups Found.</td></tr>
     #else
-										<tr><td colspan="6">No Groups Found.</td></tr>
+                <tr><td colspan="6">No Groups Found.</td></tr>
     #end
 	#end
-									</tbody>
-								</table>
-							</div>
+              </tbody>
+            </table>
+          </div>
 	
 	## Proxy users table.
 							
-							<div class="panel panel-info">
-								<div class="panel-heading">Proxy Users</div>
-								<table class="table table-striped permission-table" id="proxy-user-table">
-									<thead>
-										<tr>
-											<th class="tb-username">Proxy User</th>
+          <div class="panel panel-info">
+            <div class="panel-heading">
+              Proxy Users
+  #if ($isAdmin)
+              <div class="pull-right">                
+                <button id="addProxyUser" class="btn btn-xs btn-info">Add</button>
+              </div>
+	#end
+            </div>
+            <table class="table table-striped permission-table" id="proxy-user-table">
+              <thead>
+                <tr>
+                  <th class="tb-username">Proxy User</th>
 	#if ($isAdmin)
-											<th class="tb-action"></th>
+                  <th class="tb-action"></th>
 	#end
-										</tr>
-									</thead>
-									<tbody>
+                </tr>
+              </thead>
+              <tbody>
 	#if ($proxyUsers)
 		#foreach ($proxyUser in $proxyUsers)
-										<tr>
-											<td class="tb-username">#if($proxyUser == $username) ${proxyUser} <span class="sublabel">(you)</span> #else $proxyUser #end</td>
+                <tr>
+                  <td class="tb-username">#if($proxyUser == $username) ${proxyUser} <span class="sublabel">(you)</span> #else $proxyUser #end</td>
 			#if ($isAdmin)
-											<td><button id="proxy-${proxyUser}" name="${proxyUser}" class="btn btn-xs btn-primary">Remove</button></td>
+                  <td><button id="proxy-${proxyUser}" name="${proxyUser}" class="btn btn-xs btn-primary">Remove</button></td>
 			#end
-										</tr>
+                </tr>
 		#end
 	#else
     #if ($isAdmin)
-										<tr><td colspan="2">No Proxy User Found.</td></tr>
+                <tr><td colspan="2">No Proxy User Found.</td></tr>
     #else
-										<tr><td>No Proxy User Found.</td></tr>
+                <tr><td>No Proxy User Found.</td></tr>
     #end
 	#end
-									</tbody>
-								</table>
-							</div>
+              </tbody>
+            </table>
+          </div>
 	
-						</div><!-- /panel-body -->
-					</div><!-- /panel -->
 				</div><!-- /col-lg-8 -->
 				<div class="col-lg-4">
 	#parse ("azkaban/webapp/servlet/velocity/projectsidebar.vm")
@@ -354,6 +356,7 @@
 				</div>
 			</div>
 
+	#parse ("azkaban/webapp/servlet/velocity/projectmodals.vm")
 	#parse ("azkaban/webapp/servlet/velocity/invalidsessionmodal.vm")
 #end
 #parse ("azkaban/webapp/servlet/velocity/footer.vm")
diff --git a/src/java/azkaban/webapp/servlet/velocity/projectlogpage.vm b/src/java/azkaban/webapp/servlet/velocity/projectlogpage.vm
index 9d21afe..3a36e85 100644
--- a/src/java/azkaban/webapp/servlet/velocity/projectlogpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/projectlogpage.vm
@@ -24,6 +24,7 @@
 		<script type="text/javascript" src="${context}/js/azkaban.date.utils.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.ajax.utils.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.projectlog.view.js"></script>
+		<script type="text/javascript" src="${context}/js/azkaban.projectmodals.view.js"></script>
 		<script type="text/javascript">
 			var contextURL = "${context}";
 			var currentTime = ${currentTime};
@@ -61,13 +62,8 @@
 		</div>
 
 	## Page header.
-
-		<div class="az-page-header">
-			<div class="container">
-				<h1><a href="${context}/manager?project=${project.name}">Project <small>$project.name</small></a></h1>
-				<p>$project.description</p>
-			</div>
-		</div>
+	
+  #parse ("azkaban/webapp/servlet/velocity/projectpageheader.vm")
 
 	## Page content.
 
@@ -75,12 +71,6 @@
 			<div class="row">
 				<div class="col-lg-8">
 	
-	## Breadcrumb
-
-					<ol class="breadcrumb">
-						<li><a href="${context}/manager?project=${project.name}"><strong>Project</strong> $project.name</a></li>
-					</ol>
-
 	#set ($project_page = "logs")
 	#parse ("azkaban/webapp/servlet/velocity/projectnav.vm")
 
@@ -100,6 +90,7 @@
 				</div>
 			</div>
 
+	#parse ("azkaban/webapp/servlet/velocity/projectmodals.vm")
 #end
 
 #parse ("azkaban/webapp/servlet/velocity/footer.vm")
diff --git a/src/java/azkaban/webapp/servlet/velocity/projectmodals.vm b/src/java/azkaban/webapp/servlet/velocity/projectmodals.vm
new file mode 100644
index 0000000..1d22d58
--- /dev/null
+++ b/src/java/azkaban/webapp/servlet/velocity/projectmodals.vm
@@ -0,0 +1,71 @@
+#*
+ * Copyright 2012 LinkedIn Corp.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+*#
+
+  ## Upload project modal
+
+			<div class="modal fade" id="upload-project-modal">
+				<div class="modal-dialog">
+					<div class="modal-content">
+						<form id="upload-project-form" enctype="multipart/form-data" method="post" action="$!context/manager">
+							<div class="modal-header">
+								<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+								<h4 class="modal-title">Upload Project Files</h4>
+							</div>
+							<div class="modal-body">
+								<div class="alert alert-danger" id="upload-project-modal-error-msg">$error_msg</div>
+								<fieldset class="form-horizontal">
+									<div class="form-group">
+										<label for="path" class="col-sm-2 control-label">Job Archive</label>
+										<div class="col-sm-10">
+											<input type="file" class="form-control" id="file" name="file">
+										</div>
+									</div>
+								</fieldset>
+							</div>
+							<div class="modal-footer">
+								<input type="hidden" name="project" value="$project.name">
+								<input type="hidden" name="action" value="upload">
+								<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+								<button type="button" class="btn btn-primary" id="upload-project-btn">Upload</button>
+							</div>
+						</form>
+					</div>
+				</div>
+			</div>
+
+	## Delete project modal.
+			
+			<div class="modal fade" id="delete-project-modal">
+				<div class="modal-dialog">
+					<div class="modal-content">
+						<div class="modal-header">
+							<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+							<h4 class="modal-title">Delete Project</h4>
+						</div>
+						<div class="modal-body">
+							<p><strong>Warning:</strong> This project will be deleted and may not be recoverable.</p>
+						</div>
+						<div class="modal-footer">
+							<form id="delete-form">
+								<input type="hidden" name="project" value="$project.name">
+								<input type="hidden" name="delete" value="true">
+								<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+								<button type="button" class="btn btn-danger" id="delete-btn">Delete Project</button>
+							</form>
+						</div>
+					</div>
+				</div>
+			</div>
diff --git a/src/java/azkaban/webapp/servlet/velocity/projectnav.vm b/src/java/azkaban/webapp/servlet/velocity/projectnav.vm
index 01952bf..c19a6ab 100644
--- a/src/java/azkaban/webapp/servlet/velocity/projectnav.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/projectnav.vm
@@ -14,7 +14,7 @@
  * the License.
 *#
 
-					<ul class="nav nav-pills">
+					<ul class="nav nav-tabs">
 						<li#if($project_page == 'flows') class="active"#end><a href="${context}/manager?project=${project.name}">Flows</a></li>
 						<li#if($project_page == 'permissions') class="active"#end><a id="project-permission-btn" href="${context}/manager?project=${project.name}&permissions">Permissions</a></li>
 	#if ($admin)
diff --git a/src/java/azkaban/webapp/servlet/velocity/projectpage.vm b/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
index 49b652d..e09811d 100644
--- a/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
@@ -21,11 +21,13 @@
 #parse ("azkaban/webapp/servlet/velocity/style.vm")
 #parse ("azkaban/webapp/servlet/velocity/javascript.vm")
 
-		<link rel="stylesheet" type="text/css" href="${context}/css/jquery-ui-1.10.1.custom.css" />
+		<link rel="stylesheet" type="text/css" href="${context}/css/bootstrap-datetimepicker.css" />
 		<link rel="stylesheet" type="text/css" href="${context}/css/azkaban-svg.css" />
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-1.10.1.custom.js"></script>
+		<script type="text/javascript" src="${context}/js/moment.min.js"></script>
+		<script type="text/javascript" src="${context}/js/bootstrap-datetimepicker.min.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.ajax.utils.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.project.view.js"></script>
+		<script type="text/javascript" src="${context}/js/azkaban.projectmodals.view.js"></script>
 		<script type="text/javascript">
 			var contextURL = "${context}";
 			var currentTime = ${currentTime};
@@ -70,66 +72,47 @@
 		</div>
 
 	## Page header.
-
-		<div class="az-page-header">
-			<div class="container">
-				<h1><a href="${context}/manager?project=${project.name}">Project <small>$project.name</small></a></h1>
-				<p>$project.description</p>
-			</div>
-		</div>
-
-  
-	## Breadcrumb
-
-    <div class="container">
-      <ol class="breadcrumb">
-        <li class="active"><strong>Project</strong> $project.name</li>
-      </ol>
+	
+  #parse ("azkaban/webapp/servlet/velocity/projectpageheader.vm")
 
 	## Page content.
 
+    <div class="container">
 			<div class="row">
-				<div class="col-lg-8">
+				<div class="col-lg-8" id="flow-tabs">
 					
 	#set ($project_page = "flows")
 	#parse ("azkaban/webapp/servlet/velocity/projectnav.vm")
 
-					<div class="panel panel-default" id="flow-tabs">
-						<div class="panel-heading">
-							<div class="pull-right" id="project-options">
-								<button id="project-upload-btn" class="btn btn-xs btn-primary">Upload</button>
-								<button id="project-delete-btn" class="btn btn-xs btn-danger">Delete Project</button>
-							</div>
-							Flows
-						</div>
-						<div class="panel-body">
-
+            <div id="flow-tabs">
 	#if ($flows)
 		#foreach ($flow in $flows)
-							<div class="panel panel-info" flow="${flow.id}" project="${project.name}">
-								<div class="panel-heading flow-expander" id="${flow.id}">
+              <div class="panel panel-info" flow="${flow.id}" project="${project.name}">
+                <div class="panel-heading flow-expander" id="${flow.id}">
 			#if (${exec})
-									<div class="pull-right">
-										<button type="button" class="btn btn-xs btn-primary execute-flow" flowId="${flow.id}">Execute Flow</button>
-										<a href="${context}/manager?project=${project.name}&flow=${flow.id}#executions" class="btn btn-primary btn-xs">Executions</a>
-										<a href="${context}/manager?project=${project.name}&flow=${flow.id}#summary" class="btn btn-primary btn-xs">Summary</a>
-									</div>
+                <div class="pull-right">
+                  <button type="button" class="btn btn-xs btn-primary execute-flow" flowId="${flow.id}">Execute Flow</button>
+                  <a href="${context}/manager?project=${project.name}&flow=${flow.id}#executions" class="btn btn-primary btn-xs">Executions</a>
+                  <a href="${context}/manager?project=${project.name}&flow=${flow.id}#summary" class="btn btn-primary btn-xs">Summary</a>
+                </div>
 			#end
-									<a href="${context}/manager?project=${project.name}&flow=${flow.id}">${flow.id}</a>
-								</div>
-								<div id="${flow.id}-child" class="panel-collapse collapse">
-									<table class="table">
-										<tbody id="${flow.id}-tbody">
-										</tbody>
-									</table>
-								</div>
-							</div>
+                <a href="${context}/manager?project=${project.name}&flow=${flow.id}">${flow.id}</a>
+              </div>
+              <div id="${flow.id}-child" class="panel-collapse collapse">
+                <table class="table">
+                  <tbody id="${flow.id}-tbody">
+                  </tbody>
+                </table>
+              </div>
+            </div>
 		#end
 	#else
-							<p>No flows uploaded to this project</p>
+            <div class="alert alert-info">
+              <h4>No Flows</h4>
+              <p>No flows have been uploaded to this project yet.</p>
+            </div>
 	#end
-						</div>
-					</div>
+          </div><!-- /#flow-tabs -->
 				</div><!-- /col-lg-8 -->
 
 				<div class="col-lg-4">
@@ -137,62 +120,7 @@
 				</div><!-- /col-lg-4 -->
 			</div><!-- /row -->
 
-## Upload project modal
-
-			<div class="modal fade" id="upload-project-modal">
-				<div class="modal-dialog">
-					<div class="modal-content">
-						<form id="upload-project-form" enctype="multipart/form-data" method="post" action="$!context/manager">
-							<div class="modal-header">
-								<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-								<h4 class="modal-title">Upload Project Files</h4>
-							</div>
-							<div class="modal-body">
-								<div class="alert alert-danger" id="upload-project-modal-error-msg">$error_msg</div>
-								<fieldset class="form-horizontal">
-									<div class="form-group">
-										<label for="path" class="col-sm-2 control-label">Job Archive</label>
-										<div class="col-sm-10">
-											<input type="file" class="form-control" id="file" name="file">
-										</div>
-									</div>
-								</fieldset>
-							</div>
-							<div class="modal-footer">
-								<input type="hidden" name="project" value="$project.name">
-								<input type="hidden" name="action" value="upload">
-								<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
-								<button type="button" class="btn btn-primary" id="upload-project-btn">Upload</button>
-							</div>
-						</form>
-					</div>
-				</div>
-			</div>
-
-	## Delete project modal.
-			
-			<div class="modal fade" id="delete-project-modal">
-				<div class="modal-dialog">
-					<div class="modal-content">
-						<div class="modal-header">
-							<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-							<h4 class="modal-title">Delete Project</h4>
-						</div>
-						<div class="modal-body">
-							<p><strong>Warning:</strong> This project will be deleted and may not be recoverable.</p>
-						</div>
-						<div class="modal-footer">
-							<form id="delete-form">
-								<input type="hidden" name="project" value="$project.name">
-								<input type="hidden" name="delete" value="true">
-								<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
-								<button type="button" class="btn btn-danger" id="delete-btn">Delete Project</button>
-							</form>
-						</div>
-					</div>
-				</div>
-			</div>
-
+	#parse ("azkaban/webapp/servlet/velocity/projectmodals.vm")
 	#parse ("azkaban/webapp/servlet/velocity/invalidsessionmodal.vm")
 	#parse ("azkaban/webapp/servlet/velocity/flowexecutionpanel.vm")
 	#parse ("azkaban/webapp/servlet/velocity/messagedialog.vm")
diff --git a/src/java/azkaban/webapp/servlet/velocity/projectpageheader.vm b/src/java/azkaban/webapp/servlet/velocity/projectpageheader.vm
new file mode 100644
index 0000000..5fda594
--- /dev/null
+++ b/src/java/azkaban/webapp/servlet/velocity/projectpageheader.vm
@@ -0,0 +1,36 @@
+#*
+ * Copyright 2012 LinkedIn Corp.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+*#
+
+		<div class="az-page-header">
+			<div class="container">
+        <div class="row">
+          <div class="col-lg-6">
+            <h1><a href="${context}/manager?project=${project.name}">Project <small>$project.name</small></a></h1>
+            <p>$project.description</p>
+          </div>
+          <div class="col-lg-6">
+            <div class="pull-right az-page-header-form" id="project-options">
+              <button id="project-delete-btn" class="btn btn-sm btn-danger">
+                <span class="glyphicon glyphicon-trash"></span> Delete Project
+              </button>
+              <button id="project-upload-btn" class="btn btn-sm btn-primary">
+                <span class="glyphicon glyphicon-upload"></span> Upload
+              </button>
+            </div>
+          </div>
+        </div>
+			</div>
+		</div>
diff --git a/src/java/azkaban/webapp/servlet/velocity/scheduledflowpage.vm b/src/java/azkaban/webapp/servlet/velocity/scheduledflowpage.vm
index 361da87..708cfaa 100644
--- a/src/java/azkaban/webapp/servlet/velocity/scheduledflowpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/scheduledflowpage.vm
@@ -21,11 +21,10 @@
 #parse ("azkaban/webapp/servlet/velocity/style.vm")
 #parse ("azkaban/webapp/servlet/velocity/javascript.vm")
 
-		<link rel="stylesheet" type="text/css" href="${context}/css/jquery-ui-1.10.1.custom.css" />
+		<link rel="stylesheet" type="text/css" href="${context}/css/bootstrap-datetimepicker.css" />
 		
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-1.10.1.custom.js"></script>
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-timepicker-addon.js"></script> 
-		<script type="text/javascript" src="${context}/js/jqueryui/jquery-ui-sliderAccess.js"></script>
+		<script type="text/javascript" src="${context}/js/moment.min.js"></script>
+		<script type="text/javascript" src="${context}/js/bootstrap-datetimepicker.min.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.table.sort.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.scheduled.view.js"></script>
 		<script type="text/javascript">
@@ -80,52 +79,48 @@
 		<div class="container">
 			<div class="row">
 				<div class="col-lg-12">
-					<div class="panel panel-default">
-						<div class="panel-heading">Scheduled Flows</div>
-						<table id="scheduledFlowsTbl" class="table table-striped">
-							<thead>
-								<tr>
-									<!--th class="execid">Execution Id</th-->
-									<th>ID</th>
-									<th>Flow</th>
-									<th>Project</th>
-									<th>Submitted By</th>
-									<th class="date">First Scheduled to Run</th>
-									<th class="date">Next Execution Time</th>
-									<th class="date">Repeats Every</th>
-									<th>Has SLA</th>
-									<th colspan="2" class="action ignoresort">Action</th>
-								</tr>
-							</thead>
-							<tbody>
+          <table id="scheduledFlowsTbl" class="table table-striped table-condensed table-bordered table-hover">
+            <thead>
+              <tr>
+                <!--th class="execid">Execution Id</th-->
+                <th>ID</th>
+                <th>Flow</th>
+                <th>Project</th>
+                <th>Submitted By</th>
+                <th class="date">First Scheduled to Run</th>
+                <th class="date">Next Execution Time</th>
+                <th class="date">Repeats Every</th>
+                <th>Has SLA</th>
+                <th colspan="2" class="action ignoresort">Action</th>
+              </tr>
+            </thead>
+            <tbody>
 	#if(!$schedules.isEmpty())
 		#foreach($sched in $schedules)
-								<tr>
-									<td>${sched.scheduleId}</td>
-									<td class="tb-name">
-										<a href="${context}/manager?project=${sched.projectName}&flow=${sched.flowName}">${sched.flowName}</a>
-									</td>
-									<td>
-										<a href="${context}/manager?project=${sched.projectName}">${sched.projectName}</a>
-									</td>
-									<td>${sched.submitUser}</td>
-									<td>$utils.formatDateTime(${sched.firstSchedTime})</td>
-									<td>$utils.formatDateTime(${sched.nextExecTime})</td>
-									<td>$utils.formatPeriod(${sched.period})</td>
-									<td>#if(${sched.slaOptions}) true #else false #end</td>
-									<td><button type="button" id="removeSchedBtn" class="btn btn-sm btn-danger" onclick="removeSched(${sched.scheduleId})" >Remove Schedule</button></td>
-									<td><button type="button" id="addSlaBtn" class="btn btn-sm btn-primary" onclick="slaView.initFromSched(${sched.scheduleId}, '${sched.flowName}')" >Set SLA</button></td>
-								</tr>
-
+              <tr>
+                <td>${sched.scheduleId}</td>
+                <td class="tb-name">
+                  <a href="${context}/manager?project=${sched.projectName}&flow=${sched.flowName}">${sched.flowName}</a>
+                </td>
+                <td>
+                  <a href="${context}/manager?project=${sched.projectName}">${sched.projectName}</a>
+                </td>
+                <td>${sched.submitUser}</td>
+                <td>$utils.formatDateTime(${sched.firstSchedTime})</td>
+                <td>$utils.formatDateTime(${sched.nextExecTime})</td>
+                <td>$utils.formatPeriod(${sched.period})</td>
+                <td>#if(${sched.slaOptions}) true #else false #end</td>
+                <td><button type="button" id="removeSchedBtn" class="btn btn-sm btn-danger" onclick="removeSched(${sched.scheduleId})" >Remove Schedule</button></td>
+                <td><button type="button" id="addSlaBtn" class="btn btn-sm btn-primary" onclick="slaView.initFromSched(${sched.scheduleId}, '${sched.flowName}')" >Set SLA</button></td>
+              </tr>
 		#end
 	#else
-								<tr>
-									<td colspan="10">No scheduled flow found.</td>
-								</tr>
+              <tr>
+                <td colspan="10">No scheduled flow found.</td>
+              </tr>
 	#end
-							</tbody>
-						</table>
-					</div><!-- /panel -->
+            </tbody>
+          </table>
 				</div><!-- /col-lg-12 -->
 			</div><!-- /row -->
 
diff --git a/src/java/azkaban/webapp/servlet/velocity/triggerspage.vm b/src/java/azkaban/webapp/servlet/velocity/triggerspage.vm
index ff0b457..48f6473 100644
--- a/src/java/azkaban/webapp/servlet/velocity/triggerspage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/triggerspage.vm
@@ -92,7 +92,7 @@
             <tbody>
 #if($triggers)
   #foreach($trigger in $triggers)
-              <tr class="row">
+              <tr>
                 <td>${trigger.triggerId}</td>
                 <td>${trigger.source}</td>
                 <td>${trigger.submitUser}</td>
diff --git a/src/less/bootstrap-azkaban.less b/src/less/bootstrap-azkaban.less
index 203f867..2cf664b 100644
--- a/src/less/bootstrap-azkaban.less
+++ b/src/less/bootstrap-azkaban.less
@@ -1,3 +1,10 @@
+// Since the azkaban navbar no longer has the 20px bottom margin so that the
+// page header sits flush below the navbar, add a 20px top margin to the login
+// form.
+.az-login {
+  margin-top: 20px;
+}
+
 // Wide modal used for certain panels such as executing flow panel.
 .modal-wide .modal-dialog {
   width: 80%;
@@ -13,13 +20,22 @@
   margin-bottom: 15px;
 }
 
+.az-project-row {
+	cursor: pointer;
+}
+
 // Flow panel heading.
 .flow-expander {
   cursor: pointer;
 }
 
 // Flow summary.
-table .worksheet-key {
+td.flow-summary-key {
+  width: 25%;
+  font-weight: bold;
+}
+
+td.flow-summary-value {
   width: 25%;
 }
 
@@ -257,6 +273,14 @@ table .worksheet-key {
   }
 }
 
+.az-page-header-form {
+  margin-top: 20px;
+}
+
+.az-exflow-stats {
+  margin-top: 10px;
+}
+
 .contextMenu {
   position: absolute;
   background-color: #FFF;
@@ -342,11 +366,11 @@ table .worksheet-key {
   }
 
   &.SUCCEEDED {
-    background-color: #82b859;
+    background-color: #5cb85c;
   }
 
   &.FAILED {
-    background-color: #c82123;
+    background-color: #d9534f;
   }
 
   &.RUNNING {
@@ -376,11 +400,11 @@ td {
     margin-top: 2px;
     
     &.SUCCEEDED {
-      background-color: #82b859;
+      background-color: #5cb85c;
     }
 
     &.FAILED {
-      background-color: #c82123;
+      background-color: #d9534f;
     }
 
     &.PAUSED {
@@ -408,7 +432,7 @@ td {
     }
 
     &.KILLED {
-      background-color: #cc0000;
+      background-color: #d9534f;
     }
 
     &.UNKNOWN {
@@ -416,3 +440,9 @@ td {
     }
   }
 }
+
+.nav {
+	.nav-button {
+		margin-left: 5px;
+	}
+}

src/tl/flowsummary.tl 293(+98 -195)

diff --git a/src/tl/flowsummary.tl b/src/tl/flowsummary.tl
index 85c9a99..7e42852 100644
--- a/src/tl/flowsummary.tl
+++ b/src/tl/flowsummary.tl
@@ -1,209 +1,112 @@
+        <div class="col-lg-12">
+          <table class="table table-striped table-bordered table-condensed table-hover">
+            <tbody>
+              <tr>
+                <td class="flow-summary-key">Workflow name</td>
+                <td class="flow-summary-value">{general.flowId}</td>
+                <td class="flow-summary-key">Project name</td>
+                <td class="flow-summary-value">{general.projectName}</td>
+              </tr>
+              <tr>
+                <td class="flow-summary-key">Workflow Hadoop User Name</td>
+                <td class="flow-summary-value">{general.user}</td>
+                <td class="flow-summary-key">Job Types Used</td>
+                <td class="flow-summary-value">{general.apis}</td>
+              </tr>
+            </tbody>
+          </table>
+					
 					<div class="panel panel-default">
-						<div class="panel-heading">General</div>
-						<table class="table table-striped table-bordered table-condensed table-hover">
+						<div class="panel-heading">
+							Scheduling
+							{?schedule}
+							<div class="pull-right">
+								<button type="button" id="removeSchedBtn" class="btn btn-xs btn-danger" onclick="removeSched({schedule.scheduleId})" >Remove Schedule</button>
+							</div>
+							{/schedule}
+						</div>
+						{?schedule}
+						<table class="table table-striped table-condensed table-bordered table-hover">
 							<tbody>
 								<tr>
-									<td class="worksheet-key">Workflow name</td>
-									<td>{general.flowId}</td>
-								</tr>
-								<tr class="editRow">
-									<td class="worksheet-key">Workflow Purpose/Description</td>
-									<td class="editable"><span class="spanValue">{general.flowDescription}</span></td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Project name</td>
-									<td>{general.projectName}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Name of scheduled item</td>
-									<td>{general.flowId}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Workflow Hadoop User Name</td>
-									<td>{general.user}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Responsible team</td>
-									<td class="editable"><span class="spanValue">{general.team}</span></td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Responsible manager</td>
-									<td class="editable"><span class="spanValue">{general.manager}</span></td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Responsible Developer</td>
-									<td class="editable"><span class="spanValue">{general.developer}</span></td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Hadoop APIs Used</td>
-									<td>{general.apis}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Additional Hadoop APIs Used</td>
-									<td>{general.additionalApis}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Streaming Languages Used</td>
-									<td>{general.streamingLanguages}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Code Repository</td>
-									<td>{general.codeRepository}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Does this workflow perform any second, third, or higher level connection graph calculations?</td>
-									<td>{general.higherLevelGraphOperations}</td>
+									<td class="flow-summary-key">Schedule ID</td>
+									<td class="flow-summary-value">{schedule.scheduleId}</td>
+									<td class="flow-summary-key">Submitted By</td>
+									<td class="flow-summary-value">{schedule.submitUser}</td>
 								</tr>
 								<tr>
-									<td class="worksheet-key">Can this workflow be run with an empty <strong>/jobs</strong> directory</td>
-									<td>{general.emptyJobsDirectory}</td>
+									<td class="flow-summary-key">First Scheduled to Run</td>
+									<td class="flow-summary-value">{schedule.firstSchedTime}</td>
+									<td class="flow-summary-key">Repeats Every</td>
+									<td class="flow-summary-value">{schedule.period}</td>
 								</tr>
 								<tr>
-									<td class="worksheet-key">If not, why not?</td>
-									<td>{general.emptyJobsDirectoryReason}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">How does the result get to front-end servers?</td>
-									<td>{general.toFrontEnd}</td>
+									<td class="flow-summary-key">Next Execution Time</td>
+									<td class="flow-summary-value">{schedule.nextExecTime}</td>
+									<td class="flow-summary-key">SLA</td>
+									<td class="flow-summary-value">
+									{?schedule.slaOptions}
+										true 
+									{:else} 
+										false 
+									{/schedule.slaOptions}
+										<div class="pull-right">
+											<button type="button" id="addSlaBtn" class="btn btn-xs btn-primary" onclick="slaView.initFromSched({schedule.scheduleId}, '{flowName}')" >Set SLA</button>
+										</div>
+									</td>
 								</tr>
 							</tbody>
 						</table>
+						{:else}
+						<div class="panel-body">
+							<div class="alert alert-info">
+								<h4>No Schedule</h4>
+								<p>This flow has not been scheduled.</p>
+							</div>
+						</div>
+						{/schedule}
 					</div>
 
-					<div class="panel panel-default">
-						<div class="panel-heading">Scheduling</div>
-						<table class="table table-striped table-bordered table-condensed table-hover">
-							<tbody>
-								<tr>
-									<td class="worksheet-key">Max Map Slots from Largest Job</td>
-									<td>{scheduling.maxMapSlots}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Max Reduce Slots from Largest Job</td>
-									<td>{scheduling.maxReduceSlots}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Total Reduce Slots from All Jobs</td>
-									<td>{scheduling.totalReduceSlots}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Total Number of Jobs</td>
-									<td>{scheduling.numJobs}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Longest Task Time</td>
-									<td>{scheduling.longestTaskTime}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Required Schedule</td>
-									<td>{scheduling.schedule}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Launch Time</td>
-									<td>{scheduling.launchTime}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Total Workflow Run Time (hours)</td>
-									<td>{scheduling.totalFlowTime}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Expected Time of Completion</td>
-									<td>{scheduling.expectedCompletionTime}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Max Permitted Delay</td>
-									<td>{scheduling.maxPermittedDelay}</td>
-								</tr>
-							</tbody>
-						</table>
-					</div>
+          <div class="panel panel-default">
+            <div class="panel-heading">Last Run Stats</div>
+            {?lastRun}
+            <table class="table table-striped table-bordered table-condensed table-hover">
+              <tbody>
+								<tr>
+									<td class="flow-summary-key">Max Map Slots from Largest Job</td>
+									<td>{lastRun.maxMapSlots}</td>
+                </tr>
+                <tr>
+									<td class="flow-summary-key">Max Reduce Slots from Largest Job</td>
+									<td>{lastRun.maxReduceSlots}</td>
+								</tr>
+								<tr>
+									<td class="flow-summary-key">Total Map Slots from All Jobs</td>
+									<td>{lastRun.totalMapSlots}</td>
+                </tr>
+                <tr>
+									<td class="flow-summary-key">Total Reduce Slots from All Jobs</td>
+									<td>{lastRun.totalReduceSlots}</td>
+								</tr>
+								<tr>
+									<td class="flow-summary-key">Total Number of Jobs</td>
+									<td>{lastRun.numJobs}</td>
+                </tr>
+                <tr>
+									<td class="flow-summary-key">Longest Task Time</td>
+									<td>{lastRun.longestTaskTime}</td>
+								</tr>
+              </tbody>
+            </table>
+            {:else}
+            <div class="panel-body">
+              <div class="alert alert-info">
+                <h4>No last run stats available</h4>
+                <p>Last run stats requires at least one successful run of the flow.</p>
+              </div>
+            </div>
+            {/lastRun}
+          </div>
+        </div><!-- /.col-lg-12 -->
 
-					<div class="panel panel-default">
-						<div class="panel-heading">Resources</div>
-						<table class="table table-striped table-bordered table-condensed table-hover">
-							<tbody>
-								<tr>
-									<td class="worksheet-key">Is any of the code specifically multi-threaded?</td>
-									<td colspan="3">{resources.multithreaded}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Do you 'fat jar' any hadoop-core jars?</td>
-									<td colspan="3">{resources.fatJar}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Which job has the largest spill count?</td>
-									<td>{resources.largestSpill.job}</td>
-									<td class="worksheet-key">Largest spill count for any given task?</td>
-									<td>{resources.largestSpill.count}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Is there a distributed cache in use?</td>
-									<td>{resources.distributedCache.using}</td>
-									<td class="worksheet-key">How big is the distributed cache?</td>
-									<td>{resources.distributedCache.size}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Size of largest <code>-Xmx</code> value?</td>
-									<td>{resources.largestXmx.size}</td>
-									<td class="worksheet-key">If this is above 1G, please explain why</td>
-									<td>{resources.largestXmx.reason}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Do any jobs use <code>-Xms</code>?</td>
-									<td>{resources.xms.using}</td>
-									<td class="worksheet-key">If so, why?</td>
-									<td>{resources.xms.reason}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Is <em>intermediate compression</em> specifically turned on?</td>
-									<td>{resources.intermediateCompression.on}</td>
-									<td class="worksheet-key">If so, which codec</td>
-									<td>{resources.intermediateCompression.codec}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Are there combiners in use?</td>
-									<td colspan="3">{resources.combiners}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Size of largest <code>mapred.job.map.memory.mb</code></td>
-									<td>{resources.largestMapredJobMapMemoryMb.size}</td>
-									<td class="worksheet-key">Used by job</td>
-									<td>{resources.largestMapredJobMapMemoryMb.job}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Size of largest <code>mapred.job.reduce.memory.mb</code></td>
-									<td>{resources.largestMapredJobReduceMemoryMb.size}</td>
-									<td class="worksheet-key">Used by job</td>
-									<td>{resources.largestMapredJobMapMemoryMb.job}</td>
-								</tr>
-							</tbody>
-						</table>
-					</div>
 
-					<div class="panel panel-default">
-						<div class="panel-heading">Input/Output</div>
-						<table class="table table-striped table-bordered table-condensed table-hover">
-							<tbody>
-								<tr>
-									<td class="worksheet-key">List of input HDFS file paths</td>
-									<td>{io.hdfsPaths}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Number of files generated (hadoop dfs -count)</td>
-									<td>{io.hdfsFileCount}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Average size of files generated in GB</td>
-									<td>{io.averageFileSize}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Size of intermediate data (content of /jobs - output going to production) in GB on HDFS</td>
-									<td>{io.intermediateFileSize}</td>
-								</tr>
-								<tr>
-									<td class="worksheet-key">Size of final output data in GB on HDFS</td>
-									<td>{io.finalOutputSize}</td>
-								</tr>
-							</tbody>
-						</table>
-					</div>
diff --git a/src/web/css/bootstrap.css b/src/web/css/bootstrap.css
index 6aef1f6..fb50e38 100644
--- a/src/web/css/bootstrap.css
+++ b/src/web/css/bootstrap.css
@@ -2634,8 +2634,8 @@ input[type="button"].btn-block {
 
 @font-face {
   font-family: 'Glyphicons Halflings';
-  src: url('../fonts/glyphicons-halflings-regular.eot');
-  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+  src: url('../../fonts/glyphicons-halflings-regular.eot');
+  src: url('../../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
 }
 
 .glyphicon {
@@ -7095,4 +7095,4 @@ td.visible-print {
   td.hidden-print {
     display: none !important;
   }
-}
\ No newline at end of file
+}
diff --git a/src/web/css/bootstrap-datetimepicker.css b/src/web/css/bootstrap-datetimepicker.css
new file mode 100644
index 0000000..e5eb7a6
--- /dev/null
+++ b/src/web/css/bootstrap-datetimepicker.css
@@ -0,0 +1,174 @@
+/**
+ * Build file for the dist version of datetimepicker.css
+ */
+/*!
+ * Datetimepicker for Bootstrap v3
+ * https://github.com/Eonasdan/bootstrap-datetimepicker/
+ * Copyright 2012 Stefan Petre
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+.bootstrap-datetimepicker-widget {
+  top: 0;
+  left: 0;
+  width: 250px;
+  padding: 4px;
+  margin-top: 1px;
+  z-index: 9999;
+  border-radius: 4px;
+  /*.dow {
+  border-top: 1px solid #ddd !important;
+  }*/
+}
+.bootstrap-datetimepicker-widget .btn {
+  padding: 6px;
+}
+.bootstrap-datetimepicker-widget:before {
+  content: '';
+  display: inline-block;
+  border-left: 7px solid transparent;
+  border-right: 7px solid transparent;
+  border-bottom: 7px solid #ccc;
+  border-bottom-color: rgba(0, 0, 0, 0.2);
+  position: absolute;
+  top: -7px;
+  left: 6px;
+}
+.bootstrap-datetimepicker-widget:after {
+  content: '';
+  display: inline-block;
+  border-left: 6px solid transparent;
+  border-right: 6px solid transparent;
+  border-bottom: 6px solid white;
+  position: absolute;
+  top: -6px;
+  left: 7px;
+}
+.bootstrap-datetimepicker-widget.pull-right:before {
+  left: auto;
+  right: 6px;
+}
+.bootstrap-datetimepicker-widget.pull-right:after {
+  left: auto;
+  right: 7px;
+}
+.bootstrap-datetimepicker-widget > ul {
+  list-style-type: none;
+  margin: 0;
+}
+.bootstrap-datetimepicker-widget .timepicker-hour,
+.bootstrap-datetimepicker-widget .timepicker-minute,
+.bootstrap-datetimepicker-widget .timepicker-second {
+  width: 100%;
+  font-weight: bold;
+  font-size: 1.2em;
+}
+.bootstrap-datetimepicker-widget table[data-hour-format="12"] .separator {
+  width: 4px;
+  padding: 0;
+  margin: 0;
+}
+.bootstrap-datetimepicker-widget .datepicker > div {
+  display: none;
+}
+.bootstrap-datetimepicker-widget .picker-switch {
+  text-align: center;
+}
+.bootstrap-datetimepicker-widget table {
+  width: 100%;
+  margin: 0;
+}
+.bootstrap-datetimepicker-widget td,
+.bootstrap-datetimepicker-widget th {
+  text-align: center;
+  width: 20px;
+  height: 20px;
+  border-radius: 4px;
+}
+.bootstrap-datetimepicker-widget td.day:hover,
+.bootstrap-datetimepicker-widget td.hour:hover,
+.bootstrap-datetimepicker-widget td.minute:hover,
+.bootstrap-datetimepicker-widget td.second:hover {
+  background: #eeeeee;
+  cursor: pointer;
+}
+.bootstrap-datetimepicker-widget td.old,
+.bootstrap-datetimepicker-widget td.new {
+  color: #999999;
+}
+.bootstrap-datetimepicker-widget td.active,
+.bootstrap-datetimepicker-widget td.active:hover {
+  background-color: #428bca;
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.bootstrap-datetimepicker-widget td.disabled,
+.bootstrap-datetimepicker-widget td.disabled:hover {
+  background: none;
+  color: #999999;
+  cursor: not-allowed;
+}
+.bootstrap-datetimepicker-widget td span {
+  display: block;
+  width: 47px;
+  height: 54px;
+  line-height: 54px;
+  float: left;
+  margin: 2px;
+  cursor: pointer;
+  border-radius: 4px;
+}
+.bootstrap-datetimepicker-widget td span:hover {
+  background: #eeeeee;
+}
+.bootstrap-datetimepicker-widget td span.active {
+  background-color: #428bca;
+  color: #fff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.bootstrap-datetimepicker-widget td span.old {
+  color: #999999;
+}
+.bootstrap-datetimepicker-widget td span.disabled,
+.bootstrap-datetimepicker-widget td span.disabled:hover {
+  background: none;
+  color: #999999;
+  cursor: not-allowed;
+}
+.bootstrap-datetimepicker-widget th.switch {
+  width: 145px;
+}
+.bootstrap-datetimepicker-widget th.next,
+.bootstrap-datetimepicker-widget th.prev {
+  font-size: 21px;
+}
+.bootstrap-datetimepicker-widget th.disabled,
+.bootstrap-datetimepicker-widget th.disabled:hover {
+  background: none;
+  color: #999999;
+  cursor: not-allowed;
+}
+.bootstrap-datetimepicker-widget thead tr:first-child th {
+  cursor: pointer;
+}
+.bootstrap-datetimepicker-widget thead tr:first-child th:hover {
+  background: #eeeeee;
+}
+.input-group.date .input-group-addon span {
+  display: block;
+  cursor: pointer;
+  width: 16px;
+  height: 16px;
+}
+.bootstrap-datetimepicker-widget.left-oriented:before {
+  left: auto;
+  right: 6px;
+}
+.bootstrap-datetimepicker-widget.left-oriented:after {
+  left: auto;
+  right: 7px;
+}
+.bootstrap-datetimepicker-widget ul.list-unstyled li.in div.timepicker div.timepicker-picker table.table-condensed tbody > tr > td {
+  padding: 0px !important;
+}
diff --git a/src/web/js/azkaban.executions.view.js b/src/web/js/azkaban.executions.view.js
new file mode 100644
index 0000000..58b75c4
--- /dev/null
+++ b/src/web/js/azkaban.executions.view.js
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 LinkedIn Corp.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+$.namespace('azkaban');
+
+var executionsTabView;
+azkaban.ExecutionsTabView = Backbone.View.extend({
+  events: {
+    'click #currently-running-view-link': 'handleCurrentlyRunningViewLinkClick',
+    'click #recently-finished-view-link': 'handleRecentlyFinishedViewLinkClick'
+  },
+
+  initialize: function(settings) {
+    var selectedView = settings.selectedView;
+    if (selectedView == 'recently-finished') {
+      this.handleRecentlyFinishedViewLinkClick();
+    }
+    else {
+      this.handleCurrentlyRunningViewLinkClick();
+    }
+  },
+
+  render: function() {
+  },
+
+  handleCurrentlyRunningViewLinkClick: function() {
+    $('#recently-finished-view-link').removeClass('active');
+    $('#recently-finished-view').hide();
+    $('#currently-running-view-link').addClass('active');
+    $('#currently-running-view').show();
+  },
+
+  handleRecentlyFinishedViewLinkClick: function() {
+    $('#currently-running-view-link').removeClass('active');
+    $('#currently-running-view').hide();
+    $('#recently-finished-view-link').addClass('active');
+    $('#recently-finished-view').show();
+  }
+});
+
+$(function() {
+  executionsTabView = new azkaban.ExecutionsTabView({el: $('#header-tabs')});
+  if (window.location.hash) {
+    var hash = window.location.hash;
+    if (hash == '#recently-finished') {
+      executionsTabView.handleRecentlyFinishedLinkClick();
+    }
+  }
+});
diff --git a/src/web/js/azkaban.exflow.view.js b/src/web/js/azkaban.exflow.view.js
index 0209a2c..4ac616b 100644
--- a/src/web/js/azkaban.exflow.view.js
+++ b/src/web/js/azkaban.exflow.view.js
@@ -396,7 +396,7 @@ azkaban.ExecutionListView = Backbone.View.extend({
 		var flowLastTime = data.endTime == -1 ? (new Date()).getTime() : data.endTime;
 		var flowStartTime = data.startTime;
 
-		var outerWidth = $(".outerProgress").css("width");
+		var outerWidth = $(".flow-progress").css("width");
 		if (outerWidth) {
 			if (outerWidth.substring(outerWidth.length - 2, outerWidth.length) == "px") {
 				outerWidth = outerWidth.substring(0, outerWidth.length - 2);
diff --git a/src/web/js/azkaban.flow.view.js b/src/web/js/azkaban.flow.view.js
index 8d8eb6e..897f09b 100644
--- a/src/web/js/azkaban.flow.view.js
+++ b/src/web/js/azkaban.flow.view.js
@@ -84,7 +84,7 @@ azkaban.FlowTabView = Backbone.View.extend({
 		executionModel.trigger("change:view");
 	},
 
-	handleSummaryLinkClick: function() {
+  handleSummaryLinkClick: function() {
 		$('#graphViewLink').removeClass('active');
 		$('#executionsViewLink').removeClass('active');
 		$('#summaryViewLink').addClass('active');
@@ -181,7 +181,7 @@ azkaban.ExecutionsView = Backbone.View.extend({
 		var total = this.model.get("total");
 		total = total? total : 1;
 		var pageSize = this.model.get("pageSize");
-		var numPages = Math.ceil(total/pageSize);
+		var numPages = Math.ceil(total / pageSize);
 		
 		this.model.set({"numPages": numPages});
 		var page = this.model.get("page");
@@ -295,93 +295,72 @@ azkaban.ExecutionsView = Backbone.View.extend({
 var summaryView;
 azkaban.SummaryView = Backbone.View.extend({
 	events: {
-		"click": "closeEditingTarget",
-		"click table .editable": "handleEditField"
 	},
 	
 	initialize: function(settings) {
 		console.log("summaryView initialize");
 		var general = {
-			flowName: "",
-			flowDescription: "",
 			projectName: projectName,
 			flowId: flowId
 		};
-
-		var scheduling = {};
-		var resources = {};
-		var io = {};
+    /*var schedule = {
+			scheduleId: "0",
+			submitUser: "azkaban",
+			firstSchedTime: "1",
+			nextExecTime: "2",
+			period: "3",
+		};
+    var lastRun = {
+			maxMapSlots: 3,
+			maxReduceSlots: 9999,
+			totalMapSlots: 3,
+			totalReduceSlots: 9999,
+			numJobs: 3,
+			longestTaskTime: 1111
+		};*/
+		var lastRun = null;
 
 		this.model.bind('change:view', this.handleChangeView, this);
 		this.model.bind('render', this.render, this);
-		this.model.set({
-			'general': general,
-			'scheduling': scheduling,
-			'resources': resources,
-			'io': io
-		});
+		
+		this.model.set({'general': general});
+		this.fetchSchedule();
+		this.fetchLastRun();
 		this.model.trigger('render');
 	},
 
-	handleChangeView: function(evt) {
-		console.log("summaryView handleChangeView");
+	fetchSchedule: function() {
+		var requestURL = contextURL + "/schedule"
+		var requestData = {
+			'ajax': 'fetchSchedule',
+			'projectId': projectId,
+			'flowId': flowId
+		};
+		var model = this.model;
+		var successHandler = function(data) {
+			if (data.schedule != null) {
+				model.set({'schedule': data.schedule});
+				model.trigger('render');
+			}
+		};
+		$.get(requestURL, requestData, successHandler, 'json');
 	},
 
-	handleEditField: function(evt) {
-		var curTarget = evt.currentTarget;
-		console.log("summaryView handleEditField");
-		if (this.editingTarget != curTarget) {
-			this.closeEditingTarget(evt);
-
-			var text = $(curTarget).children('.spanValue').text();
-			$(curTarget).empty();
-
-			var input = document.createElement('input');
-			$(input).attr('type', 'text');
-			$(input).css('width', '100%');
-			$(input).val(text);
-
-			$(curTarget).addClass('editing');
-			$(curTarget).append(input);
-			$(input).focus();
-			var obj = this;
-			$(input).keypress(function(evt) {
-				if (evt.which == 13) {
-					obj.closeEditingTarget(evt);
-				}
-			});
-			this.editingTarget = curTarget;
-		}
-		evt.preventDefault();
-		evt.stopPropagation();
+	fetchLastRun: function() {
+
 	},
 
-	closeEditingTarget: function(evt) {
-		console.log("summaryView closeEditingTarget");
-		if (this.editingTarget != null &&
-				this.editingTarget != evt.target &&
-				this.editingTarget != evt.target.myparent) {
-			var input = $(this.editingTarget).children("input")[0];
-			var text = $(input).val();
-			$(input).remove();
-
-			var valueData = document.createElement("span");
-			$(valueData).addClass("spanValue");
-			$(valueData).text(text);
-
-			$(this.editingTarget).removeClass("editing");
-			$(this.editingTarget).append(valueData);
-			valueData.myparent = this.editingTarget;
-			this.editingTarget = null;
-		}
+	handleChangeView: function(evt) {
+		console.log("summaryView handleChangeView");
 	},
-	
+
 	render: function(evt) {
 		console.log("summaryView render");
 		var data = {
+			flowName: flowId,
 			general: this.model.get('general'),
-			scheduling: this.model.get('scheduling'),
-			resources: this.model.get('resources')
+			schedule: this.model.get('schedule'),
+			lastRun: this.model.get('lastRun')
 		};
 		dust.render("flowsummary", data, function(err, out) {
 			$('#summaryView').html(out);
@@ -454,12 +433,14 @@ $(function() {
 		el: $('#executionsView'), 
 		model: executionModel
 	});
-	summaryModel = new azkaban.SummaryModel();
+	
+  summaryModel = new azkaban.SummaryModel();
 	summaryView = new azkaban.SummaryView({
 		el: $('#summaryView'),
 		model: summaryModel
 	});
-	flowTabView = new azkaban.FlowTabView({
+	
+  flowTabView = new azkaban.FlowTabView({
 		el: $('#headertabs'), 
 		selectedView: selected 
 	});
@@ -474,7 +455,8 @@ $(function() {
 			"graph": exGraphClickCallback 
 		}
 	});
-	jobsListView = new azkaban.JobListView({
+	
+  jobsListView = new azkaban.JobListView({
 		el: $('#jobList'), 
 		model: graphModel, 
 		contextMenuCallback: exJobClickCallback
diff --git a/src/web/js/azkaban.history.view.js b/src/web/js/azkaban.history.view.js
index ebd2179..a381e74 100644
--- a/src/web/js/azkaban.history.view.js
+++ b/src/web/js/azkaban.history.view.js
@@ -23,17 +23,15 @@ azkaban.AdvFilterView = Backbone.View.extend({
 	},
 	
 	initialize: function(settings) {
-		$( "#datetimebegin" ).datetimepicker({
-			dateFormat: "mm/dd/yy",
-			separator: '-',
-			timeFormat: "HH:mm"
-		});
-		$( "#datetimeend" ).datetimepicker({
-			dateFormat: "mm/dd/yy",
-			separator: '-',
-			timeFormat: "HH:mm"
-		});
-		$("#adv-filter-error-msg").hide();
+		$('#datetimebegin').datetimepicker();
+		$('#datetimeend').datetimepicker();
+		$('#datetimebegin').on('change.dp', function(e) {
+      $('#datetimeend').data('DateTimePicker').setStartDate(e.date);
+    });
+		$('#datetimeend').on('change.dp', function(e) {
+      $('#datetimebegin').data('DateTimePicker').setEndDate(e.date);
+    });
+		$('#adv-filter-error-msg').hide();
 	},
 	
 	handleAdvFilter: function(evt) {
diff --git a/src/web/js/azkaban.jobedit.view.js b/src/web/js/azkaban.jobedit.view.js
index b1441c8..0e62de1 100644
--- a/src/web/js/azkaban.jobedit.view.js
+++ b/src/web/js/azkaban.jobedit.view.js
@@ -236,7 +236,7 @@ azkaban.JobEditView = Backbone.View.extend({
 
 			$(this.editingTarget).removeClass("editing");
 			$(this.editingTarget).append(valueData);
-			valueData.myparent=this.editingTarget;
+			valueData.myparent = this.editingTarget;
 			this.editingTarget = null;
 		}
 	}
diff --git a/src/web/js/azkaban.main.view.js b/src/web/js/azkaban.main.view.js
index e0d10c6..62dc8f5 100644
--- a/src/web/js/azkaban.main.view.js
+++ b/src/web/js/azkaban.main.view.js
@@ -26,7 +26,7 @@ azkaban.ProjectTableView = Backbone.View.extend({
 	},
 	
 	expandProject: function(evt) {
-		if (evt.target.tagName != "SPAN") {
+		if (evt.target.tagName == "A") {
 			return;
 		}
 		
@@ -44,10 +44,16 @@ azkaban.ProjectTableView = Backbone.View.extend({
 		else if (target.loaded) {
 			if ($(targetExpanded).is(':visible')) {
 				$(target).addClass('expanded').removeClass('collapsed');
+				var expander = $(target).children('.az-expander')[0];
+				$(expander).removeClass('glyphicon-chevron-up');
+				$(expander).addClass('glyphicon-chevron-down');
 				$(targetExpanded).fadeOut("fast");
 			}
 			else {
 				$(target).addClass('collapsed').removeClass('expanded');
+				var expander = $(target).children('.az-expander')[0];
+				$(expander).removeClass('glyphicon-chevron-down');
+				$(expander).addClass('glyphicon-chevron-up');
 				$(targetExpanded).fadeIn();
 			}
 		}
@@ -69,6 +75,9 @@ azkaban.ProjectTableView = Backbone.View.extend({
 				createFlowListFunction(data, targetTBody);
 				
 				$(target).addClass('collapsed').removeClass('wait');
+				var expander = $(target).children('.az-expander')[0];
+				$(expander).removeClass('glyphicon-chevron-down');
+				$(expander).addClass('glyphicon-chevron-up');
 				$(targetExpanded).fadeIn("fast");
 			};
 			
diff --git a/src/web/js/azkaban.project.view.js b/src/web/js/azkaban.project.view.js
index a1b8f3d..6f04950 100644
--- a/src/web/js/azkaban.project.view.js
+++ b/src/web/js/azkaban.project.view.js
@@ -16,67 +16,6 @@
 
 $.namespace('azkaban');
 
-var projectView;
-azkaban.ProjectView = Backbone.View.extend({
-	events: {
-		"click #project-upload-btn": "handleUploadProjectJob",
-		"click #project-delete-btn": "handleDeleteProject"
-	},
-
-	initialize: function(settings) {
-	},
-
-	handleUploadProjectJob: function(evt) {
-		console.log("click upload project");
-		$('#upload-project-modal').modal();
-	},
-
-	handleDeleteProject: function(evt) {
-		console.log("click delete project");
-		$('#delete-project-modal').modal();
-	},
-	
-	render: function() {
-	}
-});
-
-var uploadProjectView;
-azkaban.UploadProjectView = Backbone.View.extend({
-	events: {
-		"click #upload-project-btn": "handleCreateProject"
-	},
-
-	initialize: function(settings) {
-		console.log("Hide upload project modal error msg");
-		$("#upload-project-modal-error-msg").hide();
-	},
-	
-	handleCreateProject: function(evt) {
-		console.log("Upload project button.");
-		$("#upload-project-form").submit();
-	},
-	
-	render: function() {
-	}
-});
-
-var deleteProjectView;
-azkaban.DeleteProjectView = Backbone.View.extend({
-	events: {
-		"click #delete-btn": "handleDeleteProject"
-	},
-	
-	initialize: function(settings) {
-	},
-	
-	handleDeleteProject: function(evt) {
-		$("#delete-form").submit();
-	},
-
-	render: function() {
-	}
-});
-
 var flowTableView;
 azkaban.FlowTableView = Backbone.View.extend({
 	events : {
@@ -294,65 +233,6 @@ azkaban.FlowTableView = Backbone.View.extend({
 	}
 });
 
-var projectSummary;
-azkaban.ProjectSummaryView = Backbone.View.extend({
-	events: {
-		"click #edit": "handleDescriptionEdit"
-	},
-
-	initialize: function(settings) {
-	},
-	
-	handleDescriptionEdit: function(evt) {
-		console.log("Edit description");
-		var editText = $("#edit").text();
-		var descriptionTD = $('#pdescription');
-		
-		if (editText != "Edit Description") {
-			var requestURL = contextURL + "/manager";
-			var newText = $("#descEdit").val();
-
-			$.get(
-				requestURL,
-				{
-					"project": projectName, 
-					"ajax":"changeDescription", 
-					"description":newText
-				},
-				function(data) {
-					if (data.error) {
-						alert(data.error);
-					}
-				},
-				"json"
-			);
-				
-			$(descriptionTD).remove("#descEdit");
-			$(descriptionTD).text(newText);
-			$("#edit").text("Edit Description");
-		}
-		else {
-			var text = $(descriptionTD).text();
-			var edit = document.createElement("textarea");
-			
-			$(edit).addClass("editTextArea");
-			$(edit).attr("id", "descEdit");
-			$(edit).val(text);
-			$(descriptionTD).text("");
-			$(descriptionTD).append(edit);
-			
-			$("#edit").text("Commit");
-		}
-	},
-	render: function() {
-	}
-});
-
 $(function() {
-	projectView = new azkaban.ProjectView({el:$('#project-options')});
-	uploadView = new azkaban.UploadProjectView({el:$('#upload-project-modal')});
 	flowTableView = new azkaban.FlowTableView({el:$('#flow-tabs')});
-	projectSummary = new azkaban.ProjectSummaryView({el:$('#project-summary')});
-	deleteProjectView = new azkaban.DeleteProjectView({el: $('#delete-project-modal')});
-	// Setting up the project tabs
 });
diff --git a/src/web/js/azkaban.projectmodals.view.js b/src/web/js/azkaban.projectmodals.view.js
new file mode 100644
index 0000000..0362b8a
--- /dev/null
+++ b/src/web/js/azkaban.projectmodals.view.js
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2012 LinkedIn Corp.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+$.namespace('azkaban');
+
+var projectView;
+azkaban.ProjectView = Backbone.View.extend({
+	events: {
+		"click #project-upload-btn": "handleUploadProjectJob",
+		"click #project-delete-btn": "handleDeleteProject"
+	},
+
+	initialize: function(settings) {
+	},
+
+	handleUploadProjectJob: function(evt) {
+		console.log("click upload project");
+		$('#upload-project-modal').modal();
+	},
+
+	handleDeleteProject: function(evt) {
+		console.log("click delete project");
+		$('#delete-project-modal').modal();
+	},
+	
+	render: function() {
+	}
+});
+
+var uploadProjectView;
+azkaban.UploadProjectView = Backbone.View.extend({
+	events: {
+		"click #upload-project-btn": "handleCreateProject"
+	},
+
+	initialize: function(settings) {
+		console.log("Hide upload project modal error msg");
+		$("#upload-project-modal-error-msg").hide();
+	},
+	
+	handleCreateProject: function(evt) {
+		console.log("Upload project button.");
+		$("#upload-project-form").submit();
+	},
+	
+	render: function() {
+	}
+});
+
+var deleteProjectView;
+azkaban.DeleteProjectView = Backbone.View.extend({
+	events: {
+		"click #delete-btn": "handleDeleteProject"
+	},
+	
+	initialize: function(settings) {
+	},
+	
+	handleDeleteProject: function(evt) {
+		$("#delete-form").submit();
+	},
+
+	render: function() {
+	}
+});
+
+var projectSummary;
+azkaban.ProjectSummaryView = Backbone.View.extend({
+	events: {
+		"click #edit": "handleDescriptionEdit"
+	},
+
+	initialize: function(settings) {
+	},
+	
+	handleDescriptionEdit: function(evt) {
+		console.log("Edit description");
+		var editText = $("#edit").text();
+		var descriptionTD = $('#pdescription');
+		
+		if (editText != "Edit Description") {
+			var requestURL = contextURL + "/manager";
+			var newText = $("#descEdit").val();
+
+			$.get(
+				requestURL,
+				{
+					"project": projectName, 
+					"ajax":"changeDescription", 
+					"description":newText
+				},
+				function(data) {
+					if (data.error) {
+						alert(data.error);
+					}
+				},
+				"json"
+			);
+				
+			$(descriptionTD).remove("#descEdit");
+			$(descriptionTD).text(newText);
+			$("#edit").text("Edit Description");
+		}
+		else {
+			var text = $(descriptionTD).text();
+			var edit = document.createElement("textarea");
+			
+			$(edit).addClass("editTextArea");
+			$(edit).attr("id", "descEdit");
+			$(edit).val(text);
+			$(descriptionTD).text("");
+			$(descriptionTD).append(edit);
+			
+			$("#edit").text("Commit");
+		}
+	},
+	render: function() {
+	}
+});
+
+$(function() {
+	projectView = new azkaban.ProjectView({el:$('#project-options')});
+	uploadView = new azkaban.UploadProjectView({el:$('#upload-project-modal')});
+	deleteProjectView = new azkaban.DeleteProjectView({el: $('#delete-project-modal')});
+	projectSummary = new azkaban.ProjectSummaryView({el:$('#project-summary')});
+});
diff --git a/src/web/js/azkaban.schedule.panel.view.js b/src/web/js/azkaban.schedule.panel.view.js
index 2e26845..1541fbb 100644
--- a/src/web/js/azkaban.schedule.panel.view.js
+++ b/src/web/js/azkaban.schedule.panel.view.js
@@ -24,9 +24,7 @@ azkaban.SchedulePanelView = Backbone.View.extend({
 
 	initialize: function(settings) {
 		$("#datepicker").css("backgroundColor", "transparent");
-		$("#datepicker").datepicker();
-		$("#datepicker").datepicker('setDate', new Date());
-		$("#datepicker").datepicker("hide");
+		$("#datepicker").datetimepicker({pickTime: false});
 	},
 
 	render: function() {
diff --git a/src/web/js/azkaban.scheduled.view.js b/src/web/js/azkaban.scheduled.view.js
index 25cad1c..dcc6c35 100644
--- a/src/web/js/azkaban.scheduled.view.js
+++ b/src/web/js/azkaban.scheduled.view.js
@@ -177,10 +177,10 @@ azkaban.ChangeSlaView = Backbone.View.extend({
 						}
 					}
 					cKill.appendChild(killCheck);
-					$('.durationpick').timepicker({hourMax: 99});
+					$('.durationpick').datetimepicker({ pickDate: false });
 				}
 			}
-			$('.durationpick').timepicker({hourMax: 99});
+      $('.durationpick').datetimepicker({ pickDate: false });
 		};
 
 		$.get(this.scheduleURL, fetchScheduleData, successHandler, "json");
@@ -285,7 +285,7 @@ azkaban.ChangeSlaView = Backbone.View.extend({
 		killCheck.type = "checkbox";
 		cKill.appendChild(killCheck);
 		
-		$('.durationpick').timepicker({hourMax: 99});
+    $('.durationpick').datetimepicker({ pickDate: false });
 		return rFlowRule;
 	},
 	
diff --git a/src/web/js/bootstrap-datetimepicker.min.js b/src/web/js/bootstrap-datetimepicker.min.js
index 12d186f..3bc74fc 100644
--- a/src/web/js/bootstrap-datetimepicker.min.js
+++ b/src/web/js/bootstrap-datetimepicker.min.js
@@ -25,4 +25,4 @@
  * limitations under the License.
  * =========================================================
  */
-(function(d){if(typeof moment==="undefined"){alert("momentjs is requried");throw new Error("momentjs is requried")}var c=0,a=moment,b=function(g,i){var s={pickDate:true,pickTime:true,startDate:new a({y:1970}),endDate:new a().add(50,"y"),collapse:true,language:"en",defaultDate:"",disabledDates:[],icons:{},useStrict:false},K={time:"glyphicon glyphicon-time",date:"glyphicon glyphicon-calendar",up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down"},q=this,E=function(){var O=false,N,P,M;q.options=d.extend({},s,i);q.options.icons=d.extend({},K,q.options.icons);if(!(q.options.pickTime||q.options.pickDate)){throw new Error("Must choose at least one picker")}q.id=c++;a.lang(q.options.language);q.date=a();q.element=d(g);q.unset=false;q.isInput=q.element.is("input");q.component=false;if(q.element.hasClass("input-group")){if(q.element.find(".datepickerbutton").size()==0){q.component=q.element.find(".input-group-addon")}else{q.component=q.element.find(".datepickerbutton")}}q.format=q.options.format;M=a()._lang._longDateFormat;if(!q.format){if(q.isInput){q.format=q.element.data("format")}else{q.format=q.element.find("input").data("format")}if(!q.format){q.format=(q.options.pickDate?M.L:"");if(q.options.pickDate&&q.options.pickTime){q.format+=" "}q.format+=(q.options.pickTime?M.LT:"")}}q.use24hours=q.format.toLowerCase().indexOf("a")<1;if(q.component){O=q.component.find("span")}if(q.options.pickTime){if(O){O.addClass(q.options.icons.time)}}if(q.options.pickDate){if(O){O.removeClass(q.options.icons.time);O.addClass(q.options.icons.date)}}q.widget=d(I(q.options.pickDate,q.options.pickTime,q.options.collapse)).appendTo("body");q.minViewMode=q.options.minViewMode||q.element.data("date-minviewmode")||0;if(typeof q.minViewMode==="string"){switch(q.minViewMode){case"months":q.minViewMode=1;break;case"years":q.minViewMode=2;break;default:q.minViewMode=0;break}}q.viewMode=q.options.viewMode||q.element.data("date-viewmode")||0;if(typeof q.viewMode==="string"){switch(q.viewMode){case"months":q.viewMode=1;break;case"years":q.viewMode=2;break;default:q.viewMode=0;break}}for(N=0;N<q.options.disabledDates.length;N++){P=q.options.disabledDates[N];P=a(P);if(!P.isValid()){P=a(q.options.startDate).subtract(1,"day")}q.options.disabledDates[N]=P.format("L")}q.startViewMode=q.viewMode;q.setStartDate(q.options.startDate||q.element.data("date-startdate"));q.setEndDate(q.options.endDate||q.element.data("date-enddate"));H();L();l();C();n();f();J();if(q.options.defaultDate!==""){q.setValue(q.options.defaultDate)}},o=function(){var M="absolute",O=q.component?q.component.offset():q.element.offset(),N=d(window);q.width=q.component?q.component.outerWidth():q.element.outerWidth();O.top=O.top+q.element.outerHeight();if(q.options.width!==undefined){q.widget.width(q.options.width)}if(q.options.orientation==="left"){q.widget.addClass("left-oriented");O.left=O.left-q.widget.width()+20}if(A()){M="fixed";O.top-=N.scrollTop();O.left-=N.scrollLeft()}if(N.width()<O.left+q.widget.outerWidth()){O.right=N.width()-O.left-q.width;O.left="auto";q.widget.addClass("pull-right")}else{O.right="auto";q.widget.removeClass("pull-right")}q.widget.css({position:M,top:O.top,left:O.left,right:O.right})},z=function(M){q.element.trigger({type:"change.dp",date:q.getDate(),oldDate:M})},w=function(M){q.element.trigger({type:"error.dp",date:M})},n=function(M){a.lang(q.options.language);var N=M;if(!N){if(q.isInput){N=q.element.val()}else{N=q.element.find("input").val()}if(N){q.date=a(N,q.format,q.options.useStrict)}if(!q.date){q.date=a()}}q.viewDate=a(q.date).startOf("month");h();y()},H=function(){a.lang(q.options.language);var O=d("<tr>"),M=a.weekdaysMin(),N;if(a()._lang._week.dow==0){for(N=0;N<7;N++){O.append('<th class="dow">'+M[N]+"</th>")}}else{for(N=1;N<8;N++){if(N==7){O.append('<th class="dow">'+M[0]+"</th>")}else{O.append('<th class="dow">'+M[N]+"</th>")}}}q.widget.find(".datepicker-days thead").append(O)},L=function(){a.lang(q.options.language);var N="",M=0,O=a.monthsShort();while(M<12){N+='<span class="month">'+O[M++]+"</span>"}q.widget.find(".datepicker-months td").append(N)},h=function(){a.lang(q.options.language);var X=q.viewDate.year(),V=q.viewDate.month(),W=q.options.startDate.year(),Z=q.options.startDate.month(),aa=q.options.endDate.year(),T=q.options.endDate.month(),P,S,R=[],ab,O,Q,Y,N,U,M=a.months();q.widget.find(".datepicker-days").find(".disabled").removeClass("disabled");q.widget.find(".datepicker-months").find(".disabled").removeClass("disabled");q.widget.find(".datepicker-years").find(".disabled").removeClass("disabled");q.widget.find(".datepicker-days th:eq(1)").text(M[V]+" "+X);P=a(q.viewDate).subtract("months",1);Y=P.daysInMonth();P.date(Y).startOf("week");if((X==W&&V<=Z)||X<W){q.widget.find(".datepicker-days th:eq(0)").addClass("disabled")}if((X==aa&&V>=T)||X>aa){q.widget.find(".datepicker-days th:eq(2)").addClass("disabled")}S=a(P).add(42,"d");while(P.isBefore(S)){if(P.weekday()===a().startOf("week").weekday()){ab=d("<tr>");R.push(ab)}O="";if(P.year()<X||(P.year()==X&&P.month()<V)){O+=" old"}else{if(P.year()>X||(P.year()==X&&P.month()>V)){O+=" new"}}if(P.isSame(a({y:q.date.year(),M:q.date.month(),d:q.date.date()}))){O+=" active"}if((a(P).add(1,"d")<=q.options.startDate)||(P>q.options.endDate)||e(P)){O+=" disabled"}ab.append('<td class="day'+O+'">'+P.date()+"</td>");P.add(1,"d")}q.widget.find(".datepicker-days tbody").empty().append(R);U=a().year(),M=q.widget.find(".datepicker-months").find("th:eq(1)").text(X).end().find("span").removeClass("active");if(U===X){M.eq(a().month()).addClass("active")}if(U-1<W){q.widget.find(".datepicker-months th:eq(0)").addClass("disabled")}if(U+1>aa){q.widget.find(".datepicker-months th:eq(2)").addClass("disabled")}for(Q=0;Q<12;Q++){if((X==W&&Z>Q)||(X<W)){d(M[Q]).addClass("disabled")}else{if((X==aa&&T<Q)||(X>aa)){d(M[Q]).addClass("disabled")}}}R="";X=parseInt(X/10,10)*10;N=q.widget.find(".datepicker-years").find("th:eq(1)").text(X+"-"+(X+9)).end().find("td");q.widget.find(".datepicker-years").find("th").removeClass("disabled");if(W>X){q.widget.find(".datepicker-years").find("th:eq(0)").addClass("disabled")}if(aa<X+9){q.widget.find(".datepicker-years").find("th:eq(2)").addClass("disabled")}X-=1;for(Q=-1;Q<11;Q++){R+='<span class="year'+(Q===-1||Q===10?" old":"")+(U===X?" active":"")+((X<W||X>aa)?" disabled":"")+'">'+X+"</span>";X+=1}N.html(R)},l=function(){a.lang(q.options.language);var P=q.widget.find(".timepicker .timepicker-hours table"),O="",Q,N,M;P.parent().hide();if(q.use24hours){Q=0;for(N=0;N<6;N+=1){O+="<tr>";for(M=0;M<4;M+=1){O+='<td class="hour">'+D(Q.toString())+"</td>";Q++}O+="</tr>"}}else{Q=1;for(N=0;N<3;N+=1){O+="<tr>";for(M=0;M<4;M+=1){O+='<td class="hour">'+D(Q.toString())+"</td>";Q++}O+="</tr>"}}P.html(O)},C=function(){var P=q.widget.find(".timepicker .timepicker-minutes table"),O="",Q=0,N,M;P.parent().hide();for(N=0;N<5;N++){O+="<tr>";for(M=0;M<4;M+=1){O+='<td class="minute">'+D(Q.toString())+"</td>";Q+=3}O+="</tr>"}P.html(O)},y=function(){if(!q.date){return}var O=q.widget.find(".timepicker span[data-time-component]"),M=q.date.hours(),N="AM";if(!q.use24hours){if(M>=12){N="PM"}if(M===0){M=12}else{if(M!=12){M=M%12}}q.widget.find(".timepicker [data-action=togglePeriod]").text(N)}O.filter("[data-time-component=hours]").text(D(M));O.filter("[data-time-component=minutes]").text(D(q.date.minutes()))},B=function(S){S.stopPropagation();S.preventDefault();q.unset=false;var R=d(S.target).closest("span, td, th"),Q,O,P,M,N=q.date;if(R.length===1){if(!R.is(".disabled")){switch(R[0].nodeName.toLowerCase()){case"th":switch(R[0].className){case"switch":f(1);break;case"prev":case"next":P=G.modes[q.viewMode].navStep;if(R[0].className==="prev"){P=P*-1}q.viewDate.add(P,G.modes[q.viewMode].navFnc);h();break}break;case"span":if(R.is(".month")){Q=R.parent().find("span").index(R);q.viewDate.month(Q)}else{O=parseInt(R.text(),10)||0;q.viewDate.year(O)}if(q.viewMode!==0){q.date=a({y:q.viewDate.year(),M:q.viewDate.month(),d:q.viewDate.date(),h:q.date.hours(),m:q.date.minutes()});z(N)}f(-1);h();break;case"td":if(R.is(".day")){M=parseInt(R.text(),10)||1;Q=q.viewDate.month();O=q.viewDate.year();if(R.is(".old")){if(Q===0){Q=11;O-=1}else{Q-=1}}else{if(R.is(".new")){if(Q==11){Q=0;O+=1}else{Q+=1}}}q.date=a({y:O,M:Q,d:M,h:q.date.hours(),m:q.date.minutes()});q.viewDate=a({y:O,M:Q,d:Math.min(28,M)});h();x();z(N)}break}}}},r={incrementHours:function(){j("add","hours")},incrementMinutes:function(){j("add","minutes")},decrementHours:function(){j("subtract","hours")},decrementMinutes:function(){j("subtract","minutes")},togglePeriod:function(){var M=q.date.hours();if(M>=12){M-=12}else{M+=12}q.date.hours(M)},showPicker:function(){q.widget.find(".timepicker > div:not(.timepicker-picker)").hide();q.widget.find(".timepicker .timepicker-picker").show()},showHours:function(){q.widget.find(".timepicker .timepicker-picker").hide();q.widget.find(".timepicker .timepicker-hours").show()},showMinutes:function(){q.widget.find(".timepicker .timepicker-picker").hide();q.widget.find(".timepicker .timepicker-minutes").show()},selectHour:function(M){q.date.hours(parseInt(d(M.target).text(),10));r.showPicker.call(q)},selectMinute:function(M){q.date.minutes(parseInt(d(M.target).text(),10));r.showPicker.call(q)}},v=function(O){var N=d(O.currentTarget).data("action"),P=r[N].apply(q,arguments),M=q.date;F(O);if(!q.date){q.date=a({y:1970})}x();y();z(M);return P},F=function(M){M.stopPropagation();M.preventDefault()},u=function(O){a.lang(q.options.language);var M=d(O.target),N=q.date,P=a(M.val(),q.format,q.options.useStrict);if(P.isValid()){n();q.setValue(P);z(N);x()}else{q.viewDate=N;z(N);w(P);q.unset=true;M.val("")}},f=function(M){if(M){q.viewMode=Math.max(q.minViewMode,Math.min(2,q.viewMode+M))}q.widget.find(".datepicker > div").hide().filter(".datepicker-"+G.modes[q.viewMode].clsName).show()},J=function(){var Q,P,N,M,O;q.widget.on("click",".datepicker *",d.proxy(B,this));q.widget.on("click","[data-action]",d.proxy(v,this));q.widget.on("mousedown",d.proxy(F,this));if(q.options.pickDate&&q.options.pickTime){q.widget.on("click.togglePicker",".accordion-toggle",function(R){R.stopPropagation();Q=d(this);P=Q.closest("ul");N=P.find(".in");M=P.find(".collapse:not(.in)");if(N&&N.length){O=N.data("collapse");if(O&&O.transitioning){return}N.collapse("hide");M.collapse("show");Q.find("span").toggleClass(q.options.icons.time+" "+q.options.icons.date);q.element.find(".input-group-addon span").toggleClass(q.options.icons.time+" "+q.options.icons.date)}})}if(q.isInput){q.element.on({focus:d.proxy(q.show,this),change:d.proxy(u,this),blur:d.proxy(q.hide,this)})}else{q.element.on({change:d.proxy(u,this)},"input");if(q.component){q.component.on("click",d.proxy(q.show,this))}else{q.element.on("click",d.proxy(q.show,this))}}},p=function(){d(window).on("resize.datetimepicker"+q.id,d.proxy(o,this));if(!q.isInput){d(document).on("mousedown.datetimepicker"+q.id,d.proxy(q.hide,this))}},t=function(){q.widget.off("click",".datepicker *",q.click);q.widget.off("click","[data-action]");q.widget.off("mousedown",q.stopEvent);if(q.options.pickDate&&q.options.pickTime){q.widget.off("click.togglePicker")}if(q.isInput){q.element.off({focus:q.show,change:q.change})}else{q.element.off({change:q.change},"input");if(q.component){q.component.off("click",q.show)}else{q.element.off("click",q.show)}}},k=function(){d(window).off("resize.datetimepicker"+q.id);if(!q.isInput){d(document).off("mousedown.datetimepicker"+q.id)}},A=function(){if(q.element){var N=q.element.parents(),M=false,O;for(O=0;O<N.length;O++){if(d(N[O]).css("position")=="fixed"){M=true;break}}return M}else{return false}},x=function(){a.lang(q.options.language);var N="",M;if(!q.unset){N=a(q.date).format(q.format)}if(!q.isInput){if(q.component){M=q.element.find("input");M.val(N)}q.element.data("date",N)}else{q.element.val(N)}if(!q.options.pickTime){q.hide()}},j=function(O,N){a.lang(q.options.language);var M;if(O=="add"){M=a(q.date);if(M.hours()==23){M.add(1,N)}M.add(1,N)}else{M=a(q.date).subtract(1,N)}if(M.isAfter(q.options.endDate)||M.subtract(1,N).isBefore(q.options.startDate)||e(M)){w(M.format(q.format));return}if(O=="add"){q.date.add(1,N)}else{q.date.subtract(1,N)}},e=function(M){a.lang(q.options.language);var O=q.options.disabledDates,N;for(N in O){if(O[N]==a(M).format("L")){return true}}return false},D=function(M){M=M.toString();if(M.length>=2){return M}else{return"0"+M}},I=function(N,M,O){if(N&&M){return('<div class="bootstrap-datetimepicker-widget dropdown-menu" style="z-index:9999 !important;"><ul class="list-unstyled"><li'+(O?' class="collapse in"':"")+'><div class="datepicker">'+G.template+'</div></li><li class="picker-switch accordion-toggle"><a class="btn" style="width:100%"><span class="'+q.options.icons.time+'"></span></a></li><li'+(O?' class="collapse"':"")+'><div class="timepicker">'+m.getTemplate()+"</div></li></ul></div>")}else{if(M){return('<div class="bootstrap-datetimepicker-widget dropdown-menu"><div class="timepicker">'+m.getTemplate()+"</div></div>")}else{return('<div class="bootstrap-datetimepicker-widget dropdown-menu"><div class="datepicker">'+G.template+"</div></div>")}}},G={modes:[{clsName:"days",navFnc:"month",navStep:1},{clsName:"months",navFnc:"year",navStep:1},{clsName:"years",navFnc:"year",navStep:10}],headTemplate:'<thead><tr><th class="prev">&lsaquo;</th><th colspan="5" class="switch"></th><th class="next">&rsaquo;</th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>'},m={hourTemplate:'<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>',minuteTemplate:'<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>'};G.template='<div class="datepicker-days"><table class="table-condensed">'+G.headTemplate+'<tbody></tbody></table></div><div class="datepicker-months"><table class="table-condensed">'+G.headTemplate+G.contTemplate+'</table></div><div class="datepicker-years"><table class="table-condensed">'+G.headTemplate+G.contTemplate+"</table></div>";m.getTemplate=function(){return('<div class="timepicker-picker"><table class="table-condensed"><tr><td><a href="#" class="btn" data-action="incrementHours"><span class="'+q.options.icons.up+'"></span></a></td><td class="separator"></td><td><a href="#" class="btn" data-action="incrementMinutes"><span class="'+q.options.icons.up+'"></span></a></td>'+(!q.use24hours?'<td class="separator"></td>':"")+"</tr><tr><td>"+m.hourTemplate+'</td> <td class="separator">:</td><td>'+m.minuteTemplate+"</td> "+(!q.use24hours?'<td class="separator"></td><td><button type="button" class="btn btn-primary" data-action="togglePeriod"></button></td>':"")+'</tr><tr><td><a href="#" class="btn" data-action="decrementHours"><span class="'+q.options.icons.down+'"></span></a></td><td class="separator"></td><td><a href="#" class="btn" data-action="decrementMinutes"><span class="'+q.options.icons.down+'"></span></a></td>'+(!q.use24hours?'<td class="separator"></td>':"")+'</tr></table></div><div class="timepicker-hours" data-action="selectHour"><table class="table-condensed"></table></div><div class="timepicker-minutes" data-action="selectMinute"><table class="table-condensed"></table></div>')};q.destroy=function(){t();k();q.widget.remove();q.element.removeData("DateTimePicker");q.component.removeData("DateTimePicker")};q.show=function(M){q.widget.show();q.height=q.component?q.component.outerHeight():q.element.outerHeight();o();q.element.trigger({type:"show.dp",date:q.date});p();if(M){F(M)}},q.disable=function(){q.element.find("input").prop("disabled",true);t()},q.enable=function(){q.element.find("input").prop("disabled",false);J()},q.hide=function(){var O=q.widget.find(".collapse"),M,N;for(M=0;M<O.length;M++){N=O.eq(M).data("collapse");if(N&&N.transitioning){return}}q.widget.hide();q.viewMode=q.startViewMode;f();q.element.trigger({type:"hide.dp",date:q.date});k()},q.setValue=function(M){a.lang(q.options.language);if(!M){q.unset=true}else{q.unset=false}if(!a.isMoment(M)){M=a(M)}if(M.isValid()){q.date=M;x();q.viewDate=a({y:q.date.year(),M:q.date.month()});h();y()}else{w(M)}},q.getDate=function(){if(q.unset){return null}return q.date},q.setDate=function(M){if(!M){q.setValue(null)}else{q.setValue(M)}},q.setEndDate=function(M){q.options.endDate=a(M);if(!q.options.endDate.isValid()){q.options.endDate=a().add(50,"y")}if(q.viewDate){n()}},q.setStartDate=function(M){q.options.startDate=a(M);if(!q.options.startDate.isValid()){q.options.startDate=a({y:1970})}if(q.viewDate){n()}};E()};d.fn.datetimepicker=function(e){return this.each(function(){var g=d(this),f=g.data("DateTimePicker");if(!f){g.data("DateTimePicker",new b(this,e))}})}})(jQuery);
\ No newline at end of file
+(function($){if(typeof moment==="undefined"){alert("momentjs is requried");throw new Error("momentjs is requried")}var dpgId=0,pMoment=moment,DateTimePicker=function(element,options){var defaults={pickDate:true,pickTime:true,startDate:new pMoment({y:1970}),endDate:(new pMoment).add(50,"y"),collapse:true,language:"en",defaultDate:"",disabledDates:[],icons:{},useStrict:false},icons={time:"glyphicon glyphicon-time",date:"glyphicon glyphicon-calendar",up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down"},picker=this,init=function(){var icon=false,i,dDate,longDateFormat;picker.options=$.extend({},defaults,options);picker.options.icons=$.extend({},icons,picker.options.icons);if(!(picker.options.pickTime||picker.options.pickDate))throw new Error("Must choose at least one picker");picker.id=dpgId++;pMoment.lang(picker.options.language);picker.date=pMoment();picker.element=$(element);picker.unset=false;picker.isInput=picker.element.is("input");picker.component=false;if(picker.element.hasClass("input-group")){if(picker.element.find(".datepickerbutton").size()==0){picker.component=picker.element.find(".input-group-addon")}else{picker.component=picker.element.find(".datepickerbutton")}}picker.format=picker.options.format;longDateFormat=pMoment()._lang._longDateFormat;if(!picker.format){if(picker.isInput)picker.format=picker.element.data("format");else picker.format=picker.element.find("input").data("format");if(!picker.format){picker.format=picker.options.pickDate?longDateFormat.L:"";if(picker.options.pickDate&&picker.options.pickTime)picker.format+=" ";picker.format+=picker.options.pickTime?longDateFormat.LT:""}}picker.use24hours=picker.format.toLowerCase().indexOf("a")<1;if(picker.component)icon=picker.component.find("span");if(picker.options.pickTime){if(icon)icon.addClass(picker.options.icons.time)}if(picker.options.pickDate){if(icon){icon.removeClass(picker.options.icons.time);icon.addClass(picker.options.icons.date)}}picker.widget=$(getTemplate(picker.options.pickDate,picker.options.pickTime,picker.options.collapse)).appendTo("body");picker.minViewMode=picker.options.minViewMode||picker.element.data("date-minviewmode")||0;if(typeof picker.minViewMode==="string"){switch(picker.minViewMode){case"months":picker.minViewMode=1;break;case"years":picker.minViewMode=2;break;default:picker.minViewMode=0;break}}picker.viewMode=picker.options.viewMode||picker.element.data("date-viewmode")||0;if(typeof picker.viewMode==="string"){switch(picker.viewMode){case"months":picker.viewMode=1;break;case"years":picker.viewMode=2;break;default:picker.viewMode=0;break}}for(i=0;i<picker.options.disabledDates.length;i++){dDate=picker.options.disabledDates[i];dDate=pMoment(dDate);if(!dDate.isValid())dDate=pMoment(picker.options.startDate).subtract(1,"day");picker.options.disabledDates[i]=dDate.format("L")}picker.startViewMode=picker.viewMode;picker.setStartDate(picker.options.startDate||picker.element.data("date-startdate"));picker.setEndDate(picker.options.endDate||picker.element.data("date-enddate"));fillDow();fillMonths();fillHours();fillMinutes();update();showMode();attachDatePickerEvents();if(picker.options.defaultDate!=="")picker.setValue(picker.options.defaultDate)},place=function(){var position="absolute",offset=picker.component?picker.component.offset():picker.element.offset(),$window=$(window);picker.width=picker.component?picker.component.outerWidth():picker.element.outerWidth();offset.top=offset.top+picker.element.outerHeight();if(picker.options.width!==undefined){picker.widget.width(picker.options.width)}if(picker.options.orientation==="left"){picker.widget.addClass("left-oriented");offset.left=offset.left-picker.widget.width()+20}if(isInFixed()){position="fixed";offset.top-=$window.scrollTop();offset.left-=$window.scrollLeft()}if($window.width()<offset.left+picker.widget.outerWidth()){offset.right=$window.width()-offset.left-picker.width;offset.left="auto";picker.widget.addClass("pull-right")}else{offset.right="auto";picker.widget.removeClass("pull-right")}picker.widget.css({position:position,top:offset.top,left:offset.left,right:offset.right})},notifyChange=function(oldDate){picker.element.trigger({type:"change.dp",date:picker.getDate(),oldDate:oldDate})},notifyError=function(date){picker.element.trigger({type:"error.dp",date:date})},update=function(newDate){pMoment.lang(picker.options.language);var dateStr=newDate;if(!dateStr){if(picker.isInput){dateStr=picker.element.val()}else{dateStr=picker.element.find("input").val()}if(dateStr)picker.date=pMoment(dateStr,picker.format,picker.options.useStrict);if(!picker.date)picker.date=pMoment()}picker.viewDate=pMoment(picker.date).startOf("month");fillDate();fillTime()},fillDow=function(){pMoment.lang(picker.options.language);var html=$("<tr>"),weekdaysMin=pMoment.weekdaysMin(),i;if(pMoment()._lang._week.dow==0){for(i=0;i<7;i++){html.append('<th class="dow">'+weekdaysMin[i]+"</th>")}}else{for(i=1;i<8;i++){if(i==7){html.append('<th class="dow">'+weekdaysMin[0]+"</th>")}else{html.append('<th class="dow">'+weekdaysMin[i]+"</th>")}}}picker.widget.find(".datepicker-days thead").append(html)},fillMonths=function(){pMoment.lang(picker.options.language);var html="",i=0,monthsShort=pMoment.monthsShort();while(i<12){html+='<span class="month">'+monthsShort[i++]+"</span>"}picker.widget.find(".datepicker-months td").append(html)},fillDate=function(){pMoment.lang(picker.options.language);var year=picker.viewDate.year(),month=picker.viewDate.month(),startYear=picker.options.startDate.year(),startMonth=picker.options.startDate.month(),endYear=picker.options.endDate.year(),endMonth=picker.options.endDate.month(),prevMonth,nextMonth,html=[],row,clsName,i,days,yearCont,currentYear,months=pMoment.months();picker.widget.find(".datepicker-days").find(".disabled").removeClass("disabled");picker.widget.find(".datepicker-months").find(".disabled").removeClass("disabled");picker.widget.find(".datepicker-years").find(".disabled").removeClass("disabled");picker.widget.find(".datepicker-days th:eq(1)").text(months[month]+" "+year);prevMonth=pMoment(picker.viewDate).subtract("months",1);days=prevMonth.daysInMonth();prevMonth.date(days).startOf("week");if(year==startYear&&month<=startMonth||year<startYear){picker.widget.find(".datepicker-days th:eq(0)").addClass("disabled")}if(year==endYear&&month>=endMonth||year>endYear){picker.widget.find(".datepicker-days th:eq(2)").addClass("disabled")}nextMonth=pMoment(prevMonth).add(42,"d");while(prevMonth.isBefore(nextMonth)){if(prevMonth.weekday()===pMoment().startOf("week").weekday()){row=$("<tr>");html.push(row)}clsName="";if(prevMonth.year()<year||prevMonth.year()==year&&prevMonth.month()<month){clsName+=" old"}else if(prevMonth.year()>year||prevMonth.year()==year&&prevMonth.month()>month){clsName+=" new"}if(prevMonth.isSame(pMoment({y:picker.date.year(),M:picker.date.month(),d:picker.date.date()}))){clsName+=" active"}if(pMoment(prevMonth).add(1,"d")<=picker.options.startDate||prevMonth>picker.options.endDate||isInDisableDates(prevMonth)){clsName+=" disabled"}row.append('<td class="day'+clsName+'">'+prevMonth.date()+"</td>");prevMonth.add(1,"d")}picker.widget.find(".datepicker-days tbody").empty().append(html);currentYear=pMoment().year(),months=picker.widget.find(".datepicker-months").find("th:eq(1)").text(year).end().find("span").removeClass("active");if(currentYear===year){months.eq(pMoment().month()).addClass("active")}if(currentYear-1<startYear){picker.widget.find(".datepicker-months th:eq(0)").addClass("disabled")}if(currentYear+1>endYear){picker.widget.find(".datepicker-months th:eq(2)").addClass("disabled")}for(i=0;i<12;i++){if(year==startYear&&startMonth>i||year<startYear){$(months[i]).addClass("disabled")}else if(year==endYear&&endMonth<i||year>endYear){$(months[i]).addClass("disabled")}}html="";year=parseInt(year/10,10)*10;yearCont=picker.widget.find(".datepicker-years").find("th:eq(1)").text(year+"-"+(year+9)).end().find("td");picker.widget.find(".datepicker-years").find("th").removeClass("disabled");if(startYear>year){picker.widget.find(".datepicker-years").find("th:eq(0)").addClass("disabled")}if(endYear<year+9){picker.widget.find(".datepicker-years").find("th:eq(2)").addClass("disabled")}year-=1;for(i=-1;i<11;i++){html+='<span class="year'+(i===-1||i===10?" old":"")+(currentYear===year?" active":"")+(year<startYear||year>endYear?" disabled":"")+'">'+year+"</span>";year+=1}yearCont.html(html)},fillHours=function(){pMoment.lang(picker.options.language);var table=picker.widget.find(".timepicker .timepicker-hours table"),html="",current,i,j;table.parent().hide();if(picker.use24hours){current=0;for(i=0;i<6;i+=1){html+="<tr>";for(j=0;j<4;j+=1){html+='<td class="hour">'+padLeft(current.toString())+"</td>";current++}html+="</tr>"}}else{current=1;for(i=0;i<3;i+=1){html+="<tr>";for(j=0;j<4;j+=1){html+='<td class="hour">'+padLeft(current.toString())+"</td>";current++}html+="</tr>"}}table.html(html)},fillMinutes=function(){var table=picker.widget.find(".timepicker .timepicker-minutes table"),html="",current=0,i,j;table.parent().hide();for(i=0;i<5;i++){html+="<tr>";for(j=0;j<4;j+=1){html+='<td class="minute">'+padLeft(current.toString())+"</td>";current+=3}html+="</tr>"}table.html(html)},fillTime=function(){if(!picker.date)return;var timeComponents=picker.widget.find(".timepicker span[data-time-component]"),hour=picker.date.hours(),period="AM";if(!picker.use24hours){if(hour>=12)period="PM";if(hour===0)hour=12;else if(hour!=12)hour=hour%12;picker.widget.find(".timepicker [data-action=togglePeriod]").text(period)}timeComponents.filter("[data-time-component=hours]").text(padLeft(hour));timeComponents.filter("[data-time-component=minutes]").text(padLeft(picker.date.minutes()))},click=function(e){e.stopPropagation();e.preventDefault();picker.unset=false;var target=$(e.target).closest("span, td, th"),month,year,step,day,oldDate=picker.date;if(target.length===1){if(!target.is(".disabled")){switch(target[0].nodeName.toLowerCase()){case"th":switch(target[0].className){case"switch":showMode(1);break;case"prev":case"next":step=dpGlobal.modes[picker.viewMode].navStep;if(target[0].className==="prev")step=step*-1;picker.viewDate.add(step,dpGlobal.modes[picker.viewMode].navFnc);fillDate();break}break;case"span":if(target.is(".month")){month=target.parent().find("span").index(target);picker.viewDate.month(month)}else{year=parseInt(target.text(),10)||0;picker.viewDate.year(year)}if(picker.viewMode!==0){picker.date=pMoment({y:picker.viewDate.year(),M:picker.viewDate.month(),d:picker.viewDate.date(),h:picker.date.hours(),m:picker.date.minutes()});notifyChange(oldDate)}showMode(-1);fillDate();break;case"td":if(target.is(".day")){day=parseInt(target.text(),10)||1;month=picker.viewDate.month();year=picker.viewDate.year();if(target.is(".old")){if(month===0){month=11;year-=1}else{month-=1}}else if(target.is(".new")){if(month==11){month=0;year+=1}else{month+=1}}picker.date=pMoment({y:year,M:month,d:day,h:picker.date.hours(),m:picker.date.minutes()});picker.viewDate=pMoment({y:year,M:month,d:Math.min(28,day)});fillDate();set();notifyChange(oldDate)}break}}}},actions={incrementHours:function(){checkDate("add","hours")},incrementMinutes:function(){checkDate("add","minutes")},decrementHours:function(){checkDate("subtract","hours")},decrementMinutes:function(){checkDate("subtract","minutes")},togglePeriod:function(){var hour=picker.date.hours();if(hour>=12)hour-=12;else hour+=12;picker.date.hours(hour)},showPicker:function(){picker.widget.find(".timepicker > div:not(.timepicker-picker)").hide();picker.widget.find(".timepicker .timepicker-picker").show()},showHours:function(){picker.widget.find(".timepicker .timepicker-picker").hide();picker.widget.find(".timepicker .timepicker-hours").show()},showMinutes:function(){picker.widget.find(".timepicker .timepicker-picker").hide();picker.widget.find(".timepicker .timepicker-minutes").show()},selectHour:function(e){picker.date.hours(parseInt($(e.target).text(),10));actions.showPicker.call(picker)},selectMinute:function(e){picker.date.minutes(parseInt($(e.target).text(),10));actions.showPicker.call(picker)}},doAction=function(e){var action=$(e.currentTarget).data("action"),rv=actions[action].apply(picker,arguments),oldDate=picker.date;stopEvent(e);if(!picker.date)picker.date=pMoment({y:1970});set();fillTime();notifyChange(oldDate);return rv},stopEvent=function(e){e.stopPropagation();e.preventDefault()},change=function(e){pMoment.lang(picker.options.language);var input=$(e.target),oldDate=picker.date,d=pMoment(input.val(),picker.format,picker.options.useStrict);if(d.isValid()){update();picker.setValue(d);notifyChange(oldDate);set()}else{picker.viewDate=oldDate;notifyChange(oldDate);notifyError(d);picker.unset=true;input.val("")}},showMode=function(dir){if(dir){picker.viewMode=Math.max(picker.minViewMode,Math.min(2,picker.viewMode+dir))}picker.widget.find(".datepicker > div").hide().filter(".datepicker-"+dpGlobal.modes[picker.viewMode].clsName).show()},attachDatePickerEvents=function(){var $this,$parent,expanded,closed,collapseData;picker.widget.on("click",".datepicker *",$.proxy(click,this));picker.widget.on("click","[data-action]",$.proxy(doAction,this));picker.widget.on("mousedown",$.proxy(stopEvent,this));if(picker.options.pickDate&&picker.options.pickTime){picker.widget.on("click.togglePicker",".accordion-toggle",function(e){e.stopPropagation();$this=$(this);$parent=$this.closest("ul");expanded=$parent.find(".in");closed=$parent.find(".collapse:not(.in)");if(expanded&&expanded.length){collapseData=expanded.data("collapse");if(collapseData&&collapseData.transitioning)return;expanded.collapse("hide");closed.collapse("show");$this.find("span").toggleClass(picker.options.icons.time+" "+picker.options.icons.date);picker.element.find(".input-group-addon span").toggleClass(picker.options.icons.time+" "+picker.options.icons.date)}})}if(picker.isInput){picker.element.on({focus:$.proxy(picker.show,this),change:$.proxy(change,this),blur:$.proxy(picker.hide,this)})}else{picker.element.on({change:$.proxy(change,this)},"input");if(picker.component){picker.component.on("click",$.proxy(picker.show,this))}else{picker.element.on("click",$.proxy(picker.show,this))}}},attachDatePickerGlobalEvents=function(){$(window).on("resize.datetimepicker"+picker.id,$.proxy(place,this));if(!picker.isInput){$(document).on("mousedown.datetimepicker"+picker.id,$.proxy(picker.hide,this))}},detachDatePickerEvents=function(){picker.widget.off("click",".datepicker *",picker.click);picker.widget.off("click","[data-action]");picker.widget.off("mousedown",picker.stopEvent);if(picker.options.pickDate&&picker.options.pickTime){picker.widget.off("click.togglePicker")}if(picker.isInput){picker.element.off({focus:picker.show,change:picker.change})}else{picker.element.off({change:picker.change},"input");if(picker.component){picker.component.off("click",picker.show)}else{picker.element.off("click",picker.show)}}},detachDatePickerGlobalEvents=function(){$(window).off("resize.datetimepicker"+picker.id);if(!picker.isInput){$(document).off("mousedown.datetimepicker"+picker.id)}},isInFixed=function(){if(picker.element){var parents=picker.element.parents(),inFixed=false,i;for(i=0;i<parents.length;i++){if($(parents[i]).css("position")=="fixed"){inFixed=true;break}}return inFixed}else{return false}},set=function(){pMoment.lang(picker.options.language);var formatted="",input;if(!picker.unset)formatted=pMoment(picker.date).format(picker.format);if(!picker.isInput){if(picker.component){input=picker.element.find("input");input.val(formatted)}picker.element.data("date",formatted)}else{picker.element.val(formatted)}if(!picker.options.pickTime)picker.hide()},checkDate=function(direction,unit){pMoment.lang(picker.options.language);var newDate;if(direction=="add"){newDate=pMoment(picker.date);if(newDate.hours()==23)newDate.add(1,unit);newDate.add(1,unit)}else{newDate=pMoment(picker.date).subtract(1,unit)}if(newDate.isAfter(picker.options.endDate)||newDate.subtract(1,unit).isBefore(picker.options.startDate)||isInDisableDates(newDate)){notifyError(newDate.format(picker.format));return}if(direction=="add"){picker.date.add(1,unit)}else{picker.date.subtract(1,unit)}},isInDisableDates=function(date){pMoment.lang(picker.options.language);var disabled=picker.options.disabledDates,i;for(i in disabled){if(disabled[i]==pMoment(date).format("L")){return true}}return false},padLeft=function(string){string=string.toString();if(string.length>=2)return string;else return"0"+string},getTemplate=function(pickDate,pickTime,collapse){if(pickDate&&pickTime){return'<div class="bootstrap-datetimepicker-widget dropdown-menu" style="z-index:9999 !important;">'+'<ul class="list-unstyled">'+"<li"+(collapse?' class="collapse in"':"")+">"+'<div class="datepicker">'+dpGlobal.template+"</div>"+"</li>"+'<li class="picker-switch accordion-toggle"><a class="btn" style="width:100%"><span class="'+picker.options.icons.time+'"></span></a></li>'+"<li"+(collapse?' class="collapse"':"")+">"+'<div class="timepicker">'+tpGlobal.getTemplate()+"</div>"+"</li>"+"</ul>"+"</div>"}else if(pickTime){return'<div class="bootstrap-datetimepicker-widget dropdown-menu">'+'<div class="timepicker">'+tpGlobal.getTemplate()+"</div>"+"</div>"}else{return'<div class="bootstrap-datetimepicker-widget dropdown-menu">'+'<div class="datepicker">'+dpGlobal.template+"</div>"+"</div>"}},dpGlobal={modes:[{clsName:"days",navFnc:"month",navStep:1},{clsName:"months",navFnc:"year",navStep:1},{clsName:"years",navFnc:"year",navStep:10}],headTemplate:"<thead>"+"<tr>"+'<th class="prev">&lsaquo;</th><th colspan="5" class="switch"></th><th class="next">&rsaquo;</th>'+"</tr>"+"</thead>",contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>'},tpGlobal={hourTemplate:'<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>',minuteTemplate:'<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>'};dpGlobal.template='<div class="datepicker-days">'+'<table class="table-condensed">'+dpGlobal.headTemplate+"<tbody></tbody></table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+dpGlobal.headTemplate+dpGlobal.contTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+dpGlobal.headTemplate+dpGlobal.contTemplate+"</table>"+"</div>";tpGlobal.getTemplate=function(){return'<div class="timepicker-picker">'+'<table class="table-condensed">'+"<tr>"+'<td><a href="#" class="btn" data-action="incrementHours"><span class="'+picker.options.icons.up+'"></span></a></td>'+'<td class="separator"></td>'+'<td><a href="#" class="btn" data-action="incrementMinutes"><span class="'+picker.options.icons.up+'"></span></a></td>'+(!picker.use24hours?'<td class="separator"></td>':"")+"</tr>"+"<tr>"+"<td>"+tpGlobal.hourTemplate+"</td> "+'<td class="separator">:</td>'+"<td>"+tpGlobal.minuteTemplate+"</td> "+(!picker.use24hours?'<td class="separator"></td>'+'<td><button type="button" class="btn btn-primary" data-action="togglePeriod"></button></td>':"")+"</tr>"+"<tr>"+'<td><a href="#" class="btn" data-action="decrementHours"><span class="'+picker.options.icons.down+'"></span></a></td>'+'<td class="separator"></td>'+'<td><a href="#" class="btn" data-action="decrementMinutes"><span class="'+picker.options.icons.down+'"></span></a></td>'+(!picker.use24hours?'<td class="separator"></td>':"")+"</tr>"+"</table>"+"</div>"+'<div class="timepicker-hours" data-action="selectHour">'+'<table class="table-condensed"></table>'+"</div>"+'<div class="timepicker-minutes" data-action="selectMinute">'+'<table class="table-condensed"></table>'+"</div>"};picker.destroy=function(){detachDatePickerEvents();detachDatePickerGlobalEvents();picker.widget.remove();picker.element.removeData("DateTimePicker");if(picker.component)picker.component.removeData("DateTimePicker")};picker.show=function(e){picker.widget.show();picker.height=picker.component?picker.component.outerHeight():picker.element.outerHeight();place();picker.element.trigger({type:"show.dp",date:picker.date});attachDatePickerGlobalEvents();if(e){stopEvent(e)}},picker.disable=function(){picker.element.find("input").prop("disabled",true);detachDatePickerEvents()},picker.enable=function(){picker.element.find("input").prop("disabled",false);attachDatePickerEvents()},picker.hide=function(){var collapse=picker.widget.find(".collapse"),i,collapseData;for(i=0;i<collapse.length;i++){collapseData=collapse.eq(i).data("collapse");if(collapseData&&collapseData.transitioning)return}picker.widget.hide();picker.viewMode=picker.startViewMode;showMode();picker.element.trigger({type:"hide.dp",date:picker.date});detachDatePickerGlobalEvents()},picker.setValue=function(newDate){pMoment.lang(picker.options.language);if(!newDate){picker.unset=true}else{picker.unset=false}if(!pMoment.isMoment(newDate))newDate=pMoment(newDate);if(newDate.isValid()){picker.date=newDate;set();picker.viewDate=pMoment({y:picker.date.year(),M:picker.date.month()});fillDate();fillTime()}else{notifyError(newDate)}},picker.getDate=function(){if(picker.unset)return null;return picker.date},picker.setDate=function(date){if(!date)picker.setValue(null);else picker.setValue(date)},picker.setEndDate=function(date){picker.options.endDate=pMoment(date);if(!picker.options.endDate.isValid()){picker.options.endDate=pMoment().add(50,"y")}if(picker.viewDate)update()},picker.setStartDate=function(date){picker.options.startDate=pMoment(date);if(!picker.options.startDate.isValid()){picker.options.startDate=pMoment({y:1970})}if(picker.viewDate)update()};init()};$.fn.datetimepicker=function(options){return this.each(function(){var $this=$(this),data=$this.data("DateTimePicker");if(!data)$this.data("DateTimePicker",new DateTimePicker(this,options))})}})(jQuery);
\ No newline at end of file
diff --git a/src/web/js/moment.min.js b/src/web/js/moment.min.js
new file mode 100644
index 0000000..568ad05
--- /dev/null
+++ b/src/web/js/moment.min.js
@@ -0,0 +1,6 @@
+//! moment.js
+//! version : 2.4.0
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+(function(a){function b(a,b){return function(c){return i(a.call(this,c),b)}}function c(a,b){return function(c){return this.lang().ordinal(a.call(this,c),b)}}function d(){}function e(a){u(a),g(this,a)}function f(a){var b=o(a),c=b.year||0,d=b.month||0,e=b.week||0,f=b.day||0,g=b.hour||0,h=b.minute||0,i=b.second||0,j=b.millisecond||0;this._input=a,this._milliseconds=+j+1e3*i+6e4*h+36e5*g,this._days=+f+7*e,this._months=+d+12*c,this._data={},this._bubble()}function g(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return b.hasOwnProperty("toString")&&(a.toString=b.toString),b.hasOwnProperty("valueOf")&&(a.valueOf=b.valueOf),a}function h(a){return 0>a?Math.ceil(a):Math.floor(a)}function i(a,b){for(var c=a+"";c.length<b;)c="0"+c;return c}function j(a,b,c,d){var e,f,g=b._milliseconds,h=b._days,i=b._months;g&&a._d.setTime(+a._d+g*c),(h||i)&&(e=a.minute(),f=a.hour()),h&&a.date(a.date()+h*c),i&&a.month(a.month()+i*c),g&&!d&&bb.updateOffset(a),(h||i)&&(a.minute(e),a.hour(f))}function k(a){return"[object Array]"===Object.prototype.toString.call(a)}function l(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function m(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&q(a[d])!==q(b[d]))&&g++;return g+f}function n(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=Kb[a]||Lb[b]||b}return a}function o(a){var b,c,d={};for(c in a)a.hasOwnProperty(c)&&(b=n(c),b&&(d[b]=a[c]));return d}function p(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}bb[b]=function(e,f){var g,h,i=bb.fn._lang[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=bb().utc().set(d,a);return i.call(bb.fn._lang,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function q(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function r(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function s(a){return t(a)?366:365}function t(a){return 0===a%4&&0!==a%100||0===a%400}function u(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[gb]<0||a._a[gb]>11?gb:a._a[hb]<1||a._a[hb]>r(a._a[fb],a._a[gb])?hb:a._a[ib]<0||a._a[ib]>23?ib:a._a[jb]<0||a._a[jb]>59?jb:a._a[kb]<0||a._a[kb]>59?kb:a._a[lb]<0||a._a[lb]>999?lb:-1,a._pf._overflowDayOfYear&&(fb>b||b>hb)&&(b=hb),a._pf.overflow=b)}function v(a){a._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function w(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length)),a._isValid}function x(a){return a?a.toLowerCase().replace("_","-"):a}function y(a,b){return b.abbr=a,mb[a]||(mb[a]=new d),mb[a].set(b),mb[a]}function z(a){delete mb[a]}function A(a){var b,c,d,e,f=0,g=function(a){if(!mb[a]&&nb)try{require("./lang/"+a)}catch(b){}return mb[a]};if(!a)return bb.fn._lang;if(!k(a)){if(c=g(a))return c;a=[a]}for(;f<a.length;){for(e=x(a[f]).split("-"),b=e.length,d=x(a[f+1]),d=d?d.split("-"):null;b>0;){if(c=g(e.slice(0,b).join("-")))return c;if(d&&d.length>=b&&m(e,d,!0)>=b-1)break;b--}f++}return bb.fn._lang}function B(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function C(a){var b,c,d=a.match(rb);for(b=0,c=d.length;c>b;b++)d[b]=Pb[d[b]]?Pb[d[b]]:B(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function D(a,b){return a.isValid()?(b=E(b,a.lang()),Mb[b]||(Mb[b]=C(b)),Mb[b](a)):a.lang().invalidDate()}function E(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(sb.lastIndex=0;d>=0&&sb.test(a);)a=a.replace(sb,c),sb.lastIndex=0,d-=1;return a}function F(a,b){var c;switch(a){case"DDDD":return vb;case"YYYY":case"GGGG":case"gggg":return wb;case"YYYYY":case"GGGGG":case"ggggg":return xb;case"S":case"SS":case"SSS":case"DDD":return ub;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return zb;case"a":case"A":return A(b._l)._meridiemParse;case"X":return Cb;case"Z":case"ZZ":return Ab;case"T":return Bb;case"SSSS":return yb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"ww":case"W":case"WW":case"e":case"E":return tb;default:return c=new RegExp(N(M(a.replace("\\","")),"i"))}}function G(a){var b=(Ab.exec(a)||[])[0],c=(b+"").match(Hb)||["-",0,0],d=+(60*c[1])+q(c[2]);return"+"===c[0]?-d:d}function H(a,b,c){var d,e=c._a;switch(a){case"M":case"MM":null!=b&&(e[gb]=q(b)-1);break;case"MMM":case"MMMM":d=A(c._l).monthsParse(b),null!=d?e[gb]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[hb]=q(b));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=q(b));break;case"YY":e[fb]=q(b)+(q(b)>68?1900:2e3);break;case"YYYY":case"YYYYY":e[fb]=q(b);break;case"a":case"A":c._isPm=A(c._l).isPM(b);break;case"H":case"HH":case"h":case"hh":e[ib]=q(b);break;case"m":case"mm":e[jb]=q(b);break;case"s":case"ss":e[kb]=q(b);break;case"S":case"SS":case"SSS":case"SSSS":e[lb]=q(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=G(b);break;case"w":case"ww":case"W":case"WW":case"d":case"dd":case"ddd":case"dddd":case"e":case"E":a=a.substr(0,1);case"gg":case"gggg":case"GG":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=b)}}function I(a){var b,c,d,e,f,g,h,i,j,k,l=[];if(!a._d){for(d=K(a),a._w&&null==a._a[hb]&&null==a._a[gb]&&(f=function(b){return b?b.length<3?parseInt(b,10)>68?"19"+b:"20"+b:b:null==a._a[fb]?bb().weekYear():a._a[fb]},g=a._w,null!=g.GG||null!=g.W||null!=g.E?h=X(f(g.GG),g.W||1,g.E,4,1):(i=A(a._l),j=null!=g.d?T(g.d,i):null!=g.e?parseInt(g.e,10)+i._week.dow:0,k=parseInt(g.w,10)||1,null!=g.d&&j<i._week.dow&&k++,h=X(f(g.gg),k,j,i._week.doy,i._week.dow)),a._a[fb]=h.year,a._dayOfYear=h.dayOfYear),a._dayOfYear&&(e=null==a._a[fb]?d[fb]:a._a[fb],a._dayOfYear>s(e)&&(a._pf._overflowDayOfYear=!0),c=S(e,0,a._dayOfYear),a._a[gb]=c.getUTCMonth(),a._a[hb]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=l[b]=d[b];for(;7>b;b++)a._a[b]=l[b]=null==a._a[b]?2===b?1:0:a._a[b];l[ib]+=q((a._tzm||0)/60),l[jb]+=q((a._tzm||0)%60),a._d=(a._useUTC?S:R).apply(null,l)}}function J(a){var b;a._d||(b=o(a._i),a._a=[b.year,b.month,b.day,b.hour,b.minute,b.second,b.millisecond],I(a))}function K(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function L(a){a._a=[],a._pf.empty=!0;var b,c,d,e,f,g=A(a._l),h=""+a._i,i=h.length,j=0;for(d=E(a._f,g).match(rb)||[],b=0;b<d.length;b++)e=d[b],c=(F(e,a).exec(h)||[])[0],c&&(f=h.substr(0,h.indexOf(c)),f.length>0&&a._pf.unusedInput.push(f),h=h.slice(h.indexOf(c)+c.length),j+=c.length),Pb[e]?(c?a._pf.empty=!1:a._pf.unusedTokens.push(e),H(e,c,a)):a._strict&&!c&&a._pf.unusedTokens.push(e);a._pf.charsLeftOver=i-j,h.length>0&&a._pf.unusedInput.push(h),a._isPm&&a._a[ib]<12&&(a._a[ib]+=12),a._isPm===!1&&12===a._a[ib]&&(a._a[ib]=0),I(a),u(a)}function M(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function N(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function O(a){var b,c,d,e,f;if(0===a._f.length)return a._pf.invalidFormat=!0,a._d=new Date(0/0),void 0;for(e=0;e<a._f.length;e++)f=0,b=g({},a),v(b),b._f=a._f[e],L(b),w(b)&&(f+=b._pf.charsLeftOver,f+=10*b._pf.unusedTokens.length,b._pf.score=f,(null==d||d>f)&&(d=f,c=b));g(a,c||b)}function P(a){var b,c=a._i,d=Db.exec(c);if(d){for(a._pf.iso=!0,b=4;b>0;b--)if(d[b]){a._f=Fb[b-1]+(d[6]||" ");break}for(b=0;4>b;b++)if(Gb[b][1].exec(c)){a._f+=Gb[b][0];break}Ab.exec(c)&&(a._f+="Z"),L(a)}else a._d=new Date(c)}function Q(b){var c=b._i,d=ob.exec(c);c===a?b._d=new Date:d?b._d=new Date(+d[1]):"string"==typeof c?P(b):k(c)?(b._a=c.slice(0),I(b)):l(c)?b._d=new Date(+c):"object"==typeof c?J(b):b._d=new Date(c)}function R(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function S(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function T(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function U(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function V(a,b,c){var d=eb(Math.abs(a)/1e3),e=eb(d/60),f=eb(e/60),g=eb(f/24),h=eb(g/365),i=45>d&&["s",d]||1===e&&["m"]||45>e&&["mm",e]||1===f&&["h"]||22>f&&["hh",f]||1===g&&["d"]||25>=g&&["dd",g]||45>=g&&["M"]||345>g&&["MM",eb(g/30)]||1===h&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,i[4]=c,U.apply({},i)}function W(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=bb(a).add("d",f),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function X(a,b,c,d,e){var f,g,h=new Date(Date.UTC(a,0)).getUTCDay();return c=null!=c?c:e,f=e-h+(h>d?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:s(a-1)+g}}function Y(a){var b=a._i,c=a._f;return"undefined"==typeof a._pf&&v(a),null===b?bb.invalid({nullInput:!0}):("string"==typeof b&&(a._i=b=A().preparse(b)),bb.isMoment(b)?(a=g({},b),a._d=new Date(+b._d)):c?k(c)?O(a):L(a):Q(a),new e(a))}function Z(a,b){bb.fn[a]=bb.fn[a+"s"]=function(a){var c=this._isUTC?"UTC":"";return null!=a?(this._d["set"+c+b](a),bb.updateOffset(this),this):this._d["get"+c+b]()}}function $(a){bb.duration.fn[a]=function(){return this._data[a]}}function _(a,b){bb.duration.fn["as"+a]=function(){return+this/b}}function ab(a){var b=!1,c=bb;"undefined"==typeof ender&&(this.moment=a?function(){return!b&&console&&console.warn&&(b=!0,console.warn("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.")),c.apply(null,arguments)}:bb)}for(var bb,cb,db="2.4.0",eb=Math.round,fb=0,gb=1,hb=2,ib=3,jb=4,kb=5,lb=6,mb={},nb="undefined"!=typeof module&&module.exports,ob=/^\/?Date\((\-?\d+)/i,pb=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,qb=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,rb=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,sb=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,tb=/\d\d?/,ub=/\d{1,3}/,vb=/\d{3}/,wb=/\d{1,4}/,xb=/[+\-]?\d{1,6}/,yb=/\d+/,zb=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Ab=/Z|[\+\-]\d\d:?\d\d/i,Bb=/T/i,Cb=/[\+\-]?\d+(\.\d{1,3})?/,Db=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d:?\d\d|Z)?)?$/,Eb="YYYY-MM-DDTHH:mm:ssZ",Fb=["YYYY-MM-DD","GGGG-[W]WW","GGGG-[W]WW-E","YYYY-DDD"],Gb=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],Hb=/([\+\-]|\d\d)/gi,Ib="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),Jb={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},Kb={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},Lb={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},Mb={},Nb="DDD w W M D d".split(" "),Ob="M D H h m s w W".split(" "),Pb={M:function(){return this.month()+1},MMM:function(a){return this.lang().monthsShort(this,a)},MMMM:function(a){return this.lang().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.lang().weekdaysMin(this,a)},ddd:function(a){return this.lang().weekdaysShort(this,a)},dddd:function(a){return this.lang().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return i(this.year()%100,2)},YYYY:function(){return i(this.year(),4)},YYYYY:function(){return i(this.year(),5)},gg:function(){return i(this.weekYear()%100,2)},gggg:function(){return this.weekYear()},ggggg:function(){return i(this.weekYear(),5)},GG:function(){return i(this.isoWeekYear()%100,2)},GGGG:function(){return this.isoWeekYear()},GGGGG:function(){return i(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return q(this.milliseconds()/100)},SS:function(){return i(q(this.milliseconds()/10),2)},SSS:function(){return i(this.milliseconds(),3)},SSSS:function(){return i(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(q(a/60),2)+":"+i(q(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(q(10*a/6),4)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()}},Qb=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];Nb.length;)cb=Nb.pop(),Pb[cb+"o"]=c(Pb[cb],cb);for(;Ob.length;)cb=Ob.pop(),Pb[cb+cb]=b(Pb[cb],2);for(Pb.DDDD=b(Pb.DDD,3),g(d.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=bb.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=bb([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return W(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),bb=function(b,c,d,e){return"boolean"==typeof d&&(e=d,d=a),Y({_i:b,_f:c,_l:d,_strict:e,_isUTC:!1})},bb.utc=function(b,c,d,e){var f;return"boolean"==typeof d&&(e=d,d=a),f=Y({_useUTC:!0,_isUTC:!0,_l:d,_i:b,_f:c,_strict:e}).utc()},bb.unix=function(a){return bb(1e3*a)},bb.duration=function(a,b){var c,d,e,g=bb.isDuration(a),h="number"==typeof a,i=g?a._input:h?{}:a,j=null;return h?b?i[b]=a:i.milliseconds=a:(j=pb.exec(a))?(c="-"===j[1]?-1:1,i={y:0,d:q(j[hb])*c,h:q(j[ib])*c,m:q(j[jb])*c,s:q(j[kb])*c,ms:q(j[lb])*c}):(j=qb.exec(a))&&(c="-"===j[1]?-1:1,e=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*c},i={y:e(j[2]),M:e(j[3]),d:e(j[4]),h:e(j[5]),m:e(j[6]),s:e(j[7]),w:e(j[8])}),d=new f(i),g&&a.hasOwnProperty("_lang")&&(d._lang=a._lang),d},bb.version=db,bb.defaultFormat=Eb,bb.updateOffset=function(){},bb.lang=function(a,b){var c;return a?(b?y(x(a),b):null===b?(z(a),a="en"):mb[a]||A(a),c=bb.duration.fn._lang=bb.fn._lang=A(a),c._abbr):bb.fn._lang._abbr},bb.langData=function(a){return a&&a._lang&&a._lang._abbr&&(a=a._lang._abbr),A(a)},bb.isMoment=function(a){return a instanceof e},bb.isDuration=function(a){return a instanceof f},cb=Qb.length-1;cb>=0;--cb)p(Qb[cb]);for(bb.normalizeUnits=function(a){return n(a)},bb.invalid=function(a){var b=bb.utc(0/0);return null!=a?g(b._pf,a):b._pf.userInvalidated=!0,b},bb.parseZone=function(a){return bb(a).parseZone()},g(bb.fn=e.prototype,{clone:function(){return bb(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){return D(bb(this).utc(),"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds()]},isValid:function(){return w(this)},isDSTShifted:function(){return this._a?this.isValid()&&m(this._a,(this._isUTC?bb.utc(this._a):bb(this._a)).toArray())>0:!1},parsingFlags:function(){return g({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(a){var b=D(this,a||bb.defaultFormat);return this.lang().postformat(b)},add:function(a,b){var c;return c="string"==typeof a?bb.duration(+b,a):bb.duration(a,b),j(this,c,1),this},subtract:function(a,b){var c;return c="string"==typeof a?bb.duration(+b,a):bb.duration(a,b),j(this,c,-1),this},diff:function(a,b,c){var d,e,f=this._isUTC?bb(a).zone(this._offset||0):bb(a).local(),g=6e4*(this.zone()-f.zone());return b=n(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-bb(this).startOf("month")-(f-bb(f).startOf("month")))/d,e-=6e4*(this.zone()-bb(this).startOf("month").zone()-(f.zone()-bb(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:h(e)},from:function(a,b){return bb.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)},fromNow:function(a){return this.from(bb(),a)},calendar:function(){var a=this.diff(bb().zone(this.zone()).startOf("day"),"days",!0),b=-6>a?"sameElse":-1>a?"lastWeek":0>a?"lastDay":1>a?"sameDay":2>a?"nextDay":7>a?"nextWeek":"sameElse";return this.format(this.lang().calendar(b,this))},isLeapYear:function(){return t(this.year())},isDST:function(){return this.zone()<this.clone().month(0).zone()||this.zone()<this.clone().month(5).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=T(a,this.lang()),this.add({d:a-b})):b},month:function(a){var b,c=this._isUTC?"UTC":"";return null!=a?"string"==typeof a&&(a=this.lang().monthsParse(a),"number"!=typeof a)?this:(b=this.date(),this.date(1),this._d["set"+c+"Month"](a),this.date(Math.min(b,this.daysInMonth())),bb.updateOffset(this),this):this._d["get"+c+"Month"]()},startOf:function(a){switch(a=n(a)){case"year":this.month(0);case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a?this.weekday(0):"isoWeek"===a&&this.isoWeekday(1),this},endOf:function(a){return a=n(a),this.startOf(a).add("isoWeek"===a?"week":a,1).subtract("ms",1)},isAfter:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)>+bb(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+bb(a).startOf(b)},isSame:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)===+bb(a).startOf(b)},min:function(a){return a=bb.apply(null,arguments),this>a?this:a},max:function(a){return a=bb.apply(null,arguments),a>this?this:a},zone:function(a){var b=this._offset||0;return null==a?this._isUTC?b:this._d.getTimezoneOffset():("string"==typeof a&&(a=G(a)),Math.abs(a)<16&&(a=60*a),this._offset=a,this._isUTC=!0,b!==a&&j(this,bb.duration(b-a,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?bb(a).zone():0,0===(this.zone()-a)%60},daysInMonth:function(){return r(this.year(),this.month())},dayOfYear:function(a){var b=eb((bb(this).startOf("day")-bb(this).startOf("year"))/864e5)+1;return null==a?b:this.add("d",a-b)},weekYear:function(a){var b=W(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==a?b:this.add("y",a-b)},isoWeekYear:function(a){var b=W(this,1,4).year;return null==a?b:this.add("y",a-b)},week:function(a){var b=this.lang().week(this);return null==a?b:this.add("d",7*(a-b))},isoWeek:function(a){var b=W(this,1,4).week;return null==a?b:this.add("d",7*(a-b))},weekday:function(a){var b=(this.day()+7-this.lang()._week.dow)%7;return null==a?b:this.add("d",a-b)},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},get:function(a){return a=n(a),this[a]()},set:function(a,b){return a=n(a),"function"==typeof this[a]&&this[a](b),this},lang:function(b){return b===a?this._lang:(this._lang=A(b),this)}}),cb=0;cb<Ib.length;cb++)Z(Ib[cb].toLowerCase().replace(/s$/,""),Ib[cb]);Z("year","FullYear"),bb.fn.days=bb.fn.day,bb.fn.months=bb.fn.month,bb.fn.weeks=bb.fn.week,bb.fn.isoWeeks=bb.fn.isoWeek,bb.fn.toJSON=bb.fn.toISOString,g(bb.duration.fn=f.prototype,{_bubble:function(){var a,b,c,d,e=this._milliseconds,f=this._days,g=this._months,i=this._data;i.milliseconds=e%1e3,a=h(e/1e3),i.seconds=a%60,b=h(a/60),i.minutes=b%60,c=h(b/60),i.hours=c%24,f+=h(c/24),i.days=f%30,g+=h(f/30),i.months=g%12,d=h(g/12),i.years=d},weeks:function(){return h(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*(this._months%12)+31536e6*q(this._months/12)},humanize:function(a){var b=+this,c=V(b,!a,this.lang());return a&&(c=this.lang().pastFuture(b,c)),this.lang().postformat(c)},add:function(a,b){var c=bb.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=bb.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=n(a),this[a.toLowerCase()+"s"]()},as:function(a){return a=n(a),this["as"+a.charAt(0).toUpperCase()+a.slice(1)+"s"]()},lang:bb.fn.lang,toIsoString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"}});for(cb in Jb)Jb.hasOwnProperty(cb)&&(_(cb,Jb[cb]),$(cb.toLowerCase()));_("Weeks",6048e5),bb.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},bb.lang("en",{ordinal:function(a){var b=a%10,c=1===q(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),nb?(module.exports=bb,ab(!0)):"function"==typeof define&&define.amd?define("moment",function(b,c,d){return d.config().noGlobal!==!0&&ab(d.config().noGlobal===a),bb}):ab()}).call(this);
\ No newline at end of file