diff --git a/horizon/static/horizon/js/horizon.d3barchart.js b/horizon/static/horizon/js/horizon.d3barchart.js index 103e2d624b..72f0b18be4 100644 --- a/horizon/static/horizon/js/horizon.d3barchart.js +++ b/horizon/static/horizon/js/horizon.d3barchart.js @@ -42,7 +42,7 @@ Json with variety of settings described below. used-label-placement='string' OPTIONAL - String determinign where the floating label stating number of percent + String determining where the floating label stating number of percent will be placed. So far only left is supported. width="integer" OPTIONAL diff --git a/horizon/static/horizon/js/horizon.d3piechart.js b/horizon/static/horizon/js/horizon.d3piechart.js index 4991295111..4aae5ddb1f 100644 --- a/horizon/static/horizon/js/horizon.d3piechart.js +++ b/horizon/static/horizon/js/horizon.d3piechart.js @@ -1,31 +1,64 @@ /* - Draw pie chart in d3. + Draw pie charts in d3. - To use, a div is required with the class .d3_pie_chart - and a data-used attribute in the div - that stores the percentage to fill the chart + To use, a div is required with the class .d3_pie_chart_usage or + .d3_pie_chart_distribution, and a data-used attribute in the div + that stores the data used to fill the chart. - Example: -
+ + Example (distribution): +
+
*/ -horizon.d3_pie_chart = { - w: 100, - h: 100, - r: 45, - bkgrnd: "#F2F2F2", - frgrnd: "#006CCF", - full: "#D0342B", - nearlyfull: "orange", +// Pie chart dimensions +var WIDTH = 100; +var HEIGHT = 100; +var RADIUS = 45; +// Colors +var BKGRND = "#F2F2F2"; +var FRGRND = "#006CCF"; +var FULL = "#D0342B"; +var NEARLY_FULL = "#FFA500"; +var STROKE = "#CCCCCC"; + + +function create_vis(chart) { + return d3.select(chart).append("svg:svg") + .attr("class", "chart") + .attr("width", WIDTH) + .attr("height", HEIGHT) + .append("g") + .attr("transform", + "translate(" + (RADIUS + 2) + "," + (RADIUS + 2) + ")"); +} + +function create_arc() { + return d3.svg.arc() + .outerRadius(RADIUS) + .innerRadius(0); +} + +function create_pie(param) { + return d3.layout.pie() + .sort(null) + .value(function(d){ return d[param]; }); +} + + +horizon.d3_pie_chart_usage = { init: function() { var self = this; // Pie Charts - var pie_chart_data = $(".d3_pie_chart"); - self.chart = d3.selectAll(".d3_pie_chart"); + var pie_chart_data = $(".d3_pie_chart_usage"); + self.chart = d3.selectAll(".d3_pie_chart_usage"); for (var i = 0; i < pie_chart_data.length; i++) { var used = Math.min(parseInt($(pie_chart_data[i]).data("used")), 100); @@ -36,79 +69,179 @@ horizon.d3_pie_chart = { // Draw a pie chart pieChart: function(i) { var self = this; - var vis = d3.select(self.chart[0][i]).append("svg:svg") - .attr("class", "chart") - .attr("width", self.w) - .attr("height", self.h) - .append("g") - .attr("transform", - "translate(" + (self.r + 2) + "," + (self.r + 2) + ")"); - - var arc = d3.svg.arc() - .outerRadius(self.r) - .innerRadius(0); - - var pie = d3.layout.pie() - .sort(null) - .value(function(d){ return d.percentage; }); + var vis = create_vis(self.chart[0][i]); + var arc = create_arc(); + var pie = create_pie("percentage"); // Draw an empty pie chart - var piechart = vis.selectAll(".arc") + vis.selectAll(".arc") .data(pie([{"percentage":10}])) .enter() - .append("path") - .attr("class","arc") - .attr("d", arc) - .style("fill", function(d){ - if (self.data[0].percentage >= 100) { - return self.full; - } else if (self.data[0].percentage >= 80) { - return self.nearlyfull; - } else { - return self.frgrnd; - } - }) - .style("stroke", "#CCCCCC") - .style("stroke-width", 1) - .each(function(d) { - self.current = d; - return d; - }); + .append("path") + .attr("class","arc") + .attr("d", arc) + .style("fill", function(){ + if (self.data[0].percentage >= 100) { + return FULL; + } else if (self.data[0].percentage >= 80) { + return NEARLY_FULL; + } else { + return FRGRND; + } + }) + .style("stroke", STROKE) + .style("stroke-width", 1) + .each(function(d) { + self.current = d; + return d; + }); // Animate filling the pie chart - animate = function(data) { - var piechart = vis.selectAll(".arc") + var animate = function(data) { + vis.selectAll(".arc") .data(pie(data)) .enter() - .append("path") - .attr("class","arc") - .attr("d", arc) - .style("fill", self.bkgrnd) - .style("stroke", "#CCCCCC") - .style("stroke-width", function(d) { - if (self.data[0].percentage >= 100) { - return 0; - } else { - return 1; - } - }) - .each(function(d) { - self.current = d; - return d; - }) + .append("path") + .attr("class","arc") + .attr("d", arc) + .style("fill", BKGRND) + .style("stroke", STROKE) + .style("stroke-width", function() { + if (self.data[0].percentage >= 100) { + return 0; + } else { + return 1; + } + }) + .each(function(d) { + self.current = d; + return d; + }) .transition() - .duration(500) - .attrTween("d", function(a) { - var tween = d3.interpolate(self.current, a); - self.current = tween(0); - return function(t) { return arc(tween(t)); }; - }); + .duration(500) + .attrTween("d", function(a) { + var tween = d3.interpolate(self.current, a); + self.current = tween(0); + return function(t) { return arc(tween(t)); }; + }); }; animate(self.data); } }; + +horizon.d3_pie_chart_distribution = { + colors: d3.scale.category20(), + + init: function() { + var self = this; + var pie_chart_data = $(".d3_pie_chart_distribution"); + self.chart = d3.selectAll(".d3_pie_chart_distribution"); + + for (var i = 0; i < pie_chart_data.length; i++) { + var parts = $(pie_chart_data[i]).data("used").split("|"); + self.data = []; + self.keys = []; + for (var j = 0; j < parts.length; j++) { + var key_value = parts[j].split("="); + var d = {}; + d["key"] = key_value[0]; + d["value"] = key_value[1]; + self.data.push(d); + self.keys.push(key_value[0]); + } + self.pieChart(i); + } + }, + // Draw a pie chart + pieChart: function(i) { + var self = this; + var vis = create_vis(self.chart[0][i]); + var arc = create_arc(); + var pie = create_pie("value"); + + var total = 0; + for (var j = 0; j < self.data.length; j++) { + total = total + parseInt(self.data[j]["value"]); + } + + // Draw an empty pie chart + vis.selectAll(".arc") + .data(pie([])) + .enter() + .append("path") + .attr("class","arc") + .attr("d", arc) + .style("stroke", STROKE) + .style("stroke-width", 1); + + // Animate filling the pie chart + var animate = function(data) { + vis.selectAll(".arc") + .data(pie(data)) + .enter() + .append("path") + .attr("class","arc") + .attr("d", arc) + .style("fill", function(d) { return self.colors(d.data.key); }) + .style("stroke", STROKE) + .style("stroke-width", 1) + .transition() + .duration(500) + .attrTween("d", function(start) { + start.endAngle = start.startAngle; + var end = jQuery.extend({}, start); + end.endAngle = end.startAngle + 2 * Math.PI / total * end.value; + var tween = d3.interpolate(start, end); + return function(t) { return arc(tween(t)); }; + }); + }; + + animate(self.data); + + // Add a legend + var legend = d3.select(self.chart[0][i]) + .append("svg") + .attr("class", "legend") + .attr("width", WIDTH * 2) + .attr("height", self.data.length * 18 + 20) + .selectAll("g") + .data(self.keys) + .enter() + .append("g") + .attr("transform", function(d, i) { + return "translate(0," + i * 20 + ")"; + }); + + legend.append("rect") + .attr("width", 18) + .attr("height", 18) + .style("fill", self.colors); + + legend.append("text") + .attr("x", 24) + .attr("y", 9) + .attr("dy", ".35em") + .text(function(d) { + var value = 0; + for (var j = 0; j < self.data.length; j++) { + if (self.data[j]["key"] == d) { + value = self.data[j]["value"]; + break; + } + } + return d + " " + Math.round(value/total * 100) + "%"; + }); + } +}; + + horizon.addInitFunction(function () { - horizon.d3_pie_chart.init(); + horizon.d3_pie_chart_usage.init(); +}); + + +horizon.addInitFunction(function () { + horizon.d3_pie_chart_distribution.init(); }); diff --git a/horizon/templates/horizon/common/_limit_summary.html b/horizon/templates/horizon/common/_limit_summary.html index d3fb25882e..743694ef16 100644 --- a/horizon/templates/horizon/common/_limit_summary.html +++ b/horizon/templates/horizon/common/_limit_summary.html @@ -3,49 +3,49 @@

{% trans "Limit Summary" %}

-
+
{% trans "Instances" %}
{% blocktrans with used=usage.limits.totalInstancesUsed|intcomma available=usage.limits.maxTotalInstances|quotainf|intcomma %}Used {{ used }} of {{ available }} {% endblocktrans %}
-
+
{% trans "VCPUs" %}
{% blocktrans with used=usage.limits.totalCoresUsed|intcomma available=usage.limits.maxTotalCores|quotainf|intcomma %}Used {{ used }} of {{ available }} {% endblocktrans %}
-
+
{% trans "RAM" %}
{% blocktrans with used=usage.limits.totalRAMUsed|mb_float_format available=usage.limits.maxTotalRAMSize|quotainf|mb_float_format %}Used {{ used }} of {{ available }} {% endblocktrans %}
-
+
{% trans "Floating IPs" %}
{% blocktrans with used=usage.limits.totalFloatingIpsUsed|intcomma available=usage.limits.maxTotalFloatingIps|quotainf|intcomma %}Used {{ used }} of {{ available }} {% endblocktrans %}
-
+
{% trans "Security Groups" %}
{% blocktrans with used=usage.limits.totalSecurityGroupsUsed|intcomma available=usage.limits.maxSecurityGroups|quotainf|intcomma%}Used {{ used }} of {{ available }} {% endblocktrans %}
{% if usage.limits.totalVolumesUsed >= 0 %}
-
+
{% trans "Volumes" %}
{% blocktrans with used=usage.limits.totalVolumesUsed|intcomma available=usage.limits.maxTotalVolumes|quotainf|intcomma %}Used {{ used }} of {{ available }} {% endblocktrans %}
-
+
{% trans "Volume Storage" %}
{% blocktrans with used=usage.limits.totalGigabytesUsed|diskgbformat available=usage.limits.maxTotalVolumeGigabytes|quotainf|diskgbformat %}Used {{ used }} of {{ available }} {% endblocktrans %}
diff --git a/openstack_dashboard/dashboards/admin/hypervisors/templates/hypervisors/index.html b/openstack_dashboard/dashboards/admin/hypervisors/templates/hypervisors/index.html index 49b0237ccf..e590462b8f 100644 --- a/openstack_dashboard/dashboards/admin/hypervisors/templates/hypervisors/index.html +++ b/openstack_dashboard/dashboards/admin/hypervisors/templates/hypervisors/index.html @@ -11,21 +11,21 @@

{% trans "Hypervisor Summary" %}

-
+
{% trans "VCPU Usage" %}
{% blocktrans with used=stats.vcpus_used|intcomma available=stats.vcpus|intcomma %}Used {{ used }} of {{ available }} {% endblocktrans %}
-
+
{% trans "Memory Usage" %}
{% blocktrans with used=stats.memory_mb_used|mbformat available=stats.memory_mb|mbformat %}Used {{ used }} of {{ available }} {% endblocktrans %}
-
+
{% trans "Disk Usage" %}
{% blocktrans with used=stats.local_gb_used|diskgbformat available=stats.local_gb|diskgbformat %}Used {{ used }} of {{ available }} {% endblocktrans %}