Skip to content

Commit

Permalink
[Multiple Datasource] Add empty icon and fix empty state handling (#6597
Browse files Browse the repository at this point in the history
)

* add empty icon and fix empty state handling

Signed-off-by: Lu Yu <[email protected]>

* add back missing import

Signed-off-by: Lu Yu <[email protected]>

---------

Signed-off-by: Lu Yu <[email protected]>
Co-authored-by: ZilongX <[email protected]>
  • Loading branch information
BionIT and ZilongX authored Apr 23, 2024
1 parent 104ee42 commit 543bbea
Show file tree
Hide file tree
Showing 16 changed files with 365 additions and 194 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import React from 'react';

export const EmptyIcon = () => {
return (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.88072 12.9734C7.24621 12.991 7.62038 13 8 13C9.79424 13 11.4669 12.7979 12.675 12.4527C12.7139 12.4416 12.7534 12.4304 12.7931 12.419C13.2562 12.2873 13.7656 12.1424 14.0018 12H14V10.0307C12.7751 10.6115 10.5463 11 8 11C7.61431 11 7.23591 10.9911 6.86718 10.9739C6.77052 10.6087 6.62348 10.2639 6.43395 9.94748C6.93903 9.98197 7.46409 10 8 10C9.79424 10 11.4669 9.79786 12.675 9.45269C12.7139 9.44158 12.7534 9.43036 12.7931 9.41904C13.2562 9.28731 13.7656 9.1424 14.0018 9H14V7.03074C12.7751 7.61155 10.5463 8 8 8C5.45367 8 3.2249 7.61155 2 7.03074V8.12602C1.64523 8.21733 1.30951 8.35609 1 8.53513V3C1 1.89543 4.13401 1 8 1C11.866 1 15 1.89543 15 3V12C15 13.1046 11.866 14 8 14C7.48207 14 6.97727 13.9839 6.49139 13.9534C6.66201 13.6491 6.79401 13.3202 6.88072 12.9734ZM2 6V4.03074C3.2249 4.61155 5.45367 5 8 5C10.5463 5 12.7751 4.61155 14 4.03074V6H14.0018C13.7656 6.1424 13.2562 6.28731 12.7931 6.41904C12.7534 6.43036 12.7139 6.44158 12.675 6.45269C11.4669 6.79786 9.79424 7 8 7C6.20576 7 4.53308 6.79786 3.32497 6.45269C3.28838 6.44223 3.25131 6.43168 3.21394 6.42104C2.74926 6.28878 2.23754 6.14312 2.00012 6H2ZM8 2C9.79424 2 11.4669 2.20214 12.675 2.54731C13.1666 2.68777 13.5549 2.84537 13.8114 3C13.5549 3.15463 13.1666 3.31223 12.675 3.45269C11.4669 3.79786 9.79424 4 8 4C6.20576 4 4.53308 3.79786 3.32497 3.45269C2.83335 3.31223 2.44512 3.15463 2.1886 3C2.44512 2.84537 2.83335 2.68777 3.32497 2.54731C4.53308 2.20214 6.20576 2 8 2Z"
fill="#006BB4"
/>
<mask id="path-2-inside-1_1269_81032" fill="white">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6 12C6 13.6569 4.65685 15 3 15C1.34315 15 0 13.6569 0 12C0 10.3431 1.34315 9 3 9C4.65685 9 6 10.3431 6 12Z"
/>
</mask>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6 12C6 13.6569 4.65685 15 3 15C1.34315 15 0 13.6569 0 12C0 10.3431 1.34315 9 3 9C4.65685 9 6 10.3431 6 12Z"
fill="#FAFBFD"
/>
<path
d="M3 16C5.20914 16 7 14.2091 7 12H5C5 13.1046 4.10457 14 3 14V16ZM-1 12C-1 14.2091 0.790861 16 3 16V14C1.89543 14 1 13.1046 1 12H-1ZM3 8C0.790861 8 -1 9.79086 -1 12H1C1 10.8954 1.89543 10 3 10V8ZM7 12C7 9.79086 5.20914 8 3 8V10C4.10457 10 5 10.8954 5 12H7Z"
fill="#6A717D"
mask="url(#path-2-inside-1_1269_81032)"
/>
</svg>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
* SPDX-License-Identifier: Apache-2.0
*/
export { ErrorIcon } from './error_icon';
export { EmptyIcon } from './empty_icon';
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ import {
SavedObjectsClientContract,
ToastsStart,
} from 'opensearch-dashboards/public';
import { getApplication, getDataSourcesWithFields, handleDataSourceFetchError } from '../utils';
import {
getApplication,
getDataSourcesWithFields,
handleDataSourceFetchError,
handleNoAvailableDataSourceError,
} from '../utils';
import { SavedObject } from '../../../../../core/public';
import { DataSourceAttributes } from '../../types';
import { NoDataSource } from '../no_data_source';
Expand Down Expand Up @@ -114,6 +119,15 @@ export class DataSourceAggregatedView extends React.Component<
allDataSourcesIdToTitleMap.set('', 'Local cluster');
}

if (allDataSourcesIdToTitleMap.size === 0) {
handleNoAvailableDataSourceError(
this.onEmptyState.bind(this),
this.props.notifications,
this.props.application
);
return;
}

this.setState({
...this.state,
allDataSourcesIdToTitleMap,
Expand All @@ -126,13 +140,17 @@ export class DataSourceAggregatedView extends React.Component<
});
}

onEmptyState() {
this.setState({ showEmptyState: true });
}

onError() {
this.setState({ showError: true });
}

render() {
if (this.state.showEmptyState) {
return <NoDataSource />;
return <NoDataSource application={this.props.application} />;
}
if (this.state.showError) {
return <DataSourceErrorMenu application={this.props.application} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import {
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 {
getDataSourcesWithFields,
handleDataSourceFetchError,
handleNoAvailableDataSourceError,
} from '../utils';
import { DataSourceBaseState } from '../data_source_menu/types';
import { DataSourceErrorMenu } from '../data_source_error_menu';

Expand Down Expand Up @@ -85,11 +89,20 @@ export class DataSourceMultiSelectable extends React.Component<

if (!this._isMounted) return;

if (selectedOptions.length === 0) {
handleNoAvailableDataSourceError(
this.onEmptyState.bind(this),
this.props.notifications,
this.props.application,
this.props.onSelectedDataSources
);
return;
}

this.setState({
...this.state,
selectedOptions,
defaultDataSource,
showEmptyState: (fetchedDataSources?.length === 0 && this.props.hideLocalCluster) || false,
});

this.props.onSelectedDataSources(selectedOptions);
Expand All @@ -102,6 +115,10 @@ export class DataSourceMultiSelectable extends React.Component<
}
}

onEmptyState() {
this.setState({ showEmptyState: true });
}

onError() {
this.setState({ showError: true });
}
Expand All @@ -116,7 +133,7 @@ export class DataSourceMultiSelectable extends React.Component<

render() {
if (this.state.showEmptyState) {
return <NoDataSource />;
return <NoDataSource application={this.props.application} />;
}
if (this.state.showError) {
return <DataSourceErrorMenu application={this.props.application} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ describe('DataSourceSelectable', () => {
});
it('should render no data source when no data source filtered out and hide local cluster', async () => {
const onSelectedDataSource = jest.fn();
const container = render(
render(
<DataSourceSelectable
savedObjectsClient={client}
notifications={toasts}
Expand All @@ -418,7 +418,7 @@ describe('DataSourceSelectable', () => {
/>
);
await nextTick();
const button = await container.findByTestId('dataSourceEmptyStateHeaderButton');
expect(button).toHaveTextContent('No data sources');
expect(toasts.add).toBeCalled();
expect(onSelectedDataSource).toBeCalledWith([]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
getDefaultDataSource,
getFilteredDataSources,
handleDataSourceFetchError,
handleNoAvailableDataSourceError,
} from '../utils';
import { LocalCluster } from '../data_source_selector/data_source_selector';
import { SavedObject } from '../../../../../core/public';
Expand Down Expand Up @@ -185,6 +186,16 @@ export class DataSourceSelectable extends React.Component<
dataSourceOptions.unshift(LocalCluster);
}

if (dataSourceOptions.length === 0) {
handleNoAvailableDataSourceError(
this.onEmptyState.bind(this),
this.props.notifications,
this.props.application,
this.props.onSelectedDataSources
);
return;
}

const defaultDataSource = this.props.uiSettings?.get('defaultDataSource', null) ?? null;

if (this.props.selectedOption?.length) {
Expand All @@ -203,6 +214,10 @@ export class DataSourceSelectable extends React.Component<
}
}

onEmptyState() {
this.setState({ showEmptyState: true });
}

onError() {
this.setState({ showError: true });
}
Expand All @@ -227,12 +242,7 @@ export class DataSourceSelectable extends React.Component<

render() {
if (this.state.showEmptyState) {
return (
<NoDataSource
totalDataSourceCount={this.state.dataSourceOptions.length}
application={this.props.application}
/>
);
return <NoDataSource application={this.props.application} />;
}

if (this.state.showError) {
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 @@ -39,17 +39,18 @@ describe('DataSourceView', () => {
expect(toasts.addWarning).toBeCalledTimes(0);
});
it('When selected option is local cluster and hide local Cluster is true, should return error', () => {
const onSelectedDataSources = jest.fn();
component = shallow(
<DataSourceView
fullWidth={false}
selectedOption={[{ id: '' }]}
hideLocalCluster={true}
notifications={toasts}
onSelectedDataSources={jest.fn()}
onSelectedDataSources={onSelectedDataSources}
/>
);
expect(component).toMatchSnapshot();
expect(toasts.addWarning).toBeCalledTimes(1);
expect(onSelectedDataSources).toBeCalledWith([]);
});
it('Should return error when provided datasource has been filtered out', async () => {
component = shallow(
Expand All @@ -65,7 +66,6 @@ describe('DataSourceView', () => {
/>
);
expect(component).toMatchSnapshot();
expect(toasts.addWarning).toBeCalledTimes(1);
});
it('Should render successfully when provided datasource has not been filtered out', async () => {
spyOn(utils, 'getDataSourceById').and.returnValue([{ id: 'test1', label: 'test1' }]);
Expand Down Expand Up @@ -139,7 +139,7 @@ describe('DataSourceView', () => {

it('should render no data source when no data source filtered out and hide local cluster', async () => {
const onSelectedDataSource = jest.fn();
const container = render(
render(
<DataSourceView
savedObjectsClient={client}
notifications={toasts}
Expand All @@ -150,7 +150,6 @@ describe('DataSourceView', () => {
dataSourceFilter={(ds) => false}
/>
);
const button = await container.findByTestId('dataSourceEmptyStateHeaderButton');
expect(button).toHaveTextContent('No data sources');
expect(onSelectedDataSource).toBeCalledWith([]);
});
});
Loading

0 comments on commit 543bbea

Please sign in to comment.