Skip to content

Commit

Permalink
Move Metrics Explorer date span, range into redux metrics-slice (#1105)
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Fitzgibbons <peter.fitzgibbons@gmail.com>
  • Loading branch information
pjfitzgibbons authored Oct 10, 2023
1 parent 4a8b500 commit f981407
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 171 deletions.
20 changes: 0 additions & 20 deletions public/components/metrics/helpers/__tests__/utils.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,6 @@ import _ from 'lodash';
describe('Utils helper functions', () => {
configure({ adapter: new Adapter() });

it('validates onTimeChange function', () => {
const setRecentlyUsedRanges = jest.fn((x) => x);
const setStart = jest.fn();
const setEnd = jest.fn();
const recentlyUsedRanges: DurationRange[] = [];
onTimeChange(
'2022-01-30T18:44:40.577Z',
'2022-02-25T19:18:33.075Z',
recentlyUsedRanges,
setRecentlyUsedRanges,
setStart,
setEnd
);
expect(setRecentlyUsedRanges).toHaveBeenCalledWith([
{ start: '2022-01-30T18:44:40.577Z', end: '2022-02-25T19:18:33.075Z' },
]);
expect(setStart).toHaveBeenCalledWith('2022-01-30T18:44:40.577Z');
expect(setEnd).toHaveBeenCalledWith('2022-02-25T19:18:33.075Z');
});

it('validates getNewVizDimensions function', () => {
expect(getNewVizDimensions([])).toMatchObject({
x: 0,
Expand Down
36 changes: 9 additions & 27 deletions public/components/metrics/helpers/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,6 @@ import { VisualizationType } from '../../../../common/types/custom_panels';
import { DEFAULT_METRIC_HEIGHT, DEFAULT_METRIC_WIDTH } from '../../../../common/constants/metrics';
import { updateQuerySpanInterval } from '../../custom_panels/helpers/utils';

export const onTimeChange = (
start: ShortDate,
end: ShortDate,
recentlyUsedRanges: DurationRange[],
setRecentlyUsedRanges: React.Dispatch<React.SetStateAction<DurationRange[]>>,
setStart: React.Dispatch<React.SetStateAction<string>>,
setEnd: React.Dispatch<React.SetStateAction<string>>
) => {
const recentlyUsedRange = recentlyUsedRanges.filter((recentlyUsedRange) => {
const isDuplicate = recentlyUsedRange.start === start && recentlyUsedRange.end === end;
return !isDuplicate;
});
recentlyUsedRange.unshift({ start, end });
setStart(start);
setEnd(end);
setRecentlyUsedRanges(recentlyUsedRange.slice(0, 9));
};

// PPL Service requestor
export const pplServiceRequestor = (pplService: PPLService, finalQuery: string) => {
return pplService.fetch({ query: finalQuery, format: VISUALIZATION }).catch((error: Error) => {
Expand All @@ -58,21 +40,21 @@ export const getVisualizations = (http: CoreStart['http']) => {
});
};

interface boxType {
interface BoxType {
x1: number;
y1: number;
x2: number;
y2: number;
}

const calculatOverlapArea = (bb1: boxType, bb2: boxType) => {
const x_left = Math.max(bb1.x1, bb2.x1);
const y_top = Math.max(bb1.y1, bb2.y1);
const x_right = Math.min(bb1.x2, bb2.x2);
const y_bottom = Math.min(bb1.y2, bb2.y2);
const calculatOverlapArea = (bb1: BoxType, bb2: BoxType) => {
const xLeft = Math.max(bb1.x1, bb2.x1);
const yTop = Math.max(bb1.y1, bb2.y1);
const xRight = Math.min(bb1.x2, bb2.x2);
const yBottom = Math.min(bb1.y2, bb2.y2);

if (x_right < x_left || y_bottom < y_top) return 0;
return (x_right - x_left) * (y_bottom - y_top);
if (xRight < xLeft || yBottom < yTop) return 0;
return (xRight - xLeft) * (yBottom - yTop);
};

const getTotalOverlapArea = (panelVisualizations: MetricType[]) => {
Expand Down Expand Up @@ -149,7 +131,7 @@ export const mergeLayoutAndMetrics = (

for (let i = 0; i < newVisualizationList.length; i++) {
for (let j = 0; j < layout.length; j++) {
if (newVisualizationList[i].id == layout[j].i) {
if (newVisualizationList[i].id === layout[j].i) {
newPanelVisualizations.push({
...newVisualizationList[i],
x: layout[j].x,
Expand Down
44 changes: 0 additions & 44 deletions public/components/metrics/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ import {
OnTimeChangeProps,
ShortDate,
} from '@elastic/eui';
import { DurationRange } from '@elastic/eui/src/components/date_picker/types';
import React, { ReactChild, useEffect, useState } from 'react';
import { HashRouter, Route, RouteComponentProps } from 'react-router-dom';
import { StaticContext } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { ChromeBreadcrumb, Toast } from '../../../../../src/core/public';
import { onTimeChange } from './helpers/utils';
import { Sidebar } from './sidebar/sidebar';
import { EmptyMetricsView } from './view/empty_view';
import PPLService from '../../services/requests/ppl';
Expand All @@ -44,19 +42,10 @@ export const Home = ({ chrome, parentBreadcrumb }: MetricsProps) => {
const selectedMetrics = useSelector(selectedMetricsSelector);
const metricsLayout = useSelector(metricsLayoutSelector);

// Date picker constants
const [recentlyUsedRanges, setRecentlyUsedRanges] = useState<DurationRange[]>([]);
const [startTime, setStartTime] = useState<ShortDate>('now-1d');
const [endTime, setEndTime] = useState<ShortDate>('now');

// Top panel
const [IsTopPanelDisabled, setIsTopPanelDisabled] = useState(false);
const [editMode, setEditMode] = useState(false);
const [onRefresh, setOnRefresh] = useState(false);
const [editActionType, setEditActionType] = useState('');
const [resolutionValue, setResolutionValue] = useState(resolutionOptions[2].value);
const [spanValue, setSpanValue] = useState(1);
const resolutionSelectId = htmlIdGenerator('resolutionSelect')();
const [toasts, setToasts] = useState<Toast[]>([]);
const [toastRightSide, setToastRightSide] = useState<boolean>(true);

Expand All @@ -69,26 +58,6 @@ export const Home = ({ chrome, parentBreadcrumb }: MetricsProps) => {
setToasts([...toasts, { id: new Date().toISOString(), title, text, color } as Toast]);
};

const onRefreshFilters = () => {
if (spanValue < 1) {
setToast('Please add a valid span interval', 'danger');
return;
}
setOnRefresh(!onRefresh);
};

const onDatePickerChange = (props: OnTimeChangeProps) => {
onTimeChange(
props.start,
props.end,
recentlyUsedRanges,
setRecentlyUsedRanges,
setStartTime,
setEndTime
);
onRefreshFilters();
};

const onEditClick = (savedVisualizationId: string) => {
window.location.assign(`${observabilityLogsID}#/explorer/${savedVisualizationId}`);
};
Expand Down Expand Up @@ -135,20 +104,11 @@ export const Home = ({ chrome, parentBreadcrumb }: MetricsProps) => {
<EuiPageBody component="div">
<TopMenu
IsTopPanelDisabled={IsTopPanelDisabled}
startTime={startTime}
endTime={endTime}
onDatePickerChange={onDatePickerChange}
recentlyUsedRanges={recentlyUsedRanges}
editMode={editMode}
setEditMode={setEditMode}
setEditActionType={setEditActionType}
panelVisualizations={panelVisualizations}
setPanelVisualizations={setPanelVisualizations}
resolutionValue={resolutionValue}
setResolutionValue={setResolutionValue}
spanValue={spanValue}
setSpanValue={setSpanValue}
resolutionSelectId={resolutionSelectId}
setToast={setToast}
/>
<div className="dscAppContainer">
Expand All @@ -168,13 +128,9 @@ export const Home = ({ chrome, parentBreadcrumb }: MetricsProps) => {
panelVisualizations={panelVisualizations}
setPanelVisualizations={setPanelVisualizations}
editMode={editMode}
startTime={startTime}
endTime={endTime}
moveToEvents={onEditClick}
onRefresh={onRefresh}
editActionType={editActionType}
setEditActionType={setEditActionType}
spanParam={spanValue + resolutionValue}
/>
) : (
<EmptyMetricsView />
Expand Down
48 changes: 43 additions & 5 deletions public/components/metrics/redux/slices/metrics_slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ const initialState = {
dataSources: [OBSERVABILITY_CUSTOM_METRIC],
dataSourceTitles: ['Observability Custom Metrics'],
dataSourceIcons: coloredIconsFrom([OBSERVABILITY_CUSTOM_METRIC]),
dateSpanFilter: {
start: 'now-1d',
end: 'now',
span: 1,
resolution: 'h',
recentlyUsedRanges: [],
},
refresh: 0, // set to new Date() to trigger
};

export const loadMetrics = () => async (dispatch) => {
Expand Down Expand Up @@ -168,20 +176,30 @@ export const metricSlice = createSlice({
setDataSourceIcons: (state, { payload }) => {
state.dataSourceIcons = payload;
},
setDateSpan: (state, { payload }) => {
state.dateSpanFilter = { ...state.dateSpanFilter, ...payload };
},
setRefresh: (state) => {
state.refresh = Date.now();
},
},
});

export const {
setMetrics,
deSelectMetric,
selectMetric,
updateMetricsLayout,
setSearch,
setDataSources,
setDataSourceTitles,
setDataSourceIcons,
setDataSourceTitles,
setDataSources,
setMetrics,
setRefresh,
setSearch,
updateMetricsLayout,
} = metricSlice.actions;

/** private actions */
const { setDateSpan } = metricSlice.actions;

export const availableMetricsSelector = (state) =>
state.metrics.metrics
.filter((metric) => !state.metrics.selected.includes(metric.id))
Expand All @@ -190,6 +208,22 @@ export const availableMetricsSelector = (state) =>
state.metrics.search === '' || metric.name.match(new RegExp(state.metrics.search, 'i'))
);

export const updateStartEndDate = ({ start, end }) => (dispatch, getState) => {
const currentDateSpanFilter = getState().metrics.dateSpanFilter;
const recentlyUsedRange = currentDateSpanFilter.recentlyUsedRanges.filter((r) => {
const isDuplicate = r.start === start && r.end === end;
return !isDuplicate;
});
recentlyUsedRange.unshift({ start, end });

dispatch(setDateSpan({ start, end, recentlyUsedRanges: recentlyUsedRange.slice(0, 9) }));
dispatch(setRefresh());
};

export const updateDateSpan = (props: { span?: string; resolution?: string }) => (dispatch) => {
dispatch(setDateSpan(props)); // specifically use props variable to partial update
};

export const selectedMetricsSelector = (state) =>
state.metrics.selected.map((id) => state.metrics.metrics.find((metric) => metric.id === id));

Expand All @@ -201,4 +235,8 @@ export const metricsLayoutSelector = (state) => state.metrics.metricsLayout;

export const dataSourcesSelector = (state) => state.metrics.dataSources;

export const dateSpanFilterSelector = (state) => state.metrics.dateSpanFilter;

export const refreshSelector = (state) => state.metrics.refresh;

export const metricsReducers = metricSlice.reducer;
Loading

0 comments on commit f981407

Please sign in to comment.