From 45e57768daadd91d8757f5398cd7070932e9f941 Mon Sep 17 00:00:00 2001 From: jennypavlova Date: Mon, 6 Feb 2023 17:44:09 +0100 Subject: [PATCH] [Infrastructure UI] Inventory educate about show button (#149981) Closes [#149615](https://github.com/elastic/kibana/issues/149615) ## Summary This PR adds a tooltip educating the user about the filter in the Show drop-down list. Testing - Navigate to the Inventory Page and the new tour should be visible: image - if it's dismissed (after the button is clicked it should not be visible anymore until the session is active - can be tested with page refresh or navigating to a different page and back) - If it's not dismissed it should be persisted per user/browser session - can be also checked with page refresh --- .../components/dropdown_button.tsx | 38 ++++++++---- .../components/kubernetes_tour.tsx | 60 +++++++++++++++++++ .../waffle/waffle_inventory_switcher.tsx | 1 + .../test/functional/apps/infra/home_page.ts | 29 +++++++-- .../test/functional/apps/infra/hosts_view.ts | 2 + .../page_objects/infra_home_page.ts | 14 +++++ 6 files changed, 127 insertions(+), 17 deletions(-) create mode 100644 x-pack/plugins/infra/public/pages/metrics/inventory_view/components/kubernetes_tour.tsx diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/dropdown_button.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/dropdown_button.tsx index 89bc192606944..0e4aa275a7879 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/dropdown_button.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/dropdown_button.tsx @@ -8,6 +8,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; import React, { ReactNode } from 'react'; import { withTheme, EuiTheme } from '@kbn/kibana-react-plugin/common'; +import { KubernetesTour } from './kubernetes_tour'; interface Props { 'data-test-subj'?: string; @@ -15,10 +16,26 @@ interface Props { onClick: () => void; theme: EuiTheme | undefined; children: ReactNode; + showKubernetesInfo?: boolean; } +const ButtonLabel = ({ label, theme }: { label: string; theme?: EuiTheme }) => ( + + {label} + +); + export const DropdownButton = withTheme((props: Props) => { - const { onClick, label, theme, children } = props; + const { onClick, label, theme, children, showKubernetesInfo } = props; return ( { boxShadow: `0px 3px 2px ${theme?.eui.euiTableActionsBorderColor}, 0px 1px 1px ${theme?.eui.euiTableActionsBorderColor}`, }} > - - {label} - + {showKubernetesInfo ? ( + + + + ) : ( + + )} { + const [isTourSeen, setIsTourSeen] = useLocalStorage(KUBERNETES_TOUR_STORAGE_KEY, false); + const markTourAsSeen = () => setIsTourSeen(true); + + return ( +
+ + {i18n.translate('xpack.infra.homePage.kubernetesTour.text', { + defaultMessage: + 'Click here to see your infrastructure in different ways, including Kubernetes pods.', + })} + + } + isStepOpen={!isTourSeen} + maxWidth={350} + onFinish={markTourAsSeen} + step={1} + stepsTotal={1} + title={i18n.translate('xpack.infra.homePage.kubernetesTour.title', { + defaultMessage: 'Want a different view?', + })} + anchorPosition="downCenter" + footerAction={ + + {i18n.translate('xpack.infra.homePage.kubernetesTour.dismiss', { + defaultMessage: 'Dismiss', + })} + + } + > + {children} + +
+ ); +}; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx index 6234dcc0bbf0b..e3ca9b770e2ef 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx @@ -124,6 +124,7 @@ export const WaffleInventorySwitcher: React.FC = () => { data-test-subj={'openInventorySwitcher'} onClick={openPopover} label={i18n.translate('xpack.infra.waffle.showLabel', { defaultMessage: 'Show' })} + showKubernetesInfo={true} > {selectedText} diff --git a/x-pack/test/functional/apps/infra/home_page.ts b/x-pack/test/functional/apps/infra/home_page.ts index 1c0323808270d..54435f11a33e1 100644 --- a/x-pack/test/functional/apps/infra/home_page.ts +++ b/x-pack/test/functional/apps/infra/home_page.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { KUBERNETES_TOUR_STORAGE_KEY } from '@kbn/infra-plugin/public/pages/metrics/inventory_view/components/kubernetes_tour'; import { FtrProviderContext } from '../../ftr_provider_context'; import { DATES } from './constants'; @@ -59,10 +60,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.common.navigateToApp('infraOps'); await pageObjects.infraHome.waitForLoading(); }); - after( - async () => - await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs') - ); + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + await browser.removeLocalStorageItem(KUBERNETES_TOUR_STORAGE_KEY); + }); it('renders the correct page title', async () => { await pageObjects.header.waitUntilLoadingHasFinished(); @@ -71,6 +72,26 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(documentTitle).to.contain('Inventory - Infrastructure - Observability - Elastic'); }); + it('renders the kubernetes tour component and allows user to dismiss it without seeing it again', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + const kubernetesTourText = + 'Click here to see your infrastructure in different ways, including Kubernetes pods.'; + const ensureKubernetesTourVisible = + await pageObjects.infraHome.ensureKubernetesTourIsVisible(); + + expect(ensureKubernetesTourVisible).to.contain(kubernetesTourText); + + // Persist after refresh + await browser.refresh(); + await pageObjects.infraHome.waitForLoading(); + + expect(ensureKubernetesTourVisible).to.contain(kubernetesTourText); + + await pageObjects.infraHome.clickDismissKubernetesTourButton(); + + await pageObjects.infraHome.ensureKubernetesTourIsClosed(); + }); + it('renders an empty data prompt for dates with no data', async () => { await pageObjects.infraHome.goToTime(DATE_WITHOUT_DATA); await pageObjects.infraHome.getNoMetricsDataPrompt(); diff --git a/x-pack/test/functional/apps/infra/hosts_view.ts b/x-pack/test/functional/apps/infra/hosts_view.ts index 9975a2772a193..224a924b7c1fa 100644 --- a/x-pack/test/functional/apps/infra/hosts_view.ts +++ b/x-pack/test/functional/apps/infra/hosts_view.ts @@ -108,6 +108,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); await pageObjects.common.navigateToApp('infraOps'); + await pageObjects.infraHome.clickDismissKubernetesTourButton(); await pageObjects.infraHostsView.clickTryHostViewBadge(); }); after(async () => { @@ -126,6 +127,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); await loginWithReadOnlyUserAndNavigateToInfra(); + await pageObjects.infraHome.clickDismissKubernetesTourButton(); await pageObjects.infraHostsView.clickTryHostViewBadge(); }); after(async () => { diff --git a/x-pack/test/functional/page_objects/infra_home_page.ts b/x-pack/test/functional/page_objects/infra_home_page.ts index cb01de3c596e3..a13c9a89ae0cb 100644 --- a/x-pack/test/functional/page_objects/infra_home_page.ts +++ b/x-pack/test/functional/page_objects/infra_home_page.ts @@ -376,5 +376,19 @@ export function InfraHomePageProvider({ getService, getPageObjects }: FtrProvide async ensureSuggestionsPanelVisible() { await testSubjects.find('infraSuggestionsPanel'); }, + + async ensureKubernetesTourIsVisible() { + const container = await testSubjects.find('infra-kubernetesTour-text'); + const containerText = await container.getVisibleText(); + return containerText; + }, + + async ensureKubernetesTourIsClosed() { + await testSubjects.missingOrFail('infra-kubernetesTour-text'); + }, + + async clickDismissKubernetesTourButton() { + return await testSubjects.click('infra-kubernetesTour-dismiss'); + }, }; }