');
- const renderbot = metricVisType.createRenderbot(vis, $el);
- const render = (esResponse) => {
- renderbot.render(esResponse);
- $rootScope.$digest();
- };
-
- return { $el, render };
- };
- }));
-
- it('renders html value from field formatter', () => {
- const { $el, render } = setup();
-
- const ip = '235.195.237.208';
- render({
- hits: { total: 0, hits: [] },
- aggregations: {
- '1': {
- hits: { total: 1, hits: [{ _source: { ip } }] }
- }
- }
- });
-
- const $link = $el
- .find('a[href]')
- .filter(function () { return this.href.includes('ip.info'); });
-
- expect($link).to.have.length(1);
- expect($link.text()).to.be(`ip[${ip}]`);
- });
-});
diff --git a/src/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js b/src/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js
deleted file mode 100644
index c07b3cfc4bd33..0000000000000
--- a/src/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import ngMock from 'ng_mock';
-import expect from 'expect.js';
-import $ from 'jquery';
-
-describe('metric vis', function () {
- let $scope;
-
- const formatter = function (value) {
- return value.toFixed(3);
- };
-
- beforeEach(ngMock.module('kibana/metric_vis'));
- beforeEach(ngMock.inject(function ($rootScope, $controller) {
- $scope = $rootScope.$new();
- const $element = $('
');
- $controller('KbnMetricVisController', { $scope, $element });
- $scope.$digest();
- }));
-
- it('should set the metric label and value', function () {
- $scope.processTableGroups({
- tables: [{
- columns: [{ title: 'Count' }],
- rows: [[ { toString: () => formatter(4301021) } ]]
- }]
- });
-
- expect($scope.metrics.length).to.be(1);
- expect($scope.metrics[0].label).to.be('Count');
- expect($scope.metrics[0].value).to.be('4301021.000');
- });
-
- it('should support multi-value metrics', function () {
- $scope.processTableGroups({
- tables: [{
- columns: [
- { title: '1st percentile of bytes' },
- { title: '99th percentile of bytes' }
- ],
- rows: [[ { toString: () => formatter(182) }, { toString: () => formatter(445842.4634666484) } ]]
- }]
- });
-
- expect($scope.metrics.length).to.be(2);
- expect($scope.metrics[0].label).to.be('1st percentile of bytes');
- expect($scope.metrics[0].value).to.be('182.000');
- expect($scope.metrics[1].label).to.be('99th percentile of bytes');
- expect($scope.metrics[1].value).to.be('445842.463');
- });
-});
diff --git a/src/core_plugins/metric_vis/public/metric_vis.html b/src/core_plugins/metric_vis/public/metric_vis.html
deleted file mode 100644
index 42bc974a73ec5..0000000000000
--- a/src/core_plugins/metric_vis/public/metric_vis.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/src/core_plugins/metric_vis/public/metric_vis.js b/src/core_plugins/metric_vis/public/metric_vis.js
deleted file mode 100644
index ce67b4d4dd1dc..0000000000000
--- a/src/core_plugins/metric_vis/public/metric_vis.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import 'plugins/metric_vis/metric_vis.less';
-import 'plugins/metric_vis/metric_vis_controller';
-import { VisVisTypeProvider } from 'ui/vis/vis_type';
-import { TemplateVisTypeProvider } from 'ui/template_vis_type/template_vis_type';
-import { VisSchemasProvider } from 'ui/vis/schemas';
-import metricVisTemplate from 'plugins/metric_vis/metric_vis.html';
-import metricVisParamsTemplate from 'plugins/metric_vis/metric_vis_params.html';
-import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
-import image from './images/icon-number.svg';
-// we need to load the css ourselves
-
-// we also need to load the controller and used by the template
-
-// register the provider with the visTypes registry
-VisTypesRegistryProvider.register(MetricVisProvider);
-
-function MetricVisProvider(Private) {
- const VisType = Private(VisVisTypeProvider);
- const TemplateVisType = Private(TemplateVisTypeProvider);
- const Schemas = Private(VisSchemasProvider);
-
- // return the visType object, which kibana will use to display and configure new
- // Vis object of this type.
- return new TemplateVisType({
- name: 'metric',
- title: 'Metric',
- image,
- description: 'Display a calculation as a single number',
- category: VisType.CATEGORY.DATA,
- template: metricVisTemplate,
- params: {
- defaults: {
- handleNoResults: true,
- fontSize: 60
- },
- editor: metricVisParamsTemplate
- },
- implementsRenderComplete: true,
- schemas: new Schemas([
- {
- group: 'metrics',
- name: 'metric',
- title: 'Metric',
- min: 1,
- aggFilter: ['!derivative', '!geo_centroid'],
- defaults: [
- { type: 'count', schema: 'metric' }
- ]
- }
- ])
- });
-}
-
-// export the provider so that the visType can be required with Private()
-export default MetricVisProvider;
diff --git a/src/core_plugins/metric_vis/public/metric_vis.less b/src/core_plugins/metric_vis/public/metric_vis.less
deleted file mode 100644
index a770c09ec428e..0000000000000
--- a/src/core_plugins/metric_vis/public/metric_vis.less
+++ /dev/null
@@ -1,18 +0,0 @@
-@import (reference) "~ui/styles/mixins.less";
-
-.metric-vis {
- width: 100%;
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
-
- .metric-value {
- font-weight: bold;
- .ellipsis();
- }
-
- .metric-container {
- text-align: center;
- margin: auto;
- }
-}
diff --git a/src/core_plugins/metric_vis/public/metric_vis_controller.js b/src/core_plugins/metric_vis/public/metric_vis_controller.js
deleted file mode 100644
index 2f98c3f9ae20f..0000000000000
--- a/src/core_plugins/metric_vis/public/metric_vis_controller.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { AggResponseTabifyProvider } from 'ui/agg_response/tabify/tabify';
-import { uiModules } from 'ui/modules';
-// get the kibana/metric_vis module, and make sure that it requires the "kibana" module if it
-// didn't already
-const module = uiModules.get('kibana/metric_vis', ['kibana']);
-
-module.controller('KbnMetricVisController', function ($scope, $element, Private) {
- const tabifyAggResponse = Private(AggResponseTabifyProvider);
-
- const metrics = $scope.metrics = [];
-
- $scope.processTableGroups = function (tableGroups) {
- tableGroups.tables.forEach(function (table) {
- table.columns.forEach(function (column, i) {
- const value = table.rows[0][i];
-
- metrics.push({
- label: column.title,
- value: value.toString('html')
- });
- });
- });
- };
-
- $scope.$watch('esResponse', function (resp) {
- if (resp) {
- const options = {
- asAggConfigResults: true
- };
-
- metrics.length = 0;
- $scope.processTableGroups(tabifyAggResponse($scope.vis, resp, options));
- $element.trigger('renderComplete');
- }
- });
-});
diff --git a/src/core_plugins/metric_vis/public/metric_vis_params.html b/src/core_plugins/metric_vis/public/metric_vis_params.html
deleted file mode 100644
index cdbfc7f2d3998..0000000000000
--- a/src/core_plugins/metric_vis/public/metric_vis_params.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/fixtures/vislib/mock_data/terms/_seriesMultiple.js b/src/fixtures/vislib/mock_data/terms/_seriesMultiple.js
new file mode 100644
index 0000000000000..64b9d0e452403
--- /dev/null
+++ b/src/fixtures/vislib/mock_data/terms/_seriesMultiple.js
@@ -0,0 +1,71 @@
+import _ from 'lodash';
+
+module.exports = {
+ 'yAxisLabel': 'Count',
+ 'zAxisLabel': 'machine.os.raw: Descending',
+ 'yScale': null,
+ 'series': [{
+ 'label': 'ios',
+ 'aggLabel': 'Count',
+ 'aggId': '1',
+ 'values': [{
+ 'x': '_all',
+ 'y': 2820,
+ 'series': 'ios'
+ }]
+ }, {
+ 'label': 'win 7',
+ 'aggLabel': 'Count',
+ 'aggId': '1',
+ 'values': [{
+ 'x': '_all',
+ 'y': 2319,
+ 'series': 'win 7'
+ }]
+ }, {
+ 'label': 'win 8',
+ 'aggLabel': 'Count',
+ 'aggId': '1',
+ 'values': [{
+ 'x': '_all',
+ 'y': 1835,
+ 'series': 'win 8'
+ }]
+ }, {
+ 'label': 'win xp',
+ 'aggLabel': 'Count',
+ 'aggId': '1',
+ 'values': [{
+ 'x': '_all',
+ 'y': 734,
+ 'series': 'win xp'
+ }]
+ }, {
+ 'label': 'osx',
+ 'aggLabel': 'Count',
+ 'aggId': '1',
+ 'values': [{
+ 'x': '_all',
+ 'y': 1352,
+ 'series': 'osx'
+ }]
+ }],
+ 'hits': 14005,
+ 'xAxisFormatter': function (val) {
+ if (_.isObject(val)) {
+ return JSON.stringify(val);
+ }
+ else if (val == null) {
+ return '';
+ }
+ else {
+ return '' + val;
+ }
+ },
+ 'yAxisFormatter': function (val) {
+ return val;
+ },
+ 'tooltipFormatter': function (d) {
+ return d;
+ }
+};
diff --git a/src/ui/public/styles/dark-theme.less b/src/ui/public/styles/dark-theme.less
index 46c9652a508fa..eac3b45a08beb 100644
--- a/src/ui/public/styles/dark-theme.less
+++ b/src/ui/public/styles/dark-theme.less
@@ -270,6 +270,10 @@
fill: @svg-tick-text-color;
}
+ .chart-label {
+ fill: @svg-tick-text-color;
+ }
+
.brush .extent {
stroke: @svg-brush-color;
}
diff --git a/src/ui/public/vislib/__tests__/visualizations/gauge_chart.js b/src/ui/public/vislib/__tests__/visualizations/gauge_chart.js
new file mode 100644
index 0000000000000..70e39e0adf9fa
--- /dev/null
+++ b/src/ui/public/vislib/__tests__/visualizations/gauge_chart.js
@@ -0,0 +1,144 @@
+import expect from 'expect.js';
+import ngMock from 'ng_mock';
+import $ from 'jquery';
+import _ from 'lodash';
+import data from 'fixtures/vislib/mock_data/terms/_seriesMultiple';
+import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture';
+import 'ui/persisted_state';
+
+describe('Vislib Gauge Chart Test Suite', function () {
+ let PersistedState;
+ let vislibVis;
+ let vis;
+ let persistedState;
+ let chartEl;
+ const visLibParams = {
+ type: 'gauge',
+ addTooltip: true,
+ addLegend: false,
+ gauge: {
+ verticalSplit: false,
+ autoExtend: false,
+ percentageMode: false,
+ gaugeStyle: 'Full',
+ backStyle: 'Full',
+ orientation: 'vertical',
+ colorSchema: 'Green to Red',
+ colorsRange: [
+ { from: 0, to: 1500 },
+ { from: 1500, to: 2500 },
+ { from: 2500, to: 3000 }
+ ],
+ invertColors: false,
+ labels: {
+ show: true,
+ color: 'black'
+ },
+ scale: {
+ show: true,
+ labels: false,
+ color: '#333',
+ width: 2
+ },
+ type: 'meter',
+ style: {
+ bgWidth: 0.9,
+ width: 0.9,
+ mask: false,
+ bgMask: false,
+ maskBars: 50,
+ bgFill: '#eee',
+ subText: '',
+ }
+ }
+ };
+
+ function generateVis(opts = {}) {
+ const config = _.defaultsDeep({}, opts, visLibParams);
+ if (vis) {
+ vis.destroy();
+ $('.visualize-chart').remove();
+ }
+ vis = vislibVis(config);
+ persistedState = new PersistedState();
+ vis.on('brush', _.noop);
+ vis.render(data, persistedState);
+ chartEl = vis.handler.charts[0].chartEl;
+ }
+
+ beforeEach(ngMock.module('kibana'));
+ beforeEach(ngMock.inject(function (Private, $injector) {
+ vislibVis = Private(FixturesVislibVisFixtureProvider);
+ PersistedState = $injector.get('PersistedState');
+ generateVis();
+ }));
+
+ afterEach(function () {
+ vis.destroy();
+ $('.visualize-chart').remove();
+ });
+
+ it('creates meter gauge', function () {
+ expect($(chartEl).find('svg').length).to.equal(5);
+ expect($(chartEl).find('svg > g > g > text').text()).to.equal('2820231918357341352');
+ });
+
+ it('creates circle gauge', function () {
+ generateVis({
+ gauge: {
+ minAngle: 0,
+ maxAngle: 2 * Math.PI
+ }
+ });
+ expect($(chartEl).find('svg').length).to.equal(5);
+ });
+
+ it('creates gauge with percentage mode', function () {
+ generateVis({
+ gauge: {
+ percentageMode: true
+ }
+ });
+ expect($(chartEl).find('svg > g > g > text').text()).to.equal('94%77%61%24%45%');
+ });
+
+ it('creates gauge with vertical mode', function () {
+ generateVis({
+ gauge: {
+ verticalSplit: true
+ }
+ });
+ expect($(chartEl).find('svg').width()).to.equal($(chartEl).width());
+ });
+
+ it('applies range settings correctly', function () {
+ const paths = $(chartEl).find('svg > g > g:nth-child(1) > path:nth-child(2)');
+ const fills = [];
+ paths.each(function () { fills.push(this.style.fill); });
+ expect(fills).to.eql([
+ 'rgb(165, 0, 38)',
+ 'rgb(255, 255, 190)',
+ 'rgb(255, 255, 190)',
+ 'rgb(0, 104, 55)',
+ 'rgb(0, 104, 55)'
+ ]);
+ });
+
+ it('applies color schema correctly', function () {
+ generateVis({
+ gauge: {
+ colorSchema: 'Blues'
+ }
+ });
+ const paths = $(chartEl).find('svg > g > g:nth-child(1) > path:nth-child(2)');
+ const fills = [];
+ paths.each(function () { fills.push(this.style.fill); });
+ expect(fills).to.eql([
+ 'rgb(8, 48, 107)',
+ 'rgb(107, 174, 214)',
+ 'rgb(107, 174, 214)',
+ 'rgb(247, 251, 255)',
+ 'rgb(247, 251, 255)'
+ ]);
+ });
+});
diff --git a/src/ui/public/vislib/components/color/colormaps.js b/src/ui/public/vislib/components/color/colormaps.js
index 797a521abb372..cf848ac5e4929 100644
--- a/src/ui/public/vislib/components/color/colormaps.js
+++ b/src/ui/public/vislib/components/color/colormaps.js
@@ -2562,3 +2562,175 @@ vislibColorMaps['Yellow to Red'] = [[0.000, [1.000, 1.000, 0.800]],
[0.998, [0.502, 0.000, 0.149]],
[1.000, [0.502, 0.000, 0.149]]];
+vislibColorMaps['Green to Red'] = [
+ [0, [0, 0.408, 0.216]], [0.002, [0, 0.408, 0.216]], [0.004, [0.004, 0.415, 0.22]],
+ [0.006, [0.004, 0.415, 0.22]], [0.008, [0.008, 0.423, 0.223]], [0.01, [0.008, 0.423, 0.223]],
+ [0.012, [0.012, 0.43, 0.227]], [0.014, [0.012, 0.43, 0.227]], [0.016, [0.016, 0.437, 0.231]],
+ [0.018, [0.016, 0.437, 0.231]], [0.02, [0.02, 0.445, 0.235]], [0.022, [0.02, 0.445, 0.235]],
+ [0.023, [0.024, 0.452, 0.239]], [0.025, [0.024, 0.452, 0.239]], [0.027, [0.028, 0.46, 0.243]],
+ [0.029, [0.028, 0.46, 0.243]], [0.031, [0.032, 0.467, 0.246]], [0.033, [0.032, 0.467, 0.246]],
+ [0.035, [0.036, 0.474, 0.25]], [0.037, [0.036, 0.474, 0.25]], [0.039, [0.04, 0.482, 0.254]],
+ [0.041, [0.04, 0.482, 0.254]], [0.043, [0.044, 0.489, 0.258]], [0.045, [0.044, 0.489, 0.258]],
+ [0.047, [0.048, 0.496, 0.262]], [0.049, [0.048, 0.496, 0.262]], [0.051, [0.052, 0.504, 0.266]],
+ [0.053, [0.052, 0.504, 0.266]], [0.055, [0.056, 0.511, 0.27]], [0.057, [0.056, 0.511, 0.27]],
+ [0.059, [0.06, 0.519, 0.273]], [0.061, [0.06, 0.519, 0.273]], [0.063, [0.064, 0.526, 0.277]],
+ [0.065, [0.064, 0.526, 0.277]], [0.067, [0.068, 0.533, 0.281]], [0.068, [0.068, 0.533, 0.281]],
+ [0.07, [0.072, 0.541, 0.285]], [0.072, [0.072, 0.541, 0.285]], [0.074, [0.076, 0.548, 0.289]],
+ [0.076, [0.076, 0.548, 0.289]], [0.078, [0.08, 0.555, 0.293]], [0.08, [0.08, 0.555, 0.293]],
+ [0.082, [0.084, 0.563, 0.296]], [0.084, [0.084, 0.563, 0.296]], [0.086, [0.088, 0.57, 0.3]],
+ [0.088, [0.088, 0.57, 0.3]], [0.09, [0.092, 0.578, 0.304]], [0.092, [0.092, 0.578, 0.304]],
+ [0.094, [0.096, 0.585, 0.308]], [0.096, [0.096, 0.585, 0.308]], [0.098, [0.1, 0.592, 0.312]],
+ [0.1, [0.1, 0.592, 0.312]], [0.102, [0.108, 0.599, 0.315]], [0.104, [0.108, 0.599, 0.315]],
+ [0.106, [0.119, 0.605, 0.318]], [0.108, [0.119, 0.605, 0.318]], [0.11, [0.131, 0.61, 0.321]],
+ [0.112, [0.131, 0.61, 0.321]], [0.114, [0.143, 0.616, 0.324]], [0.115, [0.143, 0.616, 0.324]],
+ [0.117, [0.155, 0.622, 0.327]], [0.119, [0.155, 0.622, 0.327]], [0.121, [0.166, 0.627, 0.33]],
+ [0.123, [0.166, 0.627, 0.33]], [0.125, [0.178, 0.633, 0.333]], [0.127, [0.178, 0.633, 0.333]],
+ [0.129, [0.19, 0.639, 0.336]], [0.131, [0.19, 0.639, 0.336]], [0.133, [0.201, 0.644, 0.339]],
+ [0.135, [0.201, 0.644, 0.339]], [0.137, [0.213, 0.65, 0.341]], [0.139, [0.213, 0.65, 0.341]],
+ [0.141, [0.225, 0.656, 0.344]], [0.143, [0.225, 0.656, 0.344]], [0.145, [0.236, 0.662, 0.347]],
+ [0.147, [0.236, 0.662, 0.347]], [0.149, [0.248, 0.667, 0.35]], [0.151, [0.248, 0.667, 0.35]],
+ [0.153, [0.26, 0.673, 0.353]], [0.155, [0.26, 0.673, 0.353]], [0.157, [0.271, 0.679, 0.356]],
+ [0.159, [0.271, 0.679, 0.356]], [0.16, [0.283, 0.684, 0.359]], [0.162, [0.283, 0.684, 0.359]],
+ [0.164, [0.295, 0.69, 0.362]], [0.166, [0.295, 0.69, 0.362]], [0.168, [0.306, 0.696, 0.365]],
+ [0.17, [0.306, 0.696, 0.365]], [0.172, [0.318, 0.701, 0.368]], [0.174, [0.318, 0.701, 0.368]],
+ [0.176, [0.33, 0.707, 0.371]], [0.178, [0.33, 0.707, 0.371]], [0.18, [0.342, 0.713, 0.374]],
+ [0.182, [0.342, 0.713, 0.374]], [0.184, [0.353, 0.718, 0.377]], [0.186, [0.353, 0.718, 0.377]],
+ [0.188, [0.365, 0.724, 0.379]], [0.19, [0.365, 0.724, 0.379]], [0.192, [0.377, 0.73, 0.382]],
+ [0.194, [0.377, 0.73, 0.382]], [0.196, [0.388, 0.735, 0.385]], [0.198, [0.388, 0.735, 0.385]],
+ [0.2, [0.4, 0.741, 0.388]], [0.202, [0.4, 0.741, 0.388]], [0.204, [0.41, 0.745, 0.389]],
+ [0.205, [0.41, 0.745, 0.389]], [0.207, [0.42, 0.75, 0.39]], [0.209, [0.42, 0.75, 0.39]],
+ [0.211, [0.43, 0.754, 0.391]], [0.213, [0.43, 0.754, 0.391]], [0.215, [0.439, 0.758, 0.393]],
+ [0.217, [0.439, 0.758, 0.393]], [0.219, [0.449, 0.763, 0.394]], [0.221, [0.449, 0.763, 0.394]],
+ [0.223, [0.459, 0.767, 0.395]], [0.225, [0.459, 0.767, 0.395]], [0.227, [0.469, 0.771, 0.396]],
+ [0.229, [0.469, 0.771, 0.396]], [0.231, [0.479, 0.776, 0.397]], [0.233, [0.479, 0.776, 0.397]],
+ [0.235, [0.489, 0.78, 0.398]], [0.237, [0.489, 0.78, 0.398]], [0.239, [0.498, 0.784, 0.399]],
+ [0.241, [0.498, 0.784, 0.399]], [0.243, [0.508, 0.789, 0.4]], [0.245, [0.508, 0.789, 0.4]],
+ [0.247, [0.518, 0.793, 0.401]], [0.249, [0.518, 0.793, 0.401]], [0.25, [0.528, 0.797, 0.402]],
+ [0.252, [0.528, 0.797, 0.402]], [0.254, [0.538, 0.801, 0.403]], [0.256, [0.538, 0.801, 0.403]],
+ [0.258, [0.548, 0.806, 0.404]], [0.26, [0.548, 0.806, 0.404]], [0.262, [0.557, 0.81, 0.405]],
+ [0.264, [0.557, 0.81, 0.405]], [0.266, [0.567, 0.814, 0.407]], [0.268, [0.567, 0.814, 0.407]],
+ [0.27, [0.577, 0.819, 0.408]], [0.272, [0.577, 0.819, 0.408]], [0.274, [0.587, 0.823, 0.409]],
+ [0.276, [0.587, 0.823, 0.409]], [0.278, [0.597, 0.827, 0.41]], [0.28, [0.597, 0.827, 0.41]],
+ [0.282, [0.607, 0.832, 0.411]], [0.284, [0.607, 0.832, 0.411]], [0.286, [0.617, 0.836, 0.412]],
+ [0.288, [0.617, 0.836, 0.412]], [0.29, [0.626, 0.84, 0.413]], [0.292, [0.626, 0.84, 0.413]],
+ [0.294, [0.636, 0.845, 0.414]], [0.295, [0.636, 0.845, 0.414]], [0.297, [0.646, 0.849, 0.415]],
+ [0.299, [0.646, 0.849, 0.415]], [0.301, [0.655, 0.853, 0.418]], [0.303, [0.655, 0.853, 0.418]],
+ [0.305, [0.663, 0.856, 0.423]], [0.307, [0.663, 0.856, 0.423]], [0.309, [0.671, 0.859, 0.428]],
+ [0.311, [0.671, 0.859, 0.428]], [0.313, [0.678, 0.863, 0.433]], [0.315, [0.678, 0.863, 0.433]],
+ [0.317, [0.686, 0.866, 0.439]], [0.319, [0.686, 0.866, 0.439]], [0.321, [0.694, 0.87, 0.444]],
+ [0.323, [0.694, 0.87, 0.444]], [0.325, [0.702, 0.873, 0.449]], [0.327, [0.702, 0.873, 0.449]],
+ [0.329, [0.71, 0.876, 0.454]], [0.331, [0.71, 0.876, 0.454]], [0.333, [0.718, 0.88, 0.459]],
+ [0.335, [0.718, 0.88, 0.459]], [0.337, [0.725, 0.883, 0.464]], [0.339, [0.725, 0.883, 0.464]],
+ [0.341, [0.733, 0.887, 0.469]], [0.342, [0.733, 0.887, 0.469]], [0.344, [0.741, 0.89, 0.474]],
+ [0.346, [0.741, 0.89, 0.474]], [0.348, [0.749, 0.893, 0.479]], [0.35, [0.749, 0.893, 0.479]],
+ [0.352, [0.757, 0.897, 0.484]], [0.354, [0.757, 0.897, 0.484]], [0.356, [0.765, 0.9, 0.489]],
+ [0.358, [0.765, 0.9, 0.489]], [0.36, [0.773, 0.903, 0.494]], [0.362, [0.773, 0.903, 0.494]],
+ [0.364, [0.78, 0.907, 0.499]], [0.366, [0.78, 0.907, 0.499]], [0.368, [0.788, 0.91, 0.504]],
+ [0.37, [0.788, 0.91, 0.504]], [0.372, [0.796, 0.914, 0.51]], [0.374, [0.796, 0.914, 0.51]],
+ [0.376, [0.804, 0.917, 0.515]], [0.378, [0.804, 0.917, 0.515]], [0.38, [0.812, 0.92, 0.52]],
+ [0.382, [0.812, 0.92, 0.52]], [0.384, [0.82, 0.924, 0.525]], [0.386, [0.82, 0.924, 0.525]],
+ [0.387, [0.827, 0.927, 0.53]], [0.389, [0.827, 0.927, 0.53]], [0.391, [0.835, 0.93, 0.535]],
+ [0.393, [0.835, 0.93, 0.535]], [0.395, [0.843, 0.934, 0.54]], [0.397, [0.843, 0.934, 0.54]],
+ [0.399, [0.851, 0.937, 0.545]], [0.401, [0.851, 0.937, 0.545]], [0.403, [0.857, 0.94, 0.553]],
+ [0.405, [0.857, 0.94, 0.553]], [0.407, [0.863, 0.942, 0.561]], [0.409, [0.863, 0.942, 0.561]],
+ [0.411, [0.869, 0.945, 0.569]], [0.413, [0.869, 0.945, 0.569]], [0.415, [0.874, 0.947, 0.577]],
+ [0.417, [0.874, 0.947, 0.577]], [0.419, [0.88, 0.95, 0.585]], [0.421, [0.88, 0.95, 0.585]],
+ [0.423, [0.886, 0.952, 0.593]], [0.425, [0.886, 0.952, 0.593]], [0.427, [0.892, 0.954, 0.601]],
+ [0.429, [0.892, 0.954, 0.601]], [0.431, [0.898, 0.957, 0.609]], [0.432, [0.898, 0.957, 0.609]],
+ [0.434, [0.904, 0.959, 0.617]], [0.436, [0.904, 0.959, 0.617]], [0.438, [0.909, 0.962, 0.625]],
+ [0.44, [0.909, 0.962, 0.625]], [0.442, [0.915, 0.964, 0.633]], [0.444, [0.915, 0.964, 0.633]],
+ [0.446, [0.921, 0.967, 0.641]], [0.448, [0.921, 0.967, 0.641]], [0.45, [0.927, 0.969, 0.649]],
+ [0.452, [0.927, 0.969, 0.649]], [0.454, [0.933, 0.972, 0.657]], [0.456, [0.933, 0.972, 0.657]],
+ [0.458, [0.939, 0.974, 0.665]], [0.46, [0.939, 0.974, 0.665]], [0.462, [0.944, 0.977, 0.673]],
+ [0.464, [0.944, 0.977, 0.673]], [0.466, [0.95, 0.979, 0.681]], [0.468, [0.95, 0.979, 0.681]],
+ [0.47, [0.956, 0.982, 0.689]], [0.472, [0.956, 0.982, 0.689]], [0.474, [0.962, 0.984, 0.697]],
+ [0.476, [0.962, 0.984, 0.697]], [0.477, [0.968, 0.986, 0.705]], [0.479, [0.968, 0.986, 0.705]],
+ [0.481, [0.974, 0.989, 0.713]], [0.483, [0.974, 0.989, 0.713]], [0.485, [0.98, 0.991, 0.721]],
+ [0.487, [0.98, 0.991, 0.721]], [0.489, [0.985, 0.994, 0.729]], [0.491, [0.985, 0.994, 0.729]],
+ [0.493, [0.991, 0.996, 0.737]], [0.495, [0.991, 0.996, 0.737]], [0.497, [0.997, 0.999, 0.745]],
+ [0.499, [0.997, 0.999, 0.745]], [0.501, [1, 0.998, 0.745]], [0.503, [1, 0.998, 0.745]],
+ [0.505, [1, 0.993, 0.737]], [0.507, [1, 0.993, 0.737]], [0.509, [1, 0.988, 0.729]],
+ [0.511, [1, 0.988, 0.729]], [0.513, [0.999, 0.983, 0.721]], [0.515, [0.999, 0.983, 0.721]],
+ [0.517, [0.999, 0.979, 0.713]], [0.519, [0.999, 0.979, 0.713]], [0.521, [0.999, 0.974, 0.705]],
+ [0.523, [0.999, 0.974, 0.705]], [0.524, [0.999, 0.969, 0.697]], [0.526, [0.999, 0.969, 0.697]],
+ [0.528, [0.999, 0.964, 0.689]], [0.53, [0.999, 0.964, 0.689]], [0.532, [0.999, 0.959, 0.681]],
+ [0.534, [0.999, 0.959, 0.681]], [0.536, [0.999, 0.955, 0.673]], [0.538, [0.999, 0.955, 0.673]],
+ [0.54, [0.998, 0.95, 0.665]], [0.542, [0.998, 0.95, 0.665]], [0.544, [0.998, 0.945, 0.657]],
+ [0.546, [0.998, 0.945, 0.657]], [0.548, [0.998, 0.94, 0.649]], [0.55, [0.998, 0.94, 0.649]],
+ [0.552, [0.998, 0.936, 0.641]], [0.554, [0.998, 0.936, 0.641]], [0.556, [0.998, 0.931, 0.633]],
+ [0.558, [0.998, 0.931, 0.633]], [0.56, [0.998, 0.926, 0.625]], [0.562, [0.998, 0.926, 0.625]],
+ [0.564, [0.997, 0.921, 0.617]], [0.566, [0.997, 0.921, 0.617]], [0.568, [0.997, 0.917, 0.609]],
+ [0.569, [0.997, 0.917, 0.609]], [0.571, [0.997, 0.912, 0.601]], [0.573, [0.997, 0.912, 0.601]],
+ [0.575, [0.997, 0.907, 0.593]], [0.577, [0.997, 0.907, 0.593]], [0.579, [0.997, 0.902, 0.585]],
+ [0.581, [0.997, 0.902, 0.585]], [0.583, [0.997, 0.898, 0.577]], [0.585, [0.997, 0.898, 0.577]],
+ [0.587, [0.997, 0.893, 0.569]], [0.589, [0.997, 0.893, 0.569]], [0.591, [0.996, 0.888, 0.561]],
+ [0.593, [0.996, 0.888, 0.561]], [0.595, [0.996, 0.883, 0.553]], [0.597, [0.996, 0.883, 0.553]],
+ [0.599, [0.996, 0.878, 0.545]], [0.601, [0.996, 0.878, 0.545]], [0.603, [0.996, 0.871, 0.539]],
+ [0.605, [0.996, 0.871, 0.539]], [0.607, [0.996, 0.863, 0.532]], [0.609, [0.996, 0.863, 0.532]],
+ [0.611, [0.996, 0.855, 0.526]], [0.613, [0.996, 0.855, 0.526]], [0.614, [0.995, 0.848, 0.519]],
+ [0.616, [0.995, 0.848, 0.519]], [0.618, [0.995, 0.84, 0.513]], [0.62, [0.995, 0.84, 0.513]],
+ [0.622, [0.995, 0.832, 0.506]], [0.624, [0.995, 0.832, 0.506]], [0.626, [0.995, 0.825, 0.5]],
+ [0.628, [0.995, 0.825, 0.5]], [0.63, [0.995, 0.817, 0.493]], [0.632, [0.995, 0.817, 0.493]],
+ [0.634, [0.995, 0.809, 0.487]], [0.636, [0.995, 0.809, 0.487]],
+ [0.638, [0.995, 0.802, 0.481]], [0.64, [0.995, 0.802, 0.481]], [0.642, [0.994, 0.794, 0.474]],
+ [0.644, [0.994, 0.794, 0.474]], [0.646, [0.994, 0.786, 0.468]], [0.648, [0.994, 0.786, 0.468]],
+ [0.65, [0.994, 0.778, 0.461]], [0.652, [0.994, 0.778, 0.461]], [0.654, [0.994, 0.771, 0.455]],
+ [0.656, [0.994, 0.771, 0.455]], [0.658, [0.994, 0.763, 0.448]], [0.659, [0.994, 0.763, 0.448]],
+ [0.661, [0.994, 0.755, 0.442]], [0.663, [0.994, 0.755, 0.442]], [0.665, [0.993, 0.748, 0.435]],
+ [0.667, [0.993, 0.748, 0.435]], [0.669, [0.993, 0.74, 0.429]], [0.671, [0.993, 0.74, 0.429]],
+ [0.673, [0.993, 0.732, 0.422]], [0.675, [0.993, 0.732, 0.422]], [0.677, [0.993, 0.725, 0.416]],
+ [0.679, [0.993, 0.725, 0.416]], [0.681, [0.993, 0.717, 0.409]], [0.683, [0.993, 0.717, 0.409]],
+ [0.685, [0.993, 0.709, 0.403]], [0.687, [0.993, 0.709, 0.403]], [0.689, [0.993, 0.702, 0.397]],
+ [0.691, [0.993, 0.702, 0.397]], [0.693, [0.992, 0.694, 0.39]], [0.695, [0.992, 0.694, 0.39]],
+ [0.697, [0.992, 0.686, 0.384]], [0.699, [0.992, 0.686, 0.384]], [0.701, [0.991, 0.677, 0.378]],
+ [0.703, [0.991, 0.677, 0.378]], [0.705, [0.99, 0.667, 0.373]], [0.706, [0.99, 0.667, 0.373]],
+ [0.708, [0.989, 0.657, 0.369]], [0.71, [0.989, 0.657, 0.369]], [0.712, [0.987, 0.647, 0.364]],
+ [0.714, [0.987, 0.647, 0.364]], [0.716, [0.986, 0.637, 0.36]], [0.718, [0.986, 0.637, 0.36]],
+ [0.72, [0.985, 0.627, 0.355]], [0.722, [0.985, 0.627, 0.355]], [0.724, [0.983, 0.617, 0.35]],
+ [0.726, [0.983, 0.617, 0.35]], [0.728, [0.982, 0.607, 0.346]], [0.73, [0.982, 0.607, 0.346]],
+ [0.732, [0.98, 0.597, 0.341]], [0.734, [0.98, 0.597, 0.341]], [0.736, [0.979, 0.587, 0.337]],
+ [0.738, [0.979, 0.587, 0.337]], [0.74, [0.978, 0.577, 0.332]], [0.742, [0.978, 0.577, 0.332]],
+ [0.744, [0.976, 0.567, 0.327]], [0.746, [0.976, 0.567, 0.327]], [0.748, [0.975, 0.557, 0.323]],
+ [0.75, [0.975, 0.557, 0.323]], [0.751, [0.973, 0.547, 0.318]], [0.753, [0.973, 0.547, 0.318]],
+ [0.755, [0.972, 0.537, 0.313]], [0.757, [0.972, 0.537, 0.313]], [0.759, [0.971, 0.527, 0.309]],
+ [0.761, [0.971, 0.527, 0.309]], [0.763, [0.969, 0.517, 0.304]], [0.765, [0.969, 0.517, 0.304]],
+ [0.767, [0.968, 0.507, 0.3]], [0.769, [0.968, 0.507, 0.3]], [0.771, [0.967, 0.497, 0.295]],
+ [0.773, [0.967, 0.497, 0.295]], [0.775, [0.965, 0.487, 0.29]], [0.777, [0.965, 0.487, 0.29]],
+ [0.779, [0.964, 0.477, 0.286]], [0.781, [0.964, 0.477, 0.286]], [0.783, [0.962, 0.467, 0.281]],
+ [0.785, [0.962, 0.467, 0.281]], [0.787, [0.961, 0.457, 0.277]], [0.789, [0.961, 0.457, 0.277]],
+ [0.791, [0.96, 0.447, 0.272]], [0.793, [0.96, 0.447, 0.272]], [0.795, [0.958, 0.437, 0.267]],
+ [0.796, [0.958, 0.437, 0.267]], [0.798, [0.957, 0.427, 0.263]], [0.8, [0.957, 0.427, 0.263]],
+ [0.802, [0.952, 0.418, 0.258]], [0.804, [0.952, 0.418, 0.258]], [0.806, [0.948, 0.409, 0.254]],
+ [0.808, [0.948, 0.409, 0.254]], [0.81, [0.943, 0.399, 0.25]], [0.812, [0.943, 0.399, 0.25]],
+ [0.814, [0.939, 0.39, 0.246]], [0.816, [0.939, 0.39, 0.246]], [0.818, [0.935, 0.381, 0.241]],
+ [0.82, [0.935, 0.381, 0.241]], [0.822, [0.93, 0.371, 0.237]], [0.824, [0.93, 0.371, 0.237]],
+ [0.826, [0.926, 0.362, 0.233]], [0.828, [0.926, 0.362, 0.233]], [0.83, [0.921, 0.352, 0.228]],
+ [0.832, [0.921, 0.352, 0.228]], [0.834, [0.917, 0.343, 0.224]], [0.836, [0.917, 0.343, 0.224]],
+ [0.838, [0.912, 0.334, 0.22]], [0.84, [0.912, 0.334, 0.22]], [0.841, [0.908, 0.324, 0.215]],
+ [0.843, [0.908, 0.324, 0.215]], [0.845, [0.903, 0.315, 0.211]], [0.847, [0.903, 0.315, 0.211]],
+ [0.849, [0.899, 0.305, 0.207]], [0.851, [0.899, 0.305, 0.207]], [0.853, [0.894, 0.296, 0.202]],
+ [0.855, [0.894, 0.296, 0.202]], [0.857, [0.89, 0.287, 0.198]], [0.859, [0.89, 0.287, 0.198]],
+ [0.861, [0.886, 0.277, 0.194]], [0.863, [0.886, 0.277, 0.194]], [0.865, [0.881, 0.268, 0.19]],
+ [0.867, [0.881, 0.268, 0.19]], [0.869, [0.877, 0.259, 0.185]], [0.871, [0.877, 0.259, 0.185]],
+ [0.873, [0.872, 0.249, 0.181]], [0.875, [0.872, 0.249, 0.181]], [0.877, [0.868, 0.24, 0.177]],
+ [0.879, [0.868, 0.24, 0.177]], [0.881, [0.863, 0.23, 0.172]], [0.883, [0.863, 0.23, 0.172]],
+ [0.885, [0.859, 0.221, 0.168]], [0.886, [0.859, 0.221, 0.168]], [0.888, [0.854, 0.212, 0.164]],
+ [0.89, [0.854, 0.212, 0.164]], [0.892, [0.85, 0.202, 0.159]], [0.894, [0.85, 0.202, 0.159]],
+ [0.896, [0.845, 0.193, 0.155]], [0.898, [0.845, 0.193, 0.155]], [0.9, [0.839, 0.185, 0.153]],
+ [0.902, [0.839, 0.185, 0.153]], [0.904, [0.832, 0.177, 0.153]], [0.906, [0.832, 0.177, 0.153]],
+ [0.908, [0.824, 0.17, 0.153]], [0.91, [0.824, 0.17, 0.153]], [0.912, [0.816, 0.162, 0.152]],
+ [0.914, [0.816, 0.162, 0.152]], [0.916, [0.809, 0.155, 0.152]], [0.918, [0.809, 0.155, 0.152]],
+ [0.92, [0.801, 0.148, 0.152]], [0.922, [0.801, 0.148, 0.152]], [0.924, [0.793, 0.14, 0.152]],
+ [0.926, [0.793, 0.14, 0.152]], [0.928, [0.785, 0.133, 0.152]], [0.93, [0.785, 0.133, 0.152]],
+ [0.932, [0.778, 0.125, 0.152]], [0.933, [0.778, 0.125, 0.152]], [0.935, [0.77, 0.118, 0.151]],
+ [0.937, [0.77, 0.118, 0.151]], [0.939, [0.762, 0.111, 0.151]], [0.941, [0.762, 0.111, 0.151]],
+ [0.943, [0.755, 0.103, 0.151]], [0.945, [0.755, 0.103, 0.151]], [0.947, [0.747, 0.096, 0.151]],
+ [0.949, [0.747, 0.096, 0.151]], [0.951, [0.739, 0.089, 0.151]], [0.953, [0.739, 0.089, 0.151]],
+ [0.955, [0.732, 0.081, 0.151]], [0.957, [0.732, 0.081, 0.151]], [0.959, [0.724, 0.074, 0.151]],
+ [0.961, [0.724, 0.074, 0.151]], [0.963, [0.716, 0.066, 0.15]], [0.965, [0.716, 0.066, 0.15]],
+ [0.967, [0.709, 0.059, 0.15]], [0.969, [0.709, 0.059, 0.15]], [0.971, [0.701, 0.052, 0.15]],
+ [0.973, [0.701, 0.052, 0.15]], [0.975, [0.693, 0.044, 0.15]], [0.977, [0.693, 0.044, 0.15]],
+ [0.978, [0.686, 0.037, 0.15]], [0.98, [0.686, 0.037, 0.15]], [0.982, [0.678, 0.03, 0.15]],
+ [0.984, [0.678, 0.03, 0.15]], [0.986, [0.67, 0.022, 0.149]], [0.988, [0.67, 0.022, 0.149]],
+ [0.99, [0.662, 0.015, 0.149]], [0.992, [0.662, 0.015, 0.149]], [0.994, [0.655, 0.007, 0.149]],
+ [0.996, [0.655, 0.007, 0.149]], [0.998, [0.647, 0, 0.149]], [1, [0.647, 0, 0.149]]];
diff --git a/src/ui/public/vislib/lib/layout/layout_types.js b/src/ui/public/vislib/lib/layout/layout_types.js
index cc80b3857fe42..c6158d9a846e9 100644
--- a/src/ui/public/vislib/lib/layout/layout_types.js
+++ b/src/ui/public/vislib/lib/layout/layout_types.js
@@ -1,5 +1,6 @@
import { VislibLibLayoutTypesColumnLayoutProvider } from './types/column_layout';
import { VislibLibLayoutTypesPieLayoutProvider } from './types/pie_layout';
+import { GaugeLayoutProvider } from './types/gauge_layout';
export function VislibLibLayoutLayoutTypesProvider(Private) {
@@ -13,6 +14,7 @@ export function VislibLibLayoutLayoutTypesProvider(Private) {
*/
return {
pie: Private(VislibLibLayoutTypesPieLayoutProvider),
+ gauge: Private(GaugeLayoutProvider),
point_series: Private(VislibLibLayoutTypesColumnLayoutProvider)
};
}
diff --git a/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js b/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js
new file mode 100644
index 0000000000000..533c2f0dcd118
--- /dev/null
+++ b/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js
@@ -0,0 +1,51 @@
+import d3 from 'd3';
+define(function () {
+ return function ChartSplitFactory() {
+
+ /*
+ * Adds div DOM elements to the `.chart-wrapper` element based on the data layout.
+ * For example, if the data has rows, it returns the same number of
+ * `.chart` elements as row objects.
+ */
+
+ return function split(selection) {
+ selection.each(function (data) {
+ const div = d3.select(this)
+ .attr('class', function () {
+ if (data.rows) {
+ return 'chart-wrapper-row';
+ } else if (data.columns) {
+ return 'chart-wrapper-column';
+ } else {
+ return 'chart-wrapper';
+ }
+ });
+ let divClass;
+
+ const charts = div.selectAll('charts')
+ .append('div')
+ .data(function (d) {
+ if (d.rows) {
+ divClass = 'chart-row';
+ return d.rows;
+ } else if (d.columns) {
+ divClass = 'chart-column';
+ return d.columns;
+ } else {
+ divClass = 'chart';
+ return [d];
+ }
+ })
+ .enter()
+ .append('div')
+ .attr('class', function () {
+ return divClass;
+ });
+
+ if (!data.series) {
+ charts.call(split);
+ }
+ });
+ };
+ };
+});
diff --git a/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js b/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js
new file mode 100644
index 0000000000000..d9c70f5ddff44
--- /dev/null
+++ b/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js
@@ -0,0 +1,40 @@
+import d3 from 'd3';
+define(function () {
+ return function ChartTitleSplitFactory() {
+
+ /*
+ * Adds div DOM elements to either the `.y-axis-chart-title` element or the
+ * `.x-axis-chart-title` element based on the data layout.
+ * For example, if the data has rows, it returns the same number of
+ * `.chart-title` elements as row objects.
+ * if not data.rows or data.columns, return no chart titles
+ */
+
+ return function (selection, parent) {
+ selection.each(function (data) {
+ const div = d3.select(this);
+
+ if (!data.slices) {
+ div.selectAll('.chart-title')
+ .append('div')
+ .data(function (d) {
+ return d.rows ? d.rows : d.columns;
+ })
+ .enter()
+ .append('div')
+ .attr('class', 'chart-title');
+
+ if (data.rows) {
+ d3.select(parent).select('.x-axis-chart-title').remove();
+ } else {
+ d3.select(parent).select('.y-axis-chart-title').remove();
+ }
+
+ return div;
+ }
+
+ return d3.select(this).remove();
+ });
+ };
+ };
+});
diff --git a/src/ui/public/vislib/lib/layout/types/gauge_layout.js b/src/ui/public/vislib/lib/layout/types/gauge_layout.js
new file mode 100644
index 0000000000000..05e35a8065a5d
--- /dev/null
+++ b/src/ui/public/vislib/lib/layout/types/gauge_layout.js
@@ -0,0 +1,65 @@
+import GaugeChartSplitProvider from '../splits/gauge_chart/chart_split';
+//import VislibLibLayoutSplitsPieChartChartTitleSplitProvider from '../splits/gauge_chart/chart_title_split';
+export function GaugeLayoutProvider(Private) {
+ const chartSplit = Private(GaugeChartSplitProvider);
+ //const chartTitleSplit = Private(VislibLibLayoutSplitsPieChartChartTitleSplitProvider);
+
+ /**
+ * Specifies the visualization layout for column charts.
+ *
+ * This is done using an array of objects. The first object has
+ * a `parent` DOM element, a DOM `type` (e.g. div, svg, etc),
+ * and a `class` (required). Each child can omit the parent object,
+ * but must include a type and class.
+ *
+ * Optionally, you can specify `datum` to be bound to the DOM
+ * element, a `splits` function that divides the selected element
+ * into more DOM elements based on a callback function provided, or
+ * a children array which nests other layout objects.
+ *
+ * Objects in children arrays are children of the current object and return
+ * DOM elements which are children of their respective parent element.
+ */
+
+ return function (el, data) {
+ if (!el || !data) {
+ throw new Error('Both an el and data need to be specified');
+ }
+
+ return [
+ {
+ parent: el,
+ type: 'div',
+ class: 'vis-wrapper',
+ datum: data,
+ children: [
+ {
+ type: 'div',
+ class: 'y-axis-chart-title',
+ //splits: chartTitleSplit
+ },
+ {
+ type: 'div',
+ class: 'vis-col-wrapper',
+ children: [
+ {
+ type: 'div',
+ class: 'chart-wrapper',
+ splits: chartSplit
+ },
+ {
+ type: 'div',
+ class: 'vis-alerts'
+ },
+ {
+ type: 'div',
+ class: 'x-axis-chart-title',
+ //splits: chartTitleSplit
+ }
+ ]
+ }
+ ]
+ }
+ ];
+ };
+}
diff --git a/src/ui/public/vislib/lib/types/gauge.js b/src/ui/public/vislib/lib/types/gauge.js
new file mode 100644
index 0000000000000..d53bf491779b5
--- /dev/null
+++ b/src/ui/public/vislib/lib/types/gauge.js
@@ -0,0 +1,14 @@
+import _ from 'lodash';
+
+export function vislibGaugeProvider() {
+
+ return function (config) {
+ if (!config.chart) {
+ config.chart = _.defaults({}, config, {
+ type: 'gauge'
+ });
+ }
+
+ return config;
+ };
+}
diff --git a/src/ui/public/vislib/lib/types/index.js b/src/ui/public/vislib/lib/types/index.js
index adcedc172453f..9721e89677d2d 100644
--- a/src/ui/public/vislib/lib/types/index.js
+++ b/src/ui/public/vislib/lib/types/index.js
@@ -1,5 +1,6 @@
import { VislibTypesPointSeries } from './point_series';
import { VislibPieConfigProvider } from './pie';
+import { vislibGaugeProvider } from './gauge';
export function VislibTypesProvider(Private) {
const pointSeries = Private(VislibTypesPointSeries);
@@ -17,5 +18,6 @@ export function VislibTypesProvider(Private) {
area: pointSeries.area,
point_series: pointSeries.line,
heatmap: pointSeries.heatmap,
+ gauge: Private(vislibGaugeProvider)
};
}
diff --git a/src/ui/public/vislib/styles/_svg.less b/src/ui/public/vislib/styles/_svg.less
index a1fd676b93f0f..be46f39d23dab 100644
--- a/src/ui/public/vislib/styles/_svg.less
+++ b/src/ui/public/vislib/styles/_svg.less
@@ -17,6 +17,10 @@
fill: @svg-tick-text-color;
}
+.chart-text {
+ fill: @svg-tick-text-color;
+}
+
/* Brush Styling */
.brush .extent {
stroke: @svg-brush-color;
diff --git a/src/ui/public/vislib/visualizations/gauge_chart.js b/src/ui/public/vislib/visualizations/gauge_chart.js
new file mode 100644
index 0000000000000..a7a5363c0af34
--- /dev/null
+++ b/src/ui/public/vislib/visualizations/gauge_chart.js
@@ -0,0 +1,71 @@
+import d3 from 'd3';
+import $ from 'jquery';
+import { VislibVisualizationsChartProvider } from './_chart';
+import { GaugeTypesProvider } from './gauges/gauge_types';
+
+export function GaugeChartProvider(Private) {
+
+ const Chart = Private(VislibVisualizationsChartProvider);
+ const gaugeTypes = Private(GaugeTypesProvider);
+
+ class GaugeChart extends Chart {
+ constructor(handler, chartEl, chartData) {
+ super(handler, chartEl, chartData);
+ this.gaugeConfig = handler.visConfig.get('gauge', {});
+ this.gauge = new gaugeTypes[this.gaugeConfig.type](this);
+ }
+
+ addEvents(element) {
+ const events = this.events;
+
+ return element
+ .call(events.addHoverEvent())
+ .call(events.addMouseoutEvent())
+ .call(events.addClickEvent());
+ }
+
+ draw() {
+ const self = this;
+ const verticalSplit = this.gaugeConfig.verticalSplit;
+
+ return function (selection) {
+ selection.each(function (data) {
+ const div = d3.select(this);
+ const width = verticalSplit ? $(this).width() : $(this).width() / data.series.length;
+ const height = (verticalSplit ? $(this).height() / data.series.length : $(this).height()) - 25;
+ const transformX = width / 2;
+ const transformY = self.gaugeConfig.gaugeType === 'Meter' ? height / 1.5 : height / 2;
+
+
+
+ data.series.forEach(series => {
+ const svg = div.append('svg')
+ .attr('width', width)
+ .attr('height', height)
+ .style('display', 'inline-block')
+ .style('overflow', 'hidden');
+
+ const g = svg.append('g')
+ .attr('transform', `translate(${transformX}, ${transformY})`);
+
+ const gauges = self.gauge.drawGauge(g, series, width, height);
+ self.addEvents(gauges);
+ });
+
+ div.append('div')
+ .attr('class', 'chart-title')
+ .style('text-align', 'center')
+ .text(data.label || data.yAxisLabel);
+
+ self.events.emit('rendered', {
+ chart: data
+ });
+
+ return div;
+ });
+ };
+ }
+ }
+
+ return GaugeChart;
+}
diff --git a/src/ui/public/vislib/visualizations/gauges/gauge_types.js b/src/ui/public/vislib/visualizations/gauges/gauge_types.js
new file mode 100644
index 0000000000000..7d4c6b7de122b
--- /dev/null
+++ b/src/ui/public/vislib/visualizations/gauges/gauge_types.js
@@ -0,0 +1,10 @@
+import { MeterGaugeProvider } from './meter';
+import { SimpleGaugeProvider } from './simple';
+
+export function GaugeTypesProvider(Private) {
+
+ return {
+ meter: Private(MeterGaugeProvider),
+ simple: Private(SimpleGaugeProvider),
+ };
+}
diff --git a/src/ui/public/vislib/visualizations/gauges/meter.js b/src/ui/public/vislib/visualizations/gauges/meter.js
new file mode 100644
index 0000000000000..01c02b6df5fbb
--- /dev/null
+++ b/src/ui/public/vislib/visualizations/gauges/meter.js
@@ -0,0 +1,300 @@
+import d3 from 'd3';
+import _ from 'lodash';
+import { getHeatmapColors } from 'ui/vislib/components/color/heatmap_color';
+
+export function MeterGaugeProvider() {
+
+
+ const defaultConfig = {
+ showTooltip: true,
+ percentageMode: true,
+ maxAngle: 2 * Math.PI * 1.3,
+ minAngle: 2 * Math.PI * 0.7,
+ innerSpace: 5,
+ extents: [0, 10000],
+ scale: {
+ show: true,
+ color: '#666',
+ width: 2,
+ ticks: 10,
+ tickLength: 8,
+ },
+ labels: {
+ show: true,
+ color: '#666'
+ },
+ style: {
+ bgWidth: 0.5,
+ width: 0.9
+ }
+ };
+
+ class MeterGauge {
+ constructor(gaugeChart) {
+ this.gaugeChart = gaugeChart;
+ this.gaugeConfig = gaugeChart.gaugeConfig;
+ this.gaugeConfig = _.defaultsDeep(this.gaugeConfig, defaultConfig);
+
+ this.gaugeChart.handler.visConfig.set('legend', {
+ labels: this.getLabels(),
+ colors: this.getColors()
+ });
+
+ const colors = this.gaugeChart.handler.visConfig.get('legend.colors', null);
+ if (colors) {
+ this.gaugeChart.handler.vis.uiState.setSilent('vis.defaultColors', null);
+ this.gaugeChart.handler.vis.uiState.setSilent('vis.defaultColors', colors);
+ }
+
+ this.colorFunc = this.gaugeChart.handler.data.getColorFunc();
+ }
+
+ getLabels() {
+ const isPercentageMode = this.gaugeConfig.percentageMode;
+ const colorsRange = this.gaugeConfig.colorsRange;
+ const max = _.last(colorsRange).to;
+ const labels = [];
+ colorsRange.forEach(range => {
+ const from = isPercentageMode ? Math.round(100 * range.from / max) : range.from;
+ const to = isPercentageMode ? Math.round(100 * range.to / max) : range.to;
+ labels.push(`${from} - ${to}`);
+ });
+
+ return labels;
+ }
+
+ getColors() {
+ const invertColors = this.gaugeConfig.invertColors;
+ const colorSchema = this.gaugeConfig.colorSchema;
+ const colorsRange = this.gaugeConfig.colorsRange;
+ const labels = this.getLabels();
+ const colors = {};
+ for (let i = 0; i < labels.length; i += 1) {
+ const divider = Math.max(colorsRange.length - 1, 1);
+ const val = invertColors ? 1 - i / divider : i / divider;
+ colors[labels[i]] = getHeatmapColors(val, colorSchema);
+ }
+ return colors;
+ }
+
+ getBucket(val) {
+ let bucket = _.findIndex(this.gaugeConfig.colorsRange, range => {
+ return range.from <= val && range.to > val;
+ });
+
+ if (bucket === -1) {
+ if (val < this.gaugeConfig.colorsRange[0].from) bucket = 0;
+ else bucket = this.gaugeConfig.colorsRange.length - 1;
+ }
+
+ return bucket;
+ }
+
+ getLabel(val) {
+ const bucket = this.getBucket(val);
+ const labels = this.gaugeChart.handler.visConfig.get('legend.labels');
+ return labels[bucket];
+ }
+
+ getColorBucket(val) {
+ const bucket = this.getBucket(val);
+ const labels = this.gaugeChart.handler.visConfig.get('legend.labels');
+ return this.colorFunc(labels[bucket]);
+ }
+
+ drawScale(svg, radius, angle) {
+ const scaleWidth = this.gaugeConfig.scale.width;
+ const tickLength = this.gaugeConfig.scale.tickLength;
+ const scaleTicks = this.gaugeConfig.scale.ticks;
+
+ const scale = svg.append('g');
+
+ this.gaugeConfig.colorsRange.forEach(range => {
+ const color = this.getColorBucket(range.from);
+
+ const scaleArc = d3.svg.arc()
+ .startAngle(angle(range.from))
+ .endAngle(angle(range.to))
+ .innerRadius(radius)
+ .outerRadius(radius + scaleWidth);
+
+ scale
+ .append('path')
+ .attr('d', scaleArc)
+ .style('stroke', color)
+ .style('fill', color);
+ });
+
+
+ const extents = angle.domain();
+ for (let i = 0; i <= scaleTicks; i++) {
+ const val = i * (extents[1] - extents[0]) / scaleTicks;
+ const tickAngle = angle(val) - Math.PI / 2;
+ const x0 = Math.cos(tickAngle) * radius;
+ const x1 = Math.cos(tickAngle) * (radius - tickLength);
+ const y0 = Math.sin(tickAngle) * radius;
+ const y1 = Math.sin(tickAngle) * (radius - tickLength);
+ const color = this.getColorBucket(val);
+ scale.append('line')
+ .attr('x1', x0).attr('x2', x1)
+ .attr('y1', y0).attr('y2', y1)
+ .style('stroke-width', scaleWidth)
+ .style('stroke', color);
+ }
+
+ return scale;
+ }
+
+ drawGauge(svg, data, width, height) {
+ const marginFactor = 0.95;
+ const tooltip = this.gaugeChart.tooltip;
+ const isTooltip = this.gaugeChart.handler.visConfig.get('addTooltip');
+ const maxAngle = this.gaugeConfig.maxAngle;
+ const minAngle = this.gaugeConfig.minAngle;
+ const angleFactor = this.gaugeConfig.gaugeType === 'Meter' ? 0.75 : 1;
+ const maxRadius = (Math.min(width, height / angleFactor) / 2) * marginFactor;
+ const yFieldFormatter = this.gaugeChart.handler.data.get('yAxisFormatter');
+
+ const extendRange = this.gaugeConfig.extendRange;
+ const maxY = _.max(data.values, 'y').y;
+ const min = this.gaugeConfig.colorsRange[0].from;
+ const max = _.last(this.gaugeConfig.colorsRange).to;
+ const angle = d3.scale.linear()
+ .range([minAngle, maxAngle])
+ .domain([min, extendRange && max < maxY ? maxY : max]);
+ const radius = d3.scale.linear()
+ .range([0, maxRadius])
+ .domain([this.gaugeConfig.innerSpace + 1, 0]);
+
+ const totalWidth = Math.abs(radius(0) - radius(1));
+ const bgPadding = totalWidth * (1 - this.gaugeConfig.style.bgWidth) / 2;
+ const gaugePadding = totalWidth * (1 - this.gaugeConfig.style.width) / 2;
+ const arc = d3.svg.arc()
+ .startAngle(minAngle)
+ .endAngle(function (d) {
+ return Math.max(0, Math.min(maxAngle, angle(d.y)));
+ })
+ .innerRadius(function (d, i, j) {
+ return Math.max(0, radius(j + 1) + gaugePadding);
+ })
+ .outerRadius(function (d, i, j) {
+ return Math.max(0, radius(j) - gaugePadding);
+ });
+
+
+ const bgArc = d3.svg.arc()
+ .startAngle(minAngle)
+ .endAngle(maxAngle)
+ .innerRadius(function (d, i, j) {
+ return Math.max(0, radius(j + 1) + bgPadding);
+ })
+ .outerRadius(function (d, i, j) {
+ return Math.max(0, radius(j) - bgPadding);
+ });
+
+ const gaugeHolders = svg
+ .selectAll('path')
+ .data([data])
+ .enter()
+ .append('g')
+ .attr('data-label', (d) => this.getLabel(d.values[0].y));
+
+
+ const gauges = gaugeHolders
+ .selectAll('g')
+ .data(d => d.values)
+ .enter();
+
+
+ gauges
+ .append('path')
+ .attr('d', bgArc)
+ .style('fill', this.gaugeConfig.style.bgFill);
+
+ const self = this;
+ const series = gauges
+ .append('path')
+ .attr('d', arc)
+ .style('fill', function (d) {
+ return self.getColorBucket(d.y);
+ });
+
+ const smallContainer = svg.node().getBBox().height < 70;
+ let hiddenLabels = smallContainer;
+
+ if (this.gaugeConfig.labels.show) {
+ svg
+ .append('text')
+ .attr('class', 'chart-label')
+ .text(data.label)
+ .attr('y', -30)
+ .attr('style', 'dominant-baseline: central; text-anchor: middle;')
+ .style('display', function () {
+ const textLength = this.getBBox().width;
+ const textTooLong = textLength > maxRadius;
+ if (textTooLong) {
+ hiddenLabels = true;
+ }
+ return smallContainer || textTooLong ? 'none' : 'initial';
+ });
+
+ svg
+ .append('text')
+ .attr('class', 'chart-label')
+ .text(this.gaugeConfig.style.subText)
+ .attr('y', 20)
+ .attr('style', 'dominant-baseline: central; text-anchor: middle;')
+ .style('display', function () {
+ const textLength = this.getBBox().width;
+ const textTooLong = textLength > maxRadius;
+ if (textTooLong) {
+ hiddenLabels = true;
+ }
+ return smallContainer || textTooLong ? 'none' : 'initial';
+ });
+
+ gauges
+ .append('text')
+ .attr('class', 'chart-label')
+ .attr('y', -5)
+ .text(d => {
+ if (this.gaugeConfig.percentageMode) {
+ const percentage = Math.round(100 * (d.y - min) / (max - min));
+ return `${percentage}%`;
+ }
+ return yFieldFormatter(d.y);
+ })
+ .attr('style', 'dominant-baseline: central;')
+ .style('text-anchor', 'middle')
+ .style('font-size', '2em')
+ .style('display', function () {
+ const textLength = this.getBBox().width;
+ const textTooLong = textLength > maxRadius;
+ if (textTooLong) {
+ hiddenLabels = true;
+ }
+ return textTooLong ? 'none' : 'initial';
+ });
+ }
+
+ if (this.gaugeConfig.scale.show) {
+ this.drawScale(svg, radius(1), angle);
+ }
+
+ if (isTooltip) {
+ series.each(function () {
+ const gauge = d3.select(this);
+ gauge.call(tooltip.render());
+ });
+ }
+
+ if (hiddenLabels) {
+ this.gaugeChart.handler.alerts.show('Some labels were hidden due to size constrains');
+ }
+
+ return series;
+ }
+ }
+
+ return MeterGauge;
+}
diff --git a/src/ui/public/vislib/visualizations/gauges/simple.js b/src/ui/public/vislib/visualizations/gauges/simple.js
new file mode 100644
index 0000000000000..ab8c98ab99949
--- /dev/null
+++ b/src/ui/public/vislib/visualizations/gauges/simple.js
@@ -0,0 +1,207 @@
+import d3 from 'd3';
+import _ from 'lodash';
+import { getHeatmapColors } from 'ui/vislib/components/color/heatmap_color';
+
+export function SimpleGaugeProvider() {
+
+
+ const defaultConfig = {
+ showTooltip: true,
+ percentageMode: true,
+ extents: [0, 10000],
+ scale: {
+ show: true,
+ color: '#666',
+ width: 2,
+ ticks: 10,
+ tickLength: 5,
+ },
+ labels: {
+ show: true,
+ color: '#666'
+ },
+ style: {
+ bgColor: true,
+ bgFill: '#666'
+ }
+ };
+
+ class SimpleGauge {
+ constructor(gaugeChart) {
+ this.gaugeChart = gaugeChart;
+ this.gaugeConfig = gaugeChart.gaugeConfig;
+ this.gaugeConfig = _.defaultsDeep(this.gaugeConfig, defaultConfig);
+ this.randomNumber = Math.round(Math.random() * 100000);
+
+ this.gaugeChart.handler.visConfig.set('legend', {
+ labels: this.getLabels(),
+ colors: this.getColors()
+ });
+
+ const colors = this.gaugeChart.handler.visConfig.get('legend.colors', null);
+ if (colors) {
+ this.gaugeChart.handler.vis.uiState.setSilent('vis.defaultColors', null);
+ this.gaugeChart.handler.vis.uiState.setSilent('vis.defaultColors', colors);
+ }
+
+ this.colorFunc = this.gaugeChart.handler.data.getColorFunc();
+ }
+
+ getLabels() {
+ const isPercentageMode = this.gaugeConfig.percentageMode;
+ const colorsRange = this.gaugeConfig.colorsRange;
+ const max = _.last(colorsRange).to;
+ const labels = [];
+ colorsRange.forEach(range => {
+ const from = isPercentageMode ? Math.round(100 * range.from / max) : range.from;
+ const to = isPercentageMode ? Math.round(100 * range.to / max) : range.to;
+ labels.push(`${from} - ${to}`);
+ });
+
+ return labels;
+ }
+
+ getColors() {
+ const invertColors = this.gaugeConfig.invertColors;
+ const colorSchema = this.gaugeConfig.colorSchema;
+ const colorsRange = this.gaugeConfig.colorsRange;
+ const labels = this.getLabels();
+ const colors = {};
+ for (let i = 0; i < labels.length; i += 1) {
+ const divider = Math.max(colorsRange.length - 1, 1);
+ const val = invertColors ? 1 - i / divider : i / divider;
+ colors[labels[i]] = getHeatmapColors(val, colorSchema);
+ }
+ return colors;
+ }
+
+ getBucket(val) {
+ let bucket = _.findIndex(this.gaugeConfig.colorsRange, range => {
+ return range.from <= val && range.to > val;
+ });
+
+ if (bucket === -1) {
+ if (val < this.gaugeConfig.colorsRange[0].from) bucket = 0;
+ else bucket = this.gaugeConfig.colorsRange.length - 1;
+ }
+
+ return bucket;
+ }
+
+ getLabel(val) {
+ const bucket = this.getBucket(val);
+ const labels = this.gaugeChart.handler.visConfig.get('legend.labels');
+ return labels[bucket];
+ }
+
+ getColorBucket(val) {
+ const bucket = this.getBucket(val);
+ const labels = this.gaugeChart.handler.visConfig.get('legend.labels');
+ return this.colorFunc(labels[bucket]);
+ }
+
+ drawGauge(svg, data, width) {
+ const tooltip = this.gaugeChart.tooltip;
+ const isTooltip = this.gaugeChart.handler.visConfig.get('addTooltip');
+ const yFieldFormatter = this.gaugeChart.handler.data.get('yAxisFormatter');
+ const fontSize = this.gaugeChart.handler.visConfig.get('gauge.style.fontSize');
+
+ const labelColor = this.gaugeConfig.style.labelColor;
+ const bgColor = this.gaugeConfig.style.bgColor;
+ const bgFill = this.gaugeConfig.style.bgFill;
+ const min = this.gaugeConfig.colorsRange[0].from;
+ const max = _.last(this.gaugeConfig.colorsRange).to;
+
+ const gaugeHolders = svg
+ .selectAll('path')
+ .data([data])
+ .enter()
+ .append('g')
+ .attr('data-label', (d) => this.getLabel(d.values[0].y));
+
+
+ const gauges = gaugeHolders
+ .selectAll('g')
+ .data(d => d.values)
+ .enter();
+
+
+ const self = this;
+ const series = gauges
+ .append('rect')
+ .attr('x', '-50%')
+ .attr('y', '-50%')
+ .attr('width', '99%')
+ .attr('height', '99%')
+ .style('fill', function (d) {
+ return bgColor ? self.getColorBucket(d.y) : 'transparent';
+ });
+
+ const smallContainer = svg.node().getBBox().height < 70;
+ let hiddenLabels = smallContainer;
+
+ const isTextTooLong = function () {
+ const textLength = this.getBBox().width;
+ const textTooLong = textLength > width;
+ if (textTooLong) {
+ hiddenLabels = true;
+ }
+ return smallContainer || textTooLong ? 'none' : 'initial';
+ };
+
+
+ if (this.gaugeConfig.labels.show) {
+ svg
+ .append('text')
+ .attr('class', 'chart-label')
+ .text(data.label)
+ .attr('y', Math.min(-25, -fontSize))
+ .attr('style', 'dominant-baseline: central; text-anchor: middle;')
+ .style('display', isTextTooLong)
+ .style('fill', bgFill);
+
+ svg
+ .append('text')
+ .attr('class', 'chart-label')
+ .text(this.gaugeConfig.style.subText)
+ .attr('y', Math.max(15, fontSize))
+ .attr('style', 'dominant-baseline: central; text-anchor: middle;')
+ .style('display', isTextTooLong)
+ .style('fill', bgFill);
+ }
+
+ gauges
+ .append('text')
+ .attr('class', 'chart-label')
+ .attr('y', -5)
+ .text(d => {
+ if (this.gaugeConfig.percentageMode) {
+ const percentage = Math.round(100 * (d.y - min) / (max - min));
+ return `${percentage}%`;
+ }
+ return yFieldFormatter(d.y);
+ })
+ .attr('style', 'dominant-baseline: central; font-weight: bold; white-space: nowrap;text-overflow: ellipsis;overflow: hidden;')
+ .style('text-anchor', 'middle')
+ .style('font-size', fontSize + 'pt')
+ .style('fill', function () {
+ return !bgColor && labelColor ? self.getColorBucket(data.values[0].y) : bgFill;
+ });
+
+ if (isTooltip) {
+ series.each(function () {
+ const gauge = d3.select(this);
+ gauge.call(tooltip.render());
+ });
+ }
+
+ if (hiddenLabels) {
+ this.gaugeChart.handler.alerts.show('Some labels were hidden due to size constrains');
+ }
+
+ return series;
+ }
+ }
+
+ return SimpleGauge;
+}
diff --git a/src/ui/public/vislib/visualizations/vis_types.js b/src/ui/public/vislib/visualizations/vis_types.js
index fa7a99113b819..a1219f7ea997b 100644
--- a/src/ui/public/vislib/visualizations/vis_types.js
+++ b/src/ui/public/vislib/visualizations/vis_types.js
@@ -1,5 +1,6 @@
import { VislibVisualizationsPointSeriesProvider } from './point_series';
import { VislibVisualizationsPieChartProvider } from './pie_chart';
+import { GaugeChartProvider } from './gauge_chart';
export function VislibVisualizationsVisTypesProvider(Private) {
@@ -13,6 +14,7 @@ export function VislibVisualizationsVisTypesProvider(Private) {
*/
return {
pie: Private(VislibVisualizationsPieChartProvider),
- point_series: Private(VislibVisualizationsPointSeriesProvider)
+ point_series: Private(VislibVisualizationsPointSeriesProvider),
+ gauge: Private(GaugeChartProvider)
};
}
diff --git a/src/ui/public/vislib_vis_type/vislib_vis_type.js b/src/ui/public/vislib_vis_type/vislib_vis_type.js
index daa2bcc40a39a..e6100de6a1357 100644
--- a/src/ui/public/vislib_vis_type/vislib_vis_type.js
+++ b/src/ui/public/vislib_vis_type/vislib_vis_type.js
@@ -5,6 +5,7 @@ import 'plugins/kbn_vislib_vis_types/controls/point_series_options';
import 'plugins/kbn_vislib_vis_types/controls/line_interpolation_option';
import 'plugins/kbn_vislib_vis_types/controls/heatmap_options';
import 'plugins/kbn_vislib_vis_types/controls/point_series';
+import 'plugins/kbn_vislib_vis_types/controls/gauge_options';
import { VisVisTypeProvider } from 'ui/vis/vis_type';
import { AggResponsePointSeriesProvider } from 'ui/agg_response/point_series/point_series';
import VislibVisTypeVislibRenderbotProvider from 'ui/vislib_vis_type/vislib_renderbot';
diff --git a/src/ui/public/visualize/visualize_legend.js b/src/ui/public/visualize/visualize_legend.js
index 080fac6e3856c..428fe835114fc 100644
--- a/src/ui/public/visualize/visualize_legend.js
+++ b/src/ui/public/visualize/visualize_legend.js
@@ -113,7 +113,7 @@ uiModules.get('kibana')
$scope.open = $scope.vis.params.addLegend;
}
- if (vislibVis.visConfigArgs.type === 'heatmap') {
+ if (['heatmap', 'gauge'].includes(vislibVis.visConfigArgs.type)) {
const labels = vislibVis.getLegendLabels();
if (labels) {
$scope.labels = _.map(labels, label => {
diff --git a/test/functional/apps/visualize/_chart_types.js b/test/functional/apps/visualize/_chart_types.js
index 30644869b70b5..c5c0f591c89be 100644
--- a/test/functional/apps/visualize/_chart_types.js
+++ b/test/functional/apps/visualize/_chart_types.js
@@ -22,6 +22,8 @@ export default function ({ getService, getPageObjects }) {
'Pie',
'Vertical Bar',
'Data Table',
+ 'Gauge',
+ 'Goal',
'Metric',
'Tile Map',
'Timelion',
diff --git a/test/functional/apps/visualize/_gauge_chart.js b/test/functional/apps/visualize/_gauge_chart.js
new file mode 100644
index 0000000000000..364edaa552db0
--- /dev/null
+++ b/test/functional/apps/visualize/_gauge_chart.js
@@ -0,0 +1,74 @@
+import expect from 'expect.js';
+
+export default function ({ getService, getPageObjects }) {
+ const log = getService('log');
+ const retry = getService('retry');
+ const screenshots = getService('screenshots');
+ const PageObjects = getPageObjects(['common', 'visualize', 'header']);
+
+ describe('visualize app', function describeIndexTests() {
+ const fromTime = '2015-09-19 06:31:44.000';
+ const toTime = '2015-09-23 18:31:44.000';
+
+ before(function () {
+ log.debug('navigateToApp visualize');
+ return PageObjects.common.navigateToUrl('visualize', 'new')
+ .then(function () {
+ log.debug('clickGauge');
+ return PageObjects.visualize.clickGauge();
+ })
+ .then(function clickNewSearch() {
+ return PageObjects.visualize.clickNewSearch();
+ })
+ .then(function setAbsoluteRange() {
+ log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"');
+ return PageObjects.header.setAbsoluteRange(fromTime, toTime);
+ });
+ });
+
+ describe('gauge chart', function indexPatternCreation() {
+
+ it('should show Count', function () {
+ const expectedCount = ['14,004', 'Count'];
+
+ // initial metric of "Count" is selected by default
+ return retry.try(function tryingForTime() {
+ return PageObjects.visualize.getGaugeValue()
+ .then(function (metricValue) {
+ screenshots.take('Visualize-gauge-chart');
+ expect(expectedCount).to.eql(metricValue[0].split('\n'));
+ });
+ });
+ });
+
+ it('should show Split Gauges', function () {
+ const expectedTexts = [ 'win 8', 'win xp', 'win 7', 'ios', 'osx' ];
+ return PageObjects.visualize.clickMetricEditor()
+ .then(function clickBucket() {
+ log.debug('Bucket = Split Group');
+ return PageObjects.visualize.clickBucket('Split Group');
+ })
+ .then(function selectAggregation() {
+ log.debug('Aggregation = Terms');
+ return PageObjects.visualize.selectAggregation('Terms');
+ })
+ .then(function selectField() {
+ log.debug('Field = machine.os.raw');
+ return PageObjects.visualize.selectField('machine.os.raw');
+ })
+ .then(function clickGo() {
+ return PageObjects.visualize.clickGo();
+ })
+ .then(function () {
+ return retry.try(function tryingForTime() {
+ return PageObjects.visualize.getGaugeValue()
+ .then(function (metricValue) {
+ expect(expectedTexts).to.eql(metricValue);
+ });
+ });
+ });
+ });
+
+ });
+ });
+}
diff --git a/test/functional/apps/visualize/_metric_chart.js b/test/functional/apps/visualize/_metric_chart.js
deleted file mode 100644
index 401d69eb51932..0000000000000
--- a/test/functional/apps/visualize/_metric_chart.js
+++ /dev/null
@@ -1,263 +0,0 @@
-import expect from 'expect.js';
-
-export default function ({ getService, getPageObjects }) {
- const log = getService('log');
- const retry = getService('retry');
- const screenshots = getService('screenshots');
- const PageObjects = getPageObjects(['common', 'visualize', 'header']);
-
- describe('visualize app', function describeIndexTests() {
- const fromTime = '2015-09-19 06:31:44.000';
- const toTime = '2015-09-23 18:31:44.000';
-
- before(function () {
- log.debug('navigateToApp visualize');
- return PageObjects.common.navigateToUrl('visualize', 'new')
- .then(function () {
- log.debug('clickMetric');
- return PageObjects.visualize.clickMetric();
- })
- .then(function clickNewSearch() {
- return PageObjects.visualize.clickNewSearch();
- })
- .then(function setAbsoluteRange() {
- log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"');
- return PageObjects.header.setAbsoluteRange(fromTime, toTime);
- });
- });
-
- describe('metric chart', function indexPatternCreation() {
-
- it('should show Count', function () {
- const expectedCount = ['14,004', 'Count'];
-
- // initial metric of "Count" is selected by default
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- screenshots.take('Visualize-metric-chart');
- expect(expectedCount).to.eql(metricValue.split('\n'));
- });
- });
- });
-
- it('should show Average', function () {
- const avgMachineRam = ['13,104,036,080.615', 'Average machine.ram'];
- return PageObjects.visualize.clickMetricEditor()
- .then(function () {
- log.debug('Aggregation = Average');
- return PageObjects.visualize.selectAggregation('Average');
- })
- .then(function selectField() {
- log.debug('Field = machine.ram');
- return PageObjects.visualize.selectField('machine.ram', 'metrics');
- })
- .then(function clickGo() {
- return PageObjects.visualize.clickGo();
- })
- .then(function () {
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- expect(avgMachineRam).to.eql(metricValue.split('\n'));
- });
- });
- });
- });
-
- it('should show Sum', function () {
- const sumPhpMemory = ['85,865,880', 'Sum of phpmemory'];
- log.debug('Aggregation = Sum');
- return PageObjects.visualize.selectAggregation('Sum')
- .then(function selectField() {
- log.debug('Field = phpmemory');
- return PageObjects.visualize.selectField('phpmemory', 'metrics');
- })
- .then(function clickGo() {
- return PageObjects.visualize.clickGo();
- })
- .then(function () {
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- expect(sumPhpMemory).to.eql(metricValue.split('\n'));
- });
- });
- });
- });
-
- it('should show Median', function () {
- const medianBytes = ['5,565.263', '50th percentile of bytes'];
- // For now, only comparing the text label part of the metric
- log.debug('Aggregation = Median');
- return PageObjects.visualize.selectAggregation('Median')
- .then(function selectField() {
- log.debug('Field = bytes');
- return PageObjects.visualize.selectField('bytes', 'metrics');
- })
- .then(function clickGo() {
- return PageObjects.visualize.clickGo();
- })
- .then(function () {
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- // only comparing the text label!
- expect(medianBytes[1]).to.eql(metricValue.split('\n')[1]);
- });
- });
- });
- });
-
- it('should show Min', function () {
- const minTimestamp = ['September 20th 2015, 00:00:00.000', 'Min @timestamp'];
- log.debug('Aggregation = Min');
- return PageObjects.visualize.selectAggregation('Min')
- .then(function selectField() {
- log.debug('Field = @timestamp');
- return PageObjects.visualize.selectField('@timestamp', 'metrics');
- })
- .then(function clickGo() {
- return PageObjects.visualize.clickGo();
- })
- .then(function () {
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- expect(minTimestamp).to.eql(metricValue.split('\n'));
- });
- });
- });
- });
-
- it('should show Max', function () {
- const maxRelatedContentArticleModifiedTime = ['April 4th 2015, 00:54:41.000', 'Max relatedContent.article:modified_time'];
- log.debug('Aggregation = Max');
- return PageObjects.visualize.selectAggregation('Max')
- .then(function selectField() {
- log.debug('Field = relatedContent.article:modified_time');
- return PageObjects.visualize.selectField('relatedContent.article:modified_time', 'metrics');
- })
- .then(function clickGo() {
- return PageObjects.visualize.clickGo();
- })
- .then(function () {
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- expect(maxRelatedContentArticleModifiedTime).to.eql(metricValue.split('\n'));
- });
- });
- });
- });
-
- it('should show Standard Deviation', function () {
- const standardDeviationBytes = [
- '-1,435.138', 'Lower Standard Deviation of bytes',
- '12,889.766', 'Upper Standard Deviation of bytes'
- ];
- log.debug('Aggregation = Standard Deviation');
- return PageObjects.visualize.selectAggregation('Standard Deviation')
- .then(function selectField() {
- log.debug('Field = bytes');
- return PageObjects.visualize.selectField('bytes', 'metrics');
- })
- .then(function clickGo() {
- return PageObjects.visualize.clickGo();
- })
- .then(function () {
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- expect(standardDeviationBytes).to.eql(metricValue.split('\n'));
- });
- });
- });
- });
-
- it('should show Unique Count', function () {
- const uniqueCountClientip = ['1,000', 'Unique count of clientip'];
- log.debug('Aggregation = Unique Count');
- return PageObjects.visualize.selectAggregation('Unique Count')
- .then(function selectField() {
- log.debug('Field = clientip');
- return PageObjects.visualize.selectField('clientip', 'metrics');
- })
- .then(function clickGo() {
- return PageObjects.visualize.clickGo();
- })
- .then(function () {
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- expect(uniqueCountClientip).to.eql(metricValue.split('\n'));
- });
- });
- })
- .then(function () {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- log.debug('metricValue=' + metricValue.split('\n'));
- expect(uniqueCountClientip).to.eql(metricValue.split('\n'));
- });
- });
- });
-
- it('should show Percentiles', function () {
- const percentileMachineRam = [
- '2,147,483,648', '1st percentile of machine.ram',
- '3,221,225,472', '5th percentile of machine.ram',
- '7,516,192,768', '25th percentile of machine.ram',
- '12,884,901,888', '50th percentile of machine.ram',
- '18,253,611,008', '75th percentile of machine.ram',
- '32,212,254,720', '95th percentile of machine.ram',
- '32,212,254,720', '99th percentile of machine.ram'
- ];
-
- log.debug('Aggregation = Percentiles');
- return PageObjects.visualize.selectAggregation('Percentiles')
- .then(function selectField() {
- log.debug('Field = machine.ram');
- return PageObjects.visualize.selectField('machine.ram', 'metrics');
- })
- .then(function clickGo() {
- return PageObjects.visualize.clickGo();
- })
- .then(function () {
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- expect(percentileMachineRam).to.eql(metricValue.split('\n'));
- });
- });
- });
- });
-
- it('should show Percentile Ranks', function () {
- const percentileRankBytes = [ '2.036%', 'Percentile rank 99 of "memory"'];
- log.debug('Aggregation = Percentile Ranks');
- return PageObjects.visualize.selectAggregation('Percentile Ranks')
- .then(function selectField() {
- log.debug('Field = bytes');
- return PageObjects.visualize.selectField('memory', 'metrics');
- })
- .then(function selectField() {
- log.debug('Values = 99');
- return PageObjects.visualize.setValue('99');
- })
- .then(function clickGo() {
- return PageObjects.visualize.clickGo();
- })
- .then(function () {
- return retry.try(function tryingForTime() {
- return PageObjects.visualize.getMetric()
- .then(function (metricValue) {
- expect(percentileRankBytes).to.eql(metricValue.split('\n'));
- });
- });
- });
- });
-
- });
- });
-}
diff --git a/test/functional/apps/visualize/index.js b/test/functional/apps/visualize/index.js
index 7f1235ee18d11..1c47c1717c076 100644
--- a/test/functional/apps/visualize/index.js
+++ b/test/functional/apps/visualize/index.js
@@ -24,10 +24,10 @@ export default function ({ getService, loadTestFile }) {
loadTestFile(require.resolve('./_editor'));
loadTestFile(require.resolve('./_chart_types'));
+ loadTestFile(require.resolve('./_gauge_chart'));
loadTestFile(require.resolve('./_area_chart'));
loadTestFile(require.resolve('./_line_chart'));
loadTestFile(require.resolve('./_data_table'));
- loadTestFile(require.resolve('./_metric_chart'));
loadTestFile(require.resolve('./_pie_chart'));
loadTestFile(require.resolve('./_tag_cloud'));
loadTestFile(require.resolve('./_tile_map'));
diff --git a/test/functional/page_objects/visualize_page.js b/test/functional/page_objects/visualize_page.js
index 834fdf519c6ff..61465f1430a4e 100644
--- a/test/functional/page_objects/visualize_page.js
+++ b/test/functional/page_objects/visualize_page.js
@@ -50,6 +50,13 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
.click();
}
+ clickGauge() {
+ return remote
+ .setFindTimeout(defaultFindTimeout)
+ .findByPartialLinkText('Gauge')
+ .click();
+ }
+
clickPieChart() {
return remote
.setFindTimeout(defaultFindTimeout)
@@ -167,6 +174,13 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
.getVisibleText();
}
+ getGaugeValue() {
+ return remote
+ .setFindTimeout(2000)
+ .findAllByCssSelector('visualize .chart svg')
+ .getVisibleText();
+ }
+
clickMetricEditor() {
return remote
.setFindTimeout(defaultFindTimeout)