mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
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.
This commit is contained in:
parent
8da32357d2
commit
bc375cacab
8 changed files with 164 additions and 57 deletions
|
@ -6,3 +6,4 @@
|
|||
|
||||
export { SectionError } from './section_error';
|
||||
export { SectionLoading } from './section_loading';
|
||||
export { ToastNotificationText } from './toast_notification_text';
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -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';
|
||||
|
@ -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} />,
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
|
@ -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';
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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} />,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
|
|
|
@ -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';
|
||||
|
@ -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} />,
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -6985,21 +6985,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",
|
||||
|
|
|
@ -7143,21 +7143,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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue