From 684331428448f7a8f5c95886f0c19070cd0579c0 Mon Sep 17 00:00:00 2001 From: Christopher Henn Date: Tue, 27 Aug 2019 12:55:56 -0700 Subject: [PATCH] feat(ui): link to alerting history from alerting page --- .../alerting/components/AlertHistoryIndex.tsx | 18 ++++++++-- .../components/AlertHistoryQueryParams.tsx | 32 +++++++++++++++++ ui/src/alerting/components/CheckCard.tsx | 15 ++++++-- .../components/endpoints/EndpointCard.tsx | 22 ++++++++++-- .../components/notifications/RuleCard.tsx | 20 +++++++++-- ui/src/alerting/constants/history.ts | 3 ++ ui/src/alerting/utils/history.ts | 34 +++++++++++++++++-- ui/src/eventViewer/components/EventViewer.tsx | 9 +++-- 8 files changed, 140 insertions(+), 13 deletions(-) create mode 100644 ui/src/alerting/components/AlertHistoryQueryParams.tsx diff --git a/ui/src/alerting/components/AlertHistoryIndex.tsx b/ui/src/alerting/components/AlertHistoryIndex.tsx index 202a2a50749..0558c1be5b5 100644 --- a/ui/src/alerting/components/AlertHistoryIndex.tsx +++ b/ui/src/alerting/components/AlertHistoryIndex.tsx @@ -6,6 +6,7 @@ import {Page} from '@influxdata/clockface' import EventViewer from 'src/eventViewer/components/EventViewer' import EventTable from 'src/eventViewer/components/EventTable' import AlertHistoryControls from 'src/alerting/components/AlertHistoryControls' +import AlertHistoryQueryParams from 'src/alerting/components/AlertHistoryQueryParams' // Constants import { @@ -14,7 +15,12 @@ import { } from 'src/alerting/constants/history' // Utils -import {loadStatuses, loadNotifications} from 'src/alerting/utils/history' +import { + loadStatuses, + loadNotifications, + getInitialHistoryType, + getInitialState, +} from 'src/alerting/utils/history' // Types import {AlertHistoryType} from 'src/types' @@ -24,7 +30,9 @@ interface Props { } const AlertHistoryIndex: FC = ({params: {orgID}}) => { - const [historyType, setHistoryType] = useState('statuses') + const [historyType, setHistoryType] = useState( + getInitialHistoryType() + ) const loadRows = useMemo(() => { return historyType === 'statuses' @@ -36,7 +44,7 @@ const AlertHistoryIndex: FC = ({params: {orgID}}) => { historyType === 'statuses' ? STATUS_FIELDS : NOTIFICATION_FIELDS return ( - + {props => ( = ({params: {orgID}}) => {
+ = ({searchInput, historyType}) => { + useEffect(() => { + updateQueryParams({ + [SEARCH_QUERY_PARAM]: searchInput || null, + [HISTORY_TYPE_QUERY_PARAM]: historyType, + }) + }, [searchInput, historyType]) + + return null +} + +export default AlertHistoryQueryParams diff --git a/ui/src/alerting/components/CheckCard.tsx b/ui/src/alerting/components/CheckCard.tsx index c03927a3ad6..a317fbc23a4 100644 --- a/ui/src/alerting/components/CheckCard.tsx +++ b/ui/src/alerting/components/CheckCard.tsx @@ -10,6 +10,10 @@ import InlineLabels from 'src/shared/components/inlineLabels/InlineLabels' // Constants import {DEFAULT_CHECK_NAME} from 'src/alerting/constants' +import { + SEARCH_QUERY_PARAM, + HISTORY_TYPE_QUERY_PARAM, +} from 'src/alerting/constants/history' // Actions and Selectors import { @@ -23,7 +27,7 @@ import {createLabel as createLabelAsync} from 'src/labels/actions' import {viewableLabels} from 'src/labels/selectors' // Types -import {Check, Label, AppState} from 'src/types' +import {Check, Label, AppState, AlertHistoryType} from 'src/types' interface DispatchProps { updateCheck: typeof updateCheck @@ -83,7 +87,14 @@ const CheckCard: FunctionComponent = ({ } const onCheckClick = () => { - router.push(`/orgs/${orgID}/alerting/checks/${check.id}/`) + const historyType: AlertHistoryType = 'statuses' + + const queryParams = new URLSearchParams({ + [HISTORY_TYPE_QUERY_PARAM]: historyType, + [SEARCH_QUERY_PARAM]: `"checkID" == "${check.id}"`, + }) + + router.push(`/orgs/${orgID}/alert-history?${queryParams}`) } const handleAddCheckLabel = (label: Label) => { diff --git a/ui/src/alerting/components/endpoints/EndpointCard.tsx b/ui/src/alerting/components/endpoints/EndpointCard.tsx index a6ce4b52450..510203e1b32 100644 --- a/ui/src/alerting/components/endpoints/EndpointCard.tsx +++ b/ui/src/alerting/components/endpoints/EndpointCard.tsx @@ -21,8 +21,19 @@ import {SlideToggle, ComponentSize, ResourceCard} from '@influxdata/clockface' import EndpointCardMenu from 'src/alerting/components/endpoints/EndpointCardMenu' import InlineLabels from 'src/shared/components/inlineLabels/InlineLabels' +// Constants +import { + SEARCH_QUERY_PARAM, + HISTORY_TYPE_QUERY_PARAM, +} from 'src/alerting/constants/history' + // Types -import {NotificationEndpoint, Label, AppState} from 'src/types' +import { + NotificationEndpoint, + Label, + AppState, + AlertHistoryType, +} from 'src/types' import {Action} from 'src/alerting/actions/notifications/endpoints' interface DispatchProps { @@ -70,7 +81,14 @@ const EndpointCard: FC = ({ onUpdateEndpointProperties(id, {name}) } const handleClick = () => { - router.push(`orgs/${orgID}/alerting/endpoints/${endpoint.id}/`) + const historyType: AlertHistoryType = 'notifications' + + const queryParams = new URLSearchParams({ + [HISTORY_TYPE_QUERY_PARAM]: historyType, + [SEARCH_QUERY_PARAM]: `"notificationEndpointID" == "${endpoint.id}"`, + }) + + router.push(`/orgs/${orgID}/alert-history?${queryParams}`) } const nameComponent = ( = ({ } const onRuleClick = () => { - router.push(`/orgs/${orgID}/alerting/rules/${rule.id}/`) + const historyType: AlertHistoryType = 'notifications' + + const queryParams = new URLSearchParams({ + [HISTORY_TYPE_QUERY_PARAM]: historyType, + [SEARCH_QUERY_PARAM]: `"notificationRuleID" == "${rule.id}"`, + }) + + router.push(`/orgs/${orgID}/alert-history?${queryParams}`) } const handleAddRuleLabel = (label: Label) => { diff --git a/ui/src/alerting/constants/history.ts b/ui/src/alerting/constants/history.ts index 5506968a04f..55d5abaf53e 100644 --- a/ui/src/alerting/constants/history.ts +++ b/ui/src/alerting/constants/history.ts @@ -93,3 +93,6 @@ export const EXAMPLE_NOTIFICATION_SEARCHES = [ '"level" != "ok"', '"notification rule" == "my rule"', ] + +export const HISTORY_TYPE_QUERY_PARAM = 'type' +export const SEARCH_QUERY_PARAM = 'filter' diff --git a/ui/src/alerting/utils/history.ts b/ui/src/alerting/utils/history.ts index b24186f0ff1..7eaca4f993b 100644 --- a/ui/src/alerting/utils/history.ts +++ b/ui/src/alerting/utils/history.ts @@ -4,17 +4,27 @@ import {fromFlux} from '@influxdata/giraffe' // Utils import {runQuery, RunQueryResult} from 'src/shared/apis/query' -import {searchExprToFlux} from 'src/eventViewer/utils/search' +import {parseSearchInput, searchExprToFlux} from 'src/eventViewer/utils/search' import {findNodes} from 'src/shared/utils/ast' +import {readQueryParams} from 'src/shared/utils/queryParams' // Constants import { STATUS_BUCKET, NOTIFICATION_BUCKET, + HISTORY_TYPE_QUERY_PARAM, + SEARCH_QUERY_PARAM, } from 'src/alerting/constants/history' // Types -import {CancelBox, StatusRow, NotificationRow} from 'src/types' +import {State as EventViewerState} from 'src/eventViewer/components/EventViewer.reducer' + +import { + CancelBox, + StatusRow, + NotificationRow, + AlertHistoryType, +} from 'src/types' import { LoadRowsOptions, @@ -161,3 +171,23 @@ const processResponse = ({ cancel, } } + +export const getInitialHistoryType = (): AlertHistoryType => { + return readQueryParams()[HISTORY_TYPE_QUERY_PARAM] || 'statuses' +} + +export const getInitialState = (): Partial => { + const searchInput = readQueryParams()[SEARCH_QUERY_PARAM] + + if (!searchInput) { + return {} + } + + try { + const searchExpr = parseSearchInput(searchInput) + + return {searchInput, searchExpr} + } catch { + return {searchInput} + } +} diff --git a/ui/src/eventViewer/components/EventViewer.tsx b/ui/src/eventViewer/components/EventViewer.tsx index c2ea1a53a44..a1b400f775b 100644 --- a/ui/src/eventViewer/components/EventViewer.tsx +++ b/ui/src/eventViewer/components/EventViewer.tsx @@ -12,14 +12,19 @@ import { // Types import {LoadRows, EventViewerChildProps} from 'src/eventViewer/types' +import {State} from 'src/eventViewer/components/EventViewer.reducer' interface Props { loadRows: LoadRows children: (props: EventViewerChildProps) => ReactElement + initialState?: Partial } -const EventViewer: FC = ({loadRows, children}) => { - const [state, dispatch] = useReducer(reducer, INITIAL_STATE) +const EventViewer: FC = ({loadRows, children, initialState}) => { + const [state, dispatch] = useReducer(reducer, { + ...INITIAL_STATE, + ...initialState, + }) useEffect(() => { loadNextRows(state, dispatch, loadRows, Date.now())