diff --git a/packages/ui/src/components/Visualization/Custom/CustomGroup.tsx b/packages/ui/src/components/Visualization/Custom/CustomGroup.tsx index 6761a934a..38d53ea9c 100644 --- a/packages/ui/src/components/Visualization/Custom/CustomGroup.tsx +++ b/packages/ui/src/components/Visualization/Custom/CustomGroup.tsx @@ -4,11 +4,13 @@ import { Layer, isNode, observer, - withSelection, withContextMenu, + withSelection, } from '@patternfly/react-topology'; import { FunctionComponent } from 'react'; +import { AddStepMode } from '../../../models/visualization/base-visual-entity'; import { CanvasNode } from '../Canvas/canvas.models'; +import { ItemInsertChildNode } from './ItemInsertChildNode'; import { ItemRemoveGroup } from './ItemRemoveGroup'; type IDefaultGroup = Parameters[0]; @@ -44,5 +46,10 @@ const CustomGroup: FunctionComponent = observer(({ element, ...res }); export const CustomGroupWithSelection = withContextMenu(() => [ + , , ])(withSelection()(CustomGroup)); diff --git a/packages/ui/src/components/Visualization/Custom/CustomNode.tsx b/packages/ui/src/components/Visualization/Custom/CustomNode.tsx index 7601a066b..56e1d7d70 100644 --- a/packages/ui/src/components/Visualization/Custom/CustomNode.tsx +++ b/packages/ui/src/components/Visualization/Custom/CustomNode.tsx @@ -17,6 +17,7 @@ import { ItemAddNode } from './ItemAddNode'; import { ItemInsertChildNode } from './ItemInsertChildNode'; import { ItemRemoveNode } from './ItemRemoveNode'; import { ItemReplaceNode } from './ItemReplaceNode'; +import { ItemRemoveGroup } from './ItemRemoveGroup'; interface CustomNodeProps extends WithSelectionProps { element: Node; @@ -78,4 +79,5 @@ export const CustomNodeWithSelection: typeof DefaultNode = withContextMenu(() => />, , , + , ])(withSelection()(CustomNode) as typeof DefaultNode) as typeof DefaultNode; diff --git a/packages/ui/src/components/Visualization/Custom/ItemRemoveGroup.tsx b/packages/ui/src/components/Visualization/Custom/ItemRemoveGroup.tsx index 14bd1cd66..e3cca4b28 100644 --- a/packages/ui/src/components/Visualization/Custom/ItemRemoveGroup.tsx +++ b/packages/ui/src/components/Visualization/Custom/ItemRemoveGroup.tsx @@ -1,6 +1,6 @@ import { TrashIcon } from '@patternfly/react-icons'; import { ContextMenuItem, ElementContext, ElementModel, GraphElement } from '@patternfly/react-topology'; -import { FunctionComponent, useCallback, useContext } from 'react'; +import { FunctionComponent, useCallback, useContext, useMemo } from 'react'; import { IDataTestID } from '../../../models'; import { EntitiesContext } from '../../../providers/entities.provider'; import { CanvasNode } from '../Canvas/canvas.models'; @@ -10,15 +10,20 @@ export const ItemRemoveGroup: FunctionComponent = (props) => { const element: GraphElement = useContext(ElementContext); const vizNode = element.getData()?.vizNode; const flowId = vizNode?.getBaseEntity()?.getId(); + const shouldRender = useMemo(() => { + const nodeInteractions = vizNode?.getNodeInteraction() ?? { canRemoveFlow: false }; + + return nodeInteractions.canRemoveFlow; + }, [vizNode]); const onRemoveGroup = useCallback(() => { entitiesContext?.camelResource.removeEntity(flowId); entitiesContext?.updateEntitiesFromCamelResource(); - }, [entitiesContext]); + }, [entitiesContext, flowId]); - return ( + return shouldRender ? ( Delete - ); + ) : null; }; diff --git a/packages/ui/src/models/visualization/base-visual-entity.ts b/packages/ui/src/models/visualization/base-visual-entity.ts index b7abea016..095e3f935 100644 --- a/packages/ui/src/models/visualization/base-visual-entity.ts +++ b/packages/ui/src/models/visualization/base-visual-entity.ts @@ -155,4 +155,5 @@ export interface NodeInteraction { canHaveSpecialChildren: boolean; canReplaceStep: boolean; canRemoveStep: boolean; + canRemoveFlow: boolean; } diff --git a/packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts b/packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts index 4770c6315..ad2f2dcd4 100644 --- a/packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts +++ b/packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts @@ -217,6 +217,7 @@ export abstract class AbstractCamelVisualEntity implements BaseVisualCamelEntity canHaveSpecialChildren, canReplaceStep: true, canRemoveStep: true, + canRemoveFlow: data.path === ROOT_PATH, }; } diff --git a/packages/ui/src/models/visualization/flows/camel-error-handler-visual-entity.test.ts b/packages/ui/src/models/visualization/flows/camel-error-handler-visual-entity.test.ts index f8ada2134..19729a25d 100644 --- a/packages/ui/src/models/visualization/flows/camel-error-handler-visual-entity.test.ts +++ b/packages/ui/src/models/visualization/flows/camel-error-handler-visual-entity.test.ts @@ -62,7 +62,7 @@ describe('CamelErrorHandlerVisualEntity', () => { it('should return node label', () => { const entity = new CamelErrorHandlerVisualEntity(errorHandlerDef); - expect(entity.getNodeLabel()).toEqual('errorHandler'); + expect(entity.getNodeLabel()).toEqual('noErrorHandlerId'); }); it('should return tooltip content', () => { @@ -130,6 +130,7 @@ describe('CamelErrorHandlerVisualEntity', () => { canHaveSpecialChildren: false, canRemoveStep: false, canReplaceStep: false, + canRemoveFlow: true, }); }); diff --git a/packages/ui/src/models/visualization/flows/camel-error-handler-visual-entity.ts b/packages/ui/src/models/visualization/flows/camel-error-handler-visual-entity.ts index 76b2d5d13..84d4a166c 100644 --- a/packages/ui/src/models/visualization/flows/camel-error-handler-visual-entity.ts +++ b/packages/ui/src/models/visualization/flows/camel-error-handler-visual-entity.ts @@ -1,8 +1,8 @@ -import { ErrorHandler, ProcessorDefinition } from '@kaoto-next/camel-catalog/types'; +import { ErrorHandlerBuilderDeserializer, ProcessorDefinition } from '@kaoto-next/camel-catalog/types'; import { getCamelRandomId } from '../../../camel-utils/camel-random-id'; import { SchemaService } from '../../../components/Form/schema.service'; import { useSchemasStore } from '../../../store'; -import { isDefined, setValue } from '../../../utils'; +import { getValue, isDefined, setValue } from '../../../utils'; import { EntityType } from '../../camel/entities/base-entity'; import { BaseVisualCamelEntity, @@ -17,12 +17,12 @@ export class CamelErrorHandlerVisualEntity implements BaseVisualCamelEntity { id: string; readonly type = EntityType.ErrorHandler; - constructor(public errorHandlerDef: { errorHandler: ErrorHandler }) { + constructor(public errorHandlerDef: { errorHandler: ErrorHandlerBuilderDeserializer }) { const id = getCamelRandomId('errorHandler'); this.id = id; } - static isApplicable(errorHandlerDef: unknown): errorHandlerDef is { errorHandler: ErrorHandler } { + static isApplicable(errorHandlerDef: unknown): errorHandlerDef is { errorHandler: ErrorHandlerBuilderDeserializer } { if (!isDefined(errorHandlerDef) || Array.isArray(errorHandlerDef) || typeof errorHandlerDef !== 'object') { return false; } @@ -43,7 +43,32 @@ export class CamelErrorHandlerVisualEntity implements BaseVisualCamelEntity { } getNodeLabel(): string { - return 'errorHandler'; + const deadLetterChannelId: string | undefined = getValue(this.errorHandlerDef.errorHandler, 'deadLetterChannel.id'); + const defaultErrorHandlerId: string | undefined = getValue( + this.errorHandlerDef.errorHandler, + 'defaultErrorHandler.id', + ); + const jtaTransactionErrorHandlerId: string | undefined = getValue( + this.errorHandlerDef.errorHandler, + 'jtaTransactionErrorHandler.id', + ); + const noErrorHandlerId: string | undefined = getValue(this.errorHandlerDef.errorHandler, 'noErrorHandler.id'); + const refErrorHandlerId: string | undefined = getValue(this.errorHandlerDef.errorHandler, 'refErrorHandler.id'); + const springTransactionErrorHandlerId: string | undefined = getValue( + this.errorHandlerDef.errorHandler, + 'springTransactionErrorHandler.id', + ); + + let errorHandlerId = + deadLetterChannelId ?? + defaultErrorHandlerId ?? + jtaTransactionErrorHandlerId ?? + noErrorHandlerId ?? + refErrorHandlerId ?? + springTransactionErrorHandlerId; + + if (!errorHandlerId?.trim()) errorHandlerId = 'errorHandler'; + return errorHandlerId; } getTooltipContent(): string { @@ -90,6 +115,7 @@ export class CamelErrorHandlerVisualEntity implements BaseVisualCamelEntity { canHaveSpecialChildren: false, canRemoveStep: false, canReplaceStep: false, + canRemoveFlow: true, }; } @@ -109,7 +135,7 @@ export class CamelErrorHandlerVisualEntity implements BaseVisualCamelEntity { return errorHandlerGroupNode; } - toJSON(): unknown { - return this.errorHandlerDef; + toJSON(): { errorHandler: ErrorHandlerBuilderDeserializer } { + return { errorHandler: this.errorHandlerDef.errorHandler }; } } diff --git a/packages/ui/src/models/visualization/flows/camel-on-exception-visual-entity.ts b/packages/ui/src/models/visualization/flows/camel-on-exception-visual-entity.ts index b61d37a11..eb344ffb4 100644 --- a/packages/ui/src/models/visualization/flows/camel-on-exception-visual-entity.ts +++ b/packages/ui/src/models/visualization/flows/camel-on-exception-visual-entity.ts @@ -225,6 +225,7 @@ export class CamelOnExceptionVisualEntity implements BaseVisualCamelEntity { canHaveSpecialChildren, canReplaceStep, canRemoveStep, + canRemoveFlow: data.path === CamelOnExceptionVisualEntity.ROOT_PATH, }; } diff --git a/packages/ui/src/models/visualization/flows/camel-rest-configuration-visual-entity.test.ts b/packages/ui/src/models/visualization/flows/camel-rest-configuration-visual-entity.test.ts index 6a63ab04b..9a037844f 100644 --- a/packages/ui/src/models/visualization/flows/camel-rest-configuration-visual-entity.test.ts +++ b/packages/ui/src/models/visualization/flows/camel-rest-configuration-visual-entity.test.ts @@ -136,6 +136,7 @@ describe('CamelRestConfigurationVisualEntity', () => { canHaveSpecialChildren: false, canRemoveStep: false, canReplaceStep: false, + canRemoveFlow: true, }); }); diff --git a/packages/ui/src/models/visualization/flows/camel-rest-configuration-visual-entity.ts b/packages/ui/src/models/visualization/flows/camel-rest-configuration-visual-entity.ts index 6f11e3439..864a76c6d 100644 --- a/packages/ui/src/models/visualization/flows/camel-rest-configuration-visual-entity.ts +++ b/packages/ui/src/models/visualization/flows/camel-rest-configuration-visual-entity.ts @@ -100,6 +100,7 @@ export class CamelRestConfigurationVisualEntity implements BaseVisualCamelEntity canHaveSpecialChildren: false, canRemoveStep: false, canReplaceStep: false, + canRemoveFlow: true, }; } diff --git a/packages/ui/src/models/visualization/flows/pipe-visual-entity.ts b/packages/ui/src/models/visualization/flows/pipe-visual-entity.ts index 103eaf1c3..7fad719f8 100644 --- a/packages/ui/src/models/visualization/flows/pipe-visual-entity.ts +++ b/packages/ui/src/models/visualization/flows/pipe-visual-entity.ts @@ -3,7 +3,7 @@ import get from 'lodash/get'; import set from 'lodash/set'; import { getCamelRandomId } from '../../../camel-utils/camel-random-id'; import { SchemaService } from '../../../components/Form/schema.service'; -import { getArrayProperty, NodeIconResolver } from '../../../utils'; +import { getArrayProperty, NodeIconResolver, ROOT_PATH } from '../../../utils'; import { DefinedComponent } from '../../camel-catalog-index'; import { EntityType } from '../../camel/entities'; import { PipeMetadata, PipeSpec, PipeStep } from '../../camel/entities/pipe-overrides'; @@ -165,6 +165,7 @@ export class PipeVisualEntity implements BaseVisualCamelEntity { canHaveSpecialChildren: false, canReplaceStep: true, canRemoveStep: true, + canRemoveFlow: data.path === ROOT_PATH, }; } diff --git a/packages/ui/src/models/visualization/visualization-node.ts b/packages/ui/src/models/visualization/visualization-node.ts index 892bd9cd2..368591161 100644 --- a/packages/ui/src/models/visualization/visualization-node.ts +++ b/packages/ui/src/models/visualization/visualization-node.ts @@ -24,6 +24,15 @@ class VisualizationNode