azkaban-uncached

Merge pull request #78 from davidzchen/bootstrap_ui Initial

12/13/2013 12:10:26 AM

Details

build.xml 26(+26 -0)

diff --git a/build.xml b/build.xml
index 7b1479b..4b81f6d 100644
--- a/build.xml
+++ b/build.xml
@@ -5,6 +5,7 @@
 	<property name="base.dir" value="${basedir}" />
 	<property name="dist.jar.dir" value="${basedir}/dist/jars" />
 	<property name="dist.dust.dir" value="${basedir}/dist/dust" />
+	<property name="dist.less.dir" value="${basedir}/dist/less" />
 	<property name="dist.classes.dir" value="${basedir}/dist/classes" />
 	<property name="dist.packages.dir" value="${basedir}/dist/packages" />
 	<property name="dist.web.package.dir" value="${dist.packages.dir}/azkaban-web-server" />
@@ -21,6 +22,7 @@
 	<property name="bin.dir" value="${basedir}/bin" />
 	<property name="java.src.dir" value="${basedir}/src/java" />
 	<property name="dust.src.dir" value="${basedir}/src/tl" />
+	<property name="less.src.dir" value="${basedir}/src/less" />
 	<property name="web.src.dir" value="${basedir}/src/web" />
 	<property name="sql.src.dir" value="${basedir}/src/sql" />
 	
@@ -52,6 +54,8 @@
 		<mkdir dir="${dist.classes.dir}" />
 		<delete dir="${dist.dust.dir}" />
 		<mkdir dir="${dist.dust.dir}" />
+		<delete dir="${dist.less.dir}" />
+		<mkdir dir="${dist.less.dir}" />
 		
 		<!-- copy non-java files to classes dir to load from classpath -->
 		<copy todir="${dist.classes.dir}">
@@ -71,6 +75,7 @@
 				 elements, and for and foreach requires ant-contrib, we use targetfile 
 				 for the template name parameter and then redirect the output of dustc
 				 to the final output file -->
+		<echo message="Compiling Dust templates." />
 		<apply dir="${dust.src.dir}" executable="dustc" relative="true">
 			<mapper type="glob" from="*.tl" to="*" />
 			<targetfile prefix="--name=" />
@@ -80,6 +85,17 @@
 				<outputmapper id="out" type="glob" from="*.tl" to="${dist.dust.dir}/*.js" />
 			</redirector>
 		</apply>
+
+		<!-- Compile LESS to CSS -->
+		<echo message="Compiling LESS style sheets." />
+		<apply dir="${less.src.dir}" executable="lessc" relative="true">
+			<mapper type="glob" from="*.less" to="*.css" />
+			<srcfile />
+			<fileset dir="${less.src.dir}" includes="*.less" />
+			<redirector>
+				<outputmapper id="out" type="glob" from="*.less" to="${dist.less.dir}/*.css" />
+			</redirector>
+		</apply>
 	</target>
 	
 	<target name="jars" depends="build" description="Create azkaban jar">
@@ -179,6 +195,11 @@
 		<copy todir="${dist.web.package.dir}/web/js">
 			<fileset dir="${dist.dust.dir}" />
 		</copy>
+
+		<!-- Copy compiled less CSS -->
+		<copy todir="${dist.web.package.dir}/web/css">
+			<fileset dir="${dist.less.dir}" />
+		</copy>
 		
 		<!-- Copy conf create table scripts -->
 		<copy todir="${dist.web.package.dir}/conf">
@@ -270,6 +291,11 @@
 			<fileset dir="${dist.dust.dir}" />
 		</copy>
 		
+		<!-- Copy compiled less CSS -->
+		<copy todir="${dist.solo.package.dir}/web/css">
+			<fileset dir="${dist.less.dir}" />
+		</copy>
+		
 		<!-- Copy sql files -->
 		<copy todir="${dist.solo.package.dir}/sql" >
 			<fileset dir="${sql.src.dir}" />
diff --git a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
index d25ea39..890fc79 100644
--- a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
+++ b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
@@ -727,21 +727,49 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 	
 	private void handleProjectLogsPage(HttpServletRequest req, HttpServletResponse resp, Session session) throws ServletException, IOException {
 		Page page = newPage(req, resp, session, "azkaban/webapp/servlet/velocity/projectlogpage.vm");
-
 		String projectName = getParam(req, "project");
-		
-		Project project = projectManager.getProject(projectName);
-		if (project == null) {
-			page.add("errorMsg", "Project " + projectName + " doesn't exist.");
+
+		User user = session.getUser();
+		Project project = null;
+		try {
+			project = projectManager.getProject(projectName);
+			if (project == null) {
+				page.add("errorMsg", "Project " + projectName + " doesn't exist.");
+			}
+			else {
+				if (!hasPermission(project,user,Type.READ)) {
+					throw new AccessControlException( "No permission to view project " + projectName + ".");
+				}
+				
+				page.add("project", project);
+				page.add("admins", Utils.flattenToString(project.getUsersWithPermission(Type.ADMIN), ","));
+				Permission perm = this.getPermissionObject(project, user, Type.ADMIN);
+				page.add("userpermission", perm);
+	
+				boolean adminPerm = perm.isPermissionSet(Type.ADMIN);
+				if (adminPerm) {
+					page.add("admin", true);
+				}
+				// Set this so we can display execute buttons only to those who have access.
+				if (perm.isPermissionSet(Type.EXECUTE) || adminPerm) {
+					page.add("exec", true);
+				}
+				else {
+					page.add("exec", false);
+				}
+			}
 		}
-		page.add("projectName", projectName);
+		catch (AccessControlException e) {
+			page.add("errorMsg", e.getMessage());
+		}
+
 		//page.add("projectManager", projectManager);
 		//int bytesSkip = 0;
 		int numBytes = 1024;
 
-		// Really sucks if we do a lot of these because it'll eat up memory fast. But it's expected
-		// that this won't be a heavily used thing. If it is, then we'll revisit it to make it more stream
-		// friendly.
+		// Really sucks if we do a lot of these because it'll eat up memory fast. 
+		// But it's expected that this won't be a heavily used thing. If it is, 
+		// then we'll revisit it to make it more stream friendly.
 		StringBuffer buffer = new StringBuffer(numBytes);
 		page.add("log", buffer.toString());
 
@@ -908,20 +936,18 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 				}
 				else {
 					page.add("flowid", flow.getId());
-					
 					Node node = flow.getNode(jobName);
-					
 					if (node == null) {
 						page.add("errorMsg", "Job " + jobName + " not found.");
 					}
 					else {
 						Props prop = projectManager.getProperties(project, node.getJobSource());
 						Props overrideProp = projectManager.getJobOverrideProperty(project, jobName);
-						if(overrideProp == null) {
+						if (overrideProp == null) {
 							overrideProp = new Props();
 						}
 						Props comboProp = new Props(prop);
-						for(String key : overrideProp.getKeySet()) {
+						for (String key : overrideProp.getKeySet()) {
 							comboProp.put(key, overrideProp.get(key));
 						}
 						page.add("jobid", node.getId());
@@ -930,7 +956,7 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 						ArrayList<String> dependencies = new ArrayList<String>();
 						Set<Edge> inEdges = flow.getInEdges(node.getId());
 						if (inEdges != null) {
-							for ( Edge dependency: inEdges ) {
+							for (Edge dependency: inEdges) {
 								dependencies.add(dependency.getSourceId());
 							}
 						}
@@ -941,7 +967,7 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 						ArrayList<String> dependents = new ArrayList<String>();
 						Set<Edge> outEdges = flow.getOutEdges(node.getId());
 						if (outEdges != null) {
-							for ( Edge dependent: outEdges ) {
+							for (Edge dependent: outEdges) {
 								dependents.add(dependent.getTargetId());
 							}
 						}
@@ -952,15 +978,15 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 						// Resolve property dependencies
 						ArrayList<String> source = new ArrayList<String>(); 
 						String nodeSource = node.getPropsSource();
-						if(nodeSource != null) {
+						if (nodeSource != null) {
 							source.add(nodeSource);
 							FlowProps parent = flow.getFlowProps(nodeSource);
-							while(parent.getInheritedSource() != null) {
+							while (parent.getInheritedSource() != null) {
 								source.add(parent.getInheritedSource());
 								parent = flow.getFlowProps(parent.getInheritedSource()); 
 							}
 						}
-						if(!source.isEmpty()) {
+						if (!source.isEmpty()) {
 							page.add("properties", source);
 						}
 						
@@ -978,7 +1004,8 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 		}
 		catch (AccessControlException e) {
 			page.add("errorMsg", e.getMessage());
-		} catch (ProjectManagerException e) {
+		}
+		catch (ProjectManagerException e) {
 			page.add("errorMsg", e.getMessage());
 		}
 		
@@ -1014,7 +1041,6 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 				}
 				else {
 					page.add("flowid", flow.getId());
-					
 					Node node = flow.getNode(jobName);
 					
 					if (node == null) {
diff --git a/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm b/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
index e21ca51..cec8db1 100644
--- a/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
@@ -138,7 +138,7 @@
 
 			<div class="row" id="jobListView">
 				<div class="col-lg-12">
-					<table class="table table-striped table-bordered">
+					<table class="table table-striped table-bordered table-condensed table-hover executions-table">
 						<thead>
 							<tr>
 								<th>Name</th>
diff --git a/src/java/azkaban/webapp/servlet/velocity/executionspage.vm b/src/java/azkaban/webapp/servlet/velocity/executionspage.vm
index 7c0a5d0..7ec5a6c 100644
--- a/src/java/azkaban/webapp/servlet/velocity/executionspage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/executionspage.vm
@@ -56,7 +56,7 @@
 				<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 id="executingJobs" class="table table-striped table-bordered table-hover table-condensed executions-table">
 							<thead>
 								<tr>
 									<th class="execid">Execution Id</th>
@@ -93,8 +93,7 @@
 	#end
 #else
 								<tr>
-									<td></td>
-									<td class="last">No Executing Flows</td>
+									<td colspan="10">No Executing Flows</td>
 								</tr>
 #end
 							</tbody>
@@ -107,7 +106,7 @@
 				<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 id="recentlyFinished" class="table table-striped table-bordered table-hover table-condensed executions-table">
 							<thead>
 								<tr>
 									<th class="execid">Execution Id</th>
@@ -144,8 +143,7 @@
 	#end
 #else
 								<tr>
-									<td></td>
-									<td class="last">No Recently Finished</td>
+									<td colspan="10">No Recently Finished</td>
 								</tr>
 #end	
 							</tbody>
diff --git a/src/java/azkaban/webapp/servlet/velocity/historypage.vm b/src/java/azkaban/webapp/servlet/velocity/historypage.vm
index b1b93dc..e31bc0d 100644
--- a/src/java/azkaban/webapp/servlet/velocity/historypage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/historypage.vm
@@ -89,7 +89,7 @@
 								</div>
 							</form>
 						</div>
-						<table id="executingJobs" class="table table-striped">
+						<table id="executingJobs" class="table table-striped table-bordered table-hover table-condensed executions-table">
 							<thead>
 								<tr>
 									<th class="execid">Execution Id</th>
diff --git a/src/java/azkaban/webapp/servlet/velocity/index.vm b/src/java/azkaban/webapp/servlet/velocity/index.vm
index b332247..7eafaae 100644
--- a/src/java/azkaban/webapp/servlet/velocity/index.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/index.vm
@@ -34,8 +34,8 @@
 	</head>
 	<body>
 
-#set($current_page="all")
-#parse("azkaban/webapp/servlet/velocity/nav2.vm")
+#set ($current_page="all")
+#parse ("azkaban/webapp/servlet/velocity/nav2.vm")
 
 		<div class="container">
 
diff --git a/src/java/azkaban/webapp/servlet/velocity/jobnav.vm b/src/java/azkaban/webapp/servlet/velocity/jobnav.vm
index 70f974e..bb27f16 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-tabs">
+					<ul class="nav nav-pills">
 						<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 95a2368..db11bdd 100644
--- a/src/java/azkaban/webapp/servlet/velocity/jobpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/jobpage.vm
@@ -83,7 +83,7 @@
 					<ol class="breadcrumb">
 						<li><a href="${context}/manager?project=${project.name}"><strong>Project</strong> $project.name</a></li>
 						<li><a href="${context}/manager?project=${project.name}&flow=${flowid}"><strong>Flow</strong> $flowid</a></li>
-						<li><a href="${context}/manager?project=${project.name}&flow=${flowid}&job=${jobid}"><strong>Job</strong> $jobid</a></li>
+						<li class="active"><a href="${context}/manager?project=${project.name}&flow=${flowid}&job=${jobid}"><strong>Job</strong> $jobid</a></li>
 					</ol>
 				
 	#set ($job_page="properties")
@@ -99,7 +99,7 @@
 							Job Properties
 						</div>
 
-						<table id="all-jobs" class="table table-striped table-bordered">
+						<table class="table table-striped table-bordered properties-table">
 							<thead>
 								<tr>
 									<th class="tb-pname">Parameter Name</th>
@@ -123,7 +123,7 @@
 
 ## Edit job modal.
 
-			<div class="modal fade" id="job-edit-pane">
+			<div class="modal modal-wide fade" id="job-edit-pane">
 				<div class="modal-dialog">
 					<div class="modal-content">
 						<div class="modal-header">
@@ -132,7 +132,7 @@
 						</div>
 						<div class="modal-body">
 							<h4>Job Essentials</h4>
-							<dl>
+							<dl class="dl-horizontal">
 								<dt>Job Name</dt>
 								<dd id="jobName"></dd>
 								<dt>Job Type</dt>
diff --git a/src/java/azkaban/webapp/servlet/velocity/login.vm b/src/java/azkaban/webapp/servlet/velocity/login.vm
index 4064be3..62a33f3 100644
--- a/src/java/azkaban/webapp/servlet/velocity/login.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/login.vm
@@ -27,20 +27,10 @@
 		</script>
   </head>
   <body>
-    <div class="navbar navbar-inverse navbar-static-top">
-      <div class="container">
-        <div class="navbar-header">
-          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
-            <span class="icon-bar"></span>
-            <span class="icon-bar"></span>
-            <span class="icon-bar"></span>
-          </button>
-#parse("azkaban/webapp/servlet/velocity/title2.vm")
-        </div>
-        <div class="navbar-collapse collapse">
-				</div>
-			</div>
-		</div>
+
+#set ($current_page="all")
+#set ($navbar_disabled=1)
+#parse ("azkaban/webapp/servlet/velocity/nav2.vm")
 
 		<div class="container">
 			<div class="row">
diff --git a/src/java/azkaban/webapp/servlet/velocity/nav2.vm b/src/java/azkaban/webapp/servlet/velocity/nav2.vm
index 44f2134..b0b89ac 100644
--- a/src/java/azkaban/webapp/servlet/velocity/nav2.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/nav2.vm
@@ -17,31 +17,40 @@
     <div class="navbar navbar-inverse navbar-static-top">
       <div class="container">
         <div class="navbar-header">
+#if ($navbar_disabled != 1)
           <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
             <span class="icon-bar"></span>
             <span class="icon-bar"></span>
             <span class="icon-bar"></span>
           </button>
-#parse("azkaban/webapp/servlet/velocity/title2.vm")
+#end
+					<div class="navbar-logo">
+						<a href="${context}/">Azkaban</a>
+					</div>
         </div>
+				<div class="navbar-left navbar-enviro">
+					<div class="navbar-enviro-name">${azkaban_name}</div>
+					<div class="navbar-enviro-server">${azkaban_label}</div>
+				</div>
         <div class="navbar-collapse collapse">
+#if ($navbar_disabled != 1)
           <ul class="nav navbar-nav">
 						<li#if($current_page == 'all') class="active"#end><a href="$!context/index">Projects</a></li>
 						<li#if($current_page == 'schedule') class="active"#end><a href="$!context/schedule">Scheduling</a></li>
 						<!--<li#if($current_page == 'triggers') class="active"#end><a href="$!context/triggers">Triggers</a></li>-->
 						<li#if($current_page == 'executing') class="active"#end><a href="$!context/executor">Executing</a></li>
 						<li#if($current_page == 'history') class="active"#end><a href="$!context/history">History</a></li>
-#foreach($viewer in $viewers)
-	#if(!$viewer.hidden)
+	#foreach ($viewer in $viewers)
+		#if (!$viewer.hidden)
 						<li#if($current_page == $viewer.pluginName) class="active"#end><a href="$!context/$viewer.pluginPath">$viewer.pluginName</a></li>
+		#end
 	#end
-#end
 
-#foreach($trigger in $triggerPlugins)
-	#if(!$trigger.hidden)
+	#foreach ($trigger in $triggerPlugins)
+		#if (!$trigger.hidden)
 						<li#if($current_page == $trigger.pluginName) class="active"#end><a href="$!context/$trigger.pluginPath">$trigger.pluginName</a></li>
+		#end
 	#end
-#end
           </ul>
           <ul class="nav navbar-nav navbar-right">
             <li class="dropdown">
@@ -51,6 +60,7 @@
               </ul>
             </li>
           </ul>
+#end
         </div><!--/.nav-collapse -->
       </div>
     </div>
diff --git a/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm b/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm
index a7c5e34..e6bcdeb 100644
--- a/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm
@@ -97,7 +97,7 @@
 
 							<div class="panel panel-success">
 								<div class="panel-heading">User</div>
-								<table class="table table-striped" id="permissions-table">
+								<table class="table table-striped permission-table" id="permissions-table">
 									<thead>
 										<th class="tb-username">User</th>
 										<th class="tb-perm">Admin</th>
@@ -151,7 +151,7 @@
 							
 							<div class="panel panel-warning">
 								<div class="panel-heading">Group</div>
-								<table class="table table-striped" id="group-permissions-table">
+								<table class="table table-striped permission-table" id="group-permissions-table">
 									<thead>
 										<tr>
 											<th class="tb-username">Group</th>
@@ -206,7 +206,7 @@
 							
 							<div class="panel panel-info">
 								<div class="panel-heading">Proxy Users</div>
-								<table class="table table-striped" id="proxy-user-table">
+								<table class="table table-striped permission-table" id="proxy-user-table">
 									<thead>
 										<tr>
 											<th class="tb-username">Proxy User</th>
@@ -255,7 +255,7 @@
 						</div>
 						<div class="modal-footer">
 							<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
-							<button type="button" class="btn btn-primary" id="remove-proxy-btn">Remove Proxy User</a>
+							<button type="button" class="btn btn-danger" id="remove-proxy-btn">Remove Proxy User</a>
 						</div>
 					</div>
 				</div>
diff --git a/src/java/azkaban/webapp/servlet/velocity/projectlogpage.vm b/src/java/azkaban/webapp/servlet/velocity/projectlogpage.vm
index 1bf473a..3a5a7c7 100644
--- a/src/java/azkaban/webapp/servlet/velocity/projectlogpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/projectlogpage.vm
@@ -31,8 +31,9 @@
 			var timezone = "${timezone}";
 			var errorMessage = null;
 			var successMessage = null;
-			
-			var projectName = "${projectName}";
+		
+			var projectId = ${project.id};
+			var projectName = "$project.name";
 		</script>
 	</head>
 	<body>
diff --git a/src/java/azkaban/webapp/servlet/velocity/projectnav.vm b/src/java/azkaban/webapp/servlet/velocity/projectnav.vm
index c19a6ab..01952bf 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-tabs">
+					<ul class="nav nav-pills">
 						<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 e96d96e..73546c6 100644
--- a/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
@@ -104,6 +104,13 @@
 		#foreach ($flow in $flows)
 							<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>
+			#end
 									<a href="${context}/manager?project=${project.name}&flow=${flow.id}">${flow.id}</a>
 								</div>
 								<div id="${flow.id}-child" class="panel-collapse collapse">
@@ -112,13 +119,6 @@
 										</tbody>
 									</table>
 								</div>
-								<div class="panel-footer">
-			#if (${exec})
-									<button type="button" class="btn btn-sm 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-sm">Executions</a>
-									<a href="${context}/manager?project=${project.name}&flow=${flow.id}#summary" class="btn btn-primary btn-sm">Summary</a>
-			#end
-								</div>
 							</div>
 		#end
 	#else
@@ -175,14 +175,14 @@
 							<h4 class="modal-title">Delete Project</h4>
 						</div>
 						<div class="modal-body">
-							<p>Warning: This project will be deleted and may not be recoverable.</p>
+							<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">Yes</button>
+								<button type="button" class="btn btn-danger" id="delete-btn">Delete Project</button>
 							</form>
 						</div>
 					</div>
diff --git a/src/java/azkaban/webapp/servlet/velocity/propertypage.vm b/src/java/azkaban/webapp/servlet/velocity/propertypage.vm
index 192c105..81eb31f 100644
--- a/src/java/azkaban/webapp/servlet/velocity/propertypage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/propertypage.vm
@@ -85,7 +85,7 @@
 					<div class="panel panel-default">
 						<div class="panel-heading">Property $property</div>
 
-						<table id="all-jobs" class="table table-striped table-bordered">
+						<table class="table table-striped table-bordered properties-table">
 							<thead>
 								<tr>
 									<th class="tb-pname">Parameter Name</th>
diff --git a/src/less/bootstrap-azkaban.less b/src/less/bootstrap-azkaban.less
new file mode 100644
index 0000000..55c12c3
--- /dev/null
+++ b/src/less/bootstrap-azkaban.less
@@ -0,0 +1,255 @@
+// Wide modal used for certain panels such as executing flow panel.
+.modal-wide .modal-dialog {
+	width: 80%;
+}
+
+// Hide messaging alert by default.
+.alert-messaging {
+	display: none;
+}
+
+// Add additional space under navs.
+.nav-tabs, .nav-pills {
+	margin-bottom: 15px;
+}
+
+// Flow panel heading.
+.flow-expander {
+	cursor: pointer;
+}
+
+// Flow summary.
+table .worksheet-key {
+	width: 25%;
+}
+
+// Job table.
+#all-jobs {
+  .tb-name {
+    width: 70%;
+    border-bottom-width: 0;
+    border-bottom-style: none;
+  }
+
+  .tb-up-date {
+    width: 140px;
+    min-width: 130px;
+  }
+
+  .tb-owner {
+    width: 10%;
+    min-width: 95px;
+  }
+}
+
+// Properties table.
+.properties-table {
+  .all-jobs .tb-pname {
+  }
+
+  .all-jobs .tb-pvalue {
+  }
+}
+
+// Permissions page table.
+.permission-table {
+  .tb-perm {
+    width: 41px;
+    margin: 0px;
+  }
+
+  .tb-admin {
+    width: 41px;
+    margin: 0px;
+  }
+
+  .tb-read {
+    width: 33px;
+    margin: 0px;
+  }
+
+  .tb-write {
+    width: 34px;
+    margin: 0px;
+  }
+
+  .tb-execute {
+    width: 51px;
+    margin: 0px;
+  }
+
+  .tb-schedule {
+    margin: 0px;
+    width: 60px;
+  }
+
+  .tb-action {
+    margin: 0px;
+    width: 70px;
+    min-width: 70px;
+    max-width: 70px;
+  }
+}
+
+// Table of executions.
+.executions-table {
+  th.date {
+    width: 140px;
+  }
+
+  th.execid {
+    width: 100px;
+  }
+
+  th.project {
+    width: 200px;
+  }
+
+  th.user {
+    width: 60px;
+  }
+
+  th.elapse {
+    width: 90px;
+  }
+
+  th.status {
+    width: 100px;
+  }
+
+  th.details {
+    width: 10px;
+  }
+
+  th.action {
+    width: 20px;
+  }
+
+  td.timeline {
+    width: 280px;
+    padding: 0px;
+    height: 100%;
+    vertical-align: bottom;
+    margin: 0px;
+  }
+
+  td.execId {
+    font-weight: bold;
+  }
+}
+
+
+.navbar-logo {
+  float: left;
+  padding: 15px 15px;
+  font-size: 18px;
+  line-height: 20px;
+
+  a {
+    &:hover,
+    &:focus {
+      text-decoration: none;
+    }
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar > .container .navbar-logo {
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-enviro {
+    width: auto;
+  }
+}
+
+.navbar-enviro {
+  margin: 25px 20px 0px 10px;
+     
+  .navbar-enviro-name {
+    color: #ff3601;
+    font-family: Helvetica, Arial, Sans-Serif;
+    font-size: 118.75%;
+    font-weight: bold;
+  }
+       
+  .navbar-enviro-server {
+    color: #999;
+    font-family: Helvetica, Arial, Sans-Serif;
+    font-size: 75%;
+  }
+}
+
+.navbar-inverse {
+  background-image: -o-linear-gradient(bottom, rgb(56,56,56) 33%, rgb(73,73,73) 66%);
+  background-image: -moz-linear-gradient(bottom, rgb(56,56,56) 33%, rgb(73,73,73) 66%);
+  background-image: -webkit-linear-gradient(bottom, rgb(56,56,56) 33%, rgb(73,73,73) 66%);
+  background-image: -ms-linear-gradient(bottom, rgb(56,56,56) 33%, rgb(73,73,73) 66%);
+  background-image: -webkit-gradient(
+   	linear,
+   	left bottom,
+   	left top,
+   	color-stop(0.33, rgb(56,56,56)),
+   	color-stop(0.66, rgb(73,73,73))
+  );
+  background-image: linear-gradient(bottom, rgb(56,56,56) 33%, rgb(73,73,73) 66%); 
+  border-top: 5px solid #ff3601;
+  box-shadow: 0 1px 4px 1px #000;
+
+  .navbar-logo {
+    background: url('../../images/logo.png') top left no-repeat;
+    color: #ffffff;
+    font-size: 156.25%;
+    font-weight: bold;
+    margin: 15px 0.6% 15px 4.75%;
+    padding: 12px 0 11px 42px;
+
+    a {
+      color: #ffffff;
+      &:hover,
+      &:focus {
+        color: #ffffff;
+        background-color: transparent;
+      }
+    }
+  }
+
+  .navbar-nav {
+    font-family: Arial;
+    font-size: 81.25%;
+
+    > li {
+      padding: 25px 12px 25px 12px;
+      cursor: pointer;
+      &:hover {
+        background-color: rgba(0, 0, 0, 0.1);
+      }
+    }
+
+    > li > a {
+      padding: 0px;
+      color: #ccc;
+    }
+
+    > .active {
+      background-color: rgba(0, 0, 0, 0.1);
+    }
+
+    > .active > a {
+      color: #fff;
+      font-weight: bold;
+      background-color: transparent;
+      border-bottom: 1px solid #ff3601;
+      &:hover {
+        background-color: transparent;
+      }
+    }
+
+    > .active > .open {
+      background-color: transparent;
+    }
+  }
+}
+
diff --git a/src/web/js/azkaban.project.view.js b/src/web/js/azkaban.project.view.js
index 0ccd2d5..a1b8f3d 100644
--- a/src/web/js/azkaban.project.view.js
+++ b/src/web/js/azkaban.project.view.js
@@ -117,8 +117,8 @@ azkaban.FlowTableView = Backbone.View.extend({
 			target.loading = true;
 			var requestData = {
 				"project": projectName, 
-				"ajax":"fetchflowjobs", 
-				"flow":targetId
+				"ajax": "fetchflowjobs", 
+				"flow": targetId
 			};
 			var successHandler = function(data) {
 				console.log("Success");
diff --git a/src/web/js/azkaban.schedule.panel.view.js b/src/web/js/azkaban.schedule.panel.view.js
index b869552..2e26845 100644
--- a/src/web/js/azkaban.schedule.panel.view.js
+++ b/src/web/js/azkaban.schedule.panel.view.js
@@ -72,9 +72,11 @@ azkaban.SchedulePanelView = Backbone.View.extend({
 			
 		var successHandler = function(data) {
 			if (data.error) {
+				schedulePanelView.hideSchedulePanel();
 				messageDialogView.show("Error Scheduling Flow", data.message);
 			}
 			else {
+				schedulePanelView.hideSchedulePanel();
 				messageDialogView.show("Flow Scheduled", data.message,
 					function() {
 						window.location.href = scheduleURL;