[Synthetics] Errors page loading and empty state (#149154)

Fixes https://github.com/elastic/kibana/issues/145374
Fixes https://github.com/elastic/kibana/issues/145370
This commit is contained in:
Shahzad 2023-01-19 12:54:54 +01:00 committed by GitHub
parent 1af7e3626b
commit 357900f97e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 147 additions and 72 deletions

View file

@ -18,16 +18,13 @@ import {
formatTestDuration,
formatTestRunAt,
} from '../../../utils/monitor_test_result/test_time_formats';
import { useMonitorErrors } from '../hooks/use_monitor_errors';
export const ErrorsList = () => {
export const ErrorsList = ({ errorStates, loading }: { errorStates: Ping[]; loading: boolean }) => {
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [sortField, setSortField] = useState('@timestamp');
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc');
const { errorStates, loading } = useMonitorErrors();
const { monitorId } = useParams<{ monitorId: string }>();
const items = errorStates.slice(pageIndex * pageSize, pageIndex * pageSize + pageSize);

View file

@ -0,0 +1,85 @@
/*
* 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 React from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { Ping } from '../../../../../../common/runtime_types';
import { PanelWithTitle } from '../../common/components/panel_with_title';
import { MonitorErrorsCount } from '../monitor_summary/monitor_errors_count';
import { FailedTestsCount } from './failed_tests_count';
import { MonitorFailedTests } from './failed_tests';
import { ErrorsList } from './errors_list';
import { useAbsoluteDate, useGetUrlParams } from '../../../hooks';
import { useMonitorQueryId } from '../hooks/use_monitor_query_id';
export const ErrorsTabContent = ({
errorStates,
loading,
}: {
errorStates: Ping[];
loading: boolean;
}) => {
const { dateRangeStart, dateRangeEnd } = useGetUrlParams();
const time = useAbsoluteDate({ from: dateRangeStart, to: dateRangeEnd });
const monitorId = useMonitorQueryId();
return (
<>
<EuiFlexGroup gutterSize="m">
<EuiFlexItem grow={1}>
<PanelWithTitle title={OVERVIEW_LABEL}>
<EuiFlexGroup>
<EuiFlexItem>
{monitorId && (
<MonitorErrorsCount from={time.from} to={time.to} monitorId={[monitorId]} />
)}
</EuiFlexItem>
<EuiFlexItem>
<FailedTestsCount from={time.from} to={time.to} />
</EuiFlexItem>
</EuiFlexGroup>
</PanelWithTitle>
</EuiFlexItem>
<EuiFlexItem grow={3}>
<PanelWithTitle title={FAILED_TESTS_LABEL}>
<MonitorFailedTests time={time} />
</PanelWithTitle>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
<EuiFlexGroup gutterSize="m">
<EuiFlexItem grow={2}>
<PanelWithTitle title={ERRORS_LABEL}>
<ErrorsList errorStates={errorStates} loading={loading} />
</PanelWithTitle>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<PanelWithTitle title={FAILED_TESTS_BY_STEPS_LABEL} />
</EuiFlexItem>
</EuiFlexGroup>
</>
);
};
const ERRORS_LABEL = i18n.translate('xpack.synthetics.errors.label', {
defaultMessage: 'Errors',
});
const OVERVIEW_LABEL = i18n.translate('xpack.synthetics.errors.overview', {
defaultMessage: 'Overview',
});
const FAILED_TESTS_LABEL = i18n.translate('xpack.synthetics.errors.failedTests', {
defaultMessage: 'Failed tests',
});
const FAILED_TESTS_BY_STEPS_LABEL = i18n.translate('xpack.synthetics.errors.failedTests.byStep', {
defaultMessage: 'Failed tests by step',
});

View file

@ -7,97 +7,90 @@
import {
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiIcon,
EuiLoadingSpinner,
EuiSpacer,
EuiText,
EuiTitle,
useEuiTheme,
} from '@elastic/eui';
import React from 'react';
import { i18n } from '@kbn/i18n';
import { useMonitorQueryId } from '../hooks/use_monitor_query_id';
import { FailedTestsCount } from './failed_tests_count';
import { useAbsoluteDate, useGetUrlParams } from '../../../hooks';
import { useMonitorErrors } from '../hooks/use_monitor_errors';
import { SyntheticsDatePicker } from '../../common/date_picker/synthetics_date_picker';
import { MonitorErrorsCount } from '../monitor_summary/monitor_errors_count';
import { ErrorsList } from './errors_list';
import { MonitorFailedTests } from './failed_tests';
import { ErrorsTabContent } from './errors_tab_content';
export const MonitorErrors = () => {
const { euiTheme } = useEuiTheme();
const { errorStates, loading } = useMonitorErrors();
const { dateRangeStart, dateRangeEnd } = useGetUrlParams();
const initialLoading = loading && errorStates.length === 0;
const time = useAbsoluteDate({ from: dateRangeStart, to: dateRangeEnd });
const monitorId = useMonitorQueryId();
const emptyState = !loading && errorStates.length === 0;
return (
<>
<SyntheticsDatePicker fullWidth={true} />
<EuiSpacer size="m" />
<EuiFlexGroup gutterSize="m">
<EuiFlexItem grow={1}>
<EuiPanel hasBorder>
<EuiTitle size="xs">
<h3 css={{ margin: euiTheme.size.s, marginBottom: 0 }}>{OVERVIEW_LABEL}</h3>
</EuiTitle>
<EuiFlexGroup>
<EuiFlexItem>
{monitorId && (
<MonitorErrorsCount from={time.from} to={time.to} monitorId={[monitorId]} />
)}
</EuiFlexItem>
<EuiFlexItem>
<FailedTestsCount from={time.from} to={time.to} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={3}>
<EuiPanel hasBorder>
<EuiTitle size="xs">
<h3 css={{ margin: euiTheme.size.s, marginBottom: 0 }}>{FAILED_TESTS_LABEL}</h3>
</EuiTitle>
<MonitorFailedTests time={time} />
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
<EuiFlexGroup gutterSize="m">
<EuiFlexItem grow={2}>
<EuiPanel hasBorder>
<EuiTitle size="xs">
<h3 css={{ margin: euiTheme.size.s, marginBottom: 0 }}>{ERRORS_LABEL}</h3>
</EuiTitle>
<ErrorsList />
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<EuiPanel hasBorder>
<EuiTitle size="xs">
<h3 css={{ margin: euiTheme.size.s, marginBottom: 0 }}>
{FAILED_TESTS_BY_STEPS_LABEL}
</h3>
</EuiTitle>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
{initialLoading && <LoadingErrors />}
{emptyState && <EmptyErrors />}
<div style={{ visibility: initialLoading || emptyState ? 'collapse' : 'initial' }}>
<ErrorsTabContent errorStates={errorStates} loading={loading} />
</div>
</>
);
};
const ERRORS_LABEL = i18n.translate('xpack.synthetics.errors.label', {
defaultMessage: 'Errors',
const LoadingErrors = () => {
return (
<EuiFlexGroup alignItems="center" justifyContent="center" style={{ height: '65vh' }}>
<EuiFlexItem grow={false} style={{ textAlign: 'center' }}>
<span>
<EuiLoadingSpinner size="xxl" />
</span>
<EuiSpacer size="m" />
<EuiTitle size="m">
<h3>{CHEKCING_FOR_ERRORS}</h3>
</EuiTitle>
<EuiSpacer size="m" />
<EuiText color="subdued">{LOADING_DESCRIPTION}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
);
};
const EmptyErrors = () => {
return (
<EuiFlexGroup alignItems="center" justifyContent="center" style={{ height: '65vh' }}>
<EuiFlexItem grow={false} style={{ textAlign: 'center' }}>
<span>
<EuiIcon type="checkInCircleFilled" color="success" size="xl" />
</span>
<EuiSpacer size="m" />
<EuiTitle size="m">
<h3>{NO_ERRORS_FOUND}</h3>
</EuiTitle>
<EuiSpacer size="m" />
<EuiText color="subdued">{KEEP_CALM}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
);
};
const KEEP_CALM = i18n.translate('xpack.synthetics.errors.keepCalm', {
defaultMessage: 'Keep calm and carry on.',
});
const OVERVIEW_LABEL = i18n.translate('xpack.synthetics.errors.overview', {
defaultMessage: 'Overview',
const NO_ERRORS_FOUND = i18n.translate('xpack.synthetics.errors.noErrorsFound', {
defaultMessage: 'No errors found',
});
const FAILED_TESTS_LABEL = i18n.translate('xpack.synthetics.errors.failedTests', {
defaultMessage: 'Failed tests',
const LOADING_DESCRIPTION = i18n.translate('xpack.synthetics.errors.loadingDescription', {
defaultMessage: 'This will take just a second.',
});
const FAILED_TESTS_BY_STEPS_LABEL = i18n.translate('xpack.synthetics.errors.failedTests.byStep', {
defaultMessage: 'Failed tests by step',
const CHEKCING_FOR_ERRORS = i18n.translate('xpack.synthetics.errors.checkingForErrors', {
defaultMessage: 'Checking for errors',
});