Skip to content

Commit

Permalink
Merge branch 'main' into fix-workspace-update-page-missing-apps
Browse files Browse the repository at this point in the history
  • Loading branch information
ruanyl authored Apr 17, 2024
2 parents 72baa1d + d2d410b commit e4b5b5a
Show file tree
Hide file tree
Showing 14 changed files with 157 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [Mulitple Datasource] Add multi data source support to TSVB ([#6298](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6298))
- [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))
- [Multiple Datasource] Add empty state component for no connected data source ([#6499](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6499))
- [Workspace] Add APIs to support plugin state in request ([#6303](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6303))
- [Workspace] Filter left nav menu items according to the current workspace ([#6234](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6234))
- [Multiple Datasource] Add multi data source support to Timeline ([#6385](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6385))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { shallow } from 'enzyme';
import { SavedObjectsClientContract } from '../../../../../core/public';
import React from 'react';
import IndexPatternSelect from './index_pattern_select';

describe('IndexPatternSelect', () => {
let client: SavedObjectsClientContract;
const bulkGetMock = jest.fn();

const nextTick = () => new Promise((res) => process.nextTick(res));

beforeEach(() => {
client = {
find: jest.fn().mockResolvedValue({
savedObjects: [
{
references: [{ id: 'testDataSourceId', type: 'data-source' }],
attributes: { title: 'testTitle1' },
},
{
references: [{ id: 'testDataSourceId', type: 'data-source' }],
attributes: { title: 'testTitle2' },
},
],
}),
bulkGet: bulkGetMock,
get: jest.fn().mockResolvedValue({
references: [{ id: 'someId', type: 'data-source' }],
attributes: { title: 'testTitle' },
}),
} as any;
});

it('should render index pattern select', async () => {
const onChangeMock = jest.fn();
const compInstance = shallow(
<IndexPatternSelect
placeholder={'test index pattern'}
indexPatternId={'testId'}
onChange={onChangeMock}
data-test-subj={'testId'}
savedObjectsClient={client}
/>
).instance();

bulkGetMock.mockResolvedValue({ savedObjects: [{ attributes: { title: 'test1' } }] });
compInstance.debouncedFetch('');
await new Promise((resolve) => setTimeout(resolve, 300));
await nextTick();
expect(bulkGetMock).toBeCalledWith([{ id: 'testDataSourceId', type: 'data-source' }]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,15 @@ export default class IndexPatternSelect extends Component<IndexPatternSelectProp
// order than they were sent out. Only load results for the most recent search.
if (searchValue === this.state.searchValue) {
const dataSourcesToFetch: Array<{ type: string; id: string }> = [];
const dataSourceIdSet = new Set();
savedObjects.map((indexPatternSavedObject: SimpleSavedObject<any>) => {
const dataSourceReference = getDataSourceReference(indexPatternSavedObject.references);
if (dataSourceReference && !this.state.dataSourceIdToTitle.has(dataSourceReference.id)) {
if (
dataSourceReference &&
!this.state.dataSourceIdToTitle.has(dataSourceReference.id) &&
!dataSourceIdSet.has(dataSourceReference.id)
) {
dataSourceIdSet.add(dataSourceReference.id);
dataSourcesToFetch.push({ type: 'data-source', id: dataSourceReference.id });
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { SavedObjectsClientContract, ToastsStart } from 'opensearch-dashboards/p
import { getDataSourcesWithFields, handleDataSourceFetchError } from '../utils';
import { SavedObject } from '../../../../../core/public';
import { DataSourceAttributes } from '../../types';
import { NoDataSource } from '../no_data_source';
import { DataSourceErrorMenu } from '../data_source_error_menu';
import { DataSourceBaseState } from '../data_source_menu/types';

Expand Down Expand Up @@ -46,6 +47,7 @@ export class DataSourceAggregatedView extends React.Component<
this.state = {
isPopoverOpen: false,
allDataSourcesIdToTitleMap: new Map(),
showEmptyState: false,
showError: false,
};
}
Expand Down Expand Up @@ -73,7 +75,6 @@ export class DataSourceAggregatedView extends React.Component<
this.props.dataSourceFilter!(ds)
);
}

const allDataSourcesIdToTitleMap = new Map();

filteredDataSources.forEach((ds) => {
Expand Down Expand Up @@ -101,6 +102,9 @@ export class DataSourceAggregatedView extends React.Component<
}

render() {
if (this.state.showEmptyState) {
return <NoDataSource />;
}
if (this.state.showError) {
return <DataSourceErrorMenu />;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { DataSourceSelectable } from '../data_source_selectable';

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

function renderDataSourceView(config: DataSourceViewConfig): ReactElement | null {
const {
activeOption,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface DataSourceBaseConfig {
}

export interface DataSourceBaseState {
showEmptyState: boolean;
showError: boolean;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React from 'react';
import { SavedObjectsClientContract, ToastsStart } from 'opensearch-dashboards/public';
import { IUiSettingsClient } from 'src/core/public';
import { DataSourceFilterGroup, SelectedDataSourceOption } from './data_source_filter_group';
import { NoDataSource } from '../no_data_source';
import { getDataSourcesWithFields, handleDataSourceFetchError } from '../utils';
import { DataSourceBaseState } from '../data_source_menu/types';
import { DataSourceErrorMenu } from '../data_source_error_menu';
Expand Down Expand Up @@ -39,6 +40,7 @@ export class DataSourceMultiSelectable extends React.Component<
dataSourceOptions: [],
selectedOptions: [],
defaultDataSource: null,
showEmptyState: false,
showError: false,
};
}
Expand Down Expand Up @@ -82,6 +84,7 @@ export class DataSourceMultiSelectable extends React.Component<
...this.state,
selectedOptions,
defaultDataSource,
showEmptyState: (fetchedDataSources?.length === 0 && this.props.hideLocalCluster) || false,
});

this.props.onSelectedDataSources(selectedOptions);
Expand All @@ -107,6 +110,9 @@ export class DataSourceMultiSelectable extends React.Component<
}

render() {
if (this.state.showEmptyState) {
return <NoDataSource />;
}
if (this.state.showError) {
return <DataSourceErrorMenu />;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ describe('DataSourceSelectable', () => {
],
defaultDataSource: null,
isPopoverOpen: false,
showEmptyState: false,
selectedOption: [
{
id: 'test2',
Expand All @@ -159,6 +160,7 @@ describe('DataSourceSelectable', () => {
],
defaultDataSource: null,
isPopoverOpen: false,
showEmptyState: false,
selectedOption: [
{
checked: 'on',
Expand Down Expand Up @@ -337,6 +339,7 @@ describe('DataSourceSelectable', () => {
],
defaultDataSource: null,
isPopoverOpen: false,
showEmptyState: false,
selectedOption: [
{
id: 'test2',
Expand Down Expand Up @@ -371,6 +374,7 @@ describe('DataSourceSelectable', () => {
defaultDataSource: null,
isPopoverOpen: false,
selectedOption: [],
showEmptyState: false,
showError: true,
});

Expand All @@ -385,6 +389,7 @@ describe('DataSourceSelectable', () => {
],
defaultDataSource: null,
isPopoverOpen: false,
showEmptyState: false,
selectedOption: [
{
checked: 'on',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import {
} from '../data_source_menu/types';
import { DataSourceErrorMenu } from '../data_source_error_menu';
import { DataSourceItem } from '../data_source_item';
import { NoDataSource } from '../no_data_source';
import './data_source_selectable.scss';
import { DataSourceDropDownHeader } from '../drop_down_header';
import '../button_title.scss';
import './data_source_selectable.scss';
Expand Down Expand Up @@ -81,6 +83,7 @@ export class DataSourceSelectable extends React.Component<
isPopoverOpen: false,
selectedOption: [],
defaultDataSource: null,
showEmptyState: false,
showError: false,
};

Expand Down Expand Up @@ -186,6 +189,10 @@ export class DataSourceSelectable extends React.Component<
this.props.dataSourceFilter
);

if (dataSourceOptions.length === 0 && this.props.hideLocalCluster) {
this.setState({ showEmptyState: true });
}

if (!this.props.hideLocalCluster) {
dataSourceOptions.unshift(LocalCluster);
}
Expand Down Expand Up @@ -243,6 +250,9 @@ export class DataSourceSelectable extends React.Component<
};

render() {
if (this.state.showEmptyState) {
return <NoDataSource />;
}
if (this.state.showError) {
return <DataSourceErrorMenu />;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
handleNoAvailableDataSourceError,
} from '../utils';
import { LocalCluster } from '../constants';
import { NoDataSource } from '../no_data_source';

interface DataSourceViewProps {
fullWidth: boolean;
Expand All @@ -43,6 +44,7 @@ export class DataSourceView extends React.Component<DataSourceViewProps, DataSou
this.state = {
isPopoverOpen: false,
selectedOption: this.props.selectedOption ? this.props.selectedOption : [],
showEmptyState: !this.props.selectedOption?.length && this.props.hideLocalCluster,
showError: false,
};
}
Expand Down Expand Up @@ -138,6 +140,9 @@ export class DataSourceView extends React.Component<DataSourceViewProps, DataSou
}

render() {
if (this.state.showEmptyState) {
return <NoDataSource />;
}
if (this.state.showError) {
return <DataSourceErrorMenu />;
}
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
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { NoDataSource } from './no_data_source';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { ShallowWrapper, shallow } from 'enzyme';
import React from 'react';
import { NoDataSource } from './no_data_source';

describe('NoDataSource', () => {
let component: ShallowWrapper<any, Readonly<{}>, React.Component<{}, {}, any>>;
it('should render normally', () => {
component = shallow(<NoDataSource />);
expect(component).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';

import { EuiButtonEmpty } from '@elastic/eui';

export const NoDataSource = () => {
const label = ' No data sources';
return (
<EuiButtonEmpty
className="euiHeaderLink"
data-test-subj="dataSourceViewContextMenuHeaderLink"
iconType="alert"
iconSide="left"
size="s"
color="primary"
>
{label}
</EuiButtonEmpty>
);
};

0 comments on commit e4b5b5a

Please sign in to comment.