azkaban-uncached

Details

diff --git a/src/web/css/graph/azkaban.css b/src/web/css/graph/azkaban.css
new file mode 100644
index 0000000..f7f3fa8
--- /dev/null
+++ b/src/web/css/graph/azkaban.css
@@ -0,0 +1,2902 @@
+/* GLOBAL RESET */
+html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; -webkit-text-size-adjust: 100%; }
+ol, ul {list-style: none;}
+table {border-collapse: separate; border-spacing: 0;}
+caption, th, td {text-align: left; font-weight: normal;}
+blockquote:before, blockquote:after, q:before, q:after {content: "";}
+blockquote, q {quotes: "" "";}
+input[data-ime-mode-disabled] { ime-mode: disabled !important; }
+input[type=file] { ime-mode: disabled !important; }
+
+body {
+  background-color: #f0f0f0;
+  font-family: Helvetica, Arial, Sans-Serif;
+}
+
+body.nonelastic {
+  overflow: hidden;
+}
+
+textarea {
+	border: 2px inset;
+}
+
+dt.disabled {
+	color: #CCC;
+}
+label.disabled {
+	color: #CCC;
+}
+
+.header {
+  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;
+  height: 80px;
+  overflow: hidden;
+  position: relative;
+}
+
+.logo {
+  background: url(../../images/logo.png) top left no-repeat;
+  float: left;
+  font-family: "Helvetica Neue";
+  font-size: 156.25%;
+  font-weight: bold;
+  margin: 15px 0.6% 0 4.75%;
+  padding: 5px 0 11px 42px;
+}
+     
+.logo a {
+  color: #fff;
+  text-decoration: none;
+  font-family: Helvetica, Arial, Sans-Serif;
+}
+
+.enviro {
+  float: left;
+  margin-top: 25px;
+}
+     
+.enviro-name {
+  color: #ff3601;
+  font-family: Helvetica, Arial, Sans-Serif;
+  font-size: 118.75%;
+  font-weight: bold;
+}
+     
+.enviro-server {
+  color: #999;
+  font-family: Helvetica, Arial, Sans-Serif;
+  font-size: 75%;
+}
+
+.nav {
+  float: left;  
+  font-family: Arial;
+  font-size: 81.25%;
+  margin-left: 9.583333%;
+  overflow: hidden;
+}
+     
+.nav li {
+  float:left;
+  height: 48px;     
+  padding: 30px 12px 0 12px;
+}
+     
+.nav li:hover {
+  background-color: rgba(0, 0, 0, 0.1);
+  cursor: pointer;
+}
+
+.nav .selected {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+
+.nav .selected:hover,
+.nav .selected a:hover {
+  cursor: default;
+}
+     
+.nav a {
+  color: #ccc;
+  text-decoration: none;
+}
+     
+.nav .selected a {
+  border-bottom: 1px solid #ff3601;
+  color: #fff;
+  font-weight: bold;
+}
+
+.content {
+  background-color: #E0E0E0;
+  border: 1px solid #cdcdcd;
+  margin: 0 50px 10px;
+  min-height: 150px;
+}
+
+.content.history {
+  min-height: 75px;
+}
+
+.section-ft {
+  border-top: 1px solid #cdcdcd;
+}
+
+.section-ft,
+.section-hd {
+  overflow: hidden;
+  padding: 25px 2.7272727% 15px;
+}
+     
+.section-hd h2 {
+  clear: both;
+  float: left;
+  font-size: 125%;
+  font-weight: bold;
+}
+
+.section-hd h2 span{
+  padding-left: 5px;
+  font-weight: normal;
+  font-size: 90%;
+}
+
+.section-hd h2 a {
+  text-decoration:none;
+  color: #000;
+}
+
+.section-hd h2 a:hover {
+  color: #009FC9;
+}
+
+.section-hd h3 {
+  clear: both;
+  font-weight: bold;
+}
+
+.section-hd h3 a {
+  text-decoration:none;
+  color: #000;
+}
+
+.section-hd h3 a:hover {
+  color: #009FC9;
+}
+
+.section-hd h3 span {
+  padding-left: 5px;
+  font-weight: normal;
+  font-size: 90%;
+}
+
+.section-sub-hd {
+	clear: both;
+}
+
+.section-hd h4 {
+  float: left;
+  font-weight: bold;
+  font-size:11pt;
+  margin-right: 5px;
+}
+
+.section-hd h4 a {
+  text-decoration:none;
+  color: #888;
+}
+
+.section-hd h4 a:hover {
+  color: #009FC9;
+}
+
+.section-hd h4 span {
+  padding-left: 5px;
+  font-weight: normal;
+  font-size: 10pt;
+}
+
+.section-hd h4.separator {
+	color: #AAA;
+	padding-left: 5px;
+	font-weight: normal;
+  	font-size: 10pt;
+}
+
+table {
+  background-color: #fff;
+  font-family: Arial;
+  width: 100%;
+}
+
+th {
+  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%);
+  color: #fff;
+  font-weight: bold;
+  line-height: 1em;
+  font-size: 10.5pt;
+}
+     
+th,
+td {
+  border: 1px solid #cdcdcd;
+  border-left: none;
+  border-bottom: none;
+  padding: 5px;
+  font-size: 10pt;
+}
+
+.all-jobs td a {
+	color: #000;
+	text-decoration: none;
+	margin-left: 10px;
+}
+
+td a:hover {
+	color: #009FC9;
+}
+
+table .last {
+  border-right: none;
+}
+
+tr:hover td {
+  background-color: #E1E3E2;
+}
+
+.all-jobs .tb-name {
+  padding-left: 2.7272727%;
+  width: 70%;
+  border-bottom-width: 0;
+  border-bottom-style: none;
+}
+
+.all-jobs .tb-up-date {
+  width: 140px;
+  min-width: 130px;
+}
+
+.all-jobs .tb-owner {
+  width: 10%;
+  min-width: 95px;
+}
+
+.all-jobs .tb-pname {
+
+}
+
+.all-jobs .tb-pvalue {
+
+}
+
+/* messaging */
+.messaging {
+  color: #fff;
+  display: none;
+  font-weight: bold;
+  height: 30px;
+  margin: 2px 4.75% 0;
+  padding: 25px 0 20px;
+  position: absolute;
+  text-align: center;
+  width: 90.3%;
+}
+
+#messageClose {
+  float: right;
+  margin-right: 25px;
+}
+
+#messageClose:hover {
+  cursor: pointer;
+}
+
+.messaging.success {
+  background-color: #4e911e;
+  display: block;
+}
+
+.messaging.error {
+  background-color: #F80700;
+  display: block;
+}
+
+.rightbutton {
+	padding-top: 20px;
+	right: 10px;
+	margin-left: 5px;
+	margin-right: 5px;
+}
+
+/* buttons */
+.btn1,
+.btn2,
+.btn3,
+.btn4,
+.btn5,
+.btn6,
+.btn7,
+.btn-disabled {
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+  border-radius: 3px;
+  border-style: solid;
+  border-width: 1px;
+  cursor: pointer;
+  font-size: 12px;
+  font-weight: bold;
+  line-height: 1.35;
+  margin: 0;
+  padding: 3px 10px 2px;
+  text-decoration: none;
+}
+
+/* green */
+.btn1 {
+  background: -moz-linear-gradient(center top , #AFD47B 0pt, #AFD47B 1px, #8BC03F 1px, #69A219 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, color-stop(0,#AFD47B), color-stop(5%,#8BC03F),color-stop(100%,#69A219));
+  border-color: #669933;
+  color: #fff;
+}
+.btn1:hover {
+  background: -moz-linear-gradient(center top , #AFE47B 0pt, #AFE47B 1px, #8BD03F 1px, #69B219 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, color-stop(0,#AFE47B), color-stop(5%,#8BD03F),color-stop(100%,#69B219));
+}
+
+.section-hd .btn2,
+.section-hd .btn4,
+.section-hd .btn5,
+.section-hd .btn6,
+.section-ft .btn4, 
+.section-ft .btn5{
+  float: right;
+  margin-right: 10px;
+}
+
+.section-hd .btn1,
+.section-ft .btn1 {
+  float: right;
+  margin-right: 25px;
+}
+.section-hd .btn2,
+.section-ft .btn2 {
+  float: right;
+  margin-right: 25px;
+}
+
+/* blue */
+.btn2 {
+  background: -moz-linear-gradient(center top , #73AEC9 0pt, #73AEC9 1px, #338AB0 1px, #0571A6 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, color-stop(0,#73AEC9), color-stop(5%,#338AB0),color-stop(100%,#0571A6));
+  border-color: #045A8B;
+  color: #fff;
+}
+.btn2:hover {
+  background: -moz-linear-gradient(center top , #83BED9 0pt, #83BED9 1px, #43AAC0 1px, #1581B6 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, color-stop(0,#83BED9), color-stop(5%,#43AAC0),color-stop(100%,#1581B6));
+}
+/* grey */
+.btn3 {
+  background: #CECECE;
+  background: -moz-linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  background: -o-linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#F2F2F2), color-stop(5%,#F2F2F2), color-stop(5%,#E4E4E4), color-stop(100%,#CECECE));
+  background: linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#E4E4E4', endColorstr='#CECECE',GradientType=0 );
+  border-color: #999;
+  color: #666;
+}
+/* white */
+.btn4 {
+  background: -moz-linear-gradient(center top , white 0pt, #ECECEC 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, from(#FFF), to(#ECECEC));
+  background: linear-gradient(top, #FFF 0, #FFF 1px, #E4E4E4 1px, #CECECE 100%);
+  
+  border-color: #ccc;
+  color: #585858;
+  display: inline-block;
+  font-weight: normal;
+}
+
+/* grey */
+.btn7 {
+	background: #f2f5f6; /* Old browsers */
+	background: -moz-linear-gradient(top, #f2f5f6 0%, #e3eaed 37%, #c8d7dc 100%); /* FF3.6+ */
+	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f2f5f6), color-stop(37%,#e3eaed), color-stop(100%,#c8d7dc)); /* Chrome,Safari4+ */
+	background: -webkit-linear-gradient(top, #f2f5f6 0%,#e3eaed 37%,#c8d7dc 100%); /* Chrome10+,Safari5.1+ */
+	background: -o-linear-gradient(top, #f2f5f6 0%,#e3eaed 37%,#c8d7dc 100%); /* Opera 11.10+ */
+	background: -ms-linear-gradient(top, #f2f5f6 0%,#e3eaed 37%,#c8d7dc 100%); /* IE10+ */
+	background: linear-gradient(to bottom, #f2f5f6 0%,#e3eaed 37%,#c8d7dc 100%); /* W3C */
+	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f2f5f6', endColorstr='#c8d7dc',GradientType=0 ); /* IE6-9 */
+	  
+	border-color: #9BA7AA;
+	color: #61696B;
+	display: inline-block;
+	font-weight: bold;
+}
+.btn7:hover {
+	background: #fcfeff; /* Old browsers */
+	background: -moz-linear-gradient(top, #fcfeff 0%, #f2f9fc 37%, #deeff4 100%); /* FF3.6+ */
+	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fcfeff), color-stop(37%,#f2f9fc), color-stop(100%,#deeff4)); /* Chrome,Safari4+ */
+	background: -webkit-linear-gradient(top, #fcfeff 0%,#f2f9fc 37%,#deeff4 100%); /* Chrome10+,Safari5.1+ */
+	background: -o-linear-gradient(top, #fcfeff 0%,#f2f9fc 37%,#deeff4 100%); /* Opera 11.10+ */
+	background: -ms-linear-gradient(top, #fcfeff 0%,#f2f9fc 37%,#deeff4 100%); /* IE10+ */
+	background: linear-gradient(to bottom, #fcfeff 0%,#f2f9fc 37%,#deeff4 100%); /* W3C */
+	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fcfeff', endColorstr='#deeff4',GradientType=0 ); /* IE6-9 */
+}
+
+/* grey right */
+.btn5 {
+  background: #CECECE;
+  background: -moz-linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  background: -o-linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#F2F2F2), color-stop(5%,#F2F2F2), color-stop(5%,#E4E4E4), color-stop(100%,#CECECE));
+  background: linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#E4E4E4', endColorstr='#CECECE',GradientType=0 );
+  border-color: #999;
+  color: #666;
+}
+.btn3:hover {
+  background: -moz-linear-gradient(center top , white 0pt, #ECECEC 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, from(#FFF), to(#ECECEC));
+}
+
+.btn-disabled {
+  background: #CECECE;
+  background: -moz-linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  background: -o-linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#F2F2F2), color-stop(5%,#F2F2F2), color-stop(5%,#E4E4E4), color-stop(100%,#CECECE));
+  background: linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  color: #EEE;
+}
+
+/* red */
+.btn6 {
+  background: #cc9999;
+  background: -moz-linear-gradient(top, #cc6161 0, #cc6161 1px, #cc0000 1px, #931100 100%);
+  background: -o-linear-gradient(top, #cc6161 0, #cc6161 1px, #cc0000 1px, #931100 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#cc6161), color-stop(5%,#cc6161), color-stop(5%,#cc0000), color-stop(100%,#931100));
+  background: linear-gradient(top, #cc6161 0, #cc6161 1px, #cc0000 1px, #931100 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cc0000', endColorstr='#931100',GradientType=0 );
+  border-color: #931100;
+  color: #fff;
+}
+
+.btn6:hover {
+  background: #cc9999;
+  background: -moz-linear-gradient(top, #cc6161 0, #cc6161 1px, #CC4343 1px, #912C21 100%);
+  background: -o-linear-gradient(top, #cc6161 0, #cc6161 1px, #CC4343 1px, #912C21 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#cc6161), color-stop(5%,#cc6161), color-stop(5%,#CC4343), color-stop(100%,#912C21));
+  background: linear-gradient(top, #cc6161 0, #cc6161 1px, #CC4343 1px, #931100 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#CC4343', endColorstr='#912C21',GradientType=0 );
+  border-color: #912C21;
+  color: #fff;
+}
+
+/* confirm modal */
+
+.modalContainer2 {
+  display: none;
+  position: absolute;
+}
+
+.modalBackground2 {
+	position: absolute;
+	display: none;
+	left: 0px;
+	right: 0px;
+	top: 0px;
+	bottom: 0px;
+	background-color: rgba(0, 0, 0, 0.4);
+}
+
+.modalBackground3 {
+	position: absolute;
+	display: none;
+	left: 0px;
+	right: 0px;
+	top: 0px;
+	bottom: 0px;
+	background-color: rgba(0, 0, 0, 0);
+}
+
+.search-input {
+  border: 1px solid;
+  border-color: #7C7C7C #C3C3C3 #DDDDDD;
+  float: right;
+  height: 18px;
+  line-height: 12px;
+  padding: 4px 2px 0;
+  width: 310px;
+}
+
+.search-btn {
+  background: -moz-linear-gradient(center top , #E8E8E8 0pt, #CCC 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, from(#E8E8E8), to(#CCC));
+  border: 1px solid #999;
+  border-top-right-radius: 3px;
+  border-bottom-right-radius: 3px;
+  border-left: none;
+  color: #666;
+  float: right;
+  font-weight: bold;
+  height: 24px;
+  font-size: 10pt;
+}
+
+.search-btn:hover {
+  background: -moz-linear-gradient(center top , #F0F0F0 0pt, #DDD 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, from(#F0F0F0), to(#DDD));
+  cursor: pointer;
+}
+
+.advfilter-btn {
+  background: -moz-linear-gradient(center top , #E8E8E8 0pt, #CCC 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, from(#E8E8E8), to(#CCC));
+  border: 1px solid #999;
+  border-top-right-radius: 3px;
+  border-bottom-right-radius: 3px;
+  border-left: none;
+  color: #666;
+  float: right;
+  font-weight: bold;
+  height: 24px;
+  font-size: 10pt;
+}
+
+.advfilter-btn:hover {
+  background: -moz-linear-gradient(center top , #F0F0F0 0pt, #DDD 100%) repeat scroll 0 0 transparent;
+  background: -webkit-gradient(linear, center top, center bottom, from(#F0F0F0), to(#DDD));
+  cursor: pointer;
+}
+
+
+#scheduled-jobs-content,
+#executing-jobs-content {
+  display: none;
+}
+
+.subpage-nav {
+  float: left;
+  overflow: hidden;
+  padding-top: 4px;
+  width: 250px;
+}
+
+.subpage-nav li {
+  float: left;
+  padding: 0 10px;
+  border-right: 1px solid #848484;
+}
+
+.subpage-nav .last {
+  border-right: none;
+}
+
+.subpage-nav a {
+  color: #006699;
+  text-decoration: none;
+}
+
+.subpage-nav .selected {
+  color: #000;
+  font-weight: bold;
+}
+
+.job-properties  {
+  clear: both;
+  font-size: 13px;
+  margin-top: 50px;
+  overflow: hidden;
+}
+
+.job-properties dt {
+  clear: both;
+  float: left;
+  font-weight: bold;
+  padding-bottom: 3px;
+  width: 110px;
+}
+
+.job-properties dd {
+  float: left;
+  padding-bottom: 3px;
+}
+
+.tb-key {
+  padding-left: 2.72727%;
+  width: 40%;
+}
+
+.tb-value {
+  padding-left: 5%;
+}
+
+.no-jobs {
+  padding: 0 0 25px 2.72727%;
+}
+
+.modal {
+  display: none;
+  background-color: #fff;
+  border: 1px solid #DDD;
+  -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);
+  -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);
+  overflow: hidden;
+}
+
+.modal p {
+	margin-left: 30px;
+}
+
+.modal h3 {
+  border-bottom: 1px solid #d0d0d0;
+  font-weight: bold;
+  margin: 20px 20px 10px 20px;
+  padding-bottom: 8px; 
+}
+
+.modal h4 {
+  font-weight: bold;
+  margin: 20px 20px 10px 40px;
+  padding-bottom: 8px;
+}
+
+.modal .message {
+  padding: 20px;
+}
+
+.modal .actions {
+  clear: both;
+  background-color: #f0f0f0;
+  margin-top: 10px;
+  overflow: hidden;
+  padding: 16px 16px 20px 0;
+}
+
+.modalContainer2.modal .actions {
+  position: absolute;
+  background-color: #f0f0f0;
+  margin-top: 10px;
+  overflow: hidden;
+  padding: 16px 16px 20px 0;
+  bottom: 0px;
+  right: 0px;
+  left: 0px;
+}
+
+.modal .btn1,
+.modal .btn2,
+.modal .btn3,
+.modal .btn6 {
+  float: right;
+  margin-left: 10px;
+}
+
+.modal-close {
+  color: #666;
+  font-weight: bold;
+  text-decoration: none;
+  cursor: pointer;
+  position: absolute;
+  top: 10px;
+  right: 17px;
+}
+
+.modal dt {
+  clear: both;
+  float: left;
+  padding: 0 10px 6px 0;
+  text-align: right;
+  font-weight: bold;
+  font-size: 11pt;
+  width: 150px;
+}
+
+.modal dd {
+  float: left;
+  padding-bottom: 6px;
+}
+
+#change-permission dt {
+  clear: none;
+  width: 75px;
+  padding: 0 0 0 0;
+}
+
+#change-permission dt.nextline {
+	clear: both;
+}
+
+#user-box {
+	background-color: #FFF;
+	margin-left: 10px;
+	width: 300px;
+	border-style: solid;
+	border-color: #CCC;
+	height: 20px;
+	font-size: 11pt;
+}
+
+#proxy-user-box {
+	background-color: #FFF;
+	margin-left: 10px;
+	width: 300px;
+	border-style: solid;
+	border-color: #CCC;
+	height: 20px;
+	font-size: 11pt;
+}
+
+#create-project #overwrite {
+  width: 12px;
+}
+
+.simplemodal-wrap {
+  overflow: visible !important;
+}
+
+#schedule-job .message {
+  padding-top: 0;
+}
+
+.message p {
+  margin-bottom: 15px;
+}
+
+#create-project dt {
+  width: 100px;
+}
+
+#create-project input {
+  width: 280px;
+}
+
+.filter_statuses {
+  float: right;
+  margin-right: 25px;
+}
+
+.joblist:hover a {
+  display: inline;
+}
+
+/* clean up */
+.state-icon {
+  background-image: url("../css/images/ui-icons_cccccc_256x240.png");
+  cursor: pointer;
+  display: block;
+  float: left;
+  height: 16px;
+  margin-right: 5px;
+  width: 16px;
+}
+
+.flowSubmenu li {
+	clear: both;
+}
+
+.flowSubmenu a {
+	float: left;
+	width: 70%;
+}
+
+.context-sub-icon {
+  float: right;
+  background-image: url("../css/images/ui-icons_cccccc_256x240.png");
+  cursor: pointer;
+  display: block;
+  height: 16px;
+  margin-right: 5px;
+  width: 16px;
+  background-position: -32px -16px;
+}
+
+.collapse.context-sub-icon {
+  	background-position: 0 -16px;
+}
+
+.collapse.state-icon {
+	background-position: 0 -16px;
+}
+
+.collapse tr {
+	border-bottom: none;
+}
+
+.expand .state-icon {
+	background-position: -32px -16px;
+}
+
+.wait .state-icon {
+	background-position: -64px -80px
+}
+
+.tb-name a {
+	font-size: 10pt;
+	text-decoration: none;
+	color: #000;
+}
+
+.tb-name a:hover {
+	color: #009FC9;
+}
+
+.azkaban-charts,
+.azkaban-charts td {
+	width: 100%;
+}
+
+.azkaban-charts td {
+  border: none;
+  padding: 0;
+}
+
+.treeline {
+	background: url(../../images/treeview-default-line.gif) 0 0 no-repeat;
+	float: left;
+	height: 22px;
+}
+
+.treeline.last { background-position: 0 -1766px }
+
+.joblist {
+  margin-left: 10px;
+}
+
+.joblist a {
+  color: #006699;
+  padding-left: 15px;
+}
+
+.joblist .job-name {
+  color: #666;
+  text-decoration: none;
+}
+
+.joblist .hidden {
+  display: none;
+}
+
+#login {
+	width: 500px;
+	margin: 50px auto;
+}
+
+.login-form {
+    margin-top: 10px;
+}
+
+.login-form p {
+	margin-top: 10px;
+}
+
+.login-textbox {
+	width: 300px;
+	border-style: solid;
+	border-color: #CCC;
+	height: 20px;
+	font-size: 11pt;
+	position: relative;
+	float: left;
+}
+
+.login-password {
+	width: 100%;
+	height: 300px;
+}
+
+.login-label {
+	clear: both;
+	text-align: right;
+	width: 120px;
+	float: left;
+	margin: 10px;
+	font-size: 11pt;
+	font-weight: bold;
+}
+
+.login-submit {
+	clear: both;
+    color: #333;   
+    font: bold 12pt 'trebuchet ms',helvetica,sans-serif;
+    margin-top: 20px;
+    padding: 3px 20px;
+    
+}
+
+.box-title {
+  margin-top: 15px;
+  padding: 5px 12px;
+  font-size: 14pt;
+  font-weight: bold;
+}
+
+.box-success-message {
+  background-color: #4e911e;
+  margin: 0px 2px;
+  padding: 2px 12px;
+  color: white;
+}
+
+.box-error-message {
+  background-color: #C00000;
+  margin: 0px 2px;
+  padding: 2px 12px;
+  color: white;
+}
+
+.shadow-box {
+  -moz-box-shadow: 5px 5px 5px #CCC;
+  -webkit-box-shadow: 5px 5px 5px #CCC;
+  box-shadow: 5px 5px 5px #CCC;
+  background-color: white;
+  border-style: solid;
+  border-width: 1px;
+  border-color: #AAA;
+}
+
+.shadow-box-header {
+	margin-left: 20px;
+	margin-right: 20px;
+	border-bottom-width: 1px;
+	border-bottom-style: solid;
+	border-bottom-color: #AAA;
+}
+
+.shadow-box-content {
+	margin-left: 20px;
+	margin-right: 20px;
+}
+
+.shadow-box-footer {
+  clear: both;
+  background-color: #EEE;
+  height: 50px;
+}
+
+.shadow-box-footer .button1 {
+	float: right;
+	margin-right: 10px;
+	margin-top: 10px;
+	padding-left: 15px;
+	padding-right: 15px;
+}
+
+#user-id {
+  position: absolute;
+  right:40px;
+  top: 28px;
+  font-size: 100%;
+  height: 40px;
+  margin: 3px;
+}
+
+#user-id a {
+  color: #CCC;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+#user-id a:hover {
+  text-decoration: underline;
+}
+
+#user-down {
+  float: right;
+  background-image: url("../css/images/ui-icons_cccccc_256x240.png");
+  height: 16px;
+  width: 16px;
+  background-position: -64px -16px;
+}
+
+#user-down:hover {
+  cursor: pointer;
+}
+
+#user-menu {
+	position: absolute;
+	background: #222;
+	width: 75px;
+	padding-left: 5px;
+	padding-top: 2px;
+	padding-bottom: 2px;
+	-moz-border-radius: 4px;
+	border-radius: 4px;
+	top: 20px;
+}
+
+/*project manager page*/
+#project-summary {
+	margin-left: 30px;
+	margin-bottom: 10px;
+	width: 60%;
+}
+
+#project-users {
+	float: right;
+	margin-right: 30px;
+	margin-bottom: 10px;
+	width: 30%;
+}
+
+#adminActions {
+	
+}
+
+#job-summary {
+	margin-left: 30px;
+	margin-bottom: 10px;
+	width:90%;
+}
+
+#job-summary table tr td a {
+	text-decoration: none;
+	color: #555;
+	margin-left: 0px;
+	margin-right: 10px;
+}
+
+#job-summary table tr td span {
+	color: #555;
+}
+
+#job-summary table tr td a:hover {
+	text-decoration: none;
+	color: #009FC9;
+}
+
+#job-summary .first {
+	width: 100px;
+}
+
+.summary-table {
+	font-size: 12px;
+	background: none;
+	border-style: none;
+	border-width: 0px;
+}
+.summary-table .first {
+	min-width: 100px;
+	font-weight: bold;
+}
+
+.summary-table td {
+	border-style: none;
+}
+
+.summary-table td.left{
+	text-align: left;
+}
+
+.user-table {
+	font-size: 12px;
+	background: none;
+	border-style: none;
+	border-width: 0px;
+}
+.user-table .first {
+	width: 150px;
+	font-weight: bold;
+}
+
+.user-table td {
+	border-style: none;
+}
+
+/* Style for job display table */
+.childrow td.innerTd {
+	padding: 0px;
+	height: 100px;
+	width: 100%;
+}
+
+/* Style for job display table */
+.childrow {
+	padding: 0px;
+	width: 100%;
+}
+
+.childrow .innerTable {
+	margin-left:auto;
+	margin-right: auto;
+	text-align: center;
+	width: 90%;
+}
+
+.childrow .expandedFlow {
+	border-style: none;
+	background-color: #FFF;
+}
+
+.childrow:hover td {
+	background-color: #FFF;
+}
+
+.childrow .expandedFlow:hover {
+	border-style: none;
+	background-color: #FFF;
+}
+
+.childrow .expandedFlow td{
+	border-style: solid solid none none;
+}
+
+.childrow .innerTable {
+	border-style: none none solid solid;
+	border-width: 1px;
+	border-color: #CDCDCD;
+}
+
+.childrow .innerTable tr {
+}
+
+.childrow .innerTable td {
+	border-style: solid solid none none;
+	border-width: 1px 1px medium medium;
+	border-color: #CDCDCD;
+}
+
+.childrow .innerTable a {
+	cursor: pointer;
+}
+
+.childrow .innerTable a:hover {
+	color: #009FC9;
+}
+
+.childrow .innerTable a.dependent {
+	color: #3B8194;
+}
+
+.childrow .innerTable a.dependency {
+	color: #0099CC;
+}
+
+.childrow .innerJobRow {
+	border-top: none;
+	height: 100px;
+}
+
+.headertabs {
+	height: 26px;
+	width:100%;
+	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%);
+  color: #fff;
+  font-weight: bold;
+  line-height: 1em;
+  font-size: 10.5pt;
+}
+
+.headertabs ul li {
+	float: left;
+	margin-top: 5px;
+	margin-left: 12px;
+}
+
+.headertabs ul.buttons {
+	float: right;
+	margin-right: 10px;
+}
+
+.headertabs ul.buttons li {
+	margin-top: 1px;
+	margin-left: 2px;
+}
+
+.headertabs ul li.lidivider {
+	color: #808080;
+}
+
+.headertabs ul li:hover {
+	
+}
+
+/* Flow view tabs */
+.headertabs ul li a {
+	color: #aaa;
+}
+
+.headertabs ul li a:hover {
+	color: #fff;
+}
+
+/* Flow view tabs */
+.headertabs ul li a.selected {
+	color: #fff;
+}
+
+.actualcontent {
+	clear: both;
+}
+
+/* Graph SVG */
+#graphView {
+	position: absolute;
+	top: 202px;
+	bottom: 5px;
+	left: 50px;
+	right: 50px;
+	padding: 10px;
+	background: #E0E0E0;
+}
+
+#jobListView {
+	position: absolute;
+	top: 210px;
+	bottom: 5px;
+	left: 50px;
+	right: 50px;
+	padding: 0px;
+	background: #E0E0E0;
+	overflow-y: auto;
+}
+
+.logView {
+	position: absolute;
+	top: 210px;
+	bottom: 5px;
+	left: 50px;
+	right: 50px;
+	background: #E0E0E0;
+}
+
+#flowLogView {
+	top: 210px;
+	bottom: 5px;
+}
+
+#jobLogView {
+	top: 210px;
+	bottom: 5px;
+}
+
+.logHeader {
+	height: 30px;
+	margin: 0px;
+	width: 100%;
+	background-color: #CCC;
+}
+
+.logButtonRow {
+	padding-top: 4px;
+	padding-left: 4px;
+}
+
+.logViewer {
+	position: absolute;
+	top: 35px;
+	bottom: 5px;
+	left: 5px;
+	right: 5px;
+	background-color: #FFF;
+	overflow:auto;
+}
+
+.logLink {
+	text-align: center;
+}
+
+.logLink a {
+	text-decoration: underline;
+	margin: 0px;
+}
+
+.log {
+	padding-left: 15px;
+	font-family: "courier";
+	font-size: 10pt;
+}
+
+#logTable td.time {
+	width: 160px;
+}
+
+#logTable td.user {
+	width: 80px;
+}
+
+#logTable td.type {
+	width: 160px;
+}
+
+.relative {
+	position: relative;
+	width: 100%;
+	height: 100%;
+}
+
+#editIcon {
+	text-align: center;
+}
+
+#toolsBar .btn3{
+	float: left;
+	margin-left: 3px;
+}
+
+.svgGraph {
+	width: 100%;
+	height: 100%;
+	background: #fff;
+	left: 0px
+}
+
+.rightPanel {
+	position: absolute;
+	top: 0px;
+	right: 0px;
+	left: 280px;
+	bottom: 0px;
+}
+.rightPanel .sidePanel {
+	width: 100%;
+	height: 100%;
+	background: #fff;
+	left: 0px;
+	overflow:auto;
+}
+.rightPanel h4 {
+	font-size: 11pt;
+	padding: 0px;
+	margin: 15px 10px 5px 2px;
+}
+
+.rightPanel p {
+	font-size: 10pt;
+	margin-left: 25px;
+	color: #555;
+}
+
+.rightPanel .sidePanel.svgDiv {
+	overflow:hidden;
+}
+
+.rightPanel .checkbox {
+	height: 10px;
+	margin-left: 20px;
+}
+
+.rightPanel label {
+	font-size: 11pt;
+}
+
+.rightPanel textarea {
+	font-size: 10pt;
+	width: 500px;
+}
+
+.rightPanel .radio {
+	margin-left: 15px;
+	margin-bottom: 5px;
+	margin-top: 15px;
+}
+
+.radioLabel.disabled {
+	opacity: 0.3;
+}
+
+.sideMenu p {
+	color: #555;
+}
+
+.rightPanel ul {
+	margin-left: 20px;
+}
+
+.rightPanel li {
+	list-style-type: circle;
+	margin-left: 20px;
+	font-size: 9pt;
+	color: #555;
+}
+
+.rightPanel select {
+	margin: 15px 20px 5px 20px;
+}
+
+/* executing options panel*/
+#executing-options {
+	left: 100px;
+	right: 100px;
+	top: 50px;
+	bottom: 40px;
+}
+
+#executing-options .svgDiv {
+	position: absolute;
+	padding: 1px;
+	left: 270px;
+	right: 0px;
+	top: 0px;
+	bottom: 0px;
+}
+
+#executing-options .jobList {
+	position: absolute;
+	width: 255px;
+	top: 0px;
+	bottom: 0px;
+	padding: 5px;
+}
+
+#executing-options .list {
+	width: 255px;
+}
+
+#executing-options ul.optionsPicker {
+	margin-left: 30px;
+}
+
+#executing-options ul.optionsPicker li {
+	float: left;
+	font-size: 12pt;
+	font-weight: bold;
+	margin-right: 15px;
+	cursor: pointer;
+	color: #CCC;
+}
+
+#executing-options ul.optionsPicker li.selected {
+	text-decoration: underline;
+	color: #000;
+}
+
+#executing-options ul.optionsPicker li.selected:hover {
+	color: #000;
+}
+
+#executing-options ul.optionsPicker li:hover {
+	color: #888;
+}
+
+#executing-options .optionsPane {
+	position: absolute;
+	top: 85px;
+	background-color: #FFF;
+	left: 0px;
+	right: 0px;
+	bottom: 0px;
+}
+
+#executing-options .panel {
+	position: absolute;
+	width: 100%;
+	top: 0px;
+	bottom: 65px;
+}
+
+#executing-options .generalPanel.panel {
+	background-color: #F4F4F4;
+	padding-top: 15px;
+}
+
+#executing-options h3 {
+	margin-left: 20px;
+	font-size: 14pt;
+	border-bottom: 1px solid #CCC;
+}
+
+#executing-options h4 {
+	margin-left: 20px;
+	font-size: 12pt;
+	border-bottom: 1px solid #CCC;
+}
+
+#sla-options {
+	left: 100px;
+	right: 100px;
+	top: 50px;
+	bottom: 40px;
+}
+
+#sla-options .svgDiv {
+	position: absolute;
+	background-color: #CCC;
+	padding: 1px;
+	left: 270px;
+	right: 0px;
+	top: 0px;
+	bottom: 0px;
+}
+
+#sla-options .jobList {
+	position: absolute;
+	width: 255px;
+	top: 0px;
+	bottom: 0px;
+	padding: 5px;
+	background-color: #F0F0F0;
+}
+
+#sla-options .list {
+	width: 255px;
+}
+
+#sla-options ul.optionsPicker {
+	margin-left: 30px;
+}
+
+#sla-options ul.optionsPicker li {
+	float: left;
+	font-size: 12pt;
+	font-weight: bold;
+	margin-right: 15px;
+	cursor: pointer;
+	color: #CCC;
+}
+
+#sla-options ul.optionsPicker li.selected {
+	text-decoration: underline;
+	color: #000;
+}
+
+#sla-options ul.optionsPicker li.selected:hover {
+	color: #000;
+}
+
+#sla-options ul.optionsPicker li:hover {
+	color: #888;
+}
+
+#sla-options .optionsPane {
+	position: absolute;
+	top: 85px;
+	background-color: #FFF;
+	left: 0px;
+	right: 0px;
+	bottom: 0px;
+}
+
+#sla-options .panel {
+	position: absolute;
+	width: 100%;
+	top: 0px;
+	bottom: 65px;
+}
+
+#sla-options .generalPanel.panel {
+	background-color: #F4F4F4;
+	padding-top: 15px;
+}
+
+#sla-options h3 {
+	margin-left: 20px;
+	font-size: 14pt;
+	border-bottom: 1px solid #CCC;
+}
+
+#sla-options h4 {
+	margin-left: 20px;
+	font-size: 12pt;
+	border-bottom: 1px solid #CCC;
+}
+
+
+#job-edit-pane {
+	left: 100px;
+	right: 100px;
+	top: 50px;
+	bottom: 40px;
+}
+
+#job-edit-pane .list {
+	width: 255px;
+}
+
+#job-edit-pane .optionsPane {
+	position: absolute;
+	top: 85px;
+	background-color: #FFF;
+	left: 0px;
+	right: 0px;
+	bottom: 0px;
+}
+
+#job-edit-pane .panel {
+	position: absolute;
+	width: 100%;
+	top: 0px;
+	bottom: 65px;
+}
+
+#job-edit-pane .generalPanel.panel {
+	background-color: #F4F4F4;
+	padding-top: 15px;
+}
+
+#job-edit-pane h3 {
+	margin-left: 20px;
+	font-size: 14pt;
+	border-bottom: 1px solid #CCC;
+}
+
+#job-edit-pane h4 {
+	margin-left: 20px;
+	font-size: 12pt;
+	border-bottom: 1px solid #CCC;
+}
+
+#schedule-options {
+	left: 100px;
+	right: 100px;
+	top: 50px;
+	bottom: 40px;
+}
+
+#schedule-options .svgDiv {
+	position: absolute;
+	background-color: #CCC;
+	padding: 1px;
+	left: 270px;
+	right: 0px;
+	top: 0px;
+	bottom: 0px;
+}
+
+#schedule-options .jobList {
+	position: absolute;
+	width: 255px;
+	top: 0px;
+	bottom: 0px;
+	padding: 5px;
+	background-color: #F0F0F0;
+}
+
+#schedule-options .list {
+	width: 255px;
+}
+
+#schedule-options ul.optionsPicker {
+	margin-left: 30px;
+}
+
+#schedule-options ul.optionsPicker li {
+	float: left;
+	font-size: 12pt;
+	font-weight: bold;
+	margin-right: 15px;
+	cursor: pointer;
+	color: #CCC;
+}
+
+#schedule-options ul.optionsPicker li.selected {
+	text-decoration: underline;
+	color: #000;
+}
+
+#schedule-options ul.optionsPicker li.selected:hover {
+	color: #000;
+}
+
+#schedule-options ul.optionsPicker li:hover {
+	color: #888;
+}
+
+#schedule-options .optionsPane {
+	position: absolute;
+	top: 85px;
+	background-color: #FFF;
+	left: 0px;
+	right: 0px;
+	bottom: 0px;
+}
+
+#schedule-options .panel {
+	position: absolute;
+	width: 100%;
+	top: 0px;
+	bottom: 65px;
+}
+
+#schedule-options .generalPanel.panel {
+	background-color: #F4F4F4;
+	padding-top: 15px;
+}
+
+#schedule-options h3 {
+	margin-left: 20px;
+	font-size: 14pt;
+	border-bottom: 1px solid #CCC;
+}
+
+#schedule-options h4 {
+	margin-left: 20px;
+	font-size: 12pt;
+	border-bottom: 1px solid #CCC;
+}
+
+#graphPanel {
+	background-color: #F0F0F0;
+}
+
+#generalPanel {
+	overflow: auto;
+}
+
+#generalPanel dt {
+	width: 150px;
+	font-size: 10pt;
+	font-weight: bold;
+	margin-top: 5px;
+}
+
+#generalPanel textarea {
+	width: 500px;
+}
+
+#generalPanel table #addRow {
+	cursor: pointer;
+}
+
+#generalPanel table tr {
+	height: 24px;
+}
+
+#generalPanel table .editable {
+
+}
+
+#generalPanel table .editable input {
+	border: 1px solid #009FC9;
+	height: 16px;
+}
+
+#generalPanel table .name {
+	width: 40%;
+}
+
+#generalPanel span.addIcon {
+	display: block;
+	width: 16px;
+	height: 16px;
+	background-image: url("./images/addIcon.png");
+}
+
+#generalPanel span.removeIcon {
+	display: block;
+	visibility:hidden;
+	disabled: true;
+	width: 16px;
+	height: 16px;
+	background-image: url("./images/removeIcon.png");
+	cursor: pointer;
+}
+
+#generalPanel .editable:hover span.removeIcon {
+	visibility:visible;
+}
+
+#generalPanel {
+}
+
+#generalPanel span {
+	float: left;
+	margin-left: 5px;
+}
+
+#generalPanel dd {
+	font-size: 10pt;
+}
+
+#flowPropertyOverride {
+	clear: both;
+	padding-top: 30px;
+}
+
+#flowPropertyOverride .tableDiv {
+	padding-right: 20px;
+	padding-left: 20px;
+}
+
+#jobList {
+	position: absolute;
+	top: 0px;
+	left: 0px;
+	height: 100%;
+	width: 250px;
+}
+
+#flowGraphOptions {
+	position: absolute;
+	bottom: 70px;
+}
+
+#flowGraphOptions label{
+	font-size: 9pt;
+}
+
+#nodeOptions {
+	position: absolute;
+	bottom: 10px;
+}
+
+#flowProperties {
+	position: absolute:
+	height: 100px;
+	width: 100%;
+	background-color: #000;
+	top: 100px;
+}
+
+#scheduleGraphPanel {
+	background-color: #F0F0F0;
+}
+
+#scheduleGeneralPanel {
+	overflow: auto;
+}
+
+#scheduleGeneralPanel dt {
+	width: 150px;
+	font-size: 10pt;
+	font-weight: bold;
+	margin-top: 5px;
+}
+
+#scheduleGeneralPanel textarea {
+	width: 500px;
+}
+
+#scheduleGeneralPanel table #addRow {
+	cursor: pointer;
+}
+
+#scheduleGeneralPanel table tr {
+	height: 24px;
+}
+
+#scheduleGeneralPanel table .editable {
+
+}
+
+#scheduleGeneralPanel table .editable input {
+	border: 1px solid #009FC9;
+	height: 16px;
+}
+
+#scheduleGeneralPanel table .name {
+	width: 40%;
+}
+
+#scheduleGeneralPanel span.addIcon {
+	display: block;
+	width: 16px;
+	height: 16px;
+	background-image: url("./images/addIcon.png");
+}
+
+#scheduleGeneralPanel span.removeIcon {
+	display: block;
+	visibility:hidden;
+	disabled: true;
+	width: 16px;
+	height: 16px;
+	background-image: url("./images/removeIcon.png");
+	cursor: pointer;
+}
+
+#scheduleGeneralPanel .editable:hover span.removeIcon {
+	visibility:visible;
+}
+
+#scheduleGeneralPanel {
+}
+
+#scheduleGeneralPanel span {
+	float: left;
+	margin-left: 5px;
+}
+
+#scheduleGeneralPanel dd {
+	font-size: 10pt;
+}
+
+#scheduleFlowPropertyOverride {
+	clear: both;
+	padding-top: 30px;
+}
+
+#scheduledFlowsTbl td a:hover {
+	color: #009FC9;
+}
+
+#scheduledFlowsTbl td a {
+	font-size: 10pt;
+	text-decoration: none;
+	color: #000;
+}
+
+#scheduleFlowPropertyOverride .tableDiv {
+	padding-right: 20px;
+	padding-left: 20px;
+}
+
+#scheduleJobList {
+	position: absolute;
+	top: 0px;
+	left: 0px;
+	height: 100%;
+	width: 250px;
+}
+
+.filter {
+	width: 100%;
+}
+
+
+.list {
+	position: absolute;
+	background-color: #fff;
+	margin-right: 10px;
+	border: solid;
+	border-color: #CCC;
+	border-width: 1px;
+	overflow: auto;
+	top: 26px;
+	width: 100%;
+	bottom: 120px;
+}
+
+.list ul {
+	white-space: nowrap
+}
+
+.list ul li {
+	margin: 4px 5px;
+	border-bottom: 1px solid #EEE;
+	cursor: pointer;
+	background-position: 16px 0px;
+}
+
+.list ul li:hover {
+	background-color: #E1E3E2;
+	color: #009FC9;
+}
+
+.list ul li.selected {
+	background-color: #009FC9;
+	color: #EEE;
+}
+
+.list ul li.nodedisabled {
+	opacity: 0.3;
+}
+
+.list ul li.DISABLED {
+	opacity: 0.3;
+}
+
+.list ul li.DISABLED .icon {
+	background-position: 16px 0px;
+}
+
+.list ul li.READY .icon {
+	background-position: 16px 0px;
+}
+
+.list ul li.QUEUED .icon {
+	opacity: 0.5;
+	background-position: 32px 0px;
+}
+
+.list ul li.RUNNING .icon {
+	background-position: 32px 0px;
+}
+
+.list ul li.SUCCEEDED .icon {
+	background-position: 48px 0px;
+}
+
+.list ul li.FAILED .icon {
+	background-position: 0px 0px;
+}
+
+.list ul li.KILLED .icon {
+	background-position: 0px 0px;
+}
+
+.list ul li a {
+	font-size: 10pt;
+	margin-left: 5px;
+}
+
+.list ul li a span {
+	background-color: #FF0;
+	color: black;
+}
+
+.list ul li .icon {
+	float: left;
+	width: 16px;
+	height: 16px;
+	background-image: url("./images/dot-icon.png");
+	background-position: 16px 0px;
+}
+
+#messageDialog .messageDiv {
+	margin: 20px;
+}
+
+table.parameters tr td.first {
+	font-weight: bold;
+}
+
+table.parameters tr td {
+	font-size: 11pt;
+	padding-left: 10px;
+}
+
+#pdescription {
+	width: 70%;
+}
+
+.editTextArea {
+	width: 100%;
+}
+
+#edit {
+	width: 100px;
+	text-align: center;
+}
+
+#group-permissions-table {
+	margin-top: 20px;
+}
+
+.permission-table .tb-username {
+	text-align:left;
+	padding-left: 10px;
+}
+
+.permission-table .tb-perm {
+	width: 41px;
+	margin: 0px;
+}
+
+.permission-table .tb-admin {
+	width: 41px;
+	margin: 0px;
+}
+
+.permission-table .tb-read {
+	width: 33px;
+	margin: 0px;
+}
+
+.permission-table .tb-write {
+	width: 34px;
+	margin: 0px;
+}
+
+.permission-table .tb-execute {
+	width: 51px;
+	margin: 0px;
+}
+
+.permission-table .tb-schedule {
+	margin: 0px;
+	width: 60px;
+}
+
+.permission-table .tb-action {
+	margin: 0px;
+	width: 70px;
+	min-width: 70px;
+	max-width: 70px;
+}
+
+.permission-table thead tr th.tb-username {
+	padding-left: 15px;
+	text-align:left;
+}
+
+.permission-table thead tr th {
+	text-align:center;
+}
+
+.permission-table tbody tr td.tb-name {
+	text-align:left;
+}
+
+.permission-table tbody tr td {
+	text-align:center;
+}
+
+span.sublabel {
+	font-size: 8pt;
+	margin-left: 12px;
+	color: #333;
+}
+
+#td-adduser {
+	text-align: left;
+	padding-left: 12px;
+}
+
+#pageSelection {
+}
+
+#pageSelection ul {
+	margin-top: 5px;
+}
+
+#pageSelection ul li:hover {
+	background-color: #D5F2FF;
+}
+
+#pageSelection ul li.first {
+	border-left: 1px solid #CCC; 
+}
+
+#pageSelection ul li {
+	float: left;
+	background-color: #FFF;
+	border-top: 1px solid #CCC;
+	border-bottom: 1px solid #CCC;
+	border-right: 1px solid #CCC;
+	cursor: pointer;
+	padding-top: 8px;
+	padding-bottom: 8px;
+	font-size: 11pt;
+	text-decoration: none;
+	color: #3398cc;
+}
+
+#pageSelection ul li.disabled {
+	cursor: default;
+	color: #CCC;
+}
+
+#pageSelection ul li a{
+	font-size: 11pt;
+	text-decoration: none;
+	color: inherit;
+	cursor: inherit;
+	padding: 8px 12px;
+}
+
+#pageSelection ul li .arrow{
+	top: 0px;
+	margin: 0px 6px;
+}
+
+#pageSelection ul li.selected{
+	background-color: #c7eeff;
+}
+
+#flow-status {
+	position: absolute;
+	top: 115px;
+	right: 55px;
+	width: 420px;
+}
+
+#flow-status table {
+	float: left;
+	border: none;
+	background: none;
+	width: 190px;
+	margin-left: 10px;
+}
+
+#flow-status table.status {
+	width: 200px;
+}
+
+#flow-status table.status td {
+	font-size: 11.5pt;
+}
+
+#flow-status td.first {
+	font-weight: bold;
+}
+
+#flow-status table tr {
+}
+
+#flow-status table td {
+	border: none;
+	padding: 1px;
+	font-size: 12px;
+}
+
+
+#flow-status table td.SKIPPED {
+	color:  #AAA;
+}
+
+#flow-status table td.SUCCEEDED {
+	color:  #4e911e;
+}
+
+#flow-status table td.RUNNING {
+	color:  #009FC9;
+}
+
+#flow-status table td.FAILED {
+	color: #CC0000;
+}
+
+#flow-status table td.PAUSED {
+	color: #C82123;
+}
+
+#flow-status table td.FAILED_FINISHING {
+	color:  #CC0000;
+}
+
+#flow-status table td.KILLED {
+	color:  #CC0000;
+}
+
+#flowStatus {
+	font-weight: bold;
+}
+
+.executionInfo table th.date {
+	width: 140px;
+}
+
+.executionInfo table th.execid {
+	width: 80px;
+}
+
+.executionInfo table th.project {
+	width: 200px;
+}
+
+.executionInfo table th.user {
+	width: 60px;
+}
+
+.executionInfo table th.elapse {
+	width: 90px;
+}
+
+.executionInfo table th.status {
+	width: 100px;
+}
+
+.executionInfo table th.logs {
+	width: 10px;
+}
+
+.executionInfo table th.timeline {
+	width: 280px;
+}
+
+.executionInfo table th.action {
+	width: 20px;
+}
+
+.executionInfo table td.timeline {
+	padding: 0px;
+	height: 100%;
+	vertical-align: bottom;
+	margin: 0px;
+}
+
+.executionInfo table td.execId {
+	font-weight: bold;
+}
+
+.executionInfo table td {
+	padding-left: 3px;
+	height: 20px;
+}
+
+.executionInfo table td a {
+	color: #000;
+	text-decoration: none;
+	margin-left: 10px;
+	margin-right: 10px;
+}
+
+.executionInfo table td a:hover {
+	color: #009FC9;
+}
+
+td .status {
+	-moz-border-radius: 2px;
+	border-radius: 2px;
+
+	padding: 2px 2px;
+	color: #FFF;
+	text-align: center;
+	margin-top: 2px;
+}
+
+td .status.SUCCEEDED {
+	background-color: #82B859;
+}
+
+td .status.FAILED {
+	background-color: #C82123;
+}
+
+td .status.PAUSED {
+	background-color: #C82123;
+}
+
+td .status.READY {
+	background-color: #CCC;
+}
+
+td .status.RUNNING {
+	background-color: #3398CC;	
+}
+
+td .status.FAILED_FINISHING {
+	background-color: #F19153;	
+}
+
+td .status.DISABLED {
+	background-color: #AAA;	
+}
+
+td .status.SKIPPED {
+	background-color: #AAA;	
+}
+
+td .status.KILLED {
+	background-color: #CC0000;
+}
+
+td .status.UNKNOWN {
+	background-color: #CCC;
+}
+
+
+.flow-header {
+	height: 48px;
+}
+
+.outerProgress {
+	width: 280px;
+	margin: 4px;
+	background-color: #e2e4e3;
+	border: 1px solid #FFF;
+}
+
+tr:hover .outerProgress {
+	background-color: #F8F8F8;
+}
+
+.progressBox {
+	height: 24px;
+	background-color: #CCC;
+}
+
+.progressBox.attempt:hover {
+	opacity: 1;
+}
+
+.progressBox.attempt {
+	opacity: 0.70;
+}
+
+.progressBox.SUCCEEDED {
+	background-color: #4e911e;
+	background: -moz-linear-gradient(top, #5bb41c 0, #598d1e 100%);
+    background: -o-linear-gradient(top, #5bb41c 0, #598d1e 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#5bb41c), color-stop(100%,#598d1e));
+    background: linear-gradient(top, #5bb41c 0, #598d1e 100%);
+}
+
+.progressBox.FAILED {
+	background-color: #9e3600;
+	background: -moz-linear-gradient(top, #d43c00 0, #9e3600 100%);
+    background: -o-linear-gradient(top, #d43c00 0, #9e3600 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#d43c00), color-stop(100%,#9e3600));
+    background: linear-gradient(top, #d43c00 0, #9e3600 100%);
+}
+
+.progressBox.RUNNING {
+	background-color: #009FC9;
+	background: -moz-linear-gradient(top, #009FC9 0, #007b9b 100%);
+    background: -o-linear-gradient(top, #009FC9 0, #007b9b 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#009FC9), color-stop(100%,#007b9b));
+    background: linear-gradient(top, #009FC9 0, #007b9b 100%);
+}
+
+.progressBox.QUEUED {
+	opacity: 0.5;
+	background-color: #009FC9;
+	background: -moz-linear-gradient(top, #009FC9 0, #007b9b 100%);
+    background: -o-linear-gradient(top, #009FC9 0, #007b9b 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#009FC9), color-stop(100%,#007b9b));
+    background: linear-gradient(top, #009FC9 0, #007b9b 100%);
+}
+
+h3.subhead {
+	margin: 15px 20px 8px 20px;
+	font-size: 14pt;
+	font-weight: bold;
+}
+
+ul.subMenu {
+	margin-left: 15px;
+}
+
+ul.disableMenu {
+	margin-left: 15px;
+}
+
+.warn {
+	margin-left: 30px;
+	height: 40px;
+}
+
+.warning-icon {
+	float: left;
+	background-image: url("./images/redwarning.png");
+	width: 48px;
+	height: 43px;
+}
+
+.warning-message {
+	float: left;
+	margin-left: 10px;
+	margin-top: 10px;
+}
+
+span .nowrap {
+	white-space: nowrap;
+}
+
+.sched-form {
+	margin: 20px 20px;
+}
+
+#timeGraph {
+	width: 100%;
+	height: 300px;
+	background-color: #fff;
+	margin-bottom: 5px;
+}
+
+#dayByDayPanel {
+	
+}
+
+#dayGraph {
+	background-color: #fff;
+}
+
+#historyTimeLine {
+	position: absolute;
+	top: 160px;
+	bottom: 5px;
+	left: 50px;
+	right: 50px;
+	padding: 10px;
+	background: #E0E0E0;
+}
+
+.comment {
+	font-size: 11pt;
+	margin: 0px 20px;
+}
+
+.comment-small {
+	font-size: 11pt;
+	margin: 0px 20px;
+}
+
+.admin {
+	margin: 20px;
+}
+
+.admin-panel {
+	border-top: 2px groove #FFF;
+	margin: 40px 5px;
+	padding-top: 10px;
+	padding-bottom: 10px;
+}
+
+.admin-panel label {
+	font-size: 10pt;
+}
+
+.admin-panel input[type="radio"] {
+	margin-left: 50px;
+}
+
+
+.admin-panel h3 {
+	font-size: 12pt;
+	font-weight: bold;
+	margin: 3px 30px;
+}
+
+.admin-setup-points {
+	font-size: 10pt;
+	margin: 8px 25px;
+	list-style-type: disc;
+}
+
+.upload {
+	margin: 10px 20px;
+}
+
+.upload fieldset {
+	float: left;
+}
+
+.upload a {
+	float: left;
+}
+
+.upload .installed {
+	float: left;
+	font-size: 9pt;
+	margin-left: 20px;
+}
+
+#upload-jar-btn {
+	float: left;
+}
+
+#dbconnection {
+	margin-left: 40px;
+}
+
+#dbconnection label {
+	font-size: 10pt;
+	width: 100px;
+}
+
+#dbconnection table {
+	margin-top: 5px;
+}
+
+#dbconnection table tr td{
+	padding: 0;
+	border-top: none;
+	border-right: none;
+}
+
+#dbconnection table tr td.left{
+	width: 100px;
+}
+
+#dbconnection table tr td.param{
+	width: 310px;
+}
+
+#dbconnection table tr td.desc{
+	text-align:left;
+	font-style: italic;
+}
+
+#dbconnection table tr td input{
+	width: 300px;
+}
+
+#save-connection-button {
+	float: left;
+	margin-top: 5px;
+}
+
+#save-results {
+	float: left;
+	font-size: 10pt;
+	padding-top: 10px;
+	padding-left: 20px;
+	padding-bottom: 10px;
+}
+
+#save-results .fail{
+	background-color: #FF0000;
+	color: #FFFFFF;
+}
+
+.block {
+	display: block;
+}
+
+.bold {
+	font-weight: bold;
+}
+
+/*Azkaban Hover Menu */
+#flow-tabs .row .tb-name {
+	
+}
+
+tr .job-hover-menu {
+	visibility:hidden;
+}
+
+.flowrow:hover .job-hover-menu {
+	visibility:visible;
+}
+
+.jobrow:hover .job-hover-menu {
+	visibility:visible;
+}
+
+.job-hover-menu {
+	float: right;
+}
+
+.job-hover-menu div {
+	margin-left: 2px;
+	float: left;
+}
+
+/*Azkaban Hover Menu */
+.jobfolder {
+	padding-top: 3px;
+	height: 22px;
+	float: left;
+}
+
+tr.row td.tb-name {
+	padding-top: 0px;
+	padding-bottom: 0px;
+}
+
+.expandedFlow td.tb-job-name {
+	padding-top: 0px;
+	padding-bottom: 0px;
+	height: 25px;
+}
+
+.expandedFlow td.tb-job-name:hover {
+	background-color: #E1E3E2;
+}
+
+.expandedFlow td.tb-job-name a{
+	padding-top: 3px;
+	padding-bottom: 0px;
+	float: left;
+}
+
+#schedule-btn {
+	float: left;
+	margin-left: 20px;
+}
+
+#execute-flow-panel {
+	left: 150px;
+	right: 150px;
+	top: 150px;
+	bottom: 200px;
+	min-width: 600px;
+	min-height: 400px;
+}
+
+#execute-flow-panel .svgDiv {
+	position: absolute;
+	padding: 1px;
+	left: 0px;
+	right: 0px;
+	top: 0px;
+	bottom: 0px;
+	border: none;
+}
+
+#execute-flow-panel .panel {
+	position: absolute;
+	width: 100%;
+	top: 50px;
+	bottom: 65px;
+	border: none;
+}
+
+h3.menuHeader {
+	font-size: 12pt;
+	margin: 0px 20px;
+	padding: 5px 3px 5px 15px;
+	color: #888;
+	border: none;
+	cursor: pointer;
+}
+
+h3.menuHeader:hover {
+	color: #000;
+	background-color: #CCC;
+}
+
+h3.menuHeader.selected {
+	color: #000;
+}
+
+div.menuContent {
+	font-size: 10pt;
+	padding-left: 20px;
+	padding-bottom: 10px;
+}
+
+.contextMenu {
+	position: absolute;
+	background-color: #FFF;
+	border: 1px solid #DDD;
+	-moz-box-shadow: 2px 2px 5px #888;
+	-webkit-box-shadow: 2px 2px 5px #888;
+	box-shadow: 2px 2px 5px #888;
+}
+.contextMenu li.menuitem {
+	background-color: #FFF;
+	padding: 3px 20px;
+	min-width: 50px;
+	font-size: 10pt;
+	cursor: pointer;
+}
+
+.contextMenu li.menuitem .expandSymbol {
+	background-image: url("../css/images/ui-icons_cccccc_256x240.png");
+	background-position: -32px -16px;
+	height: 16px;
+	width: 16px;
+	float:right;
+}
+
+.contextMenu li.break {
+	border-bottom: 1px solid #BBB;
+	margin: 2px 5px;
+}
+
+.contextMenu li.menuitem:hover {
+	background-color: #555;
+	color: #FFF;
+}
+
+.tableDiv .addRow a {
+	cursor: pointer;
+}
+
+.tableDiv span {
+	float: left;
+	margin-left: 5px;
+}
+
+
+.tableDiv span.addIcon {
+	display: block;
+	width: 16px;
+	height: 16px;
+	background-image: url("./images/addIcon.png");
+	cursor: pointer;
+}
+
+.tableDiv table .editable {
+
+}
+
+.tableDiv table .editable input {
+	border: 1px solid #009FC9;
+	height: 16px;
+}
+
+.tableDiv table .name {
+	width: 40%;
+}
+
+.tableDiv span.removeIcon {
+	display: block;
+	visibility:hidden;
+	disabled: true;
+	width: 16px;
+	height: 16px;
+	background-image: url("./images/removeIcon.png");
+	cursor: pointer;
+}
+
+.tableDiv .editable:hover span.removeIcon {
+	visibility:visible;
+}
+
+#schedule-panel {
+	position: relative;
+	left: -50%;
+}
+
+#schedule-panel p {
+	margin: 10px 30px;
+	font-size: 11pt;
+}
+
+#schedule-panel-top {
+	width: 450px;
+	margin-top: 250px;
+	position: absolute;
+	left: 50%;
+}
+
+#ui-div-datepicker td a.ui-state-default {
+	margin-left: 1px;
+}
+
+#svgDiv {
+	position: absolute;
+	padding: 1px;
+	left: 260px;
+	right: 0px;
+	top: 0px;
+	bottom: 0px;
+}
+
+#azkabanMessageDialogText {
+	margin: 10px 20px;
+}
+
+.sortableTable .sortable:hover .sortIcon {
+	visibility: visible;
+}
+
+.sortableTable .sortable .sortIcon {
+	float: right;
+	width: 16px;
+	height: 16px;
+	background-image: url("../css/images/ui-icons_cccccc_256x240.png");
+	background-position: -128px -16px;
+	visibility: hidden;
+}
+
+.sortableTable .sortable.desc .sortIcon {
+	background-position: -64px -16px;
+	visibility: visible;
+}
+
+.sortableTable .sortable.asc .sortIcon {
+	background-position: 0 -16px;
+	visibility: visible;
+}
+
+/* old styles */
+.azkaban-charts .hitarea {
+	background-image: url("../css/images/ui-icons_cccccc_256x240.png");
+	background-position: 0 -16px;
+	height: 16px;
+	margin-left: 15px;
+	width: 16px;
+	cursor: pointer;
+}
+
+#executionGraphOptions {
+	width: 270px;
+	height: 100%;
+}
+
+.azkaban-charts .expandable-hitarea { background-position: -32px -16px; }
+.azkaban-charts .expandable-hitarea.collapse { background-position: 0 -16px; }
+/* clean up */
diff --git a/src/web/css/graph/azkaban-graph.css b/src/web/css/graph/azkaban-graph.css
new file mode 100644
index 0000000..5c6f51e
--- /dev/null
+++ b/src/web/css/graph/azkaban-graph.css
@@ -0,0 +1,247 @@
+
+svg .edge {
+	stroke: #BBB;
+	stroke-width: 2;
+}
+
+svg .edge:hover {
+	stroke: #009FC9;
+	stroke-width: 4;
+}
+
+svg .node.disabled {
+	opacity: 0.3;
+}
+
+svg .node .backboard {
+	fill: #FFF;
+	opacity: 0.05;
+}
+
+svg .node:hover {
+	cursor: pointer;
+}
+
+svg .node:hover .backboard {
+	opacity: 0.7;
+}
+
+svg .selected .backboard {
+	opacity: 0.4;
+}
+
+svg .node circle {
+	fill: #888;
+	stroke: #777;
+	stroke-width: 2;
+}
+
+svg .node:hover circle {
+	stroke: #009FC9;
+}
+
+svg .node:hover text {
+	fill: #009FC9;
+}
+
+svg .selected text {
+	fill: #338AB0;
+}
+
+svg .selected circle {
+	stroke: #009FC9;
+	stroke-width: 4;
+}
+
+svg .READY circle {
+	fill: #CCC;
+}
+
+svg .RUNNING circle {
+	fill: #009FC9;
+}
+
+svg .QUEUED circle {
+	opacity: 0.5;
+	fill: #009FC9;
+}
+
+svg .FAILED circle {
+	fill: #CC0000;
+}
+
+svg .KILLED circle {
+	fill: #CC0000;
+}
+
+svg .SUCCEEDED circle {
+	fill: #00CC33;
+}
+
+svg .DISABLED circle {
+	opacity: 0.3;
+}
+
+svg .SKIPPED circle {
+	opacity: 0.3;
+}
+
+svg .selected circle {
+	stroke: #009FC9;
+	stroke-width: 4;
+}
+
+svg .selected .nodebox rect {
+	stroke: #009FC9;
+	stroke-width: 3;
+}
+
+svg .node rect {
+	fill: #F8F8F8;
+	stroke: #CCC;
+	stroke-width: 2;
+}
+
+svg .node .nodebox text {
+	fill: #FFF;
+}
+
+svg .READY .nodebox text {
+	fill: #000;
+}
+
+svg .node:hover rect {
+	stroke: #009FC9;
+}
+
+svg .READY rect {
+	fill: #EEE;
+}
+
+svg .RUNNING rect {
+	fill: #009FC9;
+}
+
+svg .QUEUED rect {
+	opacity: 0.5;
+	fill: #009FC9;
+}
+
+svg .FAILED rect {
+	fill: #CC0000;
+}
+
+svg .KILLED rect {
+	fill: #CC0000;
+}
+
+svg .SUCCEEDED rect {
+	fill: #30ad23;
+}
+
+svg .DISABLED rect {
+	opacity: 0.3;
+}
+
+svg .SKIPPED rect {
+	opacity: 0.3;
+}
+
+svg .nodebox text {
+	fill: #fff;
+}
+
+
+#Used for charts
+svg circle.READY {
+	stroke: #CCC;
+	stroke-width: 2px;
+	fill: #FFF;
+}
+
+svg circle.RUNNING {
+	stroke: #009FC9;
+	stroke-width: 2px;
+	fill: #FFF;
+}
+
+svg circle.FAILED {
+	stroke: #CC0000;
+	stroke-width: 2px;
+	fill: #FFF;
+}
+
+svg circle.KILLED {
+	stroke: #CC0000;
+	stroke-width: 2px;
+	fill: #FFF;
+}
+
+svg circle.SUCCEEDED {
+	stroke: #00CC33;
+	stroke-width: 2px;
+	fill: #FFF;
+}
+
+svg circle.DISABLED {
+	stroke: #CCC;
+	opacity: 0.3;
+	stroke-width: 2px;
+	fill: #FFF;
+}
+
+svg circle.SKIPPED {
+	stroke: #CCC;
+	opacity: 0.3;
+	stroke-width: 2px;
+	fill: #FFF;
+}
+
+.flowExtendedView {
+	position: absolute;
+	background-color: rgba(255, 255, 255, 0.95);
+	-moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5);
+	-webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5);
+	box-shadow:         1px 1px 5px rgba(0, 0, 0, 0.5);
+
+	min-width: 200px;
+	min-height: 150px;
+}
+
+.dataJobProperties {
+
+}
+
+.flowInfoTitle {
+	padding-top: 8px;
+	padding-left: 8px;
+	padding-bottom: 5px;
+	cursor: pointer;
+}
+
+.flowInfoTitle:hover {
+	background-color: #CCC;
+}
+
+.nodeId {
+	font-size: 16px;
+	font-weight: bold;
+	margin: 20px 20px;
+}
+
+.nodeType {
+	font-style: italic;
+}
+
+.dataContent {
+	margin: 5px;
+}
+
+.dataFlow {
+	width: 100%;
+}
+
+.svgTiny {
+	width: 100%;
+	height: 100%;
+}
diff --git a/src/web/js/graph/azkaban.layout.js b/src/web/js/graph/azkaban.layout.js
new file mode 100644
index 0000000..8ebe486
--- /dev/null
+++ b/src/web/js/graph/azkaban.layout.js
@@ -0,0 +1,308 @@
+var maxTextSize = 32;
+var reductionSize = 26;
+var degreeRatio = 1/8;
+var maxHeight = 200;
+var cornerGap = 10;
+
+function layoutGraph(nodes, edges, hmargin) {
+	var startLayer = [];
+	var numLayer = 0;
+	var nodeMap = {};
+	
+	var maxLayer = 0;
+	var layers = {};
+	
+	if (!hmargin) {
+		hmargin = 8;
+	}
+	
+	// Assign to layers
+	for (var i = 0; i < nodes.length; ++i) {
+		numLayer = Math.max(numLayer, nodes[i].level);
+
+		var width = nodes[i].width ? nodes[i].width : nodes[i].label.length * 11.5 + 4;
+		var height = nodes[i].height ? nodes[i].height : 1;
+		var node = { id: nodes[i].id, node: nodes[i], level: nodes[i].level, in:[], out:[], width: width + hmargin, x:0, height:height };
+		nodeMap[nodes[i].id] = node;
+
+		maxLayer = Math.max(node.level, maxLayer);
+		if(!layers[node.level]) {
+			layers[node.level] = [];
+		}
+		
+		layers[node.level].push(node);
+	}
+	
+	// Create dummy nodes
+	var edgeDummies = {};
+	
+	for (var i=0; i < edges.length; ++i ) {
+		var edge = edges[i];
+		var src = edges[i].from;
+		var dest = edges[i].target;
+		
+		var edgeId = src + ">>" + dest;
+		
+		var srcNode = nodeMap[src];
+		var destNode = nodeMap[dest];
+		
+		var lastNode = srcNode;
+
+		var guides = [];
+		
+		for (var j = srcNode.level + 1; j < destNode.level; ++j) {
+			var dummyNode = {level: j, in: [], x: lastNode.x, out: [], realSrc: srcNode, realDest: destNode, width: 10, height: 10};
+			layers[j].push(dummyNode);
+			dummyNode.in.push(lastNode);
+			lastNode.out.push(dummyNode);
+			lastNode = dummyNode;
+			
+			guides.push(dummyNode);
+		}
+		
+		destNode.in.push(lastNode);
+		lastNode.out.push(destNode);
+		
+		if (edgeDummies.length != 0) {
+			edgeDummies[edgeId] = guides;
+		}
+	}
+
+	spreadLayerSmart(layers[maxLayer]);
+	sort(layers[maxLayer]);
+	for (var i=maxLayer - 1; i >=0; --i) {
+		uncrossWithOut(layers[i]);
+		sort(layers[i]);
+		
+		spreadLayerSmart(layers[i]);
+	}
+
+	// The top level can get out of alignment, so we do this kick back
+	// manouver before we seriously get started sorting.
+	if (maxLayer > 1) {
+		uncrossWithIn(layers[1]);
+		sort(layers[1]);
+		spreadLayerSmart(layers[1]);
+
+		uncrossWithOut(layers[0]);
+		sort(layers[0]);
+		spreadLayerSmart(layers[0]);
+	}
+
+	// Uncross down
+	for (var i=1; i <= maxLayer; ++i) {
+		uncrossWithIn(layers[i]);
+		sort(layers[i]);
+		spreadLayerSmart(layers[i]);
+	}
+	
+
+	// Space it vertically
+	spaceVertically(layers, maxLayer);
+	
+	// Assign points to nodes
+	for (var i = 0; i < nodes.length; ++i) {
+		var node = nodes[i];
+		var layerNode = nodeMap[node.id];
+		node.x = layerNode.x;
+		node.y = layerNode.y;
+	}
+	
+	// Dummy node for more points.
+	for (var i = 0; i < edges.length; ++i) {
+		var edge = edges[i];
+		var src = edges[i].from;
+		var dest = edges[i].target;
+		
+		var edgeId = src + ">>" + dest;
+
+		if (edgeDummies[edgeId] && edgeDummies[edgeId].length > 0) {
+			var prevX = nodeMap[src].x;
+			var destX = nodeMap[dest].x; 
+			
+			var guides = [];
+			var dummies = edgeDummies[edgeId];
+			for (var j=0; j< dummies.length; ++j) {
+				var point = {x: dummies[j].x, y: dummies[j].y};
+				guides.push(point);
+				
+				var nextX = j == dummies.length - 1 ? destX: dummies[j + 1].x; 
+
+				if (point.x != prevX && point.x != nextX) {
+					// Add gap
+					if ((point.x > prevX) == (point.x > nextX)) {
+						guides.push({x: point.x, y:point.y + cornerGap});
+					}
+				}
+				prevX = point.x;
+			}
+						
+			edge.guides = guides;
+		}
+		else {
+			edge.guides = null;
+		}
+	}
+}
+
+function spreadLayerSmart(layer) {
+	var ranges = [];
+	ranges.push({start: 0, end:0, width: layer[0].width, x: layer[0].x, index: 0});
+	var largestRangeIndex = -1;
+	
+	var totalX = layer[0].x;
+	var totalWidth = layer[0].width;
+	var count = 1;
+	
+	for (var i = 1; i < layer.length; ++i ) {
+		var prevRange = ranges[ranges.length - 1];
+		var delta = layer[i].x - prevRange.x;
+				
+		if (delta == 0) {
+			prevRange.end = i;
+			prevRange.width += layer[i].width;
+			totalWidth+=layer[i].width;
+		}
+		else {
+			totalWidth+=Math.max(layer[i].width, delta);
+			ranges.push({start: i, end: i, width: layer[i].width, x: layer[i].x, index: ranges.length});
+		}
+		
+		totalX += layer[i].x;
+		count++;
+	}
+
+	// Space the ranges, but place the left and right most last
+	var startIndex = 0;
+	var endIndex = 0;
+	if (ranges.length == 1) {
+		startIndex = -1;
+		endIndex = 1;
+	}
+	else if ((ranges.length % 2) == 1) {
+		var index = Math.ceil(ranges.length/2);
+		startIndex = index - 1;
+		endIndex = index + 1;
+	}
+	else {
+		var e = ranges.length/2;
+		var s = e - 1;
+		
+		var crossPointS = ranges[s].x + ranges[s].width/2;
+		var crossPointE = ranges[e].x - ranges[e].width/2;
+		
+		if (crossPointS > crossPointE) {
+			var midPoint = (ranges[s].x + ranges[e].x)/2;
+			ranges[s].x = midPoint - ranges[s].width/2;
+			ranges[e].x = midPoint + ranges[e].width/2;
+		}
+		
+		startIndex = s - 1;
+		endIndex = e + 1;
+	}
+	
+	for (var i=startIndex; i >= 0; --i) {
+		var range = ranges[i];
+		var crossPointS = range.x + range.width/2;
+		var crossPointE = ranges[i + 1].x - ranges[i + 1].width/2;
+		
+		if (crossPointE < crossPointS) {
+			range.x -= crossPointS - crossPointE;
+		}
+	}
+	
+	for (var i=endIndex; i < ranges.length; ++i) {
+		var range = ranges[i];
+		var crossPointE = range.x - range.width/2;
+		var crossPointS = ranges[i - 1].x + ranges[i - 1].width/2;
+		
+		if (crossPointE < crossPointS) {
+			range.x += crossPointS - crossPointE;
+		}
+	}
+	
+	for (var i=0; i < ranges.length; ++i) {
+		var range = ranges[i];
+		if (range.start == range.end) {
+			layer[range.start].x = range.x;
+		}
+		else {
+			var start = range.x - range.width/2;
+			
+			for (var j=range.start;j <=range.end; ++j) {
+				layer[j].x = start + layer[j].width/2;
+				start += layer[j].width;
+			}
+		}
+	}
+}
+
+
+function spaceVertically(layers, maxLayer) {
+	var startY = 0;
+	var startLayer = layers[0];
+	var startMaxHeight = 1;
+	for (var i=0; i < startLayer.length; ++i) {
+		startLayer[i].y = startY;
+		startMaxHeight = Math.max(startMaxHeight, startLayer[i].height);
+	}
+	
+	var minHeight = 40;
+	for (var a=1; a <= maxLayer; ++a) {
+		var maxDelta = 0;
+		var layer = layers[a];
+		
+		var layerMaxHeight = 1;
+		for (var i=0; i < layer.length; ++i) {
+			layerMaxHeight = Math.max(layerMaxHeight, layer[i].height);
+
+			for (var j=0; j < layer[i].in.length; ++j) {
+				var upper = layer[i].in[j];
+				var delta = Math.abs(upper.x - layer[i].x);
+				
+				maxDelta = Math.max(maxDelta, delta);
+			}
+		}
+		
+		console.log("Max " + maxDelta);
+		var calcHeight = maxDelta*degreeRatio;
+		
+		var newMinHeight = minHeight + startMaxHeight/2 + layerMaxHeight / 2;
+		startMaxHeight = layerMaxHeight;
+
+		startY += Math.max(calcHeight, newMinHeight);
+		for (var i=0; i < layer.length; ++i) {
+			layer[i].y=startY;
+		}
+	}
+
+}
+
+function uncrossWithIn(layer) {
+	for (var i = 0; i < layer.length; ++i) {
+		var pos = findAverage(layer[i].in);
+		layer[i].x = pos;
+	}
+}
+
+function findAverage(nodes) {
+	var sum = 0;
+	for (var i = 0; i < nodes.length; ++i) {
+		sum += nodes[i].x;
+	}
+	
+	return sum/nodes.length;
+}
+
+function uncrossWithOut(layer) {
+	for (var i = 0; i < layer.length; ++i) {
+		var pos = findAverage(layer[i].out);
+		layer[i].x = pos;
+	}
+}
+
+function sort(layer) {
+	layer.sort(function(a, b) {
+		return a.x - b.x;
+	});
+}
diff --git a/src/web/js/graph/azkaban.svg.graph.helper.js b/src/web/js/graph/azkaban.svg.graph.helper.js
new file mode 100644
index 0000000..67ee1f7
--- /dev/null
+++ b/src/web/js/graph/azkaban.svg.graph.helper.js
@@ -0,0 +1,152 @@
+var extendedViewPanels = {};
+var extendedDataModels = {};
+var openJobDisplayCallback = function(nodeId, flowId, evt) {
+	console.log("Open up data");
+	
+	var nodeInfoPanelID = flowId + ":" + nodeId + "-info";
+	if ($("#" + nodeInfoPanelID).length) {
+		$("#flowInfoBase").before(cloneStuff);
+		extendedViewPanels[nodeInfoPanelID].showExtendedView(evt);
+		return;
+	}
+	
+	var cloneStuff = $("#flowInfoBase").clone();
+	$(cloneStuff).attr("id", nodeInfoPanelID);
+	
+	$("#flowInfoBase").before(cloneStuff);
+	var requestURL = contextURL + "/manager";
+	
+	$.get(
+      requestURL,
+      {"project": projectName, "ajax":"fetchflownodedata", "flow":flowId, "node": nodeId},
+      function(data) {
+  		var graphModel = new azkaban.GraphModel();
+  		graphModel.set({id: data.id, flow: data.flowData, type: data.type, props: data.props});
+
+  		var flowData = data.flowData;
+  		if (flowData) {
+  			createModelFromAjaxCall(flowData, graphModel);
+  		}
+  		
+  		var backboneView = new azkaban.FlowExtendedViewPanel({el:cloneStuff, model: graphModel});
+  		extendedViewPanels[nodeInfoPanelID] = backboneView;
+  		extendedDataModels[nodeInfoPanelID] = graphModel;
+  		backboneView.showExtendedView(evt);
+      },
+      "json"
+    );
+}
+
+var createModelFromAjaxCall = function(data, model) {
+	  var nodes = {};
+  	  for (var i=0; i < data.nodes.length; ++i) {
+  	  	var node = data.nodes[i];
+  	  	nodes[node.id] = node;
+  	  }
+  	  for (var i=0; i < data.edges.length; ++i) {
+  	  	var edge = data.edges[i];
+  	  	var fromNode = nodes[edge.from];
+  	  	var toNode = nodes[edge.target];
+  	  	
+  	  	if (!fromNode.outNodes) {
+  	  		fromNode.outNodes = {};
+  	  	}
+  	  	fromNode.outNodes[toNode.id] = toNode;
+  	  	
+  	  	if (!toNode.inNodes) {
+  	  		toNode.inNodes = {};
+  	  	}
+  	  	toNode.inNodes[fromNode.id] = fromNode;
+  	  }
+  
+      console.log("data fetched");
+      model.set({data: data});
+      model.set({nodes: nodes});
+      model.set({disabled: {}});
+}
+
+var nodeClickCallback = function(event, model, type) {
+	console.log("Node clicked callback");
+	var jobId = event.currentTarget.jobid;
+	var flowId = model.get("flowId");
+	var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + flowId + "&job=" + jobId;
+
+	if (event.currentTarget.jobtype == "flow") {
+		var flowRequestURL = contextURL + "/manager?project=" + projectName + "&flow=" + event.currentTarget.flowId;
+		menu = [
+				{title: "View Flow...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
+				{break: 1},
+				{title: "Open Flow...", callback: function() {window.location.href=flowRequestURL;}},
+				{title: "Open Flow in New Window...", callback: function() {window.open(flowRequestURL);}},
+				{break: 1},
+				{title: "Open Properties...", callback: function() {window.location.href=requestURL;}},
+				{title: "Open Properties in New Window...", callback: function() {window.open(requestURL);}},
+				{break: 1},
+				{title: "Center Flow", callback: function() {model.trigger("centerNode", jobId)}}
+		];
+	}
+	else {
+		menu = [
+				{title: "View Job...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
+				{break: 1},
+				{title: "Open Job...", callback: function() {window.location.href=requestURL;}},
+				{title: "Open Job in New Window...", callback: function() {window.open(requestURL);}},
+				{break: 1},
+				{title: "Center Job", callback: function() {model.trigger("centerNode", jobId)}}
+		];
+	}
+	contextMenuView.show(event, menu);
+}
+
+var jobClickCallback = function(event, model) {
+	console.log("Node clicked callback");
+	var jobId = event.currentTarget.jobid;
+	var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + flowId + "&job=" + jobId;
+
+	var menu;
+	if (event.currentTarget.jobtype == "flow") {
+		var flowRequestURL = contextURL + "/manager?project=" + projectName + "&flow=" + event.currentTarget.flowId;
+		menu = [
+				{title: "View Flow...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
+				{break: 1},
+				{title: "Open Flow...", callback: function() {window.location.href=flowRequestURL;}},
+				{title: "Open Flow in New Window...", callback: function() {window.open(flowRequestURL);}},
+				{break: 1},
+				{title: "Open Properties...", callback: function() {window.location.href=requestURL;}},
+				{title: "Open Properties in New Window...", callback: function() {window.open(requestURL);}},
+				{break: 1},
+				{title: "Center Flow", callback: function() {model.trigger("centerNode", jobId)}}
+		];
+	}
+	else {
+		menu = [
+				{title: "View Job...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
+				{break: 1},
+				{title: "Open Job...", callback: function() {window.location.href=requestURL;}},
+				{title: "Open Job in New Window...", callback: function() {window.open(requestURL);}},
+				{break: 1},
+				{title: "Center Job", callback: function() {graphModel.trigger("centerNode", jobId)}}
+		];
+	}
+	contextMenuView.show(event, menu);
+}
+
+var edgeClickCallback = function(event, model) {
+	console.log("Edge clicked callback");
+}
+
+var graphClickCallback = function(event, model) {
+	console.log("Graph clicked callback");
+	var jobId = event.currentTarget.jobid;
+	var flowId = model.get("flowId");
+	var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + flowId;
+
+	var menu = [	
+		{title: "Open Flow...", callback: function() {window.location.href=requestURL;}},
+		{title: "Open Flow in New Window...", callback: function() {window.open(requestURL);}},
+		{break: 1},
+		{title: "Center Graph", callback: function() {model.trigger("resetPanZoom");}}
+	];
+	
+	contextMenuView.show(event, menu);
+}
diff --git a/src/web/js/graph/azkaban.svg.graph.view.js b/src/web/js/graph/azkaban.svg.graph.view.js
new file mode 100644
index 0000000..3b82c10
--- /dev/null
+++ b/src/web/js/graph/azkaban.svg.graph.view.js
@@ -0,0 +1,549 @@
+function hasClass(el, name) 
+{
+	var classes = el.getAttribute("class");
+	if (classes == null) {
+		return false;
+	}
+   return new RegExp('(\\s|^)'+name+'(\\s|$)').test(classes);
+}
+
+function addClass(el, name)
+{
+   if (!hasClass(el, name)) { 
+   		var classes = el.getAttribute("class");
+   		classes += classes ? ' ' + name : '' +name;
+   		el.setAttribute("class", classes);
+   }
+}
+
+function removeClass(el, name)
+{
+   if (hasClass(el, name)) {
+      var classes = el.getAttribute("class");
+      el.setAttribute("class", classes.replace(new RegExp('(\\s|^)'+name+'(\\s|$)'),' ').replace(/^\s+|\s+$/g, ''));
+   }
+}
+
+
+azkaban.SvgGraphView = Backbone.View.extend({
+	events: {
+		"click g" : "clickGraph",
+		"contextmenu" : "handleRightClick",
+		"contextmenu g" : "handleRightClick",
+		"contextmenu polyline": "handleRightClick"
+	},
+	initialize: function(settings) {
+		this.model.bind('change:selected', this.changeSelected, this);
+		this.model.bind('centerNode', this.centerNode, this);
+		this.model.bind('change:graph', this.render, this);
+		this.model.bind('resetPanZoom', this.resetPanZoom, this);
+		this.model.bind('change:update', this.handleStatusUpdate, this);
+		this.model.bind('change:disabled', this.handleDisabledChange, this);
+		this.model.bind('change:updateAll', this.handleUpdateAllStatus, this);
+		
+		this.graphMargin = settings.graphMargin ? settings.graphMargin : 25;
+		this.svgns = "http://www.w3.org/2000/svg";
+		this.xlinksn = "http://www.w3.org/1999/xlink";
+		
+		var graphDiv = this.el[0];
+		var svg = $(this.el).find('svg')[0];
+		this.svgGraph = svg;
+		
+		var gNode = document.createElementNS(this.svgns, 'g');
+		svg.appendChild(gNode);
+		this.mainG = gNode;
+		if (settings.rightClick) {
+			this.rightClick = settings.rightClick;
+		}
+
+		$(svg).svgNavigate();
+		
+		if (settings.render) {
+			this.render();
+		}
+	},
+	initializeDefs: function(self) {
+		var def = document.createElementNS(svgns, 'defs');
+		def.setAttribute("id", "buttonDefs");
+
+		// ArrowHead
+		var arrowHeadMarker = document.createElementNS(svgns, 'marker');
+		arrowHeadMarker.setAttribute("id", "triangle");
+		arrowHeadMarker.setAttribute("viewBox", "0 0 10 10");
+		arrowHeadMarker.setAttribute("refX", "5");
+		arrowHeadMarker.setAttribute("refY", "5");
+		arrowHeadMarker.setAttribute("markerUnits", "strokeWidth");
+		arrowHeadMarker.setAttribute("markerWidth", "4");
+		arrowHeadMarker.setAttribute("markerHeight", "3");
+		arrowHeadMarker.setAttribute("orient", "auto");
+		var path = document.createElementNS(svgns, 'polyline');
+		arrowHeadMarker.appendChild(path);
+		path.setAttribute("points", "0,0 10,5 0,10 1,5");
+
+		def.appendChild(arrowHeadMarker);
+		
+		this.svgGraph.appendChild(def);
+	},
+	render: function(self) {
+		console.log("graph render");
+
+		// Clean everything
+		while (this.mainG.lastChild) {
+			this.mainG.removeChild(this.mainG.lastChild);
+		}
+
+		var data = this.model.get("data");
+		var nodes = data.nodes;
+		var edges = data.edges;
+		if (nodes.length == 0) {
+			console.log("No results");
+			return;
+		};
+	
+		nodes.sort();
+		edges.sort();
+		
+		var bounds = {};
+		this.nodes = {};
+		for (var i = 0; i < nodes.length; ++i) {
+			this.nodes[nodes[i].id] = nodes[i];
+			nodes[i].label = nodes[i].id;
+		}
+		
+		this.gNodes = {};
+		for (var i = 0; i < nodes.length; ++i) {
+			this.drawNode(this, nodes[i]);
+		}
+		
+		// layout
+		layoutGraph(nodes, edges, 10);
+		this.moveNodes(bounds);
+		
+		for (var i = 0; i < edges.length; ++i) {
+			var inNodes = this.nodes[edges[i].target].inNodes;
+			if (!inNodes) {
+				inNodes = {};
+				this.nodes[edges[i].target].inNodes = inNodes;
+			}
+			inNodes[edges[i].from] = this.nodes[edges[i].from];
+			
+			var outNodes = this.nodes[edges[i].from].outNodes;
+			if (!outNodes) {
+				outNodes = {};
+				this.nodes[edges[i].from].outNodes = outNodes;
+			}
+			outNodes[edges[i].target] = this.nodes[edges[i].target];
+
+			this.drawEdge(this, edges[i]);
+		}
+		
+		this.model.set({"flowId":data.flowId, "nodes": this.nodes, "edges": edges});
+		
+		var margin = this.graphMargin;
+		bounds.minX = bounds.minX ? bounds.minX - margin : -margin;
+		bounds.minY = bounds.minY ? bounds.minY - margin : -margin;
+		bounds.maxX = bounds.maxX ? bounds.maxX + margin : margin;
+		bounds.maxY = bounds.maxY ? bounds.maxY + margin : margin;
+		
+		this.assignInitialStatus(self);
+		
+		if (this.model.get("disabled")) {
+			this.handleDisabledChange(self);
+		}
+		else {
+			this.model.set({"disabled":[]})
+		}
+		this.graphBounds = bounds;
+		this.resetPanZoom(0);
+	},
+	handleDisabledChange: function(evt) {
+		var disabledMap = this.model.get("disabled");
+
+		for(var id in this.nodes) {
+			 var g = this.gNodes[id];
+			if (disabledMap[id]) {
+				this.nodes[id].disabled = true;
+				addClass(g, "disabled");
+			}
+		    else {
+		    	this.nodes[id].disabled = false;
+		    	removeClass(g, "disabled");
+			}
+		}
+	},
+	assignInitialStatus: function(evt) {
+		var data = this.model.get("data");
+		for (var i = 0; i < data.nodes.length; ++i) {
+			var updateNode = data.nodes[i];
+			var g = this.gNodes[updateNode.id];
+			if (updateNode.status) {
+				addClass(g, updateNode.status);
+			}
+			else {
+				addClass(g, "READY");
+			}
+		}
+	},
+	changeSelected: function(self) {
+		console.log("change selected");
+		var selected = this.model.get("selected");
+		var previous = this.model.previous("selected");
+		
+		if (previous) {
+			// Unset previous
+			var g = this.gNodes[previous];
+			removeClass(g, "selected");
+		}
+		
+		if (selected) {
+			var g = this.gNodes[selected];
+			var node = this.nodes[selected];
+			
+			addClass(g, "selected");
+			
+			console.log(this.model.get("autoPanZoom"));
+			if (this.model.get("autoPanZoom")) {
+				var offset = 150;
+				var widthHeight = offset*2;
+				var x = node.x - offset;
+				var y = node.y - offset;
+				
+				$(this.svgGraph).svgNavigate("transformToBox", {x: x, y: y, width: widthHeight, height: widthHeight});
+			}
+		}
+	},
+	handleStatusUpdate: function(evt) {
+		var updateData = this.model.get("update");
+		if (updateData.nodes) {
+			for (var i = 0; i < updateData.nodes.length; ++i) {
+				var updateNode = updateData.nodes[i];
+				
+				var g = this.gNodes[updateNode.id];
+				this.handleRemoveAllStatus(g);
+				
+				addClass(g, updateNode.status);
+			}
+		}
+	},
+	handleRemoveAllStatus: function(gNode) {
+		for (var j = 0; j < statusList.length; ++j) {
+			var status = statusList[j];
+			removeClass(gNode, status);
+		}
+	},
+	clickGraph: function(self) {
+		console.log("click");
+		if (self.currentTarget.jobid) {
+			this.model.set({"selected": self.currentTarget.jobid});
+		}
+	},
+	handleRightClick: function(self) {
+		if (this.rightClick) {
+			var callbacks = this.rightClick;
+			var currentTarget = self.currentTarget;
+			if (callbacks.node && currentTarget.jobid) {
+				callbacks.node(self, this.model);
+			}
+			else if (callbacks.edge && (currentTarget.nodeName == "polyline" || currentTarget.nodeName == "line")) {
+				callbacks.edge(self, this.model);
+			}
+			else if (callbacks.graph) {
+				callbacks.graph(self, this.model);
+			}
+			return false;
+		}
+	
+		return true;
+	},	
+	drawEdge: function(self, edge) {
+		var svg = self.svgGraph;
+		var svgns = self.svgns;
+		
+		var startNode = this.nodes[edge.from];
+		var endNode = this.nodes[edge.target];
+		
+		var startPointY = startNode.y + startNode.height/2 - 3;
+		var endPointY = endNode.y - endNode.height/2 + 3;
+		if (edge.guides) {
+			var pointString = "" + startNode.x + "," + startPointY + " ";
+
+			for (var i = 0; i < edge.guides.length; ++i ) {
+				edgeGuidePoint = edge.guides[i];
+				pointString += edgeGuidePoint.x + "," + edgeGuidePoint.y + " ";
+			}
+			
+			pointString += endNode.x + "," + endPointY;
+			var polyLine = document.createElementNS(svgns, "polyline");
+			polyLine.setAttribute("class", "edge");
+			polyLine.setAttribute("points", pointString);
+			polyLine.setAttribute("style", "fill:none;");
+			$(self.mainG).prepend(polyLine);
+		}
+		else { 
+			var line = document.createElementNS(svgns, 'line');
+			line.setAttribute("class", "edge");
+			line.setAttribute("x1", startNode.x);
+			line.setAttribute("y1", startPointY);
+			line.setAttribute("x2", endNode.x);
+			line.setAttribute("y2", endPointY);
+			
+			$(self.mainG).prepend(line);
+		}
+	},
+	drawNode: function(self, node) {
+		if (node.type == 'flow') {
+			this.drawFlowNode(self, node);
+		}
+		else {
+			this.drawBoxNode(self,node);
+			//this.drawCircleNode(self,node,bounds);
+		}
+	},
+	moveNodes: function(bounds) {
+		var nodes = this.nodes;
+		var gNodes = this.gNodes;
+		
+		for (var key in nodes) {
+			var node = nodes[key];
+			var gNode = gNodes[node.id];
+			var centerX = node.centerX;
+			var centerY = node.centerY;
+			
+			gNode.setAttribute("transform", "translate(" + node.x + "," + node.y + ")");
+			this.addBounds(bounds, {minX:node.x - centerX, minY: node.y - centerY, maxX: node.x + centerX, maxY: node.y + centerY});
+		}
+	},
+	drawFlowNode: function(self, node) {
+		var svg = self.svgGraph;
+		var svgns = self.svgns;
+
+		var height = 26;
+		var nodeG = document.createElementNS(svgns, "g");
+		nodeG.setAttribute("class", "jobnode");
+		nodeG.setAttribute("font-family", "helvetica");
+		nodeG.setAttribute("transform", "translate(" + node.x + "," + node.y + ")");
+		this.gNodes[node.id] = nodeG;
+		
+		var innerG = document.createElementNS(svgns, "g");
+		innerG.setAttribute("class", "nodebox");
+		
+		var rect = document.createElementNS(svgns, 'rect');
+		rect.setAttribute("rx", 3);
+		rect.setAttribute("ry", 5);
+		rect.setAttribute("style", "width:inherit;stroke-opacity:1");
+		//rect.setAttribute("class", "nodecontainer");
+		
+		var text = document.createElementNS(svgns, 'text');
+		var textLabel = document.createTextNode(node.label);
+		text.appendChild(textLabel);
+		text.setAttribute("y", 1);
+		text.setAttribute("height", 10);
+
+		var flowIdText = document.createElementNS(svgns, 'text');
+		var flowIdLabel = document.createTextNode(node.flowId);
+		flowIdText.appendChild(flowIdLabel);
+		flowIdText.setAttribute("y", 11);
+		flowIdText.setAttribute("font-size", 8);
+		
+		var iconHeight = 20;
+		var iconWidth = 21;
+		var iconMargin = 4;
+		var iconNode = document.createElementNS(svgns, 'image');
+		iconNode.setAttribute("width", iconHeight);
+		iconNode.setAttribute("height", iconWidth);
+		iconNode.setAttribute("x", 0);
+		iconNode.setAttribute("y", -10);
+		iconNode.setAttributeNS('http://www.w3.org/1999/xlink', "xlink:href", contextURL + "/images/graph-icon.png");
+		
+		innerG.appendChild(rect);
+		innerG.appendChild(text);
+		innerG.appendChild(flowIdText);
+		innerG.appendChild(iconNode);
+		innerG.jobid = node.id;
+		innerG.jobtype = "flow";
+		innerG.flowId = node.flowId;
+
+		nodeG.appendChild(innerG);
+		self.mainG.appendChild(nodeG);
+
+		var horizontalMargin = 8;
+		var verticalMargin = 2;
+		
+		// Need to get text width after attaching to SVG.
+		var subLabelTextLength = flowIdText.getComputedTextLength();
+		
+		var computeTextLength = text.getComputedTextLength();
+		var computeTextHeight = 22;
+		
+		var width = computeTextLength > subLabelTextLength ? computeTextLength : subLabelTextLength;
+		width += iconWidth + iconMargin;
+		var halfWidth = width/2;
+		var halfHeight = height/2;
+		
+		// Margin for surrounding box.
+		var boxWidth = width + horizontalMargin * 2;
+		var boxHeight = height + verticalMargin * 2;
+		
+		node.width = boxWidth;
+		node.height = boxHeight;
+		node.centerX = boxWidth/2;
+		node.centerY = boxHeight/2;
+		
+		var textXOffset = -halfWidth + iconWidth + iconMargin;
+		iconNode.setAttribute("x", -halfWidth);
+		text.setAttribute("x", textXOffset);
+		flowIdText.setAttribute("x",textXOffset);
+		rect.setAttribute("x", -node.centerX);
+		rect.setAttribute("y", -node.centerY);
+		rect.setAttribute("width", node.width);
+		rect.setAttribute("height", node.height);
+		
+		nodeG.setAttribute("class", "node");
+		nodeG.jobid=node.id;
+	},
+	drawBoxNode: function(self, node) {
+		var svg = self.svgGraph;
+		var svgns = self.svgns;
+
+		var height = 18;
+		var nodeG = document.createElementNS(svgns, "g");
+		nodeG.setAttribute("class", "jobnode");
+		nodeG.setAttribute("font-family", "helvetica");
+		nodeG.setAttribute("transform", "translate(" + node.x + "," + node.y + ")");
+		this.gNodes[node.id] = nodeG;
+		
+		var innerG = document.createElementNS(svgns, "g");
+		innerG.setAttribute("class", "nodebox");
+		
+		var rect = document.createElementNS(svgns, 'rect');
+		rect.setAttribute("rx", 3);
+		rect.setAttribute("ry", 5);
+		rect.setAttribute("style", "width:inherit;stroke-opacity:1");
+		//rect.setAttribute("class", "nodecontainer");
+		
+		var text = document.createElementNS(svgns, 'text');
+		var textLabel = document.createTextNode(node.label);
+		text.appendChild(textLabel);
+		text.setAttribute("y", 6);
+		text.setAttribute("height", 10); 
+
+		//this.addBounds(bounds, {minX:node.x - xOffset, minY: node.y - yOffset, maxX: node.x + xOffset, maxY: node.y + yOffset});
+
+		innerG.appendChild(rect);
+		innerG.appendChild(text);
+		innerG.jobid = node.id;
+
+		nodeG.appendChild(innerG);
+		self.mainG.appendChild(nodeG);
+
+		var horizontalMargin = 8;
+		var verticalMargin = 2;
+		
+		// Need to get text width after attaching to SVG.
+		var computeText = text.getComputedTextLength();
+		var computeTextHeight = 22;
+		var halfWidth = computeText/2;
+		var halfHeight = height/2;
+		
+		// Margin for surrounding box.
+		var boxWidth = computeText + horizontalMargin * 2;
+		var boxHeight = height + verticalMargin * 2;
+		
+		node.width = boxWidth;
+		node.height = boxHeight;
+		node.centerX = boxWidth/2;
+		node.centerY = boxHeight/2;
+		
+		text.setAttribute("x", -halfWidth);
+		rect.setAttribute("x", -node.centerX);
+		rect.setAttribute("y", -node.centerY);
+		rect.setAttribute("width", node.width);
+		rect.setAttribute("height", node.height);
+		
+		nodeG.setAttribute("class", "node");
+		nodeG.jobid=node.id;
+	},
+	drawCircleNode: function(self, node, bounds) {
+		var svg = self.svgGraph;
+		var svgns = self.svgns;
+
+		var xOffset = 10;
+		var yOffset = 10;
+		
+		var nodeG = document.createElementNS(svgns, "g");
+		nodeG.setAttribute("class", "jobnode");
+		nodeG.setAttribute("font-family", "helvetica");
+		nodeG.setAttribute("transform", "translate(" + node.x + "," + node.y + ")");
+		this.gNodes[node.id] = nodeG;
+		
+		var innerG = document.createElementNS(svgns, "g");
+		innerG.setAttribute("transform", "translate(-10,-10)");
+		
+		var circle = document.createElementNS(svgns, 'circle');
+		circle.setAttribute("cy", 10);
+		circle.setAttribute("cx", 10);
+		circle.setAttribute("r", 12);
+		circle.setAttribute("style", "width:inherit;stroke-opacity:1");
+		//circle.setAttribute("class", "border");
+		//circle.setAttribute("class", "nodecontainer");
+		
+		var text = document.createElementNS(svgns, 'text');
+		var textLabel = document.createTextNode(node.label);
+		text.appendChild(textLabel);
+		text.setAttribute("x", 0);
+		text.setAttribute("y", 0);
+				
+		this.addBounds(bounds, {minX:node.x - xOffset, minY: node.y - yOffset, maxX: node.x + xOffset, maxY: node.y + yOffset});
+		
+		var backRect = document.createElementNS(svgns, 'rect');
+		backRect.setAttribute("x", 0);
+		backRect.setAttribute("y", 2);
+		backRect.setAttribute("class", "backboard");
+		backRect.setAttribute("width", 10);
+		backRect.setAttribute("height", 15);
+		
+		innerG.appendChild(circle);
+		innerG.appendChild(backRect);
+		innerG.appendChild(text);
+		innerG.jobid = node.id;
+
+		nodeG.appendChild(innerG);
+		self.mainG.appendChild(nodeG);
+
+		// Need to get text width after attaching to SVG.
+		var computeText = text.getComputedTextLength();
+		var halfWidth = computeText/2;
+		text.setAttribute("x", -halfWidth + 10);
+		backRect.setAttribute("x", -halfWidth);
+		backRect.setAttribute("width", computeText + 20);
+
+		nodeG.setAttribute("class", "node");
+		nodeG.jobid=node.id;
+	},
+	addBounds: function(toBounds, addBounds) {
+		toBounds.minX = toBounds.minX ? Math.min(toBounds.minX, addBounds.minX) : addBounds.minX;
+		toBounds.minY = toBounds.minY ? Math.min(toBounds.minY, addBounds.minY) : addBounds.minY;
+		toBounds.maxX = toBounds.maxX ? Math.max(toBounds.maxX, addBounds.maxX) : addBounds.maxX;
+		toBounds.maxY = toBounds.maxY ? Math.max(toBounds.maxY, addBounds.maxY) : addBounds.maxY;
+	},
+	resetPanZoom : function(duration) {
+		var bounds = this.graphBounds;
+		var param = {x: bounds.minX, y: bounds.minY, width: (bounds.maxX - bounds.minX), height: (bounds.maxY - bounds.minY), duration: duration };
+
+		this.panZoom(param);
+	},
+	centerNode: function(jobId) {
+		var node = this.nodes[jobId];
+		
+		var offset = 150;
+		var widthHeight = offset*2;
+		var x = node.x - offset;
+		var y = node.y - offset;
+		
+		this.panZoom({x: x, y: y, width: widthHeight, height: widthHeight});
+	},
+	panZoom: function(params) {
+		params.maxScale = 2;
+		$(this.svgGraph).svgNavigate("transformToBox", params);
+	}
+});