Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/components/error-display.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import React from "react";6import * as misc from "@cocalc/util/misc";7import { Icon } from "./index";8import { Alert, Button } from "antd";910// use "style" to customize11const ELEMENT_STYLE: React.CSSProperties = {12overflowY: "auto",13} as const;1415// use "body_style" prop to customize16const BODY_STYLE: React.CSSProperties = {17marginRight: "10px",18whiteSpace: "pre-wrap",19} as const;2021const CLOSE_X: React.CSSProperties = {22float: "right",23position: "absolute",24top: "5px",25right: "10px",26zIndex: 1,27} as const;2829interface Props {30error?: string | object;31error_component?: JSX.Element | JSX.Element[];32title?: string;33style?: React.CSSProperties;34body_style?: React.CSSProperties;35componentStyle?: React.CSSProperties;36bsStyle?: string;37onClose?: () => void;38banner?: boolean;39}4041export const ErrorDisplay: React.FC<Props> = React.memo((props: Props) => {42const {43error,44error_component,45title,46body_style,47componentStyle,48style,49bsStyle,50onClose,51banner = false,52} = props;5354function render_title() {55return <h4>{title}</h4>;56}5758function render_error() {59if (error != undefined) {60if (typeof error === "string") {61return error;62} else {63return misc.to_json(error);64}65} else {66return error_component;67}68}6970function type(): string {71if (72// only types that antd has...73bsStyle != null &&74["success", "info", "warning", "error"].includes(bsStyle)75) {76return bsStyle;77} else {78return "error";79}80}8182function msgdesc() {83if (title) {84return [85render_title(),86<div style={{ ...BODY_STYLE, ...body_style }}>{render_error()}</div>,87];88} else {89return [90<div style={{ ...BODY_STYLE, ...body_style }}>{render_error()}</div>,91undefined,92];93}94}9596// must be rendered as the first child element!97function render_close() {98if (onClose == null || banner === false) return;99return (100<Button101style={CLOSE_X}102shape="circle"103size="small"104type="text"105onClick={onClose}106>107<Icon style={style} name="times" />108</Button>109);110}111112function render_alert() {113const [message, description] = msgdesc();114// tweak the case where it's not a banner115const extra = banner ? undefined : { closable: true, onClose };116return (117<Alert118banner={banner}119showIcon={false}120style={{ ...ELEMENT_STYLE, ...style }}121type={type() as any}122message={message}123description={description}124{...extra}125/>126);127}128129const divprops = banner ? { className: "cc-error-display" } : undefined;130131return (132<div {...divprops} style={componentStyle}>133{render_close()}134{render_alert()}135</div>136);137});138139140