From 79b494ee7fc634bf5764079ddec5db6b95f7c0fa Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 21 Oct 2021 09:20:00 -0400 Subject: [PATCH] [RAC][Observability] Use no data screen for the alerts and cases pages (#115178) (#115919) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Chris Cowan Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Alejandro Fernández Gómez Co-authored-by: Chris Cowan --- .../public/pages/alerts/index.tsx | 20 ++++++++++++++++ .../public/pages/cases/all_cases.tsx | 23 +++++++++++++++++-- .../page_objects/observability_page.ts | 7 ++++-- .../services/observability/alerts/common.ts | 5 ++++ .../apps/observability/alerts/add_to_case.ts | 2 ++ .../apps/observability/alerts/index.ts | 15 ++++++++++++ .../observability/alerts/workflow_status.ts | 2 ++ .../observability_security.ts | 9 ++++++++ 8 files changed, 79 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx index bba3b426598dfd..142ba11407c5ae 100644 --- a/x-pack/plugins/observability/public/pages/alerts/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx @@ -16,9 +16,12 @@ import type { AlertWorkflowStatus } from '../../../common/typings'; import { ExperimentalBadge } from '../../components/shared/experimental_badge'; import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; import { useFetcher } from '../../hooks/use_fetcher'; +import { useHasData } from '../../hooks/use_has_data'; import { usePluginContext } from '../../hooks/use_plugin_context'; import { RouteParams } from '../../routes'; import { callObservabilityApi } from '../../services/call_observability_api'; +import { getNoDataConfig } from '../../utils/no_data_config'; +import { LoadingObservability } from '../overview/loading_observability'; import { AlertsSearchBar } from './alerts_search_bar'; import { AlertsTableTGrid } from './alerts_table_t_grid'; import './styles.scss'; @@ -141,8 +144,25 @@ export function AlertsPage({ routeParams }: AlertsPageProps) { refetch.current = ref; }, []); + const { hasAnyData, isAllRequestsComplete } = useHasData(); + + // If there is any data, set hasData to true otherwise we need to wait till all the data is loaded before setting hasData to true or false; undefined indicates the data is still loading. + const hasData = hasAnyData === true || (isAllRequestsComplete === false ? undefined : false); + + if (!hasAnyData && !isAllRequestsComplete) { + return ; + } + + const noDataConfig = getNoDataConfig({ + hasData, + basePath: core.http.basePath, + docsLink: core.docLinks.links.observability.guide, + }); + return ( diff --git a/x-pack/plugins/observability/public/pages/cases/all_cases.tsx b/x-pack/plugins/observability/public/pages/cases/all_cases.tsx index 442104a7106017..4ac7c4cfd92a59 100644 --- a/x-pack/plugins/observability/public/pages/cases/all_cases.tsx +++ b/x-pack/plugins/observability/public/pages/cases/all_cases.tsx @@ -16,16 +16,35 @@ import { usePluginContext } from '../../hooks/use_plugin_context'; import { useReadonlyHeader } from '../../hooks/use_readonly_header'; import { casesBreadcrumbs } from './links'; import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; +import { useHasData } from '../../hooks/use_has_data'; +import { LoadingObservability } from '../overview/loading_observability'; +import { getNoDataConfig } from '../../utils/no_data_config'; export const AllCasesPage = React.memo(() => { const userPermissions = useGetUserCasesPermissions(); - const { ObservabilityPageTemplate } = usePluginContext(); + const { core, ObservabilityPageTemplate } = usePluginContext(); useReadonlyHeader(); - useBreadcrumbs([casesBreadcrumbs.cases]); + const { hasAnyData, isAllRequestsComplete } = useHasData(); + + if (!hasAnyData && !isAllRequestsComplete) { + return ; + } + + // If there is any data, set hasData to true otherwise we need to wait till all the data is loaded before setting hasData to true or false; undefined indicates the data is still loading. + const hasData = hasAnyData === true || (isAllRequestsComplete === false ? undefined : false); + + const noDataConfig = getNoDataConfig({ + hasData, + basePath: core.http.basePath, + docsLink: core.docLinks.links.observability.guide, + }); + return userPermissions == null || userPermissions?.read ? ( {i18n.PAGE_TITLE}, }} diff --git a/x-pack/test/functional/page_objects/observability_page.ts b/x-pack/test/functional/page_objects/observability_page.ts index d9e413d473adf3..f89dafe4f3a732 100644 --- a/x-pack/test/functional/page_objects/observability_page.ts +++ b/x-pack/test/functional/page_objects/observability_page.ts @@ -11,7 +11,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function ObservabilityPageProvider({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); - const find = getService('find'); return { async expectCreateCaseButtonEnabled() { @@ -32,6 +31,10 @@ export function ObservabilityPageProvider({ getService, getPageObjects }: FtrPro await testSubjects.missingOrFail('case-callout-e41900b01c9ef0fa81dd6ff326083fb3'); }, + async expectNoDataPage() { + await testSubjects.existOrFail('noDataPage'); + }, + async expectCreateCase() { await testSubjects.existOrFail('case-creation-form-steps'); }, @@ -47,7 +50,7 @@ export function ObservabilityPageProvider({ getService, getPageObjects }: FtrPro }, async expectForbidden() { - const h2 = await find.byCssSelector('body', 20000); + const h2 = await testSubjects.find('no_feature_permissions', 20000); const text = await h2.getVisibleText(); expect(text).to.contain('Kibana feature privileges required'); }, diff --git a/x-pack/test/functional/services/observability/alerts/common.ts b/x-pack/test/functional/services/observability/alerts/common.ts index d5a2ce2a18c411..866febc9b9f5bd 100644 --- a/x-pack/test/functional/services/observability/alerts/common.ts +++ b/x-pack/test/functional/services/observability/alerts/common.ts @@ -66,6 +66,10 @@ export function ObservabilityAlertsCommonProvider({ return await testSubjects.existOrFail(ALERTS_TABLE_CONTAINER_SELECTOR); }; + const getNoDataPageOrFail = async () => { + return await testSubjects.existOrFail('noDataPage'); + }; + const getNoDataStateOrFail = async () => { return await testSubjects.existOrFail('tGridEmptyState'); }; @@ -193,6 +197,7 @@ export function ObservabilityAlertsCommonProvider({ getCopyToClipboardButton, getFilterForValueButton, copyToClipboardButtonExists, + getNoDataPageOrFail, getNoDataStateOrFail, getTableCells, getTableCellsInRows, diff --git a/x-pack/test/observability_functional/apps/observability/alerts/add_to_case.ts b/x-pack/test/observability_functional/apps/observability/alerts/add_to_case.ts index f29111f2cb66bb..5e80a5769b44d0 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/add_to_case.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/add_to_case.ts @@ -17,9 +17,11 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); + await esArchiver.load('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 esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); }); diff --git a/x-pack/test/observability_functional/apps/observability/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/alerts/index.ts index 14019472eb2ca3..a247f42da5821c 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/index.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/index.ts @@ -38,7 +38,22 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); }); + describe('With no data', () => { + it('Shows the no data screen', async () => { + await observability.alerts.common.getNoDataPageOrFail(); + }); + }); + describe('Alerts table', () => { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + await observability.alerts.common.navigateToTimeWithData(); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + }); + it('Renders the table', async () => { await observability.alerts.common.getTableOrFail(); }); diff --git a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts index a68636b8cb0c00..879cef01c2ada2 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts @@ -21,11 +21,13 @@ export default ({ getService }: FtrProviderContext) => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); await observability.alerts.common.navigateToTimeWithData(); }); after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); }); it('is filtered to only show "open" alerts by default', async () => { diff --git a/x-pack/test/observability_functional/apps/observability/feature_controls/observability_security.ts b/x-pack/test/observability_functional/apps/observability/feature_controls/observability_security.ts index 69bf995c49ae48..85512f8333038b 100644 --- a/x-pack/test/observability_functional/apps/observability/feature_controls/observability_security.ts +++ b/x-pack/test/observability_functional/apps/observability/feature_controls/observability_security.ts @@ -31,8 +31,14 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await esArchiver.unload('x-pack/test/functional/es_archives/cases/default'); }); + it('Shows the no data page on load', async () => { + await PageObjects.common.navigateToActualUrl('observabilityCases'); + await PageObjects.observability.expectNoDataPage(); + }); + describe('observability cases all privileges', () => { before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ observabilityCases: ['all'], @@ -42,6 +48,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); await observability.users.restoreDefaultTestUserRole(); }); @@ -83,6 +90,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('observability cases read-only privileges', () => { before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); await observability.users.setTestUserRole( observability.users.defineBasicObservabilityRole({ observabilityCases: ['read'], @@ -92,6 +100,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); await observability.users.restoreDefaultTestUserRole(); });