[Controls] Close controls flyouts on unmount, save, and view mode change (#128198)

* Manage flyout via global ref in control group container

* Add functional tests for settings flyout
This commit is contained in:
Hannah Mudge 2022-04-01 09:54:00 -06:00 committed by GitHub
parent 75c5cf2093
commit dd9aa84724
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 11 deletions

View file

@ -16,6 +16,7 @@ import { ControlGroupStrings } from '../control_group_strings';
import { ControlWidth, ControlInput, IEditableControlFactory } from '../../types';
import { toMountPoint } from '../../../../kibana_react/public';
import { DEFAULT_CONTROL_WIDTH } from '../../../common/control_group/control_group_constants';
import { setFlyoutRef } from '../embeddable/control_group_container';
export type CreateControlButtonTypes = 'toolbar' | 'callout';
export interface CreateControlButtonProps {
@ -99,9 +100,13 @@ export const CreateControlButton = ({
),
{
outsideClickCloses: false,
onClose: (flyout) => onCancel(flyout),
onClose: (flyout) => {
onCancel(flyout);
setFlyoutRef(undefined);
},
}
);
setFlyoutRef(flyoutInstance);
});
initialInputPromise.then(

View file

@ -20,7 +20,7 @@ import { IEditableControlFactory, ControlInput } from '../../types';
import { controlGroupReducers } from '../state/control_group_reducers';
import { EmbeddableFactoryNotFoundError } from '../../../../embeddable/public';
import { useReduxContainerContext } from '../../../../presentation_util/public';
import { ControlGroupContainer } from '../embeddable/control_group_container';
import { ControlGroupContainer, setFlyoutRef } from '../embeddable/control_group_container';
export const EditControlButton = ({ embeddableId }: { embeddableId: string }) => {
// Controls Services Context
@ -127,9 +127,13 @@ export const EditControlButton = ({ embeddableId }: { embeddableId: string }) =>
),
{
outsideClickCloses: false,
onClose: (flyout) => onCancel(flyout),
onClose: (flyout) => {
setFlyoutRef(undefined);
onCancel(flyout);
},
}
);
setFlyoutRef(flyoutInstance);
};
return (

View file

@ -15,6 +15,7 @@ import { ControlGroupEditor } from './control_group_editor';
import { OverlayRef } from '../../../../../core/public';
import { pluginServices } from '../../services';
import { ControlGroupContainer } from '..';
import { setFlyoutRef } from '../embeddable/control_group_container';
export interface EditControlGroupButtonProps {
controlGroupContainer: ControlGroupContainer;
@ -60,9 +61,13 @@ export const EditControlGroup = ({
),
{
outsideClickCloses: false,
onClose: () => flyoutInstance.close(),
onClose: () => {
flyoutInstance.close();
setFlyoutRef(undefined);
},
}
);
setFlyoutRef(flyoutInstance);
};
const commonButtonProps = {

View file

@ -46,11 +46,17 @@ import { Container, EmbeddableFactory } from '../../../../embeddable/public';
import { ControlEmbeddable, ControlInput, ControlOutput } from '../../types';
import { ControlGroupChainingSystems } from './control_group_chaining_system';
import { CreateControlButton, CreateControlButtonTypes } from '../editor/create_control';
import { OverlayRef } from '../../../../../core/public';
const ControlGroupReduxWrapper = withSuspense<
ReduxEmbeddableWrapperPropsWithChildren<ControlGroupInput>
>(LazyReduxEmbeddableWrapper);
let flyoutRef: OverlayRef | undefined;
export const setFlyoutRef = (newRef: OverlayRef | undefined) => {
flyoutRef = newRef;
};
export interface ChildEmbeddableOrderCache {
IdsToOrder: { [key: string]: number };
idsInOrder: string[];
@ -96,6 +102,11 @@ export class ControlGroupContainer extends Container<
return this.lastUsedDataViewId ?? this.relevantDataViewId;
};
public closeAllFlyouts() {
flyoutRef?.close();
flyoutRef = undefined;
}
/**
* Returns a button that allows controls to be created externally using the embeddable
* @param buttonType Controls the button styling
@ -367,6 +378,7 @@ export class ControlGroupContainer extends Container<
public destroy() {
super.destroy();
this.closeAllFlyouts();
this.subscriptions.unsubscribe();
if (this.domNode) ReactDOM.unmountComponentAtNode(this.domNode);
}

View file

@ -210,16 +210,17 @@ export function DashboardTopNav({
[stateTransferService, data.search.session, trackUiMetric]
);
const clearAddPanel = useCallback(() => {
const closeAllFlyouts = useCallback(() => {
dashboardAppState.dashboardContainer.controlGroup?.closeAllFlyouts();
if (state.addPanelOverlay) {
state.addPanelOverlay.close();
setState((s) => ({ ...s, addPanelOverlay: undefined }));
}
}, [state.addPanelOverlay]);
}, [state.addPanelOverlay, dashboardAppState.dashboardContainer.controlGroup]);
const onChangeViewMode = useCallback(
(newMode: ViewMode) => {
clearAddPanel();
closeAllFlyouts();
const willLoseChanges = newMode === ViewMode.VIEW && dashboardAppState.hasUnsavedChanges;
if (!willLoseChanges) {
@ -231,7 +232,7 @@ export function DashboardTopNav({
dashboardAppState.resetToLastSavedState?.()
);
},
[clearAddPanel, core.overlays, dashboardAppState, dispatchDashboardStateChange]
[closeAllFlyouts, core.overlays, dashboardAppState, dispatchDashboardStateChange]
);
const runSaveAs = useCallback(async () => {
@ -296,7 +297,7 @@ export function DashboardTopNav({
showCopyOnSave={lastDashboardId ? true : false}
/>
);
clearAddPanel();
closeAllFlyouts();
showSaveModal(dashboardSaveModal, core.i18n.Context);
}, [
dispatchDashboardStateChange,
@ -305,7 +306,7 @@ export function DashboardTopNav({
dashboardAppState,
core.i18n.Context,
chrome.docTitle,
clearAddPanel,
closeAllFlyouts,
kibanaVersion,
timefilter,
redirectTo,
@ -468,7 +469,7 @@ export function DashboardTopNav({
]);
UseUnmount(() => {
clearAddPanel();
closeAllFlyouts();
setMounted(false);
});

View file

@ -99,5 +99,33 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await dashboardControls.deleteAllControls();
});
});
describe('control group settings flyout closes', async () => {
it('on save', async () => {
await dashboardControls.openControlGroupSettingsFlyout();
await dashboard.saveDashboard('Test Control Group Settings', {
saveAsNew: false,
exitFromEditMode: false,
});
await testSubjects.missingOrFail('control-group-settings-flyout');
});
it('on view mode change', async () => {
await dashboardControls.openControlGroupSettingsFlyout();
await dashboard.clickCancelOutOfEditMode();
await testSubjects.missingOrFail('control-group-settings-flyout');
});
it('when navigating away from dashboard', async () => {
await dashboard.switchToEditMode();
await dashboardControls.openControlGroupSettingsFlyout();
await dashboard.gotoDashboardLandingPage();
await testSubjects.missingOrFail('control-group-settings-flyout');
});
after(async () => {
await dashboard.loadSavedDashboard('Test Control Group Settings');
});
});
});
}