mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
errorboundary fallback, errorboundary in block frame header. fix workspace error boundary
This commit is contained in:
parent
639e796296
commit
766a976718
@ -28,6 +28,7 @@ import {
|
||||
} from "@/app/store/global";
|
||||
import * as services from "@/app/store/services";
|
||||
import { WshServer } from "@/app/store/wshserver";
|
||||
import { ErrorBoundary } from "@/element/errorboundary";
|
||||
import { IconButton } from "@/element/iconbutton";
|
||||
import { MagnifyIcon } from "@/element/magnify";
|
||||
import { NodeModel } from "@/layout/index";
|
||||
@ -116,7 +117,7 @@ function computeEndIcons(
|
||||
onContextMenu: (e: React.MouseEvent<HTMLDivElement>) => void
|
||||
): JSX.Element[] {
|
||||
const endIconsElem: JSX.Element[] = [];
|
||||
const endIconButtons = util.useAtomValueSafe(viewModel.endIconButtons);
|
||||
const endIconButtons = util.useAtomValueSafe(viewModel?.endIconButtons);
|
||||
const magnified = jotai.useAtomValue(nodeModel.isMagnified);
|
||||
const numLeafs = jotai.useAtomValue(nodeModel.numLeafs);
|
||||
const magnifyDisabled = numLeafs <= 1;
|
||||
@ -155,15 +156,16 @@ const BlockFrame_Header = ({
|
||||
preview,
|
||||
connBtnRef,
|
||||
changeConnModalAtom,
|
||||
}: BlockFrameProps & { changeConnModalAtom: jotai.PrimitiveAtom<boolean> }) => {
|
||||
error,
|
||||
}: BlockFrameProps & { changeConnModalAtom: jotai.PrimitiveAtom<boolean>; error?: Error }) => {
|
||||
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", nodeModel.blockId));
|
||||
const viewName = util.useAtomValueSafe(viewModel.viewName) ?? blockViewToName(blockData?.meta?.view);
|
||||
const viewName = util.useAtomValueSafe(viewModel?.viewName) ?? blockViewToName(blockData?.meta?.view);
|
||||
const showBlockIds = jotai.useAtomValue(useSettingsKeyAtom("blockheader:showblockids"));
|
||||
const viewIconUnion = util.useAtomValueSafe(viewModel.viewIcon) ?? blockViewToIcon(blockData?.meta?.view);
|
||||
const preIconButton = util.useAtomValueSafe(viewModel.preIconButton);
|
||||
const headerTextUnion = util.useAtomValueSafe(viewModel.viewText);
|
||||
const viewIconUnion = util.useAtomValueSafe(viewModel?.viewIcon) ?? blockViewToIcon(blockData?.meta?.view);
|
||||
const preIconButton = util.useAtomValueSafe(viewModel?.preIconButton);
|
||||
const headerTextUnion = util.useAtomValueSafe(viewModel?.viewText);
|
||||
const magnified = jotai.useAtomValue(nodeModel.isMagnified);
|
||||
const manageConnection = util.useAtomValueSafe(viewModel.manageConnection);
|
||||
const manageConnection = util.useAtomValueSafe(viewModel?.manageConnection);
|
||||
const dragHandleRef = preview ? null : nodeModel.dragHandleRef;
|
||||
|
||||
const onContextMenu = React.useCallback(
|
||||
@ -193,6 +195,19 @@ const BlockFrame_Header = ({
|
||||
headerTextElems.push(...renderHeaderElements(headerTextUnion, preview));
|
||||
}
|
||||
headerTextElems.unshift(<ControllerStatusIcon key="connstatus" blockId={nodeModel.blockId} />);
|
||||
if (error != null) {
|
||||
const copyHeaderErr = () => {
|
||||
navigator.clipboard.writeText(error.message + "\n" + error.stack);
|
||||
};
|
||||
headerTextElems.push(
|
||||
<div className="iconbutton disabled" key="controller-status" onClick={copyHeaderErr}>
|
||||
<i
|
||||
className="fa-sharp fa-solid fa-triangle-exclamation"
|
||||
title={"Error Rendering View Header: " + error.message}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="block-frame-default-header" ref={dragHandleRef} onContextMenu={onContextMenu}>
|
||||
@ -377,9 +392,9 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
const { nodeModel, viewModel, blockModel, preview, numBlocksInTab, children } = props;
|
||||
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", nodeModel.blockId));
|
||||
const isFocused = jotai.useAtomValue(nodeModel.isFocused);
|
||||
const viewIconUnion = util.useAtomValueSafe(viewModel.viewIcon) ?? blockViewToIcon(blockData?.meta?.view);
|
||||
const customBg = util.useAtomValueSafe(viewModel.blockBg);
|
||||
const manageConnection = util.useAtomValueSafe(viewModel.manageConnection);
|
||||
const viewIconUnion = util.useAtomValueSafe(viewModel?.viewIcon) ?? blockViewToIcon(blockData?.meta?.view);
|
||||
const customBg = util.useAtomValueSafe(viewModel?.blockBg);
|
||||
const manageConnection = util.useAtomValueSafe(viewModel?.manageConnection);
|
||||
const changeConnModalAtom = useBlockAtom(nodeModel.blockId, "changeConn", () => {
|
||||
return jotai.atom(false);
|
||||
}) as jotai.PrimitiveAtom<boolean>;
|
||||
@ -429,6 +444,10 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
}
|
||||
}
|
||||
const previewElem = <div className="block-frame-preview">{viewIconElem}</div>;
|
||||
const headerElem = (
|
||||
<BlockFrame_Header {...props} connBtnRef={connBtnRef} changeConnModalAtom={changeConnModalAtom} />
|
||||
);
|
||||
const headerElemNoView = React.cloneElement(headerElem, { viewModel: null });
|
||||
return (
|
||||
<div
|
||||
className={clsx("block", "block-frame-default", "block-" + nodeModel.blockId, {
|
||||
@ -442,7 +461,7 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
ref={blockModel?.blockRef}
|
||||
>
|
||||
<BlockMask nodeModel={nodeModel} />
|
||||
{preview ? null : (
|
||||
{preview || viewModel == null ? null : (
|
||||
<ConnStatusOverlay
|
||||
nodeModel={nodeModel}
|
||||
viewModel={viewModel}
|
||||
@ -450,10 +469,10 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
/>
|
||||
)}
|
||||
<div className="block-frame-default-inner" style={innerStyle}>
|
||||
<BlockFrame_Header {...props} connBtnRef={connBtnRef} changeConnModalAtom={changeConnModalAtom} />
|
||||
<ErrorBoundary fallback={headerElemNoView}>{headerElem}</ErrorBoundary>
|
||||
{preview ? previewElem : children}
|
||||
</div>
|
||||
{preview || !connModalOpen ? null : (
|
||||
{preview || viewModel == null || !connModalOpen ? null : (
|
||||
<ChangeConnectionBlockModal
|
||||
blockId={nodeModel.blockId}
|
||||
nodeModel={nodeModel}
|
||||
|
@ -3,7 +3,10 @@
|
||||
|
||||
import React, { ReactNode } from "react";
|
||||
|
||||
export class ErrorBoundary extends React.Component<{ children: ReactNode }, { error: Error }> {
|
||||
export class ErrorBoundary extends React.Component<
|
||||
{ children: ReactNode; fallback?: React.ReactElement & { error?: Error } },
|
||||
{ error: Error }
|
||||
> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { error: null };
|
||||
@ -14,8 +17,12 @@ export class ErrorBoundary extends React.Component<{ children: ReactNode }, { er
|
||||
}
|
||||
|
||||
render() {
|
||||
const { fallback } = this.props;
|
||||
const { error } = this.state;
|
||||
if (error) {
|
||||
if (fallback != null) {
|
||||
return React.cloneElement(fallback as any, { error });
|
||||
}
|
||||
const errorMsg = `Error: ${error?.message}\n\n${error?.stack}`;
|
||||
return <pre className="error-boundary">{errorMsg}</pre>;
|
||||
} else {
|
||||
|
@ -108,7 +108,7 @@ const WorkspaceElem = React.memo(() => {
|
||||
<div className="workspace">
|
||||
<TabBar key={ws.oid} workspace={ws} />
|
||||
<div className="workspace-tabcontent">
|
||||
<ErrorBoundary>
|
||||
<ErrorBoundary key={activeTabId}>
|
||||
{activeTabId == "" ? (
|
||||
<CenteredDiv>No Active Tab</CenteredDiv>
|
||||
) : (
|
||||
|
Loading…
Reference in New Issue
Block a user