Skip to content

Commit

Permalink
[Infra UI] Node Details using Asset Details component (elastic#164077)
Browse files Browse the repository at this point in the history
part of [elastic#162898](elastic#162898)

## Summary

This PR implements the new node details page for hosts. It uses the
Asset Details component, which is the same used in the Hosts View
flyout.


https://github.com/elastic/kibana/assets/2767137/0d3d2b2d-ed82-4275-b424-ddae82cdbddc

It **does not** change the behaviour of other asset types (kubernetes,
container, aws...). The main change this PR introduces is internalizing
the Data Views logic so that clients don't have to worry about passing
it to the Asset Details.

The fundamental change between flyout and page is the template.
Everything else is shared.

Functional tests will be added in a separate PR.

### How to test this PR
- Setup a local Kibana instance
- Navigate to `Infrastructure` > `Hosts`
  - Click on a host name and check if the new Node Details page opened
  - Return to the hosts page and open a flyout
- Click on `Open as page` and check if the new Node Details page opened
- Navigate to `Infrastructure` > `Inventory`
- With `Show: Host` selected, click on a waffle item to open the flyout,
click on `Open as page` and check if the new Node Details page opened
- Select another asset type in `Show` , open the flyout and check if the
old version of the Node Details Page will show

#### Storybook
`yarn storybook infra`


### For reviewers

Errors in the new page will be handled differently from what the current
Node Details page. i.e: accessing the page with invalid asset id, won't
show this page

<img width="1443" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/93de3caf-ac63-4a34-a90d-226b212096fe">

---------

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
crespocarlos and kibanamachine authored Aug 22, 2023
1 parent 2e854d6 commit 2ca1081
Show file tree
Hide file tree
Showing 47 changed files with 1,141 additions and 691 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* 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 { type AssetDetailsProps, FlyoutTabIds, type Tab } from '../../../types';

const links: AssetDetailsProps['links'] = ['alertRule', 'nodeDetails', 'apmServices'];
const tabs: Tab[] = [
{
id: FlyoutTabIds.OVERVIEW,
name: i18n.translate('xpack.infra.nodeDetails.tabs.overview.title', {
defaultMessage: 'Overview',
}),
},
{
id: FlyoutTabIds.LOGS,
name: i18n.translate('xpack.infra.nodeDetails.tabs.logs', {
defaultMessage: 'Logs',
}),
},
{
id: FlyoutTabIds.METADATA,
name: i18n.translate('xpack.infra.metrics.nodeDetails.tabs.metadata', {
defaultMessage: 'Metadata',
}),
},
{
id: FlyoutTabIds.PROCESSES,
name: i18n.translate('xpack.infra.metrics.nodeDetails.tabs.processes', {
defaultMessage: 'Processes',
}),
},
{
id: FlyoutTabIds.ANOMALIES,
name: i18n.translate('xpack.infra.nodeDetails.tabs.anomalies', {
defaultMessage: 'Anomalies',
}),
},
{
id: FlyoutTabIds.LINK_TO_APM,
name: i18n.translate('xpack.infra.infra.nodeDetails.apmTabLabel', {
defaultMessage: 'APM',
}),
},
];

export const assetDetailsProps: AssetDetailsProps = {
asset: {
name: 'host1',
id: 'host1',
},
overrides: {
metadata: {
showActionsColumn: true,
},
},
assetType: 'host',
renderMode: {
mode: 'page',
},
dateRange: {
from: '2023-04-09T11:07:49Z',
to: '2023-04-09T11:23:49Z',
},
tabs,
links,
metricAlias: 'metrics-*',
};

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ export { alertsSummaryHttpResponse, type AlertsSummaryHttpMocks } from './alerts
export { anomaliesHttpResponse, type AnomaliesHttpMocks } from './anomalies';
export { snapshotAPItHttpResponse, type SnapshotAPIHttpMocks } from './snapshot_api';
export { getLogEntries } from './log_entries';
export { assetDetailsState } from './asset_details_state';
export { assetDetailsProps } from './asset_details_props';
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,25 @@ import type { IKibanaSearchRequest, ISearchOptions } from '@kbn/data-plugin/publ
import { AlertSummaryWidget } from '@kbn/triggers-actions-ui-plugin/public/application/sections/alert_summary_widget/alert_summary_widget';
import type { Theme } from '@elastic/charts/dist/utils/themes/theme';
import type { AlertSummaryWidgetProps } from '@kbn/triggers-actions-ui-plugin/public/application/sections/alert_summary_widget';
import { defaultLogViewAttributes } from '@kbn/logs-shared-plugin/common';
import { DataView, DataViewField } from '@kbn/data-views-plugin/common';
import type { PluginKibanaContextValue } from '../../../hooks/use_kibana';
import { SourceProvider } from '../../../containers/metrics_source';
import { getHttp } from './context/http';
import { assetDetailsState, getLogEntries } from './context/fixtures';
import { AssetDetailsStateProvider } from '../hooks/use_asset_details_state';
import { assetDetailsProps, getLogEntries } from './context/fixtures';
import { ContextProviders } from '../context_providers';
import { DataViewsProvider } from '../hooks/use_data_views';

const settings: Record<string, any> = {
'dateFormat:scaled': [['', 'HH:mm:ss.SSS']],
};
const getSettings = (key: string): any => settings[key];

const mockDataView = {
id: 'default',
getFieldByName: () => 'hostname' as unknown as DataViewField,
} as unknown as DataView;

export const DecorateWithKibanaContext: DecoratorFn = (story) => {
const initialProcesses = useParameter<{ mock: string }>('apiResponse', {
mock: 'default',
Expand All @@ -58,6 +66,9 @@ export const DecorateWithKibanaContext: DecoratorFn = (story) => {
},
},
},
dataViews: {
create: () => Promise.resolve(mockDataView),
},
locators: {
nodeLogsLocator: {
getRedirectUrl: () => {
Expand Down Expand Up @@ -111,6 +122,22 @@ export const DecorateWithKibanaContext: DecoratorFn = (story) => {
},
},
},
logsShared: {
logViews: {
client: {
getLogView: () =>
Promise.resolve({
id: 'log',
attributes: defaultLogViewAttributes,
origin: 'internal',
}),
getResolvedLogView: () =>
Promise.resolve({
dataViewReference: mockDataView,
} as any),
},
},
},
lens: {
navigateToPrefilledEditor: () => {},
stateHelperApi: () => new Promise(() => {}),
Expand All @@ -130,5 +157,17 @@ export const DecorateWithKibanaContext: DecoratorFn = (story) => {
};

export const DecorateWithAssetDetailsStateContext: DecoratorFn = (story) => {
return <AssetDetailsStateProvider state={assetDetailsState}>{story()}</AssetDetailsStateProvider>;
return (
<ContextProviders
props={{
...assetDetailsProps,
dateRange: {
from: '2023-04-09T11:07:49Z',
to: '2023-04-09T11:23:49Z',
},
}}
>
<DataViewsProvider metricAlias="metrics-*">{story()}</DataViewsProvider>
</ContextProviders>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,69 +8,26 @@
import React, { useState } from 'react';
import { EuiButton } from '@elastic/eui';
import type { Meta, Story } from '@storybook/react/types-6-0';
import { i18n } from '@kbn/i18n';
import { AssetDetails } from './asset_details';
import { decorateWithGlobalStorybookThemeProviders } from '../../test_utils/use_global_storybook_theme';
import { FlyoutTabIds, Tab, type AssetDetailsProps } from './types';
import { type AssetDetailsProps } from './types';
import { DecorateWithKibanaContext } from './__stories__/decorator';
import { assetDetailsState } from './__stories__/context/fixtures';

const links: AssetDetailsProps['links'] = ['alertRule', 'nodeDetails', 'apmServices'];
const tabs: Tab[] = [
{
id: FlyoutTabIds.OVERVIEW,
name: i18n.translate('xpack.infra.nodeDetails.tabs.overview.title', {
defaultMessage: 'Overview',
}),
},
{
id: FlyoutTabIds.LOGS,
name: i18n.translate('xpack.infra.nodeDetails.tabs.logs', {
defaultMessage: 'Logs',
}),
},
{
id: FlyoutTabIds.METADATA,
name: i18n.translate('xpack.infra.metrics.nodeDetails.tabs.metadata', {
defaultMessage: 'Metadata',
}),
},
{
id: FlyoutTabIds.PROCESSES,
name: i18n.translate('xpack.infra.metrics.nodeDetails.tabs.processes', {
defaultMessage: 'Processes',
}),
},
{
id: FlyoutTabIds.ANOMALIES,
name: i18n.translate('xpack.infra.nodeDetails.tabs.anomalies', {
defaultMessage: 'Anomalies',
}),
},
{
id: FlyoutTabIds.LINK_TO_APM,
name: i18n.translate('xpack.infra.infra.nodeDetails.apmTabLabel', {
defaultMessage: 'APM',
}),
},
];
import { assetDetailsProps } from './__stories__/context/fixtures';

const stories: Meta<AssetDetailsProps> = {
title: 'infra/Asset Details View',
decorators: [decorateWithGlobalStorybookThemeProviders, DecorateWithKibanaContext],
component: AssetDetails,
argTypes: {
links: {
options: links,
options: assetDetailsProps.links,
control: {
type: 'inline-check',
},
},
},
args: {
...assetDetailsState,
tabs,
links,
...assetDetailsProps,
},
};

Expand Down Expand Up @@ -99,11 +56,5 @@ const FlyoutTemplate: Story<AssetDetailsProps> = (args) => {
export const Page = PageTemplate.bind({});

export const Flyout = FlyoutTemplate.bind({});
Flyout.args = {
renderMode: {
mode: 'flyout',
closeFlyout: () => {},
},
};

export default stories;
Original file line number Diff line number Diff line change
Expand Up @@ -6,92 +6,42 @@
*/

import React from 'react';
import { EuiFlyout, EuiFlyoutHeader, EuiFlyoutBody } from '@elastic/eui';
import useEffectOnce from 'react-use/lib/useEffectOnce';
import type { AssetDetailsProps, RenderMode } from './types';
import { Content } from './content/content';
import { Header } from './header/header';
import { TabSwitcherProvider, useTabSwitcherContext } from './hooks/use_tab_switcher';
import {
AssetDetailsStateProvider,
useAssetDetailsStateContext,
} from './hooks/use_asset_details_state';
import { useKibanaContextForPlugin } from '../../hooks/use_kibana';
import { ASSET_DETAILS_FLYOUT_COMPONENT_NAME } from './constants';

interface ContentTemplateProps {
header: React.ReactElement;
body: React.ReactElement;
renderMode: RenderMode;
}

const ContentTemplate = ({ header, body, renderMode }: ContentTemplateProps) => {
const { assetType } = useAssetDetailsStateContext();
const { initialActiveTabId } = useTabSwitcherContext();
const {
services: { telemetry },
} = useKibanaContextForPlugin();

useEffectOnce(() => {
telemetry.reportAssetDetailsFlyoutViewed({
componentName: ASSET_DETAILS_FLYOUT_COMPONENT_NAME,
assetType,
tabId: initialActiveTabId,
});
});
import type { AssetDetailsProps, ContentTemplateProps, RenderMode } from './types';
import { Flyout } from './template/flyout';
import { Page } from './template/page';
import { ContextProviders } from './context_providers';
import { TabSwitcherProvider } from './hooks/use_tab_switcher';
import { DataViewsProvider } from './hooks/use_data_views';

const ContentTemplate = ({
header,
renderMode,
}: ContentTemplateProps & { renderMode: RenderMode }) => {
return renderMode.mode === 'flyout' ? (
<EuiFlyout
onClose={renderMode.closeFlyout}
ownFocus={false}
data-component-name={ASSET_DETAILS_FLYOUT_COMPONENT_NAME}
data-asset-type={assetType}
>
<EuiFlyoutHeader hasBorder>{header}</EuiFlyoutHeader>
<EuiFlyoutBody>{body}</EuiFlyoutBody>
</EuiFlyout>
<Flyout header={header} closeFlyout={renderMode.closeFlyout} />
) : (
<>
{header}
{body}
</>
<Page header={header} />
);
};

export const AssetDetails = ({
asset,
dateRange,
tabs,
links,
renderMode,
activeTabId,
overrides,
onTabsStateChange,
tabs = [],
links = [],
assetType = 'host',
renderMode = {
mode: 'page',
},
metricAlias,
...props
}: AssetDetailsProps) => {
return (
<AssetDetailsStateProvider
state={{
asset,
assetType,
overrides,
onTabsStateChange,
dateRange,
renderMode,
}}
>
<ContextProviders props={{ ...props, renderMode }}>
<TabSwitcherProvider
initialActiveTabId={tabs.length > 0 ? activeTabId ?? tabs[0].id : undefined}
>
<ContentTemplate
header={<Header compact={renderMode.mode === 'flyout'} tabs={tabs} links={links} />}
body={<Content />}
renderMode={renderMode}
/>
<DataViewsProvider metricAlias={metricAlias}>
<ContentTemplate header={{ tabs, links }} renderMode={renderMode} />
</DataViewsProvider>
</TabSwitcherProvider>
</AssetDetailsStateProvider>
</ContextProviders>
);
};

Expand Down
Loading

0 comments on commit 2ca1081

Please sign in to comment.