[vislis/alerts] warn the user when they stack an area chart that has posotive and negative values
This commit is contained in:
parent
093e7a22fa
commit
94705cd91b
61
src/kibana/components/vislib/lib/alerts.js
Normal file
61
src/kibana/components/vislib/lib/alerts.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
define(function (require) {
|
||||
return function AlertsFactory(d3, Private) {
|
||||
var $ = require('jquery');
|
||||
var _ = require('lodash');
|
||||
|
||||
var ErrorHandler = Private(require('components/vislib/lib/_error_handler'));
|
||||
/**
|
||||
* Appends chart titles to the visualization
|
||||
*
|
||||
* @class Alerts
|
||||
* @constructor
|
||||
* @param el {HTMLElement} Reference to DOM element
|
||||
*/
|
||||
|
||||
function Alerts(vis, data, alertDefs) {
|
||||
if (!(this instanceof Alerts)) {
|
||||
return new Alerts(vis, data, alertDefs);
|
||||
}
|
||||
|
||||
this.vis = vis;
|
||||
this.data = data;
|
||||
this.alertDefs = alertDefs || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders chart titles
|
||||
*
|
||||
* @method render
|
||||
* @returns {D3.Selection|D3.Transition.Transition} DOM element with chart titles
|
||||
*/
|
||||
Alerts.prototype.render = function () {
|
||||
var vis = this.vis;
|
||||
var data = this.data;
|
||||
|
||||
var alerts = _(this.alertDefs)
|
||||
.map(function (alertDef) {
|
||||
if (!alertDef) return;
|
||||
if (alertDef.test && !alertDef.test(vis, data)) return;
|
||||
|
||||
var type = alertDef.type || 'info';
|
||||
var icon = alertDef.icon || type;
|
||||
var msg = alertDef.msg;
|
||||
|
||||
// alert container
|
||||
var $icon = $('<i>').addClass('vis-alerts-icon fa fa-' + icon);
|
||||
var $text = $('<p>').addClass('vis-alerts-text').text(msg);
|
||||
|
||||
return $('<div>').addClass('vis-alert vis-alert-' + type).append([$icon, $text]);
|
||||
})
|
||||
.compact();
|
||||
|
||||
if (!alerts.size()) return;
|
||||
|
||||
$(vis.el).find('.vis-alerts').append(
|
||||
$('<div>').addClass('vis-alerts-tray').append(alerts.value())
|
||||
);
|
||||
};
|
||||
|
||||
return Alerts;
|
||||
};
|
||||
});
|
|
@ -21,7 +21,6 @@ define(function (require) {
|
|||
}
|
||||
|
||||
this.data = opts.data || new Data(vis.data, vis._attr);
|
||||
|
||||
this.vis = vis;
|
||||
this.el = vis.el;
|
||||
this.ChartClass = vis.ChartClass;
|
||||
|
@ -36,6 +35,7 @@ define(function (require) {
|
|||
this.yAxis = opts.yAxis;
|
||||
this.chartTitle = opts.chartTitle;
|
||||
this.axisTitle = opts.axisTitle;
|
||||
this.alerts = opts.alerts;
|
||||
|
||||
if (this._attr.addLegend) {
|
||||
this.legend = opts.legend;
|
||||
|
@ -46,6 +46,7 @@ define(function (require) {
|
|||
this.legend,
|
||||
this.axisTitle,
|
||||
this.chartTitle,
|
||||
this.alerts,
|
||||
this.xAxis,
|
||||
this.yAxis
|
||||
], Boolean);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
define(function (require) {
|
||||
return function ColumnHandler(d3, Private) {
|
||||
var $ = require('jquery');
|
||||
|
||||
var injectZeros = Private(require('components/vislib/components/zero_injection/inject_zeros'));
|
||||
var Handler = Private(require('components/vislib/lib/handler/handler'));
|
||||
var Data = Private(require('components/vislib/lib/data'));
|
||||
|
@ -8,15 +10,18 @@ define(function (require) {
|
|||
var YAxis = Private(require('components/vislib/lib/y_axis'));
|
||||
var AxisTitle = Private(require('components/vislib/lib/axis_title'));
|
||||
var ChartTitle = Private(require('components/vislib/lib/chart_title'));
|
||||
var Alerts = Private(require('components/vislib/lib/alerts'));
|
||||
|
||||
/*
|
||||
* Create handlers for Area, Column, and Line charts which
|
||||
* are all nearly the same minus a few details
|
||||
*/
|
||||
function create(zeroFill, expandLastBucket) {
|
||||
function create(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
return function (vis) {
|
||||
var data;
|
||||
if (zeroFill) {
|
||||
if (opts.zeroFill) {
|
||||
data = new Data(injectZeros(vis.data), vis._attr);
|
||||
} else {
|
||||
data = new Data(vis.data, vis._attr);
|
||||
|
@ -32,9 +37,10 @@ define(function (require) {
|
|||
xValues : data.xValues(),
|
||||
ordered : data.get('ordered'),
|
||||
xAxisFormatter : data.get('xAxisFormatter'),
|
||||
expandLastBucket : expandLastBucket,
|
||||
expandLastBucket : opts.expandLastBucket,
|
||||
_attr : vis._attr
|
||||
}),
|
||||
alerts: new Alerts(vis, data, opts.alerts),
|
||||
yAxis: new YAxis({
|
||||
el : vis.el,
|
||||
yMin : data.getYMinValue(),
|
||||
|
@ -46,9 +52,26 @@ define(function (require) {
|
|||
}
|
||||
|
||||
return {
|
||||
line: create(false, false),
|
||||
area: create(true, false),
|
||||
column: create(true, true)
|
||||
line: create(),
|
||||
|
||||
column: create({
|
||||
zeroFill: true,
|
||||
expandLastBucket: true
|
||||
}),
|
||||
|
||||
area: create({
|
||||
zeroFill: true,
|
||||
alerts: [
|
||||
{
|
||||
type: 'warning',
|
||||
msg: 'Positive and negative values are not accurately represented by stacked ' +
|
||||
'area charts. The line chart is better suited for this type of data.',
|
||||
test: function (vis, data) {
|
||||
return vis._attr.mode === 'stacked' && data.getYMaxValue() > 0 && data.getYMinValue() < 0;
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
};
|
||||
};
|
||||
});
|
||||
|
|
|
@ -73,6 +73,10 @@ define(function (require) {
|
|||
class: 'chart-wrapper',
|
||||
splits: chartSplit
|
||||
},
|
||||
{
|
||||
type: 'div',
|
||||
class: 'vis-alerts'
|
||||
},
|
||||
{
|
||||
type: 'div',
|
||||
class: 'x-axis-wrapper',
|
||||
|
|
48
src/kibana/components/vislib/styles/_alerts.less
Normal file
48
src/kibana/components/vislib/styles/_alerts.less
Normal file
|
@ -0,0 +1,48 @@
|
|||
|
||||
.vis-alerts {
|
||||
position: relative;
|
||||
|
||||
&-tray {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.vis-alert {
|
||||
margin: 0 10px 10px;
|
||||
padding: 5px 10px 5px 5px; // @alert-padding
|
||||
color: white;
|
||||
border-radius: @alert-border-radius;
|
||||
border: 1px solid white;
|
||||
.display(flex);
|
||||
|
||||
&-success {
|
||||
.alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);
|
||||
}
|
||||
&-info {
|
||||
.alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);
|
||||
}
|
||||
&-warning {
|
||||
.alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);
|
||||
}
|
||||
&-danger {
|
||||
.alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);
|
||||
}
|
||||
}
|
||||
|
||||
&-icon {
|
||||
margin: 0;
|
||||
padding: 0 10px;
|
||||
.flex(0, 0, auto);
|
||||
.align-self(center);
|
||||
}
|
||||
|
||||
&-text {
|
||||
.flex(1, 1, auto);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
@import (reference) "lesshat.less";
|
||||
|
||||
.error {
|
||||
.flex(1 1 100%);
|
||||
text-align: center;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@import (reference) "lesshat.less";
|
||||
|
||||
.visualize-chart {
|
||||
.display(flex);
|
||||
.flex(1 1 100%);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@import (reference) "lesshat.less";
|
||||
|
||||
.legend-col-wrapper {
|
||||
.flex(0 1 auto);
|
||||
z-index: 10;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@import (reference) "../../../styles/main.less";
|
||||
|
||||
/* _tilemap */
|
||||
|
||||
.tilemap {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@import (reference) "../../../styles/main";
|
||||
|
||||
@tooltip-padding: 8px;
|
||||
|
||||
.vis-tooltip,
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
@import (reference) "../../../styles/main.less";
|
||||
@import (reference) "lesshat.less";
|
||||
|
||||
@import "_error";
|
||||
@import "_layout";
|
||||
@import "_legend";
|
||||
@import "_svg";
|
||||
@import "_tooltip";
|
||||
@import "_tilemap";
|
||||
@import "_tilemap";
|
||||
@import "_alerts";
|
|
@ -82,6 +82,10 @@ button {
|
|||
color: @brand-danger;
|
||||
}
|
||||
|
||||
// alias for alert types - allows class="fa fa-{{alertType}}"
|
||||
.fa-success:before { content: @fa-var-check; }
|
||||
.fa-danger:before { content: @fa-var-exclamation-circle; }
|
||||
|
||||
ul.navbar-inline li {
|
||||
display: inline;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue