From e74bdb357e0e1ba4c7cde21e3c5ab6de15549a3c Mon Sep 17 00:00:00 2001 From: PanSpagetka Date: Thu, 22 Dec 2016 13:52:02 +0100 Subject: [PATCH] Add dynamic change of Y axis (cherry picked from commit 5bc7efab2573a508c58f7e32ee5275a5caf646e1) --- app/assets/javascripts/miq_application.js | 127 ++++++++++++++++-- .../application_controller/performance.rb | 2 +- lib/report_formatter/c3.rb | 6 +- 3 files changed, 121 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/miq_application.js b/app/assets/javascripts/miq_application.js index 1612831f6d58..ca530759a192 100644 --- a/app/assets/javascripts/miq_application.js +++ b/app/assets/javascripts/miq_application.js @@ -1668,7 +1668,7 @@ function chartData(type, data, data2) { // small C&U charts have very limited height if (data.miq.flat_chart) { - var max = _.max(_.flatten(_.tail(data.data.columns).map(_.tail))); + var max = _.max(getChartColumnDataValues(data.data.columns)); data.axis.y.tick.values = [0, max]; } @@ -1681,7 +1681,7 @@ function chartData(type, data, data2) { return data.miq.category_table[x]; }; } - if(data.miq.zoomed){ + if (data.miq.zoomed){ data.size = { height: $('#lightbox-panel').height() - 200 }; data.data.names = data.miq.name_table; data.legend = { position : 'bottom'}; @@ -1695,18 +1695,45 @@ function chartData(type, data, data2) { _.isObject(data.axis.y.tick) && _.isObject(data.axis.y.tick.format) && data.axis.y.tick.format.function) { + var format = data.axis.y.tick.format; - var max = _.max(_.flatten(_.tail(data.data.columns).map(_.tail))); - var min = _.min(_.flatten(_.tail(data.data.columns).map(_.tail))); - max = ManageIQ.charts.formatters[format.function].c3(format.options)(max).split(/[^0-9\,\.]/)[0]; - min = ManageIQ.charts.formatters[format.function].c3(format.options)(min).split(/[^0-9\,\.]/)[0]; - console.log(min); - console.log(max); - if(max - min < Math.pow(10, 1 - format.options.precision)){ - format.options.precision += 1; - console.log(format); + max = _.max(getChartColumnDataValues(data.data.columns)); + var min = _.min(getChartColumnDataValues(data.data.columns)); + var max_showed = getChartFormatedValue(format, max); + var min_showed = getChartFormatedValue(format, min); + var change_format = true; + // if there are no valid values or there is only single values big enough, then not change formating function + // TODO MOVE IT TO FUNCTION + if (max <= min || max_showed <= min_showed) { + if (max < min || max > 10) { + change_format = false; + } + else if (max > 0){ + min = 0; + } + } + + if (change_format) { + // if min and max are close, labels should be more precise + if (max_showed - min_showed <= Math.pow(10, 1 - format.options.precision)) { + while (((max_showed - min_showed ) * Math.pow(10, format.options.precision)) < 9.9) { + format.options.precision += 1; + } + } + // if min and max are not close, labels should be less precise + else if ((max_showed - min_showed) >= Math.pow(10, 2 - format.options.precision)) { + while (((max_showed - min_showed ) * Math.pow(10, format.options.precision)) > 99) { + if (format.options.precision < 1) { + break; + } + format.options.precision -= 1; + } + } } data.axis.y.tick.format = ManageIQ.charts.formatters[format.function].c3(format.options); + data.legend.item = { + onclick: recalculateChartYLabels + } var title_format = _.cloneDeep(format); title_format.options.precision += 1; @@ -1737,6 +1764,84 @@ $(function () { $().setupVerticalNavigation(true); }); +function getMinMaxFromChart(chart) { + var data = []; + _.forEach(chart.api.data.shown(), function(o) { + _.forEach(o.values, function(elem) { + data.push(elem.value); + }); + }); + + var max = _.max(_.filter(data, function(o) { return o !== null; })); + var min = _.min(_.filter(data, function(o) { return o !== null; })); + if (max == -Infinity || min == Infinity) { + return false; + } + return [min, max]; +} + +function getChartColumnDataValues(columns) { + return _.filter(_.flatten(_.tail(columns).map(_.tail)), function(o) { return o !== null; }) +} + +function getChartFormatedValue(format, value) { + return numeral(ManageIQ.charts.formatters[format.function].c3(format.options)(value).split(/[^0-9\,\.]/)[0]).value(); +} + +function getChartFormatedValueWithFormat(format, value) { + var tmp = /^([0-9\,\.]+)(.*)/.exec(ManageIQ.charts.formatters[format.function].c3(format.options)(value)); + return [numeral(tmp[1]).value(), tmp[2]]; +} + + + + +function recalculateChartYLabels (id) { + this.api.toggle(id); + var format = ManageIQ.charts.chartData.candu[this.config.bindto.split('_').pop()].xml.miq.format; + var minMax = getMinMaxFromChart(this); + // if there are no valid values or there is only single values big enough, then return + if (!minMax || minMax[0] == minMax[1]) { + if (!minMax || minMax[1] >= 10) { + return; + } + else if (minMax[1] > 0){ + minMax[0] = 0; + } + } + + var tmp = getChartFormatedValueWithFormat(format, minMax[0]); + var tmp2 = getChartFormatedValueWithFormat(format, minMax[1]); + var min_showed = tmp[0]; + var max_showed = tmp2[0]; + var min_units = tmp[1]; + var max_units = tmp2[1]; + if (min_units !== max_units){ + return; + } + // if min and max are close, labels should be more precise + if (max_showed - min_showed <= Math.pow(10, 1 - format.options.precision)) { + while (((max_showed - min_showed ) * Math.pow(10, format.options.precision)) < 9.9) { + format.options.precision += 1; + min_showed = getChartFormatedValue(format, minMax[0]); + max_showed = getChartFormatedValue(format, minMax[1]); + } + this.config.axis_y_tick_format = ManageIQ.charts.formatters[format.function].c3(format.options); + this.api.flush(); + } + // if min and max are not, labels should be less precise + else if ((max_showed - min_showed) >= Math.pow(10, 2 - format.options.precision)) { + while (((max_showed - min_showed ) * Math.pow(10, format.options.precision)) > 99) { + if(format.options.precision < 1){ + break; + } + format.options.precision -= 1; + } + this.config.axis_y_tick_format = ManageIQ.charts.formatters[format.function].c3(format.options); + this.api.flush(); + } +} + function miqScrollToSelected(div_name) { var rowpos = $('tr.selected').position(); if (rowpos) { diff --git a/app/controllers/application_controller/performance.rb b/app/controllers/application_controller/performance.rb index 14402ba53458..44a93c8d9e82 100644 --- a/app/controllers/application_controller/performance.rb +++ b/app/controllers/application_controller/performance.rb @@ -859,7 +859,7 @@ def prepare_perf_tag_chart(chart, rpt, cat_desc) # Grab the first (and should be only) chart column col = chart[:columns].first # Create the new chart columns for each tag - chart[:columns] = rpt.extras[:group_by_tags].collect { |t| col + "_" + t } + chart[:columns] ||= rpt.extras[:group_by_tags].collect { |t| col + "_" + t } end def gen_perf_chart(chart, rpt, idx, zoom_action) diff --git a/lib/report_formatter/c3.rb b/lib/report_formatter/c3.rb index 088575041ca9..d661220c85ad 100644 --- a/lib/report_formatter/c3.rb +++ b/lib/report_formatter/c3.rb @@ -60,7 +60,8 @@ def build_document_header :data => {:columns => [], :names => {}}, :axis => {:x => {:tick => {}}, :y => {:tick => {}}}, :tooltip => {:format => {}}, - :miq => {:name_table => {}, :category_table => {}} + :miq => {:name_table => {}, :category_table => {}}, + :legend => {} } if chart_is_2d? @@ -95,6 +96,7 @@ def build_document_header axis_formatter = {:function => format, :options => options} mri.chart[:axis][:y] = {:tick => {:format => axis_formatter}} + mri.chart[:miq][:format] = axis_formatter end end @@ -142,7 +144,7 @@ def change_structure_to_timeseries # set x axis type to timeseries and remove categories mri.chart[:axis][:x] = {:type => 'timeseries', :tick => {}} # set flag for performance chart - mri.chart[:miq] = {:performance_chart => true} + mri.chart[:miq][:performance_chart] = true # this conditions are taken from build_performance_chart_area method from chart_commons.rb if mri.db.include?("Daily") || (mri.where_clause && mri.where_clause.include?("daily")) # set format for parsing