From ca6df02289d6f9b03795cf2ab4ada9787056bcb2 Mon Sep 17 00:00:00 2001 From: Carlos Crespo Date: Mon, 3 Jul 2023 17:12:39 +0200 Subject: [PATCH 1/3] [Infrastructure UI] Hosts view charts fix (#160736) closes: [#160734](https://github.com/elastic/kibana/issues/160734) ## Summary This PR fixes an inconsistency between the table and charts when there is no data to be displayed image The Lens charts were not receiving the `query` property from Unified Search, causing them to run a query with incomplete filters ### How to test - Start a local Kibana instance - Navigate to `Infrastructure > Hosts` - Use the unified search using filters that won't match with any hosts - Verify the charts - Navigate from a KPI and Metrics charts to Lens --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/pages/metrics/hosts/components/kpis/tile.tsx | 7 +++++-- .../metrics/hosts/components/tabs/metrics/metric_chart.tsx | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/tile.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/tile.tsx index cf409e878cb71..0c1d254342b84 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/tile.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/tile.tsx @@ -85,13 +85,14 @@ export const Tile = ({ const filters = useMemo(() => { return [ + ...searchCriteria.filters, buildCombinedHostsFilter({ field: 'host.name', values: hostNodes.map((p) => p.name), dataView, }), ]; - }, [hostNodes, dataView]); + }, [searchCriteria.filters, hostNodes, dataView]); const handleBrushEnd = useCallback( ({ range }: BrushTriggerEvent['data']) => { @@ -122,9 +123,10 @@ export const Tile = ({ () => getExtraActions({ timeRange: afterLoadedState.dateRange, + query: searchCriteria.query, filters, }), - [afterLoadedState.dateRange, filters, getExtraActions] + [afterLoadedState.dateRange, filters, getExtraActions, searchCriteria.query] ); return ( @@ -168,6 +170,7 @@ export const Tile = ({ lastReloadRequestTime={afterLoadedState.lastReloadRequestTime} dateRange={afterLoadedState.dateRange} filters={afterLoadedState.filters} + query={afterLoadedState.query} onBrushEnd={handleBrushEnd} loading={loading} /> diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx index 51a0a4ea30931..5d7e946f25e2a 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx @@ -65,21 +65,23 @@ export const MetricChart = ({ title, type, breakdownSize }: MetricChartProps) => const filters = useMemo(() => { return [ + ...searchCriteria.filters, buildCombinedHostsFilter({ field: 'host.name', values: currentPage.map((p) => p.name), dataView, }), ]; - }, [currentPage, dataView]); + }, [currentPage, dataView, searchCriteria.filters]); const extraActions: Action[] = useMemo( () => getExtraActions({ timeRange: afterLoadedState.dateRange, + query: afterLoadedState.query, filters, }), - [afterLoadedState.dateRange, filters, getExtraActions] + [afterLoadedState.dateRange, afterLoadedState.query, filters, getExtraActions] ); const handleBrushEnd = useCallback( @@ -137,6 +139,7 @@ export const MetricChart = ({ title, type, breakdownSize }: MetricChartProps) => lastReloadRequestTime={afterLoadedState.lastReloadRequestTime} dateRange={afterLoadedState.dateRange} filters={filters} + query={afterLoadedState.query} onBrushEnd={handleBrushEnd} loading={loading} hasTitle From d7454d47334678ec06784b926f111fc0ad3aa49c Mon Sep 17 00:00:00 2001 From: Liam Thompson <32779855+leemthompo@users.noreply.github.com> Date: Mon, 3 Jul 2023 17:18:48 +0200 Subject: [PATCH 2/3] [Enterprise Search] Minor copyedits for connector configs (#161099) Some tiny copyedits --- .../search_index/connector/connector_configuration.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx index 81bd97840b190..9cd4802ed2be4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx @@ -111,7 +111,7 @@ export const ConnectorConfiguration: React.FC = () => { @@ -180,7 +180,7 @@ service_type: "${index.connector.service_type || 'changeme'}" title: i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.steps.deployConnector.title', { - defaultMessage: 'Deploy a connector', + defaultMessage: 'Deploy connector', } ), titleSize: 'xs', @@ -325,7 +325,7 @@ service_type: "${index.connector.service_type || 'changeme'}" 'xpack.enterpriseSearch.content.indices.configurationConnector.support.description', { defaultMessage: - 'Your connector will have to be deployed to your own infrastructure.', + 'You need to deploy this connector on your own infrastructure.', } )} @@ -345,7 +345,7 @@ service_type: "${index.connector.service_type || 'changeme'}" {i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.support.manageKeys.label', { - defaultMessage: 'Manage keys', + defaultMessage: 'Manage API keys', } )} From a81287f10c2bcc4ca893878e3ca8b9d141960209 Mon Sep 17 00:00:00 2001 From: Jeramy Soucy Date: Mon, 3 Jul 2023 11:25:58 -0400 Subject: [PATCH 3/3] Implements profile theme selection with KeyPadMenu (#160925) Closes #155941 ## Summary This PR changes the implementation of the theme selection component in the user profile screen from EuiButtonGroup to EuiKeyPadMenu. This better matches the original design. ### Previous Implementation Screenshot 2023-06-28 at 1 49 22 PM ### Tests - `x-pack/plugins/security/public/account_management/user_profile/user_profile.test.tsx` ### Manual Testing - Start Elasricsearch, and start Kibana with an empty kibana.yml/kibana.dev.yml - Navigate to the _Edit profile_ screen via the profile/avatar button in the top right portion of the uI Screenshot 2023-06-29 at 11 47 42 AM - Verify the theme settings appear as a KeyPadMenu and function as expected Screenshot 2023-06-28 at 2 38 44 PM - Modify the kibana.yml (or kibana.dev.yml) with the line `uiSettings.overrides.theme:darkMode: true` - Refresh Kibana and verify that the dark theme is rendered and the theme settings are disabled and includes a lock icon tip explaining why the mode setting is locked Screenshot 2023-06-30 at 12 24 12 PM - Modify the kibana.yml (or kibana.dev.yml) with the line `uiSettings.overrides.theme:darkMode: false` - Refresh Kibana and verify that the light theme is rendered and the theme settings are disabled and includes a lock icon tip explaining why the mode setting is locked --- .../user_profile/user_profile.test.tsx | 59 ++++++-- .../user_profile/user_profile.tsx | 134 +++++++++++------- 2 files changed, 126 insertions(+), 67 deletions(-) diff --git a/x-pack/plugins/security/public/account_management/user_profile/user_profile.test.tsx b/x-pack/plugins/security/public/account_management/user_profile/user_profile.test.tsx index 9eb1d9d17be38..87df8261d9ec6 100644 --- a/x-pack/plugins/security/public/account_management/user_profile/user_profile.test.tsx +++ b/x-pack/plugins/security/public/account_management/user_profile/user_profile.test.tsx @@ -256,9 +256,20 @@ describe('useUserProfileForm', () => { ); - const darkModeButton = testWrapper.find('EuiButtonGroup[data-test-subj="darkModeButton"]'); - expect(darkModeButton).toBeTruthy(); - expect(darkModeButton.getDOMNode()).not.toBeDisabled(); + + const overrideMsg = testWrapper.find('EuiText[data-test-subj="themeOverrideMessage"]'); + expect(overrideMsg).toHaveLength(0); + + const themeMenu = testWrapper.find('EuiKeyPadMenu[data-test-subj="themeMenu"]'); + expect(themeMenu).toHaveLength(1); + + const themeOptions = themeMenu.find('EuiKeyPadMenuItem'); + expect(themeOptions).toHaveLength(3); + themeOptions.forEach((option) => { + expect(option.getDOMNode().classList.contains('euiKeyPadMenuItem-isDisabled')).toEqual( + false + ); + }); }); it('should not display if the User is a cloud user', () => { @@ -281,7 +292,7 @@ describe('useUserProfileForm', () => { ); - expect(testWrapper.exists('EuiButtonGroup[data-test-subj="darkModeButton"]')).toBeFalsy(); + expect(testWrapper.exists('EuiButtonGroup[data-test-subj="themeMenu"]')).toBeFalsy(); }); it('should add special toast after submitting form successfully since darkMode requires a refresh', async () => { @@ -314,8 +325,8 @@ describe('useUserProfileForm', () => { const data: UserProfileData = {}; const nonCloudUser = mockAuthenticatedUser({ elastic_cloud_user: false }); - coreStart.settings.client.get.mockReturnValueOnce(true); - coreStart.settings.client.isOverridden.mockReturnValueOnce(true); + coreStart.settings.client.get.mockReturnValue(true); + coreStart.settings.client.isOverridden.mockReturnValue(true); const testWrapper = mount( { ); - const darkModeButton = testWrapper.find('EuiButtonGroup[data-test-subj="darkModeButton"]'); - expect(darkModeButton).toBeTruthy(); - expect(darkModeButton.getDOMNode()).toHaveProperty('disabled'); + const overrideMsg = testWrapper.find('EuiIconTip[data-test-subj="themeOverrideTooltip"]'); + expect(overrideMsg).toHaveLength(1); + + const themeMenu = testWrapper.find('EuiKeyPadMenu[data-test-subj="themeMenu"]'); + expect(themeMenu).toHaveLength(1); + + const themeOptions = themeMenu.find('EuiKeyPadMenuItem'); + expect(themeOptions).toHaveLength(3); + themeOptions.forEach((option) => { + expect(option.getDOMNode().classList.contains('euiKeyPadMenuItem-isDisabled')).toEqual( + true + ); + }); }); it('should be disabled if the theme has been set to `darkMode: false` in the config', () => { const data: UserProfileData = {}; const nonCloudUser = mockAuthenticatedUser({ elastic_cloud_user: false }); - coreStart.settings.client.get.mockReturnValueOnce(false); - coreStart.settings.client.isOverridden.mockReturnValueOnce(true); + coreStart.settings.client.get.mockReturnValue(false); + coreStart.settings.client.isOverridden.mockReturnValue(true); const testWrapper = mount( { ); - const darkModeButton = testWrapper.find('EuiButtonGroup[data-test-subj="darkModeButton"]'); - expect(darkModeButton).toBeTruthy(); - expect(darkModeButton.getDOMNode()).toHaveProperty('disabled'); + const overrideMsg = testWrapper.find('EuiIconTip[data-test-subj="themeOverrideTooltip"]'); + expect(overrideMsg).toHaveLength(1); + + const themeMenu = testWrapper.find('EuiKeyPadMenu[data-test-subj="themeMenu"]'); + expect(themeMenu).toHaveLength(1); + + const themeOptions = themeMenu.find('EuiKeyPadMenuItem'); + expect(themeOptions).toHaveLength(3); + themeOptions.forEach((option) => { + expect(option.getDOMNode().classList.contains('euiKeyPadMenuItem-isDisabled')).toEqual( + true + ); + }); }); }); }); diff --git a/x-pack/plugins/security/public/account_management/user_profile/user_profile.tsx b/x-pack/plugins/security/public/account_management/user_profile/user_profile.tsx index 5114fe2f38757..0ffa627ac1a3f 100644 --- a/x-pack/plugins/security/public/account_management/user_profile/user_profile.tsx +++ b/x-pack/plugins/security/public/account_management/user_profile/user_profile.tsx @@ -18,6 +18,8 @@ import { EuiFormRow, EuiIcon, EuiIconTip, + EuiKeyPadMenu, + EuiKeyPadMenuItem, EuiPageTemplate_Deprecated as EuiPageTemplate, EuiSpacer, EuiText, @@ -165,6 +167,27 @@ function UserSettingsEditor({ } } + interface ThemeKeyPadItem { + id: string; + label: string; + icon: string; + } + + const themeKeyPadMenuItem = ({ id, label, icon }: ThemeKeyPadItem) => { + return ( + formik.setFieldValue('data.userSettings.darkMode', id)} + > + + + ); + }; + return ( - - + + + + + + + {renderHelpText(isThemeOverridden)} + } fullWidth > - - ), - }, - { - id: 'light', - label: ( - - ), - iconType: 'sun', - }, - { - id: 'dark', - label: ( - - ), - iconType: 'moon', - }, - ]} - onChange={(id: string) => formik.setFieldValue('data.userSettings.darkMode', id)} - isFullWidth - /> + data-test-subj="themeMenu" + checkable={true} + > + {themeKeyPadMenuItem({ + id: '', + label: i18n.translate( + 'xpack.security.accountManagement.userProfile.defaultModeButton', + { + defaultMessage: 'Space default', + } + ), + icon: 'spaces', + })} + {themeKeyPadMenuItem({ + id: 'light', + label: i18n.translate('xpack.security.accountManagement.userProfile.lightModeButton', { + defaultMessage: 'Light', + }), + icon: 'sun', + })} + {themeKeyPadMenuItem({ + id: 'dark', + label: i18n.translate('xpack.security.accountManagement.userProfile.darkModeButton', { + defaultMessage: 'Dark', + }), + icon: 'moon', + })} + ); @@ -912,12 +929,23 @@ export const SaveChangesBottomBar: FunctionComponent = () => { function renderHelpText(isOverridden: boolean) { if (isOverridden) { return ( - - - + + } + /> ); } }