mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-02 04:02:13 +01:00
error boundary for screens (#45)
* error boundary for screens * error boundary for plugins * remove changes.diff * move load-error-text class to app.less * implement mikes suggestions * apply error boundary to workspace view * fix minor issues
This commit is contained in:
parent
49f18a3e94
commit
7e9e76f089
@ -373,6 +373,15 @@ a.a-block {
|
||||
}
|
||||
}
|
||||
|
||||
.load-error-text {
|
||||
color: @term-red;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.view-error {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
@keyframes loader-ring {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
|
@ -24,6 +24,7 @@ import { TosModal } from "./common/modals/modals";
|
||||
import { WorkspaceView } from "../app/workspace/workspaceview";
|
||||
import { MainSideBar } from "./sidebar/MainSideBar";
|
||||
import { DisconnectedModal, ClientStopModal, AlertModal, WelcomeModal } from "./common/modals/modals";
|
||||
import { ErrorBoundary } from "./common/error/errorboundary";
|
||||
import "./app.less";
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
@ -110,9 +111,11 @@ class App extends React.Component<{}, {}> {
|
||||
<div id="main" className={"platform-" + platform} onContextMenu={this.handleContextMenu}>
|
||||
<div className="main-content">
|
||||
<MainSideBar />
|
||||
<WorkspaceView />
|
||||
<HistoryView />
|
||||
<BookmarksView />
|
||||
<ErrorBoundary>
|
||||
<WorkspaceView />
|
||||
<HistoryView />
|
||||
<BookmarksView />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
<AlertModal />
|
||||
<If condition={GlobalModel.needsTos()}>
|
||||
|
65
src/app/common/error/errorboundary.tsx
Normal file
65
src/app/common/error/errorboundary.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import React, { Component, ReactNode } from "react";
|
||||
import { RendererContext } from "../../../plugins/types/types";
|
||||
import cn from "classnames";
|
||||
|
||||
interface ErrorBoundaryState {
|
||||
hasError: boolean;
|
||||
error: Error | null;
|
||||
}
|
||||
|
||||
interface ErrorBoundaryProps {
|
||||
children: ReactNode;
|
||||
plugin?: string;
|
||||
lineContext?: RendererContext;
|
||||
}
|
||||
|
||||
class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
state: ErrorBoundaryState = {
|
||||
hasError: false,
|
||||
error: null,
|
||||
};
|
||||
|
||||
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
|
||||
const { plugin, lineContext } = this.props;
|
||||
|
||||
if (plugin && lineContext) {
|
||||
console.log(`Plugin Name: ${plugin}\n`);
|
||||
console.log(`Line Context: \n`);
|
||||
console.log(`${JSON.stringify(lineContext, null, 4)}\n`);
|
||||
}
|
||||
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
resetErrorBoundary = (): void => {
|
||||
this.setState({ hasError: false, error: null });
|
||||
};
|
||||
|
||||
renderFallback() {
|
||||
const { error } = this.state;
|
||||
const { plugin } = this.props;
|
||||
|
||||
return (
|
||||
<div className={cn("load-error-text", { "view-error": !plugin })}>
|
||||
<div>{`${error?.message}`}</div>
|
||||
{plugin && <div>An error occurred in the {plugin} plugin</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { hasError } = this.state;
|
||||
|
||||
if (hasError) {
|
||||
return this.renderFallback();
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export { ErrorBoundary };
|
@ -38,6 +38,7 @@ import { isBlank } from "../../util/util";
|
||||
import { PluginModel } from "../../plugins/plugins";
|
||||
import { Prompt } from "../common/prompt/prompt";
|
||||
import * as lineutil from "./lineutil";
|
||||
import { ErrorBoundary } from "../../app/common/error/errorboundary";
|
||||
|
||||
import { ReactComponent as CheckIcon } from "../assets/icons/line/check.svg";
|
||||
import { ReactComponent as CommentIcon } from "../assets/icons/line/comment.svg";
|
||||
@ -594,7 +595,6 @@ class LineCmd extends React.Component<
|
||||
let isRunning = cmd.isRunning();
|
||||
let isExpanded = this.isCmdExpanded.get();
|
||||
let rsdiff = this.rtnStateDiff.get();
|
||||
// console.log("render", "#" + line.linenum, termHeight, usedRows, cmd.getStatus(), (this.rtnStateDiff.get() != null), (!cmd.isRunning() ? "cmd-done" : "running"));
|
||||
let mainDivCn = cn(
|
||||
"line",
|
||||
"line-cmd",
|
||||
@ -664,39 +664,41 @@ class LineCmd extends React.Component<
|
||||
</div>
|
||||
</div>
|
||||
<If condition={!this.isMinimised.get()}>
|
||||
<If condition={rendererPlugin == null && !isNoneRenderer}>
|
||||
<TerminalRenderer
|
||||
screen={screen}
|
||||
line={line}
|
||||
width={width}
|
||||
staticRender={staticRender}
|
||||
visible={visible}
|
||||
onHeightChange={this.handleHeightChange}
|
||||
collapsed={false}
|
||||
/>
|
||||
</If>
|
||||
<If condition={rendererPlugin != null && rendererPlugin.rendererType == "simple"}>
|
||||
<SimpleBlobRenderer
|
||||
rendererContainer={screen}
|
||||
lineId={line.lineid}
|
||||
plugin={rendererPlugin}
|
||||
onHeightChange={this.handleHeightChange}
|
||||
initParams={this.makeRendererModelInitializeParams()}
|
||||
scrollToBringIntoViewport={this.scrollToBringIntoViewport}
|
||||
isSelected={isSelected}
|
||||
shouldFocus={shouldCmdFocus}
|
||||
/>
|
||||
</If>
|
||||
<If condition={rendererPlugin != null && rendererPlugin.rendererType == "full"}>
|
||||
<IncrementalRenderer
|
||||
rendererContainer={screen}
|
||||
lineId={line.lineid}
|
||||
plugin={rendererPlugin}
|
||||
onHeightChange={this.handleHeightChange}
|
||||
initParams={this.makeRendererModelInitializeParams()}
|
||||
isSelected={isSelected}
|
||||
/>
|
||||
</If>
|
||||
<ErrorBoundary plugin={rendererPlugin?.name} lineContext={lineutil.getRendererContext(line)}>
|
||||
<If condition={rendererPlugin == null && !isNoneRenderer}>
|
||||
<TerminalRenderer
|
||||
screen={screen}
|
||||
line={line}
|
||||
width={width}
|
||||
staticRender={staticRender}
|
||||
visible={visible}
|
||||
onHeightChange={this.handleHeightChange}
|
||||
collapsed={false}
|
||||
/>
|
||||
</If>
|
||||
<If condition={rendererPlugin != null && rendererPlugin.rendererType == "simple"}>
|
||||
<SimpleBlobRenderer
|
||||
rendererContainer={screen}
|
||||
lineId={line.lineid}
|
||||
plugin={rendererPlugin}
|
||||
onHeightChange={this.handleHeightChange}
|
||||
initParams={this.makeRendererModelInitializeParams()}
|
||||
scrollToBringIntoViewport={this.scrollToBringIntoViewport}
|
||||
isSelected={isSelected}
|
||||
shouldFocus={shouldCmdFocus}
|
||||
/>
|
||||
</If>
|
||||
<If condition={rendererPlugin != null && rendererPlugin.rendererType == "full"}>
|
||||
<IncrementalRenderer
|
||||
rendererContainer={screen}
|
||||
lineId={line.lineid}
|
||||
plugin={rendererPlugin}
|
||||
onHeightChange={this.handleHeightChange}
|
||||
initParams={this.makeRendererModelInitializeParams()}
|
||||
isSelected={isSelected}
|
||||
/>
|
||||
</If>
|
||||
</ErrorBoundary>
|
||||
<If condition={cmd.getRtnState()}>
|
||||
<div
|
||||
key="rtnstate"
|
||||
|
@ -11,6 +11,7 @@ import { GlobalModel } from "../../model/model";
|
||||
import { CmdInput } from "./cmdinput/cmdinput";
|
||||
import { ScreenView } from "./screen/screenview";
|
||||
import { ScreenTabs } from "./screen/tabs";
|
||||
import { ErrorBoundary } from "../../app/common/error/errorboundary";
|
||||
import "./workspace.less";
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
@ -31,12 +32,15 @@ class WorkspaceView extends React.Component<{}, {}> {
|
||||
cmdInputHeight = 110;
|
||||
}
|
||||
let isHidden = GlobalModel.activeMainView.get() != "session";
|
||||
|
||||
return (
|
||||
<div className={cn("session-view", { "is-hidden": isHidden })} data-sessionid={session.sessionId}>
|
||||
<ScreenTabs session={session} />
|
||||
<ScreenView screen={activeScreen} />
|
||||
<div style={{ height: cmdInputHeight }}></div>
|
||||
<CmdInput />
|
||||
<ErrorBoundary>
|
||||
<ScreenView screen={activeScreen} />
|
||||
<div style={{ height: cmdInputHeight }}></div>
|
||||
<CmdInput />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user