Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Discover] Dismiss flyouts when opening another one #193865

Merged
merged 6 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/kbn-discover-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ export {
getFieldValue,
getVisibleColumns,
canPrependTimeFieldColumn,
DiscoverFlyouts,
dismissAllFlyoutsExceptFor,
dismissFlyouts,
} from './src';

export type { LogsContextService } from './src';
Expand Down
48 changes: 48 additions & 0 deletions packages/kbn-discover-utils/src/utils/dismiss_flyouts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export enum DiscoverFlyouts {
lensEdit = 'lensEdit',
docViewer = 'docViewer',
esqlDocs = 'esqlDocs',
}

const AllDiscoverFlyouts = Object.values(DiscoverFlyouts);

const getFlyoutCloseButton = (flyout: DiscoverFlyouts): HTMLElement | null => {
switch (flyout) {
case DiscoverFlyouts.lensEdit:
return document.getElementById('lnsCancelEditOnFlyFlyout');
case DiscoverFlyouts.docViewer:
return document.querySelector('[data-test-subj="docViewerFlyoutCloseButton"]');
case DiscoverFlyouts.esqlDocs:
return document.querySelector(
'[data-test-subj="esqlInlineDocumentationFlyout"] [data-test-subj="euiFlyoutCloseButton"]'
);
}
};

export const dismissFlyouts = (
selectedFlyouts: DiscoverFlyouts[] = AllDiscoverFlyouts,
excludedFlyout?: DiscoverFlyouts
) => {
selectedFlyouts.forEach((flyout) => {
if (flyout === excludedFlyout) {
return;
}
const closeButton = getFlyoutCloseButton(flyout);
if (closeButton) {
closeButton.click?.();
}
});
};

export const dismissAllFlyoutsExceptFor = (excludedFlyout: DiscoverFlyouts) => {
dismissFlyouts(AllDiscoverFlyouts, excludedFlyout);
};
1 change: 1 addition & 0 deletions packages/kbn-discover-utils/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export * from './get_field_value';
export * from './calc_field_counts';
export * from './get_visible_columns';
export { isLegacyTableEnabled } from './is_legacy_table_enabled';
export { DiscoverFlyouts, dismissAllFlyoutsExceptFor, dismissFlyouts } from './dismiss_flyouts';
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function DocumentationFlyout({
ownFocus
onClose={() => onHelpMenuVisibilityChange(false)}
aria-labelledby="esqlInlineDocumentationFlyout"
data-test-subj="esqlInlineDocumentationFlyout"
type="push"
size={DEFAULT_WIDTH}
paddingSize="m"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { type DataView, DataViewType } from '@kbn/data-views-plugin/public';
import { DataViewPickerProps } from '@kbn/unified-search-plugin/public';
import { ENABLE_ESQL } from '@kbn/esql-utils';
import { TextBasedLanguages } from '@kbn/esql-utils';
import { DiscoverFlyouts, dismissAllFlyoutsExceptFor } from '@kbn/discover-utils';
import { useSavedSearchInitial } from '../../state_management/discover_state_provider';
import { ESQL_TRANSITION_MODAL_KEY } from '../../../../../common/constants';
import { useInternalStateSelector } from '../../state_management/discover_internal_state_container';
Expand Down Expand Up @@ -233,6 +234,12 @@ export const DiscoverTopNav = ({
uiSettings,
]);

const onESQLDocsFlyoutVisibilityChanged = useCallback((isOpen: boolean) => {
if (isOpen) {
dismissAllFlyoutsExceptFor(DiscoverFlyouts.esqlDocs);
}
}, []);

const searchBarCustomization = useDiscoverCustomization('search_bar');

const SearchBar = useMemo(
Expand Down Expand Up @@ -278,6 +285,7 @@ export const DiscoverTopNav = ({
<searchBarCustomization.PrependFilterBar />
) : undefined
}
onESQLDocsFlyoutVisibilityChanged={onESQLDocsFlyoutVisibilityChanged}
/>
{isESQLToDataViewTransitionModalVisible && (
<ESQLToDataViewTransitionModal onClose={onESQLToDataViewTransitionModalClose} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { TopNavMenuBadgeProps } from '@kbn/navigation-plugin/public';
import { getTopNavUnsavedChangesBadge } from '@kbn/unsaved-changes-badge';
import { getManagedContentBadge } from '@kbn/managed-content-badge';
import { i18n } from '@kbn/i18n';
import { dismissFlyouts, DiscoverFlyouts } from '@kbn/discover-utils';
import { DiscoverStateContainer } from '../../state_management/discover_state';
import type { TopNavCustomization } from '../../../../customizations';
import { onSaveSearch } from './on_save_search';
Expand Down Expand Up @@ -47,10 +48,7 @@ export const getTopNavBadges = ({
entries.push({
data: getTopNavUnsavedChangesBadge({
onRevert: async () => {
const lensEditFlyoutCancelButton = document.getElementById('lnsCancelEditOnFlyFlyout');
if (lensEditFlyoutCancelButton) {
lensEditFlyoutCancelButton.click?.();
}
dismissFlyouts([DiscoverFlyouts.lensEdit]);
await stateContainer.actions.undoSavedSearchChanges();
},
onSave:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import React, { useMemo } from 'react';
import React, { useEffect, useMemo } from 'react';
import type { DataView } from '@kbn/data-views-plugin/public';
import { Filter, Query, AggregateQuery, isOfAggregateQueryType } from '@kbn/es-query';
import { AggregateQuery, Filter, isOfAggregateQueryType, Query } from '@kbn/es-query';
import type { DataTableRecord } from '@kbn/discover-utils/types';
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
import type { DataTableColumnsMeta } from '@kbn/unified-data-table';
import type { DocViewsRegistry } from '@kbn/unified-doc-viewer';
import { DiscoverFlyouts, dismissAllFlyoutsExceptFor } from '@kbn/discover-utils';
import { UnifiedDocViewerFlyout } from '@kbn/unified-doc-viewer-plugin/public';
import { useDiscoverServices } from '../../hooks/use_discover_services';
import { useFlyoutActions } from './use_flyout_actions';
Expand Down Expand Up @@ -88,6 +89,10 @@ export function DiscoverGridFlyout({
return getDocViewer({ record: actualHit });
}, [flyoutCustomization, getDocViewerAccessor, actualHit]);

useEffect(() => {
dismissAllFlyoutsExceptFor(DiscoverFlyouts.docViewer);
}, []);

return (
<UnifiedDocViewerFlyout
flyoutTitle={docViewer.title}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { isEqual, isObject } from 'lodash';
import type { LensEmbeddableOutput, Suggestion } from '@kbn/lens-plugin/public';
import type { Datatable } from '@kbn/expressions-plugin/common';
import { EditLensConfigPanelComponent } from '@kbn/lens-plugin/public/plugin';
import { DiscoverFlyouts, dismissAllFlyoutsExceptFor } from '@kbn/discover-utils';
import { deriveLensSuggestionFromLensAttributes } from '../utils/external_vis_context';

import {
Expand Down Expand Up @@ -144,5 +145,13 @@ export function ChartConfigPanel({
currentSuggestionType,
]);

return isPlainRecord ? editLensConfigPanel : null;
const flyoutElement = isPlainRecord ? editLensConfigPanel : null;

useEffect(() => {
if (flyoutElement) {
dismissAllFlyoutsExceptFor(DiscoverFlyouts.lensEdit);
}
}, [flyoutElement]);

return flyoutElement;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ import { FEEDBACK_LINK } from '@kbn/esql-utils';
import { LanguageDocumentationFlyout } from '@kbn/language-documentation';
import type { IUnifiedSearchPluginServices } from '../types';

export const ESQLMenuPopover = () => {
export interface ESQLMenuPopoverProps {
onESQLDocsFlyoutVisibilityChanged?: (isOpen: boolean) => void;
}

export const ESQLMenuPopover: React.FC<ESQLMenuPopoverProps> = ({
onESQLDocsFlyoutVisibilityChanged,
}) => {
const kibana = useKibana<IUnifiedSearchPluginServices>();

const { docLinks } = kibana.services;
Expand All @@ -34,6 +40,14 @@ export const ESQLMenuPopover = () => {
setIsESQLMenuPopoverOpen(false);
}, [isLanguageComponentOpen]);

const onHelpMenuVisibilityChange = useCallback(
(status: boolean) => {
setIsLanguageComponentOpen(status);
onESQLDocsFlyoutVisibilityChanged?.(status);
},
[setIsLanguageComponentOpen, onESQLDocsFlyoutVisibilityChanged]
);

const esqlPanelItems = useMemo(() => {
const panelItems: EuiContextMenuPanelProps['items'] = [];
panelItems.push(
Expand Down Expand Up @@ -122,7 +136,7 @@ export const ESQLMenuPopover = () => {
searchInDescription
linkToDocumentation={docLinks?.links?.query?.queryESQL ?? ''}
isHelpMenuOpen={isLanguageComponentOpen}
onHelpMenuVisibilityChange={setIsLanguageComponentOpen}
onHelpMenuVisibilityChange={onHelpMenuVisibilityChange}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { NoDataPopover } from './no_data_popover';
import { shallowEqual } from '../utils/shallow_equal';
import { AddFilterPopover } from './add_filter_popover';
import { DataViewPicker, DataViewPickerProps } from '../dataview_picker';
import { ESQLMenuPopover } from './esql_menu_popover';
import { ESQLMenuPopover, type ESQLMenuPopoverProps } from './esql_menu_popover';

import { FilterButtonGroup } from '../filter_bar/filter_button_group/filter_button_group';
import type {
Expand Down Expand Up @@ -186,6 +186,7 @@ export interface QueryBarTopRowProps<QT extends Query | AggregateQuery = Query>
submitOnBlur?: boolean;
renderQueryInputAppend?: () => React.ReactNode;
disableExternalPadding?: boolean;
onESQLDocsFlyoutVisibilityChanged?: ESQLMenuPopoverProps['onESQLDocsFlyoutVisibilityChanged'];
}

export const SharingMetaFields = React.memo(function SharingMetaFields({
Expand Down Expand Up @@ -774,7 +775,11 @@ export const QueryBarTopRow = React.memo(
wrap
>
{props.dataViewPickerOverride || renderDataViewsPicker()}
{Boolean(isQueryLangSelected) && <ESQLMenuPopover />}
{Boolean(isQueryLangSelected) && (
<ESQLMenuPopover
onESQLDocsFlyoutVisibilityChanged={props.onESQLDocsFlyoutVisibilityChanged}
/>
)}
<EuiFlexItem
grow={!shouldShowDatePickerAsBadge()}
style={{ minWidth: shouldShowDatePickerAsBadge() ? 'auto' : 320, maxWidth: '100%' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ export function createSearchBar({
dataTestSubj={props.dataTestSubj}
filtersForSuggestions={props.filtersForSuggestions}
prependFilterBar={props.prependFilterBar}
onESQLDocsFlyoutVisibilityChanged={props.onESQLDocsFlyoutVisibilityChanged}
/>
</core.i18n.Context>
</KibanaContextProvider>
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/unified_search/public/search_bar/search_bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export interface SearchBarOwnProps<QT extends AggregateQuery | Query = Query> {
submitOnBlur?: boolean;

renderQueryInputAppend?: () => React.ReactNode;
onESQLDocsFlyoutVisibilityChanged?: QueryBarTopRowProps['onESQLDocsFlyoutVisibilityChanged'];
}

export type SearchBarProps<QT extends Query | AggregateQuery = Query> = SearchBarOwnProps<QT> &
Expand Down Expand Up @@ -660,6 +661,7 @@ class SearchBarUI<QT extends (Query | AggregateQuery) | Query = Query> extends C
suggestionsAbstraction={this.props.suggestionsAbstraction}
renderQueryInputAppend={this.props.renderQueryInputAppend}
disableExternalPadding={this.props.displayStyle === 'withBorders'}
onESQLDocsFlyoutVisibilityChanged={this.props.onESQLDocsFlyoutVisibilityChanged}
/>
</div>
);
Expand Down
104 changes: 104 additions & 0 deletions test/functional/apps/discover/group8/_flyouts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';

export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const { common, discover, timePicker, header } = getPageObjects([
'common',
'discover',
'timePicker',
'header',
]);
const kibanaServer = getService('kibanaServer');
const security = getService('security');
const retry = getService('retry');
const dataGrid = getService('dataGrid');
const esql = getService('esql');
const testSubjects = getService('testSubjects');

describe('discover flyouts', function () {
async function isLensEditFlyoutOpen() {
return await testSubjects.exists('lnsChartSwitchPopover');
}

async function openLensEditFlyout() {
await testSubjects.click('unifiedHistogramEditFlyoutVisualization');
await retry.waitFor('flyout', async () => {
return await isLensEditFlyoutOpen();
});
}

before(async function () {
await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']);
await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover');
await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' });
await timePicker.setDefaultAbsoluteRangeViaUiSettings();
});

beforeEach(async function () {
await common.navigateToApp('discover');
await header.waitUntilLoadingHasFinished();
await discover.waitUntilSearchingHasFinished();
await discover.selectTextBaseLang();
await header.waitUntilLoadingHasFinished();
await discover.waitUntilSearchingHasFinished();
});

after(async () => {
await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional');
await kibanaServer.uiSettings.replace({});
await kibanaServer.savedObjects.cleanStandardList();
});

it('doc viewer flyout should get dismissed on opening ESQL docs flyout', async function () {
await dataGrid.clickRowToggle({ rowIndex: 0 });
expect(await dataGrid.isShowingDocViewer()).to.be(true);
await esql.openQuickReferenceFlyout();
expect(await dataGrid.isShowingDocViewer()).to.be(false);
expect(await esql.isOpenQuickReferenceFlyout()).to.be(true);
});

it('doc viewer flyout should get dismissed on opening Lens Edit flyout', async function () {
await dataGrid.clickRowToggle({ rowIndex: 0 });
expect(await dataGrid.isShowingDocViewer()).to.be(true);
await openLensEditFlyout();
expect(await dataGrid.isShowingDocViewer()).to.be(false);
expect(await isLensEditFlyoutOpen()).to.be(true);
});

it('ESQL docs flyout should get dismissed on opening doc viewer flyout', async function () {
await esql.openQuickReferenceFlyout();
expect(await esql.isOpenQuickReferenceFlyout()).to.be(true);
await dataGrid.clickRowToggle({ rowIndex: 0 });
expect(await dataGrid.isShowingDocViewer()).to.be(true);
expect(await esql.isOpenQuickReferenceFlyout()).to.be(false);
});

it('ESQL docs flyout should get dismissed on opening Lens Edit flyout', async function () {
await esql.openQuickReferenceFlyout();
expect(await esql.isOpenQuickReferenceFlyout()).to.be(true);
await openLensEditFlyout();
expect(await isLensEditFlyoutOpen()).to.be(true);
expect(await esql.isOpenQuickReferenceFlyout()).to.be(false);
});

it('Lens Edit flyout should get dismissed on opening doc viewer flyout', async function () {
await openLensEditFlyout();
expect(await isLensEditFlyoutOpen()).to.be(true);
await dataGrid.clickRowToggle({ rowIndex: 0 });
expect(await dataGrid.isShowingDocViewer()).to.be(true);
expect(await isLensEditFlyoutOpen()).to.be(false);
});
});
}
1 change: 1 addition & 0 deletions test/functional/apps/discover/group8/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {

loadTestFile(require.resolve('./_default_route'));
loadTestFile(require.resolve('./_hide_announcements'));
loadTestFile(require.resolve('./_flyouts'));
});
}
Loading