Skip to content

Commit

Permalink
[Uptime] Synthetic check steps list view (#90978) (#94716)
Browse files Browse the repository at this point in the history
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Shahzad <shahzad.muhammad@elastic.co>
  • Loading branch information
kibanamachine and shahzad31 authored Mar 17, 2021
1 parent 657bff3 commit 572af17
Show file tree
Hide file tree
Showing 63 changed files with 1,514 additions and 1,020 deletions.
6 changes: 0 additions & 6 deletions x-pack/plugins/translations/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -23251,12 +23251,8 @@
"xpack.uptime.synthetics.emptyJourney.message.footer": "表示する詳細情報はありません。",
"xpack.uptime.synthetics.emptyJourney.message.heading": "ステップが含まれていませんでした。",
"xpack.uptime.synthetics.emptyJourney.title": "ステップがありません。",
"xpack.uptime.synthetics.executedJourney.heading": "概要情報",
"xpack.uptime.synthetics.executedStep.errorHeading": "エラー",
"xpack.uptime.synthetics.executedStep.scriptHeading": "スクリプトのステップ",
"xpack.uptime.synthetics.executedStep.stackTrace": "スタックトレース",
"xpack.uptime.synthetics.executedStep.stepName": "{stepNumber}. {stepName}",
"xpack.uptime.synthetics.experimentalCallout.title": "実験的機能",
"xpack.uptime.synthetics.imageLoadingSpinner.ariaLabel": "画像を示すアニメーションスピナーを読み込んでいます",
"xpack.uptime.synthetics.journey.allFailedMessage": "{total}ステップ - すべて失敗またはスキップされました",
"xpack.uptime.synthetics.journey.allSucceededMessage": "{total}ステップ - すべて成功しました",
Expand All @@ -23267,8 +23263,6 @@
"xpack.uptime.synthetics.screenshot.noImageMessage": "画像がありません",
"xpack.uptime.synthetics.screenshotDisplay.altText": "名前「{stepName}」のステップのスクリーンショット",
"xpack.uptime.synthetics.screenshotDisplay.altTextWithoutName": "スクリーンショット",
"xpack.uptime.synthetics.screenshotDisplay.thumbnailAltText": "名前「{stepName}」のステップのサムネイルスクリーンショット",
"xpack.uptime.synthetics.screenshotDisplay.thumbnailAltTextWithoutName": "サムネイルスクリーンショット",
"xpack.uptime.synthetics.statusBadge.failedMessage": "失敗",
"xpack.uptime.synthetics.statusBadge.skippedMessage": "スキップ",
"xpack.uptime.synthetics.statusBadge.succeededMessage": "成功",
Expand Down
6 changes: 0 additions & 6 deletions x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -23607,12 +23607,8 @@
"xpack.uptime.synthetics.emptyJourney.message.footer": "没有更多可显示的信息。",
"xpack.uptime.synthetics.emptyJourney.message.heading": "此过程不包含任何步骤。",
"xpack.uptime.synthetics.emptyJourney.title": "没有此过程的任何步骤",
"xpack.uptime.synthetics.executedJourney.heading": "摘要信息",
"xpack.uptime.synthetics.executedStep.errorHeading": "错误",
"xpack.uptime.synthetics.executedStep.scriptHeading": "步骤脚本",
"xpack.uptime.synthetics.executedStep.stackTrace": "堆栈跟踪",
"xpack.uptime.synthetics.executedStep.stepName": "{stepNumber}:{stepName}",
"xpack.uptime.synthetics.experimentalCallout.title": "实验功能",
"xpack.uptime.synthetics.imageLoadingSpinner.ariaLabel": "表示图像正在加载的动画旋转图标",
"xpack.uptime.synthetics.journey.allFailedMessage": "{total} 个步骤 - 全部失败或跳过",
"xpack.uptime.synthetics.journey.allSucceededMessage": "{total} 个步骤 - 全部成功",
Expand All @@ -23623,8 +23619,6 @@
"xpack.uptime.synthetics.screenshot.noImageMessage": "没有可用图像",
"xpack.uptime.synthetics.screenshotDisplay.altText": "名称为“{stepName}”的步骤的屏幕截图",
"xpack.uptime.synthetics.screenshotDisplay.altTextWithoutName": "屏幕截图",
"xpack.uptime.synthetics.screenshotDisplay.thumbnailAltText": "名称为“{stepName}”的步骤的缩略屏幕截图",
"xpack.uptime.synthetics.screenshotDisplay.thumbnailAltTextWithoutName": "缩略屏幕截图",
"xpack.uptime.synthetics.statusBadge.failedMessage": "失败",
"xpack.uptime.synthetics.statusBadge.skippedMessage": "已跳过",
"xpack.uptime.synthetics.statusBadge.succeededMessage": "成功",
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/uptime/common/constants/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export const CERTIFICATES_ROUTE = '/certificates';

export const STEP_DETAIL_ROUTE = '/journey/:checkGroupId/step/:stepIndex';

export const SYNTHETIC_CHECK_STEPS_ROUTE = '/journey/:checkGroupId/steps';

export enum STATUS {
UP = 'up',
DOWN = 'down',
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/uptime/common/runtime_types/ping/ping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ export const PingType = t.intersection([
type: t.string,
url: t.string,
end: t.number,
text: t.string,
}),
}),
tags: t.array(t.string),
Expand Down Expand Up @@ -251,6 +252,7 @@ export const SyntheticsJourneyApiResponseType = t.intersection([
t.intersection([
t.type({
timestamp: t.string,
journey: PingType,
}),
t.partial({
next: t.type({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import React, { FC } from 'react';
import { ReactRouterEuiButton } from './react_router_helpers';
import { ReactRouterEuiButtonEmpty } from './react_router_helpers';

interface StepDetailLinkProps {
/**
Expand All @@ -23,14 +23,8 @@ export const StepDetailLink: FC<StepDetailLinkProps> = ({ children, checkGroupId
const to = `/journey/${checkGroupId}/step/${stepIndex}`;

return (
<ReactRouterEuiButton
data-test-subj={`step-detail-link`}
to={to}
size="s"
fill
fullWidth={false}
>
<ReactRouterEuiButtonEmpty data-test-subj={`step-detail-link`} to={to}>
{children}
</ReactRouterEuiButton>
</ReactRouterEuiButtonEmpty>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { EuiButtonIcon, EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
import React from 'react';
import React, { MouseEvent } from 'react';
import { nextAriaLabel, prevAriaLabel } from './translations';

export interface NavButtonsProps {
Expand Down Expand Up @@ -34,8 +34,9 @@ export const NavButtons: React.FC<NavButtonsProps> = ({
disabled={stepNumber === 1}
color="subdued"
size="s"
onClick={() => {
onClick={(evt: MouseEvent<HTMLButtonElement>) => {
setStepNumber(stepNumber - 1);
evt.stopPropagation();
}}
iconType="arrowLeft"
aria-label={prevAriaLabel}
Expand All @@ -46,8 +47,9 @@ export const NavButtons: React.FC<NavButtonsProps> = ({
disabled={stepNumber === maxSteps}
color="subdued"
size="s"
onClick={() => {
onClick={(evt: MouseEvent<HTMLButtonElement>) => {
setStepNumber(stepNumber + 1);
evt.stopPropagation();
}}
iconType="arrowRight"
aria-label={nextAriaLabel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { mockReduxHooks } from '../../../../../lib/helper/test_helpers';
import { render } from '../../../../../lib/helper/rtl_helpers';
import { Ping } from '../../../../../../common/runtime_types/ping';
import * as observabilityPublic from '../../../../../../../observability/public';
import { getShortTimeStamp } from '../../../../overview/monitor_list/columns/monitor_status_column';
import moment from 'moment';

mockReduxHooks();

Expand Down Expand Up @@ -68,7 +70,7 @@ describe('Ping Timestamp component', () => {
.spyOn(observabilityPublic, 'useFetcher')
.mockReturnValue({ status: fetchStatus, data: null, refetch: () => null });
const { getByTestId } = render(
<PingTimestamp ping={response} timestamp={response.timestamp} />
<PingTimestamp ping={response} label={getShortTimeStamp(moment(response.timestamp))} />
);
expect(getByTestId('pingTimestampSpinner')).toBeInTheDocument();
}
Expand All @@ -79,7 +81,7 @@ describe('Ping Timestamp component', () => {
.spyOn(observabilityPublic, 'useFetcher')
.mockReturnValue({ status: FETCH_STATUS.SUCCESS, data: null, refetch: () => null });
const { getByTestId } = render(
<PingTimestamp ping={response} timestamp={response.timestamp} />
<PingTimestamp ping={response} label={getShortTimeStamp(moment(response.timestamp))} />
);
expect(getByTestId('pingTimestampNoImageAvailable')).toBeInTheDocument();
});
Expand All @@ -91,7 +93,9 @@ describe('Ping Timestamp component', () => {
data: { src },
refetch: () => null,
});
const { container } = render(<PingTimestamp ping={response} timestamp={response.timestamp} />);
const { container } = render(
<PingTimestamp ping={response} label={getShortTimeStamp(moment(response.timestamp))} />
);
expect(container.querySelector('img')?.src).toBe(src);
});

Expand All @@ -103,7 +107,7 @@ describe('Ping Timestamp component', () => {
refetch: () => null,
});
const { getByAltText, getAllByText, queryByAltText } = render(
<PingTimestamp ping={response} timestamp={response.timestamp} />
<PingTimestamp ping={response} label={getShortTimeStamp(moment(response.timestamp))} />
);
const caption = getAllByText('Nov 26, 2020 10:28:56 AM');
fireEvent.mouseEnter(caption[0]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,32 @@
import React, { useContext, useEffect, useState } from 'react';
import useIntersection from 'react-use/lib/useIntersection';
import styled from 'styled-components';
import moment from 'moment';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { Ping } from '../../../../../../common/runtime_types/ping';
import { useFetcher, FETCH_STATUS } from '../../../../../../../observability/public';
import { getJourneyScreenshot } from '../../../../../state/api/journey';
import { UptimeSettingsContext } from '../../../../../contexts';
import { NavButtons } from './nav_buttons';
import { NoImageDisplay } from './no_image_display';
import { StepImageCaption } from './step_image_caption';
import { StepImagePopover } from './step_image_popover';
import { formatCaptionContent } from './translations';
import { getShortTimeStamp } from '../../../../overview/monitor_list/columns/monitor_status_column';

const StepDiv = styled.div`
figure.euiImage {
div.stepArrowsFullScreen {
display: none;
}
}
position: relative;
div.stepArrows {
display: none;
}
:hover {
div.stepArrows {
display: flex;
}
}
`;

interface Props {
timestamp: string;
label?: string;
ping: Ping;
initialStepNo?: number;
}

export const PingTimestamp = ({ timestamp, ping }: Props) => {
const [stepNumber, setStepNumber] = useState(1);
export const PingTimestamp = ({ label, ping, initialStepNo = 1 }: Props) => {
const [stepNumber, setStepNumber] = useState(initialStepNo);
const [isImagePopoverOpen, setIsImagePopoverOpen] = useState(false);

const [stepImages, setStepImages] = useState<string[]>([]);
Expand Down Expand Up @@ -77,18 +65,33 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => {

const captionContent = formatCaptionContent(stepNumber, data?.maxSteps);

const [numberOfCaptions, setNumberOfCaptions] = useState(0);

const ImageCaption = (
<StepImageCaption
captionContent={captionContent}
imgSrc={imgSrc}
maxSteps={data?.maxSteps}
setStepNumber={setStepNumber}
stepNumber={stepNumber}
timestamp={timestamp}
isLoading={status === FETCH_STATUS.LOADING || status === FETCH_STATUS.PENDING}
label={label}
onVisible={(val) => setNumberOfCaptions((prevVal) => (val ? prevVal + 1 : prevVal - 1))}
/>
);

useEffect(() => {
// This is a hack to get state if image is in full screen, we should refactor
// it once eui image exposes it's full screen state
// we are checking if number of captions are 2, that means
// image is in full screen mode since caption is also rendered on
// full screen image
// we dont want to change image displayed in thumbnail
if (numberOfCaptions === 1 && stepNumber !== initialStepNo) {
setStepNumber(initialStepNo);
}
}, [numberOfCaptions, initialStepNo, stepNumber]);

return (
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
Expand All @@ -111,16 +114,10 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => {
isPending={status === FETCH_STATUS.PENDING}
/>
)}
<NavButtons
maxSteps={data?.maxSteps}
setIsImagePopoverOpen={setIsImagePopoverOpen}
setStepNumber={setStepNumber}
stepNumber={stepNumber}
/>
</StepDiv>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<span className="eui-textNoWrap">{getShortTimeStamp(moment(timestamp))}</span>
<span className="eui-textNoWrap">{label}</span>
</EuiFlexItem>
</EuiFlexGroup>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { fireEvent, waitFor } from '@testing-library/react';
import React from 'react';
import { render } from '../../../../../lib/helper/rtl_helpers';
import { StepImageCaption, StepImageCaptionProps } from './step_image_caption';
import { getShortTimeStamp } from '../../../../overview/monitor_list/columns/monitor_status_column';
import moment from 'moment';

describe('StepImageCaption', () => {
let defaultProps: StepImageCaptionProps;
Expand All @@ -20,7 +22,8 @@ describe('StepImageCaption', () => {
maxSteps: 3,
setStepNumber: jest.fn(),
stepNumber: 2,
timestamp: '2020-11-26T15:28:56.896Z',
label: getShortTimeStamp(moment('2020-11-26T15:28:56.896Z')),
onVisible: jest.fn(),
isLoading: false,
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
* 2.0.
*/

import React, { MouseEvent, useEffect } from 'react';
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import React from 'react';
import moment from 'moment';
import { nextAriaLabel, prevAriaLabel } from './translations';
import { getShortTimeStamp } from '../../../../overview/monitor_list/columns/monitor_status_column';
import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common';

export interface StepImageCaptionProps {
Expand All @@ -18,7 +16,8 @@ export interface StepImageCaptionProps {
maxSteps?: number;
setStepNumber: React.Dispatch<React.SetStateAction<number>>;
stepNumber: number;
timestamp: string;
label?: string;
onVisible: (val: boolean) => void;
isLoading: boolean;
}

Expand All @@ -35,19 +34,34 @@ export const StepImageCaption: React.FC<StepImageCaptionProps> = ({
maxSteps,
setStepNumber,
stepNumber,
timestamp,
isLoading,
label,
onVisible,
}) => {
useEffect(() => {
onVisible(true);
return () => {
onVisible(false);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<ImageCaption>
<ImageCaption
onClick={(evt) => {
// we don't want this to be captured by row click which leads to step list page
evt.stopPropagation();
}}
>
<div className="stepArrowsFullScreen">
{imgSrc && (
<EuiFlexGroup alignItems="center" justifyContent="center">
<EuiFlexItem grow={false}>
<EuiButtonEmpty
disabled={stepNumber === 1}
onClick={() => {
onClick={(evt: MouseEvent<HTMLButtonElement>) => {
setStepNumber(stepNumber - 1);
evt.preventDefault();
}}
iconType="arrowLeft"
aria-label={prevAriaLabel}
Expand All @@ -62,8 +76,9 @@ export const StepImageCaption: React.FC<StepImageCaptionProps> = ({
<EuiFlexItem grow={false}>
<EuiButtonEmpty
disabled={stepNumber === maxSteps}
onClick={() => {
onClick={(evt: MouseEvent<HTMLButtonElement>) => {
setStepNumber(stepNumber + 1);
evt.stopPropagation();
}}
iconType="arrowRight"
iconSide="right"
Expand All @@ -75,7 +90,7 @@ export const StepImageCaption: React.FC<StepImageCaptionProps> = ({
</EuiFlexItem>
</EuiFlexGroup>
)}
<span className="eui-textNoWrap">{getShortTimeStamp(moment(timestamp))}</span>
<span className="eui-textNoWrap">{label}</span>
</div>
</ImageCaption>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const StepImagePopover: React.FC<StepImagePopoverProps> = ({
isImagePopoverOpen,
}) => (
<EuiPopover
anchorPosition="upCenter"
anchorPosition="leftDown"
button={
<StepImage
allowFullScreen={true}
Expand All @@ -52,6 +52,7 @@ export const StepImagePopover: React.FC<StepImagePopoverProps> = ({
/>
}
isOpen={isImagePopoverOpen}
closePopover={() => {}}
>
<EuiImage
alt={fullSizeImageAlt}
Expand Down
Loading

0 comments on commit 572af17

Please sign in to comment.