Skip to content

Instantly share code, notes, and snippets.

@ilivessevili
Created November 1, 2017 13:05
Show Gist options
  • Save ilivessevili/84ab12a642bea07b397a24608838240c to your computer and use it in GitHub Desktop.
Save ilivessevili/84ab12a642bea07b397a24608838240c to your computer and use it in GitHub Desktop.
{% 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">&#9658;</span>
<span ng-show="n.idx==nav_idx">&#9660;</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">&#x25b4;</b>
<b ng-show="ov_srt=='ref' && ov_dir">&#x25be;</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">&#x25b4;</b>
<b ng-show="ov_srt=='load_duration' && ov_dir">&#x25be;</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">&#x25b4;</b>
<b ng-show="ov_srt=='full_duration' && ov_dir">&#x25be;</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">&#x25b4;</b>
<b ng-show="ov_srt=='iterations_count' && ov_dir">&#x25be;</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">&#x25b4;</b>
<b ng-show="ov_srt=='runner' && ov_dir">&#x25be;</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">&#x25b4;</b>
<b ng-show="ov_srt=='errors.length' && ov_dir">&#x25be;</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">&#x25b4;</b>
<b ng-show="ov_srt=='hooks.length' && ov_dir">&#x25be;</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">&#x25b4;</b>
<b ng-show="ov_srt=='sla_success' && ov_dir">&#x25be;</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">&#x2714;</span>
<span ng-hide="sc.sla_success" class="status-fail">&#x2716;</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> &nbsp;
Full duration: <b>{{scenario.full_duration | number:3}} s</b> &nbsp;
Iterations: <b>{{scenario.iterations_count}}</b> &nbsp;
Failures: <b>{{scenario.errors.length}}</b> &nbsp;
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">&#9658;</span>
<span ng-show="i.expanded">&#9660;</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