@@ -14,7 +14,10 @@ import {
1414 useModel ,
1515 useComponentFactory ,
1616 ComponentFactory ,
17- GraphElement
17+ GraphElement ,
18+ DefaultEdge ,
19+ Edge ,
20+ isEdge
1821} from '@patternfly/react-topology' ;
1922import defaultComponentFactory from '../components/defaultComponentFactory' ;
2023import DemoDefaultNode from '../components/DemoDefaultNode' ;
@@ -254,6 +257,166 @@ export const DndShiftRegroup = withTopologySetup(() => {
254257 return null ;
255258} ) ;
256259
260+ export const DndEdges = withTopologySetup ( ( ) => {
261+ useComponentFactory ( defaultComponentFactory ) ;
262+ // support pan zoom and drag
263+ useComponentFactory (
264+ React . useCallback < ComponentFactory > ( ( kind , type ) => {
265+ if ( kind === ModelKind . graph ) {
266+ return withPanZoom ( ) ( GraphComponent ) ;
267+ }
268+ if ( type === 'group-drop' ) {
269+ return withDndDrop <
270+ GraphElement ,
271+ any ,
272+ { droppable ?: boolean ; hover ?: boolean ; canDrop ?: boolean } ,
273+ ElementProps
274+ > ( {
275+ accept : 'test' ,
276+ canDrop : ( item , monitor , props ) => ! ! props && ( item as Node ) . getParent ( ) !== props . element ,
277+ collect : ( monitor ) => ( {
278+ droppable : monitor . isDragging ( ) ,
279+ hover : monitor . isOver ( ) ,
280+ canDrop : monitor . canDrop ( )
281+ } )
282+ } ) ( GroupHull ) ;
283+ }
284+ if ( type === 'node-drag' ) {
285+ return withDndDrag < DragObjectWithType , Node , { } , ElementProps > ( {
286+ item : { type : 'test' } ,
287+ begin : ( monitor , props ) => {
288+ props . element . raise ( ) ;
289+ return props . element ;
290+ } ,
291+ drag : ( event , monitor , props ) => {
292+ const nodeElement = props . element as Node ;
293+ nodeElement . setPosition ( nodeElement . getPosition ( ) . clone ( ) . translate ( event . dx , event . dy ) ) ;
294+ } ,
295+ end : ( dropResult , monitor , props ) => {
296+ if ( monitor . didDrop ( ) && dropResult && props ) {
297+ if ( isEdge ( dropResult ) ) {
298+ const droppedEdge = dropResult as Edge ;
299+ const newEdge1 = {
300+ type : droppedEdge . getType ( ) ,
301+ id : `${ droppedEdge . getSource ( ) . getId ( ) } -${ props . element . getId ( ) } ` ,
302+ source : droppedEdge . getSource ( ) . getId ( ) ,
303+ target : props . element . getId ( )
304+ } ;
305+ const newEdge2 = {
306+ type : droppedEdge . getType ( ) ,
307+ id : `${ props . element . getId ( ) } -${ droppedEdge . getTarget ( ) . getId ( ) } ` ,
308+ source : props . element . getId ( ) ,
309+ target : droppedEdge . getTarget ( ) . getId ( )
310+ } ;
311+ const model = droppedEdge . getController ( ) . toModel ( ) ;
312+ const updateModel : Model = { edges : [ newEdge1 , newEdge2 ] , nodes : model . nodes } ;
313+ droppedEdge . getController ( ) . fromModel ( updateModel , true ) ;
314+ } else {
315+ dropResult . appendChild ( props . element ) ;
316+ }
317+ }
318+ }
319+ } ) ( DemoDefaultNode ) ;
320+ }
321+ if ( type === 'edge' ) {
322+ return withDndDrop < Node , any , { droppable ?: boolean ; hover ?: boolean ; canDrop ?: boolean } , ElementProps > ( {
323+ accept : 'test' ,
324+ canDrop : ( item , monitor , props ) =>
325+ ! ! props &&
326+ ( props . element as Edge ) . getSource ( ) . getId ( ) !== item . getId ( ) &&
327+ ( props . element as Edge ) . getTarget ( ) . getId ( ) !== item . getId ( ) ,
328+ collect : ( monitor ) => ( {
329+ droppable : monitor . isDragging ( ) ,
330+ dropTarget : monitor . isOver ( ) ,
331+ canDrop : monitor . canDrop ( )
332+ } )
333+ } ) ( DefaultEdge ) ;
334+ }
335+ return undefined ;
336+ } , [ ] )
337+ ) ;
338+ useModel (
339+ React . useMemo (
340+ ( ) : Model => ( {
341+ graph : {
342+ id : 'g1' ,
343+ type : 'graph'
344+ } ,
345+ nodes : [
346+ {
347+ id : 'gr1' ,
348+ type : 'group-drop' ,
349+ group : true ,
350+ children : [ 'n2' , 'n3' ] ,
351+ style : {
352+ padding : 10
353+ }
354+ } ,
355+ {
356+ id : 'gr2' ,
357+ type : 'group-drop' ,
358+ group : true ,
359+ children : [ 'n4' , 'n5' ] ,
360+ style : {
361+ padding : 10
362+ }
363+ } ,
364+ {
365+ id : 'n1' ,
366+ type : 'node-drag' ,
367+ x : 50 ,
368+ y : 50 ,
369+ width : 30 ,
370+ height : 30
371+ } ,
372+ {
373+ id : 'n2' ,
374+ type : 'node' ,
375+ x : 200 ,
376+ y : 20 ,
377+ width : 10 ,
378+ height : 10
379+ } ,
380+ {
381+ id : 'n3' ,
382+ type : 'node' ,
383+ x : 150 ,
384+ y : 100 ,
385+ width : 20 ,
386+ height : 20
387+ } ,
388+ {
389+ id : 'n4' ,
390+ type : 'node' ,
391+ x : 300 ,
392+ y : 250 ,
393+ width : 30 ,
394+ height : 30
395+ } ,
396+ {
397+ id : 'n5' ,
398+ type : 'node' ,
399+ x : 350 ,
400+ y : 370 ,
401+ width : 15 ,
402+ height : 15
403+ }
404+ ] ,
405+ edges : [
406+ {
407+ id : 'e1' ,
408+ type : 'edge' ,
409+ source : 'n2' ,
410+ target : 'n4'
411+ }
412+ ]
413+ } ) ,
414+ [ ]
415+ )
416+ ) ;
417+ return null ;
418+ } ) ;
419+
257420export const DragAndDrop : React . FunctionComponent = ( ) => {
258421 const [ activeKey , setActiveKey ] = React . useState < string | number > ( 0 ) ;
259422
@@ -270,6 +433,9 @@ export const DragAndDrop: React.FunctionComponent = () => {
270433 < Tab eventKey = { 1 } title = { < TabTitleText > Dnd Shift Regroup</ TabTitleText > } >
271434 < DndShiftRegroup />
272435 </ Tab >
436+ < Tab eventKey = { 2 } title = { < TabTitleText > Dnd Edges</ TabTitleText > } >
437+ < DndEdges />
438+ </ Tab >
273439 </ Tabs >
274440 </ div >
275441 ) ;
0 commit comments