Skip to content

Commit

Permalink
[ML] Transforms: Fix error toasts. (#48509)
Browse files Browse the repository at this point in the history
Previously, error messages were just output within the toast as raw text which could result in overflows and overall unreadable results. This update fixes it by providing a "View details" button which opens a modal with the properly formatted error message. Plain text error message up to 140 character will still be shown in the toast itself.
  • Loading branch information
walterra authored Oct 18, 2019
1 parent 713993c commit 39c8aeb
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@

export { SectionError } from './section_error';
export { SectionLoading } from './section_loading';
export { ToastNotificationText } from './toast_notification_text';
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { cleanup, render } from 'react-testing-library';
import { ToastNotificationText } from './toast_notification_text';

describe('ToastNotificationText', () => {
afterEach(cleanup);

test('should render the text as plain text', () => {
const props = {
text: 'a short text message',
};
const { container } = render(<ToastNotificationText {...props} />);
expect(container.textContent).toBe('a short text message');
});

test('should render the text within a modal', () => {
const props = {
text:
'a text message that is longer than 140 characters. a text message that is longer than 140 characters. a text message that is longer than 140 characters. ',
};
const { container } = render(<ToastNotificationText {...props} />);
expect(container.textContent).toBe('View details');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React, { FC } from 'react';

import {
EuiButtonEmpty,
EuiCodeBlock,
EuiModal,
EuiModalBody,
EuiModalFooter,
EuiModalHeader,
EuiModalHeaderTitle,
} from '@elastic/eui';

import { i18n } from '@kbn/i18n';

import { npStart } from 'ui/new_platform';

const MAX_SIMPLE_MESSAGE_LENGTH = 140;

export const ToastNotificationText: FC<{ text: any }> = ({ text }) => {
if (typeof text === 'string' && text.length <= MAX_SIMPLE_MESSAGE_LENGTH) {
return text;
}

if (
typeof text === 'object' &&
typeof text.message === 'string' &&
text.message.length <= MAX_SIMPLE_MESSAGE_LENGTH
) {
return text.message;
}

const formattedText = text.message ? text.message : JSON.stringify(text, null, 2);

const openModal = () => {
const modal = npStart.core.overlays.openModal(
<EuiModal onClose={() => modal.close()}>
<EuiModalHeader>
<EuiModalHeaderTitle>
{i18n.translate('xpack.transform.toastText.modalTitle', {
defaultMessage: 'Error details',
})}
</EuiModalHeaderTitle>
</EuiModalHeader>
<EuiModalBody>
<EuiCodeBlock language="json" fontSize="m" paddingSize="s" isCopyable>
{formattedText}
</EuiCodeBlock>
</EuiModalBody>
<EuiModalFooter>
<EuiButtonEmpty onClick={() => modal.close()}>
{i18n.translate('xpack.transform.toastText.closeModalButtonText', {
defaultMessage: 'Close',
})}
</EuiButtonEmpty>
</EuiModalFooter>
</EuiModal>
);
};

return (
<>
<EuiButtonEmpty onClick={openModal}>
{i18n.translate('xpack.transform.toastText.openModalButtonText', {
defaultMessage: 'View details',
})}
</EuiButtonEmpty>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';

import { i18n } from '@kbn/i18n';
import { toastNotifications } from 'ui/notify';

import { TransformListRow, refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../common';
import { ToastNotificationText } from '../components';

import { useApi } from './use_api';
import { TransformEndpointRequest, TransformEndpointResult } from './use_api_types';
Expand Down Expand Up @@ -46,11 +49,12 @@ export const useDeleteTransforms = () => {

refreshTransformList$.next(REFRESH_TRANSFORM_LIST_STATE.REFRESH);
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.transform.transformList.deleteTransformGenericErrorMessage', {
toastNotifications.addDanger({
title: i18n.translate('xpack.transform.transformList.deleteTransformGenericErrorMessage', {
defaultMessage: 'An error occurred calling the API endpoint to delete transforms.',
})
);
}),
text: <ToastNotificationText text={e} />,
});
}
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
EuiText,
} from '@elastic/eui';

import { ToastNotificationText } from '../../../../components';
import { useApi } from '../../../../hooks/use_api';
import { isKibanaContextInitialized, KibanaContext } from '../../../../lib/kibana';
import { RedirectToTransformManagement } from '../../../../common/navigation';
Expand Down Expand Up @@ -96,12 +97,13 @@ export const StepCreateForm: SFC<Props> = React.memo(
);
} catch (e) {
setCreated(false);
toastNotifications.addDanger(
i18n.translate('xpack.transform.stepCreateForm.createTransformErrorMessage', {
defaultMessage: 'An error occurred creating the transform {transformId}: {error}',
values: { transformId, error: JSON.stringify(e) },
})
);
toastNotifications.addDanger({
title: i18n.translate('xpack.transform.stepCreateForm.createTransformErrorMessage', {
defaultMessage: 'An error occurred creating the transform {transformId}:',
values: { transformId },
}),
text: <ToastNotificationText text={e} />,
});
return false;
}

Expand All @@ -125,12 +127,13 @@ export const StepCreateForm: SFC<Props> = React.memo(
);
} catch (e) {
setStarted(false);
toastNotifications.addDanger(
i18n.translate('xpack.transform.stepCreateForm.startTransformErrorMessage', {
defaultMessage: 'An error occurred starting the transform {transformId}: {error}',
values: { transformId, error: JSON.stringify(e) },
})
);
toastNotifications.addDanger({
title: i18n.translate('xpack.transform.stepCreateForm.startTransformErrorMessage', {
defaultMessage: 'An error occurred starting the transform {transformId}:',
values: { transformId },
}),
text: <ToastNotificationText text={e} />,
});
}
}

Expand Down Expand Up @@ -182,13 +185,14 @@ export const StepCreateForm: SFC<Props> = React.memo(
setIndexPatternId(id);
return true;
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.transform.stepCreateForm.createIndexPatternErrorMessage', {
toastNotifications.addDanger({
title: i18n.translate('xpack.transform.stepCreateForm.createIndexPatternErrorMessage', {
defaultMessage:
'An error occurred creating the Kibana index pattern {indexPatternName}: {error}',
values: { indexPatternName, error: JSON.stringify(e) },
})
);
'An error occurred creating the Kibana index pattern {indexPatternName}:',
values: { indexPatternName },
}),
text: <ToastNotificationText text={e} />,
});
return false;
}
};
Expand All @@ -214,12 +218,12 @@ export const StepCreateForm: SFC<Props> = React.memo(
}
}
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.transform.stepCreateForm.progressErrorMessage', {
defaultMessage: 'An error occurred getting the progress percentage: {error}',
values: { error: JSON.stringify(e) },
})
);
toastNotifications.addDanger({
title: i18n.translate('xpack.transform.stepCreateForm.progressErrorMessage', {
defaultMessage: 'An error occurred getting the progress percentage:',
}),
text: <ToastNotificationText text={e} />,
});
clearInterval(interval);
}
}, PROGRESS_REFRESH_INTERVAL_MS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { EuiLink, EuiSwitch, EuiFieldText, EuiForm, EuiFormRow, EuiSelect } from
import { isKibanaContextInitialized, KibanaContext } from '../../../../lib/kibana';
import { isValidIndexName } from '../../../../../../common/utils/es_utils';

import { ToastNotificationText } from '../../../../components';
import { useApi } from '../../../../hooks/use_api';

import { isTransformIdValid, TransformId, TransformPivotConfig } from '../../../../common';
Expand Down Expand Up @@ -86,35 +87,37 @@ export const StepDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChang
)
);
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.transform.stepDetailsForm.errorGettingTransformList', {
defaultMessage: 'An error occurred getting the existing transform IDs: {error}',
values: { error: JSON.stringify(e) },
})
);
toastNotifications.addDanger({
title: i18n.translate('xpack.transform.stepDetailsForm.errorGettingTransformList', {
defaultMessage: 'An error occurred getting the existing transform IDs:',
}),
text: <ToastNotificationText text={e} />,
});
}

try {
setIndexNames((await api.getIndices()).map(index => index.name));
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.transform.stepDetailsForm.errorGettingIndexNames', {
defaultMessage: 'An error occurred getting the existing index names: {error}',
values: { error: JSON.stringify(e) },
})
);
toastNotifications.addDanger({
title: i18n.translate('xpack.transform.stepDetailsForm.errorGettingIndexNames', {
defaultMessage: 'An error occurred getting the existing index names:',
}),
text: <ToastNotificationText text={e} />,
});
}

try {
setIndexPatternTitles(await kibanaContext.indexPatterns.getTitles());
} catch (e) {
toastNotifications.addDanger(
i18n.translate('xpack.transform.stepDetailsForm.errorGettingIndexPatternTitles', {
defaultMessage:
'An error occurred getting the existing index pattern titles: {error}',
values: { error: JSON.stringify(e) },
})
);
toastNotifications.addDanger({
title: i18n.translate(
'xpack.transform.stepDetailsForm.errorGettingIndexPatternTitles',
{
defaultMessage: 'An error occurred getting the existing index pattern titles:',
}
),
text: <ToastNotificationText text={e} />,
});
}
}
})();
Expand Down
7 changes: 1 addition & 6 deletions x-pack/plugins/translations/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -6975,21 +6975,16 @@
"xpack.transform.groupByLabelForm.editIntervalAriaLabel": "間隔を編集",
"xpack.transform.stepCreateForm.copyTransformConfigToClipboardButton": "クリップボードにコピー",
"xpack.transform.stepCreateForm.copyTransformConfigToClipboardDescription": "ジョブを作成する Kibana 開発コンソールのコマンドをクリップボードにコピーします。",
"xpack.transform.stepCreateForm.createIndexPatternErrorMessage": "Kibana インデックスパターン {indexPatternName} の作成中にエラーが発生しました: {error}",
"xpack.transform.stepCreateForm.createIndexPatternLabel": "インデックスパターンを作成",
"xpack.transform.stepCreateForm.createTransformErrorMessage": "データフレームジョブ {transformId} の作成中にエラーが発生しました: {error}",
"xpack.transform.stepCreateForm.createTransformSuccessMessage": "データフレームジョブ {transformId} が作成されました",
"xpack.transform.stepCreateForm.creatingIndexPatternMessage": "Kibana インデックスパターンを作成中…",
"xpack.transform.stepCreateForm.discoverCardDescription": "ディスカバリでデータフレームピボットを閲覧します。",
"xpack.transform.stepCreateForm.discoverCardTitle": "ディスカバー",
"xpack.transform.stepCreateForm.transformListCardDescription": "データフレームジョブの管理ページに戻ります。",
"xpack.transform.stepCreateForm.transformListCardTitle": "データフレームジョブ",
"xpack.transform.stepCreateForm.progressErrorMessage": "進捗パーセンテージの取得中にエラーが発生しました: {error}",
"xpack.transform.stepCreateForm.progressTitle": "進捗",
"xpack.transform.stepCreateForm.createIndexPatternSuccessMessage": "Kibana インデックスパターン {indexPatternName} が作成されました",
"xpack.transform.stepCreateForm.startTransformErrorMessage": "データフレームジョブ {transformId} の開始中にエラーが発生しました: {error}",
"xpack.transform.stepCreateForm.startTransformSuccessMessage": "データフレームジョブ {transformId} が開始しました",
"xpack.transform.stepDetailsForm.errorGettingIndexPatternTitles": "既存のインデックスパターンのタイトルの取得中にエラーが発生しました: {error}",
"xpack.transform.stepDetailsForm.indexPatternTitleError": "このタイトルのインデックスパターンが既に存在します。",
"xpack.transform.stepDetailsForm.transformIdInputAriaLabel": "固有のジョブ ID を選択してください。",
"xpack.transform.stepDetailsForm.transformIdLabel": "ジョブ ID",
Expand Down Expand Up @@ -10506,4 +10501,4 @@
"xpack.fileUpload.fileParser.errorReadingFile": "ファイルの読み込み中にエラーが発生しました",
"xpack.fileUpload.fileParser.noFileProvided": "エラー、ファイルが提供されていません"
}
}
}
7 changes: 1 addition & 6 deletions x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -7133,21 +7133,16 @@
"xpack.transform.groupByLabelForm.editIntervalAriaLabel": "编辑时间间隔",
"xpack.transform.stepCreateForm.copyTransformConfigToClipboardButton": "复制到剪贴板",
"xpack.transform.stepCreateForm.copyTransformConfigToClipboardDescription": "将用于创建作业的 Kibana 开发控制台命令复制到剪贴板。",
"xpack.transform.stepCreateForm.createIndexPatternErrorMessage": "创建 Kibana 索引模式 {indexPatternName} 时发生错误:{error}",
"xpack.transform.stepCreateForm.createIndexPatternLabel": "创建索引模式",
"xpack.transform.stepCreateForm.createTransformErrorMessage": "创建数据帧作业 {transformId} 时发生错误:{error}",
"xpack.transform.stepCreateForm.createTransformSuccessMessage": "数据帧作业 {transformId} 创建成功。",
"xpack.transform.stepCreateForm.creatingIndexPatternMessage": "正在创建 Kibana 索引模式......",
"xpack.transform.stepCreateForm.discoverCardDescription": "使用 Discover 浏览数据帧透视表。",
"xpack.transform.stepCreateForm.discoverCardTitle": "Discover",
"xpack.transform.stepCreateForm.transformListCardDescription": "返回数据帧作业管理页面。",
"xpack.transform.stepCreateForm.transformListCardTitle": "数据帧作业",
"xpack.transform.stepCreateForm.progressErrorMessage": "获取进度百分比时出错:{error}",
"xpack.transform.stepCreateForm.progressTitle": "进度",
"xpack.transform.stepCreateForm.createIndexPatternSuccessMessage": "Kibana 索引模式 {indexPatternName} 成功创建。",
"xpack.transform.stepCreateForm.startTransformErrorMessage": "启动数据帧作业 {transformId} 时发生错误:{error}",
"xpack.transform.stepCreateForm.startTransformSuccessMessage": "数据帧作业 {transformId} 启动成功。",
"xpack.transform.stepDetailsForm.errorGettingIndexPatternTitles": "获取现有索引名称时发生错误:{error}",
"xpack.transform.stepDetailsForm.indexPatternTitleError": "具有此名称的索引模式已存在。",
"xpack.transform.stepDetailsForm.transformIdInputAriaLabel": "选择唯一的作业 ID。",
"xpack.transform.stepDetailsForm.transformIdLabel": "作业 ID",
Expand Down Expand Up @@ -10663,4 +10658,4 @@
"xpack.fileUpload.fileParser.errorReadingFile": "读取文件时出错",
"xpack.fileUpload.fileParser.noFileProvided": "错误,未提供任何文件"
}
}
}

0 comments on commit 39c8aeb

Please sign in to comment.