From bd52cc0cdf346ba55fab297dc271581319d33fea Mon Sep 17 00:00:00 2001 From: Shahzad Date: Wed, 18 Sep 2019 17:49:19 +0500 Subject: [PATCH] [Uptime] Fix/issue 48 integration popup closes after refresh (#45759) (#45999) * integrate redux into uptime app * update integrations popup handling * keep popover open after page refresh * updated unit test snaps * update unit tests * fixed types --- .../functional/monitor_list/monitor_list.tsx | 2 +- .../monitor_list_actions_popover.tsx | 41 ++++-- .../uptime/public/state/actions/index.ts | 7 + .../plugins/uptime/public/state/actions/ui.ts | 26 ++++ .../plugins/uptime/public/state/index.ts | 14 ++ .../uptime/public/state/reducers/index.ts | 13 ++ .../uptime/public/state/reducers/ui.ts | 31 +++++ .../uptime/public/state/sagas/index.ts | 11 ++ .../uptime/public/state/selectors/index.ts | 8 ++ .../plugins/uptime/public/uptime_app.tsx | 124 +++++++++--------- 10 files changed, 208 insertions(+), 69 deletions(-) create mode 100644 x-pack/legacy/plugins/uptime/public/state/actions/index.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/actions/ui.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/index.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/reducers/index.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/sagas/index.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/selectors/index.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx index 373e626ec43e4..124045f79b726 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx @@ -208,7 +208,7 @@ export const MonitorListComponent = (props: Props) => { { defaultMessage: 'Integrations', description: - 'The heading column of some action buttons that will take users to other Obsevability apps', + 'The heading column of some action buttons that will take users to other Observability apps', } ), render: (state: any, summary: MonitorSummary) => ( diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_actions_popover.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_actions_popover.tsx index d8480498930bb..04f195d42531b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_actions_popover.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_actions_popover.tsx @@ -5,20 +5,29 @@ */ import { EuiButtonIcon, EuiPopover } from '@elastic/eui'; -import React, { useState, useContext } from 'react'; +import React, { useContext } from 'react'; import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; +import { connect } from 'react-redux'; import { MonitorSummary } from '../../../../common/graphql/types'; import { IntegrationGroup } from '../integration_group'; import { UptimeSettingsContext } from '../../../contexts'; +import { isIntegrationsPopupOpen } from '../../../state/selectors'; +import { AppState } from '../../../state'; +import { toggleIntegrationsPopover, PopoverState } from '../../../state/actions'; interface MonitorListActionsPopoverProps { summary: MonitorSummary; + popoverState: PopoverState | null; + togglePopoverIsVisible: typeof toggleIntegrationsPopover; } -export const MonitorListActionsPopover = ({ summary }: MonitorListActionsPopoverProps) => { +const MonitorListActionsPopoverComponent = ({ + summary, + popoverState, + togglePopoverIsVisible, +}: MonitorListActionsPopoverProps) => { const popoverId = `${summary.monitor_id}_popover`; - const [popoverIsVisible, setPopoverIsVisible] = useState(false); const { basePath, dateRangeStart, @@ -28,8 +37,9 @@ export const MonitorListActionsPopover = ({ summary }: MonitorListActionsPopover isLogsAvailable, } = useContext(UptimeSettingsContext); - const monitorUrl = get(summary, 'state.url.full', undefined); - + const monitorUrl: string | undefined = get(summary, 'state.url.full', undefined); + const isPopoverOpen: boolean = + !!popoverState && popoverState.open && popoverState.id === popoverId; return ( setPopoverIsVisible(true)} + onClick={() => togglePopoverIsVisible({ id: popoverId, open: true })} /> } - closePopover={() => setPopoverIsVisible(false)} + closePopover={() => togglePopoverIsVisible({ id: popoverId, open: false })} id={popoverId} - isOpen={popoverIsVisible} + isOpen={isPopoverOpen} > ); }; + +const mapStateToProps = (state: AppState) => ({ + popoverState: isIntegrationsPopupOpen(state), +}); + +const mapDispatchToProps = (dispatch: any) => ({ + togglePopoverIsVisible: (popoverState: PopoverState) => { + return dispatch(toggleIntegrationsPopover(popoverState)); + }, +}); + +export const MonitorListActionsPopover = connect( + mapStateToProps, + mapDispatchToProps +)(MonitorListActionsPopoverComponent); diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/index.ts b/x-pack/legacy/plugins/uptime/public/state/actions/index.ts new file mode 100644 index 0000000000000..1a33812ca8566 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/actions/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export * from './ui'; diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/ui.ts b/x-pack/legacy/plugins/uptime/public/state/actions/ui.ts new file mode 100644 index 0000000000000..7c18774e1d67d --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/actions/ui.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +export const SET_INTEGRATION_POPOVER_STATE = 'SET_INTEGRATION_POPOVER_STATE'; + +export interface PopoverState { + id: string; + open: boolean; +} + +interface SetIntegrationPopoverAction { + type: typeof SET_INTEGRATION_POPOVER_STATE; + payload: PopoverState; +} + +export function toggleIntegrationsPopover(popoverState: PopoverState): SetIntegrationPopoverAction { + return { + type: SET_INTEGRATION_POPOVER_STATE, + payload: popoverState, + }; +} + +export type UiActionTypes = SetIntegrationPopoverAction; diff --git a/x-pack/legacy/plugins/uptime/public/state/index.ts b/x-pack/legacy/plugins/uptime/public/state/index.ts new file mode 100644 index 0000000000000..4ef3d26776a7e --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/index.ts @@ -0,0 +1,14 @@ +/* + * 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 { compose, createStore } from 'redux'; + +import { rootReducer } from './reducers'; + +const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; + +export const store = createStore(rootReducer, composeEnhancers()); + +export type AppState = ReturnType; diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts new file mode 100644 index 0000000000000..faa932a321cd1 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts @@ -0,0 +1,13 @@ +/* + * 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 { combineReducers } from 'redux'; + +import { uiReducer } from './ui'; + +export const rootReducer = combineReducers({ + ui: uiReducer, +}); diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts new file mode 100644 index 0000000000000..1550b6c9936c3 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts @@ -0,0 +1,31 @@ +/* + * 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 { UiActionTypes, PopoverState, SET_INTEGRATION_POPOVER_STATE } from '../actions/ui'; + +export interface UiState { + integrationsPopoverOpen: PopoverState | null; +} + +const initialState: UiState = { + integrationsPopoverOpen: null, +}; + +export function uiReducer(state = initialState, action: UiActionTypes): UiState { + switch (action.type) { + case SET_INTEGRATION_POPOVER_STATE: + const popoverState = action.payload; + return { + ...state, + integrationsPopoverOpen: { + id: popoverState.id, + open: popoverState.open, + }, + }; + default: + return state; + } +} diff --git a/x-pack/legacy/plugins/uptime/public/state/sagas/index.ts b/x-pack/legacy/plugins/uptime/public/state/sagas/index.ts new file mode 100644 index 0000000000000..7bb3c694f5120 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/sagas/index.ts @@ -0,0 +1,11 @@ +/* + * 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 { fork } from 'redux-saga/effects'; + +// export function* rootSaga() { +// yield fork(); +// } diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts new file mode 100644 index 0000000000000..223e7c029cb1c --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts @@ -0,0 +1,8 @@ +/* + * 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 { AppState } from '../../state'; + +export const isIntegrationsPopupOpen = (state: AppState) => state.ui.integrationsPopoverOpen; diff --git a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx index 2aa2d86d70b91..d65cff8f45697 100644 --- a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx +++ b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx @@ -11,6 +11,7 @@ import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import React, { useEffect, useState } from 'react'; import { ApolloProvider } from 'react-apollo'; +import { Provider as ReduxProvider } from 'react-redux'; import { BrowserRouter as Router, Route, RouteComponentProps, Switch } from 'react-router-dom'; import { capabilities } from 'ui/capabilities'; import { I18nContext } from 'ui/i18n'; @@ -19,6 +20,7 @@ import { MonitorPage, OverviewPage, NotFoundPage } from './pages'; import { UptimeRefreshContext, UptimeSettingsContext, UMSettingsContextValues } from './contexts'; import { UptimeDatePicker } from './components/functional/uptime_date_picker'; import { useUrlParams } from './hooks'; +import { store } from './state'; export interface UptimeAppColors { danger: string; @@ -132,66 +134,68 @@ const Application = (props: UptimeAppProps) => { return ( - - { - return ( - - - - -
- - - -

{headingText}

-
-
- - - -
- - - ( - - )} - /> - ( - - )} - /> - - -
-
-
-
-
- ); - }} - /> -
+ + + { + return ( + + + + +
+ + + +

{headingText}

+
+
+ + + +
+ + + ( + + )} + /> + ( + + )} + /> + + +
+
+
+
+
+ ); + }} + /> +
+
); };