diff --git a/CHANGELOG.md b/CHANGELOG.md index abaf2f303b4a..9b84ff088874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Multiple Datasource] Add default icon for selectable component and make sure the default datasource shows automatically ([#6327](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6327)) - [Multiple Datasource] Pass selected data sources to plugin consumers when the multi-select component initially loads ([#6333](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6333)) - [Multiple Datasource] Add installedPlugins list to data source saved object ([#6348](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6348)) +- [Multiple Datasource] Add default icon in multi-selectable picker ([#6357](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6357)) - [Workspace] Add APIs to support plugin state in request ([#6303](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6303)) ### 🐛 Bug Fixes diff --git a/src/plugins/data_source_management/public/components/data_source_menu/data_source_menu.tsx b/src/plugins/data_source_management/public/components/data_source_menu/data_source_menu.tsx index b1f7ed1eaadd..0099e918246f 100644 --- a/src/plugins/data_source_management/public/components/data_source_menu/data_source_menu.tsx +++ b/src/plugins/data_source_management/public/components/data_source_menu/data_source_menu.tsx @@ -50,6 +50,7 @@ export function DataSourceMenu(props: DataSourceMenuProps): ReactElement | savedObjectsClient={savedObjects!} notifications={notifications!.toasts} onSelectedDataSources={onSelectedDataSources!} + uiSettings={uiSettings} /> ); } diff --git a/src/plugins/data_source_management/public/components/data_source_multi_selectable/__snapshots__/data_source_filter_group.test.tsx.snap b/src/plugins/data_source_management/public/components/data_source_multi_selectable/__snapshots__/data_source_filter_group.test.tsx.snap index 665f9cfa27dc..ba0ef237524c 100644 --- a/src/plugins/data_source_management/public/components/data_source_multi_selectable/__snapshots__/data_source_filter_group.test.tsx.snap +++ b/src/plugins/data_source_management/public/components/data_source_multi_selectable/__snapshots__/data_source_filter_group.test.tsx.snap @@ -62,7 +62,24 @@ exports[`DataSourceFilterGroup should render normally 1`] = ` } } > - name1 + + + name1 + + + + Default + + + @@ -204,7 +221,33 @@ Object { - name1 +
+
+ name1 +
+
+ + + + Default + + + +
+
@@ -497,7 +540,15 @@ Object { - name1 +
+
+ name1 +
+
diff --git a/src/plugins/data_source_management/public/components/data_source_multi_selectable/__snapshots__/data_source_multi_selectable.test.tsx.snap b/src/plugins/data_source_management/public/components/data_source_multi_selectable/__snapshots__/data_source_multi_selectable.test.tsx.snap index 627a1169c15b..9f457a898d74 100644 --- a/src/plugins/data_source_management/public/components/data_source_multi_selectable/__snapshots__/data_source_multi_selectable.test.tsx.snap +++ b/src/plugins/data_source_management/public/components/data_source_multi_selectable/__snapshots__/data_source_multi_selectable.test.tsx.snap @@ -2,6 +2,7 @@ exports[`DataSourceMultiSelectable should render normally with local cluster hidden 1`] = ` @@ -9,6 +10,7 @@ exports[`DataSourceMultiSelectable should render normally with local cluster hid exports[`DataSourceMultiSelectable should render normally with local cluster not hidden 1`] = ` diff --git a/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_filter_group.test.tsx b/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_filter_group.test.tsx index 62bf10ec8310..b75dbdf8a55c 100644 --- a/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_filter_group.test.tsx +++ b/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_filter_group.test.tsx @@ -17,6 +17,7 @@ describe('DataSourceFilterGroup', () => { mockCallBack(items)} + defaultDataSource="1" /> ); expect(component).toMatchSnapshot(); @@ -28,6 +29,7 @@ describe('DataSourceFilterGroup', () => { mockCallBack(items)} + defaultDataSource="1" /> ); const button = await container.findByTestId('dataSourceFilterGroupButton'); diff --git a/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_filter_group.tsx b/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_filter_group.tsx index 8d0e22beadaf..5ea7ffff29a1 100644 --- a/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_filter_group.tsx +++ b/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_filter_group.tsx @@ -14,6 +14,9 @@ import { EuiPopoverFooter, EuiButtonGroup, EuiButtonEmpty, + EuiBadge, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; import { DataSourceOption } from '../data_source_selector/data_source_selector'; @@ -27,6 +30,7 @@ export interface SelectedDataSourceOption extends DataSourceOption { export interface DataSourceFilterGroupProps { selectedOptions: SelectedDataSourceOption[]; setSelectedOptions: (options: SelectedDataSourceOption[]) => void; + defaultDataSource: string | null; } type SelectionToggleOptionIds = 'select_all' | 'deselect_all'; @@ -45,6 +49,7 @@ const selectionToggleButtons = [ export const DataSourceFilterGroup: React.FC = ({ selectedOptions, setSelectedOptions, + defaultDataSource, }) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [selectionToggleSelectedId, setSelectionToggleSelectedId] = useState< @@ -148,7 +153,14 @@ export const DataSourceFilterGroup: React.FC = ({ showIcons={true} style={itemStyle} > - {item.label} + + {item.label} + {item.id === defaultDataSource && ( + + Default + + )} + ); })} diff --git a/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_multi_selectable.test.tsx b/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_multi_selectable.test.tsx index afe65f554626..448eb404d995 100644 --- a/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_multi_selectable.test.tsx +++ b/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_multi_selectable.test.tsx @@ -5,7 +5,11 @@ import { SavedObjectsClientContract } from 'opensearch-dashboards/public'; import { notificationServiceMock } from '../../../../../core/public/mocks'; -import { getDataSourcesWithFieldsResponse, mockResponseForSavedObjectsCalls } from '../../mocks'; +import { + getDataSourcesWithFieldsResponse, + mockResponseForSavedObjectsCalls, + mockManagementPlugin, +} from '../../mocks'; import { ShallowWrapper, shallow } from 'enzyme'; import { DataSourceMultiSelectable } from './data_source_multi_selectable'; import React from 'react'; @@ -17,8 +21,12 @@ describe('DataSourceMultiSelectable', () => { let client: SavedObjectsClientContract; const { toasts } = notificationServiceMock.createStartContract(); const nextTick = () => new Promise((res) => process.nextTick(res)); + const mockedContext = mockManagementPlugin.createDataSourceManagementContext(); + const uiSettings = mockedContext.uiSettings; beforeEach(() => { + jest.clearAllMocks(); + client = { find: jest.fn().mockResolvedValue([]), } as any; @@ -102,4 +110,40 @@ describe('DataSourceMultiSelectable', () => { expect(callbackMock).toBeCalledWith([]); }); + + it('should retrun correct state when ui Settings provided', async () => { + spyOn(uiSettings, 'get').and.returnValue('test1'); + component = shallow( + + ); + await component.instance().componentDidMount!(); + expect(uiSettings.get).toBeCalledWith('defaultDataSource', null); + expect(component.state('defaultDataSource')).toEqual('test1'); + expect(component.state('selectedOptions')).toHaveLength(3); + }); + + it('should retrun correct state when ui Settings provided and hide cluster is false', async () => { + spyOn(uiSettings, 'get').and.returnValue('test1'); + component = shallow( + + ); + await component.instance().componentDidMount!(); + expect(uiSettings.get).toBeCalledWith('defaultDataSource', null); + expect(component.state('defaultDataSource')).toEqual('test1'); + expect(component.state('selectedOptions')).toHaveLength(4); + }); }); diff --git a/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_multi_selectable.tsx b/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_multi_selectable.tsx index 2bcf57899189..c5ee3717ff57 100644 --- a/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_multi_selectable.tsx +++ b/src/plugins/data_source_management/public/components/data_source_multi_selectable/data_source_multi_selectable.tsx @@ -6,6 +6,7 @@ import React from 'react'; import { SavedObjectsClientContract, ToastsStart } from 'opensearch-dashboards/public'; import { i18n } from '@osd/i18n'; +import { IUiSettingsClient } from 'src/core/public'; import { DataSourceFilterGroup, SelectedDataSourceOption } from './data_source_filter_group'; import { getDataSourcesWithFields } from '../utils'; @@ -15,11 +16,13 @@ export interface DataSourceMultiSeletableProps { onSelectedDataSources: (dataSources: SelectedDataSourceOption[]) => void; hideLocalCluster: boolean; fullWidth: boolean; + uiSettings?: IUiSettingsClient; } interface DataSourceMultiSeletableState { dataSourceOptions: SelectedDataSourceOption[]; selectedOptions: SelectedDataSourceOption[]; + defaultDataSource: string | null; } export class DataSourceMultiSelectable extends React.Component< @@ -34,6 +37,7 @@ export class DataSourceMultiSelectable extends React.Component< this.state = { dataSourceOptions: [], selectedOptions: [], + defaultDataSource: null, }; } @@ -43,46 +47,49 @@ export class DataSourceMultiSelectable extends React.Component< async componentDidMount() { this._isMounted = true; - getDataSourcesWithFields(this.props.savedObjectsClient, ['id', 'title', 'auth.type']) - .then((fetchedDataSources) => { - if (fetchedDataSources?.length) { - // all data sources are selected by default on initial page load - const selectedOptions: SelectedDataSourceOption[] = fetchedDataSources.map( - (dataSource) => ({ - id: dataSource.id, - label: dataSource.attributes?.title || '', - checked: 'on', - visible: true, - }) - ); + try { + const defaultDataSource = this.props.uiSettings?.get('defaultDataSource', null) ?? null; + let selectedOptions: SelectedDataSourceOption[] = []; + const fetchedDataSources = await getDataSourcesWithFields(this.props.savedObjectsClient, [ + 'id', + 'title', + 'auth.type', + ]); - if (!this.props.hideLocalCluster) { - selectedOptions.unshift({ - id: '', - label: 'Local cluster', - checked: 'on', - visible: true, - }); - } + if (fetchedDataSources?.length) { + selectedOptions = fetchedDataSources.map((dataSource) => ({ + id: dataSource.id, + label: dataSource.attributes?.title || '', + checked: 'on', + visible: true, + })); + } - if (!this._isMounted) return; - this.setState({ - ...this.state, - selectedOptions, - }); + if (!this.props.hideLocalCluster) { + selectedOptions.unshift({ + id: '', + label: 'Local cluster', + checked: 'on', + visible: true, + }); + } - this.props.onSelectedDataSources( - selectedOptions.filter((option) => option.checked === 'on') - ); - } - }) - .catch(() => { - this.props.notifications.addWarning( - i18n.translate('dataSource.fetchDataSourceError', { - defaultMessage: 'Unable to fetch existing data sources', - }) - ); + if (!this._isMounted) return; + + this.setState({ + ...this.state, + selectedOptions, + defaultDataSource, }); + + this.props.onSelectedDataSources(selectedOptions.filter((option) => option.checked === 'on')); + } catch (error) { + this.props.notifications.addWarning( + i18n.translate('dataSource.fetchDataSourceError', { + defaultMessage: 'Unable to fetch existing data sources', + }) + ); + } } onChange(selectedOptions: SelectedDataSourceOption[]) { @@ -98,6 +105,7 @@ export class DataSourceMultiSelectable extends React.Component< ); }