From da8f0127e1a3fc305c4ae02e4d6584014e622ae5 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 2 Jan 2025 16:18:34 +0100 Subject: [PATCH 01/11] [ML] Anomaly Detection: Consolidate severity colors (#204803) ## Summary Part of #140695. We defined the hex codes for anomaly detection severity colors in several places. This PR consolidates this and makes sure the hex codes are defined in just one place. Note this PR doesn't change any of the colors or styling related to anomaly detection, it is pure refactoring to make future updates to these colors more easy. - Renames `BLANK` to `UNKNOWN` to be in line with severity labels. - Uses `ML_SEVERITY_COLORS.*` in test assertions so future color changes won't need updating every assertion. - Migrates all SCSS that made use of severity colors to emotion so it can reuse `ML_SEVERITY_COLORS`. Therefor the SCSS based severity colors get removed in this PR. ### Checklist - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../anomaly_utils/get_severity_color.test.ts | 27 ++-- .../ml/anomaly_utils/get_severity_color.ts | 4 +- .../ml/anomaly_utils/severity_colors.ts | 2 +- .../render_cell_value.test.tsx | 17 ++- .../shared/ml/public/application/_index.scss | 5 +- .../ml/public/application/_variables.scss | 12 -- .../severity_cell/severity_cell.test.tsx | 5 +- .../influencers_list_styles.ts | 18 +-- .../severity_control/severity_control.tsx | 10 +- .../explorer_charts/_explorer_chart.scss | 120 ---------------- .../explorer/explorer_charts/_index.scss | 2 - .../explorer_chart_distribution.js | 3 +- .../explorer_chart_single_metric.js | 12 +- .../explorer_charts/explorer_chart_styles.ts | 131 ++++++++++++++++++ .../explorer_charts_container.js | 5 +- .../explorer_charts_container.test.js | 8 +- .../timeseries_chart/timeseries_chart.js | 14 +- .../application/timeseriesexplorer/styles.ts | 12 +- .../ml/score/create_description_list.tsx | 2 +- .../ml/score/get_score_string.test.ts | 2 +- .../components/ml/score/get_score_string.ts} | 11 +- .../common/components/ml/score/score.tsx | 2 +- .../components/ml/score/score_health.tsx | 44 ------ .../functional/services/ml/anomaly_charts.ts | 2 +- 24 files changed, 222 insertions(+), 248 deletions(-) delete mode 100644 x-pack/platform/plugins/shared/ml/public/application/_variables.scss delete mode 100644 x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/_explorer_chart.scss create mode 100644 x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_styles.ts rename x-pack/{platform/plugins/shared/ml/public/application/styles.ts => solutions/security/plugins/security_solution/public/common/components/ml/score/get_score_string.ts} (52%) delete mode 100644 x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/score_health.tsx diff --git a/x-pack/platform/packages/shared/ml/anomaly_utils/get_severity_color.test.ts b/x-pack/platform/packages/shared/ml/anomaly_utils/get_severity_color.test.ts index 64bf7a5284c89..e91142934359d 100644 --- a/x-pack/platform/packages/shared/ml/anomaly_utils/get_severity_color.test.ts +++ b/x-pack/platform/packages/shared/ml/anomaly_utils/get_severity_color.test.ts @@ -6,36 +6,37 @@ */ import { getSeverityColor } from './get_severity_color'; +import { ML_SEVERITY_COLORS } from './severity_colors'; describe('getSeverityColor', () => { test('returns correct hex code for low for 0 <= score < 3', () => { - expect(getSeverityColor(0)).toBe('#d2e9f7'); - expect(getSeverityColor(0.001)).toBe('#d2e9f7'); - expect(getSeverityColor(2.99)).toBe('#d2e9f7'); + expect(getSeverityColor(0)).toBe(ML_SEVERITY_COLORS.LOW); + expect(getSeverityColor(0.001)).toBe(ML_SEVERITY_COLORS.LOW); + expect(getSeverityColor(2.99)).toBe(ML_SEVERITY_COLORS.LOW); }); test('returns correct hex code for warning for 3 <= score < 25', () => { - expect(getSeverityColor(3)).toBe('#8bc8fb'); - expect(getSeverityColor(24.99)).toBe('#8bc8fb'); + expect(getSeverityColor(3)).toBe(ML_SEVERITY_COLORS.WARNING); + expect(getSeverityColor(24.99)).toBe(ML_SEVERITY_COLORS.WARNING); }); test('returns correct hex code for minor for 25 <= score < 50', () => { - expect(getSeverityColor(25)).toBe('#fdec25'); - expect(getSeverityColor(49.99)).toBe('#fdec25'); + expect(getSeverityColor(25)).toBe(ML_SEVERITY_COLORS.MINOR); + expect(getSeverityColor(49.99)).toBe(ML_SEVERITY_COLORS.MINOR); }); test('returns correct hex code for major for 50 <= score < 75', () => { - expect(getSeverityColor(50)).toBe('#fba740'); - expect(getSeverityColor(74.99)).toBe('#fba740'); + expect(getSeverityColor(50)).toBe(ML_SEVERITY_COLORS.MAJOR); + expect(getSeverityColor(74.99)).toBe(ML_SEVERITY_COLORS.MAJOR); }); test('returns correct hex code for critical for score >= 75', () => { - expect(getSeverityColor(75)).toBe('#fe5050'); - expect(getSeverityColor(100)).toBe('#fe5050'); - expect(getSeverityColor(1000)).toBe('#fe5050'); + expect(getSeverityColor(75)).toBe(ML_SEVERITY_COLORS.CRITICAL); + expect(getSeverityColor(100)).toBe(ML_SEVERITY_COLORS.CRITICAL); + expect(getSeverityColor(1000)).toBe(ML_SEVERITY_COLORS.CRITICAL); }); test('returns correct hex code for unknown for scores less than 0', () => { - expect(getSeverityColor(-10)).toBe('#ffffff'); + expect(getSeverityColor(-10)).toBe(ML_SEVERITY_COLORS.UNKNOWN); }); }); diff --git a/x-pack/platform/packages/shared/ml/anomaly_utils/get_severity_color.ts b/x-pack/platform/packages/shared/ml/anomaly_utils/get_severity_color.ts index f17609ecef5e7..dcc5ac3544e1b 100644 --- a/x-pack/platform/packages/shared/ml/anomaly_utils/get_severity_color.ts +++ b/x-pack/platform/packages/shared/ml/anomaly_utils/get_severity_color.ts @@ -9,7 +9,7 @@ import { ML_ANOMALY_THRESHOLD } from './anomaly_threshold'; import { ML_SEVERITY_COLORS } from './severity_colors'; /** - * Returns a severity RGB color (one of critical, major, minor, warning, low or blank) + * Returns a severity RGB color (one of critical, major, minor, warning, low or unknown) * for the supplied normalized anomaly score (a value between 0 and 100). * @param normalizedScore - A normalized score between 0-100, which is based on the probability of the anomalousness of this record */ @@ -25,6 +25,6 @@ export function getSeverityColor(normalizedScore: number): string { } else if (normalizedScore >= ML_ANOMALY_THRESHOLD.LOW) { return ML_SEVERITY_COLORS.LOW; } else { - return ML_SEVERITY_COLORS.BLANK; + return ML_SEVERITY_COLORS.UNKNOWN; } } diff --git a/x-pack/platform/packages/shared/ml/anomaly_utils/severity_colors.ts b/x-pack/platform/packages/shared/ml/anomaly_utils/severity_colors.ts index e871528463399..67cc59fe46a2b 100644 --- a/x-pack/platform/packages/shared/ml/anomaly_utils/severity_colors.ts +++ b/x-pack/platform/packages/shared/ml/anomaly_utils/severity_colors.ts @@ -38,5 +38,5 @@ export const ML_SEVERITY_COLORS = { /** * Color used in the UI to indicate an anomaly for which the score is unknown. */ - BLANK: '#ffffff', + UNKNOWN: '#ffffff', }; diff --git a/x-pack/platform/plugins/shared/ml/public/alerting/anomaly_detection_alerts_table/render_cell_value.test.tsx b/x-pack/platform/plugins/shared/ml/public/alerting/anomaly_detection_alerts_table/render_cell_value.test.tsx index bba6b909863bb..5df6f4c018ffe 100644 --- a/x-pack/platform/plugins/shared/ml/public/alerting/anomaly_detection_alerts_table/render_cell_value.test.tsx +++ b/x-pack/platform/plugins/shared/ml/public/alerting/anomaly_detection_alerts_table/render_cell_value.test.tsx @@ -5,11 +5,16 @@ * 2.0. */ +import React from 'react'; + import { EuiHealth } from '@elastic/eui'; + import { type FieldFormatsRegistry } from '@kbn/field-formats-plugin/common'; import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; -import React from 'react'; +import { ML_SEVERITY_COLORS } from '@kbn/ml-anomaly-utils'; + import { ALERT_ANOMALY_SCORE } from '../../../common/constants/alerts'; + import { getAlertFormatters } from './render_cell_value'; describe('getAlertFormatters', () => { @@ -19,31 +24,31 @@ describe('getAlertFormatters', () => { test('format anomaly score correctly', () => { expect(alertFormatter(ALERT_ANOMALY_SCORE, 50.3)).toEqual( - + 50 ); expect(alertFormatter(ALERT_ANOMALY_SCORE, '50.3,89.6')).toEqual( - + 89 ); expect(alertFormatter(ALERT_ANOMALY_SCORE, '0.7')).toEqual( - + < 1 ); expect(alertFormatter(ALERT_ANOMALY_SCORE, '0')).toEqual( - + < 1 ); expect(alertFormatter(ALERT_ANOMALY_SCORE, '')).toEqual( - + < 1 ); diff --git a/x-pack/platform/plugins/shared/ml/public/application/_index.scss b/x-pack/platform/plugins/shared/ml/public/application/_index.scss index 91201434b20b1..66b04a8ff0e78 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/_index.scss +++ b/x-pack/platform/plugins/shared/ml/public/application/_index.scss @@ -1,6 +1,3 @@ -// ML has it's own variables for coloring -@import 'variables'; - // Protect the rest of Kibana from ML generic namespacing // SASSTODO: Prefix ml selectors instead .ml-app { @@ -14,4 +11,4 @@ @import 'components/job_selector/index'; @import 'components/rule_editor/index'; // SASSTODO: This file overwrites EUI directly -} \ No newline at end of file +} diff --git a/x-pack/platform/plugins/shared/ml/public/application/_variables.scss b/x-pack/platform/plugins/shared/ml/public/application/_variables.scss deleted file mode 100644 index f81a97cf8c156..0000000000000 --- a/x-pack/platform/plugins/shared/ml/public/application/_variables.scss +++ /dev/null @@ -1,12 +0,0 @@ -$mlColorCritical: #FE5050; -$mlColorMajor: #FBA740; -$mlColorMinor: #FDEC25; -$mlColorWarning: #8BC8FB; -$mlColorLowWarning: #D2E9F7; -$mlColorUnknown: #C0C0C0; - -$mlColorCriticalText: makeHighContrastColor($mlColorCritical, $euiColorEmptyShade); -$mlColorMajorText: makeHighContrastColor($mlColorMajor, $euiColorEmptyShade); -$mlColorMinorText: makeHighContrastColor($mlColorMinor, $euiColorEmptyShade); -$mlColorWarningText: makeHighContrastColor($mlColorWarning, $euiColorEmptyShade); -$mlColorUnknownText: $euiColorDarkShade; diff --git a/x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/severity_cell/severity_cell.test.tsx b/x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/severity_cell/severity_cell.test.tsx index e9166c0c6c28c..25071f30400cb 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/severity_cell/severity_cell.test.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/severity_cell/severity_cell.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { render } from '@testing-library/react'; +import { ML_SEVERITY_COLORS } from '@kbn/ml-anomaly-utils/severity_colors'; import { SeverityCell } from './severity_cell'; describe('SeverityCell', () => { @@ -18,7 +19,7 @@ describe('SeverityCell', () => { const { container } = render(); expect(container.textContent).toBe('75'); const svgEl = container.querySelectorAll('[data-euiicon-type]')[0]; - expect(svgEl && svgEl.getAttribute('color')).toBe('#fe5050'); + expect(svgEl && svgEl.getAttribute('color')).toBe(ML_SEVERITY_COLORS.CRITICAL); }); test('should render a multi-bucket marker with low severity score', () => { @@ -29,6 +30,6 @@ describe('SeverityCell', () => { const { container } = render(); expect(container.textContent).toBe('< 1'); const svgEl = container.getElementsByTagName('svg').item(0); - expect(svgEl && svgEl.getAttribute('fill')).toBe('#d2e9f7'); + expect(svgEl && svgEl.getAttribute('fill')).toBe(ML_SEVERITY_COLORS.LOW); }); }); diff --git a/x-pack/platform/plugins/shared/ml/public/application/components/influencers_list/influencers_list_styles.ts b/x-pack/platform/plugins/shared/ml/public/application/components/influencers_list/influencers_list_styles.ts index d54eb495a0a33..e6cfd5b3f66fa 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/components/influencers_list/influencers_list_styles.ts +++ b/x-pack/platform/plugins/shared/ml/public/application/components/influencers_list/influencers_list_styles.ts @@ -9,7 +9,7 @@ import { css } from '@emotion/react'; import { useEuiFontSize, useEuiTheme } from '@elastic/eui'; -import { mlColors } from '../../styles'; +import { ML_SEVERITY_COLORS } from '@kbn/ml-anomaly-utils'; export const useInfluencersListStyles = () => { const { euiTheme } = useEuiTheme(); @@ -50,12 +50,12 @@ export const useInfluencersListStyles = () => { width: `${barScore}%`, backgroundColor: severity === 'critical' - ? mlColors.critical + ? ML_SEVERITY_COLORS.CRITICAL : severity === 'major' - ? mlColors.major + ? ML_SEVERITY_COLORS.MAJOR : severity === 'minor' - ? mlColors.minor - : mlColors.warning, + ? ML_SEVERITY_COLORS.MINOR + : ML_SEVERITY_COLORS.WARNING, }), scoreLabel: (severity: string) => css({ @@ -67,12 +67,12 @@ export const useInfluencersListStyles = () => { display: 'inline', borderColor: severity === 'critical' - ? mlColors.critical + ? ML_SEVERITY_COLORS.CRITICAL : severity === 'major' - ? mlColors.major + ? ML_SEVERITY_COLORS.MAJOR : severity === 'minor' - ? mlColors.minor - : mlColors.warning, + ? ML_SEVERITY_COLORS.MINOR + : ML_SEVERITY_COLORS.WARNING, }), totalScoreLabel: css({ width: euiTheme.size.xl, diff --git a/x-pack/platform/plugins/shared/ml/public/application/components/severity_control/severity_control.tsx b/x-pack/platform/plugins/shared/ml/public/application/components/severity_control/severity_control.tsx index 1392c38d84507..096b7d263b183 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/components/severity_control/severity_control.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/components/severity_control/severity_control.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import type { EuiRangeProps } from '@elastic/eui'; import { EuiFieldNumber, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiRange } from '@elastic/eui'; -import { ML_ANOMALY_THRESHOLD } from '@kbn/ml-anomaly-utils'; +import { ML_ANOMALY_THRESHOLD, ML_SEVERITY_COLORS } from '@kbn/ml-anomaly-utils'; export interface SeveritySelectorProps { value: number | undefined; @@ -24,22 +24,22 @@ export const SeverityControl: FC = React.memo(({ value, o { min: ML_ANOMALY_THRESHOLD.LOW, max: ML_ANOMALY_THRESHOLD.MINOR, - color: '#8BC8FB', + color: ML_SEVERITY_COLORS.WARNING, }, { min: ML_ANOMALY_THRESHOLD.MINOR, max: ML_ANOMALY_THRESHOLD.MAJOR, - color: '#FDEC25', + color: ML_SEVERITY_COLORS.MINOR, }, { min: ML_ANOMALY_THRESHOLD.MAJOR, max: ML_ANOMALY_THRESHOLD.CRITICAL, - color: '#FBA740', + color: ML_SEVERITY_COLORS.MAJOR, }, { min: ML_ANOMALY_THRESHOLD.CRITICAL, max: MAX_ANOMALY_SCORE, - color: '#FE5050', + color: ML_SEVERITY_COLORS.CRITICAL, }, ]; diff --git a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/_explorer_chart.scss b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/_explorer_chart.scss deleted file mode 100644 index 29967e8db9b3f..0000000000000 --- a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/_explorer_chart.scss +++ /dev/null @@ -1,120 +0,0 @@ -// stylelint-disable selector-no-qualifying-type -.ml-explorer-chart-container { - overflow: hidden; - - .ml-explorer-chart-svg { - font-size: $euiFontSizeXS; - font-family: $euiFontFamily; - - .line-chart { - rect { - fill: $euiColorEmptyShade; - opacity: 1; - } - - rect.selected-interval { - fill: rgba(200, 200, 200, .1); - stroke: $euiColorDarkShade; - stroke-width: calc($euiSizeXS / 2); - stroke-opacity: .8; - } - - rect.scheduled-event-marker { - stroke-width: 1px; - stroke: $euiColorDarkShade; - fill: $euiColorLightShade; - pointer-events: none; - } - } - } - - .axis path, .axis line { - fill: none; - stroke: $euiBorderColor; - shape-rendering: crispEdges; - } - - .axis .tick line.ml-tick-emphasis { - stroke: rgba(0, 0, 0, .2); - } - - .axis text { - fill: $euiColorDarkShade; - } - - .axis .tick line { - stroke: $euiColorLightShade; - stroke-width: 1px; - } - - .values-line { - fill: none; - stroke: $euiColorPrimary; - stroke-width: 2; - } - - .values-dots circle, - .values-dots-circle { - fill: $euiColorPrimary; - stroke-width: 0; - } - - .values-dots circle.values-dots-circle-blur { - fill: $euiColorMediumShade; - } - - .metric-value { - opacity: 1; - fill: transparent; - stroke: $euiColorPrimary; - stroke-width: 0; - } - - .anomaly-marker { - stroke-width: 1px; - stroke: $euiColorMediumShade; - } - - .anomaly-marker:hover { - stroke-width: 6px; - stroke: $euiColorPrimary; - } - - .anomaly-marker.critical { - fill: $mlColorCritical; - } - - .anomaly-marker.major { - fill: $mlColorMajor; - } - - .anomaly-marker.minor { - fill: $mlColorMinor; - } - - .anomaly-marker.warning { - fill: $mlColorWarning; - } - - .anomaly-marker.low { - fill: $mlColorLowWarning; - } - - .metric-value:hover, - .anomaly-marker:hover { - stroke-width: 6px; - stroke-opacity: .65; - } -} - -.ml-explorer-chart { - overflow: hidden; -} - -.ml-explorer-chart-content-wrapper { - height: 215px; -} - -.ml-explorer-chart-axis-emphasis { - font-weight: bold; -} diff --git a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/_index.scss b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/_index.scss index d32d1ce81cd78..62ef4c05e1f7a 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/_index.scss +++ b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/_index.scss @@ -1,3 +1 @@ -@import '../../../application/variables'; @import 'components/explorer_chart_label/index'; -@import 'explorer_chart'; diff --git a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_distribution.js b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_distribution.js index c7fcddbe4c515..0210663103ac5 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_distribution.js +++ b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_distribution.js @@ -47,6 +47,7 @@ import { CHART_HEIGHT, TRANSPARENT_BACKGROUND } from './constants'; import { filter } from 'rxjs'; import { drawCursor } from './utils/draw_anomaly_explorer_charts_cursor'; import { SCHEDULE_EVENT_MARKER_ENTITY } from '../../../../common/constants/charts'; +import { cssMlExplorerChart } from './explorer_chart_styles'; const popoverMenuOffset = 0; const CONTENT_WRAPPER_HEIGHT = 215; @@ -776,7 +777,7 @@ export class ExplorerChartDistribution extends React.Component { )} -
+
{isLoading && } {!isLoading &&
}
diff --git a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_single_metric.js b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_single_metric.js index 1b746647ef38d..9935af37feec6 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_single_metric.js +++ b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_single_metric.js @@ -12,6 +12,7 @@ import PropTypes from 'prop-types'; import React from 'react'; +import { css } from '@emotion/react'; import d3 from 'd3'; import moment from 'moment'; @@ -48,10 +49,15 @@ import { LoadingIndicator } from '../../components/loading_indicator/loading_ind import { CHART_HEIGHT, TRANSPARENT_BACKGROUND } from './constants'; import { filter } from 'rxjs'; import { drawCursor } from './utils/draw_anomaly_explorer_charts_cursor'; +import { cssMlExplorerChart } from './explorer_chart_styles'; const popoverMenuOffset = 0; const CONTENT_WRAPPER_HEIGHT = 215; +// Not used for CSS, but with d3 to select elements. const CONTENT_WRAPPER_CLASS = 'ml-explorer-chart-content-wrapper'; +const mlExplorerChartContentWrapper = css({ + height: `${CONTENT_WRAPPER_HEIGHT}px`, +}); export class ExplorerChartSingleMetric extends React.Component { static contextType = context; @@ -721,9 +727,11 @@ export class ExplorerChartSingleMetric extends React.Component {
)} -
+
{isLoading && } - {!isLoading &&
} + {!isLoading && ( +
+ )}
); diff --git a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_styles.ts b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_styles.ts new file mode 100644 index 0000000000000..e89877fc03392 --- /dev/null +++ b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_chart_styles.ts @@ -0,0 +1,131 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { css } from '@emotion/react'; + +import { useEuiFontSize, useEuiTheme, mathWithUnits, transparentize } from '@elastic/eui'; + +import { ML_SEVERITY_COLORS } from '@kbn/ml-anomaly-utils'; + +export const useCssMlExplorerChartContainer = () => { + const { euiTheme } = useEuiTheme(); + const euiFontSizeXS = useEuiFontSize('xs').fontSize; + + return css({ + overflow: 'hidden', + + '.ml-explorer-chart-svg': { + fontSize: euiFontSizeXS, + fontFamily: euiTheme.font.family, + + '.line-chart': { + rect: { + fill: euiTheme.colors.emptyShade, + opacity: 1, + }, + + 'rect.selected-interval': { + fill: transparentize('#c8c8c8', 0.1), + stroke: euiTheme.colors.darkShade, + strokeWidth: mathWithUnits(euiTheme.size.xs, (x) => x / 2), + strokeOpacity: 0.8, + }, + + 'rect.scheduled-event-marker': { + strokeWidth: '1px', + stroke: euiTheme.colors.darkShade, + fill: euiTheme.colors.lightShade, + pointerEvents: 'none', + }, + }, + }, + + '.axis path, .axis line': { + fill: 'none', + stroke: euiTheme.border.color, + shapeRendering: 'crispEdges', + }, + + '.axis .tick line.ml-tick-emphasis': { + stroke: transparentize('#000', 0.2), + }, + + '.axis text': { + fill: euiTheme.colors.lightShade, + }, + + '.axis .tick line': { + stroke: euiTheme.colors.lightShade, + strokeWidth: '1px', + }, + + '.values-line': { + fill: 'none', + stroke: euiTheme.colors.primary, + strokeWidth: '2px', + }, + + '.values-dots circle, .values-dots-circle': { + fill: euiTheme.colors.primary, + strokeWidth: 0, + }, + + '.values-dots circle.values-dots-circle-blur': { + fill: euiTheme.colors.mediumShade, + }, + + '.metric-value': { + opacity: 1, + fill: 'transparent', + stroke: euiTheme.colors.primary, + strokeWidth: 0, + }, + + '.anomaly-marker': { + strokeWidth: '1px', + stroke: euiTheme.colors.mediumShade, + }, + + '.anomaly-marker:hover': { + strokeWidth: '6px', + stroke: euiTheme.colors.primary, + }, + + '.anomaly-marker.critical': { + fill: ML_SEVERITY_COLORS.CRITICAL, + }, + + '.anomaly-marker.major': { + fill: ML_SEVERITY_COLORS.MAJOR, + }, + + '.anomaly-marker.minor': { + fill: ML_SEVERITY_COLORS.MINOR, + }, + + '.anomaly-marker.warning': { + fill: ML_SEVERITY_COLORS.WARNING, + }, + + '.anomaly-marker.low': { + fill: ML_SEVERITY_COLORS.LOW, + }, + + '.metric-value:hover, .anomaly-marker:hover': { + strokeWidth: '6px', + strokeOpacity: 0.65, + }, + + 'ml-explorer-chart-axis-emphasis': { + fontWeight: 'bold', + }, + }); +}; + +export const cssMlExplorerChart = css({ + overflow: 'hidden', +}); diff --git a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_charts_container.js b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_charts_container.js index 9bc1317a9aa50..1f3a2d20eea28 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_charts_container.js +++ b/x-pack/platform/plugins/shared/ml/public/application/explorer/explorer_charts/explorer_charts_container.js @@ -45,6 +45,7 @@ import { EmbeddedMapComponentWrapper } from './explorer_chart_embedded_map'; import { useActiveCursor } from '@kbn/charts-plugin/public'; import { BarSeries, Chart, Settings, LEGACY_LIGHT_THEME } from '@elastic/charts'; import { escapeKueryForFieldValuePair } from '../../util/string_utils'; +import { useCssMlExplorerChartContainer } from './explorer_chart_styles'; const textTooManyBuckets = i18n.translate('xpack.ml.explorer.charts.tooManyBucketsDescription', { defaultMessage: @@ -398,6 +399,7 @@ export const ExplorerChartsContainerUI = ({ chartsService, showFilterIcons = true, }) => { + const cssMlExplorerChartContainer = useCssMlExplorerChartContainer(); const { services: { embeddable: embeddablePlugin, maps: mapsPlugin }, } = kibana; @@ -443,7 +445,8 @@ export const ExplorerChartsContainerUI = ({ return ( { // We test child components with snapshots separately // so we just do a high level check here. - expect(wrapper.find('div.ml-explorer-chart-container').children()).toHaveLength(1); + expect( + wrapper.find('div[data-test-subj="mlExplorerChartContainerItem"]').children() + ).toHaveLength(1); // Check if the additional y-axis information for rare charts is not part of the chart expect(wrapper.html().search(rareChartUniqueString)).toBe(-1); @@ -148,7 +150,9 @@ describe('ExplorerChartsContainer', () => { // We test child components with snapshots separately // so we just do a high level check here. - expect(wrapper.find('div.ml-explorer-chart-container').children()).toHaveLength(1); + expect( + wrapper.find('div[data-test-subj="mlExplorerChartContainerItem"]').children() + ).toHaveLength(1); // Check if the additional y-axis information for rare charts is part of the chart expect(wrapper.html().search(rareChartUniqueString)).toBeGreaterThan(0); diff --git a/x-pack/platform/plugins/shared/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js b/x-pack/platform/plugins/shared/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js index f39bab106c643..d43603684b043 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js +++ b/x-pack/platform/plugins/shared/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js @@ -20,7 +20,11 @@ import moment from 'moment'; import { EuiPopover } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { getFormattedSeverityScore, getSeverityWithLow } from '@kbn/ml-anomaly-utils'; +import { + getFormattedSeverityScore, + getSeverityWithLow, + ML_SEVERITY_COLORS, +} from '@kbn/ml-anomaly-utils'; import { formatHumanReadableDateTimeSeconds } from '@kbn/ml-date-utils'; import { context } from '@kbn/kibana-react-plugin/public'; @@ -87,7 +91,13 @@ const ZOOM_INTERVAL_OPTIONS = [ const anomalyColorScale = d3.scale .threshold() .domain([3, 25, 50, 75, 100]) - .range(['#d2e9f7', '#8bc8fb', '#ffdd00', '#ff7e00', '#fe5050']); + .range([ + ML_SEVERITY_COLORS.LOW, + ML_SEVERITY_COLORS.WARNING, + ML_SEVERITY_COLORS.MINOR, + ML_SEVERITY_COLORS.MAJOR, + ML_SEVERITY_COLORS.CRITICAL, + ]); // Create a gray-toned version of the color scale to use under the context chart mask. const anomalyGrayScale = d3.scale diff --git a/x-pack/platform/plugins/shared/ml/public/application/timeseriesexplorer/styles.ts b/x-pack/platform/plugins/shared/ml/public/application/timeseriesexplorer/styles.ts index 7c4315e01688b..0c9ba5619908d 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/timeseriesexplorer/styles.ts +++ b/x-pack/platform/plugins/shared/ml/public/application/timeseriesexplorer/styles.ts @@ -10,7 +10,7 @@ import { css } from '@emotion/react'; import { useEuiFontSize, useEuiTheme, transparentize } from '@elastic/eui'; -import { mlColors } from '../styles'; +import { ML_SEVERITY_COLORS } from '@kbn/ml-anomaly-utils'; // Annotations constants const mlAnnotationBorderWidth = '2px'; @@ -119,23 +119,23 @@ export const useTimeseriesExplorerStyles = () => { stroke: euiTheme.colors.mediumShade, '&.critical': { - fill: mlColors.critical, + fill: ML_SEVERITY_COLORS.CRITICAL, }, '&.major': { - fill: mlColors.major, + fill: ML_SEVERITY_COLORS.MAJOR, }, '&.minor': { - fill: mlColors.minor, + fill: ML_SEVERITY_COLORS.MINOR, }, '&.warning': { - fill: mlColors.warning, + fill: ML_SEVERITY_COLORS.WARNING, }, '&.low': { - fill: mlColors.lowWarning, + fill: ML_SEVERITY_COLORS.LOW, }, }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/create_description_list.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/create_description_list.tsx index 7ca8bf81ed06e..b197daff4d301 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/create_description_list.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/create_description_list.tsx @@ -11,7 +11,7 @@ import styled from 'styled-components'; import type { DescriptionList } from '../../../../../common/utility_types'; import type { Anomaly, NarrowDateRange } from '../types'; -import { getScoreString } from './score_health'; +import { getScoreString } from './get_score_string'; import { PreferenceFormattedDate } from '../../formatted_date'; import { createInfluencers } from '../influencers/create_influencers'; import * as i18n from './translations'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/get_score_string.test.ts b/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/get_score_string.test.ts index 1eeaa3521f030..87b2d092ada78 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/get_score_string.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/get_score_string.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { getScoreString } from './score_health'; +import { getScoreString } from './get_score_string'; describe('create_influencers', () => { test('it rounds up to 1 from 0.3', () => { diff --git a/x-pack/platform/plugins/shared/ml/public/application/styles.ts b/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/get_score_string.ts similarity index 52% rename from x-pack/platform/plugins/shared/ml/public/application/styles.ts rename to x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/get_score_string.ts index 86f4dbe3bbcd4..d0edd52c68f1e 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/styles.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/get_score_string.ts @@ -5,13 +5,4 @@ * 2.0. */ -// Replacement for ./_variables.scss as we aim to remove the scss files - -export const mlColors = { - critical: '#FE5050', - major: '#FBA740', - minor: '#FDEC25', - warning: '#8BC8FB', - lowWarning: '#D2E9F7', - unknown: '#C0C0C0', -}; +export const getScoreString = (score: number) => String(Math.ceil(score)); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/score.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/score.tsx index 3c5030706da05..b4baad7b392c8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/score.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/score.tsx @@ -13,7 +13,7 @@ import { } from '../../cell_actions'; import type { Anomaly } from '../types'; import { Spacer } from '../../page'; -import { getScoreString } from './score_health'; +import { getScoreString } from './get_score_string'; export const ScoreComponent = ({ index = 0, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/score_health.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/score_health.tsx deleted file mode 100644 index ac179b2ac8337..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/ml/score/score_health.tsx +++ /dev/null @@ -1,44 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiHealth } from '@elastic/eui'; - -interface Props { - score: number; -} - -export const getScoreString = (score: number) => String(Math.ceil(score)); - -export const ScoreHealth = React.memo(({ score }) => { - const scoreCeiling = getScoreString(score); - const color = getSeverityColor(score); - return {scoreCeiling}; -}); - -ScoreHealth.displayName = 'ScoreHealth'; - -// ಠ_ಠ A hard-fork of the @kbn/ml-anomaly-utils;#getSeverityColor ಠ_ಠ -// -// Returns a severity label (one of critical, major, minor, warning, low or unknown) -// for the supplied normalized anomaly score (a value between 0 and 100), where scores -// less than 3 are assigned a severity of 'low'. -export const getSeverityColor = (normalizedScore: number): string => { - if (normalizedScore >= 75) { - return '#fe5050'; - } else if (normalizedScore >= 50) { - return '#fba740'; - } else if (normalizedScore >= 25) { - return '#fdec25'; - } else if (normalizedScore >= 3) { - return '#8bc8fb'; - } else if (normalizedScore >= 0) { - return '#d2e9f7'; - } else { - return '#ffffff'; - } -}; diff --git a/x-pack/test/functional/services/ml/anomaly_charts.ts b/x-pack/test/functional/services/ml/anomaly_charts.ts index 50c639094408e..8f63c8cf3710a 100644 --- a/x-pack/test/functional/services/ml/anomaly_charts.ts +++ b/x-pack/test/functional/services/ml/anomaly_charts.ts @@ -31,7 +31,7 @@ export function AnomalyChartsProvider({ getService }: FtrProviderContext) { ? await testSubjects.find(chartsContainerSubj) : await testSubjects.find('mlExplorerChartsContainer'); const actualChartsCount = ( - await chartsContainer?.findAllByClassName('ml-explorer-chart-container', 3000) + await chartsContainer?.findAllByTestSubject('mlExplorerChartContainerItem', 3000) ).length; expect(actualChartsCount).to.eql( expectedChartsCount, From d28ed76b977a366af68b6f0f987c833b6f6afeb2 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 2 Jan 2025 15:34:29 +0000 Subject: [PATCH 02/11] [Streams] Schema API integration tests (#204401) ## Summary Just API integration tests for the APIs added in https://github.com/elastic/kibana/pull/202372. --- .../apis/streams/helpers/requests.ts | 12 +++ .../api_integration/apis/streams/index.ts | 1 + .../api_integration/apis/streams/schema.ts | 98 +++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 x-pack/test/api_integration/apis/streams/schema.ts diff --git a/x-pack/test/api_integration/apis/streams/helpers/requests.ts b/x-pack/test/api_integration/apis/streams/helpers/requests.ts index ae3a325b5f9b4..f26c53aaaf0aa 100644 --- a/x-pack/test/api_integration/apis/streams/helpers/requests.ts +++ b/x-pack/test/api_integration/apis/streams/helpers/requests.ts @@ -60,3 +60,15 @@ export async function deleteStream(supertest: Agent, id: string) { const response = await req.send().expect(200); return response.body; } + +export async function getUnmappedFieldsForStream(supertest: Agent, id: string) { + const req = supertest.get(`/api/streams/${id}/schema/unmapped_fields`).set('kbn-xsrf', 'xxx'); + const response = await req.send().expect(200); + return response.body; +} + +export async function simulateFieldsForStream(supertest: Agent, id: string, body: JsonObject) { + const req = supertest.post(`/api/streams/${id}/schema/fields_simulation`).set('kbn-xsrf', 'xxx'); + const response = await req.send(body).expect(200); + return response.body; +} diff --git a/x-pack/test/api_integration/apis/streams/index.ts b/x-pack/test/api_integration/apis/streams/index.ts index 14decb2400196..6c4cf358b8ac3 100644 --- a/x-pack/test/api_integration/apis/streams/index.ts +++ b/x-pack/test/api_integration/apis/streams/index.ts @@ -13,5 +13,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./enrichment')); loadTestFile(require.resolve('./classic')); loadTestFile(require.resolve('./flush_config')); + loadTestFile(require.resolve('./schema')); }); } diff --git a/x-pack/test/api_integration/apis/streams/schema.ts b/x-pack/test/api_integration/apis/streams/schema.ts new file mode 100644 index 0000000000000..c8b90e90939c1 --- /dev/null +++ b/x-pack/test/api_integration/apis/streams/schema.ts @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { + deleteStream, + enableStreams, + forkStream, + getUnmappedFieldsForStream, + indexDocument, + simulateFieldsForStream, +} from './helpers/requests'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { cleanUpRootStream } from './helpers/cleanup'; +import { waitForDocumentInIndex } from '../../../alerting_api_integration/observability/helpers/alerting_wait_for_helpers'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const esClient = getService('es'); + const retryService = getService('retry'); + const logger = getService('log'); + + describe('Streams Schema', () => { + after(async () => { + await deleteStream(supertest, 'logs.nginx'); + await cleanUpRootStream(esClient); + }); + + before(async () => { + await enableStreams(supertest); + + const doc = { + '@timestamp': '2024-01-01T00:00:10.000Z', + message: '2023-01-01T00:00:10.000Z error test', + ['some.field']: 'some value', + ['another.field']: 'another value', + lastField: 'last value', + ['log.level']: 'warning', + }; + + await indexDocument(esClient, 'logs', doc); + await waitForDocumentInIndex({ esClient, indexName: 'logs', retryService, logger }); + }); + + describe('Unmapped fields API', () => { + it('Returns unmapped fields', async () => { + const response = await getUnmappedFieldsForStream(supertest, 'logs'); + expect(response.unmappedFields).to.eql(['another.field', 'lastField', 'some.field']); + }); + }); + + describe('Fields simulation API', () => { + it('Returns failure status when simulation would fail', async () => { + const response = await simulateFieldsForStream(supertest, 'logs', { + field_definitions: [{ name: 'message', type: 'boolean' }], + }); + + expect(response.status).to.be('failure'); + expect(response.simulationError).to.be.a('string'); + expect(response.documentsWithRuntimeFieldsApplied).to.be(null); + }); + it('Returns success status when simulation would succeed', async () => { + const response = await simulateFieldsForStream(supertest, 'logs', { + field_definitions: [{ name: 'message', type: 'keyword' }], + }); + + expect(response.status).to.be('success'); + expect(response.simulationError).to.be(null); + expect(response.documentsWithRuntimeFieldsApplied).length(1); + }); + it('Returns unknown status when documents are missing and status cannot be determined', async () => { + const forkBody = { + stream: { + name: 'logs.nginx', + }, + condition: { + field: 'log.logger', + operator: 'eq', + value: 'nginx', + }, + }; + + await forkStream(supertest, 'logs', forkBody); + const response = await simulateFieldsForStream(supertest, 'logs.nginx', { + field_definitions: [{ name: 'message', type: 'keyword' }], + }); + + expect(response.status).to.be('unknown'); + expect(response.simulationError).to.be(null); + expect(response.documentsWithRuntimeFieldsApplied).to.be(null); + }); + }); + }); +} From 4ae8b674947a2ce45fea48277d8d409135d55f75 Mon Sep 17 00:00:00 2001 From: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:38:33 +0000 Subject: [PATCH 03/11] [ResponseOps][Rules] Remove invalid rule type warnings (#204366) ## Summary Fixes https://github.com/elastic/kibana/issues/204101 --- .../server/search_strategy/search_strategy.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/x-pack/platform/plugins/shared/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/platform/plugins/shared/rule_registry/server/search_strategy/search_strategy.ts index 246b38aaf733d..bfecc958ce3d1 100644 --- a/x-pack/platform/plugins/shared/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/platform/plugins/shared/rule_registry/server/search_strategy/search_strategy.ts @@ -64,7 +64,7 @@ export const ruleRegistrySearchStrategyProvider = ( const registeredRuleTypes = alerting.listTypes(); - const [validRuleTypeIds, invalidRuleTypeIds] = partition(request.ruleTypeIds, (ruleTypeId) => + const [validRuleTypeIds, _] = partition(request.ruleTypeIds, (ruleTypeId) => registeredRuleTypes.has(ruleTypeId) ); @@ -75,12 +75,6 @@ export const ruleRegistrySearchStrategyProvider = ( ); } - invalidRuleTypeIds.forEach((ruleTypeId) => { - logger.warn( - `Found invalid rule type '${ruleTypeId}' while using ${RULE_SEARCH_STRATEGY_NAME} search strategy. No alert data from this rule type will be searched.` - ); - }); - const securityAuditLogger = security?.audit.asScoped(deps.request); const getActiveSpace = async () => spaces?.spacesService.getActiveSpace(deps.request); From 750a0f305823aff23cf9cc8b922fd3c07b63c622 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Thu, 2 Jan 2025 10:59:13 -0500 Subject: [PATCH 04/11] feat(slo): Remember last sort, view and group option used (#205340) --- .../slo/overview/group_view/group_view.tsx | 6 +-- .../helpers/build_kql_query.test.ts | 2 +- .../group_view/helpers/build_kql_query.ts | 2 +- .../slo/public/hooks/use_fetch_slo_groups.ts | 2 +- .../slo/public/hooks/use_fetch_slo_list.ts | 3 +- .../slos/components/common/sort_by_select.tsx | 3 +- .../grouped_slos/group_list_view.tsx | 6 +-- .../components/grouped_slos/group_view.tsx | 8 ++-- .../grouped_slos/hooks/use_group_name.ts | 2 +- .../slos/components/slo_list_group_by.tsx | 8 +--- .../pages/slos/components/slos_view.tsx | 4 +- .../pages/slos/components/toggle_slo_view.tsx | 8 ++-- .../ungrouped_slos/ungrouped_view.tsx | 4 +- .../pages/slos/hooks/use_url_search_state.ts | 47 ++++++++++--------- .../plugins/slo/public/pages/slos/types.ts | 24 ++++++++++ 15 files changed, 74 insertions(+), 55 deletions(-) create mode 100644 x-pack/solutions/observability/plugins/slo/public/pages/slos/types.ts diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/group_view.tsx b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/group_view.tsx index 76221ecabe496..db2e2a213a20a 100644 --- a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/group_view.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/group_view.tsx @@ -9,16 +9,14 @@ import { Filter } from '@kbn/es-query'; import React, { useEffect, useState } from 'react'; import { Subject } from 'rxjs'; import { GroupView } from '../../../../pages/slos/components/grouped_slos/group_view'; -import { GroupByField } from '../../../../pages/slos/components/slo_list_group_by'; -import { SLOView } from '../../../../pages/slos/components/toggle_slo_view'; -import { SortField } from '../../../../pages/slos/hooks/use_url_search_state'; +import type { ViewType, GroupByField, SortField } from '../../../../pages/slos/types'; import { buildCombinedKqlQuery } from './helpers/build_kql_query'; interface Props { groupBy: GroupByField; groups?: string[]; kqlQuery?: string; - view: SLOView; + view: ViewType; sort?: SortField; filters?: Filter[]; reloadSubject: Subject; diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/helpers/build_kql_query.test.ts b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/helpers/build_kql_query.test.ts index fff968f7459f3..8d007e99c831d 100644 --- a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/helpers/build_kql_query.test.ts +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/helpers/build_kql_query.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { GroupByField } from '../../../../../pages/slos/components/slo_list_group_by'; +import type { GroupByField } from '../../../../../pages/slos/types'; import { buildCombinedKqlQuery } from './build_kql_query'; describe('buildCombinedKqlQuery', () => { diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/helpers/build_kql_query.ts b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/helpers/build_kql_query.ts index 019536a2156a5..1319bbdb39009 100644 --- a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/helpers/build_kql_query.ts +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/helpers/build_kql_query.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { GroupByField } from '../../../../../pages/slos/components/slo_list_group_by'; +import type { GroupByField } from '../../../../../pages/slos/types'; interface Props { kqlQuery: string; diff --git a/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_groups.ts b/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_groups.ts index 4b409a2c56562..da9b93e0eb209 100644 --- a/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_groups.ts +++ b/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_groups.ts @@ -18,7 +18,7 @@ import { DEFAULT_SLO_GROUPS_PAGE_SIZE, SLO_SUMMARY_DESTINATION_INDEX_PATTERN, } from '../../common/constants'; -import { GroupByField } from '../pages/slos/components/slo_list_group_by'; +import type { GroupByField } from '../pages/slos/types'; import { SearchState } from '../pages/slos/hooks/use_url_search_state'; import { useKibana } from './use_kibana'; import { sloKeys } from './query_key_factory'; diff --git a/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_list.ts b/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_list.ts index aba2fe66dcb03..2ed986fd1ffc8 100644 --- a/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_list.ts +++ b/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_list.ts @@ -14,11 +14,12 @@ import { DEFAULT_SLO_PAGE_SIZE, SLO_SUMMARY_DESTINATION_INDEX_PATTERN, } from '../../common/constants'; -import { SearchState, SortDirection, SortField } from '../pages/slos/hooks/use_url_search_state'; +import { SearchState } from '../pages/slos/hooks/use_url_search_state'; import { useKibana } from './use_kibana'; import { sloKeys } from './query_key_factory'; import { useCreateDataView } from './use_create_data_view'; import { usePluginContext } from './use_plugin_context'; +import type { SortDirection, SortField } from '../pages/slos/types'; export interface SLOListParams { kqlQuery?: string; diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/common/sort_by_select.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/common/sort_by_select.tsx index 189dbee8b4f8c..d7114800f5bec 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/common/sort_by_select.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/common/sort_by_select.tsx @@ -9,9 +9,10 @@ import { EuiPanel, EuiSelectableOption, EuiText } from '@elastic/eui'; import { EuiSelectableOptionCheckedType } from '@elastic/eui/src/components/selectable/selectable_option'; import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; -import type { SortField, SearchState } from '../../hooks/use_url_search_state'; +import type { SearchState } from '../../hooks/use_url_search_state'; import type { Option } from '../slo_context_menu'; import { ContextMenuItem, SLOContextMenu } from '../slo_context_menu'; +import type { SortField } from '../../types'; export interface Props { onStateChange: (newState: Partial) => void; diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/group_list_view.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/group_list_view.tsx index a433b57073e3b..98e4d64283486 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/group_list_view.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/group_list_view.tsx @@ -28,16 +28,14 @@ import { paths } from '../../../../../common/locators/paths'; import { useFetchSloList } from '../../../../hooks/use_fetch_slo_list'; import { useKibana } from '../../../../hooks/use_kibana'; import { useSloFormattedSLIValue } from '../../hooks/use_slo_summary'; -import type { SortDirection, SortField } from '../../hooks/use_url_search_state'; import { SlosView } from '../slos_view'; -import { GroupByField } from '../slo_list_group_by'; -import { SLOView } from '../toggle_slo_view'; +import type { ViewType, GroupByField, SortDirection, SortField } from '../../types'; import { useGroupName } from './hooks/use_group_name'; interface Props { group: string; kqlQuery?: string; - view: SLOView; + view: ViewType; sort?: SortField; direction?: SortDirection; groupBy: GroupByField; diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/group_view.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/group_view.tsx index 3cec6fef539e6..bbccbfb40b532 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/group_view.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/group_view.tsx @@ -8,10 +8,8 @@ import { EuiEmptyPrompt, EuiFlexItem, EuiLoadingSpinner, EuiTablePagination } fr import { Filter } from '@kbn/es-query'; import React, { useEffect } from 'react'; import { useFetchSloGroups } from '../../../../hooks/use_fetch_slo_groups'; -import type { SortDirection } from '../../hooks/use_url_search_state'; -import { SortField, useUrlSearchState } from '../../hooks/use_url_search_state'; -import { GroupByField } from '../slo_list_group_by'; -import { SLOView } from '../toggle_slo_view'; +import { useUrlSearchState } from '../../hooks/use_url_search_state'; +import type { ViewType, GroupByField, SortDirection, SortField } from '../../types'; import { SloGroupListEmpty } from './group_list_empty'; import { SloGroupListError } from './group_list_error'; import { GroupListView } from './group_list_view'; @@ -19,7 +17,7 @@ import { GroupListView } from './group_list_view'; interface Props { groupBy: GroupByField; kqlQuery?: string; - view: SLOView; + view: ViewType; sort?: SortField; direction?: SortDirection; filters?: Filter[]; diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.ts b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.ts index ba19459d4dded..689c0ec1819d8 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.ts +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { ALL_VALUE, GroupSummary } from '@kbn/slo-schema'; import { assertNever } from '@kbn/std'; import { SLI_OPTIONS } from '../../../../slo_edit/constants'; -import { GroupByField } from '../../slo_list_group_by'; +import type { GroupByField } from '../../../types'; export function useGroupName(groupBy: GroupByField, group: string, summary?: GroupSummary) { const groupName = group.toLowerCase(); diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/slo_list_group_by.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/slo_list_group_by.tsx index 7223f91d49519..a7f0de71e1054 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/slo_list_group_by.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/slo_list_group_by.tsx @@ -12,14 +12,8 @@ import { useGetSettings } from '../../slo_settings/hooks/use_get_settings'; import type { SearchState } from '../hooks/use_url_search_state'; import type { Option } from './slo_context_menu'; import { ContextMenuItem, SLOContextMenu } from './slo_context_menu'; +import type { GroupByField } from '../types'; -export type GroupByField = - | 'ungrouped' - | 'slo.tags' - | 'status' - | 'slo.indicator.type' - | 'slo.instanceId' - | '_index'; export interface Props { onStateChange: (newState: Partial) => void; state: SearchState; diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/slos_view.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/slos_view.tsx index eca4282508404..02b624577ab9b 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/slos_view.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/slos_view.tsx @@ -14,13 +14,13 @@ import { HealthCallout } from './health_callout/health_callout'; import { SloListEmpty } from './slo_list_empty'; import { SloListError } from './slo_list_error'; import { SloListView } from './slo_list_view/slo_list_view'; -import { SLOView } from './toggle_slo_view'; +import type { ViewType } from '../types'; export interface Props { sloList: SLOWithSummaryResponse[]; loading: boolean; error: boolean; - view: SLOView; + view: ViewType; } export function SlosView({ sloList, loading, error, view }: Props) { diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/toggle_slo_view.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/toggle_slo_view.tsx index a6a35912269a1..03470fd0dde5f 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/toggle_slo_view.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/toggle_slo_view.tsx @@ -13,12 +13,12 @@ import React from 'react'; import type { SearchState } from '../hooks/use_url_search_state'; import { SLOSortBy } from './common/sort_by_select'; import { SloGroupBy } from './slo_list_group_by'; -export type SLOView = 'cardView' | 'listView' | 'compactView'; +import type { ViewType } from '../types'; interface Props { - onChangeView: (view: SLOView) => void; + onChangeView: (view: ViewType) => void; onStateChange: (newState: Partial) => void; - view: SLOView; + view: ViewType; state: SearchState; sloList?: FindSLOResponse; loading: boolean; @@ -96,7 +96,7 @@ export function ToggleSLOView({ })} options={toggleButtonsIcons} idSelected={view} - onChange={(id) => onChangeView(id as SLOView)} + onChange={(id) => onChangeView(id as ViewType)} isIconOnly isDisabled={loading} /> diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/ungrouped_slos/ungrouped_view.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/ungrouped_slos/ungrouped_view.tsx index 0374204b7e651..a96d3ba963634 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/ungrouped_slos/ungrouped_view.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/ungrouped_slos/ungrouped_view.tsx @@ -10,13 +10,13 @@ import { FindSLOResponse } from '@kbn/slo-schema'; import React from 'react'; import { useUrlSearchState } from '../../hooks/use_url_search_state'; import { SlosView } from '../slos_view'; -import { SLOView } from '../toggle_slo_view'; +import type { ViewType } from '../../types'; export interface Props { sloList: FindSLOResponse | undefined; loading: boolean; error: boolean; - view: SLOView; + view: ViewType; } export function UngroupedView({ sloList, loading, error, view }: Props) { diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/hooks/use_url_search_state.ts b/x-pack/solutions/observability/plugins/slo/public/pages/slos/hooks/use_url_search_state.ts index 5da3b4596ed71..e3d81c3d1144b 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/hooks/use_url_search_state.ts +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/hooks/use_url_search_state.ts @@ -6,25 +6,19 @@ */ import type { Filter } from '@kbn/es-query'; -import { createKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; +import { + createKbnUrlStateStorage, + createSessionStorageStateStorage, +} from '@kbn/kibana-utils-plugin/public'; import deepmerge from 'deepmerge'; +import { pick } from 'lodash'; import { useCallback, useEffect, useRef, useState } from 'react'; import { useHistory } from 'react-router-dom'; import { DEFAULT_SLO_PAGE_SIZE } from '../../../../common/constants'; -import type { GroupByField } from '../components/slo_list_group_by'; -import type { SLOView } from '../components/toggle_slo_view'; +import type { GroupByField, SortDirection, SortField, ViewType } from '../types'; export const SLO_LIST_SEARCH_URL_STORAGE_KEY = 'search'; -export type SortField = - | 'sli_value' - | 'error_budget_consumed' - | 'error_budget_remaining' - | 'status' - | 'burn_rate_5m' - | 'burn_rate_1h' - | 'burn_rate_1d'; - -export type SortDirection = 'asc' | 'desc'; +export const SLO_LIST_SEARCH_SESSION_STORAGE_KEY = 'slo.list_page_search_state'; export interface SearchState { kqlQuery: string; @@ -34,7 +28,7 @@ export interface SearchState { by: SortField; direction: SortDirection; }; - view: SLOView; + view: ViewType; groupBy: GroupByField; filters: Filter[]; lastRefresh?: number; @@ -42,13 +36,13 @@ export interface SearchState { statusFilter?: Filter; } -export const DEFAULT_STATE = { +export const DEFAULT_STATE: SearchState = { kqlQuery: '', page: 0, perPage: DEFAULT_SLO_PAGE_SIZE, - sort: { by: 'status' as const, direction: 'desc' as const }, - view: 'cardView' as const, - groupBy: 'ungrouped' as const, + sort: { by: 'status', direction: 'desc' }, + view: 'cardView', + groupBy: 'ungrouped', filters: [], lastRefresh: 0, }; @@ -67,6 +61,8 @@ export function useUrlSearchState(): { }) ); + const sessionStorage = useRef(createSessionStorageStateStorage(window.localStorage)); + useEffect(() => { const sub = urlStateStorage.current ?.change$(SLO_LIST_SEARCH_URL_STORAGE_KEY) @@ -77,21 +73,30 @@ export function useUrlSearchState(): { }); setState( - urlStateStorage.current?.get(SLO_LIST_SEARCH_URL_STORAGE_KEY) ?? DEFAULT_STATE + urlStateStorage.current?.get(SLO_LIST_SEARCH_URL_STORAGE_KEY) ?? + sessionStorage.current?.get(SLO_LIST_SEARCH_SESSION_STORAGE_KEY) ?? + DEFAULT_STATE ); return () => { sub?.unsubscribe(); }; - }, [urlStateStorage]); + }, [urlStateStorage, sessionStorage]); const onStateChange = useCallback( (newState: Partial) => { const updatedState = { ...state, page: 0, ...newState }; - setState((stateN) => updatedState); + setState(() => updatedState); + urlStateStorage.current?.set(SLO_LIST_SEARCH_URL_STORAGE_KEY, updatedState, { replace: true, }); + + // Discard search itself from session storage. Keep only view preferences + sessionStorage.current?.set( + SLO_LIST_SEARCH_SESSION_STORAGE_KEY, + pick(updatedState, 'sort', 'view', 'groupBy') + ); }, [state] ); diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/types.ts b/x-pack/solutions/observability/plugins/slo/public/pages/slos/types.ts new file mode 100644 index 0000000000000..aae9533a8a542 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/types.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export type ViewType = 'cardView' | 'listView' | 'compactView'; +export type GroupByField = + | 'ungrouped' + | 'slo.tags' + | 'status' + | 'slo.indicator.type' + | 'slo.instanceId' + | '_index'; +export type SortDirection = 'asc' | 'desc'; +export type SortField = + | 'sli_value' + | 'error_budget_consumed' + | 'error_budget_remaining' + | 'status' + | 'burn_rate_5m' + | 'burn_rate_1h' + | 'burn_rate_1d'; From de0dc5282476c1983e90d0872fdd9909b6cdf984 Mon Sep 17 00:00:00 2001 From: Clint Andrew Hall Date: Thu, 2 Jan 2025 10:27:17 -0600 Subject: [PATCH 05/11] [ai][assistant] Refactor Security solution properties to use new Assistant logo and beacon (#204286) > A follow-up to #203879 ## Summary This PR integrates the new Assistant Icon, Beacon, and Avatar into solutions and packages owned by Security. In most cases this was a 1:1 replacement, but in a few, Icon was replaced with Beacon for consistency, (e.g. welcome screens, upsells, etc) Note: the scaling of the icon/avatar _before_ was one different from EUI. The new components match EUI directly and represent a 2x scale change (e.g. 's' becomes 'l', 'm' becomes 'xl', etc). --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../icon/__stories__/beacon.stories.tsx | 5 +++++ .../shared/ai-assistant/icon/avatar.styles.ts | 22 ------------------- .../shared/ai-assistant/icon/avatar.tsx | 5 +---- .../src/chat/welcome_message.tsx | 2 +- .../assistant/assistant_body/empty_convo.tsx | 4 ++-- .../impl/assistant/assistant_body/index.tsx | 7 ++++-- .../assistant_body/welcome_setup.tsx | 4 ++-- .../impl/assistant/assistant_title/index.tsx | 4 ++-- .../shared/kbn-elastic-assistant/index.ts | 3 --- .../kbn-elastic-assistant/tsconfig.json | 1 + .../header/header.tsx | 21 ++++-------------- .../integration_assistant_card.tsx | 4 ++-- .../integration_assistant/tsconfig.json | 1 + .../data_quality_panel/actions/chat/index.tsx | 5 +++-- .../ecs_data_quality_dashboard/tsconfig.json | 1 + .../sections/attack_discovery/index.tsx | 6 ++--- .../security/packages/upselling/tsconfig.json | 1 + .../public/assistant/get_comments/index.tsx | 8 +++---- .../public/assistant/header_link.tsx | 4 ++-- .../attack_discovery_panel/title/index.tsx | 6 ++--- .../view_in_ai_assistant/index.tsx | 4 ++-- .../empty_states/empty_prompt/index.tsx | 4 ++-- .../results/empty_states/no_alerts/index.tsx | 4 ++-- .../results/empty_states/welcome/index.tsx | 4 ++-- .../components/ai_assistant/index.tsx | 12 ++++++++-- .../insights/workflow_insights_scan.tsx | 4 ++-- .../onboarding_body/cards/assistant/index.ts | 4 ++-- .../siem_migrations/ai_connector/index.ts | 4 ++-- .../tabs/summary/index.tsx | 8 +++---- 29 files changed, 69 insertions(+), 93 deletions(-) delete mode 100644 x-pack/platform/packages/shared/ai-assistant/icon/avatar.styles.ts diff --git a/x-pack/platform/packages/shared/ai-assistant/icon/__stories__/beacon.stories.tsx b/x-pack/platform/packages/shared/ai-assistant/icon/__stories__/beacon.stories.tsx index b0a77f6cab3cb..4027b431110ac 100644 --- a/x-pack/platform/packages/shared/ai-assistant/icon/__stories__/beacon.stories.tsx +++ b/x-pack/platform/packages/shared/ai-assistant/icon/__stories__/beacon.stories.tsx @@ -19,6 +19,11 @@ export default { options: ['original', 's', 'm', 'l', 'xl', 'xxl'], defaultValue: 'xxl', }, + backgroundColor: { + control: 'select', + options: ['body', 'emptyShade', 'lightShade', 'darkShade'], + defaultValue: 'body', + }, }, } as ComponentMeta; diff --git a/x-pack/platform/packages/shared/ai-assistant/icon/avatar.styles.ts b/x-pack/platform/packages/shared/ai-assistant/icon/avatar.styles.ts deleted file mode 100644 index 3b9d0b40ef274..0000000000000 --- a/x-pack/platform/packages/shared/ai-assistant/icon/avatar.styles.ts +++ /dev/null @@ -1,22 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useEuiTheme } from '@elastic/eui'; -import { css } from '@emotion/react'; - -export const useStyles = () => { - const { - euiTheme: { border, size }, - } = useEuiTheme(); - - const root = css` - border: ${border.thin}; - padding: ${size.xs}; - `; - - return { root }; -}; diff --git a/x-pack/platform/packages/shared/ai-assistant/icon/avatar.tsx b/x-pack/platform/packages/shared/ai-assistant/icon/avatar.tsx index 40142b8b30fa8..ce539979f202c 100644 --- a/x-pack/platform/packages/shared/ai-assistant/icon/avatar.tsx +++ b/x-pack/platform/packages/shared/ai-assistant/icon/avatar.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { EuiAvatar, EuiAvatarProps } from '@elastic/eui'; import { AssistantIcon } from './icon'; -import { useStyles } from './avatar.styles'; /** * Avatar component for the AI Assistant. @@ -23,11 +22,9 @@ export type AssistantAvatarProps = Omit< * A `EuiAvatar` component customized for the AI Assistant. */ export const AssistantAvatar = ({ - css, color = 'plain', size = 'm', ...props }: AssistantAvatarProps) => { - const { root } = useStyles(); - return ; + return ; }; diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/welcome_message.tsx b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/welcome_message.tsx index 6133df55c57e0..555461de16d77 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/welcome_message.tsx +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/welcome_message.tsx @@ -80,7 +80,7 @@ export function WelcomeMessage({ className={fullHeightClassName} > - + diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_body/empty_convo.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_body/empty_convo.tsx index 3aa0e2271beff..86bd31318349c 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_body/empty_convo.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_body/empty_convo.tsx @@ -9,7 +9,7 @@ import React, { Dispatch, SetStateAction } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; import { css } from '@emotion/react'; import { PromptResponse } from '@kbn/elastic-assistant-common'; -import { AssistantAnimatedIcon } from '../assistant_animated_icon'; +import { AssistantBeacon } from '@kbn/ai-assistant-icon'; import { SystemPrompt } from '../prompt_editor/system_prompt'; import { SetupKnowledgeBaseButton } from '../../knowledge_base/setup_knowledge_base_button'; import * as i18n from '../translations'; @@ -41,7 +41,7 @@ export const EmptyConvo: React.FC = ({ > - + diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_body/index.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_body/index.tsx index 757f385db058c..6fc10341864f3 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_body/index.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_body/index.tsx @@ -18,7 +18,7 @@ import { HttpSetup } from '@kbn/core-http-browser'; import { euiThemeVars } from '@kbn/ui-theme'; import { css } from '@emotion/react'; import { PromptResponse } from '@kbn/elastic-assistant-common'; -import { AssistantAnimatedIcon } from '../assistant_animated_icon'; +import { AssistantBeacon } from '@kbn/ai-assistant-icon'; import { EmptyConvo } from './empty_convo'; import { WelcomeSetup } from './welcome_setup'; import { Conversation } from '../../..'; @@ -102,7 +102,10 @@ export const AssistantBody: FunctionComponent = ({ {isLoading ? ( - } /> + } + /> ) : isWelcomeSetup ? ( = ({ data-test-subj="welcome-setup" > - + diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx index 03016f143b6b0..5c78ab2552ab4 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx @@ -8,9 +8,9 @@ import React, { useCallback, useEffect, useState } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiInlineEditTitle } from '@elastic/eui'; import { css } from '@emotion/react'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; import { DataStreamApis } from '../use_data_stream_apis'; import type { Conversation } from '../../..'; -import { AssistantAvatar } from '../assistant_avatar/assistant_avatar'; import { useConversation } from '../use_conversation'; import { NEW_CHAT } from '../conversations/conversation_sidepanel/translations'; @@ -51,7 +51,7 @@ export const AssistantTitle: React.FC<{ return ( - + (({ currentStep, isGenerating }) => { const { setStep } = useActions(); - const { euiTheme } = useEuiTheme(); const avatarCss = useAvatarCss(); + return ( @@ -56,13 +49,7 @@ export const Header = React.memo(({ currentStep, isGenerating }) => justifyContent="center" > - + diff --git a/x-pack/platform/plugins/shared/integration_assistant/public/components/create_integration/create_integration_landing/integration_assistant_card.tsx b/x-pack/platform/plugins/shared/integration_assistant/public/components/create_integration/create_integration_landing/integration_assistant_card.tsx index 3dec795111425..dbae30ad664de 100644 --- a/x-pack/platform/plugins/shared/integration_assistant/public/components/create_integration/create_integration_landing/integration_assistant_card.tsx +++ b/x-pack/platform/plugins/shared/integration_assistant/public/components/create_integration/create_integration_landing/integration_assistant_card.tsx @@ -15,7 +15,7 @@ import { EuiTitle, EuiBetaBadge, } from '@elastic/eui'; -import { AssistantAvatar } from '@kbn/elastic-assistant'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; import { useAuthorization } from '../../../common/hooks/use_authorization'; import { MissingPrivilegesTooltip } from '../../../common/components/authorization'; import { useNavigate, Page } from '../../../common/hooks/use_navigate'; @@ -28,7 +28,7 @@ export const IntegrationAssistantCard = React.memo(() => { - + = ({ indexName, markdownComment }) => { iconType={null} > - + {ASK_ASSISTANT} diff --git a/x-pack/solutions/security/packages/ecs_data_quality_dashboard/tsconfig.json b/x-pack/solutions/security/packages/ecs_data_quality_dashboard/tsconfig.json index 2d76e9b8b0b4b..95cb9be72b6ce 100644 --- a/x-pack/solutions/security/packages/ecs_data_quality_dashboard/tsconfig.json +++ b/x-pack/solutions/security/packages/ecs_data_quality_dashboard/tsconfig.json @@ -26,5 +26,6 @@ "@kbn/core", "@kbn/core-notifications-browser", "@kbn/core-notifications-browser-mocks", + "@kbn/ai-assistant-icon", ] } diff --git a/x-pack/solutions/security/packages/upselling/sections/attack_discovery/index.tsx b/x-pack/solutions/security/packages/upselling/sections/attack_discovery/index.tsx index 0c6a12c88d7fd..db9bc7c24ea69 100644 --- a/x-pack/solutions/security/packages/upselling/sections/attack_discovery/index.tsx +++ b/x-pack/solutions/security/packages/upselling/sections/attack_discovery/index.tsx @@ -5,10 +5,10 @@ * 2.0. */ -import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; import React, { useMemo } from 'react'; +import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; +import { AssistantBeacon } from '@kbn/ai-assistant-icon'; -import { AssistantAvatar } from './assistant_avatar/assistant_avatar'; import * as i18n from './translations'; interface Props { @@ -30,7 +30,7 @@ const AttackDiscoveryUpsellingSectionComponent: React.FC = ({ () => ( - + diff --git a/x-pack/solutions/security/packages/upselling/tsconfig.json b/x-pack/solutions/security/packages/upselling/tsconfig.json index 653738495ed81..93486d9365016 100644 --- a/x-pack/solutions/security/packages/upselling/tsconfig.json +++ b/x-pack/solutions/security/packages/upselling/tsconfig.json @@ -20,6 +20,7 @@ "@kbn/i18n", "@kbn/security-solution-navigation", "@kbn/shared-ux-page-kibana-template", + "@kbn/ai-assistant-icon", ], "exclude": [ "target/**/*" diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/index.tsx index b3be6370e905d..8b9dc2f2c80f4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/index.tsx @@ -9,7 +9,7 @@ import type { ClientMessage, GetAssistantMessages } from '@kbn/elastic-assistant import { EuiAvatar, EuiLoadingSpinner } from '@elastic/eui'; import React from 'react'; -import { AssistantAvatar } from '@kbn/elastic-assistant'; +import { AssistantAvatar } from '@kbn/ai-assistant-icon'; import type { Replacements } from '@kbn/elastic-assistant-common'; import { replaceAnonymizedValuesWithOriginalValues } from '@kbn/elastic-assistant-common'; import styled from '@emotion/styled'; @@ -117,9 +117,7 @@ export const getComments: GetAssistantMessages = ({ ? [ { username: i18n.SYSTEM, - timelineAvatar: ( - - ), + timelineAvatar: , timestamp: currentConversation.messages[0].timestamp.length === 0 ? new Date().toLocaleString() @@ -148,7 +146,7 @@ export const getComments: GetAssistantMessages = ({ timelineAvatar: isUser ? ( ) : ( - + ), timestamp: i18n.AT( message.timestamp.length === 0 diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/header_link.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/header_link.tsx index 342a95454cdb4..afbe0abd9fb01 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/header_link.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/header_link.tsx @@ -10,7 +10,7 @@ import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { useAssistantContext } from '@kbn/elastic-assistant/impl/assistant_context'; -import { AssistantAvatar } from '@kbn/elastic-assistant'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0; @@ -45,7 +45,7 @@ export const AssistantHeaderLink = () => { - + {LINK_LABEL} diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/title/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/title/index.tsx index 13326a07adc70..40e258f5c5116 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/title/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/title/index.tsx @@ -6,7 +6,6 @@ */ import { EuiFlexGroup, EuiFlexItem, EuiSkeletonTitle, EuiTitle, useEuiTheme } from '@elastic/eui'; -import { AssistantAvatar } from '@kbn/elastic-assistant'; import { replaceAnonymizedValuesWithOriginalValues, type Replacements, @@ -14,6 +13,7 @@ import { import { css } from '@emotion/react'; import React, { useMemo } from 'react'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; const AVATAR_SIZE = 24; // px @@ -55,11 +55,11 @@ const TitleComponent: React.FC = ({ data-test-subj="assistantAvatar" grow={false} > - diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/view_in_ai_assistant/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/view_in_ai_assistant/index.tsx index e254ce5d334b8..3a10a9be9c8c6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/view_in_ai_assistant/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/view_in_ai_assistant/index.tsx @@ -5,11 +5,11 @@ * 2.0. */ -import { AssistantAvatar } from '@kbn/elastic-assistant'; import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import { EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React from 'react'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; import * as i18n from './translations'; import { useViewInAiAssistant } from './use_view_in_ai_assistant'; @@ -48,7 +48,7 @@ const ViewInAiAssistantComponent: React.FC = ({ > - + {i18n.VIEW_IN_AI_ASSISTANT} diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/empty_prompt/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/empty_prompt/index.tsx index 3d89f5be87030..ecaf1753a3263 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/empty_prompt/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/empty_prompt/index.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import { AssistantAvatar } from '@kbn/elastic-assistant'; import { EuiEmptyPrompt, EuiFlexGroup, @@ -19,6 +18,7 @@ import { import { css } from '@emotion/react'; import React, { useMemo } from 'react'; +import { AssistantBeacon } from '@kbn/ai-assistant-icon'; import { AnimatedCounter } from './animated_counter'; import { Generate } from '../generate'; import * as i18n from './translations'; @@ -50,7 +50,7 @@ const EmptyPromptComponent: React.FC = ({ gutterSize="none" > - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/no_alerts/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/no_alerts/index.tsx index ace75f568bf3d..216b7355fe486 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/no_alerts/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/no_alerts/index.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import { AssistantAvatar } from '@kbn/elastic-assistant'; import { EuiEmptyPrompt, EuiFlexGroup, @@ -16,6 +15,7 @@ import { } from '@elastic/eui'; import React, { useMemo } from 'react'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; import * as i18n from './translations'; import { Generate } from '../generate'; @@ -35,7 +35,7 @@ const NoAlertsComponent: React.FC = ({ isDisabled, isLoading, onGenerate gutterSize="none" > - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/welcome/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/welcome/index.tsx index 7ab90b524bb93..f03727fc87dbe 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/welcome/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/empty_states/welcome/index.tsx @@ -5,11 +5,11 @@ * 2.0. */ -import { AssistantAvatar } from '@kbn/elastic-assistant'; import { ConnectorSetup } from '@kbn/elastic-assistant/impl/connectorland/connector_setup'; import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; import React, { useMemo } from 'react'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; import * as i18n from './translations'; const WelcomeComponent: React.FC = () => { @@ -22,7 +22,7 @@ const WelcomeComponent: React.FC = () => { gutterSize="none" > - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/ai_assistant/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/ai_assistant/index.tsx index b0142b0e32f7e..8900e69254753 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/ai_assistant/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/ai_assistant/index.tsx @@ -9,8 +9,10 @@ import React, { useCallback } from 'react'; import { EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { NewChat, AssistantAvatar } from '@kbn/elastic-assistant'; +import { NewChat } from '@kbn/elastic-assistant'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; +import { css } from '@emotion/react'; import { METRIC_TYPE, TELEMETRY_EVENT, track } from '../../../../common/lib/telemetry'; import { useAssistantAvailability } from '../../../../assistant/use_assistant_availability'; import * as i18nAssistant from '../../../../detections/pages/detection_engine/translations'; @@ -116,7 +118,13 @@ Proposed solution should be valid and must not contain new line symbols (\\n)`; isAssistantEnabled={isAssistantEnabled} onExportCodeBlock={handleOnExportCodeBlock} > - {i18n.ASK_ASSISTANT_ERROR_BUTTON} + {' '} + {i18n.ASK_ASSISTANT_ERROR_BUTTON} ), }} diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_scan.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_scan.tsx index 74b1147531a01..2bb37cb74b67c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_scan.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_scan.tsx @@ -8,7 +8,6 @@ import React, { useCallback, useMemo } from 'react'; import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; import { - AssistantAvatar, DEFEND_INSIGHTS_STORAGE_KEY, ConnectorSelectorInline, DEFAULT_ASSISTANT_NAMESPACE, @@ -17,6 +16,7 @@ import { import { noop } from 'lodash/fp'; import useLocalStorage from 'react-use/lib/useLocalStorage'; import { some } from 'lodash'; +import { AssistantBeacon } from '@kbn/ai-assistant-icon'; import { useSpaceId } from '../../../../../../../common/hooks/use_space_id'; import { WORKFLOW_INSIGHTS } from '../../../translations'; import { useKibana } from '../../../../../../../common/lib/kibana'; @@ -106,7 +106,7 @@ export const WorkflowInsightsScanSection = ({ - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/assistant/index.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/assistant/index.ts index 4850b1ee2d865..e1a8640249b39 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/assistant/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/assistant/index.ts @@ -6,7 +6,7 @@ */ import React from 'react'; -import { AssistantAvatar } from '@kbn/elastic-assistant'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; import type { OnboardingCardConfig } from '../../../../types'; import { OnboardingCardId } from '../../../../constants'; import { ASSISTANT_CARD_TITLE } from './translations'; @@ -16,7 +16,7 @@ import type { AssistantCardMetadata } from './types'; export const assistantCardConfig: OnboardingCardConfig = { id: OnboardingCardId.assistant, title: ASSISTANT_CARD_TITLE, - icon: AssistantAvatar, + icon: AssistantIcon, Component: React.lazy( () => import( diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/siem_migrations/ai_connector/index.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/siem_migrations/ai_connector/index.ts index d0b32eb1bd638..9e8426df92ddc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/siem_migrations/ai_connector/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/cards/siem_migrations/ai_connector/index.ts @@ -6,7 +6,7 @@ */ import React from 'react'; -import { AssistantAvatar } from '@kbn/elastic-assistant/impl/assistant/assistant_avatar/assistant_avatar'; +import { AssistantIcon } from '@kbn/ai-assistant-icon'; import type { OnboardingCardConfig } from '../../../../../types'; import { OnboardingCardId } from '../../../../../constants'; import { AI_CONNECTOR_CARD_TITLE } from './translations'; @@ -16,7 +16,7 @@ import type { AIConnectorCardMetadata } from './types'; export const aiConnectorCardConfig: OnboardingCardConfig = { id: OnboardingCardId.siemMigrationsAiConnectors, title: AI_CONNECTOR_CARD_TITLE, - icon: AssistantAvatar, + icon: AssistantIcon, Component: React.lazy( () => import( diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/index.tsx index 8561eff458a26..ab5d9deb3852d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/summary/index.tsx @@ -7,9 +7,9 @@ import React, { useMemo } from 'react'; import type { EuiCommentProps } from '@elastic/eui'; -import { EuiAvatar, EuiCommentList, EuiMarkdownFormat, EuiSpacer } from '@elastic/eui'; +import { EuiCommentList, EuiMarkdownFormat, EuiSpacer } from '@elastic/eui'; import moment from 'moment'; -import { AssistantAvatar } from '@kbn/elastic-assistant'; +import { AssistantAvatar } from '@kbn/ai-assistant-icon'; import { RuleMigrationStatusEnum, type RuleMigration, @@ -31,9 +31,7 @@ export const SummaryTab: React.FC = React.memo(({ ruleMigration return { username: i18n.ASSISTANT_USERNAME, timelineAvatarAriaLabel: i18n.ASSISTANT_USERNAME, - timelineAvatar: ( - - ), + timelineAvatar: , event: ruleMigration.status === RuleMigrationStatusEnum.failed ? i18n.COMMENT_EVENT_FAILED From a0eebb82c9ef8385cecd4a5f6c0d1ebd22561789 Mon Sep 17 00:00:00 2001 From: David Olaru Date: Thu, 2 Jan 2025 17:10:20 +0000 Subject: [PATCH 06/11] [ftr] Speed up FTR code owner check (#205093) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Switch to one matcher w/ all code owner patterns rather than separate matchers for each code owner pattern. Reduces the run time of `scripts/check_ftr_code_owners.js` by ~10x. ### Before ```console ▶ node scripts/check_ftr_code_owners.js info Reading CODEOWNERS file info Checking ownership for 8653 test files (this will take a while) info Ownership check complete (took 18.89 s) succ All test files have a code owner. 🥳 ``` #### After ```console ▶ node scripts/check_ftr_code_owners.js info Checked 8653 test files in 1.59s succ All test files have a code owner 🥳 ``` --- packages/kbn-test/index.ts | 2 - .../functional_test_runner/cli/code_owners.ts | 48 +++++++++++++ .../{cli.ts => cli/ftr.ts} | 4 +- .../src/functional_test_runner/cli/index.ts | 11 +++ .../src/functional_test_runner/index.ts | 2 +- .../run_check_ftr_code_owners.ts | 67 ------------------- scripts/check_ftr_code_owners.js | 2 +- 7 files changed, 63 insertions(+), 73 deletions(-) create mode 100644 packages/kbn-test/src/functional_test_runner/cli/code_owners.ts rename packages/kbn-test/src/functional_test_runner/{cli.ts => cli/ftr.ts} (98%) create mode 100644 packages/kbn-test/src/functional_test_runner/cli/index.ts delete mode 100644 packages/kbn-test/src/functional_test_runner/run_check_ftr_code_owners.ts diff --git a/packages/kbn-test/index.ts b/packages/kbn-test/index.ts index b5506cc804ad3..cc97a4afa7906 100644 --- a/packages/kbn-test/index.ts +++ b/packages/kbn-test/index.ts @@ -69,8 +69,6 @@ export { getUrl } from './src/jest/get_url'; export { runCheckJestConfigsCli } from './src/jest/run_check_jest_configs_cli'; -export { runCheckFtrCodeOwnersCli } from './src/functional_test_runner/run_check_ftr_code_owners'; - export { runJest } from './src/jest/run'; export * from './src/kbn_archiver_cli'; diff --git a/packages/kbn-test/src/functional_test_runner/cli/code_owners.ts b/packages/kbn-test/src/functional_test_runner/cli/code_owners.ts new file mode 100644 index 0000000000000..62948bbfcde55 --- /dev/null +++ b/packages/kbn-test/src/functional_test_runner/cli/code_owners.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { run } from '@kbn/dev-cli-runner'; +import { createFailError } from '@kbn/dev-cli-errors'; +import { getRepoFiles } from '@kbn/get-repo-files'; +import { getCodeOwnersEntries } from '@kbn/code-owners'; +import ignore from 'ignore'; + +const TEST_DIRECTORIES = ['test', 'x-pack/test', 'x-pack/test_serverless']; + +export async function checkFTRCodeOwnersCLI() { + await run( + async ({ log }) => { + const matcher = ignore().add( + getCodeOwnersEntries() + .filter((entry) => entry.teams.length > 0) + .map((entry) => entry.pattern) + ); + const hasOwner = (path: string): boolean => matcher.test(path).ignored; + + const testFiles = await getRepoFiles(TEST_DIRECTORIES); + const filesWithoutOwner = testFiles + .filter((repoPath) => !hasOwner(repoPath.repoRel)) + .map((repoPath) => repoPath.repoRel); + + log.info(`Checked ${testFiles.length} test files in ${process.uptime().toFixed(2)}s`); + + if (filesWithoutOwner.length === 0) { + log.success(`All test files have a code owner 🥳`); + return; + } + + log.write('Test files without a code owner:'); + log.write(filesWithoutOwner.map((i) => ` - ${i}`).join('\n')); + throw createFailError(`Found ${filesWithoutOwner.length} test files without code owner`); + }, + { + description: 'Check that all test files are covered by GitHub CODEOWNERS', + } + ); +} diff --git a/packages/kbn-test/src/functional_test_runner/cli.ts b/packages/kbn-test/src/functional_test_runner/cli/ftr.ts similarity index 98% rename from packages/kbn-test/src/functional_test_runner/cli.ts rename to packages/kbn-test/src/functional_test_runner/cli/ftr.ts index fe153e17b8d69..d9694973e9252 100644 --- a/packages/kbn-test/src/functional_test_runner/cli.ts +++ b/packages/kbn-test/src/functional_test_runner/cli/ftr.ts @@ -16,8 +16,8 @@ import { ToolingLog } from '@kbn/tooling-log'; import { getTimeReporter } from '@kbn/ci-stats-reporter'; import exitHook from 'exit-hook'; -import { readConfigFile, EsVersion } from './lib'; -import { FunctionalTestRunner } from './functional_test_runner'; +import { readConfigFile, EsVersion } from '../lib'; +import { FunctionalTestRunner } from '../functional_test_runner'; export function runFtrCli() { const runStartTime = Date.now(); diff --git a/packages/kbn-test/src/functional_test_runner/cli/index.ts b/packages/kbn-test/src/functional_test_runner/cli/index.ts new file mode 100644 index 0000000000000..6e29c1bdc231f --- /dev/null +++ b/packages/kbn-test/src/functional_test_runner/cli/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export { runFtrCli } from './ftr'; +export { checkFTRCodeOwnersCLI } from './code_owners'; diff --git a/packages/kbn-test/src/functional_test_runner/index.ts b/packages/kbn-test/src/functional_test_runner/index.ts index 6c5641cbe8aab..42bdde23b0439 100644 --- a/packages/kbn-test/src/functional_test_runner/index.ts +++ b/packages/kbn-test/src/functional_test_runner/index.ts @@ -18,6 +18,6 @@ export { runCheckFtrConfigsCli, DedicatedTaskRunner, } from './lib'; -export { runFtrCli } from './cli'; +export * from './cli'; export * from './lib/docker_servers'; export * from './public_types'; diff --git a/packages/kbn-test/src/functional_test_runner/run_check_ftr_code_owners.ts b/packages/kbn-test/src/functional_test_runner/run_check_ftr_code_owners.ts deleted file mode 100644 index 8a1ec50bd1a3e..0000000000000 --- a/packages/kbn-test/src/functional_test_runner/run_check_ftr_code_owners.ts +++ /dev/null @@ -1,67 +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 - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { run } from '@kbn/dev-cli-runner'; -import { createFailError } from '@kbn/dev-cli-errors'; -import { getRepoFiles } from '@kbn/get-repo-files'; -import { getOwningTeamsForPath, getCodeOwnersEntries } from '@kbn/code-owners'; - -const TEST_DIRECTORIES = ['test', 'x-pack/test', 'x-pack/test_serverless']; - -const fmtMs = (ms: number) => { - if (ms < 1000) { - return `${Math.round(ms)} ms`; - } - - return `${(Math.round(ms) / 1000).toFixed(2)} s`; -}; - -const fmtList = (list: Iterable) => [...list].map((i) => ` - ${i}`).join('\n'); - -export async function runCheckFtrCodeOwnersCli() { - run( - async ({ log }) => { - const start = performance.now(); - - const missingOwners = new Set(); - - // cache codeowners for quicker lookup - log.info('Reading CODEOWNERS file'); - const codeOwnersEntries = getCodeOwnersEntries(); - - const testFiles = await getRepoFiles(TEST_DIRECTORIES); - log.info(`Checking ownership for ${testFiles.length} test files (this will take a while)`); - - for (const { repoRel } of testFiles) { - const owners = getOwningTeamsForPath(repoRel, codeOwnersEntries); - - if (owners.length === 0) { - missingOwners.add(repoRel); - } - } - - const timeSpent = fmtMs(performance.now() - start); - log.info(`Ownership check complete (took ${timeSpent})`); - - if (missingOwners.size) { - log.error( - `The following test files do not have a GitHub code owner:\n${fmtList(missingOwners)}` - ); - throw createFailError( - `Found ${missingOwners.size} test files without code owner (checked ${testFiles.length} test files in ${timeSpent})` - ); - } - - log.success(`All test files have a code owner. 🥳`); - }, - { - description: 'Check that all test files are covered by GitHub CODEOWNERS', - } - ); -} diff --git a/scripts/check_ftr_code_owners.js b/scripts/check_ftr_code_owners.js index 875f835d1d7b4..b35590500b313 100644 --- a/scripts/check_ftr_code_owners.js +++ b/scripts/check_ftr_code_owners.js @@ -8,4 +8,4 @@ */ require('../src/setup_node_env'); -require('@kbn/test').runCheckFtrCodeOwnersCli(); +void require('@kbn/test').checkFTRCodeOwnersCLI(); From a0c94f433ac438787b4564750606efd847acfa2c Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Thu, 2 Jan 2025 12:27:26 -0500 Subject: [PATCH 07/11] chore(slo): cleanup error log message (#205334) --- .../observability/plugins/slo/server/plugin.ts | 4 ++-- .../plugins/slo/server/services/create_slo.ts | 4 ++-- .../plugins/slo/server/services/reset_slo.ts | 2 +- .../slo/server/services/resource_installer.ts | 2 +- .../plugins/slo/server/services/slo_installer.ts | 2 +- .../slo/server/services/summary_search_client.ts | 2 +- .../server/services/summay_transform_manager.ts | 10 +++++----- .../services/tasks/orphan_summary_cleanup_task.ts | 10 ++++++---- .../services/transform_generators/common.ts | 2 +- .../slo/server/services/transform_manager.ts | 15 ++++++++------- .../plugins/slo/server/services/update_slo.ts | 8 ++++---- 11 files changed, 32 insertions(+), 29 deletions(-) diff --git a/x-pack/solutions/observability/plugins/slo/server/plugin.ts b/x-pack/solutions/observability/plugins/slo/server/plugin.ts index e7b25fe06ef32..c7a5a1dda3280 100644 --- a/x-pack/solutions/observability/plugins/slo/server/plugin.ts +++ b/x-pack/solutions/observability/plugins/slo/server/plugin.ts @@ -160,8 +160,8 @@ export class SLOPlugin const sloInstaller = new DefaultSLOInstaller(sloResourceInstaller, this.logger); await sloInstaller.install(); }) - .catch((error) => { - this.logger.error(`Failed to install the default SLOs: ${error}`); + .catch(() => { + // noop - error already logged from the installer }); this.sloOrphanCleanupTask = new SloOrphanSummaryCleanupTask( diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts index a8e01fb4681f4..c74f49c1ccac8 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts @@ -100,14 +100,14 @@ export class CreateSLO { ]); } catch (err) { this.logger.error( - `Cannot install the SLO [id: ${slo.id}, revision: ${slo.revision}]. Rolling back.` + `Cannot create the SLO [id: ${slo.id}, revision: ${slo.revision}]. Rolling back. ${err}` ); await asyncForEach(rollbackOperations.reverse(), async (operation) => { try { await operation(); } catch (rollbackErr) { - this.logger.error('Rollback operation failed', rollbackErr); + this.logger.error(`Rollback operation failed. ${rollbackErr}`); } }); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/reset_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/reset_slo.ts index c9da382c2d6ce..e91e720b4fd8d 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/reset_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/reset_slo.ts @@ -87,7 +87,7 @@ export class ResetSLO { ); } catch (err) { this.logger.error( - `Cannot reset the SLO [id: ${slo.id}, revision: ${slo.revision}]. Rolling back.` + `Cannot reset the SLO [id: ${slo.id}, revision: ${slo.revision}]. Rolling back. ${err}` ); await this.summaryTransformManager.stop(summaryTransformId); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.ts b/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.ts index b81fbe183c4ff..d6544d352f90f 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.ts @@ -79,7 +79,7 @@ export class DefaultResourceInstaller implements ResourceInstaller { await this.createIndex(SLO_SUMMARY_DESTINATION_INDEX_NAME); await this.createIndex(SLO_SUMMARY_TEMP_INDEX_NAME); } catch (err) { - this.logger.error(`Error installing resources shared for SLO: ${err.message}`); + this.logger.error(`Error while installing SLO shared resources: ${err}`); throw err; } } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.ts index 9484ecd907d9f..eab4c266aae8e 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.ts @@ -29,7 +29,7 @@ export class DefaultSLOInstaller implements SLOInstaller { await this.sloResourceInstaller.ensureCommonResourcesInstalled(); } catch (error) { - this.logger.error('Failed to install SLO common resources'); + this.logger.error(`Failed to install SLO common resources: ${error}`); } finally { this.isInstalling = false; clearTimeout(installTimeout); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_search_client.ts b/x-pack/solutions/observability/plugins/slo/server/services/summary_search_client.ts index 6493e613bbedc..0d12ee7255dc8 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_search_client.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_search_client.ts @@ -177,7 +177,7 @@ export class DefaultSummarySearchClient implements SummarySearchClient { }), }; } catch (err) { - this.logger.error(new Error(`Summary search query error, ${err.message}`, { cause: err })); + this.logger.error(`Error while searching SLO summary documents. ${err}`); return { total: 0, perPage: pagination.perPage, page: pagination.page, results: [] }; } } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summay_transform_manager.ts b/x-pack/solutions/observability/plugins/slo/server/services/summay_transform_manager.ts index 27d24e7fb5039..9389210505b4c 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summay_transform_manager.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summay_transform_manager.ts @@ -32,7 +32,7 @@ export class DefaultSummaryTransformManager implements TransformManager { } ); } catch (err) { - this.logger.error(`Cannot create summary transform for SLO [${slo.id}]`); + this.logger.error(`Cannot create summary transform for SLO [${slo.id}]. ${err}`); if (err.meta?.body?.error?.type === 'security_exception') { throw new SecurityException(err.meta.body.error.reason); } @@ -57,7 +57,7 @@ export class DefaultSummaryTransformManager implements TransformManager { { logger: this.logger } ); } catch (err) { - this.logger.error(`Cannot preview SLO summary transform [${transformId}]`); + this.logger.error(`Cannot preview SLO summary transform [${transformId}]. ${err}`); throw err; } } @@ -75,7 +75,7 @@ export class DefaultSummaryTransformManager implements TransformManager { } ); } catch (err) { - this.logger.error(`Cannot start SLO summary transform [${transformId}]`); + this.logger.error(`Cannot start SLO summary transform [${transformId}]. ${err}`); throw err; } } @@ -91,7 +91,7 @@ export class DefaultSummaryTransformManager implements TransformManager { { logger: this.logger } ); } catch (err) { - this.logger.error(`Cannot stop SLO summary transform [${transformId}]`); + this.logger.error(`Cannot stop SLO summary transform [${transformId}]. ${err}`); throw err; } } @@ -107,7 +107,7 @@ export class DefaultSummaryTransformManager implements TransformManager { { logger: this.logger } ); } catch (err) { - this.logger.error(`Cannot delete SLO summary transform [${transformId}]`); + this.logger.error(`Cannot delete SLO summary transform [${transformId}]. ${err}`); throw err; } } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.ts b/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.ts index c3d56854f4946..6d0aa1ee9c587 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.ts @@ -67,7 +67,7 @@ export class SloOrphanSummaryCleanupTask { }, cancel: async () => { - this.abortController.abort('[SLO] Definitions clean up Task timed out'); + this.abortController.abort('orphan-slo-summary-cleanup task timed out'); }, }; }, @@ -101,7 +101,7 @@ export class SloOrphanSummaryCleanupTask { if (sloSummaryIdsToDelete.length > 0) { this.logger.info( - `[SLO] Deleting ${sloSummaryIdsToDelete.length} SLO Summaries from the summary index` + `[SLO] Deleting ${sloSummaryIdsToDelete.length} SLO Summary documents from the summary index` ); await this.esClient.deleteByQuery({ @@ -124,7 +124,7 @@ export class SloOrphanSummaryCleanupTask { searchAfter?: AggregationsCompositeAggregateKey; sloSummaryIds: Array<{ id: string; revision: number }>; }> => { - this.logger.debug(`[SLO] Fetching SLO Summaries ids after ${searchAfter}`); + this.logger.debug(`[TASK] Fetching SLO Summary ids after ${searchAfter}`); if (!this.esClient) { return { searchAfter: undefined, @@ -227,7 +227,9 @@ export class SloOrphanSummaryCleanupTask { this.esClient = esClient; if (!taskManager) { - this.logger.info('[SLO] Missing required service during startup, skipping task.'); + this.logger.info( + 'Missing required service during startup, skipping orphan-slo-summary-cleanup task.' + ); return; } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/common.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/common.ts index 35a6e180650fa..4958a65a17a15 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/common.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/common.ts @@ -39,7 +39,7 @@ export function parseStringFilters(filters: string, logger: Logger) { try { return JSON.parse(filters); } catch (e) { - logger.error(`Failed to parse filters: ${e.message}`); + logger.info(`Failed to parse filters: ${e}`); } return {}; diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_manager.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_manager.ts index 464d1f1aeaa59..c07c8d78a5ca4 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_manager.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_manager.ts @@ -46,7 +46,9 @@ export class DefaultTransformManager implements TransformManager { } ); } catch (err) { - this.logger.error(`Cannot create SLO transform for indicator type [${slo.indicator.type}]`); + this.logger.error( + `Cannot create SLO transform for indicator type [${slo.indicator.type}]. ${err}` + ); if (err.meta?.body?.error?.type === 'security_exception') { throw new SecurityException(err.meta.body.error.reason); } @@ -77,7 +79,7 @@ export class DefaultTransformManager implements TransformManager { { logger: this.logger } ); } catch (err) { - this.logger.error(`Cannot preview SLO transform [${transformId}]`); + this.logger.error(`Cannot preview SLO transform [${transformId}]. ${err}`); throw err; } } @@ -94,7 +96,7 @@ export class DefaultTransformManager implements TransformManager { ); await this.scheduleNowTransform(transformId); } catch (err) { - this.logger.error(`Cannot start SLO transform [${transformId}]`); + this.logger.error(`Cannot start SLO transform [${transformId}]. ${err}`); throw err; } } @@ -110,7 +112,7 @@ export class DefaultTransformManager implements TransformManager { { logger: this.logger } ); } catch (err) { - this.logger.error(`Cannot stop SLO transform [${transformId}]`); + this.logger.error(`Cannot stop SLO transform [${transformId}]. ${err}`); throw err; } } @@ -126,7 +128,7 @@ export class DefaultTransformManager implements TransformManager { { logger: this.logger } ); } catch (err) { - this.logger.error(`Cannot delete SLO transform [${transformId}]`); + this.logger.error(`Cannot delete SLO transform [${transformId}]. ${err}`); throw err; } } @@ -138,8 +140,7 @@ export class DefaultTransformManager implements TransformManager { this.logger.debug(`SLO transform [${transformId}] scheduled now successfully`); }) .catch((e) => { - this.logger.error(`Cannot schedule now SLO transform [${transformId}]`); - this.logger.error(e); + this.logger.error(`Cannot schedule now SLO transform [${transformId}]. ${e}`); }); } } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts index 402ca82acecd4..30d62140f80d9 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts @@ -103,14 +103,14 @@ export class UpdateSLO { ); } catch (err) { this.logger.error( - `Cannot update the SLO summary pipeline [id: ${updatedSlo.id}, revision: ${updatedSlo.revision}].` + `Cannot update the SLO summary pipeline [id: ${updatedSlo.id}, revision: ${updatedSlo.revision}]. ${err}` ); await asyncForEach(rollbackOperations.reverse(), async (operation) => { try { await operation(); } catch (rollbackErr) { - this.logger.error('Rollback operation failed', rollbackErr); + this.logger.error(`Rollback operation failed. ${rollbackErr}`); } }); @@ -182,14 +182,14 @@ export class UpdateSLO { ); } catch (err) { this.logger.error( - `Cannot update the SLO [id: ${updatedSlo.id}, revision: ${updatedSlo.revision}]. Rolling back.` + `Cannot update the SLO [id: ${updatedSlo.id}, revision: ${updatedSlo.revision}]. Rolling back. ${err}` ); await asyncForEach(rollbackOperations.reverse(), async (operation) => { try { await operation(); } catch (rollbackErr) { - this.logger.error('Rollback operation failed', rollbackErr); + this.logger.error(`Rollback operation failed. ${rollbackErr}`); } }); From 6a84cccbdeb801b99e2d6fe62a976f994aa429c2 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Thu, 2 Jan 2025 18:45:08 +0100 Subject: [PATCH 08/11] =?UTF-8?q?[Reporting]=20don=E2=80=99t=20wait=20for?= =?UTF-8?q?=20refresh=20when=20uploading=20a=20chunk=20(#204775)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary close https://github.com/elastic/kibana-team/issues/1367 We saw significant slowness when uploading large CSV files in serverless. This PR should speed this up. Initially wait_for was introduced to reduce test flakiness https://github.com/elastic/kibana/pull/176022#discussion_r1511001636, but it seems it can be safely removed from uploading stream chunks Co-authored-by: Elastic Machine --- x-pack/plugins/reporting/server/lib/content_stream.test.ts | 4 ---- x-pack/plugins/reporting/server/lib/content_stream.ts | 2 -- 2 files changed, 6 deletions(-) diff --git a/x-pack/plugins/reporting/server/lib/content_stream.test.ts b/x-pack/plugins/reporting/server/lib/content_stream.test.ts index 6d3fccff0b91a..91ab3953aa8a9 100644 --- a/x-pack/plugins/reporting/server/lib/content_stream.test.ts +++ b/x-pack/plugins/reporting/server/lib/content_stream.test.ts @@ -300,7 +300,6 @@ describe('ContentStream', () => { id: expect.any(String), index: '.kibana-reporting', op_type: 'create', - refresh: 'wait_for', body: { '@timestamp': '1970-01-01T00:00:00.000Z', parent_id: 'something', @@ -317,7 +316,6 @@ describe('ContentStream', () => { id: expect.any(String), index: '.kibana-reporting', op_type: 'create', - refresh: 'wait_for', body: { '@timestamp': '1970-01-01T00:00:00.000Z', parent_id: 'something', @@ -348,7 +346,6 @@ describe('ContentStream', () => { id: expect.any(String), index: '.kibana-reporting', op_type: 'create', - refresh: 'wait_for', body: { parent_id: 'something', '@timestamp': '1970-01-01T00:00:00.000Z', @@ -365,7 +362,6 @@ describe('ContentStream', () => { id: expect.any(String), index: '.kibana-reporting', op_type: 'create', - refresh: 'wait_for', body: { parent_id: 'something', '@timestamp': '1970-01-01T00:00:00.000Z', diff --git a/x-pack/plugins/reporting/server/lib/content_stream.ts b/x-pack/plugins/reporting/server/lib/content_stream.ts index b3c113dd43c3b..e5006a4a45268 100644 --- a/x-pack/plugins/reporting/server/lib/content_stream.ts +++ b/x-pack/plugins/reporting/server/lib/content_stream.ts @@ -192,7 +192,6 @@ export class ContentStream extends Duplex { const body = await this.client.update({ ...this.document, - refresh: 'wait_for', body: { doc: { output: { content }, @@ -212,7 +211,6 @@ export class ContentStream extends Duplex { await this.client.index({ id, index: REPORTING_DATA_STREAM_ALIAS, - refresh: 'wait_for', op_type: 'create', body: { parent_id: parentId, From ca28d2dc5b379e81f68b31511a587e2724458fe7 Mon Sep 17 00:00:00 2001 From: Saikat Sarkar <132922331+saikatsarkar056@users.noreply.github.com> Date: Thu, 2 Jan 2025 11:41:09 -0700 Subject: [PATCH 09/11] [Ent Search Deprecation] Redirect enterprise_search to elasticsearch Urls (#204890) This PR resolves this https://github.com/elastic/search-team/issues/7961. This PR redirects all enterprise_search urls to elasticsearch urls. https://github.com/user-attachments/assets/d0fec395-f758-478f-a478-ad12ccdd57dd --------- Co-authored-by: Elastic Machine --- .../collectors/application_usage/schema.ts | 1 + src/plugins/telemetry/schema/oss_plugins.json | 131 ++++++++++++++++++ .../enterprise_search_redirect/index.test.tsx | 51 +++++++ .../enterprise_search_redirect/index.tsx | 35 +++++ .../enterprise_search_redirect/jest.config.js | 28 ++++ .../enterprise_search/public/plugin.ts | 17 +++ 6 files changed, 263 insertions(+) create mode 100644 x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/index.test.tsx create mode 100644 x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/index.tsx create mode 100644 x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/jest.config.js diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts index dd327dd4706d5..81e564da36292 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts @@ -141,6 +141,7 @@ export const applicationUsageSchema = { enterpriseSearchAnalytics: commonSchema, enterpriseSearchApplications: commonSchema, enterpriseSearchAISearch: commonSchema, + enterpriseSearchRedirect: commonSchema, enterpriseSearchSemanticSearch: commonSchema, enterpriseSearchVectorSearch: commonSchema, enterpriseSearchElasticsearch: commonSchema, diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 0e324ad0b4343..5b0712ac1e5a4 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -2753,6 +2753,137 @@ } } }, + "enterpriseSearchRedirect": { + "properties": { + "appId": { + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } + }, + "viewId": { + "type": "keyword", + "_meta": { + "description": "Always `main`" + } + }, + "clicks_total": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } + }, + "clicks_7_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } + }, + "clicks_30_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } + }, + "clicks_90_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } + }, + "minutes_on_screen_total": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } + }, + "minutes_on_screen_7_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } + }, + "minutes_on_screen_30_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } + }, + "minutes_on_screen_90_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } + }, + "views": { + "type": "array", + "items": { + "properties": { + "appId": { + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } + }, + "viewId": { + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } + }, + "clicks_total": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } + }, + "clicks_7_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } + }, + "clicks_30_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } + }, + "clicks_90_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } + }, + "minutes_on_screen_total": { + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } + }, + "minutes_on_screen_7_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } + }, + "minutes_on_screen_30_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } + }, + "minutes_on_screen_90_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } + } + } + } + } + } + }, "enterpriseSearchSemanticSearch": { "properties": { "appId": { diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/index.test.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/index.test.tsx new file mode 100644 index 0000000000000..94c19ba7ce869 --- /dev/null +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/index.test.tsx @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { MemoryRouter } from 'react-router-dom'; + +import { render, waitFor } from '@testing-library/react'; + +import { useKibana } from '@kbn/kibana-react-plugin/public'; + +import { ApplicationRedirect } from '.'; + +jest.mock('@kbn/kibana-react-plugin/public', () => ({ + useKibana: jest.fn(), +})); + +describe('RedirectWithReplace', () => { + const navigateToUrlMock = jest.fn(); + const coreMock = { + application: { + navigateToUrl: navigateToUrlMock, + }, + }; + + beforeEach(() => { + (useKibana as jest.Mock).mockReturnValue({ services: coreMock }); + + // Mock window.location.pathname + Object.defineProperty(window, 'location', { + writable: true, + value: { pathname: '/enterprise_search/content/search_indices' }, + }); + }); + + it('should redirect to the new path', async () => { + render( + + + + ); + + await waitFor(() => { + expect(navigateToUrlMock).toHaveBeenCalledWith('/elasticsearch/content/search_indices'); + }); + }); +}); diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/index.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/index.tsx new file mode 100644 index 0000000000000..d861f9e65c580 --- /dev/null +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/index.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect } from 'react'; + +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { Routes, Route } from '@kbn/shared-ux-router'; + +const RedirectWithReplace = () => { + const { application } = useKibana().services; + + useEffect(() => { + const fullPath = location.pathname; + + // Construct the new path by replacing 'enterprise_search' with 'elasticsearch' + const newPath = fullPath.replace('/enterprise_search', '/elasticsearch'); + + // Perform the client-side navigation using core + application?.navigateToUrl(newPath); + }, []); + + return null; +}; + +export const ApplicationRedirect = () => { + return ( + + + + ); +}; diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/jest.config.js b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/jest.config.js new file mode 100644 index 0000000000000..776cca733229a --- /dev/null +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect/jest.config.js @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../../../../..', + roots: [ + '/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect', + ], + collectCoverage: true, + coverageReporters: ['text', 'html'], + collectCoverageFrom: [ + '/x-pack/solutions/search/plugins/enterprise_search/public/applications/**/*.{ts,tsx}', + '!/x-pack/solutions/search/plugins/enterprise_search/public/*.ts', + '!/x-pack/solutions/search/plugins/enterprise_search/server/*.ts', + '!/x-pack/solutions/search/plugins/enterprise_search/public/applications/test_helpers/**/*.{ts,tsx}', + ], + coverageDirectory: + '/target/kibana-coverage/jest/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_redirect', + modulePathIgnorePatterns: [ + '/x-pack/solutions/search/plugins/enterprise_search/public/applications/app_search/cypress', + '/x-pack/solutions/search/plugins/enterprise_search/public/applications/workplace_search/cypress', + ], +}; diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts b/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts index 0a472cd2aa564..6c33d08913c54 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts @@ -489,6 +489,23 @@ export class EnterpriseSearchPlugin implements Plugin { visibleIn: [], }); + core.application.register({ + appRoute: '/app/enterprise_search', + category: DEFAULT_APP_CATEGORIES.enterpriseSearch, + id: 'enterpriseSearchRedirect', + mount: async (params: AppMountParameters) => { + const kibanaDeps = await this.getKibanaDeps(core, params, cloud); + const pluginData = this.getPluginData(); + + const { renderApp } = await import('./applications'); + const { ApplicationRedirect } = await import('./applications/enterprise_search_redirect'); + + return renderApp(ApplicationRedirect, kibanaDeps, pluginData); + }, + title: 'EnterpriseSearchRedirect', + visibleIn: [], + }); + if (plugins.home) { plugins.home.featureCatalogue.registerSolution({ description: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.DESCRIPTION, From 2ee9cbf377e217cac0fa07a4394d3d0d2184285c Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 2 Jan 2025 11:43:14 -0700 Subject: [PATCH 10/11] [embeddable] remove embeddable class (#205164) Part of embeddable rebuild clean-up. Removes legacy Embeddable class and types from embeddable plugin. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Elastic Machine --- .../embeddable_api_context.ts | 22 +++++++ .../presentation_publishing/index.ts | 8 +-- .../dashboard/public/dashboard_api/types.ts | 11 +--- .../public/dashboard_container/index.ts | 1 - .../panel_placement/index.ts | 2 +- .../panel_placement/types.ts | 11 ---- .../plugins/shared/dashboard/public/index.ts | 1 - .../plugins/shared/embeddable/public/index.ts | 7 --- .../embeddables/embeddable_error_handler.tsx | 58 ------------------- .../public/lib/embeddables/index.ts | 14 ----- .../shared/embeddable/public/lib/index.ts | 1 - .../public/lib/triggers/triggers.ts | 14 ----- .../plugins/shared/embeddable/tsconfig.json | 1 - .../floating_actions/floating_actions.tsx | 3 +- .../dynamic_action_grouping.ts | 6 +- src/plugins/visualizations/kibana.jsonc | 3 +- .../create_vis_embeddable_from_object.ts | 2 +- .../embeddable}/diff_embeddable_input.test.ts | 3 +- .../embeddable}/diff_embeddable_input.ts | 2 +- .../public/legacy/embeddable}/embeddable.tsx | 2 +- .../legacy/embeddable}/error_embeddable.scss | 0 .../legacy/embeddable}/error_embeddable.tsx | 0 .../public/legacy/embeddable}/i_embeddable.ts | 2 +- .../embeddable/visualize_embeddable.tsx | 4 +- src/plugins/visualizations/tsconfig.json | 3 +- .../legacy_visualizations/is_legacy_map.ts | 11 +--- .../shared/ml/public/embeddables/types.ts | 3 +- .../public/lib/variables/event_variables.ts | 9 ++- .../plugins/apm/public/embeddable/types.ts | 2 +- .../lens/add_to_timeline.test.ts | 26 ++++----- .../lens/copy_to_clipboard.test.ts | 19 +++--- .../alerts_histogram_panel/helpers.test.tsx | 6 +- .../alerts_histogram_panel/helpers.tsx | 8 ++- 33 files changed, 77 insertions(+), 188 deletions(-) create mode 100644 src/platform/packages/shared/presentation/presentation_publishing/embeddable_api_context.ts delete mode 100644 src/platform/plugins/shared/embeddable/public/lib/embeddables/embeddable_error_handler.tsx delete mode 100644 src/platform/plugins/shared/embeddable/public/lib/embeddables/index.ts rename src/{platform/plugins/shared/embeddable/public/lib/embeddables => plugins/visualizations/public/legacy/embeddable}/diff_embeddable_input.test.ts (98%) rename src/{platform/plugins/shared/embeddable/public/lib/embeddables => plugins/visualizations/public/legacy/embeddable}/diff_embeddable_input.ts (97%) rename src/{platform/plugins/shared/embeddable/public/lib/embeddables => plugins/visualizations/public/legacy/embeddable}/embeddable.tsx (99%) rename src/{platform/plugins/shared/embeddable/public/lib/embeddables => plugins/visualizations/public/legacy/embeddable}/error_embeddable.scss (100%) rename src/{platform/plugins/shared/embeddable/public/lib/embeddables => plugins/visualizations/public/legacy/embeddable}/error_embeddable.tsx (100%) rename src/{platform/plugins/shared/embeddable/public/lib/embeddables => plugins/visualizations/public/legacy/embeddable}/i_embeddable.ts (98%) diff --git a/src/platform/packages/shared/presentation/presentation_publishing/embeddable_api_context.ts b/src/platform/packages/shared/presentation/presentation_publishing/embeddable_api_context.ts new file mode 100644 index 0000000000000..3af7b7f428596 --- /dev/null +++ b/src/platform/packages/shared/presentation/presentation_publishing/embeddable_api_context.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export interface EmbeddableApiContext { + /** + * TODO: once all actions are entirely decoupled from the embeddable system, this key should be renamed to "api" + * to reflect the fact that this context could contain any api. + */ + embeddable: unknown; +} + +export const isEmbeddableApiContext = (context: unknown): context is EmbeddableApiContext => + !!context && + typeof context === 'object' && + !!(context as EmbeddableApiContext).embeddable && + typeof (context as EmbeddableApiContext).embeddable === 'object'; diff --git a/src/platform/packages/shared/presentation/presentation_publishing/index.ts b/src/platform/packages/shared/presentation/presentation_publishing/index.ts index 09e6453586665..62e68521a5b09 100644 --- a/src/platform/packages/shared/presentation/presentation_publishing/index.ts +++ b/src/platform/packages/shared/presentation/presentation_publishing/index.ts @@ -7,13 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -export interface EmbeddableApiContext { - /** - * TODO: once all actions are entirely decoupled from the embeddable system, this key should be renamed to "api" - * to reflect the fact that this context could contain any api. - */ - embeddable: unknown; -} +export { isEmbeddableApiContext, type EmbeddableApiContext } from './embeddable_api_context'; export { getInitialValuesFromComparators, diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts b/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts index 73e7e9422641f..238bd5976bfa1 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts @@ -41,12 +41,7 @@ import { ControlGroupSerializedState, } from '@kbn/controls-plugin/public'; import { Filter, Query, TimeRange } from '@kbn/es-query'; -import { - DefaultEmbeddableApi, - EmbeddablePackageState, - ErrorEmbeddable, - IEmbeddable, -} from '@kbn/embeddable-plugin/public'; +import type { DefaultEmbeddableApi, EmbeddablePackageState } from '@kbn/embeddable-plugin/public'; import { Observable, Subject } from 'rxjs'; import { RefreshInterval, SearchSessionInfoProvider } from '@kbn/data-plugin/public'; import { IKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; @@ -175,9 +170,7 @@ export type DashboardApi = CanExpandPanels & setTags: (tags: string[]) => void; setTimeRange: (timeRange?: TimeRange | undefined) => void; unifiedSearchFilters$: PublishesUnifiedSearch['filters$']; - - // TODO remove types below this line - from legacy embeddable system - untilEmbeddableLoaded: (id: string) => Promise; + untilEmbeddableLoaded: (id: string) => Promise; }; export interface DashboardInternalApi { diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_container/index.ts b/src/platform/plugins/shared/dashboard/public/dashboard_container/index.ts index c3f1989d66cd6..02b84b619aaf9 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_container/index.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_container/index.ts @@ -16,4 +16,3 @@ export const LATEST_DASHBOARD_CONTAINER_VERSION = convertNumberToDashboardVersio export { LazyDashboardRenderer } from './external_api/lazy_dashboard_renderer'; export type { DashboardLocatorParams } from './types'; -export type { IProvidesLegacyPanelPlacementSettings } from './panel_placement'; diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_container/panel_placement/index.ts b/src/platform/plugins/shared/dashboard/public/dashboard_container/panel_placement/index.ts index d903886695745..3706aefca3512 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_container/panel_placement/index.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_container/panel_placement/index.ts @@ -11,4 +11,4 @@ export { placeClonePanel } from './place_clone_panel_strategy'; export { registerDashboardPanelPlacementSetting } from './panel_placement_registry'; -export type { GetPanelPlacementSettings, IProvidesLegacyPanelPlacementSettings } from './types'; +export type { GetPanelPlacementSettings } from './types'; diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_container/panel_placement/types.ts b/src/platform/plugins/shared/dashboard/public/dashboard_container/panel_placement/types.ts index 2dd826f9a5821..93f9d2d7fc78e 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_container/panel_placement/types.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_container/panel_placement/types.ts @@ -7,7 +7,6 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { EmbeddableInput } from '@kbn/embeddable-plugin/public'; import { MaybePromise } from '@kbn/utility-types'; import { DashboardPanelState } from '../../../common'; import type { GridData } from '../../../server/content_management'; @@ -30,16 +29,6 @@ export interface PanelPlacementProps { currentPanels: { [key: string]: DashboardPanelState }; } -export interface IProvidesLegacyPanelPlacementSettings< - InputType extends EmbeddableInput = EmbeddableInput, - AttributesType = unknown -> { - getLegacyPanelPlacementSettings: ( - input: InputType, - attributes?: AttributesType - ) => Partial; -} - export type GetPanelPlacementSettings = ( serializedState?: SerializedState ) => MaybePromise; diff --git a/src/platform/plugins/shared/dashboard/public/index.ts b/src/platform/plugins/shared/dashboard/public/index.ts index 109be5bc0eaf0..458d1cc35ddde 100644 --- a/src/platform/plugins/shared/dashboard/public/index.ts +++ b/src/platform/plugins/shared/dashboard/public/index.ts @@ -22,7 +22,6 @@ export { LazyDashboardRenderer as DashboardRenderer, DASHBOARD_CONTAINER_TYPE, type DashboardLocatorParams, - type IProvidesLegacyPanelPlacementSettings, } from './dashboard_container'; export type { DashboardSetup, DashboardStart, DashboardFeatureFlagConfig } from './plugin'; diff --git a/src/platform/plugins/shared/embeddable/public/index.ts b/src/platform/plugins/shared/embeddable/public/index.ts index 4ec1c43df2dbb..b388427f402bc 100644 --- a/src/platform/plugins/shared/embeddable/public/index.ts +++ b/src/platform/plugins/shared/embeddable/public/index.ts @@ -17,10 +17,7 @@ export { CELL_VALUE_TRIGGER, contextMenuTrigger, CONTEXT_MENU_TRIGGER, - Embeddable, EmbeddableStateTransfer, - ErrorEmbeddable, - isContextMenuTriggerContext, isMultiValueClickTriggerContext, isRangeSelectTriggerContext, isRowClickTriggerContext, @@ -41,12 +38,8 @@ export { export type { CellValueContext, ChartActionContext, - EmbeddableContext, EmbeddableEditorState, - EmbeddableInput, - EmbeddableOutput, EmbeddablePackageState, - IEmbeddable, MultiValueClickContext, PropertySpec, RangeSelectContext, diff --git a/src/platform/plugins/shared/embeddable/public/lib/embeddables/embeddable_error_handler.tsx b/src/platform/plugins/shared/embeddable/public/lib/embeddables/embeddable_error_handler.tsx deleted file mode 100644 index 33402bfb85e0d..0000000000000 --- a/src/platform/plugins/shared/embeddable/public/lib/embeddables/embeddable_error_handler.tsx +++ /dev/null @@ -1,58 +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 - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { isFunction } from 'lodash'; -import React, { ReactNode, useEffect, useRef, useState } from 'react'; -import { isPromise } from '@kbn/std'; -import type { MaybePromise } from '@kbn/utility-types'; -import type { ErrorLike } from '@kbn/expressions-plugin/common'; -import type { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable'; - -type IReactEmbeddable = IEmbeddable>; - -interface EmbeddableErrorHandlerProps { - children: IReactEmbeddable['catchError']; - embeddable?: IReactEmbeddable; - error: ErrorLike | string; -} - -export function EmbeddableErrorHandler({ - children, - embeddable, - error, -}: EmbeddableErrorHandlerProps) { - const [node, setNode] = useState(); - const ref = useRef(null); - - useEffect(() => { - if (!ref.current) { - return; - } - - const handler = embeddable?.catchError?.bind(embeddable) ?? children; - if (!handler) { - return; - } - - const renderedNode = handler( - typeof error === 'string' ? { message: error, name: '' } : error, - ref.current - ); - if (isFunction(renderedNode)) { - return renderedNode; - } - if (isPromise(renderedNode)) { - renderedNode.then(setNode); - } else { - setNode(renderedNode); - } - }, [children, embeddable, error]); - - return
{node}
; -} diff --git a/src/platform/plugins/shared/embeddable/public/lib/embeddables/index.ts b/src/platform/plugins/shared/embeddable/public/lib/embeddables/index.ts deleted file mode 100644 index 029a653a9f1c6..0000000000000 --- a/src/platform/plugins/shared/embeddable/public/lib/embeddables/index.ts +++ /dev/null @@ -1,14 +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 - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export * from '../../../common/lib/saved_object_embeddable'; -export { Embeddable } from './embeddable'; -export { EmbeddableErrorHandler } from './embeddable_error_handler'; -export { ErrorEmbeddable } from './error_embeddable'; -export type { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable'; diff --git a/src/platform/plugins/shared/embeddable/public/lib/index.ts b/src/platform/plugins/shared/embeddable/public/lib/index.ts index 60f8a3638816d..3c816f15095b3 100644 --- a/src/platform/plugins/shared/embeddable/public/lib/index.ts +++ b/src/platform/plugins/shared/embeddable/public/lib/index.ts @@ -8,7 +8,6 @@ */ export * from './errors'; -export * from './embeddables'; export * from './types'; export * from './triggers'; export * from './state_transfer'; diff --git a/src/platform/plugins/shared/embeddable/public/lib/triggers/triggers.ts b/src/platform/plugins/shared/embeddable/public/lib/triggers/triggers.ts index 818c80283bf1c..cdebc6129afb6 100644 --- a/src/platform/plugins/shared/embeddable/public/lib/triggers/triggers.ts +++ b/src/platform/plugins/shared/embeddable/public/lib/triggers/triggers.ts @@ -12,14 +12,6 @@ import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; import { Datatable, DatatableColumnMeta } from '@kbn/expressions-plugin/common'; import { Trigger, RowClickContext } from '@kbn/ui-actions-plugin/public'; import { BooleanRelation } from '@kbn/es-query'; -import { IEmbeddable } from '..'; - -/** - * @deprecated use `EmbeddableApiContext` from `@kbn/presentation-publishing` - */ -export interface EmbeddableContext { - embeddable: T; -} export type ValueClickContext = Partial & { data: { @@ -192,9 +184,3 @@ export const isRowClickTriggerContext = (context: ChartActionContext): context i !!context.data && typeof context.data === 'object' && typeof (context as RowClickContext).data.rowIndex === 'number'; - -export const isContextMenuTriggerContext = (context: unknown): context is EmbeddableContext => - !!context && - typeof context === 'object' && - !!(context as EmbeddableContext).embeddable && - typeof (context as EmbeddableContext).embeddable === 'object'; diff --git a/src/platform/plugins/shared/embeddable/tsconfig.json b/src/platform/plugins/shared/embeddable/tsconfig.json index aeb64ab3f2c32..54498ade512b6 100644 --- a/src/platform/plugins/shared/embeddable/tsconfig.json +++ b/src/platform/plugins/shared/embeddable/tsconfig.json @@ -12,7 +12,6 @@ "@kbn/utility-types", "@kbn/es-query", "@kbn/i18n", - "@kbn/std", "@kbn/expressions-plugin", "@kbn/saved-objects-management-plugin", "@kbn/saved-objects-tagging-oss-plugin", diff --git a/src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.tsx b/src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.tsx index ade106ae11098..4fcc0ef869c96 100644 --- a/src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.tsx +++ b/src/platform/plugins/shared/presentation_util/public/components/floating_actions/floating_actions.tsx @@ -15,7 +15,6 @@ import { Subscription } from 'rxjs'; import { PANEL_HOVER_TRIGGER, panelHoverTrigger, - type EmbeddableInput, type ViewMode, } from '@kbn/embeddable-plugin/public'; import { apiHasUniqueId } from '@kbn/presentation-publishing'; @@ -31,7 +30,7 @@ export interface FloatingActionsProps { isEnabled?: boolean; api?: unknown; viewMode?: ViewMode; - disabledActions?: EmbeddableInput['disabledActions']; + disabledActions?: string[]; } export type FloatingActionItem = AnyApiAction & { diff --git a/src/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_grouping.ts b/src/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_grouping.ts index 640a3bbb70391..8493c00d522b5 100644 --- a/src/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_grouping.ts +++ b/src/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_grouping.ts @@ -8,12 +8,10 @@ */ import { i18n } from '@kbn/i18n'; -import { IEmbeddable } from '@kbn/embeddable-plugin/public'; +import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; import { UiActionsPresentableGrouping as PresentableGrouping } from '@kbn/ui-actions-plugin/public'; -export const dynamicActionGrouping: PresentableGrouping<{ - embeddable?: IEmbeddable; -}> = [ +export const dynamicActionGrouping: PresentableGrouping = [ { id: 'dynamicActions', getDisplayName: () => diff --git a/src/plugins/visualizations/kibana.jsonc b/src/plugins/visualizations/kibana.jsonc index 8e8b492e99a0b..33817bed4357f 100644 --- a/src/plugins/visualizations/kibana.jsonc +++ b/src/plugins/visualizations/kibana.jsonc @@ -45,7 +45,8 @@ "kibanaUtils", "kibanaReact", "charts", - "savedObjects" + "savedObjects", + "presentationPanel" ], "extraPublicDirs": [ "common/constants", diff --git a/src/plugins/visualizations/public/legacy/embeddable/create_vis_embeddable_from_object.ts b/src/plugins/visualizations/public/legacy/embeddable/create_vis_embeddable_from_object.ts index 76acb5da63c53..843aa51731abc 100644 --- a/src/plugins/visualizations/public/legacy/embeddable/create_vis_embeddable_from_object.ts +++ b/src/plugins/visualizations/public/legacy/embeddable/create_vis_embeddable_from_object.ts @@ -7,7 +7,6 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { ErrorEmbeddable } from '@kbn/embeddable-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import { Vis } from '../../types'; import type { @@ -22,6 +21,7 @@ import { getHttp, getTimeFilter, getCapabilities } from '../../services'; import { urlFor } from '../../utils/saved_visualize_utils'; import { createVisualizeEmbeddableAsync } from './visualize_embeddable_async'; import { AttributeService } from './attribute_service'; +import { ErrorEmbeddable } from './error_embeddable'; /** @deprecated * VisualizeEmbeddable is no longer registered with the legacy embeddable system and is only diff --git a/src/platform/plugins/shared/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts b/src/plugins/visualizations/public/legacy/embeddable/diff_embeddable_input.test.ts similarity index 98% rename from src/platform/plugins/shared/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts rename to src/plugins/visualizations/public/legacy/embeddable/diff_embeddable_input.test.ts index b4b8a2a1da920..80724cca7cd9f 100644 --- a/src/platform/plugins/shared/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts +++ b/src/plugins/visualizations/public/legacy/embeddable/diff_embeddable_input.test.ts @@ -7,9 +7,8 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { ViewMode } from '..'; import { KibanaExecutionContext } from '@kbn/core/types'; -import { EmbeddableInput } from '.'; +import { EmbeddableInput, ViewMode } from '@kbn/embeddable-plugin/common'; import { omitGenericEmbeddableInput, genericEmbeddableInputIsEqual } from './diff_embeddable_input'; const getGenericEmbeddableState = (state?: Partial): EmbeddableInput => { diff --git a/src/platform/plugins/shared/embeddable/public/lib/embeddables/diff_embeddable_input.ts b/src/plugins/visualizations/public/legacy/embeddable/diff_embeddable_input.ts similarity index 97% rename from src/platform/plugins/shared/embeddable/public/lib/embeddables/diff_embeddable_input.ts rename to src/plugins/visualizations/public/legacy/embeddable/diff_embeddable_input.ts index ba55f098bba45..baf145152f72b 100644 --- a/src/platform/plugins/shared/embeddable/public/lib/embeddables/diff_embeddable_input.ts +++ b/src/plugins/visualizations/public/legacy/embeddable/diff_embeddable_input.ts @@ -9,7 +9,7 @@ import fastIsEqual from 'fast-deep-equal'; import { pick, omit } from 'lodash'; -import { EmbeddableInput } from '.'; +import type { EmbeddableInput } from '@kbn/embeddable-plugin/common'; // list out the keys from the EmbeddableInput type to allow lodash to pick them later const allGenericInputKeys: Readonly> = [ diff --git a/src/platform/plugins/shared/embeddable/public/lib/embeddables/embeddable.tsx b/src/plugins/visualizations/public/legacy/embeddable/embeddable.tsx similarity index 99% rename from src/platform/plugins/shared/embeddable/public/lib/embeddables/embeddable.tsx rename to src/plugins/visualizations/public/legacy/embeddable/embeddable.tsx index 3af13b3d998a3..738df6d3280ea 100644 --- a/src/platform/plugins/shared/embeddable/public/lib/embeddables/embeddable.tsx +++ b/src/plugins/visualizations/public/legacy/embeddable/embeddable.tsx @@ -14,8 +14,8 @@ import { merge } from 'rxjs'; import { debounceTime, distinctUntilChanged, map, skip } from 'rxjs'; import { RenderCompleteDispatcher } from '@kbn/kibana-utils-plugin/public'; import { Adapters } from '@kbn/inspector-plugin/public'; +import { EmbeddableInput, ViewMode } from '@kbn/embeddable-plugin/common'; import { EmbeddableError, EmbeddableOutput, IEmbeddable } from './i_embeddable'; -import { EmbeddableInput, ViewMode } from '../../../common/types'; import { genericEmbeddableInputIsEqual, omitGenericEmbeddableInput } from './diff_embeddable_input'; function getPanelTitle(input: EmbeddableInput, output: EmbeddableOutput) { diff --git a/src/platform/plugins/shared/embeddable/public/lib/embeddables/error_embeddable.scss b/src/plugins/visualizations/public/legacy/embeddable/error_embeddable.scss similarity index 100% rename from src/platform/plugins/shared/embeddable/public/lib/embeddables/error_embeddable.scss rename to src/plugins/visualizations/public/legacy/embeddable/error_embeddable.scss diff --git a/src/platform/plugins/shared/embeddable/public/lib/embeddables/error_embeddable.tsx b/src/plugins/visualizations/public/legacy/embeddable/error_embeddable.tsx similarity index 100% rename from src/platform/plugins/shared/embeddable/public/lib/embeddables/error_embeddable.tsx rename to src/plugins/visualizations/public/legacy/embeddable/error_embeddable.tsx diff --git a/src/platform/plugins/shared/embeddable/public/lib/embeddables/i_embeddable.ts b/src/plugins/visualizations/public/legacy/embeddable/i_embeddable.ts similarity index 98% rename from src/platform/plugins/shared/embeddable/public/lib/embeddables/i_embeddable.ts rename to src/plugins/visualizations/public/legacy/embeddable/i_embeddable.ts index 51a24527dd4aa..29bb089ceeef2 100644 --- a/src/platform/plugins/shared/embeddable/public/lib/embeddables/i_embeddable.ts +++ b/src/plugins/visualizations/public/legacy/embeddable/i_embeddable.ts @@ -10,7 +10,7 @@ import { ErrorLike } from '@kbn/expressions-plugin/common'; import { Adapters } from '@kbn/inspector-plugin/public'; import { Observable } from 'rxjs'; -import { EmbeddableInput } from '../../../common/types'; +import type { EmbeddableInput } from '@kbn/embeddable-plugin/common'; export type EmbeddableError = ErrorLike; export type { EmbeddableInput }; diff --git a/src/plugins/visualizations/public/legacy/embeddable/visualize_embeddable.tsx b/src/plugins/visualizations/public/legacy/embeddable/visualize_embeddable.tsx index 1f631f30f8eb5..3f77ce9ecb661 100644 --- a/src/plugins/visualizations/public/legacy/embeddable/visualize_embeddable.tsx +++ b/src/plugins/visualizations/public/legacy/embeddable/visualize_embeddable.tsx @@ -22,7 +22,7 @@ import type { DataView } from '@kbn/data-views-plugin/public'; import { Warnings } from '@kbn/charts-plugin/public'; import { hasUnsupportedDownsampledAggregationFailure } from '@kbn/search-response-warnings'; import { Adapters } from '@kbn/inspector-plugin/public'; -import { Embeddable, EmbeddableInput, EmbeddableOutput } from '@kbn/embeddable-plugin/public'; +import { EmbeddableInput } from '@kbn/embeddable-plugin/common'; import { SavedObjectEmbeddableInput } from '@kbn/embeddable-plugin/common'; import { ExpressionAstExpression, @@ -47,6 +47,8 @@ import { VisSavedObject } from '../../types'; import { toExpressionAst } from '../../embeddable/to_ast'; import { AttributeService } from './attribute_service'; import { VisualizationsStartDeps } from '../../plugin'; +import { Embeddable } from './embeddable'; +import { EmbeddableOutput } from './i_embeddable'; export interface VisualizeEmbeddableDeps { start: StartServicesGetter< diff --git a/src/plugins/visualizations/tsconfig.json b/src/plugins/visualizations/tsconfig.json index 51deaf4139aa2..32811524e65f7 100644 --- a/src/plugins/visualizations/tsconfig.json +++ b/src/plugins/visualizations/tsconfig.json @@ -73,7 +73,8 @@ "@kbn/search-response-warnings", "@kbn/embeddable-enhanced-plugin", "@kbn/content-management-utils", - "@kbn/react-hooks" + "@kbn/react-hooks", + "@kbn/presentation-panel-plugin" ], "exclude": ["target/**/*"] } diff --git a/x-pack/platform/plugins/shared/maps/public/legacy_visualizations/is_legacy_map.ts b/x-pack/platform/plugins/shared/maps/public/legacy_visualizations/is_legacy_map.ts index 46f7b9cf27be5..bf04fd37ea74f 100644 --- a/x-pack/platform/plugins/shared/maps/public/legacy_visualizations/is_legacy_map.ts +++ b/x-pack/platform/plugins/shared/maps/public/legacy_visualizations/is_legacy_map.ts @@ -5,16 +5,7 @@ * 2.0. */ -import { Embeddable } from '@kbn/embeddable-plugin/public'; -import type { HasVisualizeConfig, VisualizeEmbeddable } from '@kbn/visualizations-plugin/public'; - -export function isLegacyMap(embeddable: Embeddable) { - return ( - embeddable.type === 'visualization' && - typeof (embeddable as VisualizeEmbeddable).getVis === 'function' && - ['region_map', 'tile_map'].includes((embeddable as VisualizeEmbeddable).getVis()?.type?.name) - ); -} +import type { HasVisualizeConfig } from '@kbn/visualizations-plugin/public'; export function isLegacyMapApi(api: HasVisualizeConfig) { return ['region_map', 'tile_map'].includes(api.getVis().type?.name); diff --git a/x-pack/platform/plugins/shared/ml/public/embeddables/types.ts b/x-pack/platform/plugins/shared/ml/public/embeddables/types.ts index 1bcb0f9ae3579..56749e7ab40cb 100644 --- a/x-pack/platform/plugins/shared/ml/public/embeddables/types.ts +++ b/x-pack/platform/plugins/shared/ml/public/embeddables/types.ts @@ -7,7 +7,8 @@ import type { CoreStart } from '@kbn/core/public'; import type { RefreshInterval } from '@kbn/data-plugin/common'; -import type { DefaultEmbeddableApi, EmbeddableInput } from '@kbn/embeddable-plugin/public'; +import type { DefaultEmbeddableApi } from '@kbn/embeddable-plugin/public'; +import type { EmbeddableInput } from '@kbn/embeddable-plugin/common'; import type { Filter, Query, TimeRange } from '@kbn/es-query'; import type { MlEntityField } from '@kbn/ml-anomaly-utils'; import type { diff --git a/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/event_variables.ts b/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/event_variables.ts index a66f1d1905dd8..7ef361172967a 100644 --- a/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/event_variables.ts +++ b/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/event_variables.ts @@ -7,13 +7,16 @@ import { i18n } from '@kbn/i18n'; import { monaco } from '@kbn/monaco'; -import { getPanelTitle, type PublishesPanelTitle } from '@kbn/presentation-publishing'; +import { + getPanelTitle, + isEmbeddableApiContext, + type PublishesPanelTitle, +} from '@kbn/presentation-publishing'; import { ChartActionContext, isRangeSelectTriggerContext, isValueClickTriggerContext, isRowClickTriggerContext, - isContextMenuTriggerContext, RangeSelectContext, SELECT_RANGE_TRIGGER, ValueClickContext, @@ -131,7 +134,7 @@ export const getEventScopeValues = (context: ChartActionContext): UrlDrilldownEv return getEventScopeFromValueClickTriggerContext(context); } else if (isRowClickTriggerContext(context)) { return getEventScopeFromRowClickTriggerContext(context); - } else if (isContextMenuTriggerContext(context)) { + } else if (isEmbeddableApiContext(context)) { return {}; } else { throw new Error("UrlDrilldown [getEventScope] can't build scope from not supported trigger"); diff --git a/x-pack/solutions/observability/plugins/apm/public/embeddable/types.ts b/x-pack/solutions/observability/plugins/apm/public/embeddable/types.ts index 14b8d18fe2101..1e61aedcd0e2d 100644 --- a/x-pack/solutions/observability/plugins/apm/public/embeddable/types.ts +++ b/x-pack/solutions/observability/plugins/apm/public/embeddable/types.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { EmbeddableInput } from '@kbn/embeddable-plugin/public'; +import type { EmbeddableInput } from '@kbn/embeddable-plugin/common'; import type { CoreStart, CoreSetup } from '@kbn/core/public'; import type { ObservabilityRuleTypeRegistry } from '@kbn/observability-plugin/public'; import type { ApmPluginStartDeps, ApmPluginSetupDeps } from '../plugin'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts index ef920458f51dd..362fb5f9ee885 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts @@ -5,8 +5,7 @@ * 2.0. */ import { BehaviorSubject, Subject } from 'rxjs'; -import type { CellValueContext, EmbeddableInput, IEmbeddable } from '@kbn/embeddable-plugin/public'; -import { ErrorEmbeddable } from '@kbn/embeddable-plugin/public'; +import type { CellValueContext } from '@kbn/embeddable-plugin/public'; import type { SecurityAppStore } from '../../../../common/store/types'; import { createAddToTimelineLensAction, getInvestigatedValue } from './add_to_timeline'; import { KibanaServices } from '../../../../common/lib/kibana'; @@ -15,7 +14,7 @@ import type { DataProvider } from '../../../../../common/types'; import { TimelineId, EXISTS_OPERATOR } from '../../../../../common/types'; import { addProvider } from '../../../../timelines/store/actions'; import type { ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; -import type { Query, Filter, AggregateQuery, TimeRange } from '@kbn/es-query'; +import type { TimeRange } from '@kbn/es-query'; import type { LensApi } from '@kbn/lens-plugin/public'; import { getLensApiMock } from '@kbn/lens-plugin/public/react_embeddable/mocks'; @@ -46,16 +45,6 @@ const getMockLensApi = ( saveToLibrary: jest.fn(async () => 'saved-id'), }); -const getMockEmbeddable = (type: string): IEmbeddable => - ({ - type, - filters$: new BehaviorSubject([]), - query$: new BehaviorSubject({ - query: 'test', - language: 'kuery', - }), - } as unknown as IEmbeddable); - const lensEmbeddable = getMockLensApi(); const columnMeta = { @@ -90,11 +79,14 @@ describe('createAddToTimelineLensAction', () => { }); describe('isCompatible', () => { - it('should return false if error embeddable', async () => { + it('should return false if lens embeddable has blocking error', async () => { expect( await addToTimelineAction.isCompatible({ ...context, - embeddable: new ErrorEmbeddable('some error', {} as EmbeddableInput), + embeddable: { + ...getMockLensApi(), + blockingError: new BehaviorSubject(new Error('some error')), + }, }) ).toEqual(false); }); @@ -103,7 +95,9 @@ describe('createAddToTimelineLensAction', () => { expect( await addToTimelineAction.isCompatible({ ...context, - embeddable: getMockEmbeddable('not_lens') as unknown as IEmbeddable, + embeddable: { + type: 'not_lens', + }, }) ).toEqual(false); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts b/x-pack/solutions/security/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts index 0ec4e00848348..98a8b07fd127d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts @@ -5,8 +5,7 @@ * 2.0. */ -import type { CellValueContext, EmbeddableInput, IEmbeddable } from '@kbn/embeddable-plugin/public'; -import { ErrorEmbeddable } from '@kbn/embeddable-plugin/public'; +import type { CellValueContext } from '@kbn/embeddable-plugin/public'; import type { LensApi } from '@kbn/lens-plugin/public'; import { createCopyToClipboardLensAction } from './copy_to_clipboard'; import { KibanaServices } from '../../../../common/lib/kibana'; @@ -40,13 +39,6 @@ const getMockLensApi = ( saveToLibrary: jest.fn(async () => 'saved-id'), }); -const getMockEmbeddable = (type: string): IEmbeddable => - ({ - type, - getFilters: jest.fn(), - getQuery: jest.fn(), - } as unknown as IEmbeddable); - const lensEmbeddable = getMockLensApi(); const columnMeta = { @@ -83,7 +75,10 @@ describe('createCopyToClipboardLensAction', () => { expect( await copyToClipboardAction.isCompatible({ ...context, - embeddable: new ErrorEmbeddable('some error', {} as EmbeddableInput), + embeddable: { + ...getMockLensApi(), + blockingError: new BehaviorSubject(new Error('some error')), + }, }) ).toEqual(false); }); @@ -92,7 +87,9 @@ describe('createCopyToClipboardLensAction', () => { expect( await copyToClipboardAction.isCompatible({ ...context, - embeddable: getMockEmbeddable('not_lens') as unknown as IEmbeddable, + embeddable: { + type: 'not_lens', + }, }) ).toEqual(false); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/helpers.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/helpers.test.tsx index 2599b10b93a48..c590bd12bddb1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/helpers.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/helpers.test.tsx @@ -5,10 +5,8 @@ * 2.0. */ import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; -import type { Embeddable } from '@kbn/embeddable-plugin/public'; import { createResetGroupByFieldAction, showInitialLoadingSpinner } from './helpers'; -import type { LensDataTableEmbeddable } from '../../../../common/components/visualization_actions/types'; describe('helpers', () => { describe('showInitialLoadingSpinner', () => { @@ -69,13 +67,13 @@ describe('createResetGroupByFieldAction', () => { }, }, }, - } as unknown as Embeddable), + }), updateInput: jest.fn(), }; const context = { embeddable, - } as unknown as ActionExecutionContext>; + } as unknown as ActionExecutionContext; const mockCallback = jest.fn(); beforeAll(async () => { action = createResetGroupByFieldAction({ callback: mockCallback }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/helpers.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/helpers.tsx index 8757316038b4a..0b928864053ad 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/helpers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/helpers.tsx @@ -6,10 +6,14 @@ */ import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; -import type { Embeddable } from '@kbn/embeddable-plugin/public'; import { RESET_GROUP_BY_FIELDS } from '../../../../common/components/chart_settings_popover/configurations/default/translations'; import type { LensDataTableEmbeddable } from '../../../../common/components/visualization_actions/types'; +interface LegacyLensEmbeddable { + getInput: () => LensDataTableEmbeddable; + updateInput: (input: LensDataTableEmbeddable) => void; +} + /** * Returns `true` when the alerts histogram initial loading spinner should be shown * @@ -48,7 +52,7 @@ export const createResetGroupByFieldAction: CreateResetGroupByFieldAction = ({ async execute({ embeddable, }: ActionExecutionContext<{ - embeddable: Embeddable; + embeddable: LegacyLensEmbeddable; }>): Promise { callback?.(); From 50509d5c3b9b9062b7d080cfc2c99448c9c1c622 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 2 Jan 2025 21:06:47 +0200 Subject: [PATCH 11/11] fix: [Security:Get Started page]Modal dialogs for AI assistants missing title from announcement (#205391) Closes: #204206 ## Description Dialog modal visible title should be announced for the users, especially using assistive technology to know what dialog modal, flyout opened. ## Changes made: 1. The `aria-labelledby` attribute has been added for the mentioned EuiModal. This change is recommended by the EUI team, see: https://eui.elastic.co/#/layout/modal for more details ## Screen image --- .../sections/action_connector_form/connector_add_modal.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx index e90c7db5de0b4..6e590b0ed38d4 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx @@ -21,6 +21,7 @@ import { EuiBetaBadge, EuiButtonGroup, EuiSpacer, + useGeneratedHtmlId, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import './connector_add_modal.scss'; @@ -214,12 +215,15 @@ const ConnectorAddModal = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const modalTitleId = useGeneratedHtmlId(); + return ( @@ -231,7 +235,7 @@ const ConnectorAddModal = ({ - +