Skip to content

Commit

Permalink
feat(Canvas): Consolidate groups interactions
Browse files Browse the repository at this point in the history
Currently, expanded and collapsed groups don't have the interactions available, for instance:

* Expanded groups: Only allowed to delete the entire flow
* Collapsed groups: Only allowed to Insert step

This commit consolidates both functionalities where it makes sense, so expanded groups allow the deletion of the flow, and collapsed ones allow to insert step (which expands the group) and the deletion of the entire flow.

relates: #492
  • Loading branch information
lordrip committed Apr 16, 2024
1 parent 981c994 commit 477304c
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof DefaultGroup>[0];
Expand Down Expand Up @@ -44,5 +46,10 @@ const CustomGroup: FunctionComponent<ICustomGroup> = observer(({ element, ...res
});

export const CustomGroupWithSelection = withContextMenu(() => [
<ItemInsertChildNode
key="context-menu-item-insert-special"
data-testid="context-menu-item-insert-special"
mode={AddStepMode.InsertSpecialChildStep}
/>,
<ItemRemoveGroup key="context-menu-container-remove" data-testid="context-menu-container-remove" />,
])(withSelection()(CustomGroup));
Original file line number Diff line number Diff line change
Expand Up @@ -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<CanvasNode, CanvasNode['data']>;
Expand Down Expand Up @@ -78,4 +79,5 @@ export const CustomNodeWithSelection: typeof DefaultNode = withContextMenu(() =>
/>,
<ItemReplaceNode key="context-menu-item-replace" data-testid="context-menu-item-replace" />,
<ItemRemoveNode key="context-menu-item-remove" data-testid="context-menu-item-remove" />,
<ItemRemoveGroup key="context-menu-container-remove" data-testid="context-menu-container-remove" />,
])(withSelection()(CustomNode) as typeof DefaultNode) as typeof DefaultNode;
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -10,15 +10,20 @@ export const ItemRemoveGroup: FunctionComponent<IDataTestID> = (props) => {
const element: GraphElement<ElementModel, CanvasNode['data']> = 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 ? (
<ContextMenuItem onClick={onRemoveGroup} data-testid={props['data-testid']}>
<TrashIcon /> Delete
</ContextMenuItem>
);
) : null;
};
1 change: 1 addition & 0 deletions packages/ui/src/models/visualization/base-visual-entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,5 @@ export interface NodeInteraction {
canHaveSpecialChildren: boolean;
canReplaceStep: boolean;
canRemoveStep: boolean;
canRemoveFlow: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ export abstract class AbstractCamelVisualEntity implements BaseVisualCamelEntity
canHaveSpecialChildren,
canReplaceStep: true,
canRemoveStep: true,
canRemoveFlow: data.path === ROOT_PATH,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -130,6 +130,7 @@ describe('CamelErrorHandlerVisualEntity', () => {
canHaveSpecialChildren: false,
canRemoveStep: false,
canReplaceStep: false,
canRemoveFlow: true,
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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;
}
Expand All @@ -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 {
Expand Down Expand Up @@ -90,6 +115,7 @@ export class CamelErrorHandlerVisualEntity implements BaseVisualCamelEntity {
canHaveSpecialChildren: false,
canRemoveStep: false,
canReplaceStep: false,
canRemoveFlow: true,
};
}

Expand All @@ -109,7 +135,7 @@ export class CamelErrorHandlerVisualEntity implements BaseVisualCamelEntity {
return errorHandlerGroupNode;
}

toJSON(): unknown {
return this.errorHandlerDef;
toJSON(): { errorHandler: ErrorHandlerBuilderDeserializer } {
return { errorHandler: this.errorHandlerDef.errorHandler };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ export class CamelOnExceptionVisualEntity implements BaseVisualCamelEntity {
canHaveSpecialChildren,
canReplaceStep,
canRemoveStep,
canRemoveFlow: data.path === CamelOnExceptionVisualEntity.ROOT_PATH,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ describe('CamelRestConfigurationVisualEntity', () => {
canHaveSpecialChildren: false,
canRemoveStep: false,
canReplaceStep: false,
canRemoveFlow: true,
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export class CamelRestConfigurationVisualEntity implements BaseVisualCamelEntity
canHaveSpecialChildren: false,
canRemoveStep: false,
canReplaceStep: false,
canRemoveFlow: true,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -165,6 +165,7 @@ export class PipeVisualEntity implements BaseVisualCamelEntity {
canHaveSpecialChildren: false,
canReplaceStep: true,
canRemoveStep: true,
canRemoveFlow: data.path === ROOT_PATH,
};
}

Expand Down
20 changes: 10 additions & 10 deletions packages/ui/src/models/visualization/visualization-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ class VisualizationNode<T extends IVisualizationNodeData = IVisualizationNodeDat
private previousNode: IVisualizationNode | undefined = undefined;
private nextNode: IVisualizationNode | undefined = undefined;
private children: IVisualizationNode[] | undefined;
private readonly DISABLED_NODE_INTERACTION: NodeInteraction = {
canHavePreviousStep: false,
canHaveNextStep: false,
canHaveChildren: false,
canHaveSpecialChildren: false,
canReplaceStep: false,
canRemoveStep: false,
canRemoveFlow: false,
};

constructor(
public readonly id: string,
Expand All @@ -47,16 +56,7 @@ class VisualizationNode<T extends IVisualizationNodeData = IVisualizationNodeDat
}

getNodeInteraction(): NodeInteraction {
return (
this.getBaseEntity()?.getNodeInteraction(this.data) ?? {
canHavePreviousStep: false,
canHaveNextStep: false,
canHaveChildren: false,
canHaveSpecialChildren: false,
canReplaceStep: false,
canRemoveStep: false,
}
);
return this.getBaseEntity()?.getNodeInteraction(this.data) ?? this.DISABLED_NODE_INTERACTION;
}

getComponentSchema(): VisualComponentSchema | undefined {
Expand Down

0 comments on commit 477304c

Please sign in to comment.