diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d8df629285..fa22c691941 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Workspace] Add workspace list page ([#6182](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6182)) - [Workspace] Add workspaces column to saved objects page ([#6225](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6225)) - [Multiple Datasource] Add multi data source support to sample vega visualizations ([#6218](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6218)) +- [Multiple Datasource] Fetch data source title for DataSourceView when only id is provided ([#6315](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6315) - [Workspace] Add permission control logic ([#6052](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6052)) ### 🐛 Bug Fixes diff --git a/src/plugins/data_source_management/public/components/data_source_menu/__snapshots__/data_source_menu.test.tsx.snap b/src/plugins/data_source_management/public/components/data_source_menu/__snapshots__/data_source_menu.test.tsx.snap index 5edfd562076..8f8ea1a0f55 100644 --- a/src/plugins/data_source_management/public/components/data_source_menu/__snapshots__/data_source_menu.test.tsx.snap +++ b/src/plugins/data_source_management/public/components/data_source_menu/__snapshots__/data_source_menu.test.tsx.snap @@ -1,5 +1,66 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`DataSourceMenu can render data source view when only pass id in the activeOption 1`] = ` + +`; + +exports[`DataSourceMenu can render data source view when provide activeOption 1`] = ` + +`; + exports[`DataSourceMenu should render data source aggregated view 1`] = ` Object { "asFragment": [Function], @@ -344,9 +405,44 @@ exports[`DataSourceMenu should render data source selectable only with local clu /> `; +exports[`DataSourceMenu should render data source view if not pass saved object or notification 1`] = ` + +`; + exports[`DataSourceMenu should render data source view only 1`] = ` `; diff --git a/src/plugins/data_source_management/public/components/data_source_menu/data_source_menu.test.tsx b/src/plugins/data_source_management/public/components/data_source_menu/data_source_menu.test.tsx index 538d579c4b6..e7df411a9e8 100644 --- a/src/plugins/data_source_management/public/components/data_source_menu/data_source_menu.test.tsx +++ b/src/plugins/data_source_management/public/components/data_source_menu/data_source_menu.test.tsx @@ -59,7 +59,58 @@ describe('DataSourceMenu', () => { component = shallow( + ); + expect(component).toMatchSnapshot(); + }); + + it('should render data source view if not pass saved object or notification', () => { + component = shallow( + + ); + expect(component).toMatchSnapshot(); + }); + + it('can render data source view when provide activeOption', () => { + component = shallow( + + ); + expect(component).toMatchSnapshot(); + }); + + it('can render data source view when only pass id in the activeOption', () => { + component = shallow( + ); expect(component).toMatchSnapshot(); 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 70ca70fd5ce..b56063e5d25 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 @@ -22,11 +22,13 @@ export function DataSourceMenu(props: DataSourceMenuProps): ReactElement | const { componentType, componentConfig } = props; function renderDataSourceView(config: DataSourceViewConfig): ReactElement | null { - const { activeOption, fullWidth } = config; + const { activeOption, fullWidth, savedObjects, notifications } = config; return ( 0 ? activeOption : undefined} fullWidth={fullWidth} + selectedOption={activeOption} + savedObjectsClient={savedObjects} + notifications={notifications?.toasts} /> ); } diff --git a/src/plugins/data_source_management/public/components/data_source_view/__snapshots__/data_source_view.test.tsx.snap b/src/plugins/data_source_management/public/components/data_source_view/__snapshots__/data_source_view.test.tsx.snap index 29f64c4293e..183ebc56350 100644 --- a/src/plugins/data_source_management/public/components/data_source_view/__snapshots__/data_source_view.test.tsx.snap +++ b/src/plugins/data_source_management/public/components/data_source_view/__snapshots__/data_source_view.test.tsx.snap @@ -1,5 +1,107 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`DataSourceView should call getDataSourceById when only pass id no label 1`] = ` + + + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + id="dataSourceViewContextMenuPopover" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + + + +`; + +exports[`DataSourceView should call notification warning when there is data source fetch error 1`] = ` + + + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + id="dataSourceViewContextMenuPopover" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + + + +`; + exports[`DataSourceView should render normally with local cluster not hidden 1`] = ` `; + +exports[`DataSourceView should show popover when click on button 1`] = ` +Object { + "asFragment": [Function], + "baseElement": +
+ +
+
+ +
+
+
+ , + "container":
+ +
+
+ +
+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/src/plugins/data_source_management/public/components/data_source_view/data_source_view.test.tsx b/src/plugins/data_source_management/public/components/data_source_view/data_source_view.test.tsx index f7022a308a0..a3cfd5223f6 100644 --- a/src/plugins/data_source_management/public/components/data_source_view/data_source_view.test.tsx +++ b/src/plugins/data_source_management/public/components/data_source_view/data_source_view.test.tsx @@ -6,14 +6,70 @@ import { ShallowWrapper, shallow } from 'enzyme'; import React from 'react'; import { DataSourceView } from './data_source_view'; +import { SavedObjectsClientContract } from 'opensearch-dashboards/public'; +import { notificationServiceMock } from '../../../../../core/public/mocks'; +import { + getSingleDataSourceResponse, + mockErrorResponseForSavedObjectsCalls, + mockResponseForSavedObjectsCalls, +} from '../../mocks'; +import { render } from '@testing-library/react'; describe('DataSourceView', () => { let component: ShallowWrapper, React.Component<{}, {}, any>>; + let client: SavedObjectsClientContract; + const { toasts } = notificationServiceMock.createStartContract(); + + beforeEach(() => { + client = { + get: jest.fn().mockResolvedValue([]), + } as any; + mockResponseForSavedObjectsCalls(client, 'get', getSingleDataSourceResponse); + }); it('should render normally with local cluster not hidden', () => { component = shallow( ); expect(component).toMatchSnapshot(); + expect(toasts.addWarning).toBeCalledTimes(0); + }); + it('should show popover when click on button', async () => { + const container = render( + + ); + const button = await container.findByTestId('dataSourceViewContextMenuHeaderLink'); + button.click(); + expect(container).toMatchSnapshot(); + }); + it('should call getDataSourceById when only pass id no label', async () => { + component = shallow( + + ); + expect(component).toMatchSnapshot(); + expect(client.get).toBeCalledWith('data-source', 'test1'); + expect(toasts.addWarning).toBeCalledTimes(0); + }); + it('should call notification warning when there is data source fetch error', async () => { + jest.mock('../utils', () => ({ + getDataSourceById: jest.fn(), + })); + component = shallow( + + ); + expect(component).toMatchSnapshot(); + mockErrorResponseForSavedObjectsCalls(client, 'get'); + expect(toasts.addWarning).toBeCalledTimes(1); + expect(toasts.addWarning).toBeCalledWith(`Data source with id test1 is not available`); }); }); diff --git a/src/plugins/data_source_management/public/components/data_source_view/data_source_view.tsx b/src/plugins/data_source_management/public/components/data_source_view/data_source_view.tsx index 23bb2e34fea..005d54e216c 100644 --- a/src/plugins/data_source_management/public/components/data_source_view/data_source_view.tsx +++ b/src/plugins/data_source_management/public/components/data_source_view/data_source_view.tsx @@ -6,11 +6,16 @@ import React from 'react'; import { i18n } from '@osd/i18n'; import { EuiPopover, EuiButtonEmpty, EuiButtonIcon, EuiContextMenu } from '@elastic/eui'; +import { SavedObjectsClientContract, ToastsStart } from 'opensearch-dashboards/public'; import { DataSourceOption } from '../data_source_menu/types'; +import { getDataSourceById } from '../utils'; +import { MenuPanelItem } from '../../types'; interface DataSourceViewProps { fullWidth: boolean; - selectedOption?: DataSourceOption[]; + selectedOption: DataSourceOption[]; + savedObjectsClient?: SavedObjectsClientContract; + notifications?: ToastsStart; } interface DataSourceViewState { @@ -19,6 +24,8 @@ interface DataSourceViewState { } export class DataSourceView extends React.Component { + private _isMounted: boolean = false; + constructor(props: DataSourceViewProps) { super(props); @@ -28,6 +35,41 @@ export class DataSourceView extends React.Component - ); - - let items = []; - - if (this.props.selectedOption) { - items = this.props.selectedOption.map((option) => { + getPanels() { + let items: MenuPanelItem[] = []; + if (this.state.selectedOption) { + items = this.state.selectedOption.map((option) => { return { name: option.label, disabled: true, @@ -65,6 +97,20 @@ export class DataSourceView extends React.Component + ); return ( <> - {this.props.selectedOption && this.props.selectedOption.length > 0 - ? this.props.selectedOption[0].label + {this.state.selectedOption && this.state.selectedOption.length > 0 + ? this.state.selectedOption[0].label : ''}