From aeafd037df529417067f7f087af3c0d7672be08c Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Tue, 16 Nov 2021 11:04:23 +0100 Subject: [PATCH 1/4] [charts] Disable Lens/Visualize axis label orientation with multilayer time axis (#117828) --- .../category_axis_panel.test.tsx.snap | 1 + .../__snapshots__/index.test.tsx.snap | 1 + .../__snapshots__/label_options.test.tsx.snap | 65 +++++++++++-------- .../metrics_axes/category_axis_panel.test.tsx | 14 ++++ .../metrics_axes/category_axis_panel.tsx | 9 ++- .../options/metrics_axes/index.test.tsx | 5 ++ .../components/options/metrics_axes/index.tsx | 20 +++++- .../options/metrics_axes/label_options.tsx | 57 ++++++++++------ .../lens/public/xy_visualization/index.ts | 6 +- .../xy_visualization/to_expression.test.ts | 1 + .../xy_visualization/visualization.test.ts | 1 + .../public/xy_visualization/visualization.tsx | 4 +- .../xy_config_panel/axis_settings_popover.tsx | 59 +++++++++++------ .../xy_config_panel/index.tsx | 31 ++++++++- .../xy_visualization/xy_suggestions.test.ts | 1 + 15 files changed, 199 insertions(+), 76 deletions(-) diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap index bc66c1940ac729..0f3b0e8ef55769 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap @@ -61,6 +61,7 @@ exports[`CategoryAxisPanel component should init with the default set of props 1 "truncate": 0, } } + disableSingleLayerAxisControls={false} setAxisLabel={[Function]} /> diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap index 05e2532073eaf4..620e3619464431 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap @@ -154,6 +154,7 @@ exports[`MetricsAxisOptions component should init with the default set of props } onPositionChanged={[Function]} setCategoryAxis={[Function]} + useMultiLayerAxis={false} /> `; diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap index 175ec043cdbea5..d6e95dfdb87b90 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap @@ -27,7 +27,6 @@ exports[`LabelOptions component should init with the default set of props 1`] = /> - + + + - + + + diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx index 066f053d4e1865..9d18200ae7eb99 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx @@ -11,6 +11,7 @@ import { shallow } from 'enzyme'; import { CategoryAxisPanel, CategoryAxisPanelProps } from './category_axis_panel'; import { CategoryAxis } from '../../../../types'; import { LabelOptions } from './label_options'; +import { TruncateLabelsOption } from '../../common'; import { categoryAxis } from './mocks'; import { Position } from '@elastic/charts'; @@ -29,6 +30,7 @@ describe('CategoryAxisPanel component', () => { axis, onPositionChanged, setCategoryAxis, + useMultiLayerAxis: false, }; }); @@ -55,4 +57,16 @@ describe('CategoryAxisPanel component', () => { expect(setCategoryAxis).toHaveBeenLastCalledWith({ ...axis, position: value }); expect(onPositionChanged).toBeCalledWith(value); }); + + it('should disable label options with multilayer axis', () => { + const comp = shallow(); + const labelOptions = comp.find(LabelOptions).dive(); + const rotateLabelsOption = labelOptions.find({ paramName: 'rotate' }); + const filterLabelOption = labelOptions.find({ paramName: 'filter' }); + const truncateLabelOption = labelOptions.find(TruncateLabelsOption); + + expect(rotateLabelsOption.prop('disabled')).toBe(true); + expect(filterLabelOption.prop('disabled')).toBe(true); + expect(truncateLabelOption.prop('disabled')).toBe(true); + }); }); diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx index ee5cc950ff66b3..c3d1d2dcfee4de 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx @@ -25,9 +25,15 @@ export interface CategoryAxisPanelProps { axis: CategoryAxis; onPositionChanged: (position: Position) => void; setCategoryAxis: (value: CategoryAxis) => void; + useMultiLayerAxis: boolean; } -function CategoryAxisPanel({ axis, onPositionChanged, setCategoryAxis }: CategoryAxisPanelProps) { +function CategoryAxisPanel({ + axis, + onPositionChanged, + setCategoryAxis, + useMultiLayerAxis, +}: CategoryAxisPanelProps) { const setAxis = useCallback( (paramName: T, value: CategoryAxis[T]) => { const updatedAxis = { @@ -95,6 +101,7 @@ function CategoryAxisPanel({ axis, onPositionChanged, setCategoryAxis }: Categor axisLabels={axis.labels} axisFilterCheckboxName={`xAxisFilterLabelsCheckbox${axis.id}`} setAxisLabel={setAxisLabel} + disableSingleLayerAxisControls={useMultiLayerAxis} /> )} diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.test.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.test.tsx index 4996018d21120c..6a32b1f75016b6 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.test.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.test.tsx @@ -31,6 +31,11 @@ jest.mock('./category_axis_panel', () => ({ jest.mock('./value_axes_panel', () => ({ ValueAxesPanel: () => 'ValueAxesPanel', })); +jest.mock('../../../../services', () => ({ + getUISettings: jest.fn(() => ({ + get: jest.fn((key: string, defaultOverride?: unknown) => defaultOverride), + })), +})); const SERIES_PARAMS = 'seriesParams'; const VALUE_AXES = 'valueAxes'; diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.tsx index dc7e13634d6d6d..0397eec7b2c734 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.tsx @@ -10,8 +10,10 @@ import React, { useState, useEffect, useCallback } from 'react'; import { cloneDeep, get } from 'lodash'; import { EuiSpacer } from '@elastic/eui'; +import { Position } from '@elastic/charts'; -import { IAggConfig } from '../../../../../../../data/public'; +import { BUCKET_TYPES, IAggConfig } from '../../../../../../../data/public'; +import { getUISettings } from '../../../../services'; import { VisParams, ValueAxis, SeriesParam, CategoryAxis } from '../../../../types'; import { ValidationVisOptionsProps } from '../../common'; @@ -27,6 +29,7 @@ import { mapPositionOpposingOpposite, } from './utils'; import { getSeriesParams } from '../../../../utils/get_series_params'; +import { LEGACY_TIME_AXIS } from '../../../../../../../charts/common'; export type SetParamByIndex =

( axesName: 'valueAxes' | 'seriesParams', @@ -287,6 +290,20 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps) { updateAxisTitle(updatedSeries); }, [firstValueAxesId, setValue, stateParams.seriesParams, updateAxisTitle, aggs, schemaName]); + const isTimeViz = aggs.aggs.some( + (agg) => + agg.schema === 'segment' && agg.enabled && agg.type?.name === BUCKET_TYPES.DATE_HISTOGRAM + ); + const xAxisIsHorizontal = + stateParams.categoryAxes[0].position === Position.Bottom || + stateParams.categoryAxes[0].position === Position.Top; + const useLegacyTimeAxis = getUISettings().get(LEGACY_TIME_AXIS, false); + const linearOrStackedBars = stateParams.seriesParams.every( + ({ mode, type }) => type !== 'histogram' || (type === 'histogram' && mode === 'stacked') + ); + const useMultiLayerAxis = + xAxisIsHorizontal && isTimeViz && !useLegacyTimeAxis && linearOrStackedBars; + return isTabSelected ? ( <> ) { axis={stateParams.categoryAxes[0]} onPositionChanged={onCategoryAxisPositionChanged} setCategoryAxis={setCategoryAxis} + useMultiLayerAxis={useMultiLayerAxis} /> ) : null; diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx index ef48d8b6d78802..ed7ac178d3d8b7 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useMemo } from 'react'; -import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -23,9 +23,15 @@ export interface LabelOptionsProps { axisLabels: Labels; axisFilterCheckboxName: string; setAxisLabel: SetAxisLabel; + disableSingleLayerAxisControls?: boolean; } -function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: LabelOptionsProps) { +function LabelOptions({ + axisLabels, + axisFilterCheckboxName, + setAxisLabel, + disableSingleLayerAxisControls, +}: LabelOptionsProps) { const setAxisLabelRotate = useCallback( (paramName: 'rotate', value: Labels['rotate']) => { setAxisLabel(paramName, Number(value)); @@ -34,6 +40,15 @@ function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: Labe ); const rotateOptions = useMemo(getRotateOptions, []); + const multilayerAxisTooltipText = disableSingleLayerAxisControls + ? i18n.translate( + 'visTypeXy.controls.pointSeries.categoryAxis.axisLabelsOptionsMultilayer.disabled', + { + defaultMessage: 'This option can be configured only with non-time-based axes', + } + ) + : undefined; + const axisLabelControlDisabled = !axisLabels.show || disableSingleLayerAxisControls; return ( <> @@ -56,39 +71,43 @@ function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: Labe value={axisLabels.show} setValue={setAxisLabel} /> - - + + + - + + + diff --git a/x-pack/plugins/lens/public/xy_visualization/index.ts b/x-pack/plugins/lens/public/xy_visualization/index.ts index d3d461e8f8741e..8ac9076919dd9a 100644 --- a/x-pack/plugins/lens/public/xy_visualization/index.ts +++ b/x-pack/plugins/lens/public/xy_visualization/index.ts @@ -30,7 +30,7 @@ export class XyVisualization { const { getXyChartRenderer, getXyVisualization } = await import('../async_services'); const [, { charts, fieldFormats }] = await core.getStartServices(); const palettes = await charts.palettes.getPalettes(); - + const useLegacyTimeAxis = core.uiSettings.get(LEGACY_TIME_AXIS); expressions.registerRenderer( getXyChartRenderer({ formatFactory, @@ -38,10 +38,10 @@ export class XyVisualization { chartsActiveCursorService: charts.activeCursor, paletteService: palettes, timeZone: getTimeZone(core.uiSettings), - useLegacyTimeAxis: core.uiSettings.get(LEGACY_TIME_AXIS), + useLegacyTimeAxis, }) ); - return getXyVisualization({ paletteService: palettes, fieldFormats }); + return getXyVisualization({ paletteService: palettes, fieldFormats, useLegacyTimeAxis }); }); } } diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts index 7d1bd64abe9063..033e324a5d02d2 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts @@ -19,6 +19,7 @@ describe('#toExpression', () => { const xyVisualization = getXyVisualization({ paletteService: chartPluginMock.createPaletteRegistry(), fieldFormats: fieldFormatsServiceMock.createStartContract(), + useLegacyTimeAxis: false, }); let mockDatasource: ReturnType; let frame: ReturnType; diff --git a/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts b/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts index 0c3fa21708263f..029cfe8ecbe400 100644 --- a/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts @@ -40,6 +40,7 @@ const fieldFormatsMock = fieldFormatsServiceMock.createStartContract(); const xyVisualization = getXyVisualization({ paletteService: paletteServiceMock, fieldFormats: fieldFormatsMock, + useLegacyTimeAxis: false, }); describe('xy_visualization', () => { diff --git a/x-pack/plugins/lens/public/xy_visualization/visualization.tsx b/x-pack/plugins/lens/public/xy_visualization/visualization.tsx index 2f3ec7e2723d4f..0ba74f4b8bb3a6 100644 --- a/x-pack/plugins/lens/public/xy_visualization/visualization.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/visualization.tsx @@ -98,9 +98,11 @@ function getDescription(state?: State) { export const getXyVisualization = ({ paletteService, fieldFormats, + useLegacyTimeAxis, }: { paletteService: PaletteRegistry; fieldFormats: FieldFormatsStart; + useLegacyTimeAxis: boolean; }): Visualization => ({ id: 'lnsXY', @@ -573,7 +575,7 @@ export const getXyVisualization = ({ renderToolbar(domElement, props) { render( - + , domElement ); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/axis_settings_popover.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/axis_settings_popover.tsx index e0a30bdb2c511d..4ce1667ee1008a 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/axis_settings_popover.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/axis_settings_popover.tsx @@ -21,7 +21,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { XYLayerConfig, AxesSettingsConfig, AxisExtentConfig } from '../../../common/expressions'; -import { ToolbarPopover, useDebouncedValue } from '../../shared_components'; +import { ToolbarPopover, useDebouncedValue, TooltipWrapper } from '../../shared_components'; import { isHorizontalChart } from '../state_helpers'; import { EuiIconAxisBottom } from '../../assets/axis_bottom'; import { EuiIconAxisLeft } from '../../assets/axis_left'; @@ -104,6 +104,11 @@ export interface AxisSettingsPopoverProps { hasBarOrAreaOnAxis: boolean; hasPercentageAxis: boolean; dataBounds?: { min: number; max: number }; + + /** + * Toggle the visibility of legacy axis settings when using the new multilayer time axis + */ + useMultilayerTimeAxis?: boolean; } const popoverConfig = ( @@ -210,6 +215,7 @@ export const AxisSettingsPopover: React.FunctionComponent { const isHorizontal = layers?.length ? isHorizontalChart(layers) : false; const config = popoverConfig(axis, isHorizontal); @@ -314,30 +320,41 @@ export const AxisSettingsPopover: React.FunctionComponent - - value === orientation)!.id} - onChange={(optionId) => { - const newOrientation = axisOrientationOptions.find(({ id }) => id === optionId)!.value; - setOrientation(axis, newOrientation); - }} - /> - + > + value === orientation)!.id} + onChange={(optionId) => { + const newOrientation = axisOrientationOptions.find( + ({ id }) => id === optionId + )!.value; + setOrientation(axis, newOrientation); + }} + /> + + {setEndzoneVisibility && ( <> diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx index cef4a5f01ce8a4..6a43be64ec1d45 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx @@ -176,8 +176,10 @@ function hasPercentageAxis(axisGroups: GroupsConfiguration, groupId: string, sta ); } -export const XyToolbar = memo(function XyToolbar(props: VisualizationToolbarProps) { - const { state, setState, frame } = props; +export const XyToolbar = memo(function XyToolbar( + props: VisualizationToolbarProps & { useLegacyTimeAxis?: boolean } +) { + const { state, setState, frame, useLegacyTimeAxis } = props; const shouldRotate = state?.layers.length ? isHorizontalChart(state.layers) : false; const axisGroups = getAxesConfiguration(state?.layers, shouldRotate, frame.activeData); @@ -327,6 +329,28 @@ export const XyToolbar = memo(function XyToolbar(props: VisualizationToolbarProp [setState, state] ); + const filteredBarLayers = state?.layers.filter((layer) => layer.seriesType.includes('bar')); + const chartHasMoreThanOneBarSeries = + filteredBarLayers.length > 1 || + filteredBarLayers.some((layer) => layer.accessors.length > 1 || layer.splitAccessor); + + const isTimeHistogramModeEnabled = state?.layers.some( + ({ xAccessor, layerId, seriesType, splitAccessor }) => { + if (!xAccessor) { + return false; + } + const xAccessorOp = props.frame.datasourceLayers[layerId].getOperationForColumnId(xAccessor); + return ( + getScaleType(xAccessorOp, ScaleType.Linear) === ScaleType.Time && + xAccessorOp?.isBucketed && + (seriesType.includes('stacked') || !splitAccessor) && + (seriesType.includes('stacked') || + !seriesType.includes('bar') || + !chartHasMoreThanOneBarSeries) + ); + } + ); + return ( @@ -487,6 +511,9 @@ export const XyToolbar = memo(function XyToolbar(props: VisualizationToolbarProp setEndzoneVisibility={onChangeEndzoneVisiblity} hasBarOrAreaOnAxis={false} hasPercentageAxis={false} + useMultilayerTimeAxis={ + isTimeHistogramModeEnabled && !useLegacyTimeAxis && !shouldRotate + } /> { From 8873a48277b6971aec8b930b53fd8f2b79e7c02a Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Tue, 16 Nov 2021 11:06:43 +0100 Subject: [PATCH 2/4] [Discover] Add EuiErrorBoundary to catch errors in the functionals (#117976) * [Discover] Add error boundary to cath errors in functionals * Fix invalid import * Move to router Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/application/discover_router.tsx | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/plugins/discover/public/application/discover_router.tsx b/src/plugins/discover/public/application/discover_router.tsx index 6f88c28b52bf9e..66ad0cccd03c7c 100644 --- a/src/plugins/discover/public/application/discover_router.tsx +++ b/src/plugins/discover/public/application/discover_router.tsx @@ -9,6 +9,7 @@ import { Redirect, Route, Router, Switch } from 'react-router-dom'; import React from 'react'; import { History } from 'history'; +import { EuiErrorBoundary } from '@elastic/eui'; import { KibanaContextProvider } from '../../../kibana_react/public'; import { ContextAppRoute } from './context'; import { SingleDocRoute } from './doc'; @@ -25,29 +26,31 @@ export const discoverRouter = (services: DiscoverServices, history: History) => return ( - - - } - /> - ( - - )} - /> - } - /> - } /> - } /> - - - + + + + } + /> + ( + + )} + /> + } + /> + } /> + } /> + + + + ); }; From 809bdad9e8b5bc570f4cd4911350cf171433fc6b Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Tue, 16 Nov 2021 05:12:45 -0500 Subject: [PATCH 3/4] [APM] Fixes isntructions for the APM integration tutorial (#118256) (#118645) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../home/common/instruction_variant.ts | 4 +- .../tutorial_fleet_instructions/index.tsx | 56 ++++++++++++------- .../apm/server/tutorial/envs/on_prem.ts | 48 ++++++++-------- 3 files changed, 63 insertions(+), 45 deletions(-) diff --git a/src/plugins/home/common/instruction_variant.ts b/src/plugins/home/common/instruction_variant.ts index 66c841cdc8b56b..f19aa7849586b9 100644 --- a/src/plugins/home/common/instruction_variant.ts +++ b/src/plugins/home/common/instruction_variant.ts @@ -32,8 +32,8 @@ export const INSTRUCTION_VARIANT = { const DISPLAY_MAP = { [INSTRUCTION_VARIANT.ESC]: 'Elastic Cloud', [INSTRUCTION_VARIANT.OSX]: 'macOS', - [INSTRUCTION_VARIANT.DEB]: 'DEB', - [INSTRUCTION_VARIANT.RPM]: 'RPM', + [INSTRUCTION_VARIANT.DEB]: 'Linux DEB', + [INSTRUCTION_VARIANT.RPM]: 'Linux RPM', [INSTRUCTION_VARIANT.DOCKER]: 'Docker', [INSTRUCTION_VARIANT.WINDOWS]: 'Windows', [INSTRUCTION_VARIANT.NODE]: 'Node.js', diff --git a/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx b/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx index f0d6dc72b72a54..7df52b20376b0f 100644 --- a/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx +++ b/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx @@ -4,13 +4,17 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { EuiButton } from '@elastic/eui'; -import { EuiFlexItem } from '@elastic/eui'; -import { EuiFlexGroup } from '@elastic/eui'; -import { EuiPanel } from '@elastic/eui'; -import { EuiCard } from '@elastic/eui'; -import { EuiImage } from '@elastic/eui'; -import { EuiLoadingSpinner } from '@elastic/eui'; +import { + EuiButton, + EuiFlexItem, + EuiFlexGroup, + EuiPanel, + EuiCard, + EuiImage, + EuiLoadingSpinner, + EuiText, + EuiSpacer, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { HttpStart } from 'kibana/public'; import React, { useEffect, useState } from 'react'; @@ -90,18 +94,32 @@ function TutorialFleetInstructions({ http, basePath, isDarkTheme }: Props) { } )} footer={ - - {i18n.translate( - 'xpack.apm.tutorial.apmServer.fleet.apmIntegration.button', - { - defaultMessage: 'APM integration', - } - )} - + <> + + {i18n.translate( + 'xpack.apm.tutorial.apmServer.fleet.apmIntegration.button', + { + defaultMessage: 'APM integration', + } + )} + + + +

+ {i18n.translate( + 'xpack.apm.tutorial.apmServer.fleet.apmIntegration.description', + { + defaultMessage: + 'Fleet allows you to centrally manage Elastic Agents running the APM integration. The default option is to install a Fleet Server on a dedicated host. For setups without a dedicated host, we recommend following the instructions to install the standalone APM Server for your operating system by selecting the respective tab above.', + } + )} +

+ + } /> diff --git a/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts b/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts index ba99b0624c4414..8051ef2a72b6a6 100644 --- a/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts +++ b/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts @@ -64,30 +64,6 @@ export function onPremInstructions({ iconType: 'alert', }, instructionVariants: [ - // hides fleet section when plugin is disabled - ...(isFleetPluginEnabled - ? [ - { - id: INSTRUCTION_VARIANT.FLEET, - instructions: [ - { - title: i18n.translate('xpack.apm.tutorial.fleet.title', { - defaultMessage: 'Fleet', - }), - customComponentName: 'TutorialFleetInstructions', - }, - ], - }, - ] - : []), - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - createDownloadServerOsx(), - EDIT_CONFIG, - START_SERVER_UNIX, - ], - }, { id: INSTRUCTION_VARIANT.DEB, instructions: [ @@ -104,10 +80,34 @@ export function onPremInstructions({ START_SERVER_UNIX_SYSV, ], }, + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + createDownloadServerOsx(), + EDIT_CONFIG, + START_SERVER_UNIX, + ], + }, { id: INSTRUCTION_VARIANT.WINDOWS, instructions: createWindowsServerInstructions(), }, + // hides fleet section when plugin is disabled + ...(isFleetPluginEnabled + ? [ + { + id: INSTRUCTION_VARIANT.FLEET, + instructions: [ + { + title: i18n.translate('xpack.apm.tutorial.fleet.title', { + defaultMessage: 'Fleet', + }), + customComponentName: 'TutorialFleetInstructions', + }, + ], + }, + ] + : []), ], statusCheck: { title: i18n.translate( From f69ff00f4485ca676ca7d02cfe33d27b959a1ff3 Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Tue, 16 Nov 2021 12:01:15 +0100 Subject: [PATCH 4/4] [Security Solution][Endpoint] Consistent pending actions agent status label (#117875) * pull more than default 10 records!! refs elastic/kibana/pull/115691 Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * commit using ashokaditya@elastic.co * show correct isolation status badge when pending actions data is updated fixes elastic/security-team/issues/2105 Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * fix typo Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * remove redundant dependencies review changes Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * show `isolated` right after pending state is refreshed fixes elastic/security-team/issues/2105 Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * recompute only on prop change Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../endpoint_host_isolation_status.tsx | 48 +++++++++++-------- .../server/endpoint/services/actions.ts | 1 + 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_status.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_status.tsx index 6795557f17f1a3..ad86b0f3622347 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_status.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_status.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { memo, useMemo } from 'react'; +import React, { memo, useMemo, useRef, useEffect } from 'react'; import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiTextColor, EuiToolTip } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { useTestIdGenerator } from '../../../../management/components/hooks/use_test_id_generator'; @@ -28,12 +28,20 @@ export interface EndpointHostIsolationStatusProps { export const EndpointHostIsolationStatus = memo( ({ isIsolated, pendingIsolate = 0, pendingUnIsolate = 0, 'data-test-subj': dataTestSubj }) => { const getTestId = useTestIdGenerator(dataTestSubj); - const isPendingStatuseDisabled = useIsExperimentalFeatureEnabled( + const isPendingStatusDisabled = useIsExperimentalFeatureEnabled( 'disableIsolationUIPendingStatuses' ); + const wasReleasing = useRef(false); + const wasIsolating = useRef(false); + + useEffect(() => { + wasReleasing.current = pendingIsolate === 0 && pendingUnIsolate > 0; + wasIsolating.current = pendingIsolate > 0 && pendingUnIsolate === 0; + }, [pendingIsolate, pendingUnIsolate]); + return useMemo(() => { - if (isPendingStatuseDisabled) { + if (isPendingStatusDisabled) { // If nothing is pending and host is not currently isolated, then render nothing if (!isIsolated) { return null; @@ -49,21 +57,23 @@ export const EndpointHostIsolationStatus = memo - - - ); + // If nothing is pending + if (!(pendingIsolate || pendingUnIsolate)) { + // and host is either releasing and or currently released, then render nothing + if ((!wasIsolating.current && wasReleasing.current) || !isIsolated) { + return null; + } + // else host was isolating or is isolated, then show isolation badge + else if ((!isIsolated && wasIsolating.current && !wasReleasing.current) || isIsolated) { + return ( + + + + ); + } } // If there are multiple types of pending isolation actions, then show count of actions with tooltip that displays breakdown @@ -136,7 +146,7 @@ export const EndpointHostIsolationStatus = memo( { index: ENDPOINT_ACTION_RESPONSES_INDEX, + size: 10000, body: { query: { bool: {