Skip to content

Commit

Permalink
[Infra][Serverless] fix breadcrumb, page template and small layout is…
Browse files Browse the repository at this point in the history
…sues (elastic#177312)

closes [176602](elastic#176602)

## Summary

This PR fixes a few small issues that became more evident in the
serverless offering

### Serverless

- Breadcrumbs
<img width="1727" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/5808ccd2-8733-406a-8a98-7aedb3e21e8a">
<img width="1727" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/bac99d0c-8146-4946-acc8-7b52133d79fb">
<img width="1727" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/34442e1f-f7ac-425f-9712-ad0a2188cace">


- Asset Details Page Template

| before | after |
| --- | --- |
|<img width="1220" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/4bb92ff0-5e27-4ca9-b177-ba2715996648">|<img
width="1227" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/3d6f1783-01a1-4413-8acf-640b0d6af7f1">
|

The page now uses the `PageTemplate` from `observability-shared`, which
is what other pages in observability use.

### Other fixes

 - Spacing between header and unified search in the Hosts View

| before | after |
| --- | --- |
|<img width="884" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/49727fc5-0f9b-4ee4-b560-b489c175b1ba">|<img
width="885" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/858e6930-6210-42a1-8414-bb6e5d60933c">
|

The default spacing is 24px. For some reason, the hosts view had a 12px
space between the 2 components.

- Breadcrumb (still works as expected)
<img width="1714" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/ef019d40-2a88-4920-a5dc-ad72a8485536">


### How to test

- Start a serverless Kibana, ES instances and run metricbeat with system
module enabled
- run `yarn es serverless --projectType=oblt` and `yarn serverless-oblt`
  - Navigate to Inventory pages and APM Settings
  - Check the changes described above
- Start a stateful Kibana instance
  - Navigate to inventory pages and APM Settings
  - Check the changes described above

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
crespocarlos and kibanamachine authored Feb 23, 2024
1 parent 043d12a commit 2ba6978
Show file tree
Hide file tree
Showing 19 changed files with 171 additions and 107 deletions.
7 changes: 6 additions & 1 deletion packages/deeplinks/observability/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ export type ObservabilityOverviewLinkId =
| 'rules'
| 'slos';

export type MetricsLinkId = 'inventory' | 'metrics-explorer' | 'hosts' | 'settings';
export type MetricsLinkId =
| 'inventory'
| 'metrics-explorer'
| 'hosts'
| 'settings'
| 'assetDetails';

export type ApmLinkId =
| 'services'
Expand Down
14 changes: 12 additions & 2 deletions x-pack/plugins/infra/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,17 @@
"visTypeTimeseries",
"apmDataAccess"
],
"optionalPlugins": ["spaces", "ml", "home", "embeddable", "osquery", "cloud", "profilingDataAccess", "licenseManagement"],
"optionalPlugins": [
"spaces",
"ml",
"home",
"embeddable",
"osquery",
"cloud",
"profilingDataAccess",
"licenseManagement",
"serverless"
],
"requiredBundles": [
"unifiedSearch",
"observability",
Expand All @@ -46,7 +56,7 @@
"kibanaReact",
"ml",
"embeddable",
"controls",
"controls"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
* 2.0.
*/

import { EuiFlexGroup, EuiPageTemplate } from '@elastic/eui';
import { EuiFlexGroup } from '@elastic/eui';
import { css } from '@emotion/react';
import { i18n } from '@kbn/i18n';
import React, { useEffect, useMemo } from 'react';
import { useMetricsBreadcrumbs } from '../../../hooks/use_metrics_breadcrumbs';
import { useParentBreadcrumbResolver } from '../../../hooks/use_parent_breadcrumb_resolver';
import { useKibanaContextForPlugin } from '../../../hooks/use_kibana';
import { useKibanaHeader } from '../../../hooks/use_kibana_header';
import { InfraLoadingPanel } from '../../loading';
Expand All @@ -24,16 +26,36 @@ import { getIntegrationsAvailable } from '../utils';
export const Page = ({ tabs = [], links = [] }: ContentTemplateProps) => {
const { loading } = useAssetDetailsRenderPropsContext();
const { metadata, loading: metadataLoading } = useMetadataStateContext();
const { rightSideItems, tabEntries, breadcrumbs } = usePageHeader(tabs, links);
const { rightSideItems, tabEntries, breadcrumbs: headerBreadcrumbs } = usePageHeader(tabs, links);
const { asset } = useAssetDetailsRenderPropsContext();
const { actionMenuHeight } = useKibanaHeader();
const trackOnlyOnce = React.useRef(false);

const { activeTabId } = useTabSwitcherContext();
const {
services: { telemetry },
services: {
telemetry,
observabilityShared: {
navigation: { PageTemplate },
},
},
} = useKibanaContextForPlugin();

const parentBreadcrumbResolver = useParentBreadcrumbResolver();
const breadcrumbOptions = parentBreadcrumbResolver.getBreadcrumbOptions(asset.type);
useMetricsBreadcrumbs(
[
{
...breadcrumbOptions.link,
text: breadcrumbOptions.text,
},
{
text: asset.name,
},
],
{ deeperContextServerless: true }
);

useEffect(() => {
if (trackOnlyOnce.current) {
return;
Expand Down Expand Up @@ -63,44 +85,35 @@ export const Page = ({ tabs = [], links = [] }: ContentTemplateProps) => {
[actionMenuHeight]
);

return loading ? (
<EuiFlexGroup
direction="column"
css={css`
height: ${heightWithOffset};
`}
>
<InfraLoadingPanel
height="100%"
width="auto"
text={i18n.translate('xpack.infra.waffle.loadingDataText', {
defaultMessage: 'Loading data',
})}
/>
</EuiFlexGroup>
) : (
<EuiPageTemplate
panelled
contentBorder={false}
offset={0}
restrictWidth={false}
style={{
minBlockSize: heightWithOffset,
return (
<PageTemplate
pageHeader={{
pageTitle: asset.name,
tabs: tabEntries,
rightSideItems,
breadcrumbs: headerBreadcrumbs,
}}
data-component-name={ASSET_DETAILS_PAGE_COMPONENT_NAME}
data-asset-type={asset.type}
>
<EuiPageTemplate.Section paddingSize="none">
<EuiPageTemplate.Header
pageTitle={asset.name}
tabs={tabEntries}
rightSideItems={rightSideItems}
breadcrumbs={breadcrumbs}
/>
<EuiPageTemplate.Section grow>
<Content />
</EuiPageTemplate.Section>
</EuiPageTemplate.Section>
</EuiPageTemplate>
{loading ? (
<EuiFlexGroup
direction="column"
css={css`
height: ${heightWithOffset};
`}
>
<InfraLoadingPanel
height="100%"
width="auto"
text={i18n.translate('xpack.infra.waffle.loadingDataText', {
defaultMessage: 'Loading data',
})}
/>
</EuiFlexGroup>
) : (
<Content />
)}
</PageTemplate>
);
};
6 changes: 5 additions & 1 deletion x-pack/plugins/infra/public/hooks/use_kibana.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import type { PropsOf } from '@elastic/eui';
import React, { useMemo, createElement, createContext } from 'react';
import React, { useMemo, createElement, createContext, useContext } from 'react';
import { CoreStart } from '@kbn/core/public';
import {
createKibanaReactContext,
Expand Down Expand Up @@ -73,6 +73,10 @@ export const useKibanaEnvironmentContextProvider = (kibanaEnvironment?: KibanaEn
return Provider;
};

export function useKibanaEnvironmentContext() {
return useContext(KibanaEnvironmentContext);
}

export const createLazyComponentWithKibanaContext = <T extends React.ComponentType<any>>(
coreSetup: InfraClientCoreSetup,
lazyComponentFactory: () => Promise<{ default: T }>
Expand Down
37 changes: 34 additions & 3 deletions x-pack/plugins/infra/public/hooks/use_metrics_breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,42 @@
* 2.0.
*/

import { useEffect, useMemo } from 'react';
import { ChromeBreadcrumb } from '@kbn/core/public';
import { useBreadcrumbs } from './use_breadcrumbs';
import { useBreadcrumbs, useLinkProps } from '@kbn/observability-shared-plugin/public';
import { METRICS_APP } from '../../common/constants';
import { metricsTitle } from '../translations';
import { useKibanaContextForPlugin } from './use_kibana';

export const useMetricsBreadcrumbs = (extraCrumbs: ChromeBreadcrumb[]) => {
useBreadcrumbs(METRICS_APP, metricsTitle, extraCrumbs);
export const useMetricsBreadcrumbs = (
extraCrumbs: ChromeBreadcrumb[],
options?: { deeperContextServerless: boolean }
) => {
const {
services: { serverless },
} = useKibanaContextForPlugin();
const appLinkProps = useLinkProps({ app: METRICS_APP });

const breadcrumbs = useMemo(
() => [
{
...appLinkProps,
text: metricsTitle,
},
...extraCrumbs,
],
[appLinkProps, extraCrumbs]
);

useBreadcrumbs(breadcrumbs);

useEffect(() => {
// For deeper context breadcrumbs in serveless, the `serverless` plugin provides its own breadcrumb service.
// https://docs.elastic.dev/kibana-dev-docs/serverless-project-navigation#breadcrumbs
if (serverless && options?.deeperContextServerless) {
// The initial path is already set in the breadcrumbs
const [, ...serverlessBreadcrumbs] = breadcrumbs;
serverless.setBreadcrumbs(serverlessBreadcrumbs);
}
}, [breadcrumbs, options?.deeperContextServerless, serverless]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common/inventory_models/types';
import { useLinkProps } from '@kbn/observability-shared-plugin/public';
import { useLocation } from 'react-router-dom';
import { hostsTitle, inventoryTitle } from '../../../../translations';
import { BreadcrumbOptions } from '../types';
import type { LinkProps } from '@kbn/observability-shared-plugin/public/hooks/use_link_props';
import { hostsTitle, inventoryTitle } from '../translations';

interface LocationStateProps {
originPathname: string;
}

interface BreadcrumbOptions {
text: string;
link: LinkProps;
}

export function useParentBreadcrumbResolver() {
const hostsLinkProps = useLinkProps({
app: 'metrics',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ const StickyContainer = ({ children }: { children: React.ReactNode }) => {
top: calc(${actionMenuHeight}px + var(--euiFixedHeadersOffset, 0));
z-index: ${euiTheme.levels.navigation};
background: ${euiTheme.colors.emptyShade};
padding: ${euiTheme.size.m} ${euiTheme.size.l} 0px;
padding: ${euiTheme.size.l} ${euiTheme.size.l} 0px;
margin: -${euiTheme.size.l} -${euiTheme.size.l} 0px;
min-height: calc(${euiTheme.size.xxxl} * 2);
`}
Expand Down
6 changes: 3 additions & 3 deletions x-pack/plugins/infra/public/pages/metrics/hosts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
*/

import { EuiErrorBoundary } from '@elastic/eui';
import React, { useContext } from 'react';
import React from 'react';
import { useTrackPageview, FeatureFeedbackButton } from '@kbn/observability-shared-plugin/public';
import { APP_WRAPPER_CLASS } from '@kbn/core/public';
import { css } from '@emotion/react';
import { i18n } from '@kbn/i18n';
import { KibanaEnvironmentContext } from '../../../hooks/use_kibana';
import { useKibanaEnvironmentContext } from '../../../hooks/use_kibana';
import { SourceErrorPage } from '../../../components/source_error_page';
import { SourceLoadingPage } from '../../../components/source_loading_page';
import { useSourceContext } from '../../../containers/metrics_source';
Expand All @@ -29,7 +29,7 @@ const HOSTS_FEEDBACK_LINK =

export const HostsPage = () => {
const { isLoading, loadSourceFailureMessage, loadSource, source } = useSourceContext();
const { kibanaVersion, isCloudEnv, isServerlessEnv } = useContext(KibanaEnvironmentContext);
const { kibanaVersion, isCloudEnv, isServerlessEnv } = useKibanaEnvironmentContext();

useTrackPageview({ app: 'infra_metrics', path: 'hosts' });
useTrackPageview({ app: 'infra_metrics', path: 'hosts', delay: 15000 });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
*/

import { EuiFlexGroup, EuiFlexItem, EuiGlobalToastList } from '@elastic/eui';
import React, { useContext } from 'react';
import React from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import useLocalStorage from 'react-use/lib/useLocalStorage';
import { FeatureFeedbackButton } from '@kbn/observability-shared-plugin/public';
import { KibanaEnvironmentContext } from '../../../../hooks/use_kibana';
import { useKibanaEnvironmentContext } from '../../../../hooks/use_kibana';

const KUBERNETES_TOAST_STORAGE_KEY = 'kubernetesToastKey';
const KUBERNETES_FEEDBACK_LINK = 'https://ela.st/k8s-feedback';
Expand All @@ -19,7 +19,7 @@ export const SurveyKubernetes = () => {
const [isToastSeen, setIsToastSeen] = useLocalStorage(KUBERNETES_TOAST_STORAGE_KEY, false);
const markToastAsSeen = () => setIsToastSeen(true);

const { kibanaVersion, isCloudEnv, isServerlessEnv } = useContext(KibanaEnvironmentContext);
const { kibanaVersion, isCloudEnv, isServerlessEnv } = useKibanaEnvironmentContext();

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* 2.0.
*/

import React, { useContext } from 'react';
import React from 'react';
import { FeatureFeedbackButton } from '@kbn/observability-shared-plugin/public';
import { KibanaEnvironmentContext } from '../../../../hooks/use_kibana';
import { useKibanaEnvironmentContext } from '../../../../hooks/use_kibana';

import { useWaffleOptionsContext } from '../hooks/use_waffle_options';
import { SurveyKubernetes } from './survey_kubernetes';
Expand All @@ -16,7 +16,7 @@ const INVENTORY_FEEDBACK_LINK = 'https://ela.st/survey-infra-inventory?usp=pp_ur

export const SurveySection = () => {
const { nodeType } = useWaffleOptionsContext();
const { kibanaVersion, isCloudEnv, isServerlessEnv } = useContext(KibanaEnvironmentContext);
const { kibanaVersion, isCloudEnv, isServerlessEnv } = useKibanaEnvironmentContext();

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@
import React from 'react';
import { useRouteMatch } from 'react-router-dom';
import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common';
import { useMetricsBreadcrumbs } from '../../../hooks/use_metrics_breadcrumbs';
import { NoRemoteCluster } from '../../../components/empty_states';
import { SourceErrorPage } from '../../../components/source_error_page';
import { SourceLoadingPage } from '../../../components/source_loading_page';
import { useSourceContext } from '../../../containers/metrics_source';
import { AssetDetails } from '../../../components/asset_details/asset_details';
import { MetricsPageTemplate } from '../page_template';
import { commonFlyoutTabs } from '../../../common/asset_details_config/asset_details_tabs';
import { useParentBreadcrumbResolver } from './hooks/use_parent_breadcrumb_resolver';

export const AssetDetailPage = () => {
const { isLoading, loadSourceFailureMessage, loadSource, source } = useSourceContext();
Expand All @@ -26,19 +24,6 @@ export const AssetDetailPage = () => {

const { metricIndicesExist, remoteClustersExist } = source?.status ?? {};

const parentBreadcrumbResolver = useParentBreadcrumbResolver();

const breadcrumbOptions = parentBreadcrumbResolver.getBreadcrumbOptions(nodeType);
useMetricsBreadcrumbs([
{
...breadcrumbOptions.link,
text: breadcrumbOptions.text,
},
{
text: nodeId,
},
]);

if (isLoading || !source) return <SourceLoadingPage />;

if (!remoteClustersExist) {
Expand All @@ -55,21 +40,14 @@ export const AssetDetailPage = () => {
return <SourceErrorPage errorMessage={loadSourceFailureMessage || ''} retry={loadSource} />;

return (
<MetricsPageTemplate
hasData={metricIndicesExist}
pageSectionProps={{
paddingSize: 'none',
<AssetDetails
assetId={nodeId}
assetType={nodeType}
tabs={commonFlyoutTabs}
renderMode={{
mode: 'page',
}}
>
<AssetDetails
assetId={nodeId}
assetType={nodeType}
tabs={commonFlyoutTabs}
renderMode={{
mode: 'page',
}}
metricAlias={source.configuration.metricAlias}
/>
</MetricsPageTemplate>
metricAlias={source.configuration.metricAlias}
/>
);
};
Loading

0 comments on commit 2ba6978

Please sign in to comment.