kibana/examples/error_boundary/public/plugin.tsx
Luke Elmers b6287708f6
Adds AGPL 3.0 license (#192025)
Updates files outside of x-pack to be triple-licensed under Elastic
License 2.0, AGPL 3.0, or SSPL 1.0.
2024-09-06 19:02:41 -06:00

117 lines
3.9 KiB
TypeScript
Executable file

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { EuiButton, EuiProvider } from '@elastic/eui';
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
import { KibanaErrorBoundary, KibanaErrorBoundaryProvider } from '@kbn/shared-ux-error-boundary';
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
interface SetupDeps {
developerExamples: DeveloperExamplesSetup;
}
const useErrors = () => {
return useState(false);
};
export const FatalComponent = () => {
const [hasError, setHasError] = useErrors();
if (hasError) {
const fatalError = new Error('Example of unknown error type');
throw fatalError;
}
return (
<EuiButton
onClick={() => {
setHasError(true);
}}
data-test-subj="fatalErrorBtn"
>
Click for fatal error
</EuiButton>
);
};
export const RecoverableComponent = () => {
const [hasError, setHasError] = useErrors();
if (hasError) {
// FIXME: use network interception to disable responses
// for chunk requests and attempt to lazy-load a component
// https://github.com/elastic/kibana/issues/170777
const upgradeError = new Error('ChunkLoadError');
upgradeError.name = 'ChunkLoadError';
throw upgradeError;
}
return (
<EuiButton
onClick={() => {
setHasError(true);
}}
data-test-subj="recoverableErrorBtn"
>
Click for recoverable error
</EuiButton>
);
};
export class ErrorBoundaryExamplePlugin implements Plugin<void, void, SetupDeps> {
public setup(core: CoreSetup, deps: SetupDeps) {
// Register an application into the side navigation menu
core.application.register({
id: 'errorBoundaryExample',
title: 'Error Boundary Example',
async mount({ element }: AppMountParameters) {
// Using the "EuiProvider" here rather than KibanaRenderContextProvider, because KibanaRenderContextProvider
// wraps KibanaErrorBoundaryProvider and KibanaErrorBoundary and we want to test it directly, not a wrapper.
ReactDOM.render(
<EuiProvider>
<KibanaErrorBoundaryProvider analytics={core.analytics}>
<KibanaErrorBoundary>
<KibanaPageTemplate>
<KibanaPageTemplate.Header
pageTitle="KibanaErrorBoundary example"
data-test-subj="errorBoundaryExampleHeader"
/>
<KibanaPageTemplate.Section grow={false}>
<FatalComponent />
</KibanaPageTemplate.Section>
<KibanaPageTemplate.Section>
<RecoverableComponent />
</KibanaPageTemplate.Section>
</KibanaPageTemplate>
</KibanaErrorBoundary>
</KibanaErrorBoundaryProvider>
</EuiProvider>,
element
);
return () => ReactDOM.unmountComponentAtNode(element);
},
});
// This section is only needed to get this example plugin to show up in our Developer Examples.
deps.developerExamples.register({
appId: 'errorBoundaryExample',
title: 'Error Boundary Example Application',
description: `Build a plugin that registers an application that simply says "Error Boundary Example"`,
});
}
public start(_core: CoreStart) {
return {};
}
public stop() {}
}