Skip to content

Commit

Permalink
Merge pull request #3641 from stormpython/clickable-legends
Browse files Browse the repository at this point in the history
Clickable legends
  • Loading branch information
stormpython committed Jul 16, 2015
2 parents 2563f6d + 7dbba6b commit 2ce474f
Show file tree
Hide file tree
Showing 17 changed files with 257 additions and 89 deletions.
34 changes: 30 additions & 4 deletions src/kibana/components/filter_bar/filter_bar_click_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,42 @@ define(function (require) {
return function (Notifier) {
return function ($state) {
return function (event) {
// Hierarchical and tabular data set their aggConfigResult parameter
// differently because of how the point is rewritten between the two. So
// we need to check if the point.orig is set, if not use try the point.aggConfigResult
var aggConfigResult = event.point.orig && event.point.orig.aggConfigResult || event.point.aggConfigResult;
var notify = new Notifier({
location: 'Filter bar'
});
var aggConfigResult;

// Hierarchical and tabular data set their aggConfigResult parameter
// differently because of how the point is rewritten between the two. So
// we need to check if the point.orig is set, if not use try the point.aggConfigResult
if (event.point.orig) {
aggConfigResult = event.point.orig.aggConfigResult;
} else if (event.point.values) {
aggConfigResult = findAggConfig(event.point.values);
} else {
aggConfigResult = event.point.aggConfigResult;
}

function findAggConfig(values) {
if (_.isArray(values)) { // point series chart
var index = _.findIndex(values, 'aggConfigResult');
return values[index].aggConfigResult;
}
return values.aggConfigResult; // pie chart
}

function findLabel(obj) {
// TODO: find out if there is always a fieldFormatter
var formatter = obj.aggConfig.fieldFormatter();
return formatter(obj.key) === event.label;
}

if (aggConfigResult) {
var isLegendLabel = !!event.point.values;
var results = _.filter(aggConfigResult.getPath(), { type: 'bucket' });

if (isLegendLabel) results = _.filter(results, findLabel); // filter results array by legend label

var filters = _(results)
.map(function (result) {
try {
Expand Down
7 changes: 1 addition & 6 deletions src/kibana/components/vislib/components/labels/data_array.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
define(function (require) {
return function GetArrayUtilService(Private) {
var _ = require('lodash');

var flattenSeries = Private(require('components/vislib/components/labels/flatten_series'));

/*
* Accepts a Kibana data object and returns an array of values objects.
*/

return function (obj) {
if (!_.isObject(obj) || !obj.rows && !obj.columns && !obj.series) {
throw new TypeError('GetArrayUtilService expects an object with a series, rows, or columns key');
}

if (!obj.series) {
return flattenSeries(obj);
}

if (!obj.series) return flattenSeries(obj);
return obj.series;
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ define(function (require) {
* Accepts a Kibana data object with a rows or columns key
* and returns an array of flattened series values.
*/

return function (obj) {
if (!_.isObject(obj) || !obj.rows && !obj.columns) {
throw new TypeError('GetSeriesUtilService expects an object with either a rows or columns key');
Expand Down
10 changes: 4 additions & 6 deletions src/kibana/components/vislib/components/labels/labels.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ define(function (require) {

var createArr = Private(require('components/vislib/components/labels/data_array'));
var getArrOfUniqLabels = Private(require('components/vislib/components/labels/uniq_labels'));
var getPieLabels = Private(require('components/vislib/components/labels/pie/pie_labels'));

/*
* Accepts a Kibana data object and returns an array of unique labels (strings).
Expand All @@ -12,12 +13,9 @@ define(function (require) {
*
* Currently, this service is only used for vertical bar charts and line charts.
*/

return function (obj) {
if (!_.isObject(obj)) {
throw new TypeError('LabelUtil expects an object');
}

return function (obj, chartType) {
if (!_.isObject(obj)) { throw new TypeError('LabelUtil expects an object'); }
if (chartType === 'pie') { return getPieLabels(obj); }
return getArrOfUniqLabels(createArr(obj));
};
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
define(function (require) {
var _ = require('lodash');

return function GetPieNames(Private) {
var returnNames = Private(require('components/vislib/components/labels/pie/return_pie_names'));

return function (data, columns) {
var slices = data.slices;

if (slices.children) {
return _(returnNames(slices.children, 0, columns))
.sortBy(function (obj) {
return obj.index;
})
.pluck('key')
.unique()
.value();
}
};
};
});
26 changes: 26 additions & 0 deletions src/kibana/components/vislib/components/labels/pie/pie_labels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
define(function (require) {
var _ = require('lodash');

return function PieLabels(Private) {
var removeZeroSlices = Private(require('components/vislib/components/labels/pie/remove_zero_slices'));
var getNames = Private(require('components/vislib/components/labels/pie/get_pie_names'));

return function (obj) {
if (!_.isObject(obj)) { throw new TypeError('PieLabel expects an object'); }

var data = obj.columns || obj.rows || [obj];
var names = [];

data.forEach(function (obj) {
var columns = obj.raw ? obj.raw.columns : undefined;
obj.slices = removeZeroSlices(obj.slices);

getNames(obj, columns).forEach(function (name) {
names.push(name);
});
});

return _.uniq(names);
};
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
define(function (require) {
var _ = require('lodash');

return function RemoveZeroSlices() {
return function removeZeroSlices(slices) {
if (!slices.children) return slices;

slices = _.clone(slices);
slices.children = slices.children.reduce(function (children, child) {
if (child.size !== 0) { children.push(removeZeroSlices(child)); }
return children;
}, []);

return slices;
};
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
define(function () {
return function ReturnPieNames() {
return function returnNames(array, index, columns) {
var names = [];

array.forEach(function (obj) {
names.push({ key: obj.name, index: index });

if (obj.children) {
returnNames(obj.children, (index + 1), columns).forEach(function (namedObj) {
names.push(namedObj);
});
}
});

return names;
};
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ define(function (require) {
* Accepts an array of data objects and a formatter function.
* Returns a unique list of formatted labels (strings).
*/

return function (arr) {
if (!_.isArray(arr)) {
throw new TypeError('UniqLabelUtil expects an array of objects');
Expand Down
40 changes: 19 additions & 21 deletions src/kibana/components/vislib/lib/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,8 @@ define(function (require) {

this.data = data;
this.type = this.getDataType();

this.labels;

if (this.type === 'series') {
if (getLabels(data).length === 1 && getLabels(data)[0] === '') {
this.labels = [(this.get('yAxisLabel'))];
} else {
this.labels = getLabels(data);
}
} else if (this.type === 'slices') {
this.labels = this.pieNames();
}

this.labels = this._getLabels(this.data);
this.color = this.labels ? color(this.labels) : undefined;

this._normalizeOrdered();

this._attr = _.defaults(attr || {}, {
Expand All @@ -73,6 +60,15 @@ define(function (require) {
}
}

Data.prototype._getLabels = function (data) {
if (this.type === 'series') {
var noLabel = getLabels(data).length === 1 && getLabels(data)[0] === '';
if (noLabel) return [(this.get('yAxisLabel'))];
return getLabels(data);
}
return this.pieNames();
};

/**
* Returns true for positive numbers
*/
Expand Down Expand Up @@ -485,7 +481,7 @@ define(function (require) {
var self = this;

_.forEach(array, function (obj) {
names.push({ key: obj.name, index: index });
names.push({ label: obj.name, values: obj, index: index });

if (obj.children) {
var plusIndex = index + 1;
Expand Down Expand Up @@ -519,8 +515,9 @@ define(function (require) {
.sortBy(function (obj) {
return obj.index;
})
.pluck('key')
.unique()
.unique(function (d) {
return d.label;
})
.value();
}
};
Expand Down Expand Up @@ -553,9 +550,8 @@ define(function (require) {
* @method pieNames
* @returns {Array} Array of unique names (strings)
*/
Data.prototype.pieNames = function () {
Data.prototype.pieNames = function (data) {
var self = this;
var data = this.getVisData();
var names = [];

_.forEach(data, function (obj) {
Expand All @@ -567,7 +563,7 @@ define(function (require) {
});
});

return _.uniq(names);
return _.uniq(names, 'label');
};

/**
Expand Down Expand Up @@ -619,7 +615,9 @@ define(function (require) {
* @returns {Function} Performs lookup on string and returns hex color
*/
Data.prototype.getPieColorFunc = function () {
return color(this.pieNames());
return color(this.pieNames(this.getVisData()).map(function (d) {
return d.label;
}));
};

/**
Expand Down
17 changes: 9 additions & 8 deletions src/kibana/components/vislib/lib/dispatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,27 @@ define(function (require) {
*/
Dispatch.prototype.eventResponse = function (d, i) {
var datum = d._input || d;
var data = d3.event.target.nearestViewportElement.__data__;
var data = d3.event.target.nearestViewportElement ?
d3.event.target.nearestViewportElement.__data__ : d3.event.target.__data__;
var label = d.label ? d.label : d.name;
var isSeries = !!(data.series);
var isSlices = !!(data.slices);
var isSeries = !!(data && data.series);
var isSlices = !!(data && data.slices);
var series = isSeries ? data.series : undefined;
var slices = isSlices ? data.slices : undefined;
var handler = this.handler;
var color = handler.data.color;
var isPercentage = (handler._attr.mode === 'percentage');
var color = _.get(handler, 'data.color');
var isPercentage = (handler && handler._attr.mode === 'percentage');

var eventData = {
value: d.y,
point: datum,
datum: datum,
label: label,
color: color(label),
color: color ? color(label) : undefined,
pointIndex: i,
series: series,
slices: slices,
config: handler._attr,
config: handler && handler._attr,
data: data,
e: d3.event,
handler: handler
Expand Down Expand Up @@ -231,7 +232,7 @@ define(function (require) {
.select('.legend-ul')
.selectAll('li.color')
.filter(function (d, i) {
return this.getAttribute('data-label') !== label;
return String(d.label) !== label;
})
.classed('blur_shape', true);
};
Expand Down
7 changes: 7 additions & 0 deletions src/kibana/components/vislib/lib/handler/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ define(function (require) {
var errors = require('errors');

var Data = Private(require('components/vislib/lib/data'));
var Legend = Private(require('components/vislib/lib/legend'));
var Layout = Private(require('components/vislib/lib/layout/layout'));

/**
Expand Down Expand Up @@ -93,6 +94,12 @@ define(function (require) {

this._validateData();
this.renderArray.forEach(function (property) {
if (property instanceof Legend) {
self.vis.activeEvents().forEach(function (event) {
self.enable(event, property);
});
}

if (typeof property.render === 'function') {
property.render();
}
Expand Down
4 changes: 1 addition & 3 deletions src/kibana/components/vislib/lib/handler/types/pie.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ define(function (require) {
*/

return function (vis) {
var data = new Data(vis.data, vis._attr);

return new Handler(vis, {
legend: new Legend(vis, vis.el, data.pieNames(), data.getPieColorFunc(), vis._attr),
legend: new Legend(vis),
chartTitle: new ChartTitle(vis.el)
});
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ define(function (require) {

return new Handler(vis, {
data: data,
legend: new Legend(vis, vis.el, data.labels, data.color, vis._attr),
legend: new Legend(vis, vis.data),
axisTitle: new AxisTitle(vis.el, data.get('xAxisLabel'), data.get('yAxisLabel')),
chartTitle: new ChartTitle(vis.el),
xAxis: new XAxis({
Expand Down
Loading

0 comments on commit 2ce474f

Please sign in to comment.