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:
Henry Harding 2020-12-04 15:05:13 -05:00 committed by GitHub
parent c85f2545da
commit c6ef1ae30b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 290 additions and 309 deletions

View file

@ -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',
};

View file

@ -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', {

View file

@ -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};
`;

View file

@ -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',

View file

@ -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', {

View file

@ -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 = () => {

View file

@ -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>

View file

@ -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;
`; `;