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

[Infra UI] Fix page content reload when date picker has relative dates #165462

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { memoryUsage, memoryUsageBreakdown } from '../metric_charts/memory';
import { rxTx } from '../metric_charts/network';
import type { XYConfig } from '../metric_charts/types';

export const hostMetricCharts: XYConfig[] = [
export const hostMetricFlyoutCharts: XYConfig[] = [
cpuUsage,
memoryUsage,
normalizedLoad1m,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
* 2.0.
*/

import { hostMetricCharts, hostMetricChartsFullPage } from './host/host_metric_charts';
import { hostMetricFlyoutCharts, hostMetricChartsFullPage } from './host/host_metric_charts';
import { hostKPICharts, KPIChartProps } from './host/host_kpi_charts';
import { nginxAccessCharts, nginxStubstatusCharts } from './host/nginx_charts';

export { type KPIChartProps };
export const assetDetailsDashboards = {
host: { hostMetricCharts, hostMetricChartsFullPage, hostKPICharts },
nginxDashboard: { nginxStubstatusCharts, nginxAccessCharts },
host: { hostMetricFlyoutCharts, hostMetricChartsFullPage, hostKPICharts },
nginx: { nginxStubstatusCharts, nginxAccessCharts },
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,66 @@

import type { TimeRange } from '@kbn/es-query';
import createContainer from 'constate';
import { useCallback, useMemo } from 'react';
import { useCallback, useState } from 'react';
import useEffectOnce from 'react-use/lib/useEffectOnce';
import { parseDateRange } from '../../../utils/datemath';

import { toTimestampRange } from '../utils';
import { useAssetDetailsUrlState } from './use_asset_details_url_state';

const DEFAULT_DATE_RANGE: TimeRange = {
from: 'now-15m',
to: 'now',
};

export interface UseDateRangeProviderProps {
initialDateRange: TimeRange;
}

const DEFAULT_FROM_IN_MILLISECONDS = 15 * 60000;
const getDefaultDateRange = () => {
const now = Date.now();

return {
from: new Date(now - DEFAULT_FROM_IN_MILLISECONDS).toISOString(),
to: new Date(now).toISOString(),
};
};

export function useDateRangeProvider({ initialDateRange }: UseDateRangeProviderProps) {
const [urlState, setUrlState] = useAssetDetailsUrlState();
const dateRange: TimeRange = urlState?.dateRange ?? initialDateRange;
const [parsedDateRange, setParsedDateRange] = useState(parseDateRange(dateRange));
const [refreshTs, setRefreshTs] = useState(Date.now());

useEffectOnce(() => {
const { from, to } = getParsedDateRange();

// forces the date picker to initiallize with absolute dates.
setUrlState({ dateRange: { from, to } });
});

const setDateRange = useCallback(
(newDateRange: TimeRange) => {
setUrlState({ dateRange: newDateRange });
setParsedDateRange(parseDateRange(newDateRange));
setRefreshTs(Date.now());
},
[setUrlState]
);

const parsedDateRange = useMemo(() => {
const { from = DEFAULT_DATE_RANGE.from, to = DEFAULT_DATE_RANGE.to } =
parseDateRange(dateRange);
const getParsedDateRange = useCallback(() => {
const defaultDateRange = getDefaultDateRange();
const { from = defaultDateRange.from, to = defaultDateRange.to } = parsedDateRange;

return { from, to };
}, [dateRange]);
}, [parsedDateRange]);

const getDateRangeInTimestamp = useCallback(
() => toTimestampRange(parsedDateRange),
[parsedDateRange]
);
const getDateRangeInTimestamp = useCallback(() => {
return toTimestampRange(getParsedDateRange());
}, [getParsedDateRange]);

return { dateRange, setDateRange, getDateRangeInTimestamp };
return {
dateRange,
getDateRangeInTimestamp,
getParsedDateRange,
refreshTs,
setDateRange,
};
}

export const [DateRangeProvider, useDateRangeProviderContext] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
KPI_CHART_HEIGHT,
AVERAGE_SUBTITLE,
} from '../../../../../common/visualizations';
import { useDateRangeProviderContext } from '../../../hooks/use_date_range';

interface Props {
dataView?: DataView;
Expand All @@ -24,6 +25,7 @@ interface Props {
}

export const KPIGrid = React.memo(({ nodeName, dataView, timeRange }: Props) => {
const { refreshTs } = useDateRangeProviderContext();
const filters = useMemo(() => {
return [
buildCombinedHostsFilter({
Expand All @@ -43,6 +45,7 @@ export const KPIGrid = React.memo(({ nodeName, dataView, timeRange }: Props) =>
dataView={dataView}
dateRange={timeRange}
layers={{ ...layers, options: { ...layers.options, subtitle: AVERAGE_SUBTITLE } }}
lastReloadRequestTime={refreshTs}
height={KPI_CHART_HEIGHT}
filters={filters}
title={title}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@ import { MetricsSectionTitle, NginxMetricsSectionTitle } from '../../../componen

interface Props {
assetName: string;
timeRange: TimeRange;
dateRange: TimeRange;
metricsDataView?: DataView;
logsDataView?: DataView;
}

const { host, nginx } = assetDetailsDashboards;

export const MetricsGrid = React.memo(
({ assetName, metricsDataView, logsDataView, timeRange }: Props) => {
({ assetName, metricsDataView, logsDataView, dateRange: timeRange }: Props) => {
return (
<>
<Section title={MetricsSectionTitle}>
<ChartGrid
assetName={assetName}
timeRange={timeRange}
charts={assetDetailsDashboards.host.hostMetricChartsFullPage}
charts={host.hostMetricChartsFullPage}
metricsDataView={metricsDataView}
logsDataView={logsDataView}
data-test-subj="infraAssetDetailsMetricsChart"
Expand All @@ -40,12 +42,12 @@ export const MetricsGrid = React.memo(
assetName={assetName}
timeRange={timeRange}
charts={[
...assetDetailsDashboards.nginxDashboard.nginxStubstatusCharts.map((n) => ({
...n,
...nginx.nginxStubstatusCharts.map((chart) => ({
...chart,
dependsOn: ['nginx.stubstatus'],
})),
...assetDetailsDashboards.nginxDashboard.nginxAccessCharts.map((n) => ({
...n,
...nginx.nginxAccessCharts.map((chart) => ({
...chart,
dependsOn: ['nginx.access'],
})),
]}
Expand All @@ -63,13 +65,13 @@ export const MetricsGridCompact = ({
assetName,
metricsDataView,
logsDataView,
timeRange,
dateRange: timeRange,
}: Props) => (
<Section title={MetricsSectionTitle}>
<ChartGrid
assetName={assetName}
timeRange={timeRange}
charts={assetDetailsDashboards.host.hostMetricCharts}
charts={host.hostMetricFlyoutCharts}
metricsDataView={metricsDataView}
logsDataView={logsDataView}
data-test-subj="infraAssetDetailsMetricsChart"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { useDateRangeProviderContext } from '../../hooks/use_date_range';
import { SectionSeparator } from './section_separator';

export const Overview = () => {
const { dateRange } = useDateRangeProviderContext();
const { getParsedDateRange } = useDateRangeProviderContext();
const { asset, assetType, renderMode } = useAssetDetailsRenderPropsContext();
const {
metadata,
Expand All @@ -32,18 +32,19 @@ export const Overview = () => {
} = useMetadataStateProviderContext();
const { logs, metrics } = useDataViewsProviderContext();

const parsedDateRange = getParsedDateRange();
const isFullPageView = renderMode.mode !== 'flyout';

const metricsSection = isFullPageView ? (
<MetricsGrid
timeRange={dateRange}
dateRange={parsedDateRange}
logsDataView={logs.dataView}
metricsDataView={metrics.dataView}
assetName={asset.name}
/>
) : (
<MetricsGridCompact
timeRange={dateRange}
dateRange={parsedDateRange}
logsDataView={logs.dataView}
metricsDataView={metrics.dataView}
assetName={asset.name}
Expand All @@ -58,7 +59,7 @@ export const Overview = () => {
return (
<EuiFlexGroup direction="column" gutterSize="m">
<EuiFlexItem grow={false}>
<KPIGrid nodeName={asset.name} timeRange={dateRange} dataView={metrics.dataView} />
<KPIGrid nodeName={asset.name} timeRange={parsedDateRange} dataView={metrics.dataView} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
{fetchMetadataError ? (
Expand Down Expand Up @@ -88,12 +89,16 @@ export const Overview = () => {
/>
</EuiCallOut>
) : (
<>{metadataSummarySection}</>
metadataSummarySection
)}
<SectionSeparator />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<AlertsSummaryContent assetName={asset.name} assetType={assetType} dateRange={dateRange} />
<AlertsSummaryContent
assetName={asset.name}
assetType={assetType}
dateRange={parsedDateRange}
/>
<SectionSeparator />
</EuiFlexItem>
<EuiFlexItem grow={false}>{metricsSection}</EuiFlexItem>
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/infra/public/components/lens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export { ChartPlaceholder } from './chart_placeholder';
export { TooltipContent } from './metric_explanation/tooltip_content';
export { HostMetricsDocsLink } from './metric_explanation/host_metrics_docs_link';
export { HostMetricsExplanationContent } from './metric_explanation/host_metrics_explanation_content';

export * from './types';
39 changes: 17 additions & 22 deletions x-pack/plugins/infra/public/components/lens/lens_chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,43 +56,38 @@ export const LensChart = ({

const sytle: CSSProperties = useMemo(() => ({ height }), [height]);

const Lens = (
const lens = (
jennypavlova marked this conversation as resolved.
Show resolved Hide resolved
<LensWrapper
id={id}
attributes={attributes}
dateRange={dateRange}
disableTriggers={disableTriggers}
extraActions={extraActions}
filters={filters}
hidePanelTitles={hidePanelTitles}
lastReloadRequestTime={lastReloadRequestTime}
loading={isLoading}
style={sytle}
query={query}
overrides={overrides}
onBrushEnd={onBrushEnd}
hidePanelTitles={hidePanelTitles}
/>
);

const getContent = () => {
if (!toolTip) {
return Lens;
}

return (
<EuiToolTip
delay="regular"
content={React.cloneElement(toolTip, {
formula,
})}
anchorClassName="eui-fullWidth"
>
{/* EuiToolTip forwards some event handlers to the child component.
const content = !toolTip ? (
lens
) : (
<EuiToolTip
delay="regular"
content={React.cloneElement(toolTip, {
formula,
})}
anchorClassName="eui-fullWidth"
>
{/* EuiToolTip forwards some event handlers to the child component.
Wrapping Lens inside a div prevents that from causing unnecessary re-renders */}
<div>{Lens}</div>
</EuiToolTip>
);
};
<div>{lens}</div>
</EuiToolTip>
);

return (
<EuiPanel
Expand All @@ -106,7 +101,7 @@ export const LensChart = ({
min-height: ${height}px;
`}
>
{error ? <ChartLoadError /> : getContent()}
{error ? <ChartLoadError /> : content}
</EuiPanel>
);
};
33 changes: 15 additions & 18 deletions x-pack/plugins/infra/public/components/lens/lens_wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/
import React, { useEffect, useState, useRef, useCallback, useMemo } from 'react';
import type { Action } from '@kbn/ui-actions-plugin/public';

import { ViewMode } from '@kbn/embeddable-plugin/public';
import type { TimeRange } from '@kbn/es-query';
import { TypedLensByValueInput } from '@kbn/lens-plugin/public';
Expand All @@ -15,23 +15,15 @@ import { LensAttributes } from '@kbn/lens-embeddable-utils';
import { useKibanaContextForPlugin } from '../../hooks/use_kibana';
import { ChartLoadingProgress, ChartPlaceholder } from './chart_placeholder';
import { parseDateRange } from '../../utils/datemath';

export type LensWrapperProps = Omit<
TypedLensByValueInput,
'timeRange' | 'attributes' | 'viewMode'
> & {
attributes: LensAttributes | null;
dateRange: TimeRange;
extraActions: Action[];
loading?: boolean;
};
import type { LensWrapperProps } from './types';

export const LensWrapper = ({
attributes,
dateRange,
filters,
lastReloadRequestTime,
loading = false,
onLoad,
query,
...props
}: LensWrapperProps) => {
Expand Down Expand Up @@ -85,11 +77,17 @@ export const LensWrapper = ({
query,
]);

const onLoad = useCallback(() => {
if (!embeddableLoaded) {
setEmbeddableLoaded(true);
}
}, [embeddableLoaded]);
const handleOnLoad = useCallback(
(isLoading: boolean) => {
if (!embeddableLoaded) {
setEmbeddableLoaded(true);
}
if (onLoad) {
onLoad(isLoading);
}
},
[embeddableLoaded, onLoad]
);

const parsedDateRange: TimeRange = useMemo(() => {
const { from = state.dateRange.from, to = state.dateRange.to } = parseDateRange(
Expand All @@ -104,7 +102,6 @@ export const LensWrapper = ({
<div
css={css`
position: relative;
border-radius: ${euiTheme.size.s};
Copy link
Contributor Author

@crespocarlos crespocarlos Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a space between the triple dots button and the border

now:
image

then:
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks for the fix!

overflow: hidden;
height: 100%;
.echMetric {
Expand All @@ -125,7 +122,7 @@ export const LensWrapper = ({
attributes={state.attributes}
filters={state.filters}
lastReloadRequestTime={state.lastReloadRequestTime}
onLoad={onLoad}
onLoad={handleOnLoad}
query={state.query}
timeRange={parsedDateRange}
viewMode={ViewMode.VIEW}
Expand Down
Loading