mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Uptime] Fix/issue 48 integration popup closes after refresh (#45759)
* integrate redux into uptime app * update integrations popup handling * keep popover open after page refresh * updated unit test snaps * update unit tests * fixed types
This commit is contained in:
parent
4e6cf7998f
commit
a204a4347f
10 changed files with 208 additions and 69 deletions
|
@ -218,7 +218,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) => (
|
||||
|
|
|
@ -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<boolean>(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 (
|
||||
<EuiPopover
|
||||
button={
|
||||
|
@ -45,12 +55,12 @@ export const MonitorListActionsPopover = ({ summary }: MonitorListActionsPopover
|
|||
)}
|
||||
color="subdued"
|
||||
iconType="boxesHorizontal"
|
||||
onClick={() => setPopoverIsVisible(true)}
|
||||
onClick={() => togglePopoverIsVisible({ id: popoverId, open: true })}
|
||||
/>
|
||||
}
|
||||
closePopover={() => setPopoverIsVisible(false)}
|
||||
closePopover={() => togglePopoverIsVisible({ id: popoverId, open: false })}
|
||||
id={popoverId}
|
||||
isOpen={popoverIsVisible}
|
||||
isOpen={isPopoverOpen}
|
||||
>
|
||||
<IntegrationGroup
|
||||
basePath={basePath}
|
||||
|
@ -64,3 +74,18 @@ export const MonitorListActionsPopover = ({ summary }: MonitorListActionsPopover
|
|||
</EuiPopover>
|
||||
);
|
||||
};
|
||||
|
||||
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);
|
||||
|
|
|
@ -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';
|
26
x-pack/legacy/plugins/uptime/public/state/actions/ui.ts
Normal file
26
x-pack/legacy/plugins/uptime/public/state/actions/ui.ts
Normal file
|
@ -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;
|
14
x-pack/legacy/plugins/uptime/public/state/index.ts
Normal file
14
x-pack/legacy/plugins/uptime/public/state/index.ts
Normal file
|
@ -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<typeof rootReducer>;
|
13
x-pack/legacy/plugins/uptime/public/state/reducers/index.ts
Normal file
13
x-pack/legacy/plugins/uptime/public/state/reducers/index.ts
Normal file
|
@ -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,
|
||||
});
|
31
x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts
Normal file
31
x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
11
x-pack/legacy/plugins/uptime/public/state/sagas/index.ts
Normal file
11
x-pack/legacy/plugins/uptime/public/state/sagas/index.ts
Normal file
|
@ -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();
|
||||
// }
|
|
@ -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;
|
|
@ -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';
|
||||
|
@ -20,6 +21,7 @@ import { UptimeRefreshContext, UptimeSettingsContext, UMSettingsContextValues }
|
|||
import { UptimeDatePicker } from './components/functional/uptime_date_picker';
|
||||
import { useUrlParams } from './hooks';
|
||||
import { getTitle } from './lib/helper/get_title';
|
||||
import { store } from './state';
|
||||
|
||||
export interface UptimeAppColors {
|
||||
danger: string;
|
||||
|
@ -136,66 +138,68 @@ const Application = (props: UptimeAppProps) => {
|
|||
|
||||
return (
|
||||
<I18nContext>
|
||||
<Router basename={routerBasename}>
|
||||
<Route
|
||||
path="/"
|
||||
render={(rootRouteProps: RouteComponentProps) => {
|
||||
return (
|
||||
<ApolloProvider client={client}>
|
||||
<UptimeRefreshContext.Provider value={{ lastRefresh, ...rootRouteProps }}>
|
||||
<UptimeSettingsContext.Provider value={initializeSettingsContextValues()}>
|
||||
<EuiPage className="app-wrapper-panel " data-test-subj="uptimeApp">
|
||||
<div>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
justifyContent="spaceBetween"
|
||||
gutterSize="s"
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle>
|
||||
<h1>{headingText}</h1>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<UptimeDatePicker refreshApp={refreshApp} {...rootRouteProps} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="s" />
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/"
|
||||
render={routerProps => (
|
||||
<OverviewPage
|
||||
basePath={basePath}
|
||||
logOverviewPageLoad={logOverviewPageLoad}
|
||||
setBreadcrumbs={setBreadcrumbs}
|
||||
{...routerProps}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path="/monitor/:monitorId/:location?"
|
||||
render={routerProps => (
|
||||
<MonitorPage
|
||||
logMonitorPageLoad={logMonitorPageLoad}
|
||||
query={client.query}
|
||||
setBreadcrumbs={setBreadcrumbs}
|
||||
{...routerProps}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route component={NotFoundPage} />
|
||||
</Switch>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</UptimeSettingsContext.Provider>
|
||||
</UptimeRefreshContext.Provider>
|
||||
</ApolloProvider>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Router>
|
||||
<ReduxProvider store={store}>
|
||||
<Router basename={routerBasename}>
|
||||
<Route
|
||||
path="/"
|
||||
render={(rootRouteProps: RouteComponentProps) => {
|
||||
return (
|
||||
<ApolloProvider client={client}>
|
||||
<UptimeRefreshContext.Provider value={{ lastRefresh, ...rootRouteProps }}>
|
||||
<UptimeSettingsContext.Provider value={initializeSettingsContextValues()}>
|
||||
<EuiPage className="app-wrapper-panel " data-test-subj="uptimeApp">
|
||||
<div>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
justifyContent="spaceBetween"
|
||||
gutterSize="s"
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle>
|
||||
<h1>{headingText}</h1>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<UptimeDatePicker refreshApp={refreshApp} {...rootRouteProps} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="s" />
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/"
|
||||
render={routerProps => (
|
||||
<OverviewPage
|
||||
basePath={basePath}
|
||||
logOverviewPageLoad={logOverviewPageLoad}
|
||||
setBreadcrumbs={setBreadcrumbs}
|
||||
{...routerProps}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path="/monitor/:monitorId/:location?"
|
||||
render={routerProps => (
|
||||
<MonitorPage
|
||||
logMonitorPageLoad={logMonitorPageLoad}
|
||||
query={client.query}
|
||||
setBreadcrumbs={setBreadcrumbs}
|
||||
{...routerProps}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route component={NotFoundPage} />
|
||||
</Switch>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</UptimeSettingsContext.Provider>
|
||||
</UptimeRefreshContext.Provider>
|
||||
</ApolloProvider>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Router>
|
||||
</ReduxProvider>
|
||||
</I18nContext>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue