Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Multiple Datasource] Add new error database icon to handle error state for data source component #6570

Merged
merged 4 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how's it look in dark mode?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is dark mode
Screenshot 2024-04-22 at 9 46 43 AM

return (

Check warning on line 8 in src/plugins/data_source_management/public/components/custom_database_icon/error_icon.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/data_source_management/public/components/custom_database_icon/error_icon.tsx#L8

Added line #L8 was not covered by tests
<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 @@
} from '@elastic/eui';
import { i18n } from '@osd/i18n';
import {
ApplicationStart,
IUiSettingsClient,
SavedObjectsClientContract,
ToastsStart,
Expand All @@ -38,6 +39,7 @@
dataSourceFilter?: (dataSource: SavedObject<DataSourceAttributes>) => boolean;
displayAllCompatibleDataSources: boolean;
uiSettings?: IUiSettingsClient;
application?: ApplicationStart;
}

interface DataSourceAggregatedViewState extends DataSourceBaseState {
Expand Down Expand Up @@ -133,7 +135,7 @@
return <NoDataSource />;
}
if (this.state.showError) {
return <DataSourceErrorMenu />;
return <DataSourceErrorMenu application={this.props.application} />;

Check warning on line 138 in src/plugins/data_source_management/public/components/data_source_aggregated_view/data_source_aggregated_view.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/data_source_management/public/components/data_source_aggregated_view/data_source_aggregated_view.tsx#L138

Added line #L138 was not covered by tests
}
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()}

Check warning on line 35 in src/plugins/data_source_management/public/components/data_source_error_menu/data_source_error_menu.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/data_source_management/public/components/data_source_error_menu/data_source_error_menu.tsx#L35

Added line #L35 was not covered by tests
>
{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 />}

Check warning on line 50 in src/plugins/data_source_management/public/components/data_source_error_menu/data_source_error_menu.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/data_source_management/public/components/data_source_error_menu/data_source_error_menu.tsx#L50

Added line #L50 was not covered by tests
size="s"
onClick={() => setShowPopover(!showPopover)}

Check warning on line 52 in src/plugins/data_source_management/public/components/data_source_error_menu/data_source_error_menu.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/data_source_management/public/components/data_source_error_menu/data_source_error_menu.tsx#L52

Added line #L52 was not covered by tests
/>
);

export const DataSourceErrorMenu = () => {
return (
<>
<EuiIcon type={'crossInCircleFilled'} color={'danger'} />
<EuiText color={'danger'}>Error</EuiText>
<EuiPopover
id={'dataSourceErrorPopover'}
button={iconButton}
isOpen={showPopover}
closePopover={() => setShowPopover(false)}

Check warning on line 62 in src/plugins/data_source_management/public/components/data_source_error_menu/data_source_error_menu.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/data_source_management/public/components/data_source_error_menu/data_source_error_menu.tsx#L62

Added line #L62 was not covered by tests
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()}>

Check warning on line 14 in src/plugins/data_source_management/public/components/toast_button/reload_button.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/data_source_management/public/components/toast_button/reload_button.tsx#L14

Added line #L14 was not covered by tests
{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()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps we can show the error in more detail similar to how the Discover page shows the error response if clicked in the toast.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This current implementation based on requirement from UX. Since this is more of network call failure, user needs to reload the page in order to trigger another call.

color: 'danger',
});
};

interface DataSourceOptionGroupLabel {
Expand Down
Loading