Skip to content

Commit

Permalink
[MD] Add dropdown header to Data source single selector
Browse files Browse the repository at this point in the history
Signed-off-by: Zhongnan Su <szhongna@amazon.com>
  • Loading branch information
zhongnansu committed Apr 16, 2024
1 parent eef417c commit 7282698
Show file tree
Hide file tree
Showing 16 changed files with 375 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [CSP Handler] Update CSP handler to only query and modify frame ancestors instead of all CSP directives ([#6398](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6398))
- [MD] Add OpenSearch cluster group label to top of single selectable dropdown ([#6400](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6400))
- [Workspace] Support workspace in saved objects client in server side. ([#6365](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6365))
- [MD] Add dropdown header to data source single selector ([#6431](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6431))

### 🐛 Bug Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
"ui": true,
"requiredPlugins": ["management", "dataSource", "indexPatternManagement"],
"optionalPlugins": [],
"requiredBundles": ["opensearchDashboardsReact", "dataSource"],
"requiredBundles": ["opensearchDashboardsReact", "dataSource", "opensearchDashboardsUtils"],
"extraPublicDirs": ["public/components/utils"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import { DataSourcePluginSetup } from 'src/plugins/data_source/public';
import { DataSourceMenu } from './data_source_menu';
import { DataSourceMenuProps } from './types';
import { MountPointPortal } from '../../../../opensearch_dashboards_react/public';
import { getApplication } from '../utils';

export function createDataSourceMenu<T>(
uiSettings: IUiSettingsClient,
dataSourcePluginSetup: DataSourcePluginSetup
) {
const application = getApplication();
return (props: DataSourceMenuProps<T>) => {
const { hideLocalCluster } = dataSourcePluginSetup;
if (props.setMenuMountPoint) {
Expand All @@ -25,13 +27,19 @@ export function createDataSourceMenu<T>(
{...props}
uiSettings={uiSettings}
hideLocalCluster={hideLocalCluster}
application={application}
/>
</EuiHeaderLinks>
</MountPointPortal>
);
}
return (
<DataSourceMenu {...props} uiSettings={uiSettings} hideLocalCluster={hideLocalCluster} />
<DataSourceMenu
{...props}
uiSettings={uiSettings}
hideLocalCluster={hideLocalCluster}
application={application}
/>
);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ import {
import { DataSourceSelectable } from '../data_source_selectable';

export function DataSourceMenu<T>(props: DataSourceMenuProps<T>): ReactElement | null {
const { componentType, componentConfig, uiSettings, hideLocalCluster } = props;

const { componentType, componentConfig, uiSettings, hideLocalCluster, application } = props;
function renderDataSourceView(config: DataSourceViewConfig): ReactElement | null {
const {
activeOption,
Expand Down Expand Up @@ -81,6 +80,7 @@ export function DataSourceMenu<T>(props: DataSourceMenuProps<T>): ReactElement |
hideLocalCluster={hideLocalCluster || false}
fullWidth={fullWidth}
uiSettings={uiSettings}
application={application}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
SavedObjectsClientContract,
SavedObject,
IUiSettingsClient,
ApplicationStart,
} from '../../../../../core/public';
import { DataSourceAttributes } from '../../types';

Expand All @@ -32,6 +33,7 @@ export interface DataSourceMenuProps<T = any> {
componentConfig: T;
hideLocalCluster?: boolean;
uiSettings?: IUiSettingsClient;
application?: ApplicationStart;
setMenuMountPoint?: (menuMount: MountPoint | undefined) => void;
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import { ShallowWrapper, shallow, mount } from 'enzyme';
import { SavedObjectsClientContract } from '../../../../../core/public';
import { notificationServiceMock } from '../../../../../core/public/mocks';
import React from 'react';
import { DataSourceSelectable, opensearchClusterGroupLabel } from './data_source_selectable';
import { DataSourceSelectable } from './data_source_selectable';
import { AuthType } from '../../types';
import { getDataSourcesWithFieldsResponse, mockResponseForSavedObjectsCalls } from '../../mocks';
import { render } from '@testing-library/react';
import * as utils from '../utils';
import { EuiSelectable } from '@elastic/eui';
import { dataSourceOptionGroupLabel } from '../utils';

describe('DataSourceSelectable', () => {
let component: ShallowWrapper<any, Readonly<{}>, React.Component<{}, {}, any>>;
Expand Down Expand Up @@ -409,7 +410,7 @@ describe('DataSourceSelectable', () => {
component.instance().componentDidMount!();
await nextTick();
const optionsProp = component.find(EuiSelectable).prop('options');
expect(optionsProp[0]).toEqual(opensearchClusterGroupLabel);
expect(optionsProp[0]).toEqual(dataSourceOptionGroupLabel.opensearchCluster);
});

it('should not render opensearch cluster group label, when there is no option availiable', async () => {
Expand All @@ -431,4 +432,50 @@ describe('DataSourceSelectable', () => {
const optionsProp = component.find(EuiSelectable).prop('options');
expect(optionsProp).toEqual([]);
});

it('should render group lablel normally after onChange', async () => {
const onSelectedDataSource = jest.fn();
component = shallow(
<DataSourceSelectable
savedObjectsClient={client}
notifications={toasts}
onSelectedDataSources={onSelectedDataSource}
disabled={false}
hideLocalCluster={true}
fullWidth={false}
selectedOption={[{ id: 'test1', label: 'test1' }]}
/>
);
const componentInstance = component.instance();

componentInstance.componentDidMount!();
await nextTick();
const optionsPropBefore = component.find(EuiSelectable).prop('options');
expect(optionsPropBefore).toEqual([
dataSourceOptionGroupLabel.opensearchCluster,
{
id: 'test1',
label: 'test1',
checked: 'on',
},
{
id: 'test2',
label: 'test2',
},
{
id: 'test3',
label: 'test3',
},
]);
componentInstance.onChange([
dataSourceOptionGroupLabel.opensearchCluster,
{ id: 'test2', label: 'test2', checked: 'on' },
]);
await nextTick();
const optionsPropAfter = component.find(EuiSelectable).prop('options');
expect(optionsPropAfter).toEqual([
dataSourceOptionGroupLabel.opensearchCluster,
{ id: 'test2', label: 'test2', checked: 'on' },
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,27 @@ import {
EuiButtonEmpty,
EuiSelectable,
EuiSpacer,
EuiHorizontalRule,
} from '@elastic/eui';
import {
ApplicationStart,
IUiSettingsClient,
SavedObjectsClientContract,
ToastsStart,
} from 'opensearch-dashboards/public';
import { getDataSourcesWithFields, getDefaultDataSource, getFilteredDataSources } from '../utils';
import {
dataSourceOptionGroupLabel,
getDataSourcesWithFields,
getDefaultDataSource,
getFilteredDataSources,
} from '../utils';
import { LocalCluster } from '../data_source_selector/data_source_selector';
import { SavedObject } from '../../../../../core/public';
import { DataSourceAttributes } from '../../types';
import { DataSourceGroupLabelOption, DataSourceOption } from '../data_source_menu/types';
import { DataSourceItem } from '../data_source_item';
import './data_source_selectable.scss';
import { DataSourceDropDownHeader } from '../drop_down_header';

interface DataSourceSelectableProps {
savedObjectsClient: SavedObjectsClientContract;
Expand All @@ -33,6 +41,7 @@ interface DataSourceSelectableProps {
disabled: boolean;
hideLocalCluster: boolean;
fullWidth: boolean;
application?: ApplicationStart;
selectedOption?: DataSourceOption[];
dataSourceFilter?: (dataSource: SavedObject<DataSourceAttributes>) => boolean;
uiSettings?: IUiSettingsClient;
Expand Down Expand Up @@ -193,9 +202,12 @@ export class DataSourceSelectable extends React.Component<

onChange(options: DataSourceOption[]) {
if (!this._isMounted) return;
const optionsWithoutGroupLabel = options.filter(
(option) => !option.hasOwnProperty('isGroupLabel')
);
const selectedDataSource = options.find(({ checked }) => checked);

this.setState({ dataSourceOptions: options });
this.setState({ dataSourceOptions: optionsWithoutGroupLabel });

if (selectedDataSource) {
this.setState({
Expand All @@ -213,7 +225,7 @@ export class DataSourceSelectable extends React.Component<
if (dataSourceOptions.length === 0) {
optionsWithGroupLabel = [];
} else {
optionsWithGroupLabel = [opensearchClusterGroupLabel, ...dataSourceOptions];
optionsWithGroupLabel = [dataSourceOptionGroupLabel.opensearchCluster, ...dataSourceOptions];
}
return optionsWithGroupLabel;
};
Expand Down Expand Up @@ -242,6 +254,7 @@ export class DataSourceSelectable extends React.Component<

return (
<EuiPopover
initialFocus={'.euiSelectableSearch'}
id={'dataSourceSelectableContextMenuPopover'}
button={button}
isOpen={this.state.isPopoverOpen}
Expand All @@ -252,12 +265,18 @@ export class DataSourceSelectable extends React.Component<
>
<EuiContextMenuPanel>
<EuiPanel className={'dataSourceSelectableOuiPanel'} color="transparent" paddingSize="s">
<DataSourceDropDownHeader
totalDataSourceCount={this.state.dataSourceOptions.length}
application={this.props.application}
/>
<EuiHorizontalRule margin="none" />
<EuiSpacer size="s" />
<EuiSelectable
aria-label="Search"
searchable
searchProps={{
placeholder: 'Search',
compressed: true,
}}
options={this.getOptionsWithGroupLabel(this.state.dataSourceOptions)}
onChange={(newOptions) => this.onChange(newOptions)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
mockResponseForSavedObjectsCalls,
} from '../../mocks';
import { AuthType } from 'src/plugins/data_source/common/data_sources';
import * as utils from '../utils';
import { EuiComboBox } from '@elastic/eui';

describe('DataSourceSelector', () => {
Expand Down
Loading

0 comments on commit 7282698

Please sign in to comment.