[Uptime]Fix/issue 40584 section headline should be inside panel (#43468) (#44879)

* move title inside panel

* fix monitor list title

* update title in each panel and paddings

* update unit tests snapshots

* make section titles symmeteric

* update snapshots

* Add chart wrapper to improve UX experience and padding arounds charts

* removed ping list count

* removed unnecessary spacer

* update test snaps
This commit is contained in:
Shahzad 2019-09-11 00:00:42 +05:00 committed by GitHub
parent bb2a156b21
commit e981b55d9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 275 additions and 216 deletions

View file

@ -3,14 +3,9 @@
exports[`MonitorCharts component renders the component without errors 1`] = ` exports[`MonitorCharts component renders the component without errors 1`] = `
<Fragment> <Fragment>
<EuiFlexGroup> <EuiFlexGroup>
<EuiFlexItem <EuiFlexItem>
style={
Object {
"height": 400,
}
}
>
<DurationChart <DurationChart
loading={false}
locationDurationLines={ locationDurationLines={
Array [ Array [
Object { Object {
@ -73,6 +68,7 @@ exports[`MonitorCharts component renders the component without errors 1`] = `
absoluteEndDate={1322903730000} absoluteEndDate={1322903730000}
absoluteStartDate={1322903730000} absoluteStartDate={1322903730000}
dangerColor="#bd271e" dangerColor="#bd271e"
height="400px"
successColor="#017d73" successColor="#017d73"
variables={ variables={
Object { Object {

View file

@ -2,41 +2,25 @@
exports[`PingList component renders sorted list without errors 1`] = ` exports[`PingList component renders sorted list without errors 1`] = `
<Fragment> <Fragment>
<EuiFlexGroup
alignItems="center"
gutterSize="s"
responsive={false}
>
<EuiFlexItem
grow={false}
>
<EuiTitle
size="xs"
>
<h4>
<FormattedMessage
defaultMessage="History"
id="xpack.uptime.pingList.checkHistoryTitle"
values={Object {}}
/>
</h4>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem
grow={false}
>
<EuiBadge
color="hollow"
>
9231
</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
<EuiPanel <EuiPanel
grow={true} grow={true}
hasShadow={false} hasShadow={false}
paddingSize="s" paddingSize="m"
> >
<EuiTitle
size="xs"
>
<h4>
<FormattedMessage
defaultMessage="History"
id="xpack.uptime.pingList.checkHistoryTitle"
values={Object {}}
/>
</h4>
</EuiTitle>
<EuiSpacer
size="s"
/>
<EuiFlexGroup <EuiFlexGroup
justifyContent="spaceBetween" justifyContent="spaceBetween"
> >

View file

@ -2,30 +2,31 @@
exports[`Snapshot component renders without errors 1`] = ` exports[`Snapshot component renders without errors 1`] = `
<Fragment> <Fragment>
<EuiTitle
size="xs"
>
<h5>
<FormattedMessage
defaultMessage="Current status"
id="xpack.uptime.snapshot.endpointStatusTitle"
values={Object {}}
/>
</h5>
</EuiTitle>
<EuiPanel <EuiPanel
grow={true} grow={true}
hasShadow={false} hasShadow={false}
paddingSize="s" paddingSize="m"
> >
<EuiTitle
size="xs"
>
<h5>
<FormattedMessage
defaultMessage="Current status"
id="xpack.uptime.snapshot.endpointStatusTitle"
values={Object {}}
/>
</h5>
</EuiTitle>
<EuiFlexGroup <EuiFlexGroup
direction="column" direction="column"
gutterSize="m"
> >
<EuiFlexItem <EuiFlexItem
grow={false} grow={false}
> >
<EuiSpacer <EuiSpacer
size="s" size="xs"
/> />
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem>

View file

@ -0,0 +1,42 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { FC, Fragment } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiLoadingChart } from '@elastic/eui';
interface Props {
height?: string;
loading?: boolean;
}
export const ChartWrapper: FC<Props> = ({ loading = false, height = '100%', children }) => {
const opacity = loading === true ? 0.3 : 1;
return (
<Fragment>
<div
style={{
height,
opacity,
transition: 'opacity 0.2s',
}}
>
{children}
</div>
{loading === true && (
<EuiFlexGroup
justifyContent="spaceAround"
alignItems="center"
style={{ height, marginTop: `-${height}` }}
>
<EuiFlexItem grow={false}>
<EuiLoadingChart size="xl" />
</EuiFlexItem>
</EuiFlexGroup>
)}
</Fragment>
);
};

View file

@ -0,0 +1,6 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { ChartWrapper } from './chart_wrapper';

View file

@ -27,6 +27,7 @@ import {
import { LocationDurationLine } from '../../../../common/graphql/types'; import { LocationDurationLine } from '../../../../common/graphql/types';
import { UptimeSettingsContext } from '../../../contexts'; import { UptimeSettingsContext } from '../../../contexts';
import { getColorsMap } from './get_colors_map'; import { getColorsMap } from './get_colors_map';
import { ChartWrapper } from './chart_wrapper';
interface DurationChartProps { interface DurationChartProps {
/** /**
@ -42,6 +43,11 @@ interface DurationChartProps {
* The color to be used for the range duration series. * The color to be used for the range duration series.
*/ */
rangeColor: string; rangeColor: string;
/**
* To represent the loading spinner on chart
*/
loading: boolean;
} }
/** /**
@ -54,6 +60,7 @@ export const DurationChart = ({
locationDurationLines, locationDurationLines,
meanColor, meanColor,
rangeColor, rangeColor,
loading,
}: DurationChartProps) => { }: DurationChartProps) => {
const { absoluteStartDate, absoluteEndDate } = useContext(UptimeSettingsContext); const { absoluteStartDate, absoluteEndDate } = useContext(UptimeSettingsContext);
// this id is used for the line chart representing the average duration length // this id is used for the line chart representing the average duration length
@ -80,42 +87,44 @@ export const DurationChart = ({
return ( return (
<React.Fragment> <React.Fragment>
<EuiTitle size="xs"> <EuiPanel paddingSize="m">
<h4> <EuiTitle size="xs">
<FormattedMessage <h4>
id="xpack.uptime.monitorCharts.monitorDuration.titleLabel" <FormattedMessage
defaultMessage="Monitor duration" id="xpack.uptime.monitorCharts.monitorDuration.titleLabel"
description="The 'ms' is an abbreviation for milliseconds." defaultMessage="Monitor duration"
/> description="The 'ms' is an abbreviation for milliseconds."
</h4> />
</EuiTitle> </h4>
<EuiPanel style={{ height: '170px' }}> </EuiTitle>
<Chart> <ChartWrapper height="400px" loading={loading}>
<Settings <Chart>
xDomain={{ min: absoluteStartDate, max: absoluteEndDate }} <Settings
showLegend={true} xDomain={{ min: absoluteStartDate, max: absoluteEndDate }}
legendPosition={Position.Bottom} showLegend={true}
/> legendPosition={Position.Bottom}
<Axis />
id={getAxisId('bottom')} <Axis
position={Position.Bottom} id={getAxisId('bottom')}
showOverlappingTicks={true} position={Position.Bottom}
tickFormat={timeFormatter(getChartDateLabel(absoluteStartDate, absoluteEndDate))} showOverlappingTicks={true}
title={i18n.translate('xpack.uptime.monitorCharts.durationChart.bottomAxis.title', { tickFormat={timeFormatter(getChartDateLabel(absoluteStartDate, absoluteEndDate))}
defaultMessage: 'Timestamp', title={i18n.translate('xpack.uptime.monitorCharts.durationChart.bottomAxis.title', {
})} defaultMessage: 'Timestamp',
/> })}
<Axis />
domain={{ min: 0 }} <Axis
id={getAxisId('left')} domain={{ min: 0 }}
position={Position.Left} id={getAxisId('left')}
tickFormat={d => Number(d).toFixed(0)} position={Position.Left}
title={i18n.translate('xpack.uptime.monitorCharts.durationChart.leftAxis.title', { tickFormat={d => Number(d).toFixed(0)}
defaultMessage: 'Duration ms', title={i18n.translate('xpack.uptime.monitorCharts.durationChart.leftAxis.title', {
})} defaultMessage: 'Duration ms',
/> })}
{lineSeries} />
</Chart> {lineSeries}
</Chart>
</ChartWrapper>
</EuiPanel> </EuiPanel>
</React.Fragment> </React.Fragment>
); );

View file

@ -24,6 +24,7 @@ import { getColorsMap } from './get_colors_map';
import { getChartDateLabel } from '../../../lib/helper'; import { getChartDateLabel } from '../../../lib/helper';
import { withUptimeGraphQL, UptimeGraphQLQueryProps } from '../../higher_order'; import { withUptimeGraphQL, UptimeGraphQLQueryProps } from '../../higher_order';
import { snapshotHistogramQuery } from '../../../queries/snapshot_histogram_query'; import { snapshotHistogramQuery } from '../../../queries/snapshot_histogram_query';
import { ChartWrapper } from './chart_wrapper';
export interface SnapshotHistogramProps { export interface SnapshotHistogramProps {
/** /**
@ -42,6 +43,11 @@ export interface SnapshotHistogramProps {
* The color value that is used to represent down checks. * The color value that is used to represent down checks.
*/ */
dangerColor: string; dangerColor: string;
/**
* Height is needed, since by defauly charts takes height of 100%
*/
height?: string;
} }
interface SnapshotHistogramQueryResult { interface SnapshotHistogramQueryResult {
@ -56,6 +62,8 @@ export const SnapshotHistogramComponent = ({
dangerColor, dangerColor,
successColor, successColor,
data, data,
loading = false,
height,
}: Props) => { }: Props) => {
if (!data || !data.histogram) if (!data || !data.histogram)
/** /**
@ -108,68 +116,73 @@ export const SnapshotHistogramComponent = ({
const upSpecId = getSpecId(upMonitorsId); const upSpecId = getSpecId(upMonitorsId);
return ( return (
<Fragment> <Fragment>
<EuiTitle size="xs"> <EuiPanel paddingSize="m">
<h5> <EuiTitle size="xs">
<FormattedMessage <h5>
id="xpack.uptime.snapshot.pingsOverTimeTitle" <FormattedMessage
defaultMessage="Pings over time" id="xpack.uptime.snapshot.pingsOverTimeTitle"
/> defaultMessage="Pings over time"
</h5> />
</EuiTitle> </h5>
<EuiPanel paddingSize="s" style={{ height: 170 }}> </EuiTitle>
<Chart> <ChartWrapper height={height} loading={loading}>
<Settings xDomain={{ min: absoluteStartDate, max: absoluteEndDate }} showLegend={false} /> <Chart>
<Axis <Settings
id={getAxisId( xDomain={{ min: absoluteStartDate, max: absoluteEndDate }}
i18n.translate('xpack.uptime.snapshotHistogram.xAxisId', { showLegend={false}
defaultMessage: 'Snapshot X Axis', />
}) <Axis
)} id={getAxisId(
position={Position.Bottom} i18n.translate('xpack.uptime.snapshotHistogram.xAxisId', {
showOverlappingTicks={false} defaultMessage: 'Snapshot X Axis',
tickFormat={timeFormatter(getChartDateLabel(absoluteStartDate, absoluteEndDate))} })
/> )}
<Axis position={Position.Bottom}
id={getAxisId( showOverlappingTicks={false}
i18n.translate('xpack.uptime.snapshotHistogram.yAxisId', { tickFormat={timeFormatter(getChartDateLabel(absoluteStartDate, absoluteEndDate))}
defaultMessage: 'Snapshot Y Axis', />
}) <Axis
)} id={getAxisId(
position={Position.Left} i18n.translate('xpack.uptime.snapshotHistogram.yAxisId', {
showOverlappingTicks={true} defaultMessage: 'Snapshot Y Axis',
title={i18n.translate('xpack.uptime.snapshotHistogram.yAxis.title', { })
defaultMessage: 'Pings', )}
description: position={Position.Left}
'The label on the y-axis of a chart that displays the number of times Heartbeat has pinged a set of services/websites.', showOverlappingTicks={true}
})} title={i18n.translate('xpack.uptime.snapshotHistogram.yAxis.title', {
/> defaultMessage: 'Pings',
<BarSeries description:
customSeriesColors={getColorsMap(successColor, upSpecId)} 'The label on the y-axis of a chart that displays the number of times Heartbeat has pinged a set of services/websites.',
data={histogram.map(({ x, upCount }) => [x, upCount || 0])} })}
id={upSpecId} />
name={upMonitorsId} <BarSeries
stackAccessors={[0]} customSeriesColors={getColorsMap(successColor, upSpecId)}
timeZone="local" data={histogram.map(({ x, upCount }) => [x, upCount || 0])}
xAccessor={0} id={upSpecId}
xScaleType={ScaleType.Time} name={upMonitorsId}
yAccessors={[1]} stackAccessors={[0]}
yScaleType={ScaleType.Linear} timeZone="local"
/> xAccessor={0}
<BarSeries xScaleType={ScaleType.Time}
customSeriesColors={getColorsMap(dangerColor, downSpecId)} yAccessors={[1]}
data={histogram.map(({ x, downCount }) => [x, downCount || 0])} yScaleType={ScaleType.Linear}
id={downSpecId} />
name={i18n.translate('xpack.uptime.snapshotHistogram.series.downLabel', { <BarSeries
defaultMessage: 'Down', customSeriesColors={getColorsMap(dangerColor, downSpecId)}
})} data={histogram.map(({ x, downCount }) => [x, downCount || 0])}
stackAccessors={[0]} id={downSpecId}
timeZone="local" name={i18n.translate('xpack.uptime.snapshotHistogram.series.downLabel', {
xAccessor={0} defaultMessage: 'Down',
xScaleType={ScaleType.Time} })}
yAccessors={[1]} stackAccessors={[0]}
yScaleType={ScaleType.Linear} timeZone="local"
/> xAccessor={0}
</Chart> xScaleType={ScaleType.Time}
yAccessors={[1]}
yScaleType={ScaleType.Linear}
/>
</Chart>
</ChartWrapper>
</EuiPanel> </EuiPanel>
</Fragment> </Fragment>
); );

View file

@ -32,8 +32,15 @@ interface MonitorChartsProps {
type Props = MonitorChartsProps & UptimeGraphQLQueryProps<MonitorChartsQueryResult>; type Props = MonitorChartsProps & UptimeGraphQLQueryProps<MonitorChartsQueryResult>;
export const MonitorChartsComponent = (props: Props) => { export const MonitorChartsComponent = ({
const { data, mean, range, monitorId, dateRangeStart, dateRangeEnd } = props; data,
mean,
range,
monitorId,
dateRangeStart,
dateRangeEnd,
loading,
}: Props) => {
if (data && data.monitorChartsData) { if (data && data.monitorChartsData) {
const { const {
monitorChartsData: { locationDurationLines }, monitorChartsData: { locationDurationLines },
@ -47,11 +54,12 @@ export const MonitorChartsComponent = (props: Props) => {
return ( return (
<Fragment> <Fragment>
<EuiFlexGroup> <EuiFlexGroup>
<EuiFlexItem style={{ height: 400 }}> <EuiFlexItem>
<DurationChart <DurationChart
locationDurationLines={locationDurationLines} locationDurationLines={locationDurationLines}
meanColor={mean} meanColor={mean}
rangeColor={range} rangeColor={range}
loading={loading}
/> />
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem>
@ -61,6 +69,7 @@ export const MonitorChartsComponent = (props: Props) => {
successColor={colors.success} successColor={colors.success}
dangerColor={colors.danger} dangerColor={colors.danger}
variables={{ dateRangeStart, dateRangeEnd, monitorId }} variables={{ dateRangeStart, dateRangeEnd, monitorId }}
height="400px"
/> />
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>

View file

@ -2,22 +2,25 @@
exports[`MonitorList component renders a no items message when no data is provided 1`] = ` exports[`MonitorList component renders a no items message when no data is provided 1`] = `
<Fragment> <Fragment>
<EuiTitle
size="xs"
>
<h5>
<FormattedMessage
defaultMessage="Monitor status"
id="xpack.uptime.monitorList.monitoringStatusTitle"
values={Object {}}
/>
</h5>
</EuiTitle>
<EuiPanel <EuiPanel
grow={true} grow={true}
hasShadow={false} hasShadow={false}
paddingSize="s" paddingSize="m"
> >
<EuiTitle
size="xs"
>
<h5>
<FormattedMessage
defaultMessage="Monitor status"
id="xpack.uptime.monitorList.monitoringStatusTitle"
values={Object {}}
/>
</h5>
</EuiTitle>
<EuiSpacer
size="s"
/>
<EuiBasicTable <EuiBasicTable
columns={ columns={
Array [ Array [
@ -76,22 +79,25 @@ exports[`MonitorList component renders a no items message when no data is provid
exports[`MonitorList component renders the monitor list 1`] = ` exports[`MonitorList component renders the monitor list 1`] = `
<Fragment> <Fragment>
<EuiTitle
size="xs"
>
<h5>
<FormattedMessage
defaultMessage="Monitor status"
id="xpack.uptime.monitorList.monitoringStatusTitle"
values={Object {}}
/>
</h5>
</EuiTitle>
<EuiPanel <EuiPanel
grow={true} grow={true}
hasShadow={false} hasShadow={false}
paddingSize="s" paddingSize="m"
> >
<EuiTitle
size="xs"
>
<h5>
<FormattedMessage
defaultMessage="Monitor status"
id="xpack.uptime.monitorList.monitoringStatusTitle"
values={Object {}}
/>
</h5>
</EuiTitle>
<EuiSpacer
size="s"
/>
<EuiBasicTable <EuiBasicTable
columns={ columns={
Array [ Array [

View file

@ -5,6 +5,7 @@
*/ */
import { EuiBasicTable, EuiPanel, EuiTitle, EuiButtonIcon, EuiIcon, EuiLink } from '@elastic/eui'; import { EuiBasicTable, EuiPanel, EuiTitle, EuiButtonIcon, EuiIcon, EuiLink } from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react'; import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { get } from 'lodash'; import { get } from 'lodash';
@ -91,15 +92,16 @@ export const MonitorListComponent = (props: Props) => {
return ( return (
<Fragment> <Fragment>
<EuiTitle size="xs"> <EuiPanel>
<h5> <EuiTitle size="xs">
<FormattedMessage <h5>
id="xpack.uptime.monitorList.monitoringStatusTitle" <FormattedMessage
defaultMessage="Monitor status" id="xpack.uptime.monitorList.monitoringStatusTitle"
/> defaultMessage="Monitor status"
</h5> />
</EuiTitle> </h5>
<EuiPanel paddingSize="s"> </EuiTitle>
<EuiSpacer size="s" />
<EuiBasicTable <EuiBasicTable
error={errors ? formatUptimeGraphQLErrorList(errors) : errors} error={errors ? formatUptimeGraphQLErrorList(errors) : errors}
loading={loading} loading={loading}

View file

@ -182,10 +182,8 @@ export const PingListComponent = ({
onUpdateApp(); onUpdateApp();
}, [selectedOption]); }, [selectedOption]);
let pings: Ping[] = []; let pings: Ping[] = [];
let total: number = 0;
if (data && data.allPings && data.allPings.pings) { if (data && data.allPings && data.allPings.pings) {
pings = data.allPings.pings; pings = data.allPings.pings;
total = data.allPings.total;
const hasStatus: boolean = pings.reduce( const hasStatus: boolean = pings.reduce(
(hasHttpStatus: boolean, currentPing: Ping) => (hasHttpStatus: boolean, currentPing: Ping) =>
hasHttpStatus || !!get(currentPing, 'http.response.status_code'), hasHttpStatus || !!get(currentPing, 'http.response.status_code'),
@ -233,24 +231,16 @@ export const PingListComponent = ({
return ( return (
<Fragment> <Fragment>
<EuiFlexGroup responsive={false} gutterSize="s" alignItems="center"> <EuiPanel>
<EuiFlexItem grow={false}> <EuiTitle size="xs">
<EuiTitle size="xs"> <h4>
<h4> <FormattedMessage
<FormattedMessage id="xpack.uptime.pingList.checkHistoryTitle"
id="xpack.uptime.pingList.checkHistoryTitle" defaultMessage="History"
defaultMessage="History" />
/> </h4>
</h4> </EuiTitle>
</EuiTitle> <EuiSpacer size="s" />
</EuiFlexItem>
{!!total && (
<EuiFlexItem grow={false}>
<EuiBadge color="hollow">{total}</EuiBadge>
</EuiFlexItem>
)}
</EuiFlexGroup>
<EuiPanel paddingSize="s">
<EuiFlexGroup justifyContent="spaceBetween"> <EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiFlexGroup> <EuiFlexGroup>

View file

@ -26,18 +26,18 @@ interface SnapshotQueryResult {
export const SnapshotComponent = ({ data }: UptimeGraphQLQueryProps<SnapshotQueryResult>) => export const SnapshotComponent = ({ data }: UptimeGraphQLQueryProps<SnapshotQueryResult>) =>
data && data.snapshot ? ( data && data.snapshot ? (
<React.Fragment> <React.Fragment>
<EuiTitle size="xs"> <EuiPanel>
<h5> <EuiTitle size="xs">
<FormattedMessage <h5>
id="xpack.uptime.snapshot.endpointStatusTitle" <FormattedMessage
defaultMessage="Current status" id="xpack.uptime.snapshot.endpointStatusTitle"
/> defaultMessage="Current status"
</h5> />
</EuiTitle> </h5>
<EuiPanel paddingSize="s"> </EuiTitle>
<EuiFlexGroup direction="column"> <EuiFlexGroup direction="column" gutterSize="m">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiSpacer size="s" /> <EuiSpacer size="xs" />
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem>
<EuiFlexGroup justifyContent="spaceEvenly" gutterSize="s"> <EuiFlexGroup justifyContent="spaceEvenly" gutterSize="s">

View file

@ -129,6 +129,7 @@ export const OverviewPage = ({ basePath, logOverviewPageLoad, setBreadcrumbs }:
successColor={colors.success} successColor={colors.success}
dangerColor={colors.danger} dangerColor={colors.danger}
variables={sharedProps} variables={sharedProps}
height="120px"
/> />
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>