mirror of
https://github.com/ansible/awx.git
synced 2026-01-10 15:32:07 -03:30
First attempt at adding a graph to job detail page.
This commit is contained in:
parent
69aa991499
commit
a895c6beea
@ -7,7 +7,7 @@
|
||||
"jquery": true,
|
||||
"esnext": true,
|
||||
"globalstrict": true,
|
||||
"globals": { "angular":false, "alert":false, "$AnsibleConfig":true, "$basePath":true, "jsyaml":false, "_":true },
|
||||
"globals": { "angular":false, "alert":false, "$AnsibleConfig":true, "$basePath":true, "jsyaml":false, "_":false, "d3":false, "Donut3D":false },
|
||||
"strict": false,
|
||||
"quotmark": false,
|
||||
"smarttabs": true,
|
||||
|
||||
@ -269,7 +269,14 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
|
||||
'box-shadow': 'none',
|
||||
'height': 'auto'
|
||||
});
|
||||
$('#job-summary-container').css({ "width": "41.66666667%", "padding-right": "15px", "z-index": 0 }).show();
|
||||
$('#job-summary-container').css({
|
||||
"width": "41.66666667%",
|
||||
"padding-left": "7px",
|
||||
"padding-right": "15px",
|
||||
"z-index": 0
|
||||
});
|
||||
setTimeout(function() { $('#job-summary-container .job_well').height($('#job-detail-container').height() - 18); }, 500);
|
||||
$('#job-summary-container').show();
|
||||
}
|
||||
// Detail table height adjusting. First, put page height back to 'normal'.
|
||||
$('#plays-table-detail').height(150);
|
||||
|
||||
@ -40,9 +40,9 @@
|
||||
angular.module('JobDetailHelper', ['Utilities', 'RestServices'])
|
||||
|
||||
.factory('DigestEvents', ['UpdatePlayStatus', 'UpdateHostStatus', 'UpdatePlayChild', 'AddHostResult', 'SelectPlay', 'SelectTask',
|
||||
'GetHostCount', 'GetElapsed', 'UpdateTaskStatus',
|
||||
'GetHostCount', 'GetElapsed', 'UpdateTaskStatus', 'DrawGraph',
|
||||
function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, SelectPlay, SelectTask, GetHostCount, GetElapsed,
|
||||
UpdateTaskStatus) {
|
||||
UpdateTaskStatus, DrawGraph) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope,
|
||||
@ -156,6 +156,7 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
|
||||
scope: scope,
|
||||
id: event.id
|
||||
});
|
||||
DrawGraph({ scope: scope });
|
||||
}
|
||||
|
||||
if (event.event === 'runner_on_unreachable') {
|
||||
@ -229,6 +230,7 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
|
||||
});
|
||||
scope.job_status.status = (event.failed) ? 'failed' : 'successful';
|
||||
scope.job_status.status_class = "";
|
||||
DrawGraph({ scope: scope });
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -768,18 +770,66 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
|
||||
};
|
||||
}])
|
||||
|
||||
.factory('GetHostSummary', [ function() {
|
||||
.factory('DrawGraph', ['Rest', 'GetBasePath', 'ProcessErrors', function(Rest, GetBasePath, ProcessErrors) {
|
||||
return function(params) {
|
||||
var scope = params.scope,
|
||||
dark = 0, failed = 0, changed = 0, ok = 0,
|
||||
svg_height, svg_width, graph_data, svg, url;
|
||||
|
||||
}])
|
||||
svg_width = $('#graph-section').width();
|
||||
svg_height = 300;
|
||||
if ($('#graph-section svg').length === 0) {
|
||||
svg = d3.select("#graph-section").append("svg").attr("width", svg_width).attr("height", svg_height);
|
||||
}
|
||||
else {
|
||||
svg = d3.select("#graph-section svg");
|
||||
}
|
||||
svg.append("g").attr("id","completedHostsDonutNew");
|
||||
$('#completedHostsDonutNew').hide();
|
||||
|
||||
if (scope.removeRenderGraph) {
|
||||
scope.removeRenderGraph();
|
||||
}
|
||||
scope.removeRenderGraph = scope.$on('RenderGraph', function() {
|
||||
Donut3D.draw("completedHostsDonutNew", graph_data, Math.floor(svg_width / 2), 150, 130, 100, 15, 0.4);
|
||||
$('#completedHostsDonut').remove();
|
||||
$('#completedHostsDonutNew').attr('id','completedHostsDonut');
|
||||
$('#completedHostsDonut').show();
|
||||
});
|
||||
|
||||
.factory('DrawGraph', [ function() {
|
||||
/*var salesData=[
|
||||
{label:"OK", color:"#9ED89E"},
|
||||
{label:"Changed", color:"#DC3912"},
|
||||
{label:"Failed", color:"#DA4D49;"},
|
||||
{label:"Skipped", color:"#D4D4D4"},
|
||||
{label:"Unreachable", color:""}
|
||||
];*/
|
||||
url = GetBasePath('jobs') + scope.job_id + '/job_host_summaries/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function(data) {
|
||||
if (data.count) {
|
||||
data.results.forEach(function(row) {
|
||||
if (row.dark) {
|
||||
dark ++;
|
||||
}
|
||||
else if (row.failures) {
|
||||
failed++;
|
||||
}
|
||||
else if (row.changed) {
|
||||
changed++;
|
||||
}
|
||||
else if (row.ok) {
|
||||
ok++;
|
||||
}
|
||||
});
|
||||
graph_data = [
|
||||
{ label: 'OK', value: ok, color: '#9ED89E' },
|
||||
{ label: 'Changed', value: changed, color: '#FFC773' },
|
||||
{ label: 'Failed', value: failed, color: '#DA4D49' },
|
||||
{ label: 'Unreachable', value: dark, color: '#A9A9A9' }
|
||||
];
|
||||
scope.$emit('RenderGraph');
|
||||
}
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Call to ' + url + '. GET returned: ' + status });
|
||||
});
|
||||
};
|
||||
}])
|
||||
|
||||
.factory('FilterAllByHostName', ['Rest', 'GetBasePath', 'ProcessErrors', 'SelectPlay', function(Rest, GetBasePath, ProcessErrors, SelectPlay) {
|
||||
@ -787,7 +837,7 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
|
||||
var scope = params.scope,
|
||||
host = params.host,
|
||||
job_id = scope.job_id,
|
||||
url = GetBasePath('jobs') + job_id + '/job_events/?event__icontains=runner&host_name__icontains=' + host;
|
||||
url = GetBasePath('jobs') + job_id + '/job_events/?event__icontains=runner&host_name__icontains=' + host + '&parent__isnull=false';
|
||||
|
||||
scope.search_all_tasks = [];
|
||||
scope.search_all_plays = [];
|
||||
@ -811,17 +861,22 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function(data) {
|
||||
data.results.forEach(function(row) {
|
||||
if (row.parent) {
|
||||
scope.search_all_plays.push(row.parent);
|
||||
if (data.count > 0) {
|
||||
data.results.forEach(function(row) {
|
||||
if (row.parent) {
|
||||
scope.search_all_plays.push(row.parent);
|
||||
}
|
||||
});
|
||||
if (scope.search_all_plays.length > 0) {
|
||||
scope.search_all_plays.sort();
|
||||
scope.activePlay = scope.search_all_plays[scope.search_all_plays.length - 1];
|
||||
}
|
||||
else {
|
||||
scope.activePlay = null;
|
||||
}
|
||||
});
|
||||
if (scope.search_all_plays.length > 0) {
|
||||
scope.search_all_plays.sort();
|
||||
scope.activePlay = scope.search_all_plays[scope.search_all_plays.length - 1];
|
||||
}
|
||||
else {
|
||||
scope.activePlay = null;
|
||||
scope.search_all_plays.push(0);
|
||||
}
|
||||
scope.$emit('AllPlaysReady');
|
||||
})
|
||||
@ -834,13 +889,18 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function(data) {
|
||||
data.results.forEach(function(row) {
|
||||
if (row.parent) {
|
||||
scope.search_all_tasks.push(row.parent);
|
||||
if (data.count > 0) {
|
||||
data.results.forEach(function(row) {
|
||||
if (row.parent) {
|
||||
scope.search_all_tasks.push(row.parent);
|
||||
}
|
||||
});
|
||||
if (scope.search_all_tasks.length > 0) {
|
||||
scope.search_all_tasks.sort();
|
||||
}
|
||||
});
|
||||
if (scope.search_all_tasks.length > 0) {
|
||||
scope.search_all_tasks.sort();
|
||||
}
|
||||
else {
|
||||
scope.search_all_tasks.push(0);
|
||||
}
|
||||
scope.$emit('AllTasksReady');
|
||||
})
|
||||
|
||||
@ -142,6 +142,9 @@
|
||||
padding-left: 15px;
|
||||
padding-right: 7px;
|
||||
width: 58.33333333%;
|
||||
.well {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
#job-summary-container {
|
||||
@ -303,3 +306,35 @@ label.small-label {
|
||||
.mCSB_container {
|
||||
margin-right: 18px;
|
||||
}
|
||||
|
||||
|
||||
#graph-section {
|
||||
position: relative;
|
||||
.legend {
|
||||
font-size: 12px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
i {
|
||||
margin-left: 5px;
|
||||
}
|
||||
i:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
path.slice{
|
||||
stroke-width:2px;
|
||||
}
|
||||
|
||||
polyline{
|
||||
opacity: .3;
|
||||
stroke: black;
|
||||
stroke-width: 2px;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
svg text.percent{
|
||||
fill:white;
|
||||
text-anchor:middle;
|
||||
font-size:12px;
|
||||
}
|
||||
|
||||
123
awx/ui/static/lib/d3Donut/d3Donut.js
vendored
Normal file
123
awx/ui/static/lib/d3Donut/d3Donut.js
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
!function(){
|
||||
var Donut3D={};
|
||||
|
||||
function pieTop(d, rx, ry, ir ){
|
||||
if(d.endAngle - d.startAngle == 0 ) return "M 0 0";
|
||||
var sx = rx*Math.cos(d.startAngle),
|
||||
sy = ry*Math.sin(d.startAngle),
|
||||
ex = rx*Math.cos(d.endAngle),
|
||||
ey = ry*Math.sin(d.endAngle);
|
||||
|
||||
var ret =[];
|
||||
ret.push("M",sx,sy,"A",rx,ry,"0",(d.endAngle-d.startAngle > Math.PI? 1: 0),"1",ex,ey,"L",ir*ex,ir*ey);
|
||||
ret.push("A",ir*rx,ir*ry,"0",(d.endAngle-d.startAngle > Math.PI? 1: 0), "0",ir*sx,ir*sy,"z");
|
||||
return ret.join(" ");
|
||||
}
|
||||
|
||||
function pieOuter(d, rx, ry, h ){
|
||||
var startAngle = (d.startAngle > Math.PI ? Math.PI : d.startAngle);
|
||||
var endAngle = (d.endAngle > Math.PI ? Math.PI : d.endAngle);
|
||||
|
||||
var sx = rx*Math.cos(startAngle),
|
||||
sy = ry*Math.sin(startAngle),
|
||||
ex = rx*Math.cos(endAngle),
|
||||
ey = ry*Math.sin(endAngle);
|
||||
|
||||
var ret =[];
|
||||
ret.push("M",sx,h+sy,"A",rx,ry,"0 0 1",ex,h+ey,"L",ex,ey,"A",rx,ry,"0 0 0",sx,sy,"z");
|
||||
return ret.join(" ");
|
||||
}
|
||||
|
||||
function pieInner(d, rx, ry, h, ir ){
|
||||
var startAngle = (d.startAngle < Math.PI ? Math.PI : d.startAngle);
|
||||
var endAngle = (d.endAngle < Math.PI ? Math.PI : d.endAngle);
|
||||
|
||||
var sx = ir*rx*Math.cos(startAngle),
|
||||
sy = ir*ry*Math.sin(startAngle),
|
||||
ex = ir*rx*Math.cos(endAngle),
|
||||
ey = ir*ry*Math.sin(endAngle);
|
||||
|
||||
var ret =[];
|
||||
ret.push("M",sx, sy,"A",ir*rx,ir*ry,"0 0 1",ex,ey, "L",ex,h+ey,"A",ir*rx, ir*ry,"0 0 0",sx,h+sy,"z");
|
||||
return ret.join(" ");
|
||||
}
|
||||
|
||||
function getPercent(d){
|
||||
return (d.endAngle-d.startAngle > 0.2 ?
|
||||
Math.round(1000*(d.endAngle-d.startAngle)/(Math.PI*2))/10+'%' : '');
|
||||
}
|
||||
|
||||
Donut3D.transition = function(id, data, rx, ry, h, ir){
|
||||
function arcTweenInner(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return pieInner(i(t), rx+0.5, ry+0.5, h, ir); };
|
||||
}
|
||||
function arcTweenTop(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return pieTop(i(t), rx, ry, ir); };
|
||||
}
|
||||
function arcTweenOuter(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return pieOuter(i(t), rx-.5, ry-.5, h); };
|
||||
}
|
||||
function textTweenX(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return 0.6*rx*Math.cos(0.5*(i(t).startAngle+i(t).endAngle)); };
|
||||
}
|
||||
function textTweenY(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return 0.6*rx*Math.sin(0.5*(i(t).startAngle+i(t).endAngle)); };
|
||||
}
|
||||
|
||||
var _data = d3.layout.pie().sort(null).value(function(d) {return d.value;})(data);
|
||||
|
||||
d3.select("#"+id).selectAll(".innerSlice").data(_data)
|
||||
.transition().duration(750).attrTween("d", arcTweenInner);
|
||||
|
||||
d3.select("#"+id).selectAll(".topSlice").data(_data)
|
||||
.transition().duration(750).attrTween("d", arcTweenTop);
|
||||
|
||||
d3.select("#"+id).selectAll(".outerSlice").data(_data)
|
||||
.transition().duration(750).attrTween("d", arcTweenOuter);
|
||||
|
||||
d3.select("#"+id).selectAll(".percent").data(_data).transition().duration(750)
|
||||
.attrTween("x",textTweenX).attrTween("y",textTweenY).text(getPercent);
|
||||
}
|
||||
|
||||
Donut3D.draw=function(id, data, x /*center x*/, y/*center y*/,
|
||||
rx/*radius x*/, ry/*radius y*/, h/*height*/, ir/*inner radius*/){
|
||||
|
||||
var _data = d3.layout.pie().sort(null).value(function(d) {return d.value;})(data);
|
||||
|
||||
var slices = d3.select("#"+id).append("g").attr("transform", "translate(" + x + "," + y + ")")
|
||||
.attr("class", "slices");
|
||||
|
||||
slices.selectAll(".innerSlice").data(_data).enter().append("path").attr("class", "innerSlice")
|
||||
.style("fill", function(d) { return d3.hsl(d.data.color).darker(0.7); })
|
||||
.attr("d",function(d){ return pieInner(d, rx+0.5,ry+0.5, h, ir);})
|
||||
.each(function(d){this._current=d;});
|
||||
|
||||
slices.selectAll(".topSlice").data(_data).enter().append("path").attr("class", "topSlice")
|
||||
.style("fill", function(d) { return d.data.color; })
|
||||
.style("stroke", function(d) { return d.data.color; })
|
||||
.attr("d",function(d){ return pieTop(d, rx, ry, ir);})
|
||||
.each(function(d){this._current=d;});
|
||||
|
||||
slices.selectAll(".outerSlice").data(_data).enter().append("path").attr("class", "outerSlice")
|
||||
.style("fill", function(d) { return d3.hsl(d.data.color).darker(0.7); })
|
||||
.attr("d",function(d){ return pieOuter(d, rx-.5,ry-.5, h);})
|
||||
.each(function(d){this._current=d;});
|
||||
|
||||
slices.selectAll(".percent").data(_data).enter().append("text").attr("class", "percent")
|
||||
.attr("x",function(d){ return 0.6*rx*Math.cos(0.5*(d.startAngle+d.endAngle));})
|
||||
.attr("y",function(d){ return 0.6*ry*Math.sin(0.5*(d.startAngle+d.endAngle));})
|
||||
.text(getPercent).each(function(d){this._current=d;});
|
||||
}
|
||||
|
||||
this.Donut3D = Donut3D;
|
||||
}();
|
||||
@ -204,7 +204,11 @@
|
||||
</div><!-- section -->
|
||||
|
||||
<div id="graph-section">
|
||||
|
||||
<div class="header">
|
||||
<div class="title">Host Status Overview</div>
|
||||
<div class="legend"><i class="fa fa-circle successful-hosts-color"></i> Successful <i class="fa fa-circle changed-hosts-color"></i> Changed
|
||||
<i class="fa fa-circle unreachable-hosts-color"></i> Unreachable <i class="fa fa-circle failed-hosts-color"></i> Failed</div>
|
||||
</div>
|
||||
</div><!-- graph section -->
|
||||
</div>
|
||||
</div><!-- col-md-5 -->
|
||||
|
||||
@ -405,132 +405,7 @@
|
||||
<script src="{{ STATIC_URL }}lib/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js"></script>
|
||||
<script scr="{{ STATIC_URL }}lib/lib/jQuery.dotdotdot/src/js/jquery.dotdotdot.min.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/d3js/build/d3.v3.min.js"></script>
|
||||
|
||||
<script>
|
||||
!function(){
|
||||
var Donut3D={};
|
||||
|
||||
function pieTop(d, rx, ry, ir ){
|
||||
if(d.endAngle - d.startAngle == 0 ) return "M 0 0";
|
||||
var sx = rx*Math.cos(d.startAngle),
|
||||
sy = ry*Math.sin(d.startAngle),
|
||||
ex = rx*Math.cos(d.endAngle),
|
||||
ey = ry*Math.sin(d.endAngle);
|
||||
|
||||
var ret =[];
|
||||
ret.push("M",sx,sy,"A",rx,ry,"0",(d.endAngle-d.startAngle > Math.PI? 1: 0),"1",ex,ey,"L",ir*ex,ir*ey);
|
||||
ret.push("A",ir*rx,ir*ry,"0",(d.endAngle-d.startAngle > Math.PI? 1: 0), "0",ir*sx,ir*sy,"z");
|
||||
return ret.join(" ");
|
||||
}
|
||||
|
||||
function pieOuter(d, rx, ry, h ){
|
||||
var startAngle = (d.startAngle > Math.PI ? Math.PI : d.startAngle);
|
||||
var endAngle = (d.endAngle > Math.PI ? Math.PI : d.endAngle);
|
||||
|
||||
var sx = rx*Math.cos(startAngle),
|
||||
sy = ry*Math.sin(startAngle),
|
||||
ex = rx*Math.cos(endAngle),
|
||||
ey = ry*Math.sin(endAngle);
|
||||
|
||||
var ret =[];
|
||||
ret.push("M",sx,h+sy,"A",rx,ry,"0 0 1",ex,h+ey,"L",ex,ey,"A",rx,ry,"0 0 0",sx,sy,"z");
|
||||
return ret.join(" ");
|
||||
}
|
||||
|
||||
function pieInner(d, rx, ry, h, ir ){
|
||||
var startAngle = (d.startAngle < Math.PI ? Math.PI : d.startAngle);
|
||||
var endAngle = (d.endAngle < Math.PI ? Math.PI : d.endAngle);
|
||||
|
||||
var sx = ir*rx*Math.cos(startAngle),
|
||||
sy = ir*ry*Math.sin(startAngle),
|
||||
ex = ir*rx*Math.cos(endAngle),
|
||||
ey = ir*ry*Math.sin(endAngle);
|
||||
|
||||
var ret =[];
|
||||
ret.push("M",sx, sy,"A",ir*rx,ir*ry,"0 0 1",ex,ey, "L",ex,h+ey,"A",ir*rx, ir*ry,"0 0 0",sx,h+sy,"z");
|
||||
return ret.join(" ");
|
||||
}
|
||||
|
||||
function getPercent(d){
|
||||
return (d.endAngle-d.startAngle > 0.2 ?
|
||||
Math.round(1000*(d.endAngle-d.startAngle)/(Math.PI*2))/10+'%' : '');
|
||||
}
|
||||
|
||||
Donut3D.transition = function(id, data, rx, ry, h, ir){
|
||||
function arcTweenInner(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return pieInner(i(t), rx+0.5, ry+0.5, h, ir); };
|
||||
}
|
||||
function arcTweenTop(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return pieTop(i(t), rx, ry, ir); };
|
||||
}
|
||||
function arcTweenOuter(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return pieOuter(i(t), rx-.5, ry-.5, h); };
|
||||
}
|
||||
function textTweenX(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return 0.6*rx*Math.cos(0.5*(i(t).startAngle+i(t).endAngle)); };
|
||||
}
|
||||
function textTweenY(a) {
|
||||
var i = d3.interpolate(this._current, a);
|
||||
this._current = i(0);
|
||||
return function(t) { return 0.6*rx*Math.sin(0.5*(i(t).startAngle+i(t).endAngle)); };
|
||||
}
|
||||
|
||||
var _data = d3.layout.pie().sort(null).value(function(d) {return d.value;})(data);
|
||||
|
||||
d3.select("#"+id).selectAll(".innerSlice").data(_data)
|
||||
.transition().duration(750).attrTween("d", arcTweenInner);
|
||||
|
||||
d3.select("#"+id).selectAll(".topSlice").data(_data)
|
||||
.transition().duration(750).attrTween("d", arcTweenTop);
|
||||
|
||||
d3.select("#"+id).selectAll(".outerSlice").data(_data)
|
||||
.transition().duration(750).attrTween("d", arcTweenOuter);
|
||||
|
||||
d3.select("#"+id).selectAll(".percent").data(_data).transition().duration(750)
|
||||
.attrTween("x",textTweenX).attrTween("y",textTweenY).text(getPercent);
|
||||
}
|
||||
|
||||
Donut3D.draw=function(id, data, x /*center x*/, y/*center y*/,
|
||||
rx/*radius x*/, ry/*radius y*/, h/*height*/, ir/*inner radius*/){
|
||||
|
||||
var _data = d3.layout.pie().sort(null).value(function(d) {return d.value;})(data);
|
||||
|
||||
var slices = d3.select("#"+id).append("g").attr("transform", "translate(" + x + "," + y + ")")
|
||||
.attr("class", "slices");
|
||||
|
||||
slices.selectAll(".innerSlice").data(_data).enter().append("path").attr("class", "innerSlice")
|
||||
.style("fill", function(d) { return d3.hsl(d.data.color).darker(0.7); })
|
||||
.attr("d",function(d){ return pieInner(d, rx+0.5,ry+0.5, h, ir);})
|
||||
.each(function(d){this._current=d;});
|
||||
|
||||
slices.selectAll(".topSlice").data(_data).enter().append("path").attr("class", "topSlice")
|
||||
.style("fill", function(d) { return d.data.color; })
|
||||
.style("stroke", function(d) { return d.data.color; })
|
||||
.attr("d",function(d){ return pieTop(d, rx, ry, ir);})
|
||||
.each(function(d){this._current=d;});
|
||||
|
||||
slices.selectAll(".outerSlice").data(_data).enter().append("path").attr("class", "outerSlice")
|
||||
.style("fill", function(d) { return d3.hsl(d.data.color).darker(0.7); })
|
||||
.attr("d",function(d){ return pieOuter(d, rx-.5,ry-.5, h);})
|
||||
.each(function(d){this._current=d;});
|
||||
|
||||
slices.selectAll(".percent").data(_data).enter().append("text").attr("class", "percent")
|
||||
.attr("x",function(d){ return 0.6*rx*Math.cos(0.5*(d.startAngle+d.endAngle));})
|
||||
.attr("y",function(d){ return 0.6*ry*Math.sin(0.5*(d.startAngle+d.endAngle));})
|
||||
.text(getPercent).each(function(d){this._current=d;});
|
||||
}
|
||||
|
||||
this.Donut3D = Donut3D;
|
||||
}();
|
||||
</script>
|
||||
<script src="{{ STATIC_URL }}lib/d3Donut/d3Donut.js"></script>
|
||||
|
||||
<script>
|
||||
// When user clicks on main tab, fire the matching Angular route
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user