diff --git a/docs/apm/error-reports-watcher.asciidoc b/docs/apm/error-reports-watcher.asciidoc deleted file mode 100644 index f41597932b751f..00000000000000 --- a/docs/apm/error-reports-watcher.asciidoc +++ /dev/null @@ -1,18 +0,0 @@ -[role="xpack"] -[[errors-alerts-with-watcher]] -=== Error reports with Watcher - -++++ -Enable error reports -++++ - -You can use the power of the alerting features with Watcher to get reports on error occurrences. -The Watcher assistant, which is available on the errors overview, can help you set up a watch per service. - -Configure the watch with an occurrences threshold, time interval, and the desired actions, such as email or Slack notifications. -With Watcher, your team can set up reports within minutes. - -Watches are managed separately in the dedicated Watcher UI available in Advanced Settings. - -[role="screenshot"] -image::apm/images/apm-errors-watcher-assistant.png[Example view of the Watcher assistant for errors in APM app in Kibana] diff --git a/docs/apm/how-to-guides.asciidoc b/docs/apm/how-to-guides.asciidoc index 9b0efb4f7a3599..9a415375f17fd4 100644 --- a/docs/apm/how-to-guides.asciidoc +++ b/docs/apm/how-to-guides.asciidoc @@ -8,7 +8,6 @@ Learn how to perform common APM app tasks. * <> * <> * <> -* <> * <> * <> * <> @@ -21,8 +20,6 @@ include::apm-alerts.asciidoc[] include::custom-links.asciidoc[] -include::error-reports-watcher.asciidoc[] - include::filters.asciidoc[] include::machine-learning.asciidoc[] diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index c94c8e5c55f853..58687d99627b6d 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -80,3 +80,13 @@ This page was deleted. See <>. == Developing Visualizations This page was deleted. See <>. + +[role="exclude",id="errors-alerts-with-watcher"] +== Error reports with Watcher + +deprecated::[7.9.0] + +Watcher error reports have been removed and replaced with Kibana's <> feature. +To create error alerts with new tool, select **Alerts** - **Create threshold alert** - **Error rate**. + +More information on this new feature is available in <>. diff --git a/x-pack/plugins/infra/server/lib/alerting/common/messages.ts b/x-pack/plugins/infra/server/lib/alerting/common/messages.ts index 4add0ee9af5d3c..18b1460d643d5e 100644 --- a/x-pack/plugins/infra/server/lib/alerting/common/messages.ts +++ b/x-pack/plugins/infra/server/lib/alerting/common/messages.ts @@ -29,6 +29,9 @@ export const stateToAlertMessage = { }), }; +const toNumber = (value: number | string) => + typeof value === 'string' ? parseFloat(value) : value; + const comparatorToI18n = (comparator: Comparator, threshold: number[], currentValue: number) => { const gtText = i18n.translate('xpack.infra.metrics.alerting.threshold.gtComparator', { defaultMessage: 'greater than', @@ -54,10 +57,11 @@ const comparatorToI18n = (comparator: Comparator, threshold: number[], currentVa case Comparator.LT: return ltText; case Comparator.GT_OR_EQ: - case Comparator.LT_OR_EQ: + case Comparator.LT_OR_EQ: { if (threshold[0] === currentValue) return eqText; else if (threshold[0] < currentValue) return ltText; return gtText; + } } }; @@ -88,7 +92,7 @@ const recoveredComparatorToI18n = ( } }; -const thresholdToI18n = ([a, b]: number[]) => { +const thresholdToI18n = ([a, b]: Array) => { if (typeof b === 'undefined') return a; return i18n.translate('xpack.infra.metrics.alerting.threshold.thresholdRange', { defaultMessage: '{a} and {b}', @@ -99,15 +103,15 @@ const thresholdToI18n = ([a, b]: number[]) => { export const buildFiredAlertReason: (alertResult: { metric: string; comparator: Comparator; - threshold: number[]; - currentValue: number; + threshold: Array; + currentValue: number | string; }) => string = ({ metric, comparator, threshold, currentValue }) => i18n.translate('xpack.infra.metrics.alerting.threshold.firedAlertReason', { defaultMessage: '{metric} is {comparator} a threshold of {threshold} (current value is {currentValue})', values: { metric, - comparator: comparatorToI18n(comparator, threshold, currentValue), + comparator: comparatorToI18n(comparator, threshold.map(toNumber), toNumber(currentValue)), threshold: thresholdToI18n(threshold), currentValue, }, @@ -116,15 +120,19 @@ export const buildFiredAlertReason: (alertResult: { export const buildRecoveredAlertReason: (alertResult: { metric: string; comparator: Comparator; - threshold: number[]; - currentValue: number; + threshold: Array; + currentValue: number | string; }) => string = ({ metric, comparator, threshold, currentValue }) => i18n.translate('xpack.infra.metrics.alerting.threshold.recoveredAlertReason', { defaultMessage: '{metric} is now {comparator} a threshold of {threshold} (current value is {currentValue})', values: { metric, - comparator: recoveredComparatorToI18n(comparator, threshold, currentValue), + comparator: recoveredComparatorToI18n( + comparator, + threshold.map(toNumber), + toNumber(currentValue) + ), threshold: thresholdToI18n(threshold), currentValue, }, @@ -150,3 +158,56 @@ export const buildErrorAlertReason = (metric: string) => metric, }, }); + +export const groupActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.groupActionVariableDescription', + { + defaultMessage: 'Name of the group reporting data', + } +); + +export const alertStateActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.alertStateActionVariableDescription', + { + defaultMessage: 'Current state of the alert', + } +); + +export const reasonActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.reasonActionVariableDescription', + { + defaultMessage: + 'A description of why the alert is in this state, including which metrics have crossed which thresholds', + } +); + +export const timestampActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.timestampDescription', + { + defaultMessage: 'A timestamp of when the alert was detected.', + } +); + +export const valueActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.valueActionVariableDescription', + { + defaultMessage: + 'The value of the metric in the specified condition. Usage: (ctx.value.condition0, ctx.value.condition1, etc...).', + } +); + +export const metricActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.metricActionVariableDescription', + { + defaultMessage: + 'The metric name in the specified condition. Usage: (ctx.metric.condition0, ctx.metric.condition1, etc...).', + } +); + +export const thresholdActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.thresholdActionVariableDescription', + { + defaultMessage: + 'The threshold value of the metric for the specified condition. Usage: (ctx.threshold.condition0, ctx.threshold.condition1, etc...).', + } +); diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts index c991e482a62e5b..5c31c78b10fa9a 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts @@ -112,6 +112,8 @@ const getData = async ( try { const { nodes } = await snapshot.getNodes(esClient, options); + if (!nodes.length) return { [UNGROUPED_FACTORY_KEY]: null }; // No Data state + return nodes.reduce((acc, n) => { const nodePathItem = last(n.path) as any; const m = first(n.metrics); diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts index 0a3910f2c5d7c5..60eee49a5010dc 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts @@ -79,6 +79,7 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = const resultWithVerboseMetricName = { ...result[item], metric: toMetricOpt(result[item].metric)?.text || result[item].metric, + currentValue: formatMetric(result[item].metric, result[item].currentValue), }; return buildFiredAlertReason(resultWithVerboseMetricName); }) diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts index fa5277cb09987b..f664a59acd165e 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; import { createInventoryMetricThresholdExecutor, @@ -12,6 +11,15 @@ import { import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, Comparator } from './types'; import { InfraBackendLibs } from '../../infra_types'; import { oneOfLiterals, validateIsStringElasticsearchJSONFilter } from '../common/utils'; +import { + groupActionVariableDescription, + alertStateActionVariableDescription, + reasonActionVariableDescription, + timestampActionVariableDescription, + valueActionVariableDescription, + metricActionVariableDescription, + thresholdActionVariableDescription, +} from '../common/messages'; const condition = schema.object({ threshold: schema.arrayOf(schema.number()), @@ -44,45 +52,13 @@ export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs executor: createInventoryMetricThresholdExecutor(libs), actionVariables: { context: [ - { - name: 'group', - description: i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.groupActionVariableDescription', - { - defaultMessage: 'Name of the group reporting data', - } - ), - }, - { - name: 'valueOf', - description: i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.valueOfActionVariableDescription', - { - defaultMessage: - 'Record of the current value of the watched metric; grouped by condition, i.e valueOf.condition0, valueOf.condition1, etc.', - } - ), - }, - { - name: 'thresholdOf', - description: i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.thresholdOfActionVariableDescription', - { - defaultMessage: - 'Record of the alerting threshold; grouped by condition, i.e thresholdOf.condition0, thresholdOf.condition1, etc.', - } - ), - }, - { - name: 'metricOf', - description: i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.metricOfActionVariableDescription', - { - defaultMessage: - 'Record of the watched metric; grouped by condition, i.e metricOf.condition0, metricOf.condition1, etc.', - } - ), - }, + { name: 'group', description: groupActionVariableDescription }, + { name: 'alertState', description: alertStateActionVariableDescription }, + { name: 'reason', description: reasonActionVariableDescription }, + { name: 'timestamp', description: timestampActionVariableDescription }, + { name: 'value', description: valueActionVariableDescription }, + { name: 'metric', description: metricActionVariableDescription }, + { name: 'threshold', description: thresholdActionVariableDescription }, ], }, }); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts index d862f70c47caec..ca46f6cc16547a 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts @@ -67,10 +67,13 @@ export const evaluateAlert = ( currentValue: Array.isArray(points) ? last(points)?.value : NaN, timestamp: Array.isArray(points) ? last(points)?.key : NaN, shouldFire: Array.isArray(points) - ? points.map((point) => comparisonFunction(point.value, threshold)) + ? points.map( + (point) => + typeof point.value === 'number' && comparisonFunction(point.value, threshold) + ) : [false], - isNoData: points === null, - isError: isNaN(points), + isNoData: (Array.isArray(points) ? last(points)?.value : points) === null, + isError: isNaN(Array.isArray(points) ? last(points)?.value : points), }; }); }) @@ -172,7 +175,7 @@ const getValuesFromAggregations = ( } return buckets.map((bucket) => ({ key: bucket.key_as_string, - value: bucket.aggregatedValue.value, + value: bucket.aggregatedValue?.value ?? null, })); } catch (e) { return NaN; // Error state diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts index 9a46925a51762e..fa705798baf7a2 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts @@ -318,6 +318,31 @@ describe('The metric threshold alert type', () => { }); }); + describe("querying a rate-aggregated metric that hasn't reported data", () => { + const instanceID = '*'; + const execute = () => + executor({ + services, + params: { + criteria: [ + { + ...baseCriterion, + comparator: Comparator.GT, + threshold: 1, + metric: 'test.metric.3', + aggType: 'rate', + }, + ], + alertOnNoData: true, + }, + }); + test('sends a No Data alert', async () => { + await execute(); + expect(mostRecentAction(instanceID).id).toBe(FIRED_ACTIONS.id); + expect(getState(instanceID).alertState).toBe(AlertStates.NO_DATA); + }); + }); + // describe('querying a metric that later recovers', () => { // const instanceID = '*'; // const execute = (threshold: number[]) => @@ -401,7 +426,9 @@ services.callCluster.mockImplementation(async (_: string, { body, index }: any) if (metric === 'test.metric.2') { return mocks.alternateMetricResponse; } else if (metric === 'test.metric.3') { - return mocks.emptyMetricResponse; + return body.aggs.aggregatedIntervals.aggregations.aggregatedValue_max + ? mocks.emptyRateResponse + : mocks.emptyMetricResponse; } return mocks.basicMetricResponse; }); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts index 51a127e9345b44..45b1df2f03ea11 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts @@ -3,13 +3,21 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; import { METRIC_EXPLORER_AGGREGATIONS } from '../../../../common/http_api/metrics_explorer'; import { createMetricThresholdExecutor, FIRED_ACTIONS } from './metric_threshold_executor'; import { METRIC_THRESHOLD_ALERT_TYPE_ID, Comparator } from './types'; import { InfraBackendLibs } from '../../infra_types'; import { oneOfLiterals, validateIsStringElasticsearchJSONFilter } from '../common/utils'; +import { + groupActionVariableDescription, + alertStateActionVariableDescription, + reasonActionVariableDescription, + timestampActionVariableDescription, + valueActionVariableDescription, + metricActionVariableDescription, + thresholdActionVariableDescription, +} from '../common/messages'; export function registerMetricThresholdAlertType(libs: InfraBackendLibs) { const baseCriterion = { @@ -31,59 +39,6 @@ export function registerMetricThresholdAlertType(libs: InfraBackendLibs) { metric: schema.never(), }); - const groupActionVariableDescription = i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.groupActionVariableDescription', - { - defaultMessage: 'Name of the group reporting data', - } - ); - - const alertStateActionVariableDescription = i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.alertStateActionVariableDescription', - { - defaultMessage: 'Current state of the alert', - } - ); - - const reasonActionVariableDescription = i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.reasonActionVariableDescription', - { - defaultMessage: - 'A description of why the alert is in this state, including which metrics have crossed which thresholds', - } - ); - - const timestampActionVariableDescription = i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.timestampDescription', - { - defaultMessage: 'A timestamp of when the alert was detected.', - } - ); - - const valueActionVariableDescription = i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.valueActionVariableDescription', - { - defaultMessage: - 'The value of the metric in the specified condition. Usage: (ctx.value.condition0, ctx.value.condition1, etc...).', - } - ); - - const metricActionVariableDescription = i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.metricActionVariableDescription', - { - defaultMessage: - 'The metric name in the specified condition. Usage: (ctx.metric.condition0, ctx.metric.condition1, etc...).', - } - ); - - const thresholdActionVariableDescription = i18n.translate( - 'xpack.infra.metrics.alerting.threshold.alerting.thresholdActionVariableDescription', - { - defaultMessage: - 'The threshold value of the metric for the specified condition. Usage: (ctx.threshold.condition0, ctx.threshold.condition1, etc...).', - } - ); - return { id: METRIC_THRESHOLD_ALERT_TYPE_ID, name: 'Metric threshold', diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/test_mocks.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/test_mocks.ts index c7e53eb2008f54..5c2f76cea87c4b 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/test_mocks.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/test_mocks.ts @@ -62,6 +62,19 @@ export const emptyMetricResponse = { }, }; +export const emptyRateResponse = { + aggregations: { + aggregatedIntervals: { + buckets: [ + { + doc_count: 2, + aggregatedValue_max: { value: null }, + }, + ], + }, + }, +}; + export const basicCompositeResponse = { aggregations: { groupings: { diff --git a/x-pack/plugins/infra/server/lib/snapshot/response_helpers.test.ts b/x-pack/plugins/infra/server/lib/snapshot/response_helpers.test.ts index 20220aef1133df..74840afc157d25 100644 --- a/x-pack/plugins/infra/server/lib/snapshot/response_helpers.test.ts +++ b/x-pack/plugins/infra/server/lib/snapshot/response_helpers.test.ts @@ -4,7 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isIPv4, getIPFromBucket, InfraSnapshotNodeGroupByBucket } from './response_helpers'; +import { + isIPv4, + getIPFromBucket, + InfraSnapshotNodeGroupByBucket, + getMetricValueFromBucket, + InfraSnapshotMetricsBucket, +} from './response_helpers'; describe('InfraOps ResponseHelpers', () => { describe('isIPv4', () => { @@ -74,4 +80,40 @@ describe('InfraOps ResponseHelpers', () => { expect(getIPFromBucket('host', bucket)).toBe(null); }); }); + + describe('getMetricValueFromBucket', () => { + it('should return the value of a bucket with data', () => { + expect(getMetricValueFromBucket('custom', testBucket, 1)).toBe(0.5); + }); + it('should return the normalized value of a bucket with data', () => { + expect(getMetricValueFromBucket('cpu', testNormalizedBucket, 1)).toBe(50); + }); + it('should return null for a bucket with no data', () => { + expect(getMetricValueFromBucket('custom', testEmptyBucket, 1)).toBe(null); + }); + }); }); + +// Hack to get around TypeScript +const buckets = [ + { + key: 'a', + doc_count: 1, + custom_1: { + value: 0.5, + }, + }, + { + key: 'b', + doc_count: 1, + cpu: { + value: 0.5, + normalized_value: 50, + }, + }, + { + key: 'c', + doc_count: 0, + }, +] as InfraSnapshotMetricsBucket[]; +const [testBucket, testNormalizedBucket, testEmptyBucket] = buckets; diff --git a/x-pack/plugins/infra/server/lib/snapshot/response_helpers.ts b/x-pack/plugins/infra/server/lib/snapshot/response_helpers.ts index 317a7da95ce6b7..646ce9f2409af9 100644 --- a/x-pack/plugins/infra/server/lib/snapshot/response_helpers.ts +++ b/x-pack/plugins/infra/server/lib/snapshot/response_helpers.ts @@ -158,14 +158,15 @@ const findLastFullBucket = ( }, last(buckets)); }; -const getMetricValueFromBucket = ( +export const getMetricValueFromBucket = ( type: SnapshotMetricType, bucket: InfraSnapshotMetricsBucket, index: number ) => { const key = type === 'custom' ? `custom_${index}` : type; const metric = bucket[key]; - return (metric && (metric.normalized_value || metric.value)) || 0; + const value = metric && (metric.normalized_value || metric.value); + return isFinite(value) ? value : null; }; function calculateMax( diff --git a/x-pack/plugins/maps/public/actions/data_request_actions.ts b/x-pack/plugins/maps/public/actions/data_request_actions.ts index 5919feadfcc2ad..f91e272d625f69 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -40,7 +40,7 @@ import { ILayer } from '../classes/layers/layer'; import { IVectorLayer } from '../classes/layers/vector_layer/vector_layer'; import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types'; import { DataRequestAbortError } from '../classes/util/data_request'; -import { scaleBounds } from '../elasticsearch_geo_utils'; +import { scaleBounds, turfBboxToBounds } from '../elasticsearch_geo_utils'; const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1; @@ -368,13 +368,7 @@ export function fitToDataBounds() { return; } - const turfUnionBbox = turf.bbox(turf.multiPoint(corners)); - const dataBounds = { - minLon: turfUnionBbox[0], - minLat: turfUnionBbox[1], - maxLon: turfUnionBbox[2], - maxLat: turfUnionBbox[3], - }; + const dataBounds = turfBboxToBounds(turf.bbox(turf.multiPoint(corners))); dispatch(setGotoWithBounds(scaleBounds(dataBounds, FIT_TO_BOUNDS_SCALE_FACTOR))); }; diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js index 98db7bcdcc8a30..33d5deef2e39f2 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js @@ -6,6 +6,7 @@ import React from 'react'; import uuid from 'uuid/v4'; +import turf from 'turf'; import { UpdateSourceEditor } from './update_source_editor'; import { i18n } from '@kbn/i18n'; @@ -13,8 +14,9 @@ import { SOURCE_TYPES, VECTOR_SHAPE_TYPE } from '../../../../common/constants'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { convertToLines } from './convert_to_lines'; import { AbstractESAggSource, DEFAULT_METRIC } from '../es_agg_source'; -import { indexPatterns } from '../../../../../../../src/plugins/data/public'; import { registerSource } from '../source_registry'; +import { turfBboxToBounds } from '../../../elasticsearch_geo_utils'; +import { DataRequestAbortError } from '../../util/data_request'; const MAX_GEOTILE_LEVEL = 29; @@ -158,19 +160,63 @@ export class ESPewPewSource extends AbstractESAggSource { }; } - async _getGeoField() { - const indexPattern = await this.getIndexPattern(); - const field = indexPattern.fields.getByName(this._descriptor.destGeoField); - const geoField = indexPatterns.isNestedField(field) ? undefined : field; - if (!geoField) { - throw new Error( - i18n.translate('xpack.maps.source.esSource.noGeoFieldErrorMessage', { - defaultMessage: `Index pattern {indexPatternTitle} no longer contains the geo field {geoField}`, - values: { indexPatternTitle: indexPattern.title, geoField: this._descriptor.geoField }, - }) - ); + getGeoFieldName() { + return this._descriptor.destGeoField; + } + + async getBoundsForFilters(boundsFilters, registerCancelCallback) { + const searchSource = await this.makeSearchSource(boundsFilters, 0); + searchSource.setField('aggs', { + destFitToBounds: { + geo_bounds: { + field: this._descriptor.destGeoField, + }, + }, + sourceFitToBounds: { + geo_bounds: { + field: this._descriptor.sourceGeoField, + }, + }, + }); + + const corners = []; + try { + const abortController = new AbortController(); + registerCancelCallback(() => abortController.abort()); + const esResp = await searchSource.fetch({ abortSignal: abortController.signal }); + if (esResp.aggregations.destFitToBounds.bounds) { + corners.push([ + esResp.aggregations.destFitToBounds.bounds.top_left.lon, + esResp.aggregations.destFitToBounds.bounds.top_left.lat, + ]); + corners.push([ + esResp.aggregations.destFitToBounds.bounds.bottom_right.lon, + esResp.aggregations.destFitToBounds.bounds.bottom_right.lat, + ]); + } + if (esResp.aggregations.sourceFitToBounds.bounds) { + corners.push([ + esResp.aggregations.sourceFitToBounds.bounds.top_left.lon, + esResp.aggregations.sourceFitToBounds.bounds.top_left.lat, + ]); + corners.push([ + esResp.aggregations.sourceFitToBounds.bounds.bottom_right.lon, + esResp.aggregations.sourceFitToBounds.bounds.bottom_right.lat, + ]); + } + } catch (error) { + if (error.name === 'AbortError') { + throw new DataRequestAbortError(); + } + + return null; + } + + if (corners.length === 0) { + return null; } - return geoField; + + return turfBboxToBounds(turf.bbox(turf.multiPoint(corners))); } canFormatFeatureProperties() { diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js index 450894d81485c2..c043e6d6994ab2 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js @@ -150,7 +150,7 @@ export class AbstractESSource extends AbstractVectorSource { searchSource.setField('aggs', { fitToBounds: { geo_bounds: { - field: this._descriptor.geoField, + field: this.getGeoFieldName(), }, }, }); @@ -230,12 +230,12 @@ export class AbstractESSource extends AbstractVectorSource { async _getGeoField() { const indexPattern = await this.getIndexPattern(); - const geoField = indexPattern.fields.getByName(this._descriptor.geoField); + const geoField = indexPattern.fields.getByName(this.getGeoFieldName()); if (!geoField) { throw new Error( i18n.translate('xpack.maps.source.esSource.noGeoFieldErrorMessage', { defaultMessage: `Index pattern {indexPatternTitle} no longer contains the geo field {geoField}`, - values: { indexPatternTitle: indexPattern.title, geoField: this._descriptor.geoField }, + values: { indexPatternTitle: indexPattern.title, geoField: this.getGeoFieldName() }, }) ); } diff --git a/x-pack/plugins/maps/public/connected_components/_index.scss b/x-pack/plugins/maps/public/connected_components/_index.scss index bd8070e8c36fdb..a952b3b5459227 100644 --- a/x-pack/plugins/maps/public/connected_components/_index.scss +++ b/x-pack/plugins/maps/public/connected_components/_index.scss @@ -1,4 +1,4 @@ -@import 'gis_map/gis_map'; +@import 'map_container/map_container'; @import 'layer_panel/index'; @import 'widget_overlay/index'; @import 'toolbar_overlay/index'; diff --git a/x-pack/plugins/maps/public/connected_components/gis_map/index.d.ts b/x-pack/plugins/maps/public/connected_components/gis_map/index.d.ts deleted file mode 100644 index 3f3fa48b3d7692..00000000000000 --- a/x-pack/plugins/maps/public/connected_components/gis_map/index.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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 React from 'react'; -import { Filter } from 'src/plugins/data/public'; - -import { RenderToolTipContent } from '../../classes/tooltips/tooltip_property'; - -declare const GisMap: React.ComponentType<{ - addFilters: ((filters: Filter[]) => void) | null; - renderTooltipContent?: RenderToolTipContent; -}>; - -export { GisMap }; -// eslint-disable-next-line import/no-default-export -export default GisMap; diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/index.js b/x-pack/plugins/maps/public/connected_components/map/mb/index.js index 189d6bc1f0a438..4b8df07bd1f391 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/index.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/index.js @@ -5,7 +5,7 @@ */ import { connect } from 'react-redux'; -import { MBMapContainer } from './view'; +import { MBMap } from './view'; import { mapExtentChanged, mapReady, @@ -72,7 +72,7 @@ function mapDispatchToProps(dispatch) { }; } -const connectedMBMapContainer = connect(mapStateToProps, mapDispatchToProps, null, { +const connectedMBMap = connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true, -})(MBMapContainer); -export { connectedMBMapContainer as MBMapContainer }; +})(MBMap); +export { connectedMBMap as MBMap }; diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/plugins/maps/public/connected_components/map/mb/view.js index d96deb226744bb..d85959c3a08a4b 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/view.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/view.js @@ -26,7 +26,7 @@ import { getPreserveDrawingBuffer } from '../../../kibana_services'; mapboxgl.workerUrl = mbWorkerUrl; mapboxgl.setRTLTextPlugin(mbRtlPlugin); -export class MBMapContainer extends React.Component { +export class MBMap extends React.Component { state = { prevLayerList: undefined, hasSyncedLayerList: false, diff --git a/x-pack/plugins/maps/public/connected_components/gis_map/_gis_map.scss b/x-pack/plugins/maps/public/connected_components/map_container/_map_container.scss similarity index 100% rename from x-pack/plugins/maps/public/connected_components/gis_map/_gis_map.scss rename to x-pack/plugins/maps/public/connected_components/map_container/_map_container.scss diff --git a/x-pack/plugins/maps/public/connected_components/gis_map/index.js b/x-pack/plugins/maps/public/connected_components/map_container/index.ts similarity index 68% rename from x-pack/plugins/maps/public/connected_components/gis_map/index.js rename to x-pack/plugins/maps/public/connected_components/map_container/index.ts index b462c8aa4c02db..c3b49f1e807ebf 100644 --- a/x-pack/plugins/maps/public/connected_components/gis_map/index.js +++ b/x-pack/plugins/maps/public/connected_components/map_container/index.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +import { AnyAction, Dispatch } from 'redux'; import { connect } from 'react-redux'; -import { GisMap as UnconnectedGisMap } from './view'; +import { MapContainer } from './map_container'; import { getFlyoutDisplay, getIsFullScreen } from '../../selectors/ui_selectors'; import { triggerRefreshTimer, cancelAllInFlightRequests, exitFullScreen } from '../../actions'; import { @@ -15,10 +16,10 @@ import { getQueryableUniqueIndexPatternIds, isToolbarOverlayHidden, } from '../../selectors/map_selectors'; - +import { MapStoreState } from '../../reducers/store'; import { getCoreChrome } from '../../kibana_services'; -function mapStateToProps(state = {}) { +function mapStateToProps(state: MapStoreState) { return { areLayersLoaded: areLayersLoaded(state), flyoutDisplay: getFlyoutDisplay(state), @@ -30,17 +31,16 @@ function mapStateToProps(state = {}) { }; } -function mapDispatchToProps(dispatch) { +function mapDispatchToProps(dispatch: Dispatch) { return { - triggerRefreshTimer: () => dispatch(triggerRefreshTimer()), + triggerRefreshTimer: () => dispatch(triggerRefreshTimer()), exitFullScreen: () => { dispatch(exitFullScreen()); getCoreChrome().setIsVisible(true); }, - cancelAllInFlightRequests: () => dispatch(cancelAllInFlightRequests()), + cancelAllInFlightRequests: () => dispatch(cancelAllInFlightRequests()), }; } -const connectedGisMap = connect(mapStateToProps, mapDispatchToProps)(UnconnectedGisMap); -export { connectedGisMap as GisMap }; // GisMap is pulled in by name by the Maps-app itself -export default connectedGisMap; //lazy-loading in the embeddable requires default export +const connected = connect(mapStateToProps, mapDispatchToProps)(MapContainer); +export { connected as MapContainer }; diff --git a/x-pack/plugins/maps/public/connected_components/gis_map/view.js b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx similarity index 70% rename from x-pack/plugins/maps/public/connected_components/gis_map/view.js rename to x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx index 7199620d69fcf4..beb1eb0947c50e 100644 --- a/x-pack/plugins/maps/public/connected_components/gis_map/view.js +++ b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx @@ -7,27 +7,63 @@ import _ from 'lodash'; import React, { Component } from 'react'; import classNames from 'classnames'; -import { MBMapContainer } from '../map/mb'; +import { EuiFlexGroup, EuiFlexItem, EuiCallOut } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import uuid from 'uuid/v4'; +import { Filter } from 'src/plugins/data/public'; +// @ts-expect-error +import { MBMap } from '../map/mb'; +// @ts-expect-error import { WidgetOverlay } from '../widget_overlay'; +// @ts-expect-error import { ToolbarOverlay } from '../toolbar_overlay'; +// @ts-expect-error import { LayerPanel } from '../layer_panel'; import { AddLayerPanel } from '../add_layer_panel'; -import { EuiFlexGroup, EuiFlexItem, EuiCallOut } from '@elastic/eui'; import { ExitFullScreenButton } from '../../../../../../src/plugins/kibana_react/public'; import { getIndexPatternsFromIds } from '../../index_pattern_util'; import { ES_GEO_FIELD_TYPE } from '../../../common/constants'; import { indexPatterns as indexPatternsUtils } from '../../../../../../src/plugins/data/public'; -import { i18n } from '@kbn/i18n'; -import uuid from 'uuid/v4'; import { FLYOUT_STATE } from '../../reducers/ui'; import { MapSettingsPanel } from '../map_settings_panel'; import { registerLayerWizards } from '../../classes/layers/load_layer_wizards'; +import { RenderToolTipContent } from '../../classes/tooltips/tooltip_property'; +import { GeoFieldWithIndex } from '../../components/geo_field_with_index'; +import { MapRefreshConfig } from '../../../common/descriptor_types'; import 'mapbox-gl/dist/mapbox-gl.css'; const RENDER_COMPLETE_EVENT = 'renderComplete'; -export class GisMap extends Component { - state = { +interface Props { + addFilters: ((filters: Filter[]) => void) | null; + areLayersLoaded: boolean; + cancelAllInFlightRequests: () => void; + exitFullScreen: () => void; + flyoutDisplay: FLYOUT_STATE; + hideToolbarOverlay: boolean; + isFullScreen: boolean; + indexPatternIds: string[]; + mapInitError: string | null | undefined; + refreshConfig: MapRefreshConfig; + renderTooltipContent?: RenderToolTipContent; + triggerRefreshTimer: () => void; +} + +interface State { + isInitialLoadRenderTimeoutComplete: boolean; + domId: string; + geoFields: GeoFieldWithIndex[]; +} + +export class MapContainer extends Component { + private _isMounted: boolean = false; + private _isInitalLoadRenderTimerStarted: boolean = false; + private _prevIndexPatternIds: string[] = []; + private _refreshTimerId: number | null = null; + private _prevIsPaused: boolean | null = null; + private _prevInterval: number | null = null; + + state: State = { isInitialLoadRenderTimeoutComplete: false, domId: uuid(), geoFields: [], @@ -35,7 +71,6 @@ export class GisMap extends Component { componentDidMount() { this._isMounted = true; - this._isInitalLoadRenderTimerStarted = false; this._setRefreshTimer(); registerLayerWizards(); } @@ -73,7 +108,7 @@ export class GisMap extends Component { } }; - _loadGeoFields = async (nextIndexPatternIds) => { + _loadGeoFields = async (nextIndexPatternIds: string[]) => { if (_.isEqual(nextIndexPatternIds, this._prevIndexPatternIds)) { // all ready loaded index pattern ids return; @@ -81,29 +116,24 @@ export class GisMap extends Component { this._prevIndexPatternIds = nextIndexPatternIds; - const geoFields = []; - try { - const indexPatterns = await getIndexPatternsFromIds(nextIndexPatternIds); - indexPatterns.forEach((indexPattern) => { - indexPattern.fields.forEach((field) => { - if ( - !indexPatternsUtils.isNestedField(field) && - (field.type === ES_GEO_FIELD_TYPE.GEO_POINT || - field.type === ES_GEO_FIELD_TYPE.GEO_SHAPE) - ) { - geoFields.push({ - geoFieldName: field.name, - geoFieldType: field.type, - indexPatternTitle: indexPattern.title, - indexPatternId: indexPattern.id, - }); - } - }); + const geoFields: GeoFieldWithIndex[] = []; + const indexPatterns = await getIndexPatternsFromIds(nextIndexPatternIds); + indexPatterns.forEach((indexPattern) => { + indexPattern.fields.forEach((field) => { + if ( + indexPattern.id && + !indexPatternsUtils.isNestedField(field) && + (field.type === ES_GEO_FIELD_TYPE.GEO_POINT || field.type === ES_GEO_FIELD_TYPE.GEO_SHAPE) + ) { + geoFields.push({ + geoFieldName: field.name, + geoFieldType: field.type, + indexPatternTitle: indexPattern.title, + indexPatternId: indexPattern.id, + }); + } }); - } catch (e) { - // swallow errors. - // the Layer-TOC will indicate which layers are disfunctional on a per-layer basis - } + }); if (!this._isMounted) { return; @@ -115,33 +145,34 @@ export class GisMap extends Component { _setRefreshTimer = () => { const { isPaused, interval } = this.props.refreshConfig; - if (this.isPaused === isPaused && this.interval === interval) { + if (this._prevIsPaused === isPaused && this._prevInterval === interval) { // refreshConfig is the same, nothing to do return; } - this.isPaused = isPaused; - this.interval = interval; + this._prevIsPaused = isPaused; + this._prevInterval = interval; this._clearRefreshTimer(); if (!isPaused && interval > 0) { - this.refreshTimerId = setInterval(() => { + this._refreshTimerId = window.setInterval(() => { this.props.triggerRefreshTimer(); }, interval); } }; _clearRefreshTimer = () => { - if (this.refreshTimerId) { - clearInterval(this.refreshTimerId); + if (this._refreshTimerId) { + window.clearInterval(this._refreshTimerId); + this._refreshTimerId = null; } }; // Mapbox does not provide any feedback when rendering is complete. // Temporary solution is just to wait set period of time after data has loaded. _startInitialLoadRenderTimer = () => { - setTimeout(() => { + window.setTimeout(() => { if (this._isMounted) { this.setState({ isInitialLoadRenderTimeoutComplete: true }); this._onInitialLoadRenderComplete(); @@ -159,8 +190,6 @@ export class GisMap extends Component { renderTooltipContent, } = this.props; - const { domId } = this.state; - if (mapInitError) { return (
@@ -194,12 +223,12 @@ export class GisMap extends Component { - import('../connected_components/gis_map')); export class MapEmbeddable extends Embeddable { type = MAP_SAVED_OBJECT_TYPE; @@ -223,12 +222,10 @@ export class MapEmbeddable extends Embeddable - }> - - + , this._domNode diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js index bccfdbf2467d66..b26c44df251047 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js +++ b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js @@ -30,7 +30,7 @@ import { import { AppStateManager } from '../../state_syncing/app_state_manager'; import { useAppStateSyncing } from '../../state_syncing/app_sync'; import { esFilters } from '../../../../../../../src/plugins/data/public'; -import { GisMap } from '../../../connected_components/gis_map'; +import { MapContainer } from '../../../connected_components/map_container'; import { goToSpecifiedPath } from '../../maps_router'; const unsavedChangesWarning = i18n.translate('xpack.maps.breadCrumbs.unsavedChangesWarning', { @@ -464,7 +464,7 @@ export class MapsAppView extends React.Component { {this._renderTopNav()}

{`screenTitle placeholder`}

- { newFilters.forEach((filter) => { filter.$state = { store: esFilters.FilterStateStore.APP_STATE }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.tsx index 7b39b986eb0e60..010aa7b8513b5d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.tsx @@ -424,7 +424,7 @@ export const CloneButton: FC = ({ isDisabled, onClick }) => { iconType="copy" isDisabled={isDisabled} onClick={onClick} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx index c83fb6cbac387a..2bc3935c3b9f1d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx @@ -30,7 +30,7 @@ export const DeleteButton: FC = ({ isDisabled, item, onClick iconType="trash" isDisabled={isDisabled} onClick={onClick} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_edit/edit_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_edit/edit_button.tsx index 764b421821ad0d..e17862bf326f1a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_edit/edit_button.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_edit/edit_button.tsx @@ -29,7 +29,7 @@ export const EditButton: FC = ({ isDisabled, onClick }) => { iconType="pencil" isDisabled={isDisabled} onClick={onClick} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button.tsx index 3192a30f8312e0..98b9279d8469a1 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button.tsx @@ -38,7 +38,7 @@ export const StartButton: FC = ({ iconType="play" isDisabled={isDisabled} onClick={onClick} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/stop_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/stop_button.tsx index a3e8f16daf5efe..3bac183d9f3913 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/stop_button.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/stop_button.tsx @@ -33,7 +33,7 @@ export const StopButton: FC = ({ isDisabled, item, onClick }) = iconType="stop" isDisabled={isDisabled} onClick={onClick} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx index bed5c8961d45ab..2a6b365c0ca07f 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx @@ -40,7 +40,7 @@ export const ViewButton: FC = ({ item }) => { iconType="visTable" isDisabled={buttonDisabled} onClick={onClickHandler} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/clone_button.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/clone_button.tsx index 2b5ffa27e0f82a..7b371d35f8d4cb 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/clone_button.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/clone_button.tsx @@ -44,7 +44,7 @@ export const CloneButton: FC = ({ itemId }) => { iconType="copy" isDisabled={buttonDisabled} onClick={clickHandler} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/__snapshots__/delete_button.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/__snapshots__/delete_button.test.tsx.snap index 7e98fc90cfad4e..8d4568c5ce20e3 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/__snapshots__/delete_button.test.tsx.snap +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/__snapshots__/delete_button.test.tsx.snap @@ -14,7 +14,7 @@ exports[`Transform: Transform List Actions Minimal initializati iconType="trash" isDisabled={true} onClick={[Function]} - size="s" + size="xs" > Delete diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.tsx index 2ca48ed734c7f4..dc6ddcfc45a117 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.tsx @@ -56,7 +56,7 @@ export const DeleteButton: FC = ({ items, forceDisable, onCli iconType="trash" isDisabled={buttonDisabled} onClick={() => onClick(items)} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx index 40c27cff1e398f..7bae8807425fcb 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx @@ -36,7 +36,7 @@ export const EditButton: FC = ({ onClick }) => { iconType="pencil" isDisabled={buttonDisabled} onClick={onClick} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/__snapshots__/start_button.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/__snapshots__/start_button.test.tsx.snap index d8184773e16b59..543f8f9dfcffe6 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/__snapshots__/start_button.test.tsx.snap +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/__snapshots__/start_button.test.tsx.snap @@ -14,7 +14,7 @@ exports[`Transform: Transform List Actions Minimal initializatio iconType="play" isDisabled={true} onClick={[Function]} - size="s" + size="xs" > Start diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.tsx index 60f899adc5fb2b..7f5595043b775e 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.tsx @@ -95,7 +95,7 @@ export const StartButton: FC = ({ items, forceDisable, onClick iconType="play" isDisabled={buttonDisabled} onClick={() => onClick(items)} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/__snapshots__/stop_button.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/__snapshots__/stop_button.test.tsx.snap index 0052dc62547898..646162d370ac67 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/__snapshots__/stop_button.test.tsx.snap +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/__snapshots__/stop_button.test.tsx.snap @@ -14,7 +14,7 @@ exports[`Transform: Transform List Actions Minimal initialization iconType="stop" isDisabled={true} onClick={[Function]} - size="s" + size="xs" > Stop diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/stop_button.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/stop_button.tsx index 3c5e4323cc69a3..1c672193dd1eea 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/stop_button.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/stop_button.tsx @@ -68,7 +68,7 @@ export const StopButton: FC = ({ items, forceDisable }) => { iconType="stop" isDisabled={buttonDisabled} onClick={handleStop} - size="s" + size="xs" > {buttonText} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ccfb07e7add1ff..a1781bbaf17555 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7649,14 +7649,14 @@ "xpack.infra.metrics.alertFlyout.noDataHelpText": "有効にすると、メトリックが想定された期間内にデータを報告しない場合、またはアラートがElasticsearchをクエリできない場合に、アクションをトリガーします", "xpack.infra.metrics.alertFlyout.outsideRangeLabel": "is not between", "xpack.infra.metrics.alertFlyout.removeCondition": "条件を削除", - "xpack.infra.metrics.alerting.inventory.threshold.defaultActionMessage": "\\{\\{alertName\\}\\} - \\{\\{context.group\\}\\}\n\n\\{\\{context.metricOf.condition0\\}\\}はしきい値 \\{\\{context.thresholdOf.condition0\\}\\}を超えました\n現在の値は\\{\\{context.valueOf.condition0\\}\\}です\n", + "xpack.infra.metrics.alerting.inventory.threshold.defaultActionMessage": "\\{\\{alertName\\}\\} - \\{\\{context.group\\}\\}は状態\\{\\{context.alertState\\}\\}です\n\n理由:\n\\{\\{context.reason\\}\\}\n", "xpack.infra.metrics.alerting.inventory.threshold.fired": "実行", - "xpack.infra.metrics.alerting.threshold.alerting.alertStateActionVariableDescription": "現在のアラートの状態", - "xpack.infra.metrics.alerting.threshold.alerting.groupActionVariableDescription": "データを報告するグループの名前", - "xpack.infra.metrics.alerting.threshold.alerting.metricOfActionVariableDescription": "監視されたメトリックのレコード。条件でグループ化されます(metricOf.condition0、metricOf.condition1など)。", - "xpack.infra.metrics.alerting.threshold.alerting.reasonActionVariableDescription": "どのメトリックがどのしきい値を超えたのかを含む、アラートがこの状態である理由に関する説明", - "xpack.infra.metrics.alerting.threshold.alerting.thresholdOfActionVariableDescription": "アラートしきい値のレコード。条件でグループ化されます(thresholdOf.condition0、thresholdOf.condition1など)。", - "xpack.infra.metrics.alerting.threshold.alerting.valueOfActionVariableDescription": "監視されたメトリックの現在の値のレコード。条件でグループ化されます(valueOf.condition0、valueOf.condition1など)。", + "xpack.infra.metrics.alerting.alertStateActionVariableDescription": "現在のアラートの状態", + "xpack.infra.metrics.alerting.groupActionVariableDescription": "データを報告するグループの名前", + "xpack.infra.metrics.alerting.metricActionVariableDescription": "監視されたメトリックのレコード。条件でグループ化されます(metric.condition0、metric.condition1など)。", + "xpack.infra.metrics.alerting.reasonActionVariableDescription": "どのメトリックがどのしきい値を超えたのかを含む、アラートがこの状態である理由に関する説明", + "xpack.infra.metrics.alerting.thresholdActionVariableDescription": "アラートしきい値のレコード。条件でグループ化されます(threshold.condition0、threshold.condition1など)。", + "xpack.infra.metrics.alerting.valueActionVariableDescription": "監視されたメトリックの現在の値のレコード。条件でグループ化されます(value.condition0、value.condition1など)。", "xpack.infra.metrics.alerting.threshold.alertState": "アラート", "xpack.infra.metrics.alerting.threshold.betweenComparator": "の間", "xpack.infra.metrics.alerting.threshold.defaultActionMessage": "\\{\\{alertName\\}\\} - \\{\\{context.group\\}\\}は状態\\{\\{context.alertState\\}\\}です\n\n理由:\n\\{\\{context.reason\\}\\}\n", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e376aab2fbabf2..fab65745bfdece 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7654,14 +7654,14 @@ "xpack.infra.metrics.alertFlyout.noDataHelpText": "启用此选项可在指标在预期的时间段中未报告任何数据时或告警无法查询 Elasticsearch 时触发操作", "xpack.infra.metrics.alertFlyout.outsideRangeLabel": "不介于", "xpack.infra.metrics.alertFlyout.removeCondition": "删除条件", - "xpack.infra.metrics.alerting.inventory.threshold.defaultActionMessage": "\\{\\{alertName\\}\\} - \\{\\{context.group\\}\\}\n\n\\{\\{context.metricOf.condition0\\}\\} 已超过阈值 \\{\\{context.thresholdOf.condition0\\}\\}\n当前值为 \\{\\{context.valueOf.condition0\\}\\}\n", + "xpack.infra.metrics.alerting.inventory.threshold.defaultActionMessage": "\\{\\{alertName\\}\\} - \\{\\{context.group\\}\\} 处于 \\{\\{context.alertState\\}\\} 状态\n\n原因:\n\\{\\{context.reason\\}\\}\n", "xpack.infra.metrics.alerting.inventory.threshold.fired": "已触发", - "xpack.infra.metrics.alerting.threshold.alerting.alertStateActionVariableDescription": "告警的当前状态", - "xpack.infra.metrics.alerting.threshold.alerting.groupActionVariableDescription": "报告数据的组名称", - "xpack.infra.metrics.alerting.threshold.alerting.metricOfActionVariableDescription": "受监视指标的记录;按条件分组,例如按 metricOf.condition0、metricOf.condition1 等。", - "xpack.infra.metrics.alerting.threshold.alerting.reasonActionVariableDescription": "告警处于此状态的原因描述,包括哪个指标超过哪个阈值", - "xpack.infra.metrics.alerting.threshold.alerting.thresholdOfActionVariableDescription": "告警阈值的记录;按条件分组,例如按thresholdOf.condition0、thresholdOf.condition1 等。", - "xpack.infra.metrics.alerting.threshold.alerting.valueOfActionVariableDescription": "受监视指标当前值的记录;按条件分组,例如按 valueOf.condition0、valueOf.condition1 等。", + "xpack.infra.metrics.alerting.alertStateActionVariableDescription": "告警的当前状态", + "xpack.infra.metrics.alerting.groupActionVariableDescription": "报告数据的组名称", + "xpack.infra.metrics.alerting.metricActionVariableDescription": "受监视指标的记录;按条件分组,例如按 metric.condition0、metric.condition1 等。", + "xpack.infra.metrics.alerting.reasonActionVariableDescription": "告警处于此状态的原因描述,包括哪个指标超过哪个阈值", + "xpack.infra.metrics.alerting.thresholdActionVariableDescription": "告警阈值的记录;按条件分组,例如按threshold.condition0、threshold.condition1 等。", + "xpack.infra.metrics.alerting.valueActionVariableDescription": "受监视指标当前值的记录;按条件分组,例如按 value.condition0、value.condition1 等。", "xpack.infra.metrics.alerting.threshold.alertState": "告警", "xpack.infra.metrics.alerting.threshold.betweenComparator": "介于", "xpack.infra.metrics.alerting.threshold.defaultActionMessage": "\\{\\{alertName\\}\\} - \\{\\{context.group\\}\\} 处于 \\{\\{context.alertState\\}\\} 状态\n\n原因:\n\\{\\{context.reason\\}\\}\n", diff --git a/x-pack/test/functional/apps/maps/es_pew_pew_source.js b/x-pack/test/functional/apps/maps/es_pew_pew_source.js index ec02dd2901c7d1..382bde510170fd 100644 --- a/x-pack/test/functional/apps/maps/es_pew_pew_source.js +++ b/x-pack/test/functional/apps/maps/es_pew_pew_source.js @@ -35,5 +35,14 @@ export default function ({ getPageObjects, getService }) { expect(features.length).to.equal(2); expect(features[0].geometry.type).to.equal('LineString'); }); + + it('should fit to bounds', async () => { + // Set view to other side of world so no matching results + await PageObjects.maps.setView(-70, 0, 6); + await PageObjects.maps.clickFitToBounds('connections'); + const { lat, lon } = await PageObjects.maps.getView(); + expect(Math.round(lat)).to.equal(41); + expect(Math.round(lon)).to.equal(-70); + }); }); }