/* * SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. * * Any modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch B.V. licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import React from 'react'; import ReactDOM from 'react-dom'; import { EuiButton, EuiCallOut, EuiCodeBlock, EuiModalBody, EuiModalFooter, EuiModalHeader, EuiModalHeaderTitle, } from '@elastic/eui'; import { EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@osd/i18n/react'; import { OverlayStart } from 'opensearch-dashboards/public'; import { I18nStart } from '../../i18n'; interface ErrorToastProps { title: string; error: Error; toastMessage: string; openModal: OverlayStart['openModal']; i18nContext: () => I18nStart['Context']; } interface RequestError extends Error { body?: { attributes?: { error: { caused_by: { type: string; reason: string } } } }; } const isRequestError = (e: Error | RequestError): e is RequestError => { if ('body' in e) { return e.body?.attributes?.error?.caused_by !== undefined; } return false; }; /** * This should instead be replaced by the overlay service once it's available. * This does not use React portals so that if the parent toast times out, this modal * does not disappear. NOTE: this should use a global modal in the overlay service * in the future. */ function showErrorDialog({ title, error, openModal, i18nContext, }: Pick) { const I18nContext = i18nContext(); let text = ''; if (isRequestError(error)) { text += `${error?.body?.attributes?.error?.caused_by.type}\n`; text += `${error?.body?.attributes?.error?.caused_by.reason}\n\n`; } if (error.stack) { text += error.stack; } const modal = openModal( mount( {title} {text && ( {text} )} modal.close()} fill> ) ); } export function ErrorToast({ title, error, toastMessage, openModal, i18nContext, }: ErrorToastProps) { return (

{toastMessage}

showErrorDialog({ title, error, openModal, i18nContext })} >
); } const mount = (component: React.ReactElement) => (container: HTMLElement) => { ReactDOM.render(component, container); return () => ReactDOM.unmountComponentAtNode(container); };