77 lines
2.0 KiB
TypeScript
77 lines
2.0 KiB
TypeScript
import { Component, Suspense, type ErrorInfo, type ReactNode } from "react";
|
|
import Button from "./Button";
|
|
import DismissibleAlert from "./DismissibleAlert";
|
|
import LoadingIndicator from "./LoadingIndicator";
|
|
|
|
type ModuleLoadBoundaryProps = {
|
|
children: ReactNode;
|
|
resetKey: string;
|
|
loading?: boolean;
|
|
};
|
|
|
|
type ModuleLoadBoundaryState = {
|
|
error: Error | null;
|
|
};
|
|
|
|
export default class ModuleLoadBoundary extends Component<
|
|
ModuleLoadBoundaryProps,
|
|
ModuleLoadBoundaryState
|
|
> {
|
|
state: ModuleLoadBoundaryState = { error: null };
|
|
|
|
static getDerivedStateFromError(error: Error): ModuleLoadBoundaryState {
|
|
return { error };
|
|
}
|
|
|
|
componentDidCatch(error: Error, info: ErrorInfo) {
|
|
console.error("GovOPlaN module route failed to load", error, info);
|
|
}
|
|
|
|
componentDidUpdate(previousProps: ModuleLoadBoundaryProps) {
|
|
if (
|
|
previousProps.resetKey !== this.props.resetKey &&
|
|
this.state.error
|
|
) {
|
|
this.setState({ error: null });
|
|
}
|
|
}
|
|
|
|
render() {
|
|
if (this.props.loading) {
|
|
return <ModuleLoadProgress />;
|
|
}
|
|
if (this.state.error) {
|
|
return (
|
|
<div className="content-pad module-load-error">
|
|
<DismissibleAlert tone="danger" compact resetKey={`${this.props.resetKey}:${this.state.error.message}`}>
|
|
<p>i18n:govoplan-core.the_resource_could_not_be_loaded.0d1b6cbf</p>
|
|
<Button type="button" onClick={() => window.location.reload()}>
|
|
i18n:govoplan-core.reload.cce71553
|
|
</Button>
|
|
</DismissibleAlert>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Suspense
|
|
fallback={<ModuleLoadProgress />}
|
|
>
|
|
{this.props.children}
|
|
</Suspense>
|
|
);
|
|
}
|
|
}
|
|
|
|
function ModuleLoadProgress() {
|
|
return (
|
|
<div className="content-pad module-load-progress">
|
|
<LoadingIndicator
|
|
label="i18n:govoplan-core.loading_module.50161f3c"
|
|
size="md"
|
|
/>
|
|
<span>i18n:govoplan-core.loading_module.50161f3c</span>
|
|
</div>
|
|
);
|
|
}
|