[8.6] [Uptime] Don't show no data state while loading for ping histogram (#145244) (#146064)

# Backport

This will backport the following commits from `main` to `8.6`:
- [[Uptime] Don't show no data state while loading for ping histogram
(#145244)](https://github.com/elastic/kibana/pull/145244)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"Shahzad","email":"shahzad.muhammad@elastic.co"},"sourceCommit":{"committedDate":"2022-11-22T19:51:42Z","message":"[Uptime]
Don't show no data state while loading for ping histogram
(#145244)\n\nFixes
https://github.com/elastic/kibana/issues/145243","sha":"c3b96a379a341ad842fb01bd0eab533baa7fcf8f","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:uptime","release_note:skip","v8.6.0","v8.7.0"],"number":145244,"url":"https://github.com/elastic/kibana/pull/145244","mergeCommit":{"message":"[Uptime]
Don't show no data state while loading for ping histogram
(#145244)\n\nFixes
https://github.com/elastic/kibana/issues/145243","sha":"c3b96a379a341ad842fb01bd0eab533baa7fcf8f"}},"sourceBranch":"main","suggestedTargetBranches":["8.6"],"targetPullRequestStates":[{"branch":"8.6","label":"v8.6.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/145244","number":145244,"mergeCommit":{"message":"[Uptime]
Don't show no data state while loading for ping histogram
(#145244)\n\nFixes
https://github.com/elastic/kibana/issues/145243","sha":"c3b96a379a341ad842fb01bd0eab533baa7fcf8f"}}]}]
BACKPORT-->

Co-authored-by: Shahzad <shahzad.muhammad@elastic.co>
This commit is contained in:
Kibana Machine 2022-11-23 05:42:44 -05:00 committed by GitHub
parent 7b99f4c6cd
commit 1e89fbe536
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 66 additions and 84 deletions

View file

@ -17,24 +17,20 @@ import {
ElementClickListener,
ScaleType,
} from '@elastic/charts';
import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui';
import { EuiTitle, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useContext } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import numeral from '@elastic/numeral';
import moment from 'moment';
import { useSelector } from 'react-redux';
import { createExploratoryViewUrl } from '@kbn/observability-plugin/public';
import { getChartDateLabel } from '../../../lib/helper';
import { ChartWrapper } from './chart_wrapper';
import { UptimeThemeContext } from '../../../contexts';
import { HistogramResult } from '../../../../../common/runtime_types';
import { useMonitorId, useUrlParams } from '../../../hooks';
import { useUrlParams } from '../../../hooks';
import { ChartEmptyState } from './chart_empty_state';
import { getDateRangeFromChartElement } from './utils';
import { STATUS_DOWN_LABEL, STATUS_UP_LABEL } from '../translations';
import { useUptimeSettingsContext } from '../../../contexts/uptime_settings_context';
import { monitorStatusSelector } from '../../../state/selectors';
export interface PingHistogramComponentProps {
/**
@ -77,18 +73,10 @@ export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
chartTheme,
} = useContext(UptimeThemeContext);
const monitorId = useMonitorId();
const selectedMonitor = useSelector(monitorStatusSelector);
const { basePath } = useUptimeSettingsContext();
const [getUrlParams, updateUrlParams] = useUrlParams();
const { dateRangeStart, dateRangeEnd } = getUrlParams();
const [_getUrlParams, updateUrlParams] = useUrlParams();
let content: JSX.Element | undefined;
if (!data?.histogram?.length) {
if (!data?.histogram?.length && !loading) {
content = (
<ChartEmptyState
title={i18n.translate('xpack.synthetics.snapshot.noDataTitle', {
@ -100,7 +88,7 @@ export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
/>
);
} else {
const { histogram, minInterval } = data;
const { histogram, minInterval } = data ?? {};
const onBrushEnd: BrushEndListener = ({ x }) => {
if (!x) {
@ -115,13 +103,13 @@ export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
const onBarClicked: ElementClickListener = ([elementData]) => {
updateUrlParams(
getDateRangeFromChartElement(elementData as XYChartElementEvent, minInterval)
getDateRangeFromChartElement(elementData as XYChartElementEvent, minInterval!)
);
};
const barData: BarPoint[] = [];
histogram.forEach(({ x, upCount, downCount }) => {
histogram?.forEach(({ x, upCount, downCount }) => {
barData.push(
{ x, y: downCount ?? 0, type: STATUS_DOWN_LABEL },
{ x, y: upCount ?? 0, type: STATUS_UP_LABEL }
@ -195,29 +183,6 @@ export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
);
}
const pingHistogramExploratoryViewLink = createExploratoryViewUrl(
{
reportType: 'kpi-over-time',
allSeries: [
{
name: `${monitorId}-pings`,
dataType: 'synthetics',
selectedMetricField: 'summary.up',
time: { from: dateRangeStart, to: dateRangeEnd },
reportDefinitions: {
'monitor.name':
monitorId && selectedMonitor?.monitor?.name
? [selectedMonitor.monitor.name]
: ['ALL_VALUES'],
},
},
],
},
basePath
);
const showAnalyzeButton = false;
return (
<>
<EuiFlexGroup>
@ -231,16 +196,6 @@ export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
</h2>
</EuiTitle>
</EuiFlexItem>
{showAnalyzeButton && (
<EuiFlexItem grow={false}>
<EuiButton size="s" href={pingHistogramExploratoryViewLink}>
<FormattedMessage
id="xpack.synthetics.pingHistogram.analyze"
defaultMessage="Analyze"
/>
</EuiButton>
</EuiFlexItem>
)}
</EuiFlexGroup>
{content}
</>

View file

@ -29,7 +29,7 @@ const Container: React.FC<Props & ResponsiveWrapperProps> = ({ height }) => {
dateRangeStart: dateStart,
dateRangeEnd: dateEnd,
} = useGetUrlParams();
const filterCheck = useOverviewFilterCheck();
const { filterCheck, pending } = useOverviewFilterCheck();
const dispatch = useDispatch();
const monitorId = useMonitorId();
@ -76,7 +76,7 @@ const Container: React.FC<Props & ResponsiveWrapperProps> = ({ height }) => {
absoluteStartDate={absoluteDateRangeStart}
absoluteEndDate={absoluteDateRangeEnd}
height={height}
loading={loading}
loading={loading || pending}
timeZone={timeZone}
/>
);

View file

@ -44,6 +44,7 @@ interface Props extends MonitorListProps {
setPageSize: (val: number) => void;
monitorList: MonitorList;
refreshedMonitorIds: string[];
isPending?: boolean;
}
export const MonitorListComponent: ({
@ -52,12 +53,14 @@ export const MonitorListComponent: ({
pageSize,
refreshedMonitorIds,
setPageSize,
isPending,
}: Props) => any = ({
filters,
refreshedMonitorIds = [],
monitorList: { list, error, loading },
pageSize,
setPageSize,
isPending,
}) => {
const [expandedDrawerIds, updateExpandedDrawerIds] = useState<string[]>([]);
const currentBreakpoint = useCurrentEuiBreakpoint();
@ -247,13 +250,15 @@ export const MonitorListComponent: ({
<EuiBasicTable
aria-label={labels.getDescriptionLabel(items.length)}
error={error?.body?.message || error?.message}
loading={loading}
loading={loading || isPending}
isExpandable={true}
hasActions={true}
itemId="monitor_id"
itemIdToExpandedRowMap={getExpandedRowMap()}
items={items}
noItemsMessage={<NoItemsMessage loading={loading} filters={filters} />}
noItemsMessage={
<NoItemsMessage loading={Boolean(loading || isPending)} filters={filters} />
}
columns={columns}
tableLayout={'auto'}
rowProps={

View file

@ -33,7 +33,7 @@ const getPageSizeValue = () => {
export const MonitorList: React.FC<MonitorListProps> = (props) => {
const filters = useSelector(esKuerySelector);
const filterCheck = useOverviewFilterCheck();
const { filterCheck, pending } = useOverviewFilterCheck();
const [pageSize, setPageSize] = useState<number>(getPageSizeValue);
@ -101,6 +101,7 @@ export const MonitorList: React.FC<MonitorListProps> = (props) => {
pageSize={pageSize}
setPageSize={setPageSize}
refreshedMonitorIds={refreshedMonitorIds}
isPending={pending}
/>
);
};

View file

@ -9,18 +9,25 @@ import React, { useState, useEffect } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiCallOut, EuiLink, EuiButton, EuiFlexItem, EuiFlexGroup, EuiSpacer } from '@elastic/eui';
import { useFetcher } from '@kbn/observability-plugin/public';
import { useSelector } from 'react-redux';
import { getHasZipUrlMonitors } from '../../../state/api/has_zip_url_monitors';
import { getDocLinks } from '../../../../kibana_services';
import { monitorListSelector } from '../../../state/selectors';
export const ZIP_URL_DEPRECATION_SESSION_STORAGE_KEY =
'SYNTHETICS_ZIP_URL_DEPRECATION_HAS_BEEN_DISMISSED';
export const ZipUrlDeprecation = () => {
const monitorList = useSelector(monitorListSelector);
const noticeHasBeenDismissed =
window.sessionStorage.getItem(ZIP_URL_DEPRECATION_SESSION_STORAGE_KEY) === 'true';
const { data, loading } = useFetcher(() => {
return getHasZipUrlMonitors();
}, []);
// load it when list is loaded
if (!noticeHasBeenDismissed && monitorList.isLoaded) {
return getHasZipUrlMonitors();
}
return undefined;
}, [monitorList.isLoaded]);
const hasZipUrlMonitors = !loading && data && data.hasZipUrlMonitors;
const [shouldShowNotice, setShouldShowNotice] = useState(
Boolean(hasZipUrlMonitors && !noticeHasBeenDismissed)

View file

@ -45,7 +45,7 @@ describe('useOverviewFilterCheck', () => {
} = renderHook(() => useOverviewFilterCheck(), { wrapper: getWrapper() });
const fn = jest.fn();
current(fn);
current.filterCheck(fn);
expect(fn).toHaveBeenCalledTimes(1);
});
@ -57,7 +57,7 @@ describe('useOverviewFilterCheck', () => {
});
const fn = jest.fn();
current(fn);
current.filterCheck(fn);
expect(fn).not.toHaveBeenCalled();
});
@ -70,7 +70,7 @@ describe('useOverviewFilterCheck', () => {
});
const fn = jest.fn();
current(fn);
current.filterCheck(fn);
expect(fn).toHaveBeenCalledTimes(1);
});
@ -83,7 +83,7 @@ describe('useOverviewFilterCheck', () => {
});
const fn = jest.fn();
current(fn);
current.filterCheck(fn);
expect(fn).not.toHaveBeenCalledTimes(1);
});
@ -96,7 +96,7 @@ describe('useOverviewFilterCheck', () => {
});
const fn = jest.fn();
current(fn);
current.filterCheck(fn);
expect(fn).toHaveBeenCalledTimes(1);
});
});

View file

@ -42,12 +42,15 @@ export function useOverviewFilterCheck() {
*/
const shouldRun = !!filters || !hasFilters(search);
return useCallback(
(fn: () => void) => {
if (shouldRun) {
fn();
}
},
[shouldRun]
);
return {
pending: !shouldRun,
filterCheck: useCallback(
(fn: () => void) => {
if (shouldRun) {
fn();
}
},
[shouldRun]
),
};
}

View file

@ -21,6 +21,7 @@ import type { TestNowResponse } from '../api';
export interface MonitorList {
loading: boolean;
isLoaded?: boolean;
refreshedMonitorIds?: string[];
isUpdating?: string[];
list: MonitorSummariesResult;
@ -34,6 +35,7 @@ export const initialState: MonitorList = {
summaries: [],
},
loading: false,
isLoaded: false,
refreshedMonitorIds: [],
};
@ -54,6 +56,7 @@ export const monitorListReducer = handleActions<MonitorList, Payload>(
) => ({
...state,
loading: false,
isLoaded: true,
error: undefined,
list: { ...action.payload },
}),
@ -64,6 +67,7 @@ export const monitorListReducer = handleActions<MonitorList, Payload>(
...state,
error: action.payload,
loading: false,
isLoaded: true,
}),
[String(setUpdatingMonitorId)]: (state: MonitorList, action: Action<string>) => ({
...state,

View file

@ -55,6 +55,7 @@ export function createUptimeESClient({
}) {
return {
baseESClient: esClient,
heartbeatIndices: '',
async search<DocumentSource extends unknown, TParams extends estypes.SearchRequest>(
params: TParams,
operationName?: string,
@ -62,11 +63,16 @@ export function createUptimeESClient({
): Promise<{ body: ESSearchResponse<DocumentSource, TParams> }> {
let res: any;
let esError: any;
const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings(
savedObjectsClient!
);
const esParams = { index: index ?? dynamicSettings!.heartbeatIndices, ...params };
if (!this.heartbeatIndices) {
const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings(
savedObjectsClient!
);
this.heartbeatIndices = dynamicSettings?.heartbeatIndices || '';
}
const esParams = { index: index ?? this.heartbeatIndices, ...params };
const startTime = process.hrtime();
const startTimeNow = Date.now();
@ -110,11 +116,15 @@ export function createUptimeESClient({
let res: any;
let esError: any;
const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings(
savedObjectsClient!
);
if (!this.heartbeatIndices) {
const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings(
savedObjectsClient!
);
const esParams = { index: dynamicSettings!.heartbeatIndices, ...params };
this.heartbeatIndices = dynamicSettings?.heartbeatIndices || '';
}
const esParams = { index: this.heartbeatIndices, ...params };
const startTime = process.hrtime();
try {
@ -132,7 +142,7 @@ export function createUptimeESClient({
throw esError;
}
return { result: res, indices: dynamicSettings.heartbeatIndices };
return { result: res, indices: this.heartbeatIndices };
},
getSavedObjectsClient() {
return savedObjectsClient;

View file

@ -31234,7 +31234,6 @@
"xpack.synthetics.page_header.manageMonitors": "Gestion des moniteurs",
"xpack.synthetics.page_header.settingsLink": "Paramètres",
"xpack.synthetics.page_header.settingsLink.label": "Accédez à la page de paramètres Uptime",
"xpack.synthetics.pingHistogram.analyze": "Analyser",
"xpack.synthetics.pingList.checkHistoryTitle": "Historique",
"xpack.synthetics.pingList.collapseRow": "Réduire",
"xpack.synthetics.pingList.columns.failedStep": "Étape ayant échoué",

View file

@ -31210,7 +31210,6 @@
"xpack.synthetics.page_header.manageMonitors": "モニター管理",
"xpack.synthetics.page_header.settingsLink": "設定",
"xpack.synthetics.page_header.settingsLink.label": "アップタイム設定ページに移動",
"xpack.synthetics.pingHistogram.analyze": "分析",
"xpack.synthetics.pingList.checkHistoryTitle": "履歴",
"xpack.synthetics.pingList.collapseRow": "縮小",
"xpack.synthetics.pingList.columns.failedStep": "失敗したステップ",

View file

@ -31245,7 +31245,6 @@
"xpack.synthetics.page_header.manageMonitors": "监测管理",
"xpack.synthetics.page_header.settingsLink": "设置",
"xpack.synthetics.page_header.settingsLink.label": "导航到 Uptime 设置页面",
"xpack.synthetics.pingHistogram.analyze": "分析",
"xpack.synthetics.pingList.checkHistoryTitle": "历史记录",
"xpack.synthetics.pingList.collapseRow": "折叠",
"xpack.synthetics.pingList.columns.failedStep": "失败的步骤",