Design cleanup details panel (#85044)
* cleanup overlay panel. fixed sizes, variable panel height, responsive breakpoint * cleanup metrics tab. use EuiFlexGrid + ChartSizeArray for chart sizing + fixed responsive issues on flex items * cleanup metadata tab. disabled responsive table and fixed alignment of filter icon + value * cleanup logs search. adjusted button size + spacing * fix responsivness on array values * remove responsive behavior on search + view-in-logs button * fix typecheck
This commit is contained in:
parent
c85f2545da
commit
c6ef1ae30b
|
@ -4,9 +4,9 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EuiPortal, EuiTabs, EuiTab, EuiPanel, EuiTitle } from '@elastic/eui';
|
import { EuiPortal, EuiTabs, EuiTab, EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n/react';
|
import { FormattedMessage } from '@kbn/i18n/react';
|
||||||
import React, { CSSProperties, useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
|
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
|
||||||
import { euiStyled } from '../../../../../../../observability/public';
|
import { euiStyled } from '../../../../../../../observability/public';
|
||||||
import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../../../../lib/lib';
|
import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../../../../lib/lib';
|
||||||
|
@ -15,7 +15,7 @@ import { MetricsTab } from './tabs/metrics/metrics';
|
||||||
import { LogsTab } from './tabs/logs';
|
import { LogsTab } from './tabs/logs';
|
||||||
import { ProcessesTab } from './tabs/processes';
|
import { ProcessesTab } from './tabs/processes';
|
||||||
import { PropertiesTab } from './tabs/properties/index';
|
import { PropertiesTab } from './tabs/properties/index';
|
||||||
import { OVERLAY_Y_START, OVERLAY_BOTTOM_MARGIN, OVERLAY_HEADER_SIZE } from './tabs/shared';
|
import { OVERLAY_Y_START, OVERLAY_BOTTOM_MARGIN } from './tabs/shared';
|
||||||
import { useLinkProps } from '../../../../../hooks/use_link_props';
|
import { useLinkProps } from '../../../../../hooks/use_link_props';
|
||||||
import { getNodeDetailUrl } from '../../../../link_to';
|
import { getNodeDetailUrl } from '../../../../link_to';
|
||||||
import { findInventoryModel } from '../../../../../../common/inventory_models';
|
import { findInventoryModel } from '../../../../../../common/inventory_models';
|
||||||
|
@ -70,21 +70,23 @@ export const NodeContextPopover = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiPortal>
|
<EuiPortal>
|
||||||
<EuiPanel hasShadow={true} paddingSize={'none'} style={panelStyle}>
|
<OverlayPanel>
|
||||||
<OverlayHeader>
|
<OverlayHeader>
|
||||||
<OverlayHeaderTitleWrapper>
|
<EuiFlexGroup responsive={false} gutterSize="m">
|
||||||
<EuiFlexItem grow={true}>
|
<EuiFlexItem grow={true}>
|
||||||
<EuiTitle size="s">
|
<EuiTitle size="xs">
|
||||||
<h4>{node.name}</h4>
|
<h4>{node.name}</h4>
|
||||||
</EuiTitle>
|
</EuiTitle>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<EuiFlexGroup gutterSize={'xs'} alignItems={'flexEnd'}>
|
<EuiFlexGroup gutterSize="m" responsive={false}>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<EuiButtonEmpty
|
<EuiButtonEmpty
|
||||||
|
size="xs"
|
||||||
iconSide={'left'}
|
iconSide={'left'}
|
||||||
iconType={'popout'}
|
iconType={'popout'}
|
||||||
href={nodeDetailMenuItemLinkProps.href}
|
href={nodeDetailMenuItemLinkProps.href}
|
||||||
|
flush="both"
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="xpack.infra.infra.nodeDetails.openAsPage"
|
id="xpack.infra.infra.nodeDetails.openAsPage"
|
||||||
|
@ -93,7 +95,7 @@ export const NodeContextPopover = ({
|
||||||
</EuiButtonEmpty>
|
</EuiButtonEmpty>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<EuiButtonEmpty onClick={onClose} iconType={'cross'}>
|
<EuiButtonEmpty size="xs" onClick={onClose} iconType="cross" flush="both">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="xpack.infra.infra.nodeDetails.close"
|
id="xpack.infra.infra.nodeDetails.close"
|
||||||
defaultMessage="Close"
|
defaultMessage="Close"
|
||||||
|
@ -102,8 +104,9 @@ export const NodeContextPopover = ({
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
</OverlayHeaderTitleWrapper>
|
</EuiFlexGroup>
|
||||||
<EuiTabs>
|
<EuiSpacer size="s" />
|
||||||
|
<EuiTabs size="s">
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<EuiTab key={tab.id} isSelected={i === selectedTab} onClick={() => setSelectedTab(i)}>
|
<EuiTab key={tab.id} isSelected={i === selectedTab} onClick={() => setSelectedTab(i)}>
|
||||||
{tab.name}
|
{tab.name}
|
||||||
|
@ -112,32 +115,38 @@ export const NodeContextPopover = ({
|
||||||
</EuiTabs>
|
</EuiTabs>
|
||||||
</OverlayHeader>
|
</OverlayHeader>
|
||||||
{tabs[selectedTab].content}
|
{tabs[selectedTab].content}
|
||||||
</EuiPanel>
|
</OverlayPanel>
|
||||||
</EuiPortal>
|
</EuiPortal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const OverlayHeader = euiStyled.div`
|
const OverlayHeader = euiStyled.div`
|
||||||
border-color: ${(props) => props.theme.eui.euiBorderColor};
|
padding-top: ${(props) => props.theme.eui.paddingSizes.m};
|
||||||
border-bottom-width: ${(props) => props.theme.eui.euiBorderWidthThick};
|
padding-right: ${(props) => props.theme.eui.paddingSizes.m};
|
||||||
padding-bottom: 0;
|
padding-left: ${(props) => props.theme.eui.paddingSizes.m};
|
||||||
|
background-color: ${(props) => props.theme.eui.euiPageBackgroundColor};
|
||||||
|
box-shadow: inset 0 -1px ${(props) => props.theme.eui.euiBorderColor};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const OverlayPanel = euiStyled(EuiPanel).attrs({ paddingSize: 'none' })`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
right: 16px;
|
||||||
|
top: ${OVERLAY_Y_START}px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 720px;
|
||||||
|
z-index: 2;
|
||||||
|
max-height: calc(100vh - ${OVERLAY_Y_START + OVERLAY_BOTTOM_MARGIN}px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: ${(props) => props.theme.eui.euiColorLightestShade};
|
|
||||||
height: ${OVERLAY_HEADER_SIZE}px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const OverlayHeaderTitleWrapper = euiStyled(EuiFlexGroup).attrs({ alignItems: 'center' })`
|
@media (max-width: 752px) {
|
||||||
padding: ${(props) => props.theme.eui.paddingSizes.s} ${(props) =>
|
border-radius: 0px !important;
|
||||||
props.theme.eui.paddingSizes.m} 0;
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
top: 97px;
|
||||||
|
bottom: 0;
|
||||||
|
max-height: calc(100vh - 97px);
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const panelStyle: CSSProperties = {
|
|
||||||
position: 'absolute',
|
|
||||||
right: 10,
|
|
||||||
top: OVERLAY_Y_START,
|
|
||||||
width: '50%',
|
|
||||||
maxWidth: 730,
|
|
||||||
zIndex: 2,
|
|
||||||
height: `calc(100vh - ${OVERLAY_Y_START + OVERLAY_BOTTOM_MARGIN}px)`,
|
|
||||||
overflow: 'hidden',
|
|
||||||
};
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ import { TabContent, TabProps } from './shared';
|
||||||
import { LogStream } from '../../../../../../components/log_stream';
|
import { LogStream } from '../../../../../../components/log_stream';
|
||||||
import { useWaffleOptionsContext } from '../../../hooks/use_waffle_options';
|
import { useWaffleOptionsContext } from '../../../hooks/use_waffle_options';
|
||||||
import { findInventoryFields } from '../../../../../../../common/inventory_models';
|
import { findInventoryFields } from '../../../../../../../common/inventory_models';
|
||||||
import { euiStyled } from '../../../../../../../../observability/public';
|
|
||||||
import { useLinkProps } from '../../../../../../hooks/use_link_props';
|
import { useLinkProps } from '../../../../../../hooks/use_link_props';
|
||||||
import { getNodeLogsUrl } from '../../../../../link_to';
|
import { getNodeLogsUrl } from '../../../../../link_to';
|
||||||
|
|
||||||
|
@ -51,22 +50,25 @@ const TabComponent = (props: TabProps) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TabContent>
|
<TabContent>
|
||||||
<EuiFlexGroup gutterSize={'none'} alignItems="center">
|
<EuiFlexGroup gutterSize={'m'} alignItems={'center'} responsive={false}>
|
||||||
<EuiFlexItem>
|
<EuiFlexItem>
|
||||||
<QueryWrapper>
|
<EuiFieldSearch
|
||||||
<EuiFieldSearch
|
fullWidth
|
||||||
fullWidth
|
placeholder={i18n.translate('xpack.infra.nodeDetails.logs.textFieldPlaceholder', {
|
||||||
placeholder={i18n.translate('xpack.infra.nodeDetails.logs.textFieldPlaceholder', {
|
defaultMessage: 'Search for log entries...',
|
||||||
defaultMessage: 'Search for log entries...',
|
})}
|
||||||
})}
|
value={textQuery}
|
||||||
value={textQuery}
|
isClearable
|
||||||
isClearable
|
onChange={onQueryChange}
|
||||||
onChange={onQueryChange}
|
/>
|
||||||
/>
|
|
||||||
</QueryWrapper>
|
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<EuiButtonEmpty iconType={'popout'} {...nodeLogsMenuItemLinkProps}>
|
<EuiButtonEmpty
|
||||||
|
size={'xs'}
|
||||||
|
flush={'both'}
|
||||||
|
iconType={'popout'}
|
||||||
|
{...nodeLogsMenuItemLinkProps}
|
||||||
|
>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="xpack.infra.nodeDetails.logs.openLogsLink"
|
id="xpack.infra.nodeDetails.logs.openLogsLink"
|
||||||
defaultMessage="Open in Logs"
|
defaultMessage="Open in Logs"
|
||||||
|
@ -79,11 +81,6 @@ const TabComponent = (props: TabProps) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const QueryWrapper = euiStyled.div`
|
|
||||||
padding: ${(props) => props.theme.eui.paddingSizes.m};
|
|
||||||
padding-right: 0;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const LogsTab = {
|
export const LogsTab = {
|
||||||
id: 'logs',
|
id: 'logs',
|
||||||
name: i18n.translate('xpack.infra.nodeDetails.tabs.logs', {
|
name: i18n.translate('xpack.infra.nodeDetails.tabs.logs', {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import { EuiFlexGroup } from '@elastic/eui';
|
||||||
import { EuiIcon } from '@elastic/eui';
|
import { EuiIcon } from '@elastic/eui';
|
||||||
import { colorTransformer } from '../../../../../../../../common/color_palette';
|
import { colorTransformer } from '../../../../../../../../common/color_palette';
|
||||||
import { MetricsExplorerOptionsMetric } from '../../../../../metrics_explorer/hooks/use_metrics_explorer_options';
|
import { MetricsExplorerOptionsMetric } from '../../../../../metrics_explorer/hooks/use_metrics_explorer_options';
|
||||||
import { euiStyled } from '../../../../../../../../../observability/public';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -20,33 +19,33 @@ interface Props {
|
||||||
|
|
||||||
export const ChartHeader = ({ title, metrics }: Props) => {
|
export const ChartHeader = ({ title, metrics }: Props) => {
|
||||||
return (
|
return (
|
||||||
<ChartHeaderWrapper>
|
<EuiFlexGroup gutterSize={'s'} responsive={false}>
|
||||||
<EuiFlexItem grow={1}>
|
<EuiFlexItem grow={1}>
|
||||||
<EuiText>
|
<EuiText size={'s'}>
|
||||||
<strong>{title}</strong>
|
<h4>{title}</h4>
|
||||||
</EuiText>
|
</EuiText>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<EuiFlexGroup gutterSize={'s'} alignItems={'center'}>
|
<EuiFlexGroup gutterSize={'s'} alignItems={'center'} responsive={false}>
|
||||||
{metrics.map((chartMetric) => (
|
{metrics.map((chartMetric) => (
|
||||||
<EuiFlexGroup key={chartMetric.label!} gutterSize={'s'} alignItems={'center'}>
|
<EuiFlexItem key={chartMetric.label!}>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexGroup
|
||||||
<EuiIcon color={colorTransformer(chartMetric.color!)} type={'dot'} />
|
key={chartMetric.label!}
|
||||||
</EuiFlexItem>
|
gutterSize={'xs'}
|
||||||
<EuiFlexItem grow={false}>
|
alignItems={'center'}
|
||||||
<EuiText size={'xs'}>{chartMetric.label}</EuiText>
|
responsive={false}
|
||||||
</EuiFlexItem>
|
>
|
||||||
</EuiFlexGroup>
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiIcon color={colorTransformer(chartMetric.color!)} type={'dot'} />
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiText size={'xs'}>{chartMetric.label}</EuiText>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
</EuiFlexItem>
|
||||||
))}
|
))}
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
</ChartHeaderWrapper>
|
</EuiFlexGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ChartHeaderWrapper = euiStyled.div`
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
padding: ${(props) => props.theme.eui.paddingSizes.s} ${(props) =>
|
|
||||||
props.theme.eui.paddingSizes.m};
|
|
||||||
`;
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n';
|
||||||
import {
|
import {
|
||||||
Axis,
|
Axis,
|
||||||
Chart,
|
Chart,
|
||||||
|
ChartSizeArray,
|
||||||
niceTimeFormatter,
|
niceTimeFormatter,
|
||||||
Position,
|
Position,
|
||||||
Settings,
|
Settings,
|
||||||
|
@ -17,7 +18,7 @@ import {
|
||||||
PointerEvent,
|
PointerEvent,
|
||||||
} from '@elastic/charts';
|
} from '@elastic/charts';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { EuiLoadingChart } from '@elastic/eui';
|
import { EuiLoadingChart, EuiSpacer, EuiFlexGrid, EuiFlexItem } from '@elastic/eui';
|
||||||
import { TabContent, TabProps } from '../shared';
|
import { TabContent, TabProps } from '../shared';
|
||||||
import { useSnapshot } from '../../../../hooks/use_snaphot';
|
import { useSnapshot } from '../../../../hooks/use_snaphot';
|
||||||
import { useWaffleOptionsContext } from '../../../../hooks/use_waffle_options';
|
import { useWaffleOptionsContext } from '../../../../hooks/use_waffle_options';
|
||||||
|
@ -39,7 +40,6 @@ import { createInventoryMetricFormatter } from '../../../../lib/create_inventory
|
||||||
import { calculateDomain } from '../../../../../metrics_explorer/components/helpers/calculate_domain';
|
import { calculateDomain } from '../../../../../metrics_explorer/components/helpers/calculate_domain';
|
||||||
import { getTimelineChartTheme } from '../../../../../metrics_explorer/components/helpers/get_chart_theme';
|
import { getTimelineChartTheme } from '../../../../../metrics_explorer/components/helpers/get_chart_theme';
|
||||||
import { useUiSetting } from '../../../../../../../../../../../src/plugins/kibana_react/public';
|
import { useUiSetting } from '../../../../../../../../../../../src/plugins/kibana_react/public';
|
||||||
import { euiStyled } from '../../../../../../../../../observability/public';
|
|
||||||
import { ChartHeader } from './chart_header';
|
import { ChartHeader } from './chart_header';
|
||||||
import {
|
import {
|
||||||
SYSTEM_METRIC_NAME,
|
SYSTEM_METRIC_NAME,
|
||||||
|
@ -56,6 +56,8 @@ import {
|
||||||
import { TimeDropdown } from './time_dropdown';
|
import { TimeDropdown } from './time_dropdown';
|
||||||
|
|
||||||
const ONE_HOUR = 60 * 60 * 1000;
|
const ONE_HOUR = 60 * 60 * 1000;
|
||||||
|
const CHART_SIZE: ChartSizeArray = ['100%', 160];
|
||||||
|
|
||||||
const TabComponent = (props: TabProps) => {
|
const TabComponent = (props: TabProps) => {
|
||||||
const cpuChartRef = useRef<Chart>(null);
|
const cpuChartRef = useRef<Chart>(null);
|
||||||
const networkChartRef = useRef<Chart>(null);
|
const networkChartRef = useRef<Chart>(null);
|
||||||
|
@ -282,217 +284,184 @@ const TabComponent = (props: TabProps) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TabContent>
|
<TabContent>
|
||||||
<TimepickerWrapper>
|
<TimeDropdown value={time} onChange={updateTime} />
|
||||||
<TimeDropdown value={time} onChange={updateTime} />
|
|
||||||
</TimepickerWrapper>
|
<EuiSpacer size={'l'} />
|
||||||
<ChartsContainer>
|
|
||||||
<ChartContainerWrapper>
|
<EuiFlexGrid columns={2} gutterSize={'l'} responsive={false}>
|
||||||
|
<EuiFlexItem>
|
||||||
<ChartHeader title={CPU_CHART_TITLE} metrics={cpuChartMetrics} />
|
<ChartHeader title={CPU_CHART_TITLE} metrics={cpuChartMetrics} />
|
||||||
<ChartContainer>
|
<Chart ref={cpuChartRef} size={CHART_SIZE}>
|
||||||
<Chart ref={cpuChartRef}>
|
<MetricExplorerSeriesChart
|
||||||
<MetricExplorerSeriesChart
|
type={MetricsExplorerChartType.line}
|
||||||
type={MetricsExplorerChartType.line}
|
metric={cpuChartMetrics[0]}
|
||||||
metric={cpuChartMetrics[0]}
|
id={'0'}
|
||||||
id={'0'}
|
series={systemMetricsTs!}
|
||||||
series={systemMetricsTs!}
|
stack={false}
|
||||||
stack={false}
|
/>
|
||||||
/>
|
<MetricExplorerSeriesChart
|
||||||
<MetricExplorerSeriesChart
|
type={MetricsExplorerChartType.line}
|
||||||
type={MetricsExplorerChartType.line}
|
metric={cpuChartMetrics[1]}
|
||||||
metric={cpuChartMetrics[1]}
|
id={'0'}
|
||||||
id={'0'}
|
series={userMetricsTs}
|
||||||
series={userMetricsTs}
|
stack={false}
|
||||||
stack={false}
|
/>
|
||||||
/>
|
<Axis
|
||||||
<Axis
|
id={'timestamp'}
|
||||||
id={'timestamp'}
|
position={Position.Bottom}
|
||||||
position={Position.Bottom}
|
showOverlappingTicks={true}
|
||||||
showOverlappingTicks={true}
|
tickFormat={formatter}
|
||||||
tickFormat={formatter}
|
/>
|
||||||
/>
|
<Axis
|
||||||
<Axis
|
id={'values'}
|
||||||
id={'values'}
|
position={Position.Left}
|
||||||
position={Position.Left}
|
tickFormat={cpuFormatter}
|
||||||
tickFormat={cpuFormatter}
|
domain={getDomain(cpuTimeseries, cpuChartMetrics)}
|
||||||
domain={getDomain(cpuTimeseries, cpuChartMetrics)}
|
ticks={6}
|
||||||
ticks={6}
|
showGridLines
|
||||||
showGridLines
|
/>
|
||||||
/>
|
<Settings
|
||||||
<Settings
|
onPointerUpdate={pointerUpdate}
|
||||||
onPointerUpdate={pointerUpdate}
|
tooltip={tooltipProps}
|
||||||
tooltip={tooltipProps}
|
theme={getTimelineChartTheme(isDarkMode)}
|
||||||
theme={getTimelineChartTheme(isDarkMode)}
|
/>
|
||||||
/>
|
</Chart>
|
||||||
</Chart>
|
</EuiFlexItem>
|
||||||
</ChartContainer>
|
|
||||||
</ChartContainerWrapper>
|
|
||||||
|
|
||||||
<ChartContainerWrapper>
|
<EuiFlexItem>
|
||||||
<ChartHeader title={LOAD_CHART_TITLE} metrics={loadChartMetrics} />
|
<ChartHeader title={LOAD_CHART_TITLE} metrics={loadChartMetrics} />
|
||||||
<ChartContainer>
|
<Chart ref={loadChartRef} size={CHART_SIZE}>
|
||||||
<Chart ref={loadChartRef}>
|
<MetricExplorerSeriesChart
|
||||||
<MetricExplorerSeriesChart
|
type={MetricsExplorerChartType.line}
|
||||||
type={MetricsExplorerChartType.line}
|
metric={loadChartMetrics[0]}
|
||||||
metric={loadChartMetrics[0]}
|
id="0"
|
||||||
id="0"
|
series={load1mMetricsTs}
|
||||||
series={load1mMetricsTs}
|
stack={false}
|
||||||
stack={false}
|
/>
|
||||||
/>
|
<MetricExplorerSeriesChart
|
||||||
<MetricExplorerSeriesChart
|
type={MetricsExplorerChartType.line}
|
||||||
type={MetricsExplorerChartType.line}
|
metric={loadChartMetrics[1]}
|
||||||
metric={loadChartMetrics[1]}
|
id="0"
|
||||||
id="0"
|
series={load5mMetricsTs}
|
||||||
series={load5mMetricsTs}
|
stack={false}
|
||||||
stack={false}
|
/>
|
||||||
/>
|
<MetricExplorerSeriesChart
|
||||||
<MetricExplorerSeriesChart
|
type={MetricsExplorerChartType.line}
|
||||||
type={MetricsExplorerChartType.line}
|
metric={loadChartMetrics[2]}
|
||||||
metric={loadChartMetrics[2]}
|
id="0"
|
||||||
id="0"
|
series={load15mMetricsTs}
|
||||||
series={load15mMetricsTs}
|
stack={false}
|
||||||
stack={false}
|
/>
|
||||||
/>
|
<Axis
|
||||||
<Axis
|
id={'timestamp'}
|
||||||
id={'timestamp'}
|
position={Position.Bottom}
|
||||||
position={Position.Bottom}
|
showOverlappingTicks={true}
|
||||||
showOverlappingTicks={true}
|
tickFormat={formatter}
|
||||||
tickFormat={formatter}
|
/>
|
||||||
/>
|
<Axis
|
||||||
<Axis
|
id={'values1'}
|
||||||
id={'values1'}
|
position={Position.Left}
|
||||||
position={Position.Left}
|
tickFormat={loadFormatter}
|
||||||
tickFormat={loadFormatter}
|
domain={getDomain(loadTimeseries, loadChartMetrics)}
|
||||||
domain={getDomain(loadTimeseries, loadChartMetrics)}
|
ticks={6}
|
||||||
ticks={6}
|
showGridLines
|
||||||
showGridLines
|
/>
|
||||||
/>
|
<Settings
|
||||||
<Settings
|
onPointerUpdate={pointerUpdate}
|
||||||
onPointerUpdate={pointerUpdate}
|
tooltip={tooltipProps}
|
||||||
tooltip={tooltipProps}
|
theme={getTimelineChartTheme(isDarkMode)}
|
||||||
theme={getTimelineChartTheme(isDarkMode)}
|
/>
|
||||||
/>
|
</Chart>
|
||||||
</Chart>
|
</EuiFlexItem>
|
||||||
</ChartContainer>
|
|
||||||
</ChartContainerWrapper>
|
|
||||||
|
|
||||||
<ChartContainerWrapper>
|
<EuiFlexItem>
|
||||||
<ChartHeader title={MEMORY_CHART_TITLE} metrics={memoryChartMetrics} />
|
<ChartHeader title={MEMORY_CHART_TITLE} metrics={memoryChartMetrics} />
|
||||||
<ChartContainer>
|
<Chart ref={memoryChartRef} size={CHART_SIZE}>
|
||||||
<Chart ref={memoryChartRef}>
|
<MetricExplorerSeriesChart
|
||||||
<MetricExplorerSeriesChart
|
type={MetricsExplorerChartType.line}
|
||||||
type={MetricsExplorerChartType.line}
|
metric={memoryChartMetrics[0]}
|
||||||
metric={memoryChartMetrics[0]}
|
id="0"
|
||||||
id="0"
|
series={usedMemoryMetricsTs}
|
||||||
series={usedMemoryMetricsTs}
|
stack={false}
|
||||||
stack={false}
|
/>
|
||||||
/>
|
<MetricExplorerSeriesChart
|
||||||
<MetricExplorerSeriesChart
|
type={MetricsExplorerChartType.line}
|
||||||
type={MetricsExplorerChartType.line}
|
metric={memoryChartMetrics[1]}
|
||||||
metric={memoryChartMetrics[1]}
|
id="0"
|
||||||
id="0"
|
series={freeMemoryMetricsTs}
|
||||||
series={freeMemoryMetricsTs}
|
stack={false}
|
||||||
stack={false}
|
/>
|
||||||
/>
|
<Axis
|
||||||
<Axis
|
id={'timestamp'}
|
||||||
id={'timestamp'}
|
position={Position.Bottom}
|
||||||
position={Position.Bottom}
|
showOverlappingTicks={true}
|
||||||
showOverlappingTicks={true}
|
tickFormat={formatter}
|
||||||
tickFormat={formatter}
|
/>
|
||||||
/>
|
<Axis
|
||||||
<Axis
|
id={'values'}
|
||||||
id={'values'}
|
position={Position.Left}
|
||||||
position={Position.Left}
|
tickFormat={memoryFormatter}
|
||||||
tickFormat={memoryFormatter}
|
domain={getDomain(memoryTimeseries, memoryChartMetrics)}
|
||||||
domain={getDomain(memoryTimeseries, memoryChartMetrics)}
|
ticks={6}
|
||||||
ticks={6}
|
showGridLines
|
||||||
showGridLines
|
/>
|
||||||
/>
|
<Settings
|
||||||
<Settings
|
onPointerUpdate={pointerUpdate}
|
||||||
onPointerUpdate={pointerUpdate}
|
tooltip={tooltipProps}
|
||||||
tooltip={tooltipProps}
|
theme={getTimelineChartTheme(isDarkMode)}
|
||||||
theme={getTimelineChartTheme(isDarkMode)}
|
/>
|
||||||
/>
|
</Chart>
|
||||||
</Chart>
|
</EuiFlexItem>
|
||||||
</ChartContainer>
|
|
||||||
</ChartContainerWrapper>
|
|
||||||
|
|
||||||
<ChartContainerWrapper>
|
<EuiFlexItem>
|
||||||
<ChartHeader title={NETWORK_CHART_TITLE} metrics={networkChartMetrics} />
|
<ChartHeader title={NETWORK_CHART_TITLE} metrics={networkChartMetrics} />
|
||||||
<ChartContainer>
|
<Chart ref={networkChartRef} size={CHART_SIZE}>
|
||||||
<Chart ref={networkChartRef}>
|
<MetricExplorerSeriesChart
|
||||||
<MetricExplorerSeriesChart
|
type={MetricsExplorerChartType.line}
|
||||||
type={MetricsExplorerChartType.line}
|
metric={networkChartMetrics[0]}
|
||||||
metric={networkChartMetrics[0]}
|
id="0"
|
||||||
id="0"
|
series={rxMetricsTs}
|
||||||
series={rxMetricsTs}
|
stack={false}
|
||||||
stack={false}
|
/>
|
||||||
/>
|
<MetricExplorerSeriesChart
|
||||||
<MetricExplorerSeriesChart
|
type={MetricsExplorerChartType.line}
|
||||||
type={MetricsExplorerChartType.line}
|
metric={networkChartMetrics[1]}
|
||||||
metric={networkChartMetrics[1]}
|
id="0"
|
||||||
id="0"
|
series={txMetricsTs}
|
||||||
series={txMetricsTs}
|
stack={false}
|
||||||
stack={false}
|
/>
|
||||||
/>
|
<Axis
|
||||||
<Axis
|
id={'timestamp'}
|
||||||
id={'timestamp'}
|
position={Position.Bottom}
|
||||||
position={Position.Bottom}
|
showOverlappingTicks={true}
|
||||||
showOverlappingTicks={true}
|
tickFormat={formatter}
|
||||||
tickFormat={formatter}
|
/>
|
||||||
/>
|
<Axis
|
||||||
<Axis
|
id={'values'}
|
||||||
id={'values'}
|
position={Position.Left}
|
||||||
position={Position.Left}
|
tickFormat={networkFormatter}
|
||||||
tickFormat={networkFormatter}
|
domain={getDomain(networkTimeseries, networkChartMetrics)}
|
||||||
domain={getDomain(networkTimeseries, networkChartMetrics)}
|
ticks={6}
|
||||||
ticks={6}
|
showGridLines
|
||||||
showGridLines
|
/>
|
||||||
/>
|
<Settings
|
||||||
<Settings
|
onPointerUpdate={pointerUpdate}
|
||||||
onPointerUpdate={pointerUpdate}
|
tooltip={tooltipProps}
|
||||||
tooltip={tooltipProps}
|
theme={getTimelineChartTheme(isDarkMode)}
|
||||||
theme={getTimelineChartTheme(isDarkMode)}
|
/>
|
||||||
/>
|
</Chart>
|
||||||
</Chart>
|
</EuiFlexItem>
|
||||||
</ChartContainer>
|
</EuiFlexGrid>
|
||||||
</ChartContainerWrapper>
|
|
||||||
</ChartsContainer>
|
|
||||||
</TabContent>
|
</TabContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ChartsContainer = euiStyled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ChartContainerWrapper = euiStyled.div`
|
|
||||||
width: 50%
|
|
||||||
`;
|
|
||||||
|
|
||||||
const TimepickerWrapper = euiStyled.div`
|
|
||||||
padding: ${(props) => props.theme.eui.paddingSizes.m};
|
|
||||||
width: 50%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ChartContainer: React.FC = ({ children }) => (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
height: 150,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const LoadingPlaceholder = () => {
|
const LoadingPlaceholder = () => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '200px',
|
||||||
padding: '16px',
|
padding: '16px',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
|
@ -15,7 +15,7 @@ interface Props {
|
||||||
|
|
||||||
export const TimeDropdown = (props: Props) => (
|
export const TimeDropdown = (props: Props) => (
|
||||||
<EuiSelect
|
<EuiSelect
|
||||||
compressed
|
fullWidth={true}
|
||||||
options={[
|
options={[
|
||||||
{
|
{
|
||||||
text: i18n.translate('xpack.infra.nodeDetails.metrics.last15Minutes', {
|
text: i18n.translate('xpack.infra.nodeDetails.metrics.last15Minutes', {
|
||||||
|
|
|
@ -102,7 +102,9 @@ const TabComponent = (props: TabProps) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const TableWrapper = euiStyled.div`
|
const TableWrapper = euiStyled.div`
|
||||||
margin-bottom: 20px
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 16px
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const LoadingPlaceholder = () => {
|
const LoadingPlaceholder = () => {
|
||||||
|
|
|
@ -4,18 +4,20 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EuiText } from '@elastic/eui';
|
import {
|
||||||
import { EuiToolTip } from '@elastic/eui';
|
EuiText,
|
||||||
import { EuiButtonIcon } from '@elastic/eui';
|
EuiToolTip,
|
||||||
import { EuiFlexGroup } from '@elastic/eui';
|
EuiButtonIcon,
|
||||||
import { EuiFlexItem } from '@elastic/eui';
|
EuiFlexGroup,
|
||||||
import { EuiLink } from '@elastic/eui';
|
EuiFlexItem,
|
||||||
import { EuiBasicTable } from '@elastic/eui';
|
EuiLink,
|
||||||
|
EuiBasicTable,
|
||||||
|
EuiSpacer,
|
||||||
|
} from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { first } from 'lodash';
|
import { first } from 'lodash';
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { euiStyled } from '../../../../../../../../../observability/public';
|
|
||||||
|
|
||||||
interface Row {
|
interface Row {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -51,15 +53,19 @@ export const Table = (props: Props) => {
|
||||||
render: (_name: string, item: Row) => {
|
render: (_name: string, item: Row) => {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
<EuiToolTip
|
<EuiFlexGroup gutterSize={'xs'} alignItems={'center'} responsive={false}>
|
||||||
content={i18n.translate('xpack.infra.nodeDetails.tabs.metadata.setFilterTooltip', {
|
<EuiFlexItem grow={false}>
|
||||||
defaultMessage: 'View event with filter',
|
<EuiToolTip
|
||||||
})}
|
content={i18n.translate(
|
||||||
>
|
'xpack.infra.nodeDetails.tabs.metadata.setFilterTooltip',
|
||||||
<EuiFlexGroup gutterSize={'xs'}>
|
{
|
||||||
<EuiFlexItem grow={false}>
|
defaultMessage: 'View event with filter',
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
<EuiButtonIcon
|
<EuiButtonIcon
|
||||||
color="text"
|
color="subdued"
|
||||||
|
size="s"
|
||||||
iconType="filter"
|
iconType="filter"
|
||||||
aria-label={i18n.translate(
|
aria-label={i18n.translate(
|
||||||
'xpack.infra.nodeDetails.tabs.metadata.filterAriaLabel',
|
'xpack.infra.nodeDetails.tabs.metadata.filterAriaLabel',
|
||||||
|
@ -69,13 +75,13 @@ export const Table = (props: Props) => {
|
||||||
)}
|
)}
|
||||||
onClick={() => onClick(item)}
|
onClick={() => onClick(item)}
|
||||||
/>
|
/>
|
||||||
</EuiFlexItem>
|
</EuiToolTip>
|
||||||
<EuiFlexItem>
|
</EuiFlexItem>
|
||||||
{!Array.isArray(item.value) && item.value}
|
<EuiFlexItem>
|
||||||
{Array.isArray(item.value) && <ArrayValue values={item.value} />}
|
{!Array.isArray(item.value) && item.value}
|
||||||
</EuiFlexItem>
|
{Array.isArray(item.value) && <ArrayValue values={item.value} />}
|
||||||
</EuiFlexGroup>
|
</EuiFlexItem>
|
||||||
</EuiToolTip>
|
</EuiFlexGroup>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -86,20 +92,21 @@ export const Table = (props: Props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TitleWrapper>
|
<EuiText>
|
||||||
<EuiText>
|
<h4>{title}</h4>
|
||||||
<h3>{title}</h3>
|
</EuiText>
|
||||||
</EuiText>
|
<EuiSpacer size={'s'} />
|
||||||
</TitleWrapper>
|
<TableWithoutHeader
|
||||||
<TableWithoutHeader tableLayout="fixed" compressed columns={columns} items={rows} />
|
tableLayout={'fixed'}
|
||||||
|
compressed
|
||||||
|
responsive={false}
|
||||||
|
columns={columns}
|
||||||
|
items={rows}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TitleWrapper = euiStyled.div`
|
|
||||||
margin-bottom: 10px
|
|
||||||
`;
|
|
||||||
|
|
||||||
class TableWithoutHeader extends EuiBasicTable {
|
class TableWithoutHeader extends EuiBasicTable {
|
||||||
renderTableHead() {
|
renderTableHead() {
|
||||||
return <></>;
|
return <></>;
|
||||||
|
@ -123,7 +130,7 @@ const ArrayValue = (props: MoreProps) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!isExpanded && (
|
{!isExpanded && (
|
||||||
<EuiFlexGroup gutterSize="none">
|
<EuiFlexGroup gutterSize={'xs'} responsive={false} alignItems={'baseline'} wrap={true}>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
{first(values)}
|
{first(values)}
|
||||||
{' ... '}
|
{' ... '}
|
||||||
|
@ -148,7 +155,7 @@ const ArrayValue = (props: MoreProps) => {
|
||||||
))}
|
))}
|
||||||
<EuiLink onClick={collapse}>
|
<EuiLink onClick={collapse}>
|
||||||
{i18n.translate('xpack.infra.nodeDetails.tabs.metadata.seeLess', {
|
{i18n.translate('xpack.infra.nodeDetails.tabs.metadata.seeLess', {
|
||||||
defaultMessage: 'See less',
|
defaultMessage: 'Show less',
|
||||||
})}
|
})}
|
||||||
</EuiLink>
|
</EuiLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,11 +17,9 @@ export interface TabProps {
|
||||||
|
|
||||||
export const OVERLAY_Y_START = 266;
|
export const OVERLAY_Y_START = 266;
|
||||||
export const OVERLAY_BOTTOM_MARGIN = 16;
|
export const OVERLAY_BOTTOM_MARGIN = 16;
|
||||||
export const OVERLAY_HEADER_SIZE = 96;
|
|
||||||
const contentHeightOffset = OVERLAY_Y_START + OVERLAY_BOTTOM_MARGIN + OVERLAY_HEADER_SIZE;
|
|
||||||
export const TabContent = euiStyled.div`
|
export const TabContent = euiStyled.div`
|
||||||
padding: ${(props) => props.theme.eui.paddingSizes.s};
|
padding: ${(props) => props.theme.eui.paddingSizes.m};
|
||||||
height: calc(100vh - ${contentHeightOffset}px);
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
`;
|
`;
|
||||||
|
|
Loading…
Reference in a new issue