diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2f5d5ee061f..5f9e5e4d2ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,6 +32,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [Multiple Datasource] Test connection schema validation for registered auth types ([#6109](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6109))
- [Workspace] Consume workspace id in saved object client ([#6014](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6014))
- [Multiple Datasource] Export DataSourcePluginRequestContext at top level for plugins to use ([#6108](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6108))
+- [Multiple Datasource] Expose filterfn in datasource menu component to allow filter data sources before rendering in navigation bar ([#6113](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6113))
- [Workspace] Add delete saved objects by workspace functionality([#6013](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6013))
- [Workspace] Add a workspace client in workspace plugin ([#6094](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6094))
diff --git a/src/plugins/data_source_management/public/components/data_source_menu/__snapshots__/data_source_selectable.test.tsx.snap b/src/plugins/data_source_management/public/components/data_source_menu/__snapshots__/data_source_selectable.test.tsx.snap
index ff494ad932e..944750bde43 100644
--- a/src/plugins/data_source_management/public/components/data_source_menu/__snapshots__/data_source_selectable.test.tsx.snap
+++ b/src/plugins/data_source_management/public/components/data_source_menu/__snapshots__/data_source_selectable.test.tsx.snap
@@ -1,5 +1,81 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`DataSourceSelectable should filter options if configured 1`] = `
+
+
+
+ Local cluster
+
+
+ }
+ closePopover={[Function]}
+ display="inlineBlock"
+ hasArrow={true}
+ id="dataSourceSelectableContextMenuPopover"
+ isOpen={false}
+ ownFocus={true}
+ panelPaddingSize="none"
+>
+
+
+
+
+
+
+
+
+
+`;
+
exports[`DataSourceSelectable should render normally with local cluster is hidden 1`] = `
{
const component = render();
expect(component).toMatchSnapshot();
expect(client.find).toBeCalledWith({
- fields: ['id', 'description', 'title'],
+ fields: ['id', 'title', 'auth.type'],
perPage: 10000,
type: 'data-source',
});
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 57e3590f5bc..54c7642207d 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
@@ -28,6 +28,7 @@ export interface DataSourceMenuProps {
className?: string;
selectedOption?: DataSourceOption[];
setMenuMountPoint?: (menuMount: MountPoint | undefined) => void;
+ filterFn?: (dataSource: any) => boolean;
}
export function DataSourceMenu(props: DataSourceMenuProps): ReactElement | null {
@@ -40,6 +41,7 @@ export function DataSourceMenu(props: DataSourceMenuProps): ReactElement | null
fullWidth,
hideLocalCluster,
selectedOption,
+ filterFn,
} = props;
if (!showDataSourceSelectable) {
@@ -66,6 +68,7 @@ export function DataSourceMenu(props: DataSourceMenuProps): ReactElement | null
onSelectedDataSource={dataSourceCallBackFunc}
disabled={disableDataSourceSelectable || false}
selectedOption={selectedOption && selectedOption.length > 0 ? selectedOption : undefined}
+ filterFn={filterFn}
/>
);
}
diff --git a/src/plugins/data_source_management/public/components/data_source_menu/data_source_selectable.test.tsx b/src/plugins/data_source_management/public/components/data_source_menu/data_source_selectable.test.tsx
index 192aea1d642..7f3a182cf23 100644
--- a/src/plugins/data_source_management/public/components/data_source_menu/data_source_selectable.test.tsx
+++ b/src/plugins/data_source_management/public/components/data_source_menu/data_source_selectable.test.tsx
@@ -8,17 +8,21 @@ import { SavedObjectsClientContract } from '../../../../../core/public';
import { notificationServiceMock } from '../../../../../core/public/mocks';
import React from 'react';
import { DataSourceSelectable } from './data_source_selectable';
+import { AuthType } from '../../types';
+import { getDataSourcesWithFieldsResponse, mockResponseForSavedObjectsCalls } from '../../mocks';
describe('DataSourceSelectable', () => {
let component: ShallowWrapper, React.Component<{}, {}, any>>;
let client: SavedObjectsClientContract;
const { toasts } = notificationServiceMock.createStartContract();
+ const nextTick = () => new Promise((res) => process.nextTick(res));
beforeEach(() => {
client = {
find: jest.fn().mockResolvedValue([]),
} as any;
+ mockResponseForSavedObjectsCalls(client, 'find', getDataSourcesWithFieldsResponse);
});
it('should render normally with local cluster not hidden', () => {
@@ -34,7 +38,7 @@ describe('DataSourceSelectable', () => {
);
expect(component).toMatchSnapshot();
expect(client.find).toBeCalledWith({
- fields: ['id', 'description', 'title'],
+ fields: ['id', 'title', 'auth.type'],
perPage: 10000,
type: 'data-source',
});
@@ -54,10 +58,28 @@ describe('DataSourceSelectable', () => {
);
expect(component).toMatchSnapshot();
expect(client.find).toBeCalledWith({
- fields: ['id', 'description', 'title'],
+ fields: ['id', 'title', 'auth.type'],
perPage: 10000,
type: 'data-source',
});
expect(toasts.addWarning).toBeCalledTimes(0);
});
+
+ it('should filter options if configured', async () => {
+ component = shallow(
+ ds.attributes.auth.type !== AuthType.NoAuth}
+ />
+ );
+ component.instance().componentDidMount!();
+ await nextTick();
+ expect(component).toMatchSnapshot();
+ expect(toasts.addWarning).toBeCalledTimes(0);
+ });
});
diff --git a/src/plugins/data_source_management/public/components/data_source_menu/data_source_selectable.tsx b/src/plugins/data_source_management/public/components/data_source_menu/data_source_selectable.tsx
index 1c8c6bd2921..2aab73b0dd7 100644
--- a/src/plugins/data_source_management/public/components/data_source_menu/data_source_selectable.tsx
+++ b/src/plugins/data_source_management/public/components/data_source_menu/data_source_selectable.tsx
@@ -15,7 +15,7 @@ import {
EuiSpacer,
} from '@elastic/eui';
import { SavedObjectsClientContract, ToastsStart } from 'opensearch-dashboards/public';
-import { getDataSources } from '../utils';
+import { getDataSourcesWithFields } from '../utils';
import { DataSourceOption, LocalCluster } from '../data_source_selector/data_source_selector';
interface DataSourceSelectableProps {
@@ -26,6 +26,7 @@ interface DataSourceSelectableProps {
hideLocalCluster: boolean;
fullWidth: boolean;
selectedOption?: DataSourceOption[];
+ filterFn?: (dataSource: any) => boolean;
}
interface DataSourceSelectableState {
@@ -69,18 +70,24 @@ export class DataSourceSelectable extends React.Component<
async componentDidMount() {
this._isMounted = true;
- getDataSources(this.props.savedObjectsClient)
+ getDataSourcesWithFields(this.props.savedObjectsClient, ['id', 'title', 'auth.type'])
.then((fetchedDataSources) => {
if (fetchedDataSources?.length) {
- let dataSourceOptions = fetchedDataSources.map((dataSource) => ({
- id: dataSource.id,
- label: dataSource.title,
- }));
+ let filteredDataSources = [];
+ if (this.props.filterFn) {
+ filteredDataSources = fetchedDataSources.filter((ds) => this.props.filterFn!(ds));
+ }
- dataSourceOptions = dataSourceOptions.sort((a, b) =>
- a.label.toLowerCase().localeCompare(b.label.toLowerCase())
- );
+ if (filteredDataSources.length === 0) {
+ filteredDataSources = fetchedDataSources;
+ }
+ const dataSourceOptions = filteredDataSources
+ .map((dataSource) => ({
+ id: dataSource.id,
+ label: dataSource.attributes?.title || '',
+ }))
+ .sort((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase()));
if (!this.props.hideLocalCluster) {
dataSourceOptions.unshift(LocalCluster);
}