mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[ML] Enhances toast notifications to improve error reporting (#173362)
## Summary Several enhancements to the error toast notifications in the ML plugin to improve error reporting. The bulk of the changes are to add 'See the full error' buttons to the toasts allowing the user to see further details on the error that has occurred. Also makes minor edits to some of the error messages to improve clarity. Also closes #171839 by changes to `x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js` so that the the 'Jobs started successfully' toast is only shown if 1 or more jobs have been started successfully. Fixes #171839 ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
9023497cb5
commit
2c51f63dd1
26 changed files with 186 additions and 124 deletions
|
@ -118,14 +118,15 @@ export const FullTimeRangeSelector: FC<FullTimeRangeSelectorProps> = (props) =>
|
|||
callback(fullTimeRange);
|
||||
}
|
||||
} catch (e) {
|
||||
toasts.addDanger(
|
||||
i18n.translate(
|
||||
toasts.addError(e, {
|
||||
title: i18n.translate(
|
||||
'xpack.ml.datePicker.fullTimeRangeSelector.errorSettingTimeRangeNotification',
|
||||
{
|
||||
defaultMessage: 'An error occurred setting the time range.',
|
||||
defaultMessage:
|
||||
'An error occurred setting the time range. Please set the desired start and end times.',
|
||||
}
|
||||
)
|
||||
);
|
||||
),
|
||||
});
|
||||
}
|
||||
}, [
|
||||
timefilter,
|
||||
|
|
|
@ -20,7 +20,11 @@ import { getTimeFieldRange } from './time_field_range';
|
|||
const mockParamsFactory = () => ({
|
||||
timefilter: { setTime: jest.fn() } as unknown as TimefilterContract,
|
||||
dataView: { getIndexPattern: jest.fn(), getRuntimeMappings: jest.fn() } as unknown as DataView,
|
||||
toasts: { addWarning: jest.fn(), addDanger: jest.fn() } as unknown as ToastsStart,
|
||||
toasts: {
|
||||
addWarning: jest.fn(),
|
||||
addDanger: jest.fn(),
|
||||
addError: jest.fn(),
|
||||
} as unknown as ToastsStart,
|
||||
});
|
||||
|
||||
describe('setFullTimeRange', () => {
|
||||
|
|
|
@ -81,14 +81,15 @@ export async function setFullTimeRange(
|
|||
});
|
||||
}
|
||||
} catch (error) {
|
||||
toasts.addDanger(
|
||||
i18n.translate(
|
||||
toasts.addError(error, {
|
||||
title: i18n.translate(
|
||||
'xpack.ml.datePicker.fullTimeRangeSelector.errorSettingTimeRangeNotification',
|
||||
{
|
||||
defaultMessage: 'An error occurred setting the time range.',
|
||||
defaultMessage:
|
||||
'An error occurred setting the time range. Please set the desired start and end times.',
|
||||
}
|
||||
)
|
||||
);
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import { JobSelectorControl } from './job_selector';
|
|||
import { useMlKibana } from '../application/contexts/kibana';
|
||||
import { jobsApiProvider } from '../application/services/ml_api_service/jobs';
|
||||
import { HttpService } from '../application/services/http_service';
|
||||
import { useToastNotificationService } from '../application/services/toast_notification_service';
|
||||
import { SeverityControl } from '../application/components/severity_control';
|
||||
import { ResultTypeSelector } from './result_type_selector';
|
||||
import { alertingApiProvider } from '../application/services/ml_api_service/alerting';
|
||||
|
@ -44,11 +45,11 @@ const MlAnomalyAlertTrigger: FC<MlAnomalyAlertTriggerProps> = ({
|
|||
}) => {
|
||||
const {
|
||||
services: { http },
|
||||
notifications: { toasts },
|
||||
} = useMlKibana();
|
||||
const mlHttpService = useMemo(() => new HttpService(http), [http]);
|
||||
const adJobsApiService = useMemo(() => jobsApiProvider(mlHttpService), [mlHttpService]);
|
||||
const alertingApiService = useMemo(() => alertingApiProvider(mlHttpService), [mlHttpService]);
|
||||
const { displayErrorToast } = useToastNotificationService();
|
||||
|
||||
const [jobConfigs, setJobConfigs] = useState<CombinedJobWithStats[]>([]);
|
||||
|
||||
|
@ -74,13 +75,13 @@ const MlAnomalyAlertTrigger: FC<MlAnomalyAlertTriggerProps> = ({
|
|||
const jobs = await adJobsApiService.jobs(jobsAndGroupIds);
|
||||
setJobConfigs(jobs);
|
||||
} catch (e) {
|
||||
toasts.danger({
|
||||
title: i18n.translate('xpack.ml.anomalyDetectionAlert.errorFetchingJobs', {
|
||||
displayErrorToast(
|
||||
e,
|
||||
i18n.translate('xpack.ml.anomalyDetectionAlert.errorFetchingJobs', {
|
||||
defaultMessage: 'Unable to fetch jobs configuration',
|
||||
}),
|
||||
body: e.message,
|
||||
toastLifeTimeMs: 5000,
|
||||
});
|
||||
5000
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [jobsAndGroupIds]);
|
||||
|
|
|
@ -13,6 +13,14 @@ import { CustomUrlList, CustomUrlListProps } from './list';
|
|||
|
||||
jest.mock('../../../contexts/kibana');
|
||||
|
||||
jest.mock('../../../services/toast_notification_service', () => ({
|
||||
useToastNotificationService: () => {
|
||||
return {
|
||||
displayErrorToast: jest.fn(),
|
||||
};
|
||||
},
|
||||
}));
|
||||
|
||||
function prepareTest(setCustomUrlsFn: jest.Mock) {
|
||||
const customUrls = [
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
import { parseUrlState } from '@kbn/ml-url-state';
|
||||
|
||||
import { useMlKibana } from '../../../contexts/kibana';
|
||||
import { useToastNotificationService } from '../../../services/toast_notification_service';
|
||||
import { isValidLabel, openCustomUrlWindow } from '../../../util/custom_url_utils';
|
||||
import { getTestUrl } from './utils';
|
||||
|
||||
|
@ -68,10 +69,10 @@ export const CustomUrlList: FC<CustomUrlListProps> = ({
|
|||
const {
|
||||
services: {
|
||||
http,
|
||||
notifications,
|
||||
data: { dataViews },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const { displayErrorToast } = useToastNotificationService();
|
||||
const [expandedUrlIndex, setExpandedUrlIndex] = useState<number | null>(null);
|
||||
|
||||
const onLabelChange = (e: ChangeEvent<HTMLInputElement>, index: number) => {
|
||||
|
@ -161,11 +162,8 @@ export const CustomUrlList: FC<CustomUrlListProps> = ({
|
|||
const testUrl = await getTestUrl(job, customUrl, timefieldName, undefined, isPartialDFAJob);
|
||||
openCustomUrlWindow(testUrl, customUrl, http.basePath.get());
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error obtaining URL for test:', error);
|
||||
|
||||
const { toasts } = notifications;
|
||||
toasts.addDanger(
|
||||
displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.customUrlEditorList.obtainingUrlToTestConfigurationErrorMessage',
|
||||
{
|
||||
|
|
|
@ -29,6 +29,10 @@ import type { DataViewListItem } from '@kbn/data-views-plugin/common';
|
|||
import type { MlUrlConfig } from '@kbn/ml-anomaly-utils';
|
||||
import { isDataFrameAnalyticsConfigs } from '@kbn/ml-data-frame-analytics-utils';
|
||||
import type { DashboardService, DashboardItems } from '../../services/dashboard_service';
|
||||
import {
|
||||
ToastNotificationService,
|
||||
toastNotificationServiceProvider,
|
||||
} from '../../services/toast_notification_service';
|
||||
import type { MlKibanaReactContextValue } from '../../contexts/kibana';
|
||||
import { CustomUrlEditor, CustomUrlList } from './custom_url_editor';
|
||||
import {
|
||||
|
@ -58,6 +62,8 @@ interface CustomUrlsProps extends CustomUrlsWrapperProps {
|
|||
}
|
||||
|
||||
class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
|
||||
private toastNotificationService: ToastNotificationService | undefined;
|
||||
|
||||
constructor(props: CustomUrlsProps) {
|
||||
super(props);
|
||||
|
||||
|
@ -79,16 +85,17 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
|
|||
|
||||
componentDidMount() {
|
||||
const { toasts } = this.props.kibana.services.notifications;
|
||||
this.toastNotificationService = toastNotificationServiceProvider(toasts);
|
||||
const { dashboardService } = this.props;
|
||||
|
||||
dashboardService
|
||||
.fetchDashboards()
|
||||
.then((dashboards) => {
|
||||
this.setState({ dashboards });
|
||||
})
|
||||
.catch((resp) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error loading list of dashboards:', resp);
|
||||
toasts.addDanger(
|
||||
.catch((error) => {
|
||||
this.toastNotificationService!.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.jobsList.editJobFlyout.customUrls.loadSavedDashboardsErrorNotificationMessage',
|
||||
{
|
||||
|
@ -102,10 +109,9 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
|
|||
.then((dataViewListItems) => {
|
||||
this.setState({ dataViewListItems });
|
||||
})
|
||||
.catch((resp) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error loading list of dashboards:', resp);
|
||||
toasts.addDanger(
|
||||
.catch((error) => {
|
||||
this.toastNotificationService!.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.jobsList.editJobFlyout.customUrls.loadDataViewsErrorNotificationMessage',
|
||||
{
|
||||
|
@ -148,11 +154,9 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
|
|||
this.props.setCustomUrls(customUrls);
|
||||
this.setState({ editorOpen: false });
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error building custom URL from settings:', error);
|
||||
const { toasts } = this.props.kibana.services.notifications;
|
||||
toasts.addDanger(
|
||||
.catch((error) => {
|
||||
this.toastNotificationService!.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.jobsList.editJobFlyout.customUrls.addNewUrlErrorNotificationMessage',
|
||||
{
|
||||
|
@ -167,7 +171,6 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
|
|||
onTestButtonClick = () => {
|
||||
const {
|
||||
http: { basePath },
|
||||
notifications: { toasts },
|
||||
data: { dataViews },
|
||||
dashboard,
|
||||
} = this.props.kibana.services;
|
||||
|
@ -194,10 +197,9 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
|
|||
.then((testUrl) => {
|
||||
openCustomUrlWindow(testUrl, customUrl, basePath.get());
|
||||
})
|
||||
.catch((resp) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error obtaining URL for test:', resp);
|
||||
toasts.addWarning(
|
||||
.catch((error) => {
|
||||
this.toastNotificationService!.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.jobsList.editJobFlyout.customUrls.getTestUrlErrorNotificationMessage',
|
||||
{
|
||||
|
@ -210,10 +212,9 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
|
|||
}
|
||||
);
|
||||
})
|
||||
.catch((resp) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error building custom URL from settings:', resp);
|
||||
toasts.addWarning(
|
||||
.catch((error) => {
|
||||
this.toastNotificationService!.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.jobsList.editJobFlyout.customUrls.buildUrlErrorNotificationMessage',
|
||||
{
|
||||
|
|
|
@ -32,7 +32,6 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { withKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { extractErrorMessage } from '@kbn/ml-error-utils';
|
||||
import {
|
||||
ML_DETECTOR_RULE_ACTION,
|
||||
ML_DETECTOR_RULE_CONDITIONS_NOT_SUPPORTED_FUNCTIONS,
|
||||
|
@ -55,6 +54,7 @@ import {
|
|||
|
||||
import { getPartitioningFieldNames } from '../../../../common/util/job_utils';
|
||||
import { mlJobService } from '../../services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../services/toast_notification_service';
|
||||
import { ml } from '../../services/ml_api_service';
|
||||
|
||||
class RuleEditorFlyoutUI extends Component {
|
||||
|
@ -83,6 +83,9 @@ class RuleEditorFlyoutUI extends Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.toastNotificationService = toastNotificationServiceProvider(
|
||||
this.props.kibana.services.notifications.toasts
|
||||
);
|
||||
if (typeof this.props.setShowFunction === 'function') {
|
||||
this.props.setShowFunction(this.showFlyout);
|
||||
}
|
||||
|
@ -105,8 +108,7 @@ class RuleEditorFlyoutUI extends Component {
|
|||
i18n.translate(
|
||||
'xpack.ml.ruleEditor.ruleEditorFlyout.unableToConfigureRulesNotificationMesssage',
|
||||
{
|
||||
defaultMessage:
|
||||
'Unable to configure job rules as an error occurred obtaining details for job ID {jobId}',
|
||||
defaultMessage: 'Unable to configure job rules as no job found with ID {jobId}',
|
||||
values: { jobId: anomaly.jobId },
|
||||
}
|
||||
)
|
||||
|
@ -153,10 +155,9 @@ class RuleEditorFlyoutUI extends Component {
|
|||
filterListIds,
|
||||
});
|
||||
})
|
||||
.catch((resp) => {
|
||||
console.log('Error loading list of filters:', resp);
|
||||
const { toasts } = this.props.kibana.services.notifications;
|
||||
toasts.addDanger(
|
||||
.catch((error) => {
|
||||
this.toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.ruleEditor.ruleEditorFlyout.errorWithLoadingFilterListsNotificationMesssage',
|
||||
{
|
||||
|
@ -374,8 +375,8 @@ class RuleEditorFlyoutUI extends Component {
|
|||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
toasts.addDanger(
|
||||
this.toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.ruleEditor.ruleEditorFlyout.errorWithSavingChangesToJobDetectorRulesNotificationMessage',
|
||||
{
|
||||
|
@ -426,18 +427,16 @@ class RuleEditorFlyoutUI extends Component {
|
|||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
let errorMessage = i18n.translate(
|
||||
'xpack.ml.ruleEditor.ruleEditorFlyout.errorWithDeletingRuleFromJobDetectorNotificationMessage',
|
||||
{
|
||||
defaultMessage: 'Error deleting rule from {jobId} detector',
|
||||
values: { jobId },
|
||||
}
|
||||
this.toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.ruleEditor.ruleEditorFlyout.errorWithDeletingRuleFromJobDetectorNotificationMessage',
|
||||
{
|
||||
defaultMessage: 'Error deleting rule from {jobId} detector',
|
||||
values: { jobId },
|
||||
}
|
||||
)
|
||||
);
|
||||
if (error.error) {
|
||||
errorMessage += ` : ${extractErrorMessage(error.error)}`;
|
||||
}
|
||||
toasts.addDanger(errorMessage);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -467,8 +466,8 @@ class RuleEditorFlyoutUI extends Component {
|
|||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(`Error adding ${item} to filter ${filterId}:`, error);
|
||||
toasts.addDanger(
|
||||
this.toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.ruleEditor.ruleEditorFlyout.errorWithAddingItemToFilterListNotificationMessage',
|
||||
{
|
||||
|
|
|
@ -93,6 +93,11 @@ function prepareTest() {
|
|||
},
|
||||
},
|
||||
},
|
||||
notifications: {
|
||||
toasts: {
|
||||
addDanger: () => {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -185,17 +185,19 @@ function showResults(resp, action) {
|
|||
}
|
||||
|
||||
const toastNotifications = getToastNotifications();
|
||||
toastNotifications.addSuccess(
|
||||
i18n.translate('xpack.ml.jobsList.actionExecuteSuccessfullyNotificationMessage', {
|
||||
defaultMessage:
|
||||
'{successesJobsCount, plural, one{{successJob}} other{# jobs}} {actionTextPT} successfully',
|
||||
values: {
|
||||
successesJobsCount: successes.length,
|
||||
successJob: successes[0],
|
||||
actionTextPT,
|
||||
},
|
||||
})
|
||||
);
|
||||
if (successes.length > 0) {
|
||||
toastNotifications.addSuccess(
|
||||
i18n.translate('xpack.ml.jobsList.actionExecuteSuccessfullyNotificationMessage', {
|
||||
defaultMessage:
|
||||
'{successesJobsCount, plural, one{{successJob}} other{# jobs}} {actionTextPT} successfully',
|
||||
values: {
|
||||
successesJobsCount: successes.length,
|
||||
successJob: successes[0],
|
||||
actionTextPT,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (failures.length > 0) {
|
||||
failures.forEach((f) => {
|
||||
|
|
|
@ -123,7 +123,11 @@ export const useModelMemoryEstimator = (
|
|||
title: i18n.translate('xpack.ml.newJob.wizard.estimateModelMemoryError', {
|
||||
defaultMessage: 'Model memory limit could not be calculated',
|
||||
}),
|
||||
text: extractErrorMessage(error),
|
||||
text: i18n.translate('xpack.ml.newJob.wizard.estimateModelMemoryErrorText', {
|
||||
defaultMessage:
|
||||
'{errorText}. You can proceed with creating the job, but check for warning messages once the job is running that the configured limit has not been exceeded.',
|
||||
values: { errorText: extractErrorMessage(error) },
|
||||
}),
|
||||
});
|
||||
})
|
||||
);
|
||||
|
|
|
@ -113,7 +113,8 @@ export const TimeRangeStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep })
|
|||
const { toasts } = services.notifications;
|
||||
toasts.addDanger(
|
||||
i18n.translate('xpack.ml.newJob.wizard.timeRangeStep.fullTimeRangeError', {
|
||||
defaultMessage: 'An error occurred obtaining the time range for the index',
|
||||
defaultMessage:
|
||||
'An error occurred obtaining the time range for the index. Please set the desired start and end times.',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -234,21 +234,22 @@ export const Page: FC<PageProps> = ({ moduleId, existingGroupIds }) => {
|
|||
);
|
||||
} catch (e) {
|
||||
setSaveState(SAVE_STATE.FAILED);
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error setting up module', e);
|
||||
const { toasts } = notifications;
|
||||
toasts.addDanger({
|
||||
toasts.addError(e, {
|
||||
title: i18n.translate('xpack.ml.newJob.recognize.moduleSetupFailedWarningTitle', {
|
||||
defaultMessage: 'Error setting up module {moduleId}',
|
||||
values: { moduleId },
|
||||
}),
|
||||
text: i18n.translate('xpack.ml.newJob.recognize.moduleSetupFailedWarningDescription', {
|
||||
defaultMessage:
|
||||
'An error occurred trying to create the {count, plural, one {job} other {jobs}} in the module.',
|
||||
values: {
|
||||
count: jobs.length,
|
||||
},
|
||||
}),
|
||||
toastMessage: i18n.translate(
|
||||
'xpack.ml.newJob.recognize.moduleSetupFailedWarningDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'An error occurred trying to create the {count, plural, one {job} other {jobs}} in the module.',
|
||||
values: {
|
||||
count: jobs.length,
|
||||
},
|
||||
}
|
||||
),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -126,7 +126,7 @@ export const JobMemoryTreeMap: FC<Props> = ({ node, type, height }) => {
|
|||
displayErrorToast(
|
||||
error,
|
||||
i18n.translate('xpack.ml.memoryUsage.treeMap.fetchFailedErrorMessage', {
|
||||
defaultMessage: 'Models memory usage fetch failed',
|
||||
defaultMessage: 'Error loading model memory usage data',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ export const NodesList: FC<NodesListProps> = ({ compactView = false }) => {
|
|||
displayErrorToast(
|
||||
e,
|
||||
i18n.translate('xpack.ml.trainedModels.nodesList.nodesFetchError', {
|
||||
defaultMessage: 'Nodes fetch failed',
|
||||
defaultMessage: 'Error loading overview on machine learning nodes',
|
||||
})
|
||||
);
|
||||
setIsLoading(false);
|
||||
|
|
|
@ -305,7 +305,7 @@ export const ModelsList: FC<Props> = ({
|
|||
displayErrorToast(
|
||||
error,
|
||||
i18n.translate('xpack.ml.trainedModels.modelsList.fetchFailedErrorMessage', {
|
||||
defaultMessage: 'Models fetch failed',
|
||||
defaultMessage: 'Error loading trained models',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ export const ModelsList: FC<Props> = ({
|
|||
displayErrorToast(
|
||||
error,
|
||||
i18n.translate('xpack.ml.trainedModels.modelsList.fetchModelStatsErrorMessage', {
|
||||
defaultMessage: 'Fetch model stats failed',
|
||||
defaultMessage: 'Error loading trained models statistics',
|
||||
})
|
||||
);
|
||||
return false;
|
||||
|
|
|
@ -136,7 +136,7 @@ export const NotificationsList: FC = () => {
|
|||
displayErrorToast(
|
||||
error,
|
||||
i18n.translate('xpack.ml.notifications.fetchFailedError', {
|
||||
defaultMessage: 'Fetch notifications failed',
|
||||
defaultMessage: 'Error loading list of notifications',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -105,18 +105,16 @@ const CheckViewOrCreateWrapper: FC<PageProps> = ({ location }) => {
|
|||
}
|
||||
})
|
||||
.catch(async (err: Error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Error checking whether jobs in module ${moduleId} exists`, err);
|
||||
toasts.addWarning({
|
||||
toasts.addError(err, {
|
||||
title: i18n.translate('xpack.ml.newJob.recognize.moduleCheckJobsExistWarningTitle', {
|
||||
defaultMessage: 'Error checking module {moduleId}',
|
||||
values: { moduleId },
|
||||
}),
|
||||
text: i18n.translate(
|
||||
toastMessage: i18n.translate(
|
||||
'xpack.ml.newJob.recognize.moduleCheckJobsExistWarningDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'An error occurred trying to check whether the jobs in the module have been created.',
|
||||
'An error occurred checking whether the jobs in the module have been created. Search the list for matching jobs or create new jobs.',
|
||||
}
|
||||
),
|
||||
});
|
||||
|
|
|
@ -22,8 +22,8 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import { AnomalyDetectionSettingsContext } from './anomaly_detection_settings_context';
|
||||
import { useNotifications } from '../contexts/kibana';
|
||||
import { ml } from '../services/ml_api_service';
|
||||
import { useToastNotificationService } from '../services/toast_notification_service';
|
||||
import { ML_PAGES } from '../../../common/constants/locator';
|
||||
import { useCreateAndNavigateToMlLink } from '../contexts/kibana/use_create_url';
|
||||
|
||||
|
@ -35,7 +35,7 @@ export const AnomalyDetectionSettings: FC = () => {
|
|||
AnomalyDetectionSettingsContext
|
||||
);
|
||||
|
||||
const { toasts } = useNotifications();
|
||||
const { displayErrorToast } = useToastNotificationService();
|
||||
const redirectToCalendarList = useCreateAndNavigateToMlLink(ML_PAGES.CALENDARS_MANAGE);
|
||||
const redirectToNewCalendarPage = useCreateAndNavigateToMlLink(ML_PAGES.CALENDARS_NEW);
|
||||
const redirectToFilterLists = useCreateAndNavigateToMlLink(ML_PAGES.FILTER_LISTS_MANAGE);
|
||||
|
@ -53,7 +53,8 @@ export const AnomalyDetectionSettings: FC = () => {
|
|||
const calendars = await ml.calendars();
|
||||
setCalendarsCount(calendars.length);
|
||||
} catch (e) {
|
||||
toasts.addDanger(
|
||||
displayErrorToast(
|
||||
e,
|
||||
i18n.translate('xpack.ml.settings.anomalyDetection.loadingCalendarsCountErrorMessage', {
|
||||
defaultMessage: 'An error occurred obtaining the count of calendars',
|
||||
})
|
||||
|
@ -66,7 +67,8 @@ export const AnomalyDetectionSettings: FC = () => {
|
|||
const filterLists = await ml.filters.filtersStats();
|
||||
setFilterListsCount(filterLists.length);
|
||||
} catch (e) {
|
||||
toasts.addDanger(
|
||||
displayErrorToast(
|
||||
e,
|
||||
i18n.translate('xpack.ml.settings.anomalyDetection.loadingFilterListCountErrorMessage', {
|
||||
defaultMessage: 'An error occurred obtaining the count of filter lists',
|
||||
})
|
||||
|
|
|
@ -20,6 +20,7 @@ import { ml } from '../../../services/ml_api_service';
|
|||
import { withKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { GLOBAL_CALENDAR } from '../../../../../common/constants/calendars';
|
||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||
import { toastNotificationServiceProvider } from '../../../services/toast_notification_service';
|
||||
import { getDocLinks } from '../../../util/dependency_cache';
|
||||
import { HelpMenu } from '../../../components/help_menu';
|
||||
|
||||
|
@ -54,6 +55,9 @@ class NewCalendarUI extends Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.toastNotificationService = toastNotificationServiceProvider(
|
||||
this.props.kibana.services.notifications.toasts
|
||||
);
|
||||
this.formSetup();
|
||||
}
|
||||
|
||||
|
@ -118,10 +122,9 @@ class NewCalendarUI extends Component {
|
|||
isGlobalCalendar,
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
this.setState({ loading: false });
|
||||
const { toasts } = this.props.kibana.services.notifications;
|
||||
toasts.addDanger(
|
||||
this.toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate('xpack.ml.calendarsEdit.errorWithLoadingCalendarFromDataErrorMessage', {
|
||||
defaultMessage: 'An error occurred loading calendar form data. Try refreshing the page.',
|
||||
})
|
||||
|
@ -160,10 +163,9 @@ class NewCalendarUI extends Component {
|
|||
await ml.addCalendar(calendar);
|
||||
await this.returnToCalendarsManagementPage();
|
||||
} catch (error) {
|
||||
console.log('Error saving calendar', error);
|
||||
this.setState({ saving: false });
|
||||
const { toasts } = this.props.kibana.services.notifications;
|
||||
toasts.addDanger(
|
||||
this.toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate('xpack.ml.calendarsEdit.errorWithCreatingCalendarErrorMessage', {
|
||||
defaultMessage: 'An error occurred creating calendar {calendarId}',
|
||||
values: { calendarId: calendar.calendarId },
|
||||
|
@ -181,10 +183,9 @@ class NewCalendarUI extends Component {
|
|||
await ml.updateCalendar(calendar);
|
||||
await this.returnToCalendarsManagementPage();
|
||||
} catch (error) {
|
||||
console.log('Error saving calendar', error);
|
||||
this.setState({ saving: false });
|
||||
const { toasts } = this.props.kibana.services.notifications;
|
||||
toasts.addDanger(
|
||||
this.toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate('xpack.ml.calendarsEdit.errorWithUpdatingCalendarErrorMessage', {
|
||||
defaultMessage:
|
||||
'An error occurred saving calendar {calendarId}. Try refreshing the page.',
|
||||
|
|
|
@ -117,6 +117,11 @@ const props = {
|
|||
},
|
||||
},
|
||||
},
|
||||
notifications: {
|
||||
toasts: {
|
||||
addDanger: () => {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ import { EuiConfirmModal, EUI_MODAL_CONFIRM_BUTTON } from '@elastic/eui';
|
|||
import { CalendarsListHeader } from './header';
|
||||
import { CalendarsListTable } from './table';
|
||||
import { ml } from '../../../services/ml_api_service';
|
||||
import { toastNotificationServiceProvider } from '../../../services/toast_notification_service';
|
||||
import { mlNodesAvailable } from '../../../ml_nodes_check/check_ml_nodes';
|
||||
import { deleteCalendars } from './delete_calendars';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -58,6 +59,13 @@ export class CalendarsListUI extends Component {
|
|||
defaultMessage: 'An error occurred loading the list of calendars.',
|
||||
})
|
||||
);
|
||||
const toastNotificationService = toastNotificationServiceProvider(toasts);
|
||||
toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate('xpack.ml.calendarsList.errorWithLoadingListOfCalendarsErrorMessage', {
|
||||
defaultMessage: 'An error occurred loading the list of calendars.',
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import { EditFilterListToolbar } from './toolbar';
|
|||
import { ItemsGrid } from '../../../components/items_grid';
|
||||
import { isValidFilterListId, saveFilterList } from './utils';
|
||||
import { ml } from '../../../services/ml_api_service';
|
||||
import { toastNotificationServiceProvider } from '../../../services/toast_notification_service';
|
||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||
import { getDocLinks } from '../../../util/dependency_cache';
|
||||
import { HelpMenu } from '../../../components/help_menu';
|
||||
|
@ -93,6 +94,9 @@ export class EditFilterListUI extends Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.toastNotificationService = toastNotificationServiceProvider(
|
||||
this.props.kibana.services.notifications.toasts
|
||||
);
|
||||
const filterId = this.props.filterId;
|
||||
if (filterId !== undefined) {
|
||||
this.loadFilterList(filterId);
|
||||
|
@ -117,10 +121,9 @@ export class EditFilterListUI extends Component {
|
|||
.then((filter) => {
|
||||
this.setLoadedFilterState(filter);
|
||||
})
|
||||
.catch((resp) => {
|
||||
console.log(`Error loading filter ${filterId}:`, resp);
|
||||
const { toasts } = this.props.kibana.services.notifications;
|
||||
toasts.addDanger(
|
||||
.catch((error) => {
|
||||
this.toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.settings.filterLists.editFilterList.loadingDetailsOfFilterErrorMessage',
|
||||
{
|
||||
|
@ -287,10 +290,9 @@ export class EditFilterListUI extends Component {
|
|||
this.setLoadedFilterState(savedFilter);
|
||||
this.returnToFiltersList();
|
||||
})
|
||||
.catch((resp) => {
|
||||
console.log(`Error saving filter ${filterId}:`, resp);
|
||||
const { toasts } = this.props.kibana.services.notifications;
|
||||
toasts.addDanger(
|
||||
.catch((error) => {
|
||||
this.toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate('xpack.ml.settings.filterLists.editFilterList.savingFilterErrorMessage', {
|
||||
defaultMessage: 'An error occurred saving filter {filterId}',
|
||||
values: {
|
||||
|
|
|
@ -59,6 +59,15 @@ import { EditFilterList } from './edit_filter_list';
|
|||
const props = {
|
||||
canCreateFilter: true,
|
||||
canDeleteFilter: true,
|
||||
kibana: {
|
||||
services: {
|
||||
notifications: {
|
||||
toasts: {
|
||||
addWarning: () => {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function prepareEditTest() {
|
||||
|
|
|
@ -19,6 +19,7 @@ import { withKibana } from '@kbn/kibana-react-plugin/public';
|
|||
import { FilterListsHeader } from './header';
|
||||
import { FilterListsTable } from './table';
|
||||
import { ml } from '../../../services/ml_api_service';
|
||||
import { toastNotificationServiceProvider } from '../../../services/toast_notification_service';
|
||||
|
||||
import { getDocLinks } from '../../../util/dependency_cache';
|
||||
import { HelpMenu } from '../../../components/help_menu';
|
||||
|
@ -69,8 +70,8 @@ export class FilterListsUI extends Component {
|
|||
.then((filterLists) => {
|
||||
this.setFilterLists(filterLists);
|
||||
})
|
||||
.catch((resp) => {
|
||||
console.log('Error loading list of filters:', resp);
|
||||
.catch((error) => {
|
||||
console.log('Error loading list of filters:', error);
|
||||
const { toasts } = this.props.kibana.services.notifications;
|
||||
toasts.addDanger(
|
||||
i18n.translate(
|
||||
|
@ -80,6 +81,16 @@ export class FilterListsUI extends Component {
|
|||
}
|
||||
)
|
||||
);
|
||||
const toastNotificationService = toastNotificationServiceProvider(toasts);
|
||||
toastNotificationService.displayErrorToast(
|
||||
error,
|
||||
i18n.translate(
|
||||
'xpack.ml.settings.filterLists.filterLists.loadingFilterListsErrorMessage',
|
||||
{
|
||||
defaultMessage: 'An error occurred loading the filter lists',
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ jest.mock('../components/help_menu', () => ({
|
|||
jest.mock('../contexts/kibana', () => ({
|
||||
useNotifications: () => {
|
||||
return {
|
||||
toasts: { addDanger: jest.fn() },
|
||||
toasts: { addDanger: jest.fn(), addError: jest.fn() },
|
||||
};
|
||||
},
|
||||
useMlKibana: () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue