From 41b96636a2319527a148808f55a06d15868f12fd Mon Sep 17 00:00:00 2001 From: Imre Farkas Date: Mon, 22 Jul 2013 11:47:58 +0200 Subject: Unified line chart Change-Id: I815530116853ae6968263077ad7cd4629b7ff7dd --- horizon/static/horizon/js/horizon.d3linechart.js | 225 +++++++++++++++------ .../static/horizon/js/horizon.d3modallinechart.js | 132 ------------ .../horizon/client_side/_modal_chart.html | 2 +- openstack_dashboard/api/tuskar.py | 5 +- .../resource_management/racks/views.py | 10 +- .../flavors/_detail_overview.html | 25 +-- .../nodes/_detail_overview.html | 8 +- .../racks/_detail_overview.html | 2 +- .../resource_classes/_detail_overview.html | 25 +-- 9 files changed, 196 insertions(+), 238 deletions(-) delete mode 100644 horizon/static/horizon/js/horizon.d3modallinechart.js diff --git a/horizon/static/horizon/js/horizon.d3linechart.js b/horizon/static/horizon/js/horizon.d3linechart.js index d21a185d..ebe1ba9e 100644 --- a/horizon/static/horizon/js/horizon.d3linechart.js +++ b/horizon/static/horizon/js/horizon.d3linechart.js @@ -1,62 +1,129 @@ /* - Draw a non-modal line chart in d3. + Draw line chart in d3. + + It support 2 types of usage: + * as a standard line chart + * as a line chart in a modal window + + To use as a standard line chart the following data attributes need to be + provided for a div: + data-chart-type - must be "line_chart" + data-url - (string) url for the json data for the chart + data-series - (string) the list of series separated by comma + + Example: +
+
+ + To use as a line chart in a modal windows the following data attributes + need to be provided for a link: + data-chart-type - must be "modal_line_chart" + data-url - (string) url for the json data for the chart + data-series - (string) the list of series separated by comma Example: -
+ + Click me! + */ horizon.d3_line_chart = { - line_charts: [], init: function() { - this.line_charts = $('div[data-line-url]'); + var self = this; + + self.init_line_charts(); + self.init_modal_chart_links(); + }, - this._initialCreation(this.line_charts); + init_line_charts: function() { + var self = this; + + line_charts = $("div[data-chart-type='line_chart']"); + $.each(line_charts, function(index, line_chart) { + if($(line_chart).data('modal') != true) { + var template = horizon.templates.compiled_templates["#modal_chart_template"]; + self.init_svg(line_chart); + self.draw(self.data(line_chart)); + } + }); }, - draw: function(element, url) { + init_modal_chart_links: function() { var self = this; - var margin = {top: 20, right: 80, bottom: 30, left: 50}; - var width = 1000 - margin.left - margin.right; - var height = 400 - margin.top - margin.bottom; + $(document).on('click', "a[data-chart-type='modal_line_chart']", function(event) { + event.preventDefault(); + + var template = horizon.templates.compiled_templates["#modal_chart_template"]; + $('#modal_wrapper').append(template.render({classes: "modal"})); - var svg = d3.select("#"+element) - .append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + var modal = $('.modal:last'); + modal.modal(); - var x = d3.time.scale().range([0, width]); - var y = d3.scale.linear().range([height, 0]); + $(modal).on('click', 'ul#interval_selector li a', function(event){ + event.preventDefault(); - var xAxis = d3.svg.axis() - .scale(x) - .orient("bottom"); - var yAxis = d3.svg.axis() - .scale(y) - .orient("left"); + self.url_options.interval = $(event.target).data('interval'); + self.draw(self.url_options); + $("ul#interval_selector li").removeClass("active"); + $(event.target).parent().addClass("active"); + }) - var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%L").parse; + self.init_svg("#modal_chart"); + self.url_options = self.data($(event.target)) + self.draw(self.url_options) + }); + }, - var line = d3.svg.line().interpolate("linear") - .x(function(d) { return x(d.date); }) - .y(function(d) { return y(d.value); }); + init_svg: function(chart_div) { + var self = this; - var color = d3.scale.category10(); + self.margin = {top: 20, right: 80, bottom: 30, left: 50}; + self.width = 700 - self.margin.left - self.margin.right; + self.height = 400 - self.margin.top - self.margin.bottom; - d3.json(url, function(error, data) { - data.forEach(function(d) { - d.date = parseDate(d.date); - }); + self.svg = d3.select(chart_div) + .append("svg") + .attr("width", self.width + self.margin.left + self.margin.right) + .attr("height", self.height + self.margin.top + self.margin.bottom) + .append("g") + .attr("transform", "translate(" + self.margin.left + "," + self.margin.top + ")"); - color.domain(d3.keys(data[0]).filter(function(key) { return key !== 'date'; })); + self.x = d3.time.scale().range([0, self.width]); + self.y = d3.scale.linear().range([self.height, 0]); - var usage_values = color.domain().map(function(name) { + self.xAxis = d3.svg.axis() + .scale(self.x) + .orient("bottom").ticks(6); + self.yAxis = d3.svg.axis() + .scale(self.y) + .orient("left"); + + self.parse_date = d3.time.format("%Y-%m-%dT%H:%M:%S.%L").parse; + + self.line = d3.svg.line().interpolate("linear") + .x(function(d) { return self.x(d.date); }) + .y(function(d) { return self.y(d.value); }); + + self.color = d3.scale.category10(); + }, + + draw: function(url_options) { + var self = this; + var url_options = url_options || {}; + url_options.interval = url_options.interval || "1w"; + + d3.json(self.json_url(url_options), function(error, data) { + data.forEach(function(d) { d.date = self.parse_date(d.date); }); + + self.color.domain(d3.keys(data[0]).filter(function(key) { return key !== 'date'; })); + + var usage_values = self.color.domain().map(function(name) { return { name: name, values: data.map(function(d) { @@ -65,41 +132,69 @@ horizon.d3_line_chart = { }; }); - x.domain(d3.extent(data, function(d) { return d.date; })); - y.domain([ - d3.min(usage_values, function(u) { return d3.min(u.values, function(v) { return v.value; }) - 1; }), - d3.max(usage_values, function(u) { return d3.max(u.values, function(v) { return v.value; }) + 6; }) - ]); + self.svg.selectAll(".axis").remove(); + self.x.domain(d3.extent(data, function(d) { return d.date; })); + self.y.domain([0, 15]); + + self.svg.append("g") + .attr("transform", "translate(0," + self.height + ")") + .attr("class", "axis") + .call(self.xAxis); + self.svg.append("g") + .attr("class", "axis") + .call(self.yAxis) - svg.append("g") - .attr("transform", "translate(0," + height + ")") - .attr("class", "axis") - .call(xAxis); - svg.append("g") - .attr("class", "axis") - .call(yAxis) + var usages = self.svg.selectAll(".usage") + .data(usage_values, function(d) { return self.key(d) }); - var usage = svg.selectAll(".usage") - .data(usage_values) - .enter().append("g"); + var usage = usages.enter().append("g") + .attr("class", "usage"); usage.append("path") - .attr("d", function(d) { return line(d.values); }) - .style("stroke", function(d) { return color(d.name); }) - .style("fill", "none") - .style("stroke-width", 3); + .attr("d", function(d) { return self.line(d.values); }) + .style("stroke", function(d) { return self.color(d.name); }) + .style("fill", "none") + .style("stroke-width", 3); + + var legend = usage.append('g') + .attr('class', 'legend'); + + legend.append('rect') + .attr('x', self.width - 60) + .attr('y', function(d, i){ return (i * 20) + 30 ;}) + .attr('width', 10) + .attr('height', 10) + .style('fill', function(d) { return self.color(d.name); }); + + legend.append('text') + .attr('x', self.width - 40) + .attr('y', function(d, i){ return (i * 20) + 39;}) + .text(function(d){ return d.name.replace(/_/g, " "); }); + + usages.exit().remove(); }); }, - // Draw the initial d3 bars - _initialCreation: function(charts) { - var scope = this; - $(charts).each(function(index, element) { - var chart_element = $(element); + data: function(element) { + return { + url: $(element).data("url"), + series: $(element).data("series") + }; + }, + + json_url: function(url_options) { + var options = $.extend({}, url_options); + var url = options.url + delete options.url + return url + '?' + $.param(options); + }, - var chart_url = chart_element.attr('data-line-url'); + key: function(data){ + return data.name + data.values.length + data.values[0].date + data.values[data.values.length-1].date + }, - scope.draw($(element).attr('id'), chart_url); - }); - } }; + +horizon.addInitFunction(function () { + horizon.d3_line_chart.init(); +}); diff --git a/horizon/static/horizon/js/horizon.d3modallinechart.js b/horizon/static/horizon/js/horizon.d3modallinechart.js deleted file mode 100644 index a4015f51..00000000 --- a/horizon/static/horizon/js/horizon.d3modallinechart.js +++ /dev/null @@ -1,132 +0,0 @@ -/* - Draw line chart in d3. - - To use, a link is required with the class .modal_chart - - Example: - Click me! -*/ - -horizon.d3_modal_line_chart = { - - init: function() { - var self = this; - - $(document).on('click', '.modal_chart', function (evt) { - evt.preventDefault(); - var $this = $(this); - - var template = horizon.templates.compiled_templates["#modal_chart_template"]; - $('#modal_wrapper').append(template.render()); - - var modal = $('.modal:last'); - modal.modal(); - - $(modal).on('click', 'ul#interval_selector li a', function(event){ - event.preventDefault(); - - interval = $(event.target).data("interval"); - self.draw('/infrastructure/resource_management/racks/usage_data', {interval: interval}); - - $("ul#interval_selector li").removeClass("active"); - $(event.target).parent().addClass("active"); - }) - - self.init_svg(); - self.draw('/infrastructure/resource_management/racks/usage_data') - }); - }, - - init_svg: function() { - var self = this; - - self.margin = {top: 20, right: 80, bottom: 30, left: 50}; - self.width = 700 - self.margin.left - self.margin.right; - self.height = 400 - self.margin.top - self.margin.bottom; - - self.svg = d3.select("#modal_chart") - .append("svg") - .attr("width", self.width + self.margin.left + self.margin.right) - .attr("height", self.height + self.margin.top + self.margin.bottom) - .append("g") - .attr("transform", "translate(" + self.margin.left + "," + self.margin.top + ")"); - - self.x = d3.time.scale().range([0, self.width]); - self.y = d3.scale.linear().range([self.height, 0]); - - self.xAxis = d3.svg.axis() - .scale(self.x) - .orient("bottom").ticks(6); - self.yAxis = d3.svg.axis() - .scale(self.y) - .orient("left"); - - self.parse_date = d3.time.format("%Y-%m-%dT%H:%M:%S.%L").parse; - - self.line = d3.svg.line().interpolate("linear") - .x(function(d) { return self.x(d.date); }) - .y(function(d) { return self.y(d.value); }); - - self.color = d3.scale.category10(); - }, - - draw: function(url, url_options) { - var self = this; - var url_options = url_options || {}; - url_options.interval = url_options.interval || "1w"; - - d3.json(self.data_url(url, url_options), function(error, data) { - data.forEach(function(d) { d.date = self.parse_date(d.date); }); - - self.color.domain(d3.keys(data[0]).filter(function(key) { return key !== 'date'; })); - - var usage_values = self.color.domain().map(function(name) { - return { - name: name, - values: data.map(function(d) { - return {date: d.date, value: d[name]}; - }) - }; - }); - - self.svg.selectAll(".axis").remove(); - self.x.domain(d3.extent(data, function(d) { return d.date; })); - self.y.domain([0, 15]); - - self.svg.append("g") - .attr("transform", "translate(0," + self.height + ")") - .attr("class", "axis") - .call(self.xAxis); - self.svg.append("g") - .attr("class", "axis") - .call(self.yAxis) - - var usages = self.svg.selectAll(".usage") - .data(usage_values, function(d) { return self.key(d) }); - - var usage = usages.enter().append("g") - .attr("class", "usage"); - - usage.append("path") - .attr("d", function(d) { return self.line(d.values); }) - .style("stroke", function(d) { return self.color(d.name); }) - .style("fill", "none") - .style("stroke-width", 3); - - usages.exit().remove(); - }); - }, - - data_url: function(url, options) { - return url + '?' + $.param(options); - }, - - key: function(data){ - return data.name + data.values.length + data.values[0].date + data.values[data.values.length-1].date - }, - -}; - -horizon.addInitFunction(function () { - horizon.d3_modal_line_chart.init(); -}); diff --git a/horizon/templates/horizon/client_side/_modal_chart.html b/horizon/templates/horizon/client_side/_modal_chart.html index 53b9fb4c..e26a7d4d 100644 --- a/horizon/templates/horizon/client_side/_modal_chart.html +++ b/horizon/templates/horizon/client_side/_modal_chart.html @@ -5,7 +5,7 @@ {% block template %} {% jstemplate %} - - {{ flavor.ram.usage }}/{{ flavor.ram.value }} {{ flavor.ram.unit }} + {{ flavor.ram.usage }}/{{ flavor.ram.value }} {{ flavor.ram.unit }} @@ -79,7 +79,7 @@
- {{ flavor.root_disk.usage }}/{{ flavor.root_disk.value }} {{ flavor.root_disk.unit }} + {{ flavor.root_disk.usage }}/{{ flavor.root_disk.value }} {{ flavor.root_disk.unit }} @@ -93,7 +93,7 @@ - {{ flavor.ephemeral_disk.usage }}/{{ flavor.ephemeral_disk.value }} {{ flavor.ephemeral_disk.unit }} + {{ flavor.ephemeral_disk.usage }}/{{ flavor.ephemeral_disk.value }} {{ flavor.ephemeral_disk.unit }} @@ -107,7 +107,7 @@ - {{ flavor.swap_disk.usage }}/{{ flavor.swap_disk.value }} {{ flavor.swap_disk.unit }} + {{ flavor.swap_disk.usage }}/{{ flavor.swap_disk.value }} {{ flavor.swap_disk.unit }} @@ -121,22 +121,9 @@
-
-
+
- - diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html b/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html index 2f8e8a3a..f1acd571 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html @@ -51,7 +51,7 @@ - {{ node.cpu.usage }}/{{ node.cpu.value }} {{ node.cpu.unit }} + {{ node.cpu.usage }}/{{ node.cpu.value }} {{ node.cpu.unit }} @@ -65,7 +65,7 @@ - {{ node.ram.usage }}/{{ node.ram.value }} {{ node.ram.unit }} + {{ node.ram.usage }}/{{ node.ram.value }} {{ node.ram.unit }} @@ -79,7 +79,7 @@ - {{ node.storage.usage }}/{{ node.storage.value }} {{ node.storage.unit }} + {{ node.storage.usage }}/{{ node.storage.value }} {{ node.storage.unit }} @@ -93,7 +93,7 @@ - {{ node.network.usage }}/{{ node.network.value }} {{ node.network.unit }} + {{ node.network.usage }}/{{ node.network.value }} {{ node.network.unit }} diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/racks/_detail_overview.html b/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/racks/_detail_overview.html index 0d093052..81facdc3 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/racks/_detail_overview.html +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/racks/_detail_overview.html @@ -44,7 +44,7 @@ - {{ capacity.usage|default:_(" - ") }}/{{ capacity.value|default:_(" - ") }} {{ capacity.unit }} + {{ capacity.usage|default:_(" - ") }}/{{ capacity.value|default:_(" - ") }} {{ capacity.unit }} {% endfor %} diff --git a/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_overview.html b/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_overview.html index 7a0db04d..618a05cc 100644 --- a/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_overview.html +++ b/openstack_dashboard/dashboards/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_overview.html @@ -42,7 +42,7 @@ - {{ resource_class.cpu.usage }}/{{ resource_class.cpu.value }} {{ resource_class.cpu.unit }} + {{ resource_class.cpu.usage }}/{{ resource_class.cpu.value }} {{ resource_class.cpu.unit }} @@ -56,7 +56,7 @@ - {{ resource_class.ram.usage }}/{{ resource_class.ram.value }} {{ resource_class.ram.unit }} + {{ resource_class.ram.usage }}/{{ resource_class.ram.value }} {{ resource_class.ram.unit }} @@ -70,7 +70,7 @@ - {{ resource_class.storage.usage }}/{{ resource_class.storage.value }} {{ resource_class.storage.unit }} + {{ resource_class.storage.usage }}/{{ resource_class.storage.value }} {{ resource_class.storage.unit }} @@ -84,7 +84,7 @@ - {{ resource_class.network.usage }}/{{ resource_class.network.value }} {{ resource_class.network.unit }} + {{ resource_class.network.usage }}/{{ resource_class.network.value }} {{ resource_class.network.unit }} @@ -93,14 +93,9 @@
-

{% trans "Running Virtual Machines" %}

+

{% trans "Capacity Usage" %}


-
- {% for flavor_count in resource_class.running_virtual_machines %} -
{{ flavor_count.flavor.name }}
-
{{ flavor_count.max_vms }}
- {% endfor %} -
+
@@ -117,8 +112,14 @@
-

Summary of instances and usage

+

{% trans "Summary of Instances and Usage" %}


+
+ {% for flavor_count in resource_class.running_virtual_machines %} +
{{ flavor_count.flavor.name }}
+
{{ flavor_count.max_vms }}
+ {% endfor %} +
-- cgit v1.2.1