Skip to content

Commit

Permalink
Add new state for selected filters.
Browse files Browse the repository at this point in the history
  • Loading branch information
justinkambic committed Jun 5, 2020
1 parent abc7e07 commit 68c6e13
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@

import React, { useState } from 'react';
import { EuiButtonEmpty, EuiContextMenuItem, EuiContextMenuPanel, EuiPopover } from '@elastic/eui';
import { useFilterUpdate } from '../../../hooks/use_filter_update';
import * as labels from './translations';

interface Props {
newFilters: string[];
onNewFilter: (val: string) => void;
alertFilters: { [key: string]: string[] };
}

export const AddFilterButton: React.FC<Props> = ({ newFilters, onNewFilter }) => {
export const AddFilterButton: React.FC<Props> = ({ newFilters, onNewFilter, alertFilters }) => {
const [isPopoverOpen, setPopover] = useState(false);

const { selectedFilters } = useFilterUpdate();

const getSelectedItems = (fieldName: string) => selectedFilters.get(fieldName) || [];
const getSelectedItems = (fieldName: string) => alertFilters?.[fieldName] ?? [];

const onButtonClick = () => {
setPopover(!isPopoverOpen);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import React, { useState } from 'react';
import { EuiCallOut, EuiLoadingSpinner, EuiSpacer } from '@elastic/eui';
import { EuiCallOut, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { DataPublicPluginSetup } from 'src/plugins/data/public';
import * as labels from './translations';
Expand Down Expand Up @@ -110,6 +110,7 @@ export const AlertMonitorStatusComponent: React.FC<AlertMonitorStatusProps> = (p
<EuiSpacer size="xs" />

<AddFilterButton
alertFilters={alertParams.filters}
newFilters={newFilters}
onNewFilter={(newFilter) => {
setNewFilters([...newFilters, newFilter]);
Expand All @@ -118,21 +119,17 @@ export const AlertMonitorStatusComponent: React.FC<AlertMonitorStatusProps> = (p

<EuiSpacer size="m" />

{!snapshotLoading ? (
<EuiCallOut
size="s"
title={
<FormattedMessage
id="xpack.uptime.alerts.monitorStatus.monitorCallOut.title"
defaultMessage="This alert will apply to approximately {snapshotCount} monitors."
values={{ snapshotCount }}
/>
}
iconType="iInCircle"
/>
) : (
<EuiLoadingSpinner size="m" />
)}
<EuiCallOut
size="s"
title={
<FormattedMessage
id="xpack.uptime.alerts.monitorStatus.monitorCallOut.title"
defaultMessage="This alert will apply to approximately {snapshotCount} monitors."
values={{ snapshotCount: snapshotLoading ? '...' : snapshotCount }}
/>
}
iconType="iInCircle"
/>

<EuiSpacer size="m" />
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
overviewFiltersSelector,
snapshotDataSelector,
esKuerySelector,
selectedFiltersSelector,
} from '../../../../state/selectors';
import { AlertMonitorStatusComponent } from '../index';
import {
Expand Down Expand Up @@ -92,6 +93,22 @@ export const AlertMonitorStatus: React.FC<Props> = ({
);
}, [dispatch, esKuery]);

const selectedFilters = useSelector(selectedFiltersSelector);
useEffect(() => {
if (!alertParams.filters && selectedFilters !== null) {
setAlertParams('filters', {
// @ts-ignore
'url.port': selectedFilters?.ports ?? [],
// @ts-ignore
'observer.geo.name': selectedFilters?.locations ?? [],
// @ts-ignore
'monitor.type': selectedFilters?.schemes ?? [],
// @ts-ignore
tags: selectedFilters?.tags ?? [],
});
}
}, [alertParams, setAlertParams, selectedFilters]);

return (
<AlertMonitorStatusComponent
alertParams={alertParams}
Expand Down
36 changes: 36 additions & 0 deletions x-pack/plugins/uptime/public/hooks/use_url_params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { useEffect } from 'react';
import { parse, stringify } from 'query-string';
import { useLocation, useHistory } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { UptimeUrlParams, getSupportedUrlParams } from '../lib/helper';
import { selectedFiltersSelector } from '../state/selectors';
import { setSelectedFilters } from '../state/actions/selected_filters';

export type GetUrlParams = () => UptimeUrlParams;
export type UpdateUrlParams = (updatedParams: {
Expand All @@ -27,9 +31,35 @@ export const useGetUrlParams: GetUrlParams = () => {
return getSupportedUrlParams(params);
};

const getMapFromFilters = (value: any): Map<string, any> | undefined => {
try {
return new Map(JSON.parse(value));
} catch {
return undefined;
}
};

const mapMapToObject = (map: Map<string, any>) => ({
locations: map.get('observer.geo.name') ?? [],
ports: map.get('url.port') ?? [],
schemes: map.get('monitor.type') ?? [],
tags: map.get('tags') ?? [],
});

export const useUrlParams: UptimeUrlParamsHook = () => {
const location = useLocation();
const history = useHistory();
const dispatch = useDispatch();
const selectedFilters = useSelector(selectedFiltersSelector);
const { filters } = useGetUrlParams();
useEffect(() => {
if (selectedFilters === null) {
const filterMap = getMapFromFilters(filters);
if (filterMap) {
dispatch(setSelectedFilters(mapMapToObject(filterMap)));
}
}
}, [dispatch, filters, selectedFilters]);

const updateUrlParams: UpdateUrlParams = (updatedParams) => {
if (!history || !location) return;
Expand Down Expand Up @@ -57,6 +87,12 @@ export const useUrlParams: UptimeUrlParamsHook = () => {
{ sort: false }
),
});
const filterMap = getMapFromFilters(mergedParams.filters);
if (!filterMap) {
dispatch(setSelectedFilters(null));
} else {
dispatch(setSelectedFilters(mapMapToObject(filterMap)));
}
};

return [useGetUrlParams, updateUrlParams];
Expand Down
21 changes: 21 additions & 0 deletions x-pack/plugins/uptime/public/state/actions/selected_filters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { createAction } from 'redux-actions';

export interface SelectedFilters {
locations: string[];
ports: number[];
schemes: string[];
tags: string[];
}

export type SelectedFiltersPayload = SelectedFilters;

export const getSelectedFilters = createAction<void>('GET SELECTED FILTERS');
export const setSelectedFilters = createAction<SelectedFiltersPayload | null>(
'SET_SELECTED_FILTERS'
);
2 changes: 2 additions & 0 deletions x-pack/plugins/uptime/public/state/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { monitorDurationReducer } from './monitor_duration';
import { indexStatusReducer } from './index_status';
import { mlJobsReducer } from './ml_anomaly';
import { certificatesReducer } from '../certificates/certificates';
import { selectedFiltersReducer } from './selected_filters';

export const rootReducer = combineReducers({
monitor: monitorReducer,
Expand All @@ -35,4 +36,5 @@ export const rootReducer = combineReducers({
monitorDuration: monitorDurationReducer,
indexStatus: indexStatusReducer,
certificates: certificatesReducer,
selectedFilters: selectedFiltersReducer,
});
32 changes: 32 additions & 0 deletions x-pack/plugins/uptime/public/state/reducers/selected_filters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { Action } from 'redux-actions';
import {
getSelectedFilters,
setSelectedFilters,
SelectedFilters,
} from '../actions/selected_filters';

const initialState = null;

export function selectedFiltersReducer(
state = initialState,
action: Action<any>
): SelectedFilters | null {
switch (action.type) {
case String(getSelectedFilters):
return state;
case String(setSelectedFilters):
if (state === null) return { ...action.payload };
return {
...(state || {}),
...action.payload,
};
default:
return state;
}
}
2 changes: 2 additions & 0 deletions x-pack/plugins/uptime/public/state/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,5 @@ export const overviewFiltersSelector = ({ overviewFilters }: AppState) => overvi
export const esKuerySelector = ({ ui: { esKuery } }: AppState) => esKuery;

export const searchTextSelector = ({ ui: { searchText } }: AppState) => searchText;

export const selectedFiltersSelector = ({ selectedFilters }: AppState) => selectedFilters;

0 comments on commit 68c6e13

Please sign in to comment.