Skip to content

Commit

Permalink
[Discover] Adds an Options menu for switching between the two table m…
Browse files Browse the repository at this point in the history
…odes (elastic#97120)

* [Discover] Adds an Options menu for enabling the Legacy table

* Add unit test

* Layout and copy tweaks

* Update UI and fix unit test

* Change description text

* Revert legacy text mode functionality

Co-authored-by: Ryan Keairns <[email protected]>
Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
3 people committed Apr 20, 2021
1 parent a796024 commit af07b52
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ function getProps(): DiscoverTopNavProps {
discover: {
save: true,
},
advancedSettings: {
save: true,
},
},
uiSettings: mockUiSettings,
} as unknown) as DiscoverServices;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const services = ({
discover: {
save: true,
},
advancedSettings: {
save: true,
},
},
} as unknown) as DiscoverServices;

Expand All @@ -36,6 +39,13 @@ test('getTopNavLinks result', () => {
});
expect(topNavLinks).toMatchInlineSnapshot(`
Array [
Object {
"description": "Options",
"id": "options",
"label": "Options",
"run": [Function],
"testId": "discoverOptionsButton",
},
Object {
"description": "New Search",
"id": "new",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { SavedSearch } from '../../../saved_searches';
import { onSaveSearch } from './on_save_search';
import { GetStateReturn } from '../../angular/discover_state';
import { IndexPattern, ISearchSource } from '../../../kibana_services';
import { openOptionsPopover } from './open_options_popover';

/**
* Helper function to build the top nav links
Expand All @@ -38,6 +39,22 @@ export const getTopNavLinks = ({
onOpenInspector: () => void;
searchSource: ISearchSource;
}) => {
const options = {
id: 'options',
label: i18n.translate('discover.localMenu.localMenu.optionsTitle', {
defaultMessage: 'Options',
}),
description: i18n.translate('discover.localMenu.optionsDescription', {
defaultMessage: 'Options',
}),
run: (anchorElement: HTMLElement) =>
openOptionsPopover({
I18nContext: services.core.i18n.Context,
anchorElement,
}),
testId: 'discoverOptionsButton',
};

const newSearch = {
id: 'new',
label: i18n.translate('discover.localMenu.localMenu.newSearchTitle', {
Expand Down Expand Up @@ -128,6 +145,7 @@ export const getTopNavLinks = ({
};

return [
...(services.capabilities.advancedSettings.save ? [options] : []),
newSearch,
...(services.capabilities.discover.save ? [saveSearch] : []),
openSearch,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$dscOptionsPopoverWidth: $euiSizeL * 12;

.dscOptionsPopover {
width: $dscOptionsPopoverWidth;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { mountWithIntl } from '@kbn/test/jest';
import { findTestSubject } from '@elastic/eui/lib/test';
import { getServices } from '../../../kibana_services';

jest.mock('../../../kibana_services', () => {
const mockUiSettings = new Map();
return {
getServices: () => ({
core: {
uiSettings: {
get: (key: string) => {
return mockUiSettings.get(key);
},
set: (key: string, value: boolean) => {
mockUiSettings.set(key, value);
},
},
},
addBasePath: (path: string) => path,
}),
};
});

import { OptionsPopover } from './open_options_popover';

test('should display the correct text if datagrid is selected', () => {
const element = document.createElement('div');
const component = mountWithIntl(<OptionsPopover onClose={jest.fn()} anchorElement={element} />);
expect(findTestSubject(component, 'docTableMode').text()).toBe('Data grid');
});

test('should display the correct text if legacy table is selected', () => {
const {
core: { uiSettings },
} = getServices();
uiSettings.set('doc_table:legacy', true);
const element = document.createElement('div');
const component = mountWithIntl(<OptionsPopover onClose={jest.fn()} anchorElement={element} />);
expect(findTestSubject(component, 'docTableMode').text()).toBe('Legacy table');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import ReactDOM from 'react-dom';
import { I18nStart } from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiSpacer, EuiButton, EuiText, EuiWrappingPopover, EuiCode } from '@elastic/eui';
import { getServices } from '../../../kibana_services';
import './open_options_popover.scss';

let isOpen = false;

interface OptionsPopoverProps {
onClose: () => void;
anchorElement: HTMLElement;
}

export function OptionsPopover(props: OptionsPopoverProps) {
const {
core: { uiSettings },
addBasePath,
} = getServices();
const isLegacy = uiSettings.get('doc_table:legacy');

const mode = isLegacy
? i18n.translate('discover.openOptionsPopover.legacyTableText', {
defaultMessage: 'Legacy table',
})
: i18n.translate('discover.openOptionsPopover.dataGridText', {
defaultMessage: 'Data grid',
});

return (
<EuiWrappingPopover ownFocus button={props.anchorElement} closePopover={props.onClose} isOpen>
<div className="dscOptionsPopover">
<EuiText color="subdued" size="s">
<p>
<strong>Current view mode:</strong>{' '}
<EuiCode data-test-subj="docTableMode">{mode}</EuiCode>
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiText color="subdued" size="s">
<FormattedMessage
id="discover.topNav.openOptionsPopover.description"
defaultMessage="The new data grid layout includes enhanced data sorting, drag-and-drop columns, multi-document selection, and a full screen view. Toggle 'Use legacy table' in Advanced Settings to switch modes."
/>
</EuiText>
<EuiSpacer />
<EuiButton
iconType="tableDensityNormal"
fullWidth
href={addBasePath('/app/management/kibana/settings?query=Use legacy table')}
>
{i18n.translate('discover.openOptionsPopover.goToAdvancedSettings', {
defaultMessage: 'Go to Advanced Settings',
})}
</EuiButton>
</div>
</EuiWrappingPopover>
);
}

export function openOptionsPopover({
I18nContext,
anchorElement,
}: {
I18nContext: I18nStart['Context'];
anchorElement: HTMLElement;
}) {
if (isOpen) {
return;
}

isOpen = true;
const container = document.createElement('div');
const onClose = () => {
ReactDOM.unmountComponentAtNode(container);
document.body.removeChild(container);
isOpen = false;
};

document.body.appendChild(container);

const element = (
<I18nContext>
<OptionsPopover onClose={onClose} anchorElement={anchorElement} />
</I18nContext>
);
ReactDOM.render(element, container);
}

0 comments on commit af07b52

Please sign in to comment.