From 2f233030bc6b47b4104a2afcbade35b6cd9613fc Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Mon, 24 Jul 2017 09:01:37 -0400 Subject: [PATCH 001/165] Children of buttons won't capture hover events in firefox (#13015) * Children of buttons won't capture hover events in firefox Fixes https://github.com/elastic/kibana/issues/12987 * Make full screen div accessible * Remove nested aria labels --- .../kibana/public/dashboard/dashboard.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core_plugins/kibana/public/dashboard/dashboard.html b/src/core_plugins/kibana/public/dashboard/dashboard.html index 184223bb229b8..adf2797a6af38 100644 --- a/src/core_plugins/kibana/public/dashboard/dashboard.html +++ b/src/core_plugins/kibana/public/dashboard/dashboard.html @@ -1,16 +1,18 @@
- +
From 37fc9495c69fa4f1cb33673520485b4d523e7fb5 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 24 Jul 2017 11:24:11 -0400 Subject: [PATCH 002/165] Should only fit on shapes that are part of the result (#12881) --- .../region_map/public/choropleth_layer.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/core_plugins/region_map/public/choropleth_layer.js b/src/core_plugins/region_map/public/choropleth_layer.js index d48fa5d36f362..6ea21d0699fb8 100644 --- a/src/core_plugins/region_map/public/choropleth_layer.js +++ b/src/core_plugins/region_map/public/choropleth_layer.js @@ -15,6 +15,7 @@ export default class ChoroplethLayer extends KibanaMapLayer { this._colorRamp = truncatedColorMaps[Object.keys(truncatedColorMaps)[0]]; this._tooltipFormatter = () => ''; this._attribution = attribution; + this._boundsOfData = null; this._geojsonUrl = geojsonUrl; this._leafletLayer = L.geoJson(null, { @@ -75,6 +76,8 @@ export default class ChoroplethLayer extends KibanaMapLayer { const quantizeDomain = (min !== max) ? [min, max] : d3.scale.quantize().domain(); this._legendQuantizer = d3.scale.quantize().domain(quantizeDomain).range(this._legendColors); } + + this._boundsOfData = styler.getLeafletBounds(); this.emit('styleChanged', { mismatches: styler.getMismatches() }); @@ -132,6 +135,11 @@ export default class ChoroplethLayer extends KibanaMapLayer { return this._geojsonUrl === geojsonUrl; } + getBounds() { + const bounds = super.getBounds(); + return (this._boundsOfData) ? this._boundsOfData : bounds; + } + appendLegendContents(jqueryDiv) { @@ -193,12 +201,17 @@ function makeChoroplethStyler(data, colorramp, joinField) { }, getMismatches: function () { return []; + }, + getLeafletBounds: function () { + return null; } }; } const { min, max } = getMinMax(data); const outstandingFeatures = data.slice(); + + const boundsOfAllFeatures = new L.LatLngBounds(); return { getLeafletStyleFunction: function (geojsonFeature) { let lastIndex = -1; @@ -212,6 +225,10 @@ function makeChoroplethStyler(data, colorramp, joinField) { } outstandingFeatures.splice(lastIndex, 1); + + const boundsOfFeature = L.geoJson(geojsonFeature).getBounds(); + boundsOfAllFeatures.extend(boundsOfFeature); + return { fillColor: getChoroplethColor(match.value, min, max, colorramp), weight: 2, @@ -226,6 +243,9 @@ function makeChoroplethStyler(data, colorramp, joinField) { */ getMismatches: function () { return outstandingFeatures.map((bucket) => bucket.term); + }, + getLeafletBounds: function () { + return boundsOfAllFeatures.isValid() ? boundsOfAllFeatures : null; } }; From 190cd5f3f64f3b3f35e413dd9c9a0d60ce55313e Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Mon, 24 Jul 2017 09:25:08 -0700 Subject: [PATCH 003/165] Fixes #12602 - Change TSVB Fields API to use fieldCaps API (#12611) * Fixes #12602 - Change TSVB Fields API to use fieldCaps API * Removing obsolete test * updating tests * removing the extra sortBy --- .../lib/__tests__/generate_by_type_filter.js | 14 +--- .../components/lib/generate_by_type_filter.js | 7 +- .../server/lib/__tests__/get_fields.js | 84 ------------------- .../metrics/server/lib/get_fields.js | 43 ++-------- .../server/lib/get_index_pattern_service.js | 11 +++ .../metrics/server/routes/fields.js | 6 +- 6 files changed, 25 insertions(+), 140 deletions(-) delete mode 100644 src/core_plugins/metrics/server/lib/__tests__/get_fields.js create mode 100644 src/core_plugins/metrics/server/lib/get_index_pattern_service.js diff --git a/src/core_plugins/metrics/public/components/lib/__tests__/generate_by_type_filter.js b/src/core_plugins/metrics/public/components/lib/__tests__/generate_by_type_filter.js index da65b3150b918..4ec79e929c0cf 100644 --- a/src/core_plugins/metrics/public/components/lib/__tests__/generate_by_type_filter.js +++ b/src/core_plugins/metrics/public/components/lib/__tests__/generate_by_type_filter.js @@ -6,12 +6,7 @@ describe('generateByTypeFilter()', () => { describe('numeric', () => { const fn = generateByTypeFilter('numeric'); [ - 'scaled_float', - 'half_float', - 'integer', - 'float', - 'long', - 'double' + 'number' ].forEach((type) => { it(`should return true for ${type}`, () => expect(fn({ type })).to.equal(true)); }); @@ -34,12 +29,7 @@ describe('generateByTypeFilter()', () => { describe('all', () => { const fn = generateByTypeFilter('all'); [ - 'scaled_float', - 'half_float', - 'integer', - 'float', - 'long', - 'double', + 'number', 'string', 'text', 'keyword', diff --git a/src/core_plugins/metrics/public/components/lib/generate_by_type_filter.js b/src/core_plugins/metrics/public/components/lib/generate_by_type_filter.js index 91a44d1e61dd6..1f025dece219a 100644 --- a/src/core_plugins/metrics/public/components/lib/generate_by_type_filter.js +++ b/src/core_plugins/metrics/public/components/lib/generate_by_type_filter.js @@ -4,12 +4,7 @@ export default function byType(type) { switch (type) { case 'numeric': return _.includes([ - 'scaled_float', - 'half_float', - 'integer', - 'float', - 'long', - 'double' + 'number' ], field.type); case 'string': return _.includes([ diff --git a/src/core_plugins/metrics/server/lib/__tests__/get_fields.js b/src/core_plugins/metrics/server/lib/__tests__/get_fields.js deleted file mode 100644 index 1877764f83b9e..0000000000000 --- a/src/core_plugins/metrics/server/lib/__tests__/get_fields.js +++ /dev/null @@ -1,84 +0,0 @@ -import { expect } from 'chai'; -import { getParams, handleResponse } from '../get_fields'; - -describe('getFields', () => { - - describe('getParams', () => { - - it('returns a valid params object', () => { - const req = { query: { index: 'metricbeat-*' } }; - expect(getParams(req)).to.eql({ - index: 'metricbeat-*', - fields: ['*'], - ignoreUnavailable: false, - allowNoIndices: false, - includeDefaults: true - }); - }); - - }); - - describe('handleResponse', () => { - it('returns a valid response', () => { - const resp = { - 'foo': { - 'mappings': { - 'bar': { - '@timestamp': { - 'full_name': '@timestamp', - 'mapping': { - '@timestamp': { - 'type': 'date' - } - } - } - } - } - }, - 'twitter': { - 'mappings': { - 'tweet': { - 'message': { - 'full_name': 'message', - 'mapping': { - 'message': { - 'type': 'text', - 'fields': { - 'keyword': { - 'type': 'keyword', - 'ignore_above': 256 - } - } - } - } - }, - '@timestamp': { - 'full_name': '@timestamp', - 'mapping': { - '@timestamp': { - 'type': 'date' - } - } - }, - 'id.keyword': { - 'full_name': 'id.keyword', - 'mapping': { - 'keyword': { - 'type': 'keyword', - 'ignore_above': 256 - } - } - } - } - } - } - }; - expect(handleResponse(resp)).to.eql([ - { name: '@timestamp', type: 'date' }, - { name: 'id.keyword', type: 'keyword' }, - { name: 'message', type: 'text' } - ]); - }); - }); - -}); diff --git a/src/core_plugins/metrics/server/lib/get_fields.js b/src/core_plugins/metrics/server/lib/get_fields.js index 0c308e7537120..a6336befad11c 100644 --- a/src/core_plugins/metrics/server/lib/get_fields.js +++ b/src/core_plugins/metrics/server/lib/get_fields.js @@ -1,40 +1,9 @@ -import _ from 'lodash'; +import { uniq } from 'lodash'; -export function getParams(req) { +export async function getFields(req) { + const { indexPatternsService } = req.pre; const index = req.query.index || '*'; - return { - index, - fields: ['*'], - ignoreUnavailable: false, - allowNoIndices: false, - includeDefaults: true - }; + const resp = await indexPatternsService.getFieldsForWildcard({ pattern: index }); + const fields = resp.filter(field => field.aggregatable); + return uniq(fields, field => field.name); } - -export function handleResponse(resp) { - return _.reduce(resp, (acc, index) => { - _.each(index.mappings, (type) => { - _.each(type, (field, fullName) => { - const name = _.last(fullName.split(/\./)); - const enabled = _.get(field, `mapping.${name}.enabled`, true); - const fieldType = _.get(field, `mapping.${name}.type`); - if (enabled && fieldType) { - acc.push({ - name: _.get(field, 'full_name', fullName), - type: fieldType - }); - } - }); - }); - return _(acc).sortBy('name').uniq(row => row.name).value(); - }, []); -} - -function getFields(req) { - const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('data'); - const params = getParams(req); - return callWithRequest(req, 'indices.getFieldMapping', params).then(handleResponse); -} - -export default getFields; - diff --git a/src/core_plugins/metrics/server/lib/get_index_pattern_service.js b/src/core_plugins/metrics/server/lib/get_index_pattern_service.js new file mode 100644 index 0000000000000..e466de92e3f05 --- /dev/null +++ b/src/core_plugins/metrics/server/lib/get_index_pattern_service.js @@ -0,0 +1,11 @@ +import { IndexPatternsService } from '../../../../server/index_patterns/service'; +export const getIndexPatternService = { + assign: 'indexPatternsService', + method(req, reply) { + const dataCluster = req.server.plugins.elasticsearch.getCluster('data'); + const callDataCluster = (...args) => { + return dataCluster.callWithRequest(req, ...args); + }; + reply(new IndexPatternsService(callDataCluster)); + } +}; diff --git a/src/core_plugins/metrics/server/routes/fields.js b/src/core_plugins/metrics/server/routes/fields.js index a056bd05506b1..c59f5fb1776d7 100644 --- a/src/core_plugins/metrics/server/routes/fields.js +++ b/src/core_plugins/metrics/server/routes/fields.js @@ -1,7 +1,11 @@ -import getFields from '../lib/get_fields'; +import { getFields } from '../lib/get_fields'; +import { getIndexPatternService } from '../lib/get_index_pattern_service'; export default (server) => { server.route({ + config: { + pre: [getIndexPatternService] + }, path: '/api/metrics/fields', method: 'GET', handler: (req, reply) => { From 90c713fd18133cba55dcaa5bc665bcb9d48e4ccc Mon Sep 17 00:00:00 2001 From: Court Ewing Date: Mon, 24 Jul 2017 12:49:16 -0400 Subject: [PATCH 004/165] Remove translations from management section (#13049) We need to revisit how we embed translations into templates, so until we do we might as well go back to embedding text directly in the page. The translation implementation now makes it difficult to navigate throughout complicated HTML. It also suffers from an inability to flag on unused translation keys, which creates a good deal of technical debt. Close to half of all translation keys in the translation file in this initial pilot were already unused since it was introduced a couple of months ago. --- .../create_index_pattern.html | 49 +++++++++---------- .../create_index_pattern.js | 8 +-- .../pick_create_button_text.js | 10 ++-- .../edit_index_pattern.html | 2 +- .../management/sections/indices/index.html | 8 +-- src/core_plugins/kibana/translations/en.json | 44 +---------------- 6 files changed, 37 insertions(+), 84 deletions(-) diff --git a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern/create_index_pattern.html b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern/create_index_pattern.html index ad497a5f4dee8..b3a65d8db7992 100644 --- a/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern/create_index_pattern.html +++ b/src/core_plugins/kibana/public/management/sections/indices/create_index_pattern/create_index_pattern.html @@ -5,15 +5,15 @@ data-test-subj="createIndexPatternContainer" class="kuiViewContent" > -

+

+ Configure an index pattern +

-

+

+ In order to use Kibana you must configure at least one index pattern. + Index patterns are used to identify the Elasticsearch index to run + search and analytics against. They are also used to configure fields. +

@@ -27,14 +27,15 @@
@@ -67,18 +68,16 @@
-

+

+ Patterns allow you to define dynamic index names using * as a wildcard. Example: logstash-* +

-
+

+ Expand your time range +

+

-

Expand your time range

-

I see you are looking at an index with a date field. It is possible your query does not match anything in the current time range, or that there is no data at all in the currently selected time range. Click the button below to open the time picker. For future reference you can open the time picker by clicking on the time picker button in the top right corner of your screen. + I see you are looking at an index with a date field. It is possible your query does not match anything in the current time range, or that there is no data at all in the currently selected time range. Click the button below to open the time picker. For future reference you can open the time picker by clicking on the + + button in the top right corner of your screen.

-

Refine your query

+

+ Refine your query +

+

The search bar at the top uses Elasticsearch's support for Lucene Query String syntax. Let's say we're searching web server logs that have been parsed into a few fields.

-

Examples:

Find requests that contain the number 200, in any field:
200
From e3aeb0bdfa1c270d4a86dedb2c63635a12ce6728 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 26 Jul 2017 16:33:16 -0700 Subject: [PATCH 018/165] Update filter editor docs with addition of advanced option (#13084) --- docs/discover/field-filter.asciidoc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/discover/field-filter.asciidoc b/docs/discover/field-filter.asciidoc index 9bb1d33503f10..e9b05f6a0fbe8 100644 --- a/docs/discover/field-filter.asciidoc +++ b/docs/discover/field-filter.asciidoc @@ -62,8 +62,7 @@ The following operators can be selected: `is not between`:: Filter where the value for the field is not in the given range. `exists`:: Filter where any value is present for the field. `does not exist`:: Filter where no value is present for the field. -. Choose the value(s) for your filter. Values from your indices may be suggested -as selections if you are filtering against an aggregatable field. +. Choose the value(s) for your filter. + image::images/add_filter_value.png[] . (Optional) Specify a label for the filter. If you specify a label, it will be @@ -71,6 +70,10 @@ displayed below the query bar instead of the filter definition. . Click *Save*. The filter will be applied to your search and be displayed below the query bar. +NOTE: To make the filter editor more user-friendly, you can enable the `filterEditor:suggestValues` advanced setting. +Enabling this will cause the editor to suggest values from your indices if you are filtering against an aggregatable +field. However, this is not recommended for extremely large datasets, as it can result in long queries. + [float] [[filter-pinning]] === Managing Filters From dd8c1abb19047458ee490ffa647566bca5300097 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 27 Jul 2017 08:47:04 -0600 Subject: [PATCH 019/165] date_histogram: some bars are too big (#13068) * handle data sets with holes * add unit tests --- .../date_histogram/_rows_series_with_holes.js | 103 ++++++++++++++++++ .../_series_monthly_interval.js | 75 +++++++++++++ .../__tests__/visualizations/column_chart.js | 70 ++++++++++++ .../point_series/column_chart.js | 4 + 4 files changed, 252 insertions(+) create mode 100644 src/fixtures/vislib/mock_data/date_histogram/_rows_series_with_holes.js create mode 100644 src/fixtures/vislib/mock_data/date_histogram/_series_monthly_interval.js diff --git a/src/fixtures/vislib/mock_data/date_histogram/_rows_series_with_holes.js b/src/fixtures/vislib/mock_data/date_histogram/_rows_series_with_holes.js new file mode 100644 index 0000000000000..144ab06ee9ce0 --- /dev/null +++ b/src/fixtures/vislib/mock_data/date_histogram/_rows_series_with_holes.js @@ -0,0 +1,103 @@ +import moment from 'moment'; + +export const rowsSeriesWithHoles = { + rows: [ + { + 'label': '', + 'xAxisLabel': '@timestamp per 30 sec', + 'ordered': { + 'date': true, + 'min': 1411761457636, + 'max': 1411762357636, + 'interval': 30000 + }, + 'yAxisLabel': 'Count of documents', + 'series': [ + { + 'label': 'Count', + 'values': [ + { + 'x': 1411761450000, + 'y': 41 + }, + { + 'x': 1411761510000, + 'y': 22 + }, + { + 'x': 1411761540000, + 'y': 17 + }, + { + 'x': 1411761840000, + 'y': 20 + }, + { + 'x': 1411761870000, + 'y': 20 + }, + { + 'x': 1411761900000, + 'y': 21 + }, + { + 'x': 1411761930000, + 'y': 17 + }, + { + 'x': 1411761960000, + 'y': 20 + }, + { + 'x': 1411761990000, + 'y': 13 + }, + { + 'x': 1411762020000, + 'y': 14 + }, + { + 'x': 1411762050000, + 'y': 25 + }, + { + 'x': 1411762080000, + 'y': 17 + }, + { + 'x': 1411762110000, + 'y': 14 + }, + { + 'x': 1411762140000, + 'y': 22 + }, + { + 'x': 1411762170000, + 'y': 14 + }, + { + 'x': 1411762200000, + 'y': 19 + }, + { + 'x': 1411762320000, + 'y': 15 + }, + { + 'x': 1411762350000, + 'y': 4 + } + ] + } + ], + 'hits': 533, + 'xAxisFormatter': function (thing) { + return moment(thing); + }, + 'tooltipFormatter': function (d) { + return d; + } + } + ] +}; diff --git a/src/fixtures/vislib/mock_data/date_histogram/_series_monthly_interval.js b/src/fixtures/vislib/mock_data/date_histogram/_series_monthly_interval.js new file mode 100644 index 0000000000000..791b072f2cd03 --- /dev/null +++ b/src/fixtures/vislib/mock_data/date_histogram/_series_monthly_interval.js @@ -0,0 +1,75 @@ +import moment from 'moment'; + +export const seriesMonthlyInterval = { + 'label': '', + 'xAxisLabel': '@timestamp per month', + 'ordered': { + 'date': true, + 'min': 1451631600000, + 'max': 1483254000000, + 'interval': 2678000000 + }, + 'yAxisLabel': 'Count of documents', + 'series': [ + { + 'label': 'Count', + 'values': [ + { + 'x': 1451631600000, + 'y': 10220 + }, + { + 'x': 1454310000000, + 'y': 9997, + }, + { + 'x': 1456815600000, + 'y': 10792, + }, + { + 'x': 1459490400000, + 'y': 10262 + }, + { + 'x': 1462082400000, + 'y': 10080 + }, + { + 'x': 1464760800000, + 'y': 11161 + }, + { + 'x': 1467352800000, + 'y': 9933 + }, + { + 'x': 1470031200000, + 'y': 10342 + }, + { + 'x': 1472709600000, + 'y': 10887 + }, + { + 'x': 1475301600000, + 'y': 9666 + }, + { + 'x': 1477980000000, + 'y': 9556 + }, + { + 'x': 1480575600000, + 'y': 11644 + } + ] + } + ], + 'hits': 533, + 'xAxisFormatter': function (thing) { + return moment(thing); + }, + 'tooltipFormatter': function (d) { + return d; + } +}; diff --git a/src/ui/public/vislib/__tests__/visualizations/column_chart.js b/src/ui/public/vislib/__tests__/visualizations/column_chart.js index 383ba217f8e89..c3baab9d7883e 100644 --- a/src/ui/public/vislib/__tests__/visualizations/column_chart.js +++ b/src/ui/public/vislib/__tests__/visualizations/column_chart.js @@ -10,6 +10,8 @@ import seriesNeg from 'fixtures/vislib/mock_data/date_histogram/_series_neg'; import termsColumns from 'fixtures/vislib/mock_data/terms/_columns'; import histogramRows from 'fixtures/vislib/mock_data/histogram/_rows'; import stackedSeries from 'fixtures/vislib/mock_data/date_histogram/_stacked_series'; +import { seriesMonthlyInterval } from 'fixtures/vislib/mock_data/date_histogram/_series_monthly_interval'; +import { rowsSeriesWithHoles } from 'fixtures/vislib/mock_data/date_histogram/_rows_series_with_holes'; import $ from 'jquery'; import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; import 'ui/persisted_state'; @@ -184,3 +186,71 @@ dataTypesArray.forEach(function (dataType) { }); }); }); + +describe('datumWidth - split chart data set with holes', function () { + let vis; + let persistedState; + const visLibParams = { + type: 'histogram', + addLegend: true, + addTooltip: true, + mode: 'stacked', + zeroFill: true + }; + + beforeEach(ngMock.module('kibana')); + beforeEach(ngMock.inject(function (Private, $injector) { + vis = Private(FixturesVislibVisFixtureProvider)(visLibParams); + persistedState = new ($injector.get('PersistedState'))(); + vis.on('brush', _.noop); + vis.render(rowsSeriesWithHoles, persistedState); + })); + + afterEach(function () { + vis.destroy(); + }); + + it('should not have bar widths that span multiple time bins', function () { + expect(vis.handler.charts.length).to.equal(1); + const chart = vis.handler.charts[0]; + const rects = $(chart.chartEl).find('.series rect'); + const MAX_WIDTH_IN_PIXELS = 27; + rects.each(function () { + const width = $(this).attr('width'); + expect(width).to.be.lessThan(MAX_WIDTH_IN_PIXELS); + }); + }); +}); + +describe('datumWidth - monthly interval', function () { + let vis; + let persistedState; + const visLibParams = { + type: 'histogram', + addLegend: true, + addTooltip: true, + mode: 'stacked', + zeroFill: true + }; + + beforeEach(ngMock.module('kibana')); + beforeEach(ngMock.inject(function (Private, $injector) { + vis = Private(FixturesVislibVisFixtureProvider)(visLibParams); + persistedState = new ($injector.get('PersistedState'))(); + vis.on('brush', _.noop); + vis.render(seriesMonthlyInterval, persistedState); + })); + + afterEach(function () { + vis.destroy(); + }); + + it('should vary bar width when date histogram intervals are not equal', function () { + expect(vis.handler.charts.length).to.equal(1); + const chart = vis.handler.charts[0]; + const rects = $(chart.chartEl).find('.series rect'); + const januaryBarWidth = $(rects.get(0)).attr('width'); + const febuaryBarWidth = $(rects.get(1)).attr('width'); + expect(febuaryBarWidth).to.be.lessThan(januaryBarWidth); + }); +}); diff --git a/src/ui/public/vislib/visualizations/point_series/column_chart.js b/src/ui/public/vislib/visualizations/point_series/column_chart.js index fb6a9759f7e2a..46c307a99ce4e 100644 --- a/src/ui/public/vislib/visualizations/point_series/column_chart.js +++ b/src/ui/public/vislib/visualizations/point_series/column_chart.js @@ -20,6 +20,10 @@ export function VislibVisualizationsColumnChartProvider(Private) { let datumWidth = defaultWidth; if (nextDatum) { datumWidth = ((scale(nextDatum.x) - scale(datum.x)) - gutterWidth) / groupCount; + // To handle data-sets with holes, do not let width be larger than default. + if (datumWidth > defaultWidth) { + datumWidth = defaultWidth; + } } return datumWidth; } From e922f00445878a3f3bb192f2600b627729eca0ba Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Thu, 27 Jul 2017 10:52:41 -0700 Subject: [PATCH 020/165] Upgrade eslint config to 0.8.1. (#13128) * Fix incorrect peerDependency and bump eslint config version to 0.8.1. * Upgrade eslint config to 0.8.1. Fix JSX to adhere to new formatting rules. --- package.json | 4 +- packages/eslint-config-kibana/package.json | 4 +- .../public/dashboard/top_nav/clone_modal.js | 3 +- .../dashboard/top_nav/show_clone_modal.js | 2 +- .../public/components/add_delete_buttons.js | 6 +- .../metrics/public/components/aggs/agg.js | 6 +- .../metrics/public/components/aggs/agg_row.js | 7 +- .../public/components/aggs/agg_select.js | 3 +- .../public/components/aggs/calculation.js | 12 ++- .../public/components/aggs/cumulative_sum.js | 19 ++-- .../public/components/aggs/derivative.js | 12 ++- .../public/components/aggs/field_select.js | 3 +- .../public/components/aggs/filter_ratio.js | 86 ++++++++++--------- .../public/components/aggs/metric_select.js | 3 +- .../public/components/aggs/moving_average.js | 21 +++-- .../public/components/aggs/percentile.js | 27 ++++-- .../public/components/aggs/percentile_rank.js | 12 ++- .../public/components/aggs/positive_only.js | 9 +- .../public/components/aggs/serial_diff.js | 12 ++- .../public/components/aggs/series_agg.js | 19 ++-- .../metrics/public/components/aggs/static.js | 9 +- .../metrics/public/components/aggs/std_agg.js | 32 ++++--- .../public/components/aggs/std_deviation.js | 15 ++-- .../public/components/aggs/std_sibling.js | 15 ++-- .../metrics/public/components/aggs/vars.js | 9 +- .../public/components/annotations_editor.js | 37 +++++--- .../metrics/public/components/color_picker.js | 28 ++++-- .../metrics/public/components/color_rules.js | 15 ++-- .../public/components/custom_color_picker.js | 3 +- .../public/components/data_format_picker.js | 6 +- .../metrics/public/components/icon_select.js | 10 ++- .../public/components/index_pattern.js | 12 ++- .../components/lib/create_agg_row_render.js | 3 +- .../public/components/markdown_editor.js | 6 +- .../public/components/panel_config/gauge.js | 47 ++++++---- .../components/panel_config/markdown.js | 47 ++++++---- .../public/components/panel_config/metric.js | 29 +++++-- .../components/panel_config/timeseries.js | 57 ++++++++---- .../public/components/panel_config/top_n.js | 38 +++++--- .../public/components/series_config.js | 15 ++-- .../public/components/series_editor.js | 6 +- .../metrics/public/components/split.js | 12 ++- .../public/components/splits/everything.js | 3 +- .../public/components/splits/filter.js | 6 +- .../public/components/splits/filter_items.js | 12 ++- .../public/components/splits/filters.js | 6 +- .../components/splits/group_by_select.js | 3 +- .../metrics/public/components/splits/terms.js | 12 ++- .../metrics/public/components/vis_editor.js | 12 ++- .../components/vis_editor_visualization.js | 20 +++-- .../metrics/public/components/vis_picker.js | 5 +- .../components/vis_types/gauge/series.js | 37 +++++--- .../components/vis_types/markdown/series.js | 35 +++++--- .../components/vis_types/metric/series.js | 37 +++++--- .../components/vis_types/timeseries/config.js | 63 +++++++++----- .../components/vis_types/timeseries/series.js | 37 +++++--- .../components/vis_types/top_n/series.js | 37 +++++--- .../public/components/visualization.js | 2 +- .../metrics/public/components/yes_no.js | 12 ++- .../visualizations/components/annotation.js | 16 ++-- .../visualizations/components/flot_chart.js | 6 +- .../public/visualizations/components/gauge.js | 25 ++++-- .../visualizations/components/gauge_vis.js | 3 +- .../visualizations/components/metric.js | 3 +- .../visualizations/components/resize.js | 3 +- .../visualizations/components/timeseries.js | 6 +- .../components/timeseries_chart.js | 9 +- .../public/visualizations/components/top_n.js | 12 ++- .../lib/create_legend_series.js | 5 +- .../collapse_button.test.js.snap | 8 +- .../collapse_button/collapse_button.js | 16 ++-- .../empty_table_prompt.test.js | 4 +- .../components/info_button/info_button.js | 2 +- ui_framework/components/pager/pager.js | 10 +-- ui_framework/components/pager/pager.test.js | 25 +++--- .../pager/pager_button_group.test.js | 29 ++++--- .../components/table/table_row_cell.test.js | 2 +- .../table/table_row_check_box_cell.js | 21 +++-- .../table/table_row_check_box_cell.test.js | 2 +- .../tool_bar/tool_bar_search_box.js | 29 ++++--- .../src/components/guide_nav/guide_nav.js | 4 +- .../guide_sandbox_code_toggle.js | 2 +- .../components/guide_section/guide_section.js | 2 +- .../views/action_item/action_items_in_menu.js | 82 +++++++++--------- ui_framework/doc_site/src/views/bar/bar.js | 2 +- .../doc_site/src/views/bar/bar_one_section.js | 20 ++--- .../src/views/bar/bar_three_sections.js | 50 +++++------ .../src/views/button/button_elements.js | 6 +- ui_framework/doc_site/src/views/card/card.js | 2 +- .../doc_site/src/views/card/card_group.js | 4 +- .../empty_table_prompt/empty_table_prompt.js | 24 +++--- .../table_with_empty_prompt.js | 10 +-- .../doc_site/src/views/event/event.js | 2 +- .../doc_site/src/views/event/event_menu.js | 6 +- .../src/views/event/events_sandbox_content.js | 6 +- .../src/views/form_layout/field_group.js | 4 +- .../header_bar/header_bar_sandbox_content.js | 24 +++--- .../header_bar/header_bar_two_sections.js | 2 +- .../src/views/info_button/info_button.js | 2 +- .../views/local_nav/local_nav_breadcrumbs.js | 2 +- .../src/views/local_nav/local_nav_dropdown.js | 6 +- .../local_nav/local_nav_dropdown_panels.js | 6 +- .../local_nav/local_nav_menu_item_states.js | 4 +- .../src/views/local_nav/local_nav_search.js | 4 +- .../views/local_nav/local_nav_search_error.js | 4 +- .../src/views/local_nav/local_nav_simple.js | 2 +- .../src/views/local_nav/local_nav_tabs.js | 2 +- .../doc_site/src/views/modal/modal_example.js | 16 ++-- .../src/views/not_found/not_found_view.js | 2 +- .../src/views/table/controlled_table.js | 10 +-- .../table/controlled_table_loading_items.js | 4 +- .../doc_site/src/views/table/fluid_table.js | 86 +++++++++---------- .../doc_site/src/views/tool_bar/tool_bar.js | 6 +- .../src/views/tool_bar/tool_bar_footer.js | 4 +- 114 files changed, 1039 insertions(+), 669 deletions(-) diff --git a/package.json b/package.json index a94a4ab1d4b96..d78858fc48777 100644 --- a/package.json +++ b/package.json @@ -203,7 +203,7 @@ "yauzl": "2.7.0" }, "devDependencies": { - "@elastic/eslint-config-kibana": "0.6.1", + "@elastic/eslint-config-kibana": "0.8.1", "@elastic/eslint-import-resolver-kibana": "0.8.1", "@elastic/eslint-plugin-kibana-custom": "1.0.3", "angular-mocks": "1.4.7", @@ -221,7 +221,7 @@ "eslint-plugin-import": "2.3.0", "eslint-plugin-jest": "20.0.3", "eslint-plugin-mocha": "4.9.0", - "eslint-plugin-react": "7.0.1", + "eslint-plugin-react": "7.1.0", "event-stream": "3.3.2", "expect.js": "0.3.1", "faker": "1.1.0", diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json index 69abd38993ce9..f3bb21dfe7c6d 100644 --- a/packages/eslint-config-kibana/package.json +++ b/packages/eslint-config-kibana/package.json @@ -1,6 +1,6 @@ { "name": "@elastic/eslint-config-kibana", - "version": "0.8.0", + "version": "0.8.1", "description": "The eslint config used by the kibana team", "main": ".eslintrc.js", "scripts": { @@ -23,6 +23,6 @@ "eslint-plugin-babel": "^4.1.1", "eslint-plugin-import": "^2.6.0", "eslint-plugin-mocha": "^4.9.0", - "eslint-plugin-react": "^7.0.1" + "eslint-plugin-react": "^7.1.0" } } diff --git a/src/core_plugins/kibana/public/dashboard/top_nav/clone_modal.js b/src/core_plugins/kibana/public/dashboard/top_nav/clone_modal.js index 0afdcfe3041c1..564d3d0912f68 100644 --- a/src/core_plugins/kibana/public/dashboard/top_nav/clone_modal.js +++ b/src/core_plugins/kibana/public/dashboard/top_nav/clone_modal.js @@ -59,7 +59,8 @@ export class DashboardCloneModal extends React.Component { data-test-subj="clonedDashboardTitle" className="kuiTextInput kuiTextInput--large" value={ this.state.newDashboardName } - onChange={ this.onInputChange } /> + onChange={ this.onInputChange } + /> diff --git a/src/core_plugins/kibana/public/dashboard/top_nav/show_clone_modal.js b/src/core_plugins/kibana/public/dashboard/top_nav/show_clone_modal.js index 5badb1ca9851b..175d75bc68cf9 100644 --- a/src/core_plugins/kibana/public/dashboard/top_nav/show_clone_modal.js +++ b/src/core_plugins/kibana/public/dashboard/top_nav/show_clone_modal.js @@ -17,7 +17,7 @@ export function showCloneModal(onClone, title) { }; document.body.appendChild(container); const element = ( - + ); ReactDOM.render(element, container); } diff --git a/src/core_plugins/metrics/public/components/add_delete_buttons.js b/src/core_plugins/metrics/public/components/add_delete_buttons.js index afc9ff9a9b74d..38ebfc1bbbec1 100644 --- a/src/core_plugins/metrics/public/components/add_delete_buttons.js +++ b/src/core_plugins/metrics/public/components/add_delete_buttons.js @@ -9,7 +9,7 @@ function AddDeleteButtons(props) { return ( - + ); @@ -21,7 +21,7 @@ function AddDeleteButtons(props) { return ( - + ); @@ -33,7 +33,7 @@ function AddDeleteButtons(props) { clone = ( - + ); diff --git a/src/core_plugins/metrics/public/components/aggs/agg.js b/src/core_plugins/metrics/public/components/aggs/agg.js index 9cd1c0a7537a4..913bd85dae10f 100644 --- a/src/core_plugins/metrics/public/components/aggs/agg.js +++ b/src/core_plugins/metrics/public/components/aggs/agg.js @@ -15,7 +15,8 @@ function Agg(props) { className={props.className} style={style} onMouseDown={props.onMouseDown} - onTouchStart={props.onTouchStart}> + onTouchStart={props.onTouchStart} + > + siblings={props.siblings} + />
); diff --git a/src/core_plugins/metrics/public/components/aggs/agg_row.js b/src/core_plugins/metrics/public/components/aggs/agg_row.js index a9642f7c25a4e..480c7f7236306 100644 --- a/src/core_plugins/metrics/public/components/aggs/agg_row.js +++ b/src/core_plugins/metrics/public/components/aggs/agg_row.js @@ -18,7 +18,7 @@ function AggRow(props) {
- +
@@ -29,7 +29,7 @@ function AggRow(props) {
- +
{props.children} { dragHandle } @@ -38,7 +38,8 @@ function AggRow(props) { deleteTooltip="Delete Metric" onAdd={props.onAdd} onDelete={props.onDelete} - disableDelete={props.disableDelete}/> + disableDelete={props.disableDelete} + />
); diff --git a/src/core_plugins/metrics/public/components/aggs/agg_select.js b/src/core_plugins/metrics/public/components/aggs/agg_select.js index 51c2e0b8996a2..ae04f639c5d8c 100644 --- a/src/core_plugins/metrics/public/components/aggs/agg_select.js +++ b/src/core_plugins/metrics/public/components/aggs/agg_select.js @@ -147,7 +147,8 @@ function AggSelect(props) { options={options} value={props.value} optionComponent={AggSelectOption} - onChange={handleChange}/> + onChange={handleChange} + />
); } diff --git a/src/core_plugins/metrics/public/components/aggs/calculation.js b/src/core_plugins/metrics/public/components/aggs/calculation.js index 44e15b1475448..b40a3f14e8cc3 100644 --- a/src/core_plugins/metrics/public/components/aggs/calculation.js +++ b/src/core_plugins/metrics/public/components/aggs/calculation.js @@ -35,21 +35,24 @@ class CalculationAgg extends Component { model={this.props.model} onAdd={this.props.onAdd} onDelete={this.props.onDelete} - siblings={this.props.siblings}> + siblings={this.props.siblings} + >
Aggregation
+ onChange={handleSelectChange('type')} + />
Variables
+ model={model} + />
@@ -60,7 +63,8 @@ class CalculationAgg extends Component { className="vis_editor__input-grows-100" type="text" onChange={handleTextChange('script')} - value={model.script}/> + value={model.script} + />
diff --git a/src/core_plugins/metrics/public/components/aggs/cumulative_sum.js b/src/core_plugins/metrics/public/components/aggs/cumulative_sum.js index 6ec44d7faaf85..0c780e29e91f3 100644 --- a/src/core_plugins/metrics/public/components/aggs/cumulative_sum.js +++ b/src/core_plugins/metrics/public/components/aggs/cumulative_sum.js @@ -10,18 +10,20 @@ function CumlativeSumAgg(props) { const handleChange = createChangeHandler(props.onChange, model); const handleSelectChange = createSelectHandler(handleChange); return ( - +
Aggregation
+ onChange={handleSelectChange('type')} + />
Metric
@@ -29,7 +31,8 @@ function CumlativeSumAgg(props) { onChange={handleSelectChange('field')} metrics={siblings} metric={model} - value={model.field}/> + value={model.field} + />
); diff --git a/src/core_plugins/metrics/public/components/aggs/derivative.js b/src/core_plugins/metrics/public/components/aggs/derivative.js index 3e27a2e389c22..7206f33e21c61 100644 --- a/src/core_plugins/metrics/public/components/aggs/derivative.js +++ b/src/core_plugins/metrics/public/components/aggs/derivative.js @@ -24,13 +24,15 @@ class DerivativeAgg extends Component { model={this.props.model} onAdd={this.props.onAdd} onDelete={this.props.onDelete} - siblings={this.props.siblings}> + siblings={this.props.siblings} + >
Aggregation
+ onChange={handleSelectChange('type')} + />
Metric
@@ -38,7 +40,8 @@ class DerivativeAgg extends Component { onChange={handleSelectChange('field')} metrics={siblings} metric={model} - value={model.field}/> + value={model.field} + />
Units (1s, 1m, etc)
@@ -46,7 +49,8 @@ class DerivativeAgg extends Component { className="vis_editor__input" onChange={handleTextChange('unit')} value={model.unit} - type="text"/> + type="text" + />
); diff --git a/src/core_plugins/metrics/public/components/aggs/field_select.js b/src/core_plugins/metrics/public/components/aggs/field_select.js index 10f5f74ab5d8f..92d6a0520589d 100644 --- a/src/core_plugins/metrics/public/components/aggs/field_select.js +++ b/src/core_plugins/metrics/public/components/aggs/field_select.js @@ -19,7 +19,8 @@ function FieldSelect(props) { disabled={props.disabled} options={options} value={props.value} - onChange={props.onChange}/> + onChange={props.onChange} + /> ); } diff --git a/src/core_plugins/metrics/public/components/aggs/filter_ratio.js b/src/core_plugins/metrics/public/components/aggs/filter_ratio.js index ab40d4f270529..734f8ddb63556 100644 --- a/src/core_plugins/metrics/public/components/aggs/filter_ratio.js +++ b/src/core_plugins/metrics/public/components/aggs/filter_ratio.js @@ -34,7 +34,8 @@ class FilterRatioAgg extends Component { model={this.props.model} onAdd={this.props.onAdd} onDelete={this.props.onDelete} - siblings={this.props.siblings}> + siblings={this.props.siblings} + >
@@ -42,47 +43,52 @@ class FilterRatioAgg extends Component { + onChange={handleSelectChange('type')} + />
-
-
Numerator
- -
-
-
Denominator
- -
-
-
-
-
Metric Aggregation
- +
+
Numerator
+ +
+
+
Denominator
+ +
+
+
+
+
Metric Aggregation
+ +
+ { model.metric_agg !== 'count' ? ( +
+
Field
+ +
) : null } +
- { model.metric_agg !== 'count' ? ( -
-
Field
- -
) : null } -
-
); } diff --git a/src/core_plugins/metrics/public/components/aggs/metric_select.js b/src/core_plugins/metrics/public/components/aggs/metric_select.js index f7e7e84d81386..27aa0ba9b2861 100644 --- a/src/core_plugins/metrics/public/components/aggs/metric_select.js +++ b/src/core_plugins/metrics/public/components/aggs/metric_select.js @@ -41,7 +41,8 @@ function MetricSelect(props) { placeholder="Select metric..." options={options.concat(props.additionalOptions)} value={value} - onChange={onChange}/> + onChange={onChange} + /> ); } diff --git a/src/core_plugins/metrics/public/components/aggs/moving_average.js b/src/core_plugins/metrics/public/components/aggs/moving_average.js index ee922e478ce50..b2c12aa7aa993 100644 --- a/src/core_plugins/metrics/public/components/aggs/moving_average.js +++ b/src/core_plugins/metrics/public/components/aggs/moving_average.js @@ -39,7 +39,8 @@ class MovingAverageAgg extends Component { model={this.props.model} onAdd={this.props.onAdd} onDelete={this.props.onDelete} - siblings={this.props.siblings}> + siblings={this.props.siblings} + >
@@ -47,7 +48,8 @@ class MovingAverageAgg extends Component { + onChange={handleSelectChange('type')} + />
Metric
@@ -55,7 +57,8 @@ class MovingAverageAgg extends Component { onChange={handleSelectChange('field')} metrics={siblings} metric={model} - value={model.field}/> + value={model.field} + />
@@ -66,7 +69,8 @@ class MovingAverageAgg extends Component { placeholder="Select..." onChange={ handleSelectChange('model') } value={this.props.model.model} - options={ modelOptions }/> + options={ modelOptions } + />
Window Size
@@ -74,7 +78,8 @@ class MovingAverageAgg extends Component { className="vis_editor__input-grows-100" type="text" onChange={handleNumberChange('window')} - value={model.window}/> + value={model.window} + />
Minimize
@@ -82,7 +87,8 @@ class MovingAverageAgg extends Component { placeholder="Select..." onChange={ handleSelectChange('minimize') } value={model.minimize} - options={ minimizeOptions }/> + options={ minimizeOptions } + />
@@ -92,7 +98,8 @@ class MovingAverageAgg extends Component { className="vis_editor__input-grows-100" type="text" onChange={handleTextChange('settings')} - value={model.settings}/> + value={model.settings} + />
diff --git a/src/core_plugins/metrics/public/components/aggs/percentile.js b/src/core_plugins/metrics/public/components/aggs/percentile.js index 03dbe0f559a55..0573797d0ff46 100644 --- a/src/core_plugins/metrics/public/components/aggs/percentile.js +++ b/src/core_plugins/metrics/public/components/aggs/percentile.js @@ -51,14 +51,16 @@ class Percentiles extends Component { type="number" step="1" onChange={this.handleTextChange(model, 'value')} - value={model.value}/> + value={model.value} + />
Mode
+ value={model.percentile} + />
Shade (0 to 1)
+ value={model.shade} + />
+ disableDelete={items.length < 2} + /> ); } @@ -132,7 +137,8 @@ class PercentileAgg extends Component { model={this.props.model} onAdd={this.props.onAdd} onDelete={this.props.onDelete} - siblings={this.props.siblings}> + siblings={this.props.siblings} + >
@@ -140,7 +146,8 @@ class PercentileAgg extends Component { + onChange={handleSelectChange('type')} + />
Field
@@ -150,13 +157,15 @@ class PercentileAgg extends Component { restrict="numeric" indexPattern={indexPattern} value={model.field} - onChange={handleSelectChange('field')}/> + onChange={handleSelectChange('field')} + />
+ model={model} + />
); diff --git a/src/core_plugins/metrics/public/components/aggs/percentile_rank.js b/src/core_plugins/metrics/public/components/aggs/percentile_rank.js index 312f8f7af814a..e5c32a2c291ef 100644 --- a/src/core_plugins/metrics/public/components/aggs/percentile_rank.js +++ b/src/core_plugins/metrics/public/components/aggs/percentile_rank.js @@ -26,13 +26,15 @@ class PercentileRankAgg extends Component { model={this.props.model} onAdd={this.props.onAdd} onDelete={this.props.onDelete} - siblings={this.props.siblings}> + siblings={this.props.siblings} + >
Aggregation
+ onChange={handleSelectChange('type')} + />
Field
@@ -42,14 +44,16 @@ class PercentileRankAgg extends Component { restrict="numeric" indexPattern={indexPattern} value={model.field} - onChange={handleSelectChange('field')}/> + onChange={handleSelectChange('field')} + />
Value
+ onChange={handleTextChange('value')} + />
); diff --git a/src/core_plugins/metrics/public/components/aggs/positive_only.js b/src/core_plugins/metrics/public/components/aggs/positive_only.js index 6d4fe35f8fb2e..afb243c6effc0 100644 --- a/src/core_plugins/metrics/public/components/aggs/positive_only.js +++ b/src/core_plugins/metrics/public/components/aggs/positive_only.js @@ -22,13 +22,15 @@ class PositiveOnlyAgg extends Component { model={this.props.model} onAdd={this.props.onAdd} onDelete={this.props.onDelete} - siblings={this.props.siblings}> + siblings={this.props.siblings} + >
Aggregation
+ onChange={handleSelectChange('type')} + />
Metric
@@ -36,7 +38,8 @@ class PositiveOnlyAgg extends Component { onChange={handleSelectChange('field')} metrics={siblings} metric={model} - value={model.field}/> + value={model.field} + />
); diff --git a/src/core_plugins/metrics/public/components/aggs/serial_diff.js b/src/core_plugins/metrics/public/components/aggs/serial_diff.js index 6e7f0c9be24f6..1b102390c80aa 100644 --- a/src/core_plugins/metrics/public/components/aggs/serial_diff.js +++ b/src/core_plugins/metrics/public/components/aggs/serial_diff.js @@ -23,13 +23,15 @@ class SerialDiffAgg extends Component { model={this.props.model} onAdd={this.props.onAdd} onDelete={this.props.onDelete} - siblings={this.props.siblings}> + siblings={this.props.siblings} + >
Aggregation
+ onChange={handleSelectChange('type')} + />
Metric
@@ -37,7 +39,8 @@ class SerialDiffAgg extends Component { onChange={handleSelectChange('field')} metrics={siblings} metric={model} - value={model.field}/> + value={model.field} + />
Lag
@@ -45,7 +48,8 @@ class SerialDiffAgg extends Component { className="vis_editor__input" onChange={handleNumberChange('lag')} value={model.lag} - type="text"/> + type="text" + />
); diff --git a/src/core_plugins/metrics/public/components/aggs/series_agg.js b/src/core_plugins/metrics/public/components/aggs/series_agg.js index 5700ce36cba3e..c7dc99344f6c8 100644 --- a/src/core_plugins/metrics/public/components/aggs/series_agg.js +++ b/src/core_plugins/metrics/public/components/aggs/series_agg.js @@ -24,25 +24,28 @@ function SeriesAgg(props) { ]; return ( - +
Aggregation
+ onChange={handleSelectChange('type')} + />
Function
+ onChange={handleTextChange('sigma')} + />
Mode
+ onChange={handleTextChange('sigma')} + />
); @@ -43,7 +44,8 @@ class StandardSiblingAgg extends Component { + options={operatorOptions} + /> + onChange={this.handleChange(model, 'value', Number)} + />
+ disableDelete={items.length < 2} + />
); diff --git a/src/core_plugins/metrics/public/components/custom_color_picker.js b/src/core_plugins/metrics/public/components/custom_color_picker.js index bb5b4aa53557c..382aec8a116aa 100644 --- a/src/core_plugins/metrics/public/components/custom_color_picker.js +++ b/src/core_plugins/metrics/public/components/custom_color_picker.js @@ -56,7 +56,8 @@ export class CustomColorPicker extends Component { + onClick={handleSwatchChange} + /> ); }); diff --git a/src/core_plugins/metrics/public/components/data_format_picker.js b/src/core_plugins/metrics/public/components/data_format_picker.js index c718d09f07498..346ec7e2a4820 100644 --- a/src/core_plugins/metrics/public/components/data_format_picker.js +++ b/src/core_plugins/metrics/public/components/data_format_picker.js @@ -47,7 +47,8 @@ class DataFormatPicker extends Component { defaultValue={value} ref={(el) => this.custom = el} onChange={this.handleCustomChange} - type="text"/> + type="text" + /> ); } @@ -61,7 +62,8 @@ class DataFormatPicker extends Component { clearable={false} value={defaultValue} options={options} - onChange={this.handleChange}/> + onChange={this.handleChange} + /> {custom} diff --git a/src/core_plugins/metrics/public/components/icon_select.js b/src/core_plugins/metrics/public/components/icon_select.js index 2b5e7dd817a04..8a93f10e63154 100644 --- a/src/core_plugins/metrics/public/components/icon_select.js +++ b/src/core_plugins/metrics/public/components/icon_select.js @@ -29,7 +29,8 @@ class IconOption extends Component { const icon = this.props.option.value; const label = this.props.option.label; return ( - @@ -71,7 +72,7 @@ function IconValue(props) { className="Select-value-label" aria-label={`${label} icon`} > - + { props.children } @@ -92,7 +93,8 @@ function IconSelect(props) { value={props.value} optionComponent={IconOption} valueComponent={IconValue} - options={props.icons} /> + options={props.icons} + /> ); } diff --git a/src/core_plugins/metrics/public/components/index_pattern.js b/src/core_plugins/metrics/public/components/index_pattern.js index dc2b9ebefa22a..bd19c53e0b1bd 100644 --- a/src/core_plugins/metrics/public/components/index_pattern.js +++ b/src/core_plugins/metrics/public/components/index_pattern.js @@ -28,7 +28,8 @@ class IndexPattern extends Component { className="vis_editor__input" disabled={this.props.disabled} onChange={handleTextChange(indexPatternName, '*')} - value={model[indexPatternName]}/> + value={model[indexPatternName]} + />
Time Field
+ fields={fields} + />
Interval (auto, 1m, 1d, 1w, 1y)
+ value={model[intervalName]} + />
Drop Last Bucket
+ onChange={this.props.onChange} + /> ); } diff --git a/src/core_plugins/metrics/public/components/lib/create_agg_row_render.js b/src/core_plugins/metrics/public/components/lib/create_agg_row_render.js index 9594e32aa4c11..c8dd07f689f91 100644 --- a/src/core_plugins/metrics/public/components/lib/create_agg_row_render.js +++ b/src/core_plugins/metrics/public/components/lib/create_agg_row_render.js @@ -20,7 +20,8 @@ export default function createAggRowRender(props) { panel={panel} series={model} siblings={items} - sortData={row.id} /> + sortData={row.id} + /> ); }; } diff --git a/src/core_plugins/metrics/public/components/markdown_editor.js b/src/core_plugins/metrics/public/components/markdown_editor.js index 4e68add3803db..5d1913b949a14 100644 --- a/src/core_plugins/metrics/public/components/markdown_editor.js +++ b/src/core_plugins/metrics/public/components/markdown_editor.js @@ -100,7 +100,8 @@ class MarkdownEditor extends Component { name={`ace-${model.id}`} setOptions={{ wrap: true, fontSize: '14px' }} value={model.markdown} - onChange={this.handleChange}/> + onChange={this.handleChange} + />
The following variables can be used in the Markdown by using the Handlebar (mustache) syntax. Click here for documentation on the available expressions.
@@ -121,7 +122,8 @@ class MarkdownEditor extends Component { {{#each _all}} - {{ label }} {{ last.formatted }} -{{/each}}`} +{{/each}}`} +
diff --git a/src/core_plugins/metrics/public/components/panel_config/gauge.js b/src/core_plugins/metrics/public/components/panel_config/gauge.js index 5bb7553646ab7..17b690d80e613 100644 --- a/src/core_plugins/metrics/public/components/panel_config/gauge.js +++ b/src/core_plugins/metrics/public/components/panel_config/gauge.js @@ -58,7 +58,8 @@ class GaugePanelConfig extends Component { limit={1} model={this.props.model} name={this.props.name} - onChange={this.props.onChange} /> + onChange={this.props.onChange} + /> ); } else { view = ( @@ -66,39 +67,45 @@ class GaugePanelConfig extends Component { + onChange={this.props.onChange} + />
Panel Filter
+ value={model.filter} + />
Ignore Global Filter
+ onChange={this.props.onChange} + />
Background Color
+ value={model.background_color} + />
Gauge Max (empty for auto)
+ value={model.gauge_max} + />
Gauge Style
+ value={model.gauge_inner_width} + />
Gauge Line Width
+ value={model.gauge_width} + />
Color Rules
@@ -131,7 +141,8 @@ class GaugePanelConfig extends Component { secondaryVarName="text" model={model} onChange={this.props.onChange} - name="gauge_color_rules"/> + name="gauge_color_rules" + />
); @@ -139,10 +150,16 @@ class GaugePanelConfig extends Component { return (
-
this.switchTab('data')}>Data
-
this.switchTab('options')}>Panel Options
+
this.switchTab('data')} + >Data +
+
this.switchTab('options')} + >Panel Options +
{view}
diff --git a/src/core_plugins/metrics/public/components/panel_config/markdown.js b/src/core_plugins/metrics/public/components/panel_config/markdown.js index 87a10e15c7ae3..28148e1504218 100644 --- a/src/core_plugins/metrics/public/components/panel_config/markdown.js +++ b/src/core_plugins/metrics/public/components/panel_config/markdown.js @@ -60,7 +60,8 @@ class MarkdownPanelConfig extends Component { fields={this.props.fields} model={this.props.model} name={this.props.name} - onChange={this.props.onChange} /> + onChange={this.props.onChange} + /> ); } else { view = ( @@ -68,31 +69,36 @@ class MarkdownPanelConfig extends Component { + onChange={this.props.onChange} + />
Background Color
+ value={model.background_color} + />
Panel Filter
+ value={model.filter} + />
Ignore Global Filter
+ onChange={this.props.onChange} + />
Show Scrollbars
+ onChange={this.props.onChange} + />
Vertical Alignment
+ value={model.filter} + />
Ignore Global Filter
+ onChange={this.props.onChange} + />
Color Rules
@@ -69,7 +73,8 @@ class MetricPanelConfig extends Component { + name="background_color_rules" + />
); @@ -77,10 +82,16 @@ class MetricPanelConfig extends Component { return (
-
this.switchTab('data')}>Data
-
this.switchTab('options')}>Panel Options
+
this.switchTab('data')} + >Data +
+
this.switchTab('options')} + >Panel Options +
{view}
diff --git a/src/core_plugins/metrics/public/components/panel_config/timeseries.js b/src/core_plugins/metrics/public/components/panel_config/timeseries.js index 6ff74610c5608..95cd64c316622 100644 --- a/src/core_plugins/metrics/public/components/panel_config/timeseries.js +++ b/src/core_plugins/metrics/public/components/panel_config/timeseries.js @@ -47,7 +47,8 @@ class TimeseriesPanelConfig extends Component { fields={this.props.fields} model={this.props.model} name={this.props.name} - onChange={this.props.onChange} /> + onChange={this.props.onChange} + /> ); } else if (selectedTab === 'annotations') { view = ( @@ -55,7 +56,8 @@ class TimeseriesPanelConfig extends Component { fields={this.props.fields} model={this.props.model} name="annotations" - onChange={this.props.onChange} /> + onChange={this.props.onChange} + /> ); } else { view = ( @@ -63,20 +65,23 @@ class TimeseriesPanelConfig extends Component { + onChange={this.props.onChange} + />
Axis Min
+ value={model.axis_min} + />
Axis Max
+ value={model.axis_max} + />
Axis Position
+ onChange={handleSelectChange('legend_position')} + />
Display Grid
+ onChange={this.props.onChange} + />
Panel Filter
@@ -118,12 +128,14 @@ class TimeseriesPanelConfig extends Component { className="vis_editor__input-grows" type="text" onChange={handleTextChange('filter')} - value={model.filter}/> + value={model.filter} + />
Ignore Global Filter
+ onChange={this.props.onChange} + />
); @@ -131,12 +143,21 @@ class TimeseriesPanelConfig extends Component { return (
-
this.switchTab('data')}>Data
-
this.switchTab('options')}>Panel Options
-
this.switchTab('annotations')}>Annotations
+
this.switchTab('data')} + >Data +
+
this.switchTab('options')} + >Panel Options +
+
this.switchTab('annotations')} + >Annotations +
{view}
diff --git a/src/core_plugins/metrics/public/components/panel_config/top_n.js b/src/core_plugins/metrics/public/components/panel_config/top_n.js index 413d668e9afc6..6b0ae65010333 100644 --- a/src/core_plugins/metrics/public/components/panel_config/top_n.js +++ b/src/core_plugins/metrics/public/components/panel_config/top_n.js @@ -40,40 +40,47 @@ class TopNPanelConfig extends Component { fields={this.props.fields} model={this.props.model} name={this.props.name} - onChange={this.props.onChange} /> + onChange={this.props.onChange} + /> ); } else { view = (
Item Url (This supports mustache templating. - {'{{key}}'} is set to the term)
+ {'{{key}}'} is set to the term) +
+ value={model.drilldown_url} + />
+ onChange={this.props.onChange} + />
Background Color
+ value={model.background_color} + />
Panel Filter
+ value={model.filter} + />
Ignore Global Filter
+ onChange={this.props.onChange} + />
Color Rules
@@ -85,7 +92,8 @@ class TopNPanelConfig extends Component { primaryName="bar" hideSecondary={true} onChange={this.props.onChange} - name="bar_color_rules"/> + name="bar_color_rules" + />
); @@ -93,10 +101,16 @@ class TopNPanelConfig extends Component { return (
-
this.switchTab('data')}>Data
-
this.switchTab('options')}>Panel Options
+
this.switchTab('data')} + >Data +
+
this.switchTab('options')} + >Panel Options +
{view}
diff --git a/src/core_plugins/metrics/public/components/series_config.js b/src/core_plugins/metrics/public/components/series_config.js index 03be881947347..3a1883159bd29 100644 --- a/src/core_plugins/metrics/public/components/series_config.js +++ b/src/core_plugins/metrics/public/components/series_config.js @@ -18,32 +18,37 @@ class SeriesConfig extends Component {
+ value={model.formatter} + />
Template (eg.{'{{value}}/s'})
+ value={model.value_template} + />
Offset series time by (1m, 1h, 1w, 1d)
+ value={model.offset_time} + />
Override Index Pattern
+ onChange={this.props.onChange} + /> + disabled={!model.override_index_pattern} + />
diff --git a/src/core_plugins/metrics/public/components/series_editor.js b/src/core_plugins/metrics/public/components/series_editor.js index a9d5a3cd07151..36d03eb04a721 100644 --- a/src/core_plugins/metrics/public/components/series_editor.js +++ b/src/core_plugins/metrics/public/components/series_editor.js @@ -37,7 +37,8 @@ class SeriesEditor extends Component { onDelete={handleDelete.bind(null, props, row)} model={row} panel={model} - sortData={row.id} /> + sortData={row.id} + /> ); } @@ -56,7 +57,8 @@ class SeriesEditor extends Component { dynamic={true} direction="vertical" onSort={handleSort} - sortHandle="vis_editor__sort"> + sortHandle="vis_editor__sort" + > { series } diff --git a/src/core_plugins/metrics/public/components/split.js b/src/core_plugins/metrics/public/components/split.js index dca89800a091c..8cc11b22346dc 100644 --- a/src/core_plugins/metrics/public/components/split.js +++ b/src/core_plugins/metrics/public/components/split.js @@ -28,14 +28,16 @@ class Split extends Component { return ( + onChange={this.props.onChange} + /> ); } if (model.split_mode === 'filters') { return ( + onChange={this.props.onChange} + /> ); } if (model.split_mode === 'terms') { @@ -44,13 +46,15 @@ class Split extends Component { model={model} indexPattern={indexPattern} fields={this.props.fields} - onChange={this.props.onChange} /> + onChange={this.props.onChange} + /> ); } return ( + onChange={this.props.onChange} + /> ); } diff --git a/src/core_plugins/metrics/public/components/splits/everything.js b/src/core_plugins/metrics/public/components/splits/everything.js index eb38979e35491..616eff5fb06d2 100644 --- a/src/core_plugins/metrics/public/components/splits/everything.js +++ b/src/core_plugins/metrics/public/components/splits/everything.js @@ -11,7 +11,8 @@ function SplitByEverything(props) {
+ onChange={handleSelectChange('split_mode')} + />
); diff --git a/src/core_plugins/metrics/public/components/splits/filter.js b/src/core_plugins/metrics/public/components/splits/filter.js index b39950f17e46a..dab31fd56f8b6 100644 --- a/src/core_plugins/metrics/public/components/splits/filter.js +++ b/src/core_plugins/metrics/public/components/splits/filter.js @@ -17,13 +17,15 @@ class SplitByFilter extends Component {
+ onChange={handleSelectChange('split_mode')} + />
Query String
+ onChange={handleTextChange('filter')} + /> ); } diff --git a/src/core_plugins/metrics/public/components/splits/filter_items.js b/src/core_plugins/metrics/public/components/splits/filter_items.js index 23b2bcfaa5064..dc87bf4f33c40 100644 --- a/src/core_plugins/metrics/public/components/splits/filter_items.js +++ b/src/core_plugins/metrics/public/components/splits/filter_items.js @@ -39,7 +39,8 @@ class FilterItems extends Component { disableTrash={true} onChange={handleChange} name="color" - value={model.color}/> + value={model.color} + />
+ value={model.filter} + />
+ value={model.label} + />
+ disableDelete={items.length < 2} + />
); diff --git a/src/core_plugins/metrics/public/components/splits/filters.js b/src/core_plugins/metrics/public/components/splits/filters.js index 210417bae6dc3..8e68079311a91 100644 --- a/src/core_plugins/metrics/public/components/splits/filters.js +++ b/src/core_plugins/metrics/public/components/splits/filters.js @@ -12,7 +12,8 @@ function SplitByFilters(props) {
+ onChange={handleSelectChange('split_mode')} + />
@@ -20,7 +21,8 @@ function SplitByFilters(props) { + onChange={onChange} + />
diff --git a/src/core_plugins/metrics/public/components/splits/group_by_select.js b/src/core_plugins/metrics/public/components/splits/group_by_select.js index 653698885c0ea..f6904175ed6a6 100644 --- a/src/core_plugins/metrics/public/components/splits/group_by_select.js +++ b/src/core_plugins/metrics/public/components/splits/group_by_select.js @@ -12,7 +12,8 @@ function GroupBySelect(props) { clearable={false} value={ props.value || 'everything' } onChange={props.onChange} - options={ modeOptions }/> + options={ modeOptions } + /> ); } diff --git a/src/core_plugins/metrics/public/components/splits/terms.js b/src/core_plugins/metrics/public/components/splits/terms.js index aad1e31a14c11..c8e3b5d5d52f3 100644 --- a/src/core_plugins/metrics/public/components/splits/terms.js +++ b/src/core_plugins/metrics/public/components/splits/terms.js @@ -22,7 +22,8 @@ class SplitByTerms extends Component {
+ onChange={handleSelectChange('split_mode')} + />
By
@@ -30,7 +31,8 @@ class SplitByTerms extends Component { indexPattern={indexPattern} onChange={handleSelectChange('terms_field')} value={model.terms_field} - fields={this.props.fields} /> + fields={this.props.fields} + />
Top
+ onChange={handleTextChange('terms_size')} + />
Order By
+ value={model.terms_order_by} + />
); diff --git a/src/core_plugins/metrics/public/components/vis_editor.js b/src/core_plugins/metrics/public/components/vis_editor.js index 3757e961348b7..1b70132a0b081 100644 --- a/src/core_plugins/metrics/public/components/vis_editor.js +++ b/src/core_plugins/metrics/public/components/vis_editor.js @@ -65,7 +65,8 @@ class VisEditor extends Component { onBrush={this.onBrush} fields={this.props.vis.fields} model={this.props.vis.params} - visData={this.props.visData} /> + visData={this.props.visData} + /> ); } @@ -77,7 +78,8 @@ class VisEditor extends Component {
+ onChange={handleChange} + /> + onChange={handleChange} + /> + onChange={handleChange} + />
); } diff --git a/src/core_plugins/metrics/public/components/vis_editor_visualization.js b/src/core_plugins/metrics/public/components/vis_editor_visualization.js index 745d7be43105a..176655b72590a 100644 --- a/src/core_plugins/metrics/public/components/vis_editor_visualization.js +++ b/src/core_plugins/metrics/public/components/vis_editor_visualization.js @@ -66,14 +66,17 @@ class VisEditorVisualization extends Component { + onChange={this.props.onToggleAutoApply} + />
+ className={`${applyButtonClassName} md`} + > + Apply Changes +
{applyMessage} @@ -88,21 +91,24 @@ class VisEditorVisualization extends Component { style={style} data-shared-item={true} ref={(el) => this.visDiv = el} - className="vis_editor__visualization"> + className="vis_editor__visualization" + > + visData={this.props.visData} + />
{applyButton}
- + onMouseUp={this.handleMouseUp} + > +
); diff --git a/src/core_plugins/metrics/public/components/vis_picker.js b/src/core_plugins/metrics/public/components/vis_picker.js index 5bd49666b2b58..0d5c899bdaddc 100644 --- a/src/core_plugins/metrics/public/components/vis_picker.js +++ b/src/core_plugins/metrics/public/components/vis_picker.js @@ -13,7 +13,7 @@ function VisPickerItem(props) { return (
props.onClick(type)}>
- +
{ label } @@ -48,7 +48,8 @@ function VisPicker(props) { key={item.type} onClick={handleChange} selected={ item.type === model.type } - {...item}/> + {...item} + /> ); }); diff --git a/src/core_plugins/metrics/public/components/vis_types/gauge/series.js b/src/core_plugins/metrics/public/components/vis_types/gauge/series.js index bc15f02ea82eb..91ad826a7dcb9 100644 --- a/src/core_plugins/metrics/public/components/vis_types/gauge/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/gauge/series.js @@ -49,7 +49,8 @@ function GaugeSeries(props) { dynamic={true} direction="vertical" onSort={handleSort} - sortHandle="vis_editor__agg_sort"> + sortHandle="vis_editor__agg_sort" + > { aggs }
@@ -58,7 +59,8 @@ function GaugeSeries(props) { onChange={props.onChange} fields={fields} panel={panel} - model={model}/> + model={model} + />
@@ -68,16 +70,23 @@ function GaugeSeries(props) { + onChange={props.onChange} + /> ); } body = (
-
props.switchTab('metrics')}>Metrics
-
props.switchTab('options')}>Options
+
props.switchTab('metrics')} + >Metrics +
+
props.switchTab('options')} + >Options +
{seriesBody}
@@ -91,7 +100,8 @@ function GaugeSeries(props) { disableTrash={true} onChange={props.onChange} name="color" - value={model.color}/> + value={model.color} + /> ); } @@ -100,7 +110,7 @@ function GaugeSeries(props) { dragHandle = (
- +
); @@ -111,7 +121,8 @@ function GaugeSeries(props) { className={`${props.className} vis_editor__series`} style={props.style} onMouseDown={props.onMouseDown} - onTouchStart={props.onTouchStart}> + onTouchStart={props.onTouchStart} + >
@@ -121,7 +132,8 @@ function GaugeSeries(props) { className="vis_editor__input-grows" onChange={handleChange('label')} placeholder='Label' - value={model.label}/> + value={model.label} + />
{ dragHandle } + disableAdd={disableAdd} + />
{ body } diff --git a/src/core_plugins/metrics/public/components/vis_types/markdown/series.js b/src/core_plugins/metrics/public/components/vis_types/markdown/series.js index 238814154a800..5318038935a06 100644 --- a/src/core_plugins/metrics/public/components/vis_types/markdown/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/markdown/series.js @@ -47,7 +47,8 @@ function MarkdownSeries(props) { dynamic={true} direction="vertical" onSort={handleSort} - sortHandle="vis_editor__agg_sort"> + sortHandle="vis_editor__agg_sort" + > { aggs }
@@ -56,7 +57,8 @@ function MarkdownSeries(props) { onChange={props.onChange} fields={fields} panel={panel} - model={model}/> + model={model} + />
@@ -66,16 +68,23 @@ function MarkdownSeries(props) { + onChange={props.onChange} + /> ); } body = (
-
props.switchTab('metrics')}>Metrics
-
props.switchTab('options')}>Options
+
props.switchTab('metrics')} + >Metrics +
+
props.switchTab('options')} + >Options +
{seriesBody}
@@ -87,7 +96,8 @@ function MarkdownSeries(props) { className={`${props.className} vis_editor__series`} style={props.style} onMouseDown={props.onMouseDown} - onTouchStart={props.onTouchStart}> + onTouchStart={props.onTouchStart} + >
@@ -96,12 +106,14 @@ function MarkdownSeries(props) { className="vis_editor__input-grows vis_editor__row_item" onChange={handleChange('label')} placeholder='Label' - value={model.label}/> + value={model.label} + /> + value={model.var_name} + />
+ disableAdd={disableAdd} + />
{ body } diff --git a/src/core_plugins/metrics/public/components/vis_types/metric/series.js b/src/core_plugins/metrics/public/components/vis_types/metric/series.js index 19100f0090a8b..64960748a0338 100644 --- a/src/core_plugins/metrics/public/components/vis_types/metric/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/metric/series.js @@ -49,7 +49,8 @@ function MetricSeries(props) { dynamic={true} direction="vertical" onSort={handleSort} - sortHandle="vis_editor__agg_sort"> + sortHandle="vis_editor__agg_sort" + > { aggs }
@@ -58,7 +59,8 @@ function MetricSeries(props) { onChange={props.onChange} fields={fields} panel={panel} - model={model}/> + model={model} + />
@@ -68,16 +70,23 @@ function MetricSeries(props) { + onChange={props.onChange} + /> ); } body = (
-
props.switchTab('metrics')}>Metrics
-
props.switchTab('options')}>Options
+
props.switchTab('metrics')} + >Metrics +
+
props.switchTab('options')} + >Options +
{seriesBody}
@@ -91,7 +100,8 @@ function MetricSeries(props) { disableTrash={true} onChange={props.onChange} name="color" - value={model.color}/> + value={model.color} + /> ); } @@ -100,7 +110,7 @@ function MetricSeries(props) { dragHandle = (
- +
); @@ -111,7 +121,8 @@ function MetricSeries(props) { className={`${props.className} vis_editor__series`} style={props.style} onMouseDown={props.onMouseDown} - onTouchStart={props.onTouchStart}> + onTouchStart={props.onTouchStart} + >
@@ -121,7 +132,8 @@ function MetricSeries(props) { className="vis_editor__input-grows" onChange={handleChange('label')} placeholder='Label' - value={model.label}/> + value={model.label} + />
{ dragHandle } + disableAdd={disableAdd} + />
{ body } diff --git a/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js b/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js index 7b526a8446fe3..97fee28ca252d 100644 --- a/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js +++ b/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js @@ -55,7 +55,8 @@ function TimeseriesConfig(props) { clearable={false} options={chartTypeOptions} value={model.chart_type} - onChange={handleSelectChange('chart_type')}/> + onChange={handleSelectChange('chart_type')} + />
Stacked
@@ -63,7 +64,8 @@ function TimeseriesConfig(props) { clearable={false} options={stackedOptions} value={model.stacked} - onChange={handleSelectChange('stacked')}/> + onChange={handleSelectChange('stacked')} + />
Fill (0 to 1)
+ value={model.fill} + />
Line Width
+ value={model.line_width} + />
Point Size
+ value={model.point_size} + />
Steps
+ onChange={props.onChange} + /> ); } @@ -101,7 +107,8 @@ function TimeseriesConfig(props) { clearable={false} options={chartTypeOptions} value={model.chart_type} - onChange={handleSelectChange('chart_type')}/> + onChange={handleSelectChange('chart_type')} + />
Stacked
@@ -109,7 +116,8 @@ function TimeseriesConfig(props) { clearable={false} options={stackedOptions} value={model.stacked} - onChange={handleSelectChange('stacked')}/> + onChange={handleSelectChange('stacked')} + />
Fill (0 to 1)
+ value={model.fill} + />
Line Width
+ value={model.line_width} + /> ); } @@ -136,12 +146,14 @@ function TimeseriesConfig(props) {
+ value={model.formatter} + />
Template (eg.{'{{value}}/s'})
+ value={model.value_template} + />
{ type }
@@ -150,19 +162,22 @@ function TimeseriesConfig(props) { className="vis_editor__input-grows" type="text" onChange={handleTextChange('offset_time')} - value={model.offset_time}/> + value={model.offset_time} + />
Hide in Legend
+ onChange={props.onChange} + />
Split Color Theme
+ value={model.axis_min} + />
Axis Max
+ value={model.axis_max} + />
Axis Position
- No + onChange={handleChange(0)} + /> + No +
); } diff --git a/src/core_plugins/metrics/public/visualizations/components/annotation.js b/src/core_plugins/metrics/public/visualizations/components/annotation.js index 0406b2f17c1ba..b4711fdc02ab6 100644 --- a/src/core_plugins/metrics/public/visualizations/components/annotation.js +++ b/src/core_plugins/metrics/public/visualizations/components/annotation.js @@ -18,8 +18,11 @@ class Annotation extends Component { const reversed = this.props.reversed ? '-reversed' : ''; const messages = messageSource.map((message, i) => { return ( -
{ message }
+
{ message } +
); }); return ( @@ -28,7 +31,7 @@ class Annotation extends Component {
{ moment(timestamp).format('lll') }
{ messages }
-
+
); } @@ -60,12 +63,13 @@ class Annotation extends Component { }); return(
-
+
- + className="annotation__icon" + > + { tooltip }
diff --git a/src/core_plugins/metrics/public/visualizations/components/flot_chart.js b/src/core_plugins/metrics/public/visualizations/components/flot_chart.js index b72487ea2cd07..1e25d480dd2d5 100644 --- a/src/core_plugins/metrics/public/visualizations/components/flot_chart.js +++ b/src/core_plugins/metrics/public/visualizations/components/flot_chart.js @@ -259,10 +259,12 @@ class FlotChart extends Component { this.resize = el} - className="rhythm_chart__timeseries-container"> + className="rhythm_chart__timeseries-container" + >
this.target = el} - className="rhythm_chart__timeseries-container" /> + className="rhythm_chart__timeseries-container" + /> ); } diff --git a/src/core_plugins/metrics/public/visualizations/components/gauge.js b/src/core_plugins/metrics/public/visualizations/components/gauge.js index f401848d2d942..3bfc16e2013ae 100644 --- a/src/core_plugins/metrics/public/visualizations/components/gauge.js +++ b/src/core_plugins/metrics/public/visualizations/components/gauge.js @@ -92,14 +92,19 @@ class Gauge extends Component {
this.inner = el} - style={styles.inner}> + style={styles.inner} + >
{ title }
+ ref="title" + >{ title } +
{ formatter(value) }
+ ref="label" + >{ formatter(value) } +
); } else { @@ -107,14 +112,19 @@ class Gauge extends Component {
this.inner = el} - style={styles.inner}> + style={styles.inner} + >
{ formatter(value) }
+ ref="label" + >{ formatter(value) } +
{ title }
+ ref="title" + >{ title } +
); } @@ -124,7 +134,8 @@ class Gauge extends Component {
this.resize = el} - className={`${className}__resize`}> + className={`${className}__resize`} + > { metrics }
diff --git a/src/core_plugins/metrics/public/visualizations/components/gauge_vis.js b/src/core_plugins/metrics/public/visualizations/components/gauge_vis.js index 8d7ee9f721e19..dab00d18ef949 100644 --- a/src/core_plugins/metrics/public/visualizations/components/gauge_vis.js +++ b/src/core_plugins/metrics/public/visualizations/components/gauge_vis.js @@ -137,7 +137,8 @@ class GaugeVis extends Component { return (
this.resize = el} - style={styles.resize}> + style={styles.resize} + >
this.inner = el}> {svg}
diff --git a/src/core_plugins/metrics/public/visualizations/components/metric.js b/src/core_plugins/metrics/public/visualizations/components/metric.js index 867ba700be49c..8736286b345b8 100644 --- a/src/core_plugins/metrics/public/visualizations/components/metric.js +++ b/src/core_plugins/metrics/public/visualizations/components/metric.js @@ -120,7 +120,8 @@ class Metric extends Component {
this.resize = el} - className="rhythm_metric__resize"> + className="rhythm_metric__resize" + >
this.inner = el} className="rhythm_metric__inner" style={styles.inner}>
{ primaryLabel } diff --git a/src/core_plugins/metrics/public/visualizations/components/resize.js b/src/core_plugins/metrics/public/visualizations/components/resize.js index 618b795ba4165..6af1d54749a68 100644 --- a/src/core_plugins/metrics/public/visualizations/components/resize.js +++ b/src/core_plugins/metrics/public/visualizations/components/resize.js @@ -48,7 +48,8 @@ class Resize extends Component {
this.el = el} > + ref={(el) => this.el = el} + > {this.props.children}
); diff --git a/src/core_plugins/metrics/public/visualizations/components/timeseries.js b/src/core_plugins/metrics/public/visualizations/components/timeseries.js index b2c0ac3e3a700..377297544df96 100644 --- a/src/core_plugins/metrics/public/visualizations/components/timeseries.js +++ b/src/core_plugins/metrics/public/visualizations/components/timeseries.js @@ -132,7 +132,8 @@ class Timeseries extends Component { tickFormatter={this.props.tickFormatter} options={this.props.options} xaxisLabel={this.props.xaxisLabel} - yaxes={this.props.yaxes} /> + yaxes={this.props.yaxes} + />
+ tickFormatter={this.props.tickFormatter} + />
); diff --git a/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js b/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js index f1cd6237d7549..74f25aad0674f 100644 --- a/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js +++ b/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js @@ -87,7 +87,8 @@ class TimeseriesChart extends Component { key={annotation.key} icon={annotation.icon} reversed={this.props.reversed} - color={annotation.color}/> + color={annotation.color} + /> ); } @@ -163,18 +164,18 @@ class TimeseriesChart extends Component { const value = item.datapoint[2] ? item.datapoint[1] - item.datapoint[2] : item.datapoint[1]; tooltip = (
- +
- +
{ item.series.label }
{ formatter(value) }
{ moment(item.datapoint[0]).format('ll LTS') }
- +
); } diff --git a/src/core_plugins/metrics/public/visualizations/components/top_n.js b/src/core_plugins/metrics/public/visualizations/components/top_n.js index 464cddd7dffbe..02f35746ff920 100644 --- a/src/core_plugins/metrics/public/visualizations/components/top_n.js +++ b/src/core_plugins/metrics/public/visualizations/components/top_n.js @@ -35,13 +35,17 @@ class TopN extends Component { } }, this.props); return ( - + style={styles.row} + > { item.label } -
+
{ value } diff --git a/src/core_plugins/metrics/public/visualizations/lib/create_legend_series.js b/src/core_plugins/metrics/public/visualizations/lib/create_legend_series.js index d1f48dccfb770..6eca5c27ec664 100644 --- a/src/core_plugins/metrics/public/visualizations/lib/create_legend_series.js +++ b/src/core_plugins/metrics/public/visualizations/lib/create_legend_series.js @@ -17,9 +17,10 @@ export default props => (row, i) => {
props.onToggle(event, row.id) } - key={ key }> + key={ key } + >
- + { row.label }
{ value }
diff --git a/ui_framework/components/collapse_button/__snapshots__/collapse_button.test.js.snap b/ui_framework/components/collapse_button/__snapshots__/collapse_button.test.js.snap index 393b874395c23..04d40f4262f18 100644 --- a/ui_framework/components/collapse_button/__snapshots__/collapse_button.test.js.snap +++ b/ui_framework/components/collapse_button/__snapshots__/collapse_button.test.js.snap @@ -7,7 +7,7 @@ exports[`KuiCollapseButton Props direction down renders the down class 1`] = ` data-test-subj="test subject string" type="button" > -
@@ -20,7 +20,7 @@ exports[`KuiCollapseButton Props direction left renders the left class 1`] = ` data-test-subj="test subject string" type="button" > -
@@ -33,7 +33,7 @@ exports[`KuiCollapseButton Props direction right renders the right class 1`] = ` data-test-subj="test subject string" type="button" > -
@@ -46,7 +46,7 @@ exports[`KuiCollapseButton Props direction up renders the up class 1`] = ` data-test-subj="test subject string" type="button" > -
diff --git a/ui_framework/components/collapse_button/collapse_button.js b/ui_framework/components/collapse_button/collapse_button.js index 0757a275638f9..53a9c05efde9c 100644 --- a/ui_framework/components/collapse_button/collapse_button.js +++ b/ui_framework/components/collapse_button/collapse_button.js @@ -21,13 +21,15 @@ const KuiCollapseButton = ({ className, direction, ...rest }) => { const classes = classNames('kuiCollapseButton', className); const childClasses = classNames('kuiIcon', directionToClassNameMap[direction]); - return (); + return ( + + ); }; KuiCollapseButton.propTypes = { diff --git a/ui_framework/components/empty_table_prompt/empty_table_prompt.test.js b/ui_framework/components/empty_table_prompt/empty_table_prompt.test.js index 7f0cac22b9120..713c52664ba24 100644 --- a/ui_framework/components/empty_table_prompt/empty_table_prompt.test.js +++ b/ui_framework/components/empty_table_prompt/empty_table_prompt.test.js @@ -12,7 +12,7 @@ import { } from '../button'; test('renders KuiEmptyTablePrompt', () => { - const component = } @@ -26,6 +26,6 @@ test('renders KuiEmptyTablePrompt', () => { } message="Uh oh, You have no items!" { ...requiredProps } - />; + />); expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/components/info_button/info_button.js b/ui_framework/components/info_button/info_button.js index 2ed182f28915a..53448b1e06aa6 100644 --- a/ui_framework/components/info_button/info_button.js +++ b/ui_framework/components/info_button/info_button.js @@ -9,7 +9,7 @@ const KuiInfoButton = props => { return ( ); }; diff --git a/ui_framework/components/pager/pager.js b/ui_framework/components/pager/pager.js index c485091a00d4c..b96d399659dfc 100644 --- a/ui_framework/components/pager/pager.js +++ b/ui_framework/components/pager/pager.js @@ -22,11 +22,11 @@ export function KuiPager({ (startNumber === 1 && endNumber === totalItems) ? null : + hasNext={hasNextPage} + hasPrevious={hasPreviousPage} + onNext={onNextPage} + onPrevious={onPreviousPage} + /> }
); diff --git a/ui_framework/components/pager/pager.test.js b/ui_framework/components/pager/pager.test.js index fc4997b074e38..f588e709cc9c6 100644 --- a/ui_framework/components/pager/pager.test.js +++ b/ui_framework/components/pager/pager.test.js @@ -16,7 +16,7 @@ beforeEach(() => { }); test('renders KuiPager', () => { - const component = { startNumber={1} endNumber={10} totalItems={20} - { ...requiredProps }/>; + { ...requiredProps } + />); expect(render(component)).toMatchSnapshot(); }); describe('property', () => { describe('hasPreviousPage', () => { test('disables previous button when false', () => { - const component = ; + totalItems={20} + />); expect(render(component)).toMatchSnapshot(); }); }); describe('hasNextPage', () => { test('disables next button when false', () => { - const component = ; + totalItems={20} + />); expect(render(component)).toMatchSnapshot(); }); }); describe('onPreviousPage', () => { test('is called when clicked', () => { - const component = ; + totalItems={20} + />); const pager = mount(component); pager.find('[data-test-subj="pagerPreviousButton"]').simulate('click'); sinon.assert.calledOnce(onPreviousPage); @@ -76,14 +80,15 @@ describe('property', () => { describe('onNextPage', () => { test('is called when clicked', () => { - const component = ; + totalItems={20} + />); const pager = mount(component); pager.find('[data-test-subj="pagerNextButton"]').simulate('click'); sinon.assert.calledOnce(onNextPage); diff --git a/ui_framework/components/pager/pager_button_group.test.js b/ui_framework/components/pager/pager_button_group.test.js index 2e7497c5dcd8f..c5a1dc961bc90 100644 --- a/ui_framework/components/pager/pager_button_group.test.js +++ b/ui_framework/components/pager/pager_button_group.test.js @@ -16,12 +16,13 @@ beforeEach(() => { }); test('renders KuiPagerButtonGroup', () => { - const component = ; + { ...requiredProps } + />); expect(render(component)).toMatchSnapshot(); }); @@ -36,12 +37,12 @@ describe('property', () => { } test('onNext', () => { - const component = ; + />); const pager = mount(component); findNextButton(pager).simulate('click'); sinon.assert.calledOnce(onNext); @@ -49,12 +50,12 @@ describe('property', () => { }); test('onPrevious', () => { - const component = ; + />); const pager = mount(component); findPreviousButton(pager).simulate('click'); sinon.assert.calledOnce(onPrevious); @@ -63,24 +64,24 @@ describe('property', () => { describe('hasNext', () => { test('is enabled when true', () => { - const component = ; + />); const pager = mount(component); const isDisabled = findNextButton(pager).prop('disabled'); expect(isDisabled).toBe(false); }); test('is disabled when false', () => { - const component = ; + />); const pager = mount(component); const isDisabled = findNextButton(pager).prop('disabled'); expect(isDisabled).toBe(true); @@ -89,24 +90,24 @@ describe('property', () => { describe('hasPrevious', () => { test('is enabled when true', () => { - const component = ; + />); const pager = mount(component); const isDisabled = findPreviousButton(pager).prop('disabled'); expect(isDisabled).toBe(false); }); test('is disabled when false', () => { - const component = ; + />); const pager = mount(component); const isDisabled = findPreviousButton(pager).prop('disabled'); expect(isDisabled).toBe(true); diff --git a/ui_framework/components/table/table_row_cell.test.js b/ui_framework/components/table/table_row_cell.test.js index d41a092bbf66d..95928873a681f 100644 --- a/ui_framework/components/table/table_row_cell.test.js +++ b/ui_framework/components/table/table_row_cell.test.js @@ -7,6 +7,6 @@ import { } from './table_row_cell'; test('renders KuiTableRowCell', () => { - const component = ; + const component = ; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/components/table/table_row_check_box_cell.js b/ui_framework/components/table/table_row_check_box_cell.js index d35dab7902107..8d301478ac671 100644 --- a/ui_framework/components/table/table_row_check_box_cell.js +++ b/ui_framework/components/table/table_row_check_box_cell.js @@ -5,14 +5,19 @@ import { KuiTableRowCell } from './table_row_cell'; export const KuiTableRowCheckBoxCell = ({ onChange, isChecked, className, ...rest }) => { const classes = classNames('kuiTableRowCell--checkBox', className); - return - - ; + return ( + + + + ); }; KuiTableRowCheckBoxCell.propTypes = { isChecked: PropTypes.bool, diff --git a/ui_framework/components/table/table_row_check_box_cell.test.js b/ui_framework/components/table/table_row_check_box_cell.test.js index a20b02eeba745..632ce05924337 100644 --- a/ui_framework/components/table/table_row_check_box_cell.test.js +++ b/ui_framework/components/table/table_row_check_box_cell.test.js @@ -7,6 +7,6 @@ import { } from './table_row_check_box_cell'; test('renders KuiTableRowCheckBoxCell', () => { - const component = ; + const component = ; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/components/tool_bar/tool_bar_search_box.js b/ui_framework/components/tool_bar/tool_bar_search_box.js index a2fa15104657f..36803651522f5 100644 --- a/ui_framework/components/tool_bar/tool_bar_search_box.js +++ b/ui_framework/components/tool_bar/tool_bar_search_box.js @@ -6,19 +6,24 @@ export function KuiToolBarSearchBox({ filter, onFilter, placeholder, className, onFilter(event.target.value); } const classes = classNames('kuiToolBarSearch', className); - return
-
-
- + return ( +
+
+
+ +
-
; + ); } KuiToolBarSearchBox.propTypes = { diff --git a/ui_framework/doc_site/src/components/guide_nav/guide_nav.js b/ui_framework/doc_site/src/components/guide_nav/guide_nav.js index 9b40b0efea101..87c938b3554cf 100644 --- a/ui_framework/doc_site/src/components/guide_nav/guide_nav.js +++ b/ui_framework/doc_site/src/components/guide_nav/guide_nav.js @@ -61,7 +61,7 @@ export class GuideNav extends Component { className={previousClasses} to={this.state.previousRoute ? this.state.previousRoute.path : ''} > - + ); @@ -74,7 +74,7 @@ export class GuideNav extends Component { className={nextClasses} to={this.state.nextRoute ? this.state.nextRoute.path : ''} > - + ); diff --git a/ui_framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle.js b/ui_framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle.js index bce8c244d148c..88cda5ef0b658 100644 --- a/ui_framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle.js +++ b/ui_framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle.js @@ -19,7 +19,7 @@ export class GuideSandboxCodeToggle extends Component { className="guideSandboxCodeToggle guideSection__sourceButton" onClick={this.onClickSource} > - + ); } diff --git a/ui_framework/doc_site/src/components/guide_section/guide_section.js b/ui_framework/doc_site/src/components/guide_section/guide_section.js index af596a89ae6b6..8957d13de5a28 100644 --- a/ui_framework/doc_site/src/components/guide_section/guide_section.js +++ b/ui_framework/doc_site/src/components/guide_section/guide_section.js @@ -41,7 +41,7 @@ export class GuideSection extends Component { className="guideSection__sourceButton" onClick={this.onClickSource} > - +
diff --git a/ui_framework/doc_site/src/views/action_item/action_items_in_menu.js b/ui_framework/doc_site/src/views/action_item/action_items_in_menu.js index ce0bee1a09b96..9391e1198736a 100644 --- a/ui_framework/doc_site/src/views/action_item/action_items_in_menu.js +++ b/ui_framework/doc_site/src/views/action_item/action_items_in_menu.js @@ -7,56 +7,56 @@ import { } from '../../../../components'; export default () => ( - - - -

Item A

-
- - + - + -
-
-
+ +
+ + - - -

Item B

-
- - + - + -
-
-
+ +
+ + - - -

Item C

-
- - + - + -
-
-
- + +
+ + + ); diff --git a/ui_framework/doc_site/src/views/bar/bar.js b/ui_framework/doc_site/src/views/bar/bar.js index 1115fd2108046..18831c2dbb0db 100644 --- a/ui_framework/doc_site/src/views/bar/bar.js +++ b/ui_framework/doc_site/src/views/bar/bar.js @@ -18,5 +18,5 @@ export default () => (
pages
- + ); diff --git a/ui_framework/doc_site/src/views/bar/bar_one_section.js b/ui_framework/doc_site/src/views/bar/bar_one_section.js index fb00569ed6df3..da4ad4bc94d4d 100644 --- a/ui_framework/doc_site/src/views/bar/bar_one_section.js +++ b/ui_framework/doc_site/src/views/bar/bar_one_section.js @@ -7,16 +7,16 @@ import { } from '../../../../components'; export default () => ( - - -
- + + +
+ See previous 10 pages - - + + See next 10 pages - -
-
-
+
+
+
+
); diff --git a/ui_framework/doc_site/src/views/bar/bar_three_sections.js b/ui_framework/doc_site/src/views/bar/bar_three_sections.js index 93be9fb744124..f085d5027c848 100644 --- a/ui_framework/doc_site/src/views/bar/bar_three_sections.js +++ b/ui_framework/doc_site/src/views/bar/bar_three_sections.js @@ -8,37 +8,37 @@ import { } from '../../../../components'; export default () => ( - - -
+ + +
The Great American Novel -
-
+
+
- - - + + + Create new page - - + + Clear all pages - - - + + + - -
Limit to
- -
pages
+ +
Limit to
+ +
pages
- - + + Undo - - + + Redo - - -
-
+ + + + ); diff --git a/ui_framework/doc_site/src/views/button/button_elements.js b/ui_framework/doc_site/src/views/button/button_elements.js index 77e9867e32927..fe5c767ae6620 100644 --- a/ui_framework/doc_site/src/views/button/button_elements.js +++ b/ui_framework/doc_site/src/views/button/button_elements.js @@ -17,7 +17,8 @@ export default () => (
{ e.preventDefault(); window.alert('Submit'); - }}> + }} + > Submit input element @@ -27,7 +28,8 @@ export default () => ( { e.preventDefault(); window.alert('Submit'); - }}> + }} + > Submit input element, disabled diff --git a/ui_framework/doc_site/src/views/card/card.js b/ui_framework/doc_site/src/views/card/card.js index 6996584858948..054452ae006ae 100644 --- a/ui_framework/doc_site/src/views/card/card.js +++ b/ui_framework/doc_site/src/views/card/card.js @@ -26,7 +26,7 @@ export default () => { + > Banana! diff --git a/ui_framework/doc_site/src/views/card/card_group.js b/ui_framework/doc_site/src/views/card/card_group.js index 262efe473f45f..0b480d2f83398 100644 --- a/ui_framework/doc_site/src/views/card/card_group.js +++ b/ui_framework/doc_site/src/views/card/card_group.js @@ -37,7 +37,7 @@ export default () => { + > Banana! @@ -106,7 +106,7 @@ export default () => { + > Banana! diff --git a/ui_framework/doc_site/src/views/empty_table_prompt/empty_table_prompt.js b/ui_framework/doc_site/src/views/empty_table_prompt/empty_table_prompt.js index 332a448ddff00..c851fa7f4ccf1 100644 --- a/ui_framework/doc_site/src/views/empty_table_prompt/empty_table_prompt.js +++ b/ui_framework/doc_site/src/views/empty_table_prompt/empty_table_prompt.js @@ -4,19 +4,19 @@ import { KuiEmptyTablePrompt, KuiLinkButton, KuiButtonIcon } from '../../../../c export function EmptyTablePrompt() { return ( - } - aria-label="Add a new item" - data-test-subj="addNewPromptButton" - buttonType="primary" - href="#" - > + } + aria-label="Add a new item" + data-test-subj="addNewPromptButton" + buttonType="primary" + href="#" + > Add a new item - + } - message="Uh oh, You have no items!" - /> + message="Uh oh, You have no items!" + /> ); } diff --git a/ui_framework/doc_site/src/views/empty_table_prompt/table_with_empty_prompt.js b/ui_framework/doc_site/src/views/empty_table_prompt/table_with_empty_prompt.js index fe2d37c825134..fcb2a1776e7fd 100644 --- a/ui_framework/doc_site/src/views/empty_table_prompt/table_with_empty_prompt.js +++ b/ui_framework/doc_site/src/views/empty_table_prompt/table_with_empty_prompt.js @@ -43,11 +43,11 @@ export function ControlledTableWithEmptyPrompt() { } - aria-label="Add a new visualization" - data-test-subj="addNewVizPromptButton" - buttonType="primary" - href="#" + icon={} + aria-label="Add a new visualization" + data-test-subj="addNewVizPromptButton" + buttonType="primary" + href="#" > Add a new visualization diff --git a/ui_framework/doc_site/src/views/event/event.js b/ui_framework/doc_site/src/views/event/event.js index 46f1573b9a2f9..57963128e778d 100644 --- a/ui_framework/doc_site/src/views/event/event.js +++ b/ui_framework/doc_site/src/views/event/event.js @@ -11,7 +11,7 @@ import { export default () => ( - + diff --git a/ui_framework/doc_site/src/views/event/event_menu.js b/ui_framework/doc_site/src/views/event/event_menu.js index 55d19c2ec1a2f..7fdd6c6c3b243 100644 --- a/ui_framework/doc_site/src/views/event/event_menu.js +++ b/ui_framework/doc_site/src/views/event/event_menu.js @@ -15,7 +15,7 @@ export default () => ( - + @@ -33,7 +33,7 @@ export default () => ( - + @@ -51,7 +51,7 @@ export default () => ( - + diff --git a/ui_framework/doc_site/src/views/event/events_sandbox_content.js b/ui_framework/doc_site/src/views/event/events_sandbox_content.js index d1a9a7cbb1ba8..887e106e1d5a5 100644 --- a/ui_framework/doc_site/src/views/event/events_sandbox_content.js +++ b/ui_framework/doc_site/src/views/event/events_sandbox_content.js @@ -36,7 +36,7 @@ export default () => ( - + @@ -54,7 +54,7 @@ export default () => ( - + @@ -72,7 +72,7 @@ export default () => ( - + diff --git a/ui_framework/doc_site/src/views/form_layout/field_group.js b/ui_framework/doc_site/src/views/form_layout/field_group.js index 948dfcca2b278..0159408e0e05e 100644 --- a/ui_framework/doc_site/src/views/form_layout/field_group.js +++ b/ui_framework/doc_site/src/views/form_layout/field_group.js @@ -13,7 +13,7 @@ export default () => (
-
+
( placeholder="http://" type="text" rows="5" - > + /> diff --git a/ui_framework/doc_site/src/views/header_bar/header_bar_sandbox_content.js b/ui_framework/doc_site/src/views/header_bar/header_bar_sandbox_content.js index b858d78735f69..d62238524af09 100644 --- a/ui_framework/doc_site/src/views/header_bar/header_bar_sandbox_content.js +++ b/ui_framework/doc_site/src/views/header_bar/header_bar_sandbox_content.js @@ -21,7 +21,7 @@ export default () => { - + Rope Hoth @@ -34,7 +34,7 @@ export default () => {
-
+
{
@@ -64,10 +64,10 @@ export default () => {
@@ -109,7 +109,7 @@ export default () => {
-
+
@@ -137,7 +137,7 @@ export default () => {
-
+
@@ -165,7 +165,7 @@ export default () => {
-
+
@@ -193,7 +193,7 @@ export default () => {
-
+
@@ -225,10 +225,10 @@ export default () => {
diff --git a/ui_framework/doc_site/src/views/header_bar/header_bar_two_sections.js b/ui_framework/doc_site/src/views/header_bar/header_bar_two_sections.js index 1aff662737ac1..3d760ee10d4c7 100644 --- a/ui_framework/doc_site/src/views/header_bar/header_bar_two_sections.js +++ b/ui_framework/doc_site/src/views/header_bar/header_bar_two_sections.js @@ -17,7 +17,7 @@ export default () => { - + Red health diff --git a/ui_framework/doc_site/src/views/info_button/info_button.js b/ui_framework/doc_site/src/views/info_button/info_button.js index 22b0c1e88adce..8b86f56025e0b 100644 --- a/ui_framework/doc_site/src/views/info_button/info_button.js +++ b/ui_framework/doc_site/src/views/info_button/info_button.js @@ -6,7 +6,7 @@ import { export default () => (
- +
); diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_breadcrumbs.js b/ui_framework/doc_site/src/views/local_nav/local_nav_breadcrumbs.js index e3e078ccb6bb2..84cba3abee581 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_breadcrumbs.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_breadcrumbs.js @@ -28,7 +28,7 @@ export function LocalNavWithBreadcrumbs() {
Save
Open
diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown.js b/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown.js index 353403901a0e2..c55cc9d9b788b 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown.js @@ -28,7 +28,7 @@ export function LocalNavWithDropdown() {
Save
Open
@@ -37,7 +37,7 @@ export function LocalNavWithDropdown() {
{/* Dropdown close button */} {/* Title */} @@ -113,7 +113,7 @@ export function LocalNavWithDropdown() { autoComplete="off" />
diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js b/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js index e09c3067914eb..d009b0882a941 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js @@ -28,7 +28,7 @@ export function LocalNavWithDropdownPanels() {
Save
Open
@@ -37,7 +37,7 @@ export function LocalNavWithDropdownPanels() {
{/* Dropdown close button */}
@@ -73,7 +73,7 @@ export function LocalNavWithDropdownPanels() { autoComplete="off" />
diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_menu_item_states.js b/ui_framework/doc_site/src/views/local_nav/local_nav_menu_item_states.js index 85f6fac8dc451..c715aab9d6262 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_menu_item_states.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_menu_item_states.js @@ -28,7 +28,7 @@ export function LocalNavWithMenuItemStates() {
Save
Open
@@ -43,7 +43,7 @@ export function LocalNavWithMenuItemStates() { autoComplete="off" />
diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_search.js b/ui_framework/doc_site/src/views/local_nav/local_nav_search.js index a187c1f306dc6..c387b42245de7 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_search.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_search.js @@ -28,7 +28,7 @@ export function LocalNavWithSearch() {
Save
Open
@@ -66,7 +66,7 @@ export function LocalNavWithSearch() {
diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_search_error.js b/ui_framework/doc_site/src/views/local_nav/local_nav_search_error.js index bcd1c131ff143..03371c69aaaef 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_search_error.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_search_error.js @@ -28,7 +28,7 @@ export function LocalNavWithSearchError() {
Save
Open
@@ -43,7 +43,7 @@ export function LocalNavWithSearchError() { autoComplete="off" />
diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_simple.js b/ui_framework/doc_site/src/views/local_nav/local_nav_simple.js index 250a54a5dcca5..5b66e8c5c55e2 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_simple.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_simple.js @@ -22,7 +22,7 @@ export function SimpleLocalNav() {
Save
Open
diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_tabs.js b/ui_framework/doc_site/src/views/local_nav/local_nav_tabs.js index d82de7561bf24..066bf20000813 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_tabs.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_tabs.js @@ -30,7 +30,7 @@ export function LocalNavWithTabs() {
Save
Open
diff --git a/ui_framework/doc_site/src/views/modal/modal_example.js b/ui_framework/doc_site/src/views/modal/modal_example.js index b6a3b000ed4f8..0c938c1ae60bc 100644 --- a/ui_framework/doc_site/src/views/modal/modal_example.js +++ b/ui_framework/doc_site/src/views/modal/modal_example.js @@ -34,14 +34,14 @@ export default props => ( }]} > - {}} - onConfirm={() => {}} - confirmButtonText="Confirm" - cancelButtonText="Cancel" - message="This is a confirmation modal" - title="Confirm Modal Title" - /> + {}} + onConfirm={() => {}} + confirmButtonText="Confirm" + cancelButtonText="Cancel" + message="This is a confirmation modal" + title="Confirm Modal Title" + /> diff --git a/ui_framework/doc_site/src/views/not_found/not_found_view.js b/ui_framework/doc_site/src/views/not_found/not_found_view.js index 1a2abb06fab24..472d0a25f57cf 100644 --- a/ui_framework/doc_site/src/views/not_found/not_found_view.js +++ b/ui_framework/doc_site/src/views/not_found/not_found_view.js @@ -20,7 +20,7 @@ export const NotFoundView = () => ( to="/" > home page - ? + ?

diff --git a/ui_framework/doc_site/src/views/table/controlled_table.js b/ui_framework/doc_site/src/views/table/controlled_table.js index 576b57ea52fc5..6edeed7f938c0 100644 --- a/ui_framework/doc_site/src/views/table/controlled_table.js +++ b/ui_framework/doc_site/src/views/table/controlled_table.js @@ -36,25 +36,25 @@ export class ControlledTable extends React.Component { this.rows = [ [ Alligator, -
, +
, 'Tue Dec 06 2016 12:56:15 GMT-0800 (PST)', '1' ], [ Boomerang, -
, +
, 'Tue Dec 06 2016 12:56:15 GMT-0800 (PST)', '10' ], [ Celebration, -
, +
, 'Tue Dec 06 2016 12:56:15 GMT-0800 (PST)', '100' ], [ Dog, -
, +
, 'Tue Dec 06 2016 12:56:15 GMT-0800 (PST)', '1000' ] @@ -158,7 +158,7 @@ export class ControlledTable extends React.Component { - { + { this.renderTableRows() } diff --git a/ui_framework/doc_site/src/views/table/controlled_table_loading_items.js b/ui_framework/doc_site/src/views/table/controlled_table_loading_items.js index 07e56c78447b7..f396996d88941 100644 --- a/ui_framework/doc_site/src/views/table/controlled_table_loading_items.js +++ b/ui_framework/doc_site/src/views/table/controlled_table_loading_items.js @@ -58,9 +58,9 @@ export class ControlledTableLoadingItems extends React.Component { - + Loading... - + diff --git a/ui_framework/doc_site/src/views/table/fluid_table.js b/ui_framework/doc_site/src/views/table/fluid_table.js index c243e8dc675f4..7d483fdb742d0 100644 --- a/ui_framework/doc_site/src/views/table/fluid_table.js +++ b/ui_framework/doc_site/src/views/table/fluid_table.js @@ -11,56 +11,56 @@ import { export function FluidTable() { return ( - - - + + + System - - + + Action - - + + - - - + + + Cryogenics - - - - - + + + + + - - + + Propellant - - - - - + + + + + - - + + Rockets - - - - - - - + + + + + + + ); } diff --git a/ui_framework/doc_site/src/views/tool_bar/tool_bar.js b/ui_framework/doc_site/src/views/tool_bar/tool_bar.js index 03ceff52b4ba7..cfe4e71d3ae6a 100644 --- a/ui_framework/doc_site/src/views/tool_bar/tool_bar.js +++ b/ui_framework/doc_site/src/views/tool_bar/tool_bar.js @@ -46,13 +46,11 @@ export const ToolBar = () => ( } - > - + /> } - > - + />
diff --git a/ui_framework/doc_site/src/views/tool_bar/tool_bar_footer.js b/ui_framework/doc_site/src/views/tool_bar/tool_bar_footer.js index 3451d0993a8f9..1789bff874112 100644 --- a/ui_framework/doc_site/src/views/tool_bar/tool_bar_footer.js +++ b/ui_framework/doc_site/src/views/tool_bar/tool_bar_footer.js @@ -24,11 +24,11 @@ export const ToolBarFooter = () => ( } - > + /> } - > + />
From 8d5eac959f9216c5bf4ee930dbb1c8d17a062ea4 Mon Sep 17 00:00:00 2001 From: Court Ewing Date: Thu, 27 Jul 2017 14:02:30 -0400 Subject: [PATCH 021/165] esvm: use branch from package.json (#13149) Since versions are synced across the stack, the esvm config can use the same branch configuration as Kibana itself. --- tasks/config/esvm.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/config/esvm.js b/tasks/config/esvm.js index 5c7f84152cfa6..8283f39ddba14 100644 --- a/tasks/config/esvm.js +++ b/tasks/config/esvm.js @@ -4,10 +4,11 @@ module.exports = function (grunt) { const resolve = require('path').resolve; const directory = resolve(__dirname, '../../esvm'); const dataDir = resolve(directory, 'data_dir'); + const pkgBranch = grunt.config.get('pkg.branch'); return { options: { - branch: 'master', + branch: pkgBranch, fresh: !grunt.option('esvm-no-fresh'), config: { http: { From 589df61e03b3f7fc3ab815a049c45912cb81fa15 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Thu, 27 Jul 2017 15:26:09 -0400 Subject: [PATCH 022/165] Stabilize and bring back flaky tests (#13034) * Stabalize tests and bring back flaky test * Try to fix flaky map radius visualize test * fix flaky tile map zoom test * Try to fix flaky zoom test by avoiding zooming in and out with spy panel open * Remove duplicate wrapped retry around find methods The retry was moved internally, around a check for stale elements as well, so this should no longer be neccessary. --- .../apps/dashboard/_dashboard_save.js | 10 +- .../apps/dashboard/_dashboard_time.js | 4 +- test/functional/apps/dashboard/_view_edit.js | 2 +- test/functional/apps/discover/_discover.js | 2 +- test/functional/apps/discover/_field_data.js | 27 +- test/functional/apps/visualize/_area_chart.js | 6 +- test/functional/apps/visualize/_data_table.js | 2 +- .../apps/visualize/_heatmap_chart.js | 15 +- test/functional/apps/visualize/_line_chart.js | 2 +- test/functional/apps/visualize/_pie_chart.js | 2 +- .../apps/visualize/_point_series_options.js | 36 +- test/functional/apps/visualize/_tag_cloud.js | 14 +- test/functional/apps/visualize/_tile_map.js | 65 +- .../apps/visualize/_vertical_bar_chart.js | 13 +- test/functional/page_objects/common_page.js | 14 +- .../functional/page_objects/dashboard_page.js | 18 +- test/functional/page_objects/discover_page.js | 25 +- test/functional/page_objects/header_page.js | 7 +- .../functional/page_objects/visualize_page.js | 1015 ++++++----------- test/functional/services/find.js | 124 +- 20 files changed, 527 insertions(+), 876 deletions(-) diff --git a/test/functional/apps/dashboard/_dashboard_save.js b/test/functional/apps/dashboard/_dashboard_save.js index ada14e4240a86..d8fb658df9762 100644 --- a/test/functional/apps/dashboard/_dashboard_save.js +++ b/test/functional/apps/dashboard/_dashboard_save.js @@ -1,6 +1,7 @@ import expect from 'expect.js'; -export default function ({ getPageObjects }) { +export default function ({ getService, getPageObjects }) { + const retry = getService('retry'); const PageObjects = getPageObjects(['dashboard', 'header', 'common']); describe('dashboard save', function describeIndexTests() { @@ -88,8 +89,11 @@ export default function ({ getPageObjects }) { await PageObjects.dashboard.clickEdit(); await PageObjects.dashboard.enterDashboardTitleAndClickSave(dashboardName.toUpperCase()); - const isConfirmOpen = await PageObjects.common.isConfirmModalOpen(); - expect(isConfirmOpen).to.equal(true); + // We expect isConfirmModalOpen to be open, hence the retry if not found. + await retry.try(async () => { + const isConfirmOpen = await PageObjects.common.isConfirmModalOpen(); + expect(isConfirmOpen).to.equal(true); + }); await PageObjects.common.clickCancelOnModal(); }); diff --git a/test/functional/apps/dashboard/_dashboard_time.js b/test/functional/apps/dashboard/_dashboard_time.js index 3ce108ebd602c..955e8baf7cc16 100644 --- a/test/functional/apps/dashboard/_dashboard_time.js +++ b/test/functional/apps/dashboard/_dashboard_time.js @@ -29,7 +29,7 @@ export default function ({ getPageObjects }) { await PageObjects.header.clickToastOK(); }); - it.skip('Does not set the time picker on open', async function () { + it('Does not set the time picker on open', async function () { await PageObjects.header.setAbsoluteRange(fromTime, toTime); await PageObjects.dashboard.loadSavedDashboard(dashboardName); @@ -81,7 +81,7 @@ export default function ({ getPageObjects }) { // when it's opened. However, if the user then changes the time, navigates to visualize, then navigates // back to dashboard, the overridden time should be preserved. The time is *only* reset on open, not // during navigation or page refreshes. - describe.skip('time changes', function () { + describe('time changes', function () { it('preserved during navigation', async function () { await PageObjects.header.setQuickTime('Today'); await PageObjects.header.clickVisualize(); diff --git a/test/functional/apps/dashboard/_view_edit.js b/test/functional/apps/dashboard/_view_edit.js index 81d26ccc8c2b6..9d476691be90e 100644 --- a/test/functional/apps/dashboard/_view_edit.js +++ b/test/functional/apps/dashboard/_view_edit.js @@ -164,7 +164,7 @@ export default function ({ getService, getPageObjects }) { expect(query).to.equal(originalQuery); }); - it.skip('when a filter is deleted', async function () { + it('when a filter is deleted', async function () { await PageObjects.dashboard.setTimepickerInDataRange(); await PageObjects.dashboard.filterOnPieSlice(); await PageObjects.dashboard.saveDashboard(dashboardName); diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index ea58affcddbd6..aa70c7fe2f246 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -230,7 +230,7 @@ export default function ({ getService, getPageObjects }) { }); describe('data-shared-item', function () { - it.skip('should have correct data-shared-item title and description', async () => { + it('should have correct data-shared-item title and description', async () => { const expected = { title: 'A Saved Search', description: 'A Saved Search Description' diff --git a/test/functional/apps/discover/_field_data.js b/test/functional/apps/discover/_field_data.js index 5cdd153f7c556..5b58f540fd475 100644 --- a/test/functional/apps/discover/_field_data.js +++ b/test/functional/apps/discover/_field_data.js @@ -1,7 +1,6 @@ import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { - const log = getService('log'); const retry = getService('retry'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); @@ -9,31 +8,21 @@ export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['common', 'header', 'discover']); describe('discover app', function describeIndexTests() { - before(function () { + before(async function () { const fromTime = '2015-09-19 06:31:44.000'; const toTime = '2015-09-23 18:31:44.000'; + await esArchiver.loadIfNeeded('logstash_functional'); + await esArchiver.load('discover'); + await kibanaServer.waitForStabilization(); // delete .kibana index and update configDoc - return kibanaServer.uiSettings.replace({ + await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'UTC', 'defaultIndex': 'logstash-*' - }) - .then(function loadkibanaIndexPattern() { - log.debug('load kibana index with default index pattern'); - return esArchiver.load('discover'); - }) - // and load a set of makelogs data - .then(function loadIfEmptyMakelogs() { - return esArchiver.loadIfNeeded('logstash_functional'); - }) - .then(function () { - log.debug('discover'); - return PageObjects.common.navigateToApp('discover'); - }) - .then(function () { - log.debug('setAbsoluteRange'); - return PageObjects.header.setAbsoluteRange(fromTime, toTime); }); + + await PageObjects.common.navigateToApp('discover'); + await PageObjects.header.setAbsoluteRange(fromTime, toTime); }); diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js index 1087f1a615c10..fa878130d1bc6 100644 --- a/test/functional/apps/visualize/_area_chart.js +++ b/test/functional/apps/visualize/_area_chart.js @@ -68,7 +68,7 @@ export default function ({ getService, getPageObjects }) { expect(message).to.be(`Visualization Editor: Saved Visualization "${vizNamewithSpecialChars}"`); }) .then(function testVisualizeWaitForToastMessageGone() { - return PageObjects.visualize.waitForToastMessageGone(); + return PageObjects.header.waitForToastMessageGone(); }); }); @@ -79,7 +79,7 @@ export default function ({ getService, getPageObjects }) { log.debug(`Saved viz message with umlaut = ${message}`); expect(message).to.be(`Visualization Editor: Saved Visualization "${vizNamewithSpecialChars}"`); - await PageObjects.visualize.waitForToastMessageGone(); + await PageObjects.header.waitForToastMessageGone(); }); it('should save and load', function () { @@ -90,7 +90,7 @@ export default function ({ getService, getPageObjects }) { expect(message).to.be('Visualization Editor: Saved Visualization \"' + vizName1 + '\"'); }) .then(function testVisualizeWaitForToastMessageGone() { - return PageObjects.visualize.waitForToastMessageGone(); + return PageObjects.header.waitForToastMessageGone(); }) .then(function loadSavedVisualization() { return PageObjects.visualize.loadSavedVisualization(vizName1); diff --git a/test/functional/apps/visualize/_data_table.js b/test/functional/apps/visualize/_data_table.js index 06d1c4ff18546..6445817b19de7 100644 --- a/test/functional/apps/visualize/_data_table.js +++ b/test/functional/apps/visualize/_data_table.js @@ -59,7 +59,7 @@ export default function ({ getService, getPageObjects }) { expect(message).to.be('Visualization Editor: Saved Visualization \"' + vizName1 + '\"'); }) .then(function testVisualizeWaitForToastMessageGone() { - return PageObjects.visualize.waitForToastMessageGone(); + return PageObjects.header.waitForToastMessageGone(); }) .then(function () { return PageObjects.visualize.loadSavedVisualization(vizName1); diff --git a/test/functional/apps/visualize/_heatmap_chart.js b/test/functional/apps/visualize/_heatmap_chart.js index 9ea369741775b..c3315ecaa14b1 100644 --- a/test/functional/apps/visualize/_heatmap_chart.js +++ b/test/functional/apps/visualize/_heatmap_chart.js @@ -3,6 +3,7 @@ import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { const log = getService('log'); const screenshots = getService('screenshots'); + const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'visualize', 'header']); describe('visualize app', function describeIndexTests() { @@ -57,7 +58,7 @@ export default function ({ getService, getPageObjects }) { expect(message).to.be('Visualization Editor: Saved Visualization \"' + vizName1 + '\"'); }) .then(function testVisualizeWaitForToastMessageGone() { - return PageObjects.visualize.waitForToastMessageGone(); + return PageObjects.header.waitForToastMessageGone(); }) .then(function () { return PageObjects.visualize.loadSavedVisualization(vizName1); @@ -70,20 +71,14 @@ export default function ({ getService, getPageObjects }) { }); }); - it('should show correct chart, take screenshot', function () { + it('should show correct chart, take screenshot', async function () { const expectedChartValues = ['0 - 400', '0 - 400', '400 - 800', '1,200 - 1,600', '1,200 - 1,600', '400 - 800', '0 - 400', '0 - 400', '0 - 400', '0 - 400', '400 - 800', '1,200 - 1,600', '1,200 - 1,600', '400 - 800', '0 - 400', '0 - 400', '0 - 400', '0 - 400', '400 - 800', '1,200 - 1,600', '1,200 - 1,600', '400 - 800', '0 - 400', '0 - 400' ]; - // Most recent failure on Jenkins usually indicates the bar chart is still being drawn? - // return arguments[0].getAttribute(arguments[1]);","args":[{"ELEMENT":"592"},"fill"]}] arguments[0].getAttribute is not a function - // try sleeping a bit before getting that data - return PageObjects.common.sleep(5000) - .then(function () { - return PageObjects.visualize.getHeatmapData(); - }) - .then(function showData(data) { + await retry.try(async () => { + const data = await PageObjects.visualize.getHeatmapData(); log.debug('data=' + data); log.debug('data.length=' + data.length); screenshots.take('Visualize-heatmap-chart'); diff --git a/test/functional/apps/visualize/_line_chart.js b/test/functional/apps/visualize/_line_chart.js index 7d2634fbd8408..6669764c6fdff 100644 --- a/test/functional/apps/visualize/_line_chart.js +++ b/test/functional/apps/visualize/_line_chart.js @@ -131,7 +131,7 @@ export default function ({ getService, getPageObjects }) { expect(message).to.be('Visualization Editor: Saved Visualization \"' + vizName1 + '\"'); }) .then(function testVisualizeWaitForToastMessageGone() { - return PageObjects.visualize.waitForToastMessageGone(); + return PageObjects.header.waitForToastMessageGone(); }) .then(function () { return PageObjects.visualize.loadSavedVisualization(vizName1); diff --git a/test/functional/apps/visualize/_pie_chart.js b/test/functional/apps/visualize/_pie_chart.js index 7b624653643f6..a0c2950ef8a62 100644 --- a/test/functional/apps/visualize/_pie_chart.js +++ b/test/functional/apps/visualize/_pie_chart.js @@ -65,7 +65,7 @@ export default function ({ getService, getPageObjects }) { expect(message).to.be('Visualization Editor: Saved Visualization \"' + vizName1 + '\"'); }) .then(function testVisualizeWaitForToastMessageGone() { - return PageObjects.visualize.waitForToastMessageGone(); + return PageObjects.header.waitForToastMessageGone(); }) .then(function () { return PageObjects.visualize.loadSavedVisualization(vizName1); diff --git a/test/functional/apps/visualize/_point_series_options.js b/test/functional/apps/visualize/_point_series_options.js index 5203f531bfc16..1ba9a87d063fa 100644 --- a/test/functional/apps/visualize/_point_series_options.js +++ b/test/functional/apps/visualize/_point_series_options.js @@ -2,6 +2,7 @@ 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', 'pointSeries']); const pointSeriesVis = PageObjects.pointSeries; @@ -82,7 +83,7 @@ export default function ({ getService, getPageObjects }) { describe('secondary value axis', function () { - it('should show correct chart, take screenshot', function () { + it('should show correct chart, take screenshot', async function () { const expectedChartValues = [ [ 37, 202, 740, 1437, 1371, 751, 188, 31, 42, 202, 683, 1361, 1415, 707, 177, 27, 32, 175, 707, 1408, 1355, 726, 201, 29 ], @@ -92,27 +93,18 @@ export default function ({ getService, getPageObjects }) { 12807319386, 13375732998, 13190755620, 12627508458, 12731510199, 13153337344 ], ]; - // Most recent failure on Jenkins usually indicates the bar chart is still being drawn? - // return arguments[0].getAttribute(arguments[1]);","args":[{"ELEMENT":"592"},"fill"]}] arguments[0].getAttribute is not a function - // try sleeping a bit before getting that data - return PageObjects.common.sleep(2000) - .then(function () { - return PageObjects.visualize.getLineChartData('fill="#00a69b"'); - }) - .then(function showData(data) { - log.debug('count data=' + data); - log.debug('data.length=' + data.length); - screenshots.take('Visualize-secondary-value-axis'); - expect(data).to.eql(expectedChartValues[0]); - }) - .then(function () { - return PageObjects.visualize.getLineChartData('fill="#57c17b"', 'ValueAxis-2'); - }) - .then(function showData(data) { - log.debug('average memory data=' + data); - log.debug('data.length=' + data.length); - expect(data).to.eql(expectedChartValues[1]); - }); + await retry.try(async () => { + const data = await PageObjects.visualize.getLineChartData('fill="#00a69b"'); + log.debug('count data=' + data); + log.debug('data.length=' + data.length); + screenshots.take('Visualize-secondary-value-axis'); + expect(data).to.eql(expectedChartValues[0]); + + const avgMemoryData = await PageObjects.visualize.getLineChartData('fill="#57c17b"', 'ValueAxis-2'); + log.debug('average memory data=' + avgMemoryData); + log.debug('data.length=' + avgMemoryData.length); + expect(avgMemoryData).to.eql(expectedChartValues[1]); + }); }); it('should put secondary axis on the right', function () { diff --git a/test/functional/apps/visualize/_tag_cloud.js b/test/functional/apps/visualize/_tag_cloud.js index 7a935073cf465..b323a79be7107 100644 --- a/test/functional/apps/visualize/_tag_cloud.js +++ b/test/functional/apps/visualize/_tag_cloud.js @@ -53,14 +53,10 @@ export default function ({ getService, getPageObjects }) { describe('tile cloud chart', function indexPatternCreation() { const vizName1 = 'Visualization tagCloud'; - it('should show correct tag cloud data', function () { - return PageObjects.common.sleep(2000) - .then(function () { - return PageObjects.visualize.getTextTag().then(function (results) { - log.debug(results); - expect(results).to.eql([ '32212254720', '21474836480','20401094656','19327352832','18253611008' ]); - }); - }); + it('should show correct tag cloud data', async function () { + const data = await PageObjects.visualize.getTextTag(); + log.debug(data); + expect(data).to.eql([ '32212254720', '21474836480','20401094656','19327352832','18253611008' ]); }); @@ -71,7 +67,7 @@ export default function ({ getService, getPageObjects }) { expect(message).to.be('Visualization Editor: Saved Visualization \"' + vizName1 + '\"'); }) .then(function testVisualizeWaitForToastMessageGone() { - return PageObjects.visualize.waitForToastMessageGone(); + return PageObjects.header.waitForToastMessageGone(); }) .then(function () { return PageObjects.visualize.loadSavedVisualization(vizName1); diff --git a/test/functional/apps/visualize/_tile_map.js b/test/functional/apps/visualize/_tile_map.js index 0e4ef11a9d73a..9983a7a1fabe1 100644 --- a/test/functional/apps/visualize/_tile_map.js +++ b/test/functional/apps/visualize/_tile_map.js @@ -90,54 +90,34 @@ export default function ({ getService, getPageObjects }) { describe('tile map chart', function indexPatternCreation() { - it('should show correct tile map data on default zoom level', function () { + it('should show correct tile map data on default zoom level', async function () { const expectedTableData = ['9 5,787 { "lat": 37.22448418632405, "lon": -103.01935195013255 }', 'd 5,600 { "lat": 37.44271478370398, "lon": -81.72692197253595 }', 'c 1,319 { "lat": 47.72720855392425, "lon": -109.84745063951028 }', 'b 999 { "lat": 62.04130042948433, "lon": -155.28087269195967 }', 'f 187 { "lat": 45.656166475784175, "lon": -82.45831044201545 }', '8 108 { "lat": 18.85260305600241, "lon": -156.5148810390383 }']; + //level 1 + await PageObjects.visualize.clickMapZoomOut(); + //level 0 + await PageObjects.visualize.clickMapZoomOut(); - return PageObjects.visualize.openSpyPanel() - .then(function () { - //level 1 - return PageObjects.visualize.clickMapZoomOut(); - }) - .then(function () { - //level 0 - return PageObjects.visualize.clickMapZoomOut(); - }) - .then(function () { - return PageObjects.settings.setPageSize('All'); - }) - .then(function getDataTableData() { - return PageObjects.visualize.getDataTableData() - .then(function showData(actualTableData) { - compareTableData(expectedTableData, actualTableData.trim().split('\n')); - return PageObjects.visualize.closeSpyPanel(); - }); - }); + await PageObjects.visualize.openSpyPanel(); + await PageObjects.settings.setPageSize('All'); + const actualTableData = await PageObjects.visualize.getDataTableData(); + compareTableData(expectedTableData, actualTableData.trim().split('\n')); + await PageObjects.visualize.closeSpyPanel(); }); - it('should not be able to zoom out beyond 0', function () { - return PageObjects.visualize.getMapZoomOutEnabled() - // we can tell we're at level 1 because zoom out is disabled - .then(function () { - return retry.try(function tryingForTime() { - return PageObjects.visualize.getMapZoomOutEnabled() - .then(function (enabled) { - //should be able to zoom more as current config has 0 as min level. - expect(enabled).to.be(false); - }); - }); - }) - .then(function takeScreenshot() { - log.debug('Take screenshot (success)'); - screenshots.take('map-at-zoom-0'); - }); + it('should not be able to zoom out beyond 0', async function () { + await PageObjects.visualize.zoomAllTheWayOut(); + const enabled = await PageObjects.visualize.getMapZoomOutEnabled(); + expect(enabled).to.be(false); + screenshots.take('map-at-zoom-0'); }); - it('Fit data bounds should zoom to level 3', function () { + // See https://github.com/elastic/kibana/issues/13137 if this test starts failing intermittently + it('Fit data bounds should zoom to level 3', async function () { const expectedPrecision2ZoomCircles = [ { color: '#750000', radius: 192 }, { color: '#750000', radius: 191 }, @@ -187,12 +167,11 @@ export default function ({ getService, getPageObjects }) { { color: '#b99939', radius: 9 } ]; - return PageObjects.visualize.clickMapFitDataBounds() - .then(function () { - return PageObjects.visualize.getTileMapData(); - }) - .then(function (data) { + await retry.try(async() => { + await PageObjects.visualize.clickMapFitDataBounds(); + const data = await PageObjects.visualize.getTileMapData(); expect(data).to.eql(expectedPrecision2ZoomCircles); + screenshots.take('map-at-zoom-3'); }); }); @@ -238,7 +217,7 @@ export default function ({ getService, getPageObjects }) { expect(message).to.be('Visualization Editor: Saved Visualization \"' + vizName1 + '\"'); }) .then(function testVisualizeWaitForToastMessageGone() { - return PageObjects.visualize.waitForToastMessageGone(); + return PageObjects.header.waitForToastMessageGone(); }) .then(function () { return PageObjects.visualize.openSpyPanel(); diff --git a/test/functional/apps/visualize/_vertical_bar_chart.js b/test/functional/apps/visualize/_vertical_bar_chart.js index f0be93c5540f6..5fbe56c81b857 100644 --- a/test/functional/apps/visualize/_vertical_bar_chart.js +++ b/test/functional/apps/visualize/_vertical_bar_chart.js @@ -2,6 +2,7 @@ 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']); @@ -57,7 +58,7 @@ export default function ({ getService, getPageObjects }) { expect(message).to.be('Visualization Editor: Saved Visualization \"' + vizName1 + '\"'); }) .then(function testVisualizeWaitForToastMessageGone() { - return PageObjects.visualize.waitForToastMessageGone(); + return PageObjects.header.waitForToastMessageGone(); }) .then(function () { return PageObjects.visualize.loadSavedVisualization(vizName1); @@ -70,7 +71,7 @@ export default function ({ getService, getPageObjects }) { }); }); - it('should show correct chart, take screenshot', function () { + it('should show correct chart, take screenshot', async function () { const expectedChartValues = [37, 202, 740, 1437, 1371, 751, 188, 31, 42, 202, 683, 1361, 1415, 707, 177, 27, 32, 175, 707, 1408, 1355, 726, 201, 29 ]; @@ -78,11 +79,8 @@ export default function ({ getService, getPageObjects }) { // Most recent failure on Jenkins usually indicates the bar chart is still being drawn? // return arguments[0].getAttribute(arguments[1]);","args":[{"ELEMENT":"592"},"fill"]}] arguments[0].getAttribute is not a function // try sleeping a bit before getting that data - return PageObjects.common.sleep(50000) - .then(function () { - return PageObjects.visualize.getBarChartData(); - }) - .then(function showData(data) { + await retry.try(async() => { + const data = await PageObjects.visualize.getBarChartData(); log.debug('data=' + data); log.debug('data.length=' + data.length); screenshots.take('Visualize-vertical-bar-chart'); @@ -90,7 +88,6 @@ export default function ({ getService, getPageObjects }) { }); }); - it('should show correct data', function () { // this is only the first page of the tabular data. const expectedChartData = [ '2015-09-20 00:00', '37', diff --git a/test/functional/page_objects/common_page.js b/test/functional/page_objects/common_page.js index 7d700c8fcd235..56714a95b3047 100644 --- a/test/functional/page_objects/common_page.js +++ b/test/functional/page_objects/common_page.js @@ -7,6 +7,7 @@ export function CommonPageProvider({ getService, getPageObjects }) { const config = getService('config'); const remote = getService('remote'); const retry = getService('retry'); + const find = getService('find'); const testSubjects = getService('testSubjects'); const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['shield']); @@ -200,10 +201,7 @@ export function CommonPageProvider({ getService, getPageObjects }) { } async getSharedItemTitleAndDescription() { - const element = await remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('[data-shared-item]'); - + const element = await find.byCssSelector('[data-shared-item]'); return { title: await element.getAttribute('data-title'), description: await element.getAttribute('data-description') @@ -239,12 +237,8 @@ export function CommonPageProvider({ getService, getPageObjects }) { } async isConfirmModalOpen() { - const isOpen = await testSubjects - .find('confirmModalCancelButton', 2000) - .then(() => true, () => false); - - await remote.setFindTimeout(defaultFindTimeout); - return isOpen; + log.debug('isConfirmModalOpen'); + return await testSubjects.exists('confirmModalCancelButton', 2000); } async doesCssSelectorExist(selector) { diff --git a/test/functional/page_objects/dashboard_page.js b/test/functional/page_objects/dashboard_page.js index a38c0f24aa461..dc0b537a2a03a 100644 --- a/test/functional/page_objects/dashboard_page.js +++ b/test/functional/page_objects/dashboard_page.js @@ -59,9 +59,14 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } } + async getQueryInputElement() { + return retry.try(() => testSubjects.find('queryInput')); + } + async getQuery() { - const queryObject = await testSubjects.find('queryInput'); - return await queryObject.getProperty('value'); + log.debug(`getQuery`); + const queryInputElement = await this.getQueryInputElement(); + return await queryInputElement.getProperty('value'); } async setQuery(query) { @@ -104,7 +109,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } clickCancelOutOfEditMode() { - log.debug('Clicking cancel'); + log.debug('clickCancelOutOfEditMode'); return testSubjects.click('dashboardViewOnlyMode'); } @@ -229,12 +234,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { // verify that green message at the top of the page. // it's only there for about 5 seconds - await retry.try(() => { - log.debug('verify toast-message for saved dashboard'); - return getRemote() - .findByCssSelector('kbn-truncated.toast-message.ng-isolate-scope') - .getVisibleText(); - }); + return await PageObjects.header.getToastMessage(); } /** diff --git a/test/functional/page_objects/discover_page.js b/test/functional/page_objects/discover_page.js index 00cc15f9bb43a..d41d7ef97136d 100644 --- a/test/functional/page_objects/discover_page.js +++ b/test/functional/page_objects/discover_page.js @@ -45,26 +45,23 @@ export function DiscoverPageProvider({ getService, getPageObjects }) { }); } - loadSavedSearch(searchName) { - return this.clickLoadSavedSearchButton() - .then(() => { - getRemote().findByPartialLinkText(searchName).click(); - }) - .then(() => { - return PageObjects.header.waitUntilLoadingHasFinished(); - }); + async loadSavedSearch(searchName) { + await this.clickLoadSavedSearchButton(); + const searchLink = await find.byPartialLinkText(searchName); + await searchLink.click(); + await PageObjects.header.waitUntilLoadingHasFinished(); } - clickNewSearchButton() { - return testSubjects.click('discoverNewButton'); + async clickNewSearchButton() { + await testSubjects.click('discoverNewButton'); } - clickSaveSearchButton() { - return testSubjects.click('discoverSaveButton'); + async clickSaveSearchButton() { + await testSubjects.click('discoverSaveButton'); } - clickLoadSavedSearchButton() { - return testSubjects.click('discoverOpenButton'); + async clickLoadSavedSearchButton() { + await testSubjects.click('discoverOpenButton'); } async getCurrentQueryName() { diff --git a/test/functional/page_objects/header_page.js b/test/functional/page_objects/header_page.js index 6b36fa74f1a24..e66666749ed05 100644 --- a/test/functional/page_objects/header_page.js +++ b/test/functional/page_objects/header_page.js @@ -201,12 +201,13 @@ export function HeaderPageProvider({ getService, getPageObjects }) { } async isGlobalLoadingIndicatorVisible() { - return await testSubjects.find('globalLoadingIndicator', defaultFindTimeout / 5); + log.debug('isGlobalLoadingIndicatorVisible'); + return await testSubjects.exists('globalLoadingIndicator'); } async isGlobalLoadingIndicatorHidden() { - remote.setFindTimeout(defaultFindTimeout * 10); - return await remote.findByCssSelector('[data-test-subj="globalLoadingIndicator"].ng-hide'); + log.debug('isGlobalLoadingIndicatorHidden'); + return await find.byCssSelector('[data-test-subj="globalLoadingIndicator"].ng-hide', defaultFindTimeout * 10); } async getPrettyDuration() { diff --git a/test/functional/page_objects/visualize_page.js b/test/functional/page_objects/visualize_page.js index 50a65f660b82b..0682358bdf604 100644 --- a/test/functional/page_objects/visualize_page.js +++ b/test/functional/page_objects/visualize_page.js @@ -3,202 +3,129 @@ export function VisualizePageProvider({ getService, getPageObjects }) { const config = getService('config'); const testSubjects = getService('testSubjects'); const retry = getService('retry'); + const find = getService('find'); const log = getService('log'); const PageObjects = getPageObjects(['common', 'header']); const defaultFindTimeout = config.get('timeouts.find'); class VisualizePage { - clickAreaChart() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Area') - .click(); - } - clickDataTable() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Data Table') - .click(); + async clickAreaChart() { + await find.clickByPartialLinkText('Area'); } - clickLineChart() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Line') - .click(); + async clickDataTable() { + await find.clickByPartialLinkText('Data Table'); } - - clickRegionMap() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Region Map') - .click(); + async clickLineChart() { + await find.clickByPartialLinkText('Line'); } - getVectorMapData() { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('path.leaflet-clickable') - .then((chartTypes) => { - - - function getChartType(chart) { - let color; - return chart.getAttribute('fill') - .then((stroke) => { - color = stroke; - }) - .then(() => { - return { color: color }; - }); - } - - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }) - .then((data) => { - data = data.filter((country) => { - //filter empty colors - return country.color !== 'rgb(200,200,200)'; - }); - return data; - }); + async clickRegionMap() { + await find.clickByPartialLinkText('Region Map'); } - clickMarkdownWidget() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Markdown') - .click(); + async clickMarkdownWidget() { + await find.clickByPartialLinkText('Markdown'); } - clickAddMetric() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('[group-name="metrics"] [data-test-subj="visualizeEditorAddAggregationButton"]') - .click(); + async clickAddMetric() { + await find.clickByCssSelector('[group-name="metrics"] [data-test-subj="visualizeEditorAddAggregationButton"]'); } - clickMetric() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Metric') - .click(); + async clickMetric() { + await find.clickByPartialLinkText('Metric'); } - clickGauge() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Gauge') - .click(); + async clickGauge() { + await find.clickByPartialLinkText('Gauge'); } - clickPieChart() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Pie') - .click(); + async clickPieChart() { + await find.clickByPartialLinkText('Pie'); } - clickTileMap() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Coordinate Map') - .click(); + async clickTileMap() { + await find.clickByPartialLinkText('Coordinate Map'); } - clickTagCloud() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Tag Cloud') - .click(); + async clickTagCloud() { + await find.clickByPartialLinkText('Tag Cloud'); } - getTextTag() { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('text').getVisibleText(); + async getTextTag() { + const elements = await find.allByCssSelector('text'); + return await Promise.all(elements.map(async element => await element.getVisibleText())); } + async getVectorMapData() { + const chartTypes = await find.allByCssSelector('path.leaflet-clickable'); - getTextSizes() { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('text') - .then(function (tags) { - function returnTagSize(tag) { - return tag.getAttribute('style') - .then(function (style) { - return style.match(/font-size: ([^;]*);/)[1]; - }); - } - return Promise.all(tags.map(returnTagSize)); + async function getChartColors(chart) { + const stroke = await chart.getAttribute('fill'); + return { color: stroke }; + } + + let colorData = await Promise.all(chartTypes.map(getChartColors)); + colorData = colorData.filter((country) => { + //filter empty colors + return country.color !== 'rgb(200,200,200)'; }); + return colorData; } + async getTextSizes() { + const tags = await find.allByCssSelector('text'); + async function returnTagSize(tag) { + const style = await tag.getAttribute('style'); + return style.match(/font-size: ([^;]*);/)[1]; + } + return await Promise.all(tags.map(returnTagSize)); + } - clickVerticalBarChart() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Vertical Bar') - .click(); + async clickVerticalBarChart() { + await find.clickByPartialLinkText('Vertical Bar'); } - clickHeatmapChart() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Heat Map') - .click(); + async clickHeatmapChart() { + await find.clickByPartialLinkText('Heat Map'); } - getChartTypeCount() { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('a.wizard-vis-type.ng-scope') - .length; + async getChartTypeCount() { + const tags = await find.allByCssSelector('a.wizard-vis-type.ng-scope'); + return tags.length; } - getChartTypes() { - return testSubjects.findAll('visualizeWizardChartTypeTitle') - .then(function (chartTypes) { - function getChartType(chart) { - return chart.getVisibleText(); - } - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }) - .then(function (texts) { - return texts; - }); + async getChartTypes() { + const chartTypes = await testSubjects.findAll('visualizeWizardChartTypeTitle'); + async function getChartType(chart) { + return await chart.getVisibleText(); + } + const getChartTypesPromises = chartTypes.map(getChartType); + return await Promise.all(getChartTypesPromises); } - clickAbsoluteButton() { - return remote - .setFindTimeout(defaultFindTimeout * 2) - .findByCssSelector('ul.nav.nav-pills.nav-stacked.kbn-timepicker-modes:contains("absolute")') - .click(); + async clickAbsoluteButton() { + await find.clickByCssSelector( + 'ul.nav.nav-pills.nav-stacked.kbn-timepicker-modes:contains("absolute")', + defaultFindTimeout * 2); } - setFromTime(timeString) { - return remote - .setFindTimeout(defaultFindTimeout * 2) - .findByCssSelector('input[ng-model="absolute.from"]') - .clearValue() - .type(timeString); + async setFromTime(timeString) { + const input = await find.byCssSelector('input[ng-model="absolute.from"]', defaultFindTimeout * 2); + await input.clearValue(); + await input.type(timeString); } - setToTime(timeString) { - return remote - .setFindTimeout(defaultFindTimeout * 2) - .findByCssSelector('input[ng-model="absolute.to"]') - .clearValue() - .type(timeString); + async setToTime(timeString) { + const input = await find.byCssSelector('input[ng-model="absolute.to"]', defaultFindTimeout * 2); + await input.clearValue(); + await input.type(timeString); } - clickGoButton() { - return testSubjects.click('timepickerGoButton'); + async clickGoButton() { + await testSubjects.click('timepickerGoButton'); } async getSpyToggleExists() { @@ -230,259 +157,156 @@ export function VisualizePageProvider({ getService, getPageObjects }) { } } - toggleSpyPanel() { - return testSubjects.click('spyToggleButton'); + async toggleSpyPanel() { + await testSubjects.click('spyToggleButton'); } - getMetric() { - return remote - .setFindTimeout(2000) - .findByCssSelector('div[ng-controller="KbnMetricVisController"]') - .getVisibleText(); + async getMetric() { + const metricElement = await find.byCssSelector('div[ng-controller="KbnMetricVisController"]'); + return await metricElement.getVisibleText(); } - getGaugeValue() { - return remote - .setFindTimeout(2000) - .findAllByCssSelector('visualize .chart svg') - .getVisibleText(); + async getGaugeValue() { + const elements = await find.allByCssSelector('visualize .chart svg'); + return await Promise.all(elements.map(async element => await element.getVisibleText())); } - clickMetricEditor() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('button[aria-label="Open Editor"]') - .click(); + async clickMetricEditor() { + await find.clickByCssSelector('button[aria-label="Open Editor"]'); } - clickNewSearch() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('.list-group-item a') - .click(); + async clickNewSearch() { + await find.clickByCssSelector('.list-group-item a'); } - setValue(newValue) { - return remote - .setFindTimeout(defaultFindTimeout * 2) - .findByCssSelector('button[ng-click="numberListCntr.add()"]') - .click() - .then(() => { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('input[ng-model="numberListCntr.getList()[$index]"]') - .clearValue(); - }) - .then(() => { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('input[ng-model="numberListCntr.getList()[$index]"]') - .type(newValue); - }); + async setValue(newValue) { + await find.clickByCssSelector('button[ng-click="numberListCntr.add()"]', defaultFindTimeout * 2); + const input = await find.byCssSelector('input[ng-model="numberListCntr.getList()[$index]"]'); + await input.clearValue(); + await input.type(newValue); } - clickSavedSearch() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('li[ng-click="stepTwoMode=\'saved\'"]') - .click(); + async clickSavedSearch() { + await find.clickByCssSelector('li[ng-click="stepTwoMode=\'saved\'"]'); } - selectSearch(searchName) { - return remote - .setFindTimeout(defaultFindTimeout) - .findByLinkText(searchName) - .click(); + async selectSearch(searchName) { + await find.clickByLinkText(searchName); } - - getErrorMessage() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('.item>h4') - .getVisibleText(); + async getErrorMessage() { + const element = await find.byCssSelector('.item>h4'); + return await element.getVisibleText(); } // clickBucket(bucketType) 'X-Axis', 'Split Area', 'Split Chart' - clickBucket(bucketName) { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('li.list-group-item.list-group-menu-item.ng-binding.ng-scope') - .then(chartTypes => { - log.debug('found bucket types ' + chartTypes.length); - - function getChartType(chart) { - return chart - .getVisibleText() - .then(chartString => { - //log.debug(chartString); - if (chartString === bucketName) { - chart.click(); - } - }); + async clickBucket(bucketName) { + const chartTypes = await retry.try( + async () => await find.allByCssSelector('li.list-group-item.list-group-menu-item.ng-binding.ng-scope')); + log.debug('found bucket types ' + chartTypes.length); + + async function getChartType(chart) { + const chartString = await chart.getVisibleText(); + if (chartString === bucketName) { + await chart.click(); } - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }); + } + const getChartTypesPromises = chartTypes.map(getChartType); + await Promise.all(getChartTypesPromises); } - selectAggregation(myString) { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('vis-editor-agg-params:not(.ng-hide) option[label="' + myString + '"]') - .click(); + async selectAggregation(myString) { + return find.clickByCssSelector('vis-editor-agg-params:not(.ng-hide) option[label="' + myString + '"]'); } - getField() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('.ng-valid-required[name="field"] .ui-select-match-text') - .getVisibleText(); + async getField() { + const field = await retry.try( + async () => await find.byCssSelector('.ng-valid-required[name="field"] .ui-select-match-text')); + return await field.getVisibleText(); } - selectField(fieldValue, groupName = 'buckets') { - return retry.try(function tryingForTime() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector(`[group-name="${groupName}"] .ui-select-container`) - .click() - .then(() => { - return remote - .findByCssSelector(`[group-name="${groupName}"] input.ui-select-search`) - .type(fieldValue) - .pressKeys('\uE006'); - }); + async selectField(fieldValue, groupName = 'buckets') { + await retry.try(async () => { + await find.clickByCssSelector(`[group-name="${groupName}"] .ui-select-container`); + const input = await find.byCssSelector(`[group-name="${groupName}"] input.ui-select-search`); + await input.type(fieldValue); + await remote.pressKeys('\uE006'); }); } - selectFieldById(fieldValue, id) { - return retry.try(function tryingForTime() { - return remote - .setFindTimeout(defaultFindTimeout) - // the css below should be more selective - .findByCssSelector(`#${id} > option[label="${fieldValue}"]`) - .click(); - }); + async selectFieldById(fieldValue, id) { + await find.clickByCssSelector(`#${id} > option[label="${fieldValue}"]`); } - orderBy(fieldValue) { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('select.form-control.ng-pristine.ng-valid.ng-untouched.ng-valid-required[ng-model="agg.params.orderBy"] ' + - 'option.ng-binding.ng-scope:contains("' + fieldValue + '")' - ) - .click(); + async orderBy(fieldValue) { + await find.clickByCssSelector( + 'select.form-control.ng-pristine.ng-valid.ng-untouched.ng-valid-required[ng-model="agg.params.orderBy"] ' + + 'option.ng-binding.ng-scope:contains("' + fieldValue + '")'); } - selectOrderBy(fieldValue) { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('select[name="orderBy"] > option[value="' + fieldValue + '"]') - .click(); + async selectOrderBy(fieldValue) { + await find.clickByCssSelector('select[name="orderBy"] > option[value="' + fieldValue + '"]'); } - - getInterval() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('select[ng-model="agg.params.interval"]') - .getProperty('selectedIndex') - .then(selectedIndex => { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('select[ng-model="agg.params.interval"] option:nth-child(' + (selectedIndex + 1) + ')') - .getProperty('label'); - }); + async getInterval() { + const select = await find.byCssSelector('select[ng-model="agg.params.interval"]'); + const selectedIndex = await select.getProperty('selectedIndex'); + const intervalElement = await find.byCssSelector( + `select[ng-model="agg.params.interval"] option:nth-child(${(selectedIndex + 1)})`); + return await intervalElement.getProperty('label'); } - setInterval(newValue) { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('select[ng-model="agg.params.interval"]') - .type(newValue); + async setInterval(newValue) { + const input = await find.byCssSelector('select[ng-model="agg.params.interval"]'); + await input.type(newValue); } - setNumericInterval(newValue) { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('input[name="interval"]') - .type(newValue); + async setNumericInterval(newValue) { + const input = await find.byCssSelector('input[name="interval"]'); + await input.type(newValue); } - clickGo() { - return testSubjects.click('visualizeEditorRenderButton') - .then(function () { - return PageObjects.header.waitUntilLoadingHasFinished(); - }); + async clickGo() { + await testSubjects.click('visualizeEditorRenderButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); } - clickOptions() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByPartialLinkText('Options') - .click(); + async clickOptions() { + await find.clickByPartialLinkText('Options'); } - selectWMS() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('input[name="wms.enabled"]') - .click(); + async selectWMS() { + await find.clickByCssSelector('input[name="wms.enabled"]'); } + async saveVisualization(vizName) { + await testSubjects.click('visualizeSaveButton'); + log.debug('saveButton button clicked'); + const visTitle = await find.byName('visTitle'); + await visTitle.type(vizName); + log.debug('click submit button'); + await testSubjects.click('saveVisualizationButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); - saveVisualization(vizName) { - return testSubjects.click('visualizeSaveButton') - .then(() => { - return PageObjects.common.sleep(1000); - }) - .then(() => { - log.debug('saveButton button clicked'); - return remote - .setFindTimeout(defaultFindTimeout) - .findByName('visTitle') - .type(vizName); - }) - // // click save button - .then(() => { - log.debug('click submit button'); - return testSubjects.click('saveVisualizationButton'); - }) - .then(function () { - return PageObjects.header.waitUntilLoadingHasFinished(); - }) - // verify that green message at the top of the page. - // it's only there for about 5 seconds - .then(() => { - return retry.try(function tryingForTime() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('kbn-truncated.toast-message.ng-isolate-scope') - .getVisibleText(); - }); - }); + return await PageObjects.header.getToastMessage(); } - clickLoadSavedVisButton() { + async clickLoadSavedVisButton() { // TODO: Use a test subject selector once we rewrite breadcrumbs to accept each breadcrumb // element as a child instead of building the breadcrumbs dynamically. - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('[href="#/visualize"]') - .click(); + await find.clickByCssSelector('[href="#/visualize"]'); } - filterVisByName(vizName) { - return remote - .findByCssSelector('input[name="filter"]') - .click() + async filterVisByName(vizName) { + const input = await find.byCssSelector('input[name="filter"]'); + await input.click(); // can't uses dashes in saved visualizations when filtering // or extended character sets // https://github.com/elastic/kibana/issues/6300 - .type(vizName.replace('-',' ')); + await input.type(vizName.replace('-',' ')); } - clickVisualizationByName(vizName) { + async clickVisualizationByName(vizName) { log.debug('clickVisualizationByLinkText(' + vizName + ')'); return retry.try(function tryingForTime() { @@ -495,404 +319,233 @@ export function VisualizePageProvider({ getService, getPageObjects }) { // this starts by clicking the Load Saved Viz button, not from the // bottom half of the "Create a new visualization Step 1" page - loadSavedVisualization(vizName) { - return this.clickLoadSavedVisButton() - .then(() => this.openSavedVisualization(vizName)); + async loadSavedVisualization(vizName) { + await this.clickLoadSavedVisButton(); + await this.openSavedVisualization(vizName); } - openSavedVisualization(vizName) { - return this.clickVisualizationByName(vizName); + async openSavedVisualization(vizName) { + await this.clickVisualizationByName(vizName); } - getXAxisLabels() { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('.x > g') - .then(chartTypes => { - function getChartType(chart) { - return chart - .getVisibleText(); - } - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }) - .then(texts => { - // log.debug('returning types array ' + texts + ' array length =' + texts.length); - return texts; - }); + async getXAxisLabels() { + const chartTypes = await find.allByCssSelector('.x > g'); + async function getChartType(chart) { + return await chart.getVisibleText(); + } + const getChartTypesPromises = chartTypes.map(getChartType); + return await Promise.all(getChartTypesPromises); } - - getYAxisLabels() { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('.y > g') - .then(chartTypes => { - function getChartType(chart) { - return chart - .getVisibleText(); - } - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }) - .then(texts => { - // log.debug('returning types array ' + texts + ' array length =' + texts.length); - return texts; - }); + async getYAxisLabels() { + const chartTypes = await find.allByCssSelector('.y > g'); + const getChartTypesPromises = chartTypes.map(async chart => await chart.getVisibleText()); + return await Promise.all(getChartTypesPromises); } - /* ** This method gets the chart data and scales it based on chart height and label. ** Returns an array of height values */ - getAreaChartData(aggregateName) { - const chartData = []; - let tempArray = []; - let chartSections = 0; - let yAxisLabel = 0; - let yAxisHeight = 0; - + async getAreaChartData(aggregateName) { // 1). get the maximim chart Y-Axis marker value - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('div.y-axis-div-wrapper > div > svg > g > g:last-of-type') - .getVisibleText() - .then(function (yLabel) { - // since we're going to use the y-axis 'last' (top) label as a number to - // scale the chart pixel data, we need to clean out commas and % marks. - yAxisLabel = yLabel.replace(/(%|,)/g, ''); - log.debug('yAxisLabel = ' + yAxisLabel); - return yLabel; - }) - // 2). find and save the y-axis pixel size (the chart height) - .then(function () { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('rect.background') // different here - .getAttribute('height'); - }) - .then(function (chartH) { - yAxisHeight = chartH; - log.debug('height --------- ' + yAxisHeight); - }) - .then(function () { - return remote.setFindTimeout(defaultFindTimeout * 2) - .findByCssSelector('path[data-label="' + aggregateName + '"]') - .getAttribute('d'); - }) - .then(function (data) { - log.debug(data); - // This area chart data starts with a 'M'ove to a x,y location, followed - // by a bunch of 'L'ines from that point to the next. Those points are - // the values we're going to use to calculate the data values we're testing. - // So git rid of the one 'M' and split the rest on the 'L's. - tempArray = data.replace('M','').split('L'); - chartSections = tempArray.length / 2; - log.debug('chartSections = ' + chartSections + ' height = ' + yAxisHeight + ' yAxisLabel = ' + yAxisLabel); - for (let i = 0; i < chartSections; i++) { - chartData[i] = Math.round((yAxisHeight - tempArray[i].split(',')[1]) / yAxisHeight * yAxisLabel); - log.debug('chartData[i] =' + chartData[i]); - } - return chartData; - }); + const maxChartYAxisElement = await retry.try( + async () => await find.byCssSelector('div.y-axis-div-wrapper > div > svg > g > g:last-of-type')); + + const yLabel = await maxChartYAxisElement.getVisibleText(); + // since we're going to use the y-axis 'last' (top) label as a number to + // scale the chart pixel data, we need to clean out commas and % marks. + const yAxisLabel = yLabel.replace(/(%|,)/g, ''); + log.debug('yAxisLabel = ' + yAxisLabel); + + const rectangle = await find.byCssSelector('rect.background'); + const yAxisHeight = await rectangle.getAttribute('height'); + log.debug(`height --------- ${yAxisHeight}`); + + const path = await retry.try( + async () => await find.byCssSelector(`path[data-label="${aggregateName}"]`, defaultFindTimeout * 2)); + const data = await path.getAttribute('d'); + log.debug(data); + // This area chart data starts with a 'M'ove to a x,y location, followed + // by a bunch of 'L'ines from that point to the next. Those points are + // the values we're going to use to calculate the data values we're testing. + // So git rid of the one 'M' and split the rest on the 'L's. + const tempArray = data.replace('M','').split('L'); + const chartSections = tempArray.length / 2; + log.debug('chartSections = ' + chartSections + ' height = ' + yAxisHeight + ' yAxisLabel = ' + yAxisLabel); + const chartData = []; + for (let i = 0; i < chartSections; i++) { + chartData[i] = Math.round((yAxisHeight - tempArray[i].split(',')[1]) / yAxisHeight * yAxisLabel); + log.debug('chartData[i] =' + chartData[i]); + } + return chartData; } - // The current test shows dots, not a line. This function gets the dots and normalizes their height. - getLineChartData(cssPart, axis = 'ValueAxis-1') { - let yAxisLabel = 0; - let yAxisHeight; - + async getLineChartData(cssPart, axis = 'ValueAxis-1') { // 1). get the maximim chart Y-Axis marker value - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector(`div.y-axis-div-wrapper > div > svg > g.${axis} > g:last-of-type`) - .getVisibleText() - .then(function (yLabel) { - yAxisLabel = yLabel.replace(/,/g, ''); - log.debug('yAxisLabel = ' + yAxisLabel); - return yLabel; - }) + const maxYAxisMarker = await retry.try( + async () => await find.byCssSelector(`div.y-axis-div-wrapper > div > svg > g.${axis} > g:last-of-type`)); + const yLabel = await maxYAxisMarker.getVisibleText(); + const yAxisLabel = yLabel.replace(/,/g, ''); + // 2). find and save the y-axis pixel size (the chart height) - .then(function getRect() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('clipPath rect') - .getAttribute('height') - .then(function (theHeight) { - yAxisHeight = theHeight; - log.debug('theHeight = ' + theHeight); - return theHeight; - }); - }) - // 3). get the chart-wrapper elements - .then(function getChartWrapper() { - return remote - .setFindTimeout(defaultFindTimeout * 2) - .findAllByCssSelector(`.chart-wrapper circle[${cssPart}]`) - .then(function (chartTypes) { - - // 5). for each chart element, find the green circle, then the cy position - function getChartType(chart) { - return chart - .getAttribute('cy') - .then(function (cy) { - // log.debug(' yAxisHeight=' + yAxisHeight + ' yAxisLabel=' + yAxisLabel + ' cy=' + cy + - // ' ((yAxisHeight - cy)/yAxisHeight * yAxisLabel)=' + ((yAxisHeight - cy) / yAxisHeight * yAxisLabel)); - return Math.round((yAxisHeight - cy) / yAxisHeight * yAxisLabel); - }); - } - - // 4). pass the chartTypes to the getChartType function - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }); - }) - - .then(function (yCoords) { - return yCoords; - }); - } + const rectangle = await find.byCssSelector('clipPath rect'); + const theHeight = await rectangle.getAttribute('height'); + const yAxisHeight = theHeight; + log.debug('theHeight = ' + theHeight); + // 3). get the chart-wrapper elements + const chartTypes = await retry.try( + async () => await find.allByCssSelector(`.chart-wrapper circle[${cssPart}]`, defaultFindTimeout * 2)); - // this is ALMOST identical to DiscoverPage.getBarChartData - getBarChartData() { - let yAxisLabel = 0; - let yAxisHeight; + // 5). for each chart element, find the green circle, then the cy position + async function getChartType(chart) { + const cy = await chart.getAttribute('cy'); + return Math.round((yAxisHeight - cy) / yAxisHeight * yAxisLabel); + } + + // 4). pass the chartTypes to the getChartType function + const getChartTypesPromises = chartTypes.map(getChartType); + return await Promise.all(getChartTypesPromises); + } + // this is ALMOST identical to DiscoverPage.getBarChartData + async getBarChartData() { // 1). get the maximim chart Y-Axis marker value - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('div.y-axis-div-wrapper > div > svg > g > g:last-of-type') - .then(function setYAxisLabel(y) { - return y - .getVisibleText() - .then(function (yLabel) { - yAxisLabel = yLabel.replace(',', ''); - log.debug('yAxisLabel = ' + yAxisLabel); - return yLabel; - }); - }) + const maxYAxisChartMarker = await retry.try( + async () => await find.byCssSelector('div.y-axis-div-wrapper > div > svg > g > g:last-of-type')); + + const yLabel = await maxYAxisChartMarker.getVisibleText(); + const yAxisLabel = yLabel.replace(',', ''); + log.debug('yAxisLabel = ' + yAxisLabel); + // 2). find and save the y-axis pixel size (the chart height) - .then(function getRect() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('rect.background') - .then(function getRectHeight(chartAreaObj) { - return chartAreaObj - .getAttribute('height') - .then(function (theHeight) { - yAxisHeight = theHeight; - log.debug('theHeight = ' + theHeight); - return theHeight; - }); - }); - }) + const chartAreaObj = await find.byCssSelector('rect.background'); + const yAxisHeight = await chartAreaObj.getAttribute('height'); + // 3). get the chart-wrapper elements - .then(function () { - return remote - .setFindTimeout(defaultFindTimeout * 2) - // #kibana-body > div.content > div > div > div > div.vis-editor-canvas > visualize > div.visualize-chart > div > div.vis-col-wrapper > div.chart-wrapper > div > svg > g > g.series.\30 > rect:nth-child(1) - .findAllByCssSelector('svg > g > g.series > rect') // rect - .then(function (chartTypes) { - function getChartType(chart) { - return chart - .getAttribute('fill') - .then(function (fillColor) { - // we're getting the default count color from defaults.js - if (fillColor === '#00a69b') { - return chart - .getAttribute('height') - .then(function (barHeight) { - return Math.round(barHeight / yAxisHeight * yAxisLabel); - }); - } - }); - } - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }) - .then(function (bars) { - return bars; - }); - }); + const chartTypes = await find.allByCssSelector('svg > g > g.series > rect'); + async function getChartType(chart) { + const fillColor = await chart.getAttribute('fill'); + + // we're getting the default count color from defaults.js + if (fillColor === '#00a69b') { + const barHeight = await chart.getAttribute('height'); + return Math.round(barHeight / yAxisHeight * yAxisLabel); + } + } + const getChartTypesPromises = chartTypes.map(getChartType); + return await Promise.all(getChartTypesPromises); } - getHeatmapData() { - // 1). get the maximim chart Y-Axis marker value - return remote - .setFindTimeout(defaultFindTimeout * 2) - // #kibana-body > div.content > div > div > div > div.vis-editor-canvas > visualize > div.visualize-chart > div > div.vis-col-wrapper > div.chart-wrapper > div > svg > g > g.series.\30 > rect:nth-child(1) - .findAllByCssSelector('svg > g > g.series rect') // rect - .then(function (chartTypes) { - log.debug('rects=' + chartTypes); - function getChartType(chart) { - return chart - .getAttribute('data-label'); - } - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }) - .then(function (labels) { - log.debug('labels=' + labels); - return labels; - }); + async getHeatmapData() { + const chartTypes = await retry.try( + async () => await find.allByCssSelector('svg > g > g.series rect', defaultFindTimeout * 2)); + log.debug('rects=' + chartTypes); + async function getChartType(chart) { + return await chart.getAttribute('data-label'); + } + const getChartTypesPromises = chartTypes.map(getChartType); + return await Promise.all(getChartTypesPromises); } - getPieChartData() { - // 1). get the maximim chart Y-Axis marker value - return remote - .setFindTimeout(defaultFindTimeout * 2) - // path.slice:nth-child(11) - .findAllByCssSelector('path.slice') - .then(function (chartTypes) { - function getChartType(chart) { - return chart - .getAttribute('d') - .then(function (slice) { - return slice; - }); - } - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }) - .then(function (slices) { - log.debug('slices=' + slices); - return slices; - }); + async getPieChartData() { + const chartTypes = await find.allByCssSelector('path.slice', defaultFindTimeout * 2); + + const getChartTypesPromises = chartTypes.map(async chart => await chart.getAttribute('d')); + return await Promise.all(getChartTypesPromises); + } + + async getChartAreaWidth() { + const rect = await retry.try(async () => find.byCssSelector('clipPath rect')); + return await rect.getAttribute('width'); } - getChartAreaWidth() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('clipPath rect') - .getAttribute('width'); + async getChartAreaHeight() { + const rect = await retry.try(async () => find.byCssSelector('clipPath rect')); + return await rect.getAttribute('height'); } - getChartAreaHeight() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('clipPath rect') - .getAttribute('height'); + + async getDataTableData() { + const dataTable = await retry.try( + async () => find.byCssSelector('table.table.table-condensed tbody', defaultFindTimeout * 2)); + return await dataTable.getVisibleText(); } - getDataTableData() { - return remote - .setFindTimeout(defaultFindTimeout * 2) - .findByCssSelector('table.table.table-condensed tbody') - .getVisibleText(); + async getMarkdownData() { + const markdown = await retry.try(async () => find.byCssSelector('visualize.ng-isolate-scope')); + return await markdown.getVisibleText(); } - getMarkdownData() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('visualize.ng-isolate-scope') - .getVisibleText(); + async clickColumns() { + await find.clickByCssSelector('div.schemaEditors.ng-scope > div > div > button:nth-child(2)'); } - clickColumns() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('div.schemaEditors.ng-scope > div > div > button:nth-child(2)') - .click(); + async waitForVisualization() { + return await find.byCssSelector('visualization'); } - waitForToastMessageGone() { - return retry.try(function tryingForTime() { - return remote - .setFindTimeout(100) - .findAllByCssSelector('kbn-truncated.toast-message.ng-isolate-scope') - .then(function toastMessage(messages) { - if (messages.length > 0) { - throw new Error('waiting for toast message to clear'); - } else { - log.debug('now messages = 0 "' + messages + '"'); - return messages; - } - }); - }); + async getZoomSelectors(zoomSelector) { + return await find.allByCssSelector(zoomSelector); } - waitForVisualization() { - return remote - .setFindTimeout(defaultFindTimeout) - .findByCssSelector('visualization'); + async clickMapButton(zoomSelector) { + const zooms = await this.getZoomSelectors(zoomSelector); + await Promise.all(zooms.map(async zoom => await zoom.click())); + await PageObjects.header.waitUntilLoadingHasFinished(); } - clickMapButton(zoomSelector) { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector(zoomSelector) - .click() - .then(() => { - return PageObjects.common.sleep(1000); - }) - .then(() => { - return PageObjects.header.waitUntilLoadingHasFinished(); - }); + async clickMapZoomIn() { + await this.clickMapButton('a.leaflet-control-zoom-in'); } - clickMapZoomIn() { - return this.clickMapButton('a.leaflet-control-zoom-in'); + async clickMapZoomOut() { + await this.clickMapButton('a.leaflet-control-zoom-out'); } - clickMapZoomOut() { - return this.clickMapButton('a.leaflet-control-zoom-out'); + async getMapZoomEnabled(zoomSelector) { + const zooms = await this.getZoomSelectors(zoomSelector); + const classAttributes = await Promise.all(zooms.map(async zoom => await zoom.getAttribute('class'))); + return !classAttributes.join('').includes('leaflet-disabled'); } - getMapZoomEnabled(zoomSelector) { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector(zoomSelector) - .getAttribute('class') - .then((element) => { - return !element.toString().includes('leaflet-disabled'); + async zoomAllTheWayOut() { + // we can tell we're at level 1 because zoom out is disabled + return await retry.try(async () => { + await this.clickMapZoomOut(); + const enabled = await this.getMapZoomOutEnabled(); + //should be able to zoom more as current config has 0 as min level. + if (enabled) { + throw new Error('Not fully zoomed out yet'); + } }); } - getMapZoomInEnabled() { - return this.getMapZoomEnabled('a.leaflet-control-zoom-in'); + async getMapZoomInEnabled() { + return await this.getMapZoomEnabled('a.leaflet-control-zoom-in'); } - getMapZoomOutEnabled() { - return this.getMapZoomEnabled('a.leaflet-control-zoom-out'); + async getMapZoomOutEnabled() { + return await this.getMapZoomEnabled('a.leaflet-control-zoom-out'); } - clickMapFitDataBounds() { - return this.clickMapButton('a.fa-crop'); + async clickMapFitDataBounds() { + return await this.clickMapButton('a.fa-crop'); } - getTileMapData() { - return remote - .setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('path.leaflet-clickable') - .then((chartTypes) => { - - function getChartType(chart) { - let color; - let radius; - return chart.getAttribute('stroke') - .then((stroke) => { - color = stroke; - }) - .then(() => { - return chart.getAttribute('d'); - }) - .then((d) => { - // scale the radius up (sometimes less than 1) and then round to int - radius = d.replace(/.*A(\d+\.\d+),.*/,'$1') * 10; - radius = Math.round(radius); - }) - .then(() => { - return { color: color, radius: radius }; - }); - } - const getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }) - .then((circles) => { - return circles; - }); + async getTileMapData() { + const chartTypes = await find.allByCssSelector('path.leaflet-clickable'); + async function getChartType(chart) { + const color = await chart.getAttribute('stroke'); + const d = await chart.getAttribute('d'); + // scale the radius up (sometimes less than 1) and then round to int + let radius = d.replace(/.*A(\d+\.\d+),.*/,'$1') * 10; + radius = Math.round(radius); + return { color, radius }; + } + const getChartTypesPromises = chartTypes.map(getChartType); + return await Promise.all(getChartTypesPromises); } } diff --git a/test/functional/services/find.js b/test/functional/services/find.js index a93b4e7dd6448..8b5cb453dea2d 100644 --- a/test/functional/services/find.js +++ b/test/functional/services/find.js @@ -2,64 +2,118 @@ export function FindProvider({ getService }) { const log = getService('log'); const config = getService('config'); const remote = getService('remote'); + const retry = getService('retry'); const defaultFindTimeout = config.get('timeouts.find'); class Find { + async withTimeout(timeout, block) { + try { + const remoteWithTimeout = remote.setFindTimeout(timeout); + return await block(remoteWithTimeout); + } finally { + remote.setFindTimeout(defaultFindTimeout); + } + } + + async ensureElementWithTimeout(timeout, getElementFunction) { + try { + const remoteWithTimeout = remote.setFindTimeout(timeout); + return await retry.try(async () => { + const element = await getElementFunction(remoteWithTimeout); + // Calling any method forces a staleness check + element.isEnabled(); + return element; + }); + } finally { + remote.setFindTimeout(defaultFindTimeout); + } + } + + async byName(selector, timeout = defaultFindTimeout) { + log.debug(`find.byName(${selector})`); + return await this.ensureElementWithTimeout(timeout, async remote => { + return await remote.findByName(selector); + }); + } + async byCssSelector(selector, timeout = defaultFindTimeout) { log.debug(`findByCssSelector ${selector}`); - const remoteWithTimeout = remote.setFindTimeout(timeout); - const element = await remoteWithTimeout.findByCssSelector(selector); - remoteWithTimeout.setFindTimeout(defaultFindTimeout); - return element; + return await this.ensureElementWithTimeout(timeout, async remote => { + return await remote.findByCssSelector(selector); + }); } async allByCssSelector(selector, timeout = defaultFindTimeout) { log.debug('in findAllByCssSelector: ' + selector); - const remoteWithTimeout = remote.setFindTimeout(timeout); - let elements = await remoteWithTimeout.findAllByCssSelector(selector); - remoteWithTimeout.setFindTimeout(defaultFindTimeout); - if (!elements) elements = []; - log.debug(`Found ${elements.length} for selector ${selector}`); - return elements; + return await this.withTimeout(timeout, async remote => { + return await retry.try(async () => { + let elements = await remote.findAllByCssSelector(selector); + if (!elements) elements = []; + // Force isStale checks for all the retrieved elements. + await Promise.all(elements.map(async element => await element.isEnabled())); + log.debug(`Found ${elements.length} for selector ${selector}`); + return elements; + }); + }); } async displayedByCssSelector(selector, timeout = defaultFindTimeout) { log.debug('in displayedByCssSelector: ' + selector); - const remoteWithTimeout = remote.setFindTimeout(timeout); - const element = await remoteWithTimeout.findDisplayedByCssSelector(selector); - remoteWithTimeout.setFindTimeout(defaultFindTimeout); - return element; + return await this.ensureElementWithTimeout(timeout, async remote => { + return await remote.findDisplayedByCssSelector(selector); + }); + } + + async byPartialLinkText(partialLinkText, timeout = defaultFindTimeout) { + log.debug(`find.byPartialLinkText(${partialLinkText})`); + return await this.ensureElementWithTimeout(timeout, async remote => { + return await remote.findByPartialLinkText(partialLinkText); + }); } - async existsByLinkText(linkText) { + async exists(findFunction, timeout = 1000) { + return await this.withTimeout(timeout, async remote => { + try { + await findFunction(remote); + return true; + } catch (error) { + return false; + } + }); + } + + async existsByLinkText(linkText, timeout = 1000) { log.debug(`existsByLinkText ${linkText}`); - const remoteWithTimeout = remote.setFindTimeout(1000); - const exists = await remoteWithTimeout.findDisplayedByLinkText(linkText) - .then(() => true) - .catch(() => false); - remoteWithTimeout.setFindTimeout(defaultFindTimeout); - return exists; + return await this.exists(async remote => await remote.findDisplayedByLinkText(linkText), timeout); } - async existsByDisplayedByCssSelector(selector) { + async existsByDisplayedByCssSelector(selector, timeout = 1000) { log.debug(`existsByDisplayedByCssSelector ${selector}`); - const remoteWithTimeout = remote.setFindTimeout(1000); - const exists = await remoteWithTimeout.findDisplayedByCssSelector(selector) - .then(() => true) - .catch(() => false); - remoteWithTimeout.setFindTimeout(defaultFindTimeout); - return exists; + return await this.exists(async remote => await remote.findDisplayedByCssSelector(selector), timeout); } - async existsByCssSelector(selector) { + async existsByCssSelector(selector, timeout = 1000) { log.debug(`existsByCssSelector ${selector}`); - const remoteWithTimeout = remote.setFindTimeout(1000); - const exists = await remoteWithTimeout.findByCssSelector(selector) - .then(() => true) - .catch(() => false); - remoteWithTimeout.setFindTimeout(defaultFindTimeout); - return exists; + return await this.exists(async remote => await remote.findByCssSelector(selector), timeout); + } + + async clickByPartialLinkText(linkText, timeout = defaultFindTimeout) { + log.debug(`clickByPartialLinkText(${linkText})`); + const element = await retry.try(async () => await this.byPartialLinkText(linkText, timeout)); + await element.click(); + } + + async clickByLinkText(linkText, timeout = defaultFindTimeout) { + log.debug(`clickByLinkText(${linkText})`); + const element = await this.byLinkText(linkText, timeout); + await element.click(); + } + + async clickByCssSelector(selector, timeout = defaultFindTimeout) { + log.debug(`clickByCssSelector(${selector})`); + const element = await this.byCssSelector(selector, timeout); + await element.click(); } } From 2bee8bb14cf0d2d527bfca05b4e909e620c5015f Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Thu, 27 Jul 2017 21:32:26 +0200 Subject: [PATCH 023/165] Add unit tests the verify correct `dataType` in `jQuery.ajax` request when loading Console app state. (#13092) --- .../console/public/src/__tests__/app.js | 84 +++++++++++++++++++ src/core_plugins/console/public/src/app.js | 14 +++- 2 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 src/core_plugins/console/public/src/__tests__/app.js diff --git a/src/core_plugins/console/public/src/__tests__/app.js b/src/core_plugins/console/public/src/__tests__/app.js new file mode 100644 index 0000000000000..50b8763020229 --- /dev/null +++ b/src/core_plugins/console/public/src/__tests__/app.js @@ -0,0 +1,84 @@ +import sinon from 'sinon'; +import $ from 'jquery'; + +import history from '../history'; +import mappings from '../mappings'; +import init from '../app'; + +describe('app initialization', () => { + const sandbox = sinon.sandbox.create(); + + let inputMock, outputMock; + let ajaxDoneStub; + beforeEach(() => { + ajaxDoneStub = sinon.stub(); + sandbox.stub($, 'ajax').returns({ done: ajaxDoneStub }); + sandbox.stub(history, 'getSavedEditorState'); + sandbox.stub(mappings, 'startRetrievingAutoCompleteInfo'); + + inputMock = { + update: sinon.stub(), + moveToNextRequestEdge: sinon.stub(), + highlightCurrentRequestsAndUpdateActionBar: sinon.stub(), + updateActionsBar: sinon.stub(), + getSession: sinon.stub().returns({ on() {} }) + }; + + outputMock = { + update: sinon.stub() + }; + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('correctly loads state from any external HTTPS links.', () => { + const mockContent = {}; + ajaxDoneStub.yields(mockContent); + + init(inputMock, outputMock, 'https://state.link.com/content'); + + sinon.assert.calledOnce($.ajax); + sinon.assert.calledWithExactly($.ajax, { + url: 'https://state.link.com/content', + dataType: 'text', + kbnXsrfToken: false + }); + + sinon.assert.calledTwice(inputMock.moveToNextRequestEdge); + sinon.assert.calledWithExactly(inputMock.moveToNextRequestEdge, true); + sinon.assert.calledOnce(inputMock.highlightCurrentRequestsAndUpdateActionBar); + sinon.assert.calledOnce(inputMock.updateActionsBar); + sinon.assert.calledOnce(inputMock.update); + sinon.assert.calledWithExactly(inputMock.update, sinon.match.same(mockContent)); + + sinon.assert.calledOnce(outputMock.update); + sinon.assert.calledWithExactly(outputMock.update, ''); + }); + + it('correctly loads state from GitHub API HTTPS links.', () => { + const mockContent = {}; + ajaxDoneStub.yields(mockContent); + + init(inputMock, outputMock, 'https://api.github.com/content'); + + sinon.assert.calledOnce($.ajax); + sinon.assert.calledWithExactly($.ajax, { + url: 'https://api.github.com/content', + dataType: 'text', + kbnXsrfToken: false, + headers: { Accept: "application/vnd.github.v3.raw" } + }); + + sinon.assert.calledTwice(inputMock.moveToNextRequestEdge); + sinon.assert.calledWithExactly(inputMock.moveToNextRequestEdge, true); + sinon.assert.calledOnce(inputMock.highlightCurrentRequestsAndUpdateActionBar); + sinon.assert.calledOnce(inputMock.updateActionsBar); + sinon.assert.calledOnce(inputMock.update); + sinon.assert.calledWithExactly(inputMock.update, sinon.match.same(mockContent)); + + sinon.assert.calledOnce(outputMock.update); + sinon.assert.calledWithExactly(outputMock.update, ''); + }); +}); diff --git a/src/core_plugins/console/public/src/app.js b/src/core_plugins/console/public/src/app.js index bda49cc2a2551..cdfb159eaab3d 100644 --- a/src/core_plugins/console/public/src/app.js +++ b/src/core_plugins/console/public/src/app.js @@ -27,11 +27,19 @@ export default function init(input, output, sourceLocation = 'stored') { } } else if (/^https?:\/\//.test(sourceLocation)) { - var loadFrom = { url: sourceLocation, dataType: "text", kbnXsrfToken: false }; + const loadFrom = { + url: sourceLocation, + // Having dataType here is required as it doesn't allow jQuery to `eval` content + // coming from the external source thereby preventing XSS attack. + dataType: 'text', + kbnXsrfToken: false + }; + if (/https?:\/\/api.github.com/.test(sourceLocation)) { - loadFrom.headers = { Accept: "application/vnd.github.v3.raw" }; + loadFrom.headers = { Accept: 'application/vnd.github.v3.raw' }; } - $.ajax(loadFrom).done(function (data) { + + $.ajax(loadFrom).done((data) => { resetToValues(data); input.moveToNextRequestEdge(true); input.highlightCurrentRequestsAndUpdateActionBar(); From 9b949a575b9fc3d9f6ba1071a08ad7c0b799b68b Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 27 Jul 2017 17:03:36 -0400 Subject: [PATCH 024/165] Save layer setting in the region map UI (#12956) --- .../region_map/public/region_map_vis_params.html | 6 ++---- src/core_plugins/region_map/public/region_map_vis_params.js | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core_plugins/region_map/public/region_map_vis_params.html b/src/core_plugins/region_map/public/region_map_vis_params.html index 9aba92115e880..8cb0774eb799b 100644 --- a/src/core_plugins/region_map/public/region_map_vis_params.html +++ b/src/core_plugins/region_map/public/region_map_vis_params.html @@ -15,9 +15,8 @@ id="regionMap" class="kuiSelect kuiSideBarSelect" ng-model="vis.params.selectedLayer" - ng-options="layer.name for layer in collections.vectorLayers" + ng-options="layer.name for layer in collections.vectorLayers track by layer.url" ng-change="onLayerChange()" - ng-init="vis.params.selectedLayer=collections.vectorLayers[0]" >
@@ -29,8 +28,7 @@
diff --git a/src/core_plugins/region_map/public/region_map_vis_params.js b/src/core_plugins/region_map/public/region_map_vis_params.js index 5b286f2d8c06c..6c9574e6b46f5 100644 --- a/src/core_plugins/region_map/public/region_map_vis_params.js +++ b/src/core_plugins/region_map/public/region_map_vis_params.js @@ -51,6 +51,7 @@ uiModules.get('kibana/region_map') $scope.vis.params.selectedJoinField = $scope.vis.params.selectedLayer.fields[0]; } + } }; }); From 5e9a4ecaf82a6e4503e28221ce5d3d33c920381f Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 27 Jul 2017 17:04:01 -0400 Subject: [PATCH 025/165] Region map should respect saved center and zoom (#12883) --- .../public/region_map_controller.js | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/core_plugins/region_map/public/region_map_controller.js b/src/core_plugins/region_map/public/region_map_controller.js index b7943c30efb88..afa78b4b3ab71 100644 --- a/src/core_plugins/region_map/public/region_map_controller.js +++ b/src/core_plugins/region_map/public/region_map_controller.js @@ -6,7 +6,6 @@ import { KibanaMap } from '../../tile_map/public/kibana_map'; import ChoroplethLayer from './choropleth_layer'; import { truncatedColorMaps } from 'ui/vislib/components/color/truncated_colormaps'; import AggResponsePointSeriesTooltipFormatterProvider from './tooltip_formatter'; -// import '../../tile_map/public/lib/service_settings'; import 'ui/vis/map/service_settings'; @@ -14,10 +13,14 @@ const module = uiModules.get('kibana/region_map', ['kibana']); module.controller('KbnRegionMapController', function ($scope, $element, Private, Notifier, getAppState, serviceSettings, config) { + const DEFAULT_ZOOM_SETTINGS = { + zoom: 2, + mapCenter: [0, 0] + }; + const tooltipFormatter = Private(AggResponsePointSeriesTooltipFormatterProvider); const notify = new Notifier({ location: 'Region map' }); - let kibanaMap = null; let choroplethLayer = null; const kibanaMapReady = makeKibanaMap(); @@ -90,10 +93,19 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private, async function makeKibanaMap() { const tmsSettings = await serviceSettings.getTMSService(); const minMaxZoom = tmsSettings.getMinMaxZoom(false); - kibanaMap = new KibanaMap($element[0], minMaxZoom); - const url = tmsSettings.getUrl(); - const options = tmsSettings.getTMSOptions(); - kibanaMap.setBaseLayer({ baseLayerType: 'tms', options: { url, ...options } }); + + const options = { ...minMaxZoom }; + const uiState = $scope.vis.getUiState(); + const zoomFromUiState = parseInt(uiState.get('mapZoom')); + const centerFromUIState = uiState.get('mapCenter'); + options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : DEFAULT_ZOOM_SETTINGS.zoom; + options.center = centerFromUIState ? centerFromUIState : DEFAULT_ZOOM_SETTINGS.mapCenter; + kibanaMap = new KibanaMap($element[0], options); + + + const tmsUrl = tmsSettings.getUrl(); + const tmsOptions = tmsSettings.getTMSOptions(); + kibanaMap.setBaseLayer({ baseLayerType: 'tms', options: { tmsUrl, ...tmsOptions } }); kibanaMap.addLegendControl(); kibanaMap.addFitControl(); kibanaMap.persistUiStateForVisualization($scope.vis); From 3884d38913890e624110e66c974a3c3781309bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Fri, 28 Jul 2017 14:00:19 +0200 Subject: [PATCH 026/165] [eslint-config-kibana] Add jest plugin and settings (#13090) --- packages/eslint-config-kibana/.eslintrc.js | 2 +- packages/eslint-config-kibana/README.md | 28 ++++++++++++++++++++++ packages/eslint-config-kibana/jest.js | 15 ++++++++++++ packages/eslint-config-kibana/package.json | 3 ++- 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 packages/eslint-config-kibana/jest.js diff --git a/packages/eslint-config-kibana/.eslintrc.js b/packages/eslint-config-kibana/.eslintrc.js index 0da188502cf7f..91f200949342c 100644 --- a/packages/eslint-config-kibana/.eslintrc.js +++ b/packages/eslint-config-kibana/.eslintrc.js @@ -5,7 +5,7 @@ module.exports = { 'mocha', 'babel', 'react', - 'import' + 'import', ], env: { diff --git a/packages/eslint-config-kibana/README.md b/packages/eslint-config-kibana/README.md index 4b20fc999b48a..68c1639b834a5 100644 --- a/packages/eslint-config-kibana/README.md +++ b/packages/eslint-config-kibana/README.md @@ -1,3 +1,31 @@ # eslint-config-kibana The eslint config used by the kibana team + +## Usage + +To use this eslint config, just install the peer dependencies and reference it +in your `.eslintrc`: + +```javascript +{ + extends: [ + '@elastic/eslint-config-kibana' + ] +} +``` + +## Optional jest config + +If the project uses the [jest test runner](https://facebook.github.io/jest/), +the `@elastic/eslint-config-kibana/jest` config can be extended as well to use +`eslint-plugin-jest` and add settings specific to it: + +```javascript +{ + extends: [ + '@elastic/eslint-config-kibana', + '@elastic/eslint-config-kibana/jest' + ] +} +``` diff --git a/packages/eslint-config-kibana/jest.js b/packages/eslint-config-kibana/jest.js new file mode 100644 index 0000000000000..68776bb3db147 --- /dev/null +++ b/packages/eslint-config-kibana/jest.js @@ -0,0 +1,15 @@ +module.exports = { + plugins: [ + 'jest', + ], + + env: { + 'jest/globals': true, + }, + + rules: { + 'jest/no-disabled-tests': 'error', + 'jest/no-focused-tests': 'error', + 'jest/no-identical-title': 'error', + }, +}; diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json index f3bb21dfe7c6d..9c042fe34734f 100644 --- a/packages/eslint-config-kibana/package.json +++ b/packages/eslint-config-kibana/package.json @@ -1,6 +1,6 @@ { "name": "@elastic/eslint-config-kibana", - "version": "0.8.1", + "version": "0.9.0", "description": "The eslint config used by the kibana team", "main": ".eslintrc.js", "scripts": { @@ -22,6 +22,7 @@ "eslint": "^4.1.0", "eslint-plugin-babel": "^4.1.1", "eslint-plugin-import": "^2.6.0", + "eslint-plugin-jest": "^20.0.3", "eslint-plugin-mocha": "^4.9.0", "eslint-plugin-react": "^7.1.0" } From fbd9fd0197595c21a661ff6bca7cfbcf96dade61 Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Fri, 28 Jul 2017 14:35:34 +0200 Subject: [PATCH 027/165] fix metric default color (#12993) --- src/core_plugins/kbn_vislib_vis_types/public/metric.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core_plugins/kbn_vislib_vis_types/public/metric.js b/src/core_plugins/kbn_vislib_vis_types/public/metric.js index c42b34ccbffbf..04d84b8948d0b 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/metric.js +++ b/src/core_plugins/kbn_vislib_vis_types/public/metric.js @@ -48,7 +48,6 @@ export default function MetricVisType(Private) { type: 'simple', style: { fontSize: 60, - bgFill: '#000', bgColor: false, labelColor: false, subText: '' From 1e6ce8513f89e514faee5175ce2671069758c526 Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Fri, 28 Jul 2017 14:41:39 +0200 Subject: [PATCH 028/165] adding docs for goal and gauge (#13140) * adding docs for goal and gauge --- docs/visualize.asciidoc | 3 +++ docs/visualize/goal.asciidoc | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 docs/visualize/goal.asciidoc diff --git a/docs/visualize.asciidoc b/docs/visualize.asciidoc index de4f4d57ec362..40620bc4661e8 100644 --- a/docs/visualize.asciidoc +++ b/docs/visualize.asciidoc @@ -34,6 +34,7 @@ To create a visualization: [horizontal] <>:: Display the raw data of a composed aggregation. <>:: Display a single number. +<>:: Display a gauge. * *Maps* [horizontal] <>:: Associate the results of an aggregation with geographic locations. @@ -143,6 +144,8 @@ include::visualize/markdown.asciidoc[] include::visualize/metric.asciidoc[] +include::visualize/goal.asciidoc[] + include::visualize/pie.asciidoc[] include::visualize/tilemap.asciidoc[] diff --git a/docs/visualize/goal.asciidoc b/docs/visualize/goal.asciidoc new file mode 100644 index 0000000000000..32306411ae8b2 --- /dev/null +++ b/docs/visualize/goal.asciidoc @@ -0,0 +1,36 @@ +[[goal-chart]] +== Goal and Gauge + +A goal visualization displays how your metric progresses toward a fixed goal. A gauge visualization displays in which +predefined range falls your metric. + +include::y-axis-aggs.asciidoc[] + +Open the *Advanced* link to display more customization options: + +*JSON Input*:: A text field where you can add specific JSON-formatted properties to merge with the aggregation +definition, as in the following example: + +[source,shell] +{ "script" : "doc['grade'].value * 1.2" } + +NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you to enable +{ref}/modules-scripting.html[dynamic Groovy scripting]. + +The availability of these options varies depending on the aggregation you choose. + +Click the *Options* tab to change the following options: + +- *Gauge Type* select between arc, circle and metric display type. +- *Percentage Mode* will show all values as percentages +- *Vertical Split* will put the gauges one under another instead of one next to another +- *Show Labels* selects whether you want to show or hide the labels +- *Sub Text* text for the label that appears below the value +- *Auto Extend Range* automatically grows the gauge if value is over its extents. +- *Ranges* you can add custom ranges. Each range will get assigned a color. If value falls within that range it will get +assigned that color. A chart with a single range is called a goal chart. A chart with multiple ranges is called a gauge +chart. +- *Color Options* define how to color your ranges (which color schema to use). Color options are only visible if more than +one range is defined. +- *Style - Show Scale* shows or hides the scale +- *Style - Color Labels* whether the labels should have the same color as the range where the value falls in From 3f54e94c86bf8fe6d109b6c86963c6dea928bde2 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Fri, 28 Jul 2017 08:57:22 -0400 Subject: [PATCH 029/165] Remove try/catch for short url so the appropriate errors will be propagated to the UI (#13004) * Remove try/catch for short url so the appropriate errors will be propagated to the UI * Simply ensure the error is a Boom error by wrapping it, but keep the original error details. * Boom.wrap can't handle non Error instances, as exist in some of the tests. * Only support Error objects, and check both status and statusCode * fix test * Fix test errors for reals this time * Break out status and statusCode short url error tests --- src/server/http/__tests__/short_url_error.js | 54 ++++++++++++++------ src/server/http/short_url_error.js | 8 +-- src/server/http/short_url_lookup.js | 10 ++-- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/src/server/http/__tests__/short_url_error.js b/src/server/http/__tests__/short_url_error.js index 2cb6e34b99fb3..e344107075e19 100644 --- a/src/server/http/__tests__/short_url_error.js +++ b/src/server/http/__tests__/short_url_error.js @@ -2,27 +2,49 @@ import expect from 'expect.js'; import _ from 'lodash'; import { handleShortUrlError } from '../short_url_error'; +function createErrorWithStatus(status) { + const error = new Error(); + error.status = status; + return error; +} + +function createErrorWithStatusCode(statusCode) { + const error = new Error(); + error.statusCode = statusCode; + return error; +} + describe('handleShortUrlError()', () => { - const caughtErrors = [{ - status: 401 - }, { - status: 403 - }, { - status: 404 - }]; - - const uncaughtErrors = [{ - status: null - }, { - status: 500 - }]; - - caughtErrors.forEach((err) => { - it(`should handle ${err.status} errors`, function () { + const caughtErrorsWithStatus = [ + createErrorWithStatus(401), + createErrorWithStatus(403), + createErrorWithStatus(404), + ]; + + const caughtErrorsWithStatusCode = [ + createErrorWithStatusCode(401), + createErrorWithStatusCode(403), + createErrorWithStatusCode(404), + ]; + + const uncaughtErrors = [ + new Error(), + createErrorWithStatus(500), + createErrorWithStatusCode(500) + ]; + + caughtErrorsWithStatus.forEach((err) => { + it(`should handle errors with status of ${err.status}`, function () { expect(_.get(handleShortUrlError(err), 'output.statusCode')).to.be(err.status); }); }); + caughtErrorsWithStatusCode.forEach((err) => { + it(`should handle errors with statusCode of ${err.statusCode}`, function () { + expect(_.get(handleShortUrlError(err), 'output.statusCode')).to.be(err.statusCode); + }); + }); + uncaughtErrors.forEach((err) => { it(`should not handle unknown errors`, function () { expect(_.get(handleShortUrlError(err), 'output.statusCode')).to.be(500); diff --git a/src/server/http/short_url_error.js b/src/server/http/short_url_error.js index 8c617a5fbf5fd..a79eedbe2c0ec 100644 --- a/src/server/http/short_url_error.js +++ b/src/server/http/short_url_error.js @@ -1,9 +1,5 @@ import Boom from 'boom'; -export function handleShortUrlError(err) { - if (err.isBoom) return err; - if (err.status === 401) return Boom.unauthorized(); - if (err.status === 403) return Boom.forbidden(); - if (err.status === 404) return Boom.notFound(); - return Boom.badImplementation(); +export function handleShortUrlError(error) { + return Boom.wrap(error, error.statusCode || error.status || 500); } diff --git a/src/server/http/short_url_lookup.js b/src/server/http/short_url_lookup.js index 60d7cd5b1cc69..5514bd4023b18 100644 --- a/src/server/http/short_url_lookup.js +++ b/src/server/http/short_url_lookup.js @@ -37,14 +37,10 @@ export default function (server) { }, async getUrl(id, req) { - try { - const doc = await req.getSavedObjectsClient().get('url', id); - updateMetadata(doc, req); + const doc = await req.getSavedObjectsClient().get('url', id); + updateMetadata(doc, req); - return doc.attributes.url; - } catch (err) { - return '/'; - } + return doc.attributes.url; } }; } From d14da340329c3ecb3e63da8b63fc40fe93e6c86e Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Fri, 28 Jul 2017 15:17:06 +0200 Subject: [PATCH 030/165] Fix typos and punctuation in WMS settings (#13146) --- src/core_plugins/tile_map/public/editors/tile_map.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core_plugins/tile_map/public/editors/tile_map.html b/src/core_plugins/tile_map/public/editors/tile_map.html index e0a1bb60782bd..20e940107d851 100644 --- a/src/core_plugins/tile_map/public/editors/tile_map.html +++ b/src/core_plugins/tile_map/public/editors/tile_map.html @@ -129,7 +129,7 @@

WMS is an OGC standard for map image services. For more information, go here.

Date: Fri, 28 Jul 2017 10:45:43 -0400 Subject: [PATCH 031/165] Ensure conflicted fields can be searchable and/or aggregatable (#13070) * Ensure that conflict fields can be searchable and/or aggregatable in the UI * Use `some` instead of `reduce` * Revert UI changes * Attempt to convert multiple ES types to kibana types, and if they all resolve to the same kibana type, there is no conflict * Add comma back * Cleaner code * Add tests * Update failing test to handle searchable and aggregatable properly * Add functional test to ensure similar ES types are properly merged * Update tests * Revert shard size --- .../__tests__/field_caps_response.js | 30 +++++- .../fixtures/es_field_caps_response.json | 92 ++++++++++++++++++ .../field_capabilities/field_caps_response.js | 29 ++++-- .../fields_for_wildcard_route/conflicts.js | 18 +++- .../index_patterns/conflicts/data.json.gz | Bin 156 -> 264 bytes .../index_patterns/conflicts/mappings.json | 22 ++++- 6 files changed, 174 insertions(+), 17 deletions(-) diff --git a/src/server/index_patterns/service/lib/field_capabilities/__tests__/field_caps_response.js b/src/server/index_patterns/service/lib/field_capabilities/__tests__/field_caps_response.js index 2a43ca2b55a39..c0db141bb1dca 100644 --- a/src/server/index_patterns/service/lib/field_capabilities/__tests__/field_caps_response.js +++ b/src/server/index_patterns/service/lib/field_capabilities/__tests__/field_caps_response.js @@ -19,7 +19,7 @@ describe('index_patterns/field_capabilities/field_caps_response', () => { describe('conflicts', () => { it('returns a field for each in response, no filtering', () => { const fields = readFieldCapsResponse(esResponse); - expect(fields).to.have.length(13); + expect(fields).to.have.length(19); }); it('includes only name, type, searchable, aggregatable, readFromDocValues, and maybe conflictDescriptions of each field', () => { @@ -65,8 +65,8 @@ describe('index_patterns/field_capabilities/field_caps_response', () => { { name: 'success', type: 'conflict', - searchable: false, - aggregatable: false, + searchable: true, + aggregatable: true, readFromDocValues: false, conflictDescriptions: { boolean: [ @@ -79,6 +79,30 @@ describe('index_patterns/field_capabilities/field_caps_response', () => { } ]); }); + + it('does not return conflicted fields if the types are resolvable to the same kibana type', () => { + const fields = readFieldCapsResponse(esResponse); + const resolvableToString = fields.find(f => f.name === 'resolvable_to_string'); + const resolvableToNumber = fields.find(f => f.name === 'resolvable_to_number'); + expect(resolvableToString.type).to.be('string'); + expect(resolvableToNumber.type).to.be('number'); + }); + + it('returns aggregatable if at least one field is aggregatable', () => { + const fields = readFieldCapsResponse(esResponse); + const mixAggregatable = fields.find(f => f.name === 'mix_aggregatable'); + const mixAggregatableOther = fields.find(f => f.name === 'mix_aggregatable_other'); + expect(mixAggregatable.aggregatable).to.be(true); + expect(mixAggregatableOther.aggregatable).to.be(true); + }); + + it('returns searchable if at least one field is searchable', () => { + const fields = readFieldCapsResponse(esResponse); + const mixSearchable = fields.find(f => f.name === 'mix_searchable'); + const mixSearchableOther = fields.find(f => f.name === 'mix_searchable_other'); + expect(mixSearchable.searchable).to.be(true); + expect(mixSearchableOther.searchable).to.be(true); + }); }); }); }); diff --git a/src/server/index_patterns/service/lib/field_capabilities/__tests__/fixtures/es_field_caps_response.json b/src/server/index_patterns/service/lib/field_capabilities/__tests__/fixtures/es_field_caps_response.json index 659489c7361c5..d6fc2963f504e 100644 --- a/src/server/index_patterns/service/lib/field_capabilities/__tests__/fixtures/es_field_caps_response.json +++ b/src/server/index_patterns/service/lib/field_capabilities/__tests__/fixtures/es_field_caps_response.json @@ -101,6 +101,98 @@ "searchable": false, "aggregatable": true } + }, + "resolvable_to_string": { + "text": { + "type": "text", + "searchable": true, + "aggregatable": true, + "indices": [ + "index1" + ] + }, + "keyword": { + "type": "keyword", + "searchable": true, + "aggregatable": true, + "indices": [ + "index2" + ] + } + }, + "resolvable_to_number": { + "integer": { + "type": "integer", + "searchable": true, + "aggregatable": true, + "indices": [ + "index1" + ] + }, + "long": { + "type": "long", + "searchable": true, + "aggregatable": true, + "indices": [ + "index2" + ] + } + }, + "mix_searchable": { + "text": { + "type": "text", + "searchable": false, + "aggregatable": true, + "indices": [ + "index1" + ] + }, + "keyword": { + "type": "keyword", + "searchable": true, + "aggregatable": true, + "indices": [ + "index2" + ] + } + }, + "mix_aggregatable": { + "text": { + "type": "text", + "searchable": true, + "aggregatable": false, + "indices": [ + "index1" + ] + }, + "keyword": { + "type": "keyword", + "searchable": true, + "aggregatable": true, + "indices": [ + "index2" + ] + } + }, + "mix_searchable_other": { + "int": { + "type": "integer", + "searchable": false, + "aggregatable": false, + "non_searchable_indices": [ + "index1" + ] + } + }, + "mix_aggregatable_other": { + "int": { + "type": "integer", + "searchable": false, + "aggregatable": false, + "non_aggregatable_indices": [ + "index1" + ] + } } } } diff --git a/src/server/index_patterns/service/lib/field_capabilities/field_caps_response.js b/src/server/index_patterns/service/lib/field_capabilities/field_caps_response.js index 94e8b6395804c..8f50f4b454514 100644 --- a/src/server/index_patterns/service/lib/field_capabilities/field_caps_response.js +++ b/src/server/index_patterns/service/lib/field_capabilities/field_caps_response.js @@ -1,3 +1,4 @@ +import { uniq } from 'lodash'; import { castEsToKbnFieldTypeName } from '../../../../../utils'; import { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values'; @@ -63,12 +64,27 @@ export function readFieldCapsResponse(fieldCapsResponse) { const capsByType = capsByNameThenType[fieldName]; const types = Object.keys(capsByType); - if (types.length > 1) { + // If a single type is marked as searchable or aggregatable, all the types are searchable or aggregatable + const isSearchable = types.some(type => { + return !!capsByType[type].searchable || + (!!capsByType[type].non_searchable_indices && capsByType[type].non_searchable_indices.length > 0); + }); + + const isAggregatable = types.some(type => { + return !!capsByType[type].aggregatable || + (!!capsByType[type].non_aggregatable_indices && capsByType[type].non_aggregatable_indices.length > 0); + }); + + + // If there are multiple types but they all resolve to the same kibana type + // ignore the conflict and carry on (my wayward son) + const uniqueKibanaTypes = uniq(types.map(castEsToKbnFieldTypeName)); + if (uniqueKibanaTypes.length > 1) { return { name: fieldName, type: 'conflict', - searchable: false, - aggregatable: false, + searchable: isSearchable, + aggregatable: isAggregatable, readFromDocValues: false, conflictDescriptions: types.reduce((acc, esType) => ({ ...acc, @@ -78,13 +94,12 @@ export function readFieldCapsResponse(fieldCapsResponse) { } const esType = types[0]; - const caps = capsByType[esType]; return { name: fieldName, type: castEsToKbnFieldTypeName(esType), - searchable: caps.searchable, - aggregatable: caps.aggregatable, - readFromDocValues: shouldReadFieldFromDocValues(caps.aggregatable, esType), + searchable: isSearchable, + aggregatable: isAggregatable, + readFromDocValues: shouldReadFieldFromDocValues(isAggregatable, esType), }; }); } diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js index e477f59b96011..0c2aab44d0988 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js @@ -23,11 +23,25 @@ export default function ({ getService }) { searchable: true, readFromDocValues: true, }, + { + name: 'number_conflict', + type: 'number', + aggregatable: true, + searchable: true, + readFromDocValues: true, + }, + { + name: 'string_conflict', + type: 'string', + aggregatable: true, + searchable: true, + readFromDocValues: false, + }, { name: 'success', type: 'conflict', - aggregatable: false, - searchable: false, + aggregatable: true, + searchable: true, readFromDocValues: false, conflictDescriptions: { boolean: [ diff --git a/test/api_integration/fixtures/es_archiver/index_patterns/conflicts/data.json.gz b/test/api_integration/fixtures/es_archiver/index_patterns/conflicts/data.json.gz index aa3c439e6834beebd9c71752655c3d0b91dbab1b..cf767f8331ef4ecb8a02840bd630843be3af0551 100644 GIT binary patch literal 264 zcmV+j0r&nNiwFP!000026TOqoio!4yh4+1mlC>>K863uy=sbXq;$k*Zlc<3qd|1OdgK4N(W(r6IuB14>v?v*2Bv8bmBr`X)xFj*R0HhFP zsIGw_5QP{RSbxLEaWTY1uwX402-k9PRa4*rBU*UC2)_qPib_+FeE Date: Fri, 28 Jul 2017 18:03:34 +0200 Subject: [PATCH 032/165] Use version 0.9.0 of eslint-config-kibana (#13177) --- .eslintrc | 6 +++-- package.json | 2 +- .../__tests__/helpers/parse_settings.js | 7 ----- .../public/__tests__/_table_vis_controller.js | 26 ------------------- .../series_functions/__tests__/condition.js | 6 ++--- .../mappings/lib/__tests__/get_property.js | 2 +- .../state_hashing/__tests__/hash_url.js | 5 ---- .../state_hashing/__tests__/unhash_url.js | 5 ---- .../utils/lodash-mixins/__tests__/_move.js | 2 +- src/ui/public/vis/__tests__/_agg_config.js | 2 +- src/ui/public/vislib/__tests__/lib/data.js | 4 +-- .../api_integration/apis/scripts/languages.js | 1 + .../functional/apps/discover/_shared_links.js | 2 +- ui_framework/.eslintrc | 13 ---------- 14 files changed, 15 insertions(+), 68 deletions(-) delete mode 100644 ui_framework/.eslintrc diff --git a/.eslintrc b/.eslintrc index 86918b9d925b8..334f46159f232 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,8 +1,10 @@ --- -extends: '@elastic/kibana' +extends: + - '@elastic/eslint-config-kibana' + - '@elastic/eslint-config-kibana/jest' settings: import/resolver: '@elastic/eslint-import-resolver-kibana': rootPackageName: 'kibana' - kibanaPath: . \ No newline at end of file + kibanaPath: . diff --git a/package.json b/package.json index d78858fc48777..8207cc99ee2a0 100644 --- a/package.json +++ b/package.json @@ -203,7 +203,7 @@ "yauzl": "2.7.0" }, "devDependencies": { - "@elastic/eslint-config-kibana": "0.8.1", + "@elastic/eslint-config-kibana": "0.9.0", "@elastic/eslint-import-resolver-kibana": "0.8.1", "@elastic/eslint-plugin-kibana-custom": "1.0.3", "angular-mocks": "1.4.7", diff --git a/src/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/parse_settings.js b/src/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/parse_settings.js index ce62a61a9e063..c81adee08ca8d 100644 --- a/src/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/parse_settings.js +++ b/src/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/parse_settings.js @@ -16,13 +16,6 @@ describe('parseSettings', () => { }); }); - it('returns the true for "true"', () => { - const settings = 'pad=true'; - expect(parseSettings(settings)).to.eql({ - pad: true, - }); - }); - it('returns the true for 1', () => { const settings = 'pad=1'; expect(parseSettings(settings)).to.eql({ diff --git a/src/core_plugins/table_vis/public/__tests__/_table_vis_controller.js b/src/core_plugins/table_vis/public/__tests__/_table_vis_controller.js index 6f458fa3aa413..4500b8d6f21dd 100644 --- a/src/core_plugins/table_vis/public/__tests__/_table_vis_controller.js +++ b/src/core_plugins/table_vis/public/__tests__/_table_vis_controller.js @@ -160,30 +160,4 @@ describe('Controller', function () { expect(spiedTabify).to.have.property('callCount', 1); expect(spiedTabify.firstCall.args[2]).to.have.property('partialRows', false); }); - - it('passes partialRows:true to tabify based on the vis params', function () { - // spy on the tabify private module - const spiedTabify = sinon.spy(Private(AggResponseTabifyProvider)); - Private.stub(AggResponseTabifyProvider, spiedTabify); - - const vis = new OneRangeVis({ showPartialRows: true }); - initController(vis); - attachEsResponseToScope(fixtures.oneRangeBucket); - - expect(spiedTabify).to.have.property('callCount', 1); - expect(spiedTabify.firstCall.args[2]).to.have.property('partialRows', true); - }); - - it('passes partialRows:false to tabify based on the vis params', function () { - // spy on the tabify private module - const spiedTabify = sinon.spy(Private(AggResponseTabifyProvider)); - Private.stub(AggResponseTabifyProvider, spiedTabify); - - const vis = new OneRangeVis({ showPartialRows: false }); - initController(vis); - attachEsResponseToScope(fixtures.oneRangeBucket); - - expect(spiedTabify).to.have.property('callCount', 1); - expect(spiedTabify.firstCall.args[2]).to.have.property('partialRows', false); - }); }); diff --git a/src/core_plugins/timelion/server/series_functions/__tests__/condition.js b/src/core_plugins/timelion/server/series_functions/__tests__/condition.js index d1ffead1aaab6..96236853c2706 100644 --- a/src/core_plugins/timelion/server/series_functions/__tests__/condition.js +++ b/src/core_plugins/timelion/server/series_functions/__tests__/condition.js @@ -39,19 +39,19 @@ describe(filename, function () { }); }); - it('eq', function () { + it('gt', function () { return invoke(fn, [seriesList, 'gt', 17, 0]).then(function (r) { expect(_.map(r.output.list[0].data, 1)).to.eql([-51, 17, 0, 0]); }); }); - it('eq', function () { + it('lt', function () { return invoke(fn, [seriesList, 'lt', 17, 0]).then(function (r) { expect(_.map(r.output.list[0].data, 1)).to.eql([0, 17, 82, 20]); }); }); - it('eq', function () { + it('lte', function () { return invoke(fn, [seriesList, 'lte', 17, 0]).then(function (r) { expect(_.map(r.output.list[0].data, 1)).to.eql([0, 0, 82, 20]); }); diff --git a/src/server/mappings/lib/__tests__/get_property.js b/src/server/mappings/lib/__tests__/get_property.js index d4d3067f00b36..905a7e332ab0a 100644 --- a/src/server/mappings/lib/__tests__/get_property.js +++ b/src/server/mappings/lib/__tests__/get_property.js @@ -52,7 +52,7 @@ describe('getProperty(mappings, path)', () => { test('bar.baz.box', MAPPINGS.rootType.properties.bar.properties.baz.fields.box); }); }); - describe('string key', () => { + describe('array of string keys', () => { it('finds root properties', () => { test(['foo'], MAPPINGS.rootType.properties.foo); }); diff --git a/src/ui/public/state_management/state_hashing/__tests__/hash_url.js b/src/ui/public/state_management/state_hashing/__tests__/hash_url.js index debae21077d2f..4909d007218ed 100644 --- a/src/ui/public/state_management/state_hashing/__tests__/hash_url.js +++ b/src/ui/public/state_management/state_hashing/__tests__/hash_url.js @@ -75,11 +75,6 @@ describe('hashUrl', function () { expect(hashUrl(states, url)).to.be(url); }); - it('if empty hash without query', () => { - const url = 'https://localhost:5601/app/kibana#'; - expect(hashUrl(states, url)).to.be(url); - }); - it('if hash is just a path', () => { const url = 'https://localhost:5601/app/kibana#/discover'; expect(hashUrl(states, url)).to.be(url); diff --git a/src/ui/public/state_management/state_hashing/__tests__/unhash_url.js b/src/ui/public/state_management/state_hashing/__tests__/unhash_url.js index 56cc2444fa9cd..6bbd9da4f37a5 100644 --- a/src/ui/public/state_management/state_hashing/__tests__/unhash_url.js +++ b/src/ui/public/state_management/state_hashing/__tests__/unhash_url.js @@ -49,11 +49,6 @@ describe('unhashUrl', () => { expect(unhashUrl(url, unhashableStates)).to.be(url); }); - it('if empty hash without query', () => { - const url = 'https://localhost:5601/app/kibana#'; - expect(unhashUrl(url, unhashableStates)).to.be(url); - }); - it('if hash is just a path', () => { const url = 'https://localhost:5601/app/kibana#/discover'; expect(unhashUrl(url, unhashableStates)).to.be(url); diff --git a/src/ui/public/utils/lodash-mixins/__tests__/_move.js b/src/ui/public/utils/lodash-mixins/__tests__/_move.js index f80dc56ee5862..d9dc9650cf5a4 100644 --- a/src/ui/public/utils/lodash-mixins/__tests__/_move.js +++ b/src/ui/public/utils/lodash-mixins/__tests__/_move.js @@ -109,7 +109,7 @@ describe('_.move', function () { }); - it('moves an object up based on a where callback', function () { + it('moves an object down based on a where callback', function () { const list = [ { v: 1 }, { v: 1 }, diff --git a/src/ui/public/vis/__tests__/_agg_config.js b/src/ui/public/vis/__tests__/_agg_config.js index f0a21d8d952ca..123ed914368dc 100644 --- a/src/ui/public/vis/__tests__/_agg_config.js +++ b/src/ui/public/vis/__tests__/_agg_config.js @@ -128,7 +128,7 @@ describe('AggConfig', function () { expect(objs[3]).to.have.property('id', '4'); }); - it('assigns ids relative to the other items in the list', function () { + it('assigns ids relative to the other only item in the list', function () { const objs = [ { id: '100' }, {}, diff --git a/src/ui/public/vislib/__tests__/lib/data.js b/src/ui/public/vislib/__tests__/lib/data.js index 45421b21edcac..d910b5e908d9d 100644 --- a/src/ui/public/vislib/__tests__/lib/data.js +++ b/src/ui/public/vislib/__tests__/lib/data.js @@ -155,8 +155,8 @@ describe('Vislib Data Class Test Suite', function () { }); it('should return all points from every series', testLength(seriesData)); - it('should return all points from every series', testLength(rowsData)); - it('should return all points from every series', testLength(colsData)); + it('should return all points from every series in the rows', testLength(rowsData)); + it('should return all points from every series in the columns', testLength(colsData)); function testLength(inputData) { return function () { diff --git a/test/api_integration/apis/scripts/languages.js b/test/api_integration/apis/scripts/languages.js index 27fa543544099..ae2707df2fc63 100644 --- a/test/api_integration/apis/scripts/languages.js +++ b/test/api_integration/apis/scripts/languages.js @@ -12,6 +12,7 @@ export default function ({ getService }) { }) )); + // eslint-disable-next-line jest/no-disabled-tests it.skip('should only return langs enabled for inline scripting', () => ( supertest.get('/api/kibana/scripts/languages') .expect(200) diff --git a/test/functional/apps/discover/_shared_links.js b/test/functional/apps/discover/_shared_links.js index 4ac2c4d21ba9d..4ff1f1698c04a 100644 --- a/test/functional/apps/discover/_shared_links.js +++ b/test/functional/apps/discover/_shared_links.js @@ -115,7 +115,7 @@ export default function ({ getService, getPageObjects }) { }); // NOTE: This test has to run immediately after the test above - it('should show toast message for copy to clipboard', function () { + it('should show toast message for copy to clipboard of short URL', function () { return PageObjects.discover.clickCopyToClipboard() .then(function () { return PageObjects.header.getToastMessage(); diff --git a/ui_framework/.eslintrc b/ui_framework/.eslintrc deleted file mode 100644 index e20f525141316..0000000000000 --- a/ui_framework/.eslintrc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "plugins": [ - "jest" - ], - "rules": { - "jest/no-disabled-tests": "error", - "jest/no-focused-tests": "error", - "jest/no-identical-title": "error" - }, - "env": { - "jest/globals": true - } -} From 6748b22d03e7d766eded58be71df45babd405524 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 28 Jul 2017 09:47:41 -0700 Subject: [PATCH 033/165] Implement esTestCluster test util (#13099) * [es/tests] remove unused module * [testUtil/es] add utility for starting es nodes in tests * [ftr/tests] use esTestCluster util to start es * [es/tests/routes] use esTestCluster to start own es * [testUtils/kbnServer] disable uiSettings unless plugins are enabled * [testUtils/esTestCluster] use standard test es port by default * [server/http/tests] add esTestCluster to setup * [test/config] unify es test config into a single module * [testUtils/esTestCluster] directory is no longer configurable * [testUtils/esTestCluster] throw when es.start() is called again without es.stop() * [testUtils/esTestCluster] is* checks should not mutate state --- package.json | 1 - .../lib/__tests__/ensure_es_version.js | 5 +- .../elasticsearch/lib/__tests__/find_port.js | 13 --- .../lib/__tests__/health_check.js | 7 +- .../elasticsearch/lib/__tests__/routes.js | 16 +-- .../tests_bundle/tests_entry_template.js | 14 ++- .../__tests__/integration/with_es_archiver.js | 26 +++-- .../__tests__/lib/es.js | 43 -------- .../__tests__/lib/index.js | 1 - src/server/http/__tests__/index.js | 23 ++-- src/test_utils/es/es_test_cluster.js | 103 ++++++++++++++++++ src/test_utils/es/es_test_config.js | 45 ++++++++ src/test_utils/es/index.js | 2 + src/test_utils/kbn_server.js | 14 ++- tasks/config/esvm.js | 44 ++------ tasks/config/run.js | 13 +-- tasks/test.js | 2 - test/common/config.js | 4 +- test/es_test_server_url_parts.js | 10 -- test/kibana_test_server_url_parts.js | 8 +- test/shield.js | 6 +- 21 files changed, 235 insertions(+), 165 deletions(-) delete mode 100644 src/core_plugins/elasticsearch/lib/__tests__/find_port.js delete mode 100644 src/functional_test_runner/__tests__/lib/es.js create mode 100644 src/test_utils/es/es_test_cluster.js create mode 100644 src/test_utils/es/es_test_config.js create mode 100644 src/test_utils/es/index.js delete mode 100644 test/es_test_server_url_parts.js diff --git a/package.json b/package.json index 8207cc99ee2a0..cd9aab51392bb 100644 --- a/package.json +++ b/package.json @@ -266,7 +266,6 @@ "ncp": "2.0.0", "nock": "8.0.0", "node-sass": "3.8.0", - "portscanner": "1.0.0", "proxyquire": "1.7.10", "sass-loader": "4.0.0", "simple-git": "1.37.0", diff --git a/src/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js b/src/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js index e626bfc6feb93..b6828c3562261 100644 --- a/src/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js +++ b/src/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js @@ -2,9 +2,8 @@ import _ from 'lodash'; import Promise from 'bluebird'; import sinon from 'sinon'; import expect from 'expect.js'; -import url from 'url'; -import { esTestServerUrlParts } from '../../../../../test/es_test_server_url_parts'; +import { esTestConfig } from '../../../../test_utils/es'; import { ensureEsVersion } from '../ensure_es_version'; describe('plugins/elasticsearch', () => { @@ -22,7 +21,7 @@ describe('plugins/elasticsearch', () => { status: { red: sinon.stub() }, - url: url.format(esTestServerUrlParts) + url: esTestConfig.getUrl() } } }; diff --git a/src/core_plugins/elasticsearch/lib/__tests__/find_port.js b/src/core_plugins/elasticsearch/lib/__tests__/find_port.js deleted file mode 100644 index 2ef8ce083461d..0000000000000 --- a/src/core_plugins/elasticsearch/lib/__tests__/find_port.js +++ /dev/null @@ -1,13 +0,0 @@ -import Promise from 'bluebird'; -import portscanner from 'portscanner'; - -export default function findPort(start, end, host) { - host = host || 'localhost'; - return new Promise(function (resolve, reject) { - portscanner.findAPortNotInUse(start, end, host, function (err, port) { - if (err) return reject(err); - resolve(port); - }); - }); -} - diff --git a/src/core_plugins/elasticsearch/lib/__tests__/health_check.js b/src/core_plugins/elasticsearch/lib/__tests__/health_check.js index e77d730800cfc..6e315c08e5069 100644 --- a/src/core_plugins/elasticsearch/lib/__tests__/health_check.js +++ b/src/core_plugins/elasticsearch/lib/__tests__/health_check.js @@ -1,19 +1,18 @@ import Promise from 'bluebird'; import sinon from 'sinon'; import expect from 'expect.js'; -import url from 'url'; const NoConnections = require('elasticsearch').errors.NoConnections; import mappings from './fixtures/mappings'; import healthCheck from '../health_check'; import kibanaVersion from '../kibana_version'; -import { esTestServerUrlParts } from '../../../../../test/es_test_server_url_parts'; +import { esTestConfig } from '../../../../test_utils/es'; import * as patchKibanaIndexNS from '../patch_kibana_index'; import * as migrateConfigNS from '../migrate_config'; -const esPort = esTestServerUrlParts.port; -const esUrl = url.format(esTestServerUrlParts); +const esPort = esTestConfig.getPort(); +const esUrl = esTestConfig.getUrl(); describe('plugins/elasticsearch', () => { describe('lib/health_check', function () { diff --git a/src/core_plugins/elasticsearch/lib/__tests__/routes.js b/src/core_plugins/elasticsearch/lib/__tests__/routes.js index 299388388faa6..73b60561eae01 100644 --- a/src/core_plugins/elasticsearch/lib/__tests__/routes.js +++ b/src/core_plugins/elasticsearch/lib/__tests__/routes.js @@ -1,25 +1,27 @@ import { format } from 'util'; import * as kbnTestServer from '../../../../test_utils/kbn_server'; +import { esTestCluster } from '../../../../test_utils/es'; describe('plugins/elasticsearch', function () { describe('routes', function () { let kbnServer; + const es = esTestCluster.use({ + name: 'core_plugins/es/routes', + }); before(async function () { - // Sometimes waiting for server takes longer than 10s. - // NOTE: This can't be a fat-arrow function because `this` needs to refer to the execution - // context, not to the parent context. - this.timeout(60000); + this.timeout(es.getStartTimeout()); + await es.start(); kbnServer = kbnTestServer.createServerWithCorePlugins(); - await kbnServer.ready(); await kbnServer.server.plugins.elasticsearch.waitUntilReady(); }); - after(function () { - return kbnServer.close(); + after(async function () { + await kbnServer.close(); + await es.stop(); }); function testRoute(options, statusCode = 200) { diff --git a/src/core_plugins/tests_bundle/tests_entry_template.js b/src/core_plugins/tests_bundle/tests_entry_template.js index 75d34be19c7d9..dfe1157c071fe 100644 --- a/src/core_plugins/tests_bundle/tests_entry_template.js +++ b/src/core_plugins/tests_bundle/tests_entry_template.js @@ -1,3 +1,5 @@ +import { esTestConfig } from '../../test_utils/es'; + export default function ({ env, bundle }) { const pluginSlug = env.pluginInfo.sort() @@ -26,22 +28,22 @@ window.__KBN__ = { vars: { kbnIndex: '.kibana', esShardTimeout: 1500, - esApiVersion: 'master', + esApiVersion: ${JSON.stringify(esTestConfig.getBranch())}, esRequestTimeout: '300000', tilemapsConfig: { deprecated: { isOverridden: false, - config: { - options: { + config: { + options: { } - } - } + } + } }, regionmapsConfig: { layers: [] }, mapConfig: { - manifestServiceUrl: 'https://geo.elastic.co/v1/manifest' + manifestServiceUrl: 'https://geo.elastic.co/v1/manifest' } }, uiSettings: { diff --git a/src/functional_test_runner/__tests__/integration/with_es_archiver.js b/src/functional_test_runner/__tests__/integration/with_es_archiver.js index bd2fd4882aa74..5bfd1a9383832 100644 --- a/src/functional_test_runner/__tests__/integration/with_es_archiver.js +++ b/src/functional_test_runner/__tests__/integration/with_es_archiver.js @@ -4,18 +4,17 @@ import { format as formatUrl } from 'url'; import { readConfigFile } from '../../lib'; import { createToolingLog, createReduceStream } from '../../../utils'; -import { startupEs, startupKibana } from '../lib'; +import { esTestCluster } from '../../../test_utils/es'; +import { startupKibana } from '../lib'; const SCRIPT = resolve(__dirname, '../../../../scripts/functional_test_runner.js'); const CONFIG = resolve(__dirname, '../fixtures/with_es_archiver/config.js'); -describe('single test that uses esArchiver', function () { - this.timeout(3 * 60 * 1000); - +describe('single test that uses esArchiver', () => { let log; const cleanupWork = []; - before(async () => { + before(async function () { log = createToolingLog('debug'); log.pipe(process.stdout); log.indent(6); @@ -24,11 +23,17 @@ describe('single test that uses esArchiver', function () { log.info('starting elasticsearch'); log.indent(2); - const es = await startupEs({ - log, - port: config.get('servers.elasticsearch.port'), - fresh: false + + const es = esTestCluster.use({ + log: msg => log.debug(msg), + name: 'ftr/withEsArchiver', + port: config.get('servers.elasticsearch.port') }); + cleanupWork.unshift(() => es.stop()); + + this.timeout(es.getStartTimeout()); + await es.start(); + log.indent(-2); log.info('starting kibana'); @@ -39,8 +44,7 @@ describe('single test that uses esArchiver', function () { }); log.indent(-2); - cleanupWork.push(() => kibana.close()); - cleanupWork.push(() => es.shutdown()); + cleanupWork.unshift(() => kibana.close()); }); it('test', async () => { diff --git a/src/functional_test_runner/__tests__/lib/es.js b/src/functional_test_runner/__tests__/lib/es.js deleted file mode 100644 index 1dc7fbc6fec37..0000000000000 --- a/src/functional_test_runner/__tests__/lib/es.js +++ /dev/null @@ -1,43 +0,0 @@ -import { resolve } from 'path'; - -import { once, merge } from 'lodash'; -import libesvm from 'libesvm'; - -const VERSION = 'master'; -const DIRECTORY = resolve(__dirname, '../../../../esvm/functional_test_runner_tests'); - -const createCluster = (options = {}) => { - return libesvm.createCluster(merge({ - directory: DIRECTORY, - branch: VERSION, - }, options)); -}; - -const install = once(async (fresh) => { - await createCluster({ fresh }).install(); -}); - -export async function startupEs(opts) { - const { - port, - log, - fresh = true - } = opts; - - await install({ fresh }); - const cluster = createCluster({ - config: { - http: { - port - } - } - }); - - cluster.on('log', (event) => { - const method = event.level.toLowerCase() === 'info' ? 'verbose' : 'debug'; - log[method](`${event.level}: ${event.type} - ${event.message}`); - }); - - await cluster.start(); - return cluster; -} diff --git a/src/functional_test_runner/__tests__/lib/index.js b/src/functional_test_runner/__tests__/lib/index.js index eae9e26514d62..e1a31f96923b2 100644 --- a/src/functional_test_runner/__tests__/lib/index.js +++ b/src/functional_test_runner/__tests__/lib/index.js @@ -1,2 +1 @@ -export { startupEs } from './es'; export { startupKibana } from './kibana'; diff --git a/src/server/http/__tests__/index.js b/src/server/http/__tests__/index.js index 89914c9ff60ed..e51d2e8634194 100644 --- a/src/server/http/__tests__/index.js +++ b/src/server/http/__tests__/index.js @@ -1,17 +1,24 @@ import expect from 'expect.js'; import * as kbnTestServer from '../../../test_utils/kbn_server'; +import { esTestCluster } from '../../../test_utils/es'; -describe('routes', function () { - this.slow(10000); - this.timeout(60000); - +describe('routes', () => { let kbnServer; - beforeEach(function () { + const es = esTestCluster.use({ + name: 'server/http', + }); + + before(async function () { + this.timeout(es.getStartTimeout()); + await es.start(); kbnServer = kbnTestServer.createServerWithCorePlugins(); - return kbnServer.ready(); + await kbnServer.ready(); + await kbnServer.server.plugins.elasticsearch.waitUntilReady(); }); - afterEach(function () { - return kbnServer.close(); + + after(async () => { + await kbnServer.close(); + await es.stop(); }); describe('cookie validation', function () { diff --git a/src/test_utils/es/es_test_cluster.js b/src/test_utils/es/es_test_cluster.js new file mode 100644 index 0000000000000..9e96554a12e83 --- /dev/null +++ b/src/test_utils/es/es_test_cluster.js @@ -0,0 +1,103 @@ +import { resolve } from 'path'; +import { esTestConfig } from './es_test_config'; + +import libesvm from 'libesvm'; + +const ESVM_DIR = resolve(__dirname, '../../../esvm/test_utils/es_test_cluster'); + +export class EsTestCluster { + _branchesDownloaded = []; + + use(options = {}) { + const { + name, + log = console.log, + port = esTestConfig.getPort(), + branch = esTestConfig.getBranch(), + } = options; + + if (!name) { + throw new Error('esTestCluster.use() requires { name }'); + } + + // assigned in use.start(), reassigned in use.stop() + let cluster; + + return { + getStartTimeout: () => { + return esTestConfig.getLibesvmStartTimeout(); + }, + + start: async () => { + const download = this._isDownloadNeeded(branch); + + if (cluster) { + throw new Error(` + EsTestCluster[${name}] is already started, call and await es.stop() + before calling es.start() again. + `); + } + + cluster = libesvm.createCluster({ + fresh: download, + purge: !download, + directory: ESVM_DIR, + branch, + config: { + http: { + port, + }, + cluster: { + name, + }, + discovery: { + zen: { + ping: { + unicast: { + hosts: [ `localhost:${port}` ] + } + } + } + } + } + }); + + cluster.on('log', (event) => { + log(`EsTestCluster[${name}]: ${event.type} - ${event.message}`); + }); + + await cluster.install(); + + if (download) { + // track the branches that have successfully downloaded + // after cluster.install() resolves + this._branchesDownloaded.push(branch); + } + + await cluster.start(); + }, + + stop: async () => { + if (cluster) { + const c = cluster; + cluster = null; + await c.shutdown(); + } + } + }; + } + + _isDownloadNeeded(branch) { + if (process.env.ESVM_NO_FRESH || process.argv.includes('--esvm-no-fresh')) { + return false; + } + + if (this._branchesDownloaded.includes(branch)) { + return false; + } + + return true; + } +} + +export const esTestCluster = new EsTestCluster(); diff --git a/src/test_utils/es/es_test_config.js b/src/test_utils/es/es_test_config.js new file mode 100644 index 0000000000000..0240e61558c07 --- /dev/null +++ b/src/test_utils/es/es_test_config.js @@ -0,0 +1,45 @@ +import { format as formatUrl } from 'url'; +import { resolve } from 'path'; + +import pkg from '../../../package.json'; +import { admin } from '../../../test/shield'; + +const SECOND = 1000; +const MINUTE = 60 * SECOND; + +export const esTestConfig = new class EsTestConfig { + getLibesvmStartTimeout() { + return process.env.TEST_ES_STARTUP_TIMEOUT || (5 * MINUTE); + } + + getDirectoryForEsvm(uniqueSubDir) { + if (!uniqueSubDir) { + throw new Error('getDirectoryForEsvm() requires uniqueSubDir'); + } + + return resolve(__dirname, '../esvm', uniqueSubDir); + } + + getBranch() { + return process.env.TEST_ES_BRANCH || pkg.branch; + } + + getPort() { + return this.getUrlParts().port; + } + + getUrl() { + return formatUrl(this.getUrlParts()); + } + + getUrlParts() { + return { + protocol: process.env.TEST_ES_PROTOCOL || 'http', + hostname: process.env.TEST_ES_HOSTNAME || 'localhost', + port: parseInt(process.env.TEST_ES_PORT, 10) || 9220, + auth: admin.username + ':' + admin.password, + username: admin.username, + password: admin.password, + }; + } +}; diff --git a/src/test_utils/es/index.js b/src/test_utils/es/index.js new file mode 100644 index 0000000000000..7230b751960c6 --- /dev/null +++ b/src/test_utils/es/index.js @@ -0,0 +1,2 @@ +export { esTestCluster } from './es_test_cluster'; +export { esTestConfig } from './es_test_config'; diff --git a/src/test_utils/kbn_server.js b/src/test_utils/kbn_server.js index b33b5facf94e8..88b944dc2a781 100644 --- a/src/test_utils/kbn_server.js +++ b/src/test_utils/kbn_server.js @@ -1,9 +1,8 @@ -import url from 'url'; import { resolve } from 'path'; import { defaultsDeep, set } from 'lodash'; import { header as basicAuthHeader } from './base_auth'; import { kibanaUser, kibanaServer } from '../../test/shield'; -import { esTestServerUrlParts } from '../../test/es_test_server_url_parts'; +import { esTestConfig } from '../test_utils/es'; import KbnServer from '../../src/server/kbn_server'; const DEFAULTS_SETTINGS = { @@ -17,6 +16,9 @@ const DEFAULTS_SETTINGS = { quiet: true }, plugins: {}, + uiSettings: { + enabled: false + }, optimize: { enabled: false }, @@ -29,13 +31,15 @@ const DEFAULT_SETTINGS_WITH_CORE_PLUGINS = { ], }, elasticsearch: { - url: url.format(esTestServerUrlParts), + url: esTestConfig.getUrl(), username: kibanaServer.username, password: kibanaServer.password - } + }, + uiSettings: { + enabled: true + }, }; - /** * Creates an instance of KbnServer with default configuration * tailored for unit tests diff --git a/tasks/config/esvm.js b/tasks/config/esvm.js index 8283f39ddba14..04deff622f2ac 100644 --- a/tasks/config/esvm.js +++ b/tasks/config/esvm.js @@ -1,14 +1,12 @@ -import { esTestServerUrlParts } from '../../test/es_test_server_url_parts'; +import { esTestConfig } from '../../src/test_utils/es'; module.exports = function (grunt) { - const resolve = require('path').resolve; - const directory = resolve(__dirname, '../../esvm'); - const dataDir = resolve(directory, 'data_dir'); - const pkgBranch = grunt.config.get('pkg.branch'); + const branch = esTestConfig.getBranch(); + const dataDir = esTestConfig.getDirectoryForEsvm('data_dir'); return { options: { - branch: pkgBranch, + branch, fresh: !grunt.option('esvm-no-fresh'), config: { http: { @@ -19,7 +17,7 @@ module.exports = function (grunt) { dev: { options: { - directory: resolve(directory, 'dev'), + directory: esTestConfig.getDirectoryForEsvm('dev'), config: { path: { data: dataDir @@ -33,7 +31,7 @@ module.exports = function (grunt) { tribe: { options: { - directory: resolve(directory, 'tribe'), + directory: esTestConfig.getDirectoryForEsvm('tribe'), config: { path: { data: dataDir @@ -84,37 +82,13 @@ module.exports = function (grunt) { }, }, - test: { - options: { - directory: resolve(directory, 'test'), - purge: true, - config: { - http: { - port: esTestServerUrlParts.port - }, - cluster: { - name: 'esvm-test' - }, - discovery: { - zen: { - ping: { - unicast: { - hosts: [ `localhost:${esTestServerUrlParts.port}` ] - } - } - } - } - } - } - }, - ui: { options: { - directory: resolve(directory, 'test'), + directory: esTestConfig.getDirectoryForEsvm('test'), purge: true, config: { http: { - port: esTestServerUrlParts.port + port: esTestConfig.getPort() }, cluster: { name: 'esvm-ui' @@ -123,7 +97,7 @@ module.exports = function (grunt) { zen: { ping: { unicast: { - hosts: [ `localhost:${esTestServerUrlParts.port}` ] + hosts: [ `localhost:${esTestConfig.getPort()}` ] } } } diff --git a/tasks/config/run.js b/tasks/config/run.js index f10bc0d5d7560..04b56baed0f68 100644 --- a/tasks/config/run.js +++ b/tasks/config/run.js @@ -1,5 +1,4 @@ -import { format } from 'url'; -import { esTestServerUrlParts } from '../../test/es_test_server_url_parts'; +import { esTestConfig } from '../../src/test_utils/es'; import { kibanaTestServerUrlParts } from '../../test/kibana_test_server_url_parts'; module.exports = function (grunt) { @@ -55,7 +54,7 @@ module.exports = function (grunt) { args: [ ...stdDevArgs, '--optimize.enabled=false', - '--elasticsearch.url=' + format(esTestServerUrlParts), + '--elasticsearch.url=' + esTestConfig.getUrl(), '--server.port=' + kibanaTestServerUrlParts.port, '--server.xsrf.disableProtection=true', ...kbnServerFlags, @@ -75,7 +74,7 @@ module.exports = function (grunt) { '--dev', '--no-base-path', '--optimize.enabled=false', - '--elasticsearch.url=' + format(esTestServerUrlParts), + '--elasticsearch.url=' + esTestConfig.getUrl(), '--server.port=' + kibanaTestServerUrlParts.port, '--server.xsrf.disableProtection=true', ...kbnServerFlags, @@ -93,7 +92,7 @@ module.exports = function (grunt) { args: [ ...stdDevArgs, '--server.port=' + kibanaTestServerUrlParts.port, - '--elasticsearch.url=' + format(esTestServerUrlParts), + '--elasticsearch.url=' + esTestConfig.getUrl(), ...kbnServerFlags, ] }, @@ -109,7 +108,7 @@ module.exports = function (grunt) { args: [ ...stdDevArgs, '--server.port=' + kibanaTestServerUrlParts.port, - '--elasticsearch.url=' + format(esTestServerUrlParts), + '--elasticsearch.url=' + esTestConfig.getUrl(), ...kbnServerFlags, ] }, @@ -125,7 +124,7 @@ module.exports = function (grunt) { args: [ ...stdDevArgs, '--server.port=' + kibanaTestServerUrlParts.port, - '--elasticsearch.url=' + format(esTestServerUrlParts), + '--elasticsearch.url=' + esTestConfig.getUrl(), '--dev', '--no-base-path', '--optimize.lazyPort=5611', diff --git a/tasks/test.js b/tasks/test.js index d39534c4e27bf..6cb9ea838b548 100644 --- a/tasks/test.js +++ b/tasks/test.js @@ -14,9 +14,7 @@ module.exports = function (grunt) { grunt.registerTask('test:server', [ 'checkPlugins', - 'esvm:test', 'simplemocha:all', - 'esvm_shutdown:test', ]); grunt.registerTask('test:browser', [ diff --git a/test/common/config.js b/test/common/config.js index a2ec8badd7f16..a843201efa0a0 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -6,14 +6,14 @@ import { RetryProvider, } from './services'; -import { esTestServerUrlParts } from '../es_test_server_url_parts'; +import { esTestConfig } from '../../src/test_utils/es'; import { kibanaTestServerUrlParts } from '../kibana_test_server_url_parts'; export default function () { return { servers: { kibana: kibanaTestServerUrlParts, - elasticsearch: esTestServerUrlParts, + elasticsearch: esTestConfig.getUrlParts(), }, services: { kibanaServer: KibanaServerProvider, diff --git a/test/es_test_server_url_parts.js b/test/es_test_server_url_parts.js deleted file mode 100644 index 626fd348c9b58..0000000000000 --- a/test/es_test_server_url_parts.js +++ /dev/null @@ -1,10 +0,0 @@ -const shield = require('./shield'); - -export const esTestServerUrlParts = { - protocol: process.env.TEST_ES_PROTOCOL || 'http', - hostname: process.env.TEST_ES_HOSTNAME || 'localhost', - port: parseInt(process.env.TEST_ES_PORT, 10) || 9220, - auth: shield.admin.username + ':' + shield.admin.password, - username: shield.admin.username, - password: shield.admin.password, -}; diff --git a/test/kibana_test_server_url_parts.js b/test/kibana_test_server_url_parts.js index 04cecea023ffe..ca25f2fa9a7d6 100644 --- a/test/kibana_test_server_url_parts.js +++ b/test/kibana_test_server_url_parts.js @@ -1,10 +1,10 @@ -const shield = require('./shield'); +import { kibanaUser } from './shield'; export const kibanaTestServerUrlParts = { protocol: process.env.TEST_KIBANA_PROTOCOL || 'http', hostname: process.env.TEST_KIBANA_HOSTNAME || 'localhost', port: parseInt(process.env.TEST_KIBANA_PORT, 10) || 5620, - auth: shield.kibanaUser.username + ':' + shield.kibanaUser.password, - username: shield.kibanaUser.username, - password: shield.kibanaUser.password, + auth: kibanaUser.username + ':' + kibanaUser.password, + username: kibanaUser.username, + password: kibanaUser.password, }; diff --git a/test/shield.js b/test/shield.js index cdf3d4ef5ff17..eb4fdcd4a22e6 100644 --- a/test/shield.js +++ b/test/shield.js @@ -1,16 +1,16 @@ const env = process.env; -exports.kibanaUser = { +export const kibanaUser = { username: env.TEST_KIBANA_USER || 'elastic', password: env.TEST_KIBANA_PASS || 'changeme' }; -exports.kibanaServer = { +export const kibanaServer = { username: env.TEST_KIBANA_SERVER_USER || 'kibana', password: env.TEST_KIBANA_SERVER_PASS || 'changeme' }; -exports.admin = { +export const admin = { username: env.TEST_ES_USER || 'elastic', password: env.TEST_ES_PASS || 'changeme' }; From 5adc2cd4c8a311577faa07334b532d1a6386bc50 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Fri, 28 Jul 2017 13:27:41 -0400 Subject: [PATCH 034/165] Should respect pinned filters (#13019) --- .../public/kbn_vis_types/request_handler.js | 2 +- .../public/vis/timelion_request_handler.js | 2 +- src/ui/public/vis/request_handlers/courier.js | 12 +- src/ui/public/visualize/visualize.js | 190 +++++++++--------- 4 files changed, 107 insertions(+), 99 deletions(-) diff --git a/src/core_plugins/metrics/public/kbn_vis_types/request_handler.js b/src/core_plugins/metrics/public/kbn_vis_types/request_handler.js index 41b296ed0bc3e..839b79c56fcf1 100644 --- a/src/core_plugins/metrics/public/kbn_vis_types/request_handler.js +++ b/src/core_plugins/metrics/public/kbn_vis_types/request_handler.js @@ -7,7 +7,7 @@ const MetricsRequestHandlerProvider = function (Private, Notifier, config, timef return { name: 'metrics', - handler: function (vis /*, appState, uiState*/) { + handler: function (vis /*, appState, uiState, queryFilter*/) { return new Promise((resolve) => { const panel = vis.params; diff --git a/src/core_plugins/timelion/public/vis/timelion_request_handler.js b/src/core_plugins/timelion/public/vis/timelion_request_handler.js index 312de599a3bd0..978c7d4163cd1 100644 --- a/src/core_plugins/timelion/public/vis/timelion_request_handler.js +++ b/src/core_plugins/timelion/public/vis/timelion_request_handler.js @@ -11,7 +11,7 @@ const TimelionRequestHandlerProvider = function (Private, Notifier, $http, $root return { name: 'timelion', - handler: function (vis /*, appState, uiState */) { + handler: function (vis /*, appState, uiState, queryFilter*/) { return new Promise((resolve, reject) => { console.log('[timelion] get'); diff --git a/src/ui/public/vis/request_handlers/courier.js b/src/ui/public/vis/request_handlers/courier.js index 120839835a0c0..2d79342d3dd3a 100644 --- a/src/ui/public/vis/request_handlers/courier.js +++ b/src/ui/public/vis/request_handlers/courier.js @@ -5,10 +5,14 @@ import { VisRequestHandlersRegistryProvider } from 'ui/registry/vis_request_hand const CourierRequestHandlerProvider = function (Private, courier, timefilter) { return { name: 'courier', - handler: function (vis, appState, uiState, searchSource) { - if (appState && vis.editorMode) { - searchSource.set('filter', appState.filters); - if (!appState.linked) searchSource.set('query', appState.query); + handler: function (vis, appState, uiState, queryFilter, searchSource) { + + + if (queryFilter && vis.editorMode) { + searchSource.set('filter', queryFilter.getFilters()); + if (!appState.linked) { + searchSource.set('query', appState.query); + } } const shouldQuery = () => { diff --git a/src/ui/public/visualize/visualize.js b/src/ui/public/visualize/visualize.js index c911ab623aa98..a97422455ff62 100644 --- a/src/ui/public/visualize/visualize.js +++ b/src/ui/public/visualize/visualize.js @@ -8,6 +8,8 @@ import { ResizeCheckerProvider } from 'ui/resize_checker'; import 'angular-sanitize'; import './visualization'; import './visualization_editor'; +import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter'; + import { isTermSizeZeroError, @@ -15,44 +17,45 @@ import { uiModules .get('kibana/directive', ['ngSanitize']) -.directive('visualize', function (Notifier, Private, timefilter, getAppState) { - const notify = new Notifier({ location: 'Visualize' }); - const requestHandlers = Private(VisRequestHandlersRegistryProvider); - const responseHandlers = Private(VisResponseHandlersRegistryProvider); - const ResizeChecker = Private(ResizeCheckerProvider); - - function getHandler(from, name) { - if (typeof name === 'function') return name; - return from.find(handler => handler.name === name).handler; - } - - return { - restrict: 'E', - scope : { - showSpyPanel: '=?', - editorMode: '=?', - savedObj: '=', - appState: '=', - uiState: '=?' - }, - template: visualizeTemplate, - link: function ($scope, $el) { - const resizeChecker = new ResizeChecker($el); - - $scope.vis = $scope.savedObj.vis; - $scope.editorMode = $scope.editorMode || false; - $scope.vis.editorMode = $scope.editorMode; - $scope.vis.visualizeScope = true; - - if (!$scope.appState) $scope.appState = getAppState(); - - const requestHandler = getHandler(requestHandlers, $scope.vis.type.requestHandler); - const responseHandler = getHandler(responseHandlers, $scope.vis.type.responseHandler); - - $scope.fetch = _.debounce(function () { + .directive('visualize', function (Notifier, Private, timefilter, getAppState) { + const notify = new Notifier({ location: 'Visualize' }); + const requestHandlers = Private(VisRequestHandlersRegistryProvider); + const responseHandlers = Private(VisResponseHandlersRegistryProvider); + const ResizeChecker = Private(ResizeCheckerProvider); + const queryFilter = Private(FilterBarQueryFilterProvider); + + function getHandler(from, name) { + if (typeof name === 'function') return name; + return from.find(handler => handler.name === name).handler; + } + + return { + restrict: 'E', + scope : { + showSpyPanel: '=?', + editorMode: '=?', + savedObj: '=', + appState: '=', + uiState: '=?' + }, + template: visualizeTemplate, + link: function ($scope, $el) { + const resizeChecker = new ResizeChecker($el); + + $scope.vis = $scope.savedObj.vis; + $scope.editorMode = $scope.editorMode || false; + $scope.vis.editorMode = $scope.editorMode; + $scope.vis.visualizeScope = true; + + if (!$scope.appState) $scope.appState = getAppState(); + + const requestHandler = getHandler(requestHandlers, $scope.vis.type.requestHandler); + const responseHandler = getHandler(responseHandlers, $scope.vis.type.responseHandler); + + $scope.fetch = _.debounce(function () { // searchSource is only there for courier request handler - requestHandler($scope.vis, $scope.appState, $scope.uiState, $scope.savedObj.searchSource) + requestHandler($scope.vis, $scope.appState, $scope.uiState, queryFilter, $scope.savedObj.searchSource) .then(requestHandlerResponse => { //No need to call the response handler when there have been no data nor has been there changes @@ -83,73 +86,74 @@ uiModules $scope.$broadcast('render'); return resp; }); - }, 100); + }, 100); - $scope.vis.on('update', () => { - if ($scope.editorMode) { - $scope.appState.vis = $scope.vis.getState(); - $scope.appState.save(); - } else { - $scope.fetch(); - } - }); + $scope.vis.on('update', () => { + if ($scope.editorMode) { + $scope.appState.vis = $scope.vis.getState(); + $scope.appState.save(); + } else { + $scope.fetch(); + } + }); - const reload = () => { - $scope.vis.reload = true; - $scope.fetch(); - }; - $scope.vis.on('reload', reload); + const reload = () => { + $scope.vis.reload = true; + $scope.fetch(); + }; + $scope.vis.on('reload', reload); // auto reload will trigger this event - $scope.$on('courier:searchRefresh', reload); + $scope.$on('courier:searchRefresh', reload); // dashboard will fire fetch event when it wants to refresh - $scope.$on('fetch', reload); - - if ($scope.appState) { - let oldUiState; - const stateMonitor = stateMonitorFactory.create($scope.appState); - stateMonitor.onChange((status, type, keys) => { - if (keys[0] === 'vis') { - if ($scope.appState.vis) $scope.vis.setState($scope.appState.vis); - $scope.fetch(); - } - if ($scope.vis.type.requiresSearch && ['query', 'filters'].includes(keys[0])) { - $scope.fetch(); - } - if (keys[0] === 'uiState') { + $scope.$on('fetch', reload); + queryFilter.on('update', $scope.fetch); + + if ($scope.appState) { + let oldUiState; + const stateMonitor = stateMonitorFactory.create($scope.appState); + stateMonitor.onChange((status, type, keys) => { + if (keys[0] === 'vis') { + if ($scope.appState.vis) $scope.vis.setState($scope.appState.vis); + $scope.fetch(); + } + if ($scope.vis.type.requiresSearch && ['query', 'filters'].includes(keys[0])) { + $scope.fetch(); + } + if (keys[0] === 'uiState') { // uiState can be changed by other visualizations on dashboard. this makes sure this fires only if // current visualizations uiState changed. - if (!oldUiState || oldUiState !== JSON.stringify($scope.uiState.toJSON())) { - oldUiState = JSON.stringify($scope.uiState.toJSON()); - $scope.fetch(); + if (!oldUiState || oldUiState !== JSON.stringify($scope.uiState.toJSON())) { + oldUiState = JSON.stringify($scope.uiState.toJSON()); + $scope.fetch(); + } } - } - }); + }); - $scope.$on('$destroy', () => { - stateMonitor.destroy(); - }); - } + $scope.$on('$destroy', () => { + stateMonitor.destroy(); + }); + } - let resizeInit = false; - const resizeFunc = _.debounce(() => { - if (!resizeInit) return resizeInit = true; - $scope.vis.size = [$el.width(), $el.height()]; - $scope.$broadcast('render'); - }, 200); - resizeChecker.on('resize', resizeFunc); + let resizeInit = false; + const resizeFunc = _.debounce(() => { + if (!resizeInit) return resizeInit = true; + $scope.vis.size = [$el.width(), $el.height()]; + $scope.$broadcast('render'); + }, 200); + resizeChecker.on('resize', resizeFunc); // visualize needs to know about timeFilter - $scope.$listen(timefilter, 'fetch', $scope.fetch); - $scope.$on('renderComplete', () => { - $el.trigger('renderComplete'); - }); + $scope.$listen(timefilter, 'fetch', $scope.fetch); + $scope.$on('renderComplete', () => { + $el.trigger('renderComplete'); + }); - $scope.$on('$destroy', () => { - resizeChecker.destroy(); - }); + $scope.$on('$destroy', () => { + resizeChecker.destroy(); + }); - $scope.fetch(); - $scope.$root.$broadcast('ready:vis'); - } - }; -}); + $scope.fetch(); + $scope.$root.$broadcast('ready:vis'); + } + }; + }); From 7d94bb1240ffed3cd7fb3ae46438323389e6ceb9 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 28 Jul 2017 11:41:10 -0700 Subject: [PATCH 035/165] [esTestConfig] fix esvm directory (#13190) --- src/test_utils/es/es_test_config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test_utils/es/es_test_config.js b/src/test_utils/es/es_test_config.js index 0240e61558c07..2d05b77846e46 100644 --- a/src/test_utils/es/es_test_config.js +++ b/src/test_utils/es/es_test_config.js @@ -17,7 +17,7 @@ export const esTestConfig = new class EsTestConfig { throw new Error('getDirectoryForEsvm() requires uniqueSubDir'); } - return resolve(__dirname, '../esvm', uniqueSubDir); + return resolve(__dirname, '../../../esvm', uniqueSubDir); } getBranch() { From b678b4b46dd879cb3a4e1777e81288b6b30cd8d3 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 28 Jul 2017 13:37:19 -0700 Subject: [PATCH 036/165] Add Checks to Dashboard Context (#13182) * Fixes #13181 - Check values before adding them to filter * Adding tests * Adding check to make sure query is never undefined --- .../dashboard/__tests__/dashboard_context.js | 131 ++++++++++++++++++ .../public/dashboard/dashboard_context.js | 7 +- .../courier/saved_object/saved_object.js | 4 +- 3 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 src/core_plugins/kibana/public/dashboard/__tests__/dashboard_context.js diff --git a/src/core_plugins/kibana/public/dashboard/__tests__/dashboard_context.js b/src/core_plugins/kibana/public/dashboard/__tests__/dashboard_context.js new file mode 100644 index 0000000000000..6081ceb5020cb --- /dev/null +++ b/src/core_plugins/kibana/public/dashboard/__tests__/dashboard_context.js @@ -0,0 +1,131 @@ +import sinon from 'sinon'; +import { expect } from 'chai'; +import { dashboardContextProvider } from '../dashboard_context'; + +describe('Dashboard Context', () => { + + describe('with query bar', () => { + let Private; + let getAppState; + let getDashboardContext; + beforeEach(() => { + Private = sinon.stub().returns({ + getFilters() { + return []; + } + }); + }); + + it('should return an empty must and must not when there are no filters or queries', () => { + getAppState = sinon.stub().returns({ + query: { + language: 'lucene', + query: null + } + }); + getDashboardContext = dashboardContextProvider(Private, getAppState); + const context = getDashboardContext(); + expect(context).to.eql({ + bool: { + must: [], + must_not: [] + } + }); + }); + + it('should add a valid query to must', () => { + getAppState = sinon.stub().returns({ + query: { + language: 'lucene', + query: '*' + } + }); + getDashboardContext = dashboardContextProvider(Private, getAppState); + const context = getDashboardContext(); + expect(context).to.eql({ + bool: { + must: [ + { + query_string: { + query: '*' + } + } + ], + must_not: [] + } + }); + }); + + }); + + describe('with filter bar', () => { + let Private; + let getAppState; + let getDashboardContext; + beforeEach(() => { + getAppState = sinon.stub().returns({ query: { language: 'something-else' } }); + }); + + afterEach(() => { + getAppState.reset(); + }); + + it('should add a valid filter to must', () => { + Private = sinon.stub().returns({ + getFilters() { + return [ + { meta: { negate: false }, term: { foo: 'bar' } } + ]; + } + }); + getDashboardContext = dashboardContextProvider(Private, getAppState); + const context = getDashboardContext(); + expect(context).to.eql({ + bool: { + must: [{ term: { foo: 'bar' } }], + must_not: [] + } + }); + }); + + it('should add a valid filter to must_not', () => { + Private = sinon.stub().returns({ + getFilters() { + return [ + { meta: { negate: true }, term: { foo: 'bar' } } + ]; + } + }); + getDashboardContext = dashboardContextProvider(Private, getAppState); + const context = getDashboardContext(); + expect(context).to.eql({ + bool: { + must: [], + must_not: [{ term: { foo: 'bar' } }] + } + }); + }); + + it('should not add a disabled filter', () => { + Private = sinon.stub().returns({ + getFilters() { + return [ + { meta: { negate: true, disabled: true }, term: { foo: 'bar' } } + ]; + } + }); + getDashboardContext = dashboardContextProvider(Private, getAppState); + const context = getDashboardContext(); + expect(context).to.eql({ + bool: { + must: [], + must_not: [] + } + }); + }); + + }); + +}); + + diff --git a/src/core_plugins/kibana/public/dashboard/dashboard_context.js b/src/core_plugins/kibana/public/dashboard/dashboard_context.js index 5788905f58ed6..1824ba3f21bd0 100644 --- a/src/core_plugins/kibana/public/dashboard/dashboard_context.js +++ b/src/core_plugins/kibana/public/dashboard/dashboard_context.js @@ -13,7 +13,8 @@ export function dashboardContextProvider(Private, getAppState) { if (queryBarQuery.language === 'lucene') { // Add the query bar filter, its handled differently. - bool.must.push(luceneStringToDsl(queryBarQuery.query)); + const query = luceneStringToDsl(queryBarQuery.query); + if (query) bool.must.push(query); } // Add each of the filter bar filters @@ -26,10 +27,10 @@ export function dashboardContextProvider(Private, getAppState) { if (filter.meta.disabled) return; if (filter.meta.negate) { bool.must_not = bool.must_not || []; - bool.must_not.push(esFilter.query || esFilter); + if (esFilter.query || esFilter) bool.must_not.push(esFilter.query || esFilter); } else { bool.must = bool.must || []; - bool.must.push(esFilter.query || esFilter); + if (esFilter.query || esFilter) bool.must.push(esFilter.query || esFilter); } }); diff --git a/src/ui/public/courier/saved_object/saved_object.js b/src/ui/public/courier/saved_object/saved_object.js index 050f36439c048..45770af5fb4e5 100644 --- a/src/ui/public/courier/saved_object/saved_object.js +++ b/src/ui/public/courier/saved_object/saved_object.js @@ -107,7 +107,9 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm this.searchSource.set(_.defaults(state, fnProps)); - this.searchSource.set('query', migrateLegacyQuery(this.searchSource.getOwn('query'))); + if (!_.isUndefined(this.searchSource.getOwn('query'))) { + this.searchSource.set('query', migrateLegacyQuery(this.searchSource.getOwn('query'))); + } }; /** From d36080bca837ba524345d010d978fc2b4580367b Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 28 Jul 2017 15:50:15 -0700 Subject: [PATCH 037/165] [testUtils/esTestCluster] use more standard api style (#13197) --- .../elasticsearch/lib/__tests__/routes.js | 4 +- .../__tests__/integration/with_es_archiver.js | 4 +- src/server/http/__tests__/index.js | 4 +- src/test_utils/es/es_test_cluster.js | 150 +++++++++--------- src/test_utils/es/index.js | 2 +- 5 files changed, 80 insertions(+), 84 deletions(-) diff --git a/src/core_plugins/elasticsearch/lib/__tests__/routes.js b/src/core_plugins/elasticsearch/lib/__tests__/routes.js index 73b60561eae01..25ce5a2d8000c 100644 --- a/src/core_plugins/elasticsearch/lib/__tests__/routes.js +++ b/src/core_plugins/elasticsearch/lib/__tests__/routes.js @@ -1,12 +1,12 @@ import { format } from 'util'; import * as kbnTestServer from '../../../../test_utils/kbn_server'; -import { esTestCluster } from '../../../../test_utils/es'; +import { createEsTestCluster } from '../../../../test_utils/es'; describe('plugins/elasticsearch', function () { describe('routes', function () { let kbnServer; - const es = esTestCluster.use({ + const es = createEsTestCluster({ name: 'core_plugins/es/routes', }); diff --git a/src/functional_test_runner/__tests__/integration/with_es_archiver.js b/src/functional_test_runner/__tests__/integration/with_es_archiver.js index 5bfd1a9383832..48a1d168d0f00 100644 --- a/src/functional_test_runner/__tests__/integration/with_es_archiver.js +++ b/src/functional_test_runner/__tests__/integration/with_es_archiver.js @@ -4,7 +4,7 @@ import { format as formatUrl } from 'url'; import { readConfigFile } from '../../lib'; import { createToolingLog, createReduceStream } from '../../../utils'; -import { esTestCluster } from '../../../test_utils/es'; +import { createEsTestCluster } from '../../../test_utils/es'; import { startupKibana } from '../lib'; const SCRIPT = resolve(__dirname, '../../../../scripts/functional_test_runner.js'); @@ -24,7 +24,7 @@ describe('single test that uses esArchiver', () => { log.info('starting elasticsearch'); log.indent(2); - const es = esTestCluster.use({ + const es = createEsTestCluster({ log: msg => log.debug(msg), name: 'ftr/withEsArchiver', port: config.get('servers.elasticsearch.port') diff --git a/src/server/http/__tests__/index.js b/src/server/http/__tests__/index.js index e51d2e8634194..f6909114698e4 100644 --- a/src/server/http/__tests__/index.js +++ b/src/server/http/__tests__/index.js @@ -1,10 +1,10 @@ import expect from 'expect.js'; import * as kbnTestServer from '../../../test_utils/kbn_server'; -import { esTestCluster } from '../../../test_utils/es'; +import { createEsTestCluster } from '../../../test_utils/es'; describe('routes', () => { let kbnServer; - const es = esTestCluster.use({ + const es = createEsTestCluster({ name: 'server/http', }); diff --git a/src/test_utils/es/es_test_cluster.js b/src/test_utils/es/es_test_cluster.js index 9e96554a12e83..97ec418e1d831 100644 --- a/src/test_utils/es/es_test_cluster.js +++ b/src/test_utils/es/es_test_cluster.js @@ -1,103 +1,99 @@ import { resolve } from 'path'; -import { esTestConfig } from './es_test_config'; import libesvm from 'libesvm'; +import { esTestConfig } from './es_test_config'; + const ESVM_DIR = resolve(__dirname, '../../../esvm/test_utils/es_test_cluster'); +const BRANCHES_DOWNLOADED = []; -export class EsTestCluster { - _branchesDownloaded = []; +function isDownloadNeeded(branch) { + if (process.env.ESVM_NO_FRESH || process.argv.includes('--esvm-no-fresh')) { + return false; + } - use(options = {}) { - const { - name, - log = console.log, - port = esTestConfig.getPort(), - branch = esTestConfig.getBranch(), - } = options; + if (BRANCHES_DOWNLOADED.includes(branch)) { + return false; + } - if (!name) { - throw new Error('esTestCluster.use() requires { name }'); - } + return true; +} - // assigned in use.start(), reassigned in use.stop() - let cluster; +export function createEsTestCluster(options = {}) { + const { + name, + log = console.log, + port = esTestConfig.getPort(), + branch = esTestConfig.getBranch(), + } = options; - return { - getStartTimeout: () => { - return esTestConfig.getLibesvmStartTimeout(); - }, + if (!name) { + throw new Error('createEsTestCluster() requires { name }'); + } - start: async () => { - const download = this._isDownloadNeeded(branch); + // assigned in use.start(), reassigned in use.stop() + let cluster; - if (cluster) { - throw new Error(` - EsTestCluster[${name}] is already started, call and await es.stop() - before calling es.start() again. - `); - } + return new class EsTestCluster { + getStartTimeout() { + return esTestConfig.getLibesvmStartTimeout(); + } + + async start() { + const download = isDownloadNeeded(branch); - cluster = libesvm.createCluster({ - fresh: download, - purge: !download, - directory: ESVM_DIR, - branch, - config: { - http: { - port, - }, - cluster: { - name, - }, - discovery: { - zen: { - ping: { - unicast: { - hosts: [ `localhost:${port}` ] - } + if (cluster) { + throw new Error(` + EsTestCluster[${name}] is already started, call and await es.stop() + before calling es.start() again. + `); + } + + cluster = libesvm.createCluster({ + fresh: download, + purge: !download, + directory: ESVM_DIR, + branch, + config: { + http: { + port, + }, + cluster: { + name, + }, + discovery: { + zen: { + ping: { + unicast: { + hosts: [ `localhost:${port}` ] } } } } - }); - - cluster.on('log', (event) => { - log(`EsTestCluster[${name}]: ${event.type} - ${event.message}`); - }); - - await cluster.install(); - - if (download) { - // track the branches that have successfully downloaded - // after cluster.install() resolves - this._branchesDownloaded.push(branch); } + }); - await cluster.start(); - }, + cluster.on('log', (event) => { + log(`EsTestCluster[${name}]: ${event.type} - ${event.message}`); + }); - stop: async () => { - if (cluster) { - const c = cluster; - cluster = null; - await c.shutdown(); - } + await cluster.install(); + + if (download) { + // track the branches that have successfully downloaded + // after cluster.install() resolves + BRANCHES_DOWNLOADED.push(branch); } - }; - } - _isDownloadNeeded(branch) { - if (process.env.ESVM_NO_FRESH || process.argv.includes('--esvm-no-fresh')) { - return false; + await cluster.start(); } - if (this._branchesDownloaded.includes(branch)) { - return false; + async stop() { + if (cluster) { + const c = cluster; + cluster = null; + await c.shutdown(); + } } - - return true; - } + }; } - -export const esTestCluster = new EsTestCluster(); diff --git a/src/test_utils/es/index.js b/src/test_utils/es/index.js index 7230b751960c6..0409e204608eb 100644 --- a/src/test_utils/es/index.js +++ b/src/test_utils/es/index.js @@ -1,2 +1,2 @@ -export { esTestCluster } from './es_test_cluster'; export { esTestConfig } from './es_test_config'; +export { createEsTestCluster } from './es_test_cluster'; From 74cd8b1ac238556611a9f34477fe4344557a19a7 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 31 Jul 2017 14:42:08 -0400 Subject: [PATCH 038/165] Update saved objects client usage to `attributes` instead of `_source`. Also, fixing an improper "safe" apply usage. (#13223) --- .../kibana/public/management/sections/objects/_view.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core_plugins/kibana/public/management/sections/objects/_view.js b/src/core_plugins/kibana/public/management/sections/objects/_view.js index abaa5db10f1bb..e7082cfea32bf 100644 --- a/src/core_plugins/kibana/public/management/sections/objects/_view.js +++ b/src/core_plugins/kibana/public/management/sections/objects/_view.js @@ -152,7 +152,7 @@ uiModules.get('apps/management') $scope.aceInvalidEditors = _.without($scope.aceInvalidEditors, fieldName); } - if ($rootScope.$$phase) $scope.$apply(); + if (!$rootScope.$$phase) $scope.$apply(); }); }; @@ -185,7 +185,7 @@ uiModules.get('apps/management') }; $scope.submit = function () { - const source = _.cloneDeep($scope.obj._source); + const source = _.cloneDeep($scope.obj.attributes); _.each($scope.fields, function (field) { let value = field.value; @@ -209,7 +209,7 @@ uiModules.get('apps/management') }; function redirectHandler(action) { - const msg = 'You successfully ' + action + ' the "' + $scope.obj._source.title + '" ' + $scope.title.toLowerCase() + ' object'; + const msg = 'You successfully ' + action + ' the "' + $scope.obj.attributes.title + '" ' + $scope.title.toLowerCase() + ' object'; $location.path('/management/kibana/objects').search({ _a: rison.encode({ From abcc055f97b801b52ccc85187d604342ae21faf3 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 31 Jul 2017 12:45:38 -0600 Subject: [PATCH 039/165] update spy table headers when columns update (#13130) * update paginated table headers with columns update * remove unneeded sleep * update getDataTableHeaders to preffered format * use data-test-subj attribute for functional tests instead of CSS selectors --- .../paginated_table/paginated_table.html | 11 +++-- test/functional/apps/visualize/_spy_panel.js | 43 +++++++++++++++++++ test/functional/apps/visualize/index.js | 1 + .../functional/page_objects/visualize_page.js | 8 +++- 4 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 test/functional/apps/visualize/_spy_panel.js diff --git a/src/ui/public/paginated_table/paginated_table.html b/src/ui/public/paginated_table/paginated_table.html index 69242f4fda33a..fdbc998345506 100644 --- a/src/ui/public/paginated_table/paginated_table.html +++ b/src/ui/public/paginated_table/paginated_table.html @@ -5,10 +5,10 @@ class="agg-table">
- + - + + diff --git a/test/functional/apps/visualize/_spy_panel.js b/test/functional/apps/visualize/_spy_panel.js new file mode 100644 index 0000000000000..046d25b569bab --- /dev/null +++ b/test/functional/apps/visualize/_spy_panel.js @@ -0,0 +1,43 @@ +import expect from 'expect.js'; + +export default function ({ getService, getPageObjects }) { + const log = getService('log'); + const PageObjects = getPageObjects(['common', 'visualize', 'header']); + + describe('visualize app', function describeIndexTests() { + before(async function () { + const fromTime = '2015-09-19 06:31:44.000'; + const toTime = '2015-09-23 18:31:44.000'; + + await PageObjects.common.navigateToUrl('visualize', 'new'); + await PageObjects.visualize.clickVerticalBarChart(); + await PageObjects.visualize.clickNewSearch(); + + log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"'); + await PageObjects.header.setAbsoluteRange(fromTime, toTime); + await PageObjects.visualize.clickGo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + }); + + describe('spy panel tabel', function indexPatternCreation() { + + it('should update table header when columns change', async function () { + + await PageObjects.visualize.openSpyPanel(); + let headers = await PageObjects.visualize.getDataTableHeaders(); + expect(headers.trim()).to.equal('Count'); + + log.debug('Add Average Metric on machine.ram field'); + await PageObjects.visualize.clickAddMetric(); + await PageObjects.visualize.clickBucket('Y-Axis'); + await PageObjects.visualize.selectAggregation('Average'); + await PageObjects.visualize.selectField('machine.ram', 'metrics'); + await PageObjects.visualize.clickGo(); + await PageObjects.visualize.openSpyPanel(); + + headers = await PageObjects.visualize.getDataTableHeaders(); + expect(headers.trim()).to.equal('Count Average machine.ram'); + }); + }); + }); +} diff --git a/test/functional/apps/visualize/index.js b/test/functional/apps/visualize/index.js index 945bf87876cf4..f66712109576d 100644 --- a/test/functional/apps/visualize/index.js +++ b/test/functional/apps/visualize/index.js @@ -14,6 +14,7 @@ export default function ({ getService, loadTestFile }) { await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'UTC', 'defaultIndex': 'logstash-*' }); }); + loadTestFile(require.resolve('./_spy_panel')); loadTestFile(require.resolve('./_chart_types')); loadTestFile(require.resolve('./_gauge_chart')); loadTestFile(require.resolve('./_area_chart')); diff --git a/test/functional/page_objects/visualize_page.js b/test/functional/page_objects/visualize_page.js index 0682358bdf604..9390c90028fb9 100644 --- a/test/functional/page_objects/visualize_page.js +++ b/test/functional/page_objects/visualize_page.js @@ -469,10 +469,16 @@ export function VisualizePageProvider({ getService, getPageObjects }) { async getDataTableData() { const dataTable = await retry.try( - async () => find.byCssSelector('table.table.table-condensed tbody', defaultFindTimeout * 2)); + async () => testSubjects.find('paginated-table-body')); return await dataTable.getVisibleText(); } + async getDataTableHeaders() { + const dataTableHeader = await retry.try( + async () => testSubjects.find('paginated-table-header')); + return await dataTableHeader.getVisibleText(); + } + async getMarkdownData() { const markdown = await retry.try(async () => find.byCssSelector('visualize.ng-isolate-scope')); return await markdown.getVisibleText(); From 9389f0b71ac11aabdd49aa6d341dee0fff34fd83 Mon Sep 17 00:00:00 2001 From: Spencer Date: Mon, 31 Jul 2017 12:44:57 -0700 Subject: [PATCH 040/165] [server/indexPatterns] expose indexPatternService getter/factory (#13012) --- src/server/index_patterns/mixin.js | 32 +++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/server/index_patterns/mixin.js b/src/server/index_patterns/mixin.js index 6fef84aaef65c..3acaf4d5c4ac3 100644 --- a/src/server/index_patterns/mixin.js +++ b/src/server/index_patterns/mixin.js @@ -13,17 +13,35 @@ export function indexPatternsMixin(kbnServer, server) { */ getIndexPatternsService: { assign: 'indexPatterns', - method(req, reply) { - const dataCluster = req.server.plugins.elasticsearch.getCluster('data'); - const callDataCluster = (...args) => ( - dataCluster.callWithRequest(req, ...args) - ); - - reply(new IndexPatternsService(callDataCluster)); + method(request, reply) { + reply(request.getIndexPatternsService()); } } }; + /** + * Create an instance of the IndexPatternsService + * + * @method server.indexPatternsServiceFactory + * @type {IndexPatternsService} + */ + server.decorate('server', 'indexPatternsServiceFactory', ({ callCluster }) => { + return new IndexPatternsService(callCluster); + }); + + /** + * Get an instance of the IndexPatternsService configured for use + * the current request + * + * @method request.getIndexPatternsService + * @type {IndexPatternsService} + */ + server.addMemoizedFactoryToRequest('getIndexPatternsService', request => { + const { callWithRequest } = request.server.plugins.elasticsearch.getCluster('data'); + const callCluster = (...args) => callWithRequest(request, ...args); + return server.indexPatternsServiceFactory({ callCluster }); + }); + server.route(createFieldsForWildcardRoute(pre)); server.route(createFieldsForTimePatternRoute(pre)); } From 5772f56d7a5406a3216dca2782ab37e3c13d7fed Mon Sep 17 00:00:00 2001 From: Kim Joar Bekkelund Date: Mon, 31 Jul 2017 22:58:50 +0200 Subject: [PATCH 041/165] Remove `@elastic` folder from `packages/` (#13089) --- packages/{@elastic => }/eslint-plugin-kibana-custom/README.md | 0 packages/{@elastic => }/eslint-plugin-kibana-custom/index.js | 0 packages/{@elastic => }/eslint-plugin-kibana-custom/package.json | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename packages/{@elastic => }/eslint-plugin-kibana-custom/README.md (100%) rename packages/{@elastic => }/eslint-plugin-kibana-custom/index.js (100%) rename packages/{@elastic => }/eslint-plugin-kibana-custom/package.json (100%) diff --git a/packages/@elastic/eslint-plugin-kibana-custom/README.md b/packages/eslint-plugin-kibana-custom/README.md similarity index 100% rename from packages/@elastic/eslint-plugin-kibana-custom/README.md rename to packages/eslint-plugin-kibana-custom/README.md diff --git a/packages/@elastic/eslint-plugin-kibana-custom/index.js b/packages/eslint-plugin-kibana-custom/index.js similarity index 100% rename from packages/@elastic/eslint-plugin-kibana-custom/index.js rename to packages/eslint-plugin-kibana-custom/index.js diff --git a/packages/@elastic/eslint-plugin-kibana-custom/package.json b/packages/eslint-plugin-kibana-custom/package.json similarity index 100% rename from packages/@elastic/eslint-plugin-kibana-custom/package.json rename to packages/eslint-plugin-kibana-custom/package.json From 18f8455711ebdef2f88396d462e11001f8913678 Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Mon, 31 Jul 2017 18:24:46 -0400 Subject: [PATCH 042/165] Add some functional tests for query language switching (#13036) * Add some functional tests for query language switching --- .../public/query_bar/directive/query_bar.html | 1 + test/functional/apps/discover/_discover.js | 82 ++++++++++++++++++- test/functional/config.js | 2 + test/functional/services/index.js | 1 + test/functional/services/query_bar.js | 37 +++++++++ 5 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 test/functional/services/query_bar.js diff --git a/src/ui/public/query_bar/directive/query_bar.html b/src/ui/public/query_bar/directive/query_bar.html index a955403f47d65..caac42da1e080 100644 --- a/src/ui/public/query_bar/directive/query_bar.html +++ b/src/ui/public/query_bar/directive/query_bar.html @@ -55,6 +55,7 @@ ng-model="queryBar.localQuery.language" ng-change="queryBar.selectLanguage()" ng-if="queryBar.showLanguageSwitcher" + data-test-subj="queryBarLanguageSwitcher" > diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index aa70c7fe2f246..90636becb209a 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -7,7 +7,13 @@ export default function ({ getService, getPageObjects }) { const remote = getService('remote'); const kibanaServer = getService('kibanaServer'); const screenshots = getService('screenshots'); + const queryBar = getService('queryBar'); + const filterBar = getService('filterBar'); const PageObjects = getPageObjects(['common', 'discover', 'header']); + const defaultSettings = { + 'dateFormat:tz': 'UTC', + 'defaultIndex': 'logstash-*' + }; describe('discover app', function describeIndexTests() { const fromTime = '2015-09-19 06:31:44.000'; @@ -17,10 +23,7 @@ export default function ({ getService, getPageObjects }) { before(async function () { // delete .kibana index and update configDoc - await kibanaServer.uiSettings.replace({ - 'dateFormat:tz':'UTC', - 'defaultIndex':'logstash-*' - }); + await kibanaServer.uiSettings.replace(defaultSettings); log.debug('load kibana index with default index pattern'); await esArchiver.load('discover'); @@ -229,6 +232,77 @@ export default function ({ getService, getPageObjects }) { }); }); + describe('query language switching', function () { + + after(async function () { + await kibanaServer.uiSettings.replace(defaultSettings); + + log.debug('discover'); + await PageObjects.common.navigateToApp('discover'); + }); + + it('should not show a language switcher by default', async function () { + const languageSwitcherExists = await queryBar.hasLanguageSwitcher(); + expect(languageSwitcherExists).to.be(false); + }); + + it('should show a language switcher after it has been enabled in the advanced settings', async function () { + await kibanaServer.uiSettings.update({ + 'search:queryLanguage:switcher:enable': true + }); + await PageObjects.common.navigateToApp('discover'); + const languageSwitcherExists = await queryBar.hasLanguageSwitcher(); + expect(languageSwitcherExists).to.be(true); + }); + + it('should use lucene by default', async function () { + const currentLanguage = await queryBar.getCurrentLanguage(); + expect(currentLanguage).to.be('lucene'); + }); + + it('should allow changing the default language in advanced settings', async function () { + await kibanaServer.uiSettings.update({ + 'search:queryLanguage': 'kuery' + }); + await PageObjects.common.navigateToApp('discover'); + + const languageSwitcherExists = await queryBar.hasLanguageSwitcher(); + expect(languageSwitcherExists).to.be(true); + + const currentLanguage = await queryBar.getCurrentLanguage(); + expect(currentLanguage).to.be('kuery'); + }); + + it('should reset the query and filters when the language is switched', async function () { + await PageObjects.header.setAbsoluteRange(fromTime, toTime); + await PageObjects.discover.clickFieldListItem('response'); + await PageObjects.discover.clickFieldListPlusFilter('response', 200); + await PageObjects.header.waitUntilLoadingHasFinished(); + + let queryString = await queryBar.getQueryString(); + expect(queryString).to.not.be.empty(); + + await queryBar.setLanguage('lucene'); + await PageObjects.header.waitUntilLoadingHasFinished(); + queryString = await queryBar.getQueryString(); + expect(queryString).to.be.empty(); + expect(await filterBar.hasFilter('response', 200)).to.be(false); + + await PageObjects.discover.clickFieldListPlusFilter('response', 200); + await PageObjects.header.waitUntilLoadingHasFinished(); + queryString = await queryBar.getQueryString(); + expect(queryString).to.be.empty(); + expect(await filterBar.hasFilter('response', 200)).to.be(true); + + await queryBar.setLanguage('kuery'); + await PageObjects.header.waitUntilLoadingHasFinished(); + queryString = await queryBar.getQueryString(); + expect(queryString).to.be.empty(); + expect(await filterBar.hasFilter('response', 200)).to.be(false); + }); + + }); + describe('data-shared-item', function () { it('should have correct data-shared-item title and description', async () => { const expected = { diff --git a/test/functional/config.js b/test/functional/config.js index e48a07642df11..996699ca65e83 100644 --- a/test/functional/config.js +++ b/test/functional/config.js @@ -15,6 +15,7 @@ import { import { RemoteProvider, FilterBarProvider, + QueryBarProvider, FindProvider, TestSubjectsProvider, DocTableProvider, @@ -56,6 +57,7 @@ export default async function ({ readConfigFile }) { retry: commonConfig.get('services.retry'), remote: RemoteProvider, filterBar: FilterBarProvider, + queryBar: QueryBarProvider, find: FindProvider, testSubjects: TestSubjectsProvider, docTable: DocTableProvider, diff --git a/test/functional/services/index.js b/test/functional/services/index.js index 9cd9c86167d12..1785c27c572da 100644 --- a/test/functional/services/index.js +++ b/test/functional/services/index.js @@ -1,3 +1,4 @@ +export { QueryBarProvider } from './query_bar'; export { FilterBarProvider } from './filter_bar'; export { FindProvider } from './find'; export { TestSubjectsProvider } from './test_subjects'; diff --git a/test/functional/services/query_bar.js b/test/functional/services/query_bar.js new file mode 100644 index 0000000000000..96dabd876c360 --- /dev/null +++ b/test/functional/services/query_bar.js @@ -0,0 +1,37 @@ +export function QueryBarProvider({ getService }) { + const testSubjects = getService('testSubjects'); + const find = getService('find'); + + class QueryBar { + + async getQueryString() { + const queryInput = await testSubjects.find('queryInput'); + return await queryInput.getProperty('value'); + } + + async hasLanguageSwitcher() { + return await testSubjects.exists('queryBarLanguageSwitcher'); + } + + async getLanguageSwitcher() { + return await testSubjects.find('queryBarLanguageSwitcher'); + } + + async getCurrentLanguage() { + const languageSwitcher = await this.getLanguageSwitcher(); + const selectedOption = await languageSwitcher.findByCssSelector('option[selected="selected"]'); + return await selectedOption.getVisibleText(); + } + + async setLanguage(language) { + const languageSwitcher = await this.getLanguageSwitcher(); + await languageSwitcher.click(); + + const requestedOption = await find.byCssSelector(`option[label="${language}"]`); + await requestedOption.click(); + } + + } + + return new QueryBar(); +} From 99a991b78384ae0f3ce20c018afb6610f2fa5f79 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Tue, 1 Aug 2017 00:47:21 -0500 Subject: [PATCH 043/165] [docs] Add docker-compose version to example (#13006) --- docs/setup/docker.asciidoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/setup/docker.asciidoc b/docs/setup/docker.asciidoc index 4cdfb542eee95..6e5e0d91be28c 100644 --- a/docs/setup/docker.asciidoc +++ b/docs/setup/docker.asciidoc @@ -50,6 +50,7 @@ With +docker-compose+, the bind-mount can be specified like this: ["source","yaml",subs="attributes"] -------------------------------------------- +version: '3' services: kibana: image: {docker-image} @@ -86,6 +87,7 @@ These variables can be set with +docker-compose+ like this: ["source","yaml",subs="attributes"] ---------------------------------------------------------- +version: '3' services: kibana: image: {docker-image} From baabbdfa1099838b9a984359e0f510976d91f4ba Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Tue, 1 Aug 2017 10:02:59 +0200 Subject: [PATCH 044/165] removes :filters from label (#12962) --- src/ui/public/agg_response/tabify/_response_writer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ui/public/agg_response/tabify/_response_writer.js b/src/ui/public/agg_response/tabify/_response_writer.js index 271dea31947ce..d068f2e112ec7 100644 --- a/src/ui/public/agg_response/tabify/_response_writer.js +++ b/src/ui/public/agg_response/tabify/_response_writer.js @@ -75,7 +75,11 @@ export function TabbedAggResponseWriterProvider(Private) { if (group) { table.aggConfig = agg; table.key = key; - table.title = (table.fieldFormatter()(key)) + ': ' + agg.makeLabel(); + table.title = (table.fieldFormatter()(key)); + // aggs that don't implement makeLabel should not add to title + if (agg.makeLabel() !== agg.name) { + table.title += ': ' + agg.makeLabel(); + } } // link the parent and child From 5703ffc9def917a5910c14189d886375a0280340 Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Tue, 1 Aug 2017 10:06:59 +0200 Subject: [PATCH 045/165] in percentage mode tooltip should also show percentages (#13217) --- src/ui/public/vislib/lib/dispatch.js | 5 +++-- src/ui/public/vislib/visualizations/point_series.js | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ui/public/vislib/lib/dispatch.js b/src/ui/public/vislib/lib/dispatch.js index 1d3280b66513b..02f059960a23c 100644 --- a/src/ui/public/vislib/lib/dispatch.js +++ b/src/ui/public/vislib/lib/dispatch.js @@ -40,7 +40,6 @@ export function VislibLibDispatchProvider(Private, config) { const slices = isSlices ? data.slices : undefined; const handler = this.handler; const color = _.get(handler, 'data.color'); - const isPercentage = (handler && handler.visConfig.get('mode', 'normal') === 'percentage'); const eventData = { value: d.y, @@ -59,11 +58,13 @@ export function VislibLibDispatchProvider(Private, config) { if (isSeries) { // Find object with the actual d value and add it to the point object + const aggId = d3.event.target.parentElement.__data__.aggId; + const percentageMode = handler.charts[0].getSeries(aggId).getValueAxis().axisConfig.isPercentage(); const object = _.find(series, { 'label': label }); if (object) { eventData.value = +object.values[i].y; - if (isPercentage) { + if (percentageMode) { // Add the formatted percentage to the point object eventData.percent = (100 * d.y).toFixed(1) + '%'; } diff --git a/src/ui/public/vislib/visualizations/point_series.js b/src/ui/public/vislib/visualizations/point_series.js index 6847f98adec5f..53ed508ac5cd5 100644 --- a/src/ui/public/vislib/visualizations/point_series.js +++ b/src/ui/public/vislib/visualizations/point_series.js @@ -40,6 +40,10 @@ export function VislibVisualizationsPointSeriesProvider(Private) { return charts[chartIndex]; } + getSeries(seriesId) { + return this.series.find(series => series.chartData.aggId === seriesId); + } + addBackground(svg, width, height) { const startX = 0; const startY = 0; From 0353735f27a8a31520098611438505e6c09d1cb4 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 1 Aug 2017 11:23:51 -0400 Subject: [PATCH 046/165] Exclude stacktrace from error response of Timelion backend (#12973) --- src/core_plugins/timelion/server/routes/run.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core_plugins/timelion/server/routes/run.js b/src/core_plugins/timelion/server/routes/run.js index 136d5e08673dd..f821407baa00e 100644 --- a/src/core_plugins/timelion/server/routes/run.js +++ b/src/core_plugins/timelion/server/routes/run.js @@ -4,7 +4,10 @@ import chainRunnerFn from '../handlers/chain_runner.js'; const timelionDefaults = require('../lib/get_namespaced_settings')(); function replyWithError(e, reply) { - reply({ title: e.toString(), message: e.toString(), stack: e.stack }).code(400); + reply({ + title: e.toString(), + message: e.toString() + }).code(500); } @@ -39,6 +42,7 @@ export default function (server) { }); } catch (err) { + server.log(['timelion', 'error'], `${err.toString()}: ${err.stack}`); // TODO Maybe we should just replace everywhere we throw with Boom? Probably. if (err.isBoom) { reply(err); From 9057937ff2bb08466f959f60fe2b436b1b9475e2 Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Tue, 1 Aug 2017 13:49:16 -0400 Subject: [PATCH 047/165] Send map filters through so it get picked up by both kuery and lucene (#13251) --- src/core_plugins/tile_map/public/maps_visualization.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core_plugins/tile_map/public/maps_visualization.js b/src/core_plugins/tile_map/public/maps_visualization.js index efb86741ce133..eb2be81aaeff7 100644 --- a/src/core_plugins/tile_map/public/maps_visualization.js +++ b/src/core_plugins/tile_map/public/maps_visualization.js @@ -275,7 +275,7 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState const filter = { meta: { negate: false, index: indexPatternName } }; filter[filterName] = { ignore_unmapped: true }; filter[filterName][field] = filterData; - getAppState().filters.push(filter); + getAppState().$newFilters = [filter]; this.vis.updateState(); } From f37eab9b449605a3a2b520a0445b84f0a5afe082 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Tue, 1 Aug 2017 13:31:51 -0700 Subject: [PATCH 048/165] [Framework/Accessibility] Add kuiScreenReaderOnly class (#13133) * [Framework/Accessibility] Add kuiScreenReaderOnly class * fix typo * use GuideLink * add screen_reader react component and tests * export KuiScreenReaderOnly * --wip-- [skip ci] * fix lint rule * remove obsolete snapshots --- .../__snapshots__/screen_reader.test.js.snap | 17 +++++++++ .../components/accessibility/_index.scss | 1 + .../accessibility/_screen_reader.scss | 8 +++++ .../components/accessibility/index.js | 1 + .../components/accessibility/screen_reader.js | 20 +++++++++++ .../accessibility/screen_reader.test.js | 35 ++++++++++++++++++ ui_framework/components/index.js | 1 + ui_framework/components/index.scss | 1 + ui_framework/dist/ui_framework.css | 8 +++++ .../accessibility/accessibility_example.js | 36 +++++++++++++++++++ .../src/views/accessibility/screen_reader.js | 23 ++++++++++++ 11 files changed, 151 insertions(+) create mode 100644 ui_framework/components/accessibility/__snapshots__/screen_reader.test.js.snap create mode 100644 ui_framework/components/accessibility/_index.scss create mode 100644 ui_framework/components/accessibility/_screen_reader.scss create mode 100644 ui_framework/components/accessibility/screen_reader.js create mode 100644 ui_framework/components/accessibility/screen_reader.test.js create mode 100644 ui_framework/doc_site/src/views/accessibility/screen_reader.js diff --git a/ui_framework/components/accessibility/__snapshots__/screen_reader.test.js.snap b/ui_framework/components/accessibility/__snapshots__/screen_reader.test.js.snap new file mode 100644 index 0000000000000..b1f99be5c72b5 --- /dev/null +++ b/ui_framework/components/accessibility/__snapshots__/screen_reader.test.js.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`KuiScreenReaderOnly adds an accessibility class to a child element and combines other classNames (foo, bar) given as props on the child 1`] = ` +

+ This paragraph is not visibile to sighted users but will be read by screenreaders. +

+`; + +exports[`KuiScreenReaderOnly adds an accessibility class to a child element when used with no props 1`] = ` +

+ This paragraph is not visibile to sighted users but will be read by screenreaders. +

+`; diff --git a/ui_framework/components/accessibility/_index.scss b/ui_framework/components/accessibility/_index.scss new file mode 100644 index 0000000000000..37ec009af1e99 --- /dev/null +++ b/ui_framework/components/accessibility/_index.scss @@ -0,0 +1 @@ +@import "./_screen_reader"; diff --git a/ui_framework/components/accessibility/_screen_reader.scss b/ui_framework/components/accessibility/_screen_reader.scss new file mode 100644 index 0000000000000..1d846635e21be --- /dev/null +++ b/ui_framework/components/accessibility/_screen_reader.scss @@ -0,0 +1,8 @@ +.kuiScreenReaderOnly { + position: absolute; + left: -10000px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; +} diff --git a/ui_framework/components/accessibility/index.js b/ui_framework/components/accessibility/index.js index 5b0bcc6eab80c..d847a370d0d94 100644 --- a/ui_framework/components/accessibility/index.js +++ b/ui_framework/components/accessibility/index.js @@ -1 +1,2 @@ export { KuiKeyboardAccessible } from './keyboard_accessible'; +export { KuiScreenReaderOnly } from './screen_reader'; diff --git a/ui_framework/components/accessibility/screen_reader.js b/ui_framework/components/accessibility/screen_reader.js new file mode 100644 index 0000000000000..53f40e28c3534 --- /dev/null +++ b/ui_framework/components/accessibility/screen_reader.js @@ -0,0 +1,20 @@ +import { + cloneElement, + PropTypes, +} from 'react'; +import classNames from 'classnames'; + + +export const KuiScreenReaderOnly = ({ children }) => { + const classes = classNames('kuiScreenReaderOnly', children.props.className); + + const props = Object.assign({}, children.props, { + className: classes + }); + + return cloneElement(children, props); +}; + +KuiScreenReaderOnly.propTypes = { + children: PropTypes.node +}; diff --git a/ui_framework/components/accessibility/screen_reader.test.js b/ui_framework/components/accessibility/screen_reader.test.js new file mode 100644 index 0000000000000..f22e2f4079e18 --- /dev/null +++ b/ui_framework/components/accessibility/screen_reader.test.js @@ -0,0 +1,35 @@ +import React from 'react'; +import { render } from 'enzyme'; + +import { KuiScreenReaderOnly } from './screen_reader'; + +describe('KuiScreenReaderOnly', () => { + describe('adds an accessibility class to a child element', () => { + test('when used with no props', () => { + const $paragraph = render( + +

+ This paragraph is not visibile to sighted users but will be read by + screenreaders. +

+
+ ); + + expect($paragraph) + .toMatchSnapshot(); + }); + test('and combines other classNames (foo, bar) given as props on the child', () => { + const $paragraph = render( + +

+ This paragraph is not visibile to sighted users but will be read by + screenreaders. +

+
+ ); + + expect($paragraph) + .toMatchSnapshot(); + }); + }); +}); diff --git a/ui_framework/components/index.js b/ui_framework/components/index.js index 982c193589e6e..7b5b3af2f3136 100644 --- a/ui_framework/components/index.js +++ b/ui_framework/components/index.js @@ -2,6 +2,7 @@ export { KuiActionItem } from './action_item'; export { KuiKeyboardAccessible, + KuiScreenReaderOnly, } from './accessibility'; export { diff --git a/ui_framework/components/index.scss b/ui_framework/components/index.scss index 63949ddd23a3d..85d81497714d2 100644 --- a/ui_framework/components/index.scss +++ b/ui_framework/components/index.scss @@ -19,6 +19,7 @@ @import "common_styles"; // Components +@import "accessibility/index"; @import "action_item/index"; @import "badge/index"; @import "bar/index"; diff --git a/ui_framework/dist/ui_framework.css b/ui_framework/dist/ui_framework.css index cc9213e37281c..19f75b13f797b 100644 --- a/ui_framework/dist/ui_framework.css +++ b/ui_framework/dist/ui_framework.css @@ -76,6 +76,14 @@ main { display: block; /* 1 */ } +.kuiScreenReaderOnly { + position: absolute; + left: -10000px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; } + .kuiActionItem { display: -webkit-box; display: -webkit-flex; diff --git a/ui_framework/doc_site/src/views/accessibility/accessibility_example.js b/ui_framework/doc_site/src/views/accessibility/accessibility_example.js index ca71a09e09c52..470127beea624 100644 --- a/ui_framework/doc_site/src/views/accessibility/accessibility_example.js +++ b/ui_framework/doc_site/src/views/accessibility/accessibility_example.js @@ -5,6 +5,7 @@ import { renderToHtml } from '../../services'; import { GuideCode, GuideDemo, + GuideLink, GuidePage, GuideSection, GuideSectionTypes, @@ -12,9 +13,14 @@ import { } from '../../components'; import KeyboardAccessible from './keyboard_accessible'; +import ScreenReaderOnly from './screen_reader'; + const keyboardAccessibleSource = require('!!raw!./keyboard_accessible'); const keyboardAccessibleHtml = renderToHtml(KeyboardAccessible); +const screenReaderOnlyHtml = renderToHtml(ScreenReaderOnly); +const screenReaderOnlySource = require('!!raw!./screen_reader'); + export default props => ( ( + + + + This class can be useful to add accessibility to older designs that are + still in use, but it shouldn't be a permanent solution. See + http://webaim.org/techniques/css/invisiblecontent/ + { + // eslint-disable-next-line react/jsx-closing-tag-location + } for more information. + + + + Use a screenreader to verify that there is a second paragraph in this example: + + + + + + ); diff --git a/ui_framework/doc_site/src/views/accessibility/screen_reader.js b/ui_framework/doc_site/src/views/accessibility/screen_reader.js new file mode 100644 index 0000000000000..49ac86d04cb09 --- /dev/null +++ b/ui_framework/doc_site/src/views/accessibility/screen_reader.js @@ -0,0 +1,23 @@ +import React from 'react'; + +import { + KuiScreenReaderOnly, +} from '../../../../components'; + + +export default () => ( +
+

+ This is the first paragraph. It is visible to all. +

+ +

+ This is the second paragraph. It is hidden for sighted users but visible to screen readers. +

+
+

+ This is the third paragraph. It is visible to all. +

+
+); + From 08719cd86340df6c80d2f34f5b43df5d4ef2d7a2 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 1 Aug 2017 14:11:23 -0700 Subject: [PATCH 049/165] [UI Framework] Spawn compileCss as a child process to prevent a node-sass fatal error from killing the watch process (#13222) * Spawn compileCss as a child process to prevent a node-sass fatal error from killing the watch process. * Document tasks. --- tasks/ui_framework.js | 62 ++++++++++++++++++++++++++++++------------ ui_framework/README.md | 6 +++- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/tasks/ui_framework.js b/tasks/ui_framework.js index abc65f0ec05cc..cb686f3beb010 100644 --- a/tasks/ui_framework.js +++ b/tasks/ui_framework.js @@ -3,6 +3,7 @@ import postcss from 'postcss'; import postcssConfig from '../src/optimize/postcss.config'; import chokidar from 'chokidar'; import debounce from 'lodash/function/debounce'; + const platform = require('os').platform(); const isPlatformWindows = /^win/.test(platform); @@ -44,6 +45,11 @@ module.exports = function (grunt) { Promise.all([uiFrameworkWatch(), uiFrameworkServerStart()]).then(done); }); + grunt.registerTask('uiFramework:compileCss', function () { + const done = this.async(); + uiFrameworkCompile().then(done); + }); + function uiFrameworkServerStart() { const serverCmd = { cmd: isPlatformWindows ? '.\\node_modules\\.bin\\webpack-dev-server.cmd' : './node_modules/.bin/webpack-dev-server', @@ -77,27 +83,49 @@ module.exports = function (grunt) { } function uiFrameworkCompile() { - sass.render({ - file: 'ui_framework/components/index.scss' - }, function (error, result) { - if (error) { - grunt.log.error(error); - } - - postcss([postcssConfig]) - .process(result.css, { from: 'ui_framework/components/index.scss', to: 'ui_framework/dist/ui_framework.css' }) - .then(result => { - grunt.file.write('ui_framework/dist/ui_framework.css', result.css); - - if (result.map) { - grunt.file.write('ui_framework/dist/ui_framework.css.map', result.map); - } - }); + const src = 'ui_framework/components/index.scss'; + const dest = 'ui_framework/dist/ui_framework.css'; + + return new Promise(resolve => { + sass.render({ + file: src, + }, function (error, result) { + if (error) { + grunt.log.error(error); + } + + postcss([postcssConfig]) + .process(result.css, { from: src, to: dest }) + .then(result => { + grunt.file.write(dest, result.css); + + if (result.map) { + grunt.file.write(`${dest}.map`, result.map); + } + + resolve(); + }); + }); }); } function uiFrameworkWatch() { - const debouncedCompile = debounce(uiFrameworkCompile, 400, { leading: true }); + const debouncedCompile = debounce(() => { + // Compile the SCSS in a separate process because node-sass throws a fatal error if it fails + // to compile. + grunt.util.spawn({ + cmd: isPlatformWindows ? '.\\node_modules\\.bin\\grunt.cmd' : './node_modules/.bin/grunt', + args: [ + 'uiFramework:compileCss', + ], + }, (error, result) => { + if (error) { + grunt.log.error(result.stdout); + } else { + grunt.log.writeln(result); + } + }); + }, 400, { leading: true }); return new Promise(() => { debouncedCompile(); diff --git a/ui_framework/README.md b/ui_framework/README.md index 67396c5dd312b..61bb97d16ba56 100644 --- a/ui_framework/README.md +++ b/ui_framework/README.md @@ -7,8 +7,12 @@ ### Documentation +Compile the CSS with `./node_modules/grunt/bin/grunt uiFramework:compileCss` (OS X) or +`.\node_modules\grunt\bin\grunt uiFramework:compileCss` (Windows). + You can view interactive documentation by running `npm run uiFramework:start` and then visiting -`http://localhost:8020/`. +`http://localhost:8020/`. This will also start watching the SCSS files, and will recompile the CSS +automatically for you when you make changes. You can run `node scripts/jest --watch` to watch for changes and run the tests as you code. From 3838fa5ae28fcfc2b4ea613b8a0684088dddb9d9 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 1 Aug 2017 17:29:48 -0400 Subject: [PATCH 050/165] ensure we are working with data-series (#13266) This fixes a regression introduced by https://github.com/elastic/kibana/pull/13217. --- src/ui/public/vislib/lib/dispatch.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ui/public/vislib/lib/dispatch.js b/src/ui/public/vislib/lib/dispatch.js index 02f059960a23c..74edb63fe54c4 100644 --- a/src/ui/public/vislib/lib/dispatch.js +++ b/src/ui/public/vislib/lib/dispatch.js @@ -57,9 +57,16 @@ export function VislibLibDispatchProvider(Private, config) { }; if (isSeries) { - // Find object with the actual d value and add it to the point object - const aggId = d3.event.target.parentElement.__data__.aggId; - const percentageMode = handler.charts[0].getSeries(aggId).getValueAxis().axisConfig.isPercentage(); + let percentageMode = false; + //only series charts work in percentage mode. + if (handler.charts && handler.charts[0] && handler.charts[0].getSeries && d3.event.target.parentElement.__data__) { + const aggId = d3.event.target.parentElement.__data__.aggId; + const seriesFromAggId = handler.charts[0].getSeries(aggId); + if (seriesFromAggId && seriesFromAggId.getValueAxis) { + percentageMode = seriesFromAggId.getValueAxis().axisConfig.isPercentage(); + } + } + const object = _.find(series, { 'label': label }); if (object) { eventData.value = +object.values[i].y; From c33ac752ebd86a3e5c5608f21d177d7f0c9df05e Mon Sep 17 00:00:00 2001 From: Court Ewing Date: Tue, 1 Aug 2017 20:43:42 -0400 Subject: [PATCH 051/165] Revert "override version until elastic/elasticsearch#25876 is merged" (#13196) This reverts commit ce8333b70f6034735afc08c4c6792bb1bbc22e89. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cd9aab51392bb..000082eda64de 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dashboarding" ], "private": false, - "version": "6.0.0-beta1", + "version": "7.0.0-alpha1", "branch": "master", "build": { "number": 8467, From 0aa4206d2ce8455693b476667022a1b36e7cb812 Mon Sep 17 00:00:00 2001 From: Spencer Date: Tue, 1 Aug 2017 18:33:39 -0700 Subject: [PATCH 052/165] [npm] upgrade postcss-loader (#13279) Needed to get a version that included https://github.com/postcss/postcss-loader/pull/174 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 000082eda64de..3484dad4a828e 100644 --- a/package.json +++ b/package.json @@ -157,7 +157,7 @@ "no-ui-slider": "1.2.0", "node-fetch": "1.3.2", "pegjs": "0.9.0", - "postcss-loader": "1.2.1", + "postcss-loader": "1.3.3", "proxy-from-env": "1.0.0", "prop-types": "15.5.8", "pui-react-overlay-trigger": "7.5.4", From 10280e8f9c540847f0aee0469e9c74dfaaf0013a Mon Sep 17 00:00:00 2001 From: ytzlax Date: Wed, 2 Aug 2017 18:46:50 +0300 Subject: [PATCH 053/165] Add Kibana API plugin (#13206) --- docs/plugins/known-plugins.asciidoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/plugins/known-plugins.asciidoc b/docs/plugins/known-plugins.asciidoc index 6e16a618e9864..93e4038291041 100644 --- a/docs/plugins/known-plugins.asciidoc +++ b/docs/plugins/known-plugins.asciidoc @@ -48,4 +48,8 @@ This list of plugins is not guaranteed to work on your version of Kibana. Instea === Other * https://github.com/nreese/kibana-time-plugin[Time picker as a dashboard panel] Widget to view and edit the time range from within dashboards. +* https://github.com/Webiks/kibana-API.git[Kibana-API] (webiks) Exposes an API with Kibana functionality. +Use it to create, edit and embed visualizations, and also to search inside an embedded dashboard. + + NOTE: If you want your plugin to be added to this page, open a {repo}tree/{branch}/docs/plugins/known-plugins.asciidoc[pull request]. From f78bb5dc11ce8948b5b810022d7330ff00269c9a Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Wed, 2 Aug 2017 15:16:00 -0400 Subject: [PATCH 054/165] Add Kuery docs and break search page into subsections (#13074) * Add Kuery docs and break search page into subsections --- docs/discover/kuery.asciidoc | 115 ++++++++++++++++++++++++++++++++++ docs/discover/search.asciidoc | 47 +++++++++----- 2 files changed, 145 insertions(+), 17 deletions(-) create mode 100644 docs/discover/kuery.asciidoc diff --git a/docs/discover/kuery.asciidoc b/docs/discover/kuery.asciidoc new file mode 100644 index 0000000000000..af19622484485 --- /dev/null +++ b/docs/discover/kuery.asciidoc @@ -0,0 +1,115 @@ +[[kuery-query]] +=== Kuery + +experimental[This functionality is experimental and may be changed or removed completely in a future release.] + +Kuery is a new query language built specifically for Kibana. It aims to simplify the search experience in Kibana +and enable the creation of helpful features like auto-complete, seamless migration of saved searches, additional +query types, and more. Kuery is a basic experience today but we're hard at work building these additional features on +top of the foundation Kuery provides. + +Kueries are built with functions. Many functions take a field name as their first argument. Extremely common functions have shorthand notations. + +`is("response", 200)` will match documents where the response field matches the value 200. +`response:200` does the same thing. `:` is an alias for the `is` function. + +Multiple search terms are separated by whitespace. + +`response:200 extension:php` will match documents where response matches 200 and extension matches php. + +All terms must match by default. The language supports boolean logic with and/or operators. The above query is equivalent to `response:200 and extension:php`. + +We can make terms optional by using `or`. + +`response:200 or extension:php` will match documents where response matches 200, extension matches php, or both. + +By default, `and` has a higher precedence than `or`. + +`response:200 and extension:php or extension:css` will match documents where response is 200 and extension is php OR documents where extension is css and response is anything. + +We can override the default precedence with grouping. + +`response:200 and (extension:php or extension:css)` will match documents where response is 200 and extension is either php or css. + +Terms can be inverted by prefixing them with `!`. + +`!response:200` will match all documents where response is not 200. + +Entire groups can also be inverted. + +`response:200 and !(extension:php or extension:css)` + +Some query functions have named arguments. + +`range("bytes", gt=1000, lt=8000)` will match documents where the bytes field is greater than 1000 and less than 8000. + +Quotes are generally optional if your terms don't have whitespace or special characters. `range(bytes, gt=1000, lt=8000)` +would also be a valid query. + +[NOTE] +============ +Terms without fields will be matched against all fields. For example, a query for `response:200` will search for the value 200 +in the response field, but a query for just `200` will search for 200 across all fields in your index. +============ + +==== Function Reference + +[horizontal] +Function Name:: Description + +and:: +Purpose::: Match all given sub-queries +Alias::: `and` as a binary operator +Examples::: +* `and(response:200, extension:php)` +* `response:200 and extension:php` + +or:: +Purpose::: Match one or more sub-queries +Alias::: `or` as a binary operator +Examples::: +* `or(extension:css, extension:php)` +* `extension:css or extension:php` + +not:: +Purpose::: Negates a sub-query +Alias::: `!` as a prefix operator +Examples::: +* `not(response:200)` +* `!response:200` + +is:: +Purpose::: Matches a field with a given term +Alias::: `:` +Examples::: +* `is("response", 200)` +* `response:200` + +range:: +Purpose::: Match a field against a range of values. +Alias::: `:[]` +Examples::: +* `range("bytes", gt=1000, lt=8000)` +* `bytes:[1000 to 8000]` +Named arguments::: +* `gt` - greater than +* `gte` - greater than or equal to +* `lt` - less than +* `lte` - less than or equal to + +exists:: +Purpose::: Match documents where a given field exists +Examples::: `exists("response")` + +geoBoundingBox:: +Purpose::: Creates a geo_bounding_box query +Examples::: +* `geoBoundingBox("coordinates", topLeft="40.73, -74.1", bottomRight="40.01, -71.12")` (whitespace between lat and lon is ignored) +Named arguments::: +* `topLeft` - the top left corner of the bounding box as a "lat, lon" string +* `bottomRight` - the bottom right corner of the bounding box as a "lat, lon" string + +geoPolygon:: +Purpose::: Creates a geo_polygon query given 3 or more points as "lat, lon" +Examples::: +* `geoPolygon("geo.coordinates", "40.97, -127.26", "24.20, -84.375", "40.44, -66.09")` \ No newline at end of file diff --git a/docs/discover/search.asciidoc b/docs/discover/search.asciidoc index a1b141d826147..f63680d15255c 100644 --- a/docs/discover/search.asciidoc +++ b/docs/discover/search.asciidoc @@ -1,10 +1,10 @@ [[search]] == Searching Your Data You can search the indices that match the current index pattern by entering -your search criteria in the Query bar. You can perform a simple text search, -use the Lucene https://lucene.apache.org/core/2_9_4/queryparsersyntax.html[ -query syntax], or use the full JSON-based {ref}/query-dsl.html[Elasticsearch -Query DSL]. +your search criteria in the Query bar. You can use the Lucene +https://lucene.apache.org/core/2_9_4/queryparsersyntax.html[ +query syntax], the full JSON-based {ref}/query-dsl.html[Elasticsearch +Query DSL] or Kuery, an experimental new query language built specifically for Kibana. When you submit a search request, the histogram, Documents table, and Fields list are updated to reflect the search results. The total number of hits @@ -19,6 +19,17 @@ To search your data, enter your search criteria in the Query bar and press *Enter* or click *Search* image:images/search-button.jpg[] to submit the request to Elasticsearch. +[NOTE] +=========== +By default, Kibana will accept either the Lucene query syntax or the +Elasticsearch Query DSL in the Query bar. In order to use the new Kuery +language you must enable language switching in *Management > Advanced Settings* +via the `search:queryLanguage:switcher:enable` option. You can also change the +default language with the `search:queryLanguage` setting. +=========== + +[[lucene-query]] +=== Lucene Query Syntax * To perform a free text search, simply enter a text string. For example, if you're searching web server logs, you could enter `safari` to search all fields for the term `safari`. @@ -36,18 +47,22 @@ status codes, you could enter `status:[400 TO 499]`. codes and have an extension of `php` or `html`, you could enter `status:[400 TO 499] AND (extension:php OR extension:html)`. -NOTE: These examples use the Lucene query syntax. You can also submit queries -using the Elasticsearch Query DSL. For examples, see -{ref}/query-dsl-query-string-query.html#query-string-syntax[query string syntax] -in the Elasticsearch Reference. +For more detailed information about the Lucene query syntax, see the +{ref}/query-dsl-query-string-query.html#query-string-syntax[Query String Query] +docs. -[float] -[[save-search]] -=== Saving a Search +NOTE: These examples use the Lucene query syntax. When lucene is selected as your +query language you can also submit queries using the {ref}/query-dsl.html[Elasticsearch Query DSL]. + +include::kuery.asciidoc[] + +[[save-open-search]] +=== Saving and Opening Searches Saving searches enables you to reload them into Discover and use them as the basis for <>. Saving a search saves both the search query string and the currently selected index pattern. +==== Saving a Search To save the current search: . Click *Save* in the Kibana toolbar. @@ -55,18 +70,17 @@ To save the current search: You can import, export and delete saved searches from *Management/Kibana/Saved Objects*. -[float] -[[load-search]] -=== Opening a Saved Search +==== Opening a Saved Search To load a saved search into Discover: . Click *Open* in the Kibana toolbar. . Select the search you want to open. If the saved search is associated with a different index pattern than is currently -selected, opening the saved search also changes the selected index pattern. +selected, opening the saved search changes the selected index pattern. The query language +used for the saved search will also be automatically selected. + -[float] [[select-pattern]] === Changing Which Indices You're Searching When you submit a search request, the indices that match the currently-selected @@ -77,7 +91,6 @@ different index pattern. For more information about index patterns, see <>. -[float] [[autorefresh]] === Refreshing the Search Results As more documents are added to the indices you're searching, the search results From c68c0d6588a7d182e789b820eff8f2ecfe8694f4 Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 2 Aug 2017 13:25:53 -0700 Subject: [PATCH 055/165] [ui/routes] clone defaults before apply (#13295) * [ui/routes] add failing tests * [ui/routes] clone defaults before applying them * Mention issue in related tests --- .../public/routes/__tests__/_route_manager.js | 67 +++++++++++++++++++ src/ui/public/routes/route_manager.js | 4 +- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/ui/public/routes/__tests__/_route_manager.js b/src/ui/public/routes/__tests__/_route_manager.js index ef53b44dc442d..1291aacb815e0 100644 --- a/src/ui/public/routes/__tests__/_route_manager.js +++ b/src/ui/public/routes/__tests__/_route_manager.js @@ -113,4 +113,71 @@ describe('routes/route_manager', function () { expect($rp.when.lastCall.args[1]).to.have.property('requireDefaultIndex', true); }); }); + + describe('#defaults()', () => { + it('adds defaults to routes with matching paths', () => { + routes.when('/foo', { name: 'foo' }); + routes.when('/bar', { name: 'bar' }); + routes.when('/baz', { name: 'baz' }); + routes.defaults(/^\/ba/, { + withDefaults: true + }); + routes.config($rp); + + sinon.assert.calledWithExactly($rp.when, '/foo', sinon.match({ name: 'foo', withDefaults: undefined })); + sinon.assert.calledWithExactly($rp.when, '/bar', sinon.match({ name: 'bar', withDefaults: true })); + sinon.assert.calledWithExactly($rp.when, '/baz', sinon.match({ name: 'baz', withDefaults: true })); + }); + + it('does not override values specified in the route', () => { + routes.when('/foo', { name: 'foo' }); + routes.defaults(/./, { name: 'bar' }); + routes.config($rp); + + sinon.assert.calledWithExactly($rp.when, '/foo', sinon.match({ name: 'foo' })); + }); + + // See https://github.com/elastic/kibana/issues/13294 + it('does not assign defaults by reference, to prevent accidentally merging unrelated defaults together', () => { + routes.when('/foo', { name: 'foo' }); + routes.when('/bar', { name: 'bar' }); + routes.when('/baz', { name: 'baz', funcs: { bazFunc() {} } }); + + // multiple defaults must be defined that, when applied correctly, will + // create a new object property on all routes that is unique to all of them + routes.defaults(/./, { funcs: { all() {} } }); + routes.defaults(/^\/foo/, { funcs: { fooFunc() {} } }); + routes.defaults(/^\/bar/, { funcs: { barFunc() {} } }); + routes.config($rp); + + sinon.assert.calledThrice($rp.when); + sinon.assert.calledWithExactly($rp.when, '/foo', sinon.match({ + name: 'foo', + funcs: sinon.match({ + all: sinon.match.func, + fooFunc: sinon.match.func, + barFunc: undefined, + bazFunc: undefined, + }) + })); + sinon.assert.calledWithExactly($rp.when, '/bar', sinon.match({ + name: 'bar', + funcs: sinon.match({ + all: sinon.match.func, + fooFunc: undefined, + barFunc: sinon.match.func, + bazFunc: undefined, + }) + })); + sinon.assert.calledWithExactly($rp.when, '/baz', sinon.match({ + name: 'baz', + funcs: sinon.match({ + all: sinon.match.func, + fooFunc: undefined, + barFunc: undefined, + bazFunc: sinon.match.func, + }) + })); + }); + }); }); diff --git a/src/ui/public/routes/route_manager.js b/src/ui/public/routes/route_manager.js index 356525aabb4fb..4b17fbfdbdffb 100644 --- a/src/ui/public/routes/route_manager.js +++ b/src/ui/public/routes/route_manager.js @@ -1,4 +1,4 @@ -import { defaultsDeep, wrap } from 'lodash'; +import { cloneDeep, defaultsDeep, wrap } from 'lodash'; import { wrapRouteWithPrep } from './wrap_route_with_prep'; import { RouteSetupManager } from './route_setup_manager'; @@ -19,7 +19,7 @@ export default function RouteManager() { defaults.forEach(def => { if (def.regex.test(path)) { - defaultsDeep(route, def.value); + defaultsDeep(route, cloneDeep(def.value)); } }); From cb222d74e8d1a0c8b8740c38e185baba218fcce7 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Thu, 3 Aug 2017 11:42:21 +0200 Subject: [PATCH 056/165] Introduce logging `JsonLayout`. (#13180) --- package-lock.json | 39 ++++++------ platform/logging/README.md | 55 ++++++++++++----- platform/logging/layouts/JsonLayout.ts | 32 ++++++++++ platform/logging/layouts/Layouts.ts | 20 ++++++- .../layouts/__tests__/JsonLayout.test.ts | 59 +++++++++++++++++++ .../logging/layouts/__tests__/Layouts.test.ts | 16 +++-- .../layouts/__tests__/PatternLayout.test.ts | 9 +-- .../__snapshots__/JsonLayout.test.ts.snap | 13 ++++ .../__snapshots__/PatternLayout.test.ts.snap | 12 ++++ 9 files changed, 204 insertions(+), 51 deletions(-) create mode 100644 platform/logging/layouts/JsonLayout.ts create mode 100644 platform/logging/layouts/__tests__/JsonLayout.test.ts create mode 100644 platform/logging/layouts/__tests__/__snapshots__/JsonLayout.test.ts.snap diff --git a/package-lock.json b/package-lock.json index 9fc693f73dabd..aeecba7a4e02b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "kibana", - "version": "6.0.0-alpha3", + "version": "6.0.0-beta1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -125,11 +125,6 @@ "integrity": "sha1-JZrqlH1quqovUEMWliMd7ypSKSY=", "dev": true }, - "@elastic/httpolyglot": { - "version": "0.1.2-elasticpatch1", - "resolved": "https://registry.npmjs.org/@elastic/httpolyglot/-/httpolyglot-0.1.2-elasticpatch1.tgz", - "integrity": "sha1-gSKFp7EA/2ETzICA3SJomEvMSIM=" - }, "@elastic/webpack-directory-name-as-main": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@elastic/webpack-directory-name-as-main/-/webpack-directory-name-as-main-2.0.2.tgz", @@ -10215,9 +10210,9 @@ } }, "makelogs": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/makelogs/-/makelogs-4.0.1.tgz", - "integrity": "sha1-3JiZuT1SNTp12OMs5wtDEtiEl3E=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/makelogs/-/makelogs-4.0.2.tgz", + "integrity": "sha1-T7vhOY/H8LvEiXoeUTlqDBkA2xo=", "dev": true, "requires": { "async": "1.5.2", @@ -10250,6 +10245,19 @@ "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", "dev": true }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, "cli-width": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", @@ -10286,19 +10294,6 @@ "through": "2.3.8" }, "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, "lodash": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", diff --git a/platform/logging/README.md b/platform/logging/README.md index 746e7abe638cb..65fe64b045801 100644 --- a/platform/logging/README.md +++ b/platform/logging/README.md @@ -43,12 +43,30 @@ the log record is ignored. The _all_ and _off_ levels can be used only in configuration and are just handy shortcuts that allow developer to log every log record or disable logging entirely for the specific context. +## Layouts + +Every appender should know exactly how to format log messages before they are written to the console or file on the disk. +This behaviour is controlled by the layouts and configured through `appender.layout` configuration property for every +custom appender (see examples in [Configuration](#configuration)). Currently we don't define any default layout for the +custom appenders, so one should always make the choice explicitly. + +There are two types of layout supported at the moment: `pattern` and `json`. + +With `pattern` layout it's possible to define a string pattern with special placeholders wrapped into curly braces that +will be replaced with data from the actual log message. By default the following pattern is used: +`[{timestamp}][{level}][{context}] {message}`. Also `highlight` option can be enabled for `pattern` layout so that +some parts of the log message are highlighted with different colors that may be quite handy if log messages are forwarded +to the terminal with color support. + +With `json` layout log messages will be formatted as JSON strings that include timestamp, log level, context, message +text and any other metadata that may be associated with the log message itself. + ## Configuration As any configuration in the platform, logging configuration is validated against the predefined schema and if there are any issues with it, Kibana will fail to start with the detailed error message. -Once your code acquired a logger instance it should not care about any runtime changes in the configuration that may +Once the code acquired a logger instance it should not care about any runtime changes in the configuration that may happen: all changes will be applied to existing logger instances under the hood. Here is the configuration example that can be used to configure _loggers_, _appenders_ and _layouts_: @@ -63,7 +81,7 @@ logging: highlight: true file: kind: file - path: ~/Downloads/kibana.log + path: /var/log/kibana.log layout: kind: pattern custom: @@ -71,6 +89,9 @@ logging: layout: kind: pattern pattern: [{timestamp}][{level}] {message} + json-file-appender: + kind: file + path: /var/log/kibana-json.log root: appenders: [console, file] @@ -86,21 +107,26 @@ logging: level: fatal - context: optimize appenders: [console] + - context: telemetry + level: all + appenders: [json-file-appender] ``` -Here is what you get with the config above: +Here is what we get with the config above: -| Context | Appenders | Level | -| ------------- |:-------------:| -----:| -| root | console, file | error | -| plugins | custom | warn | -| plugins.pid | custom | info | -| server | console, file | fatal | -| optimize | console | error | +| Context | Appenders | Level | +| ------------- |:------------------------:| -----:| +| root | console, file | error | +| plugins | custom | warn | +| plugins.pid | custom | info | +| server | console, file | fatal | +| optimize | console | error | +| telemetry | json-file-appender | all | -As you see `root` logger has a dedicated configuration node since this context is special and should always exist. By + +The `root` logger has a dedicated configuration node since this context is special and should always exist. By default `root` is configured with `info` level and `default` appender that is also always available. This is the -configuration that all your loggers will use unless you re-configure them explicitly. +configuration that all custom loggers will use unless they're re-configured explicitly. For example to see _all_ log messages that fall back on the `root` logger configuration, just add one line to the configuration: @@ -134,7 +160,7 @@ loggerWithNestedContext.trace('Message with `trace` log level.'); loggerWithNestedContext.debug('Message with `debug` log level.'); ``` -And assuming you're using `console` appender and `trace` level for `server` context, in console you'll see: +And assuming logger for `server` context with `console` appender and `trace` level was used, console output will look like this: ```bash [2017-07-25T18:54:41.639Z][TRACE][server] Message with `trace` log level. [2017-07-25T18:54:41.639Z][DEBUG][server] Message with `debug` log level. @@ -147,10 +173,9 @@ And assuming you're using `console` appender and `trace` level for `server` cont [2017-07-25T18:54:41.639Z][DEBUG][server.http] Message with `debug` log level. ``` -Obviously your log will be less verbose with `warn` level for the `server` context: +The log will be less verbose with `warn` level for the `server` context: ```bash [2017-07-25T18:54:41.639Z][WARN ][server] Message with `warn` log level. [2017-07-25T18:54:41.639Z][ERROR][server] Message with `error` log level. [2017-07-25T18:54:41.639Z][FATAL][server] Message with `fatal` log level. ``` - diff --git a/platform/logging/layouts/JsonLayout.ts b/platform/logging/layouts/JsonLayout.ts new file mode 100644 index 0000000000000..663adf56746ff --- /dev/null +++ b/platform/logging/layouts/JsonLayout.ts @@ -0,0 +1,32 @@ +import { Schema, typeOfSchema } from '../../types'; +import { LogRecord } from '../LogRecord'; +import { Layout } from './Layouts'; + +const createSchema = ({ literal, object }: Schema) => { + return object({ + kind: literal('json') + }); +}; + +const schemaType = typeOfSchema(createSchema); +/** @internal */ +export type JsonLayoutConfigType = typeof schemaType; + +/** + * Layout that just converts `LogRecord` into JSON string. + * @internal + */ +export class JsonLayout implements Layout { + static createConfigSchema = createSchema; + + format({ timestamp, level, context, message, error, meta }: LogRecord): string { + return JSON.stringify({ + '@timestamp': timestamp.toISOString(), + level: level.id.toUpperCase(), + context, + message, + error: error && error.message, + meta + }); + } +} diff --git a/platform/logging/layouts/Layouts.ts b/platform/logging/layouts/Layouts.ts index 0fb9d82201008..40bff2cdd8510 100644 --- a/platform/logging/layouts/Layouts.ts +++ b/platform/logging/layouts/Layouts.ts @@ -1,8 +1,10 @@ +import { assertNever } from '../../lib/utils'; import { Schema } from '../../types'; +import { JsonLayout, JsonLayoutConfigType } from './JsonLayout'; import { PatternLayout, PatternLayoutConfigType } from './PatternLayout'; import { LogRecord } from '../LogRecord'; -type LayoutConfigType = PatternLayoutConfigType; +type LayoutConfigType = PatternLayoutConfigType | JsonLayoutConfigType; /** * Entity that can format `LogRecord` instance into a string. @@ -15,7 +17,12 @@ export interface Layout { /** @internal */ export class Layouts { static createConfigSchema(schema: Schema) { - return PatternLayout.createConfigSchema(schema); + const { oneOf } = schema; + + return oneOf([ + JsonLayout.createConfigSchema(schema), + PatternLayout.createConfigSchema(schema) + ]); } /** @@ -24,6 +31,13 @@ export class Layouts { * @returns Fully constructed `Layout` instance. */ static create(config: LayoutConfigType): Layout { - return new PatternLayout(config.pattern, config.highlight); + switch (config.kind) { + case 'json': + return new JsonLayout(); + case 'pattern': + return new PatternLayout(config.pattern, config.highlight); + default: + return assertNever(config); + } } } diff --git a/platform/logging/layouts/__tests__/JsonLayout.test.ts b/platform/logging/layouts/__tests__/JsonLayout.test.ts new file mode 100644 index 0000000000000..4434085829268 --- /dev/null +++ b/platform/logging/layouts/__tests__/JsonLayout.test.ts @@ -0,0 +1,59 @@ +import * as mockSchema from '../../../lib/schema'; + +import { LogLevel } from '../../LogLevel'; +import { LogRecord } from '../../LogRecord'; +import { JsonLayout } from '../JsonLayout'; + +const records: LogRecord[] = [ + { + timestamp: new Date(2012, 1, 1), + message: 'message-1', + context: 'context-1', + error: new Error('Some error message'), + level: LogLevel.Fatal + }, + { + timestamp: new Date(2012, 1, 1), + message: 'message-2', + context: 'context-2', + level: LogLevel.Error + }, + { + timestamp: new Date(2012, 1, 1), + message: 'message-3', + context: 'context-3', + level: LogLevel.Warn + }, + { + timestamp: new Date(2012, 1, 1), + message: 'message-4', + context: 'context-4', + level: LogLevel.Debug + }, + { + timestamp: new Date(2012, 1, 1), + message: 'message-5', + context: 'context-5', + level: LogLevel.Info + }, + { + timestamp: new Date(2012, 1, 1), + message: 'message-6', + context: 'context-6', + level: LogLevel.Trace + } +]; + +test('`createConfigSchema()` creates correct schema.', () => { + const layoutSchema = JsonLayout.createConfigSchema(mockSchema); + + expect(layoutSchema.validate({ kind: 'json' })).toEqual({ kind: 'json' }); +}); + +test('`format()` correctly formats record.', () => { + const layout = new JsonLayout(); + + for (const record of records) { + expect(layout.format(record)).toMatchSnapshot(); + } +}); diff --git a/platform/logging/layouts/__tests__/Layouts.test.ts b/platform/logging/layouts/__tests__/Layouts.test.ts index 01c9e3207a529..096e19f40281b 100644 --- a/platform/logging/layouts/__tests__/Layouts.test.ts +++ b/platform/logging/layouts/__tests__/Layouts.test.ts @@ -1,8 +1,9 @@ import * as mockSchema from '../../../lib/schema'; +import { JsonLayout } from '../JsonLayout'; import { PatternLayout } from '../PatternLayout'; import { Layouts } from '../Layouts'; -test('`createConfigSchema()` creates correct schema.', () => { +test('`createConfigSchema()` creates correct schema for `pattern` layout.', () => { const layoutsSchema = Layouts.createConfigSchema(mockSchema); const validConfigWithOptional = { kind: 'pattern' }; expect(layoutsSchema.validate(validConfigWithOptional)).toEqual({ @@ -22,13 +23,17 @@ test('`createConfigSchema()` creates correct schema.', () => { highlight: true }); - const wrongConfig1 = { kind: 'json' }; - expect(() => layoutsSchema.validate(wrongConfig1)).toThrow(); - const wrongConfig2 = { kind: 'pattern', pattern: 1 }; expect(() => layoutsSchema.validate(wrongConfig2)).toThrow(); }); +test('`createConfigSchema()` creates correct schema for `json` layout.', () => { + const layoutsSchema = Layouts.createConfigSchema(mockSchema); + + const validConfig = { kind: 'json' }; + expect(layoutsSchema.validate(validConfig)).toEqual({ kind: 'json' }); +}); + test('`create()` creates correct layout.', () => { const patternLayout = Layouts.create({ kind: 'pattern', @@ -36,4 +41,7 @@ test('`create()` creates correct layout.', () => { highlight: false }); expect(patternLayout).toBeInstanceOf(PatternLayout); + + const jsonLayout = Layouts.create({ kind: 'json' }); + expect(jsonLayout).toBeInstanceOf(JsonLayout); }); diff --git a/platform/logging/layouts/__tests__/PatternLayout.test.ts b/platform/logging/layouts/__tests__/PatternLayout.test.ts index ea8cb232a964f..0da8d888a5c0a 100644 --- a/platform/logging/layouts/__tests__/PatternLayout.test.ts +++ b/platform/logging/layouts/__tests__/PatternLayout.test.ts @@ -9,7 +9,7 @@ const records: LogRecord[] = [ timestamp: new Date(2012, 1, 1), message: 'message-1', context: 'context-1', - error: new Error('Error'), + error: new Error('Some error message'), level: LogLevel.Fatal }, { @@ -76,12 +76,7 @@ test('`format()` correctly formats record with full pattern.', () => { const layout = new PatternLayout(); for (const record of records) { - const { timestamp, level, context, message } = record; - const formattedLevel = level.id.toUpperCase().padEnd(5); - - expect(layout.format(record)).toBe( - `[${timestamp.toISOString()}][${formattedLevel}][${context}] ${message}` - ); + expect(layout.format(record)).toMatchSnapshot(); } }); diff --git a/platform/logging/layouts/__tests__/__snapshots__/JsonLayout.test.ts.snap b/platform/logging/layouts/__tests__/__snapshots__/JsonLayout.test.ts.snap new file mode 100644 index 0000000000000..00f3808fa6058 --- /dev/null +++ b/platform/logging/layouts/__tests__/__snapshots__/JsonLayout.test.ts.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`\`format()\` correctly formats record. 1`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-1\\",\\"context\\":\\"context-1\\",\\"error\\":\\"Some error message\\",\\"level\\":{\\"id\\":\\"fatal\\",\\"value\\":2}}"`; + +exports[`\`format()\` correctly formats record. 2`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-2\\",\\"context\\":\\"context-2\\",\\"level\\":{\\"id\\":\\"error\\",\\"value\\":3}}"`; + +exports[`\`format()\` correctly formats record. 3`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-3\\",\\"context\\":\\"context-3\\",\\"level\\":{\\"id\\":\\"warn\\",\\"value\\":4}}"`; + +exports[`\`format()\` correctly formats record. 4`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-4\\",\\"context\\":\\"context-4\\",\\"level\\":{\\"id\\":\\"debug\\",\\"value\\":6}}"`; + +exports[`\`format()\` correctly formats record. 5`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-5\\",\\"context\\":\\"context-5\\",\\"level\\":{\\"id\\":\\"info\\",\\"value\\":5}}"`; + +exports[`\`format()\` correctly formats record. 6`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-6\\",\\"context\\":\\"context-6\\",\\"level\\":{\\"id\\":\\"trace\\",\\"value\\":7}}"`; diff --git a/platform/logging/layouts/__tests__/__snapshots__/PatternLayout.test.ts.snap b/platform/logging/layouts/__tests__/__snapshots__/PatternLayout.test.ts.snap index b0623799c83cc..0f883a4977bd2 100644 --- a/platform/logging/layouts/__tests__/__snapshots__/PatternLayout.test.ts.snap +++ b/platform/logging/layouts/__tests__/__snapshots__/PatternLayout.test.ts.snap @@ -1,5 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`\`format()\` correctly formats record with full pattern. 1`] = `"[2012-01-31T23:00:00.000Z][FATAL][context-1] message-1"`; + +exports[`\`format()\` correctly formats record with full pattern. 2`] = `"[2012-01-31T23:00:00.000Z][ERROR][context-2] message-2"`; + +exports[`\`format()\` correctly formats record with full pattern. 3`] = `"[2012-01-31T23:00:00.000Z][WARN ][context-3] message-3"`; + +exports[`\`format()\` correctly formats record with full pattern. 4`] = `"[2012-01-31T23:00:00.000Z][DEBUG][context-4] message-4"`; + +exports[`\`format()\` correctly formats record with full pattern. 5`] = `"[2012-01-31T23:00:00.000Z][INFO ][context-5] message-5"`; + +exports[`\`format()\` correctly formats record with full pattern. 6`] = `"[2012-01-31T23:00:00.000Z][TRACE][context-6] message-6"`; + exports[`\`format()\` correctly formats record with highlighting. 1`] = `"[2012-01-31T23:00:00.000Z][FATAL][context-1] message-1"`; exports[`\`format()\` correctly formats record with highlighting. 2`] = `"[2012-01-31T23:00:00.000Z][ERROR][context-2] message-2"`; From 432e6c158be05bea022e8fd4fd6cbb9ddd633d70 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Thu, 3 Aug 2017 14:11:43 +0200 Subject: [PATCH 057/165] Print `error.stack` for pattern layout and `error.message`, `error.stack` and `error.name` for json layout. (#13309) --- platform/logging/layouts/JsonLayout.ts | 26 ++++++++++++++----- platform/logging/layouts/PatternLayout.ts | 4 ++- .../layouts/__tests__/JsonLayout.test.ts | 6 ++++- .../layouts/__tests__/PatternLayout.test.ts | 9 ++++--- .../__snapshots__/JsonLayout.test.ts.snap | 12 ++++----- .../__snapshots__/PatternLayout.test.ts.snap | 16 ++++++++++-- 6 files changed, 53 insertions(+), 20 deletions(-) diff --git a/platform/logging/layouts/JsonLayout.ts b/platform/logging/layouts/JsonLayout.ts index 663adf56746ff..64675a795cb24 100644 --- a/platform/logging/layouts/JsonLayout.ts +++ b/platform/logging/layouts/JsonLayout.ts @@ -19,14 +19,26 @@ export type JsonLayoutConfigType = typeof schemaType; export class JsonLayout implements Layout { static createConfigSchema = createSchema; - format({ timestamp, level, context, message, error, meta }: LogRecord): string { + format(record: LogRecord): string { return JSON.stringify({ - '@timestamp': timestamp.toISOString(), - level: level.id.toUpperCase(), - context, - message, - error: error && error.message, - meta + '@timestamp': record.timestamp.toISOString(), + level: record.level.id.toUpperCase(), + context: record.context, + message: record.message, + error: JsonLayout.errorToSerializableObject(record.error), + meta: record.meta }); } + + private static errorToSerializableObject(error: Error | undefined) { + if (error === undefined) { + return error; + } + + return { + name: error.name, + stack: error.stack, + message: error.message + }; + } } diff --git a/platform/logging/layouts/PatternLayout.ts b/platform/logging/layouts/PatternLayout.ts index c9f7bdb005c99..e84cfefbe2cd1 100644 --- a/platform/logging/layouts/PatternLayout.ts +++ b/platform/logging/layouts/PatternLayout.ts @@ -70,11 +70,13 @@ export class PatternLayout implements Layout { * @param record Instance of `LogRecord` to format into string. */ format(record: LogRecord): string { + // Error stack is much more useful than just the message. + const message = (record.error && record.error.stack) || record.message; const formattedRecord = new Map([ [Parameters.Timestamp, record.timestamp.toISOString()], [Parameters.Level, record.level.id.toUpperCase().padEnd(5)], [Parameters.Context, record.context], - [Parameters.Message, record.message] + [Parameters.Message, message] ]); if (this.highlight) { diff --git a/platform/logging/layouts/__tests__/JsonLayout.test.ts b/platform/logging/layouts/__tests__/JsonLayout.test.ts index 4434085829268..d5e674ebfd241 100644 --- a/platform/logging/layouts/__tests__/JsonLayout.test.ts +++ b/platform/logging/layouts/__tests__/JsonLayout.test.ts @@ -9,7 +9,11 @@ const records: LogRecord[] = [ timestamp: new Date(2012, 1, 1), message: 'message-1', context: 'context-1', - error: new Error('Some error message'), + error: { + message: 'Some error message', + name: 'Some error name', + stack: 'Some error stack' + }, level: LogLevel.Fatal }, { diff --git a/platform/logging/layouts/__tests__/PatternLayout.test.ts b/platform/logging/layouts/__tests__/PatternLayout.test.ts index 0da8d888a5c0a..1011c0316838f 100644 --- a/platform/logging/layouts/__tests__/PatternLayout.test.ts +++ b/platform/logging/layouts/__tests__/PatternLayout.test.ts @@ -9,7 +9,11 @@ const records: LogRecord[] = [ timestamp: new Date(2012, 1, 1), message: 'message-1', context: 'context-1', - error: new Error('Some error message'), + error: { + message: 'Some error message', + name: 'Some error name', + stack: 'Some error stack' + }, level: LogLevel.Fatal }, { @@ -84,8 +88,7 @@ test('`format()` correctly formats record with custom pattern.', () => { const layout = new PatternLayout('mock-{message}-{context}-{message}'); for (const record of records) { - const { context, message } = record; - expect(layout.format(record)).toBe(`mock-${message}-${context}-${message}`); + expect(layout.format(record)).toMatchSnapshot(); } }); diff --git a/platform/logging/layouts/__tests__/__snapshots__/JsonLayout.test.ts.snap b/platform/logging/layouts/__tests__/__snapshots__/JsonLayout.test.ts.snap index 00f3808fa6058..2d4e0e4c0e3ce 100644 --- a/platform/logging/layouts/__tests__/__snapshots__/JsonLayout.test.ts.snap +++ b/platform/logging/layouts/__tests__/__snapshots__/JsonLayout.test.ts.snap @@ -1,13 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`\`format()\` correctly formats record. 1`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-1\\",\\"context\\":\\"context-1\\",\\"error\\":\\"Some error message\\",\\"level\\":{\\"id\\":\\"fatal\\",\\"value\\":2}}"`; +exports[`\`format()\` correctly formats record. 1`] = `"{\\"@timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"level\\":\\"FATAL\\",\\"context\\":\\"context-1\\",\\"message\\":\\"message-1\\",\\"error\\":{\\"name\\":\\"Some error name\\",\\"stack\\":\\"Some error stack\\",\\"message\\":\\"Some error message\\"}}"`; -exports[`\`format()\` correctly formats record. 2`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-2\\",\\"context\\":\\"context-2\\",\\"level\\":{\\"id\\":\\"error\\",\\"value\\":3}}"`; +exports[`\`format()\` correctly formats record. 2`] = `"{\\"@timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"level\\":\\"ERROR\\",\\"context\\":\\"context-2\\",\\"message\\":\\"message-2\\"}"`; -exports[`\`format()\` correctly formats record. 3`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-3\\",\\"context\\":\\"context-3\\",\\"level\\":{\\"id\\":\\"warn\\",\\"value\\":4}}"`; +exports[`\`format()\` correctly formats record. 3`] = `"{\\"@timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"level\\":\\"WARN\\",\\"context\\":\\"context-3\\",\\"message\\":\\"message-3\\"}"`; -exports[`\`format()\` correctly formats record. 4`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-4\\",\\"context\\":\\"context-4\\",\\"level\\":{\\"id\\":\\"debug\\",\\"value\\":6}}"`; +exports[`\`format()\` correctly formats record. 4`] = `"{\\"@timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"level\\":\\"DEBUG\\",\\"context\\":\\"context-4\\",\\"message\\":\\"message-4\\"}"`; -exports[`\`format()\` correctly formats record. 5`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-5\\",\\"context\\":\\"context-5\\",\\"level\\":{\\"id\\":\\"info\\",\\"value\\":5}}"`; +exports[`\`format()\` correctly formats record. 5`] = `"{\\"@timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"level\\":\\"INFO\\",\\"context\\":\\"context-5\\",\\"message\\":\\"message-5\\"}"`; -exports[`\`format()\` correctly formats record. 6`] = `"{\\"timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"message\\":\\"message-6\\",\\"context\\":\\"context-6\\",\\"level\\":{\\"id\\":\\"trace\\",\\"value\\":7}}"`; +exports[`\`format()\` correctly formats record. 6`] = `"{\\"@timestamp\\":\\"2012-01-31T23:00:00.000Z\\",\\"level\\":\\"TRACE\\",\\"context\\":\\"context-6\\",\\"message\\":\\"message-6\\"}"`; diff --git a/platform/logging/layouts/__tests__/__snapshots__/PatternLayout.test.ts.snap b/platform/logging/layouts/__tests__/__snapshots__/PatternLayout.test.ts.snap index 0f883a4977bd2..636d4640d7c4d 100644 --- a/platform/logging/layouts/__tests__/__snapshots__/PatternLayout.test.ts.snap +++ b/platform/logging/layouts/__tests__/__snapshots__/PatternLayout.test.ts.snap @@ -1,6 +1,18 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`\`format()\` correctly formats record with full pattern. 1`] = `"[2012-01-31T23:00:00.000Z][FATAL][context-1] message-1"`; +exports[`\`format()\` correctly formats record with custom pattern. 1`] = `"mock-Some error stack-context-1-Some error stack"`; + +exports[`\`format()\` correctly formats record with custom pattern. 2`] = `"mock-message-2-context-2-message-2"`; + +exports[`\`format()\` correctly formats record with custom pattern. 3`] = `"mock-message-3-context-3-message-3"`; + +exports[`\`format()\` correctly formats record with custom pattern. 4`] = `"mock-message-4-context-4-message-4"`; + +exports[`\`format()\` correctly formats record with custom pattern. 5`] = `"mock-message-5-context-5-message-5"`; + +exports[`\`format()\` correctly formats record with custom pattern. 6`] = `"mock-message-6-context-6-message-6"`; + +exports[`\`format()\` correctly formats record with full pattern. 1`] = `"[2012-01-31T23:00:00.000Z][FATAL][context-1] Some error stack"`; exports[`\`format()\` correctly formats record with full pattern. 2`] = `"[2012-01-31T23:00:00.000Z][ERROR][context-2] message-2"`; @@ -12,7 +24,7 @@ exports[`\`format()\` correctly formats record with full pattern. 5`] = `"[2012- exports[`\`format()\` correctly formats record with full pattern. 6`] = `"[2012-01-31T23:00:00.000Z][TRACE][context-6] message-6"`; -exports[`\`format()\` correctly formats record with highlighting. 1`] = `"[2012-01-31T23:00:00.000Z][FATAL][context-1] message-1"`; +exports[`\`format()\` correctly formats record with highlighting. 1`] = `"[2012-01-31T23:00:00.000Z][FATAL][context-1] Some error stack"`; exports[`\`format()\` correctly formats record with highlighting. 2`] = `"[2012-01-31T23:00:00.000Z][ERROR][context-2] message-2"`; From b670baeeec75912022c30b365676a33db73f471e Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Thu, 3 Aug 2017 08:18:08 -0700 Subject: [PATCH 058/165] Add AirBnB linting rules for React best practices. Bump to v0.10.0. (#13259) --- packages/eslint-config-kibana/.eslintrc.js | 11 +++++++++++ packages/eslint-config-kibana/package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/eslint-config-kibana/.eslintrc.js b/packages/eslint-config-kibana/.eslintrc.js index 91f200949342c..088f2e370113a 100644 --- a/packages/eslint-config-kibana/.eslintrc.js +++ b/packages/eslint-config-kibana/.eslintrc.js @@ -89,6 +89,7 @@ module.exports = { 'object-curly-spacing': 'off', // overriden with babel/object-curly-spacing 'babel/object-curly-spacing': [ 'error', 'always' ], + 'jsx-quotes': ['error', 'prefer-double'], 'react/jsx-uses-react': 'error', 'react/react-in-jsx-scope': 'error', 'react/jsx-uses-vars': 'error', @@ -96,6 +97,7 @@ module.exports = { 'react/jsx-pascal-case': 'error', 'react/jsx-closing-bracket-location': ['error', 'line-aligned'], 'react/jsx-closing-tag-location': 'error', + 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }], 'react/jsx-indent-props': ['error', 2], 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }], 'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }], @@ -109,6 +111,15 @@ module.exports = { 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], 'react/jsx-equals-spacing': ['error', 'never'], 'react/jsx-indent': ['error', 2], + 'react/no-did-mount-set-state': 'error', + 'react/no-did-update-set-state': 'error', + 'react/no-will-update-set-state': 'error', + 'react/no-is-mounted': 'error', + 'react/no-multi-comp': ['error', { ignoreStateless: true }], + 'react/no-unknown-property': 'error', + 'react/prefer-es6-class': ['error', 'always'], + 'react/prefer-stateless-function': ['error', { ignorePureComponents: true }], + 'react/no-unescaped-entities': 'error', 'mocha/handle-done-callback': 'error', 'mocha/no-exclusive-tests': 'error', diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json index 9c042fe34734f..28e728380e657 100644 --- a/packages/eslint-config-kibana/package.json +++ b/packages/eslint-config-kibana/package.json @@ -1,6 +1,6 @@ { "name": "@elastic/eslint-config-kibana", - "version": "0.9.0", + "version": "0.10.0", "description": "The eslint config used by the kibana team", "main": ".eslintrc.js", "scripts": { From e57c4fb5bbd370c75fa1f55521fceb456e7da23d Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 3 Aug 2017 11:23:43 -0400 Subject: [PATCH 059/165] Visualization accessibility issues (#13226) --- .../public/controls/heatmap_options.html | 6 ++++-- src/core_plugins/kibana/public/visualize/wizard/step_1.html | 2 +- src/ui/public/vis/editors/default/agg_add.html | 2 ++ src/ui/public/vis/editors/default/sidebar.html | 2 ++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.html b/src/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.html index ed2affb0e34c0..6a2e223b56222 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.html +++ b/src/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.html @@ -109,16 +109,17 @@
@@ -25,7 +25,12 @@
{{col.total}}
- + - +
-
+ From 4f5313a0882a1624946c7c6d0c404b2628fbb4e6 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Thu, 3 Aug 2017 11:25:38 -0400 Subject: [PATCH 060/165] Make sure no one can show the chrome if the default setting is hidden. (#13250) * Make sure no one can show the chrome if the default setting is hidden. add tests Fixes https://github.com/elastic/kibana/issues/13040 * Improve variable and function names and fix tests --- src/ui/public/chrome/api/controls.js | 12 ++++++-- .../public/chrome/directives/kbn_chrome.html | 1 + src/ui/public/chrome/directives/kbn_chrome.js | 4 ++- test/functional/apps/dashboard/_dashboard.js | 30 +++++++++++++++++++ test/functional/page_objects/common_page.js | 4 ++- 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/ui/public/chrome/api/controls.js b/src/ui/public/chrome/api/controls.js index 771a995474a45..5a99fa0f3b433 100644 --- a/src/ui/public/chrome/api/controls.js +++ b/src/ui/public/chrome/api/controls.js @@ -11,14 +11,20 @@ export default function (chrome, internals) { * determines if the Kibana chrome should be displayed */ - let def = true; - internals.setVisibleDefault = (_def) => def = Boolean(_def); + let permanentlyHideChrome = false; + internals.permanentlyHideChrome = () => { + permanentlyHideChrome = true; + internals.visible = false; + }; /** * @param {boolean} display - should the chrome be displayed * @return {chrome} */ chrome.setVisible = function (display) { + if (permanentlyHideChrome) { + return chrome; + } internals.visible = Boolean(display); return chrome; }; @@ -27,7 +33,7 @@ export default function (chrome, internals) { * @return {boolean} - display state of the chrome */ chrome.getVisible = function () { - if (_.isUndefined(internals.visible)) return def; + if (_.isUndefined(internals.visible)) return !permanentlyHideChrome; return internals.visible; }; } diff --git a/src/ui/public/chrome/directives/kbn_chrome.html b/src/ui/public/chrome/directives/kbn_chrome.html index 6aaa3bc54ee6a..1d6a34e84bfd6 100644 --- a/src/ui/public/chrome/directives/kbn_chrome.html +++ b/src/ui/public/chrome/directives/kbn_chrome.html @@ -1,6 +1,7 @@
{ + it('hides the chrome', async () => { + let isChromeVisible = await PageObjects.common.isChromeVisible(); + expect(isChromeVisible).to.be(true); + + const currentUrl = await remote.getCurrentUrl(); + const newUrl = currentUrl + '&embed=true'; + // Embed parameter only works on a hard refresh. + const useTimeStamp = true; + await remote.get(newUrl.toString(), useTimeStamp); + + await retry.try(async () => { + isChromeVisible = await PageObjects.common.isChromeVisible(); + expect(isChromeVisible).to.be(false); + }); + }); + + after(async function () { + console.log('showing chrome again'); + const currentUrl = await remote.getCurrentUrl(); + const newUrl = currentUrl.replace('&embed=true', ''); + // First use the timestamp to cause a hard refresh so the new embed parameter works correctly. + let useTimeStamp = true; + await remote.get(newUrl.toString(), useTimeStamp); + // Then get rid of the timestamp so the rest of the tests work with state and app switching. + useTimeStamp = false; + await remote.get(newUrl.toString(), useTimeStamp); + }); + }); + describe('add new visualization link', () => { it('adds a new visualization', async () => { await PageObjects.dashboard.clickAddVisualization(); diff --git a/test/functional/page_objects/common_page.js b/test/functional/page_objects/common_page.js index 56714a95b3047..7e093da521a86 100644 --- a/test/functional/page_objects/common_page.js +++ b/test/functional/page_objects/common_page.js @@ -257,7 +257,9 @@ export function CommonPageProvider({ getService, getPageObjects }) { } async isChromeVisible() { - return await testSubjects.exists('kibanaChrome'); + const globalNavShown = await testSubjects.exists('globalNav'); + const topNavShown = await testSubjects.exists('top-nav'); + return globalNavShown && topNavShown; } async waitForTopNavToBeVisible() { From 7e28e984bd0dfc8a76740b907714470fcf06ad84 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 3 Aug 2017 11:31:43 -0500 Subject: [PATCH 061/165] [visualize spy] Pull index title instead of id (#13254) * [visualize spy] Pull index title instead of id * [visualize spy] Check for existence of index before pulling params --- .../spy_modes/public/req_resp_stats_spy_mode.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core_plugins/spy_modes/public/req_resp_stats_spy_mode.js b/src/core_plugins/spy_modes/public/req_resp_stats_spy_mode.js index 2d03f76ea966f..e4dc09d1ccbfb 100644 --- a/src/core_plugins/spy_modes/public/req_resp_stats_spy_mode.js +++ b/src/core_plugins/spy_modes/public/req_resp_stats_spy_mode.js @@ -19,10 +19,10 @@ const linkReqRespStats = function ($scope) { if (req && req.ms != null) stats.push(['Request Duration', req.ms + 'ms']); if (resp && resp.hits) stats.push(['Hits', resp.hits.total]); - if (req.fetchParams) { - if (req.fetchParams.index) stats.push(['Index', req.fetchParams.index]); - if (req.fetchParams.type) stats.push(['Type', req.fetchParams.type]); - if (req.fetchParams.id) stats.push(['Id', req.fetchParams.id]); + if (req.fetchParams && req.fetchParams.index) { + if (req.fetchParams.index.title) stats.push(['Index', req.fetchParams.index.title]); + if (req.fetchParams.index.type) stats.push(['Type', req.fetchParams.index.type]); + if (req.fetchParams.index.id) stats.push(['Id', req.fetchParams.index.id]); } }); }; From 6648335d514152638bd9ac57bba5baaec40c392b Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Thu, 3 Aug 2017 10:00:16 -0700 Subject: [PATCH 062/165] [Accessibilty] Make kbn_accessible_click part of autoload/all (#13299) * [Accessibility] Ensure kbn-accessible-click is part of autoload/all * remove unecessary kbn_accessible_click imports * use an index.js file to expose inner directives --- src/core_plugins/kibana/public/dashboard/index.js | 1 - .../public/discover/components/field_chooser/discover_field.js | 1 - src/core_plugins/timelion/public/app.js | 1 - src/ui/public/accessibility/index.js | 1 + src/ui/public/autoload/accessibility.js | 1 + src/ui/public/autoload/all.js | 1 + 6 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 src/ui/public/accessibility/index.js create mode 100644 src/ui/public/autoload/accessibility.js diff --git a/src/core_plugins/kibana/public/dashboard/index.js b/src/core_plugins/kibana/public/dashboard/index.js index d4359db84c00d..fbcb1ae500260 100644 --- a/src/core_plugins/kibana/public/dashboard/index.js +++ b/src/core_plugins/kibana/public/dashboard/index.js @@ -3,7 +3,6 @@ import 'plugins/kibana/dashboard/saved_dashboard/saved_dashboards'; import 'plugins/kibana/dashboard/styles/index.less'; import 'plugins/kibana/dashboard/dashboard_config'; import uiRoutes from 'ui/routes'; -import 'ui/accessibility/kbn_accessible_click'; import dashboardListingTemplate from './listing/dashboard_listing.html'; import { DashboardListingController } from './listing/dashboard_listing'; diff --git a/src/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js b/src/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js index fe7b0fa77970f..cd7b5d6fd1e61 100644 --- a/src/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js +++ b/src/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js @@ -3,7 +3,6 @@ import html from 'plugins/kibana/discover/components/field_chooser/discover_fiel import _ from 'lodash'; import 'ui/directives/css_truncate'; import 'ui/directives/field_name'; -import 'ui/accessibility/kbn_accessible_click'; import detailsHtml from 'plugins/kibana/discover/components/field_chooser/lib/detail_views/string.html'; import { uiModules } from 'ui/modules'; const app = uiModules.get('apps/discover'); diff --git a/src/core_plugins/timelion/public/app.js b/src/core_plugins/timelion/public/app.js index a5850886857eb..3541a4c408bf2 100644 --- a/src/core_plugins/timelion/public/app.js +++ b/src/core_plugins/timelion/public/app.js @@ -4,7 +4,6 @@ import moment from 'moment-timezone'; import { DocTitleProvider } from 'ui/doc_title'; import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; import { notify } from 'ui/notify'; -import 'ui/accessibility/kbn_accessible_click'; require('plugins/timelion/directives/cells/cells'); require('plugins/timelion/directives/fixed_element'); diff --git a/src/ui/public/accessibility/index.js b/src/ui/public/accessibility/index.js new file mode 100644 index 0000000000000..906b3f2397b6c --- /dev/null +++ b/src/ui/public/accessibility/index.js @@ -0,0 +1 @@ +import './kbn_accessible_click'; diff --git a/src/ui/public/autoload/accessibility.js b/src/ui/public/autoload/accessibility.js new file mode 100644 index 0000000000000..7d2642c61e179 --- /dev/null +++ b/src/ui/public/autoload/accessibility.js @@ -0,0 +1 @@ +import '../accessibility'; diff --git a/src/ui/public/autoload/all.js b/src/ui/public/autoload/all.js index 98b0b4961154c..12951c84346e7 100644 --- a/src/ui/public/autoload/all.js +++ b/src/ui/public/autoload/all.js @@ -1,3 +1,4 @@ +import './accessibility'; import './modules'; import './directives'; import './filters'; From 5fe682dfc2c87f26e1b93e0ab91c7d76abbc364a Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 3 Aug 2017 14:46:16 -0400 Subject: [PATCH 063/165] Improve region map documentation (#13319) --- docs/management/advanced-options.asciidoc | 1 + docs/visualize/regionmap.asciidoc | 6 ++++-- src/core_plugins/kibana/ui_setting_defaults.js | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index f601e097dc287..325e6b08fff25 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -54,6 +54,7 @@ when necessary. `visualization:colorMapping`:: Maps values to specified colors within visualizations. `visualization:loadingDelay`:: Time to wait before dimming visualizations during query. `visualization:dimmingOpacity`:: When part of a visualization is highlighted, by hovering over it for example, ths is the opacity applied to the other elements. A higher number means other elements will be less opaque. +`visualization:regionmap:showWarnings`:: Whether the region map show a warning when terms cannot be joined to a shape on the map. `csv:separator`:: A string that serves as the separator for exported values. `csv:quoteValues`:: Set this property to `true` to quote exported values. `history:limit`:: In fields that have history, such as query inputs, the value of this property limits how many recent diff --git a/docs/visualize/regionmap.asciidoc b/docs/visualize/regionmap.asciidoc index f399985eead6e..284fe611d8744 100644 --- a/docs/visualize/regionmap.asciidoc +++ b/docs/visualize/regionmap.asciidoc @@ -26,10 +26,12 @@ Configure a _Terms_ aggregation. The term is the _key_ that is used to join the ==== Options ===== Layer Settings -- *Vector map*: select from a list of vector maps. This list includes the maps that are hosted by the © [Elastic Maps Service](https://www.elastic.co/elastic-maps-service), +- *Vector map*: select from a list of vector maps. This list includes the maps that are hosted by the © https://www.elastic.co/elastic-maps-service[Elastic Maps Service], as well as your self-hosted layers that are configured in the *config/kibana.yml* file. To learn more about how to configure Kibana to make self-hosted layers available, see the <> documentation. -- *Join field*: this is the property from the selected vector map that will be used to join on the terms in your terms-aggregation. +- *Join field*: this is the property from the selected vector map that will be used to join on the terms in your terms-aggregation. +When terms cannot be joined to any of the shapes in the vector layer because there is no exact match in the vector layer, Kibana will display a warning. +To turn of these warnings, go to *Management/Kibana/Advanced Settings* and set `visualization:regionmap:showWarnings` to `vefalse`. ===== Style Settings - *Color Schema*: the color range used to color the shapes. diff --git a/src/core_plugins/kibana/ui_setting_defaults.js b/src/core_plugins/kibana/ui_setting_defaults.js index 14b112dcd4e6b..be0eaff2bb3a2 100644 --- a/src/core_plugins/kibana/ui_setting_defaults.js +++ b/src/core_plugins/kibana/ui_setting_defaults.js @@ -147,7 +147,7 @@ export function getUiSettingDefaults() { }, 'visualization:regionmap:showWarnings': { value: true, - description: 'Should the vector map show a warning when terms cannot be joined to a shape on the map.' + description: 'Whether the region map show a warning when terms cannot be joined to a shape on the map.' }, 'visualization:colorMapping': { type: 'json', From 8a1cdf19839512de79794afea2d1db1ed53afd20 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 3 Aug 2017 14:52:34 -0400 Subject: [PATCH 064/165] fix typo --- docs/visualize/regionmap.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/visualize/regionmap.asciidoc b/docs/visualize/regionmap.asciidoc index 284fe611d8744..9237677283691 100644 --- a/docs/visualize/regionmap.asciidoc +++ b/docs/visualize/regionmap.asciidoc @@ -31,7 +31,7 @@ as well as your self-hosted layers that are configured in the *config/kibana.yml to make self-hosted layers available, see the <> documentation. - *Join field*: this is the property from the selected vector map that will be used to join on the terms in your terms-aggregation. When terms cannot be joined to any of the shapes in the vector layer because there is no exact match in the vector layer, Kibana will display a warning. -To turn of these warnings, go to *Management/Kibana/Advanced Settings* and set `visualization:regionmap:showWarnings` to `vefalse`. +To turn of these warnings, go to *Management/Kibana/Advanced Settings* and set `visualization:regionmap:showWarnings` to `false`. ===== Style Settings - *Color Schema*: the color range used to color the shapes. From 14c9b7e06aa7dbb54485c86ee23a20043cde9961 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 3 Aug 2017 13:46:18 -0700 Subject: [PATCH 065/165] Use ui-select for agg selector (#13292) * Use ui-select for agg selector * Fix functional tests * Fix functional tests * Fix test * Fix visualize page object * Use sortPrefixFirst in agg selector * Fix unit tests * Fix unit test * Use not(.ng-hide) rather than last-child --- src/ui/public/agg_types/controls/field.html | 2 +- .../filter_editor/filter_field_select.html | 5 +++- .../utils/__tests__/sort_prefix_first.js | 8 ++++++ src/ui/public/utils/sort_prefix_first.js | 18 +++++++------ .../vis/editors/default/agg_select.html | 25 ++++++++++++++----- .../apps/visualize/_point_series_options.js | 2 +- test/functional/apps/visualize/_spy_panel.js | 2 +- .../functional/page_objects/visualize_page.js | 15 ++++++++--- 8 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/ui/public/agg_types/controls/field.html b/src/ui/public/agg_types/controls/field.html index 4c52e80cb2294..46835f64c8515 100644 --- a/src/ui/public/agg_types/controls/field.html +++ b/src/ui/public/agg_types/controls/field.html @@ -6,7 +6,7 @@
diff --git a/src/ui/public/utils/__tests__/sort_prefix_first.js b/src/ui/public/utils/__tests__/sort_prefix_first.js index 9d719670fee83..06dd4bc0de7c3 100644 --- a/src/ui/public/utils/__tests__/sort_prefix_first.js +++ b/src/ui/public/utils/__tests__/sort_prefix_first.js @@ -39,4 +39,12 @@ describe('sortPrefixFirst', function () { expect(result).to.not.be(array); expect(result).to.eql([50, 5, 1]); }); + + it('should handle mixed case', function () { + const array = ['Date Histogram', 'Histogram']; + const prefix = 'histo'; + const result = sortPrefixFirst(array, prefix); + expect(result).to.not.be(array); + expect(result).to.eql(['Histogram', 'Date Histogram']); + }); }); diff --git a/src/ui/public/utils/sort_prefix_first.js b/src/ui/public/utils/sort_prefix_first.js index 285b2ede7c850..bb5a397d00451 100644 --- a/src/ui/public/utils/sort_prefix_first.js +++ b/src/ui/public/utils/sort_prefix_first.js @@ -1,16 +1,20 @@ export function sortPrefixFirst(array, prefix, property) { if (!prefix) return array; + const lowerCasePrefix = ('' + prefix).toLowerCase(); return [...array].sort(sortPrefixFirstComparator); function sortPrefixFirstComparator(a, b) { - const aValue = '' + (property ? a[property] : a); - const bValue = '' + (property ? b[property] : b); + const aValue = ('' + (property ? a[property] : a)).toLowerCase(); + const bValue = ('' + (property ? b[property] : b)).toLowerCase(); - const bothStartWith = aValue.startsWith(prefix) && bValue.startsWith(prefix); - const neitherStartWith = !aValue.startsWith(prefix) && !bValue.startsWith(prefix); + const bothStartWith = aValue.startsWith(lowerCasePrefix) && bValue.startsWith(lowerCasePrefix); + const neitherStartWith = !aValue.startsWith(lowerCasePrefix) && !bValue.startsWith(lowerCasePrefix); - if (bothStartWith || neitherStartWith) return 0; - if (aValue.startsWith(prefix)) return -1; - else return 1; + if (bothStartWith || neitherStartWith) { + return 0; + } else if (aValue.startsWith(lowerCasePrefix)) { + return -1; + } + return 1; } } diff --git a/src/ui/public/vis/editors/default/agg_select.html b/src/ui/public/vis/editors/default/agg_select.html index 854996b965822..bbcbbf670a065 100644 --- a/src/ui/public/vis/editors/default/agg_select.html +++ b/src/ui/public/vis/editors/default/agg_select.html @@ -1,12 +1,25 @@
- + > + + {{$select.selected.title}} + + +
+
+
diff --git a/test/functional/apps/visualize/_point_series_options.js b/test/functional/apps/visualize/_point_series_options.js index 1ba9a87d063fa..b26a30caabdc4 100644 --- a/test/functional/apps/visualize/_point_series_options.js +++ b/test/functional/apps/visualize/_point_series_options.js @@ -49,7 +49,7 @@ export default function ({ getService, getPageObjects }) { }) .then(function selectAggregation() { log.debug('Aggregation = Average'); - return PageObjects.visualize.selectAggregation('Average'); + return PageObjects.visualize.selectAggregation('Average', 'metrics'); }) .then(function selectField() { log.debug('Field = memory'); diff --git a/test/functional/apps/visualize/_spy_panel.js b/test/functional/apps/visualize/_spy_panel.js index 046d25b569bab..963e1c02d60cd 100644 --- a/test/functional/apps/visualize/_spy_panel.js +++ b/test/functional/apps/visualize/_spy_panel.js @@ -30,7 +30,7 @@ export default function ({ getService, getPageObjects }) { log.debug('Add Average Metric on machine.ram field'); await PageObjects.visualize.clickAddMetric(); await PageObjects.visualize.clickBucket('Y-Axis'); - await PageObjects.visualize.selectAggregation('Average'); + await PageObjects.visualize.selectAggregation('Average', 'metrics'); await PageObjects.visualize.selectField('machine.ram', 'metrics'); await PageObjects.visualize.clickGo(); await PageObjects.visualize.openSpyPanel(); diff --git a/test/functional/page_objects/visualize_page.js b/test/functional/page_objects/visualize_page.js index 9390c90028fb9..5315c16a0b122 100644 --- a/test/functional/page_objects/visualize_page.js +++ b/test/functional/page_objects/visualize_page.js @@ -215,8 +215,14 @@ export function VisualizePageProvider({ getService, getPageObjects }) { await Promise.all(getChartTypesPromises); } - async selectAggregation(myString) { - return find.clickByCssSelector('vis-editor-agg-params:not(.ng-hide) option[label="' + myString + '"]'); + async selectAggregation(myString, groupName = 'buckets') { + const selector = `[group-name="${groupName}"] vis-editor-agg-params:not(.ng-hide) .agg-select`; + await retry.try(async () => { + await find.clickByCssSelector(selector); + const input = await find.byCssSelector(`${selector} input.ui-select-search`); + await input.type(myString); + await remote.pressKeys('\uE006'); + }); } async getField() { @@ -226,9 +232,10 @@ export function VisualizePageProvider({ getService, getPageObjects }) { } async selectField(fieldValue, groupName = 'buckets') { + const selector = `[group-name="${groupName}"] vis-editor-agg-params:not(.ng-hide) .field-select`; await retry.try(async () => { - await find.clickByCssSelector(`[group-name="${groupName}"] .ui-select-container`); - const input = await find.byCssSelector(`[group-name="${groupName}"] input.ui-select-search`); + await find.clickByCssSelector(selector); + const input = await find.byCssSelector(`${selector} input.ui-select-search`); await input.type(fieldValue); await remote.pressKeys('\uE006'); }); From 3e3b0cb8bae06cdd9c73193a4b2107586097a612 Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Fri, 4 Aug 2017 08:10:32 +0200 Subject: [PATCH 066/165] resize was not detected correctly (#13239) --- src/core_plugins/tile_map/public/maps_visualization.js | 6 +++--- src/ui/public/visualize/visualization.js | 4 +--- src/ui/public/visualize/visualize.js | 1 - 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/core_plugins/tile_map/public/maps_visualization.js b/src/core_plugins/tile_map/public/maps_visualization.js index eb2be81aaeff7..3964e3bf905d8 100644 --- a/src/core_plugins/tile_map/public/maps_visualization.js +++ b/src/core_plugins/tile_map/public/maps_visualization.js @@ -42,6 +42,9 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState return new Promise(async(resolve) => { await this._kibanaMapReady; + if (status.resize) { + this._kibanaMap.resize(); + } if (status.params || status.aggs) await this._updateParams(); if (esResponse && typeof esResponse.geohashGridAgg === 'undefined') { @@ -54,9 +57,6 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState if (status.uiState) { this._kibanaMap.useUiStateFromVisualization(this.vis); } - if (status.resize) { - this._kibanaMap.resize(); - } this._doRenderComplete(resolve); diff --git a/src/ui/public/visualize/visualization.js b/src/ui/public/visualize/visualization.js index e54108a4f1fe4..54e32e31332e4 100644 --- a/src/ui/public/visualize/visualization.js +++ b/src/ui/public/visualize/visualization.js @@ -98,12 +98,10 @@ uiModules }); const Visualization = $scope.vis.type.visualization; - - //todo: make this not a jquery element const visualization = new Visualization(getVisEl()[0], $scope.vis); - const renderFunction = _.debounce(() => { + $scope.vis.size = [$el.width(), $el.height()]; const status = getUpdateStatus($scope); visualization.render($scope.visData, status) .then(() => { diff --git a/src/ui/public/visualize/visualize.js b/src/ui/public/visualize/visualize.js index a97422455ff62..5b64c87d10fff 100644 --- a/src/ui/public/visualize/visualize.js +++ b/src/ui/public/visualize/visualize.js @@ -137,7 +137,6 @@ uiModules let resizeInit = false; const resizeFunc = _.debounce(() => { if (!resizeInit) return resizeInit = true; - $scope.vis.size = [$el.width(), $el.height()]; $scope.$broadcast('render'); }, 200); resizeChecker.on('resize', resizeFunc); From 3dfcf5dc9850e1b16c24215c0737ea4ea9ef9720 Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Fri, 4 Aug 2017 14:45:21 -0400 Subject: [PATCH 067/165] Remove simple_query_string hack now that multi_match supports * (#13285) --- .../public/kuery/functions/__tests__/and.js | 5 +-- src/ui/public/kuery/functions/__tests__/is.js | 34 ++++++------------- .../public/kuery/functions/__tests__/not.js | 5 +-- src/ui/public/kuery/functions/__tests__/or.js | 5 +-- src/ui/public/kuery/functions/is.js | 16 +++------ 5 files changed, 25 insertions(+), 40 deletions(-) diff --git a/src/ui/public/kuery/functions/__tests__/and.js b/src/ui/public/kuery/functions/__tests__/and.js index 8d497f92fbb0d..a14de59f775e4 100644 --- a/src/ui/public/kuery/functions/__tests__/and.js +++ b/src/ui/public/kuery/functions/__tests__/and.js @@ -4,6 +4,7 @@ import { nodeTypes } from '../../node_types'; import * as ast from '../../ast'; import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import ngMock from 'ng_mock'; +import { expectDeepEqual } from '../../../../../test_utils/expect_deep_equal'; let indexPattern; @@ -54,11 +55,11 @@ describe('kuery functions', function () { it('should wrap a literal argument with an "is" function targeting all fields', function () { const literalFoo = nodeTypes.literal.buildNode('foo'); + const expectedChild = ast.toElasticsearchQuery(nodeTypes.function.buildNode('is', '*', 'foo'), indexPattern); const node = nodeTypes.function.buildNode('and', [literalFoo]); const result = and.toElasticsearchQuery(node, indexPattern); const resultChild = result.bool.filter[0]; - expect(resultChild).to.have.property('simple_query_string'); - expect(resultChild.simple_query_string.all_fields).to.be(true); + expectDeepEqual(resultChild, expectedChild); }); }); diff --git a/src/ui/public/kuery/functions/__tests__/is.js b/src/ui/public/kuery/functions/__tests__/is.js index 29a7569d22716..2d61d93d80825 100644 --- a/src/ui/public/kuery/functions/__tests__/is.js +++ b/src/ui/public/kuery/functions/__tests__/is.js @@ -1,9 +1,9 @@ import expect from 'expect.js'; import * as is from '../is'; import { nodeTypes } from '../../node_types'; -import _ from 'lodash'; import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import ngMock from 'ng_mock'; +import { expectDeepEqual } from '../../../../../test_utils/expect_deep_equal'; let indexPattern; @@ -54,34 +54,22 @@ describe('kuery functions', function () { const node = nodeTypes.function.buildNode('is', '*', '*'); const result = is.toElasticsearchQuery(node, indexPattern); - expect(_.isEqual(expected, result)).to.be(true); + expectDeepEqual(result, expected); }); - it('should return an ES simple_query_string query in all fields mode when fieldName is "*"', function () { + it('should return an ES multi_match query when fieldName is "*"', function () { const expected = { - simple_query_string: { - query: '"200"', - all_fields: true, + multi_match: { + query: 200, + fields: ['*'], + type: 'phrase', + lenient: true, } }; const node = nodeTypes.function.buildNode('is', '*', 200); const result = is.toElasticsearchQuery(node, indexPattern); - expect(_.isEqual(expected, result)).to.be(true); - }); - - // See discussion about kuery escaping for background: - // https://github.com/elastic/kibana/pull/12624#issuecomment-312650307 - it('should ensure the simple_query_string query is wrapped in double quotes to force a phrase search', function () { - const node = nodeTypes.function.buildNode('is', '*', '+response'); - const result = is.toElasticsearchQuery(node, indexPattern); - expect(result.simple_query_string.query).to.be('"+response"'); - }); - - it('already double quoted phrases should not get wrapped a second time', function () { - const node = nodeTypes.function.buildNode('is', '*', '"+response"'); - const result = is.toElasticsearchQuery(node, indexPattern); - expect(result.simple_query_string.query).to.be('"+response"'); + expectDeepEqual(result, expected); }); it('should return an ES exists query when value is "*"', function () { @@ -91,7 +79,7 @@ describe('kuery functions', function () { const node = nodeTypes.function.buildNode('is', 'response', '*'); const result = is.toElasticsearchQuery(node, indexPattern); - expect(_.isEqual(expected, result)).to.be(true); + expectDeepEqual(result, expected); }); it('should return an ES match_phrase query when a concrete fieldName and value are provided', function () { @@ -103,7 +91,7 @@ describe('kuery functions', function () { const node = nodeTypes.function.buildNode('is', 'response', 200); const result = is.toElasticsearchQuery(node, indexPattern); - expect(_.isEqual(expected, result)).to.be(true); + expectDeepEqual(result, expected); }); it('should support scripted fields', function () { diff --git a/src/ui/public/kuery/functions/__tests__/not.js b/src/ui/public/kuery/functions/__tests__/not.js index dc25a7a84e4e6..a30909aac9268 100644 --- a/src/ui/public/kuery/functions/__tests__/not.js +++ b/src/ui/public/kuery/functions/__tests__/not.js @@ -4,6 +4,7 @@ import { nodeTypes } from '../../node_types'; import * as ast from '../../ast'; import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import ngMock from 'ng_mock'; +import { expectDeepEqual } from '../../../../../test_utils/expect_deep_equal'; let indexPattern; @@ -49,11 +50,11 @@ describe('kuery functions', function () { it('should wrap a literal argument with an "is" function targeting all fields', function () { const literalFoo = nodeTypes.literal.buildNode('foo'); + const expectedChild = ast.toElasticsearchQuery(nodeTypes.function.buildNode('is', '*', 'foo'), indexPattern); const node = nodeTypes.function.buildNode('not', literalFoo); const result = not.toElasticsearchQuery(node, indexPattern); const resultChild = result.bool.must_not; - expect(resultChild).to.have.property('simple_query_string'); - expect(resultChild.simple_query_string.all_fields).to.be(true); + expectDeepEqual(resultChild, expectedChild); }); }); diff --git a/src/ui/public/kuery/functions/__tests__/or.js b/src/ui/public/kuery/functions/__tests__/or.js index 4ee5f5e44e31a..ffede80f57dca 100644 --- a/src/ui/public/kuery/functions/__tests__/or.js +++ b/src/ui/public/kuery/functions/__tests__/or.js @@ -4,6 +4,7 @@ import { nodeTypes } from '../../node_types'; import * as ast from '../../ast'; import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import ngMock from 'ng_mock'; +import { expectDeepEqual } from '../../../../../test_utils/expect_deep_equal'; let indexPattern; @@ -54,11 +55,11 @@ describe('kuery functions', function () { it('should wrap a literal argument with an "is" function targeting all fields', function () { const literalFoo = nodeTypes.literal.buildNode('foo'); + const expectedChild = ast.toElasticsearchQuery(nodeTypes.function.buildNode('is', '*', 'foo'), indexPattern); const node = nodeTypes.function.buildNode('or', [literalFoo]); const result = or.toElasticsearchQuery(node, indexPattern); const resultChild = result.bool.should[0]; - expect(resultChild).to.have.property('simple_query_string'); - expect(resultChild.simple_query_string.all_fields).to.be(true); + expectDeepEqual(resultChild, expectedChild); }); it('should require one of the clauses to match', function () { diff --git a/src/ui/public/kuery/functions/is.js b/src/ui/public/kuery/functions/is.js index a64fe194f140f..0f58fa7302b5d 100644 --- a/src/ui/public/kuery/functions/is.js +++ b/src/ui/public/kuery/functions/is.js @@ -33,13 +33,12 @@ export function toElasticsearchQuery(node, indexPattern) { return { match_all: {} }; } else if (fieldName === '*' && value !== '*') { - const userQuery = String(value); - const query = isDoubleQuoted(userQuery) ? userQuery : `"${userQuery}"`; - return { - simple_query_string: { - query, - all_fields: true + multi_match: { + query: value, + fields: ['*'], + type: 'phrase', + lenient: true, } }; } @@ -68,8 +67,3 @@ export function toKueryExpression(node) { return `${fieldName}:${value}`; } - -function isDoubleQuoted(str) { - return str.startsWith('"') && str.endsWith('"'); -} - From a4b72f2ad70bb296473ba1a017f81ac89e34ea98 Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Fri, 4 Aug 2017 14:54:16 -0400 Subject: [PATCH 068/165] Add documentation link to query bar when Kuery is selected (#13300) * Add doc link to kuery bar --- .../documentation_links.js | 1 + .../directive/__tests__/query_bar.js | 14 ------- .../public/query_bar/directive/query_bar.html | 42 ++++++++++++------- src/ui/public/styles/local_search.less | 4 ++ 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/ui/public/documentation_links/documentation_links.js b/src/ui/public/documentation_links/documentation_links.js index 4c8c72bbe0ee5..6355b8c249631 100644 --- a/src/ui/public/documentation_links/documentation_links.js +++ b/src/ui/public/documentation_links/documentation_links.js @@ -25,6 +25,7 @@ export const documentationLinks = { luceneQuerySyntax: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/query-dsl-query-string-query.html#query-string-syntax`, queryDsl: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/query-dsl.html`, + kueryQuerySyntax: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/kuery-query.html`, }, date: { dateMath: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/common-options.html#date-math` diff --git a/src/ui/public/query_bar/directive/__tests__/query_bar.js b/src/ui/public/query_bar/directive/__tests__/query_bar.js index b023ed4534442..c7b5a26a062ea 100644 --- a/src/ui/public/query_bar/directive/__tests__/query_bar.js +++ b/src/ui/public/query_bar/directive/__tests__/query_bar.js @@ -120,20 +120,6 @@ describe('queryBar directive', function () { expectDeepEqual($parentScope.submitHandler.getCall(0).args[0], { query: 'bar', language: 'lucene' }); }); - it('should customize the input element for each language', function () { - init({ query: 'foo', language: 'lucene' }, 'discover', true); - const luceneInput = $elem.find('.kuiLocalSearchInput'); - expect(luceneInput.attr('placeholder')).to.be('Search... (e.g. status:200 AND extension:PHP)'); - - const helpLink = $elem.find('.kuiLocalSearchAssistedInput__assistance .kuiLink'); - expect(helpLink.text().trim()).to.be('Uses lucene query syntax'); - - $parentScope.query = { query: 'foo', language: 'kuery' }; - $parentScope.$digest(); - const kueryInput = $elem.find('.kuiLocalSearchInput'); - expect(kueryInput.attr('placeholder')).to.be('Search with kuery...'); - }); - }); describe('typeahead key', function () { diff --git a/src/ui/public/query_bar/directive/query_bar.html b/src/ui/public/query_bar/directive/query_bar.html index caac42da1e080..be7527436b3d1 100644 --- a/src/ui/public/query_bar/directive/query_bar.html +++ b/src/ui/public/query_bar/directive/query_bar.html @@ -15,7 +15,7 @@ ng-model="queryBar.localQuery.query" placeholder="Search... (e.g. status:200 AND extension:PHP)" aria-label="Search input" - aria-describedby="discover-lucene-syntax-hint" + aria-describedby="discoverLuceneSyntaxHint" type="text" class="kuiLocalSearchInput kuiLocalSearchInput--lucene" ng-class="{'kuiLocalSearchInput-isInvalid': queryBarForm.$invalid}" @@ -24,7 +24,7 @@

- +

+ +
+
+ Build {{::ui.buildInfo.num}}, Commit SHA {{::ui.buildInfo.sha}} +
+
diff --git a/src/core_plugins/status_page/public/status_page.js b/src/core_plugins/status_page/public/status_page.js index 413208065a5cd..2fba5d8ca659b 100644 --- a/src/core_plugins/status_page/public/status_page.js +++ b/src/core_plugins/status_page/public/status_page.js @@ -8,10 +8,15 @@ import { uiModules } from 'ui/modules'; const chrome = require('ui/chrome') .setRootTemplate(require('plugins/status_page/status_page.html')) -.setRootController('ui', function ($http) { +.setRootController('ui', function ($http, buildNum, buildSha) { const ui = this; ui.loading = false; + ui.buildInfo = { + num: buildNum, + sha: buildSha.substr(0, 8) + }; + ui.refresh = function () { ui.loading = true; diff --git a/src/core_plugins/status_page/public/status_page.less b/src/core_plugins/status_page/public/status_page.less index 7b391d5477157..99894ccf1badd 100644 --- a/src/core_plugins/status_page/public/status_page.less +++ b/src/core_plugins/status_page/public/status_page.less @@ -178,3 +178,7 @@ .overall_state_red { .state(@status-red, @icon-red); } + +.build-info { + color: #555; +} diff --git a/src/ui/public/management/section.js b/src/ui/public/management/section.js index fb1a57ec875ce..0243f240181a4 100644 --- a/src/ui/public/management/section.js +++ b/src/ui/public/management/section.js @@ -9,7 +9,6 @@ export class ManagementSection { * @param {number|null} options.order * @param {string|null} options.display - defaults to id * @param {string|null} options.url - defaults to '' - * @param {string|null} options.info * @param {boolean|null} options.visible - defaults to true * @param {boolean|null} options.disabled - defaults to false * @param {string|null} options.tooltip - defaults to '' From 32b12c71d494e7630368c28da8c227c8ea4513d2 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Tue, 8 Aug 2017 15:50:25 +0200 Subject: [PATCH 076/165] Update new-platform dependencies. (#13338) --- package-lock.json | 1327 +++++++---------- package.json | 22 +- .../__tests__/__snapshots__/cli.test.ts.snap | 44 +- platform/cli/__tests__/captureTerminal.ts | 81 +- .../appenders/__tests__/FileAppender.test.ts | 2 +- .../logging/appenders/file/FileAppender.ts | 2 +- platform/root/__tests__/index.test.ts | 9 +- platform/server/http/Router/headers.ts | 2 +- src/jest/config.json | 4 +- src/jest/tsconfig.json | 6 + 10 files changed, 651 insertions(+), 848 deletions(-) create mode 100644 src/jest/tsconfig.json diff --git a/package-lock.json b/package-lock.json index aeecba7a4e02b..9c265386e87fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -72,7 +72,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -96,7 +96,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -160,51 +160,6 @@ "resolved": "https://registry.npmjs.org/@spalger/ui-ace/-/ui-ace-0.2.3.tgz", "integrity": "sha1-2cjvhIP6ufEYVRxeJ+3aw1q6hgc=" }, - "@types/babel-core": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/@types/babel-core/-/babel-core-6.7.14.tgz", - "integrity": "sha1-oIyQCpjomHwamNLqT6ChgFp9Ex8=", - "dev": true, - "requires": { - "@types/babel-template": "6.7.14", - "@types/babel-traverse": "6.7.17", - "@types/babel-types": "6.25.0" - } - }, - "@types/babel-template": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/@types/babel-template/-/babel-template-6.7.14.tgz", - "integrity": "sha1-gIilb51pfWINPQecPvZgJbegjQI=", - "dev": true, - "requires": { - "@types/babel-types": "6.25.0", - "@types/babylon": "6.16.1" - } - }, - "@types/babel-traverse": { - "version": "6.7.17", - "resolved": "https://registry.npmjs.org/@types/babel-traverse/-/babel-traverse-6.7.17.tgz", - "integrity": "sha512-OjTZPym3oYlXcgXW5nt9vv8y2RPlf/67jwTy7AXonw+ZFyJJSTww9g8Bd5xsoJ2lYSnMOGcTtuw7P7adEKR6qw==", - "dev": true, - "requires": { - "@types/babel-types": "6.25.0" - } - }, - "@types/babel-types": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-6.25.0.tgz", - "integrity": "sha512-VS26wSCQ3LvKGTezidY0PkKVZl7tm+b8R5fVQaaG3mFhSQrasCt1lYPk4/68kNwX5RhAKLtSgFjDPtBiUjzaAw==", - "dev": true - }, - "@types/babylon": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.1.tgz", - "integrity": "sha1-5NEKueQ6c3A6F8b0FDi+3ih2k0A=", - "dev": true, - "requires": { - "@types/babel-types": "6.25.0" - } - }, "@types/chalk": { "version": "0.4.31", "resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-0.4.31.tgz", @@ -212,9 +167,9 @@ "dev": true }, "@types/chance": { - "version": "0.7.33", - "resolved": "https://registry.npmjs.org/@types/chance/-/chance-0.7.33.tgz", - "integrity": "sha1-lmauXI9gKhSmfltgjavxp4U6Hig=", + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/chance/-/chance-0.7.34.tgz", + "integrity": "sha512-HqdjDQpGaZZZsrKBL8DBT6xIeBbnRNSsSUb2vg1evrNQhTeIX87p9bvl/HJsqD5KWlxZtFgMxUuYkrGkrMi/hQ==", "dev": true }, "@types/elasticsearch": { @@ -239,19 +194,19 @@ "integrity": "sha512-b7mVHoURu1xaP/V6xw1sYwyv9V0EZ7euyi+sdnbnTZxEkAh4/hzPsI6Eflq+ZzHQ/Tgl7l16Jz+0oz8F46MLnA==", "dev": true, "requires": { - "@types/node": "6.0.78" + "@types/node": "8.0.19" } }, "@types/jest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-20.0.2.tgz", - "integrity": "sha512-r9D5PKnwZiGcxkT7cej+7kq+pobFcCsj5TlWlO+AmlbwIo8u6vCWhGd0DPo8f7ANskwQaQ6vB6GqGN/DUoL3zQ==", + "version": "20.0.6", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-20.0.6.tgz", + "integrity": "sha512-vl6ZWajVlqFpOqYwjfXTvPRDZGSwdnoSdTYaZnAfi6vNxW8W343xaGsFYXFRSQtWzsrDGf6phQK2FIQq9JkIcA==", "dev": true }, "@types/js-yaml": { - "version": "3.5.31", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.5.31.tgz", - "integrity": "sha512-tDsBKuC7nlShdRbR+rCe6qrs9Fqodi7WUxyeysCwKG0kWFWsisyZ8FhmYhCF6+lt3XhIwSExaD1MxidYtRW15w==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.9.0.tgz", + "integrity": "sha512-bNVEiBrpEdg5oWz/10gxLUSjQGeBx7HgJHgy2DfR1K7unn260FfRwjVYH/NngQucYeMqsg1hOSo0+heQLJAwZA==", "dev": true }, "@types/lodash": { @@ -267,9 +222,9 @@ "dev": true }, "@types/node": { - "version": "6.0.78", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.78.tgz", - "integrity": "sha512-+vD6E8ixntRzzZukoF3uP1iV+ZjVN3koTcaeK+BEoc/kSfGbLDIGC7RmCaUgVpUfN6cWvfczFRERCyKM9mkvXg==", + "version": "8.0.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.19.tgz", + "integrity": "sha512-VRQB+Q0L3YZWs45uRdpN9oWr82meL/8TrJ6faoKT5tp0uub2l/aRMhtm5fo68h7kjYKH60f9/bay1nF7ZpTW5g==", "dev": true }, "@types/serve-static": { @@ -294,7 +249,7 @@ "integrity": "sha512-iVzWi5I+kTalhBf52Pvbuu1uiJmPs5k2Fhr3VP87h3rfer1LEag7x14TQYQQBwWBKz0SrYObxqueIsXjQmM01g==", "dev": true, "requires": { - "@types/node": "6.0.78" + "@types/node": "8.0.19" } }, "@types/supertest": { @@ -336,7 +291,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -344,7 +299,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -358,7 +313,7 @@ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", "requires": { - "mime-types": "2.1.15", + "mime-types": "2.1.16", "negotiator": "0.6.1" } }, @@ -457,7 +412,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -465,7 +420,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -538,12 +493,12 @@ "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" }, "anymatch": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz", - "integrity": "sha1-o+Uvo5FoyCX/V7AkgSbOWo/5VQc=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "requires": { - "arrify": "1.0.1", - "micromatch": "2.3.11" + "micromatch": "2.3.11", + "normalize-path": "2.1.1" } }, "append-transform": { @@ -558,7 +513,7 @@ "aproba": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", - "integrity": "sha1-RcZikJTeTpb2k+9+q3SuB5wkD8E=", + "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==", "dev": true }, "are-we-there-yet": { @@ -590,7 +545,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=" + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "array-differ": { "version": "1.0.0", @@ -760,7 +715,7 @@ "integrity": "sha1-E4brZwjM/zau//cK3GlOz9YK8bA=", "requires": { "browserslist": "1.4.0", - "caniuse-db": "1.0.30000703", + "caniuse-db": "1.0.30000709", "normalize-range": "0.1.2", "num2fraction": "1.2.2", "postcss": "5.2.17", @@ -773,7 +728,7 @@ "integrity": "sha1-5kDEFK5Bmq4hwa1DyOoPPbgqVm0=", "requires": { "browserslist": "0.4.0", - "caniuse-db": "1.0.30000703", + "caniuse-db": "1.0.30000709", "num2fraction": "1.2.2", "postcss": "4.1.16" }, @@ -783,7 +738,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-0.4.0.tgz", "integrity": "sha1-O9SrkZncG5FQ1NbbpNnTqrvIbdQ=", "requires": { - "caniuse-db": "1.0.30000703" + "caniuse-db": "1.0.30000709" } }, "postcss": { @@ -858,9 +813,9 @@ "dev": true }, "b64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/b64/-/b64-3.0.2.tgz", - "integrity": "sha1-ep1gRmrfe43hFMvfZRpf38yQiU0=" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/b64/-/b64-3.0.3.tgz", + "integrity": "sha512-Pbeh0i6OLubPJdIdCepn8ZQHwN2MWznZHbHABSTEfQ706ie+yuxNSaPdqX1xRatT6WanaS1EazMiSg0NUW2XxQ==" }, "babel-cli": { "version": "6.18.0", @@ -870,7 +825,7 @@ "babel-core": "6.21.0", "babel-polyfill": "6.20.0", "babel-register": "6.18.0", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "chokidar": "1.7.0", "commander": "2.8.1", "convert-source-map": "1.5.0", @@ -890,7 +845,7 @@ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "optional": true, "requires": { - "anymatch": "1.3.0", + "anymatch": "1.3.2", "async-each": "1.0.1", "glob-parent": "2.0.0", "inherits": "2.0.3", @@ -964,7 +919,7 @@ "babel-helpers": "6.24.1", "babel-messages": "6.23.0", "babel-register": "6.18.0", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0", @@ -988,7 +943,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "1.1.8" } @@ -1013,7 +968,7 @@ "integrity": "sha1-M6GvcNXyiQrrRlpKd5PB32qeqfw=", "requires": { "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0", "detect-indent": "4.0.0", "jsesc": "1.3.0", @@ -1035,7 +990,7 @@ "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", "requires": { "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0" } }, @@ -1044,7 +999,7 @@ "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz", "integrity": "sha1-CteRfjPI11HmRtrKTnfMGTd9LLw=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0", "esutils": "2.0.2" } @@ -1055,7 +1010,7 @@ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", "requires": { "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0" } @@ -1066,7 +1021,7 @@ "integrity": "sha1-epdH8ljYlH0y1RX2qhx70CIEoIA=", "requires": { "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0", "lodash": "4.17.4" }, @@ -1083,7 +1038,7 @@ "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0" } @@ -1094,7 +1049,7 @@ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", "requires": { "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0" @@ -1105,7 +1060,7 @@ "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0" } }, @@ -1114,7 +1069,7 @@ "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0" } }, @@ -1123,7 +1078,7 @@ "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0" } }, @@ -1132,7 +1087,7 @@ "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz", "integrity": "sha1-024i+rEAjXnYhkjjIRaGgShFbOg=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0", "lodash": "4.17.4" }, @@ -1150,7 +1105,7 @@ "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", "requires": { "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0" @@ -1163,7 +1118,7 @@ "requires": { "babel-helper-optimise-call-expression": "6.24.1", "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0" @@ -1174,7 +1129,7 @@ "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0" } }, @@ -1204,7 +1159,7 @@ "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-add-module-exports": { @@ -1217,7 +1172,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-istanbul": { @@ -1282,7 +1237,7 @@ "requires": { "babel-helper-remap-async-to-generator": "6.24.1", "babel-plugin-syntax-async-generators": "6.13.0", - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-async-to-generator": { @@ -1292,7 +1247,7 @@ "requires": { "babel-helper-remap-async-to-generator": "6.24.1", "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-class-properties": { @@ -1302,7 +1257,7 @@ "requires": { "babel-helper-function-name": "6.24.1", "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0" } }, @@ -1311,7 +1266,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-block-scoped-functions": { @@ -1319,7 +1274,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-block-scoping": { @@ -1327,7 +1282,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz", "integrity": "sha1-dsKV3DpHQbFmWt/TFnIV3P8ypXY=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0", @@ -1351,7 +1306,7 @@ "babel-helper-optimise-call-expression": "6.24.1", "babel-helper-replace-supers": "6.24.1", "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0" @@ -1362,7 +1317,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0" } }, @@ -1371,7 +1326,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-duplicate-keys": { @@ -1379,7 +1334,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0" } }, @@ -1388,7 +1343,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-function-name": { @@ -1397,7 +1352,7 @@ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", "requires": { "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0" } }, @@ -1406,7 +1361,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-modules-amd": { @@ -1415,7 +1370,7 @@ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", "requires": { "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0" } }, @@ -1425,7 +1380,7 @@ "integrity": "sha1-0+MQtA72ZKNmIiAAl8bUQCmPK/4=", "requires": { "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0", "babel-types": "6.25.0" } @@ -1436,7 +1391,7 @@ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", "requires": { "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0" } }, @@ -1446,7 +1401,7 @@ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", "requires": { "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0" } }, @@ -1456,7 +1411,7 @@ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", "requires": { "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-parameters": { @@ -1466,7 +1421,7 @@ "requires": { "babel-helper-call-delegate": "6.24.1", "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0" @@ -1477,7 +1432,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0" } }, @@ -1486,7 +1441,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-sticky-regex": { @@ -1495,7 +1450,7 @@ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", "requires": { "babel-helper-regex": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0" } }, @@ -1504,7 +1459,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-typeof-symbol": { @@ -1512,7 +1467,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-unicode-regex": { @@ -1521,7 +1476,7 @@ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "requires": { "babel-helper-regex": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "regexpu-core": "2.0.0" } }, @@ -1532,7 +1487,7 @@ "requires": { "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-flow-strip-types": { @@ -1541,7 +1496,7 @@ "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", "requires": { "babel-plugin-syntax-flow": "6.18.0", - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-object-rest-spread": { @@ -1550,7 +1505,7 @@ "integrity": "sha1-h11ryb52HFiirj/u5dxIldjH+SE=", "requires": { "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-react-display-name": { @@ -1558,7 +1513,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-react-jsx": { @@ -1568,7 +1523,7 @@ "requires": { "babel-helper-builder-react-jsx": "6.24.1", "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-react-jsx-self": { @@ -1577,7 +1532,7 @@ "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", "requires": { "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-react-jsx-source": { @@ -1586,7 +1541,7 @@ "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", "requires": { "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.23.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-regenerator": { @@ -1602,7 +1557,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0" } }, @@ -1611,7 +1566,7 @@ "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.20.0.tgz", "integrity": "sha1-3ko3EAYTniCZCqwL42fTmDMSBOc=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "core-js": "2.4.1", "regenerator-runtime": "0.10.5" } @@ -1680,7 +1635,7 @@ "integrity": "sha1-iS4uA4ZQeN2QrSxxURHsREmzKmg=", "requires": { "babel-core": "6.21.0", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "core-js": "2.4.1", "home-or-tmp": "2.0.0", "lodash": "4.17.4", @@ -1704,9 +1659,9 @@ } }, "babel-runtime": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", - "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", + "integrity": "sha1-M7mOql1IK7AajRqmtDetKwGuxBw=", "requires": { "core-js": "2.4.1", "regenerator-runtime": "0.10.5" @@ -1717,7 +1672,7 @@ "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.25.0.tgz", "integrity": "sha1-ZlJBFmt8KqTGGdceGSlpVSsQwHE=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0", "babylon": "6.17.4", @@ -1738,7 +1693,7 @@ "requires": { "babel-code-frame": "6.22.0", "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0", "babylon": "6.17.4", "debug": "2.6.8", @@ -1759,7 +1714,7 @@ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.25.0.tgz", "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "esutils": "2.0.2", "lodash": "4.17.4", "to-fast-properties": "1.0.3" @@ -1775,7 +1730,7 @@ "babylon": { "version": "6.17.4", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.4.tgz", - "integrity": "sha1-Pot0AriNIsNCPhN6FXeIOxX/hpo=" + "integrity": "sha512-kChlV+0SXkjE0vUn9OZ7pBMWRFd8uq3mZe8x1K6jhuNcAFAtEnjchFAqB+dYEXKyd+JpT6eppRR78QAr5gTsUw==" }, "backo2": { "version": "1.0.2", @@ -1802,7 +1757,7 @@ "base64-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha1-qRlH2h9KUW6jjltOwOw3c2deCIY=" + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==" }, "base64id": { "version": "1.0.0", @@ -1847,9 +1802,9 @@ "integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg=" }, "binary-extensions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.8.0.tgz", - "integrity": "sha1-SOyNFt9Dd+rl+liEaCSAr02Vx3Q=" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.9.0.tgz", + "integrity": "sha1-ZlBsFs5vTWkopbPNajPKQelB43s=" }, "bl": { "version": "1.0.3", @@ -1901,7 +1856,7 @@ "bn.js": { "version": "4.11.7", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz", - "integrity": "sha1-3bBI5Q2UgnkAlME+s/z8gzznq0Y=", + "integrity": "sha512-LxFiV5mefv0ley0SzqkOPR1bC4EbpPx8LkOz5vMe/Yi15t5hzwgO/G+tc7wOtL4PZTYjwHu8JnEiSLumuSjSfA==", "dev": true }, "body-parser": { @@ -2078,7 +2033,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.4.0.tgz", "integrity": "sha1-nP3PU4TZFY9bcNoqoAsw6P8BkEk=", "requires": { - "caniuse-db": "1.0.30000703" + "caniuse-db": "1.0.30000709" } }, "bser": { @@ -2174,7 +2129,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -2238,15 +2193,15 @@ "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", "requires": { "browserslist": "1.4.0", - "caniuse-db": "1.0.30000703", + "caniuse-db": "1.0.30000709", "lodash.memoize": "4.1.2", "lodash.uniq": "4.5.0" } }, "caniuse-db": { - "version": "1.0.30000703", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000703.tgz", - "integrity": "sha1-x9iZuK3qbaGqWHNV05rIUz+HhAM=" + "version": "1.0.30000709", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000709.tgz", + "integrity": "sha1-C2AAcrfNu/YzaodYtxua0DJo7eI=" }, "caseless": { "version": "0.11.0", @@ -2256,7 +2211,7 @@ "catbox": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/catbox/-/catbox-7.1.5.tgz", - "integrity": "sha1-xW9+jpVV0nwNwDipbvc+V9GGux8=", + "integrity": "sha512-4fui5lELzqZ+9cnaAP/BcqXTH6LvWLBRtFhJ0I4FfgfXiSaZcf6k9m9dqOyChiTxNYtvLk7ZMYSf7ahMq3bf5A==", "requires": { "boom": "5.2.0", "hoek": "4.2.0", @@ -2266,7 +2221,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -2274,7 +2229,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -2289,7 +2244,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -2424,7 +2379,7 @@ "integrity": "sha1-kMMq1IApAddxPeUy3ChOlqY60Fg=", "dev": true, "requires": { - "anymatch": "1.3.0", + "anymatch": "1.3.2", "async-each": "1.0.1", "glob-parent": "2.0.0", "inherits": "2.0.3", @@ -2449,7 +2404,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -2463,7 +2418,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -2489,7 +2444,7 @@ "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { "inherits": "2.0.3", @@ -2497,9 +2452,9 @@ } }, "circular-json": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", - "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, "clap": { @@ -2578,7 +2533,7 @@ "dev": true, "requires": { "d": "0.1.1", - "es5-ext": "0.10.24", + "es5-ext": "0.10.26", "memoizee": "0.3.10", "timers-ext": "0.1.2" }, @@ -2589,7 +2544,7 @@ "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", "dev": true, "requires": { - "es5-ext": "0.10.24" + "es5-ext": "0.10.26" } } } @@ -2824,12 +2779,12 @@ "dev": true }, "compressible": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.10.tgz", - "integrity": "sha1-/tocf3YXkScyspv4zyYlKiC57s0=", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.11.tgz", + "integrity": "sha1-FnGKdd4oPtjmBAQWJaIGRYZ5fYo=", "dev": true, "requires": { - "mime-db": "1.27.0" + "mime-db": "1.29.0" } }, "compression": { @@ -2840,7 +2795,7 @@ "requires": { "accepts": "1.3.3", "bytes": "2.5.0", - "compressible": "2.0.10", + "compressible": "2.0.11", "debug": "2.6.8", "on-headers": "1.0.1", "safe-buffer": "5.1.1", @@ -2968,9 +2923,9 @@ "dev": true }, "content": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/content/-/content-3.0.4.tgz", - "integrity": "sha1-yj3eBEgPElGbcVJuxEvUiN37P+8=", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/content/-/content-3.0.5.tgz", + "integrity": "sha512-MQVYZuNnm5N0xalwtRGlZrcKFwgE6VKXCEh3XkCeoWUo3gL5BS52UiqswRvAwQW1ocfdCNkEKI5uy0pNGax+IQ==", "requires": { "boom": "5.2.0" }, @@ -2978,7 +2933,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -2986,7 +2941,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -3047,12 +3002,12 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cosmiconfig": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.1.3.tgz", - "integrity": "sha1-lSdx6w3dwcs/ovb75RpSLpOz7go=", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", + "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==", "requires": { "is-directory": "0.3.1", - "js-yaml": "3.9.0", + "js-yaml": "3.9.1", "minimist": "1.2.0", "object-assign": "4.1.1", "os-homedir": "1.0.2", @@ -3060,20 +3015,6 @@ "require-from-string": "1.2.1" }, "dependencies": { - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=" - }, - "js-yaml": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.0.tgz", - "integrity": "sha1-T/u/JcKsljuCmdx02n43QN4cGM4=", - "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" - } - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -3206,7 +3147,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -3214,7 +3155,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -3439,7 +3380,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.24" + "es5-ext": "0.10.26" } }, "d3": { @@ -3799,12 +3740,12 @@ "dev": true }, "duplexify": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", - "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", "dev": true, "requires": { - "end-of-stream": "1.0.0", + "end-of-stream": "1.4.0", "inherits": "2.0.3", "readable-stream": "2.3.3", "stream-shift": "1.0.0" @@ -3952,28 +3893,17 @@ "iconv-lite": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha1-I9hlaxaq5nQqwpcy6o8DNqR4nPI=" + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" } } }, "end-of-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", - "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", "dev": true, "requires": { - "once": "1.3.3" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - } + "once": "1.4.0" } }, "engine.io": { @@ -4097,7 +4027,7 @@ "dev": true, "requires": { "cheerio": "0.22.0", - "function.prototype.name": "1.0.2", + "function.prototype.name": "1.0.3", "is-subset": "0.1.1", "lodash": "4.17.4", "object-is": "1.0.1", @@ -4180,9 +4110,9 @@ } }, "es5-ext": { - "version": "0.10.24", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", - "integrity": "sha1-pVh3yZJLwMjZvTwsvhdJWsFwmxQ=", + "version": "0.10.26", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.26.tgz", + "integrity": "sha1-UbISilMbcMT2dkCTpzy+u4IYY3I=", "dev": true, "requires": { "es6-iterator": "2.0.1", @@ -4196,7 +4126,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.24", + "es5-ext": "0.10.26", "es6-symbol": "3.1.1" } }, @@ -4207,7 +4137,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.24", + "es5-ext": "0.10.26", "es6-iterator": "2.0.1", "es6-set": "0.1.5", "es6-symbol": "3.1.1", @@ -4226,7 +4156,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.24", + "es5-ext": "0.10.26", "es6-iterator": "2.0.1", "es6-symbol": "3.1.1", "event-emitter": "0.3.5" @@ -4239,7 +4169,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.24" + "es5-ext": "0.10.26" } }, "es6-templates": { @@ -4259,7 +4189,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.24", + "es5-ext": "0.10.26", "es6-iterator": "2.0.1", "es6-symbol": "3.1.1" } @@ -4341,7 +4271,7 @@ "inquirer": "0.12.0", "is-my-json-valid": "2.16.0", "is-resolvable": "1.0.0", - "js-yaml": "3.9.0", + "js-yaml": "3.9.1", "json-stable-stringify": "1.0.1", "levn": "0.3.0", "lodash": "4.17.4", @@ -4385,16 +4315,10 @@ "supports-color": "2.0.0" } }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", - "dev": true - }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -4414,16 +4338,6 @@ "ansi-regex": "2.1.1" } }, - "js-yaml": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.0.tgz", - "integrity": "sha1-T/u/JcKsljuCmdx02n43QN4cGM4=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" - } - }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", @@ -4433,7 +4347,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -4465,17 +4379,17 @@ "eslint-import-resolver-node": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz", - "integrity": "sha1-RCJXTN5mqaewmZOO5NUIoZng48w=", + "integrity": "sha512-yUtXS15gIcij68NmXmP9Ni77AQuCN0itXbCc/jWd8C6/yKZaSNXicpC8cgvjnxVdmfsosIXrjpzFq7GcDryb6A==", "dev": true, "requires": { "debug": "2.6.8", - "resolve": "1.3.3" + "resolve": "1.4.0" } }, "eslint-import-resolver-webpack": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.8.3.tgz", - "integrity": "sha1-rWHijfN4pHRFnZU/JG/UP5JnU4U=", + "integrity": "sha512-xLSNz4KbWvb8KrkDqWSmgmztq8uXq7R/rviOw1DYrh3Luxc8vpMnwO4hOt9Eot45VBiyjt1PxidrvJbZIWlItA==", "dev": true, "requires": { "array-find": "1.0.0", @@ -4487,8 +4401,8 @@ "is-absolute": "0.2.6", "lodash.get": "3.7.0", "node-libs-browser": "1.1.1", - "resolve": "1.3.3", - "semver": "5.3.0" + "resolve": "1.4.0", + "semver": "5.4.1" }, "dependencies": { "constants-browserify": { @@ -4500,7 +4414,7 @@ "crypto-browserify": { "version": "3.11.1", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz", - "integrity": "sha1-lIlF78Z1ekANbl5a9HGU0QBkJ58=", + "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==", "dev": true, "requires": { "browserify-cipher": "1.0.0", @@ -4510,7 +4424,7 @@ "create-hmac": "1.1.6", "diffie-hellman": "5.0.2", "inherits": "2.0.3", - "pbkdf2": "3.0.12", + "pbkdf2": "3.0.13", "public-encrypt": "4.0.0", "randombytes": "2.0.5" } @@ -4575,9 +4489,9 @@ "dev": true }, "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, "stream-browserify": { @@ -4619,7 +4533,7 @@ "eslint-module-utils": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", - "integrity": "sha1-q67IJBd2E7ipWymWOeG2+s9HNEk=", + "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", "dev": true, "requires": { "debug": "2.6.8", @@ -4668,7 +4582,7 @@ "requires": { "debug": "2.6.8", "object-assign": "4.1.1", - "resolve": "1.3.3" + "resolve": "1.4.0" } }, "load-json-file": { @@ -4686,7 +4600,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -4769,7 +4683,7 @@ "acorn": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", - "integrity": "sha1-U/4WERH5EquZnuiHqQoLxSgi/XU=", + "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==", "dev": true } } @@ -4846,7 +4760,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.24" + "es5-ext": "0.10.26" } }, "event-stream": { @@ -4909,13 +4823,13 @@ } }, "execa": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.5.1.tgz", - "integrity": "sha1-3j+4XLjW6RyFvLzrFkWBeFy1ezY=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "4.0.2", - "get-stream": "2.3.1", + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", "is-stream": "1.1.0", "npm-run-path": "2.0.2", "p-finally": "1.0.0", @@ -4924,12 +4838,13 @@ }, "dependencies": { "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { "lru-cache": "4.0.2", + "shebang-command": "1.2.0", "which": "1.2.14" } } @@ -5043,9 +4958,9 @@ "integrity": "sha1-s266AnRZyxI4cEFx1ciwBbd/wvM=" }, "express": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.15.2.tgz", - "integrity": "sha1-rxB/wUhQRFfy3Kmm8lcdcSm5ezU=", + "version": "4.15.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz", + "integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=", "requires": { "accepts": "1.3.3", "array-flatten": "1.1.1", @@ -5053,23 +4968,23 @@ "content-type": "1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", - "debug": "2.6.1", - "depd": "1.1.0", + "debug": "2.6.8", + "depd": "1.1.1", "encodeurl": "1.0.1", "escape-html": "1.0.3", "etag": "1.8.0", - "finalhandler": "1.0.3", + "finalhandler": "1.0.4", "fresh": "0.5.0", "merge-descriptors": "1.0.1", "methods": "1.1.2", "on-finished": "2.3.0", "parseurl": "1.3.1", "path-to-regexp": "0.1.7", - "proxy-addr": "1.1.4", - "qs": "6.4.0", + "proxy-addr": "1.1.5", + "qs": "6.5.0", "range-parser": "1.2.0", - "send": "0.15.1", - "serve-static": "1.12.1", + "send": "0.15.4", + "serve-static": "1.12.4", "setprototypeof": "1.0.3", "statuses": "1.3.1", "type-is": "1.6.15", @@ -5077,28 +4992,29 @@ "vary": "1.1.1" }, "dependencies": { - "debug": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz", - "integrity": "sha1-eYVQkLosTjEVzH2HaUkdWPBJE1E=", - "requires": { - "ms": "0.7.2" - } - }, "depd": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", - "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + "finalhandler": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz", + "integrity": "sha512-16l/r8RgzlXKmFOhZpHBztvye+lAhC5SU7hXavnerC9UfZqZxxXl3BzL8MhffPT3kF61lj9Oav2LKEzh0ei7tg==", + "requires": { + "debug": "2.6.8", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.1", + "statuses": "1.3.1", + "unpipe": "1.0.0" + } }, "on-finished": { "version": "2.3.0", @@ -5109,9 +5025,9 @@ } }, "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", + "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg==" } } }, @@ -5149,9 +5065,9 @@ } }, "extsprintf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", - "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, "faker": { @@ -5190,9 +5106,9 @@ } }, "fbjs": { - "version": "0.8.12", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz", - "integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=", + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz", + "integrity": "sha1-0dviviVMNakeCfMfnNUKQLKg7Rw=", "requires": { "core-js": "1.2.7", "isomorphic-fetch": "2.2.1", @@ -5216,7 +5132,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "requires": { "asap": "2.0.6" } @@ -5283,7 +5199,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -5297,7 +5213,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -5331,6 +5247,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk=", + "dev": true, "requires": { "debug": "2.6.7", "encodeurl": "1.0.1", @@ -5345,6 +5262,7 @@ "version": "2.6.7", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", + "dev": true, "requires": { "ms": "2.0.0" } @@ -5352,12 +5270,14 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, "requires": { "ee-first": "1.1.1" } @@ -5412,7 +5332,7 @@ "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", "dev": true, "requires": { - "circular-json": "0.3.1", + "circular-json": "0.3.3", "del": "2.2.2", "graceful-fs": "4.1.11", "write": "0.2.1" @@ -5464,13 +5384,13 @@ "requires": { "async": "2.5.0", "combined-stream": "1.0.5", - "mime-types": "2.1.15" + "mime-types": "2.1.16" }, "dependencies": { "async": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha1-hDGQ/WtzV6C54clW7d3V7IRitU0=", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", "requires": { "lodash": "4.17.4" } @@ -5562,9 +5482,9 @@ "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=" }, "function.prototype.name": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.0.2.tgz", - "integrity": "sha512-RbgGSvTDidZb8VOznhL/1EUKahRdFtyqyatfqU3OJCT7zmQYnaaMj72SRn5mmFep5tdUjsEn0RgHjhJ++gd7Dg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.0.3.tgz", + "integrity": "sha512-5EblxZUdioXi2JiMZ9FUbwYj40eQ9MFHyzFLBSPdlRl3SO8l7SLWuAnQ/at/1Wi4hjJwME/C5WpF2ZfAc8nGNw==", "dev": true, "requires": { "define-properties": "1.1.2", @@ -5622,14 +5542,10 @@ "dev": true }, "get-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "pinkie-promise": "2.0.1" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true }, "getobject": { "version": "0.1.0", @@ -5707,7 +5623,7 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=" + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" }, "globby": { "version": "5.0.0", @@ -5726,7 +5642,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -5740,7 +5656,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -5762,7 +5678,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -5782,7 +5698,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -5833,7 +5749,7 @@ "integrity": "sha1-5dDtSvVfw+701WAHdp2YGSvLLso=", "dev": true, "requires": { - "duplexify": "3.5.0", + "duplexify": "3.5.1", "infinity-agent": "2.0.3", "is-redirect": "1.0.0", "is-stream": "1.1.0", @@ -5941,7 +5857,7 @@ "iconv-lite": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha1-I9hlaxaq5nQqwpcy6o8DNqR4nPI=", + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", "dev": true }, "js-yaml": { @@ -5957,7 +5873,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -6130,7 +6046,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -6144,7 +6060,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -6216,13 +6132,13 @@ "grunt-esvm": { "version": "3.2.10", "resolved": "https://registry.npmjs.org/grunt-esvm/-/grunt-esvm-3.2.10.tgz", - "integrity": "sha1-QPTjkUN3OyhkS7VRwUt1aMUhkxo=", + "integrity": "sha512-LTIV+WXR1UTtVlPvfYrQ2kXBWAhWMv7w3jPG5kQZhVJHIdr8rVeW9MXf/xwaUmMO1emDo5bIaVxm8c9nApiGYA==", "dev": true, "requires": { "bluebird": "2.9.34", "cli-color": "0.3.3", "cli-table": "0.3.1", - "libesvm": "3.8.4", + "libesvm": "3.8.6", "lodash": "3.10.1", "moment": "2.13.0", "wreck": "5.6.1" @@ -6449,7 +6365,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, "isemail": { "version": "2.2.1", @@ -6550,7 +6466,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, "isemail": { "version": "2.2.1", @@ -6700,7 +6616,7 @@ "hash.js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha1-NA3tvmKQGHFRweodd3o0SJNd+EY=", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "dev": true, "requires": { "inherits": "2.0.3", @@ -6746,7 +6662,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -6754,7 +6670,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -6826,7 +6742,7 @@ "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=" + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" }, "html": { "version": "1.0.0", @@ -6985,6 +6901,7 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=", + "dev": true, "requires": { "depd": "1.1.0", "inherits": "2.0.3", @@ -6995,7 +6912,8 @@ "depd": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", - "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=" + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", + "dev": true } } }, @@ -7167,7 +7085,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, "isemail": { "version": "2.2.1", @@ -7330,9 +7248,9 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ipaddr.js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz", - "integrity": "sha1-HgOlL9rYOou7KyXL9JmLTP/NPew=" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", + "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=" }, "iron": { "version": "4.0.5", @@ -7347,7 +7265,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -7355,7 +7273,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -7384,7 +7302,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "requires": { - "binary-extensions": "1.8.0" + "binary-extensions": "1.9.0" } }, "is-buffer": { @@ -7712,7 +7630,7 @@ "esprima": "2.7.3", "glob": "5.0.15", "handlebars": "4.0.5", - "js-yaml": "3.4.1", + "js-yaml": "3.9.1", "mkdirp": "0.5.1", "nopt": "3.0.6", "once": "1.4.0", @@ -7778,7 +7696,7 @@ "istanbul-lib-report": "1.1.1", "istanbul-lib-source-maps": "1.2.1", "istanbul-reports": "1.1.1", - "js-yaml": "3.9.0", + "js-yaml": "3.9.1", "mkdirp": "0.5.1", "once": "1.4.0" }, @@ -7786,28 +7704,12 @@ "async": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha1-hDGQ/WtzV6C54clW7d3V7IRitU0=", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", "dev": true, "requires": { "lodash": "4.17.4" } }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", - "dev": true - }, - "js-yaml": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.0.tgz", - "integrity": "sha1-T/u/JcKsljuCmdx02n43QN4cGM4=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" - } - }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", @@ -7828,12 +7730,12 @@ "istanbul-lib-coverage": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz", - "integrity": "sha1-c7+5mIhSmUFck9OKPprfeEp3qdo=" + "integrity": "sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q==" }, "istanbul-lib-hook": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz", - "integrity": "sha1-3WYH8DB2V4/n1vKmMM8UO0m6zdw=", + "integrity": "sha512-3U2HB9y1ZV9UmFlE12Fx+nPtFqIymzrqCksrXujm3NVbAZIJg/RfYgO1XiIa0mbmxTjWpVEVlkIZJ25xVIAfkQ==", "dev": true, "requires": { "append-transform": "0.4.0" @@ -7850,20 +7752,20 @@ "babel-types": "6.25.0", "babylon": "6.17.4", "istanbul-lib-coverage": "1.1.1", - "semver": "5.3.0" + "semver": "5.4.1" }, "dependencies": { "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" } } }, "istanbul-lib-report": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", - "integrity": "sha1-8OVfVmVf+jQiIIC3oM1HYOFAX8k=", + "integrity": "sha512-tvF+YmCmH4thnez6JFX06ujIA19WPa9YUiwjc1uALF2cv5dmE3It8b5I8Ob7FHJ70H9Y5yF+TDkVa/mcADuw1Q==", "dev": true, "requires": { "istanbul-lib-coverage": "1.1.1", @@ -7886,7 +7788,7 @@ "istanbul-lib-source-maps": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz", - "integrity": "sha1-pv4ay6jOCO68Y45XLilNJnAIqgw=", + "integrity": "sha512-mukVvSXCn9JQvdJl8wP/iPhqig0MRtuWuD4ZNKo6vB2Ik//AmhAKe3QnPN02dmkRe3lTudFk3rzoHhwU4hb94w==", "dev": true, "requires": { "debug": "2.6.8", @@ -7899,7 +7801,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -7913,7 +7815,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -7933,7 +7835,7 @@ "istanbul-reports": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha1-BCvlyJ4XW8P4ZSPKqynAFOd/7k4=", + "integrity": "sha512-P8G873A0kW24XRlxHVGhMJBhQ8gWAec+dae7ZxOBzxT4w+a9ATSPvRVK3LB1RAJ9S8bg2tOyWHAGW40Zd2dKfw==", "dev": true, "requires": { "handlebars": "4.0.5" @@ -8026,7 +7928,7 @@ "throat": "3.2.0", "which": "1.2.14", "worker-farm": "1.4.1", - "yargs": "7.0.2" + "yargs": "7.1.0" }, "dependencies": { "ansi-regex": { @@ -8123,7 +8025,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -8146,7 +8048,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -8272,7 +8174,7 @@ "requires": { "asynckit": "0.4.0", "combined-stream": "1.0.5", - "mime-types": "2.1.15" + "mime-types": "2.1.16" } }, "har-validator": { @@ -8292,7 +8194,7 @@ "dev": true, "requires": { "assert-plus": "0.2.0", - "jsprim": "1.4.0", + "jsprim": "1.4.1", "sshpk": "1.13.1" } }, @@ -8348,7 +8250,7 @@ "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", + "mime-types": "2.1.16", "oauth-sign": "0.8.2", "performance-now": "0.2.0", "qs": "6.4.0", @@ -8590,7 +8492,7 @@ "requires": { "browser-resolve": "1.11.2", "is-builtin-module": "1.0.0", - "resolve": "1.3.3" + "resolve": "1.4.0" } }, "jest-resolve-dependencies": { @@ -8622,7 +8524,7 @@ "json-stable-stringify": "1.0.1", "micromatch": "2.3.11", "strip-bom": "3.0.0", - "yargs": "7.0.2" + "yargs": "7.1.0" }, "dependencies": { "ansi-regex": { @@ -8866,7 +8768,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, "isemail": { "version": "2.2.1", @@ -8904,18 +8806,18 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.4.1.tgz", - "integrity": "sha1-cYOZDGL2RjaeqgRnWy1fHnHWK4s=", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", + "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", "requires": { "argparse": "1.0.9", - "esprima": "2.2.0" + "esprima": "4.0.0" }, "dependencies": { "esprima": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.2.0.tgz", - "integrity": "sha1-QpLB1o5Bc9gV+iKQ3Hr8ltgfzYM=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" } } }, @@ -8957,7 +8859,7 @@ "iconv-lite": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha1-I9hlaxaq5nQqwpcy6o8DNqR4nPI=", + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", "dev": true }, "webidl-conversions": { @@ -9053,15 +8955,15 @@ } }, "jsprim": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", - "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, "requires": { "assert-plus": "1.0.0", - "extsprintf": "1.0.2", + "extsprintf": "1.3.0", "json-schema": "0.2.3", - "verror": "1.3.6" + "verror": "1.10.0" }, "dependencies": { "assert-plus": { @@ -9151,7 +9053,7 @@ "bytes": "2.4.0", "content-type": "1.0.2", "debug": "2.6.7", - "depd": "1.1.0", + "depd": "1.1.1", "http-errors": "1.6.1", "iconv-lite": "0.4.15", "on-finished": "2.3.0", @@ -9176,9 +9078,9 @@ } }, "depd": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", - "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", "dev": true }, "ee-first": { @@ -9190,7 +9092,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -9210,7 +9112,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -9288,7 +9190,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -9365,7 +9267,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -9443,7 +9345,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "optional": true, "requires": { "asap": "2.0.6" @@ -9476,16 +9378,16 @@ } }, "libesvm": { - "version": "3.8.4", - "resolved": "https://registry.npmjs.org/libesvm/-/libesvm-3.8.4.tgz", - "integrity": "sha1-2jYS/2b/s3+tBoGQurEZ6DYrn1U=", + "version": "3.8.6", + "resolved": "https://registry.npmjs.org/libesvm/-/libesvm-3.8.6.tgz", + "integrity": "sha512-v9CXO8o3qM1fqQp965OX9OT8tieKNmNOmkaxOGMROxiIH+b3mhfk6jZS1ua+zSl81n4y54TtzNtFNdbng/EJHg==", "dev": true, "requires": { "bcryptjs": "2.4.3", "bluebird": "2.10.2", "fs-extra": "0.24.0", "glob": "6.0.4", - "js-yaml": "3.9.0", + "js-yaml": "3.9.1", "lodash": "2.4.2", "lodash.defaultsdeep": "4.6.0", "lodash.forown": "4.4.0", @@ -9530,16 +9432,23 @@ "integrity": "sha1-AkpVFylTCIV/FPkfEQb8O1VfRGs=", "dev": true }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, "commander": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=", - "dev": true - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", "dev": true }, "glob": { @@ -9565,21 +9474,6 @@ "commander": "2.11.0", "is-my-json-valid": "2.16.0", "pinkie-promise": "2.0.1" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - } } }, "has-ansi": { @@ -9591,16 +9485,6 @@ "ansi-regex": "2.1.1" } }, - "js-yaml": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.0.tgz", - "integrity": "sha1-T/u/JcKsljuCmdx02n43QN4cGM4=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" - } - }, "lodash": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", @@ -9637,7 +9521,7 @@ "http-signature": "0.11.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", + "mime-types": "2.1.16", "node-uuid": "1.4.8", "oauth-sign": "0.8.2", "qs": "5.2.1", @@ -10192,7 +10076,7 @@ "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", "dev": true, "requires": { - "es5-ext": "0.10.24" + "es5-ext": "0.10.26" } }, "macaddress": { @@ -10385,7 +10269,7 @@ "dev": true, "requires": { "d": "0.1.1", - "es5-ext": "0.10.24", + "es5-ext": "0.10.26", "es6-weak-map": "0.1.4", "event-emitter": "0.3.5", "lru-queue": "0.1.0", @@ -10399,7 +10283,7 @@ "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", "dev": true, "requires": { - "es5-ext": "0.10.24" + "es5-ext": "0.10.26" } }, "es6-iterator": { @@ -10409,7 +10293,7 @@ "dev": true, "requires": { "d": "0.1.1", - "es5-ext": "0.10.24", + "es5-ext": "0.10.26", "es6-symbol": "2.0.1" } }, @@ -10420,7 +10304,7 @@ "dev": true, "requires": { "d": "0.1.1", - "es5-ext": "0.10.24" + "es5-ext": "0.10.26" } }, "es6-weak-map": { @@ -10430,7 +10314,7 @@ "dev": true, "requires": { "d": "0.1.1", - "es5-ext": "0.10.24", + "es5-ext": "0.10.26", "es6-iterator": "0.1.3", "es6-symbol": "2.0.1" } @@ -10523,16 +10407,16 @@ "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" }, "mime-db": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", - "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", + "integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg=" }, "mime-types": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", - "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", + "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=", "requires": { - "mime-db": "1.27.0" + "mime-db": "1.29.0" } }, "mimic-fn": { @@ -10547,13 +10431,13 @@ "integrity": "sha1-uRCQcq03jCty9qAQHEPd+ys2ZB8=", "requires": { "hoek": "4.2.0", - "mime-db": "1.27.0" + "mime-db": "1.29.0" }, "dependencies": { "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -10644,7 +10528,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -10712,7 +10596,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -10805,7 +10689,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -10839,7 +10723,7 @@ "qs": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", - "integrity": "sha1-jQSVTTZN7z78VbWgeT4eLIsebkk=", + "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg==", "dev": true } } @@ -10876,7 +10760,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -10890,7 +10774,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -10970,15 +10854,15 @@ "dev": true, "requires": { "growly": "1.3.0", - "semver": "5.3.0", + "semver": "5.4.1", "shellwords": "0.1.0", "which": "1.2.14" }, "dependencies": { "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true } } @@ -11033,7 +10917,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -11056,7 +10940,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -11082,7 +10966,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "requires": { "hosted-git-info": "2.5.0", "is-builtin-module": "1.0.0", @@ -11126,7 +11010,7 @@ "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { "are-we-there-yet": "1.1.4", @@ -11432,7 +11316,7 @@ "browserify-aes": "1.0.6", "create-hash": "1.1.3", "evp_bytestokey": "1.0.0", - "pbkdf2": "3.0.12" + "pbkdf2": "3.0.13" } }, "parse-glob": { @@ -11574,9 +11458,9 @@ } }, "pbkdf2": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.12.tgz", - "integrity": "sha1-vjZ4XFBn6kjYBv+SMojF91C2uKI=", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.13.tgz", + "integrity": "sha512-+dCHxDH+djNtjgWmvVC/my3SYBAKpKNqKSjLkp+GtWWYe4XPE+e/PSD2aCanlEZZnqPk2uekTKNC/ccbwd2X2Q==", "dev": true, "requires": { "create-hash": "1.1.3", @@ -11637,9 +11521,9 @@ "resolved": "https://registry.npmjs.org/pez/-/pez-2.1.5.tgz", "integrity": "sha1-XsLMYlAMw+tCNtSkFM9aF7XrUAc=", "requires": { - "b64": "3.0.2", + "b64": "3.0.3", "boom": "5.2.0", - "content": "3.0.4", + "content": "3.0.5", "hoek": "4.2.0", "nigel": "2.0.2" }, @@ -11647,7 +11531,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -11655,7 +11539,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -11899,7 +11783,7 @@ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", "requires": { - "cosmiconfig": "2.1.3", + "cosmiconfig": "2.2.2", "object-assign": "4.1.1", "postcss-load-options": "1.2.0", "postcss-load-plugins": "2.3.0" @@ -11910,7 +11794,7 @@ "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", "requires": { - "cosmiconfig": "2.1.3", + "cosmiconfig": "2.2.2", "object-assign": "4.1.1" } }, @@ -11919,7 +11803,7 @@ "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", "requires": { - "cosmiconfig": "2.1.3", + "cosmiconfig": "2.2.2", "object-assign": "4.1.1" } }, @@ -11969,7 +11853,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "requires": { - "caniuse-db": "1.0.30000703", + "caniuse-db": "1.0.30000709", "electron-to-chromium": "1.3.16" } } @@ -12029,24 +11913,6 @@ "postcss": "6.0.8" }, "dependencies": { - "ansi-styles": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.1.0.tgz", - "integrity": "sha1-CcIC1ckX7CMYjKpcnLkXnNlUd1A=", - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha1-2+xJQ20q4V9TYRTnbRRlbNvA9E0=", - "requires": { - "ansi-styles": "3.1.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.0" - } - }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -12055,17 +11921,17 @@ "postcss": { "version": "6.0.8", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", - "integrity": "sha1-iQZ6nOixH4qEy8URfvwwQZoIV7M=", + "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", "requires": { "chalk": "2.0.1", "source-map": "0.5.6", - "supports-color": "4.2.0" + "supports-color": "4.2.1" } }, "supports-color": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.0.tgz", - "integrity": "sha512-Ts0Mu/A1S1aZxEJNG88I4Oc9rcZSBFNac5e27yh4j2mqbhZSSzR1Ah79EYwSn9Zuh7lrlGD2cVGzw1RKGzyLSg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", + "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", "requires": { "has-flag": "2.0.0" } @@ -12081,24 +11947,6 @@ "postcss": "6.0.8" }, "dependencies": { - "ansi-styles": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.1.0.tgz", - "integrity": "sha1-CcIC1ckX7CMYjKpcnLkXnNlUd1A=", - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha1-2+xJQ20q4V9TYRTnbRRlbNvA9E0=", - "requires": { - "ansi-styles": "3.1.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.0" - } - }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -12107,17 +11955,17 @@ "postcss": { "version": "6.0.8", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", - "integrity": "sha1-iQZ6nOixH4qEy8URfvwwQZoIV7M=", + "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", "requires": { "chalk": "2.0.1", "source-map": "0.5.6", - "supports-color": "4.2.0" + "supports-color": "4.2.1" } }, "supports-color": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.0.tgz", - "integrity": "sha512-Ts0Mu/A1S1aZxEJNG88I4Oc9rcZSBFNac5e27yh4j2mqbhZSSzR1Ah79EYwSn9Zuh7lrlGD2cVGzw1RKGzyLSg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", + "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", "requires": { "has-flag": "2.0.0" } @@ -12133,24 +11981,6 @@ "postcss": "6.0.8" }, "dependencies": { - "ansi-styles": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.1.0.tgz", - "integrity": "sha1-CcIC1ckX7CMYjKpcnLkXnNlUd1A=", - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha1-2+xJQ20q4V9TYRTnbRRlbNvA9E0=", - "requires": { - "ansi-styles": "3.1.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.0" - } - }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -12159,17 +11989,17 @@ "postcss": { "version": "6.0.8", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", - "integrity": "sha1-iQZ6nOixH4qEy8URfvwwQZoIV7M=", + "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", "requires": { "chalk": "2.0.1", "source-map": "0.5.6", - "supports-color": "4.2.0" + "supports-color": "4.2.1" } }, "supports-color": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.0.tgz", - "integrity": "sha512-Ts0Mu/A1S1aZxEJNG88I4Oc9rcZSBFNac5e27yh4j2mqbhZSSzR1Ah79EYwSn9Zuh7lrlGD2cVGzw1RKGzyLSg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", + "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", "requires": { "has-flag": "2.0.0" } @@ -12185,24 +12015,6 @@ "postcss": "6.0.8" }, "dependencies": { - "ansi-styles": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.1.0.tgz", - "integrity": "sha1-CcIC1ckX7CMYjKpcnLkXnNlUd1A=", - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha1-2+xJQ20q4V9TYRTnbRRlbNvA9E0=", - "requires": { - "ansi-styles": "3.1.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.0" - } - }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -12211,17 +12023,17 @@ "postcss": { "version": "6.0.8", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", - "integrity": "sha1-iQZ6nOixH4qEy8URfvwwQZoIV7M=", + "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", "requires": { "chalk": "2.0.1", "source-map": "0.5.6", - "supports-color": "4.2.0" + "supports-color": "4.2.1" } }, "supports-color": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.0.tgz", - "integrity": "sha512-Ts0Mu/A1S1aZxEJNG88I4Oc9rcZSBFNac5e27yh4j2mqbhZSSzR1Ah79EYwSn9Zuh7lrlGD2cVGzw1RKGzyLSg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", + "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", "requires": { "has-flag": "2.0.0" } @@ -12358,7 +12170,7 @@ "dev": true, "requires": { "ansi-regex": "2.1.1", - "ansi-styles": "3.1.0" + "ansi-styles": "3.2.0" }, "dependencies": { "ansi-regex": { @@ -12368,9 +12180,9 @@ "dev": true }, "ansi-styles": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.1.0.tgz", - "integrity": "sha1-CcIC1ckX7CMYjKpcnLkXnNlUd1A=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { "color-convert": "1.9.0" @@ -12412,7 +12224,7 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.8.tgz", "integrity": "sha1-a3suFBCDvjjIWVqlH8VXdccZk5Q=", "requires": { - "fbjs": "0.8.12" + "fbjs": "0.8.14" } }, "propagate": { @@ -12428,12 +12240,12 @@ "dev": true }, "proxy-addr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz", - "integrity": "sha1-J+VF9pYKRKYn2bREZ+NcG2tM4vM=", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", + "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", "requires": { "forwarded": "0.1.0", - "ipaddr.js": "1.3.0" + "ipaddr.js": "1.4.0" } }, "proxyquire": { @@ -12488,7 +12300,7 @@ "resolved": "https://registry.npmjs.org/pui-react-animation/-/pui-react-animation-0.2.1.tgz", "integrity": "sha1-tmol6cDMfJeV/hAYyChyvQDv3SM=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "easing-js": "1.1.2", "performance-now": "0.2.0", "raf": "3.3.2", @@ -12500,7 +12312,7 @@ "resolved": "https://registry.npmjs.org/pui-react-mixins/-/pui-react-mixins-7.5.4.tgz", "integrity": "sha1-vcBX1NXAvm5Cd8YKppL3yMxMRHk=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "fbjs": "0.7.2", "pui-react-animation": "0.2.1", "raf": "3.3.2", @@ -12532,7 +12344,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "requires": { "asap": "2.0.6" } @@ -12544,7 +12356,7 @@ "resolved": "https://registry.npmjs.org/pui-react-overlay-trigger/-/pui-react-overlay-trigger-7.5.4.tgz", "integrity": "sha1-NjCYrye02ri9/HOeg/SeIFX9j9Y=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "lodash.uniqueid": "3.2.0", "pui-react-mixins": "7.5.4", "react-tether": "0.5.7" @@ -12555,7 +12367,7 @@ "resolved": "https://registry.npmjs.org/pui-react-tooltip/-/pui-react-tooltip-7.5.4.tgz", "integrity": "sha1-cE22aRkM9CiyTbLQa7zMb+s8/i0=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "classnames": "2.2.5", "pui-css-tooltips": "7.5.4" } @@ -12635,7 +12447,7 @@ "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -12672,7 +12484,7 @@ "randombytes": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", - "integrity": "sha1-3ACaJGuNCaF3tLegrne8Vw9LG3k=", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -12741,7 +12553,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-15.4.2.tgz", "integrity": "sha1-QfeZGyYYU5K6m66WyIiefgGDl+8=", "requires": { - "fbjs": "0.8.12", + "fbjs": "0.8.14", "loose-envify": "1.3.1", "object-assign": "4.1.1" } @@ -12770,7 +12582,7 @@ "resolved": "https://registry.npmjs.org/react-addons-shallow-compare/-/react-addons-shallow-compare-15.6.0.tgz", "integrity": "sha1-t6Tl/58nBMIM9obdigXdCLJt4lI=", "requires": { - "fbjs": "0.8.12", + "fbjs": "0.8.14", "object-assign": "4.1.1" } }, @@ -12779,7 +12591,7 @@ "resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.4.2.tgz", "integrity": "sha1-k7yqcY/K5zYNQuj7HAl1bMNjAqI=", "requires": { - "fbjs": "0.8.12", + "fbjs": "0.8.14", "object-assign": "4.1.1" } }, @@ -12819,7 +12631,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.4.2.tgz", "integrity": "sha1-AVNj8FsKH9Uq6e/dOgBg2QaVII8=", "requires": { - "fbjs": "0.8.12", + "fbjs": "0.8.14", "loose-envify": "1.3.1", "object-assign": "4.1.1" } @@ -12970,7 +12782,7 @@ "read-package-json": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.0.10.tgz", - "integrity": "sha1-3AIp9t3mtLcFs54lstlw6+lWha4=", + "integrity": "sha512-iNWaEs9hW9nviu5rHADmkm/Ob5dvah5zajtTS1XbyERSzkWgSwWZ6Z12bION7bEAzVc2YRFWnAz8k/tAr+5/eg==", "dev": true, "requires": { "glob": "7.1.2", @@ -12982,7 +12794,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -12996,7 +12808,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -13045,7 +12857,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -13082,7 +12894,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "1.1.8" } @@ -13126,7 +12938,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.3.3" + "resolve": "1.4.0" } }, "redent": { @@ -13196,7 +13008,7 @@ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.11.tgz", "integrity": "sha1-On0GdSDLe3F2dp61/4aGkb7+EoM=", "requires": { - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-types": "6.25.0", "private": "0.1.7" } @@ -13301,7 +13113,7 @@ "http-signature": "0.11.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", + "mime-types": "2.1.16", "node-uuid": "1.4.8", "oauth-sign": "0.8.2", "qs": "4.0.0", @@ -13368,9 +13180,9 @@ "integrity": "sha1-VaT/Pk8hKnZHCDX7dZDbtio+ZUI=" }, "resolve": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", - "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", "dev": true, "requires": { "path-parse": "1.0.5" @@ -13484,7 +13296,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "safe-json-stringify": { "version": "1.0.4", @@ -13514,7 +13326,7 @@ "integrity": "sha1-lhDEUjB6E10pwf3+JUcDQYDEZ3U=", "dev": true, "requires": { - "anymatch": "1.3.0", + "anymatch": "1.3.2", "exec-sh": "0.2.0", "fb-watchman": "1.9.2", "minimatch": "3.0.4", @@ -13544,7 +13356,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -13567,13 +13379,13 @@ "glob": "7.1.2", "lodash": "4.17.4", "scss-tokenizer": "0.2.3", - "yargs": "7.0.2" + "yargs": "7.1.0" }, "dependencies": { "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -13593,7 +13405,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -13615,7 +13427,7 @@ "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "script-loader": { "version": "0.6.1", @@ -13661,47 +13473,45 @@ } }, "send": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.15.1.tgz", - "integrity": "sha1-igI1TCbm9cynAAZfXwzeupDse18=", + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/send/-/send-0.15.4.tgz", + "integrity": "sha1-mF+qPihLAnPHkzZKNcZze9k5Bbk=", "requires": { - "debug": "2.6.1", - "depd": "1.1.0", + "debug": "2.6.8", + "depd": "1.1.1", "destroy": "1.0.4", "encodeurl": "1.0.1", "escape-html": "1.0.3", "etag": "1.8.0", "fresh": "0.5.0", - "http-errors": "1.6.1", + "http-errors": "1.6.2", "mime": "1.3.4", - "ms": "0.7.2", + "ms": "2.0.0", "on-finished": "2.3.0", "range-parser": "1.2.0", "statuses": "1.3.1" }, "dependencies": { - "debug": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz", - "integrity": "sha1-eYVQkLosTjEVzH2HaUkdWPBJE1E=", - "requires": { - "ms": "0.7.2" - } - }, "depd": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", - "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + } }, "on-finished": { "version": "2.3.0", @@ -13733,19 +13543,19 @@ "debug": "2.6.8", "escape-html": "1.0.3", "http-errors": "1.6.1", - "mime-types": "2.1.15", + "mime-types": "2.1.16", "parseurl": "1.3.1" } }, "serve-static": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.1.tgz", - "integrity": "sha1-dEOpZePO1kes61Y5+ga/TRu+ADk=", + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz", + "integrity": "sha1-m2qpjutyU8Tu3Ewfb9vKYJkBqWE=", "requires": { "encodeurl": "1.0.1", "escape-html": "1.0.3", "parseurl": "1.3.1", - "send": "0.15.1" + "send": "0.15.4" } }, "set-blocking": { @@ -13773,6 +13583,21 @@ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=" }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "shelljs": { "version": "0.7.8", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", @@ -13787,7 +13612,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -13807,7 +13632,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -13833,7 +13658,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -13871,9 +13696,9 @@ } }, "sinon": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.2.tgz", - "integrity": "sha1-wepnuEoeezNQ9sRxPvrO+OSui3E=", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", "dev": true, "requires": { "formatio": "1.1.1", @@ -14243,7 +14068,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, "isemail": { "version": "2.2.1", @@ -14332,7 +14157,7 @@ "stream-http": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "integrity": "sha1-QKBQ7I3DtTsz2ZCUFcAsC/Gr+60=", + "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", "dev": true, "requires": { "builtin-status-codes": "3.0.0", @@ -14356,7 +14181,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "requires": { "safe-buffer": "5.1.1" } @@ -14448,7 +14273,7 @@ "integrity": "sha1-L87JRd5CkoPD0YsVH/D6HxuHrsk=", "requires": { "boom": "5.2.0", - "content": "3.0.4", + "content": "3.0.5", "hoek": "4.2.0", "pez": "2.1.5", "wreck": "12.2.2" @@ -14457,7 +14282,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { "hoek": "4.2.0" } @@ -14465,7 +14290,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, "wreck": { "version": "12.2.2", @@ -14510,13 +14335,13 @@ "requires": { "asynckit": "0.4.0", "combined-stream": "1.0.5", - "mime-types": "2.1.15" + "mime-types": "2.1.16" } }, "qs": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", - "integrity": "sha1-jQSVTTZN7z78VbWgeT4eLIsebkk=", + "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg==", "dev": true } } @@ -14607,9 +14432,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "ansi-styles": { @@ -14629,23 +14454,6 @@ "has-ansi": "2.0.0", "strip-ansi": "3.0.1", "supports-color": "2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - } } }, "has-ansi": { @@ -14655,14 +14463,6 @@ "dev": true, "requires": { "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } } }, "is-fullwidth-code-point": { @@ -14680,20 +14480,28 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } } }, "supports-color": { @@ -14740,7 +14548,7 @@ "test-exclude": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.1.1.tgz", - "integrity": "sha1-TYSWSwlmsAh+zDNKLOAC09k0HiY=", + "integrity": "sha512-35+Asrsk3XHJDBgf/VRFexPgh3UyETv8IAn/LRTiZjVy6rjPVqdEk8dJcJYBzl1w0XCJM48lvTy8SfEsCWS4nA==", "requires": { "arrify": "1.0.1", "micromatch": "2.3.11", @@ -14763,7 +14571,7 @@ "throat": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/throat/-/throat-3.2.0.tgz", - "integrity": "sha1-UMsGcO28QCN7njR9fh+I5GIK+DY=", + "integrity": "sha512-/EY8VpvlqJ+sFtLPeOgc8Pl7kQVOWv0woD87KTXVHPIAE842FGT+rokxIhe8xIUP1cfgrkt0as0vDLjDiMtr8w==", "dev": true }, "through": { @@ -14812,6 +14620,12 @@ "resolved": "https://registry.npmjs.org/ticky/-/ticky-1.0.0.tgz", "integrity": "sha1-6H847gSR6jL2Lo8FZ7qWOLKfBJw=" }, + "time-stamp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", + "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", + "dev": true + }, "timed-out": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz", @@ -14832,7 +14646,7 @@ "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", "dev": true, "requires": { - "es5-ext": "0.10.24", + "es5-ext": "0.10.26", "next-tick": "1.0.0" }, "dependencies": { @@ -15032,22 +14846,20 @@ "dev": true }, "ts-jest": { - "version": "20.0.6", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-20.0.6.tgz", - "integrity": "sha1-OcKBDAXW9pCNrBWSna4ga0lLc/Q=", + "version": "20.0.10", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-20.0.10.tgz", + "integrity": "sha1-Gek4bmyJDTHCpk6TjtwMhPyTfrw=", "dev": true, "requires": { - "@types/babel-core": "6.7.14", "babel-core": "6.25.0", "babel-plugin-istanbul": "4.1.4", "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", "babel-preset-jest": "20.0.3", - "fs-extra": "3.0.1", + "fs-extra": "4.0.1", "jest-config": "20.0.4", "jest-util": "20.0.3", "pkg-dir": "2.0.0", "source-map-support": "0.4.15", - "tsconfig": "6.0.0", "yargs": "8.0.2" }, "dependencies": { @@ -15068,7 +14880,7 @@ "babel-helpers": "6.24.1", "babel-messages": "6.23.0", "babel-register": "6.24.1", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "babel-template": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0", @@ -15091,7 +14903,7 @@ "dev": true, "requires": { "babel-core": "6.25.0", - "babel-runtime": "6.23.0", + "babel-runtime": "6.25.0", "core-js": "2.4.1", "home-or-tmp": "2.0.0", "lodash": "4.17.4", @@ -15130,14 +14942,14 @@ } }, "fs-extra": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", - "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.1.tgz", + "integrity": "sha1-f8DGyJV/mD9X8waiTlud3Y0N2IA=", "dev": true, "requires": { "graceful-fs": "4.1.11", "jsonfile": "3.0.1", - "universalify": "0.1.0" + "universalify": "0.1.1" } }, "jsonfile": { @@ -15177,12 +14989,12 @@ } }, "os-locale": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.0.0.tgz", - "integrity": "sha1-FZGN7VEFIrge565aMJ1U9jn8OaQ=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "0.5.1", + "execa": "0.7.0", "lcid": "1.0.0", "mem": "1.1.0" } @@ -15284,7 +15096,7 @@ "cliui": "3.2.0", "decamelize": "1.2.0", "get-caller-file": "1.0.2", - "os-locale": "2.0.0", + "os-locale": "2.1.0", "read-pkg-up": "2.0.0", "require-directory": "2.1.1", "require-main-filename": "1.0.1", @@ -15306,24 +15118,6 @@ } } }, - "tsconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-6.0.0.tgz", - "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=", - "dev": true, - "requires": { - "strip-bom": "3.0.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -15351,9 +15145,9 @@ } }, "type-detect": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.0.tgz", - "integrity": "sha1-YgU4g1QqMh8veyV0bcaWR4sY/2s=" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", + "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=" }, "type-is": { "version": "1.6.15", @@ -15361,7 +15155,7 @@ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.15" + "mime-types": "2.1.16" } }, "typechecker": { @@ -15380,9 +15174,9 @@ "dev": true }, "typescript": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.1.tgz", - "integrity": "sha1-w8yxbdqgsjFN4DHn5v7onlujRrw=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.2.tgz", + "integrity": "sha1-+DlfhdRZJ2BnyYiqQYN6j4KHCEQ=", "dev": true }, "ua-parser-js": { @@ -15460,9 +15254,9 @@ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" }, "universalify": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.0.tgz", - "integrity": "sha1-nrHEZR3rzGcMyU8adXYjMruWd3g=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", "dev": true }, "unpipe": { @@ -15702,12 +15496,22 @@ "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=" }, "verror": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", - "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "extsprintf": "1.0.2" + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } } }, "vinyl": { @@ -15732,7 +15536,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -15758,7 +15562,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -15791,7 +15595,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } }, @@ -15806,7 +15610,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" } } } @@ -15873,7 +15677,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "requires": { - "anymatch": "1.3.0", + "anymatch": "1.3.2", "async-each": "1.0.1", "glob-parent": "2.0.0", "inherits": "2.0.3", @@ -15970,15 +15774,16 @@ } }, "webpack-dev-middleware": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.11.0.tgz", - "integrity": "sha1-CWkdCXOjCtH4Ksc6EuIIfwpHVPk=", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz", + "integrity": "sha1-007++y7dp+HTtdvgcolRMhllFwk=", "dev": true, "requires": { "memory-fs": "0.4.1", "mime": "1.3.4", "path-is-absolute": "1.0.1", - "range-parser": "1.2.0" + "range-parser": "1.2.0", + "time-stamp": "2.0.0" }, "dependencies": { "memory-fs": { @@ -16001,7 +15806,7 @@ "requires": { "compression": "1.7.0", "connect-history-api-fallback": "1.1.0", - "express": "4.15.2", + "express": "4.15.4", "http-proxy": "1.16.2", "optimist": "0.6.1", "serve-index": "1.9.0", @@ -16010,7 +15815,7 @@ "stream-cache": "0.0.2", "strip-ansi": "3.0.1", "supports-color": "3.2.3", - "webpack-dev-middleware": "1.11.0" + "webpack-dev-middleware": "1.12.0" }, "dependencies": { "supports-color": { @@ -16101,7 +15906,7 @@ "wide-align": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "dev": true, "requires": { "string-width": "1.0.2" @@ -16136,7 +15941,7 @@ "worker-farm": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.4.1.tgz", - "integrity": "sha1-pDi8mTp6fRM7y2VHyV7KfP9Il9g=", + "integrity": "sha512-tgFAtgOYLPutkAyzgpS6VJFL5HY+0ui1Tvua+fITgz8ByaJTMFGtazR6xxQfwfiAcbwE+2fLG/K49wc2TfwCNw==", "dev": true, "requires": { "errno": "0.1.4", @@ -16273,9 +16078,9 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.0.2.tgz", - "integrity": "sha1-EVuX3xMhgj6Lhkjolox4JSEiH2c=", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", "requires": { "camelcase": "3.0.0", "cliui": "3.2.0", diff --git a/package.json b/package.json index fda48285ec030..3640d01574b88 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "expiry-js": "0.1.7", "exports-loader": "0.6.2", "expose-loader": "0.7.0", - "express": "4.15.2", + "express": "4.15.4", "extract-text-webpack-plugin": "0.8.2", "file-loader": "0.8.4", "flot-charts": "0.8.3", @@ -144,7 +144,7 @@ "jade-loader": "0.7.1", "joi": "10.4.1", "jquery": "2.2.4", - "js-yaml": "3.4.1", + "js-yaml": "3.9.1", "json-loader": "0.5.3", "json-stringify-safe": "5.0.1", "jstimezonedetect": "1.0.5", @@ -197,7 +197,7 @@ "tinygradient": "0.3.0", "trunc-html": "1.0.2", "trunc-text": "1.0.2", - "type-detect": "4.0.0", + "type-detect": "4.0.3", "ui-select": "0.19.6", "url-loader": "0.5.6", "uuid": "3.0.1", @@ -205,7 +205,7 @@ "vision": "4.1.0", "webpack": "github:elastic/webpack#fix/query-params-for-aliased-loaders", "wreck": "6.2.0", - "yargs": "7.0.2", + "yargs": "7.1.0", "yauzl": "2.7.0" }, "devDependencies": { @@ -213,13 +213,13 @@ "@elastic/eslint-import-resolver-kibana": "0.8.1", "@elastic/eslint-plugin-kibana-custom": "1.0.3", "@types/chalk": "0.4.31", - "@types/chance": "0.7.33", + "@types/chance": "0.7.34", "@types/elasticsearch": "5.0.14", "@types/express": "4.0.36", - "@types/jest": "20.0.2", - "@types/js-yaml": "3.5.31", + "@types/jest": "20.0.6", + "@types/js-yaml": "3.9.0", "@types/lodash": "3.10.1", - "@types/node": "6.0.78", + "@types/node": "8.0.19", "@types/sinon": "1.16.36", "@types/supertest": "2.0.2", "@types/yargs": "6.6.0", @@ -288,15 +288,15 @@ "proxyquire": "1.7.10", "sass-loader": "4.0.0", "simple-git": "1.37.0", - "sinon": "1.17.2", + "sinon": "1.17.7", "source-map": "0.5.6", "source-map-support": "0.2.10", "strip-ansi": "^3.0.1", "supertest": "3.0.0", "supertest-as-promised": "2.0.2", "tree-kill": "1.1.0", - "ts-jest": "20.0.6", - "typescript": "2.4.1", + "ts-jest": "20.0.10", + "typescript": "2.4.2", "webpack-dev-server": "1.14.1" }, "engines": { diff --git a/platform/cli/__tests__/__snapshots__/cli.test.ts.snap b/platform/cli/__tests__/__snapshots__/cli.test.ts.snap index f252d77b6b44d..c5ea88648fce1 100644 --- a/platform/cli/__tests__/__snapshots__/cli.test.ts.snap +++ b/platform/cli/__tests__/__snapshots__/cli.test.ts.snap @@ -5,7 +5,8 @@ Object { "errors": Array [], "exit": true, "logs": Array [ - "Usage: bin/kibana [options] + Array [ + "Usage: bin/kibana [options] Kibana is an open source (Apache Licensed), browser-based analytics and search dashboard for Elasticsearch. @@ -34,6 +35,7 @@ Options: Documentation: https://elastic.co/kibana ", + ], ], "result": Object { "$0": "--help", @@ -66,7 +68,9 @@ Object { "errors": Array [], "exit": true, "logs": Array [ - "5.2.2", + Array [ + "5.2.2", + ], ], "result": Object { "$0": "--version", @@ -97,10 +101,16 @@ Object { exports[`fails for unknown options 1`] = ` Object { "errors": Array [ - "The following options were not recognized: + Array [ + "The following options were not recognized: [\\"foo\\"]", - "", - "Specify --help for available options", + ], + Array [ + "", + ], + Array [ + "Specify --help for available options", + ], ], "exit": true, "logs": Array [], @@ -134,9 +144,15 @@ Object { exports[`fails if config file does not exist 1`] = ` Object { "errors": Array [ - "Config file [/some-folder/kibana/config.yml] does not exist", - "", - "Specify --help for available options", + Array [ + "Config file [/some-folder/kibana/config.yml] does not exist", + ], + Array [ + "", + ], + Array [ + "Specify --help for available options", + ], ], "exit": true, "logs": Array [], @@ -170,9 +186,15 @@ Object { exports[`fails if port is not a number 1`] = ` Object { "errors": Array [ - "[port] must be a number, but was a string", - "", - "Specify --help for available options", + Array [ + "[port] must be a number, but was a string", + ], + Array [ + "", + ], + Array [ + "Specify --help for available options", + ], ], "exit": true, "logs": Array [], diff --git a/platform/cli/__tests__/captureTerminal.ts b/platform/cli/__tests__/captureTerminal.ts index 1d50ac5309ef3..35de4da40dbb8 100644 --- a/platform/cli/__tests__/captureTerminal.ts +++ b/platform/cli/__tests__/captureTerminal.ts @@ -1,72 +1,47 @@ -import { clone } from 'lodash'; - export function captureTerminal( fn: (argv: T) => any, argv: T ) { - const _exit = process.exit; - const _emit = process.emit; + let mockProcessExit = jest.spyOn(global.process, 'exit') + .mockImplementation(() => {}); + let mockProcessEmit = jest.spyOn(global.process, 'emit') + .mockImplementation(() => {}); + + let mockConsoleLog = jest.spyOn(global.console, 'log') + .mockImplementation(() => {}); + let mockConsoleWarn = jest.spyOn(global.console, 'warn') + .mockImplementation(() => {}); + let mockConsoleError = jest.spyOn(global.console, 'error') + .mockImplementation(() => {}); + const _env = process.env; const _argv = process.argv; - const _error = console.error; - const _log = console.log; - const _warn = console.warn; - - let exit = false; - process.exit = () => { - exit = true; + process.env = { + ...process.env, + _: 'node' }; - const env = clone(process.env); - env._ = 'node'; - process.env = env; process.argv = argv; - const errors: any[] = []; - const logs: any[] = []; - const warnings: any[] = []; - - console.error = (msg: any) => { - errors.push(msg); - }; - console.log = (msg: any) => { - logs.push(msg); - }; - console.warn = (msg: any) => { - warnings.push(msg); - }; - - let result: T; + const result: T = fn(argv); try { - result = fn(argv); + return { + errors: mockConsoleError.mock.calls, + logs: mockConsoleLog.mock.calls, + warnings: mockConsoleWarn.mock.calls, + exit: mockProcessExit.mock.calls.length > 0, + result + }; } finally { - reset(); - } - - return done(); + mockProcessExit.mockReset(); + mockProcessEmit.mockReset(); + mockConsoleLog.mockReset(); + mockConsoleWarn.mockReset(); + mockConsoleError.mockReset(); - function reset() { - process.exit = _exit; - process.emit = _emit; process.env = _env; process.argv = _argv; - - console.error = _error; - console.log = _log; - console.warn = _warn; - } - - function done() { - reset(); - - return { - errors, - logs, - warnings, - exit, - result - }; } } diff --git a/platform/logging/appenders/__tests__/FileAppender.test.ts b/platform/logging/appenders/__tests__/FileAppender.test.ts index 2fc0bbee818dd..1e991a4142041 100644 --- a/platform/logging/appenders/__tests__/FileAppender.test.ts +++ b/platform/logging/appenders/__tests__/FileAppender.test.ts @@ -66,7 +66,7 @@ test('file stream is created only once and only after first `append()` is called expect(mockCreateWriteStream).toHaveBeenCalledTimes(1); expect(mockCreateWriteStream).toHaveBeenCalledWith(mockPath, { flags: 'a', - encoding: 'utf8' + defaultEncoding: 'utf8' }); mockCreateWriteStream.mockClear(); diff --git a/platform/logging/appenders/file/FileAppender.ts b/platform/logging/appenders/file/FileAppender.ts index 2c6305ecce267..855875fe1f526 100644 --- a/platform/logging/appenders/file/FileAppender.ts +++ b/platform/logging/appenders/file/FileAppender.ts @@ -44,7 +44,7 @@ export class FileAppender implements DisposableAppender { if (this.outputStream === null) { this.outputStream = createWriteStream(this.path, { flags: 'a', - encoding: 'utf8' + defaultEncoding: 'utf8' }); } diff --git a/platform/root/__tests__/index.test.ts b/platform/root/__tests__/index.test.ts index 7e9c26a351be4..4de08c6214ff4 100644 --- a/platform/root/__tests__/index.test.ts +++ b/platform/root/__tests__/index.test.ts @@ -47,14 +47,9 @@ import { Env } from '../../config/Env'; const env = new Env('.', {}); const config$ = new BehaviorSubject({}); -let oldExit = process.exit; - -beforeEach(() => { - process.exit = jest.fn(); -}); - +let mockProcessExit = jest.spyOn(global.process, 'exit').mockImplementation(() => {}); afterEach(() => { - process.exit = oldExit; + mockProcessExit.mockReset(); }); test('starts services on "start"', async () => { diff --git a/platform/server/http/Router/headers.ts b/platform/server/http/Router/headers.ts index 4d549681a9a6b..7b4a5cc7d77d4 100644 --- a/platform/server/http/Router/headers.ts +++ b/platform/server/http/Router/headers.ts @@ -1,7 +1,7 @@ import { pick } from '../../../lib/utils'; export interface Headers { - [key: string]: string; + [key: string]: string | string[]; } const normalizeHeaderField = (field: string) => field.trim().toLowerCase(); diff --git a/src/jest/config.json b/src/jest/config.json index 1dc97c225cdb9..0b9ad3e9e5ea4 100644 --- a/src/jest/config.json +++ b/src/jest/config.json @@ -23,8 +23,8 @@ "html" ], "globals": { - "__TS_CONFIG__": { - "target": "es6" + "ts-jest": { + "tsConfigFile": "src/jest/tsconfig.json" } }, "mapCoverage": true, diff --git a/src/jest/tsconfig.json b/src/jest/tsconfig.json new file mode 100644 index 0000000000000..829bbb8463978 --- /dev/null +++ b/src/jest/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "target": "es6" + } +} From 9f05b8d5b440e019554c3b2ed085d482ceea11f6 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Tue, 8 Aug 2017 11:17:14 -0400 Subject: [PATCH 077/165] Show full screen option even when write controls are hidden (#13247) --- .../kibana/public/dashboard/dashboard.js | 2 +- .../dashboard/top_nav/get_top_nav_config.js | 20 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/core_plugins/kibana/public/dashboard/dashboard.js b/src/core_plugins/kibana/public/dashboard/dashboard.js index da1e9a87526b1..901fe38714f62 100644 --- a/src/core_plugins/kibana/public/dashboard/dashboard.js +++ b/src/core_plugins/kibana/public/dashboard/dashboard.js @@ -267,7 +267,7 @@ app.directive('dashboardApp', function ($injector) { $scope.$listen(timefilter, 'fetch', $scope.refresh); function updateViewMode(newMode) { - $scope.topNavMenu = dashboardConfig.getHideWriteControls() ? [] : getTopNavConfig(newMode, navActions); // eslint-disable-line no-use-before-define + $scope.topNavMenu = getTopNavConfig(newMode, navActions, dashboardConfig.getHideWriteControls()); // eslint-disable-line no-use-before-define dashboardState.switchViewMode(newMode); $scope.dashboardViewMode = newMode; } diff --git a/src/core_plugins/kibana/public/dashboard/top_nav/get_top_nav_config.js b/src/core_plugins/kibana/public/dashboard/top_nav/get_top_nav_config.js index 8b81645ab1890..40a25df4780ef 100644 --- a/src/core_plugins/kibana/public/dashboard/top_nav/get_top_nav_config.js +++ b/src/core_plugins/kibana/public/dashboard/top_nav/get_top_nav_config.js @@ -5,17 +5,25 @@ import { TopNavIds } from './top_nav_ids'; * @param {DashboardMode} dashboardMode. * @param actions {Object} - A mapping of TopNavIds to an action function that should run when the * corresponding top nav is clicked. + * @param hideWriteControls {boolean} if true, does not include any controls that allow editing or creating objects. * @return {Array} - Returns an array of objects for a top nav configuration, based on the * mode. */ -export function getTopNavConfig(dashboardMode, actions) { +export function getTopNavConfig(dashboardMode, actions, hideWriteControls) { switch (dashboardMode) { case DashboardViewMode.VIEW: - return [ - getFullScreenConfig(actions[TopNavIds.FULL_SCREEN]), - getShareConfig(), - getCloneConfig(actions[TopNavIds.CLONE]), - getEditConfig(actions[TopNavIds.ENTER_EDIT_MODE])]; + return ( + hideWriteControls ? + [ + getFullScreenConfig(actions[TopNavIds.FULL_SCREEN]) + ] + : [ + getFullScreenConfig(actions[TopNavIds.FULL_SCREEN]), + getShareConfig(), + getCloneConfig(actions[TopNavIds.CLONE]), + getEditConfig(actions[TopNavIds.ENTER_EDIT_MODE]) + ] + ); case DashboardViewMode.EDIT: return [ getSaveConfig(), From 6e744521b3adac25e4efa50d7d8899d46c6fb3db Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Tue, 8 Aug 2017 11:27:30 -0400 Subject: [PATCH 078/165] Create the concept of embeddableHandlers (#12146) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move dashboard panel rendering logic to each registered type. * Remove dashboard knowledge of click and brush handlers for visualizations Move it to the VisualizeEmbeddableHandler. * merge master with manual changes * No need to use lodash * Add EmbeddableHandler base class * Use correct path to embeddable_handlers_registry * clean up * Set visualize scope uiState that is of type PersistedState, otherwise it won't actually be set. * add retry to loading saved search data * Fix handleError param and remove unnecessary private param * Rename savePanelState updatePanel and return the new object rather than mutating the original * Make ContainerAPI a base class and move the dashboard specific functionality into a new class * Make api's async and clean up documentation * Fix panel tests * Fix bug which broke tests - need to pass container-api to dashboard-panel * Address code comments - Rename onFilter to addFilter - Use angular promises instead of async/await - fix jsdoc - rename createChildUiState to getInitialState * changed the wrong variable name * no need for async or Promise.reject on interface * add tests that will fail due to spy pane issue in this PR * Fix logic with spy pane toggle There is still a bit of a bug here as mentioned in https://github.com/elastic/kibana/issues/13340 but it will be fixed separately as it’s also an issue in master * Fix failing test --- src/core_plugins/kibana/index.js | 3 +- .../dashboard/__tests__/dashboard_panels.js | 13 +- .../public/dashboard/__tests__/panel.js | 38 ++-- .../kibana/public/dashboard/dashboard.html | 15 +- .../kibana/public/dashboard/dashboard.js | 31 +--- .../dashboard/dashboard_container_api.js | 34 ++++ .../public/dashboard/dashboard_state.js | 12 +- .../kibana/public/dashboard/grid.js | 36 +--- .../panel/get_object_loaders_for_dashboard.js | 11 -- .../dashboard/panel/load_saved_object.js | 16 -- .../kibana/public/dashboard/panel/panel.html | 39 +---- .../kibana/public/dashboard/panel/panel.js | 162 +++++------------- .../embeddable/search_embeddable_handler.js | 81 +++++++++ .../search_embeddable_handler_provider.js | 12 ++ .../discover/embeddable/search_template.html | 16 ++ .../visualize_embeddable_handler.js | 63 +++++++ .../visualize_embeddable_handler_provider.js | 17 ++ .../embeddable/visualize_template.html | 11 ++ src/ui/public/embeddable/container_api.js | 51 ++++++ .../public/embeddable/embeddable_handler.js | 33 ++++ .../embeddable_handlers_registry.js | 9 + src/ui/public/embeddable/index.js | 3 + src/ui/ui_exports.js | 5 + test/functional/apps/dashboard/_dashboard.js | 16 ++ test/functional/apps/discover/_discover.js | 10 +- 25 files changed, 448 insertions(+), 289 deletions(-) create mode 100644 src/core_plugins/kibana/public/dashboard/dashboard_container_api.js delete mode 100644 src/core_plugins/kibana/public/dashboard/panel/get_object_loaders_for_dashboard.js delete mode 100644 src/core_plugins/kibana/public/dashboard/panel/load_saved_object.js create mode 100644 src/core_plugins/kibana/public/discover/embeddable/search_embeddable_handler.js create mode 100644 src/core_plugins/kibana/public/discover/embeddable/search_embeddable_handler_provider.js create mode 100644 src/core_plugins/kibana/public/discover/embeddable/search_template.html create mode 100644 src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_handler.js create mode 100644 src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_handler_provider.js create mode 100644 src/core_plugins/kibana/public/visualize/embeddable/visualize_template.html create mode 100644 src/ui/public/embeddable/container_api.js create mode 100644 src/ui/public/embeddable/embeddable_handler.js create mode 100644 src/ui/public/embeddable/embeddable_handlers_registry.js create mode 100644 src/ui/public/embeddable/index.js diff --git a/src/core_plugins/kibana/index.js b/src/core_plugins/kibana/index.js index b237df06da533..9c287f42e6658 100644 --- a/src/core_plugins/kibana/index.js +++ b/src/core_plugins/kibana/index.js @@ -59,7 +59,8 @@ export default function (kibana) { 'navbarExtensions', 'managementSections', 'devTools', - 'docViews' + 'docViews', + 'embeddableHandlers', ], injectVars, }, diff --git a/src/core_plugins/kibana/public/dashboard/__tests__/dashboard_panels.js b/src/core_plugins/kibana/public/dashboard/__tests__/dashboard_panels.js index 87903c241bdd5..109e9c34e9624 100644 --- a/src/core_plugins/kibana/public/dashboard/__tests__/dashboard_panels.js +++ b/src/core_plugins/kibana/public/dashboard/__tests__/dashboard_panels.js @@ -2,14 +2,18 @@ import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; import 'plugins/kibana/dashboard/saved_dashboard/saved_dashboard'; +import { DashboardContainerAPI } from '../dashboard_container_api'; +import { DashboardState } from '../dashboard_state'; import { DEFAULT_PANEL_WIDTH, DEFAULT_PANEL_HEIGHT } from 'plugins/kibana/dashboard/panel/panel_state'; describe('dashboard panels', function () { let $scope; let $el; + let AppState; function compile(dashboard) { - ngMock.inject(($rootScope, $controller, $compile, $route) => { + ngMock.inject(($injector, $rootScope, $controller, $compile, $route) => { + AppState = $injector.get('AppState'); $scope = $rootScope.$new(); $route.current = { locals: { @@ -18,6 +22,8 @@ describe('dashboard panels', function () { params: {} }; + const dashboardState = new DashboardState(dashboard, AppState, false); + $scope.containerApi = new DashboardContainerAPI(dashboardState); $el = angular.element(` `); $compile($el)($scope); diff --git a/src/core_plugins/kibana/public/dashboard/__tests__/panel.js b/src/core_plugins/kibana/public/dashboard/__tests__/panel.js index 677a3731526b7..35b807ff0cf54 100644 --- a/src/core_plugins/kibana/public/dashboard/__tests__/panel.js +++ b/src/core_plugins/kibana/public/dashboard/__tests__/panel.js @@ -3,28 +3,30 @@ import ngMock from 'ng_mock'; import Promise from 'bluebird'; import sinon from 'sinon'; import noDigestPromise from 'test_utils/no_digest_promises'; -import mockUiState from 'fixtures/mock_ui_state'; -import { SavedObjectsClientProvider } from 'ui/saved_objects'; +import { DashboardContainerAPI } from '../dashboard_container_api'; +import { DashboardState } from '../dashboard_state'; +import { SavedObjectsClient } from 'ui/saved_objects'; describe('dashboard panel', function () { let $scope; let $el; let parentScope; + let savedDashboard; + let AppState; noDigestPromise.activateForSuite(); function init(mockDocResponse) { ngMock.module('kibana'); - ngMock.inject(($rootScope, $compile, Private) => { - Private.swap(SavedObjectsClientProvider, () => { - return { - get: sinon.stub().returns(Promise.resolve(mockDocResponse)) - }; - }); - + ngMock.inject(($rootScope, $compile, Private, $injector) => { + const SavedDashboard = $injector.get('SavedDashboard'); + AppState = $injector.get('AppState'); + savedDashboard = new SavedDashboard(); + sinon.stub(SavedObjectsClient.prototype, 'get').returns(Promise.resolve(mockDocResponse)); parentScope = $rootScope.$new(); parentScope.saveState = sinon.stub(); - parentScope.createChildUiState = sinon.stub().returns(mockUiState); + const dashboardState = new DashboardState(savedDashboard, AppState, false); + parentScope.containerApi = new DashboardContainerAPI(dashboardState); parentScope.getVisClickHandler = sinon.stub(); parentScope.getVisBrushHandler = sinon.stub(); parentScope.registerPanelIndexPattern = sinon.stub(); @@ -41,11 +43,8 @@ describe('dashboard panel', function () { panel="panel" is-full-screen-mode="false" is-expanded="false" - get-vis-click-handler="getVisClickHandler" - get-vis-brush-handler="getVisBrushHandler" - save-state="saveState" - register-panel-index-pattern="registerPanelIndexPattern" - create-child-ui-state="createChildUiState"> + container-api="containerApi" + > `)(parentScope); $scope = $el.isolateScope(); parentScope.$digest(); @@ -53,27 +52,28 @@ describe('dashboard panel', function () { } afterEach(() => { + SavedObjectsClient.prototype.get.restore(); $scope.$destroy(); $el.remove(); }); it('should not visualize the visualization if it does not exist', function () { init({ found: false }); - return $scope.loadedPanel.then(() => { + return $scope.renderPromise.then(() => { expect($scope.error).to.be('Could not locate that visualization (id: foo1)'); parentScope.$digest(); const content = $el.find('.panel-content'); - expect(content).to.have.length(0); + expect(content.children().length).to.be(0); }); }); it('should try to visualize the visualization if found', function () { init({ id: 'foo1', type: 'visualization', _version: 2, attributes: {} }); - return $scope.loadedPanel.then(() => { + return $scope.renderPromise.then(() => { expect($scope.error).not.to.be.ok(); parentScope.$digest(); const content = $el.find('.panel-content'); - expect(content).to.have.length(1); + expect(content.children().length).to.be.greaterThan(0); }); }); }); diff --git a/src/core_plugins/kibana/public/dashboard/dashboard.html b/src/core_plugins/kibana/public/dashboard/dashboard.html index 4fdcd23a8710c..e0b6ede1d73fb 100644 --- a/src/core_plugins/kibana/public/dashboard/dashboard.html +++ b/src/core_plugins/kibana/public/dashboard/dashboard.html @@ -80,16 +80,10 @@

on-panel-removed="onPanelRemoved" dashboard-view-mode="dashboardViewMode" panels="panels" - get-vis-click-handler="getFilterBarClickHandler" - get-vis-brush-handler="getBrushEvent" save-state="saveState" - app-state="appState" toggle-expand="toggleExpandPanel" - create-child-ui-state="createChildUiState" - toggle-expand="toggleExpandPanel" - register-panel-index-pattern="registerPanelIndexPattern" data-shared-items-count="{{panels.length}}" - on-filter="filter" + container-api="containerApi" > is-full-screen-mode="!chrome.getVisible()" is-expanded="true" dashboard-view-mode="dashboardViewMode" - get-vis-click-handler="getFilterBarClickHandler" - get-vis-brush-handler="getBrushEvent" - save-state="saveState" - app-state="appState" - register-panel-index-pattern="registerPanelIndexPattern" - create-child-ui-state="createChildUiState" + container-api="containerApi" toggle-expand="toggleExpandPanel(expandedPanel.panelIndex)" > diff --git a/src/core_plugins/kibana/public/dashboard/dashboard.js b/src/core_plugins/kibana/public/dashboard/dashboard.js index 901fe38714f62..69e1e4ef695db 100644 --- a/src/core_plugins/kibana/public/dashboard/dashboard.js +++ b/src/core_plugins/kibana/public/dashboard/dashboard.js @@ -19,16 +19,14 @@ import { DocTitleProvider } from 'ui/doc_title'; import { getTopNavConfig } from './top_nav/get_top_nav_config'; import { DashboardConstants, createDashboardEditUrl } from './dashboard_constants'; import { VisualizeConstants } from 'plugins/kibana/visualize/visualize_constants'; -import { UtilsBrushEventProvider } from 'ui/utils/brush_event'; -import { FilterBarClickHandlerProvider } from 'ui/filter_bar/filter_bar_click_handler'; import { DashboardState } from './dashboard_state'; import { notify } from 'ui/notify'; -import './panel/get_object_loaders_for_dashboard'; import { documentationLinks } from 'ui/documentation_links/documentation_links'; import { showCloneModal } from './top_nav/show_clone_modal'; import { migrateLegacyQuery } from 'ui/utils/migrateLegacyQuery'; import { QueryManagerProvider } from 'ui/query_manager'; import { ESC_KEY_CODE } from 'ui_framework/services'; +import { DashboardContainerAPI } from './dashboard_container_api'; const app = uiModules.get('app/dashboard', [ 'elasticsearch', @@ -86,8 +84,6 @@ app.directive('dashboardApp', function ($injector) { const confirmModal = $injector.get('confirmModal'); const config = $injector.get('config'); const Private = $injector.get('Private'); - const brushEvent = Private(UtilsBrushEventProvider); - const filterBarClickHandler = Private(FilterBarClickHandlerProvider); return { restrict: 'E', @@ -103,8 +99,10 @@ app.directive('dashboardApp', function ($injector) { docTitle.change(dash.title); } - const dashboardState = new DashboardState(dash, AppState, dashboardConfig); + const dashboardState = new DashboardState(dash, AppState, dashboardConfig.getHideWriteControls()); + $scope.appState = dashboardState.getAppState(); const queryManager = Private(QueryManagerProvider)(dashboardState.getAppState()); + $scope.containerApi = new DashboardContainerAPI(dashboardState, queryManager); // The 'previouslyStored' check is so we only update the time filter on dashboard open, not during // normal cross app navigation. @@ -124,6 +122,7 @@ app.directive('dashboardApp', function ($injector) { }; $scope.panels = dashboardState.getPanels(); $scope.fullScreenMode = dashboardState.getFullScreenMode(); + $scope.indexPatterns = dashboardState.getPanelIndexPatterns(); }; // Part of the exposed plugin API - do not remove without careful consideration. @@ -155,11 +154,8 @@ app.directive('dashboardApp', function ($injector) { $scope.timefilter = timefilter; $scope.expandedPanel = null; $scope.dashboardViewMode = dashboardState.getViewMode(); - $scope.appState = dashboardState.getAppState(); $scope.landingPageUrl = () => `#${DashboardConstants.LANDING_PAGE_PATH}`; - $scope.getBrushEvent = () => brushEvent(dashboardState.getAppState()); - $scope.getFilterBarClickHandler = () => filterBarClickHandler(dashboardState.getAppState()); $scope.hasExpandedPanel = () => $scope.expandedPanel !== null; $scope.getDashTitle = () => getDashboardTitle( dashboardState.getTitle(), @@ -212,17 +208,6 @@ app.directive('dashboardApp', function ($injector) { notify.info(`Search successfully added to your dashboard`); }; - /** - * Creates a child ui state for the panel. It's passed the ui state to use, but needs to - * be generated from the parent (why, I don't know yet). - * @param path {String} - the unique path for this ui state. - * @param uiState {Object} - the uiState for the child. - * @returns {Object} - */ - $scope.createChildUiState = function createChildUiState(path, uiState) { - return dashboardState.uiState.createChild(path, uiState, true); - }; - $scope.$watch('model.darkTheme', () => { dashboardState.setDarkTheme($scope.model.darkTheme); updateTheme(); @@ -242,12 +227,6 @@ app.directive('dashboardApp', function ($injector) { $scope.indexPatterns = dashboardState.getPanelIndexPatterns(); }; - $scope.filter = function (field, value, operator, index) { - queryManager.add(field, value, operator, index); - updateState(); - }; - - $scope.$watch('model.query', (newQuery) => { $scope.model.query = migrateLegacyQuery(newQuery); dashboardState.applyFilters($scope.model.query, filterBar.getFilters()); diff --git a/src/core_plugins/kibana/public/dashboard/dashboard_container_api.js b/src/core_plugins/kibana/public/dashboard/dashboard_container_api.js new file mode 100644 index 0000000000000..f8ca5a98f5826 --- /dev/null +++ b/src/core_plugins/kibana/public/dashboard/dashboard_container_api.js @@ -0,0 +1,34 @@ +import { ContainerAPI } from 'ui/embeddable'; + +export class DashboardContainerAPI extends ContainerAPI { + constructor(dashboardState, queryManager) { + super(); + this.dashboardState = dashboardState; + this.queryManager = queryManager; + } + + addFilter(field, value, operator, index) { + this.queryManager.add(field, value, operator, index); + } + + updatePanel(panelIndex, panelAttributes) { + const panelToUpdate = this.dashboardState.getPanels().find((panel) => panel.panelIndex === panelIndex); + Object.assign(panelToUpdate, panelAttributes); + this.dashboardState.saveState(); + return panelToUpdate; + } + + getAppState() { + return this.dashboardState.appState; + } + + createChildUistate(path, initialState) { + return this.dashboardState.uiState.createChild(path, initialState, true); + } + + registerPanelIndexPattern(panelIndex, pattern) { + this.dashboardState.registerPanelIndexPatternMap(panelIndex, pattern); + this.dashboardState.saveState(); + } + +} diff --git a/src/core_plugins/kibana/public/dashboard/dashboard_state.js b/src/core_plugins/kibana/public/dashboard/dashboard_state.js index f355482d2b8f1..e8e90a6f71011 100644 --- a/src/core_plugins/kibana/public/dashboard/dashboard_state.js +++ b/src/core_plugins/kibana/public/dashboard/dashboard_state.js @@ -59,13 +59,13 @@ export class DashboardState { * * @param savedDashboard {SavedDashboard} * @param AppState {AppState} - * @param dashboardConfig {DashboardConfigProvider} + * @param hideWriteControls {boolean} true if write controls should be hidden. */ - constructor(savedDashboard, AppState, dashboardConfig) { + constructor(savedDashboard, AppState, hideWriteControls) { this.savedDashboard = savedDashboard; - this.dashboardConfig = dashboardConfig; + this.hideWriteControls = hideWriteControls; - this.stateDefaults = getStateDefaults(this.savedDashboard, this.dashboardConfig.getHideWriteControls()); + this.stateDefaults = getStateDefaults(this.savedDashboard, this.hideWriteControls); this.appState = new AppState(this.stateDefaults); this.uiState = this.appState.makeStateful('uiState'); @@ -117,7 +117,7 @@ export class DashboardState { // The right way to fix this might be to ensure the defaults object stored on state is a deep // clone, but given how much code uses the state object, I determined that to be too risky of a change for // now. TODO: revisit this! - this.stateDefaults = getStateDefaults(this.savedDashboard, this.dashboardConfig.getHideWriteControls()); + this.stateDefaults = getStateDefaults(this.savedDashboard, this.hideWriteControls); // The original query won't be restored by the above because the query on this.savedDashboard is applied // in place in order for it to affect the visualizations. this.stateDefaults.query = this.lastSavedDashboardFilters.query; @@ -259,7 +259,7 @@ export class DashboardState { * @returns {DashboardViewMode} */ getViewMode() { - return this.dashboardConfig.getHideWriteControls() ? DashboardViewMode.VIEW : this.appState.viewMode; + return this.hideWriteControls ? DashboardViewMode.VIEW : this.appState.viewMode; } /** diff --git a/src/core_plugins/kibana/public/dashboard/grid.js b/src/core_plugins/kibana/public/dashboard/grid.js index 7cf648e9d371b..54fd3fab1ab79 100644 --- a/src/core_plugins/kibana/public/dashboard/grid.js +++ b/src/core_plugins/kibana/public/dashboard/grid.js @@ -18,17 +18,6 @@ app.directive('dashboardGrid', function ($compile, Notifier) { * @type {DashboardViewMode} */ dashboardViewMode: '=', - /** - * Used to create a child persisted state for the panel from parent state. - * @type {function} - Returns a {PersistedState} child uiState for this scope. - */ - createChildUiState: '=', - /** - * Registers an index pattern with the dashboard app used by each panel. The index patterns are used by the - * filter bar for generating field suggestions. - * @type {function(IndexPattern)} - */ - registerPanelIndexPattern: '=', /** * Trigger after a panel has been removed from the grid. */ @@ -38,22 +27,11 @@ app.directive('dashboardGrid', function ($compile, Notifier) { * @type {Array} */ panels: '=', - /** - * Returns a click handler for a visualization. - * @type {function} - */ - getVisClickHandler: '=', - /** - * Returns a brush event handler for a visualization. - * @type {function} - */ - getVisBrushHandler: '=', /** * Call when changes should be propagated to the url and thus saved in state. * @type {function} */ saveState: '=', - appState: '=', /** * Expand or collapse a panel, so it either takes up the whole screen or goes back to its * natural size. @@ -61,10 +39,9 @@ app.directive('dashboardGrid', function ($compile, Notifier) { */ toggleExpand: '=', /** - * Called when a filter action has been triggered by a panel - * @type {function} + * @type {DashboardContainerApi} */ - onFilter: '=', + containerApi: '=', }, link: function ($scope, $el) { const notify = new Notifier(); @@ -222,14 +199,9 @@ app.directive('dashboardGrid', function ($compile, Notifier) { is-full-screen-mode="isFullScreenMode" is-expanded="false" dashboard-view-mode="dashboardViewMode" - get-vis-click-handler="getVisClickHandler" - get-vis-brush-handler="getVisBrushHandler" - save-state="saveState" - app-state="appState" - register-panel-index-pattern="registerPanelIndexPattern" + container-api="containerApi" toggle-expand="toggleExpand(${panel.panelIndex})" - create-child-ui-state="createChildUiState" - on-filter="onFilter"> + > `; const panelElement = $compile(panelHtml)($scope); panelElementMapping[panel.panelIndex] = panelElement; diff --git a/src/core_plugins/kibana/public/dashboard/panel/get_object_loaders_for_dashboard.js b/src/core_plugins/kibana/public/dashboard/panel/get_object_loaders_for_dashboard.js deleted file mode 100644 index 40c99b3c29372..0000000000000 --- a/src/core_plugins/kibana/public/dashboard/panel/get_object_loaders_for_dashboard.js +++ /dev/null @@ -1,11 +0,0 @@ -import { uiModules } from 'ui/modules'; -const module = uiModules.get('app/dashboard'); - -/** - * We have more types available than just 'search' and 'visualization' but as of now, they - * can't be added to a dashboard. - */ -module.factory('getObjectLoadersForDashboard', function (savedSearches, savedVisualizations) { - return () => [savedSearches, savedVisualizations]; -}); - diff --git a/src/core_plugins/kibana/public/dashboard/panel/load_saved_object.js b/src/core_plugins/kibana/public/dashboard/panel/load_saved_object.js deleted file mode 100644 index b7f3bed8364d3..0000000000000 --- a/src/core_plugins/kibana/public/dashboard/panel/load_saved_object.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Retrieves the saved object represented by the panel and returns it, along with the appropriate - * edit Url. - * @param {Array.} loaders - The available loaders for different panel types. - * @param {PanelState} panel - * @returns {Promise.<{savedObj: SavedObject, editUrl: String}>} - */ -export function loadSavedObject(loaders, panel) { - const loader = loaders.find((loader) => loader.type === panel.type); - if (!loader) { - throw new Error(`No loader for object of type ${panel.type}`); - } - return loader.get(panel.id).then(savedObj => { - return { savedObj, editUrl: loader.urlFor(panel.id) }; - }); -} diff --git a/src/core_plugins/kibana/public/dashboard/panel/panel.html b/src/core_plugins/kibana/public/dashboard/panel/panel.html index 38d56f67777ea..d20d0fdde1bee 100644 --- a/src/core_plugins/kibana/public/dashboard/panel/panel.html +++ b/src/core_plugins/kibana/public/dashboard/panel/panel.html @@ -1,11 +1,11 @@ -
+
- {{::savedObj.title}} + {{::title}} - - - - - +
diff --git a/src/core_plugins/kibana/public/dashboard/panel/panel.js b/src/core_plugins/kibana/public/dashboard/panel/panel.js index 173f0c0454812..2c2a53e1b643a 100644 --- a/src/core_plugins/kibana/public/dashboard/panel/panel.js +++ b/src/core_plugins/kibana/public/dashboard/panel/panel.js @@ -1,21 +1,16 @@ -import _ from 'lodash'; import 'ui/visualize'; import 'ui/doc_table'; -import * as columnActions from 'ui/doc_table/actions/columns'; -import 'plugins/kibana/dashboard/panel/get_object_loaders_for_dashboard'; import 'plugins/kibana/visualize/saved_visualizations'; import 'plugins/kibana/discover/saved_searches'; import { uiModules } from 'ui/modules'; import panelTemplate from 'plugins/kibana/dashboard/panel/panel.html'; import { savedObjectManagementRegistry } from 'plugins/kibana/management/saved_object_registry'; -import { getPersistedStateId } from 'plugins/kibana/dashboard/panel/panel_state'; -import { loadSavedObject } from 'plugins/kibana/dashboard/panel/load_saved_object'; import { DashboardViewMode } from '../dashboard_view_mode'; +import { EmbeddableHandlersRegistryProvider } from 'ui/embeddable/embeddable_handlers_registry'; uiModules .get('app/dashboard') -.directive('dashboardPanel', function (savedVisualizations, savedSearches, Notifier, Private, $injector, getObjectLoadersForDashboard) { - +.directive('dashboardPanel', function (Notifier, Private, $injector) { const services = savedObjectManagementRegistry.all().map(function (serviceObj) { const service = $injector.get(serviceObj.service); return { @@ -38,17 +33,6 @@ uiModules * @type {boolean} */ isFullScreenMode: '=', - /** - * Used to create a child persisted state for the panel from parent state. - * @type {function} - Returns a {PersistedState} child uiState for this scope. - */ - createChildUiState: '=', - /** - * Registers an index pattern with the dashboard app used by this panel. Used by the filter bar for - * generating field suggestions. - * @type {function(IndexPattern)} - */ - registerPanelIndexPattern: '=', /** * Contains information about this panel. * @type {PanelState} @@ -70,122 +54,58 @@ uiModules */ isExpanded: '=', /** - * Returns a click handler for a visualization. - * @type {function} - */ - getVisClickHandler: '=', - /** - * Returns a brush event handler for a visualization. - * @type {function} + * @type {DashboardContainerApi} */ - getVisBrushHandler: '=', - /** - * Call when changes should be propagated to the url and thus saved in state. - * @type {function} - */ - saveState: '=', - /** - * Called when a filter action has been triggered - * @type {function} - */ - onFilter: '=', - appState: '=', + containerApi: '=' }, link: function ($scope, element) { if (!$scope.panel.id || !$scope.panel.type) return; - /** - * Initializes the panel for the saved object. - * @param {{savedObj: SavedObject, editUrl: String}} savedObjectInfo - */ - function initializePanel(savedObjectInfo) { - $scope.savedObj = savedObjectInfo.savedObj; - $scope.editUrl = savedObjectInfo.editUrl; - - element.on('$destroy', function () { - $scope.savedObj.destroy(); - $scope.$destroy(); - }); - - // create child ui state from the savedObj - const uiState = $scope.savedObj.uiStateJSON ? JSON.parse($scope.savedObj.uiStateJSON) : {}; - $scope.uiState = $scope.createChildUiState(getPersistedStateId($scope.panel), uiState); + $scope.isViewOnlyMode = () => { + return $scope.dashboardViewMode === DashboardViewMode.VIEW || $scope.isFullScreenMode; + }; - if ($scope.panel.type === savedVisualizations.type && $scope.savedObj.vis) { - $scope.savedObj.vis.setUiState($scope.uiState); - $scope.savedObj.vis.listeners.click = $scope.getVisClickHandler(); - $scope.savedObj.vis.listeners.brush = $scope.getVisBrushHandler(); - $scope.registerPanelIndexPattern($scope.panel.panelIndex, $scope.savedObj.vis.indexPattern); - } else if ($scope.panel.type === savedSearches.type) { - if ($scope.savedObj.searchSource) { - $scope.registerPanelIndexPattern($scope.panel.panelIndex, $scope.savedObj.searchSource.get('index')); - } - // This causes changes to a saved search to be hidden, but also allows - // the user to locally modify and save changes to a saved search only in a dashboard. - // See https://github.com/elastic/kibana/issues/9523 for more details. - $scope.panel.columns = $scope.panel.columns || $scope.savedObj.columns; - $scope.panel.sort = $scope.panel.sort || $scope.savedObj.sort; + const panelId = $scope.panel.id; - $scope.setSortOrder = function setSortOrder(columnName, direction) { - $scope.panel.sort = [columnName, direction]; - $scope.saveState(); - }; + // TODO: This function contains too much internal panel knowledge. Logic should be pushed to embeddable handlers. + const handleError = (error) => { + $scope.error = error.message; - $scope.addColumn = function addColumn(columnName) { - $scope.savedObj.searchSource.get('index').popularizeField(columnName, 1); - columnActions.addColumn($scope.panel.columns, columnName); - $scope.saveState(); // sync to sharing url - }; + // Dashboard listens for this broadcast, once for every visualization (pendingVisCount). + // We need to broadcast even in the event of an error or it'll never fetch the data for + // other visualizations. + $scope.$root.$broadcast('ready:vis'); - $scope.removeColumn = function removeColumn(columnName) { - $scope.savedObj.searchSource.get('index').popularizeField(columnName, 1); - columnActions.removeColumn($scope.panel.columns, columnName); - $scope.saveState(); // sync to sharing url - }; + // If the savedObjectType matches the panel type, this means the object itself has been deleted, + // so we shouldn't even have an edit link. If they don't match, it means something else is wrong + // with the object (but the object still exists), so we link to the object editor instead. + const objectItselfDeleted = error.savedObjectType === $scope.panel.type; + if (objectItselfDeleted) return; - $scope.moveColumn = function moveColumn(columnName, newIndex) { - columnActions.moveColumn($scope.panel.columns, columnName, newIndex); - $scope.saveState(); // sync to sharing url - }; - } + const type = $scope.panel.type; + const service = services.find(service => service.type === type); + if (!service) return; - $scope.filter = function (field, value, operator) { - const index = $scope.savedObj.searchSource.get('index').id; - $scope.onFilter(field, value, operator, index); - }; + $scope.editUrl = '#management/kibana/objects/' + service.name + '/' + panelId + '?notFound=' + error.savedObjectType; + }; + const embeddableHandlers = Private(EmbeddableHandlersRegistryProvider); + const embeddableHandler = embeddableHandlers.byName[$scope.panel.type]; + if (!embeddableHandler) { + handleError(new Error(`No embeddable handler for panel type ${$scope.panel.type} was found.`)); + return; } - - $scope.loadedPanel = loadSavedObject(getObjectLoadersForDashboard(), $scope.panel) - .then(initializePanel) - .catch(function (e) { - $scope.error = e.message; - - // Dashboard listens for this broadcast, once for every visualization (pendingVisCount). - // We need to broadcast even in the event of an error or it'll never fetch the data for - // other visualizations. - $scope.$root.$broadcast('ready:vis'); - - // If the savedObjectType matches the panel type, this means the object itself has been deleted, - // so we shouldn't even have an edit link. If they don't match, it means something else is wrong - // with the object (but the object still exists), so we link to the object editor instead. - const objectItselfDeleted = e.savedObjectType === $scope.panel.type; - if (objectItselfDeleted) return; - - const type = $scope.panel.type; - const id = $scope.panel.id; - const service = _.find(services, { type: type }); - if (!service) return; - - $scope.editUrl = '#management/kibana/objects/' + service.name + '/' + id + '?notFound=' + e.savedObjectType; - }); - - /** - * @returns {boolean} True if the user can only view, not edit. - */ - $scope.isViewOnlyMode = () => { - return $scope.dashboardViewMode === DashboardViewMode.VIEW || $scope.isFullScreenMode; - }; + embeddableHandler.getEditPath(panelId).then(path => { + $scope.editUrl = path; + }); + embeddableHandler.getTitleFor(panelId).then(title => { + $scope.title = title; + }); + $scope.renderPromise = embeddableHandler.render( + element.find('#embeddedPanel').get(0), + $scope.panel, + $scope.containerApi) + .catch(handleError); } }; }); diff --git a/src/core_plugins/kibana/public/discover/embeddable/search_embeddable_handler.js b/src/core_plugins/kibana/public/discover/embeddable/search_embeddable_handler.js new file mode 100644 index 0000000000000..1c12be3e8cab4 --- /dev/null +++ b/src/core_plugins/kibana/public/discover/embeddable/search_embeddable_handler.js @@ -0,0 +1,81 @@ +import searchTemplate from './search_template.html'; +import angular from 'angular'; +import * as columnActions from 'ui/doc_table/actions/columns'; +import { getPersistedStateId } from 'plugins/kibana/dashboard/panel/panel_state'; +import { EmbeddableHandler } from 'ui/embeddable'; + + +export class SearchEmbeddableHandler extends EmbeddableHandler { + + constructor($compile, $rootScope, searchLoader, Promise) { + super(); + this.$compile = $compile; + this.searchLoader = searchLoader; + this.$rootScope = $rootScope; + this.name = 'search'; + this.Promise = Promise; + } + + getEditPath(panelId) { + return this.Promise.resolve(this.searchLoader.urlFor(panelId)); + } + + getTitleFor(panelId) { + return this.searchLoader.get(panelId).then(savedObject => savedObject.title); + } + + render(domNode, panel, container) { + const searchScope = this.$rootScope.$new(); + return this.getEditPath(panel.id) + .then(editPath => { + searchScope.editPath = editPath; + return this.searchLoader.get(panel.id); + }) + .then(savedObject => { + searchScope.savedObj = savedObject; + searchScope.panel = panel; + container.registerPanelIndexPattern(panel.panelIndex, savedObject.searchSource.get('index')); + + // This causes changes to a saved search to be hidden, but also allows + // the user to locally modify and save changes to a saved search only in a dashboard. + // See https://github.com/elastic/kibana/issues/9523 for more details. + searchScope.panel = container.updatePanel(searchScope.panel.panelIndex, { + columns: searchScope.panel.columns || searchScope.savedObj.columns, + sort: searchScope.panel.sort || searchScope.savedObj.sort + }); + + const uiState = savedObject.uiStateJSON ? JSON.parse(savedObject.uiStateJSON) : {}; + searchScope.uiState = container.createChildUistate(getPersistedStateId(panel), uiState); + + searchScope.setSortOrder = function setSortOrder(columnName, direction) { + searchScope.panel = container.updatePanel(searchScope.panel.panelIndex, { sort: [columnName, direction] }); + }; + + searchScope.addColumn = function addColumn(columnName) { + savedObject.searchSource.get('index').popularizeField(columnName, 1); + columnActions.addColumn(searchScope.panel.columns, columnName); + searchScope.panel = container.updatePanel(searchScope.panel.panelIndex, { columns: searchScope.panel.columns }); + }; + + searchScope.removeColumn = function removeColumn(columnName) { + savedObject.searchSource.get('index').popularizeField(columnName, 1); + columnActions.removeColumn(searchScope.panel.columns, columnName); + searchScope.panel = container.updatePanel(searchScope.panel.panelIndex, { columns: searchScope.panel.columns }); + }; + + searchScope.moveColumn = function moveColumn(columnName, newIndex) { + columnActions.moveColumn(searchScope.panel.columns, columnName, newIndex); + searchScope.panel = container.updatePanel(searchScope.panel.panelIndex, { columns: searchScope.panel.columns }); + }; + + searchScope.filter = function (field, value, operator) { + const index = savedObject.searchSource.get('index').id; + container.addFilter(field, value, operator, index); + }; + + const searchInstance = this.$compile(searchTemplate)(searchScope); + const rootNode = angular.element(domNode); + rootNode.append(searchInstance); + }); + } +} diff --git a/src/core_plugins/kibana/public/discover/embeddable/search_embeddable_handler_provider.js b/src/core_plugins/kibana/public/discover/embeddable/search_embeddable_handler_provider.js new file mode 100644 index 0000000000000..d7fa5dc8b1f00 --- /dev/null +++ b/src/core_plugins/kibana/public/discover/embeddable/search_embeddable_handler_provider.js @@ -0,0 +1,12 @@ +import { SearchEmbeddableHandler } from './search_embeddable_handler'; +import { EmbeddableHandlersRegistryProvider } from 'ui/embeddable/embeddable_handlers_registry'; + +export function searchEmbeddableHandlerProvider(Private) { + const SearchEmbeddableHandlerProvider = ($compile, $rootScope, savedSearches, Promise) => { + return new SearchEmbeddableHandler($compile, $rootScope, savedSearches, Promise); + }; + return Private(SearchEmbeddableHandlerProvider); +} + + +EmbeddableHandlersRegistryProvider.register(searchEmbeddableHandlerProvider); diff --git a/src/core_plugins/kibana/public/discover/embeddable/search_template.html b/src/core_plugins/kibana/public/discover/embeddable/search_template.html new file mode 100644 index 0000000000000..0bb48561b27df --- /dev/null +++ b/src/core_plugins/kibana/public/discover/embeddable/search_template.html @@ -0,0 +1,16 @@ + + diff --git a/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_handler.js b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_handler.js new file mode 100644 index 0000000000000..8bb5c6e9ccd8c --- /dev/null +++ b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_handler.js @@ -0,0 +1,63 @@ +import angular from 'angular'; + +import visualizationTemplate from './visualize_template.html'; +import { getPersistedStateId } from 'plugins/kibana/dashboard/panel/panel_state'; +import { UtilsBrushEventProvider as utilsBrushEventProvider } from 'ui/utils/brush_event'; +import { FilterBarClickHandlerProvider as filterBarClickHandlerProvider } from 'ui/filter_bar/filter_bar_click_handler'; +import { EmbeddableHandler } from 'ui/embeddable'; +import chrome from 'ui/chrome'; + +export class VisualizeEmbeddableHandler extends EmbeddableHandler { + constructor($compile, $rootScope, visualizeLoader, timefilter, Notifier, Promise) { + super(); + this.$compile = $compile; + this.visualizeLoader = visualizeLoader; + this.$rootScope = $rootScope; + this.name = 'visualization'; + this.Promise = Promise; + this.brushEvent = utilsBrushEventProvider(timefilter); + this.filterBarClickHandler = filterBarClickHandlerProvider(Notifier); + } + + getEditPath(panelId) { + return this.Promise.resolve(this.visualizeLoader.urlFor(panelId)); + } + + getTitleFor(panelId) { + return this.visualizeLoader.get(panelId).then(savedObject => savedObject.title); + } + + render(domNode, panel, container) { + const visualizeScope = this.$rootScope.$new(); + return this.getEditPath(panel.id) + .then(editPath => { + visualizeScope.editUrl = editPath; + return this.visualizeLoader.get(panel.id); + }) + .then(savedObject => { + visualizeScope.savedObj = savedObject; + visualizeScope.panel = panel; + + const uiState = savedObject.uiStateJSON ? JSON.parse(savedObject.uiStateJSON) : {}; + visualizeScope.uiState = container.createChildUistate(getPersistedStateId(panel), uiState); + + visualizeScope.savedObj.vis.setUiState(visualizeScope.uiState); + + visualizeScope.savedObj.vis.listeners.click = this.filterBarClickHandler(container.getAppState()); + visualizeScope.savedObj.vis.listeners.brush = this.brushEvent(container.getAppState()); + visualizeScope.isFullScreenMode = !chrome.getVisible(); + + container.registerPanelIndexPattern(panel.panelIndex, visualizeScope.savedObj.vis.indexPattern); + + const visualizationInstance = this.$compile(visualizationTemplate)(visualizeScope); + const rootNode = angular.element(domNode); + rootNode.append(visualizationInstance); + + visualizationInstance.on('$destroy', function () { + visualizeScope.savedObj.destroy(); + visualizeScope.$destroy(); + }); + }); + } +} + diff --git a/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_handler_provider.js b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_handler_provider.js new file mode 100644 index 0000000000000..1f6704f1f921f --- /dev/null +++ b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_handler_provider.js @@ -0,0 +1,17 @@ +import { VisualizeEmbeddableHandler } from './visualize_embeddable_handler'; +import { EmbeddableHandlersRegistryProvider } from 'ui/embeddable/embeddable_handlers_registry'; + +export function visualizeEmbeddableHandlerProvider(Private) { + const VisualizeEmbeddableHandlerProvider = ( + $compile, + $rootScope, + savedVisualizations, + timefilter, + Notifier, + Promise) => { + return new VisualizeEmbeddableHandler($compile, $rootScope, savedVisualizations, timefilter, Notifier, Promise); + }; + return Private(VisualizeEmbeddableHandlerProvider); +} + +EmbeddableHandlersRegistryProvider.register(visualizeEmbeddableHandlerProvider); diff --git a/src/core_plugins/kibana/public/visualize/embeddable/visualize_template.html b/src/core_plugins/kibana/public/visualize/embeddable/visualize_template.html new file mode 100644 index 0000000000000..4a7d8fd6481a5 --- /dev/null +++ b/src/core_plugins/kibana/public/visualize/embeddable/visualize_template.html @@ -0,0 +1,11 @@ + + diff --git a/src/ui/public/embeddable/container_api.js b/src/ui/public/embeddable/container_api.js new file mode 100644 index 0000000000000..e1471a88d7a70 --- /dev/null +++ b/src/ui/public/embeddable/container_api.js @@ -0,0 +1,51 @@ +/** + * The ContainerAPI is an interface for embeddable objects to interact with the container they are embedded within. + */ +export class ContainerAPI { + /** + * Available so the embeddable object can trigger a filter action. + * @param field + * @param value + * @param operator + * @param index + */ + addFilter(/*field, value, operator, index */) { + throw new Error('Must implement addFilter.'); + } + + /** + * @return {AppState} + */ + getAppState() { + throw new Error('Must implement getAppState.'); + } + + /** + * Creates a new state for the panel. It's passed the ui state object to use, and is returned + * a PersistedState. + * @param path {String} - the unique path for this ui state. + * @param initialState {Object} - the initial state to use for the child. + * @returns {PersistedState} + */ + createChildUistate(/* path, initialState */) { + throw new Error('Must implement getInitalState.'); + } + + /** + * Call this to tell the container that this panel uses a particular index pattern. + * @param {string} panelIndex - a unique id that identifies the panel to update. + * @param {string} indexPattern - an index pattern the panel uses + */ + registerPanelIndexPattern(/* panelIndex, indexPattern */) { + throw new Error('Must implement registerPanelIndexPattern.'); + } + + /** + * @param {string} panelIndex - a unique id that identifies the panel to update. + * @param {Object} panelAttributes - the new panel attributes that will be applied to the panel. + * @return {Object} - the updated panel. + */ + updatePanel(/*paneIndex, panelAttributes */) { + throw new Error('Must implement updatePanel.'); + } +} diff --git a/src/ui/public/embeddable/embeddable_handler.js b/src/ui/public/embeddable/embeddable_handler.js new file mode 100644 index 0000000000000..aee16ca8e6049 --- /dev/null +++ b/src/ui/public/embeddable/embeddable_handler.js @@ -0,0 +1,33 @@ +/** + * The EmbeddableHandler defines how to render and embed any object into the Dashboard, or some other + * container that supports EmbeddableHandlers. + */ +export class EmbeddableHandler { + /** + * @param {string} panelId - the id of the panel to grab the title for. + * @return {Promise.} a promise that resolves with the path that dictates where the user will be navigated to + * when they click the edit icon. + */ + getEditPath(/* panelId */) { + throw new Error('Must implement getEditPath.'); + } + + /** + * @param {string} panelId - the id of the panel to grab the title for. + * @return {Promise.} - Promise that resolves with the title to display for the particular panel. + */ + getTitleFor(/* panelId */) { + throw new Error('Must implement getTitleFor.'); + } + + /** + * @param {Element} domNode - the dom node to mount the rendered embeddable on + * @param {PanelState} panel - a panel object which container information about the panel. Can also be modified to + * store per panel information. + * @property {ContainerApi} containerApi - an id to specify the object that this panel contains. + * @param {Promise.} A promise that resolves when the object is finished rendering. + */ + render(/* domNode, panel, container */) { + throw new Error('Must implement render.'); + } +} diff --git a/src/ui/public/embeddable/embeddable_handlers_registry.js b/src/ui/public/embeddable/embeddable_handlers_registry.js new file mode 100644 index 0000000000000..408288c842173 --- /dev/null +++ b/src/ui/public/embeddable/embeddable_handlers_registry.js @@ -0,0 +1,9 @@ +import { uiRegistry } from 'ui/registry/_registry'; + +/** + * Registry of functions (EmbeddableHandlerProviders) which return an EmbeddableHandler. + */ +export const EmbeddableHandlersRegistryProvider = uiRegistry({ + name: 'embeddableHandlers', + index: ['name'] +}); diff --git a/src/ui/public/embeddable/index.js b/src/ui/public/embeddable/index.js new file mode 100644 index 0000000000000..bdd73ce99a110 --- /dev/null +++ b/src/ui/public/embeddable/index.js @@ -0,0 +1,3 @@ +export { EmbeddableHandler } from './embeddable_handler'; +export { EmbeddableHandlersRegistryProvider } from './embeddable_handlers_registry'; +export { ContainerAPI } from './container_api'; diff --git a/src/ui/ui_exports.js b/src/ui/ui_exports.js index 70606553717ca..ba8c57f8479d2 100644 --- a/src/ui/ui_exports.js +++ b/src/ui/ui_exports.js @@ -21,6 +21,10 @@ export default class UiExports { visEditorTypes: [ 'ui/vis/editors/default/default', ], + embeddableHandlers: [ + 'plugins/kibana/visualize/embeddable/visualize_embeddable_handler_provider', + 'plugins/kibana/discover/embeddable/search_embeddable_handler_provider', + ], }; this.urlBasePath = urlBasePath; this.exportConsumer = _.memoize(this.exportConsumer); @@ -105,6 +109,7 @@ export default class UiExports { case 'visRequestHandlers': case 'visEditorTypes': case 'savedObjectTypes': + case 'embeddableHandlers': case 'fieldFormats': case 'fieldFormatEditors': case 'spyModes': diff --git a/test/functional/apps/dashboard/_dashboard.js b/test/functional/apps/dashboard/_dashboard.js index 0c1df9a6b0ab3..48f32a81e2231 100644 --- a/test/functional/apps/dashboard/_dashboard.js +++ b/test/functional/apps/dashboard/_dashboard.js @@ -182,7 +182,22 @@ export default function ({ getService, getPageObjects }) { expect(spyToggleExists).to.be(true); }); + // This was an actual bug that appeared, where the spy pane appeared on panels after adding them, but + // disappeared when a new dashboard was opened up. + it('shows the spy pane toggle directly after opening a dashboard', async () => { + await PageObjects.dashboard.saveDashboard('spy pane test'); + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.loadSavedDashboard('spy pane test'); + const panels = await PageObjects.dashboard.getDashboardPanels(); + // Simulate hover + await remote.moveMouseTo(panels[0]); + const spyToggleExists = await PageObjects.visualize.getSpyToggleExists(); + expect(spyToggleExists).to.be(true); + }); + it('shows other panels after being minimized', async () => { + // Panels are all minimized on a fresh open of a dashboard, so we need to re-expand in order to then minimize. + await PageObjects.dashboard.toggleExpandPanel(); await PageObjects.dashboard.toggleExpandPanel(); const panels = await PageObjects.dashboard.getDashboardPanels(); const visualizations = PageObjects.dashboard.getTestVisualizations(); @@ -222,6 +237,7 @@ export default function ({ getService, getPageObjects }) { describe('full screen mode', () => { it('option not available in edit mode', async () => { + await PageObjects.dashboard.clickEdit(); const exists = await PageObjects.dashboard.fullScreenModeMenuItemExists(); expect(exists).to.be(false); }); diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index 90636becb209a..818b5d50c2c5b 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -310,10 +310,12 @@ export default function ({ getService, getPageObjects }) { description: 'A Saved Search Description' }; - await PageObjects.discover.loadSavedSearch(expected.title); - const { title, description } = await PageObjects.common.getSharedItemTitleAndDescription(); - expect(title).to.eql(expected.title); - expect(description).to.eql(expected.description); + await retry.try(async () => { + await PageObjects.discover.loadSavedSearch(expected.title); + const { title, description } = await PageObjects.common.getSharedItemTitleAndDescription(); + expect(title).to.eql(expected.title); + expect(description).to.eql(expected.description); + }); }); }); }); From 9aed82272611c5ca8d3780baf27a48da8e9b78ab Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Tue, 8 Aug 2017 11:32:13 -0400 Subject: [PATCH 079/165] Use find service instead of remote (#13296) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use find service instead of remote which doesn't have built in safety checks for stale elements * use data-test-subj instead of id * add missing function and awaits * Did not realize WebElements could find descendants Added some extra functionality for this in find and testSubjects service, and using in the one place it’s required. --- .../kibana/public/dashboard/top_nav/save.html | 4 +- .../functional/page_objects/dashboard_page.js | 184 +++++++----------- test/functional/services/find.js | 56 ++++-- test/functional/services/test_subjects.js | 4 + 4 files changed, 115 insertions(+), 133 deletions(-) diff --git a/src/core_plugins/kibana/public/dashboard/top_nav/save.html b/src/core_plugins/kibana/public/dashboard/top_nav/save.html index 70367eff4cf95..7f9c2cfcdfb9e 100644 --- a/src/core_plugins/kibana/public/dashboard/top_nav/save.html +++ b/src/core_plugins/kibana/public/dashboard/top_nav/save.html @@ -11,7 +11,7 @@
( - getService('remote') - .setFindTimeout(config.get('timeouts.find')) - ); - class DashboardPage { async initTests() { const logstash = esArchiver.loadIfNeeded('logstash_functional'); @@ -78,7 +74,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { async clickDashboardBreadcrumbLink() { log.debug('clickDashboardBreadcrumbLink'); - await retry.try(() => getRemote().findByCssSelector(`a[href="#${DashboardConstants.LANDING_PAGE_PATH}"]`).click()); + await find.clickByCssSelector(`a[href="#${DashboardConstants.LANDING_PAGE_PATH}"]`); } async gotoDashboardLandingPage() { @@ -93,7 +89,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } async getQueryInputElement() { - return retry.try(() => testSubjects.find('queryInput')); + return await testSubjects.find('queryInput'); } async getQuery() { @@ -131,27 +127,27 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await testSubjects.setValue('clonedDashboardTitle', title); } - clickEdit() { + async clickEdit() { log.debug('Clicking edit'); - return testSubjects.click('dashboardEditMode'); + return await testSubjects.click('dashboardEditMode'); } - getIsInViewMode() { + async getIsInViewMode() { log.debug('getIsInViewMode'); - return testSubjects.exists('dashboardEditMode'); + return await testSubjects.exists('dashboardEditMode'); } - clickCancelOutOfEditMode() { + async clickCancelOutOfEditMode() { log.debug('clickCancelOutOfEditMode'); - return testSubjects.click('dashboardViewOnlyMode'); + return await testSubjects.click('dashboardViewOnlyMode'); } - clickNewDashboard() { - return testSubjects.click('newDashboardLink'); + async clickNewDashboard() { + return await testSubjects.click('newDashboardLink'); } async clickCreateDashboardPrompt() { - await retry.try(() => testSubjects.click('createDashboardPromptButton')); + await testSubjects.click('createDashboardPromptButton'); } async getCreateDashboardPromptExists() { @@ -166,28 +162,28 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await testSubjects.click('deleteSelectedDashboards'); } - clickAddVisualization() { - return testSubjects.click('dashboardAddPanelButton'); + async clickAddVisualization() { + await testSubjects.click('dashboardAddPanelButton'); } - clickAddNewVisualizationLink() { - return testSubjects.click('addNewSavedObjectLink'); + async clickAddNewVisualizationLink() { + await testSubjects.click('addNewSavedObjectLink'); } - clickOptions() { - return testSubjects.click('dashboardOptionsButton'); + async clickOptions() { + await testSubjects.click('dashboardOptionsButton'); } - isOptionsOpen() { + async isOptionsOpen() { log.debug('isOptionsOpen'); - return testSubjects.exists('dashboardDarkThemeCheckbox'); + return await testSubjects.exists('dashboardDarkThemeCheckbox'); } async openOptions() { log.debug('openOptions'); const isOpen = await this.isOptionsOpen(); if (!isOpen) { - return testSubjects.click('dashboardOptionsButton'); + return await testSubjects.click('dashboardOptionsButton'); } } @@ -202,28 +198,23 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await this.openOptions(); const isDarkThemeOn = await this.isDarkThemeOn(); if (isDarkThemeOn !== on) { - return testSubjects.click('dashboardDarkThemeCheckbox'); + return await testSubjects.click('dashboardDarkThemeCheckbox'); } } - filterVizNames(vizName) { - return retry.try(() => getRemote() - .findByCssSelector('input[placeholder="Visualizations Filter..."]') - .click() - .pressKeys(vizName)); + async filterVizNames(vizName) { + const visFilter = await find.byCssSelector('input[placeholder="Visualizations Filter..."]'); + await visFilter.click(); + await remote.pressKeys(vizName); } - clickVizNameLink(vizName) { - return retry.try(() => getRemote() - .findByPartialLinkText(vizName) - .click()); + async clickVizNameLink(vizName) { + await find.clickByPartialLinkText(vizName); } - closeAddVizualizationPanel() { + async closeAddVizualizationPanel() { log.debug('closeAddVizualizationPanel'); - return retry.try(() => getRemote() - .findByCssSelector('i.fa fa-chevron-up') - .click()); + await find.clickByCssSelector('i.fa fa-chevron-up'); } async gotoDashboardEditMode(dashboardName) { @@ -252,7 +243,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { async renameDashboard(dashName) { log.debug(`Naming dashboard ` + dashName); await testSubjects.click('dashboardRenameButton'); - await getRemote().findById('dashboardTitle').type(dashName); + await testSubjects.setValue('dashboardTitle', dashName); } /** @@ -281,7 +272,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); log.debug('entering new title'); - await getRemote().findById('dashboardTitle').type(dashboardTitle); + await testSubjects.setValue('dashboardTitle', dashboardTitle); if (saveOptions.storeTimeWithDashboard !== undefined) { await this.setStoreTimeWithDashboard(saveOptions.storeTimeWithDashboard); @@ -291,16 +282,14 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await this.setSaveAsNewCheckBox(saveOptions.saveAsNew); } - await retry.try(() => { + await retry.try(async () => { log.debug('clicking final Save button for named dashboard'); - return testSubjects.click('confirmSaveDashboardButton'); + return await testSubjects.click('confirmSaveDashboardButton'); }); } - clickDashboardByLinkText(dashName) { - return getRemote() - .findByLinkText(dashName) - .click(); + async clickDashboardByLinkText(dashName) { + await find.clickByLinkText(dashName); } async clearSearchValue() { @@ -339,7 +328,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { log.debug(`getDashboardCountWithName: ${dashName}`); await this.searchForDashboardWithName(dashName); - const links = await getRemote().findAllByLinkText(dashName); + const links = await find.allByLinkText(dashName); return links.length; } @@ -367,7 +356,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { function getTitles(chart) { return chart.getVisibleText(); } - const getTitlePromises = titleObjects.map(getTitles); + const getTitlePromises = _.map(titleObjects, getTitles); return Promise.all(getTitlePromises); } @@ -375,54 +364,20 @@ export function DashboardPageProvider({ getService, getPageObjects }) { return await testSubjects.findAll('dashboardPanel'); } - getPanelSizeData() { - return getRemote() - .findAllByCssSelector('li.gs-w') // These are gridster-defined elements and classes - .then(function (titleObjects) { - - function getTitles(chart) { - let obj = {}; - return chart.getAttribute('data-col') - .then(theData => { - obj = { dataCol:theData }; - return chart; - }) - .then(chart => { - return chart.getAttribute('data-row') - .then(theData => { - obj.dataRow = theData; - return chart; - }); - }) - .then(chart => { - return chart.getAttribute('data-sizex') - .then(theData => { - obj.dataSizeX = theData; - return chart; - }); - }) - .then(chart => { - return chart.getAttribute('data-sizey') - .then(theData => { - obj.dataSizeY = theData; - return chart; - }); - }) - .then(chart => { - return chart.findByCssSelector('[data-test-subj="dashboardPanelTitle"]') - .then(function (titleElement) { - return titleElement.getVisibleText(); - }) - .then(theData => { - obj.title = theData; - return obj; - }); - }); - } + async getPanelSizeData() { + const titleObjects = await find.allByCssSelector('li.gs-w'); // These are gridster-defined elements and classes + async function getTitles(chart) { + const dataCol = await chart.getAttribute('data-col'); + const dataRow = await chart.getAttribute('data-row'); + const dataSizeX = await chart.getAttribute('data-sizex'); + const dataSizeY = await chart.getAttribute('data-sizey'); + const childElement = await testSubjects.findDescendant('dashboardPanelTitle', chart); + const title = await childElement.getVisibleText(); + return { dataCol, dataRow, dataSizeX, dataSizeY, title }; + } - const getTitlePromises = titleObjects.map(getTitles); - return Promise.all(getTitlePromises); - }); + const getTitlePromises = _.map(titleObjects, getTitles); + return await Promise.all(getTitlePromises); } getTestVisualizations() { @@ -497,7 +452,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { log.debug('toggleExpandPanel'); const expandShown = await testSubjects.exists('dashboardPanelExpandIcon'); if (!expandShown) { - const panelElements = await getRemote().findAllByCssSelector('span.panel-title'); + const panelElements = await find.allByCssSelector('span.panel-title'); log.debug('click title'); await retry.try(() => panelElements[0].click()); // Click to simulate hover. } @@ -506,33 +461,26 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await retry.try(() => expandButton.click()); } - getSharedItemsCount() { + async getSharedItemsCount() { log.debug('in getSharedItemsCount'); const attributeName = 'data-shared-items-count'; - return getRemote() - .findByCssSelector(`[${attributeName}]`) - .then(function (element) { - if (element) { - return element.getAttribute(attributeName); - } + const element = await find.byCssSelector(`[${attributeName}]`); + if (element) { + return await element.getAttribute(attributeName); + } - throw new Error('no element'); - }); + throw new Error('no element'); } - getPanelSharedItemData() { + async getPanelSharedItemData() { log.debug('in getPanelSharedItemData'); - return getRemote() - .findAllByCssSelector('li.gs-w') - .then(function (elements) { - return Promise.all(elements.map(async element => { - const sharedItem = await element.findByCssSelector('[data-shared-item]'); - return { - title: await sharedItem.getAttribute('data-title'), - description: await sharedItem.getAttribute('data-description') - }; - })); - }); + const sharedItems = await find.allByCssSelector('[data-shared-item]'); + return await Promise.all(sharedItems.map(async sharedItem => { + return { + title: await sharedItem.getAttribute('data-title'), + description: await sharedItem.getAttribute('data-description') + }; + })); } } diff --git a/test/functional/services/find.js b/test/functional/services/find.js index 8b5cb453dea2d..779bdb55c6720 100644 --- a/test/functional/services/find.js +++ b/test/functional/services/find.js @@ -7,7 +7,7 @@ export function FindProvider({ getService }) { const defaultFindTimeout = config.get('timeouts.find'); class Find { - async withTimeout(timeout, block) { + async _withTimeout(timeout, block) { try { const remoteWithTimeout = remote.setFindTimeout(timeout); return await block(remoteWithTimeout); @@ -16,7 +16,17 @@ export function FindProvider({ getService }) { } } - async ensureElementWithTimeout(timeout, getElementFunction) { + async _ensureElement(getElementFunction) { + return await retry.try(async () => { + const element = await getElementFunction(); + console.log('element is ', element); + // Calling any method forces a staleness check + element.isEnabled(); + return element; + }); + } + + async _ensureElementWithTimeout(timeout, getElementFunction) { try { const remoteWithTimeout = remote.setFindTimeout(timeout); return await retry.try(async () => { @@ -32,48 +42,68 @@ export function FindProvider({ getService }) { async byName(selector, timeout = defaultFindTimeout) { log.debug(`find.byName(${selector})`); - return await this.ensureElementWithTimeout(timeout, async remote => { + return await this._ensureElementWithTimeout(timeout, async remote => { return await remote.findByName(selector); }); } async byCssSelector(selector, timeout = defaultFindTimeout) { log.debug(`findByCssSelector ${selector}`); - return await this.ensureElementWithTimeout(timeout, async remote => { + return await this._ensureElementWithTimeout(timeout, async remote => { return await remote.findByCssSelector(selector); }); } - async allByCssSelector(selector, timeout = defaultFindTimeout) { - log.debug('in findAllByCssSelector: ' + selector); - return await this.withTimeout(timeout, async remote => { + async allByCustom(findAllFunction, timeout = defaultFindTimeout) { + return await this._withTimeout(timeout, async remote => { return await retry.try(async () => { - let elements = await remote.findAllByCssSelector(selector); + let elements = await findAllFunction(remote); if (!elements) elements = []; // Force isStale checks for all the retrieved elements. await Promise.all(elements.map(async element => await element.isEnabled())); - log.debug(`Found ${elements.length} for selector ${selector}`); return elements; }); }); } - async displayedByCssSelector(selector, timeout = defaultFindTimeout) { + async allByLinkText(selector, timeout = defaultFindTimeout) { + log.debug('find.allByLinkText: ' + selector); + return await this.allByCustom(remote => remote.findAllByLinkText(selector), timeout); + } + + async allByCssSelector(selector, timeout = defaultFindTimeout) { + log.debug('in findAllByCssSelector: ' + selector); + return await this.allByCustom(remote => remote.findAllByCssSelector(selector), timeout); + } + + async descendantDisplayedByCssSelector(selector, parentElement) { + log.debug('Find.childDisplayedByCssSelector: ' + selector); + return await this._ensureElement(async () => await parentElement.findDisplayedByCssSelector(selector)); + } + + async displayedByCssSelector(selector, timeout = defaultFindTimeout, parentElement) { log.debug('in displayedByCssSelector: ' + selector); - return await this.ensureElementWithTimeout(timeout, async remote => { + return await this._ensureElementWithTimeout(timeout, async remote => { return await remote.findDisplayedByCssSelector(selector); + }, parentElement); + } + + async byLinkText(selector, timeout = defaultFindTimeout) { + log.debug('Find.byLinkText: ' + selector); + return await this._ensureElementWithTimeout(timeout, async remote => { + return await remote.findByLinkText(selector); }); } async byPartialLinkText(partialLinkText, timeout = defaultFindTimeout) { log.debug(`find.byPartialLinkText(${partialLinkText})`); - return await this.ensureElementWithTimeout(timeout, async remote => { + return await this._ensureElementWithTimeout(timeout, async remote => { return await remote.findByPartialLinkText(partialLinkText); }); } async exists(findFunction, timeout = 1000) { - return await this.withTimeout(timeout, async remote => { + return await this._withTimeout(timeout, async remote => { try { await findFunction(remote); return true; diff --git a/test/functional/services/test_subjects.js b/test/functional/services/test_subjects.js index 84aef32ba1629..59c4d47a1cafe 100644 --- a/test/functional/services/test_subjects.js +++ b/test/functional/services/test_subjects.js @@ -34,6 +34,10 @@ export function TestSubjectsProvider({ getService }) { }); } + async findDescendant(selector, parentElement) { + return await find.descendantDisplayedByCssSelector(testSubjSelector(selector), parentElement); + } + async find(selector, timeout = defaultFindTimeout) { log.debug(`TestSubjects.find(${selector})`); return await find.displayedByCssSelector(testSubjSelector(selector), timeout); From 9dbd10db1749b3ce33cec47125e37fa3f8458a34 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Tue, 8 Aug 2017 17:49:55 +0200 Subject: [PATCH 080/165] Add support for `Router.post` method and `body` validation. (#13389) --- package-lock.json | 97 ++++----- package.json | 3 +- platform/cli/__tests__/captureTerminal.ts | 15 +- platform/root/__tests__/index.test.ts | 4 +- platform/server/http/HttpServer.ts | 2 + platform/server/http/Router/index.ts | 185 +++++++++++------- .../server/http/__tests__/HttpServer.test.ts | 66 +++++++ 7 files changed, 252 insertions(+), 120 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9c265386e87fd..7047d8eeefcc9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -160,6 +160,16 @@ "resolved": "https://registry.npmjs.org/@spalger/ui-ace/-/ui-ace-0.2.3.tgz", "integrity": "sha1-2cjvhIP6ufEYVRxeJ+3aw1q6hgc=" }, + "@types/body-parser": { + "version": "1.16.4", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.16.4.tgz", + "integrity": "sha512-y8GxleWZ4ep0GG9IFMg+HpZWqLPjAjqc65cAopXPAWONWGCWGT0FCPVlXbUEBOPWpYtFrvlp2D7EJJnrqLUnEQ==", + "dev": true, + "requires": { + "@types/express": "4.0.36", + "@types/node": "8.0.19" + } + }, "@types/chalk": { "version": "0.4.31", "resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-0.4.31.tgz", @@ -1860,33 +1870,29 @@ "dev": true }, "body-parser": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.12.0.tgz", - "integrity": "sha1-l1D8PMEICzShPRjHmEDNVZl5/OU=", + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", + "integrity": "sha1-+IkqvI+eYn1Crtr7yma/WrmRBO4=", "requires": { - "bytes": "1.0.0", + "bytes": "2.4.0", "content-type": "1.0.2", - "debug": "2.1.3", - "depd": "1.0.1", - "iconv-lite": "0.4.7", - "on-finished": "2.2.1", - "qs": "2.3.3", - "raw-body": "1.3.3", + "debug": "2.6.7", + "depd": "1.1.1", + "http-errors": "1.6.1", + "iconv-lite": "0.4.15", + "on-finished": "2.3.0", + "qs": "6.4.0", + "raw-body": "2.2.0", "type-is": "1.6.15" }, "dependencies": { "debug": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.3.tgz", - "integrity": "sha1-zoqxte6PvuK/o7Yzyrk9NmtjQY4=", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", "requires": { - "ms": "0.7.0" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.0.tgz", - "integrity": "sha1-hlvpTC5zl62KV9pqYzpuLzB5i4M=" } } }, @@ -2105,9 +2111,9 @@ } }, "bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" }, "call": { "version": "3.0.4", @@ -3556,9 +3562,9 @@ "dev": true }, "depd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" }, "des.js": { "version": "1.0.0", @@ -3783,9 +3789,9 @@ "dev": true }, "ee-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz", - "integrity": "sha1-ag18YiHkkP7v2S7D9EHJzozQl/Q=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "elasticsearch": { "version": "13.0.1", @@ -6901,7 +6907,6 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=", - "dev": true, "requires": { "depd": "1.1.0", "inherits": "2.0.3", @@ -6912,8 +6917,7 @@ "depd": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", - "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", - "dev": true + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=" } } }, @@ -6949,9 +6953,9 @@ "dev": true }, "iconv-lite": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.7.tgz", - "integrity": "sha1-idMv7IIb+Fl/RGCbS8Cb7VwgmiM=" + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" }, "icss-replace-symbols": { "version": "1.1.0", @@ -11129,11 +11133,11 @@ } }, "on-finished": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.2.1.tgz", - "integrity": "sha1-XIXBzDYpn3gCllP2Z/J7a5nrwCk=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "requires": { - "ee-first": "1.1.0" + "ee-first": "1.1.1" } }, "on-headers": { @@ -12389,9 +12393,9 @@ "dev": true }, "qs": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", - "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=" + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" }, "query-string": { "version": "4.3.4", @@ -12496,12 +12500,13 @@ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.3.tgz", - "integrity": "sha1-iEGvP2StUKNR3HfyKRGLQMKPpYw=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", + "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y=", "requires": { - "bytes": "1.0.0", - "iconv-lite": "0.4.7" + "bytes": "2.4.0", + "iconv-lite": "0.4.15", + "unpipe": "1.0.0" } }, "raw-loader": { diff --git a/package.json b/package.json index 3640d01574b88..16a41bf46b2f3 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "babel-preset-react": "6.22.0", "babel-register": "6.18.0", "bluebird": "2.9.34", - "body-parser": "1.12.0", + "body-parser": "1.17.2", "boom": "2.8.0", "brace": "0.5.1", "bunyan": "1.7.1", @@ -212,6 +212,7 @@ "@elastic/eslint-config-kibana": "0.6.1", "@elastic/eslint-import-resolver-kibana": "0.8.1", "@elastic/eslint-plugin-kibana-custom": "1.0.3", + "@types/body-parser": "1.16.4", "@types/chalk": "0.4.31", "@types/chance": "0.7.34", "@types/elasticsearch": "5.0.14", diff --git a/platform/cli/__tests__/captureTerminal.ts b/platform/cli/__tests__/captureTerminal.ts index 35de4da40dbb8..2f7606619de5a 100644 --- a/platform/cli/__tests__/captureTerminal.ts +++ b/platform/cli/__tests__/captureTerminal.ts @@ -2,16 +2,21 @@ export function captureTerminal( fn: (argv: T) => any, argv: T ) { - let mockProcessExit = jest.spyOn(global.process, 'exit') + let mockProcessExit = jest + .spyOn(global.process, 'exit') .mockImplementation(() => {}); - let mockProcessEmit = jest.spyOn(global.process, 'emit') + let mockProcessEmit = jest + .spyOn(global.process, 'emit') .mockImplementation(() => {}); - let mockConsoleLog = jest.spyOn(global.console, 'log') + let mockConsoleLog = jest + .spyOn(global.console, 'log') .mockImplementation(() => {}); - let mockConsoleWarn = jest.spyOn(global.console, 'warn') + let mockConsoleWarn = jest + .spyOn(global.console, 'warn') .mockImplementation(() => {}); - let mockConsoleError = jest.spyOn(global.console, 'error') + let mockConsoleError = jest + .spyOn(global.console, 'error') .mockImplementation(() => {}); const _env = process.env; diff --git a/platform/root/__tests__/index.test.ts b/platform/root/__tests__/index.test.ts index 4de08c6214ff4..31c5ad00754ff 100644 --- a/platform/root/__tests__/index.test.ts +++ b/platform/root/__tests__/index.test.ts @@ -47,7 +47,9 @@ import { Env } from '../../config/Env'; const env = new Env('.', {}); const config$ = new BehaviorSubject({}); -let mockProcessExit = jest.spyOn(global.process, 'exit').mockImplementation(() => {}); +let mockProcessExit = jest + .spyOn(global.process, 'exit') + .mockImplementation(() => {}); afterEach(() => { mockProcessExit.mockReset(); }); diff --git a/platform/server/http/HttpServer.ts b/platform/server/http/HttpServer.ts index 55e9bc0edd130..7cefce2d76faf 100644 --- a/platform/server/http/HttpServer.ts +++ b/platform/server/http/HttpServer.ts @@ -1,4 +1,5 @@ import * as express from 'express'; +import * as bodyParser from 'body-parser'; import * as http from 'http'; import { Router } from './Router'; @@ -8,6 +9,7 @@ export class HttpServer { constructor() { this.app = express(); + this.app.use(bodyParser()); this.httpServer = http.createServer(this.app); } diff --git a/platform/server/http/Router/index.ts b/platform/server/http/Router/index.ts index e1f3dd2c6ba58..92e80bd1970a5 100644 --- a/platform/server/http/Router/index.ts +++ b/platform/server/http/Router/index.ts @@ -5,12 +5,14 @@ import { ObjectSetting, Props, Any, TypeOf } from '../../../lib/schema'; export interface Route< Params extends ObjectSetting<{}>, - Query extends ObjectSetting<{}> + Query extends ObjectSetting<{}>, + Body extends ObjectSetting<{}> > { path: string; validate?: { params?: Params; query?: Query; + body?: Body; }; } @@ -33,10 +35,11 @@ const responseFactory: ResponseFactory = { export type RequestHandler< RequestValue, Params extends Any, - Query extends Any + Query extends Any, + Body extends Any > = ( onRequestValue: RequestValue, - req: KibanaRequest, TypeOf>, + req: KibanaRequest, TypeOf, TypeOf>, createResponse: ResponseFactory ) => Promise | { [key: string]: any }>; @@ -51,20 +54,31 @@ export class KibanaResponse { // receive the headers you _have_ validated). export class KibanaRequest< Params extends Props = {}, - Query extends Props = {} + Query extends Props = {}, + Body extends Props = {} > { readonly headers: Headers; - static validate( - route: Route, ObjectSetting>, + static validate< + Params extends Props = {}, + Query extends Props = {}, + Body extends Props = {} + >( + route: Route< + ObjectSetting, + ObjectSetting, + ObjectSetting + >, req: express.Request - ): { params: Params; query: Query } { + ): { params: Params; query: Query; body: Body } { let params: Params; let query: Query; + let body: Body; if (route.validate === undefined) { params = req.params; query = req.query; + body = req.body; } else { if (route.validate.params === undefined) { params = req.params; @@ -77,15 +91,22 @@ export class KibanaRequest< } else { query = route.validate.query.validate(req.query); } + + if (route.validate.body === undefined) { + body = req.body; + } else { + body = route.validate.body.validate(req.body); + } } - return { query, params }; + return { query, params, body }; } constructor( req: express.Request, readonly params: Params, - readonly query: Query + readonly query: Query, + readonly body: Body ) { this.headers = req.headers; } @@ -104,73 +125,103 @@ export class Router { constructor(readonly path: string, readonly options: RouterOptions = {}) {} - get

, Q extends ObjectSetting>( - route: Route, - handler: RequestHandler - ) { - this.router.get(route.path, async (req, res) => { - let valid: { params: TypeOf

; query: TypeOf

}; - - // TODO Change this so we can get failures per type - try { - valid = KibanaRequest.validate(route, req); - } catch (e) { - res.status(400); - res.json({ error: e.message }); - return; - } - - const kibanaRequest = new KibanaRequest(req, valid.params, valid.query); - - const value = - this.options.onRequest !== undefined - ? this.options.onRequest(kibanaRequest) - : {} as V; - - try { - const response = await handler(value, kibanaRequest, responseFactory); - - if (response instanceof KibanaResponse) { - res.status(response.status); - - if (response.payload === undefined) { - res.send(); - } else if (response.payload instanceof Error) { - // TODO Design an error format - res.json({ error: response.payload.message }); - } else { - res.json(response.payload); - } - } else { - res.json(response); - } - } catch (e) { - // TODO Specifically handle `KibanaResponseError` and validation errors. + get< + P extends ObjectSetting, + Q extends ObjectSetting, + B extends ObjectSetting + >(route: Route, handler: RequestHandler) { + this.router.get( + route.path, + async (req, res) => await this.handle(route, req, res, handler) + ); + } - // Otherwise we default to something along the lines of - res.status(500).json({ error: e.message }); - } - }); + post< + P extends ObjectSetting, + Q extends ObjectSetting, + B extends ObjectSetting + >(route: Route, handler: RequestHandler) { + this.router.post( + route.path, + async (req, res) => await this.handle(route, req, res, handler) + ); } - post

, Q extends ObjectSetting>( - route: Route, - handler: RequestHandler - ) { + put< + P extends ObjectSetting, + Q extends ObjectSetting, + B extends ObjectSetting + >(route: Route, handler: RequestHandler) { // TODO } - put

, Q extends ObjectSetting>( - route: Route, - handler: RequestHandler - ) { + delete< + P extends ObjectSetting, + Q extends ObjectSetting, + B extends ObjectSetting + >(route: Route, handler: RequestHandler) { // TODO } - delete

, Q extends ObjectSetting>( - route: Route, - handler: RequestHandler + private async handle< + P extends ObjectSetting, + Q extends ObjectSetting, + B extends ObjectSetting + >( + route: Route, + request: express.Request, + response: express.Response, + handler: RequestHandler ) { - // TODO + let valid: { params: TypeOf

; query: TypeOf

; body: TypeOf }; + + // TODO Change this so we can get failures per type + try { + valid = KibanaRequest.validate(route, request); + } catch (e) { + response.status(400); + response.json({ error: e.message }); + return; + } + + const kibanaRequest = new KibanaRequest( + request, + valid.params, + valid.query, + valid.body + ); + + const value = + this.options.onRequest !== undefined + ? this.options.onRequest(kibanaRequest) + : {} as V; + + try { + const kibanaResponse = await handler( + value, + kibanaRequest, + responseFactory + ); + + if (kibanaResponse instanceof KibanaResponse) { + response.status(kibanaResponse.status); + + if (kibanaResponse.payload === undefined) { + response.send(); + } else if (kibanaResponse.payload instanceof Error) { + // TODO Design an error format + response.json({ error: kibanaResponse.payload.message }); + } else { + response.json(kibanaResponse.payload); + } + } else { + response.json(kibanaResponse); + } + } catch (e) { + // TODO Specifically handle `KibanaResponseError` and validation errors. + + // Otherwise we default to something along the lines of + response.status(500).json({ error: e.message }); + } } } diff --git a/platform/server/http/__tests__/HttpServer.test.ts b/platform/server/http/__tests__/HttpServer.test.ts index 368760a864114..70feaf3f92b32 100644 --- a/platform/server/http/__tests__/HttpServer.test.ts +++ b/platform/server/http/__tests__/HttpServer.test.ts @@ -204,6 +204,72 @@ test('invalid query', async () => { }); }); +test('valid body', async () => { + const router = new Router('/foo'); + + router.post( + { + path: '/', + validate: { + body: schema.object({ + bar: schema.string(), + baz: schema.number() + }) + } + }, + async (val, req, res) => { + return res.ok(req.body); + } + ); + + server.registerRouter(router); + + await server.start(port, '127.0.0.1'); + + await supertest(app) + .post('/foo') + .send({ + bar: 'test', + baz: 123 + }) + .expect(200) + .then(res => { + expect(res.body).toEqual({ bar: 'test', baz: 123 }); + }); +}); + +test('invalid body', async () => { + const router = new Router('/foo'); + + router.post( + { + path: '/', + validate: { + body: schema.object({ + bar: schema.number() + }) + } + }, + async (val, req, res) => { + return res.ok(req.body); + } + ); + + server.registerRouter(router); + + await server.start(port, '127.0.0.1'); + + await supertest(app) + .post('/foo') + .send({ bar: 'test' }) + .expect(400) + .then(res => { + expect(res.body).toEqual({ + error: '[bar]: expected value of type [number] but got [string]' + }); + }); +}); + test('returns 200 OK if returning object', async () => { const router = new Router('/foo'); From 542d553fe2c722d2bcce5a43f934ad0218993c4d Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Tue, 8 Aug 2017 13:06:20 -0400 Subject: [PATCH 081/165] Make filter pills keyboard accessible (#13331) Fixes #12639 It's now possible to tab to each filter's actions and interact with them via the keyboard. In order to get the actions to show/hide on both mouse hover and action focus I had to create a new filter-pill component that could manage a bit of state to track whether the user was interacting with a given pill or not. --- src/ui/public/filter_bar/filter_bar.html | 40 ++-------- src/ui/public/filter_bar/filter_bar.js | 1 + src/ui/public/filter_bar/filter_bar.less | 36 ++++----- .../filter_bar/filter_pill/filter_pill.html | 74 +++++++++++++++++++ .../filter_bar/filter_pill/filter_pill.js | 33 +++++++++ .../functional/page_objects/dashboard_page.js | 2 +- 6 files changed, 135 insertions(+), 51 deletions(-) create mode 100644 src/ui/public/filter_bar/filter_pill/filter_pill.html create mode 100644 src/ui/public/filter_bar/filter_pill/filter_pill.js diff --git a/src/ui/public/filter_bar/filter_bar.html b/src/ui/public/filter_bar/filter_bar.html index 29a60c192a049..d1e10b22e318b 100644 --- a/src/ui/public/filter_bar/filter_bar.html +++ b/src/ui/public/filter_bar/filter_bar.html @@ -26,39 +26,15 @@ class="filter-bar" ng-show="filters.length || showAddFilterButton()" > -

+ filter="filter" + on-toggle-filter="toggleFilter" + on-pin-filter="pinFilter" + on-invert-filter="invertFilter" + on-delete-filter="deleteFilter" + on-edit-filter="editFilter" + > + +
); } } GuideNav.propTypes = { + isChromeVisible: PropTypes.bool, isNavOpen: PropTypes.bool, + isSandbox: PropTypes.bool, onToggleNav: PropTypes.func, + onHideChrome: PropTypes.func, + onShowChrome: PropTypes.func, onClickNavItem: PropTypes.func, version: PropTypes.string, routes: PropTypes.array, diff --git a/ui_framework/doc_site/src/components/guide_sandbox/guide_sandbox.js b/ui_framework/doc_site/src/components/guide_sandbox/guide_sandbox.js index b1cfdc8276c7c..ec9501f6c5563 100644 --- a/ui_framework/doc_site/src/components/guide_sandbox/guide_sandbox.js +++ b/ui_framework/doc_site/src/components/guide_sandbox/guide_sandbox.js @@ -1,7 +1,55 @@ -import React from 'react'; +import React, { + Component, +} from 'react'; +import PropTypes from 'prop-types'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; -export const GuideSandbox = props => ( -
- {props.children} -
-); +import { + getIsSandbox, +} from '../../store'; + +import { + openSandbox, + closeSandbox, +} from '../../actions'; + +function mapStateToProps(state) { + return { + isSandbox: getIsSandbox(state), + }; +} + +function mapDispatchToProps(dispatch) { + const actions = { + openSandbox, + closeSandbox, + }; + + return bindActionCreators(actions, dispatch); +} + +class GuideSandboxComponent extends Component { + componentWillMount() { + this.props.openSandbox(); + } + + componentWillUnmount() { + this.props.closeSandbox(); + } + + render() { + return ( +
+ {this.props.children} +
+ ); + } +} + +GuideSandboxComponent.propTypes = { + openSandbox: PropTypes.func, + closeSandbox: PropTypes.func, +}; + +export const GuideSandbox = connect(mapStateToProps, mapDispatchToProps)(GuideSandboxComponent); diff --git a/ui_framework/doc_site/src/components/guide_section/_guide_section.scss b/ui_framework/doc_site/src/components/guide_section/_guide_section.scss index be596398381af..280b0026172e4 100644 --- a/ui_framework/doc_site/src/components/guide_section/_guide_section.scss +++ b/ui_framework/doc_site/src/components/guide_section/_guide_section.scss @@ -25,9 +25,15 @@ border: 1px solid $guideLinkHoverColor; border-radius: 3px; cursor: pointer; + transform: translateX(0); + transition: transform $guideChromeTransition; &:hover, &:active { background-color: #e6f7fc; } + + .is-chrome-hidden & { + transform: translateX(60px); + } } diff --git a/ui_framework/doc_site/src/store/configure_store.js b/ui_framework/doc_site/src/store/configure_store.js index 8f6de34b6733b..b7160220345bf 100644 --- a/ui_framework/doc_site/src/store/configure_store.js +++ b/ui_framework/doc_site/src/store/configure_store.js @@ -11,6 +11,7 @@ import { } from 'react-router-redux'; import codeViewerReducer from './reducers/code_viewer_reducer'; +import sandboxReducer from './reducers/sandbox_reducer'; import sectionsReducer from './reducers/sections_reducer'; /** @@ -22,6 +23,7 @@ export default function configureStore(initialState) { return { routing: routerReducer(state.routing, action), codeViewer: codeViewerReducer(state.codeViewer, action), + sandbox: sandboxReducer(state.sandbox, action), sections: sectionsReducer(state.sections, action), }; } diff --git a/ui_framework/doc_site/src/store/index.js b/ui_framework/doc_site/src/store/index.js index 0ab30476a2dbf..12be83f4b2374 100644 --- a/ui_framework/doc_site/src/store/index.js +++ b/ui_framework/doc_site/src/store/index.js @@ -2,6 +2,10 @@ export function getIsCodeViewerOpen(state) { return state.codeViewer.isOpen; } +export function getIsSandbox(state) { + return state.sandbox.isSandbox; +} + export function getSections(state) { return state.sections.sections; } diff --git a/ui_framework/doc_site/src/store/reducers/sandbox_reducer.js b/ui_framework/doc_site/src/store/reducers/sandbox_reducer.js new file mode 100644 index 0000000000000..6dd83497dc471 --- /dev/null +++ b/ui_framework/doc_site/src/store/reducers/sandbox_reducer.js @@ -0,0 +1,26 @@ +import ActionTypes from '../../actions/action_types'; + +const defaultState = { + isSandbox: false, +}; + +export default function sandboxReducer(state = defaultState, action) { + switch (action.type) { + case ActionTypes.OPEN_SANDBOX: { + return Object.assign({}, state, { + isSandbox: true, + }); + } + + case ActionTypes.CLOSE_SANDBOX: { + return Object.assign({}, state, { + isSandbox: false, + }); + } + + default: + break; + } + + return state; +} diff --git a/ui_framework/doc_site/src/views/app_container.js b/ui_framework/doc_site/src/views/app_container.js index 5289c137567c1..e54a3412302b1 100644 --- a/ui_framework/doc_site/src/views/app_container.js +++ b/ui_framework/doc_site/src/views/app_container.js @@ -3,11 +3,14 @@ import { connect } from 'react-redux'; import { getIsCodeViewerOpen, + getIsSandbox, getSections, getSource, getTitle, } from '../store'; + import { AppView } from './app_view'; + import { openCodeViewer, closeCodeViewer, @@ -19,6 +22,7 @@ function mapStateToProps(state, ownProps) { return { routes: ownProps.routes, isCodeViewerOpen: getIsCodeViewerOpen(state), + isSandbox: getIsSandbox(state), source: getSource(state), title: getTitle(state), sections: getSections(state), diff --git a/ui_framework/doc_site/src/views/app_view.js b/ui_framework/doc_site/src/views/app_view.js index 3829153e1efd1..24616e55b7763 100644 --- a/ui_framework/doc_site/src/views/app_view.js +++ b/ui_framework/doc_site/src/views/app_view.js @@ -23,11 +23,14 @@ export class AppView extends Component { this.state = { isNavOpen: false, + isChromeVisible: !props.isSandbox, }; this.onClickNavItem = this.onClickNavItem.bind(this); this.onToggleNav = this.onToggleNav.bind(this); this.onCloseCodeViewer = this.onCloseCodeViewer.bind(this); + this.onHideChrome = this.onHideChrome.bind(this); + this.onShowChrome = this.onShowChrome.bind(this); } onClickNavItem() { @@ -46,15 +49,44 @@ export class AppView extends Component { }); } + onHideChrome() { + this.setState({ + isChromeVisible: false, + isNavOpen: false, + }); + + this.props.closeCodeViewer(); + } + + onShowChrome() { + this.setState({ + isChromeVisible: true, + }); + } + + componentWillReceiveProps(nextProps) { + // Only force the chrome to be hidden if we're navigating from a non-sandbox to a sandbox. + if (!this.props.isSandbox && nextProps.isSandbox) { + this.setState({ + isChromeVisible: false, + }); + } + } + render() { const contentClasses = classNames('guideContent', { 'is-code-viewer-open': this.props.isCodeViewerOpen, + 'is-chrome-hidden': !this.state.isChromeVisible, }); return (
} from './<%= fileName %>'; +export { + <%= componentName %>, +} from './<%= fileName %>'; diff --git a/ui_framework/generator-kui/component/templates/test.js b/ui_framework/generator-kui/component/templates/test.js index aecd6497a73cb..4f384d6c2d3aa 100644 --- a/ui_framework/generator-kui/component/templates/test.js +++ b/ui_framework/generator-kui/component/templates/test.js @@ -7,7 +7,7 @@ import { <%= componentName %> } from './<%= fileName %>'; describe('<%= componentName %>', () => { test('is rendered', () => { const component = render( - <<%= componentName %> { ...requiredProps } /> + <<%= componentName %> {...requiredProps} /> ); expect(component) From fbaf4e638bb71586d79c692feaac9dbcedcb3f38 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 11 Aug 2017 11:48:54 -0700 Subject: [PATCH 108/165] [eslint-config-kibana] Upgrade eslint-config to 0.10.0. (#13323) * Upgrade eslint-config to 0.10.0. * Fix linting violations with popover and typography stuff in UI Framework. --- package.json | 2 +- .../public/dashboard/top_nav/clone_modal.js | 10 +- .../public/components/add_delete_buttons.js | 6 +- .../public/components/aggs/derivative.js | 96 ++++----- .../public/components/aggs/filter_ratio.js | 160 +++++++-------- .../public/components/aggs/moving_average.js | 193 +++++++++--------- .../public/components/aggs/percentile.js | 2 +- .../public/components/aggs/percentile_rank.js | 102 +++++---- .../public/components/aggs/positive_only.js | 82 ++++---- .../public/components/aggs/serial_diff.js | 97 ++++----- .../metrics/public/components/aggs/static.js | 93 ++++----- .../public/components/aggs/std_deviation.js | 128 ++++++------ .../public/components/aggs/std_sibling.js | 138 ++++++------- .../metrics/public/components/color_picker.js | 2 +- .../public/components/custom_color_picker.js | 10 +- .../public/components/index_pattern.js | 102 +++++---- .../public/components/lib/agg_to_component.js | 46 ++--- .../public/components/markdown_editor.js | 4 +- .../metrics/public/components/panel_config.js | 2 +- .../public/components/panel_config/gauge.js | 2 +- .../components/panel_config/markdown.js | 4 +- .../public/components/panel_config/metric.js | 2 +- .../components/panel_config/timeseries.js | 2 +- .../public/components/panel_config/top_n.js | 2 +- .../public/components/series_config.js | 99 +++++---- .../metrics/public/components/split.js | 4 +- .../public/components/splits/filter.js | 52 +++-- .../components/splits/group_by_select.js | 4 +- .../metrics/public/components/splits/terms.js | 100 +++++---- .../metrics/public/components/vis_picker.js | 2 +- .../components/vis_types/gauge/series.js | 6 +- .../components/vis_types/markdown/series.js | 8 +- .../components/vis_types/metric/series.js | 6 +- .../components/vis_types/timeseries/config.js | 2 +- .../components/vis_types/timeseries/series.js | 4 +- .../components/vis_types/top_n/series.js | 6 +- .../visualizations/components/resize.js | 2 +- .../visualizations/components/timeseries.js | 6 +- .../lib/create_legend_series.js | 8 +- .../guide_page_side_nav.js | 31 +-- .../accessibility/accessibility_example.js | 14 +- .../doc_site/src/views/bar/bar_example.js | 4 +- .../src/views/button/button_example.js | 8 +- .../src/views/button/button_with_icon.js | 2 +- .../doc_site/src/views/card/card_example.js | 2 +- .../views/collapse_button/collapse_button.js | 8 +- .../src/views/color_picker/color_picker.js | 2 +- .../views/color_picker/color_picker_clear.js | 6 +- .../color_picker_no_color_label.js | 6 +- .../src/views/column/column_example.js | 2 +- .../src/views/gallery/gallery_example.js | 2 +- .../doc_site/src/views/home/home_view.js | 4 +- .../doc_site/src/views/icon/icon_example.js | 2 +- .../src/views/local_nav/local_nav_dropdown.js | 4 +- .../local_nav/local_nav_dropdown_panels.js | 4 +- .../src/views/local_nav/local_nav_example.js | 2 +- .../views/menu_button/menu_button_example.js | 2 +- .../src/views/not_found/not_found_view.js | 16 +- .../doc_site/src/views/pager/pager_buttons.js | 4 +- .../doc_site/src/views/popover/popover.js | 2 +- .../views/popover/popover_anchor_position.js | 4 +- .../views/popover/popover_body_class_name.js | 12 +- .../src/views/table/controlled_table.js | 26 +-- .../table/controlled_table_loading_items.js | 16 +- .../controlled_table_with_empty_prompt.js | 18 +- .../table/controlled_table_with_no_items.js | 16 +- .../doc_site/src/views/table/fluid_table.js | 2 +- .../views/table/table_with_menu_buttons.js | 4 +- .../accessibility/screen_reader.test.js | 2 +- .../action_item/action_item.test.js | 2 +- ui_framework/src/components/bar/bar.test.js | 2 +- .../src/components/bar/bar_section.test.js | 2 +- .../button/button_icon/button_icon.test.js | 2 +- ui_framework/src/components/card/card.test.js | 2 +- .../components/card/card_description.test.js | 2 +- .../card/card_description_text.test.js | 2 +- .../card/card_description_title.test.js | 2 +- .../src/components/card/card_footer.test.js | 2 +- .../src/components/card/card_group.test.js | 4 +- .../collapse_button/collapse_button.test.js | 6 +- .../components/color_picker/color_picker.js | 16 +- .../color_picker/color_picker.test.js | 34 +-- .../color_picker/color_picker_swatch.js | 4 +- .../empty_table_prompt.test.js | 2 +- .../empty_table_prompt_actions.test.js | 2 +- .../empty_table_prompt_message.test.js | 2 +- .../empty_table_prompt_panel.test.js | 2 +- .../src/components/event/event.test.js | 2 +- .../src/components/event/event_body.test.js | 2 +- .../event/event_body_message.test.js | 2 +- .../event/event_body_metadata.test.js | 2 +- .../src/components/event/event_symbol.test.js | 2 +- .../form_layout/field_group.test.js | 4 +- .../form_layout/field_group_section.test.js | 4 +- .../src/components/gallery/gallery.test.js | 2 +- .../gallery_button/gallery_button.test.js | 2 +- .../gallery_button_icon.test.js | 2 +- .../gallery_button_image.test.js | 2 +- .../gallery_button_label.test.js | 2 +- .../components/header_bar/header_bar.test.js | 2 +- .../header_bar/header_bar_section.test.js | 2 +- .../src/components/info_button/info_button.js | 2 +- .../src/components/local_nav/local_nav.js | 2 +- .../components/local_nav/local_nav.test.js | 2 +- .../src/components/local_nav/local_nav_row.js | 2 +- .../local_nav/local_nav_row.test.js | 4 +- .../local_nav/local_nav_row_section.js | 2 +- .../local_nav/local_nav_row_section.test.js | 2 +- .../src/components/local_nav/local_tab.js | 2 +- .../components/local_nav/local_tab.test.js | 6 +- .../src/components/local_nav/local_tabs.js | 2 +- .../components/local_nav/local_tabs.test.js | 2 +- .../src/components/local_nav/local_title.js | 2 +- .../components/local_nav/local_title.test.js | 2 +- ui_framework/src/components/menu/menu.test.js | 2 +- .../src/components/menu/menu_item.test.js | 2 +- .../src/components/modal/confirm_modal.js | 16 +- .../components/modal/confirm_modal.test.js | 18 +- ui_framework/src/components/modal/modal.js | 2 +- .../src/components/modal/modal.test.js | 2 +- .../src/components/modal/modal_body.js | 2 +- .../src/components/modal/modal_body.test.js | 2 +- .../src/components/modal/modal_body_text.js | 2 +- .../components/modal/modal_body_text.test.js | 2 +- .../src/components/modal/modal_footer.js | 2 +- .../src/components/modal/modal_footer.test.js | 2 +- .../src/components/modal/modal_header.js | 2 +- .../src/components/modal/modal_header.test.js | 2 +- .../components/modal/modal_header_title.js | 2 +- .../modal/modal_header_title.test.js | 2 +- .../src/components/modal/modal_overlay.js | 4 +- .../components/modal/modal_overlay.test.js | 2 +- ui_framework/src/components/pager/pager.js | 2 +- .../src/components/pager/pager.test.js | 2 +- .../components/pager/pager_button_group.js | 2 +- .../pager/pager_button_group.test.js | 2 +- .../src/components/popover/popover.js | 8 +- .../src/components/popover/popover.test.js | 2 +- .../components/table/controlled_table.test.js | 2 +- .../src/components/table/table.test.js | 2 +- .../src/components/table/table_body.js | 2 +- .../src/components/table/table_header.js | 2 +- .../table/table_header_cell.test.js | 2 +- .../table/table_header_check_box_cell.js | 6 +- .../table/table_header_check_box_cell.test.js | 2 +- .../src/components/table/table_info.test.js | 2 +- .../src/components/table/table_row.test.js | 2 +- .../components/table/table_row_cell.test.js | 2 +- .../table/table_row_check_box_cell.js | 6 +- .../table/table_row_check_box_cell.test.js | 2 +- ui_framework/src/components/tabs/tab.test.js | 4 +- ui_framework/src/components/tabs/tabs.test.js | 2 +- .../src/components/tool_bar/tool_bar.test.js | 2 +- .../tool_bar/tool_bar_footer.test.js | 2 +- .../tool_bar/tool_bar_footer_section.test.js | 2 +- .../tool_bar/tool_bar_search_box.js | 10 +- .../tool_bar/tool_bar_search_box.test.js | 4 +- .../tool_bar/tool_bar_section.test.js | 2 +- .../components/tool_bar/tool_bar_text.test.js | 2 +- .../components/typography/typography.test.js | 4 +- 160 files changed, 1022 insertions(+), 1107 deletions(-) diff --git a/package.json b/package.json index 555e9c6eec43b..bbf839066db67 100644 --- a/package.json +++ b/package.json @@ -204,7 +204,7 @@ "yauzl": "2.7.0" }, "devDependencies": { - "@elastic/eslint-config-kibana": "0.9.0", + "@elastic/eslint-config-kibana": "0.10.0", "@elastic/eslint-import-resolver-kibana": "0.8.1", "@elastic/eslint-plugin-kibana-custom": "1.0.3", "angular-mocks": "1.4.7", diff --git a/src/core_plugins/kibana/public/dashboard/top_nav/clone_modal.js b/src/core_plugins/kibana/public/dashboard/top_nav/clone_modal.js index 564d3d0912f68..6cca9f6054a0a 100644 --- a/src/core_plugins/kibana/public/dashboard/top_nav/clone_modal.js +++ b/src/core_plugins/kibana/public/dashboard/top_nav/clone_modal.js @@ -42,7 +42,7 @@ export class DashboardCloneModal extends React.Component { data-tests-subj="dashboardCloneModal" aria-label="Clone a dashboard" className="dashboardCloneModal" - onKeyDown={ this.onKeyDown } + onKeyDown={this.onKeyDown} > @@ -58,8 +58,8 @@ export class DashboardCloneModal extends React.Component { autoFocus data-test-subj="clonedDashboardTitle" className="kuiTextInput kuiTextInput--large" - value={ this.state.newDashboardName } - onChange={ this.onInputChange } + value={this.state.newDashboardName} + onChange={this.onInputChange} /> @@ -68,14 +68,14 @@ export class DashboardCloneModal extends React.Component { Cancel Confirm Clone diff --git a/src/core_plugins/metrics/public/components/add_delete_buttons.js b/src/core_plugins/metrics/public/components/add_delete_buttons.js index 38ebfc1bbbec1..215a8ed9ffe14 100644 --- a/src/core_plugins/metrics/public/components/add_delete_buttons.js +++ b/src/core_plugins/metrics/public/components/add_delete_buttons.js @@ -8,7 +8,7 @@ function AddDeleteButtons(props) { } return ( - + @@ -20,7 +20,7 @@ function AddDeleteButtons(props) { } return ( - + @@ -32,7 +32,7 @@ function AddDeleteButtons(props) { if (props.onClone && !props.disableAdd) { clone = ( - + diff --git a/src/core_plugins/metrics/public/components/aggs/derivative.js b/src/core_plugins/metrics/public/components/aggs/derivative.js index 7206f33e21c61..03cfd49adf63a 100644 --- a/src/core_plugins/metrics/public/components/aggs/derivative.js +++ b/src/core_plugins/metrics/public/components/aggs/derivative.js @@ -1,4 +1,4 @@ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import AggSelect from './agg_select'; import MetricSelect from './metric_select'; import AggRow from './agg_row'; @@ -6,57 +6,53 @@ import createChangeHandler from '../lib/create_change_handler'; import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; -class DerivativeAgg extends Component { +export const DerivativeAgg = props => { + const { siblings } = props; - render() { - const { siblings } = this.props; + const defaults = { unit: '' }; + const model = { ...defaults, ...props.model }; - const defaults = { unit: '' }; - const model = { ...defaults, ...this.props.model }; + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + const handleTextChange = createTextHandler(handleChange); - const handleChange = createChangeHandler(this.props.onChange, model); - const handleSelectChange = createSelectHandler(handleChange); - const handleTextChange = createTextHandler(handleChange); - - return ( - -
-
Aggregation
- -
-
-
Metric
- -
-
-
Units (1s, 1m, etc)
- -
-
- ); - } - -} + return ( + +
+
Aggregation
+ +
+
+
Metric
+ +
+
+
Units (1s, 1m, etc)
+ +
+
+ ); +}; DerivativeAgg.propTypes = { disableDelete: PropTypes.bool, @@ -69,5 +65,3 @@ DerivativeAgg.propTypes = { series: PropTypes.object, siblings: PropTypes.array, }; - -export default DerivativeAgg; diff --git a/src/core_plugins/metrics/public/components/aggs/filter_ratio.js b/src/core_plugins/metrics/public/components/aggs/filter_ratio.js index 734f8ddb63556..94098e3bd3636 100644 --- a/src/core_plugins/metrics/public/components/aggs/filter_ratio.js +++ b/src/core_plugins/metrics/public/components/aggs/filter_ratio.js @@ -1,4 +1,4 @@ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import AggSelect from './agg_select'; import FieldSelect from './field_select'; import AggRow from './agg_row'; @@ -6,94 +6,90 @@ import createChangeHandler from '../lib/create_change_handler'; import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; -class FilterRatioAgg extends Component { +export const FilterRatioAgg = props => { + const { + series, + fields, + panel + } = props; - render() { - const { - series, - fields, - panel - } = this.props; + const handleChange = createChangeHandler(props.onChange, props.model); + const handleSelectChange = createSelectHandler(handleChange); + const handleTextChange = createTextHandler(handleChange); + const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern; - const handleChange = createChangeHandler(this.props.onChange, this.props.model); - const handleSelectChange = createSelectHandler(handleChange); - const handleTextChange = createTextHandler(handleChange); - const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern; + const defaults = { + numerator: '*', + denominator: '*', + metric_agg: 'count' + }; - const defaults = { - numerator: '*', - denominator: '*', - metric_agg: 'count' - }; + const model = { ...defaults, ...props.model }; - const model = { ...defaults, ...this.props.model }; - - return ( - -
-
-
-
Aggregation
- -
-
-
Numerator
- -
-
-
Denominator
- -
+ return ( + +
+
+
+
Aggregation
+ +
+
+
Numerator
+
-
+
+
Denominator
+ +
+
+
+
+
Metric Aggregation
+ +
+ { model.metric_agg !== 'count' ? (
-
Metric Aggregation
- Field
+ -
- { model.metric_agg !== 'count' ? ( -
-
Field
- -
) : null } -
+
) : null }
- - ); - } - -} +
+
+ ); +}; FilterRatioAgg.propTypes = { disableDelete: PropTypes.bool, @@ -106,5 +102,3 @@ FilterRatioAgg.propTypes = { series: PropTypes.object, siblings: PropTypes.array, }; - -export default FilterRatioAgg; diff --git a/src/core_plugins/metrics/public/components/aggs/moving_average.js b/src/core_plugins/metrics/public/components/aggs/moving_average.js index b2c12aa7aa993..4f9ad7bc26dc4 100644 --- a/src/core_plugins/metrics/public/components/aggs/moving_average.js +++ b/src/core_plugins/metrics/public/components/aggs/moving_average.js @@ -1,4 +1,4 @@ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import AggRow from './agg_row'; import AggSelect from './agg_select'; import MetricSelect from './metric_select'; @@ -8,106 +8,103 @@ import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; import createNumberHandler from '../lib/create_number_handler'; -class MovingAverageAgg extends Component { - render() { - const { siblings } = this.props; - const defaults = { - settings: '', - minimize: 0, - window: '', - model: 'simple' - }; - const model = { ...defaults, ...this.props.model }; - const handleChange = createChangeHandler(this.props.onChange, model); - const handleSelectChange = createSelectHandler(handleChange); - const handleTextChange = createTextHandler(handleChange); - const handleNumberChange = createNumberHandler(handleChange); - const modelOptions = [ - { label: 'Simple', value: 'simple' }, - { label: 'Linear', value: 'linear' }, - { label: 'Exponentially Weighted', value: 'ewma' }, - { label: 'Holt-Linear', value: 'holt' }, - { label: 'Holt-Winters', value: 'holt_winters' } - ]; - const minimizeOptions = [ - { label: 'True', value: 1 }, - { label: 'False', value: 0 } - ]; - return ( - -
-
-
-
Aggregation
- -
-
-
Metric
- -
+export const MovingAverageAgg = props => { + const { siblings } = props; + const defaults = { + settings: '', + minimize: 0, + window: '', + model: 'simple' + }; + const model = { ...defaults, ...props.model }; + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + const handleTextChange = createTextHandler(handleChange); + const handleNumberChange = createNumberHandler(handleChange); + const modelOptions = [ + { label: 'Simple', value: 'simple' }, + { label: 'Linear', value: 'linear' }, + { label: 'Exponentially Weighted', value: 'ewma' }, + { label: 'Holt-Linear', value: 'holt' }, + { label: 'Holt-Winters', value: 'holt_winters' } + ]; + const minimizeOptions = [ + { label: 'True', value: 1 }, + { label: 'False', value: 0 } + ]; + return ( + +
+
+
+
Aggregation
+
-
-
-
Model
- -
-
-
Minimize
- -
+
+
+
+
Model
+ +
+
+
Minimize
+ +
+
+
+ + ); +}; MovingAverageAgg.propTypes = { disableDelete: PropTypes.bool, @@ -120,5 +117,3 @@ MovingAverageAgg.propTypes = { series: PropTypes.object, siblings: PropTypes.array, }; - -export default MovingAverageAgg; diff --git a/src/core_plugins/metrics/public/components/aggs/percentile.js b/src/core_plugins/metrics/public/components/aggs/percentile.js index 0573797d0ff46..4bd24b98adae3 100644 --- a/src/core_plugins/metrics/public/components/aggs/percentile.js +++ b/src/core_plugins/metrics/public/components/aggs/percentile.js @@ -114,7 +114,7 @@ Percentiles.propTypes = { }; -class PercentileAgg extends Component { +class PercentileAgg extends Component { // eslint-disable-line react/no-multi-comp componentWillMount() { if (!this.props.model.percentiles) { diff --git a/src/core_plugins/metrics/public/components/aggs/percentile_rank.js b/src/core_plugins/metrics/public/components/aggs/percentile_rank.js index e5c32a2c291ef..de02f27856b57 100644 --- a/src/core_plugins/metrics/public/components/aggs/percentile_rank.js +++ b/src/core_plugins/metrics/public/components/aggs/percentile_rank.js @@ -1,4 +1,4 @@ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import AggSelect from './agg_select'; import FieldSelect from './field_select'; import AggRow from './agg_row'; @@ -6,60 +6,55 @@ import createChangeHandler from '../lib/create_change_handler'; import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; -class PercentileRankAgg extends Component { +export const PercentileRankAgg = props => { + const { series, panel, fields } = props; + const defaults = { value: '' }; + const model = { ...defaults, ...props.model }; - render() { - const { series, panel, fields } = this.props; - const defaults = { value: '' }; - const model = { ...defaults, ...this.props.model }; + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + const handleTextChange = createTextHandler(handleChange); + const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern; - const handleChange = createChangeHandler(this.props.onChange, model); - const handleSelectChange = createSelectHandler(handleChange); - const handleTextChange = createTextHandler(handleChange); - - const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern; - - return ( - -
-
Aggregation
- -
-
-
Field
- -
-
-
Value
- -
-
- ); - } - -} + return ( + +
+
Aggregation
+ +
+
+
Field
+ +
+
+
Value
+ +
+
+ ); +}; PercentileRankAgg.propTypes = { disableDelete: PropTypes.bool, @@ -72,6 +67,3 @@ PercentileRankAgg.propTypes = { series: PropTypes.object, siblings: PropTypes.array, }; - -export default PercentileRankAgg; - diff --git a/src/core_plugins/metrics/public/components/aggs/positive_only.js b/src/core_plugins/metrics/public/components/aggs/positive_only.js index afb243c6effc0..543c814a75956 100644 --- a/src/core_plugins/metrics/public/components/aggs/positive_only.js +++ b/src/core_plugins/metrics/public/components/aggs/positive_only.js @@ -1,51 +1,47 @@ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import AggSelect from './agg_select'; import MetricSelect from './metric_select'; import AggRow from './agg_row'; import createChangeHandler from '../lib/create_change_handler'; import createSelectHandler from '../lib/create_select_handler'; -class PositiveOnlyAgg extends Component { - - render() { - const { siblings } = this.props; - - const defaults = { unit: '' }; - const model = { ...defaults, ...this.props.model }; - - const handleChange = createChangeHandler(this.props.onChange, model); - const handleSelectChange = createSelectHandler(handleChange); - - return ( - -
-
Aggregation
- -
-
-
Metric
- -
-
- ); - } - -} +export const PositiveOnlyAgg = props => { + const { siblings } = props; + + const defaults = { unit: '' }; + const model = { ...defaults, ...props.model }; + + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + + return ( + +
+
Aggregation
+ +
+
+
Metric
+ +
+
+ ); +}; PositiveOnlyAgg.propTypes = { disableDelete: PropTypes.bool, @@ -58,5 +54,3 @@ PositiveOnlyAgg.propTypes = { series: PropTypes.object, siblings: PropTypes.array, }; - -export default PositiveOnlyAgg; diff --git a/src/core_plugins/metrics/public/components/aggs/serial_diff.js b/src/core_plugins/metrics/public/components/aggs/serial_diff.js index 1b102390c80aa..33d20a3a1e16f 100644 --- a/src/core_plugins/metrics/public/components/aggs/serial_diff.js +++ b/src/core_plugins/metrics/public/components/aggs/serial_diff.js @@ -1,4 +1,4 @@ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import AggSelect from './agg_select'; import MetricSelect from './metric_select'; import AggRow from './agg_row'; @@ -6,56 +6,52 @@ import createChangeHandler from '../lib/create_change_handler'; import createSelectHandler from '../lib/create_select_handler'; import createNumberHandler from '../lib/create_number_handler'; -class SerialDiffAgg extends Component { +export const SerialDiffAgg = props => { + const { siblings } = props; + const defaults = { lag: '' }; + const model = { ...defaults, ...props.model }; - render() { - const { siblings } = this.props; - const defaults = { lag: '' }; - const model = { ...defaults, ...this.props.model }; + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + const handleNumberChange = createNumberHandler(handleChange); - const handleChange = createChangeHandler(this.props.onChange, model); - const handleSelectChange = createSelectHandler(handleChange); - const handleNumberChange = createNumberHandler(handleChange); - - return ( - -
-
Aggregation
- -
-
-
Metric
- -
-
-
Lag
- -
-
- ); - } - -} + return ( + +
+
Aggregation
+ +
+
+
Metric
+ +
+
+
Lag
+ +
+
+ ); +}; SerialDiffAgg.propTypes = { disableDelete: PropTypes.bool, @@ -68,6 +64,3 @@ SerialDiffAgg.propTypes = { series: PropTypes.object, siblings: PropTypes.array, }; - -export default SerialDiffAgg; - diff --git a/src/core_plugins/metrics/public/components/aggs/static.js b/src/core_plugins/metrics/public/components/aggs/static.js index 7193c0bd8beb2..d383eb21f16b4 100644 --- a/src/core_plugins/metrics/public/components/aggs/static.js +++ b/src/core_plugins/metrics/public/components/aggs/static.js @@ -1,62 +1,58 @@ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import AggSelect from './agg_select'; import AggRow from './agg_row'; import createChangeHandler from '../lib/create_change_handler'; import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; -class FilterRatioAgg extends Component { +export const Static = props => { + const handleChange = createChangeHandler(props.onChange, props.model); + const handleSelectChange = createSelectHandler(handleChange); + const handleTextChange = createTextHandler(handleChange); - render() { - const handleChange = createChangeHandler(this.props.onChange, this.props.model); - const handleSelectChange = createSelectHandler(handleChange); - const handleTextChange = createTextHandler(handleChange); + const defaults = { + numerator: '*', + denominator: '*', + metric_agg: 'count' + }; - const defaults = { - numerator: '*', - denominator: '*', - metric_agg: 'count' - }; + const model = { ...defaults, ...props.model }; - const model = { ...defaults, ...this.props.model }; - - return ( - -
-
-
-
Aggregation
- -
-
-
Static Value
- -
+ return ( + +
+
+
+
Aggregation
+ +
+
+
Static Value
+
- - ); - } - -} +
+
+ ); +}; -FilterRatioAgg.propTypes = { +Static.propTypes = { disableDelete: PropTypes.bool, fields: PropTypes.object, model: PropTypes.object, @@ -67,6 +63,3 @@ FilterRatioAgg.propTypes = { series: PropTypes.object, siblings: PropTypes.array, }; - -export default FilterRatioAgg; - diff --git a/src/core_plugins/metrics/public/components/aggs/std_deviation.js b/src/core_plugins/metrics/public/components/aggs/std_deviation.js index e9b38f4a3c6a4..803d0e240e3d2 100644 --- a/src/core_plugins/metrics/public/components/aggs/std_deviation.js +++ b/src/core_plugins/metrics/public/components/aggs/std_deviation.js @@ -1,4 +1,4 @@ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import AggSelect from './agg_select'; import FieldSelect from './field_select'; import AggRow from './agg_row'; @@ -7,74 +7,70 @@ import createChangeHandler from '../lib/create_change_handler'; import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; -class StandardDeviationAgg extends Component { +export const StandardDeviationAgg = props => { + const { series, panel, fields } = props; + const defaults = { sigma: '' }; + const model = { ...defaults, ...props.model }; - render() { - const { series, panel, fields } = this.props; - const defaults = { sigma: '' }; - const model = { ...defaults, ...this.props.model }; + const modeOptions = [ + { label: 'Raw', value: 'raw' }, + { label: 'Upper Bound', value: 'upper' }, + { label: 'Lower Bound', value: 'lower' }, + { label: 'Bounds Band', value: 'band' } + ]; - const modeOptions = [ - { label: 'Raw', value: 'raw' }, - { label: 'Upper Bound', value: 'upper' }, - { label: 'Lower Bound', value: 'lower' }, - { label: 'Bounds Band', value: 'band' } - ]; + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + const handleTextChange = createTextHandler(handleChange); - const handleChange = createChangeHandler(this.props.onChange, model); - const handleSelectChange = createSelectHandler(handleChange); - const handleTextChange = createTextHandler(handleChange); + const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern; - const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern; - - return ( - -
-
Aggregation
- -
-
-
Field
- -
-
-
Sigma
- -
-
-
Mode
- +
+
+
Mode
+ -
- ); - - const modeOptions = [ - { label: 'Raw', value: 'raw' }, - { label: 'Upper Bound', value: 'upper' }, - { label: 'Lower Bound', value: 'lower' }, - { label: 'Bounds Band', value: 'band' } - ]; + const stdDev = {}; + if (model.type === 'std_deviation_bucket') { + stdDev.sigma = ( +
+
Sigma
+ +
+ ); - stdDev.mode = ( -
-
Mode
- +
); } -} + return ( + +
+
Aggregation
+ +
+
+
Metric
+ +
+ { stdDev.sigma } + { stdDev.mode } +
+ ); +}; StandardSiblingAgg.propTypes = { disableDelete: PropTypes.bool, @@ -95,5 +91,3 @@ StandardSiblingAgg.propTypes = { series: PropTypes.object, siblings: PropTypes.array, }; - -export default StandardSiblingAgg; diff --git a/src/core_plugins/metrics/public/components/color_picker.js b/src/core_plugins/metrics/public/components/color_picker.js index 30276b35b51e9..01ff23857b542 100644 --- a/src/core_plugins/metrics/public/components/color_picker.js +++ b/src/core_plugins/metrics/public/components/color_picker.js @@ -82,7 +82,7 @@ class ColorPicker extends Component { onClick={this.handleClose} />
diff --git a/src/core_plugins/metrics/public/components/custom_color_picker.js b/src/core_plugins/metrics/public/components/custom_color_picker.js index 382aec8a116aa..5f3bd4f818537 100644 --- a/src/core_plugins/metrics/public/components/custom_color_picker.js +++ b/src/core_plugins/metrics/public/components/custom_color_picker.js @@ -66,21 +66,21 @@ export class CustomColorPicker extends Component {
-
-
+
+
-
+
-
+
{ + const { fields, prefix } = props; + const handleSelectChange = createSelectHandler(props.onChange); + const handleTextChange = createTextHandler(props.onChange); + const timeFieldName = `${prefix}time_field`; + const indexPatternName = `${prefix}index_pattern`; + const intervalName = `${prefix}interval`; + const dropBucketName = `${prefix}drop_last_bucket`; - const defaults = { - [indexPatternName]: '*', - [intervalName]: 'auto', - [dropBucketName]: 1 - }; + const defaults = { + [indexPatternName]: '*', + [intervalName]: 'auto', + [dropBucketName]: 1 + }; - const model = { ...defaults, ...this.props.model }; - return ( -
-
Index Pattern
- -
Time Field
-
- -
-
Interval (auto, 1m, 1d, 1w, 1y)
- -
Drop Last Bucket
- +
Index Pattern
+ +
Time Field
+
+
- ); - } -} +
Interval (auto, 1m, 1d, 1w, 1y)
+ +
Drop Last Bucket
+ +
+ ); +}; IndexPattern.defaultProps = { prefix: '', @@ -73,5 +71,3 @@ IndexPattern.propTypes = { disabled: PropTypes.bool, className: PropTypes.string }; - -export default IndexPattern; diff --git a/src/core_plugins/metrics/public/components/lib/agg_to_component.js b/src/core_plugins/metrics/public/components/lib/agg_to_component.js index 14a1c7e552cbe..9a6b0369b26f3 100644 --- a/src/core_plugins/metrics/public/components/lib/agg_to_component.js +++ b/src/core_plugins/metrics/public/components/lib/agg_to_component.js @@ -1,45 +1,45 @@ -import MovingAverage from '../aggs/moving_average'; -import Derivative from '../aggs/derivative'; +import { MovingAverageAgg } from '../aggs/moving_average'; +import { DerivativeAgg } from '../aggs/derivative'; import Calculation from '../aggs/calculation'; import StdAgg from '../aggs/std_agg'; import Percentile from '../aggs/percentile'; import CumulativeSum from '../aggs/cumulative_sum'; -import StdDeviation from '../aggs/std_deviation'; -import StdSibling from '../aggs/std_sibling'; +import { StandardDeviationAgg } from '../aggs/std_deviation'; +import { StandardSiblingAgg } from '../aggs/std_sibling'; import SeriesAgg from '../aggs/series_agg'; -import SerialDiff from '../aggs/serial_diff'; -import PositiveOnly from '../aggs/positive_only'; -import FilterRatio from '../aggs/filter_ratio'; -import PercentileRank from '../aggs/percentile_rank'; -import Static from '../aggs/static'; +import { SerialDiffAgg } from '../aggs/serial_diff'; +import { PositiveOnlyAgg } from '../aggs/positive_only'; +import { FilterRatioAgg } from '../aggs/filter_ratio'; +import { PercentileRankAgg } from '../aggs/percentile_rank'; +import { Static } from '../aggs/static'; export default { count: StdAgg, avg: StdAgg, max: StdAgg, min: StdAgg, sum: StdAgg, - std_deviation: StdDeviation, + std_deviation: StandardDeviationAgg, sum_of_squares: StdAgg, variance: StdAgg, - avg_bucket: StdSibling, - max_bucket: StdSibling, - min_bucket: StdSibling, - sum_bucket: StdSibling, - variance_bucket: StdSibling, - sum_of_squares_bucket: StdSibling, - std_deviation_bucket: StdSibling, + avg_bucket: StandardSiblingAgg, + max_bucket: StandardSiblingAgg, + min_bucket: StandardSiblingAgg, + sum_bucket: StandardSiblingAgg, + variance_bucket: StandardSiblingAgg, + sum_of_squares_bucket: StandardSiblingAgg, + std_deviation_bucket: StandardSiblingAgg, percentile: Percentile, - percentile_rank: PercentileRank, + percentile_rank: PercentileRankAgg, cardinality: StdAgg, value_count: StdAgg, calculation: Calculation, cumulative_sum: CumulativeSum, - moving_average: MovingAverage, - derivative: Derivative, + moving_average: MovingAverageAgg, + derivative: DerivativeAgg, series_agg: SeriesAgg, - serial_diff: SerialDiff, - filter_ratio: FilterRatio, - positive_only: PositiveOnly, + serial_diff: SerialDiffAgg, + filter_ratio: FilterRatioAgg, + positive_only: PositiveOnlyAgg, static: Static }; diff --git a/src/core_plugins/metrics/public/components/markdown_editor.js b/src/core_plugins/metrics/public/components/markdown_editor.js index 5d1913b949a14..2b4bc7baac66b 100644 --- a/src/core_plugins/metrics/public/components/markdown_editor.js +++ b/src/core_plugins/metrics/public/components/markdown_editor.js @@ -48,7 +48,7 @@ class MarkdownEditor extends Component { - "{ value }" + “{ value }” ); @@ -67,7 +67,7 @@ class MarkdownEditor extends Component { - [ [ "{date}", "{value}" ], ... ] + [ [ “{date}”, “{value}” ], ... ] ); diff --git a/src/core_plugins/metrics/public/components/panel_config.js b/src/core_plugins/metrics/public/components/panel_config.js index 26aa7fda0ed9b..5ec2b849b746d 100644 --- a/src/core_plugins/metrics/public/components/panel_config.js +++ b/src/core_plugins/metrics/public/components/panel_config.js @@ -19,7 +19,7 @@ function PanelConfig(props) { if (component) { return React.createElement(component, props); } - return (
Missing panel config for "{model.type}"
); + return (
Missing panel config for “{model.type}”
); } PanelConfig.propTypes = { diff --git a/src/core_plugins/metrics/public/components/panel_config/gauge.js b/src/core_plugins/metrics/public/components/panel_config/gauge.js index 17b690d80e613..b70227b3a7f92 100644 --- a/src/core_plugins/metrics/public/components/panel_config/gauge.js +++ b/src/core_plugins/metrics/public/components/panel_config/gauge.js @@ -1,6 +1,6 @@ import React, { Component, PropTypes } from 'react'; import SeriesEditor from '../series_editor'; -import IndexPattern from '../index_pattern'; +import { IndexPattern } from '../index_pattern'; import Select from 'react-select'; import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; diff --git a/src/core_plugins/metrics/public/components/panel_config/markdown.js b/src/core_plugins/metrics/public/components/panel_config/markdown.js index 28148e1504218..8c065ece6c1a4 100644 --- a/src/core_plugins/metrics/public/components/panel_config/markdown.js +++ b/src/core_plugins/metrics/public/components/panel_config/markdown.js @@ -1,6 +1,6 @@ import React, { Component, PropTypes } from 'react'; import SeriesEditor from '../series_editor'; -import IndexPattern from '../index_pattern'; +import { IndexPattern } from '../index_pattern'; import AceEditor from 'react-ace'; import 'brace/mode/less'; import Select from 'react-select'; @@ -120,7 +120,7 @@ class MarkdownPanelConfig extends Component { width="100%" name={`ace-css-${model.id}`} setOptions={{ fontSize: '14px' }} - value={ model.markdown_less} + value={model.markdown_less} onChange={this.handleCSSChange} />
diff --git a/src/core_plugins/metrics/public/components/panel_config/metric.js b/src/core_plugins/metrics/public/components/panel_config/metric.js index 9cd6b18de3aea..5879503040a5f 100644 --- a/src/core_plugins/metrics/public/components/panel_config/metric.js +++ b/src/core_plugins/metrics/public/components/panel_config/metric.js @@ -1,6 +1,6 @@ import React, { Component, PropTypes } from 'react'; import SeriesEditor from '../series_editor'; -import IndexPattern from '../index_pattern'; +import { IndexPattern } from '../index_pattern'; import createTextHandler from '../lib/create_text_handler'; import ColorRules from '../color_rules'; import YesNo from '../yes_no'; diff --git a/src/core_plugins/metrics/public/components/panel_config/timeseries.js b/src/core_plugins/metrics/public/components/panel_config/timeseries.js index dafbfaeb54c66..ce81e1b37d1c6 100644 --- a/src/core_plugins/metrics/public/components/panel_config/timeseries.js +++ b/src/core_plugins/metrics/public/components/panel_config/timeseries.js @@ -1,7 +1,7 @@ import React, { Component, PropTypes } from 'react'; import SeriesEditor from '../series_editor'; import AnnotationsEditor from '../annotations_editor'; -import IndexPattern from '../index_pattern'; +import { IndexPattern } from '../index_pattern'; import Select from 'react-select'; import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; diff --git a/src/core_plugins/metrics/public/components/panel_config/top_n.js b/src/core_plugins/metrics/public/components/panel_config/top_n.js index 6b0ae65010333..01166f9603ae1 100644 --- a/src/core_plugins/metrics/public/components/panel_config/top_n.js +++ b/src/core_plugins/metrics/public/components/panel_config/top_n.js @@ -1,6 +1,6 @@ import React, { Component, PropTypes } from 'react'; import SeriesEditor from '../series_editor'; -import IndexPattern from '../index_pattern'; +import { IndexPattern } from '../index_pattern'; import createTextHandler from '../lib/create_text_handler'; import ColorRules from '../color_rules'; import ColorPicker from '../color_picker'; diff --git a/src/core_plugins/metrics/public/components/series_config.js b/src/core_plugins/metrics/public/components/series_config.js index 3a1883159bd29..b9b19ef70a0ba 100644 --- a/src/core_plugins/metrics/public/components/series_config.js +++ b/src/core_plugins/metrics/public/components/series_config.js @@ -1,61 +1,58 @@ -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import DataFormatPicker from './data_format_picker'; import createSelectHandler from './lib/create_select_handler'; import createTextHandler from './lib/create_text_handler'; import YesNo from './yes_no'; -import IndexPattern from './index_pattern'; +import { IndexPattern } from './index_pattern'; -class SeriesConfig extends Component { - render() { - const defaults = { offset_time: '', value_template: '' }; - const model = { ...defaults, ...this.props.model }; - const handleSelectChange = createSelectHandler(this.props.onChange); - const handleTextChange = createTextHandler(this.props.onChange); +export const SeriesConfig = props => { + const defaults = { offset_time: '', value_template: '' }; + const model = { ...defaults, ...props.model }; + const handleSelectChange = createSelectHandler(props.onChange); + const handleTextChange = createTextHandler(props.onChange); - return ( -
-
-
- -
Template (eg.{'{{value}}/s'})
- -
Offset series time by (1m, 1h, 1w, 1d)
- -
-
-
Override Index Pattern
- - -
+ return ( +
+
+
+ +
Template (eg.{'{{value}}/s'})
+ +
Offset series time by (1m, 1h, 1w, 1d)
+ +
+
+
Override Index Pattern
+ +
- ); - } - -} +
+ ); +}; SeriesConfig.propTypes = { fields: PropTypes.object, @@ -63,5 +60,3 @@ SeriesConfig.propTypes = { onChange: PropTypes.func }; -export default SeriesConfig; - diff --git a/src/core_plugins/metrics/public/components/split.js b/src/core_plugins/metrics/public/components/split.js index 8cc11b22346dc..1ef670c2623ed 100644 --- a/src/core_plugins/metrics/public/components/split.js +++ b/src/core_plugins/metrics/public/components/split.js @@ -1,8 +1,8 @@ import React, { Component, PropTypes } from 'react'; import uuid from 'uuid'; -import SplitByTerms from './splits/terms'; -import SplitByFilter from './splits/filter'; +import { SplitByTerms } from './splits/terms'; +import { SplitByFilter } from './splits/filter'; import SplitByFilters from './splits/filters'; import SplitByEverything from './splits/everything'; diff --git a/src/core_plugins/metrics/public/components/splits/filter.js b/src/core_plugins/metrics/public/components/splits/filter.js index dab31fd56f8b6..3805f25eef0cb 100644 --- a/src/core_plugins/metrics/public/components/splits/filter.js +++ b/src/core_plugins/metrics/public/components/splits/filter.js @@ -1,40 +1,34 @@ import createTextHandler from '../lib/create_text_handler'; import createSelectHandler from '../lib/create_select_handler'; import GroupBySelect from './group_by_select'; -import React, { Component, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; -class SplitByFilter extends Component { - - render() { - const { onChange } = this.props; - const defaults = { filter: '' }; - const model = { ...defaults, ...this.props.model }; - const handleTextChange = createTextHandler(onChange); - const handleSelectChange = createSelectHandler(onChange); - return ( -
-
Group By
-
- -
-
Query String
- { + const { onChange } = props; + const defaults = { filter: '' }; + const model = { ...defaults, ...props.model }; + const handleTextChange = createTextHandler(onChange); + const handleSelectChange = createSelectHandler(onChange); + return ( +
+
Group By
+
+
- ); - } - -} +
Query String
+ +
+ ); +}; SplitByFilter.propTypes = { model: PropTypes.object, onChange: PropTypes.func }; - -export default SplitByFilter; diff --git a/src/core_plugins/metrics/public/components/splits/group_by_select.js b/src/core_plugins/metrics/public/components/splits/group_by_select.js index f6904175ed6a6..02cbef254ecbf 100644 --- a/src/core_plugins/metrics/public/components/splits/group_by_select.js +++ b/src/core_plugins/metrics/public/components/splits/group_by_select.js @@ -10,9 +10,9 @@ function GroupBySelect(props) { return ( +
Group By
+
+ -
Order By
-
- -
- ); - } - -} +
By
+
+ +
+
Top
+ +
Order By
+
+ +
+
+ ); +}; SplitByTerms.propTypes = { model: PropTypes.object, @@ -65,5 +61,3 @@ SplitByTerms.propTypes = { indexPattern: PropTypes.string, fields: PropTypes.object }; - -export default SplitByTerms; diff --git a/src/core_plugins/metrics/public/components/vis_picker.js b/src/core_plugins/metrics/public/components/vis_picker.js index f919ac68c79da..82719b054911e 100644 --- a/src/core_plugins/metrics/public/components/vis_picker.js +++ b/src/core_plugins/metrics/public/components/vis_picker.js @@ -47,7 +47,7 @@ function VisPicker(props) { ); diff --git a/src/core_plugins/metrics/public/components/vis_types/gauge/series.js b/src/core_plugins/metrics/public/components/vis_types/gauge/series.js index 91ad826a7dcb9..2aa6f122ff45f 100644 --- a/src/core_plugins/metrics/public/components/vis_types/gauge/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/gauge/series.js @@ -1,7 +1,7 @@ import React, { PropTypes } from 'react'; import ColorPicker from '../../color_picker'; import AddDeleteButtons from '../../add_delete_buttons'; -import SeriesConfig from '../../series_config'; +import { SeriesConfig } from '../../series_config'; import Sortable from 'react-anything-sortable'; import Split from '../../split'; import Tooltip from '../../tooltip'; @@ -125,13 +125,13 @@ function GaugeSeries(props) { >
-
+
{ colorPicker }
diff --git a/src/core_plugins/metrics/public/components/vis_types/markdown/series.js b/src/core_plugins/metrics/public/components/vis_types/markdown/series.js index 5318038935a06..471dd47048a37 100644 --- a/src/core_plugins/metrics/public/components/vis_types/markdown/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/markdown/series.js @@ -1,6 +1,6 @@ import React, { PropTypes } from 'react'; import AddDeleteButtons from '../../add_delete_buttons'; -import SeriesConfig from '../../series_config'; +import { SeriesConfig } from '../../series_config'; import Sortable from 'react-anything-sortable'; import Split from '../../split'; import createAggRowRender from '../../lib/create_agg_row_render'; @@ -100,18 +100,18 @@ function MarkdownSeries(props) { >
-
+
diff --git a/src/core_plugins/metrics/public/components/vis_types/metric/series.js b/src/core_plugins/metrics/public/components/vis_types/metric/series.js index 64960748a0338..e853142673550 100644 --- a/src/core_plugins/metrics/public/components/vis_types/metric/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/metric/series.js @@ -1,7 +1,7 @@ import React, { PropTypes } from 'react'; import ColorPicker from '../../color_picker'; import AddDeleteButtons from '../../add_delete_buttons'; -import SeriesConfig from '../../series_config'; +import { SeriesConfig } from '../../series_config'; import Sortable from 'react-anything-sortable'; import Split from '../../split'; import Tooltip from '../../tooltip'; @@ -125,13 +125,13 @@ function MetricSeries(props) { >
-
+
{ colorPicker }
diff --git a/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js b/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js index 97fee28ca252d..667cb926544fa 100644 --- a/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js +++ b/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js @@ -4,7 +4,7 @@ import DataFormatPicker from '../../data_format_picker'; import createSelectHandler from '../../lib/create_select_handler'; import YesNo from '../../yes_no'; import createTextHandler from '../../lib/create_text_handler'; -import IndexPattern from '../../index_pattern'; +import { IndexPattern } from '../../index_pattern'; function TimeseriesConfig(props) { const handleSelectChange = createSelectHandler(props.onChange); diff --git a/src/core_plugins/metrics/public/components/vis_types/timeseries/series.js b/src/core_plugins/metrics/public/components/vis_types/timeseries/series.js index d632b65cf5b31..b6db23e0cad13 100644 --- a/src/core_plugins/metrics/public/components/vis_types/timeseries/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/timeseries/series.js @@ -125,13 +125,13 @@ function TimeseriesSeries(props) { >
-
+
{ colorPicker }
diff --git a/src/core_plugins/metrics/public/components/vis_types/top_n/series.js b/src/core_plugins/metrics/public/components/vis_types/top_n/series.js index 2049e5aac5e79..93e81b8f50843 100644 --- a/src/core_plugins/metrics/public/components/vis_types/top_n/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/top_n/series.js @@ -1,7 +1,7 @@ import React, { PropTypes } from 'react'; import ColorPicker from '../../color_picker'; import AddDeleteButtons from '../../add_delete_buttons'; -import SeriesConfig from '../../series_config'; +import { SeriesConfig } from '../../series_config'; import Sortable from 'react-anything-sortable'; import Split from '../../split'; import Tooltip from '../../tooltip'; @@ -120,13 +120,13 @@ function TopNSeries(props) { >
-
+
{ colorPicker }
diff --git a/src/core_plugins/metrics/public/visualizations/components/resize.js b/src/core_plugins/metrics/public/visualizations/components/resize.js index 6af1d54749a68..4f2c3fa50a1c0 100644 --- a/src/core_plugins/metrics/public/visualizations/components/resize.js +++ b/src/core_plugins/metrics/public/visualizations/components/resize.js @@ -29,7 +29,7 @@ class Resize extends Component { const el = findDOMNode(this.el); const currentWidth = el.parentNode.clientWidth; const currentHeight = el.parentNode.clientHeight; - this.setState({ currentHeight, currentWidth }); + this.setState({ currentHeight, currentWidth }); // eslint-disable-line react/no-did-mount-set-state this.checkSize(); } diff --git a/src/core_plugins/metrics/public/visualizations/components/timeseries.js b/src/core_plugins/metrics/public/visualizations/components/timeseries.js index 377297544df96..dafb91ea2e1f3 100644 --- a/src/core_plugins/metrics/public/visualizations/components/timeseries.js +++ b/src/core_plugins/metrics/public/visualizations/components/timeseries.js @@ -123,12 +123,12 @@ class Timeseries extends Component { (row, i) => { const classes = ['rhythm_chart__legend_item']; const key = row.id; if (!_.includes(props.seriesFilter, row.id)) classes.push('disabled'); - if (row.label == null || row.legend === false) return (
); + if (row.label == null || row.legend === false) return (
); return (
props.onToggle(event, row.id) } - key={ key } + className={classes.join(' ')} + onClick={event => props.onToggle(event, row.id)} + key={key} >
diff --git a/ui_framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js b/ui_framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js index 3ee423e6d2e11..bc061b81d5e4d 100644 --- a/ui_framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js +++ b/ui_framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js @@ -1,29 +1,20 @@ import React, { - Component, PropTypes, } from 'react'; -export class GuidePageSideNav extends Component { - - constructor(props) { - super(props); - } - - render() { - return ( -
-
- {this.props.title} -
- -
- {this.props.children} -
+export const GuidePageSideNav = props => { + return ( +
+
+ {props.title}
- ); - } -} +
+ {props.children} +
+
+ ); +}; GuidePageSideNav.propTypes = { title: PropTypes.string, diff --git a/ui_framework/doc_site/src/views/accessibility/accessibility_example.js b/ui_framework/doc_site/src/views/accessibility/accessibility_example.js index 470127beea624..b173c0e593d33 100644 --- a/ui_framework/doc_site/src/views/accessibility/accessibility_example.js +++ b/ui_framework/doc_site/src/views/accessibility/accessibility_example.js @@ -56,13 +56,13 @@ export default props => ( > This class can be useful to add accessibility to older designs that are - still in use, but it shouldn't be a permanent solution. See - http://webaim.org/techniques/css/invisiblecontent/ - { - // eslint-disable-next-line react/jsx-closing-tag-location - } for more information. + still in use, but it shouldn’t be a permanent solution. See {( + + http://webaim.org/techniques/css/invisiblecontent/ + + )} for more information. diff --git a/ui_framework/doc_site/src/views/bar/bar_example.js b/ui_framework/doc_site/src/views/bar/bar_example.js index 750f3cee84a56..381fe747d579b 100644 --- a/ui_framework/doc_site/src/views/bar/bar_example.js +++ b/ui_framework/doc_site/src/views/bar/bar_example.js @@ -60,7 +60,7 @@ export default props => ( > A Bar with one section will align it to the right, by default. To align it to the left, - just add another section and leave it empty, or don't use a Bar at all. + just add another section and leave it empty, or don’t use a Bar at all. @@ -79,7 +79,7 @@ export default props => ( }]} > - Technically the Bar can contain three or more sections, but there's no established use-case + Technically the Bar can contain three or more sections, but there’s no established use-case for this. diff --git a/ui_framework/doc_site/src/views/button/button_example.js b/ui_framework/doc_site/src/views/button/button_example.js index ef8eccfe4cbaa..8e6da0a5d52a0 100644 --- a/ui_framework/doc_site/src/views/button/button_example.js +++ b/ui_framework/doc_site/src/views/button/button_example.js @@ -92,7 +92,7 @@ export default props => ( }]} > - Use the hollow Button when presenting a neutral action, e.g. a "Cancel" button. + Use the hollow Button when presenting a neutral action, e.g. a “Cancel” button. @@ -111,7 +111,7 @@ export default props => ( }]} > - Use the primary Button to represent the most common action. Generally, there won't be a + Use the primary Button to represent the most common action. Generally, there won’t be a need to present more than one of these at a time. @@ -131,7 +131,7 @@ export default props => ( }]} > - Secondary buttons are usually used for actions ("do this") that are optional actions on a page. + Secondary buttons are usually used for actions (“do this”) that are optional actions on a page. @@ -263,7 +263,7 @@ export default props => ( }]} > - You can create a Button using a button element, link, or input[type="submit"]. + You can create a Button using a button element, link, or input[type=“submit”]. diff --git a/ui_framework/doc_site/src/views/button/button_with_icon.js b/ui_framework/doc_site/src/views/button/button_with_icon.js index 88ac3425205f9..8596f1467d3ca 100644 --- a/ui_framework/doc_site/src/views/button/button_with_icon.js +++ b/ui_framework/doc_site/src/views/button/button_with_icon.js @@ -40,7 +40,7 @@ export default () => ( } - iconPosition='right' + iconPosition="right" > Next diff --git a/ui_framework/doc_site/src/views/card/card_example.js b/ui_framework/doc_site/src/views/card/card_example.js index 65cbe5e59453f..67797bcd837eb 100644 --- a/ui_framework/doc_site/src/views/card/card_example.js +++ b/ui_framework/doc_site/src/views/card/card_example.js @@ -31,7 +31,7 @@ export default props => ( }]} > - Cards expand to fill their container. To restrict a card's width, define the width of its + Cards expand to fill their container. To restrict a card’s width, define the width of its container. diff --git a/ui_framework/doc_site/src/views/collapse_button/collapse_button.js b/ui_framework/doc_site/src/views/collapse_button/collapse_button.js index 22cdd501bb76f..59f30f324c1da 100644 --- a/ui_framework/doc_site/src/views/collapse_button/collapse_button.js +++ b/ui_framework/doc_site/src/views/collapse_button/collapse_button.js @@ -6,9 +6,9 @@ import { export default () => (
- - - - + + + +
); diff --git a/ui_framework/doc_site/src/views/color_picker/color_picker.js b/ui_framework/doc_site/src/views/color_picker/color_picker.js index 28521e851abae..c1582a8d6a44a 100644 --- a/ui_framework/doc_site/src/views/color_picker/color_picker.js +++ b/ui_framework/doc_site/src/views/color_picker/color_picker.js @@ -15,6 +15,6 @@ export class ColorPicker extends React.Component { }; render() { - return ; + return ; } } diff --git a/ui_framework/doc_site/src/views/color_picker/color_picker_clear.js b/ui_framework/doc_site/src/views/color_picker/color_picker_clear.js index d675c7ad8ab8a..3d9414f67339e 100644 --- a/ui_framework/doc_site/src/views/color_picker/color_picker_clear.js +++ b/ui_framework/doc_site/src/views/color_picker/color_picker_clear.js @@ -34,15 +34,15 @@ export class ColorPickerLabelAndClear extends React.Component {

- + Reset diff --git a/ui_framework/doc_site/src/views/color_picker/color_picker_no_color_label.js b/ui_framework/doc_site/src/views/color_picker/color_picker_no_color_label.js index 4e6b4f9877cf3..71cc5803e0173 100644 --- a/ui_framework/doc_site/src/views/color_picker/color_picker_no_color_label.js +++ b/ui_framework/doc_site/src/views/color_picker/color_picker_no_color_label.js @@ -29,9 +29,9 @@ export class ColorPickerNoColorLabel extends React.Component { diff --git a/ui_framework/doc_site/src/views/column/column_example.js b/ui_framework/doc_site/src/views/column/column_example.js index 27ddd95bdf75f..3910d26cfb2ac 100644 --- a/ui_framework/doc_site/src/views/column/column_example.js +++ b/ui_framework/doc_site/src/views/column/column_example.js @@ -21,7 +21,7 @@ export default props => ( }]} > - Note: Don't use this. It's subject to change as we evolve our grid system. + Note: Don’t use this. It’s subject to change as we evolve our grid system. diff --git a/ui_framework/doc_site/src/views/gallery/gallery_example.js b/ui_framework/doc_site/src/views/gallery/gallery_example.js index dfdab4a4155eb..326c9ab66b1cb 100644 --- a/ui_framework/doc_site/src/views/gallery/gallery_example.js +++ b/ui_framework/doc_site/src/views/gallery/gallery_example.js @@ -27,7 +27,7 @@ export default props => ( > Use GalleryButton to show a gallery item. - It's an anchor and accepts all anchor properties. + It’s an anchor and accepts all anchor properties. diff --git a/ui_framework/doc_site/src/views/home/home_view.js b/ui_framework/doc_site/src/views/home/home_view.js index c9e205d544c74..d74ad1f6c228e 100644 --- a/ui_framework/doc_site/src/views/home/home_view.js +++ b/ui_framework/doc_site/src/views/home/home_view.js @@ -20,7 +20,7 @@ export const HomeView = () => (

- The Kibana team uses the UI Framework to build Kibana's user interface. Please see + The Kibana team uses the UI Framework to build Kibana’s user interface. Please see the general Kibana docs for information on how to use Kibana, and the plugin-specific section for help developing Kibana plugins. @@ -32,7 +32,7 @@ export const HomeView = () => (

- If you're just getting started with the UI Framework for the first time, you may + If you’re just getting started with the UI Framework for the first time, you may be interested in some of the more commonly-used components:

diff --git a/ui_framework/doc_site/src/views/icon/icon_example.js b/ui_framework/doc_site/src/views/icon/icon_example.js index 16028624b03ac..d1244d09a92b7 100644 --- a/ui_framework/doc_site/src/views/icon/icon_example.js +++ b/ui_framework/doc_site/src/views/icon/icon_example.js @@ -62,7 +62,7 @@ export default props => ( }]} > - Use this Icon when you don't want to communicate any particular meaning with the icon's + Use this Icon when you don’t want to communicate any particular meaning with the icon’s color. diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown.js b/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown.js index c55cc9d9b788b..42e03c4d5ad29 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown.js @@ -45,12 +45,12 @@ export function LocalNavWithDropdown() { {/* Help text */}
- Here's some help text to explain the purpose of the dropdown. + Here’s some help text to explain the purpose of the dropdown.
{/* Warning */}
- Here's some warning text in case the user has something misconfigured. + Here’s some warning text in case the user has something misconfigured.
diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js b/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js index d009b0882a941..eaa2c471e1ba7 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js @@ -48,7 +48,7 @@ export function LocalNavWithDropdownPanels() { {/* Help text */}
- Here's some help text to explain the purpose of the dropdown. + Here’s some help text to explain the purpose of the dropdown.
@@ -59,7 +59,7 @@ export function LocalNavWithDropdownPanels() { {/* Help text */}
- Here's some help text to explain the purpose of the dropdown. + Here’s some help text to explain the purpose of the dropdown.
diff --git a/ui_framework/doc_site/src/views/local_nav/local_nav_example.js b/ui_framework/doc_site/src/views/local_nav/local_nav_example.js index 3dced032ede90..b429fe0d23ac7 100644 --- a/ui_framework/doc_site/src/views/local_nav/local_nav_example.js +++ b/ui_framework/doc_site/src/views/local_nav/local_nav_example.js @@ -61,7 +61,7 @@ export default props => ( ]} > - Here's a simple LocalNav with a Title in the top left corner and Menu in the top right. + Here’s a simple LocalNav with a Title in the top left corner and Menu in the top right. diff --git a/ui_framework/doc_site/src/views/menu_button/menu_button_example.js b/ui_framework/doc_site/src/views/menu_button/menu_button_example.js index 35812940c12a0..22d5f979b7dc9 100644 --- a/ui_framework/doc_site/src/views/menu_button/menu_button_example.js +++ b/ui_framework/doc_site/src/views/menu_button/menu_button_example.js @@ -89,7 +89,7 @@ export default props => ( }]} > - You can create a MenuButton using a button element, link, or input[type="submit"]. + You can create a MenuButton using a button element, link, or input[type=“submit”]. (

- You visited a page which doesn't exist, causing this page to exist. This page thanks + You visited a page which doesn’t exist, causing this page to exist. This page thanks you for summoning it into existence from the raw fabric of reality, but it thinks you may find another page more interesting. Might it suggest - the - home page - ? + the {( + + home page + + )}?

diff --git a/ui_framework/doc_site/src/views/pager/pager_buttons.js b/ui_framework/doc_site/src/views/pager/pager_buttons.js index ba86082f40564..51446d70cf333 100644 --- a/ui_framework/doc_site/src/views/pager/pager_buttons.js +++ b/ui_framework/doc_site/src/views/pager/pager_buttons.js @@ -17,9 +17,9 @@ export class PagerButtons extends React.Component { getPage() { switch (this.state.item) { case 1: - return
I'm Page 1!
; + return
I’m Page 1!
; case 2: - return I'm a button; + return I’m a button; case 3: return
You are at the end
; } diff --git a/ui_framework/doc_site/src/views/popover/popover.js b/ui_framework/doc_site/src/views/popover/popover.js index cf929763b9a07..7e40ccd2fdbf7 100644 --- a/ui_framework/doc_site/src/views/popover/popover.js +++ b/ui_framework/doc_site/src/views/popover/popover.js @@ -41,7 +41,7 @@ export default class extends Component { isOpen={this.state.isPopoverOpen} closePopover={this.closePopover.bind(this)} > -
Popover content that's wider than the default width
+
Popover content that’s wider than the default width
); } diff --git a/ui_framework/doc_site/src/views/popover/popover_anchor_position.js b/ui_framework/doc_site/src/views/popover/popover_anchor_position.js index 12e0617c1ac0e..a5f78f2607c11 100644 --- a/ui_framework/doc_site/src/views/popover/popover_anchor_position.js +++ b/ui_framework/doc_site/src/views/popover/popover_anchor_position.js @@ -46,7 +46,7 @@ export default class extends Component {
+ Popover anchored to the right. )} @@ -61,7 +61,7 @@ export default class extends Component { + Popover anchored to the right. )} diff --git a/ui_framework/doc_site/src/views/popover/popover_body_class_name.js b/ui_framework/doc_site/src/views/popover/popover_body_class_name.js index c5e88f5ac2fc4..bdcf9d31767e0 100644 --- a/ui_framework/doc_site/src/views/popover/popover_body_class_name.js +++ b/ui_framework/doc_site/src/views/popover/popover_body_class_name.js @@ -31,16 +31,16 @@ export default class extends Component { render() { return ( + button={( + Custom class - ) } - isOpen={ this.state.isPopoverOpen } - closePopover={ this.closePopover.bind(this) } + )} + isOpen={this.state.isPopoverOpen} + closePopover={this.closePopover.bind(this)} bodyClassName="yourClassNameHere" > - It's hard to tell but there's a custom class on this element + It’s hard to tell but there’s a custom class on this element ); } diff --git a/ui_framework/doc_site/src/views/table/controlled_table.js b/ui_framework/doc_site/src/views/table/controlled_table.js index 6edeed7f938c0..cbc0ec8848ece 100644 --- a/ui_framework/doc_site/src/views/table/controlled_table.js +++ b/ui_framework/doc_site/src/views/table/controlled_table.js @@ -64,13 +64,13 @@ export class ControlledTable extends React.Component { renderPager() { return ( {} } - onPreviousPage={ () => {} } + startNumber={1} + hasNextPage={true} + hasPreviousPage={false} + endNumber={10} + totalItems={100} + onNextPage={() => {}} + onPreviousPage={() => {}} /> ); } @@ -92,14 +92,14 @@ export class ControlledTable extends React.Component { return ( this.toggleItem(rowData) } + isChecked={this.isItemChecked(rowData)} + onChange={() => this.toggleItem(rowData)} /> { rowData.map((cellData, index) => { const align = index === rowData.length - 1 ? RIGHT_ALIGNMENT : LEFT_ALIGNMENT; return ( - + { cellData } ); @@ -114,7 +114,7 @@ export class ControlledTable extends React.Component { return ( - {} } /> + {}} /> @@ -140,8 +140,8 @@ export class ControlledTable extends React.Component { this.toggleItem('header') } + isChecked={this.isItemChecked('header')} + onChange={() => this.toggleItem('header')} /> Title diff --git a/ui_framework/doc_site/src/views/table/controlled_table_loading_items.js b/ui_framework/doc_site/src/views/table/controlled_table_loading_items.js index f396996d88941..042e3f5249c62 100644 --- a/ui_framework/doc_site/src/views/table/controlled_table_loading_items.js +++ b/ui_framework/doc_site/src/views/table/controlled_table_loading_items.js @@ -19,13 +19,13 @@ export class ControlledTableLoadingItems extends React.Component { getPager() { return ( {} } - onPreviousPage={ () => {} } + startNumber={1} + hasNextPage={true} + hasPreviousPage={false} + endNumber={10} + totalItems={100} + onNextPage={() => {}} + onPreviousPage={() => {}} /> ); } @@ -34,7 +34,7 @@ export class ControlledTableLoadingItems extends React.Component { return ( - {} } /> + {}} /> diff --git a/ui_framework/doc_site/src/views/table/controlled_table_with_empty_prompt.js b/ui_framework/doc_site/src/views/table/controlled_table_with_empty_prompt.js index 5abfd5356712f..0fb4e71863102 100644 --- a/ui_framework/doc_site/src/views/table/controlled_table_with_empty_prompt.js +++ b/ui_framework/doc_site/src/views/table/controlled_table_with_empty_prompt.js @@ -19,13 +19,13 @@ export class ControlledTableWithEmptyPrompt extends React.Component { getPager() { return ( {} } - onPreviousPage={ () => {} } + startNumber={1} + hasNextPage={true} + hasPreviousPage={false} + endNumber={10} + totalItems={100} + onNextPage={() => {}} + onPreviousPage={() => {}} /> ); } @@ -34,7 +34,7 @@ export class ControlledTableWithEmptyPrompt extends React.Component { return ( - {} } /> + {}} /> @@ -59,7 +59,7 @@ export class ControlledTableWithEmptyPrompt extends React.Component { Add Items } + actions={Add Items} message="Uh oh you have no items!" /> diff --git a/ui_framework/doc_site/src/views/table/controlled_table_with_no_items.js b/ui_framework/doc_site/src/views/table/controlled_table_with_no_items.js index 6120839049479..7f9b99bd07d8c 100644 --- a/ui_framework/doc_site/src/views/table/controlled_table_with_no_items.js +++ b/ui_framework/doc_site/src/views/table/controlled_table_with_no_items.js @@ -19,13 +19,13 @@ export class ControlledTableWithNoItems extends React.Component { getPager() { return ( {} } - onPreviousPage={ () => {} } + startNumber={1} + hasNextPage={true} + hasPreviousPage={false} + endNumber={10} + totalItems={100} + onNextPage={() => {}} + onPreviousPage={() => {}} /> ); } @@ -34,7 +34,7 @@ export class ControlledTableWithNoItems extends React.Component { return ( - {} } /> + {}} /> diff --git a/ui_framework/doc_site/src/views/table/fluid_table.js b/ui_framework/doc_site/src/views/table/fluid_table.js index 7d483fdb742d0..7de2f0d4da1f8 100644 --- a/ui_framework/doc_site/src/views/table/fluid_table.js +++ b/ui_framework/doc_site/src/views/table/fluid_table.js @@ -11,7 +11,7 @@ import { export function FluidTable() { return ( - + System diff --git a/ui_framework/doc_site/src/views/table/table_with_menu_buttons.js b/ui_framework/doc_site/src/views/table/table_with_menu_buttons.js index aa8c1addba0e1..cb45e7df798e9 100644 --- a/ui_framework/doc_site/src/views/table/table_with_menu_buttons.js +++ b/ui_framework/doc_site/src/views/table/table_with_menu_buttons.js @@ -48,7 +48,7 @@ export function TableWithMenuButtons() { C - +
); }; diff --git a/ui_framework/src/components/local_nav/local_nav.js b/ui_framework/src/components/local_nav/local_nav.js index 7594f9d4d6ff0..d70e3c24f3d47 100644 --- a/ui_framework/src/components/local_nav/local_nav.js +++ b/ui_framework/src/components/local_nav/local_nav.js @@ -5,7 +5,7 @@ import React from 'react'; export function KuiLocalNav({ className, children, ...rest }) { const classes = classnames('kuiLocalNav', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/local_nav/local_nav.test.js b/ui_framework/src/components/local_nav/local_nav.test.js index 12ab75cabad21..2c1d5b8a9edad 100644 --- a/ui_framework/src/components/local_nav/local_nav.test.js +++ b/ui_framework/src/components/local_nav/local_nav.test.js @@ -5,6 +5,6 @@ import { requiredProps } from '../../test/required_props'; import { KuiLocalNav } from './local_nav'; test('renders KuiLocalNav', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/local_nav/local_nav_row.js b/ui_framework/src/components/local_nav/local_nav_row.js index 806b7223564fc..2d9b577abb3cc 100644 --- a/ui_framework/src/components/local_nav/local_nav_row.js +++ b/ui_framework/src/components/local_nav/local_nav_row.js @@ -7,7 +7,7 @@ export function KuiLocalNavRow({ className, children, isSecondary, ...rest }) { 'kuiLocalNavRow--secondary': isSecondary, }); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/local_nav/local_nav_row.test.js b/ui_framework/src/components/local_nav/local_nav_row.test.js index c0ad465aa8d31..0bd55a22a9fa9 100644 --- a/ui_framework/src/components/local_nav/local_nav_row.test.js +++ b/ui_framework/src/components/local_nav/local_nav_row.test.js @@ -5,13 +5,13 @@ import { requiredProps } from '../../test/required_props'; import { KuiLocalNavRow } from './local_nav_row'; test('renders KuiLocalNavRow', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); describe('property isSecondary', () => { test('renders the secondary modifier', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); }); diff --git a/ui_framework/src/components/local_nav/local_nav_row_section.js b/ui_framework/src/components/local_nav/local_nav_row_section.js index 364d8acd40736..541a60d9f57c1 100644 --- a/ui_framework/src/components/local_nav/local_nav_row_section.js +++ b/ui_framework/src/components/local_nav/local_nav_row_section.js @@ -5,7 +5,7 @@ import React from 'react'; export function KuiLocalNavRowSection({ className, children, ...rest }) { const classes = classnames('kuiLocalNavRow__section', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/local_nav/local_nav_row_section.test.js b/ui_framework/src/components/local_nav/local_nav_row_section.test.js index 35235dc017bd9..dbc9509177127 100644 --- a/ui_framework/src/components/local_nav/local_nav_row_section.test.js +++ b/ui_framework/src/components/local_nav/local_nav_row_section.test.js @@ -5,6 +5,6 @@ import { requiredProps } from '../../test/required_props'; import { KuiLocalNavRowSection } from './local_nav_row_section'; test('renders KuiLocalNavRowSection', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/local_nav/local_tab.js b/ui_framework/src/components/local_nav/local_tab.js index e4040367e3e34..823bf4eabbb44 100644 --- a/ui_framework/src/components/local_nav/local_tab.js +++ b/ui_framework/src/components/local_nav/local_tab.js @@ -8,7 +8,7 @@ export function KuiLocalTab({ className, children, isDisabled, isSelected, ...re 'kuiLocalTab-isSelected': isSelected, }); return ( - + { children } ); diff --git a/ui_framework/src/components/local_nav/local_tab.test.js b/ui_framework/src/components/local_nav/local_tab.test.js index 0a34baab37296..3dc458768d155 100644 --- a/ui_framework/src/components/local_nav/local_tab.test.js +++ b/ui_framework/src/components/local_nav/local_tab.test.js @@ -5,20 +5,20 @@ import { requiredProps } from '../../test/required_props'; import { KuiLocalTab } from './local_tab'; test('renders KuiLocalTab', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); describe('property isSelected', () => { test('renders the isSelected modifier', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); }); describe('property isDisabled', () => { test('renders the isDisabled modifier', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); }); diff --git a/ui_framework/src/components/local_nav/local_tabs.js b/ui_framework/src/components/local_nav/local_tabs.js index 1aaa458d5688f..f65f5fe905215 100644 --- a/ui_framework/src/components/local_nav/local_tabs.js +++ b/ui_framework/src/components/local_nav/local_tabs.js @@ -5,7 +5,7 @@ import React from 'react'; export function KuiLocalTabs({ className, children, ...rest }) { const classes = classnames('kuiLocalTabs', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/local_nav/local_tabs.test.js b/ui_framework/src/components/local_nav/local_tabs.test.js index ffc70aeba75b6..094495ad0f897 100644 --- a/ui_framework/src/components/local_nav/local_tabs.test.js +++ b/ui_framework/src/components/local_nav/local_tabs.test.js @@ -5,6 +5,6 @@ import { requiredProps } from '../../test/required_props'; import { KuiLocalTabs } from './local_tabs'; test('renders KuiLocalTabs', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/local_nav/local_title.js b/ui_framework/src/components/local_nav/local_title.js index 1d1eb53406f35..0f40d5c198198 100644 --- a/ui_framework/src/components/local_nav/local_title.js +++ b/ui_framework/src/components/local_nav/local_title.js @@ -5,7 +5,7 @@ import React from 'react'; export function KuiLocalTitle({ className, children, ...rest }) { const classes = classnames('kuiLocalTitle', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/local_nav/local_title.test.js b/ui_framework/src/components/local_nav/local_title.test.js index f393653afd3a9..17d3877f4cadf 100644 --- a/ui_framework/src/components/local_nav/local_title.test.js +++ b/ui_framework/src/components/local_nav/local_title.test.js @@ -5,6 +5,6 @@ import { requiredProps } from '../../test/required_props'; import { KuiLocalTitle } from './local_title'; test('renders KuiLocalTitle', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/menu/menu.test.js b/ui_framework/src/components/menu/menu.test.js index 170003121cdd4..265703fed390e 100644 --- a/ui_framework/src/components/menu/menu.test.js +++ b/ui_framework/src/components/menu/menu.test.js @@ -7,7 +7,7 @@ import { } from './menu'; test('renders KuiMenu', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/menu/menu_item.test.js b/ui_framework/src/components/menu/menu_item.test.js index 7ba271f5e057d..1b08117b9c2b3 100644 --- a/ui_framework/src/components/menu/menu_item.test.js +++ b/ui_framework/src/components/menu/menu_item.test.js @@ -7,6 +7,6 @@ import { } from './menu_item'; test('renders KuiMenuItem', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/modal/confirm_modal.js b/ui_framework/src/components/modal/confirm_modal.js index 6655f3050a7f5..f1a04c6c761d5 100644 --- a/ui_framework/src/components/modal/confirm_modal.js +++ b/ui_framework/src/components/modal/confirm_modal.js @@ -42,10 +42,10 @@ export function KuiConfirmModal({ return ( { title ? @@ -65,17 +65,17 @@ export function KuiConfirmModal({ {cancelButtonText} {confirmButtonText} diff --git a/ui_framework/src/components/modal/confirm_modal.test.js b/ui_framework/src/components/modal/confirm_modal.test.js index 216074d7ab2bd..2c14f19493622 100644 --- a/ui_framework/src/components/modal/confirm_modal.test.js +++ b/ui_framework/src/components/modal/confirm_modal.test.js @@ -24,7 +24,7 @@ test('renders KuiConfirmModal', () => { onConfirm={onConfirm} cancelButtonText="Cancel Button Text" confirmButtonText="Confirm Button Text" - { ...requiredProps } + {...requiredProps} />); expect(component).toMatchSnapshot(); }); @@ -37,7 +37,7 @@ test('onConfirm', () => { onConfirm={onConfirm} cancelButtonText="Cancel" confirmButtonText="Confirm" - { ...requiredProps } + {...requiredProps} />); component.find('[data-test-subj="confirmModalConfirmButton"]').simulate('click'); sinon.assert.calledOnce(onConfirm); @@ -53,7 +53,7 @@ describe('onCancel', () => { onConfirm={onConfirm} cancelButtonText="Cancel" confirmButtonText="Confirm" - { ...requiredProps } + {...requiredProps} />); component.find('[data-test-subj="confirmModalCancelButton"]').simulate('click'); sinon.assert.notCalled(onConfirm); @@ -68,7 +68,7 @@ describe('onCancel', () => { onConfirm={onConfirm} cancelButtonText="Cancel" confirmButtonText="Confirm" - { ...requiredProps } + {...requiredProps} />); component.simulate('keydown', { keyCode: 27 }); sinon.assert.notCalled(onConfirm); @@ -85,8 +85,8 @@ describe('defaultFocusedButton', () => { onConfirm={onConfirm} cancelButtonText="Cancel" confirmButtonText="Confirm" - defaultFocusedButton={ CANCEL_BUTTON } - { ...requiredProps } + defaultFocusedButton={CANCEL_BUTTON} + {...requiredProps} />); const button = component.find('[data-test-subj="confirmModalCancelButton"]').getDOMNode(); expect(document.activeElement).toEqual(button); @@ -100,8 +100,8 @@ describe('defaultFocusedButton', () => { onConfirm={onConfirm} cancelButtonText="Cancel" confirmButtonText="Confirm" - defaultFocusedButton={ CONFIRM_BUTTON } - { ...requiredProps } + defaultFocusedButton={CONFIRM_BUTTON} + {...requiredProps} />); const button = component.find('[data-test-subj="confirmModalConfirmButton"]').getDOMNode(); expect(document.activeElement).toEqual(button); @@ -115,7 +115,7 @@ describe('defaultFocusedButton', () => { onConfirm={onConfirm} cancelButtonText="Cancel" confirmButtonText="Confirm" - { ...requiredProps } + {...requiredProps} />); const button = component.find('[data-test-subj="confirmModalConfirmButton"]').getDOMNode(); expect(document.activeElement).toEqual(button); diff --git a/ui_framework/src/components/modal/modal.js b/ui_framework/src/components/modal/modal.js index 8ea7a08b96869..da89951ebae90 100644 --- a/ui_framework/src/components/modal/modal.js +++ b/ui_framework/src/components/modal/modal.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; export function KuiModal({ className, children, ...rest }) { const classes = classnames('kuiModal', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/modal/modal.test.js b/ui_framework/src/components/modal/modal.test.js index 4a393c27a008d..948c7da07f99c 100644 --- a/ui_framework/src/components/modal/modal.test.js +++ b/ui_framework/src/components/modal/modal.test.js @@ -7,6 +7,6 @@ import { } from './modal'; test('renders KuiModal', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/modal/modal_body.js b/ui_framework/src/components/modal/modal_body.js index efd954b834f12..e43d7ab5af189 100644 --- a/ui_framework/src/components/modal/modal_body.js +++ b/ui_framework/src/components/modal/modal_body.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; export function KuiModalBody({ className, children, ...rest }) { const classes = classnames('kuiModalBody', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/modal/modal_body.test.js b/ui_framework/src/components/modal/modal_body.test.js index b8b4d8e02d802..985b2cdb5a2b4 100644 --- a/ui_framework/src/components/modal/modal_body.test.js +++ b/ui_framework/src/components/modal/modal_body.test.js @@ -7,6 +7,6 @@ import { } from './modal_body'; test('renders KuiModalBody', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/modal/modal_body_text.js b/ui_framework/src/components/modal/modal_body_text.js index 197bf7f0a7975..55efdc723fa88 100644 --- a/ui_framework/src/components/modal/modal_body_text.js +++ b/ui_framework/src/components/modal/modal_body_text.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; export function KuiModalBodyText({ className, children, ...rest }) { const classes = classnames('kuiModalBodyText', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/modal/modal_body_text.test.js b/ui_framework/src/components/modal/modal_body_text.test.js index f71a5f6ed0bee..a8d6af9df7352 100644 --- a/ui_framework/src/components/modal/modal_body_text.test.js +++ b/ui_framework/src/components/modal/modal_body_text.test.js @@ -7,6 +7,6 @@ import { } from './modal_body_text'; test('renders KuiModalBodyText', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/modal/modal_footer.js b/ui_framework/src/components/modal/modal_footer.js index a62ba3dccef2e..b91240efe570d 100644 --- a/ui_framework/src/components/modal/modal_footer.js +++ b/ui_framework/src/components/modal/modal_footer.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; export function KuiModalFooter({ className, children, ...rest }) { const classes = classnames('kuiModalFooter', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/modal/modal_footer.test.js b/ui_framework/src/components/modal/modal_footer.test.js index ab80fa6b14079..9a54e5d8cae5f 100644 --- a/ui_framework/src/components/modal/modal_footer.test.js +++ b/ui_framework/src/components/modal/modal_footer.test.js @@ -7,6 +7,6 @@ import { } from './modal_footer'; test('renders KuiModalFooter', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/modal/modal_header.js b/ui_framework/src/components/modal/modal_header.js index c6ccc30e2e110..7aa74a1cff9f2 100644 --- a/ui_framework/src/components/modal/modal_header.js +++ b/ui_framework/src/components/modal/modal_header.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; export function KuiModalHeader({ className, children, ...rest }) { const classes = classnames('kuiModalHeader', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/modal/modal_header.test.js b/ui_framework/src/components/modal/modal_header.test.js index 0caaaa07ae896..f3a603bcb2567 100644 --- a/ui_framework/src/components/modal/modal_header.test.js +++ b/ui_framework/src/components/modal/modal_header.test.js @@ -7,6 +7,6 @@ import { } from './modal_header'; test('renders KuiModalHeader', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/modal/modal_header_title.js b/ui_framework/src/components/modal/modal_header_title.js index a4a237ad8f1d3..5baa3bd0be1eb 100644 --- a/ui_framework/src/components/modal/modal_header_title.js +++ b/ui_framework/src/components/modal/modal_header_title.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; export function KuiModalHeaderTitle({ className, children, ...rest }) { const classes = classnames('kuiModalHeader__title', className); return ( -
+
{ children }
); diff --git a/ui_framework/src/components/modal/modal_header_title.test.js b/ui_framework/src/components/modal/modal_header_title.test.js index 35fbbca89c95c..7f0632ad5b60b 100644 --- a/ui_framework/src/components/modal/modal_header_title.test.js +++ b/ui_framework/src/components/modal/modal_header_title.test.js @@ -7,6 +7,6 @@ import { } from './modal_header_title'; test('renders KuiModalHeaderTitle', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/modal/modal_overlay.js b/ui_framework/src/components/modal/modal_overlay.js index 34334e1a75072..4467bdee3667f 100644 --- a/ui_framework/src/components/modal/modal_overlay.js +++ b/ui_framework/src/components/modal/modal_overlay.js @@ -6,8 +6,8 @@ export function KuiModalOverlay({ className, ...rest }) { const classes = classnames('kuiModalOverlay', className); return (
); } diff --git a/ui_framework/src/components/modal/modal_overlay.test.js b/ui_framework/src/components/modal/modal_overlay.test.js index 94f5015de662c..0600b5a45187a 100644 --- a/ui_framework/src/components/modal/modal_overlay.test.js +++ b/ui_framework/src/components/modal/modal_overlay.test.js @@ -7,6 +7,6 @@ import { } from './modal_overlay'; test('renders KuiModalOverlay', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/pager/pager.js b/ui_framework/src/components/pager/pager.js index b96d399659dfc..55d6ab8f39f64 100644 --- a/ui_framework/src/components/pager/pager.js +++ b/ui_framework/src/components/pager/pager.js @@ -16,7 +16,7 @@ export function KuiPager({ }) { const classes = classNames('kuiPager', className); return ( -
+
{startNumber}–{endNumber} of {totalItems}
{ (startNumber === 1 && endNumber === totalItems) diff --git a/ui_framework/src/components/pager/pager.test.js b/ui_framework/src/components/pager/pager.test.js index f588e709cc9c6..ab05d73e92d7e 100644 --- a/ui_framework/src/components/pager/pager.test.js +++ b/ui_framework/src/components/pager/pager.test.js @@ -24,7 +24,7 @@ test('renders KuiPager', () => { startNumber={1} endNumber={10} totalItems={20} - { ...requiredProps } + {...requiredProps} />); expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/pager/pager_button_group.js b/ui_framework/src/components/pager/pager_button_group.js index daaaada470385..6c105e3114096 100644 --- a/ui_framework/src/components/pager/pager_button_group.js +++ b/ui_framework/src/components/pager/pager_button_group.js @@ -4,7 +4,7 @@ import { KuiButton, KuiButtonIcon, KuiButtonGroup } from '../button'; export function KuiPagerButtonGroup({ className, onPrevious, onNext, hasNext, hasPrevious, ...rest }) { return ( - + { onPrevious={onPrevious} hasNext={true} hasPrevious={true} - { ...requiredProps } + {...requiredProps} />); expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/popover/popover.js b/ui_framework/src/components/popover/popover.js index c8dbfc21b7673..ce55ab06d9379 100644 --- a/ui_framework/src/components/popover/popover.js +++ b/ui_framework/src/components/popover/popover.js @@ -67,16 +67,16 @@ export class KuiPopover extends Component { const bodyClasses = classNames('kuiPopover__body', bodyClassName); const body = ( -
+
{ children }
); return (
{ button } { body } diff --git a/ui_framework/src/components/popover/popover.test.js b/ui_framework/src/components/popover/popover.test.js index 0476d6b36f9d3..39f20fccc002a 100644 --- a/ui_framework/src/components/popover/popover.test.js +++ b/ui_framework/src/components/popover/popover.test.js @@ -10,7 +10,7 @@ describe('KuiPopover', () => { } closePopover={() => {}} - { ...requiredProps } + {...requiredProps} /> ); diff --git a/ui_framework/src/components/table/controlled_table.test.js b/ui_framework/src/components/table/controlled_table.test.js index e8f546858f82e..579549b85e2cd 100644 --- a/ui_framework/src/components/table/controlled_table.test.js +++ b/ui_framework/src/components/table/controlled_table.test.js @@ -7,6 +7,6 @@ import { } from './controlled_table'; test('renders KuiToolControlledTable', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/table/table.test.js b/ui_framework/src/components/table/table.test.js index 253239d20e43f..4a384bef13547 100644 --- a/ui_framework/src/components/table/table.test.js +++ b/ui_framework/src/components/table/table.test.js @@ -11,7 +11,7 @@ import { KuiTableHeaderCell } from './table_header_cell'; test('renders KuiTable', () => { const component = ( - + Hi Title diff --git a/ui_framework/src/components/table/table_body.js b/ui_framework/src/components/table/table_body.js index 40588e57efef5..79c8b285b761a 100644 --- a/ui_framework/src/components/table/table_body.js +++ b/ui_framework/src/components/table/table_body.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; export const KuiTableBody = ({ children, className, ...rest }) => { return ( - + { children } ); diff --git a/ui_framework/src/components/table/table_header.js b/ui_framework/src/components/table/table_header.js index cb4fa51d82725..e48b2af7694ab 100644 --- a/ui_framework/src/components/table/table_header.js +++ b/ui_framework/src/components/table/table_header.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; export const KuiTableHeader = ({ children, className, ...rest }) => { return ( - + { children } ); diff --git a/ui_framework/src/components/table/table_header_cell.test.js b/ui_framework/src/components/table/table_header_cell.test.js index ec39c1bacceba..44e52ace91488 100644 --- a/ui_framework/src/components/table/table_header_cell.test.js +++ b/ui_framework/src/components/table/table_header_cell.test.js @@ -7,6 +7,6 @@ import { } from './table_header_cell'; test('renders KuiTableHeaderCell', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/table/table_header_check_box_cell.js b/ui_framework/src/components/table/table_header_check_box_cell.js index 65c36d5c44d44..84d12b0e3034f 100644 --- a/ui_framework/src/components/table/table_header_check_box_cell.js +++ b/ui_framework/src/components/table/table_header_check_box_cell.js @@ -7,14 +7,14 @@ export const KuiTableHeaderCheckBoxCell = ({ onChange, isChecked, className, ... const classes = classNames('kuiTableHeaderCell--checkBox', className); return ( ); diff --git a/ui_framework/src/components/table/table_header_check_box_cell.test.js b/ui_framework/src/components/table/table_header_check_box_cell.test.js index 44930ddba01ed..e998beabecb48 100644 --- a/ui_framework/src/components/table/table_header_check_box_cell.test.js +++ b/ui_framework/src/components/table/table_header_check_box_cell.test.js @@ -7,6 +7,6 @@ import { } from './table_header_check_box_cell'; test('renders KuiTableHeaderCheckBoxCell', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/table/table_info.test.js b/ui_framework/src/components/table/table_info.test.js index 59d7890f0afca..4c5eb34c7265e 100644 --- a/ui_framework/src/components/table/table_info.test.js +++ b/ui_framework/src/components/table/table_info.test.js @@ -7,6 +7,6 @@ import { } from './table_info'; test('renders KuiTableInfo', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/table/table_row.test.js b/ui_framework/src/components/table/table_row.test.js index 5732b4d404ea7..abc210710418c 100644 --- a/ui_framework/src/components/table/table_row.test.js +++ b/ui_framework/src/components/table/table_row.test.js @@ -12,7 +12,7 @@ import { test('renders KuiTableRow', () => { const component = ( - + hi ); diff --git a/ui_framework/src/components/table/table_row_cell.test.js b/ui_framework/src/components/table/table_row_cell.test.js index 95928873a681f..117a3e8ef1336 100644 --- a/ui_framework/src/components/table/table_row_cell.test.js +++ b/ui_framework/src/components/table/table_row_cell.test.js @@ -7,6 +7,6 @@ import { } from './table_row_cell'; test('renders KuiTableRowCell', () => { - const component = ; + const component = ; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/table/table_row_check_box_cell.js b/ui_framework/src/components/table/table_row_check_box_cell.js index 8d301478ac671..49bca782cd4ae 100644 --- a/ui_framework/src/components/table/table_row_check_box_cell.js +++ b/ui_framework/src/components/table/table_row_check_box_cell.js @@ -7,14 +7,14 @@ export const KuiTableRowCheckBoxCell = ({ onChange, isChecked, className, ...res const classes = classNames('kuiTableRowCell--checkBox', className); return ( ); diff --git a/ui_framework/src/components/table/table_row_check_box_cell.test.js b/ui_framework/src/components/table/table_row_check_box_cell.test.js index 632ce05924337..3429b36fcf385 100644 --- a/ui_framework/src/components/table/table_row_check_box_cell.test.js +++ b/ui_framework/src/components/table/table_row_check_box_cell.test.js @@ -7,6 +7,6 @@ import { } from './table_row_check_box_cell'; test('renders KuiTableRowCheckBoxCell', () => { - const component = ; + const component = ; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/tabs/tab.test.js b/ui_framework/src/components/tabs/tab.test.js index e820d148755b5..66311c4f90b8e 100644 --- a/ui_framework/src/components/tabs/tab.test.js +++ b/ui_framework/src/components/tabs/tab.test.js @@ -9,12 +9,12 @@ import { describe('KuiTab', () => { test('renders', () => { - const component = {}} { ...requiredProps }>children; + const component = {}} {...requiredProps}>children; expect(render(component)).toMatchSnapshot(); }); test('renders isSelected', () => { - const component = {}} isSelected { ...requiredProps }>children; + const component = {}} isSelected {...requiredProps}>children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/tabs/tabs.test.js b/ui_framework/src/components/tabs/tabs.test.js index 24e934021a43d..947bd1394da44 100644 --- a/ui_framework/src/components/tabs/tabs.test.js +++ b/ui_framework/src/components/tabs/tabs.test.js @@ -9,7 +9,7 @@ import { describe('KuiTabs', () => { test('renders', () => { const component = ( - + ); expect(render(component)).toMatchSnapshot(); diff --git a/ui_framework/src/components/tool_bar/tool_bar.test.js b/ui_framework/src/components/tool_bar/tool_bar.test.js index 5fc1eb6d38227..bb6d745573683 100644 --- a/ui_framework/src/components/tool_bar/tool_bar.test.js +++ b/ui_framework/src/components/tool_bar/tool_bar.test.js @@ -7,7 +7,7 @@ import { } from './tool_bar'; test('renders KuiToolBar', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/tool_bar/tool_bar_footer.test.js b/ui_framework/src/components/tool_bar/tool_bar_footer.test.js index c48ee7fcdcac0..67c5d6132115e 100644 --- a/ui_framework/src/components/tool_bar/tool_bar_footer.test.js +++ b/ui_framework/src/components/tool_bar/tool_bar_footer.test.js @@ -7,6 +7,6 @@ import { } from './tool_bar_footer'; test('renders KuiToolBarFooter', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/tool_bar/tool_bar_footer_section.test.js b/ui_framework/src/components/tool_bar/tool_bar_footer_section.test.js index 10008b58e0399..f41d6566cb75e 100644 --- a/ui_framework/src/components/tool_bar/tool_bar_footer_section.test.js +++ b/ui_framework/src/components/tool_bar/tool_bar_footer_section.test.js @@ -7,6 +7,6 @@ import { } from './tool_bar_footer_section'; test('renders KuiToolBarFooterSection', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/tool_bar/tool_bar_search_box.js b/ui_framework/src/components/tool_bar/tool_bar_search_box.js index 36803651522f5..41bf0e9925890 100644 --- a/ui_framework/src/components/tool_bar/tool_bar_search_box.js +++ b/ui_framework/src/components/tool_bar/tool_bar_search_box.js @@ -8,18 +8,18 @@ export function KuiToolBarSearchBox({ filter, onFilter, placeholder, className, const classes = classNames('kuiToolBarSearch', className); return (
diff --git a/ui_framework/src/components/tool_bar/tool_bar_search_box.test.js b/ui_framework/src/components/tool_bar/tool_bar_search_box.test.js index 17685a506e1da..7f54bb3bb4e69 100644 --- a/ui_framework/src/components/tool_bar/tool_bar_search_box.test.js +++ b/ui_framework/src/components/tool_bar/tool_bar_search_box.test.js @@ -10,13 +10,13 @@ import { const onFilter = sinon.spy(); test('renders KuiToolBarSearchBox', () => { - const component = ; + const component = ; expect(render(component)).toMatchSnapshot(); }); describe('onFilter', () => { test('is called on change event, with the value entered', () => { - const searchBox = mount(); + const searchBox = mount(); onFilter.reset(); const event = { target: { value: 'a' } }; searchBox.find('input').simulate('change', event); diff --git a/ui_framework/src/components/tool_bar/tool_bar_section.test.js b/ui_framework/src/components/tool_bar/tool_bar_section.test.js index 8a6e92e038f11..7a98f905d9c22 100644 --- a/ui_framework/src/components/tool_bar/tool_bar_section.test.js +++ b/ui_framework/src/components/tool_bar/tool_bar_section.test.js @@ -7,6 +7,6 @@ import { } from './tool_bar_section'; test('renders KuiToolBarSection', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/tool_bar/tool_bar_text.test.js b/ui_framework/src/components/tool_bar/tool_bar_text.test.js index c8e697c4a4c0a..b55b49b2be893 100644 --- a/ui_framework/src/components/tool_bar/tool_bar_text.test.js +++ b/ui_framework/src/components/tool_bar/tool_bar_text.test.js @@ -7,7 +7,7 @@ import { } from './tool_bar_text'; test('renders KuiToolBarText', () => { - const component = children; + const component = children; expect(render(component)).toMatchSnapshot(); }); diff --git a/ui_framework/src/components/typography/typography.test.js b/ui_framework/src/components/typography/typography.test.js index 4e2d0959e54f0..d0fd054cba873 100644 --- a/ui_framework/src/components/typography/typography.test.js +++ b/ui_framework/src/components/typography/typography.test.js @@ -11,7 +11,7 @@ import { describe('KuiTitle', () => { test('is rendered', () => { const component = render( - +

Hello

); @@ -39,7 +39,7 @@ describe('KuiTitle', () => { describe('KuiText', () => { test('is rendered', () => { const component = render( - +

Hello

); From dfc6408c2575a6440fb5c118bb47f11d15864262 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Fri, 11 Aug 2017 13:39:31 -0700 Subject: [PATCH 109/165] [DOCS] Use shared versions file for doc builds (#13277) * [DOCS] Use shared versions file for doc builds * [DOCS] Address feedback in index-shared1.asciidoc --- docs/index-shared1.asciidoc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/docs/index-shared1.asciidoc b/docs/index-shared1.asciidoc index 173c755043940..266049a581150 100644 --- a/docs/index-shared1.asciidoc +++ b/docs/index-shared1.asciidoc @@ -1,11 +1,5 @@ -////////// -release-state can be: released | prerelease | unreleased -////////// -:release-state: unreleased -:version: 7.0.0-alpha1 -:major-version: 7.x -:branch: master +include::{asciidoc-dir}/../../shared/versions.asciidoc[] :docker-image: docker.elastic.co/kibana/kibana:{version} :repo: https://github.com/elastic/kibana/ From 2fbfa531c7526c48f965b46c9ce1efe0127f556a Mon Sep 17 00:00:00 2001 From: Court Ewing Date: Sat, 12 Aug 2017 10:28:21 -0400 Subject: [PATCH 110/165] github: PR template checklist in a comment The checklist of items in the PR description should be in a comment so you don't have to manually remove them on every pull request. --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5ff8531861a06..e7ca77ccc22f0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,10 +4,10 @@ are a few simple things to check before submitting your pull request that can help with the review process. You should delete these items from your submission, but they are here to help bring them to your attention. ---> - Have you signed the [contributor license agreement](https://www.elastic.co/contributor-agreement)? - Have you followed the [contributor guidelines](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md)? - If submitting code, have you included unit tests that cover the changes? - If submitting code, have you tested and built your code locally prior to submission with `npm test && npm run build`? - If submitting code, is your pull request against master? Unless there is a good reason otherwise, we prefer pull requests against master and will backport as needed. +--> From 99f1c65c4b937b3c8a544b2794baa95faf475987 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Mon, 14 Aug 2017 07:42:06 +0200 Subject: [PATCH 111/165] Initial version of accessibility guide (#13390) * Initial version of a11y guide * Move a11y content from HTML guide to a11y guide * Add PR feedback * Add PRs feedback * Add more roles * Refactor labeling elements section * Rename "labeling elements" -> "naming elements" * Use span instead of i for icon examples * Correct typo --- STYLEGUIDE.md | 1 + style_guides/accessibility_guide.md | 230 ++++++++++++++++++++++++++++ style_guides/html_style_guide.md | 50 ------ 3 files changed, 231 insertions(+), 50 deletions(-) create mode 100644 style_guides/accessibility_guide.md diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md index f9108ba16797b..5064899781a9f 100644 --- a/STYLEGUIDE.md +++ b/STYLEGUIDE.md @@ -11,6 +11,7 @@ recommended for the development of all Kibana plugins. - [HTML](style_guides/html_style_guide.md) - [API](style_guides/api_style_guide.md) - [Architecture](style_guides/architecture_style_guide.md) +- [Accessibility](style_guides/acecssibility_guide.md) ## Filenames diff --git a/style_guides/accessibility_guide.md b/style_guides/accessibility_guide.md new file mode 100644 index 0000000000000..2ccc5c9f7ad69 --- /dev/null +++ b/style_guides/accessibility_guide.md @@ -0,0 +1,230 @@ +# Accessibility (A11Y) Guide + +This document provides some technical guidelines how to prevent several common +accessibility issues. + +## Naming elements + +### `aria-label` and `aria-labelledby` + +Every element on a page will have a name, that is read out to an assistive technology +like a screen reader. This will for most elements be the content of the element. +For form elements it will be the content of the assosciated `
+
diff --git a/src/ui/public/doc_table/__tests__/lib/rows_headers.js b/src/ui/public/doc_table/__tests__/lib/rows_headers.js index 0ba965cc8fa33..bb117f355ecf5 100644 --- a/src/ui/public/doc_table/__tests__/lib/rows_headers.js +++ b/src/ui/public/doc_table/__tests__/lib/rows_headers.js @@ -120,6 +120,22 @@ describe('Doc Table', function () { columnTests('[data-test-subj~="docTableHeaderField"]', $elem); }); + describe('sorting button', function () { + + beforeEach(function () { + $parentScope.columns = ['bytes', '_source']; + $elem.scope().$digest(); + }); + + it('should show for sortable columns', function () { + expect($elem.find(`[data-test-subj="docTableHeaderFieldSort_bytes"]`).length).to.be(1); + }); + + it('should not be shown for unsortable columns', function () { + expect($elem.find(`[data-test-subj="docTableHeaderFieldSort__source"]`).length).to.be(0); + }); + }); + describe('cycleSortOrder function', function () { it('should exist', function () { expect($scope.cycleSortOrder).to.be.a(Function); diff --git a/src/ui/public/doc_table/components/table_header.html b/src/ui/public/doc_table/components/table_header.html index 3d14a7e08b9ff..0c87931e1ea3a 100644 --- a/src/ui/public/doc_table/components/table_header.html +++ b/src/ui/public/doc_table/components/table_header.html @@ -25,8 +25,9 @@ {{name | shortDots}} +
+
+ +
    +
  • Apply these filters?
  • +
  • {{ filter.meta.key }}: {{ filter.meta.value }}
  • +
  • Change time to: {{changeTimeFilter.meta.value}}
  • +
  • +
    + - -
    -
  • -
- -
- -
- + +
+ + + +