Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Synthetics] Step details page screenshot #143452

Merged
merged 22 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
92a62b3
added screenshot
shahzad31 Oct 17, 2022
27c69b1
Merge branch 'main' of github.com:elastic/kibana into step-detail-pag…
shahzad31 Oct 18, 2022
70e2710
fix type
shahzad31 Oct 18, 2022
7170388
test fix
shahzad31 Oct 18, 2022
b9bf384
update
shahzad31 Oct 18, 2022
f6d8f90
data
shahzad31 Oct 18, 2022
a9644a6
Merge branch 'main' of github.com:elastic/kibana into step-detail-pag…
shahzad31 Oct 20, 2022
8da9545
tr test
shahzad31 Oct 20, 2022
580d0d9
Merge branch 'main' of github.com:elastic/kibana into step-detail-pag…
shahzad31 Oct 20, 2022
ef442f2
Merge branch 'main' into step-detail-page-screenshot
shahzad31 Oct 24, 2022
3a14d34
Merge branch 'main' of github.com:elastic/kibana into step-detail-pag…
shahzad31 Oct 24, 2022
06f800c
fix default mode
shahzad31 Oct 24, 2022
afbcd02
PR feedback fix
shahzad31 Oct 24, 2022
b6150b9
Merge branch 'main' of github.com:elastic/kibana into step-detail-pag…
shahzad31 Oct 24, 2022
80e909a
test
shahzad31 Oct 24, 2022
5ebc15c
update test
shahzad31 Oct 25, 2022
25b40b0
Merge branch 'update-test' into step-detail-page-screenshot
shahzad31 Oct 25, 2022
edbdd7e
Merge branch 'main' into step-detail-page-screenshot
shahzad31 Oct 31, 2022
afd946d
Merge branch 'main' of github.com:elastic/kibana into step-detail-pag…
shahzad31 Oct 31, 2022
d393733
fix pr feedback
shahzad31 Oct 31, 2022
3ad9e87
Merge branch 'main' of github.com:elastic/kibana into step-detail-pag…
shahzad31 Oct 31, 2022
bf52e21
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Oct 31, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion x-pack/plugins/synthetics/common/runtime_types/ping/ping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ export const MonitorType = t.intersection([
id: t.string,
status: t.string,
type: t.string,
check_group: t.string,
shahzad31 marked this conversation as resolved.
Show resolved Hide resolved
}),
t.partial({
duration: t.type({
us: t.number,
}),
check_group: t.string,
ip: t.string,
name: t.string,
timespan: t.type({
Expand Down Expand Up @@ -268,6 +268,7 @@ export const makePing = (f: {
status: f.status || 'up',
duration: { us: f.duration || 100000 },
name: f.name,
check_group: 'myCheckGroup',
},
...(f.location ? { observer: { geo: { name: f.location } } } : {}),
...(f.url ? { url: { full: f.url } } : {}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kib

async navigateToEditMonitor() {
await this.clickByTestSubj('syntheticsMonitorListActions');
await page.click('text=Edit');
await page.click('text=Edit', { timeout: 2 * 60 * 1000 });
await this.findByText('Edit monitor');
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const BrowserStepsList = ({ steps, error, loading, showStepNumber = false
aria-label={VIEW_DETAILS}
title={VIEW_DETAILS}
size="s"
href={`${basePath}/app/uptime/journey/${item.monitor.check_group}/step/${item.synthetics?.step?.index}`}
href={`${basePath}/app/synthetics/journey/${item.monitor.check_group}/step/${item.synthetics?.step?.index}`}
target="_self"
iconType="apmTrace"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const THUMBNAIL_HEIGHT = 64;

export const thumbnailStyle = css`
padding: 0;
margin: 0;
margin: auto;
width: ${THUMBNAIL_WIDTH}px;
height: ${THUMBNAIL_HEIGHT}px;
object-fit: contain;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ import React from 'react';
import { css } from '@emotion/react';
import { EuiImage, EuiPopover, useEuiTheme } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useRouteMatch } from 'react-router-dom';
import { EmptyImage } from '../screenshot/empty_image';
import { ScreenshotRefImageData } from '../../../../../../common/runtime_types';
import { useCompositeImage } from '../../../hooks/use_composite_image';

import { EmptyThumbnail, thumbnailStyle } from './empty_thumbnail';
import { STEP_DETAIL_ROUTE } from '../../../../../../common/constants';

const POPOVER_IMG_HEIGHT = 360;
const POPOVER_IMG_WIDTH = 640;
Expand All @@ -22,6 +25,7 @@ interface ScreenshotImageProps {
imageCaption: JSX.Element;
isStepFailed: boolean;
isLoading: boolean;
asThumbnail?: boolean;
}

const ScreenshotThumbnail: React.FC<ScreenshotImageProps & { imageData?: string }> = ({
Expand All @@ -30,6 +34,7 @@ const ScreenshotThumbnail: React.FC<ScreenshotImageProps & { imageData?: string
imageData,
isStepFailed,
isLoading,
asThumbnail = true,
}) => {
return imageData ? (
<EuiImage
Expand All @@ -39,11 +44,13 @@ const ScreenshotThumbnail: React.FC<ScreenshotImageProps & { imageData?: string
data-test-subj="stepScreenshotThumbnail"
hasShadow
url={imageData}
size="s"
size="l"
className="syntheticsStepImage"
/>
) : (
) : asThumbnail ? (
<EmptyThumbnail isLoading={isLoading} />
) : (
<EmptyImage isLoading={isLoading} />
);
};
/**
Expand All @@ -64,6 +71,7 @@ const RecomposedScreenshotImage: React.FC<
setImageData,
isStepFailed,
isLoading,
asThumbnail,
}) => {
// initially an undefined URL value is passed to the image display, and a loading spinner is rendered.
// `useCompositeImage` will call `setImageData` when the image is composited, and the updated `imageData` will display.
Expand All @@ -76,6 +84,7 @@ const RecomposedScreenshotImage: React.FC<
imageData={imageData}
isStepFailed={isStepFailed}
isLoading={isLoading}
asThumbnail={asThumbnail}
/>
);
};
Expand All @@ -88,6 +97,7 @@ export interface StepImagePopoverProps {
isImagePopoverOpen: boolean;
isStepFailed: boolean;
isLoading: boolean;
asThumbnail?: boolean;
}

const JourneyStepImage: React.FC<
Expand All @@ -104,6 +114,7 @@ const JourneyStepImage: React.FC<
setImageData,
isStepFailed,
isLoading,
asThumbnail = true,
}) => {
if (imgSrc) {
return (
Expand All @@ -113,6 +124,7 @@ const JourneyStepImage: React.FC<
imageData={imageData}
isStepFailed={isStepFailed}
isLoading={isLoading}
asThumbnail={asThumbnail}
/>
);
} else if (imgRef) {
Expand All @@ -125,6 +137,7 @@ const JourneyStepImage: React.FC<
setImageData={setImageData}
isStepFailed={isStepFailed}
isLoading={isLoading}
asThumbnail={asThumbnail}
/>
);
}
Expand All @@ -139,6 +152,7 @@ export const JourneyStepImagePopover: React.FC<StepImagePopoverProps> = ({
isImagePopoverOpen,
isStepFailed,
isLoading,
asThumbnail = true,
}) => {
const { euiTheme } = useEuiTheme();

Expand All @@ -158,12 +172,16 @@ export const JourneyStepImagePopover: React.FC<StepImagePopoverProps> = ({

const isImageLoading = isLoading || (!!imgRef && !imageData);

const isStepDetailPage = useRouteMatch(STEP_DETAIL_ROUTE)?.isExact;

const thumbnailS = isStepDetailPage ? null : thumbnailStyle;

return (
<EuiPopover
css={css`
figure {
img {
${thumbnailStyle};
${thumbnailS};
border: ${euiTheme.border.thin};
${isStepFailed ? `border-color: ${euiTheme.colors.danger}` : ``};
}
Expand All @@ -180,6 +198,7 @@ export const JourneyStepImagePopover: React.FC<StepImagePopoverProps> = ({
imageData={imageData}
isStepFailed={isStepFailed}
isLoading={isImageLoading}
asThumbnail={asThumbnail}
/>
}
isOpen={isImagePopoverOpen}
Expand All @@ -195,12 +214,10 @@ export const JourneyStepImagePopover: React.FC<StepImagePopoverProps> = ({
object-fit: contain;
`}
/>
) : asThumbnail ? (
<EmptyThumbnail isLoading={isLoading} />
) : (
<EmptyThumbnail
isLoading={isLoading}
width={POPOVER_IMG_WIDTH}
height={POPOVER_IMG_HEIGHT}
/>
<EmptyImage isLoading={isLoading} />
)}
</EuiPopover>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import React, { CSSProperties } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiText, useEuiTheme } from '@elastic/eui';
import { JourneyStep } from '../../../../../../common/runtime_types';
import { JourneyStepScreenshotContainer } from './journey_step_screenshot_container';
import { JourneyStepScreenshotContainer } from '../screenshot/journey_step_screenshot_container';
import { getTextColorForMonitorStatus, parseBadgeStatus } from './status_badge';

interface Props {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* 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 { css } from '@emotion/react';
import { i18n } from '@kbn/i18n';
import {
useEuiTheme,
useEuiBackgroundColor,
EuiIcon,
EuiLoadingContent,
EuiText,
} from '@elastic/eui';

export const IMAGE_WIDTH = 360;
export const IMAGE_HEIGHT = 203;

export const imageStyle = css`
padding: 0;
margin: auto;
width: ${IMAGE_WIDTH}px;
height: ${IMAGE_HEIGHT}px;
object-fit: contain;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
`;

export const EmptyImage = ({
isLoading = false,
width = IMAGE_WIDTH,
height = IMAGE_HEIGHT,
}: {
isLoading: boolean;
width?: number;
height?: number;
}) => {
const { euiTheme } = useEuiTheme();

return (
<div
data-test-subj="stepScreenshotPlaceholder"
role="img"
aria-label={isLoading ? SCREENSHOT_LOADING_ARIA_LABEL : SCREENSHOT_NOT_AVAILABLE}
title={isLoading ? SCREENSHOT_LOADING_ARIA_LABEL : SCREENSHOT_NOT_AVAILABLE}
css={css`
${imageStyle};
width: ${width}px;
height: ${height}px;
background: ${useEuiBackgroundColor('subdued')};
border: ${euiTheme.border.thin};
`}
>
{isLoading ? (
<EuiLoadingContent
lines={1}
data-test-subj="stepScreenshotPlaceholderLoading"
css={css`
width: 100%;
height: 8%;
transform: scale(1, 13); // To create a skeleton loading effect
`}
/>
) : (
<div>
<EuiIcon
data-test-subj="stepScreenshotNotAvailable"
type="eyeClosed"
color={euiTheme.colors.disabledText}
/>
<EuiText color={euiTheme.colors.disabledText}>{IMAGE_UN_AVAILABLE}</EuiText>
</div>
)}
</div>
);
};

export const SCREENSHOT_LOADING_ARIA_LABEL = i18n.translate(
'xpack.synthetics.monitor.step.screenshot.ariaLabel',
{
defaultMessage: 'Step screenshot is being loaded.',
}
);

export const SCREENSHOT_NOT_AVAILABLE = i18n.translate(
'xpack.synthetics.monitor.step.screenshot.notAvailable',
{
defaultMessage: 'Step screenshot is not available.',
}
);

export const IMAGE_UN_AVAILABLE = i18n.translate(
'xpack.synthetics.monitor.step.screenshot.unAvailable',
{
defaultMessage: 'Image unavailable',
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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, { useMemo } from 'react';
import { useJourneySteps } from '../../monitor_details/hooks/use_journey_steps';
import { parseBadgeStatus } from '../monitor_test_result/status_badge';
import { JourneyStepScreenshotContainer } from './journey_step_screenshot_container';

export const JourneyScreenshot = ({ checkGroupId }: { checkGroupId: string }) => {
const { loading: stepsLoading, stepEnds } = useJourneySteps(checkGroupId);
const stepLabels = stepEnds.map((stepEnd) => stepEnd?.synthetics?.step?.name ?? '');

const lastSignificantStep = useMemo(() => {
const copy = [...stepEnds];
// Sort desc by timestamp
copy.sort(
(stepA, stepB) =>
Number(new Date(stepB['@timestamp'])) - Number(new Date(stepA['@timestamp']))
);
return copy.find(
(stepEnd) => parseBadgeStatus(stepEnd?.synthetics?.step?.status ?? 'skipped') !== 'skipped'
);
}, [stepEnds]);

return (
<JourneyStepScreenshotContainer
checkGroup={lastSignificantStep?.monitor.check_group}
initialStepNo={lastSignificantStep?.synthetics?.step?.index}
stepStatus={lastSignificantStep?.synthetics.payload?.status}
allStepsLoaded={!stepsLoading}
stepLabels={stepLabels}
retryFetchOnRevisit={false}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import * as observabilityPublic from '@kbn/observability-plugin/public';
import { getShortTimeStamp } from '../../../utils/monitor_test_result/timestamp';
import '../../../utils/testing/__mocks__/use_composite_image.mock';
import { mockRef } from '../../../utils/testing/__mocks__/screenshot_ref.mock';
import * as retrieveHooks from './use_retrieve_step_image';
import * as retrieveHooks from '../monitor_test_result/use_retrieve_step_image';

jest.mock('@kbn/observability-plugin/public');

Expand Down
Loading