Skip to content

Commit

Permalink
Add dynamic change of Y axis
Browse files Browse the repository at this point in the history
(cherry picked from commit 5bc7efab2573a508c58f7e32ee5275a5caf646e1)
  • Loading branch information
PanSpagetka committed Jan 20, 2017
1 parent d922a73 commit 114a6fb
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 17 deletions.
51 changes: 37 additions & 14 deletions app/assets/javascripts/miq_application.js
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}

Expand All @@ -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'};
Expand All @@ -1695,23 +1695,46 @@ 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);
var max = _.max(getChartColumnDataValues(data.data.columns));
var min = _.min(getChartColumnDataValues(data.data.columns));
var maxShowed = getChartFormatedValue(format, max);
var minShowed = getChartFormatedValue(format, min);
var changeFormat = true;

var tmp = validateMinMax(min, max, minShowed, maxShowed);
changeFormat = !tmp.invalid;
min = tmp.min;

if (changeFormat) {
//var o = recalculatePrecision(minShowed, maxShowed, format, min, max);
//format = o.format;
// if min and max are close, labels should be more precise
if (maxShowed - minShowed <= Math.pow(10, 1 - format.options.precision)) {
while (((maxShowed - minShowed ) * 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 ((maxShowed - minShowed) >= Math.pow(10, 2 - format.options.precision)) {
while (((maxShowed - minShowed ) * 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: recalculateChartYAxisLabels
}

var title_format = _.cloneDeep(format);
title_format.options.precision += 1;
var titleFormat = _.cloneDeep(format);
titleFormat.options.precision += 1;
data.tooltip.format.value = function (value, _ratio, _id) {
var format = ManageIQ.charts.formatters[title_format.function].c3(title_format.options);
var format = ManageIQ.charts.formatters[titleFormat.function].c3(titleFormat.options);
return format(value);
}
}
Expand Down
117 changes: 117 additions & 0 deletions app/assets/javascripts/miq_c3.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,123 @@ function load_c3_chart(data, chart_id, height) {
ManageIQ.charts.c3[chart_id] = chart;
};


function recalculateChartYAxisLabels (id) {
// hide/show chart with id
this.api.toggle(id);

var minMax = getMinMaxFromChart(this);
// if there are no valid values or there is only single value big enough, then return
/*if (!minMax || minMax[0] === minMax[1]) {
if (!minMax || minMax[1] >= 10) {
return;
}
else if (minMax[1] > 0){
minMax[0] = 0;
}
}*/

if (minMax) {
var columnsData = validateMinMax(minMax[0], minMax[1], minShowed, maxShowed);
if (columnsData.invalid) {
return;
}
minMax[0] = columnsData.min;
} else {
return;
}

var format = ManageIQ.charts.chartData.candu[this.config.bindto.split('_').pop()].xml.miq.format;
var tmpMin = getChartFormatedValueWithFormat(format, minMax[0]);
var tmpMax = getChartFormatedValueWithFormat(format, minMax[1]);
var minShowed = tmpMin[0];
var maxShowed = tmpMax[0];
var min_units = tmpMin[1];
var max_units = tmpMax[1];
if (min_units !== max_units) {
return;
}

var o = recalculatePrecision(minShowed, maxShowed, format, minMax[0], minMax[1]);
if (o.changed) {
this.config.axis_y_tick_format = o.format;
this.api.flush();
}
}

function recalculatePrecision(minShowed, maxShowed, format, min, max) {
var changed = false;
if (min == max) {
return {'changed' : changed, 'format' : ManageIQ.charts.formatters[format.function].c3(format.options)}
}
if (maxShowed - minShowed <= Math.pow(10, 1 - format.options.precision)) {
// if min and max are close, labels should be more precise
changed = true;
while (((maxShowed - minShowed ) * Math.pow(10, format.options.precision)) < 9.9) {
format.options.precision += 1;
minShowed = getChartFormatedValue(format, min);
maxShowed = getChartFormatedValue(format, max);
}
} else if ((maxShowed - minShowed) >= Math.pow(10, 2 - format.options.precision)) {
changed = true;
// if min and max are not, labels should be less precise
while (((maxShowed - minShowed ) * Math.pow(10, format.options.precision)) > 99) {
if (format.options.precision < 1) {
break;
}
format.options.precision -= 1;
minShowed = getChartFormatedValue(format, min);
maxShowed = getChartFormatedValue(format, max);
}
}
return {'changed' : changed, 'format' : ManageIQ.charts.formatters[format.function].c3(format.options)}
}

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 validateMinMax(min, max, minShowed, maxShowed) {
var invalid = false;
// if there are no valid values or there is only single values big enough, then not change formating function
if (max <= min || maxShowed <= minShowed) {
if (max < min || max > 10) {
invalid = true;
}
else if (max > 0){
min = 0;
}
}

return {'invalid' : invalid, 'min' : min };
}


c3.chart.internal.fn.categoryName = function (i) {
var config = this.config, categoryIndex = Math.ceil(i);
return i < config.axis_x_categories.length ? config.axis_x_categories[categoryIndex] : i;
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/application_controller/performance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 4 additions & 2 deletions lib/report_formatter/c3.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 114a6fb

Please sign in to comment.