Skip to content

Commit c7ce14a

Browse files
committed
fix(Drag&Drop): Enabled container drag and drop support
1 parent 8d1402b commit c7ce14a

File tree

10 files changed

+534
-191
lines changed

10 files changed

+534
-191
lines changed

packages/ui/src/components/Visualization/Custom/Edge/AddStepIcon.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,8 @@
2222
color: var(--pf-topology__edge--Stroke);
2323
}
2424
}
25+
26+
&__icon__validDropTarget &__icon {
27+
border: 3px dashed var(--custom-component-dropTarget);
28+
}
2529
}

packages/ui/src/components/Visualization/Custom/Edge/CustomEdge.test.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,16 @@ describe('CustomEdge', () => {
2424
it('should render without error', () => {
2525
const parentElement = new BaseGraph();
2626
const element = new BaseEdge();
27+
const edgeSource = new BaseNode();
28+
const edgeTarget = new BaseNode();
29+
edgeSource.setParent(parentElement);
30+
edgeTarget.setParent(parentElement);
31+
element.setSource(edgeSource);
32+
element.setTarget(edgeTarget);
2733
const controller = ControllerService.createController();
2834
parentElement.setController(controller);
2935
element.setController(controller);
3036
element.setParent(parentElement);
31-
element.setSource(new BaseNode());
32-
element.setTarget(new BaseNode());
3337
element.setStartPoint(0, 0);
3438
element.setEndPoint(100, 100);
3539

packages/ui/src/components/Visualization/Custom/Edge/CustomEdge.tsx

Lines changed: 84 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import {
1111
GraphElement,
1212
GraphElementProps,
1313
isEdge,
14+
Layer,
1415
observer,
1516
Point,
17+
TOP_LAYER,
1618
useDndDrop,
1719
} from '@patternfly/react-topology';
1820
import { clsx } from 'clsx';
@@ -23,7 +25,7 @@ import { useEntityContext } from '../../../../hooks/useEntityContext/useEntityCo
2325
import { AddStepMode, IVisualizationNode } from '../../../../models';
2426
import { LayoutType } from '../../Canvas';
2527
import { CanvasDefaults } from '../../Canvas/canvas.defaults';
26-
import { canDropOnEdge, NODE_DRAG_TYPE } from '../customComponentUtils';
28+
import { canDropOnEdge, GROUP_DRAG_TYPE, NODE_DRAG_TYPE } from '../customComponentUtils';
2729
import { AddStepIcon } from './AddStepIcon';
2830

2931
type DefaultEdgeProps = Parameters<typeof DefaultEdge>[0];
@@ -46,15 +48,23 @@ export const CustomEdge: FunctionComponent<CustomEdgeProps> = observer(({ elemen
4648
const customNodeDropTargetSpec: DropTargetSpec<
4749
GraphElement,
4850
unknown,
49-
{ droppable: boolean; hover: boolean; canDrop: boolean },
51+
{
52+
droppable: boolean;
53+
hover: boolean;
54+
canDrop: boolean;
55+
dragItemType: string | undefined;
56+
dragItem: GraphElement | undefined;
57+
},
5058
GraphElementProps
5159
> = useMemo(
5260
() => ({
53-
accept: [NODE_DRAG_TYPE],
61+
accept: [NODE_DRAG_TYPE, GROUP_DRAG_TYPE],
5462
canDrop: (item, _monitor, _props) =>
5563
canDropOnEdge(item.getData().vizNode, element, entitiesContext.camelResource, catalogModalContext),
5664
collect: (monitor) => ({
5765
droppable: monitor.isDragging(),
66+
dragItemType: monitor.getItemType(),
67+
dragItem: monitor.getItem(),
5868
hover: monitor.isOver(),
5969
canDrop: monitor.canDrop(),
6070
}),
@@ -63,6 +73,14 @@ export const CustomEdge: FunctionComponent<CustomEdgeProps> = observer(({ elemen
6373
);
6474

6575
const [dndDropProps, dndDropRef] = useDndDrop(customNodeDropTargetSpec);
76+
const dragItemType = dndDropProps.dragItemType;
77+
const dragItem = dndDropProps.dragItem;
78+
const edgeSourceParent = element.getSource().getParent()?.getId();
79+
const edgeTargetParent = element.getTarget().getParent()?.getId();
80+
const refreshEdge =
81+
dragItemType === GROUP_DRAG_TYPE &&
82+
edgeSourceParent.slice(0, dragItem?.getId().length) === dragItem?.getId() &&
83+
edgeTargetParent.slice(0, dragItem?.getId().length) === dragItem?.getId();
6684

6785
/* If the edge connects to nodes in a collapsed group don't draw */
6886
const sourceParent = getClosestVisibleParent(element.getSource());
@@ -104,37 +122,70 @@ export const CustomEdge: FunctionComponent<CustomEdgeProps> = observer(({ elemen
104122
}
105123

106124
return (
107-
<g className="custom-edge" ref={dndDropRef}>
108-
<path className="custom-edge__background" d={edgeDRef.current} />
109-
<path
110-
className={clsx('custom-edge__body', {
111-
'custom-edge__body__validDropTarget': dndDropProps.hover && dndDropProps.canDrop,
112-
})}
113-
d={edgeDRef.current}
114-
/>
115-
<ConnectorArrow
116-
isTarget
117-
className={clsx('custom-edge__connector', {
118-
'custom-edge__connector__validDropTarget': dndDropProps.hover && dndDropProps.canDrop,
119-
})}
120-
startPoint={startPointRef.current}
121-
endPoint={endPointRef.current}
122-
/>
125+
<Layer id={refreshEdge ? TOP_LAYER : undefined}>
126+
<g className="custom-edge" ref={dndDropRef}>
127+
<path className="custom-edge__background" d={edgeDRef.current} />
128+
<path
129+
className={clsx('custom-edge__body', {
130+
'custom-edge__body__validDropTarget': dndDropProps.hover && dndDropProps.canDrop,
131+
})}
132+
d={edgeDRef.current}
133+
/>
134+
<ConnectorArrow
135+
isTarget
136+
className={clsx('custom-edge__connector', {
137+
'custom-edge__connector__validDropTarget': dndDropProps.hover && dndDropProps.canDrop,
138+
})}
139+
startPoint={startPointRef.current}
140+
endPoint={endPointRef.current}
141+
/>
123142

124-
{!dndDropProps.droppable && shouldShowPrepend && (
125-
<foreignObject x={x} y={y} width={CanvasDefaults.ADD_STEP_ICON_SIZE} height={CanvasDefaults.ADD_STEP_ICON_SIZE}>
126-
<AddStepIcon
127-
className="custom-edge__add-step"
128-
title="Add step"
129-
vizNode={vizNode}
130-
mode={AddStepMode.PrependStep}
143+
{!dndDropProps.droppable && shouldShowPrepend && (
144+
<foreignObject
145+
x={x}
146+
y={y}
147+
width={CanvasDefaults.ADD_STEP_ICON_SIZE}
148+
height={CanvasDefaults.ADD_STEP_ICON_SIZE}
131149
>
132-
<Icon size="lg">
133-
<PlusCircleIcon />
134-
</Icon>
135-
</AddStepIcon>
136-
</foreignObject>
137-
)}
138-
</g>
150+
<AddStepIcon
151+
className="custom-edge__add-step"
152+
title="Add step"
153+
vizNode={vizNode}
154+
mode={AddStepMode.PrependStep}
155+
>
156+
<Icon size="lg">
157+
<PlusCircleIcon />
158+
</Icon>
159+
</AddStepIcon>
160+
</foreignObject>
161+
)}
162+
163+
{dndDropProps.droppable && shouldShowPrepend && dndDropProps.hover && dndDropProps.canDrop && (
164+
<foreignObject
165+
x={
166+
startPointRef.current.x +
167+
(endPointRef.current.x - startPointRef.current.x - CanvasDefaults.ADD_STEP_ICON_SIZE) / 2
168+
}
169+
y={
170+
startPointRef.current.y +
171+
(endPointRef.current.y - startPointRef.current.y - CanvasDefaults.ADD_STEP_ICON_SIZE) / 2
172+
}
173+
width={CanvasDefaults.ADD_STEP_ICON_SIZE}
174+
height={CanvasDefaults.ADD_STEP_ICON_SIZE}
175+
>
176+
<AddStepIcon
177+
className="add-step-icon__icon__validDropTarget"
178+
title="Add step"
179+
vizNode={vizNode}
180+
mode={AddStepMode.PrependStep}
181+
>
182+
<Icon size="lg">
183+
<PlusCircleIcon />
184+
</Icon>
185+
</AddStepIcon>
186+
</foreignObject>
187+
)}
188+
</g>
189+
</Layer>
139190
);
140191
});

packages/ui/src/components/Visualization/Custom/Group/CustomGroupExpanded.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@
7373
border-color: var(--pf-topology__node--m-danger--Background--Fill);
7474
box-shadow: var(--custom-node-Shadow);
7575
}
76+
77+
&__draggedGroup {
78+
@include custom.drag-group;
79+
}
80+
81+
&__dropTarget-right {
82+
border-right: var(--custom-group-border-dropTarget);
83+
}
84+
85+
&__dropTarget-left {
86+
border-left: var(--custom-group-border-dropTarget);
87+
}
7688
}
7789

7890
&__disabled-icon {

0 commit comments

Comments
 (0)