Created
November 1, 2017 13:05
-
-
Save ilivessevili/84ab12a642bea07b397a24608838240c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% extends "/base.html" %} | |
{% block html_attr %} ng-app="App"{% endblock %} | |
{% block title_text %}Rally Task Report{% endblock %} | |
{% block libs %} | |
{% if include_libs %} | |
<style> | |
{{ include_raw_file("/libs/nv.d3.1.1.15-beta.min.css") }} | |
</style> | |
<script type="text/javascript"> | |
{{ include_raw_file("/libs/angular.1.3.3.min.js") }} | |
{{ include_raw_file("/libs/d3.3.4.13.min.js") }} | |
{{ include_raw_file("/libs/nv.d3.1.1.15-beta.min.js") }} | |
</script> | |
{% else %} | |
<link rel="stylesheet" href="https://http://cdn.bootcss.com/nvd3/1.1.15-beta/nv.d3.css"> | |
<script type="text/javascript" src="http://cdn.bootcss.com/angular.js/1.3.3/angular.min.js"></script> | |
<script type="text/javascript" src="http://cdn.bootcss.com/d3/3.4.13/d3.min.js"></script> | |
<script type="text/javascript" src="http://cdn.bootcss.com/nvd3/1.1.15-beta/nv.d3.min.js"></script> | |
{% endif %} | |
{% endblock %} | |
{% block js_before %} | |
"use strict"; | |
{{ include_raw_file("/task/directive_widget.js") }} | |
var controllerFunction = function($scope, $location) { | |
$scope.source = {{ source }}; | |
$scope.scenarios = {{ data }}; | |
{% raw %} | |
$scope.location = { | |
/* #/path/hash/sub/div */ | |
normalize: function(str) { | |
/* Remove unwanted characters from string */ | |
if (typeof str !== "string") { return "" } | |
return str.replace(/[^\w\-\.]/g, "") | |
}, | |
uri: function(obj) { | |
/* Getter/Setter */ | |
if (! obj) { | |
var uri = {path: "", hash: "", sub: "", div: ""}; | |
var arr = ["div", "sub", "hash", "path"]; | |
angular.forEach($location.url().split("/"), function(value){ | |
var v = $scope.location.normalize(value); | |
if (v) { var k = arr.pop(); if (k) { this[k] = v }} | |
}, uri); | |
return uri | |
} | |
var arr = [obj.path, obj.hash, obj.sub, obj.div], res = []; | |
for (var i in arr) { if (! arr[i]) { break }; res.push(arr[i]) } | |
return $location.url("/" + res.join("/")) | |
}, | |
path: function(path, hash) { | |
/* Getter/Setter */ | |
if (path === "") { return this.uri({}) } | |
path = this.normalize(path); | |
var uri = this.uri(); | |
if (! path) { return uri.path } | |
uri.path = path; | |
var _hash = this.normalize(hash); | |
if (_hash || hash === "") { uri.hash = _hash } | |
return this.uri(uri) | |
}, | |
hash: function(hash) { | |
/* Getter/Setter */ | |
if (hash) { this.uri({path:this.uri().path, hash:hash}) } | |
return this.uri().hash | |
} | |
} | |
/* Dispatch */ | |
$scope.route = function(uri) { | |
if (! $scope.scenarios_map) { return } | |
// Expand menu if there is only one menu group | |
if ($scope.nav.length === 1) { | |
$scope.nav_idx = $scope.nav[0].idx; | |
} | |
if (uri.path in $scope.scenarios_map) { | |
$scope.view = {is_scenario:true}; | |
$scope.scenario = $scope.scenarios_map[uri.path]; | |
$scope.nav_idx = $scope.nav_map[uri.path]; | |
if ($scope.scenario.iterations.histogram.views.length) { | |
$scope.mainHistogram = $scope.scenario.iterations.histogram.views[0] | |
} | |
if ($scope.scenario.atomic.histogram.views.length) { | |
$scope.atomicHistogram = $scope.scenario.atomic.histogram.views[0] | |
} | |
$scope.outputIteration = 0; | |
$scope.showTab(uri); | |
} else { | |
$scope.scenario = null; | |
if (uri.path === "source") { | |
$scope.view = {is_source:true} | |
} else { | |
$scope.view = {is_main:true} | |
} | |
} | |
} | |
$scope.$on("$locationChangeSuccess", function (event, newUrl, oldUrl) { | |
$scope.route($scope.location.uri()) | |
}); | |
$scope.showNav = function(nav_idx) { $scope.nav_idx = nav_idx } | |
/* Tabs */ | |
$scope.tabs = [ | |
{ | |
id: "overview", | |
name: "Overview", | |
visible: function(){ return !! $scope.scenario.iterations.pie.length } | |
},{ | |
id: "details", | |
name: "Details", | |
visible: function(){ return !! $scope.scenario.atomic.pie.length } | |
},{ | |
id: "output", | |
name: "Scenario Data", | |
visible: function(){ return $scope.scenario.has_output } | |
},{ | |
id: "hooks", | |
name: "Hooks", | |
visible: function(){ return $scope.scenario.hooks.length } | |
},{ | |
id: "failures", | |
name: "Failures", | |
visible: function(){ return !! $scope.scenario.errors.length } | |
},{ | |
id: "task", | |
name: "Input task", | |
visible: function(){ return !! $scope.scenario.config } | |
} | |
]; | |
$scope.tabs_map = {}; | |
angular.forEach($scope.tabs, | |
function(tab){ this[tab.id] = tab }, $scope.tabs_map); | |
$scope.showTab = function(uri) { | |
$scope.tab = uri.hash in $scope.tabs_map ? uri.hash : "overview"; | |
if (uri.hash === "output") { | |
if (typeof $scope.scenario.output === "undefined") { | |
var has_additive = !! $scope.scenario.additive_output.length; | |
var has_complete = !! ($scope.scenario.complete_output.length | |
&& $scope.scenario.complete_output[0].length); | |
$scope.scenario.output = { | |
has_additive: has_additive, | |
has_complete: has_complete, | |
length: has_additive + has_complete, | |
active: has_additive ? "additive" : (has_complete ? "complete" : "") | |
} | |
} | |
if (uri.sub && $scope.scenario.output["has_" + uri.sub]) { | |
$scope.scenario.output.active = uri.sub | |
} | |
} | |
else if (uri.hash === "hooks") { | |
if ($scope.scenario.hooks.length) { | |
var hook_idx = parseInt(uri.sub); | |
if (isNaN(hook_idx) || ($scope.scenario.hooks.length - hook_idx) <= 0) { | |
hook_idx = 0 | |
} | |
if ($scope.scenario.hook_idx === hook_idx) { | |
return | |
} | |
$scope.scenario.hooks.cur = $scope.scenario.hooks[hook_idx]; | |
$scope.scenario.hook_idx = hook_idx; | |
if (typeof $scope.scenario.hooks.cur.active === "undefined") { | |
if ($scope.scenario.hooks.cur.additive.length) { | |
$scope.scenario.hooks.cur.active = "additive" | |
} | |
if ($scope.scenario.hooks.cur.complete.length) { | |
if (typeof $scope.scenario.hooks.cur.active === "undefined") { | |
$scope.scenario.hooks.cur.active = "complete" | |
} | |
$scope.set_hook_run() | |
} | |
} | |
} | |
} | |
} | |
for (var i in $scope.tabs) { | |
if ($scope.tabs[i].id === $scope.location.hash()) { | |
$scope.tab = $scope.tabs[i].id | |
} | |
$scope.tabs[i].isVisible = function() { | |
if ($scope.scenario) { | |
if (this.visible()) { return true } | |
/* If tab should be hidden but is selected - show another one */ | |
if (this.id === $scope.location.hash()) { | |
for (var i in $scope.tabs) { | |
var tab = $scope.tabs[i]; | |
if (tab.id != this.id && tab.visible()) { | |
$scope.tab = tab.id; | |
return false | |
} | |
} | |
} | |
} | |
return false | |
} | |
} | |
$scope.set_hook_run = function(idx) { | |
if (typeof idx !== "undefined") { | |
$scope.scenario.hooks.cur.run_idx = idx | |
} | |
else if (typeof $scope.scenario.hooks.cur.run_idx === "undefined") { | |
$scope.scenario.hooks.cur.run_idx = 0 | |
} | |
idx = $scope.scenario.hooks.cur.run_idx; | |
if (($scope.scenario.hooks.cur.complete.length - idx) > 0) { | |
$scope.scenario.hooks.cur.run = $scope.scenario.hooks.cur.complete[idx] | |
} | |
} | |
$scope.complete_hooks_as_dropdown = function() { | |
return $scope.scenario.hooks.cur.complete.length > 10 | |
} | |
/* Other helpers */ | |
$scope.showError = function(message) { | |
return (function (e) { | |
e.style.display = "block"; | |
e.textContent = message | |
})(document.getElementById("page-error")) | |
} | |
$scope.compact_atomics = function() { | |
return ($scope.scenario && $scope.scenario.atomic.iter.length < 9) | |
} | |
/* Initialization */ | |
angular.element(document).ready(function(){ | |
if (! $scope.scenarios.length) { | |
return $scope.showError("No data...") | |
} | |
/* Compose data mapping */ | |
$scope.nav = []; | |
$scope.nav_map = {}; | |
$scope.scenarios_map = {}; | |
var met = [], itr = 0, cls_idx = 0; | |
var prev_cls, prev_met; | |
for (var idx in $scope.scenarios) { | |
var sc = $scope.scenarios[idx]; | |
if (! prev_cls) { | |
prev_cls = sc.cls | |
} | |
else if (prev_cls !== sc.cls) { | |
$scope.nav.push({cls:prev_cls, met:met, idx:cls_idx}); | |
prev_cls = sc.cls; | |
met = []; | |
itr = 1; | |
cls_idx += 1 | |
} | |
if (prev_met !== sc.met) { itr = 1 }; | |
sc.ref = $scope.location.normalize(sc.cls+"."+sc.met+(itr > 1 ? "-"+itr : "")); | |
$scope.scenarios_map[sc.ref] = sc; | |
$scope.nav_map[sc.ref] = cls_idx; | |
met.push({name:sc.name, itr:itr, idx:idx, ref:sc.ref}); | |
prev_met = sc.met; | |
itr += 1; | |
} | |
if (met.length) { | |
$scope.nav.push({cls:prev_cls, met:met, idx:cls_idx}) | |
} | |
/* Start */ | |
var uri = $scope.location.uri(); | |
uri.path = $scope.location.path(); | |
$scope.route(uri); | |
$scope.$digest() | |
}) | |
}; | |
if (typeof angular === "object") { | |
angular.module("App", []) | |
.controller("Controller", ["$scope", "$location", controllerFunction]) | |
.directive("widget", widgetDirective) | |
} | |
{% endraw %} | |
{% endblock %} | |
{% block css %} | |
.aside { margin:0 20px 0 0; display:block; width:255px; float:left } | |
.aside > div { margin-bottom: 15px } | |
.aside > div div:first-child { border-top-left-radius:4px; border-top-right-radius:4px } | |
.aside > div div:last-child { border-bottom-left-radius:4px; border-bottom-right-radius:4px } | |
.navcls { color:#678; background:#eee; border:1px solid #ddd; margin-bottom:-1px; display:block; padding:8px 9px; font-weight:bold; text-align:left; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; cursor:pointer } | |
.navcls.expanded { color:#469 } | |
.navcls.active { background:#428bca; background-image:linear-gradient(to bottom, #428bca 0px, #3278b3 100%); border-color:#3278b3; color:#fff } | |
.navmet { color:#555; background:#fff; border:1px solid #ddd; font-size:12px; display:block; margin-bottom:-1px; padding:8px 10px; text-align:left; text-overflow:ellipsis; white-space:nowrap; overflow:hidden; cursor:pointer } | |
.navmet:hover { background:#f8f8f8 } | |
.navmet.active, .navmet.active:hover { background:#428bca; background-image:linear-gradient(to bottom, #428bca 0px, #3278b3 100%); border-color:#3278b3; color:#fff } | |
.buttn { color:#555; background:#fff; border:1px solid #ddd; border-radius:5px; font-size:12px; margin-bottom:-1px; padding:5px 7px; text-align:left; text-overflow:ellipsis; white-space:nowrap; overflow:hidden; cursor:pointer } | |
.buttn:hover { background:#f8f8f8 } | |
.buttn.active, .bttn.active:hover { background:#428bca; background-image:linear-gradient(to bottom, #428bca 0px, #3278b3 100%); border-color:#3278b3; color:#fff; cursor:default } | |
.tabs { list-style:outside none none; margin:0 0 5px; padding:0; border-bottom:1px solid #ddd } | |
.tabs:after { clear:both } | |
.tabs li { float:left; margin-bottom:-1px; display:block; position:relative } | |
.tabs li div { border:1px solid transparent; border-radius:4px 4px 0 0; line-height:20px; margin-right:2px; padding:10px 15px; color:#428bca } | |
.tabs li div:hover { border-color:#eee #eee #ddd; background:#eee; cursor:pointer; } | |
.tabs li.active div { background:#fff; border-color:#ddd #ddd transparent; border-style:solid; border-width:1px; color:#555; cursor:default } | |
.failure-mesg { color:#900 } | |
.failure-trace { color:#333; white-space:pre; overflow:auto } | |
.link { color:#428BCA; padding:5px 15px 5px 5px; text-decoration:underline; cursor:pointer } | |
.link.active { color:#333; text-decoration:none; cursor:default } | |
.chart { padding:0; margin:0; width:890px } | |
.chart svg { height:300px; padding:0; margin:0; overflow:visible; float:right } | |
.chart.lower svg { height:180px } | |
.chart-label-y { font-size:12px; position:relative; top:5px; padding:0; margin:0 } | |
.expandable { cursor:pointer } | |
.clearfix { clear:both } | |
.sortable > .arrow { display:inline-block; width:12px; height:inherit; color:#c90 } | |
.content-main { margin:0 5px; display:block; float:left } | |
{% endblock %} | |
{% block media_queries %} | |
@media only screen and (min-width: 320px) { .content-wrap { width:900px } .content-main { width:600px } } | |
@media only screen and (min-width: 900px) { .content-wrap { width:880px } .content-main { width:590px } } | |
@media only screen and (min-width: 1000px) { .content-wrap { width:980px } .content-main { width:690px } } | |
@media only screen and (min-width: 1100px) { .content-wrap { width:1080px } .content-main { width:790px } } | |
@media only screen and (min-width: 1200px) { .content-wrap { width:1180px } .content-main { width:890px } } | |
{% endblock %} | |
{% block body_attr %} ng-controller="Controller"{% endblock %} | |
{% block header_text %}task results{% endblock %} | |
{% block content %} | |
{% raw %} | |
<p id="page-error" class="notify-error" style="display:none"></p> | |
<div id="content-nav" class="aside" ng-show="scenarios.length" ng-cloack> | |
<div> | |
<div class="navcls" | |
ng-class="{active:view.is_main}" | |
ng-click="location.path('')">Task overview</div> | |
<div class="navcls" | |
ng-class="{active:view.is_source}" | |
ng-click="location.path('source', '')">Input file</div> | |
</div> | |
<div> | |
<div class="navcls" title="{{n.cls}}" | |
ng-repeat-start="n in nav track by $index" | |
ng-click="showNav(n.idx)" | |
ng-class="{expanded:n.idx==nav_idx}"> | |
<span ng-hide="n.idx==nav_idx">►</span> | |
<span ng-show="n.idx==nav_idx">▼</span> | |
{{n.cls}}</div> | |
<div class="navmet" title="{{m.name}}" | |
ng-show="n.idx==nav_idx" | |
ng-class="{active:m.ref==scenario.ref}" | |
ng-click="location.path(m.ref)" | |
ng-repeat="m in n.met track by $index" | |
ng-repeat-end>{{m.name}}</div> | |
</div> | |
</div> | |
<div id="content-main" class="content-main" ng-show="scenarios.length" ng-cloak> | |
<div ng-show="view.is_main"> | |
<h1>Task overview</h1> | |
<table class="linked compact" | |
ng-init="ov_srt='ref'; ov_dir=false"> | |
<thead> | |
<tr> | |
<th class="sortable" | |
title="Scenario name, with optional suffix of call number" | |
ng-click="ov_srt='ref'; ov_dir=!ov_dir"> | |
Scenario | |
<span class="arrow"> | |
<b ng-show="ov_srt=='ref' && !ov_dir">▴</b> | |
<b ng-show="ov_srt=='ref' && ov_dir">▾</b> | |
</span> | |
<th class="sortable" | |
title="How long the scenario run, without context duration" | |
ng-click="ov_srt='load_duration'; ov_dir=!ov_dir"> | |
Load duration (s) | |
<span class="arrow"> | |
<b ng-show="ov_srt=='load_duration' && !ov_dir">▴</b> | |
<b ng-show="ov_srt=='load_duration' && ov_dir">▾</b> | |
</span> | |
<th class="sortable" | |
title="Scenario duration plus context duration" | |
ng-click="ov_srt='full_duration'; ov_dir=!ov_dir"> | |
Full duration (s) | |
<span class="arrow"> | |
<b ng-show="ov_srt=='full_duration' && !ov_dir">▴</b> | |
<b ng-show="ov_srt=='full_duration' && ov_dir">▾</b> | |
</span> | |
<th class="sortable" title="Number of iterations" | |
ng-click="ov_srt='iterations_count'; ov_dir=!ov_dir"> | |
Iterations | |
<span class="arrow"> | |
<b ng-show="ov_srt=='iterations_count' && !ov_dir">▴</b> | |
<b ng-show="ov_srt=='iterations_count' && ov_dir">▾</b> | |
</span> | |
<th class="sortable" title="Scenario runner type" | |
ng-click="ov_srt='runner'; ov_dir=!ov_dir"> | |
Runner | |
<span class="arrow"> | |
<b ng-show="ov_srt=='runner' && !ov_dir">▴</b> | |
<b ng-show="ov_srt=='runner' && ov_dir">▾</b> | |
</span> | |
<th class="sortable" title="Number of errors occurred" | |
ng-click="ov_srt='errors.length'; ov_dir=!ov_dir"> | |
Errors | |
<span class="arrow"> | |
<b ng-show="ov_srt=='errors.length' && !ov_dir">▴</b> | |
<b ng-show="ov_srt=='errors.length' && ov_dir">▾</b> | |
</span> | |
<th class="sortable" title="Number of hooks" | |
ng-click="ov_srt='hooks.length'; ov_dir=!ov_dir"> | |
Hooks | |
<span class="arrow"> | |
<b ng-show="ov_srt=='hooks.length' && !ov_dir">▴</b> | |
<b ng-show="ov_srt=='hooks.length' && ov_dir">▾</b> | |
</span> | |
<th class="sortable" title="Whether SLA check is successful" | |
ng-click="ov_srt='sla_success'; ov_dir=!ov_dir"> | |
Success (SLA) | |
<span class="arrow"> | |
<b ng-show="ov_srt=='sla_success' && !ov_dir">▴</b> | |
<b ng-show="ov_srt=='sla_success' && ov_dir">▾</b> | |
</span> | |
<tr> | |
</thead> | |
<tbody> | |
<tr ng-repeat="sc in scenarios | orderBy:ov_srt:ov_dir" | |
ng-click="location.path(sc.ref)"> | |
<td>{{sc.ref}} | |
<td>{{sc.load_duration | number:3}} | |
<td>{{sc.full_duration | number:3}} | |
<td>{{sc.iterations_count}} | |
<td>{{sc.runner}} | |
<td>{{sc.errors.length}} | |
<td>{{sc.hooks.length}} | |
<td> | |
<span ng-show="sc.sla_success" class="status-pass">✔</span> | |
<span ng-hide="sc.sla_success" class="status-fail">✖</span> | |
<tr> | |
</tbody> | |
</table> | |
</div> | |
<div ng-show="view.is_source"> | |
<h1>Input file</h1> | |
<pre class="code">{{source}}</pre> | |
</div> | |
<div ng-show="view.is_scenario"> | |
<h1>{{scenario.cls}}.<wbr>{{scenario.name}} ({{scenario.full_duration | number:3}}s)</h1> | |
<div ng-show="scenario.description" style="margin-bottom: 20px;"> | |
<i>{{scenario.description}}</i> | |
</div> | |
<ul class="tabs"> | |
<li ng-repeat="t in tabs" | |
ng-show="t.isVisible()" | |
ng-class="{active:t.id == tab}" | |
ng-click="location.hash(t.id)"> | |
<div>{{t.name}}</div> | |
</li> | |
<div class="clearfix"></div> | |
</ul> | |
<div ng-include="tab"></div> | |
<script type="text/ng-template" id="overview"> | |
<p class="thesis"> | |
Load duration: <b>{{scenario.load_duration | number:3}} s</b> | |
Full duration: <b>{{scenario.full_duration | number:3}} s</b> | |
Iterations: <b>{{scenario.iterations_count}}</b> | |
Failures: <b>{{scenario.errors.length}}</b> | |
Started at: <b>{{scenario.created_at}}</b> | |
</p> | |
<div ng-show="scenario.sla.length"> | |
<h2>Service-level agreement</h2> | |
<table class="striped"> | |
<thead> | |
<tr> | |
<th>Criterion | |
<th>Detail | |
<th>Success | |
<tr> | |
</thead> | |
<tbody> | |
<tr class="rich" | |
ng-repeat="row in scenario.sla track by $index" | |
ng-class="{'status-fail':!row.success, 'status-pass':row.success}"> | |
<td>{{row.criterion}} | |
<td>{{row.detail}} | |
<td class="capitalize">{{row.success}} | |
<tr> | |
</tbody> | |
</table> | |
</div> | |
<div widget="Table" | |
data="scenario.table" | |
lastrow-class="rich" | |
title="Total durations"> | |
</div> | |
<div widget="StackedArea" | |
data="scenario.iterations.iter" | |
name-x="Iteration sequence number" | |
controls="true" | |
guide="true"> | |
</div> | |
<div widget="StackedArea" | |
data="scenario.load_profile" | |
title="Load Profile" | |
title-class="h3" | |
name-x="Timeline (seconds)" | |
format-y="d" | |
format-x=",.2f" | |
class="lower"> | |
</div> | |
<div widget="Pie" | |
data="scenario.iterations.pie" | |
title="Distribution" | |
title-class="h3" | |
style="float:left; width:40%; margin-top:15px"> | |
</div> | |
<div widget="Histogram" | |
ng-if="scenario.iterations.histogram.data.length" | |
data="scenario.iterations.histogram.data[mainHistogram.id]" | |
style="float:left; width:59%; margin-top:15px; position:relative; top:40px"> | |
</div> | |
<select ng-model="mainHistogram" | |
ng-show="scenario.iterations.histogram.data.length" | |
ng-options="i.name for i in scenario.iterations.histogram.views track by i.id" | |
style="float:right; margin:45px 35px 0"> | |
</select> | |
<div class="clearfix"></div> | |
</script> | |
<script type="text/ng-template" id="details"> | |
<div widget="StackedArea" | |
data="scenario.atomic.iter" | |
title="Atomic Action Durations" | |
name-x="Iteration sequence number" | |
controls="true" | |
guide="true"> | |
</div> | |
<div widget="Pie" | |
data="scenario.atomic.pie" | |
title="Distribution" | |
title-class="h3" | |
style="float:left; margin-top:15px" | |
ng-style="compact_atomics() ? {width:'40%'} : {}"> | |
</div> | |
<div widget="Histogram" data="scenario.atomic.histogram.data[atomicHistogram.id]" | |
ng-if="scenario.atomic.histogram.data.length" | |
style="float:left; position:relative; top:40px" | |
ng-style="compact_atomics() ? {width:'59%', 'margin-top':'15px'} : {}"> | |
</div> | |
<select ng-show="scenario.atomic.histogram.data.length" | |
ng-model="atomicHistogram" | |
ng-options="i.name for i in scenario.atomic.histogram.views track by i.id" | |
style="float:right; margin:45px 35px 0"> | |
</select> | |
<div class="clearfix"></div> | |
</script> | |
<script type="text/ng-template" id="output"> | |
<div style="padding:10px 0 0"> | |
<span class="link" | |
ng-click="location.hash('output/additive')" | |
ng-class="{active:scenario.output.active === 'additive'}" | |
ng-if="scenario.output.has_additive">Aggregated</span> | |
<span class="link" | |
ng-click="location.hash('output/complete')" | |
ng-class="{active:scenario.output.active === 'complete'}" | |
ng-if="scenario.output.has_complete">Per iteration</span> | |
</div> | |
<div ng-repeat="chart in scenario.additive_output" | |
ng-if="scenario.output.active === 'additive'"> | |
<div widget="{{chart.widget}}" | |
title="{{chart.title}}" | |
description="{{chart.description}}" | |
name-x="{{chart.axis_label}}" | |
name-y="{{chart.label}}" | |
data="chart.data"> | |
</div> | |
</div> | |
<div ng-if="scenario.output.active === 'complete'" style="padding:10px 0 0"> | |
<select ng-model="outputIteration"> | |
<option ng-repeat="i in scenario.complete_output track by $index" | |
value="{{$index}}"> | |
Iteration {{$index}} | |
</select> | |
<div ng-repeat="chart in scenario.complete_output[outputIteration]"> | |
<div widget="{{chart.widget}}" | |
title="{{chart.title}}" | |
description="{{chart.description}}" | |
name-x="{{chart.axis_label}}" | |
name-y="{{chart.label}}" | |
data="chart.data"> | |
</div> | |
</div> | |
</div> | |
</script> | |
<script type="text/ng-template" id="hooks"> | |
<div style="padding:15px 0"> | |
<span ng-repeat="h in scenario.hooks track by $index" | |
class="buttn" | |
title="{{h.desc}}" | |
style="margin:0 10px 0 0" | |
ng-click="location.hash('hooks/'+$index)" | |
ng-class="{active:scenario.hook_idx===$index}"> | |
{{h.name}} | |
</span> | |
</div> | |
<table class="striped" style="margin:5px 0 25px"> | |
<thead> | |
<tr> | |
<th>Plugin | |
<th>Description | |
</thead> | |
<tbody> | |
<tr> | |
<td>{{scenario.hooks.cur.name}} | |
<td>{{scenario.hooks.cur.desc}} | |
</tbody> | |
</table> | |
<div> | |
<span class="link" | |
ng-click="scenario.hooks.cur.active = 'additive'" | |
ng-class="{active:scenario.hooks.cur.active === 'additive'}" | |
ng-if="scenario.hooks.cur.additive.length">Aggregated</span> | |
<span class="link" | |
ng-click="scenario.hooks.cur.active = 'complete'" | |
ng-class="{active:scenario.hooks.cur.active === 'complete'}" | |
ng-if="scenario.hooks.cur.complete.length">Per hook run</span> | |
</div> | |
<div ng-repeat="chart in scenario.hooks.cur.additive" | |
ng-if="scenario.hooks.cur.active === 'additive'"> | |
<div widget="{{chart.widget}}" | |
title="{{chart.title}}" | |
description="{{chart.description}}" | |
name-x="{{chart.axis_label}}" | |
name-y="{{chart.label}}" | |
data="chart.data"> | |
</div> | |
</div> | |
<div ng-if="scenario.hooks.cur.active === 'complete'" style="padding:10px 0 0"> | |
<select ng-if="complete_hooks_as_dropdown()" | |
ng-model="scenario.hooks.cur.run_idx" | |
ng-change="set_hook_run()"> | |
<option ng-repeat="h in scenario.hooks.cur.complete track by $index" | |
ng-selected="scenario.hooks.cur.run_idx == $index" | |
value="{{$index}}"> | |
{{h.triggered_by}} | |
</select> | |
<div ng-if="! complete_hooks_as_dropdown()" | |
style="border:#ccc solid; border-width:1px 0 0; padding:5px 0 0"> | |
<span ng-repeat="h in scenario.hooks.cur.complete track by $index" | |
class="link" | |
ng-class="{active:scenario.hooks.cur.run_idx == $index}" | |
ng-click="set_hook_run($index)"> | |
{{h.triggered_by}} | |
</span> | |
</div> | |
<table class="striped" style="margin:15px 0 15px"> | |
<thead> | |
<tr> | |
<th>Status | |
<th>Triggered by | |
<th>Started at | |
<th>Finished at | |
</thead> | |
<tbody> | |
<tr> | |
<td ng-style="scenario.hooks.cur.run.status === 'success' ? {color:'green'} : {color:'red'}"> | |
<b>{{scenario.hooks.cur.run.status}}</b> | |
<td>{{scenario.hooks.cur.run.triggered_by}} | |
<td>{{scenario.hooks.cur.run.started_at}} | |
<td>{{scenario.hooks.cur.run.finished_at}} | |
</tbody> | |
</table> | |
<div ng-repeat="chart in scenario.hooks.cur.run.charts"> | |
<div widget="{{chart.widget}}" | |
title="{{chart.title}}" | |
description="{{chart.description}}" | |
name-x="{{chart.axis_label}}" | |
name-y="{{chart.label}}" | |
data="chart.data"> | |
</div> | |
</div> | |
</div> | |
</script> | |
<script type="text/ng-template" id="failures"> | |
<h2>Task failures (<ng-pluralize | |
count="scenario.errors.length" | |
when="{'1': '1 iteration', 'other': '{} iterations'}"></ng-pluralize> failed) | |
</h2> | |
<table class="striped"> | |
<thead> | |
<tr> | |
<th> | |
<th>Iteration | |
<th>Exception type | |
<th>Exception message | |
</tr> | |
</thead> | |
<tbody> | |
<tr class="expandable" | |
ng-repeat-start="i in scenario.errors track by $index" | |
ng-click="i.expanded = ! i.expanded"> | |
<td> | |
<span ng-hide="i.expanded">►</span> | |
<span ng-show="i.expanded">▼</span> | |
<td>{{i.iteration}} | |
<td>{{i.type}} | |
<td class="failure-mesg">{{i.message}} | |
</tr> | |
<tr ng-show="i.expanded" ng-repeat-end> | |
<td colspan="4" class="failure-trace">{{i.traceback}} | |
</tr> | |
</tbody> | |
</table> | |
</script> | |
<script type="text/ng-template" id="task"> | |
<h2>The Workload Configuration</h2> | |
<pre class="code">{{scenario.config}}</pre> | |
</script> | |
</div> | |
</div> | |
<div class="clearfix"></div> | |
{% endraw %} | |
{% endblock %} | |
{% block js_after %} | |
if (! window.angular) {(function(f){ | |
f(document.getElementById("content-nav"), "none"); | |
f(document.getElementById("content-main"), "none"); | |
f(document.getElementById("page-error"), "block").textContent = "Failed to load AngularJS framework" | |
})(function(e, s){e.style.display = s; return e})} | |
{% endblock %} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment