From 7e20835f75682de5aeb43cfa267e2e9a87e71f41 Mon Sep 17 00:00:00 2001 From: Joel Griffith Date: Wed, 9 Jan 2019 10:36:35 -0800 Subject: [PATCH 01/21] Reporting: Better job statuses when processing (#26930) * Revealing kibana instance info in report info --- .../public/components/report_info_button.tsx | 10 +++++- .../public/components/report_listing.tsx | 32 ++++++++++++------- .../reporting/public/lib/job_queue_client.ts | 2 ++ .../reporting/server/lib/create_workers.js | 7 +++- .../lib/esqueue/helpers/create_index.js | 4 ++- .../reporting/server/lib/esqueue/worker.js | 4 +++ 6 files changed, 44 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/reporting/public/components/report_info_button.tsx b/x-pack/plugins/reporting/public/components/report_info_button.tsx index 56ad3f927498..2e60a49148ef 100644 --- a/x-pack/plugins/reporting/public/components/report_info_button.tsx +++ b/x-pack/plugins/reporting/public/components/report_info_button.tsx @@ -15,7 +15,7 @@ import { EuiText, EuiTitle, } from '@elastic/eui'; -import { get } from 'lodash'; +import { get, has } from 'lodash'; import React, { Component, Fragment } from 'react'; import { USES_HEADLESS_JOB_TYPES } from '../../common/constants'; import { JobInfo, jobQueueClient } from '../lib/job_queue_client'; @@ -76,6 +76,10 @@ export class ReportInfoButton extends Component { } const jobType = get(info, 'jobtype', NA); + const processedBy = + has(info, 'kibana_name') && has(info, 'kibana_id') + ? `${info.kibana_name} (${info.kibana_id})` + : UNKNOWN; // TODO queue method (clicked UI, watcher, etc) const jobInfoParts = { @@ -96,6 +100,10 @@ export class ReportInfoButton extends Component { title: 'Completed At', description: get(info, 'completed_at', NA), }, + { + title: 'Processed By', + description: processedBy, + }, { title: 'Browser Timezone', description: get(info, 'payload.browserTimezone', NA), diff --git a/x-pack/plugins/reporting/public/components/report_listing.tsx b/x-pack/plugins/reporting/public/components/report_listing.tsx index 449785a43a71..dabcea42c983 100644 --- a/x-pack/plugins/reporting/public/components/report_listing.tsx +++ b/x-pack/plugins/reporting/public/components/report_listing.tsx @@ -45,6 +45,8 @@ interface Job { status: string; statusLabel: string; max_size_reached: boolean; + attempts: number; + max_attempts: number; } interface Props { @@ -66,31 +68,31 @@ const jobStatusLabelsMap = new Map([ [ JobStatuses.PENDING, i18n.translate('xpack.reporting.jobStatuses.pendingText', { - defaultMessage: 'pending', + defaultMessage: 'Pending', }), ], [ JobStatuses.PROCESSING, i18n.translate('xpack.reporting.jobStatuses.processingText', { - defaultMessage: 'processing', + defaultMessage: 'Processing', }), ], [ JobStatuses.COMPLETED, i18n.translate('xpack.reporting.jobStatuses.completedText', { - defaultMessage: 'completed', + defaultMessage: 'Completed', }), ], [ JobStatuses.FAILED, i18n.translate('xpack.reporting.jobStatuses.failedText', { - defaultMessage: 'failed', + defaultMessage: 'Failed', }), ], [ JobStatuses.CANCELLED, i18n.translate('xpack.reporting.jobStatuses.cancelledText', { - defaultMessage: 'cancelled', + defaultMessage: 'Cancelled', }), ], ]); @@ -206,7 +208,7 @@ class ReportListingUi extends Component {
); @@ -218,7 +220,7 @@ class ReportListingUi extends Component { ); @@ -234,7 +236,11 @@ class ReportListingUi extends Component { statusTimestamp = this.formatDate(record.completed_at); } - const statusLabel = jobStatusLabelsMap.get(status as JobStatuses) || status; + let statusLabel = jobStatusLabelsMap.get(status as JobStatuses) || status; + + if (status === JobStatuses.PROCESSING) { + statusLabel = statusLabel + ` (attempt ${record.attempts} of ${record.max_attempts})`; + } if (statusTimestamp) { return ( @@ -407,8 +413,8 @@ class ReportListingUi extends Component { this.setState({ isLoading: false, total, - jobs: jobs.map((job: JobQueueEntry) => { - return { + jobs: jobs.map( + (job: JobQueueEntry): Job => ({ id: job._id, type: job._source.jobtype, object_type: job._source.payload.type, @@ -421,8 +427,10 @@ class ReportListingUi extends Component { statusLabel: jobStatusLabelsMap.get(job._source.status as JobStatuses) || job._source.status, max_size_reached: job._source.output ? job._source.output.max_size_reached : false, - }; - }), + attempts: job._source.attempts, + max_attempts: job._source.max_attempts, + }) + ), }); } }; diff --git a/x-pack/plugins/reporting/public/lib/job_queue_client.ts b/x-pack/plugins/reporting/public/lib/job_queue_client.ts index ca5d21dccfb1..173a4e31cfef 100644 --- a/x-pack/plugins/reporting/public/lib/job_queue_client.ts +++ b/x-pack/plugins/reporting/public/lib/job_queue_client.ts @@ -21,6 +21,8 @@ export interface JobContent { } export interface JobInfo { + kibana_name: string; + kibana_id: string; browser_type: string; created_at: string; priority: number; diff --git a/x-pack/plugins/reporting/server/lib/create_workers.js b/x-pack/plugins/reporting/server/lib/create_workers.js index feaf825a3390..198ea7bcb63a 100644 --- a/x-pack/plugins/reporting/server/lib/create_workers.js +++ b/x-pack/plugins/reporting/server/lib/create_workers.js @@ -8,7 +8,10 @@ import { events as esqueueEvents } from './esqueue'; import { oncePerServer } from './once_per_server'; function createWorkersFn(server) { - const queueConfig = server.config().get('xpack.reporting.queue'); + const config = server.config(); + const queueConfig = config.get('xpack.reporting.queue'); + const kibanaName = config.get('server.name'); + const kibanaId = config.get('server.uuid'); const exportTypesRegistry = server.plugins.reporting.exportTypesRegistry; // Once more document types are added, this will need to be passed in @@ -25,6 +28,8 @@ function createWorkersFn(server) { return executeJob(payload, cancellationToken); }; const workerOptions = { + kibanaName, + kibanaId, interval: queueConfig.pollInterval, intervalErrorMultiplier: queueConfig.pollIntervalErrorMultiplier, }; diff --git a/x-pack/plugins/reporting/server/lib/esqueue/helpers/create_index.js b/x-pack/plugins/reporting/server/lib/esqueue/helpers/create_index.js index bf58039e424d..1a7c243711c4 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/helpers/create_index.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/helpers/create_index.js @@ -53,12 +53,14 @@ const schema = { completed_at: { type: 'date' }, attempts: { type: 'short' }, max_attempts: { type: 'short' }, + kibana_name: { type: 'keyword' }, + kibana_id: { type: 'keyword' }, status: { type: 'keyword' }, output: { type: 'object', properties: { content_type: { type: 'keyword' }, - size: { type: 'keyword' }, + size: { type: 'long' }, content: { type: 'object', enabled: false } } } diff --git a/x-pack/plugins/reporting/server/lib/esqueue/worker.js b/x-pack/plugins/reporting/server/lib/esqueue/worker.js index c1236b8c9cd7..8c6bd5125e67 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/worker.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/worker.js @@ -49,6 +49,8 @@ export class Worker extends events.EventEmitter { super(); this.id = puid.generate(); + this.kibanaId = opts.kibanaId; + this.kibanaName = opts.kibanaName; this.queue = queue; this.client = opts.client || this.queue.client; this.jobtype = type; @@ -120,6 +122,8 @@ export class Worker extends events.EventEmitter { started_at: startTime, process_expiration: expirationTime, status: constants.JOB_STATUS_PROCESSING, + kibana_id: this.kibanaId, + kibana_name: this.kibanaName, }; return this.client.update({ From 087d6d1fbf739fe2df341f0fd99c13c89da30918 Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Wed, 9 Jan 2019 11:52:19 -0700 Subject: [PATCH 02/21] Chore: cleans up Canvas function error messages (#28194) * Added op value to compare error message. Removed duplicate unit test * Added single quotes to ply error message to help distinguish incorrect value * Added value of context to progress error message * Added percent value to reveal image error message * Added single quotes to alterColumn error message to help distinguish incorrect value * Added single quotes to timefilter error message to help distinguish incorrect value * Added single quotes to axisConfg error message to help distinguish incorrect value * Cleaned up error message in compare * Added single quotes to font error messages * Added single quotes to getCell error messages * Added single quotes to progress error messages * Added single quotes to revealImage error messages * Cleaned up timefilter error message * Added single quotes to demodata error messages * Added unit test back * Updated error message in ply --- .../functions/common/__tests__/alterColumn.js | 2 +- .../functions/common/__tests__/axis_config.js | 6 +++--- .../functions/common/__tests__/compare.js | 8 ++++++-- .../functions/common/__tests__/font.js | 4 ++-- .../functions/common/__tests__/getCell.js | 8 ++++---- .../functions/common/__tests__/ply.js | 4 ++-- .../functions/common/__tests__/progress.js | 4 ++-- .../functions/common/__tests__/reveal_image.js | 6 ++++-- .../functions/common/__tests__/timefilter.js | 2 +- .../canvas_plugin_src/functions/common/alterColumn.js | 2 +- .../canvas_plugin_src/functions/common/axisConfig.js | 10 +++++----- .../canvas_plugin_src/functions/common/compare.js | 2 +- .../canvas/canvas_plugin_src/functions/common/font.js | 4 ++-- .../canvas_plugin_src/functions/common/getCell.js | 4 ++-- .../canvas/canvas_plugin_src/functions/common/ply.js | 2 +- .../canvas_plugin_src/functions/common/progress.js | 4 ++-- .../canvas_plugin_src/functions/common/revealImage.js | 2 +- .../canvas_plugin_src/functions/common/timefilter.js | 2 +- .../functions/server/src/__tests__/demodata.js | 2 +- .../functions/server/src/demodata/get_demo_rows.js | 2 +- 20 files changed, 43 insertions(+), 37 deletions(-) diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/alterColumn.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/alterColumn.js index 763fe0fe5720..a9ad20c05c6f 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/alterColumn.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/alterColumn.js @@ -79,7 +79,7 @@ describe('alterColumn', () => { it('throws when converting to an invalid type', () => { expect(() => fn(testTable, { column: 'name', type: 'foo' })).to.throwException(e => { - expect(e.message).to.be('Cannot convert to foo'); + expect(e.message).to.be(`Cannot convert to 'foo'`); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/axis_config.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/axis_config.js index f74f568080dc..1e4bbccb8ae3 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/axis_config.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/axis_config.js @@ -59,7 +59,7 @@ describe('axisConfig', () => { expect(fn) .withArgs(testTable, { position: 'foo' }) .to.throwException(e => { - expect(e.message).to.be('Invalid position foo'); + expect(e.message).to.be(`Invalid position: 'foo'`); }); }); }); @@ -83,7 +83,7 @@ describe('axisConfig', () => { .withArgs(testTable, { min: 'foo' }) .to.throwException(e => { expect(e.message).to.be( - `Invalid date string 'foo' found. 'min' must be a number, date in ms, or ISO8601 date string` + `Invalid date string: 'foo'. 'min' must be a number, date in ms, or ISO8601 date string` ); }); }); @@ -108,7 +108,7 @@ describe('axisConfig', () => { .withArgs(testTable, { max: '20/02/17' }) .to.throwException(e => { expect(e.message).to.be( - `Invalid date string '20/02/17' found. 'max' must be a number, date in ms, or ISO8601 date string` + `Invalid date string: '20/02/17'. 'max' must be a number, date in ms, or ISO8601 date string` ); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js index c7b61be4e4b2..2bd31f5d69ff 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js @@ -24,10 +24,14 @@ describe('compare', () => { it('throws when invalid op is provided', () => { expect(() => fn(1, { op: 'boo', to: 2 })).to.throwException(e => { - expect(e.message).to.be('Invalid compare operator. Use eq, ne, lt, gt, lte, or gte.'); + expect(e.message).to.be( + `Invalid compare operator: 'boo'. Use eq, ne, lt, gt, lte, or gte.` + ); }); expect(() => fn(1, { op: 'boo' })).to.throwException(e => { - expect(e.message).to.be('Invalid compare operator. Use eq, ne, lt, gt, lte, or gte.'); + expect(e.message).to.be( + `Invalid compare operator: 'boo'. Use eq, ne, lt, gt, lte, or gte.` + ); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/font.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/font.js index b05945c500e1..0bd5871b03ad 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/font.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/font.js @@ -105,7 +105,7 @@ describe('font', () => { it('throws when provided an invalid weight', () => { expect(() => fn(null, { weight: 'foo' })).to.throwException(e => { - expect(e.message).to.be('Invalid font weight: foo'); + expect(e.message).to.be(`Invalid font weight: 'foo'`); }); }); }); @@ -175,7 +175,7 @@ describe('font', () => { expect(fn) .withArgs(null, { align: 'foo' }) .to.throwException(e => { - expect(e.message).to.be('Invalid text alignment: foo'); + expect(e.message).to.be(`Invalid text alignment: 'foo'`); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/getCell.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/getCell.js index 9509c05f9229..7b73dbec4df0 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/getCell.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/getCell.js @@ -44,7 +44,7 @@ describe('getCell', () => { it('throws when invalid column is provided', () => { expect(() => fn(testTable, { column: 'foo' })).to.throwException(e => { - expect(e.message).to.be('Column not found: foo'); + expect(e.message).to.be(`Column not found: 'foo'`); }); }); }); @@ -66,15 +66,15 @@ describe('getCell', () => { const invalidRow = testTable.rows.length; expect(() => fn(testTable, { column: 'name', row: invalidRow })).to.throwException(e => { - expect(e.message).to.be(`Row not found: ${invalidRow}`); + expect(e.message).to.be(`Row not found: '${invalidRow}'`); }); expect(() => fn(emptyTable, { column: 'foo' })).to.throwException(e => { - expect(e.message).to.be('Row not found: 0'); + expect(e.message).to.be(`Row not found: '0'`); }); expect(() => fn(emptyTable)).to.throwException(e => { - expect(e.message).to.be('Row not found: 0'); + expect(e.message).to.be(`Row not found: '0'`); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/ply.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/ply.js index 0e72cb38885b..54e33de91a47 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/ply.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/ply.js @@ -82,12 +82,12 @@ describe('ply', () => { it('throws when by is an invalid column', () => { expect(() => fn(testTable, { by: [''], expression: [averagePrice] })).to.throwException( e => { - expect(e.message).to.be('No such column: '); + expect(e.message).to.be(`Column not found: ''`); } ); expect(() => fn(testTable, { by: ['foo'], expression: [averagePrice] })).to.throwException( e => { - expect(e.message).to.be('No such column: foo'); + expect(e.message).to.be(`Column not found: 'foo'`); } ); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js index 5b16b80ddd74..61df4292e025 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js @@ -29,7 +29,7 @@ describe('progress', () => { expect(fn) .withArgs(3) .to.throwException(e => { - expect(e.message).to.be('Context must be between 0 and 1'); + expect(e.message).to.be(`Invalid value: '3'. Value must be between 0 and 1`); }); }); @@ -65,7 +65,7 @@ describe('progress', () => { expect(fn) .withArgs(value, { max: -0.5 }) .to.throwException(e => { - expect(e.message).to.be(`'max' must be greater than 0`); + expect(e.message).to.be(`Invalid max value: '-0.5'. 'max' must be greater than 0`); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/reveal_image.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/reveal_image.js index 3dc00b3c5559..3a3707e7c0b7 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/reveal_image.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/reveal_image.js @@ -29,7 +29,7 @@ describe('revealImage', () => { origin: 'top', }) .to.throwException(e => { - expect(e.message).to.be.equal('input must be between 0 and 1'); + expect(e.message).to.be.equal(`Invalid value: '10'. Percentage must be between 0 and 1`); }); expect(fn) @@ -39,7 +39,9 @@ describe('revealImage', () => { origin: 'top', }) .to.throwException(e => { - expect(e.message).to.be.equal('input must be between 0 and 1'); + expect(e.message).to.be.equal( + `Invalid value: '-0.1'. Percentage must be between 0 and 1` + ); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter.js index a63adc3d0533..70a3a007b889 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter.js @@ -88,7 +88,7 @@ describe('timefilter', () => { it('throws when provided an invalid date string', () => { expect(() => fn(emptyFilter, { from: '2018-13-42T15:00:00.950Z' })).to.throwException(e => { - expect(e.message).to.be.equal('Invalid date/time string 2018-13-42T15:00:00.950Z'); + expect(e.message).to.be.equal(`Invalid date/time string: '2018-13-42T15:00:00.950Z'`); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.js index 0c706e4d562b..c12056488540 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.js @@ -74,7 +74,7 @@ export const alterColumn = () => ({ case 'null': return () => null; default: - throw new Error(`Cannot convert to ${type}`); + throw new Error(`Cannot convert to '${type}'`); } })(); } diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axisConfig.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axisConfig.js index a89f2206023a..f2672552f0c3 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axisConfig.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axisConfig.js @@ -43,7 +43,7 @@ export const axisConfig = () => ({ fn: (context, args) => { const positions = ['top', 'bottom', 'left', 'right', '']; if (!positions.includes(args.position)) { - throw new Error(`Invalid position ${args.position}`); + throw new Error(`Invalid position: '${args.position}'`); } const min = typeof args.min === 'string' ? moment.utc(args.min).valueOf() : args.min; @@ -51,16 +51,16 @@ export const axisConfig = () => ({ if (min != null && isNaN(min)) { throw new Error( - `Invalid date string '${ + `Invalid date string: '${ args.min - }' found. 'min' must be a number, date in ms, or ISO8601 date string` + }'. 'min' must be a number, date in ms, or ISO8601 date string` ); } if (max != null && isNaN(max)) { throw new Error( - `Invalid date string '${ + `Invalid date string: '${ args.max - }' found. 'max' must be a number, date in ms, or ISO8601 date string` + }'. 'max' must be a number, date in ms, or ISO8601 date string` ); } diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/compare.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/compare.js index a0c117af7dd8..43d386229e3b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/compare.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/compare.js @@ -61,7 +61,7 @@ export const compare = () => ({ } return false; default: - throw new Error('Invalid compare operator. Use eq, ne, lt, gt, lte, or gte.'); + throw new Error(`Invalid compare operator: '${op}'. Use eq, ne, lt, gt, lte, or gte.`); } return false; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/font.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/font.js index ec99f19d8d59..7e9a3e9887f2 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/font.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/font.js @@ -80,10 +80,10 @@ export const font = () => ({ }, fn: (context, args) => { if (!weights.includes(args.weight)) { - throw new Error(`Invalid font weight: ${args.weight}`); + throw new Error(`Invalid font weight: '${args.weight}'`); } if (!alignments.includes(args.align)) { - throw new Error(`Invalid text alignment: ${args.align}`); + throw new Error(`Invalid text alignment: '${args.align}'`); } // the line height shouldn't ever be lower than the size diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.js index e978c6d64c9f..28232ab0035b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.js @@ -26,14 +26,14 @@ export const getCell = () => ({ fn: (context, args) => { const row = context.rows[args.row]; if (!row) { - throw new Error(`Row not found: ${args.row}`); + throw new Error(`Row not found: '${args.row}'`); } const { column = context.columns[0].name } = args; const value = row[column]; if (typeof value === 'undefined') { - throw new Error(`Column not found: ${column}`); + throw new Error(`Column not found: '${column}'`); } return value; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.js index c082c5c4c988..94644d976180 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.js @@ -95,7 +95,7 @@ export const ply = () => ({ byColumns = args.by.map(by => { const column = context.columns.find(column => column.name === by); if (!column) { - throw new Error(`No such column: ${by}`); + throw new Error(`Column not found: '${by}'`); } return column; }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.js index 863e606984f7..d78fe4b062aa 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.js @@ -72,10 +72,10 @@ export const progress = () => ({ }, fn: (value, args) => { if (args.max <= 0) { - throw new Error(`'max' must be greater than 0`); + throw new Error(`Invalid max value: '${args.max}'. 'max' must be greater than 0`); } if (value > args.max || value < 0) { - throw new Error(`Context must be between 0 and ${args.max}`); + throw new Error(`Invalid value: '${value}'. Value must be between 0 and ${args.max}`); } let label = ''; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/revealImage.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/revealImage.js index 888f0899978d..a57830bdf9a5 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/revealImage.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/revealImage.js @@ -35,7 +35,7 @@ export const revealImage = () => ({ }, fn: (percent, args) => { if (percent > 1 || percent < 0) { - throw new Error('input must be between 0 and 1'); + throw new Error(`Invalid value: '${percent}'. Percentage must be between 0 and 1`); } return { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.js index f9a8b12497ac..88a89233b222 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.js @@ -50,7 +50,7 @@ export const timefilter = () => ({ const moment = dateMath.parse(str); if (!moment || !moment.isValid()) { - throw new Error(`Invalid date/time string ${str}`); + throw new Error(`Invalid date/time string: '${str}'`); } return moment.toISOString(); } diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/src/__tests__/demodata.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/src/__tests__/demodata.js index 86ca52ebbc4b..1871bc560b79 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/src/__tests__/demodata.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/src/__tests__/demodata.js @@ -36,7 +36,7 @@ describe('demodata', () => { expect(fn) .withArgs(null, { type: 'foo' }) .to.throwException(e => { - expect(e.message).to.be("Invalid data set: foo, use 'ci' or 'shirts'."); + expect(e.message).to.be("Invalid data set: 'foo', use 'ci' or 'shirts'."); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/src/demodata/get_demo_rows.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/src/demodata/get_demo_rows.js index 78bb441e242c..e61d800e9e86 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/src/demodata/get_demo_rows.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/src/demodata/get_demo_rows.js @@ -15,5 +15,5 @@ export function getDemoRows(arg) { if (arg === 'shirts') { return cloneDeep(shirts); } - throw new Error(`Invalid data set: ${arg}, use 'ci' or 'shirts'.`); + throw new Error(`Invalid data set: '${arg}', use 'ci' or 'shirts'.`); } From 76f3816dd1314755eb31fd44737ddb52d40423a4 Mon Sep 17 00:00:00 2001 From: Sarah Hersh Date: Wed, 9 Jan 2019 15:18:53 -0500 Subject: [PATCH 03/21] DOCS/update to reflect new UI text (#28088) --- docs/management/managing-fields.asciidoc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/management/managing-fields.asciidoc b/docs/management/managing-fields.asciidoc index 2926ddd89520..6bfd36bc1c06 100644 --- a/docs/management/managing-fields.asciidoc +++ b/docs/management/managing-fields.asciidoc @@ -94,13 +94,13 @@ https://www.elastic.co/blog/using-painless-kibana-scripted-fields[Using Painless === Creating a Scripted Field To create a scripted field: -. Go to *Settings > Indices* +. Go to *Management > Kibana > Index Patterns* . Select the index pattern you want to add a scripted field to. -. Go to the pattern's *Scripted Fields* tab. -. Click *Add Scripted Field*. +. Go to the pattern's *Scripted fields* tab. +. Click *Add scripted field*. . Enter a name for the scripted field. . Enter the expression that you want to use to compute a value on the fly from your index data. -. Click *Save Scripted Field*. +. Click *Create field*. For more information about scripted fields in Elasticsearch, see {ref}/modules-scripting.html[Scripting]. @@ -110,9 +110,10 @@ For more information about scripted fields in Elasticsearch, see === Updating a Scripted Field To modify a scripted field: -. Go to *Settings > Indices* +. Go to *Management > Kibana > Index Patterns* +. Click the index pattern's *Scripted fields* tab. . Click the *Edit* button for the scripted field you want to change. -. Make your changes and then click *Save Scripted Field* to update the field. +. Make your changes and then click *Save field* to update the field. WARNING: Keep in mind that there's no built-in validation of a scripted field. If your scripts are buggy, you'll get exceptions whenever you try to view the dynamically generated data. @@ -122,6 +123,7 @@ exceptions whenever you try to view the dynamically generated data. === Deleting a Scripted Field To delete a scripted field: -. Go to *Settings > Indices* +. Go to *Management > Kibana > Index Patterns* +. Click the index pattern's *Scripted fields* tab. . Click the *Delete* button for the scripted field you want to remove. -. Confirm that you really want to delete the field. +. Click *Delete* in the confirmation window. From ddea7e30aebb76f448b39774f12c267668a186f0 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Wed, 9 Jan 2019 12:22:38 -0800 Subject: [PATCH 04/21] Fix incorrect variable (#28404) --- x-pack/plugins/index_management/server/lib/enrich_response.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/index_management/server/lib/enrich_response.js b/x-pack/plugins/index_management/server/lib/enrich_response.js index be9661792304..6948a6610bef 100644 --- a/x-pack/plugins/index_management/server/lib/enrich_response.js +++ b/x-pack/plugins/index_management/server/lib/enrich_response.js @@ -17,5 +17,5 @@ export const enrichResponse = async (response, callWithRequest) => { // silently swallow enricher response errors } } - return response; + return enrichedResponse; }; From c4be00fae74a00dfa0840ea914fb9b10e3bde1ab Mon Sep 17 00:00:00 2001 From: Jason Rhodes Date: Wed, 9 Jan 2019 16:08:35 -0500 Subject: [PATCH 05/21] Switched tabs to render to avoid unnecessary mount cycles (#28389) * Switched tabs to render to avoid unnecessary mount cycles We were previously using the 'component' prop for React Router routes inside of our history tabs component, which causes lots of extra mount cycles. Using the 'render' prop avoids that. We also decided to *only* allow the render prop, which means using a component is a little more verbose b/c you have to pass down props from the render method, but it's worth it to avoid accidentally using 'component'. For more, see: https://reacttraining.com/react-router/web/api/Route Specifically: "When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop (below)." * Prevents trace list from flickering on data load, while still preventing inaccurate no items message while loading * Updates tests --- x-pack/plugins/apm/public/components/app/Main/Home.tsx | 4 ++-- .../app/Main/__test__/__snapshots__/Home.test.js.snap | 4 ++-- .../components/app/ServiceDetails/ServiceDetailTabs.tsx | 6 +++--- .../apm/public/components/app/TraceOverview/TraceList.tsx | 5 +++-- .../shared/HistoryTabs/__test__/HistoryTabs.test.tsx | 6 +++--- .../__test__/__snapshots__/HistoryTabs.test.tsx.snap | 6 +++--- .../apm/public/components/shared/HistoryTabs/index.tsx | 6 +++--- 7 files changed, 19 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/Main/Home.tsx b/x-pack/plugins/apm/public/components/app/Main/Home.tsx index 53b2be947688..ef185c5f072d 100644 --- a/x-pack/plugins/apm/public/components/app/Main/Home.tsx +++ b/x-pack/plugins/apm/public/components/app/Main/Home.tsx @@ -20,12 +20,12 @@ const homeTabs: IHistoryTab[] = [ { path: '/services', name: 'Services', - component: ServiceOverview + render: props => }, { path: '/traces', name: 'Traces', - component: TraceOverview + render: props => } ]; diff --git a/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/Home.test.js.snap b/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/Home.test.js.snap index 87451ecb3743..970d3692b0a8 100644 --- a/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/Home.test.js.snap +++ b/x-pack/plugins/apm/public/components/app/Main/__test__/__snapshots__/Home.test.js.snap @@ -39,14 +39,14 @@ exports[`Home component should render 1`] = ` tabs={ Array [ Object { - "component": [Function], "name": "Services", "path": "/services", + "render": [Function], }, Object { - "component": [Function], "name": "Traces", "path": "/traces", + "render": [Function], }, ] } diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx index 435085afe5dd..d83b07d325ab 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx @@ -26,7 +26,7 @@ export class ServiceDetailTabs extends React.Component { name: 'Transactions', path: `/${serviceName}/transactions/${transactionTypes[0]}`, routePath: `/${serviceName}/transactions/:transactionType?`, - component: () => ( + render: () => ( { { name: 'Errors', path: `/${serviceName}/errors`, - component: () => { + render: () => { return ( ); @@ -45,7 +45,7 @@ export class ServiceDetailTabs extends React.Component { { name: 'Metrics', path: `/${serviceName}/metrics`, - component: () => + render: () => } ]; diff --git a/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx b/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx index e587f513a58b..b29387f11933 100644 --- a/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx +++ b/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx @@ -70,12 +70,13 @@ const traceListColumns: ITableColumn[] = [ ]; export function TraceList({ items = [], noItemsMessage, isLoading }: Props) { - return isLoading ? null : ( + const noItems = isLoading ? null : noItemsMessage; + return ( ); diff --git a/x-pack/plugins/apm/public/components/shared/HistoryTabs/__test__/HistoryTabs.test.tsx b/x-pack/plugins/apm/public/components/shared/HistoryTabs/__test__/HistoryTabs.test.tsx index 312f22d7760e..124d355e19a9 100644 --- a/x-pack/plugins/apm/public/components/shared/HistoryTabs/__test__/HistoryTabs.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/HistoryTabs/__test__/HistoryTabs.test.tsx @@ -40,17 +40,17 @@ describe('HistoryTabs', () => { { name: 'One', path: '/one', - component: () => + render: props => }, { name: 'Two', path: '/two', - component: () => + render: () => }, { name: 'Three', path: '/three', - component: () => + render: () => } ]; diff --git a/x-pack/plugins/apm/public/components/shared/HistoryTabs/__test__/__snapshots__/HistoryTabs.test.tsx.snap b/x-pack/plugins/apm/public/components/shared/HistoryTabs/__test__/__snapshots__/HistoryTabs.test.tsx.snap index f23eb64416aa..3e4c0b065657 100644 --- a/x-pack/plugins/apm/public/components/shared/HistoryTabs/__test__/__snapshots__/HistoryTabs.test.tsx.snap +++ b/x-pack/plugins/apm/public/components/shared/HistoryTabs/__test__/__snapshots__/HistoryTabs.test.tsx.snap @@ -55,19 +55,19 @@ exports[`HistoryTabs should render correctly 1`] = ` size="l" /> `; diff --git a/x-pack/plugins/apm/public/components/shared/HistoryTabs/index.tsx b/x-pack/plugins/apm/public/components/shared/HistoryTabs/index.tsx index c5f67d440878..ff3f7e79357a 100644 --- a/x-pack/plugins/apm/public/components/shared/HistoryTabs/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/HistoryTabs/index.tsx @@ -17,7 +17,7 @@ export interface IHistoryTab { path: string; routePath?: string; name: React.ReactNode; - component?: React.SFC | React.ComponentClass; + render?: (props: RouteComponentProps) => React.ReactNode; } export interface HistoryTabsProps extends RouteComponentProps { @@ -51,10 +51,10 @@ const HistoryTabsWithoutRouter = ({ {tabs.map(tab => - tab.component ? ( + tab.render ? ( ) : null From b57461117d755c74b9bd1d2f7b94a6f792310553 Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Wed, 9 Jan 2019 14:46:46 -0700 Subject: [PATCH 06/21] Adds options to download workpad from an active workpad (#28131) * Change download icon from sortDown to exportAction in workpad loader * Added context menu and download menu item to workpad export popover * Updated icon on download button in workpad loader * Added TODO in workpad export * Added copy to clipboard on click to disabled reporting panel view --- .../public/components/clipboard/clipboard.js | 2 +- .../components/clipboard/clipboard.scss | 3 + .../public/components/workpad_export/index.js | 40 ++-- .../workpad_export/workpad_export.js | 184 ++++++++++++------ .../workpad_export/workpad_export.scss | 10 + .../public/components/workpad_loader/index.js | 12 +- .../workpad_loader/workpad_loader.js | 4 +- .../canvas/public/lib/download_workpad.js | 18 ++ x-pack/plugins/canvas/public/style/index.scss | 2 + 9 files changed, 190 insertions(+), 85 deletions(-) create mode 100644 x-pack/plugins/canvas/public/components/clipboard/clipboard.scss create mode 100644 x-pack/plugins/canvas/public/components/workpad_export/workpad_export.scss create mode 100644 x-pack/plugins/canvas/public/lib/download_workpad.js diff --git a/x-pack/plugins/canvas/public/components/clipboard/clipboard.js b/x-pack/plugins/canvas/public/components/clipboard/clipboard.js index 72ed24dc5f10..1b516fdc3e9f 100644 --- a/x-pack/plugins/canvas/public/components/clipboard/clipboard.js +++ b/x-pack/plugins/canvas/public/components/clipboard/clipboard.js @@ -28,7 +28,7 @@ export class Clipboard extends React.PureComponent { render() { return ( -
+
{this.props.children}
); diff --git a/x-pack/plugins/canvas/public/components/clipboard/clipboard.scss b/x-pack/plugins/canvas/public/components/clipboard/clipboard.scss new file mode 100644 index 000000000000..206b5eaf760e --- /dev/null +++ b/x-pack/plugins/canvas/public/components/clipboard/clipboard.scss @@ -0,0 +1,3 @@ +.canvasClipboard { + cursor: pointer; +} diff --git a/x-pack/plugins/canvas/public/components/workpad_export/index.js b/x-pack/plugins/canvas/public/components/workpad_export/index.js index a54acaca0140..897a2e06e436 100644 --- a/x-pack/plugins/canvas/public/components/workpad_export/index.js +++ b/x-pack/plugins/canvas/public/components/workpad_export/index.js @@ -13,6 +13,7 @@ import { getWorkpad, getPages } from '../../state/selectors/workpad'; import { getReportingBrowserType } from '../../state/selectors/app'; import { notify } from '../../lib/notify'; import { getWindow } from '../../lib/get_window'; +import { downloadWorkpad } from '../../lib/download_workpad'; import { WorkpadExport as Component } from './workpad_export'; import { getPdfUrl, createPdf } from './utils'; @@ -43,29 +44,34 @@ export const WorkpadExport = compose( throw new Error(`Unknown export type: ${type}`); }, onCopy: type => { - if (type === 'pdf') { - return notify.info('The PDF generation URL was copied to your clipboard.'); + switch (type) { + case 'pdf': + return notify.info('The PDF generation URL was copied to your clipboard.'); + case 'reportingConfig': + return notify.info(`Copied reporting configuration to clipboard`); } - throw new Error(`Unknown export type: ${type}`); }, onExport: type => { - if (type === 'pdf') { - return createPdf(workpad, { pageCount }) - .then(({ data }) => { - notify.info('Exporting PDF. You can track the progress in Management.', { - title: `PDF export of workpad '${workpad.name}'`, + switch (type) { + case 'pdf': + return createPdf(workpad, { pageCount }) + .then(({ data }) => { + notify.info('Exporting PDF. You can track the progress in Management.', { + title: `PDF export of workpad '${workpad.name}'`, + }); + + // register the job so a completion notification shows up when it's ready + jobCompletionNotifications.add(data.job.id); + }) + .catch(err => { + notify.error(err, { title: `Failed to create PDF for '${workpad.name}'` }); }); - - // register the job so a completion notification shows up when it's ready - jobCompletionNotifications.add(data.job.id); - }) - .catch(err => { - notify.error(err, { title: `Failed to create PDF for '${workpad.name}'` }); - }); + case 'json': + return downloadWorkpad(workpad.id); + default: + throw new Error(`Unknown export type: ${type}`); } - - throw new Error(`Unknown export type: ${type}`); }, })) )(Component); diff --git a/x-pack/plugins/canvas/public/components/workpad_export/workpad_export.js b/x-pack/plugins/canvas/public/components/workpad_export/workpad_export.js index 7056e6250789..9b36b2e1f479 100644 --- a/x-pack/plugins/canvas/public/components/workpad_export/workpad_export.js +++ b/x-pack/plugins/canvas/public/components/workpad_export/workpad_export.js @@ -9,12 +9,12 @@ import PropTypes from 'prop-types'; import { EuiButton, EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, EuiSpacer, EuiCodeBlock, - EuiHorizontalRule, - EuiFormRow, + EuiCode, + EuiContextMenu, + EuiIcon, + EuiText, } from '@elastic/eui'; import { Popover } from '../popover'; import { Clipboard } from '../clipboard'; @@ -27,81 +27,155 @@ export class WorkpadExport extends React.PureComponent { getExportUrl: PropTypes.func.isRequired, }; + anchorElement = React.createRef(); + + flattenPanelTree(tree, array = []) { + array.push(tree); + + if (tree.items) { + tree.items.forEach(item => { + if (item.panel) { + this.flattenPanelTree(item.panel, array); + item.panel = item.panel.id; + } + }); + } + + return array; + } + exportPdf = () => { this.props.onExport('pdf'); }; - renderControls = closePopover => { + downloadWorkpad = () => { + this.props.onExport('json'); + }; + + renderPDFControls = closePopover => { const pdfUrl = this.props.getExportUrl('pdf'); return ( -
- - - - { - this.exportPdf(); - closePopover(); - }} - > - Export as PDF - - - - - - - - - - {pdfUrl} - - +
+ +

PDFs can take a minute or two to generate based upon the size of your workpad

+
+ - - { - this.props.onCopy('pdf'); - closePopover(); - }} - > - - - - - + {this.props.options} + + { + closePopover(); + this.exportPdf(); + }} + size="s" + style={{ width: '100%' }} + > + Generate PDF + + + + +

+ Alternatively, copy this POST URL to call generation from outside Kibana or from + Watcher. +

+
+ + + { + this.props.onCopy('pdf'); + closePopover(); + }} + > + + Copy POST URL + +
); }; + renderPanelTree = closePopover => ({ + id: 0, + title: 'Share this workpad', + items: [ + { + name: 'Download as JSON', + icon: , + onClick: () => { + closePopover(); + this.downloadWorkpad(); + }, + }, + { + name: 'PDF Reports', + icon: 'document', + panel: { + id: 1, + title: 'PDF Reports', + content: this.props.enabled + ? this.renderPDFControls(closePopover) + : this.renderDisabled(), + }, + }, + ], + }); + renderDisabled = () => { + const reportingConfig = `xpack.reporting: + enabled: true + capture.browser.type: chromium`; + return ( -
- Export to PDF is disabled. You must configure reporting to use the Chromium browser. Add - this to your kibana.yml file. +
+ +

+ Export to PDF is disabled. You must configure reporting to use the Chromium browser. Add + this to your kibana.yml file. +

+
- - xpack.reporting.capture.browser.type: chromium - + this.props.onCopy('reportingConfig')}> + + {reportingConfig} + +
); }; render() { const exportControl = togglePopover => ( - + ); + // TODO: replace this with `showShareContextMenu` in `ui/share` once it's been converted to React return ( - + {({ closePopover }) => ( - - - {this.props.enabled && this.renderControls(closePopover)} - {!this.props.enabled && this.renderDisabled()} - - + )} ); diff --git a/x-pack/plugins/canvas/public/components/workpad_export/workpad_export.scss b/x-pack/plugins/canvas/public/components/workpad_export/workpad_export.scss new file mode 100644 index 000000000000..a35db90e963c --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_export/workpad_export.scss @@ -0,0 +1,10 @@ +.canvasWorkpadExport__panelContent { + padding: $euiSize; +} +.canvasWorkpadExport__reportingConfig { + .euiCodeBlock__pre { + @include euiScrollBar; + overflow-x: auto; + white-space: pre; + } +} diff --git a/x-pack/plugins/canvas/public/components/workpad_loader/index.js b/x-pack/plugins/canvas/public/components/workpad_loader/index.js index 8e83819054fd..996d541cb424 100644 --- a/x-pack/plugins/canvas/public/components/workpad_loader/index.js +++ b/x-pack/plugins/canvas/public/components/workpad_loader/index.js @@ -7,13 +7,13 @@ import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { compose, withState, getContext, withHandlers } from 'recompose'; -import fileSaver from 'file-saver'; import * as workpadService from '../../lib/workpad_service'; import { notify } from '../../lib/notify'; import { canUserWrite } from '../../state/selectors/app'; import { getWorkpad } from '../../state/selectors/workpad'; import { getId } from '../../lib/get_id'; import { setCanUserWrite } from '../../state/actions/transient'; +import { downloadWorkpad } from '../../lib/download_workpad'; import { WorkpadLoader as Component } from './workpad_loader'; const mapStateToProps = state => ({ @@ -67,15 +67,7 @@ export const WorkpadLoader = compose( }, // Workpad import/export methods - downloadWorkpad: () => async workpadId => { - try { - const workpad = await workpadService.get(workpadId); - const jsonBlob = new Blob([JSON.stringify(workpad)], { type: 'application/json' }); - fileSaver.saveAs(jsonBlob, `canvas-workpad-${workpad.name}-${workpad.id}.json`); - } catch (err) { - notify.error(err, { title: `Couldn't download workpad` }); - } - }, + downloadWorkpad: () => workpadId => downloadWorkpad(workpadId), // Clone workpad given an id cloneWorkpad: props => async workpadId => { diff --git a/x-pack/plugins/canvas/public/components/workpad_loader/workpad_loader.js b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_loader.js index 66def18abaf8..9008ae94a232 100644 --- a/x-pack/plugins/canvas/public/components/workpad_loader/workpad_loader.js +++ b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_loader.js @@ -142,7 +142,7 @@ export class WorkpadLoader extends React.PureComponent { this.props.downloadWorkpad(workpad.id)} aria-label="Download Workpad" /> @@ -288,7 +288,7 @@ export class WorkpadLoader extends React.PureComponent { ); const downloadButton = ( - + {`Download (${selectedWorkpads.length})`} ); diff --git a/x-pack/plugins/canvas/public/lib/download_workpad.js b/x-pack/plugins/canvas/public/lib/download_workpad.js new file mode 100644 index 000000000000..20cd4ad46ce0 --- /dev/null +++ b/x-pack/plugins/canvas/public/lib/download_workpad.js @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import fileSaver from 'file-saver'; +import { notify } from './notify'; +import * as workpadService from './workpad_service'; + +export const downloadWorkpad = async workpadId => { + try { + const workpad = await workpadService.get(workpadId); + const jsonBlob = new Blob([JSON.stringify(workpad)], { type: 'application/json' }); + fileSaver.saveAs(jsonBlob, `canvas-workpad-${workpad.name}-${workpad.id}.json`); + } catch (err) { + notify.error(err, { title: `Couldn't download workpad` }); + } +}; diff --git a/x-pack/plugins/canvas/public/style/index.scss b/x-pack/plugins/canvas/public/style/index.scss index 300a060040e1..c37755ba595e 100644 --- a/x-pack/plugins/canvas/public/style/index.scss +++ b/x-pack/plugins/canvas/public/style/index.scss @@ -24,6 +24,7 @@ @import '../components/autocomplete/autocomplete'; @import '../components/border_connection/border_connection'; @import '../components/border_resize_handle/border_resize_handle'; +@import '../components/clipboard/clipboard'; @import '../components/color_dot/color_dot'; @import '../components/color_palette/color_palette'; @import '../components/color_picker_mini/color_picker_mini'; @@ -52,6 +53,7 @@ @import '../components/toolbar/toolbar'; @import '../components/toolbar/tray/tray'; @import '../components/workpad/workpad'; +@import '../components/workpad_export/workpad_export'; @import '../components/workpad_loader/workpad_loader'; @import '../components/workpad_loader/workpad_dropzone/workpad_dropzone'; @import '../components/workpad_page/workpad_page'; From baa7ac2c70f81c65250356252c68ac90587bc36c Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Wed, 9 Jan 2019 14:56:55 -0700 Subject: [PATCH 07/21] [Canvas] Fixes error handling of NetworkErrors (#28282) * Fixes error handling with NetworkErrors * Removed lodash get --- .../canvas/public/apps/workpad/routes.js | 4 +-- .../public/components/workpad_loader/index.js | 6 ++-- .../public/state/middleware/es_persist.js | 36 +++++++++---------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/canvas/public/apps/workpad/routes.js b/x-pack/plugins/canvas/public/apps/workpad/routes.js index 9d8af8cd11b9..727f03a779da 100644 --- a/x-pack/plugins/canvas/public/apps/workpad/routes.js +++ b/x-pack/plugins/canvas/public/apps/workpad/routes.js @@ -33,7 +33,7 @@ export const routes = [ notify.error(err, { title: `Couldn't create workpad` }); // TODO: remove this and switch to checking user privileges when canvas loads when granular app privileges are introduced // https://github.com/elastic/kibana/issues/20277 - if (err.response.status === 403) { + if (err.response && err.response.status === 403) { dispatch(setCanUserWrite(false)); } router.redirectTo('home'); @@ -61,7 +61,7 @@ export const routes = [ // TODO: remove this and switch to checking user privileges when canvas loads when granular app privileges are introduced // https://github.com/elastic/kibana/issues/20277 workpadService.update(params.id, fetchedWorkpad).catch(err => { - if (err.response.status === 403) { + if (err.response && err.response.status === 403) { dispatch(setCanUserWrite(false)); } }); diff --git a/x-pack/plugins/canvas/public/components/workpad_loader/index.js b/x-pack/plugins/canvas/public/components/workpad_loader/index.js index 996d541cb424..31ea8f7d41e5 100644 --- a/x-pack/plugins/canvas/public/components/workpad_loader/index.js +++ b/x-pack/plugins/canvas/public/components/workpad_loader/index.js @@ -46,7 +46,7 @@ export const WorkpadLoader = compose( notify.error(err, { title: `Couldn't upload workpad` }); // TODO: remove this and switch to checking user privileges when canvas loads when granular app privileges are introduced // https://github.com/elastic/kibana/issues/20277 - if (err.response.status === 403) { + if (err.response && err.response.status === 403) { props.setCanUserWrite(false); } } @@ -81,7 +81,7 @@ export const WorkpadLoader = compose( notify.error(err, { title: `Couldn't clone workpad` }); // TODO: remove this and switch to checking user privileges when canvas loads when granular app privileges are introduced // https://github.com/elastic/kibana/issues/20277 - if (err.response.status === 403) { + if (err.response && err.response.status === 403) { props.setCanUserWrite(false); } } @@ -114,7 +114,7 @@ export const WorkpadLoader = compose( errors.push(result.id); // TODO: remove this and switch to checking user privileges when canvas loads when granular app privileges are introduced // https://github.com/elastic/kibana/issues/20277 - if (result.err.response.status === 403) { + if (result.err.response && result.err.response.status === 403) { props.setCanUserWrite(false); } } else { diff --git a/x-pack/plugins/canvas/public/state/middleware/es_persist.js b/x-pack/plugins/canvas/public/state/middleware/es_persist.js index 34af6b4fc839..5f906010e75b 100644 --- a/x-pack/plugins/canvas/public/state/middleware/es_persist.js +++ b/x-pack/plugins/canvas/public/state/middleware/es_persist.js @@ -55,26 +55,26 @@ export const esPersistMiddleware = ({ getState }) => { if (workpadChanged(curState, newState) || assetsChanged(curState, newState)) { const persistedWorkpad = getWorkpadPersisted(getState()); return update(persistedWorkpad.id, persistedWorkpad).catch(err => { - if (err.response.status === 400) { - return notify.error(err.response, { - title: `Couldn't save your changes to Elasticsearch`, - }); - } - - if (err.response.status === 413) { - return notify.error( - `The server gave a response that the workpad data was too large. This - usually means uploaded image assets that are too large for Kibana or - a proxy. Try removing some assets in the asset manager.`, - { + const statusCode = err.response && err.response.status; + switch (statusCode) { + case 400: + return notify.error(err.response, { title: `Couldn't save your changes to Elasticsearch`, - } - ); + }); + case 413: + return notify.error( + `The server gave a response that the workpad data was too large. This + usually means uploaded image assets that are too large for Kibana or + a proxy. Try removing some assets in the asset manager.`, + { + title: `Couldn't save your changes to Elasticsearch`, + } + ); + default: + return notify.error(err, { + title: `Couldn't update workpad`, + }); } - - return notify.error(err.response, { - title: `Couldn't update workpad`, - }); }); } }; From aea3613ec0f1d64f90e37e9eab3d7b6fa1272468 Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Wed, 9 Jan 2019 14:58:58 -0700 Subject: [PATCH 08/21] Removes backticks from font values (#28283) --- x-pack/plugins/canvas/common/lib/fonts.ts | 33 ++++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/canvas/common/lib/fonts.ts b/x-pack/plugins/canvas/common/lib/fonts.ts index 69b3bf2bb71b..b413e1c74d2b 100644 --- a/x-pack/plugins/canvas/common/lib/fonts.ts +++ b/x-pack/plugins/canvas/common/lib/fonts.ts @@ -6,52 +6,53 @@ export const americanTypewriter = { label: 'American Typewriter', - value: `'American Typewriter', 'Courier New', Courier, Monaco, mono`, + value: "'American Typewriter', 'Courier New', Courier, Monaco, mono", }; -export const arial = { label: 'Arial', value: `Arial, sans-serif` }; +export const arial = { label: 'Arial', value: 'Arial, sans-serif' }; export const baskerville = { label: 'Baskerville', - value: `Baskerville, Georgia, Garamond, 'Times New Roman', Times, serif`, + value: "Baskerville, Georgia, Garamond, 'Times New Roman', Times, serif", }; export const bookAntiqua = { label: 'Book Antiqua', - value: `'Book Antiqua', Georgia, Garamond, 'Times New Roman', Times, serif`, + value: "'Book Antiqua', Georgia, Garamond, 'Times New Roman', Times, serif", }; export const brushScript = { label: 'Brush Script', - value: `'Brush Script MT', 'Comic Sans', sans-serif`, + value: "'Brush Script MT', 'Comic Sans', sans-serif", }; -export const chalkboard = { label: 'Chalkboard', value: `Chalkboard, 'Comic Sans', sans-serif` }; +export const chalkboard = { label: 'Chalkboard', value: "Chalkboard, 'Comic Sans', sans-serif" }; export const didot = { label: 'Didot', - value: `Didot, Georgia, Garamond, 'Times New Roman', Times, serif`, + value: "Didot, Georgia, Garamond, 'Times New Roman', Times, serif", }; -export const futura = { label: 'Futura', value: `Futura, Impact, Helvetica, Arial, sans-serif` }; +export const futura = { label: 'Futura', value: 'Futura, Impact, Helvetica, Arial, sans-serif' }; export const gillSans = { label: 'Gill Sans', - value: `'Gill Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, Arial, sans-serif`, + value: + "'Gill Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, Arial, sans-serif", }; export const helveticaNeue = { label: 'Helvetica Neue', - value: `'Helvetica Neue', Helvetica, Arial, sans-serif`, + value: "'Helvetica Neue', Helvetica, Arial, sans-serif", }; export const hoeflerText = { label: 'Hoefler Text', - value: `'Hoefler Text', Garamond, Georgia, 'Times New Roman', Times, serif`, + value: "'Hoefler Text', Garamond, Georgia, 'Times New Roman', Times, serif", }; export const lucidaGrande = { label: 'Lucida Grande', - value: `'Lucida Grande', 'Lucida Sans Unicode', Lucida, Verdana, Helvetica, Arial, sans-serif`, + value: "'Lucida Grande', 'Lucida Sans Unicode', Lucida, Verdana, Helvetica, Arial, sans-serif", }; -export const myriad = { label: 'Myriad', value: `Myriad, Helvetica, Arial, sans-serif` }; -export const openSans = { label: 'Open Sans', value: `'Open Sans', Helvetica, Arial, sans-serif` }; +export const myriad = { label: 'Myriad', value: 'Myriad, Helvetica, Arial, sans-serif' }; +export const openSans = { label: 'Open Sans', value: "'Open Sans', Helvetica, Arial, sans-serif" }; export const optima = { label: 'Optima', - value: `Optima, 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, Arial, sans-serif`, + value: "Optima, 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Helvetica, Arial, sans-serif", }; export const palatino = { label: 'Palatino', - value: `Palatino, 'Book Antiqua', Georgia, Garamond, 'Times New Roman', Times, serif`, + value: "Palatino, 'Book Antiqua', Georgia, Garamond, 'Times New Roman', Times, serif", }; export const fonts = [ americanTypewriter, From db91d15f3715cdb5d8487b07142e8ec94cae54e5 Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Wed, 9 Jan 2019 15:02:02 -0700 Subject: [PATCH 09/21] Changed classname from canvas_download to canvasDownload (#28421) --- .../canvas/public/components/download/__tests__/download.js | 4 ++-- x-pack/plugins/canvas/public/components/download/download.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/canvas/public/components/download/__tests__/download.js b/x-pack/plugins/canvas/public/components/download/__tests__/download.js index 2d2b40236fdf..36c3a199e6fc 100644 --- a/x-pack/plugins/canvas/public/components/download/__tests__/download.js +++ b/x-pack/plugins/canvas/public/components/download/__tests__/download.js @@ -10,13 +10,13 @@ import { render } from 'enzyme'; import { Download } from '../'; describe('', () => { - it('has canvas_download class', () => { + it('has canvasDownload class', () => { const wrapper = render( ); - expect(wrapper.hasClass('canvas_download')).to.be.ok; + expect(wrapper.hasClass('canvasDownload')).to.be.ok; }); }); diff --git a/x-pack/plugins/canvas/public/components/download/download.js b/x-pack/plugins/canvas/public/components/download/download.js index e2b39f15d48d..835ea3d14abf 100644 --- a/x-pack/plugins/canvas/public/components/download/download.js +++ b/x-pack/plugins/canvas/public/components/download/download.js @@ -28,7 +28,7 @@ export class Download extends React.PureComponent { render() { return ( -
+
{this.props.children}
); From 337292394d64133edde718b2aa5fe91f1786447b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 9 Jan 2019 15:40:00 -0700 Subject: [PATCH 10/21] Avoid rendering JoinEditor on every state change (#28401) --- .../layer_panel/join_editor/index.js | 9 ++++--- .../gis/public/components/layer_panel/view.js | 2 +- .../gis/public/selectors/map_selectors.js | 24 ++++++++++++------- .../shared/layers/sources/ems_file_source.js | 4 ---- .../shared/layers/sources/vector_source.js | 5 +--- .../gis/public/shared/layers/vector_layer.js | 2 +- 6 files changed, 22 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/gis/public/components/layer_panel/join_editor/index.js b/x-pack/plugins/gis/public/components/layer_panel/join_editor/index.js index 6aabd1fd3b47..957382d3f7ac 100644 --- a/x-pack/plugins/gis/public/components/layer_panel/join_editor/index.js +++ b/x-pack/plugins/gis/public/components/layer_panel/join_editor/index.js @@ -6,6 +6,7 @@ import { connect } from 'react-redux'; import { JoinEditor } from './view'; +import { getSelectedLayer, getSelectedLayerJoinDescriptors } from '../../../selectors/map_selectors'; import { setJoinsForLayer } from '../../../actions/store_actions'; function mapDispatchToProps(dispatch) { @@ -16,12 +17,10 @@ function mapDispatchToProps(dispatch) { }; } -function mapStateToProps({}, props) { +function mapStateToProps(state = {}) { return { - joins: props.layer.getJoins().map(join => { - return join.toDescriptor(); - }), - layer: props.layer, + joins: getSelectedLayerJoinDescriptors(state), + layer: getSelectedLayer(state), }; } diff --git a/x-pack/plugins/gis/public/components/layer_panel/view.js b/x-pack/plugins/gis/public/components/layer_panel/view.js index ff14a5762d74..7bdd6edf3776 100644 --- a/x-pack/plugins/gis/public/components/layer_panel/view.js +++ b/x-pack/plugins/gis/public/components/layer_panel/view.js @@ -49,7 +49,7 @@ export class LayerPanel extends React.Component { return ( - + ); } diff --git a/x-pack/plugins/gis/public/selectors/map_selectors.js b/x-pack/plugins/gis/public/selectors/map_selectors.js index a9c74677bfb1..a9f6dbc10245 100644 --- a/x-pack/plugins/gis/public/selectors/map_selectors.js +++ b/x-pack/plugins/gis/public/selectors/map_selectors.js @@ -135,15 +135,6 @@ export const getDataFilters = createSelector( export const getDataSources = createSelector(getMetadata, metadata => metadata ? metadata.data_sources : null); -export const getSelectedLayer = createSelector( - getSelectedLayerId, - getLayerListRaw, - getDataSources, - (selectedLayerId, layerList, dataSources) => { - const selectedLayer = layerList.find(layerDescriptor => layerDescriptor.id === selectedLayerId); - return createLayerInstance(selectedLayer, dataSources); - }); - export const getLayerList = createSelector( getLayerListRaw, getDataSources, @@ -152,4 +143,19 @@ export const getLayerList = createSelector( createLayerInstance(layerDescriptor, dataSources)); }); +export const getSelectedLayer = createSelector( + getSelectedLayerId, + getLayerList, + (selectedLayerId, layerList) => { + return layerList.find(layer => layer.getId() === selectedLayerId); + }); + +export const getSelectedLayerJoinDescriptors = createSelector( + getSelectedLayer, + (selectedLayer) => { + return selectedLayer.getJoins().map(join => { + return join.toDescriptor(); + }); + }); + export const getTemporaryLayers = createSelector(getLayerList, (layerList) => layerList.filter(layer => layer.isTemporary())); diff --git a/x-pack/plugins/gis/public/shared/layers/sources/ems_file_source.js b/x-pack/plugins/gis/public/shared/layers/sources/ems_file_source.js index 5f490239c2dd..887e73c8934e 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/ems_file_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/ems_file_source.js @@ -108,10 +108,6 @@ export class EMSFileSource extends VectorSource { } - async isTimeAware() { - return false; - } - canFormatFeatureProperties() { return true; } diff --git a/x-pack/plugins/gis/public/shared/layers/sources/vector_source.js b/x-pack/plugins/gis/public/shared/layers/sources/vector_source.js index 92d5d5da8bfe..6f4ad01f01b2 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/vector_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/vector_source.js @@ -57,17 +57,14 @@ export class VectorSource extends ASource { } isFilterByMapBounds() { - console.warn('Should implement VectorSource#isFilterByMapBounds'); return false; } async getNumberFields() { - console.warn('Should implement VectorSource#getNumberFields'); return []; } async getStringFields() { - console.warn('Should implement VectorSource@getStringFields'); return []; } @@ -93,7 +90,7 @@ export class VectorSource extends ASource { } async isTimeAware() { - throw new Error('Should implement'); + return false; } } diff --git a/x-pack/plugins/gis/public/shared/layers/vector_layer.js b/x-pack/plugins/gis/public/shared/layers/vector_layer.js index 57fe4688c683..7f551ddd6a32 100644 --- a/x-pack/plugins/gis/public/shared/layers/vector_layer.js +++ b/x-pack/plugins/gis/public/shared/layers/vector_layer.js @@ -223,7 +223,7 @@ export class VectorLayer extends ALayer { join: join }; } - startLoading(sourceDataId, requestToken, { timeFilters: dataFilters.timeFilters }); + startLoading(sourceDataId, requestToken, dataFilters); const leftSourceName = await this.getSourceName(); const { rawData, From 9254c829fbfd6a01352abd10bbe1ab9c0e3f6ff7 Mon Sep 17 00:00:00 2001 From: Fabien Baligand Date: Thu, 10 Jan 2019 00:23:21 +0100 Subject: [PATCH 11/21] Add setting to hide the 'Time' column in discover and saved searches. --- docs/management/advanced-options.asciidoc | 1 + .../kibana/public/discover/controllers/discover.js | 3 ++- src/legacy/core_plugins/kibana/ui_setting_defaults.js | 10 ++++++++++ src/ui/public/doc_table/components/table_header.html | 2 +- src/ui/public/doc_table/components/table_header.js | 4 +++- src/ui/public/doc_table/components/table_row.js | 5 +++-- 6 files changed, 20 insertions(+), 5 deletions(-) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index ca2050e574ff..20d57d1d2ae0 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -39,6 +39,7 @@ document. `discover:sort:defaultOrder`:: Controls the default sort direction for time based index patterns in the Discover app. `doc_table:highlight`:: Highlight results in Discover and Saved Searches Dashboard. Highlighting makes request slow when working on big documents. Set this property to `false` to disable highlighting. +`doc_table:hideTimeColumn`:: Hide the 'Time' column in Discover and in all Saved Searches on Dashboards. `search:includeFrozen`:: Will include {ref}/frozen-indices.html[frozen indices] in results if enabled. Searching through frozen indices might increase the search time. `courier:maxSegmentCount`:: Kibana splits requests in the Discover app into segments to limit the size of requests sent to diff --git a/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js b/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js index 1965870d5ef1..0fb7042ac1cd 100644 --- a/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js @@ -380,7 +380,8 @@ function discoverController( } const timeFieldName = $scope.indexPattern.timeFieldName; - const fields = timeFieldName ? [timeFieldName, ...selectedFields] : selectedFields; + const hideTimeColumn = config.get('doc_table:hideTimeColumn'); + const fields = (timeFieldName && !hideTimeColumn) ? [timeFieldName, ...selectedFields] : selectedFields; return { searchFields: fields, selectFields: fields diff --git a/src/legacy/core_plugins/kibana/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/ui_setting_defaults.js index 8c222aca15fb..ee646aacec19 100644 --- a/src/legacy/core_plugins/kibana/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/ui_setting_defaults.js @@ -269,6 +269,16 @@ export function getUiSettingDefaults() { }), category: ['discover'], }, + 'doc_table:hideTimeColumn': { + name: i18n.translate('kbn.advancedSettings.docTableHideTimeColumnTitle', { + defaultMessage: 'Hide \'Time\' column', + }), + value: false, + description: i18n.translate('kbn.advancedSettings.docTableHideTimeColumnText', { + defaultMessage: 'Hide the \'Time\' column in Discover and in all Saved Searches on Dashboards.', + }), + category: ['discover'], + }, 'courier:maxSegmentCount': { name: i18n.translate('kbn.advancedSettings.courier.maxSegmentCountTitle', { defaultMessage: 'Maximum segment count', diff --git a/src/ui/public/doc_table/components/table_header.html b/src/ui/public/doc_table/components/table_header.html index 00ae62bace9b..455604830beb 100644 --- a/src/ui/public/doc_table/components/table_header.html +++ b/src/ui/public/doc_table/components/table_header.html @@ -1,7 +1,7 @@ diff --git a/src/ui/public/doc_table/components/table_header.js b/src/ui/public/doc_table/components/table_header.js index edaaef460b02..200a7d4de7da 100644 --- a/src/ui/public/doc_table/components/table_header.js +++ b/src/ui/public/doc_table/components/table_header.js @@ -36,7 +36,9 @@ module.directive('kbnTableHeader', function (shortDotsFilter) { onMoveColumn: '=?', }, template: headerHtml, - controller: function ($scope) { + controller: function ($scope, config) { + $scope.hideTimeColumn = config.get('doc_table:hideTimeColumn'); + $scope.isSortableColumn = function isSortableColumn(columnName) { return ( !!$scope.indexPattern diff --git a/src/ui/public/doc_table/components/table_row.js b/src/ui/public/doc_table/components/table_row.js index 06cc47d4203e..b7c5768bbaa9 100644 --- a/src/ui/public/doc_table/components/table_row.js +++ b/src/ui/public/doc_table/components/table_row.js @@ -45,7 +45,7 @@ const MIN_LINE_LENGTH = 20; * * ``` */ -module.directive('kbnTableRow', function ($compile, $httpParamSerializer, kbnUrl) { +module.directive('kbnTableRow', function ($compile, $httpParamSerializer, kbnUrl, config) { const cellTemplate = _.template(noWhiteSpace(require('ui/doc_table/components/table_row/cell.html'))); const truncateByHeightTemplate = _.template(noWhiteSpace(require('ui/partials/truncate_by_height.html'))); @@ -139,7 +139,8 @@ module.directive('kbnTableRow', function ($compile, $httpParamSerializer, kbnUrl ]; const mapping = indexPattern.fields.byName; - if (indexPattern.timeFieldName) { + const hideTimeColumn = config.get('doc_table:hideTimeColumn'); + if (indexPattern.timeFieldName && !hideTimeColumn) { newHtmls.push(cellTemplate({ timefield: true, formatted: _displayField(row, indexPattern.timeFieldName), From 9b0a093448626e18aee9d335c41c5170038efa29 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Wed, 9 Jan 2019 17:07:06 -0700 Subject: [PATCH 12/21] fix: reject instead of resolving (#28129) --- x-pack/plugins/canvas/server/routes/workpad.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/canvas/server/routes/workpad.js b/x-pack/plugins/canvas/server/routes/workpad.js index 8042a82aedbd..cfc53ac4b85d 100644 --- a/x-pack/plugins/canvas/server/routes/workpad.js +++ b/x-pack/plugins/canvas/server/routes/workpad.js @@ -41,7 +41,7 @@ export function workpad(server) { const savedObjectsClient = req.getSavedObjectsClient(); if (!req.payload) { - return Promise.resolve(boom.badRequest('A workpad payload is required')); + return Promise.reject(boom.badRequest('A workpad payload is required')); } const now = new Date().toISOString(); From e8ba176f87bc259097e498ffceda29d1f8cc2f71 Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 9 Jan 2019 17:30:29 -0700 Subject: [PATCH 13/21] Implement built_assets directory (#27468) * [sass] build sass into built_assets directory * [optimize/dlls] move dll optimization into built_assets directory * [dlls] update path to dll manifest * [built_assets] ignore when searching for notice files * [sass] build into variable directory * revert changes to ui_export_types/style_sheet_paths.js * revert changes to ui_export_types/style_sheet_paths.test.js * [uiExports/styleSheetPaths] switch .scss extension for stylesheets that are already compiled * update comment for clarity * [testBundle] include css from built_assets * [dlls] move url to built_assets/dlls * fix merge conflict issues * [server/sass] pass log in test --- .eslintignore | 2 +- .gitignore | 3 +- package.json | 2 +- .../clean_client_modules_on_dll_task.js | 2 +- src/dev/build/tasks/transpile_scss_task.js | 2 +- src/dev/notice/generate_notice_from_source.js | 2 +- src/legacy/core_plugins/tests_bundle/index.js | 4 +- src/optimize/bundles_route/bundles_route.js | 2 +- .../bundles_route/proxy_bundles_route.js | 2 +- .../dynamic_dll_plugin/dll_compiler.js | 2 +- src/optimize/index.js | 2 +- src/optimize/watch/watch.js | 2 +- src/server/sass/__fixtures__/index.scss | 5 ++ src/server/sass/build.js | 21 +++----- src/server/sass/build.test.js | 53 ++++++++++--------- src/server/sass/build_all.js | 6 ++- src/server/sass/index.js | 4 +- .../ui_export_types/style_sheet_paths.js | 19 ++++--- src/ui/ui_render/ui_render_mixin.js | 15 +++++- tasks/config/karma.js | 10 ++-- 20 files changed, 89 insertions(+), 71 deletions(-) create mode 100644 src/server/sass/__fixtures__/index.scss diff --git a/.eslintignore b/.eslintignore index 61128f38d867..aed4548f41f0 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,7 +5,7 @@ bower_components /.es /plugins /optimize -/dlls +/built_assets /src/fixtures/vislib/mock_data /src/ui/public/angular-bootstrap /src/ui/public/flot-charts diff --git a/.gitignore b/.gitignore index 167d677100df..0ed1cf89ba58 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ node_modules !/src/dev/notice/__fixtures__/node_modules trash /optimize -/dlls +/built_assets target /build .jruby @@ -44,4 +44,3 @@ package-lock.json *.sublime-* npm-debug.log* .tern-project -**/public/index.css diff --git a/package.json b/package.json index 43e1e69cb960..63eb9cff65f7 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "extraPatterns": [ "build", "optimize", - "dlls", + "built_assets", ".eslintcache" ] } diff --git a/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js b/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js index 31028154bf8c..be8bebbac280 100644 --- a/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js +++ b/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js @@ -64,7 +64,7 @@ export const CleanClientModulesOnDLLTask = { ]; // Resolve the client vendors dll manifest path - const dllManifestPath = `${baseDir}/dlls/vendors.manifest.dll.json`; + const dllManifestPath = `${baseDir}/built_assets/dlls/vendors.manifest.dll.json`; // Get dll entries filtering out the ones // from any whitelisted module diff --git a/src/dev/build/tasks/transpile_scss_task.js b/src/dev/build/tasks/transpile_scss_task.js index 0c06a421bf50..c2004f1d9b21 100644 --- a/src/dev/build/tasks/transpile_scss_task.js +++ b/src/dev/build/tasks/transpile_scss_task.js @@ -34,7 +34,7 @@ export const TranspileScssTask = { const uiExports = collectUiExports(enabledPlugins); try { - const bundles = await buildAll(uiExports.styleSheetPaths, log); + const bundles = await buildAll(uiExports.styleSheetPaths, log, build.resolvePath('built_assets/css')); bundles.forEach(bundle => log.info(`Compiled SCSS: ${bundle.source}`)); } catch (error) { const { message, line, file } = error; diff --git a/src/dev/notice/generate_notice_from_source.js b/src/dev/notice/generate_notice_from_source.js index 86ebd59553e2..31c40e7714ee 100644 --- a/src/dev/notice/generate_notice_from_source.js +++ b/src/dev/notice/generate_notice_from_source.js @@ -42,7 +42,7 @@ export async function generateNoticeFromSource({ productName, directory, log }) cwd: directory, nodir: true, ignore: [ - '{node_modules,build,target,dist,optimize,dlls}/**', + '{node_modules,build,target,dist,optimize,built_assets}/**', 'packages/*/{node_modules,build,target,dist}/**', 'x-pack/{node_modules,build,target,dist,optimize}/**', 'x-pack/packages/*/{node_modules,build,target,dist}/**', diff --git a/src/legacy/core_plugins/tests_bundle/index.js b/src/legacy/core_plugins/tests_bundle/index.js index 71e79f0ea7d1..146c8373a13f 100644 --- a/src/legacy/core_plugins/tests_bundle/index.js +++ b/src/legacy/core_plugins/tests_bundle/index.js @@ -70,7 +70,7 @@ export default (kibana) => { } testGlobs.push(`${plugin.publicDir}/**/__tests__/**/*.js`); - testGlobs.push(`${plugin.publicDir}/**/*.css`); + testGlobs.push(`built_assets/css/plugins/${plugin.id}/**/*.css`); }); } else { // add the modules from all of the apps @@ -80,7 +80,7 @@ export default (kibana) => { for (const plugin of plugins) { testGlobs.push(`${plugin.publicDir}/**/__tests__/**/*.js`); - testGlobs.push(`${plugin.publicDir}/**/*.css`); + testGlobs.push(`built_assets/css/plugins/${plugin.id}/**/*.css`); } } diff --git a/src/optimize/bundles_route/bundles_route.js b/src/optimize/bundles_route/bundles_route.js index d00f4dd3378a..2be8de45e336 100644 --- a/src/optimize/bundles_route/bundles_route.js +++ b/src/optimize/bundles_route/bundles_route.js @@ -59,7 +59,7 @@ export function createBundlesRoute({ regularBundlesPath, dllBundlesPath, basePub return [ buildRouteForBundles(basePublicPath, '/bundles/', regularBundlesPath, fileHashCache), - buildRouteForBundles(basePublicPath, '/dlls/', dllBundlesPath, fileHashCache), + buildRouteForBundles(basePublicPath, '/built_assets/dlls/', dllBundlesPath, fileHashCache), ]; } diff --git a/src/optimize/bundles_route/proxy_bundles_route.js b/src/optimize/bundles_route/proxy_bundles_route.js index 300c6296a8d9..a15330ed5002 100644 --- a/src/optimize/bundles_route/proxy_bundles_route.js +++ b/src/optimize/bundles_route/proxy_bundles_route.js @@ -20,7 +20,7 @@ export function createProxyBundlesRoute({ host, port }) { return [ buildProxyRouteForBundles('/bundles/', host, port), - buildProxyRouteForBundles('/dlls/', host, port) + buildProxyRouteForBundles('/built_assets/dlls/', host, port) ]; } diff --git a/src/optimize/dynamic_dll_plugin/dll_compiler.js b/src/optimize/dynamic_dll_plugin/dll_compiler.js index eb0325591460..26065c90d345 100644 --- a/src/optimize/dynamic_dll_plugin/dll_compiler.js +++ b/src/optimize/dynamic_dll_plugin/dll_compiler.js @@ -46,7 +46,7 @@ export class DllCompiler { dllExt: '.bundle.dll.js', manifestExt: '.manifest.dll.json', styleExt: '.style.dll.css', - outputPath: fromRoot('./dlls'), + outputPath: fromRoot('built_assets/dlls'), publicPath: PUBLIC_PATH_PLACEHOLDER }; } diff --git a/src/optimize/index.js b/src/optimize/index.js index f8373eb4e6ae..b6ba806573e5 100644 --- a/src/optimize/index.js +++ b/src/optimize/index.js @@ -29,7 +29,7 @@ export default async (kbnServer, server, config) => { // bundles in a "middleware" style. // // the server listening on 5601 may be restarted a number of times, depending - // on the watch setup managed by the cli. It proxies all bundles/* and dlls/* + // on the watch setup managed by the cli. It proxies all bundles/* and built_assets/dlls/* // requests to the other server. The server on 5602 is long running, in order // to prevent complete rebuilds of the optimize content. const watch = config.get('optimize.watch'); diff --git a/src/optimize/watch/watch.js b/src/optimize/watch/watch.js index 7089524b8a46..6d46fd259b7c 100644 --- a/src/optimize/watch/watch.js +++ b/src/optimize/watch/watch.js @@ -33,7 +33,7 @@ export default async kbnServer => { * while the optimizer is running * * server: this process runs the entire kibana server and proxies - * all requests for /bundles/* or /dlls/* to the optmzr process + * all requests for /bundles/* or /built_assets/dlls/* to the optmzr process * * @param {string} process.env.kbnWorkerType */ diff --git a/src/server/sass/__fixtures__/index.scss b/src/server/sass/__fixtures__/index.scss new file mode 100644 index 000000000000..c542dd82ca68 --- /dev/null +++ b/src/server/sass/__fixtures__/index.scss @@ -0,0 +1,5 @@ +foo { + bar { + display: flex; + } +} diff --git a/src/server/sass/build.js b/src/server/sass/build.js index 55e4d26a287f..fcdb813b4e60 100644 --- a/src/server/sass/build.js +++ b/src/server/sass/build.js @@ -23,30 +23,24 @@ import fs from 'fs'; import sass from 'node-sass'; import autoprefixer from 'autoprefixer'; import postcss from 'postcss'; +import mkdirp from 'mkdirp'; const renderSass = promisify(sass.render); const writeFile = promisify(fs.writeFile); +const mkdirpAsync = promisify(mkdirp); export class Build { - constructor(source, log) { + constructor(source, log, targetPath) { this.source = source; this.log = log; + this.targetPath = targetPath; this.includedFiles = [source]; } - outputPath() { - const fileName = path.basename(this.source, path.extname(this.source)) + '.css'; - return path.join(path.dirname(this.source), fileName); - } - /** * Glob based on source path */ - getGlob() { - return path.join(path.dirname(this.source), '**', '*.s{a,c}ss'); - } - async buildIfIncluded(path) { if (this.includedFiles && this.includedFiles.includes(path)) { await this.build(); @@ -61,11 +55,9 @@ export class Build { */ async build() { - const outFile = this.outputPath(); - const rendered = await renderSass({ file: this.source, - outFile, + outFile: this.targetPath, sourceMap: true, sourceMapEmbed: true, includePaths: [ @@ -78,7 +70,8 @@ export class Build { this.includedFiles = rendered.stats.includedFiles; - await writeFile(outFile, prefixed.css); + await mkdirpAsync(path.dirname(this.targetPath)); + await writeFile(this.targetPath, prefixed.css); return this; } diff --git a/src/server/sass/build.test.js b/src/server/sass/build.test.js index fbc3ede3a355..f77db1cba976 100644 --- a/src/server/sass/build.test.js +++ b/src/server/sass/build.test.js @@ -17,34 +17,35 @@ * under the License. */ -import path from 'path'; -import sass from 'node-sass'; +import { resolve } from 'path'; +import { readFileSync } from 'fs'; + +import del from 'del'; + import { Build } from './build'; -jest.mock('node-sass'); +const TMP = resolve(__dirname, '__tmp__'); +const FIXTURE = resolve(__dirname, '__fixtures__/index.scss'); -describe('SASS builder', () => { - jest.mock('fs'); +afterEach(async () => { + await del(TMP); +}); - it('generates a glob', () => { - const builder = new Build('/foo/style.sass'); - expect(builder.getGlob()).toEqual(path.join('/foo', '**', '*.s{a,c}ss')); - }); +it('builds SASS', async () => { + const cssPath = resolve(TMP, 'style.css'); + await (new Build(FIXTURE, { + info: () => {}, + warn: () => {}, + error: () => {}, + }, cssPath)).build(); - it('builds SASS', () => { - sass.render.mockImplementation(() => Promise.resolve(null, { css: 'test' })); - const builder = new Build('/foo/style.sass'); - builder.build(); - - const sassCall = sass.render.mock.calls[0][0]; - expect(sassCall.file).toEqual('/foo/style.sass'); - expect(sassCall.outFile).toEqual(path.join('/foo', 'style.css')); - expect(sassCall.sourceMap).toBe(true); - expect(sassCall.sourceMapEmbed).toBe(true); - }); - - it('has an output file with a different extension', () => { - const builder = new Build('/foo/style.sass'); - expect(builder.outputPath()).toEqual(path.join('/foo', 'style.css')); - }); -}); \ No newline at end of file + expect(readFileSync(cssPath, 'utf8').replace(/(\/\*# sourceMappingURL=).*( \*\/)/, '$1...$2')) + .toMatchInlineSnapshot(` +"foo bar { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; } +/*# sourceMappingURL=... */" +`); +}); diff --git a/src/server/sass/build_all.js b/src/server/sass/build_all.js index 08fdf9d41f68..ee449ad53297 100644 --- a/src/server/sass/build_all.js +++ b/src/server/sass/build_all.js @@ -17,16 +17,18 @@ * under the License. */ +import { resolve } from 'path'; + import { Build } from './build'; -export async function buildAll(styleSheets = [], log) { +export async function buildAll(styleSheets, log, buildDir) { const bundles = await Promise.all(styleSheets.map(async styleSheet => { if (!styleSheet.localPath.endsWith('.scss')) { return; } - const bundle = new Build(styleSheet.localPath, log); + const bundle = new Build(styleSheet.localPath, log, resolve(buildDir, styleSheet.publicPath)); await bundle.build(); return bundle; diff --git a/src/server/sass/index.js b/src/server/sass/index.js index 4def49cafc06..44a8470ace88 100644 --- a/src/server/sass/index.js +++ b/src/server/sass/index.js @@ -17,7 +17,7 @@ * under the License. */ -import { IS_KIBANA_DISTRIBUTABLE } from '../../utils'; +import { IS_KIBANA_DISTRIBUTABLE, fromRoot } from '../../utils'; export async function sassMixin(kbnServer, server, config) { if (process.env.kbnWorkerType === 'optmzr') { @@ -45,7 +45,7 @@ export async function sassMixin(kbnServer, server, config) { }; try { - scssBundles = await buildAll(kbnServer.uiExports.styleSheetPaths, log); + scssBundles = await buildAll(kbnServer.uiExports.styleSheetPaths, log, fromRoot('built_assets/css')); scssBundles.forEach(bundle => { bundle.includedFiles.forEach(file => trackedFiles.add(file)); diff --git a/src/ui/ui_exports/ui_export_types/style_sheet_paths.js b/src/ui/ui_exports/ui_export_types/style_sheet_paths.js index 81644a494288..016b1b1dd32d 100644 --- a/src/ui/ui_exports/ui_export_types/style_sheet_paths.js +++ b/src/ui/ui_exports/ui_export_types/style_sheet_paths.js @@ -18,6 +18,7 @@ */ import path from 'path'; +import { existsSync } from 'fs'; import { flatConcatAtType } from './reduce'; import { mapSpec, wrap } from './modify_reduce'; @@ -46,16 +47,22 @@ function normalize(localPath, type, pluginSpec) { ); } + // replace the extension of localPath to be .css + // publicPath will always point to the css file + const localCssPath = localPath.slice(0, -extname.length) + '.css'; + + // update localPath to point to the .css file if it exists and + // the .scss path does not, which is the case for built plugins + if (extname === '.scss' && !existsSync(localPath) && existsSync(localCssPath)) { + localPath = localCssPath; + } + // get the path of the stylesheet relative to the public dir for the plugin - let relativePath = path.relative(publicDir, localPath); + let relativePath = path.relative(publicDir, localCssPath); // replace back slashes on windows relativePath = relativePath.split('\\').join('/'); - // replace the extension of relativePath to be .css - // publicPath will always point to the css file - relativePath = relativePath.slice(0, -extname.length) + '.css'; - const publicPath = `plugins/${pluginSpec.getId()}/${relativePath}`; return { @@ -64,4 +71,4 @@ function normalize(localPath, type, pluginSpec) { }; } -export const styleSheetPaths = wrap(mapSpec(normalize), flatConcatAtType); \ No newline at end of file +export const styleSheetPaths = wrap(mapSpec(normalize), flatConcatAtType); diff --git a/src/ui/ui_render/ui_render_mixin.js b/src/ui/ui_render/ui_render_mixin.js index 833588a6de53..7ecd0d7af142 100644 --- a/src/ui/ui_render/ui_render_mixin.js +++ b/src/ui/ui_render/ui_render_mixin.js @@ -23,6 +23,7 @@ import { resolve } from 'path'; import { i18n } from '@kbn/i18n'; import { AppBootstrap } from './bootstrap'; import { mergeVariables } from './lib'; +import { fromRoot } from '../../utils'; export function uiRenderMixin(kbnServer, server, config) { function replaceInjectedVars(request, injectedVars) { @@ -50,6 +51,9 @@ export function uiRenderMixin(kbnServer, server, config) { // render all views from ./views server.setupViews(resolve(__dirname, 'views')); + // expose built css + server.exposeStaticDir('/built_assets/css/{path*}', fromRoot('built_assets/css')); + server.route({ path: '/bundles/app/{id}/bootstrap.js', method: 'GET', @@ -63,12 +67,19 @@ export function uiRenderMixin(kbnServer, server, config) { const basePath = config.get('server.basePath'); const regularBundlePath = `${basePath}/bundles`; - const dllBundlePath = `${basePath}/dlls`; + const dllBundlePath = `${basePath}/built_assets/dlls`; const styleSheetPaths = [ `${dllBundlePath}/vendors.style.dll.css`, `${regularBundlePath}/commons.style.css`, `${regularBundlePath}/${app.getId()}.style.css`, - ].concat(kbnServer.uiExports.styleSheetPaths.map(path => `${basePath}/${path.publicPath}`).reverse()); + ...kbnServer.uiExports.styleSheetPaths + .map(path => ( + path.localPath.endsWith('.scss') + ? `${basePath}/built_assets/css/${path.publicPath}` + : `${basePath}/${path.publicPath}` + )) + .reverse() + ]; const bootstrap = new AppBootstrap({ templateData: { diff --git a/tasks/config/karma.js b/tasks/config/karma.js index d2ca40cef2b3..5862d69b9fcc 100644 --- a/tasks/config/karma.js +++ b/tasks/config/karma.js @@ -85,17 +85,17 @@ module.exports = function (grunt) { // list of files / patterns to load in the browser files: [ - 'http://localhost:5610/dlls/vendors.bundle.dll.js', + 'http://localhost:5610/built_assets/dlls/vendors.bundle.dll.js', 'http://localhost:5610/bundles/tests.bundle.js', - 'http://localhost:5610/dlls/vendors.style.dll.css', + 'http://localhost:5610/built_assets/dlls/vendors.style.dll.css', 'http://localhost:5610/bundles/tests.style.css' ], proxies: { '/tests/': 'http://localhost:5610/tests/', '/bundles/': 'http://localhost:5610/bundles/', - '/dlls/': 'http://localhost:5610/dlls/' + '/built_assets/dlls/': 'http://localhost:5610/built_assets/dlls/' }, client: { @@ -176,10 +176,10 @@ module.exports = function (grunt) { singleRun: true, options: { files: [ - 'http://localhost:5610/dlls/vendors.bundle.dll.js', + 'http://localhost:5610/built_assets/dlls/vendors.bundle.dll.js', `http://localhost:5610/bundles/tests.bundle.js?shards=${TOTAL_CI_SHARDS}&shard_num=${n}`, - 'http://localhost:5610/dlls/vendors.style.dll.css', + 'http://localhost:5610/built_assets/dlls/vendors.style.dll.css', 'http://localhost:5610/bundles/tests.style.css' ] } From 1018e756bf069938a4651780eae3c856d04d0a22 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 10 Jan 2019 10:47:11 +0000 Subject: [PATCH 14/21] [ML] Fix for groups input population when cloning job (#28449) --- .../ml/public/components/job_group_select/job_group_select.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/plugins/ml/public/components/job_group_select/job_group_select.js b/x-pack/plugins/ml/public/components/job_group_select/job_group_select.js index 1b413476e83a..b4c77ebe94ac 100644 --- a/x-pack/plugins/ml/public/components/job_group_select/job_group_select.js +++ b/x-pack/plugins/ml/public/components/job_group_select/job_group_select.js @@ -67,6 +67,9 @@ module.directive('mlJobGroupSelect', function () { .catch((error) => { console.log('Could not load groups from calendars', error); this.populateSelectedGroups(this.jobGroups); + }) + .then(() => { + $scope.$applyAsync(); }); }); From fbb2fc96ad60ba0c0da9da3ea06f46633905cfba Mon Sep 17 00:00:00 2001 From: pavel06081991 Date: Thu, 10 Jan 2019 13:59:01 +0300 Subject: [PATCH 15/21] fix ids typos (#28450) --- src/legacy/core_plugins/vega/public/data_model/vega_parser.js | 2 +- src/legacy/core_plugins/vega/public/vega_type.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/vega/public/data_model/vega_parser.js b/src/legacy/core_plugins/vega/public/data_model/vega_parser.js index 8f5d4fc6d3c4..ad76d424459f 100644 --- a/src/legacy/core_plugins/vega/public/data_model/vega_parser.js +++ b/src/legacy/core_plugins/vega/public/data_model/vega_parser.js @@ -185,7 +185,7 @@ export class VegaParser { delete this.spec.width; delete this.spec.height; } else { - this._onWarning(i18n.translate('vega.vegaParser.widthAndHeightParamsAreIngroredWithAutosizeFitWarningMessage', { + this._onWarning(i18n.translate('vega.vegaParser.widthAndHeightParamsAreIgnoredWithAutosizeFitWarningMessage', { defaultMessage: 'The {widthParam} and {heightParam} params are ignored with {autosizeParam}', values: { autosizeParam: 'autosize=fit', diff --git a/src/legacy/core_plugins/vega/public/vega_type.js b/src/legacy/core_plugins/vega/public/vega_type.js index 28f5bd5bd298..f19d5db66e56 100644 --- a/src/legacy/core_plugins/vega/public/vega_type.js +++ b/src/legacy/core_plugins/vega/public/vega_type.js @@ -42,7 +42,7 @@ VisTypesRegistryProvider.register((Private) => { return VisFactory.createBaseVisualization({ name: 'vega', title: 'Vega', - description: i18n.translate('vega.type.vegaĐ’escription', { + description: i18n.translate('vega.type.vegaDescription', { defaultMessage: 'Create custom visualizations using Vega and Vega-Lite', description: 'Vega and Vega-Lite are product names and should not be translated', }), From 6076d85882305e7eea5b189dad9bf96a7f38b4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Casper=20H=C3=BCbertz?= Date: Thu, 10 Jan 2019 13:14:56 +0100 Subject: [PATCH 16/21] [APM] Use form label for Transaction type selector (#28322) * Use form label for type selector Removes the inline copy for filtering by transaction type and uses the FormRow label as a substitute. * [APM] Updated test snapshot --- .../__jest__/__snapshots__/TransactionOverview.test.js.snap | 5 +++-- .../apm/public/components/app/TransactionOverview/index.tsx | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap index 1f38d5961e4b..d960d846a1da 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap @@ -6,6 +6,7 @@ exports[`TransactionOverviewView should render with type filter controls 1`] = ` describedByIds={Array []} fullWidth={false} hasEmptyLabelSpace={false} + label="Filter by type" > {serviceTransactionTypes.length > 1 ? ( - + ({ - text: `Filter by type: ${type}`, + text: `${type}`, value: type }))} value={transactionType} From 4c7050984382c9a5d486ed14ba5f5578a135f8cb Mon Sep 17 00:00:00 2001 From: Jason Rhodes Date: Thu, 10 Jan 2019 07:40:45 -0500 Subject: [PATCH 17/21] Updates error message when creating ML job (#28085) * Updates error message when creating ML job * Updated error message based on feedback --- .../MachineLearningFlyout.tsx | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout.tsx index 9cf82a08cde2..c69ae43c627c 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout.tsx @@ -90,26 +90,19 @@ export class MachineLearningFlyout extends Component { }; public addErrorToast = () => { - const { location, urlParams } = this.props; - const { serviceName = 'unknown', transactionType } = urlParams; + const { urlParams } = this.props; + const { serviceName = 'unknown' } = urlParams; if (!serviceName) { return; } toastNotifications.addWarning({ - title: 'Job already exists', + title: 'Job creation failed', text: (

- There's already a job running for anomaly detection on{' '} - {serviceName} ({transactionType}).{' '} - - View existing job - + Your current license may not allow for creating machine learning jobs, + or this job may already exist.

) }); From 8b03d360c5f64f5fdd6587b22ddb609b623b1e24 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Thu, 10 Jan 2019 09:29:06 -0500 Subject: [PATCH 18/21] [ML] For categorization anomalies, display the category regex/terms in the expanded row (#28376) * Fetch terms/regex when row expanded * Adds error handling for definition fetch * update anomalyDetails tests * Handle definition regex/terms not returned * Adds tooltip to regex header --- .../anomalies_table/_anomalies_table.scss | 4 + .../anomalies_table/anomalies_table.js | 24 +++++- .../anomalies_table_constants.js | 2 + .../anomalies_table/anomaly_details.js | 52 ++++++++++++- .../anomalies_table/anomaly_details.test.js | 73 ++++++++++++++++++- 5 files changed, 151 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/ml/public/components/anomalies_table/_anomalies_table.scss b/x-pack/plugins/ml/public/components/anomalies_table/_anomalies_table.scss index 9593fb00dc23..24aac271706c 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/_anomalies_table.scss +++ b/x-pack/plugins/ml/public/components/anomalies_table/_anomalies_table.scss @@ -75,6 +75,10 @@ min-width: 150px; } + .mlAnomalyCategoryExamples__header { + display: inline; + } + .mlAnomalyCategoryExamples__link { width: 100%; } diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.js b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.js index dc100071cf25..bb9c5a5e8534 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.js +++ b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.js @@ -29,9 +29,11 @@ import { AnomalyDetails } from './anomaly_details'; import { mlTableService } from '../../services/table_service'; import { RuleEditorFlyout } from '../../components/rule_editor'; +import { ml } from '../../services/ml_api_service'; import { INFLUENCERS_LIMIT, - ANOMALIES_TABLE_TABS + ANOMALIES_TABLE_TABS, + MAX_CHARS } from './anomalies_table_constants'; class AnomaliesTable extends Component { @@ -71,18 +73,36 @@ class AnomaliesTable extends Component { return null; } - toggleRow = (item, tab = ANOMALIES_TABLE_TABS.DETAILS) => { + toggleRow = async (item, tab = ANOMALIES_TABLE_TABS.DETAILS) => { const itemIdToExpandedRowMap = { ...this.state.itemIdToExpandedRowMap }; if (itemIdToExpandedRowMap[item.rowId]) { delete itemIdToExpandedRowMap[item.rowId]; } else { const examples = (item.entityName === 'mlcategory') ? _.get(this.props.tableData, ['examplesByJobId', item.jobId, item.entityValue]) : undefined; + let definition = undefined; + + if (examples !== undefined) { + try { + definition = await ml.results.getCategoryDefinition(item.jobId, item.source.mlcategory[0]); + + if (definition.terms && definition.terms.length > MAX_CHARS) { + definition.terms = `${definition.terms.substring(0, MAX_CHARS)}...`; + } + if (definition.regex && definition.regex.length > MAX_CHARS) { + definition.terms = `${definition.regex.substring(0, MAX_CHARS)}...`; + } + } catch(error) { + console.log('Error fetching category definition for row item.', error); + } + } + itemIdToExpandedRowMap[item.rowId] = ( - {this.props.examples.map((example, i) => { + {(definition !== undefined && definition.terms) && + + + +

Terms

  + +
+ + {definition.terms} + +
+ +
} + {(definition !== undefined && definition.regex) && + + + +

Regex

  + +
+ + {definition.regex} + +
+ +
} + + {examples.map((example, i) => { return ( + {(i === 0 && definition !== undefined) && + +

Examples

+
} {example}
); @@ -384,6 +433,7 @@ export class AnomalyDetails extends Component { AnomalyDetails.propTypes = { anomaly: PropTypes.object.isRequired, examples: PropTypes.array, + definition: PropTypes.object, isAggregatedData: PropTypes.bool, filter: PropTypes.func, influencersLimit: PropTypes.number, diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.test.js b/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.test.js index 6bc9f3b83b28..3f603f659040 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.test.js +++ b/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.test.js @@ -6,7 +6,7 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow, mount } from 'enzyme'; import { AnomalyDetails } from './anomaly_details'; const props = { @@ -86,4 +86,75 @@ describe('AnomalyDetails', () => { ); expect(wrapper.prop('initialSelectedTab').id).toBe('Category examples'); }); + + test('Renders with terms and regex when definition prop is not undefined', () => { + const categoryTabProps = { + ...props, + tabIndex: 1, + definition: { + terms: 'example terms for test', + regex: '.*?DBMS.+?ERROR.+?svc_prod.+?Err.+?Microsoft.+?ODBC.+?SQL.+?Server.+?Driver' + } + }; + + const wrapper = mount( + + ); + + expect(wrapper.containsMatchingElement(

Regex

)).toBe(true); + expect(wrapper.containsMatchingElement(

Terms

)).toBe(true); + expect(wrapper.contains(

Examples

)).toBe(true); + }); + + test('Renders only with examples when definition prop is undefined', () => { + const categoryTabProps = { + ...props, + tabIndex: 1, + definition: undefined + }; + + const wrapper = mount( + + ); + + expect(wrapper.containsMatchingElement(

Regex

)).toBe(false); + expect(wrapper.containsMatchingElement(

Terms

)).toBe(false); + expect(wrapper.contains(

Examples

)).toBe(false); + }); + + test('Renders only with terms when definition.regex is undefined', () => { + const categoryTabProps = { + ...props, + tabIndex: 1, + definition: { + terms: 'example terms for test', + } + }; + + const wrapper = mount( + + ); + + expect(wrapper.containsMatchingElement(

Regex

)).toBe(false); + expect(wrapper.containsMatchingElement(

Terms

)).toBe(true); + expect(wrapper.contains(

Examples

)).toBe(true); + }); + + test('Renders only with regex when definition.terms is undefined', () => { + const categoryTabProps = { + ...props, + tabIndex: 1, + definition: { + regex: '.*?DBMS.+?ERROR.+?svc_prod.+?Err.+?Microsoft.+?ODBC.+?SQL.+?Server.+?Driver' + } + }; + + const wrapper = mount( + + ); + + expect(wrapper.containsMatchingElement(

Regex

)).toBe(true); + expect(wrapper.containsMatchingElement(

Terms

)).toBe(false); + expect(wrapper.contains(

Examples

)).toBe(true); + }); }); From 57ed7f1218eccde66b739a24f872e7dc5d0c5fc3 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 10 Jan 2019 07:46:35 -0700 Subject: [PATCH 19/21] [Maps] Update data source text (#28435) * [Maps] Update data source text * update order --- .../plugins/gis/public/shared/layers/sources/all_sources.js | 2 +- .../gis/public/shared/layers/sources/ems_file_source.js | 6 ++++-- .../gis/public/shared/layers/sources/ems_tms_source.js | 6 ++++-- .../sources/es_geohashgrid_source/es_geohashgrid_source.js | 3 +-- .../layers/sources/es_search_source/es_search_source.js | 2 +- .../public/shared/layers/sources/kibana_regionmap_source.js | 4 ++-- .../public/shared/layers/sources/kibana_tilemap_source.js | 6 ++++-- .../plugins/gis/public/shared/layers/sources/wms_source.js | 6 ++++-- .../gis/public/shared/layers/sources/xyz_tms_source.js | 6 ++++-- 9 files changed, 25 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/gis/public/shared/layers/sources/all_sources.js b/x-pack/plugins/gis/public/shared/layers/sources/all_sources.js index f65862c4241d..3b57e583d29b 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/all_sources.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/all_sources.js @@ -21,7 +21,7 @@ export const ALL_SOURCES = [ EMSFileSource, EMSTMSSource, KibanaRegionmapSource, + KibanaTilemapSource, XYZTMSSource, WMSSource, - KibanaTilemapSource ]; diff --git a/x-pack/plugins/gis/public/shared/layers/sources/ems_file_source.js b/x-pack/plugins/gis/public/shared/layers/sources/ems_file_source.js index 887e73c8934e..cd074ff53c54 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/ems_file_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/ems_file_source.js @@ -20,7 +20,7 @@ import { emsServiceSettings } from '../../../kibana_services'; export class EMSFileSource extends VectorSource { static type = 'EMS_FILE'; - static typeDisplayName = 'Elastic Maps Service region boundaries'; + static typeDisplayName = 'Elastic Maps Service vector shapes'; static createDescriptor(id) { return { @@ -60,7 +60,9 @@ export class EMSFileSource extends VectorSource { {EMSFileSource.typeDisplayName} -

Political boundry vectors hosted by EMS.

+

+ Vector shapes of administrative boundaries from Elastic Maps Service +

); diff --git a/x-pack/plugins/gis/public/shared/layers/sources/ems_tms_source.js b/x-pack/plugins/gis/public/shared/layers/sources/ems_tms_source.js index 72b2f4a3081f..304b67c3e25f 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/ems_tms_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/ems_tms_source.js @@ -18,7 +18,7 @@ import _ from 'lodash'; export class EMSTMSSource extends TMSSource { static type = 'EMS_TMS'; - static typeDisplayName = 'Elastic Maps Service Tile Service'; + static typeDisplayName = 'Elastic Maps Service tiles'; static createDescriptor(serviceId) { return { @@ -58,7 +58,9 @@ export class EMSTMSSource extends TMSSource { {EMSTMSSource.typeDisplayName} -

Tile services hosted by EMS.

+

+ Map tiles from Elastic Maps Service +

); diff --git a/x-pack/plugins/gis/public/shared/layers/sources/es_geohashgrid_source/es_geohashgrid_source.js b/x-pack/plugins/gis/public/shared/layers/sources/es_geohashgrid_source/es_geohashgrid_source.js index f7512ea8c570..5711a87079c0 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/es_geohashgrid_source/es_geohashgrid_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/es_geohashgrid_source/es_geohashgrid_source.js @@ -91,8 +91,7 @@ export class ESGeohashGridSource extends VectorSource {

- Group documents into grid cells and display metrics for each cell. - Great for displaying large datasets. + Group geospatial data in grids with metrics for each gridded cell

diff --git a/x-pack/plugins/gis/public/shared/layers/sources/es_search_source/es_search_source.js b/x-pack/plugins/gis/public/shared/layers/sources/es_search_source/es_search_source.js index d8fa28287440..964f23ca9751 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/es_search_source/es_search_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/es_search_source/es_search_source.js @@ -50,7 +50,7 @@ export class ESSearchSource extends VectorSource {

- Display documents from an elasticsearch index. + Geospatial data from an Elasticsearch index

); diff --git a/x-pack/plugins/gis/public/shared/layers/sources/kibana_regionmap_source.js b/x-pack/plugins/gis/public/shared/layers/sources/kibana_regionmap_source.js index 321a9a2ca732..162bae2903cd 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/kibana_regionmap_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/kibana_regionmap_source.js @@ -16,7 +16,7 @@ import { export class KibanaRegionmapSource extends VectorSource { static type = 'REGIONMAP_FILE'; - static typeDisplayName = 'Custom region boundaries'; + static typeDisplayName = 'Custom vector shapes'; constructor(descriptor, { ymlFileLayers }) { super(descriptor); @@ -62,7 +62,7 @@ export class KibanaRegionmapSource extends VectorSource {

- Region map boundary layers configured in your config/kibana.yml file. + Vector shapes from static files configured in kibana.yml.

diff --git a/x-pack/plugins/gis/public/shared/layers/sources/kibana_tilemap_source.js b/x-pack/plugins/gis/public/shared/layers/sources/kibana_tilemap_source.js index 82f2e81dcb21..4d44d1f989e2 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/kibana_tilemap_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/kibana_tilemap_source.js @@ -16,7 +16,7 @@ import { export class KibanaTilemapSource extends TMSSource { static type = 'KIBANA_TILEMAP'; - static typeDisplayName = 'TMS from kibana.yml'; + static typeDisplayName = 'Custom Tile Map Service'; static createDescriptor(url) { return { @@ -41,7 +41,9 @@ export class KibanaTilemapSource extends TMSSource { {KibanaTilemapSource.typeDisplayName} -

TMS service configured in kibana.yml

+

+ Map tiles configured in kibana.yml +

); diff --git a/x-pack/plugins/gis/public/shared/layers/sources/wms_source.js b/x-pack/plugins/gis/public/shared/layers/sources/wms_source.js index a4b2dc9e61b1..85021fea39cf 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/wms_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/wms_source.js @@ -20,7 +20,7 @@ export class WMSSource extends TMSSource { static type = 'WMS'; - static typeDisplayName = 'WMS'; + static typeDisplayName = 'Web Map Service'; static createDescriptor({ serviceUrl, layers, styles }) { return { @@ -46,7 +46,9 @@ export class WMSSource extends TMSSource { {WMSSource.typeDisplayName} -

Web Map Service (WMS)

+

+ Maps from OGC Standard WMS +

); diff --git a/x-pack/plugins/gis/public/shared/layers/sources/xyz_tms_source.js b/x-pack/plugins/gis/public/shared/layers/sources/xyz_tms_source.js index f2de1bb418e6..1a266dc41029 100644 --- a/x-pack/plugins/gis/public/shared/layers/sources/xyz_tms_source.js +++ b/x-pack/plugins/gis/public/shared/layers/sources/xyz_tms_source.js @@ -20,7 +20,7 @@ export class XYZTMSSource extends TMSSource { static type = 'EMS_XYZ'; - static typeDisplayName = 'TMS XYZ'; + static typeDisplayName = 'Tile Map Service from URL'; static createDescriptor(urlTemplate) { return { @@ -44,7 +44,9 @@ export class XYZTMSSource extends TMSSource { {XYZTMSSource.typeDisplayName} -

Tile Map Service with XYZ url.

+

+ Map tiles from a URL that includes the XYZ coordinates +

); From 2b593f1217fa8ec6f3e6c223adff3a36a04cb85f Mon Sep 17 00:00:00 2001 From: Chris Davies Date: Thu, 10 Jan 2019 10:18:05 -0500 Subject: [PATCH 20/21] Fix migrations to unblock Kibana devs who are working with ES7 (master) (#28369) --- .../__snapshots__/elastic_index.test.ts.snap | 18 ++++++++++++++ .../migrations/core/elastic_index.test.ts | 17 +++++++++++++ .../migrations/core/elastic_index.ts | 24 +++++++++++++++++-- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/server/saved_objects/migrations/core/__snapshots__/elastic_index.test.ts.snap b/src/server/saved_objects/migrations/core/__snapshots__/elastic_index.test.ts.snap index 17db6cbe1df4..25ebffb17c58 100644 --- a/src/server/saved_objects/migrations/core/__snapshots__/elastic_index.test.ts.snap +++ b/src/server/saved_objects/migrations/core/__snapshots__/elastic_index.test.ts.snap @@ -1,5 +1,23 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`ElasticIndex fetchInfo handles v7 indices 1`] = ` +Object { + "aliases": Object { + "foo": ".baz", + }, + "exists": true, + "indexName": ".baz", + "mappings": Object { + "doc": Object { + "dynamic": "strict", + "properties": Object { + "a": "b", + }, + }, + }, +} +`; + exports[`ElasticIndex write writes documents in bulk to the index 1`] = ` Array [ "bulk", diff --git a/src/server/saved_objects/migrations/core/elastic_index.test.ts b/src/server/saved_objects/migrations/core/elastic_index.test.ts index f66c021e81e6..fcaaf246656b 100644 --- a/src/server/saved_objects/migrations/core/elastic_index.test.ts +++ b/src/server/saved_objects/migrations/core/elastic_index.test.ts @@ -56,6 +56,23 @@ describe('ElasticIndex', () => { ); }); + test('handles v7 indices', async () => { + const callCluster = sinon.spy(async (path: string, { index }: any) => { + return { + [index]: { + aliases: { foo: index }, + mappings: { + dynamic: 'strict', + properties: { a: 'b' }, + }, + }, + }; + }); + + const result = await Index.fetchInfo(callCluster, '.baz'); + expect(result).toMatchSnapshot(); + }); + test('fails if there are multiple root types', async () => { const callCluster = sinon.spy(async (path: string, { index }: any) => { return { diff --git a/src/server/saved_objects/migrations/core/elastic_index.ts b/src/server/saved_objects/migrations/core/elastic_index.ts index 15a6d2519951..6fd9a60cf2dc 100644 --- a/src/server/saved_objects/migrations/core/elastic_index.ts +++ b/src/server/saved_objects/migrations/core/elastic_index.ts @@ -65,7 +65,7 @@ export async function fetchInfo(callCluster: CallCluster, index: string): Promis const [indexName, indexInfo] = Object.entries(result)[0]; - return assertIsSupportedIndex({ ...indexInfo, exists: true, indexName }); + return assertIsSupportedIndex({ ...normalizeV6AndV7(indexInfo), exists: true, indexName }); } /** @@ -287,6 +287,26 @@ export async function claimAlias( await callCluster('indices.refresh', { index }); } +/** + * ES7 removed the "doc" property from mappings. This function takes a v6 or v7 + * index info object and returns an object in v6 form. + */ +function normalizeV6AndV7(indexInfo: FullIndexInfo) { + const mappings = indexInfo.mappings as any; + const isV7Index = !mappings.doc && mappings.dynamic && mappings.properties; + + if (!isV7Index) { + return indexInfo; + } + + return { + ...indexInfo, + mappings: { + doc: mappings, + }, + }; +} + /** * This is a rough check to ensure that the index being migrated satisfies at least * some rudimentary expectations. Past Kibana indices had multiple root documents, etc @@ -296,7 +316,7 @@ export async function claimAlias( * * @param {FullIndexInfo} indexInfo */ -async function assertIsSupportedIndex(indexInfo: FullIndexInfo) { +function assertIsSupportedIndex(indexInfo: FullIndexInfo) { const currentTypes = getTypes(indexInfo.mappings); const isV5Index = currentTypes.length > 1 || currentTypes[0] !== ROOT_TYPE; if (isV5Index) { From cbe3a4508365f5d49dab662195503aca59b2e992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Thu, 10 Jan 2019 16:56:54 +0100 Subject: [PATCH 21/21] [APM] Fix agent status check (#28254) --- .../kibana/server/tutorials/apm/envs/on_prem.js | 11 ++++++----- .../apm/server/lib/status_check/agent_check.js | 12 +++++++----- .../apm/server/lib/status_check/server_check.js | 1 + 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/on_prem.js b/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/on_prem.js index 4e2dcd5a19a0..9d941d9b4234 100644 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/on_prem.js +++ b/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/on_prem.js @@ -158,11 +158,12 @@ export function onPremInstructions(apmIndexPattern) { index: apmIndexPattern, query: { bool: { - filter: { - exists: { - field: 'processor.name', - }, - }, + should: [ + { term: { 'processor.name': 'error' } }, + { term: { 'processor.name': 'transaction' } }, + { term: { 'processor.name': 'metric' } }, + { term: { 'processor.name': 'sourcemap' } }, + ], }, }, }, diff --git a/x-pack/plugins/apm/server/lib/status_check/agent_check.js b/x-pack/plugins/apm/server/lib/status_check/agent_check.js index 65482791e38e..accd7eb84244 100644 --- a/x-pack/plugins/apm/server/lib/status_check/agent_check.js +++ b/x-pack/plugins/apm/server/lib/status_check/agent_check.js @@ -6,6 +6,7 @@ import { PROCESSOR_NAME } from '../../../common/constants'; +// Note: this logic is duplicated in tutorials/apm/envs/on_prem export async function getAgentStatus({ setup }) { const { client, config } = setup; @@ -18,11 +19,12 @@ export async function getAgentStatus({ setup }) { size: 0, query: { bool: { - filter: { - exists: { - field: PROCESSOR_NAME - } - } + should: [ + { term: { [PROCESSOR_NAME]: 'error' } }, + { term: { [PROCESSOR_NAME]: 'transaction' } }, + { term: { [PROCESSOR_NAME]: 'metric' } }, + { term: { [PROCESSOR_NAME]: 'sourcemap' } } + ] } } } diff --git a/x-pack/plugins/apm/server/lib/status_check/server_check.js b/x-pack/plugins/apm/server/lib/status_check/server_check.js index 6df2135426d2..d13a63adda61 100644 --- a/x-pack/plugins/apm/server/lib/status_check/server_check.js +++ b/x-pack/plugins/apm/server/lib/status_check/server_check.js @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +// Note: this logic is duplicated in tutorials/apm/envs/on_prem export async function getServerStatus({ setup }) { const { client, config } = setup;