;
+function calculateBucketSize({ start, end }: { start?: number; end?: number }) {
+ if (start && end) {
+ return getBucketSize({ start, end, minInterval: '60s' });
+ }
+}
+
+export function OverviewPage({ routeParams }: Props) {
+ useTrackPageview({ app: 'observability-overview', path: 'overview' });
+ useTrackPageview({ app: 'observability-overview', path: 'overview', delay: 15000 });
+ useBreadcrumbs([
+ {
+ text: i18n.translate('xpack.observability.breadcrumbs.overviewLinkText', {
+ defaultMessage: 'Overview',
+ }),
+ },
+ ]);
+
+ const { core, ObservabilityPageTemplate } = usePluginContext();
+
+ const { relativeStart, relativeEnd, absoluteStart, absoluteEnd } = useTimeRange();
+
+ const relativeTime = { start: relativeStart, end: relativeEnd };
+ const absoluteTime = { start: absoluteStart, end: absoluteEnd };
+
+ const { data: newsFeed } = useFetcher(() => getNewsFeed({ core }), [core]);
+
+ const { hasDataMap, hasAnyData, isAllRequestsComplete } = useHasData();
+
+ if (hasAnyData === undefined) {
+ return ;
+ }
+
+ const hasData = hasAnyData === true || (isAllRequestsComplete === false ? undefined : false);
+
+ const noDataConfig = getNoDataConfig({
+ hasData,
+ basePath: core.http.basePath,
+ docsLink: core.docLinks.links.observability.guide,
+ });
+
+ const { refreshInterval = 10000, refreshPaused = true } = routeParams.query;
+
+ const bucketSize = calculateBucketSize({
+ start: absoluteTime.start,
+ end: absoluteTime.end,
+ });
+
+ return (
+ ,
+ ],
+ }
+ : undefined
+ }
+ >
+ {hasData && (
+ <>
+
+
+
+ {/* Data sections */}
+ {hasAnyData && }
+
+
+
+
+ {/* Resources / What's New sections */}
+
+
+
+ {!!newsFeed?.items?.length && }
+
+
+ {hasDataMap?.alert?.hasData && (
+
+
+
+
+
+ )}
+
+
+
+ >
+ )}
+
+ );
+}
+
+const overviewPageTitle = i18n.translate('xpack.observability.overview.pageTitle', {
+ defaultMessage: 'Overview',
+});
diff --git a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx
index 6549e892cab1..6213ea3e66d4 100644
--- a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx
+++ b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx
@@ -66,7 +66,11 @@ const withCore = makeDecorator({
setHeaderActionMenu: () => {},
} as unknown as AppMountParameters,
config: {
- unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } },
+ unsafe: {
+ alertingExperience: { enabled: true },
+ cases: { enabled: true },
+ overviewNext: { enabled: false },
+ },
},
core: options as CoreStart,
plugins: {
diff --git a/x-pack/plugins/observability/public/pages/overview/overview_page.tsx b/x-pack/plugins/observability/public/pages/overview/overview_page.tsx
new file mode 100644
index 000000000000..f4cdec680af9
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/overview/overview_page.tsx
@@ -0,0 +1,82 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+import React from 'react';
+import { useTrackPageview } from '../..';
+import { DatePicker } from '../../components/shared/date_picker';
+import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
+import { useHasData } from '../../hooks/use_has_data';
+import { usePluginContext } from '../../hooks/use_plugin_context';
+import { useTimeRange } from '../../hooks/use_time_range';
+import { RouteParams } from '../../routes';
+import { getNoDataConfig } from '../../utils/no_data_config';
+import { LoadingObservability } from './loading_observability';
+
+interface Props {
+ routeParams: RouteParams<'/overview'>;
+}
+
+export function OverviewPage({ routeParams }: Props) {
+ useTrackPageview({ app: 'observability-overview', path: 'overview' });
+ useTrackPageview({ app: 'observability-overview', path: 'overview', delay: 15000 });
+ useBreadcrumbs([
+ {
+ text: i18n.translate('xpack.observability.breadcrumbs.overviewLinkText', {
+ defaultMessage: 'Overview',
+ }),
+ },
+ ]);
+
+ const { core, ObservabilityPageTemplate } = usePluginContext();
+
+ const { relativeStart, relativeEnd } = useTimeRange();
+
+ const relativeTime = { start: relativeStart, end: relativeEnd };
+
+ const { hasAnyData, isAllRequestsComplete } = useHasData();
+
+ if (hasAnyData === undefined) {
+ return ;
+ }
+
+ const hasData = hasAnyData === true || (isAllRequestsComplete === false ? undefined : false);
+
+ const noDataConfig = getNoDataConfig({
+ hasData,
+ basePath: core.http.basePath,
+ docsLink: core.docLinks.links.observability.guide,
+ });
+
+ const { refreshInterval = 10000, refreshPaused = true } = routeParams.query;
+
+ return (
+ ,
+ ],
+ }
+ : undefined
+ }
+ >
+ {hasData && New observability content goes here
}
+
+ );
+}
+
+const overviewPageTitle = i18n.translate('xpack.observability.overview.pageTitle', {
+ defaultMessage: 'Overview',
+});
diff --git a/x-pack/plugins/observability/public/utils/test_helper.tsx b/x-pack/plugins/observability/public/utils/test_helper.tsx
index 544f3feecb2b..a3ec446e5c30 100644
--- a/x-pack/plugins/observability/public/utils/test_helper.tsx
+++ b/x-pack/plugins/observability/public/utils/test_helper.tsx
@@ -34,7 +34,13 @@ export const core = {
},
} as unknown as CoreStart;
-const config = { unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } } };
+const config = {
+ unsafe: {
+ alertingExperience: { enabled: true },
+ cases: { enabled: true },
+ overviewNext: { enabled: false },
+ },
+};
const plugins = {
data: { query: { timefilter: { timefilter: { setTime: jest.fn() } } } },
diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts
index d99cf0865c0d..51204c7512a3 100644
--- a/x-pack/plugins/observability/server/index.ts
+++ b/x-pack/plugins/observability/server/index.ts
@@ -34,6 +34,7 @@ export const config: PluginConfigDescriptor = {
unsafe: schema.object({
alertingExperience: schema.object({ enabled: schema.boolean({ defaultValue: true }) }),
cases: schema.object({ enabled: schema.boolean({ defaultValue: true }) }),
+ overviewNext: schema.object({ enabled: schema.boolean({ defaultValue: false }) }),
}),
}),
};