Skip to content

Commit

Permalink
[Multiple Datasource] Add new error database icon to handle error sta…
Browse files Browse the repository at this point in the history
…te for data source component (opensearch-project#6570)

* add error icon and add popover

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

* fix tests

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

* fix typo

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

---------

Signed-off-by: Lu Yu <[email protected]>
  • Loading branch information
BionIT authored Apr 22, 2024
1 parent 8db9688 commit b117fd3
Show file tree
Hide file tree
Showing 16 changed files with 197 additions and 33 deletions.
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';

export const ErrorIcon = () => {
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="currentColor"
/>
<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="#BD271E"
/>
</svg>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
export { ErrorIcon } from './error_icon';
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@osd/i18n';
import {
ApplicationStart,
IUiSettingsClient,
SavedObjectsClientContract,
ToastsStart,
Expand All @@ -38,6 +39,7 @@ interface DataSourceAggregatedViewProps {
dataSourceFilter?: (dataSource: SavedObject<DataSourceAttributes>) => boolean;
displayAllCompatibleDataSources: boolean;
uiSettings?: IUiSettingsClient;
application?: ApplicationStart;
}

interface DataSourceAggregatedViewState extends DataSourceBaseState {
Expand Down Expand Up @@ -133,7 +135,7 @@ export class DataSourceAggregatedView extends React.Component<
return <NoDataSource />;
}
if (this.state.showError) {
return <DataSourceErrorMenu />;
return <DataSourceErrorMenu application={this.props.application} />;
}
const button = (
<EuiButtonEmpty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,86 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiIcon, EuiText } from '@elastic/eui';
import React from 'react';
import React, { useState } from 'react';
import { i18n } from '@osd/i18n';
import { ApplicationStart } from 'opensearch-dashboards/public';
import {
EuiButton,
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiPopover,
EuiPopoverFooter,
EuiText,
} from '@elastic/eui';
import { ErrorIcon } from '../custom_database_icon';
import { DataSourceDropDownHeader } from '../drop_down_header';

interface DataSourceErrorMenuProps {
application?: ApplicationStart;
}

export const DataSourceErrorMenu = ({ application }: DataSourceErrorMenuProps) => {
const [showPopover, setShowPopover] = useState<boolean>(false);

const refreshButton = (
<EuiButton
data-test-subj="dataSourceErrorRefreshButton"
fill={false}
iconType={'refresh'}
size="s"
onClick={() => window.location.reload()}
>
{i18n.translate('dataSourcesManagement.dataSourceErrorMenu.refreshPage', {
defaultMessage: 'Refresh the page',
})}
</EuiButton>
);

const iconButton = (
<EuiButtonIcon
className="euiHeaderLink"
data-test-subj="dataSourceErrorMenuHeaderLink"
aria-label={i18n.translate('dataSourceError.dataSourceErrorMenuHeaderLink', {
defaultMessage: 'dataSourceErrorMenuHeaderLink',
})}
iconType={() => <ErrorIcon />}
size="s"
onClick={() => setShowPopover(!showPopover)}
/>
);

export const DataSourceErrorMenu = () => {
return (
<>
<EuiIcon type={'crossInCircleFilled'} color={'danger'} />
<EuiText color={'danger'}>Error</EuiText>
<EuiPopover
id={'dataSourceErrorPopover'}
button={iconButton}
isOpen={showPopover}
closePopover={() => setShowPopover(false)}
panelPaddingSize="none"
anchorPosition="downLeft"
data-test-subj={'dataSourceErrorPopover'}
>
<DataSourceDropDownHeader totalDataSourceCount={0} application={application} />
<EuiPanel
hasBorder={false}
hasShadow={false}
className="dataSourceEmptyStatePanel"
data-test-subj="datasourceTableEmptyState"
>
<EuiText size="s" textAlign="center">
{i18n.translate('dataSourcesManagement.dataSourceErrorMenu.text', {
defaultMessage: 'Failed to fetch data sources',
})}
</EuiText>
</EuiPanel>
<EuiPopoverFooter>
<EuiFlexGroup justifyContent="spaceAround">
<EuiFlexItem>{refreshButton}</EuiFlexItem>
</EuiFlexGroup>
</EuiPopoverFooter>
</EuiPopover>
</>
);
};

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 @@ -85,7 +85,7 @@ describe('create data source menu', () => {
perPage: 10000,
type: 'data-source',
});
expect(notifications.toasts.addWarning).toBeCalledTimes(2);
expect(notifications.toasts.add).toBeCalledTimes(2);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export function DataSourceMenu<T>(props: DataSourceMenuProps<T>): ReactElement |
notifications={notifications!.toasts}
onSelectedDataSources={onSelectedDataSources!}
uiSettings={uiSettings}
application={application}
/>
);
}
Expand Down Expand Up @@ -108,6 +109,7 @@ export function DataSourceMenu<T>(props: DataSourceMenuProps<T>): ReactElement |
dataSourceFilter={dataSourceFilter}
displayAllCompatibleDataSources={displayAllCompatibleDataSources}
uiSettings={uiSettings}
application={application}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ describe('DataSourceMultiSelectable', () => {
/>
);
await nextTick();
expect(toasts.addWarning).toBeCalledTimes(1);
expect(toasts.add).toBeCalledTimes(1);
});

it('should callback when onChange happens', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
*/

import React from 'react';
import { SavedObjectsClientContract, ToastsStart } from 'opensearch-dashboards/public';
import {
ApplicationStart,
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';
Expand All @@ -19,6 +23,7 @@ export interface DataSourceMultiSeletableProps {
hideLocalCluster: boolean;
fullWidth: boolean;
uiSettings?: IUiSettingsClient;
application?: ApplicationStart;
}

interface DataSourceMultiSeletableState extends DataSourceBaseState {
Expand Down Expand Up @@ -114,7 +119,7 @@ export class DataSourceMultiSelectable extends React.Component<
return <NoDataSource />;
}
if (this.state.showError) {
return <DataSourceErrorMenu />;
return <DataSourceErrorMenu application={this.props.application} />;
}
return (
<DataSourceFilterGroup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,11 @@ export class DataSourceSelectable extends React.Component<
/>
);
}

if (this.state.showError) {
return <DataSourceErrorMenu />;
return <DataSourceErrorMenu application={this.props.application} />;
}

const button = (
<>
<EuiButtonEmpty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ describe('DataSourceView', () => {
/>
);
expect(component).toMatchSnapshot();
expect(toasts.addWarning).toBeCalledTimes(1);
expect(toasts.add).toBeCalledTimes(1);
expect(utils.getDataSourceById).toBeCalledTimes(1);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export class DataSourceView extends React.Component<DataSourceViewProps, DataSou
);
}
if (this.state.showError) {
return <DataSourceErrorMenu />;
return <DataSourceErrorMenu application={this.props.application} />;
}
const label = this.state.selectedOption.length > 0 ? this.state.selectedOption[0].label : '';
const options =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
export { getReloadButton } from './reload_button';
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React from 'react';
import { i18n } from '@osd/i18n';

export const getReloadButton = () => {
return (
<>
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiButton size="s" onClick={() => window.location.reload()}>
{i18n.translate('dataSourceMenu.requiresPageReloadToastButtonLabel', {
defaultMessage: 'Refresh the page',
})}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('DataSourceManagement: Utils.ts', () => {
const changeStateMock = jest.fn();
handleDataSourceFetchError(changeStateMock, toasts);
expect(changeStateMock).toBeCalledWith({ showError: true });
expect(toasts.addWarning).toHaveBeenCalledWith(`Failed to fetch data source`);
expect(toasts.add).toBeCalledTimes(1);
});
});

Expand Down
14 changes: 9 additions & 5 deletions src/plugins/data_source_management/public/components/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { AuthenticationMethodRegistry } from '../auth_registry';
import { DataSourceOption } from './data_source_menu/types';
import { DataSourceGroupLabelOption } from './data_source_menu/types';
import { createGetterSetter } from '../../../opensearch_dashboards_utils/public';
import { toMountPoint } from '../../../opensearch_dashboards_react/public';
import { getReloadButton } from './toast_button';

export async function getDataSources(savedObjectsClient: SavedObjectsClientContract) {
return savedObjectsClient
Expand Down Expand Up @@ -282,11 +284,13 @@ export const handleDataSourceFetchError = (
) => {
changeState({ showError: true });
if (callback) callback([]);
notifications.addWarning(
i18n.translate('dataSource.fetchDataSourceError', {
defaultMessage: 'Failed to fetch data source',
})
);
notifications.add({
title: i18n.translate('dataSource.fetchDataSourceError', {
defaultMessage: 'Failed to fetch data sources',
}),
text: toMountPoint(getReloadButton()),
color: 'danger',
});
};

interface DataSourceOptionGroupLabel {
Expand Down

0 comments on commit b117fd3

Please sign in to comment.