Skip to content

Commit

Permalink
ErrorBoundaryWrapper for designer
Browse files Browse the repository at this point in the history
  • Loading branch information
mgubaidullin committed Dec 4, 2024
1 parent a9d79f1 commit b08ef5f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 10 deletions.
21 changes: 21 additions & 0 deletions karavan-designer/src/designer/ErrorBoundaryWrapper.tsx
Original file line number Diff line number Diff line change
@@ -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;
}
}
45 changes: 35 additions & 10 deletions karavan-designer/src/designer/KaravanDesigner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -65,14 +66,15 @@ 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)

useEffect(() => {
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);
Expand Down Expand Up @@ -104,6 +106,8 @@ export function KaravanDesigner(props: Props) {
sub?.unsubscribe();
setSelectedStep(undefined);
reset();
resetErrorBoundary();
setIntegration(Integration.createNew("demo"), false);
};
}, []);

Expand Down Expand Up @@ -141,24 +145,43 @@ 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>
<TabTitleText>{title}</TabTitleText>
{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>
)
}

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"
Expand All @@ -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>
)
}

0 comments on commit b08ef5f

Please sign in to comment.