diff --git a/packages/kbn-babel-preset/styled_components_files.js b/packages/kbn-babel-preset/styled_components_files.js index 42564e7010df7..c9393397c6c12 100644 --- a/packages/kbn-babel-preset/styled_components_files.js +++ b/packages/kbn-babel-preset/styled_components_files.js @@ -152,7 +152,6 @@ module.exports = { /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]synthetics[\/\\]public[\/\\]apps[\/\\]synthetics[\/\\]components[\/\\]monitor_add_edit[\/\\]fields[\/\\]key_value_field.tsx/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]synthetics[\/\\]public[\/\\]apps[\/\\]synthetics[\/\\]components[\/\\]monitors_page[\/\\]overview[\/\\]overview[\/\\]actions_popover.tsx/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]synthetics[\/\\]public[\/\\]apps[\/\\]synthetics[\/\\]components[\/\\]monitors_page[\/\\]overview[\/\\]overview[\/\\]grid_by_group[\/\\]grid_items_by_group.tsx/, - /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]synthetics[\/\\]public[\/\\]apps[\/\\]synthetics[\/\\]components[\/\\]monitors_page[\/\\]overview[\/\\]overview[\/\\]metric_item_icon.tsx/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]synthetics[\/\\]public[\/\\]apps[\/\\]synthetics[\/\\]components[\/\\]settings[\/\\]alerting_defaults[\/\\]connector_field.tsx/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]synthetics[\/\\]public[\/\\]apps[\/\\]synthetics[\/\\]components[\/\\]test_now_mode[\/\\]browser[\/\\]browser_test_results.tsx/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]synthetics[\/\\]public[\/\\]apps[\/\\]synthetics[\/\\]components[\/\\]test_now_mode[\/\\]simple[\/\\]ping_list[\/\\]columns[\/\\]ping_error.tsx/, diff --git a/x-pack/solutions/observability/plugins/synthetics/common/runtime_types/monitor_management/synthetics_overview_status.ts b/x-pack/solutions/observability/plugins/synthetics/common/runtime_types/monitor_management/synthetics_overview_status.ts index aec3d3ac3390f..87fe9cdadaddb 100644 --- a/x-pack/solutions/observability/plugins/synthetics/common/runtime_types/monitor_management/synthetics_overview_status.ts +++ b/x-pack/solutions/observability/plugins/synthetics/common/runtime_types/monitor_management/synthetics_overview_status.ts @@ -51,7 +51,6 @@ export const OverviewStatusMetaDataCodec = t.intersection([ t.partial({ projectId: t.string, updated_at: t.string, - ping: OverviewPingCodec, timestamp: t.string, spaceId: t.string, }), diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/grid_by_group/grid_group_item.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/grid_by_group/grid_group_item.tsx index 6fcf90f631fad..31e913cd8b68e 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/grid_by_group/grid_group_item.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/grid_by_group/grid_group_item.tsx @@ -25,7 +25,7 @@ import { OverviewLoader } from '../overview_loader'; import { useFilteredGroupMonitors } from './use_filtered_group_monitors'; import { OverviewStatusMetaData } from '../../types'; import { selectOverviewStatus } from '../../../../../state/overview_status'; -import { MetricItem } from '../metric_item'; +import { MetricItem } from '../metric_item/metric_item'; const PER_ROW = 4; const DEFAULT_ROW_SIZE = 2; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/metric_error_icon.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/metric_error_icon.tsx new file mode 100644 index 0000000000000..10cea56014292 --- /dev/null +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/metric_error_icon.tsx @@ -0,0 +1,93 @@ +/* + * 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 { EuiButtonIcon, useEuiShadow, useEuiTheme } from '@elastic/eui'; +import * as React from 'react'; +import { useRef } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; +import { useSyntheticsSettingsContext } from '../../../../../contexts'; +import { selectErrorPopoverState, toggleErrorPopoverOpen } from '../../../../../state'; + +export const MetricErrorIcon = ({ configIdByLocation }: { configIdByLocation: string }) => { + const isPopoverOpen = useSelector(selectErrorPopoverState); + const dispatch = useDispatch(); + + const setIsPopoverOpen = () => { + dispatch(toggleErrorPopoverOpen(configIdByLocation)); + }; + const timer = useRef(null); + const euiShadow = useEuiShadow('s'); + + const theme = useEuiTheme().euiTheme; + const { darkMode } = useSyntheticsSettingsContext(); + + return ( +
{ + // show popover with delay + if (timer.current) { + clearTimeout(timer.current); + } + timer.current = setTimeout(() => { + setIsPopoverOpen(); + }, 300); + }} + onMouseLeave={() => { + if (isPopoverOpen) { + return; + } else if (timer.current) { + clearTimeout(timer.current); + } + }} + onClick={() => { + if (configIdByLocation === isPopoverOpen) { + dispatch(toggleErrorPopoverOpen(null)); + } else { + dispatch(toggleErrorPopoverOpen(configIdByLocation)); + } + }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + if (configIdByLocation === isPopoverOpen) { + dispatch(toggleErrorPopoverOpen(null)); + } else { + dispatch(toggleErrorPopoverOpen(configIdByLocation)); + } + } + }} + > + +
+ ); +}; +const ERROR_DETAILS = i18n.translate('xpack.synthetics.errorDetails.label', { + defaultMessage: 'Error details', +}); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/metric_item.tsx similarity index 91% rename from x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item.tsx rename to x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/metric_item.tsx index c8c266db63736..a91a07d17ba6c 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/metric_item.tsx @@ -15,24 +15,24 @@ import { useTheme } from '@kbn/observability-shared-plugin/public'; import moment from 'moment'; import { useSelector, useDispatch } from 'react-redux'; -import { FlyoutParamProps } from './types'; -import { MetricItemBody } from './metric_item/metric_item_body'; +import { FlyoutParamProps } from '../types'; +import { MetricItemBody } from './metric_item_body'; import { selectErrorPopoverState, selectOverviewTrends, toggleErrorPopoverOpen, -} from '../../../../state'; -import { useLocationName, useStatusByLocationOverview } from '../../../../hooks'; -import { formatDuration } from '../../../../utils/formatting'; -import { OverviewStatusMetaData } from '../../../../../../../common/runtime_types'; -import { ActionsPopover } from './actions_popover'; +} from '../../../../../state'; +import { useLocationName, useStatusByLocationOverview } from '../../../../../hooks'; +import { formatDuration } from '../../../../../utils/formatting'; +import { OverviewStatusMetaData } from '../../../../../../../../common/runtime_types'; +import { ActionsPopover } from '../actions_popover'; import { hideTestNowFlyoutAction, manualTestRunInProgressSelector, toggleTestNowFlyoutAction, -} from '../../../../state/manual_test_runs'; +} from '../../../../../state/manual_test_runs'; import { MetricItemIcon } from './metric_item_icon'; -import { MetricItemExtra } from './metric_item/metric_item_extra'; +import { MetricItemExtra } from './metric_item_extra'; const METRIC_ITEM_HEIGHT = 160; @@ -69,7 +69,7 @@ export const MetricItem = ({ const [isPopoverOpen, setIsPopoverOpen] = useState(false); const isErrorPopoverOpen = useSelector(selectErrorPopoverState); const locationName = useLocationName(monitor); - const { status, timestamp, ping, configIdByLocation } = useStatusByLocationOverview({ + const { status, timestamp, configIdByLocation } = useStatusByLocationOverview({ configId: monitor.configId, locationId: monitor.locationId, }); @@ -184,7 +184,6 @@ export const MetricItem = ({ diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item_icon.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/metric_item_icon.tsx similarity index 58% rename from x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item_icon.tsx rename to x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/metric_item_icon.tsx index f932b74d07ba9..11fb4cdc91ce5 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item_icon.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/metric_item_icon.tsx @@ -14,23 +14,24 @@ import { EuiPopoverTitle, EuiPopoverFooter, EuiButton, - useEuiShadow, EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiLink, EuiSpacer, + EuiSkeletonText, } from '@elastic/eui'; import { useDispatch, useSelector } from 'react-redux'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { i18n } from '@kbn/i18n'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { useRef } from 'react'; -import { selectErrorPopoverState, toggleErrorPopoverOpen } from '../../../../state'; -import { useErrorDetailsLink } from '../../../common/links/error_details_link'; -import { OverviewPing, OverviewStatusMetaData } from '../../../../../../../common/runtime_types'; -import { isTestRunning, manualTestRunSelector } from '../../../../state/manual_test_runs'; -import { useDateFormat } from '../../../../../../hooks/use_date_format'; + +import { MetricErrorIcon } from './metric_error_icon'; +import { OverviewStatusMetaData } from '../../../../../../../../common/runtime_types'; +import { isTestRunning, manualTestRunSelector } from '../../../../../state/manual_test_runs'; +import { selectErrorPopoverState, toggleErrorPopoverOpen } from '../../../../../state'; +import { useErrorDetailsLink } from '../../../../common/links/error_details_link'; +import { useDateFormat } from '../../../../../../../hooks/use_date_format'; +import { useLatestError } from './use_latest_error'; const Container = styled.div` display: inline-block; @@ -43,7 +44,6 @@ const Container = styled.div` export const MetricItemIcon = ({ monitor, status, - ping, timestamp, configIdByLocation, }: { @@ -51,27 +51,24 @@ export const MetricItemIcon = ({ status: string; configIdByLocation: string; timestamp?: string; - ping?: OverviewPing; }) => { const testNowRun = useSelector(manualTestRunSelector(monitor.configId)); const isPopoverOpen = useSelector(selectErrorPopoverState); + const { latestPing } = useLatestError({ + configIdByLocation, + monitorId: monitor.configId, + locationLabel: monitor.locationLabel, + }); const dispatch = useDispatch(); - const timer = useRef(null); - - const setIsPopoverOpen = () => { - dispatch(toggleErrorPopoverOpen(configIdByLocation)); - }; - const inProgress = isTestRunning(testNowRun); const errorLink = useErrorDetailsLink({ configId: monitor.configId, - stateId: ping?.state?.id!, + stateId: latestPing?.state?.id!, locationId: monitor.locationId, }); - const euiShadow = useEuiShadow('s'); const formatter = useDateFormat(); const testTime = formatter(timestamp); @@ -94,42 +91,7 @@ export const MetricItemIcon = ({ return ( { - // show popover with delay - if (timer.current) { - clearTimeout(timer.current); - } - timer.current = setTimeout(() => { - setIsPopoverOpen(); - }, 300); - }} - onMouseLeave={() => { - if (isPopoverOpen) { - return; - } else if (timer.current) { - clearTimeout(timer.current); - } - }} - boxShadow={euiShadow} - onClick={() => { - if (configIdByLocation === isPopoverOpen) { - dispatch(toggleErrorPopoverOpen(null)); - } else { - dispatch(toggleErrorPopoverOpen(configIdByLocation)); - } - }} - > - - - } + button={} isOpen={configIdByLocation === isPopoverOpen} closePopover={closePopover} anchorPosition="upCenter" @@ -145,27 +107,43 @@ export const MetricItemIcon = ({ data-test-subj="syntheticsMetricItemIconButton" iconType="cross" onClick={closePopover} + aria-label={i18n.translate( + 'xpack.synthetics.metricItemIcon.euiButtonIcon.closePopover', + { + defaultMessage: 'Close popover', + } + )} /> -
- {ping?.url?.full && ( +
+ {latestPing?.url?.full && ( <> {i18n.translate('xpack.synthetics.metricItemIcon.div.urlLabel', { defaultMessage: 'URL: ', })} - {ping.url.full} + {latestPing.url.full} )} - + + ) + } + color="danger" + iconType="warning" + />
); } else { - if (ping?.url) { + if (latestPing?.url) { return ( ` - box-sizing: border-box; - display: flex; - flex-direction: column; - align-items: center; - gap: 10px; - width: 32px; - height: 32px; - background: ${({ theme }) => - theme.darkMode ? theme.eui.euiColorDarkestShade : theme.eui.euiColorLightestShade}; - border: 1px solid ${({ theme }) => - theme.darkMode ? theme.eui.euiColorDarkShade : theme.eui.euiColorLightShade}; - ${({ boxShadow }) => boxShadow} - border-radius: 16px; - flex: none; - order: 0; - flex-grow: 0; -`; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/use_latest_error.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/use_latest_error.tsx new file mode 100644 index 0000000000000..767385138f6ad --- /dev/null +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item/use_latest_error.tsx @@ -0,0 +1,41 @@ +/* + * 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 { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useSyntheticsRefreshContext } from '../../../../../contexts'; +import { + getMonitorLastErrorRunAction, + selectErrorPopoverState, + selectLastErrorRunMetadata, +} from '../../../../../state'; + +interface UseMonitorLatestPingParams { + monitorId: string; + locationLabel: string; + configIdByLocation: string; +} + +export const useLatestError = ({ + monitorId, + locationLabel, + configIdByLocation, +}: UseMonitorLatestPingParams) => { + const dispatch = useDispatch(); + const { lastRefresh } = useSyntheticsRefreshContext(); + const isPopoverOpen = useSelector(selectErrorPopoverState); + + const { data: latestPing, loading } = useSelector(selectLastErrorRunMetadata); + + useEffect(() => { + if (monitorId && locationLabel && isPopoverOpen === configIdByLocation) { + dispatch(getMonitorLastErrorRunAction.get({ monitorId, locationLabel })); + } + }, [dispatch, monitorId, locationLabel, lastRefresh, isPopoverOpen, configIdByLocation]); + + return { loading, latestPing }; +}; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_grid.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_grid.tsx index f0612498f8664..0c077faf6b9d3 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_grid.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_grid.tsx @@ -18,6 +18,7 @@ import { EuiAutoSizer, EuiAutoSize, } from '@elastic/eui'; +import { MetricItem } from './metric_item/metric_item'; import { ShowAllSpaces } from '../../common/show_all_spaces'; import { OverviewStatusMetaData } from '../../../../../../../common/runtime_types'; import { quietFetchOverviewStatusAction } from '../../../../state/overview_status'; @@ -40,7 +41,6 @@ import { SortFields } from './sort_fields'; import { NoMonitorsFound } from '../../common/no_monitors_found'; import { MonitorDetailFlyout } from './monitor_detail_flyout'; import { useSyntheticsRefreshContext } from '../../../../contexts'; -import { MetricItem } from './metric_item'; import { FlyoutParamProps } from './types'; const ITEM_HEIGHT = 172; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx index 518920ee0fd52..da9db1e163927 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx @@ -56,6 +56,7 @@ export interface SyntheticsSettingsContextValues { isDev?: boolean; isServerless?: boolean; setBreadcrumbs?: (crumbs: ChromeBreadcrumb[]) => void; + darkMode: boolean; } const { BASE_PATH } = CONTEXT_DEFAULTS; @@ -76,6 +77,7 @@ const defaultContext: SyntheticsSettingsContextValues = { isDev: false, canSave: false, canManagePrivateLocations: false, + darkMode: false, }; export const SyntheticsSettingsContext = createContext(defaultContext); @@ -91,6 +93,7 @@ export const SyntheticsSettingsContextProvider: React.FC { return { + darkMode, canSave, isDev, basePath, @@ -116,6 +120,7 @@ export const SyntheticsSettingsContextProvider: React.FC { ('[MONITOR DETAILS] GET LAST RUN'); +export const getMonitorLastErrorRunAction = createAsyncAction< + { monitorId: string; locationLabel: string }, + { ping?: Ping } +>('[MONITOR DETAILS] GET LAST ERROR RUN'); + export const resetMonitorLastRunAction = createAction('[MONITOR DETAILS] LAST RUN RESET'); export const updateMonitorLastRunAction = createAction<{ data: Ping }>( diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/api.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/api.ts index 31abd049a4dac..3e35295221ce8 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/api.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/api.ts @@ -43,7 +43,7 @@ export const fetchMonitorRecentPings = async ({ { monitorId, from: from ?? moment().subtract(30, 'days').toISOString(), - to: to ?? new Date().toISOString(), + to: to ?? moment().toISOString(), locations, sort, size, diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/effects.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/effects.ts index bd7a9e8386c20..ee97477db95b5 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/effects.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/effects.ts @@ -15,6 +15,7 @@ import { getMonitorRecentPingsAction, getMonitorAction, updateMonitorLastRunAction, + getMonitorLastErrorRunAction, } from './actions'; import { fetchSyntheticsMonitor, fetchMonitorRecentPings, fetchLatestTestRun } from './api'; import { selectLastRunMetadata } from './selectors'; @@ -38,6 +39,15 @@ export function* fetchSyntheticsMonitorEffect() { ) ); + yield takeLeading( + getMonitorLastErrorRunAction.get, + fetchEffectFactory( + fetchLatestTestRun, + getMonitorLastErrorRunAction.success, + getMonitorLastErrorRunAction.fail + ) + ); + // Additional listener on `getMonitorRecentPingsAction.success` to possibly update the `lastRun` as well yield takeEvery( getMonitorRecentPingsAction.success, diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/index.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/index.ts index d7130d7240926..2dd51a0c93694 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/index.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/index.ts @@ -20,6 +20,7 @@ import { setMonitorDetailsLocationAction, getMonitorAction, setStatusFilter, + getMonitorLastErrorRunAction, } from './actions'; export interface MonitorDetailsState { @@ -33,6 +34,10 @@ export interface MonitorDetailsState { loading: boolean; loaded: boolean; }; + lastErrorRun: { + data?: Ping; + loading: boolean; + }; syntheticsMonitorLoading: boolean; syntheticsMonitor: SyntheticsMonitorWithId | null; syntheticsMonitorError?: IHttpSerializedFetchError | null; @@ -45,6 +50,7 @@ export interface MonitorDetailsState { const initialState: MonitorDetailsState = { pings: { total: 0, data: [], loading: false }, lastRun: { loading: false, loaded: false }, + lastErrorRun: { loading: false }, syntheticsMonitor: null, syntheticsMonitorLoading: false, syntheticsMonitorDispatchedAt: 0, @@ -73,6 +79,21 @@ export const monitorDetailsReducer = createReducer(initialState, (builder) => { state.lastRun.loading = false; state.error = action.payload; }) + .addCase(getMonitorLastErrorRunAction.get, (state, action) => { + state.lastErrorRun.loading = true; + const configId = state.lastErrorRun?.data?.config_id; + if (action.payload.monitorId !== configId) { + state.lastErrorRun.data = undefined; + } + }) + .addCase(getMonitorLastErrorRunAction.success, (state, action) => { + state.lastErrorRun.loading = false; + state.lastErrorRun.data = action.payload?.ping; + }) + .addCase(getMonitorLastErrorRunAction.fail, (state, action) => { + state.lastErrorRun.loading = false; + state.error = action.payload; + }) .addCase(updateMonitorLastRunAction, (state, action) => { state.lastRun.data = action.payload.data; }) diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/selectors.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/selectors.ts index 47d116594eb3b..93528f9c0ae5e 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/selectors.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/monitor_details/selectors.ts @@ -19,6 +19,7 @@ export const selectSelectedLocationId = createSelector( ); export const selectLastRunMetadata = createSelector(getState, (state) => state.lastRun); +export const selectLastErrorRunMetadata = createSelector(getState, (state) => state.lastErrorRun); export const selectPingsLoading = createSelector(getState, (state) => state.pings.loading); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts index dc71f90ea9e18..10d3145bd560f 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts @@ -197,6 +197,9 @@ function getBrowserJourneyMockSlice() { function getMonitorDetailsMockSlice() { return { + lastErrorRun: { + loading: false, + }, lastRun: { loading: false, loaded: true,