This is an automated email from the ASF dual-hosted git repository.
marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
The following commit(s) were added to refs/heads/main by this push:
new b08ef5f5 ErrorBoundaryWrapper for designer
b08ef5f5 is described below
commit b08ef5f504b6737fc09652247876a40e630f0540
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Wed Dec 4 18:31:43 2024 -0500
ErrorBoundaryWrapper for designer
---
.../src/designer/ErrorBoundaryWrapper.tsx | 21 ++++++++++
karavan-designer/src/designer/KaravanDesigner.tsx | 45 +++++++++++++++++-----
2 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/karavan-designer/src/designer/ErrorBoundaryWrapper.tsx
b/karavan-designer/src/designer/ErrorBoundaryWrapper.tsx
new file mode 100644
index 00000000..a8ef292d
--- /dev/null
+++ b/karavan-designer/src/designer/ErrorBoundaryWrapper.tsx
@@ -0,0 +1,21 @@
+import React, {ReactNode} from "react";
+
+export interface ErrorBoundaryState {
+ hasError: boolean;
+ error: Error | null;
+}
+
+export class ErrorBoundaryWrapper extends React.Component<{
+ children: ReactNode;
+ onError: (error: Error) => void;
+}> {
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
+ // Handle error (logging, etc.)
+ console.error("Error caught in ErrorBoundary:", error, errorInfo);
+ this.props.onError(error);
+ }
+
+ render() {
+ return this.props.children;
+ }
+}
\ No newline at end of file
diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx
b/karavan-designer/src/designer/KaravanDesigner.tsx
index 511a2038..c4fa3c32 100644
--- a/karavan-designer/src/designer/KaravanDesigner.tsx
+++ b/karavan-designer/src/designer/KaravanDesigner.tsx
@@ -43,6 +43,7 @@ import BellIcon from
'@patternfly/react-icons/dist/esm/icons/bell-icon';
import {KameletDesigner} from "./kamelet/KameletDesigner";
import {BeanFactoryDefinition} from "karavan-core/lib/model/CamelDefinition";
import {VariableUtil} from "karavan-core/lib/api/VariableUtil";
+import {ErrorBoundaryState, ErrorBoundaryWrapper} from
"./ErrorBoundaryWrapper";
interface Props {
onSave: (filename: string, yaml: string, propertyOnly: boolean) => void
@@ -65,7 +66,7 @@ export function KaravanDesigner(props: Props) {
const [tab, setTab] = useState<string>('routes');
const [setDark, setSelectedStep, reset, badge, message,
setPropertyPlaceholders, setBeans] =
useDesignerStore((s) =>
- [s.setDark, s.setSelectedStep, s.reset, s.notificationBadge,
s.notificationMessage, s.setPropertyPlaceholders, s.setBeans], shallow)
+ [s.setDark, s.setSelectedStep, s.reset, s.notificationBadge,
s.notificationMessage, s.setPropertyPlaceholders, s.setBeans], shallow)
const [integration, setIntegration, resetFiles, setVariables] =
useIntegrationStore((s) =>
[s.integration, s.setIntegration, s.resetFiles, s.setVariables],
shallow)
@@ -73,6 +74,7 @@ export function KaravanDesigner(props: Props) {
const sub = EventBus.onIntegrationUpdate()?.subscribe((update:
IntegrationUpdate) =>
save(update.integration, update.propertyOnly));
try {
+ resetErrorBoundary();
InfrastructureAPI.setOnSaveCustomCode(props.onSaveCustomCode);
InfrastructureAPI.setOnGetCustomCode(props.onGetCustomCode);
InfrastructureAPI.setOnSave(props.onSave);
@@ -104,6 +106,8 @@ export function KaravanDesigner(props: Props) {
sub?.unsubscribe();
setSelectedStep(undefined);
reset();
+ resetErrorBoundary();
+ setIntegration(Integration.createNew("demo"), false);
};
}, []);
@@ -141,7 +145,7 @@ export function KaravanDesigner(props: Props) {
const counts = CamelUi.getFlowCounts(integration);
const count = counts.has(icon) && counts.get(icon) ? counts.get(icon)
: undefined;
const showCount = count && count > 0;
- const color= showBadge && badge ? "red" : "initial";
+ const color = showBadge && badge ? "red" : "initial";
return (
<div className="top-menu-item" style={{color: color}}>
<TabTitleIcon>{getDesignerIcon(icon)}</TabTitleIcon>
@@ -149,9 +153,9 @@ export function KaravanDesigner(props: Props) {
{showCount && <Badge isRead
className="count">{counts.get(icon)}</Badge>}
{showBadge && badge &&
<Button variant="link"
- icon={<BellIcon color="red"/>}
- style={{visibility: (badge ? 'visible' : 'hidden'),
padding: '0', margin: '0'}}
- onClick={event => EventBus.sendAlert(message[0],
message[1], 'danger')}/>
+ icon={<BellIcon color="red"/>}
+ style={{visibility: (badge ? 'visible' :
'hidden'), padding: '0', margin: '0'}}
+ onClick={event => EventBus.sendAlert(message[0],
message[1], 'danger')}/>
}
</div>
)
@@ -159,6 +163,25 @@ export function KaravanDesigner(props: Props) {
const isKamelet = integration.type === 'kamelet';
+ const [state, setState] = useState<ErrorBoundaryState>({ hasError: false,
error: null });
+
+ const resetErrorBoundary = () => {
+ setState({ hasError: false, error: null });
+ };
+
+ // Mimic `getDerivedStateFromError`
+ const handleError = (error: Error) => {
+ setState({ hasError: true, error });
+ setTab('code')
+ console.log(props.filename, error)
+ }
+
+ useEffect(() => {
+ if (state.hasError && state.error) {
+ EventBus.sendAlert(state.error.message,
state.error?.stack?.toString()?.substring(0, 300) || '', 'danger');
+ }
+ }, [state]);
+
return (
<PageSection variant={props.dark ? PageSectionVariants.darker :
PageSectionVariants.light}
className="page"
@@ -178,11 +201,13 @@ export function KaravanDesigner(props: Props) {
{props.showCodeTab && <Tab eventKey='code'
title={getTab("YAML", "YAML Code", "code", true)}></Tab>}
</Tabs>
</div>
- {tab === 'kamelet' && <KameletDesigner/>}
- {tab === 'routes' && <RouteDesigner/>}
- {tab === 'rest' && <RestDesigner/>}
- {tab === 'beans' && <BeansDesigner/>}
- {tab === 'code' && <CodeEditor/>}
+ <ErrorBoundaryWrapper onError={handleError}>
+ {tab === 'kamelet' && <KameletDesigner/>}
+ {tab === 'routes' && <RouteDesigner/>}
+ {tab === 'rest' && <RestDesigner/>}
+ {tab === 'beans' && <BeansDesigner/>}
+ {tab === 'code' && <CodeEditor/>}
+ </ErrorBoundaryWrapper>
</PageSection>
)
}
\ No newline at end of file