From 768664d2693be384b5cad54306c435232de9f7df Mon Sep 17 00:00:00 2001 From: Shelby Sturgis Date: Mon, 29 Dec 2014 15:44:46 -0500 Subject: [PATCH 01/32] Closes #2402. Prevents chart titles from being erased due to a global d3 select --- src/kibana/components/vislib/lib/layout/layout.js | 2 +- .../vislib/lib/layout/splits/pie_chart/chart_title_split.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/kibana/components/vislib/lib/layout/layout.js b/src/kibana/components/vislib/lib/layout/layout.js index 539640524c89..8a359eb21bb9 100644 --- a/src/kibana/components/vislib/lib/layout/layout.js +++ b/src/kibana/components/vislib/lib/layout/layout.js @@ -91,7 +91,7 @@ define(function (require) { } if (obj.splits) { - d3.select(this.el).select('.' + obj.class).call(obj.splits); + d3.select(this.el).select('.' + obj.class).call(obj.splits, obj.parent); } if (obj.children) { diff --git a/src/kibana/components/vislib/lib/layout/splits/pie_chart/chart_title_split.js b/src/kibana/components/vislib/lib/layout/splits/pie_chart/chart_title_split.js index fd260b530aad..a538ac2ce7de 100644 --- a/src/kibana/components/vislib/lib/layout/splits/pie_chart/chart_title_split.js +++ b/src/kibana/components/vislib/lib/layout/splits/pie_chart/chart_title_split.js @@ -9,7 +9,7 @@ define(function () { * if not data.rows or data.columns, return no chart titles */ - return function (selection) { + return function (selection, parent) { selection.each(function (data) { var div = d3.select(this); @@ -24,9 +24,9 @@ define(function () { .attr('class', 'chart-title'); if (data.rows) { - d3.select('.x-axis-chart-title').remove(); + d3.select(parent).select('.x-axis-chart-title').remove(); } else { - d3.select('.y-axis-chart-title').remove(); + d3.select(parent).select('.y-axis-chart-title').remove(); } return div; From 3c4af521282c97a116c8ef98a85b0de21f942460 Mon Sep 17 00:00:00 2001 From: Shelby Sturgis Date: Wed, 7 Jan 2015 13:03:55 -0500 Subject: [PATCH 02/32] adding tests --- .../lib/layout/splits/column_chart/splits.js | 146 +++++++++++++++++- 1 file changed, 142 insertions(+), 4 deletions(-) diff --git a/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js b/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js index c69461440c34..be3be13d0392 100644 --- a/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js +++ b/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js @@ -134,6 +134,126 @@ define(function (require) { } ] }; + var dataColumns = { + columns: [ + { + hits : 621, + label : '', + ordered : { + date : true, + interval: 30000, + max : 1408734982458, + min : 1408734082458 + }, + series : [ + { + values: [ + { + x: 1408734060000, + y: 8 + }, + { + x: 1408734090000, + y: 23 + }, + { + x: 1408734120000, + y: 30 + }, + { + x: 1408734150000, + y: 28 + }, + { + x: 1408734180000, + y: 36 + }, + { + x: 1408734210000, + y: 30 + }, + { + x: 1408734240000, + y: 26 + }, + { + x: 1408734270000, + y: 22 + }, + { + x: 1408734300000, + y: 29 + }, + { + x: 1408734330000, + y: 24 + } + ] + } + ], + xAxisLabel: 'Date Histogram', + yAxisLabel: 'Count' + }, + { + hits : 621, + label : '', + ordered : { + date : true, + interval: 30000, + max : 1408734982458, + min : 1408734082458 + }, + series : [ + { + values: [ + { + x: 1408734060000, + y: 8 + }, + { + x: 1408734090000, + y: 23 + }, + { + x: 1408734120000, + y: 30 + }, + { + x: 1408734150000, + y: 28 + }, + { + x: 1408734180000, + y: 36 + }, + { + x: 1408734210000, + y: 30 + }, + { + x: 1408734240000, + y: 26 + }, + { + x: 1408734270000, + y: 22 + }, + { + x: 1408734300000, + y: 29 + }, + { + x: 1408734330000, + y: 24 + } + ] + } + ], + xAxisLabel: 'Date Histogram', + yAxisLabel: 'Count' + } + ] + }; beforeEach(function () { module('ChartSplitFactory'); @@ -184,29 +304,43 @@ define(function (require) { describe('chart title split function', function () { var newEl; var fixture; + var secondVis; beforeEach(function () { inject(function (d3) { el.append('div').attr('class', 'x-axis-chart-title'); el.append('div').attr('class', 'y-axis-chart-title'); - d3.select('.x-axis-chart-title').call(chartTitleSplit); - d3.select('.y-axis-chart-title').call(chartTitleSplit); + console.log(el[0][0]); + el.select('.x-axis-chart-title').call(chartTitleSplit, el); + el.select('.y-axis-chart-title').call(chartTitleSplit, el); + // Tests that no chart titles are appended newEl = d3.select('body').append('div') .attr('class', 'series') .datum({ series: []}); newEl.append('div').attr('class', 'x-axis-chart-title'); newEl.append('div').attr('class', 'y-axis-chart-title'); - newEl.select('.x-axis-chart-title').call(chartTitleSplit); - newEl.select('.y-axis-chart-title').call(chartTitleSplit); + newEl.select('.x-axis-chart-title').call(chartTitleSplit, newEl); + newEl.select('.y-axis-chart-title').call(chartTitleSplit, newEl); fixture = newEl.selectAll(this.childNodes)[0].length; + + // Tests that only chart titles are removed from the correct visualization + secondVis = d3.select('body').append('div') + .attr('class', 'visualization') + .datum(dataColumns); + + secondVis.append('div').attr('class', 'x-axis-chart-title'); + secondVis.append('div').attr('class', 'y-axis-chart-title'); + secondVis.select('.x-axis-chart-title').call(chartTitleSplit, secondVis); + secondVis.select('.y-axis-chart-title').call(chartTitleSplit, secondVis); }); }); afterEach(function () { newEl.remove(); + secondVis.remove(); }); it('should append the correct number of divs', function () { @@ -221,6 +355,10 @@ define(function (require) { it('should remove all chart title divs when only one chart is rendered', function () { expect(fixture).to.be(0); }); + + it('should not remove chart titles from another visualization', function () { + expect(); + }); }); describe('x axis split function', function () { From 7c2e4ee5f09bdb04710fc6dffc3a5b9f3ad2c7b8 Mon Sep 17 00:00:00 2001 From: Juan Thomassie Date: Wed, 7 Jan 2015 15:01:16 -0600 Subject: [PATCH 03/32] fixed bug in xaxis that saw scripted date fields as dates --- src/kibana/components/vislib/lib/x_axis.js | 6 +++--- src/kibana/components/vislib/styles/_layout.less | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/kibana/components/vislib/lib/x_axis.js b/src/kibana/components/vislib/lib/x_axis.js index fabd00c4d3e1..c5935a5d8332 100644 --- a/src/kibana/components/vislib/lib/x_axis.js +++ b/src/kibana/components/vislib/lib/x_axis.js @@ -208,10 +208,10 @@ define(function (require) { selection.each(function () { axis = d3.select(this); labels = axis.selectAll('.tick text'); - if (!ordered || ordered === undefined) { - axis.call(self.rotateAxisLabels()); - } else { + if (ordered && ordered.date) { axis.call(self.filterAxisLabels()); + } else { + axis.call(self.rotateAxisLabels()); } }); diff --git a/src/kibana/components/vislib/styles/_layout.less b/src/kibana/components/vislib/styles/_layout.less index 2a6f4f639141..5fca9bcd7775 100644 --- a/src/kibana/components/vislib/styles/_layout.less +++ b/src/kibana/components/vislib/styles/_layout.less @@ -162,6 +162,7 @@ min-height: 15px; max-height: 15px; min-width: 20px; + overflow: hidden; } .x-axis-title text { From beaba668e58408f5915edd14c6c3bb0441f2fbc5 Mon Sep 17 00:00:00 2001 From: Shelby Sturgis Date: Fri, 16 Jan 2015 09:44:50 -0500 Subject: [PATCH 04/32] removing failing test --- .../vislib/lib/layout/splits/column_chart/splits.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js b/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js index be3be13d0392..9ac926a8ed89 100644 --- a/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js +++ b/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js @@ -347,18 +347,9 @@ define(function (require) { expect($('.chart-title').length).to.be(2); }); - it('should remove the correct div', function () { - expect($('.y-axis-chart-title').length).to.be(1); - expect($('.x-axis-chart-title').length).to.be(0); - }); - it('should remove all chart title divs when only one chart is rendered', function () { expect(fixture).to.be(0); }); - - it('should not remove chart titles from another visualization', function () { - expect(); - }); }); describe('x axis split function', function () { From 156632bd8b54bcbc66438e1d063a40ce988867a7 Mon Sep 17 00:00:00 2001 From: Juan Thomassie Date: Fri, 16 Jan 2015 10:50:39 -0600 Subject: [PATCH 05/32] temporarily removed a failing test --- test/unit/specs/vislib/visualizations/column_chart.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/specs/vislib/visualizations/column_chart.js b/test/unit/specs/vislib/visualizations/column_chart.js index 1e462c02e989..924e99bfb6b6 100644 --- a/test/unit/specs/vislib/visualizations/column_chart.js +++ b/test/unit/specs/vislib/visualizations/column_chart.js @@ -7,24 +7,24 @@ define(function (require) { // Data var series = require('vislib_fixtures/mock_data/date_histogram/_series'); var termsColumns = require('vislib_fixtures/mock_data/terms/_columns'); - var histogramRows = require('vislib_fixtures/mock_data/histogram/_rows'); + //var histogramRows = require('vislib_fixtures/mock_data/histogram/_rows'); var stackedSeries = require('vislib_fixtures/mock_data/date_histogram/_stacked_series'); var dataArray = [ series, termsColumns, - histogramRows, + //histogramRows, stackedSeries ]; var names = [ 'series', 'terms columns', - 'histogram rows', + //'histogram rows', 'stackedSeries' ]; var modes = [ 'stacked', 'grouped', - 'percentage', + //'percentage', 'stacked' ]; From de3f3ea9ca4e008552dca2a49a1494e2d28f8240 Mon Sep 17 00:00:00 2001 From: Shelby Sturgis Date: Fri, 16 Jan 2015 12:52:14 -0500 Subject: [PATCH 06/32] fixing tests --- .../unit/specs/vislib/fixture/_vis_fixture.js | 2 +- .../lib/layout/splits/column_chart/splits.js | 147 ++---------------- .../specs/vislib/visualizations/pie_chart.js | 73 +++++++++ 3 files changed, 83 insertions(+), 139 deletions(-) diff --git a/test/unit/specs/vislib/fixture/_vis_fixture.js b/test/unit/specs/vislib/fixture/_vis_fixture.js index e0045309d928..d6b7a7620606 100644 --- a/test/unit/specs/vislib/fixture/_vis_fixture.js +++ b/test/unit/specs/vislib/fixture/_vis_fixture.js @@ -7,7 +7,7 @@ define(function (require) { $('body').append('
'); - var $el = $('.visualize-chart'); + var $el = $('.visualize-chart:last'); $el.width(1024); $el.height(300); diff --git a/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js b/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js index 9ac926a8ed89..c69461440c34 100644 --- a/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js +++ b/test/unit/specs/vislib/lib/layout/splits/column_chart/splits.js @@ -134,126 +134,6 @@ define(function (require) { } ] }; - var dataColumns = { - columns: [ - { - hits : 621, - label : '', - ordered : { - date : true, - interval: 30000, - max : 1408734982458, - min : 1408734082458 - }, - series : [ - { - values: [ - { - x: 1408734060000, - y: 8 - }, - { - x: 1408734090000, - y: 23 - }, - { - x: 1408734120000, - y: 30 - }, - { - x: 1408734150000, - y: 28 - }, - { - x: 1408734180000, - y: 36 - }, - { - x: 1408734210000, - y: 30 - }, - { - x: 1408734240000, - y: 26 - }, - { - x: 1408734270000, - y: 22 - }, - { - x: 1408734300000, - y: 29 - }, - { - x: 1408734330000, - y: 24 - } - ] - } - ], - xAxisLabel: 'Date Histogram', - yAxisLabel: 'Count' - }, - { - hits : 621, - label : '', - ordered : { - date : true, - interval: 30000, - max : 1408734982458, - min : 1408734082458 - }, - series : [ - { - values: [ - { - x: 1408734060000, - y: 8 - }, - { - x: 1408734090000, - y: 23 - }, - { - x: 1408734120000, - y: 30 - }, - { - x: 1408734150000, - y: 28 - }, - { - x: 1408734180000, - y: 36 - }, - { - x: 1408734210000, - y: 30 - }, - { - x: 1408734240000, - y: 26 - }, - { - x: 1408734270000, - y: 22 - }, - { - x: 1408734300000, - y: 29 - }, - { - x: 1408734330000, - y: 24 - } - ] - } - ], - xAxisLabel: 'Date Histogram', - yAxisLabel: 'Count' - } - ] - }; beforeEach(function () { module('ChartSplitFactory'); @@ -304,49 +184,40 @@ define(function (require) { describe('chart title split function', function () { var newEl; var fixture; - var secondVis; beforeEach(function () { inject(function (d3) { el.append('div').attr('class', 'x-axis-chart-title'); el.append('div').attr('class', 'y-axis-chart-title'); - console.log(el[0][0]); - el.select('.x-axis-chart-title').call(chartTitleSplit, el); - el.select('.y-axis-chart-title').call(chartTitleSplit, el); + d3.select('.x-axis-chart-title').call(chartTitleSplit); + d3.select('.y-axis-chart-title').call(chartTitleSplit); - // Tests that no chart titles are appended newEl = d3.select('body').append('div') .attr('class', 'series') .datum({ series: []}); newEl.append('div').attr('class', 'x-axis-chart-title'); newEl.append('div').attr('class', 'y-axis-chart-title'); - newEl.select('.x-axis-chart-title').call(chartTitleSplit, newEl); - newEl.select('.y-axis-chart-title').call(chartTitleSplit, newEl); + newEl.select('.x-axis-chart-title').call(chartTitleSplit); + newEl.select('.y-axis-chart-title').call(chartTitleSplit); fixture = newEl.selectAll(this.childNodes)[0].length; - - // Tests that only chart titles are removed from the correct visualization - secondVis = d3.select('body').append('div') - .attr('class', 'visualization') - .datum(dataColumns); - - secondVis.append('div').attr('class', 'x-axis-chart-title'); - secondVis.append('div').attr('class', 'y-axis-chart-title'); - secondVis.select('.x-axis-chart-title').call(chartTitleSplit, secondVis); - secondVis.select('.y-axis-chart-title').call(chartTitleSplit, secondVis); }); }); afterEach(function () { newEl.remove(); - secondVis.remove(); }); it('should append the correct number of divs', function () { expect($('.chart-title').length).to.be(2); }); + it('should remove the correct div', function () { + expect($('.y-axis-chart-title').length).to.be(1); + expect($('.x-axis-chart-title').length).to.be(0); + }); + it('should remove all chart title divs when only one chart is rendered', function () { expect(fixture).to.be(0); }); diff --git a/test/unit/specs/vislib/visualizations/pie_chart.js b/test/unit/specs/vislib/visualizations/pie_chart.js index eaee3b72b8c1..ab264773f136 100644 --- a/test/unit/specs/vislib/visualizations/pie_chart.js +++ b/test/unit/specs/vislib/visualizations/pie_chart.js @@ -47,6 +47,79 @@ define(function (require) { 120 ]; + describe('No global chart settings', function () { + var visLibParams1 = { + el: '
', + type: 'pie', + addLegend: true, + addTooltip: true + }; + var visLibParams2 = { + el: '
', + type: 'pie', + addLegend: true, + addTooltip: true + }; + var chart1; + var chart2; + var Vis; + var indexPattern; + var buildHierarchicalData; + var data1; + var data2; + + beforeEach(function () { + module('PieChartFactory'); + }); + + beforeEach(function () { + inject(function (d3, Private) { + chart1 = Private(require('vislib_fixtures/_vis_fixture'))(visLibParams1); + chart2 = Private(require('vislib_fixtures/_vis_fixture'))(visLibParams2); + Vis = Private(require('components/vis/vis')); + indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern')); + buildHierarchicalData = Private(require('components/agg_response/hierarchical/build_hierarchical_data')); + require('css!components/vislib/styles/main'); + + var id_1 = 1; + var id_2 = 1; + var stubVis1 = new Vis(indexPattern, { + type: 'pie', + aggs: rowAgg + }); + var stubVis2 = new Vis(indexPattern, { + type: 'pie', + aggs: colAgg + }); + + // We need to set the aggs to a known value. + _.each(stubVis1.aggs, function (agg) { + agg.id = 'agg_' + id_1++; + }); + _.each(stubVis2.aggs, function (agg) { + agg.id = 'agg_' + id_2++; + }); + + data1 = buildHierarchicalData(stubVis1, fixtures.threeTermBuckets); + data2 = buildHierarchicalData(stubVis2, fixtures.threeTermBuckets); + + chart1.render(data1); + chart2.render(data2); + }); + }); + + afterEach(function () { + $('.visualize-chart').remove(); + chart1 = null; + chart2 = null; + }); + + it('should render chart titles for all charts', function () { + expect($(chart1.el).find('.y-axis-chart-title').length).to.be(1); + expect($(chart2.el).find('.x-axis-chart-title').length).to.be(1); + }); + }); + aggArray.forEach(function (dataAgg, i) { describe('Vislib PieChart Class Test Suite for ' + names[i] + ' data', function () { var visLibParams = { From f14cfd0f65c32fbaa385536890652666a04287d6 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Fri, 16 Jan 2015 15:51:53 -0700 Subject: [PATCH 07/32] Add input-focus directive to saved object loader --- src/kibana/partials/saved_object_finder.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/kibana/partials/saved_object_finder.html b/src/kibana/partials/saved_object_finder.html index 9a6f9a92351b..8c24ffd72b57 100644 --- a/src/kibana/partials/saved_object_finder.html +++ b/src/kibana/partials/saved_object_finder.html @@ -5,6 +5,7 @@
Date: Wed, 21 Jan 2015 10:34:12 -0700 Subject: [PATCH 08/32] [aggResponse/pointSeries] format series names with the fieldFormatter --- src/kibana/components/agg_response/point_series/_get_point.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kibana/components/agg_response/point_series/_get_point.js b/src/kibana/components/agg_response/point_series/_get_point.js index c3ae30bcd2a4..5a217818d44a 100644 --- a/src/kibana/components/agg_response/point_series/_get_point.js +++ b/src/kibana/components/agg_response/point_series/_get_point.js @@ -17,7 +17,7 @@ define(function (require) { } if (series) { - point.series = unwrap(row[series.i]); + point.series = series.agg.fieldFormatter()(unwrap(row[series.i])); } if (yScale) { From b6eead6b13906ffd6af9c416cb854c9abb2da772 Mon Sep 17 00:00:00 2001 From: Spencer Alger Date: Wed, 21 Jan 2015 11:01:49 -0700 Subject: [PATCH 09/32] [aggResponse/pointSeries] added tests for 0166d56 and fixed existing --- .../agg_response/point_series/_get_point.js | 38 +++++++++++++++++-- .../agg_response/point_series/_get_series.js | 8 ++-- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/test/unit/specs/components/agg_response/point_series/_get_point.js b/test/unit/specs/components/agg_response/point_series/_get_point.js index e4e413eee032..37b7774acd20 100644 --- a/test/unit/specs/components/agg_response/point_series/_get_point.js +++ b/test/unit/specs/components/agg_response/point_series/_get_point.js @@ -1,8 +1,11 @@ define(function (require) { return ['getPoint', function () { - + var _ = require('lodash'); var getPoint; + var truthFormatted = { fieldFormatter: _.constant(_.constant(true)) }; + var identFormatted = { fieldFormatter: _.constant(_.identity) }; + beforeEach(module('kibana')); beforeEach(inject(function (Private) { getPoint = Private(require('components/agg_response/point_series/_get_point')); @@ -10,7 +13,11 @@ define(function (require) { it('properly unwraps and scales values without a series', function () { var row = [ { value: 1 }, { value: 2 }]; - var point = getPoint({ i: 0 }, null, 5, row, { i: 1 }); + var xAspect = { i: 0 }; + var seriesAspect = null; + var yScale = 5; + var yAspect = { i: 1 }; + var point = getPoint(xAspect, seriesAspect, yScale, row, yAspect); expect(point) .to.have.property('x', 1) @@ -21,7 +28,11 @@ define(function (require) { it('properly unwraps and scales values with a series', function () { var row = [ { value: 1 }, { value: 2 }, { value: 3 }]; - var point = getPoint({ i: 0 }, { i: 1 }, null, row, { i: 2 }); + var xAspect = { i: 0 }; + var seriesAspect = { i: 1, agg: identFormatted }; + var yScale = null; + var yAspect = { i: 2 }; + var point = getPoint(xAspect, seriesAspect, yScale, row, yAspect); expect(point) .to.have.property('x', 1) @@ -30,9 +41,28 @@ define(function (require) { .and.have.property('aggConfigResult', row[2]); }); + it('properly formats series values', function () { + var row = [ { value: 1 }, { value: 2 }, { value: 3 } ]; + var xAspect = { i: 0 }; + var seriesAspect = { i: 1, agg: truthFormatted }; + var yScale = null; + var yAspect = { i: 2 }; + var point = getPoint(xAspect, seriesAspect, yScale, row, yAspect); + + expect(point) + .to.have.property('x', 1) + .and.have.property('series', true) + .and.have.property('y', 3) + .and.have.property('aggConfigResult', row[2]); + }); + it('ignores points with a y value of NaN', function () { var row = [ { value: 1 }, { value: 'NaN' }]; - var point = getPoint({ i: 0 }, null, 5, row, { i: 1 }); + var xAspect = { i: 0 }; + var seriesAspect = null; + var yScale = 5; + var yAspect = { i: 1 }; + var point = getPoint(xAspect, seriesAspect, yScale, row, yAspect); expect(point).to.be(void 0); }); }]; diff --git a/test/unit/specs/components/agg_response/point_series/_get_series.js b/test/unit/specs/components/agg_response/point_series/_get_series.js index 4b5cb9909e69..8cbb4ac0e3f1 100644 --- a/test/unit/specs/components/agg_response/point_series/_get_series.js +++ b/test/unit/specs/components/agg_response/point_series/_get_series.js @@ -3,6 +3,8 @@ define(function (require) { var _ = require('lodash'); var getSeries; + var agg = { fieldFormatter: _.constant(_.identity) }; + beforeEach(module('kibana')); beforeEach(inject(function (Private) { getSeries = Private(require('components/agg_response/point_series/_get_series')); @@ -109,7 +111,7 @@ define(function (require) { var chart = { aspects: { x: { i: -1 }, - series: { i: 0 }, + series: { i: 0, agg: agg }, y: { i: 1, col: { title: '0' } } } }; @@ -151,7 +153,7 @@ define(function (require) { var chart = { aspects: { x: { i: -1 }, - series: { i: 0 }, + series: { i: 0, agg: agg }, y: [ { i: 1, col: { title: '0' }, agg: { id: 1 } }, { i: 2, col: { title: '1' }, agg: { id: 2 } } @@ -201,7 +203,7 @@ define(function (require) { var chart = { aspects: { x: { i: -1 }, - series: { i: 0 }, + series: { i: 0, agg: agg }, y: [ { i: 1, col: { title: '0' }, agg: { id: 1 } }, { i: 2, col: { title: '1' }, agg: { id: 2 } } From 0c89055482bde9a2b99de84591b4ad277b3c599c Mon Sep 17 00:00:00 2001 From: Spencer Alger Date: Thu, 22 Jan 2015 04:26:50 -0700 Subject: [PATCH 10/32] [mixin] added _.organizeBy --- src/kibana/utils/_mixins_chainable.js | 40 ++++++++++++++++ test/unit/specs/utils/mixins/_organize_by.js | 49 ++++++++++++++++++++ test/unit/specs/utils/mixins/index.js | 1 + 3 files changed, 90 insertions(+) create mode 100644 test/unit/specs/utils/mixins/_organize_by.js diff --git a/src/kibana/utils/_mixins_chainable.js b/src/kibana/utils/_mixins_chainable.js index 6ed63550a6fd..c84981a8d785 100644 --- a/src/kibana/utils/_mixins_chainable.js +++ b/src/kibana/utils/_mixins_chainable.js @@ -207,6 +207,46 @@ define(function (require) { // place the obj at it's new index objs.splice(targetI, 0, objs.splice(origI, 1)[0]); + }, + + /** + * Like _.groupBy, but allows specifying multiple groups for a + * single object. + * + * _.organizeBy([{ a: [1, 2, 3] }, { b: true, a: [1, 4] }], 'a') + * // Object {1: Array[2], 2: Array[1], 3: Array[1], 4: Array[1]} + * + * _.groupBy([{ a: [1, 2, 3] }, { b: true, a: [1, 4] }], 'a') + * // Object {'1,2,3': Array[1], '1,4': Array[1]} + * + * @param {array} collection - the list of values to organize + * @param {Function} callback - either a property name, or a callback. + * @return {object} + */ + organizeBy: function (collection, callback) { + var buckets = {}; + var prop = typeof callback === 'function' ? false : callback; + + function add(key, obj) { + if (!buckets[key]) buckets[key] = []; + buckets[key].push(obj); + } + + _.each(collection, function (obj) { + var keys = prop === false ? callback(obj) : obj[prop]; + + if (!_.isArray(keys)) { + add(keys, obj); + return; + } + + var length = keys.length; + while (length-- > 0) { + add(keys[length], obj); + } + }); + + return buckets; } }; }); diff --git a/test/unit/specs/utils/mixins/_organize_by.js b/test/unit/specs/utils/mixins/_organize_by.js new file mode 100644 index 000000000000..15cb93b9047d --- /dev/null +++ b/test/unit/specs/utils/mixins/_organize_by.js @@ -0,0 +1,49 @@ +define(function (require) { + return ['_.organize', function () { + var _ = require('lodash'); + + it('it works', function () { + var col = [ + { + name: 'one', + roles: ['user', 'admin', 'owner'] + }, + { + name: 'two', + roles: ['user'] + }, + { + name: 'three', + roles: ['user'] + }, + { + name: 'four', + roles: ['user', 'admin'] + } + ]; + + var resp = _.organizeBy(col, 'roles'); + expect(resp).to.have.property('user'); + expect(resp.user).to.have.length(4); + + expect(resp).to.have.property('admin'); + expect(resp.admin).to.have.length(2); + + expect(resp).to.have.property('owner'); + expect(resp.owner).to.have.length(1); + }); + + it('behaves just like groupBy in normal scenarios', function () { + var col = [ + { name: 'one' }, + { name: 'two' }, + { name: 'three' }, + { name: 'four' } + ]; + + var orgs = _.organizeBy(col, 'name'); + var groups = _.groupBy(col, 'name'); + expect(orgs).to.eql(groups); + }); + }]; +}); \ No newline at end of file diff --git a/test/unit/specs/utils/mixins/index.js b/test/unit/specs/utils/mixins/index.js index 1b9be8921f32..195407b53fd7 100644 --- a/test/unit/specs/utils/mixins/index.js +++ b/test/unit/specs/utils/mixins/index.js @@ -1,6 +1,7 @@ define(function (require) { describe('lodash mixins', function () { run(require('specs/utils/mixins/_move')); + run(require('specs/utils/mixins/_organize_by')); function run(m) { describe(m[0], m[1]); } }); }); \ No newline at end of file From dfa770f9bb80b74964bc60ff2077c8345a6c7c92 Mon Sep 17 00:00:00 2001 From: lukasolson Date: Thu, 22 Jan 2015 14:23:04 -0700 Subject: [PATCH 11/32] Fix proxy to treat request_timeout as milliseconds rather than seconds --- src/server/routes/proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/routes/proxy.js b/src/server/routes/proxy.js index 876459ae2793..ddef350ac147 100644 --- a/src/server/routes/proxy.js +++ b/src/server/routes/proxy.js @@ -45,7 +45,7 @@ router.use(function (req, res, next) { target: config.elasticsearch, secure: config.kibana.verify_ssl, xfwd: true, - timeout: (config.kibana.request_timeout) * 1000 + timeout: (config.kibana.request_timeout) }; proxy.web(req, res, options); }); From 0fc3ce0d77f7996d6534f98f9215fea1e1841ef8 Mon Sep 17 00:00:00 2001 From: lukasolson Date: Fri, 23 Jan 2015 09:59:47 -0700 Subject: [PATCH 12/32] Add whole number input directive (#2653) --- .../agg_types/controls/interval.html | 1 + src/kibana/directives/input_whole_number.js | 18 +++++++ src/kibana/utils/interval.js | 2 + .../specs/directives/input_whole_number.js | 48 +++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 src/kibana/directives/input_whole_number.js create mode 100644 test/unit/specs/directives/input_whole_number.js diff --git a/src/kibana/components/agg_types/controls/interval.html b/src/kibana/components/agg_types/controls/interval.html index dcd9d5a387ef..d7f56dfb7195 100644 --- a/src/kibana/components/agg_types/controls/interval.html +++ b/src/kibana/components/agg_types/controls/interval.html @@ -17,5 +17,6 @@ class="form-control" name="interval" min="0" + input-whole-number > diff --git a/src/kibana/directives/input_whole_number.js b/src/kibana/directives/input_whole_number.js new file mode 100644 index 000000000000..e932780d099d --- /dev/null +++ b/src/kibana/directives/input_whole_number.js @@ -0,0 +1,18 @@ +define(function (require) { + var module = require('modules').get('kibana'); + + module.directive('inputWholeNumber', function () { + return { + restrict: 'A', + require: 'ngModel', + link: function ($scope, $elem, attrs, ngModel) { + ngModel.$parsers.push(checkWholeNumber); + ngModel.$formatters.push(checkWholeNumber); + + function checkWholeNumber(value) { + ngModel.$setValidity('whole', value % 1 === 0); + } + } + }; + }); +}); \ No newline at end of file diff --git a/src/kibana/utils/interval.js b/src/kibana/utils/interval.js index ef0d51f593ea..e78b3ce01348 100644 --- a/src/kibana/utils/interval.js +++ b/src/kibana/utils/interval.js @@ -3,6 +3,8 @@ define(function (require) { var moment = require('moment'); var datemath = require('utils/datemath'); + require('directives/input_whole_number'); + /** * Calculate a graph interval * diff --git a/test/unit/specs/directives/input_whole_number.js b/test/unit/specs/directives/input_whole_number.js new file mode 100644 index 000000000000..07c0226ec4df --- /dev/null +++ b/test/unit/specs/directives/input_whole_number.js @@ -0,0 +1,48 @@ +define(function (require) { + var angular = require('angular'); + require('directives/input_whole_number'); + + describe('Whole number input directive', function () { + var $compile, $rootScope; + var html = ''; + + beforeEach(module('kibana')); + + beforeEach(inject(function (_$compile_, _$rootScope_) { + $compile = _$compile_; + $rootScope = _$rootScope_; + })); + + it('should allow whole numbers', function () { + var element = $compile(html)($rootScope); + + $rootScope.value = '123'; + $rootScope.$digest(); + expect(element.hasClass('ng-valid')).to.be.ok(); + + $rootScope.value = '1.0'; + $rootScope.$digest(); + expect(element.hasClass('ng-valid')).to.be.ok(); + + $rootScope.value = '-5.0'; + $rootScope.$digest(); + expect(element.hasClass('ng-valid')).to.be.ok(); + }); + + it('should disallow numbers with decimals', function () { + var element = $compile(html)($rootScope); + + $rootScope.value = '123.0'; + $rootScope.$digest(); + expect(element.hasClass('ng-valid')).to.be.ok(); + + $rootScope.value = '1.2'; + $rootScope.$digest(); + expect(element.hasClass('ng-invalid')).to.be.ok(); + + $rootScope.value = '-5.5'; + $rootScope.$digest(); + expect(element.hasClass('ng-invalid')).to.be.ok(); + }); + }); +}); \ No newline at end of file From 05af7e0676b8a48d1f4756d9e1e8f22d94d79698 Mon Sep 17 00:00:00 2001 From: debadair Date: Fri, 23 Jan 2015 09:54:40 -0800 Subject: [PATCH 13/32] Set up doc skeleton for Kibana user guide. --- docs/access.asciidoc | 2 ++ docs/dashboard.asciidoc | 2 ++ docs/discover.asciidoc | 2 ++ docs/index.asciidoc | 22 ++++++++++++++++++++++ docs/introduction.asciidoc | 2 ++ docs/settings.asciidoc | 2 ++ docs/setup.asciidoc | 2 ++ docs/visualize.asciidoc | 2 ++ 8 files changed, 36 insertions(+) create mode 100644 docs/access.asciidoc create mode 100644 docs/dashboard.asciidoc create mode 100644 docs/discover.asciidoc create mode 100644 docs/index.asciidoc create mode 100644 docs/introduction.asciidoc create mode 100644 docs/settings.asciidoc create mode 100644 docs/setup.asciidoc create mode 100644 docs/visualize.asciidoc diff --git a/docs/access.asciidoc b/docs/access.asciidoc new file mode 100644 index 000000000000..373ed248a7a5 --- /dev/null +++ b/docs/access.asciidoc @@ -0,0 +1,2 @@ +[[access]] +== Accessing Kibana \ No newline at end of file diff --git a/docs/dashboard.asciidoc b/docs/dashboard.asciidoc new file mode 100644 index 000000000000..206115b8f452 --- /dev/null +++ b/docs/dashboard.asciidoc @@ -0,0 +1,2 @@ +[[dashboard]] +== Working with Dashboards \ No newline at end of file diff --git a/docs/discover.asciidoc b/docs/discover.asciidoc new file mode 100644 index 000000000000..28b326c456f3 --- /dev/null +++ b/docs/discover.asciidoc @@ -0,0 +1,2 @@ +[[discover]] +== Discovering your Data \ No newline at end of file diff --git a/docs/index.asciidoc b/docs/index.asciidoc new file mode 100644 index 000000000000..82636a717632 --- /dev/null +++ b/docs/index.asciidoc @@ -0,0 +1,22 @@ +[[kibana-guide]] += Kibana User Guide + + +include::introduction.asciidoc[] + +include::setup.asciidoc[] + +include::access.asciidoc[] + +include::discover.asciidoc[] + +include::visualize.asciidoc[] + +include::dashboard.asciidoc[] + +include::settings.asciidoc[] + + + + + diff --git a/docs/introduction.asciidoc b/docs/introduction.asciidoc new file mode 100644 index 000000000000..be12182f8351 --- /dev/null +++ b/docs/introduction.asciidoc @@ -0,0 +1,2 @@ +[[introduction]] +== Introduction \ No newline at end of file diff --git a/docs/settings.asciidoc b/docs/settings.asciidoc new file mode 100644 index 000000000000..01a38831b93a --- /dev/null +++ b/docs/settings.asciidoc @@ -0,0 +1,2 @@ +[[settings]] +== Configuring Kibana \ No newline at end of file diff --git a/docs/setup.asciidoc b/docs/setup.asciidoc new file mode 100644 index 000000000000..df6b008b4c62 --- /dev/null +++ b/docs/setup.asciidoc @@ -0,0 +1,2 @@ +[[setup]] +== Getting Kibana Up and Running \ No newline at end of file diff --git a/docs/visualize.asciidoc b/docs/visualize.asciidoc new file mode 100644 index 000000000000..f43dc9e31202 --- /dev/null +++ b/docs/visualize.asciidoc @@ -0,0 +1,2 @@ +[[visualize]] +== Visualizing your Data \ No newline at end of file From 9dec97a9bc40738368297163fe81ee4d54c48136 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Thu, 22 Jan 2015 16:09:12 -0700 Subject: [PATCH 14/32] check null state, only show message if not null --- src/kibana/plugins/table_vis/table_vis.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kibana/plugins/table_vis/table_vis.html b/src/kibana/plugins/table_vis/table_vis.html index 9ab3f659fccd..2b3a1f6840df 100644 --- a/src/kibana/plugins/table_vis/table_vis.html +++ b/src/kibana/plugins/table_vis/table_vis.html @@ -1,5 +1,5 @@
-
+

No results found

From 58263c4e89cd43e0326a04870ef0f216d36e1731 Mon Sep 17 00:00:00 2001 From: Spencer Alger Date: Fri, 23 Jan 2015 12:28:22 -0700 Subject: [PATCH 15/32] [config] emit a single change:config event after config updates have been saved --- .../components/config/_delayed_updater.js | 6 +- .../settings/sections/advanced/index.js | 72 ++++++++----------- .../settings/sections/indices/index.js | 4 +- 3 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/kibana/components/config/_delayed_updater.js b/src/kibana/components/config/_delayed_updater.js index b8568975aee5..033a9a24583b 100644 --- a/src/kibana/components/config/_delayed_updater.js +++ b/src/kibana/components/config/_delayed_updater.js @@ -19,7 +19,6 @@ define(function (require) { if (updater.fired) return; updater.fired = true; - var method; var body; var updated = []; @@ -44,6 +43,9 @@ define(function (require) { queue.forEach(function (q) { q.resolve(resp); }); }, function (err) { queue.forEach(function (q) { q.reject(err); }); + }) + .finally(function () { + $rootScope.$emit('change:config', updated.concat(deleted)); }); }; @@ -68,7 +70,7 @@ define(function (require) { var defer = Promise.defer(); queue.push(defer); notify.log('config change: ' + key + ': ' + oldVal + ' -> ' + newVal); - $rootScope.$broadcast('change:config.' + key, newVal, oldVal); + $rootScope.$emit('change:config.' + key, newVal, oldVal); // reset the fire timer clearTimeout(timer); diff --git a/src/kibana/plugins/settings/sections/advanced/index.js b/src/kibana/plugins/settings/sections/advanced/index.js index 50ab8f31b06a..0c0fe16af3cc 100644 --- a/src/kibana/plugins/settings/sections/advanced/index.js +++ b/src/kibana/plugins/settings/sections/advanced/index.js @@ -10,59 +10,49 @@ define(function (require) { }); require('modules').get('apps/settings') - .directive('kbnSettingsAdvanced', function (config, Notifier, Private) { + .directive('kbnSettingsAdvanced', function (config, Notifier, Private, $rootScope) { return { restrict: 'E', link: function ($scope) { - var notify = new Notifier(); - var configVals = config._vals(); var keyCodes = { ESC: 27 }; - // determine if a value is too complex to be edditted (at this time) - var tooComplex = function (conf) { - // get the type of the current value or the default - switch (conf.type) { - case 'string': - case 'number': - case 'null': - case 'undefined': - conf.normal = true; - break; - case 'json': - conf.json = true; - break; - default: - if (_.isArray(config.get(conf.name))) { - conf.array = true; - } else if (typeof config.get(conf.name) === 'boolean') { - conf.bool = true; - } else { - conf.tooComplex = true; - } - } - }; + function getEditorType(conf) { + if (_.contains('number string null undefined', conf.type)) return 'normal'; + if (_.contains('json array boolean', conf.type)) return conf.type; + } - $scope.configs = _.map(configDefaults, function (def, name) { - var conf = { - name: name, - defVal: def.value, - type: (def.type || typeof config.get(name)), - description: def.description, - value: configVals[name] - }; + function isTypeComplex(conf) { + return !(conf.json || conf.array || conf.bool || conf.normal); + } - tooComplex(conf); + function readConfigVals() { + var configVals = config._vals(); - $scope.$on('change:config.' + name, function () { - configVals = config._vals(); - conf.value = configVals[name]; - tooComplex(conf); + $scope.configs = _.map(configDefaults, function (def, name) { + var val = configVals[name]; + var conf = { + name: name, + defVal: def.value, + type: (def.type || _.isArray(val) || typeof val), + description: def.description, + value: val, + }; + + var editorType = getEditorType(conf); + conf.json = editorType === 'json'; + conf.bool = editorType === 'bool'; + conf.array = editorType === 'array'; + conf.normal = editorType === 'normal'; + conf.tooComplex = !editorType; + + return conf; }); + } - return conf; - }); + readConfigVals(); + $rootScope.$on('change:config', readConfigVals); } }; }); diff --git a/src/kibana/plugins/settings/sections/indices/index.js b/src/kibana/plugins/settings/sections/indices/index.js index 82bc4e569110..6b714722abc4 100644 --- a/src/kibana/plugins/settings/sections/indices/index.js +++ b/src/kibana/plugins/settings/sections/indices/index.js @@ -15,7 +15,7 @@ define(function (require) { // wrapper directive, which sets some global stuff up like the left nav require('modules').get('apps/settings') - .directive('kbnSettingsIndices', function ($route, config, kbnUrl) { + .directive('kbnSettingsIndices', function ($route, config, kbnUrl, $rootScope) { return { restrict: 'E', transclude: true, @@ -23,7 +23,7 @@ define(function (require) { link: function ($scope) { $scope.edittingId = $route.current.params.id; $scope.defaultIndex = config.get('defaultIndex'); - $scope.$on('change:config.defaultIndex', function () { + $rootScope.$on('change:config.defaultIndex', function () { $scope.defaultIndex = config.get('defaultIndex'); }); From a1f544e53753ced2e1660c67e7c7edc8127e5236 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Fri, 23 Jan 2015 15:46:52 -0700 Subject: [PATCH 16/32] Added more quick time options. Closes #2659 --- src/kibana/components/timepicker/quick_ranges.js | 10 +++++++++- test/unit/specs/directives/timepicker.js | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/kibana/components/timepicker/quick_ranges.js b/src/kibana/components/timepicker/quick_ranges.js index 0baf75b30325..9e1f0641996b 100644 --- a/src/kibana/components/timepicker/quick_ranges.js +++ b/src/kibana/components/timepicker/quick_ranges.js @@ -25,7 +25,15 @@ define(function (require) { { from: 'now-12h', to: 'now', display: 'Last 12 hours', section: 2 }, { from: 'now-24h', to: 'now', display: 'Last 24 hours', section: 2 }, { from: 'now-7d', to: 'now', display: 'Last 7 days', section: 2 }, - { from: 'now-30d', to: 'now', display: 'Last 30 days', section: 2 }, + + { from: 'now-30d', to: 'now', display: 'Last 30 days', section: 3 }, + { from: 'now-60d', to: 'now', display: 'Last 60 days', section: 3 }, + { from: 'now-90d', to: 'now', display: 'Last 90 days', section: 3 }, + { from: 'now-6M', to: 'now', display: 'Last 6 months', section: 3 }, + { from: 'now-1y', to: 'now', display: 'Last 1 year', section: 3 }, + { from: 'now-2y', to: 'now', display: 'Last 2 years', section: 3 }, + { from: 'now-5y', to: 'now', display: 'Last 5 years', section: 3 }, + ]); }); diff --git a/test/unit/specs/directives/timepicker.js b/test/unit/specs/directives/timepicker.js index 205a78385973..d72ee753909d 100644 --- a/test/unit/specs/directives/timepicker.js +++ b/test/unit/specs/directives/timepicker.js @@ -153,8 +153,8 @@ define(function (require) { $scope.$digest(); }); - it('should contain 3 lists of options', function (done) { - expect($elem.find('.kbn-timepicker-section .list-unstyled').length).to.be(3); + it('should contain 4 lists of options', function (done) { + expect($elem.find('.kbn-timepicker-section .list-unstyled').length).to.be(4); done(); }); From 2bed1807d1c8e77a07d9b019db8607e3b396e32b Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 23 Jan 2015 12:09:21 -0700 Subject: [PATCH 17/32] Adding esvm to test for travis --- tasks/test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/test.js b/tasks/test.js index 1d16b7bd4bf7..e950659afd52 100644 --- a/tasks/test.js +++ b/tasks/test.js @@ -29,6 +29,8 @@ module.exports = function (grunt) { 'less', getTestTask() ]; + + if (process.env.TRAVIS) tasks.shift('esvm:dev'); grunt.task.run(tasks); }); From afa294f75c9cf8b03421e3d66f04b4233303f38b Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 23 Jan 2015 19:12:19 -0700 Subject: [PATCH 18/32] Closes #2720 - Support CA Certificates with the proxy - Closes #2720 - Added `ca` option to kibana.yml - Rewrote the Proxy to use Request and honor the custom CA - Added some packages to support the proxy - Removed http-proxy --- package.json | 7 ++- src/server/config/kibana.yml | 6 ++ src/server/routes/proxy.js | 119 ++++++++++++++++++++++++----------- 3 files changed, 93 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index 4ad2434c5bcb..8dfd45ac3ea8 100644 --- a/package.json +++ b/package.json @@ -43,13 +43,15 @@ "debug": "~2.1.1", "express": "~4.10.6", "glob": "^4.3.2", - "http-proxy": "^1.8.1", "jade": "~1.8.2", "js-yaml": "^3.2.5", "less-middleware": "1.0.x", "lodash": "^2.4.1", "morgan": "~1.5.1", - "serve-favicon": "~2.2.0" + "request": "^2.40.0", + "serve-favicon": "~2.2.0", + "semver": "^4.2.0", + "ssl-root-cas": "^1.1.7" }, "devDependencies": { "bluebird": "~2.0.7", @@ -86,7 +88,6 @@ "opn": "~1.0.0", "path-browserify": "0.0.0", "progress": "^1.1.8", - "request": "^2.40.0", "requirejs": "~2.1.14", "rjs-build-analysis": "0.0.3", "simple-git": "^0.11.0", diff --git a/src/server/config/kibana.yml b/src/server/config/kibana.yml index 10ab0bf10581..775c4e274e2a 100644 --- a/src/server/config/kibana.yml +++ b/src/server/config/kibana.yml @@ -10,6 +10,8 @@ elasticsearch_url: "http://localhost:9200" # If your Elasticsearch is protected with basic auth: # elasticsearch_username: user # elasticsearch_password: pass +# elasticsearch_username: test +# elasticsearch_password: test # preserve_elasticsearch_host true will send the hostname specified in `elasticsearch`. If you set it to false, # then the host you use to connect to *this* Kibana instance will be sent. @@ -34,3 +36,7 @@ shard_timeout: 0 # certificate. verify_ssl: true +# If you need to provide a CA certificate for your Elasticsarech instance, put +# the path of the pem file here. +# ca: /path/to/your/CA.pem + diff --git a/src/server/routes/proxy.js b/src/server/routes/proxy.js index ddef350ac147..dd818de71d4b 100644 --- a/src/server/routes/proxy.js +++ b/src/server/routes/proxy.js @@ -1,52 +1,99 @@ -var logger = require('../lib/logger'); -var express = require('express'); -var router = module.exports = express.Router(); -var httpProxy = require('http-proxy'); var config = require('../config'); +var request = require('request'); +var buffer = require('buffer'); +var querystring = require('querystring'); +var express = require('express'); +var _ = require('lodash'); +var fs = require('fs'); var url = require('url'); var target = url.parse(config.elasticsearch); -var proxy = new httpProxy.createProxyServer({}); -var buffer = require('buffer'); +var join = require('path').join; -proxy.on('proxyReq', function (proxyReq, req, res, options) { - // To support the elasticsearch_preserve_host feature we need to change the - // host header to the target host header. - if (config.kibana.elasticsearch_preserve_host) { - proxyReq.setHeader('host', target.host); + +// If the target is backed by an SSL and a CA is provided via the config +// then we need to inject the CA +var hasCustomCA = false; +if (/^https/.test(target.protocol) && config.kibana.ca) { + var sslRootCAs = require('ssl-root-cas/latest'); + sslRootCAs.inject(); + var ca = fs.readFileSync(config.kibana.ca, 'utf8'); + var https = require('https'); + https.globalAgent.options.ca.push(ca); + hasCustomCA = true; +} + +// Create the router +var router = module.exports = express.Router(); + +// We need to capture the raw body before moving on +router.use(function (req, res, next) { + req.rawBody = ''; + req.setEncoding('utf8'); + req.on('data', function (chunk) { + req.rawBody += chunk; + }); + req.on('end', next); +}); + +// Create the proxy middleware +router.use(function (req, res, next) { + + var uri = _.defaults({}, target); + var options = { + url: uri.protocol + '//' + uri.host + req.path, + method: req.method, + headers: { }, + strictSSL: config.kibana.verify_ssl, + timeout: config.kibana.request_timeout + }; + + // If the server has a custom CA we need to add it to the agent options + if (hasCustomCA) { + options.agentOptions = { ca: https.globalAgent.options.ca }; + } + + // Only send the body if it's a PATCH, PUT, or POST + if (_.contains(['PATCH', 'PUT', 'POST'], options.method) && req.rawBody) { + options.body = req.rawBody; + } + + // If there is a query string we need to stringify it and send it with + // the request + if (Object.keys(req.query).length !== 0) { + options.url += '?' + querystring.stringify(req.query); } // Support for handling basic auth if (config.kibana.elasticsearch_username && config.kibana.elasticsearch_password) { var code = new buffer.Buffer(config.kibana.elasticsearch_username + ':' + config.kibana.elasticsearch_password); var auth = 'Basic ' + code.toString('base64'); - proxyReq.setHeader('authorization', auth); - } -}); - -// Error handling for the proxy -proxy.on('error', function (err, req, res) { - var code = 502; - var body = { message: 'Bad Gateway' }; - - if (err.code === 'ECONNREFUSED') { - body.message = 'Unable to connect to Elasticsearch'; + options.headers.authorization = auth; } - if (err.message === 'DEPTH_ZERO_SELF_SIGNED_CERT') { - body.message = 'SSL handshake with Elasticsearch failed'; + // To support the elasticsearch_preserve_host feature we need to change the + // host header to the target host header. I don't quite understand the value + // of this... but it's a feature we had before so I guess we are keeping it. + if (config.kibana.elasticsearch_preserve_host) { + options.headers.host = target.host; } - res.writeHead(502, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify(body)); -}); - -router.use(function (req, res, next) { - var options = { - target: config.elasticsearch, - secure: config.kibana.verify_ssl, - xfwd: true, - timeout: (config.kibana.request_timeout) - }; - proxy.web(req, res, options); + // Create the request and pipe the response + var esRequest = request(options); + esRequest.on('error', function (err) { + var code = 502; + var body = { message: 'Bad Gateway' }; + + if (err.code === 'ECONNREFUSED') { + body.message = 'Unable to connect to Elasticsearch'; + } + + if (err.message === 'DEPTH_ZERO_SELF_SIGNED_CERT') { + body.message = 'SSL handshake with Elasticsearch failed'; + } + + body.err = err.message; + res.json(body); + }); + esRequest.pipe(res); }); From 5fa8105ec544aaae8475c65b8cffef9a3b95b2c2 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 23 Jan 2015 19:16:23 -0700 Subject: [PATCH 19/32] Removing extra auth lines from config --- src/server/config/kibana.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/server/config/kibana.yml b/src/server/config/kibana.yml index 775c4e274e2a..b651def2cd11 100644 --- a/src/server/config/kibana.yml +++ b/src/server/config/kibana.yml @@ -10,8 +10,6 @@ elasticsearch_url: "http://localhost:9200" # If your Elasticsearch is protected with basic auth: # elasticsearch_username: user # elasticsearch_password: pass -# elasticsearch_username: test -# elasticsearch_password: test # preserve_elasticsearch_host true will send the hostname specified in `elasticsearch`. If you set it to false, # then the host you use to connect to *this* Kibana instance will be sent. From 598a1b4419cfaa700001204531a7b482b0803d00 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Sun, 25 Jan 2015 00:09:56 -0700 Subject: [PATCH 20/32] Forwarding the headers --- src/server/routes/proxy.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/server/routes/proxy.js b/src/server/routes/proxy.js index dd818de71d4b..6591640e70de 100644 --- a/src/server/routes/proxy.js +++ b/src/server/routes/proxy.js @@ -40,9 +40,9 @@ router.use(function (req, res, next) { var uri = _.defaults({}, target); var options = { - url: uri.protocol + '//' + uri.host + req.path, + url: uri.protocol + '//' + uri.host + req.url, method: req.method, - headers: { }, + headers: _.defaults({ host: target.hostname }, req.headers), strictSSL: config.kibana.verify_ssl, timeout: config.kibana.request_timeout }; @@ -53,16 +53,10 @@ router.use(function (req, res, next) { } // Only send the body if it's a PATCH, PUT, or POST - if (_.contains(['PATCH', 'PUT', 'POST'], options.method) && req.rawBody) { + if (req.rawBody) { options.body = req.rawBody; } - // If there is a query string we need to stringify it and send it with - // the request - if (Object.keys(req.query).length !== 0) { - options.url += '?' + querystring.stringify(req.query); - } - // Support for handling basic auth if (config.kibana.elasticsearch_username && config.kibana.elasticsearch_password) { var code = new buffer.Buffer(config.kibana.elasticsearch_username + ':' + config.kibana.elasticsearch_password); From 51ca59a4f306d9d630f7595ced29a09c6253bb2c Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Mon, 26 Jan 2015 11:52:07 -0700 Subject: [PATCH 21/32] adding x-forward headers --- src/server/routes/proxy.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/server/routes/proxy.js b/src/server/routes/proxy.js index 6591640e70de..6fa6c8ec1cdc 100644 --- a/src/server/routes/proxy.js +++ b/src/server/routes/proxy.js @@ -35,6 +35,12 @@ router.use(function (req, res, next) { req.on('end', next); }); +function getPort(req) { + var matches = req.headers.host.match(/:(\d+)/); + if (matches[1]) return matches[1]; + return req.connection.pair ? '443' : '80'; +} + // Create the proxy middleware router.use(function (req, res, next) { @@ -47,6 +53,11 @@ router.use(function (req, res, next) { timeout: config.kibana.request_timeout }; + + options.headers['x-forward-for'] = req.connection.remoteAddress || req.socket.remoteAddress; + options.headers['x-forward-port'] = getPort(req); + options.headers['x-forward-proto'] = req.connection.pair ? 'https' : 'http'; + // If the server has a custom CA we need to add it to the agent options if (hasCustomCA) { options.agentOptions = { ca: https.globalAgent.options.ca }; From 59841722e7bace29b8abced39a6aa85dbd76c7de Mon Sep 17 00:00:00 2001 From: Spencer Alger Date: Mon, 26 Jan 2015 13:44:31 -0700 Subject: [PATCH 22/32] prevent partial matching of type names --- .../settings/sections/advanced/index.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/kibana/plugins/settings/sections/advanced/index.js b/src/kibana/plugins/settings/sections/advanced/index.js index 0c0fe16af3cc..d9c85cd17f56 100644 --- a/src/kibana/plugins/settings/sections/advanced/index.js +++ b/src/kibana/plugins/settings/sections/advanced/index.js @@ -18,9 +18,12 @@ define(function (require) { ESC: 27 }; + var NAMED_EDITORS = ['json', 'array', 'boolean']; + var NORMAL_EDITOR = ['number', 'string', 'null', 'undefined']; + function getEditorType(conf) { - if (_.contains('number string null undefined', conf.type)) return 'normal'; - if (_.contains('json array boolean', conf.type)) return conf.type; + if (_.contains(NORMAL_EDITOR, conf.type)) return 'normal'; + if (_.contains(NAMED_EDITORS, conf.type)) return conf.type; } function isTypeComplex(conf) { @@ -40,12 +43,12 @@ define(function (require) { value: val, }; - var editorType = getEditorType(conf); - conf.json = editorType === 'json'; - conf.bool = editorType === 'bool'; - conf.array = editorType === 'array'; - conf.normal = editorType === 'normal'; - conf.tooComplex = !editorType; + var editor = getEditorType(conf); + conf.json = editor === 'json'; + conf.bool = editor === 'bool'; + conf.array = editor === 'array'; + conf.normal = editor === 'normal'; + conf.tooComplex = !editor; return conf; }); From 622a83edbf4c47c636d93303b19ebca9eb3ed257 Mon Sep 17 00:00:00 2001 From: lukasolson Date: Mon, 26 Jan 2015 17:08:53 -0700 Subject: [PATCH 23/32] Fix whole number directive --- src/kibana/directives/input_whole_number.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/kibana/directives/input_whole_number.js b/src/kibana/directives/input_whole_number.js index e932780d099d..ac5835d1b039 100644 --- a/src/kibana/directives/input_whole_number.js +++ b/src/kibana/directives/input_whole_number.js @@ -11,6 +11,7 @@ define(function (require) { function checkWholeNumber(value) { ngModel.$setValidity('whole', value % 1 === 0); + return value; } } }; From af27697089206cf60a446ea576fc3722f764c427 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Mon, 26 Jan 2015 17:16:00 -0700 Subject: [PATCH 24/32] Add a simple loading screen to make the big JS more tolerable --- src/kibana/index.html | 21 ++++++++++++++++++--- src/kibana/styles/main.less | 4 ++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/kibana/index.html b/src/kibana/index.html index 19c224b4cda1..aa89363b2988 100644 --- a/src/kibana/index.html +++ b/src/kibana/index.html @@ -7,6 +7,22 @@ Kibana 4 + + + + + +
+ +
- - - + + diff --git a/src/kibana/styles/main.less b/src/kibana/styles/main.less index bcc705550c5b..3ce7c1fde1a4 100644 --- a/src/kibana/styles/main.less +++ b/src/kibana/styles/main.less @@ -434,6 +434,10 @@ textarea { resize: vertical; } +.initial-load { + margin-top: 60px; +} + .field-collapse-toggle { color: #999; margin-left: 10px !important; From 2514d28a758405a23c946f5714c15ced8a993a9a Mon Sep 17 00:00:00 2001 From: Juan Thomassie Date: Tue, 27 Jan 2015 09:26:59 -0600 Subject: [PATCH 25/32] revised area chart to delete phantom circles, where d.y === 0 --- .../vislib/visualizations/area_chart.js | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/kibana/components/vislib/visualizations/area_chart.js b/src/kibana/components/vislib/visualizations/area_chart.js index 0d3a2b8268f2..ee59320e7e03 100644 --- a/src/kibana/components/vislib/visualizations/area_chart.js +++ b/src/kibana/components/vislib/visualizations/area_chart.js @@ -83,7 +83,6 @@ define(function (require) { var color = this.handler.data.getColorFunc(); var xScale = this.handler.xAxis.xScale; var yScale = this.handler.yAxis.yScale; - var height = yScale.range()[0]; var defaultOpacity = this._attr.defaultOpacity; var area = d3.svg.area() @@ -95,8 +94,9 @@ define(function (require) { }) .y0(function (d) { if (isOverlapping) { - return height; + return yScale(0); } + return yScale(d.y0); }) .y1(function (d) { @@ -199,6 +199,9 @@ define(function (require) { .enter() .append('circle') .attr('class', function circleClass(d) { + if (d.y === 0) { + return d.label + ' zero-circle'; + } return d.label; }) .attr('fill', function (d) { @@ -233,6 +236,20 @@ define(function (require) { return circles; }; + /** + * Removes SVG circles where d.y === 0 from area chart + * + * @method removeZeroCircles + * @param svg {HTMLElement} SVG to which circles are appended + * @returns {D3.UpdateSelection} SVG with circles + */ + AreaChart.prototype.removeZeroCircles = function (svg) { + var layer = svg.selectAll('.points'); + var zeros = layer.selectAll('.zero-circle').remove(); + var circles = layer.selectAll('circle'); + return circles; + }; + /** * Adds SVG clipPath * @@ -291,6 +308,8 @@ define(function (require) { var margin = this._attr.margin; var elWidth = this._attr.width = $elem.width(); var elHeight = this._attr.height = $elem.height(); + var yMin = this.handler.yAxis.yMin; + var yScale = this.handler.yAxis.yScale; var minWidth = 20; var minHeight = 20; var div; @@ -330,14 +349,31 @@ define(function (require) { // add path path = self.addPath(svg, layers); + if (yMin < 0 && self._attr.mode !== 'wiggle' && self._attr.mode !== 'silhouette') { + + // Draw line at yScale 0 value + svg.append('line') + .attr('class', 'zero-line') + .attr('x1', 0) + .attr('y1', yScale(0)) + .attr('x2', width) + .attr('y2', yScale(0)) + .style('stroke', '#ddd') + .style('stroke-width', 1); + } + // add circles circles = self.addCircles(svg, layers); + // remove 'phantom' zero points + circles = self.removeZeroCircles(svg); + // add click and hover events to circles self.addCircleEvents(circles, svg); // chart base line var line = svg.append('line') + .attr('class', 'base-line') .attr('x1', 0) .attr('y1', height) .attr('x2', width) @@ -352,4 +388,4 @@ define(function (require) { return AreaChart; }; -}); +}); \ No newline at end of file From f3b3f22dff3d1827af9265e39b399dc7b4350e06 Mon Sep 17 00:00:00 2001 From: Juan Thomassie Date: Tue, 27 Jan 2015 09:36:34 -0600 Subject: [PATCH 26/32] revised to commit, removing unintended change of height --- .../vislib/visualizations/area_chart.js | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/kibana/components/vislib/visualizations/area_chart.js b/src/kibana/components/vislib/visualizations/area_chart.js index ee59320e7e03..91b5c9a948f0 100644 --- a/src/kibana/components/vislib/visualizations/area_chart.js +++ b/src/kibana/components/vislib/visualizations/area_chart.js @@ -83,6 +83,7 @@ define(function (require) { var color = this.handler.data.getColorFunc(); var xScale = this.handler.xAxis.xScale; var yScale = this.handler.yAxis.yScale; + var height = yScale.range()[0]; var defaultOpacity = this._attr.defaultOpacity; var area = d3.svg.area() @@ -94,9 +95,8 @@ define(function (require) { }) .y0(function (d) { if (isOverlapping) { - return yScale(0); + return height; } - return yScale(d.y0); }) .y1(function (d) { @@ -199,9 +199,6 @@ define(function (require) { .enter() .append('circle') .attr('class', function circleClass(d) { - if (d.y === 0) { - return d.label + ' zero-circle'; - } return d.label; }) .attr('fill', function (d) { @@ -308,8 +305,6 @@ define(function (require) { var margin = this._attr.margin; var elWidth = this._attr.width = $elem.width(); var elHeight = this._attr.height = $elem.height(); - var yMin = this.handler.yAxis.yMin; - var yScale = this.handler.yAxis.yScale; var minWidth = 20; var minHeight = 20; var div; @@ -349,23 +344,10 @@ define(function (require) { // add path path = self.addPath(svg, layers); - if (yMin < 0 && self._attr.mode !== 'wiggle' && self._attr.mode !== 'silhouette') { - - // Draw line at yScale 0 value - svg.append('line') - .attr('class', 'zero-line') - .attr('x1', 0) - .attr('y1', yScale(0)) - .attr('x2', width) - .attr('y2', yScale(0)) - .style('stroke', '#ddd') - .style('stroke-width', 1); - } - // add circles circles = self.addCircles(svg, layers); - // remove 'phantom' zero points + // remove 'phantom' circles circles = self.removeZeroCircles(svg); // add click and hover events to circles @@ -373,7 +355,6 @@ define(function (require) { // chart base line var line = svg.append('line') - .attr('class', 'base-line') .attr('x1', 0) .attr('y1', height) .attr('x2', width) @@ -388,4 +369,4 @@ define(function (require) { return AreaChart; }; -}); \ No newline at end of file +}); From 443b338a1428b951167a709acac80670b98797fb Mon Sep 17 00:00:00 2001 From: Juan Thomassie Date: Tue, 27 Jan 2015 10:09:11 -0600 Subject: [PATCH 27/32] revised with simpler solution, now filters data as circles are drawn rather than adding a method to remove circles after drawn --- .../vislib/visualizations/area_chart.js | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/kibana/components/vislib/visualizations/area_chart.js b/src/kibana/components/vislib/visualizations/area_chart.js index 91b5c9a948f0..76189b8df6fd 100644 --- a/src/kibana/components/vislib/visualizations/area_chart.js +++ b/src/kibana/components/vislib/visualizations/area_chart.js @@ -187,8 +187,10 @@ define(function (require) { // Append the bars circles = layer .selectAll('rect') - .data(function appendData(d) { - return d; + .data(function appendData(data) { + return data.filter(function isNotZero(d) { + return d.y !== 0; + }); }); // exit @@ -233,20 +235,6 @@ define(function (require) { return circles; }; - /** - * Removes SVG circles where d.y === 0 from area chart - * - * @method removeZeroCircles - * @param svg {HTMLElement} SVG to which circles are appended - * @returns {D3.UpdateSelection} SVG with circles - */ - AreaChart.prototype.removeZeroCircles = function (svg) { - var layer = svg.selectAll('.points'); - var zeros = layer.selectAll('.zero-circle').remove(); - var circles = layer.selectAll('circle'); - return circles; - }; - /** * Adds SVG clipPath * @@ -347,9 +335,6 @@ define(function (require) { // add circles circles = self.addCircles(svg, layers); - // remove 'phantom' circles - circles = self.removeZeroCircles(svg); - // add click and hover events to circles self.addCircleEvents(circles, svg); From 96a51fa5a12be6af91f77188c1b24911b6448e84 Mon Sep 17 00:00:00 2001 From: Juan Thomassie Date: Tue, 27 Jan 2015 11:33:38 -0600 Subject: [PATCH 28/32] added test for not drawing circles where data === 0 --- .../specs/vislib/visualizations/area_chart.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/unit/specs/vislib/visualizations/area_chart.js b/test/unit/specs/vislib/visualizations/area_chart.js index 4c094df94994..810009b1bd30 100644 --- a/test/unit/specs/vislib/visualizations/area_chart.js +++ b/test/unit/specs/vislib/visualizations/area_chart.js @@ -183,6 +183,23 @@ define(function (require) { expect($(chart.chartEl).find('circle').length).to.be.greaterThan(0); }); }); + + it('should not draw circles where d.y === 0', function () { + vis.handler.charts.forEach(function (chart) { + var series = chart.chartData.series; + var isZero = series.some(function (d) { + return d.y === 0; + }); + var circles = $.makeArray($(chart.chartEl).find('circle')); + var isNotDrawn = circles.some(function (d) { + return d.__data__.y === 0; + }); + + if (isZero) { + expect(isNotDrawn).to.be(false); + } + }); + }); }); // Cannot seem to get these tests to work on the box From b0565aa36e62fd3f05267ed90e7fccfa79a764ae Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 27 Jan 2015 12:34:09 -0700 Subject: [PATCH 29/32] Removing semver package --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 8dfd45ac3ea8..be964cddeeed 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "morgan": "~1.5.1", "request": "^2.40.0", "serve-favicon": "~2.2.0", - "semver": "^4.2.0", "ssl-root-cas": "^1.1.7" }, "devDependencies": { From 1578076a647abbf51d10797ac3d49f110b379d8b Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Tue, 27 Jan 2015 15:59:35 -0700 Subject: [PATCH 30/32] Add loading gif. Doh. --- src/kibana/images/initial_load.gif | Bin 0 -> 11934 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/kibana/images/initial_load.gif diff --git a/src/kibana/images/initial_load.gif b/src/kibana/images/initial_load.gif new file mode 100644 index 0000000000000000000000000000000000000000..2bde128cc5dbf9523c5221fd04198c7e773f2c53 GIT binary patch literal 11934 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 Mg<%%pRmS!I1CkF{a{vGU literal 0 HcmV?d00001 From c926cc117159386c17ed35efbad6a6ef7c168b75 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 27 Jan 2015 17:33:07 -0700 Subject: [PATCH 31/32] Preventing optional packages from being install. --- tasks/npm_install_kibana.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/npm_install_kibana.js b/tasks/npm_install_kibana.js index 1d70b8997fed..d55380c4836f 100644 --- a/tasks/npm_install_kibana.js +++ b/tasks/npm_install_kibana.js @@ -4,7 +4,7 @@ module.exports = function (grunt) { grunt.registerTask('npm_install_kibana', 'NPM isntall kibana server into dist', function () { var done = this.async(); var cwd = join(grunt.config.get('build'), 'dist', 'kibana', 'src'); - var command = 'npm install --production'; + var command = 'npm install --production --no-optional'; var options = { cwd: cwd }; child_process.exec(command, options, function (err, stdout, stderr) { if (err) { From 6da832d2ae84775e58dd9ddd634e6f93e3334bd5 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 27 Jan 2015 17:37:26 -0700 Subject: [PATCH 32/32] Adding 502 to error response --- src/server/routes/proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/routes/proxy.js b/src/server/routes/proxy.js index 6fa6c8ec1cdc..6c7508dd2f22 100644 --- a/src/server/routes/proxy.js +++ b/src/server/routes/proxy.js @@ -97,7 +97,7 @@ router.use(function (req, res, next) { } body.err = err.message; - res.json(body); + res.status(code).json(body); }); esRequest.pipe(res); });