summaryrefslogtreecommitdiff
path: root/openstack_dashboard/dashboards/infrastructure/static/infrastructure/js/horizon.d3circleschart.js
diff options
context:
space:
mode:
Diffstat (limited to 'openstack_dashboard/dashboards/infrastructure/static/infrastructure/js/horizon.d3circleschart.js')
-rw-r--r--openstack_dashboard/dashboards/infrastructure/static/infrastructure/js/horizon.d3circleschart.js279
1 files changed, 279 insertions, 0 deletions
diff --git a/openstack_dashboard/dashboards/infrastructure/static/infrastructure/js/horizon.d3circleschart.js b/openstack_dashboard/dashboards/infrastructure/static/infrastructure/js/horizon.d3circleschart.js
new file mode 100644
index 00000000..305b2182
--- /dev/null
+++ b/openstack_dashboard/dashboards/infrastructure/static/infrastructure/js/horizon.d3circleschart.js
@@ -0,0 +1,279 @@
+/*
+ Draw circles chart in d3.
+
+ To use, a div is required with the data attributes
+ data-chart-type="circles_chart", data-url and data-size in the
+ div.
+
+ data-chart-type - must be "circles_chart" so chart gets initialized
+ data-url - (string) url for the json data for the chart
+ data-time - (string) time parameter, gets appended to url as time=...
+ data-size - (integer) size of the circles in pixels
+
+ If used in popup, initialization must be made manually e.g.:
+ addHorizonLoadEvent(function() {
+ horizon.d3_circles_chart.init('.html_element');
+ horizon.d3_circles_chart.init('.health_chart');
+ });
+
+
+ Example:
+ <div class="html_element"
+ data-chart-type="circles_chart"
+ data-url="/infrastructure/racks/1/top_communicating.json?cond=to"
+ data-time="now"
+ data-size="22">
+ </div>
+
+ There are controll elements for the cirles chart, implementing some commands
+ that will be executed over the chart.
+
+ 1. The selectbox for time change, implements ChangeTime command. It has to
+ have data attribute data-circles-chart-command="change_time", with defined
+ receiver as jquery selector (selector can point to more elements and it will
+ execute the command on all of them) e.g. data-receiver="#rack_health_chart"
+ Option value is then appended to url and chart is refreshed.
+
+ Example
+ <div class="span3 circles_chart_time_picker">
+ <select data-circles-chart-command="change_time"
+ data-receiver="#rack_health_chart">
+ <option value="now">Now</option>
+ <option value="yesterday">Yesterday</option>
+ <option value="last_week">Last Week</option>
+ <option value="last_month">Last Month</option>
+ </select>
+ </div>
+ <div class="clear"></div>
+
+ 2. Bootstrap tabs for switching different circle_charts implement command
+ ChangeUrl. It has to have data attribute data-circles-chart-command="change_url",
+ with defined receiver as jquery selector (selector can point to more elements and
+ it will execute the command on all of them) e.g. data-receiver="#rack_health_chart"
+
+ Inner li a element has to have attribute data-url, e.g.
+ data-url="/infrastructure/racks/1/top_communicating.json?type=alerts"
+
+ The url of the chart is then switched and chart is refreshed.
+
+ <ul class="nav nav-tabs"
+ data-circles-chart-command="change_url"
+ data-receiver="#rack_health_chart">
+ <li class="active">
+ <a data-url="/infrastructure/racks/1/top_communicating.json?type=overall_health" href="#">
+ Overall Health</a>
+ </li>
+ <li>
+ <a data-url="/infrastructure/racks/1/top_communicating.json?type=alerts" href="#">
+ Alerts</a>
+ </li>
+ <li>
+ <a data-url="/infrastructure/racks/1/top_communicating.json?type=capacities" href="#">
+ Capacities</a>
+ </li>
+ <li>
+ <a data-url="/infrastructure/racks/1/top_communicating.json?type=status" href="#">
+ Status</a>
+ </li>
+ </ul>
+*/
+
+
+horizon.d3_circles_chart = {
+ CirclesChart: function(chart_class, html_element){
+ this.chart_class = chart_class;
+ this.html_element = html_element;
+
+ var jquery_element = $(html_element);
+ this.size = jquery_element.data('size');
+ this.time = jquery_element.data('time');
+ this.url = jquery_element.data('url');
+
+ this.final_url = this.url;
+ if (this.final_url.indexOf('?') > -1){
+ this.final_url += '&time=' + this.time;
+ }else{
+ this.final_url += '?time=' + this.time;
+ }
+
+ this.time = jquery_element.data('time');
+ this.data = []
+
+ this.refresh = refresh;
+ function refresh(){
+ var self = this;
+ this.jqxhr = $.getJSON( this.final_url, function() {
+ //FIXME add loader in the target element
+ })
+ .done(function(data) {
+ // FIXME find a way how to only update graph with new data
+ // not delete and create
+ $(self.html_element).html("");
+
+ self.data = data.data;
+ self.settings = data.settings;
+ self.chart_class.render(self.html_element, self.size, self.data, self.settings);
+ })
+ .fail(function() {
+ // FIXME add proper fail message
+ console.log( "error" ); })
+ .always(function() {
+ // FIXME add behaviour that should be always done
+ });
+ }
+ },
+ init: function(selector, settings) {
+ var self = this;
+ $(selector).each(function() {
+ self.refresh(this);
+ });
+ self.bind_commands();
+ },
+ refresh: function(html_element){
+ var chart = new this.CirclesChart(this, html_element)
+ // FIXME save chart objects somewhere so I can use them again when
+ // e.g. I am swithing tabs, or if I want to update them
+ // via web sockets
+ // this.charts.add_or_update(chart)
+ chart.refresh();
+ },
+ render: function(html_element, size, data, settings){
+ var self = this;
+ // FIXME rewrite to scatter plot once we have some cool D3 chart
+ // library
+ var width = size + 4,
+ height = size + 4,
+ round = size / 2;
+ center_x = width / 2,
+ center_y = height / 2;
+
+ var svg = d3.select(html_element).selectAll("svg")
+ .data(data)
+ .enter().append("svg")
+ .attr("width", width)
+ .attr("height", height);
+
+ // FIXME use some pretty tooltip from some library we will use
+ // this one is just temporary
+ var tooltip = d3.select(html_element).append("div")
+ .style("position", "absolute")
+ .style("z-index", "10")
+ .style("visibility", "hidden")
+ .style("min-width", "100px")
+ .style("max-width", "110px")
+ .style("min-height", "30px")
+ .style("border", "1px ridge grey")
+ .style("background-color", "white")
+ .text(function(d) { "a simple tooltip"; });
+
+ var circle = svg.append("circle")
+ .attr("r", round)//function(d) { return d.r; })// can be sent form server
+ .attr("cx", center_x)
+ .attr("cy", center_y)
+ .attr("stroke", "#cecece")
+ .attr("stroke-width", function(d) {
+ return 1;
+ })
+ .style("fill", function(d) {
+ if (d.color){
+ return d.color;
+ } else if (settings.scale == "linear_color_scale"){
+ return self.linear_color_scale(d.percentage, settings.domain, settings.range)
+
+ }
+ })
+ .on("mouseover", function(d){
+ if (d.tooltip) {
+ tooltip.html(d.tooltip);
+ } else {
+ tooltip.html(d.name + "<br/>" + d.status);
+ }
+ tooltip.style("visibility", "visible");})
+ .on("mousemove", function(d){tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
+ .on("mouseout", function(d){tooltip.style("visibility", "hidden");});
+ ;
+
+ /*
+ // or just d3 title element
+ circle.append("svg:title")
+ .text(function(d) { return d.x; });
+
+ */
+ },
+ linear_color_scale: function(percentage, domain, range){
+ usage_color = d3.scale.linear()
+ .domain(domain)
+ .range(range);
+ return usage_color(percentage);
+ },
+ bind_commands: function (){
+ var change_time_command_selector = 'select[data-circles-chart-command="change_time"]';
+ var change_url_command_selector = '[data-circles-chart-command="change_url"]';
+ var self = this;
+ bind_change_time = function(){
+ $(change_time_command_selector).each(function() {
+ $(this).change(function(){
+ var invoker = $(this);
+ var command = new self.Command.ChangeTime(self, invoker);
+ command.execute();
+ });
+ });
+ }
+ bind_change_url = function(){
+ $(change_url_command_selector + ' a').click(function (e) {
+ // Bootstrap tabs functionality
+ e.preventDefault();
+ $(this).tab('show');
+
+ // Command for url change and refresh
+ var invoker = $(this);
+ var command = new self.Command.ChangeUrl(self, invoker);
+ command.execute();
+ })
+ }
+ bind_change_time();
+ bind_change_url();
+ },
+ Command: {
+ ChangeTime: function (chart_class, invoker){
+ // Invoker of the command should know about it's receiver.
+ // Also invoker brings all parameters of the command.
+ this.receiver_selector = invoker.data('receiver');
+ this.new_time = invoker.find("option:selected").val();
+
+ this.execute = execute;
+ function execute(){
+ var self = this;
+ $(this.receiver_selector).each(function(){
+ // change time of the chart
+ $(this).data('time', self.new_time);
+ // refresh the chart
+ chart_class.refresh(this)
+ });
+ }
+ },
+ ChangeUrl: function (chart_class, invoker, new_url){
+ // Invoker of the command should know about it's receiver.
+ // Also invoker brings all parameters of the command.
+ this.receiver_selector = invoker.parents('ul').first().data('receiver');
+ this.new_url = invoker.data('url');
+
+ this.execute = execute;
+ function execute(){
+ var self = this;
+ $(this.receiver_selector).each(function(){
+ // change time of the chart
+ $(this).data('url', self.new_url);
+ // refresh the chart
+ chart_class.refresh(this)
+ });
+ }
+ }
+ }
+}
+
+/* init the graphs */
+horizon.addInitFunction(function () {
+ horizon.d3_circles_chart.init('div[data-chart-type="circles_chart"]');
+});
+