azkaban-uncached
Changes
src/java/azkaban/sla/SLAManager.java 1(+1 -0)
src/web/css/azkaban.css 75(+73 -2)
src/web/css/azkaban2.css 2690(+2690 -0)
src/web/js/azkaban.context.menu.js 19(+19 -0)
src/web/js/azkaban.flow.execute.view.js 347(+347 -0)
src/web/js/azkaban.flow.graph.view.js 11(+11 -0)
src/web/js/azkaban.project.view.js 28(+1 -27)
src/web/js/azkaban.svg.graph.view.js 338(+338 -0)
src/web/js/svgNavigate.js 8(+7 -1)
Details
diff --git a/src/java/azkaban/execapp/FlowRunnerManager.java b/src/java/azkaban/execapp/FlowRunnerManager.java
index 26bddd0..11c6bc1 100644
--- a/src/java/azkaban/execapp/FlowRunnerManager.java
+++ b/src/java/azkaban/execapp/FlowRunnerManager.java
@@ -81,7 +81,7 @@ public class FlowRunnerManager implements EventListener {
private long lastSubmitterThreadCheckTime = -1;
private long lastCleanerThreadCheckTime = -1;
- private long executionDirRetention = 7*24*60*60*1000;
+ private long executionDirRetention = 1*24*60*60*1000;
private Object executionDirDeletionSync = new Object();
diff --git a/src/java/azkaban/executor/ExecutorManager.java b/src/java/azkaban/executor/ExecutorManager.java
index 975a58e..f83b49c 100644
--- a/src/java/azkaban/executor/ExecutorManager.java
+++ b/src/java/azkaban/executor/ExecutorManager.java
@@ -396,6 +396,10 @@ public class ExecutorManager {
return jsonResponse;
}
+ public void shutdown() {
+ executingManager.shutdown();
+ }
+
private class ExecutingManagerUpdaterThread extends Thread {
private boolean shutdown = false;
@@ -412,6 +416,10 @@ public class ExecutorManager {
private int numErrors = 6;
private long errorThreshold = 10000;
+ private void shutdown() {
+ shutdown = true;
+ }
+
@SuppressWarnings("unchecked")
public void run() {
while(!shutdown) {
src/java/azkaban/sla/SLAManager.java 1(+1 -0)
diff --git a/src/java/azkaban/sla/SLAManager.java b/src/java/azkaban/sla/SLAManager.java
index 1adffc6..124e8f4 100644
--- a/src/java/azkaban/sla/SLAManager.java
+++ b/src/java/azkaban/sla/SLAManager.java
@@ -153,6 +153,7 @@ public class SLAManager {
private static final int TIMEOUT_MS = 60000;
public SLARunner() {
+ this.setName("SLAManagerThread");
SLAs = new PriorityBlockingQueue<SLA>(1,new SLAComparator());
}
diff --git a/src/java/azkaban/webapp/AzkabanWebServer.java b/src/java/azkaban/webapp/AzkabanWebServer.java
index 97c7414..3e4a654 100644
--- a/src/java/azkaban/webapp/AzkabanWebServer.java
+++ b/src/java/azkaban/webapp/AzkabanWebServer.java
@@ -456,7 +456,6 @@ public class AzkabanWebServer implements AzkabanServer {
public void run() {
logger.info("Shutting down http server...");
try {
- app.getScheduleManager().shutdown();
app.close();
server.stop();
server.destroy();
@@ -465,7 +464,6 @@ public class AzkabanWebServer implements AzkabanServer {
logger.error("Error while shutting down http server.", e);
}
logger.info("kk thx bye.");
- System.exit(0);
}
});
logger.info("Server running on port " + sslPortNumber + ".");
@@ -703,6 +701,9 @@ public class AzkabanWebServer implements AzkabanServer {
} catch (Exception e) {
logger.error("Failed to cleanup MBeanServer", e);
}
+ scheduleManager.shutdown();
+ slaManager.shutdown();
+ executorManager.shutdown();
}
private void registerMbean(String name, Object mbean) {
diff --git a/src/java/azkaban/webapp/servlet/ExecutorServlet.java b/src/java/azkaban/webapp/servlet/ExecutorServlet.java
index b3eaba0..9c68784 100644
--- a/src/java/azkaban/webapp/servlet/ExecutorServlet.java
+++ b/src/java/azkaban/webapp/servlet/ExecutorServlet.java
@@ -54,7 +54,7 @@ public class ExecutorServlet extends LoginAbstractAzkabanServlet {
private ProjectManager projectManager;
private ExecutorManager executorManager;
private ScheduleManager scheduleManager;
- private ExecutorVMHelper vmHelper;
+ private ExecutorVelocityHelper velocityHelper;
@Override
public void init(ServletConfig config) throws ServletException {
@@ -63,7 +63,7 @@ public class ExecutorServlet extends LoginAbstractAzkabanServlet {
projectManager = server.getProjectManager();
executorManager = server.getExecutorManager();
scheduleManager = server.getScheduleManager();
- vmHelper = new ExecutorVMHelper();
+ velocityHelper = new ExecutorVelocityHelper();
}
@Override
@@ -127,7 +127,7 @@ public class ExecutorServlet extends LoginAbstractAzkabanServlet {
List<ExecutableFlow> finishedFlows = executorManager.getRecentlyFinishedFlows();
page.add("recentlyFinished", finishedFlows.isEmpty() ? null : finishedFlows);
- page.add("vmutils", vmHelper);
+ page.add("vmutils", velocityHelper);
page.render();
}
@@ -764,7 +764,7 @@ public class ExecutorServlet extends LoginAbstractAzkabanServlet {
}
}
- public class ExecutorVMHelper {
+ public class ExecutorVelocityHelper {
public String getProjectName(int id) {
Project project = projectManager.getProject(id);
if (project == null) {
diff --git a/src/java/azkaban/webapp/servlet/velocity/executionoptionspanel.vm b/src/java/azkaban/webapp/servlet/velocity/executionoptionspanel.vm
index a16ddd7..d882d33 100644
--- a/src/java/azkaban/webapp/servlet/velocity/executionoptionspanel.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/executionoptionspanel.vm
@@ -1,82 +1,82 @@
<div id="modalBackground" class="modalBackground2">
- <div id="executing-options" class="modal modalContainer2">
- <a href='#' title='Close' class='modal-close'>x</a>
- <h3>Executing Flow Options</h3>
- <div>
- <ul class="optionsPicker">
- <li id="generalOptions">General Options</li>
- <li id="flowOptions">Flow Options</li>
- </ul>
- </div>
- <div class="optionsPane">
- <div id="generalPanel" class="generalPanel panel">
- <div id="completeActions">
- <h4>Completion Actions</h4>
- <dl>
- <dt>Failure Action</dt>
- <dd>
- <select id="failureAction" name="failureAction">
- <option value="finishCurrent">Finish Current Running</option>
- <option value="cancelImmediately">Cancel All</option>
- <option value="finishPossible">Finish All Possible</option>
- </select>
- </dd>
- <dt>Failure Email</dt>
- <dd>
- <textarea id="failureEmails"></textarea>
- </dd>
- <dt>Notify on Failure</dt>
- <dd>
- <input id="notifyFailureFirst" class="checkbox" type="checkbox" name="notify" value="first" checked >First Failure</input>
- <input id="notifyFailureLast" class="checkbox" type="checkbox" name="notify" value="last">Flow Stop</input>
- </dd>
- <dt>Success Email</dt>
- <dd>
- <textarea id="successEmails"></textarea>
- </dd>
- <dt>Concurrent Execution</dt>
- <dd id="executingJob" class="disabled">
- <input id="ignore" class="radio" type="radio" name="concurrent" value="ignore" checked /><label class="radioLabel" for="ignore">Run Concurrently</label>
- <input id="pipeline" class="radio" type="radio" name="concurrent" value="pipeline" /><label class="radioLabel" for="pipeline">Pipeline</label>
- <input id="queue" class="radio" type="radio" name="concurrent" value="queue" /><label class="radioLabel" for="queue">Queue Job</label>
- </dd>
- </dl>
- </div>
- <div id="flowPropertyOverride">
- <h4>Flow Property Override</h4>
- <div class="tableDiv">
- <table>
- <thead>
- <tr>
- <th>Name</th>
- <th>Value</th>
- </tr>
- </thead>
- <tbody>
- <tr id="addRow"><td id="addRow-col" colspan="2"><span class="addIcon"></span><a href="#">Add Row</a></td></tr>
- </tbody>
- </table>
+ <div id="executing-options" class="modal modalContainer2">
+ <a href='#' title='Close' class='modal-close'>x</a>
+ <h3>Executing Flow Options</h3>
+ <div>
+ <ul class="optionsPicker">
+ <li id="generalOptions">General Options</li>
+ <li id="flowOptions">Flow Options</li>
+ </ul>
+ </div>
+ <div class="optionsPane">
+ <div id="generalPanel" class="generalPanel panel">
+ <div id="completeActions">
+ <h4>Completion Actions</h4>
+ <dl>
+ <dt>Failure Action</dt>
+ <dd>
+ <select id="failureAction" name="failureAction">
+ <option value="finishCurrent">Finish Current Running</option>
+ <option value="cancelImmediately">Cancel All</option>
+ <option value="finishPossible">Finish All Possible</option>
+ </select>
+ </dd>
+ <dt>Failure Email</dt>
+ <dd>
+ <textarea id="failureEmails"></textarea>
+ </dd>
+ <dt>Notify on Failure</dt>
+ <dd>
+ <input id="notifyFailureFirst" class="checkbox" type="checkbox" name="notify" value="first" checked >First Failure</input>
+ <input id="notifyFailureLast" class="checkbox" type="checkbox" name="notify" value="last">Flow Stop</input>
+ </dd>
+ <dt>Success Email</dt>
+ <dd>
+ <textarea id="successEmails"></textarea>
+ </dd>
+ <dt>Concurrent Execution</dt>
+ <dd id="executingJob" class="disabled">
+ <input id="ignore" class="radio" type="radio" name="concurrent" value="ignore" checked /><label class="radioLabel" for="ignore">Run Concurrently</label>
+ <input id="pipeline" class="radio" type="radio" name="concurrent" value="pipeline" /><label class="radioLabel" for="pipeline">Pipeline</label>
+ <input id="queue" class="radio" type="radio" name="concurrent" value="queue" /><label class="radioLabel" for="queue">Queue Job</label>
+ </dd>
+ </dl>
+ </div>
+ <div id="flowPropertyOverride">
+ <h4>Flow Property Override</h4>
+ <div class="tableDiv">
+ <table>
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr id="addRow"><td id="addRow-col" colspan="2"><span class="addIcon"></span><a href="#">Add Row</a></td></tr>
+ </tbody>
+ </table>
+ </div>
</div>
</div>
- </div>
- <div id="graphPanel" class="graphPanel panel">
- <div id="jobListCustom" class="jobList">
- <div class="filterList">
- <input class="filter" placeholder=" Job Filter" />
+ <div id="graphPanel" class="graphPanel panel">
+ <div id="jobListCustom" class="jobList">
+ <div class="filterList">
+ <input class="filter" placeholder=" Job Filter" />
+ </div>
+ <div class="list">
+ </div>
+ <div class="btn5 resetPanZoomBtn" >Reset Pan Zoom</div>
</div>
- <div class="list">
+ <div id="svgDivCustom" class="svgDiv" >
+ <svg class="svgGraph" xmlns="http://www.w3.org/2000/svg" version="1.1" shape-rendering="optimize-speed" text-rendering="optimize-speed" >
+ </svg>
</div>
- <div class="btn5 resetPanZoomBtn" >Reset Pan Zoom</div>
- </div>
- <div id="svgDivCustom" class="svgDiv" >
- <svg class="svgGraph" xmlns="http://www.w3.org/2000/svg" version="1.1" shape-rendering="optimize-speed" text-rendering="optimize-speed" >
- </svg>
- </div>
+ </div>
+ </div>
+ <div class="actions">
+ <a class="yes btn1" id="execute-btn" href="#">Execute Now</a>
+ <a class="no simplemodal-close btn3" id="cancel-btn" href="#">Cancel</a>
</div>
- </div>
- <div class="actions">
- <a class="yes btn1" id="execute-btn" href="#">Execute Now</a>
- <a class="no simplemodal-close btn3" id="cancel-btn" href="#">Cancel</a>
- </div>
</div>
</div>
\ No newline at end of file
diff --git a/src/java/azkaban/webapp/servlet/velocity/flowexecutionpanel.vm b/src/java/azkaban/webapp/servlet/velocity/flowexecutionpanel.vm
new file mode 100644
index 0000000..9319c46
--- /dev/null
+++ b/src/java/azkaban/webapp/servlet/velocity/flowexecutionpanel.vm
@@ -0,0 +1,53 @@
+<script type="text/javascript" src="${context}/js/azkaban.layout.js"></script>
+<script type="text/javascript" src="${context}/js/svgNavigate.js"></script>
+<script type="text/javascript" src="${context}/js/azkaban.svg.graph.view.js"></script>
+<script type="text/javascript" src="${context}/js/azkaban.flow.execute.view.js"></script>
+
+<div id="modalBackground" class="modalBackground2">
+<div id="execute-flow-panel" class="modal modalContainer2">
+ <h3 id="execute-flow-panel-title"></h3>
+ <a title="Close" class="modal-close">x</a>
+ <div id="execute-message" class="message">
+ </div>
+
+ <div class="panel">
+ <div id="executionGraphOptions">
+ <div id="graphOptions" class="sideMenu">
+ <h3>Jobs</h3>
+ <div>
+ <p>Jobs Panel</p>
+ </div>
+ <h3>Notification</h3>
+ <div>
+ <p>Jobs Panel</p>
+ </div>
+ <h3>Concurrent Runs</h3>
+ <div>
+ <p>Jobs Panel</p>
+ </div>
+ <h3>SLA</h3>
+ <div>
+ <p>Jobs Panel</p>
+ </div>
+ <h3>Flow Parameters</h3>
+ <div>
+ <p>Jobs Panel</p>
+ </div>
+ </div>
+ </div>
+ <div id="svgDivCustom" class="svgDiv" >
+ <svg class="svgGraph" xmlns="http://www.w3.org/2000/svg" version="1.1" shape-rendering="optimize-speed" text-rendering="optimize-speed" >
+ </svg>
+ </div>
+ </div>
+
+ <div class="actions">
+ <a class="btn2" id="advanced-btn">Advanced Settings</a>
+ <a class="yes btn1" id="execute-btn">Execute</a>
+ <a class="no simplemodal-close btn3">Cancel</a>
+ </div>
+</div>
+</div>
+<div id="contextMenu">
+
+</div>
diff --git a/src/java/azkaban/webapp/servlet/velocity/projectpage.vm b/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
index f592314..34e5954 100644
--- a/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
@@ -19,7 +19,7 @@
<head>
#parse( "azkaban/webapp/servlet/velocity/style.vm" )
<script type="text/javascript" src="${context}/js/jquery/jquery.js"></script>
- <script type="text/javascript" src="${context}/js/jqueryui/jquery-ui.custom.min.js"></script>
+ <script type="text/javascript" src="${context}/js/jqueryui/jquery-ui.custom.min.js"></script>
<script type="text/javascript" src="${context}/js/namespace.js"></script>
<script type="text/javascript" src="${context}/js/underscore-1.2.1-min.js"></script>
<script type="text/javascript" src="${context}/js/backbone-0.5.3-min.js"></script>
@@ -27,6 +27,8 @@
<script type="text/javascript" src="${context}/js/azkaban.ajax.utils.js"></script>
<script type="text/javascript" src="${context}/js/azkaban.nav.js"></script>
<script type="text/javascript" src="${context}/js/azkaban.project.view.js"></script>
+
+ <link rel="stylesheet" type="text/css" href="${context}/css/jquery-ui-1.9.2.custom.css" />
<script type="text/javascript">
var contextURL = "${context}";
var currentTime = ${currentTime};
@@ -167,16 +169,9 @@
<a class="yes btn6" id="delete-btn" href="#">Yes</a>
</div>
</div>
- <div id="flow-execute" class="modal">
- <h3>Execute Flow</h3>
- <div id="executeErrorMsg" class="box-error-message"></div>
- <div id="execute-message" class="message">
- </div>
- <div class="actions">
- <a class="yes btn1" id="execute-btn">Execute</a>
- <a class="no simplemodal-close btn3">Cancel</a>
- </div>
- </div>
+
+ #parse( "azkaban/webapp/servlet/velocity/flowexecutionpanel.vm" )
</body>
+
</html>
diff --git a/src/java/azkaban/webapp/session/SessionCache.java b/src/java/azkaban/webapp/session/SessionCache.java
index 8788226..e110be2 100644
--- a/src/java/azkaban/webapp/session/SessionCache.java
+++ b/src/java/azkaban/webapp/session/SessionCache.java
@@ -28,12 +28,12 @@ import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
*
* The following global azkaban properties can be used: max.num.sessions - used
* to determine the number of live sessions that azkaban will handle. Default is
- * 10000 session.time.to.live -Number of seconds before sessione expires.
- * Default set to 3 days.
+ * 10000 session.time.to.live -Number of seconds before session expires.
+ * Default set to 1 days.
*/
public class SessionCache {
private static final int MAX_NUM_SESSIONS = 10000;
- private static final int SESSION_TIME_TO_LIVE = 86400 * 3;
+ private static final int SESSION_TIME_TO_LIVE = 86400;
private CacheManager manager = CacheManager.create();
private Cache cache;
src/web/css/azkaban.css 75(+73 -2)
diff --git a/src/web/css/azkaban.css b/src/web/css/azkaban.css
index 9f38ce3..845017d 100644
--- a/src/web/css/azkaban.css
+++ b/src/web/css/azkaban.css
@@ -691,6 +691,7 @@ tr:hover td {
color: #666;
font-weight: bold;
text-decoration: none;
+ cursor: pointer;
position: absolute;
top: 10px;
right: 17px;
@@ -1350,6 +1351,7 @@ tr:hover td {
opacity: 0.3;
}
+/* executing options panel*/
#executing-options {
left: 100px;
right: 100px;
@@ -1359,7 +1361,6 @@ tr:hover td {
#executing-options .svgDiv {
position: absolute;
- background-color: #CCC;
padding: 1px;
left: 270px;
right: 0px;
@@ -1373,7 +1374,6 @@ tr:hover td {
top: 0px;
bottom: 0px;
padding: 5px;
- background-color: #F0F0F0;
}
#executing-options .list {
@@ -2671,6 +2671,72 @@ tr.row td.tb-name {
float: left;
}
+#advanced-btn {
+ float: left;
+ margin-left: 20px;
+}
+
+#execute-flow-panel {
+ left: 150px;
+ right: 150px;
+ top: 200px;
+ bottom: 200px;
+ min-width: 600px;
+ min-height: 400px;
+}
+
+#execute-flow-panel .svgDiv {
+ position: absolute;
+ padding: 1px;
+ left: 270px;
+ right: 0px;
+ top: 0px;
+ bottom: 0px;
+ border: none;
+}
+
+#execute-flow-panel .panel {
+ position: absolute;
+ width: 100%;
+ top: 50px;
+ bottom: 65px;
+ border: none;
+}
+
+.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("../../js/jqueryui/themes/custom-theme/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;
+}
+
/* old styles */
.azkaban-charts .hitarea {
background-image: url("../../js/jqueryui/themes/custom-theme/images/ui-icons_cccccc_256x240.png");
@@ -2681,6 +2747,11 @@ tr.row td.tb-name {
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 */
src/web/css/azkaban2.css 2690(+2690 -0)
diff --git a/src/web/css/azkaban2.css b/src/web/css/azkaban2.css
new file mode 100644
index 0000000..47cf2e0
--- /dev/null
+++ b/src/web/css/azkaban2.css
@@ -0,0 +1,2690 @@
+/* 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%;
+}
+
+.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;
+}
+
+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: 64.818182%;
+ border-bottom-width: 0;
+ border-bottom-style: none;
+}
+
+.all-jobs .tb-up-date {
+ width: 160px;
+}
+
+.all-jobs .tb-owner {
+ width: 10%;
+}
+
+.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);
+}
+
+.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;
+ 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;
+ border-width: 1px;
+ border-color: #CCC;
+ width: 300px;
+ margin-left: 10px;
+}
+
+#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;
+}
+
+#ui-datepicker-div {
+ display: none;
+}
+
+.filter_statuses {
+ float: right;
+ margin-right: 25px;
+}
+
+.joblist:hover a {
+ display: inline;
+}
+
+/* clean up */
+.state-icon {
+ background-image: url("../../js/jqueryui/themes/custom-theme/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("../../js/jqueryui/themes/custom-theme/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("../js/jqueryui/themes/custom-theme/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: 210px;
+ 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;
+}
+
+
+.svgDiv {
+ position: absolute;
+ top: 0px;
+ right: 0px;
+ left: 260px;
+ bottom: 0px;
+}
+
+.radioLabel.disabled {
+ opacity: 0.3;
+}
+
+#executing-options {
+ left: 100px;
+ right: 100px;
+ top: 50px;
+ bottom: 40px;
+}
+
+#executing-options .svgDiv {
+ position: absolute;
+ background-color: #CCC;
+ padding: 1px;
+ left: 270px;
+ right: 0px;
+ top: 0px;
+ bottom: 0px;
+}
+
+#executing-options .jobList {
+ position: absolute;
+ width: 255px;
+ top: 0px;
+ bottom: 0px;
+ padding: 5px;
+ background-color: #F0F0F0;
+}
+
+#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;
+}
+
+.resetPanZoomBtn {
+ position: absolute;
+ bottom: 90px;
+}
+
+#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;
+}
+
+#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.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 {
+ margin: 0px;
+}
+
+.permission-table .tb-perm {
+ width: 60px;
+ margin: 0px;
+}
+
+.permission-table .tb-admin {
+ width: 60px;
+ margin: 0px;
+}
+
+.permission-table .tb-read {
+ width: 60px;
+ margin: 0px;
+}
+
+.permission-table .tb-write {
+ width: 60px;
+ margin: 0px;
+}
+
+.permission-table .tb-execute {
+ width: 60px;
+ margin: 0px;
+}
+
+.permission-table .tb-schedule {
+ margin: 0px;
+ width: 60px;
+}
+
+.permission-table .tb-action {
+ margin: 0px;
+ width: 100px;
+}
+
+.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;
+}
+
+svg .edge {
+ stroke: #777;
+ 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 .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;
+}
+
+#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;
+}
+
+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: #FF6600;
+}
+
+#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;
+}
+
+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.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.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%);
+}
+
+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 {
+
+}
+
+.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;
+}
+
+.contextMenu {
+
+}
+
+/* old styles */
+.azkaban-charts .hitarea {
+ background-image: url("../../js/jqueryui/themes/custom-theme/images/ui-icons_cccccc_256x240.png");
+ background-position: 0 -16px;
+ height: 16px;
+ margin-left: 15px;
+ width: 16px;
+ cursor: pointer;
+}
+
+.azkaban-charts .expandable-hitarea { background-position: -32px -16px; }
+.azkaban-charts .expandable-hitarea.collapse { background-position: 0 -16px; }
+/* clean up */
src/web/js/azkaban.context.menu.js 19(+19 -0)
diff --git a/src/web/js/azkaban.context.menu.js b/src/web/js/azkaban.context.menu.js
new file mode 100644
index 0000000..cdb2c9c
--- /dev/null
+++ b/src/web/js/azkaban.context.menu.js
@@ -0,0 +1,19 @@
+$.namespace('azkaban');
+
+var flowExecuteDialogView;
+azkaban.FlowExecuteDialogView= Backbone.View.extend({
+ events : {
+ },
+ initialize : function(settings) {
+ },
+ render: function() {
+ },
+ showContextMenu: function(menuData) {
+ //$('#execute-flow-panel').show();
+ $(this.el).show();
+ },
+ hideContextMenu: function(menuData) {
+ //$('#execute-flow-panel').hide();
+ $(this.el).hide();
+ }
+});
\ No newline at end of file
src/web/js/azkaban.flow.execute.view.js 347(+347 -0)
diff --git a/src/web/js/azkaban.flow.execute.view.js b/src/web/js/azkaban.flow.execute.view.js
new file mode 100644
index 0000000..ff2931d
--- /dev/null
+++ b/src/web/js/azkaban.flow.execute.view.js
@@ -0,0 +1,347 @@
+$.namespace('azkaban');
+
+function recurseAllAncestors(nodes, disabledMap, id, disable) {
+ var node = nodes[id];
+
+ if (node.inNodes) {
+ for (var key in node.inNodes) {
+ disabledMap[key] = disable;
+ recurseAllAncestors(nodes, disabledMap, key, disable);
+ }
+ }
+}
+
+function recurseAllDescendents(nodes, disabledMap, id, disable) {
+ var node = nodes[id];
+
+ if (node.outNodes) {
+ for (var key in node.outNodes) {
+ disabledMap[key] = disable;
+ recurseAllDescendents(nodes, disabledMap, key, disable);
+ }
+ }
+}
+
+var flowExecuteDialogView;
+azkaban.FlowExecuteDialogView= Backbone.View.extend({
+ events : {
+ "click .simplemodal-close": "hideExecutionOptionPanel",
+ "click .modal-close" : "hideExecutionOptionPanel"
+ },
+ initialize : function(settings) {
+ },
+ render: function() {
+ },
+ show: function(data) {
+ var projectId = data.project;
+ var flowId = data.flow;
+ var jobId = data.job;
+
+ var loadedId = executableGraphModel.get("flowId");
+ if (loadedId != flowId) {
+ this.loadGraph(projectId, flowId);
+ }
+
+ if (jobId) {
+ this.showExecuteJob(projectId, flowId, jobId, data.withDep);
+ }
+ else {
+ this.showExecuteFlow(projectId, flowId);
+ }
+ },
+ showExecuteFlow: function(projectId, flowId) {
+ $("#execute-flow-panel-title").text("Execute Flow " + flowId);
+ this.showExecutionOptionPanel();
+ },
+ showExecuteJob: function(projectId, flowId, jobId, withDep) {
+ $("#execute-message").text("Execute the complete flow '" + flowId + "'.");
+ },
+ showExecutionOptionPanel: function() {
+ $('#modalBackground').show();
+ $('#execute-flow-panel').show();
+ },
+ hideExecutionOptionPanel: function() {
+ $('#modalBackground').hide();
+ $('#execute-flow-panel').hide();
+ },
+ loadGraph: function(projectId, flowId) {
+ console.log("Loading flow " + flowId);
+ var managerUrl = contextURL + "/manager";
+ var fetchData = {
+ "ajax" : "fetchflowgraph",
+ "project" : projectId,
+ "flow" : flowId
+ };
+
+ $.get(
+ managerUrl,
+ fetchData,
+ function(data) {
+ if (data.error) {
+ alert(data.error);
+ }
+ else {
+ var disabled = data.disabled ? data.disabled : {};
+
+ executableGraphModel.set({flowId: data.flowId, data:data, disabled: disabled});
+ executableGraphModel.trigger("change:graph");
+ }
+ },
+ "json"
+ );
+ }
+});
+
+var sideMenuDialogView;
+azkaban.SideMenuDialogView= Backbone.View.extend({
+ events : {
+ "click .menuHeader" : "expandItem"
+ },
+ initialize : function(settings) {
+ var children = $(this.el).children();
+ for (var i = 0; i < children.length; ++i ) {
+ var child = children[i];
+ if ((i % 2) == 0) {
+ $(child).addClass("menuHeader");
+ }
+ else {
+ $(child).addClass("menuContent");
+ $(child).hide();
+
+
+ }
+ }
+ },
+ expandItem : function(self) {
+
+ }
+});
+
+var contextMenuView;
+azkaban.ContextMenuView = Backbone.View.extend({
+ events : {
+ },
+ initialize : function(settings) {
+ var div = this.el;
+ $('body').click(function(e) {
+ $(".contextMenu").remove();
+ });
+ $('body').bind("contextmenu", function(e) {$(".contextMenu").remove()});
+ this.svgGraph = settings.graph;
+ },
+ show : function(evt, menu) {
+ console.log("Show context menu");
+ $(".contextMenu").remove();
+ var x = evt.pageX;
+ var y = evt.pageY;
+
+ var contextMenu = this.setupMenu(menu);
+ $(contextMenu).css({top: y, left: x});
+ $(this.el).after(contextMenu);
+ },
+ hide : function(evt) {
+ console.log("Hide context menu");
+ $(".contextMenu").remove();
+ },
+ handleClick: function(evt) {
+ console.log("handling click");
+ },
+ setupMenu: function(menu) {
+ var contextMenu = document.createElement("div");
+ $(contextMenu).addClass("contextMenu");
+ var ul = document.createElement("ul");
+ $(contextMenu).append(ul);
+
+ for (var i = 0; i < menu.length; ++i) {
+ var menuItem = document.createElement("li");
+ if (menu[i].break) {
+ $(menuItem).addClass("break");
+ }
+ else {
+ var title = menu[i].title;
+ var callback = menu[i].callback;
+ $(menuItem).addClass("menuitem");
+ $(menuItem).text(title);
+ menuItem.callback = callback;
+ $(menuItem).click(function() {
+ $(contextMenu).hide();
+ this.callback.call();});
+
+ if (menu[i].submenu) {
+ var expandSymbol = document.createElement("div");
+ $(expandSymbol).addClass("expandSymbol");
+ $(menuItem).append(expandSymbol);
+
+ var subMenu = this.setupMenu(menu[i].submenu);
+ $(subMenu).addClass("subMenu");
+ subMenu.parent = contextMenu;
+ menuItem.subMenu = subMenu;
+ $(subMenu).hide();
+ $(this.el).after(subMenu);
+
+ $(menuItem).mouseenter(function() {
+ $(".subMenu").hide();
+ var menuItem = this;
+ menuItem.selected = true;
+ setTimeout(function() {
+ if (menuItem.selected) {
+ var offset = $(menuItem).offset();
+ var left = offset.left;
+ var top = offset.top;
+ var width = $(menuItem).width();
+ var subMenu = menuItem.subMenu;
+
+ var newLeft = left + width - 5;
+ $(subMenu).css({left: newLeft, top: top});
+ $(subMenu).show();
+ }
+ }, 500);
+ });
+ $(menuItem).mouseleave(function() {this.selected = false;});
+ }
+ }
+
+ $(ul).append(menuItem);
+ }
+
+ return contextMenu;
+ }
+});
+
+var handleJobMenuClick = function(action, el, pos) {
+ var jobid = el[0].jobid;
+
+ var requestURL = contextURL + "/manager?project=" + projectId + "&flow=" + flowName + "&job=" + jobid;
+ if (action == "open") {
+ window.location.href = requestURL;
+ }
+ else if(action == "openwindow") {
+ window.open(requestURL);
+ }
+}
+
+var executableGraphModel;
+azkaban.GraphModel = Backbone.Model.extend({});
+
+var enableAll = function() {
+ disabled = {};
+ executableGraphModel.set({disabled: disabled});
+ executableGraphModel.trigger("change:disabled");
+}
+
+var disableAll = function() {
+ var disabled = executableGraphModel.get("disabled");
+
+ var nodes = executableGraphModel.get("nodes");
+ for (var key in nodes) {
+ disabled[key] = true;
+ }
+
+ executableGraphModel.set({disabled: disabled});
+ executableGraphModel.trigger("change:disabled");
+}
+
+var touchNode = function(jobid, disable) {
+ var disabled = executableGraphModel.get("disabled");
+
+ disabled[jobid] = disable;
+ executableGraphModel.set({disabled: disabled});
+ executableGraphModel.trigger("change:disabled");
+}
+
+var touchParents = function(jobid, disable) {
+ var disabled = executableGraphModel.get("disabled");
+ var nodes = executableGraphModel.get("nodes");
+ var inNodes = nodes[jobid].inNodes;
+
+ if (inNodes) {
+ for (var key in inNodes) {
+ disabled[key] = disable;
+ }
+ }
+
+ executableGraphModel.set({disabled: disabled});
+ executableGraphModel.trigger("change:disabled");
+}
+
+var touchChildren = function(jobid, disable) {
+ var disabledMap = executableGraphModel.get("disabled");
+ var nodes = executableGraphModel.get("nodes");
+ var outNodes = nodes[jobid].outNodes;
+
+ if (outNodes) {
+ for (var key in outNodes) {
+ disabledMap[key] = disable;
+ }
+ }
+
+ executableGraphModel.set({disabled: disabledMap});
+ executableGraphModel.trigger("change:disabled");
+}
+
+var touchAncestors = function(jobid, disable) {
+ var disabled = executableGraphModel.get("disabled");
+ var nodes = executableGraphModel.get("nodes");
+
+ recurseAllAncestors(nodes, disabled, jobid, disable);
+
+ executableGraphModel.set({disabled: disabled});
+ executableGraphModel.trigger("change:disabled");
+}
+
+var touchDescendents = function(jobid, disable) {
+ var disabled = executableGraphModel.get("disabled");
+ var nodes = executableGraphModel.get("nodes");
+
+ recurseAllDescendents(nodes, disabled, jobid, disable);
+
+ executableGraphModel.set({disabled: disabled});
+ executableGraphModel.trigger("change:disabled");
+}
+
+var nodeClickCallback = function(event) {
+ console.log("Node clicked callback");
+ var jobId = event.currentTarget.jobid;
+ var flowId = executableGraphModel.get("flowId");
+ var requestURL = contextURL + "/manager?project=" + projectId + "&flow=" + flowId + "&job=" + jobId;
+
+ var menu = [ {title: "Open in New Window...", callback: function() {window.location.href=requestURL;}},
+ {break: 1},
+ {title: "Enable", callback: function() {touchNode(jobId, false);}, submenu: [
+ {title: "Parents", callback: function(){touchParents(jobId, false);}},
+ {title: "Ancestors", callback: function(){touchAncestors(jobId, false);}},
+ {title: "Children", callback: function(){touchChildren(jobId, false);}},
+ {title: "Descendents", callback: function(){touchDescendents(jobId, false);}},
+ {title: "Enable All", callback: function(){enableAll();}}
+ ]
+ },
+ {title: "Disable", callback: function() {touchNode(jobId, true)}, submenu: [
+ {title: "Parents", callback: function(){touchParents(jobId, true);}},
+ {title: "Ancestors", callback: function(){touchAncestors(jobId, true);}},
+ {title: "Children", callback: function(){touchChildren(jobId, true);}},
+ {title: "Descendents", callback: function(){touchDescendents(jobId, true);}},
+ {title: "Disable All", callback: function(){disableAll();}}
+ ]
+ }
+ ];
+
+ contextMenuView.show(event, menu);
+}
+
+var edgeClickCallback = function(event) {
+ console.log("Edge clicked callback");
+}
+
+var graphClickCallback = function(event) {
+ console.log("Graph clicked callback");
+}
+
+$(function() {
+ flowExecuteDialogView = new azkaban.FlowExecuteDialogView({el:$('#execute-flow-panel')});
+ executableGraphModel = new azkaban.GraphModel();
+ svgGraphView = new azkaban.SvgGraphView({el:$('#svgDivCustom'), model: executableGraphModel, topGId:"topG", graphMargin: 10, rightClick: { "node": nodeClickCallback, "edge": edgeClickCallback, "graph": graphClickCallback }});
+
+ sideMenuDialogView = new azkaban.SideMenuDialogView({el:$('#graphOptions')});
+ var svgGraph = document.getElementById('svgGraph');
+ contextMenuView = new azkaban.ContextMenuView({el:$('#contextMenu'), graph: svgGraph});
+});
src/web/js/azkaban.flow.graph.view.js 11(+11 -0)
diff --git a/src/web/js/azkaban.flow.graph.view.js b/src/web/js/azkaban.flow.graph.view.js
index a26ca3a..7d7b9f9 100644
--- a/src/web/js/azkaban.flow.graph.view.js
+++ b/src/web/js/azkaban.flow.graph.view.js
@@ -21,6 +21,14 @@ azkaban.SvgGraphView = Backbone.View.extend({
this.contextMenu = settings.rightClick;
var gNode = document.createElementNS(this.svgns, 'g');
+ if (settings.topGId) {
+ gNode.setAttribute("id", settings.topGId);
+ }
+ if (settings.clickCallback) {
+ this.clickCallback = settings.clickCallback;
+ $(this.el).click(this.clickCallback);
+ }
+
svg.appendChild(gNode);
this.mainG = gNode;
@@ -159,6 +167,9 @@ azkaban.SvgGraphView = Backbone.View.extend({
if (self.currentTarget.jobid) {
this.model.set({"selected": self.currentTarget.jobid});
}
+ if (this.clickCallback) {
+ this.clickCallback(self);
+ }
},
drawEdge: function(self, edge) {
var svg = self.svgGraph;
src/web/js/azkaban.project.view.js 28(+1 -27)
diff --git a/src/web/js/azkaban.project.view.js b/src/web/js/azkaban.project.view.js
index 5dd066b..d880221 100644
--- a/src/web/js/azkaban.project.view.js
+++ b/src/web/js/azkaban.project.view.js
@@ -206,7 +206,6 @@ azkaban.FlowTableView= Backbone.View.extend({
var projectName = evt.currentTarget.projectName;
var flowId = evt.currentTarget.flowId;
var jobName = evt.currentTarget.jobName;
- console.log("job run options " + projectName + ":" + flowId + ":" + jobName);
var hover = evt.type == "mouseover";
@@ -319,7 +318,6 @@ azkaban.FlowTableView= Backbone.View.extend({
executeFlow: function(evt) {
console.log("Execute Flow");
var flowId = evt.currentTarget.flowId;
- $("#execute-message").text("Execute the complete flow '" + flowId + "'.");
var executingData = {
project: projectId,
@@ -330,31 +328,7 @@ azkaban.FlowTableView= Backbone.View.extend({
this.executeFlowDialog(executingData);
},
executeFlowDialog: function(executingData) {
- var flowId = executingData.flow;
- var executionIds = flowExecutingStatus(projectId, flowId);
-
- if (executionIds && executionIds.length > 0) {
- $("#executeErrorMsg").text("Flow '" + flowId + "' is already running. Click on Execute to proceed anyways.");
- }
- else {
- $("#executeErrorMsg").hide();
- }
-
- $('#flow-execute').modal({
- closeHTML: "<a href='#' title='Close' class='modal-close'>x</a>",
- position: ["20%",],
- containerId: 'confirm-container',
- containerCss: {
- 'height': '220px',
- 'width': '565px'
- },
- onShow: function (dialog) {
- var modal = this;
- $('#execute-btn').click(function() {
- executeFlow(executingData);
- });
- }
- });
+ flowExecuteDialogView.show(executingData);
},
render: function() {
}
src/web/js/azkaban.svg.graph.view.js 338(+338 -0)
diff --git a/src/web/js/azkaban.svg.graph.view.js b/src/web/js/azkaban.svg.graph.view.js
new file mode 100644
index 0000000..fbd877b
--- /dev/null
+++ b/src/web/js/azkaban.svg.graph.view.js
@@ -0,0 +1,338 @@
+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, ''));
+ }
+}
+
+
+var svgGraphView;
+azkaban.SvgGraphView = Backbone.View.extend({
+ events: {
+ "click g" : "clickGraph",
+ "contextmenu svg" : "rightClick",
+ "contextmenu g" : "rightClick",
+ "contextmenu polyline": "rightClick"
+ },
+ initialize: function(settings) {
+ this.model.bind('change:selected', this.changeSelected, 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 : 200;
+ 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();
+ },
+ initializeDefs: function(self) {
+ var def = document.createElementNS(svgns, 'defs');
+ def.setAttributeNS(null, "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();
+ // layout
+ layoutGraph(nodes, edges);
+
+ var bounds = {};
+ this.nodes = {};
+ for (var i = 0; i < nodes.length; ++i) {
+ this.nodes[nodes[i].id] = nodes[i];
+ }
+
+ 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.gNodes = {};
+ for (var i = 0; i < nodes.length; ++i) {
+ this.drawNode(this, nodes[i], bounds);
+ }
+
+ this.model.set({"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);
+ this.handleDisabledChange(self);
+ 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];
+ addClass(g, updateNode.status);
+ }
+ },
+ 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");
+
+ var offset = 200;
+ 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});
+ }
+ },
+ rightClick: function(self) {
+ if (this.rightClick) {
+ var callbacks = this.rightClick;
+ var currentTarget = self.currentTarget;
+ if (callbacks.node && currentTarget.jobid) {
+ callbacks.node(self);
+ }
+ else if (callbacks.edge && (currentTarget.nodeName == "polyline" || currentTarget.nodeName == "line")) {
+ callbacks.edge(self);
+ }
+ else if (callbacks.graph) {
+ callbacks.graph(self);
+ }
+ 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];
+
+ if (edge.guides) {
+ var pointString = "" + startNode.x + "," + startNode.y + " ";
+
+ for (var i = 0; i < edge.guides.length; ++i ) {
+ edgeGuidePoint = edge.guides[i];
+ pointString += edgeGuidePoint.x + "," + edgeGuidePoint.y + " ";
+ }
+
+ pointString += endNode.x + "," + endNode.y;
+ var polyLine = document.createElementNS(svgns, "polyline");
+ polyLine.setAttributeNS(null, "class", "edge");
+ polyLine.setAttributeNS(null, "points", pointString);
+ polyLine.setAttributeNS(null, "style", "fill:none;");
+ self.mainG.appendChild(polyLine);
+ }
+ else {
+ var line = document.createElementNS(svgns, 'line');
+ line.setAttributeNS(null, "class", "edge");
+ line.setAttributeNS(null, "x1", startNode.x);
+ line.setAttributeNS(null, "y1", startNode.y);
+ line.setAttributeNS(null, "x2", endNode.x);
+ line.setAttributeNS(null, "y2", endNode.y);
+
+ self.mainG.appendChild(line);
+ }
+ },
+ drawNode: 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.setAttributeNS(null, "class", "jobnode");
+ nodeG.setAttributeNS(null, "font-family", "helvetica");
+ nodeG.setAttributeNS(null, "transform", "translate(" + node.x + "," + node.y + ")");
+ this.gNodes[node.id] = nodeG;
+
+ var innerG = document.createElementNS(svgns, "g");
+ innerG.setAttributeNS(null, "transform", "translate(-10,-10)");
+
+ var circle = document.createElementNS(svgns, 'circle');
+ circle.setAttributeNS(null, "cy", 10);
+ circle.setAttributeNS(null, "cx", 10);
+ circle.setAttributeNS(null, "r", 12);
+ circle.setAttributeNS(null, "style", "width:inherit;stroke-opacity:1");
+
+
+ var text = document.createElementNS(svgns, 'text');
+ var textLabel = document.createTextNode(node.label);
+ text.appendChild(textLabel);
+ text.setAttributeNS(null, "x", 4);
+ text.setAttributeNS(null, "y", 15);
+ text.setAttributeNS(null, "height", 10);
+
+ 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.setAttributeNS(null, "x", 0);
+ backRect.setAttributeNS(null, "y", 2);
+ backRect.setAttributeNS(null, "class", "backboard");
+ backRect.setAttributeNS(null, "width", 10);
+ backRect.setAttributeNS(null, "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.setAttributeNS(null, "x", -halfWidth + 10);
+ backRect.setAttributeNS(null, "x", -halfWidth);
+ backRect.setAttributeNS(null, "width", computeText + 20);
+
+ nodeG.setAttributeNS(null, "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.svgGraph).svgNavigate("transformToBox", param);
+ }
+});
\ No newline at end of file
src/web/js/svgNavigate.js 8(+7 -1)
diff --git a/src/web/js/svgNavigate.js b/src/web/js/svgNavigate.js
index 076f700..68121f9 100644
--- a/src/web/js/svgNavigate.js
+++ b/src/web/js/svgNavigate.js
@@ -1,6 +1,9 @@
(function($) {
var mouseUp = function(evt) {
+ if (evt.button > 1) {
+ return;
+ }
var target = evt.target;
target.mx = evt.clientX;
target.my = evt.clientY;
@@ -8,6 +11,9 @@
}
var mouseDown = function(evt) {
+ if (evt.button > 1) {
+ return;
+ }
//alert("mouseDown");
var target = evt.target;
target.mx = evt.clientX;
@@ -358,4 +364,4 @@
$.error('Method ' + method + ' does not exist on svgNavigate');
}
};
-})(jQuery);
\ No newline at end of file
+})(jQuery);