You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2021/11/12 18:15:01 UTC

[camel-karavan] branch main updated: Reorder (#85)

This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git


The following commit(s) were added to refs/heads/main by this push:
     new f20be24  Reorder (#85)
f20be24 is described below

commit f20be24cbca46de4c0e006177e3993223786c895
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Nov 12 13:14:55 2021 -0500

    Reorder (#85)
    
    * Drag and Drop reorder prototype
    
    * Prototype of move
    
    * Reorder drag-n-drop non-generated
    
    * Reorder drag-n-drop non-generated
    
    * Fix #39
---
 karavan-designer/src/App.tsx                       |  23 ++-
 karavan-designer/src/designer/api/CamelApi.tsx     | 213 +++++++++++++++------
 karavan-designer/src/designer/api/CamelApiExt.tsx  |  32 +++-
 karavan-designer/src/designer/model/CamelModel.tsx |  14 ++
 karavan-designer/src/designer/ui/DslElement.tsx    |  70 ++++++-
 .../src/designer/ui/KaravanDesigner.tsx            |   8 +-
 .../karavan/generator/CamelModelGenerator.java     |  35 +++-
 .../main/resources/CamelApi.addStep.choiceStep.tx  |   4 +-
 .../main/resources/CamelApi.addStep.otherwise.tx   |   4 +-
 .../src/main/resources/CamelApi.addStep.when.tx    |   4 +-
 .../main/resources/CamelApi.findStep.choiceStep.tx |   8 +
 .../src/main/resources/CamelApi.findStep.footer.tx |   9 +
 .../src/main/resources/CamelApi.findStep.header.tx |   6 +
 .../main/resources/CamelApi.findStep.otherwise.tx  |   3 +
 .../src/main/resources/CamelApi.findStep.when.tx   |   3 +
 .../src/main/resources/camel-model.template        |  14 ++
 16 files changed, 360 insertions(+), 90 deletions(-)

diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index a331f5d..ccd9be2 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -45,16 +45,19 @@ class App extends React.Component<Props, State> {
             '    - from:\n' +
             '        uri: \'kamelet:http-secured-source\'\n' +
             '        steps:\n' +
-            // '          - set-body:\n' +
-            // '              expression: \n' +
-            // '                constant: "Hello Yaml !!!"\n' +
-            // '          - set-body:\n' +
-            // '              constant: "Hello Yaml !!!"\n' +
-            // '          - pollEnrich:\n' +
-            // '              expression: {}\n' +
-            // '          - to: \n' +
-            // '               uri: "log:info"\n' +
-            '          - to: "log:info"\n'
+            '          - set-body:\n' +
+            '              expression: \n' +
+            '                constant: "Hello Yaml !!!"\n' +
+            '          - pollEnrich:\n' +
+            '              expression: {}\n' +
+            '          - to: \n' +
+            '               uri: "log:info"\n' +
+            '          - choice:\n' +
+            '              otherwise: {}\n' +
+            '              when:\n' +
+            '                - expression: {}\n' +
+            '                  steps:\n' +
+            '                    - to-d: {}\n'
             ,
         key: ''
     };
diff --git a/karavan-designer/src/designer/api/CamelApi.tsx b/karavan-designer/src/designer/api/CamelApi.tsx
index 5556525..e6bdf92 100644
--- a/karavan-designer/src/designer/api/CamelApi.tsx
+++ b/karavan-designer/src/designer/api/CamelApi.tsx
@@ -1,8 +1,10 @@
 /**
  * Generated by karavan build tools - do NOT edit this file!
  */
-import {    CamelElement, 
+import {
+    CamelElement, 
     ProcessorStep, 
+    ProcessorStepMeta, 
     FromStep, 
     Expression, 
     PolicyStep, 
@@ -823,14 +825,15 @@ export class CamelApi {
             default : return new CamelElement('')
         }
     }
-    static addStep = (steps: ProcessorStep[], step: ProcessorStep, parentId: string): ProcessorStep[] => {
+
+    static addStep = (steps: ProcessorStep[], step: ProcessorStep, parentId: string, position?: number): ProcessorStep[] => {
         const result: ProcessorStep[] = [];
         steps.forEach(el => {
             switch (el.dslName) {
                 case 'policyStep':
                     const policyChildren = (el as PolicyStep).policy?.steps || [];
-                    if (el.uuid === parentId) policyChildren.push(step)
-                    else (el as PolicyStep).policy.steps = CamelApi.addStep(policyChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? policyChildren.splice(position, 0, step) : policyChildren.push(step);
+                    else (el as PolicyStep).policy.steps = CamelApi.addStep(policyChildren, step, parentId, position);
                     break;
                 case 'choiceStep':
                     const choiceChildren = (el as ChoiceStep).choice?.when || [];
@@ -840,137 +843,137 @@ export class CamelApi {
                     }  else if (el.uuid === parentId && step.dslName === 'otherwise' && !(el as ChoiceStep).choice.otherwise) {
                         (el as ChoiceStep).choice.otherwise = step;
                     } else {
-                        (el as ChoiceStep).choice.when = CamelApi.addStep(choiceChildren, step, parentId) as When[];
+                        (el as ChoiceStep).choice.when = CamelApi.addStep(choiceChildren, step, parentId, position) as When[];
                         const otherwise = (el as ChoiceStep).choice.otherwise;
                         if (otherwise?.uuid === parentId){
                             otherwise.steps = otherwise.steps ? [...otherwise.steps] : [];
                             otherwise.steps.push(step);
                             (el as ChoiceStep).choice.otherwise = otherwise
                         } else if (otherwise && otherwise.steps && otherwise.steps.length > 0){
-                            otherwise.steps = CamelApi.addStep(otherwise.steps, step, parentId);
+                            otherwise.steps = CamelApi.addStep(otherwise.steps, step, parentId, position);
                             (el as ChoiceStep).choice.otherwise = otherwise;
                         }
                     }
                     break;
                 case 'otherwise':
                     const otherwiseChildren = (el as Otherwise).steps || [];
-                    if (el.uuid === parentId) otherwiseChildren.push(step)
-                    else (el as Otherwise).steps = CamelApi.addStep(otherwiseChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? otherwiseChildren.splice(position, 0, step) : otherwiseChildren.push(step);
+                    else (el as Otherwise).steps = CamelApi.addStep(otherwiseChildren, step, parentId, position);
                     break;
                 case 'fromStep':
                     const fromChildren = (el as FromStep).from?.steps || [];
-                    if (el.uuid === parentId) fromChildren.push(step)
-                    else (el as FromStep).from.steps = CamelApi.addStep(fromChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? fromChildren.splice(position, 0, step) : fromChildren.push(step);
+                    else (el as FromStep).from.steps = CamelApi.addStep(fromChildren, step, parentId, position);
                     break;
                 case 'onCompletionStep':
                     const onCompletionChildren = (el as OnCompletionStep).onCompletion?.steps || [];
-                    if (el.uuid === parentId) onCompletionChildren.push(step)
-                    else (el as OnCompletionStep).onCompletion.steps = CamelApi.addStep(onCompletionChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? onCompletionChildren.splice(position, 0, step) : onCompletionChildren.push(step);
+                    else (el as OnCompletionStep).onCompletion.steps = CamelApi.addStep(onCompletionChildren, step, parentId, position);
                     break;
                 case 'splitStep':
                     const splitChildren = (el as SplitStep).split?.steps || [];
-                    if (el.uuid === parentId) splitChildren.push(step)
-                    else (el as SplitStep).split.steps = CamelApi.addStep(splitChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? splitChildren.splice(position, 0, step) : splitChildren.push(step);
+                    else (el as SplitStep).split.steps = CamelApi.addStep(splitChildren, step, parentId, position);
                     break;
                 case 'transactedStep':
                     const transactedChildren = (el as TransactedStep).transacted?.steps || [];
-                    if (el.uuid === parentId) transactedChildren.push(step)
-                    else (el as TransactedStep).transacted.steps = CamelApi.addStep(transactedChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? transactedChildren.splice(position, 0, step) : transactedChildren.push(step);
+                    else (el as TransactedStep).transacted.steps = CamelApi.addStep(transactedChildren, step, parentId, position);
                     break;
                 case 'interceptFromStep':
                     const interceptFromChildren = (el as InterceptFromStep).interceptFrom?.steps || [];
-                    if (el.uuid === parentId) interceptFromChildren.push(step)
-                    else (el as InterceptFromStep).interceptFrom.steps = CamelApi.addStep(interceptFromChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? interceptFromChildren.splice(position, 0, step) : interceptFromChildren.push(step);
+                    else (el as InterceptFromStep).interceptFrom.steps = CamelApi.addStep(interceptFromChildren, step, parentId, position);
                     break;
                 case 'doCatchStep':
                     const doCatchChildren = (el as DoCatchStep).doCatch?.steps || [];
-                    if (el.uuid === parentId) doCatchChildren.push(step)
-                    else (el as DoCatchStep).doCatch.steps = CamelApi.addStep(doCatchChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? doCatchChildren.splice(position, 0, step) : doCatchChildren.push(step);
+                    else (el as DoCatchStep).doCatch.steps = CamelApi.addStep(doCatchChildren, step, parentId, position);
                     break;
                 case 'circuitBreakerStep':
                     const circuitBreakerChildren = (el as CircuitBreakerStep).circuitBreaker?.steps || [];
-                    if (el.uuid === parentId) circuitBreakerChildren.push(step)
-                    else (el as CircuitBreakerStep).circuitBreaker.steps = CamelApi.addStep(circuitBreakerChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? circuitBreakerChildren.splice(position, 0, step) : circuitBreakerChildren.push(step);
+                    else (el as CircuitBreakerStep).circuitBreaker.steps = CamelApi.addStep(circuitBreakerChildren, step, parentId, position);
                     break;
                 case 'interceptStep':
                     const interceptChildren = (el as InterceptStep).intercept?.steps || [];
-                    if (el.uuid === parentId) interceptChildren.push(step)
-                    else (el as InterceptStep).intercept.steps = CamelApi.addStep(interceptChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? interceptChildren.splice(position, 0, step) : interceptChildren.push(step);
+                    else (el as InterceptStep).intercept.steps = CamelApi.addStep(interceptChildren, step, parentId, position);
                     break;
                 case 'onFallbackStep':
                     const onFallbackChildren = (el as OnFallbackStep).onFallback?.steps || [];
-                    if (el.uuid === parentId) onFallbackChildren.push(step)
-                    else (el as OnFallbackStep).onFallback.steps = CamelApi.addStep(onFallbackChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? onFallbackChildren.splice(position, 0, step) : onFallbackChildren.push(step);
+                    else (el as OnFallbackStep).onFallback.steps = CamelApi.addStep(onFallbackChildren, step, parentId, position);
                     break;
                 case 'multicastStep':
                     const multicastChildren = (el as MulticastStep).multicast?.steps || [];
-                    if (el.uuid === parentId) multicastChildren.push(step)
-                    else (el as MulticastStep).multicast.steps = CamelApi.addStep(multicastChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? multicastChildren.splice(position, 0, step) : multicastChildren.push(step);
+                    else (el as MulticastStep).multicast.steps = CamelApi.addStep(multicastChildren, step, parentId, position);
                     break;
                 case 'loadBalanceStep':
                     const loadBalanceChildren = (el as LoadBalanceStep).loadBalance?.steps || [];
-                    if (el.uuid === parentId) loadBalanceChildren.push(step)
-                    else (el as LoadBalanceStep).loadBalance.steps = CamelApi.addStep(loadBalanceChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? loadBalanceChildren.splice(position, 0, step) : loadBalanceChildren.push(step);
+                    else (el as LoadBalanceStep).loadBalance.steps = CamelApi.addStep(loadBalanceChildren, step, parentId, position);
                     break;
                 case 'whenSkipSendToEndpointStep':
                     const whenSkipSendToEndpointChildren = (el as WhenSkipSendToEndpointStep).whenSkipSendToEndpoint?.steps || [];
-                    if (el.uuid === parentId) whenSkipSendToEndpointChildren.push(step)
-                    else (el as WhenSkipSendToEndpointStep).whenSkipSendToEndpoint.steps = CamelApi.addStep(whenSkipSendToEndpointChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? whenSkipSendToEndpointChildren.splice(position, 0, step) : whenSkipSendToEndpointChildren.push(step);
+                    else (el as WhenSkipSendToEndpointStep).whenSkipSendToEndpoint.steps = CamelApi.addStep(whenSkipSendToEndpointChildren, step, parentId, position);
                     break;
                 case 'loopStep':
                     const loopChildren = (el as LoopStep).loop?.steps || [];
-                    if (el.uuid === parentId) loopChildren.push(step)
-                    else (el as LoopStep).loop.steps = CamelApi.addStep(loopChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? loopChildren.splice(position, 0, step) : loopChildren.push(step);
+                    else (el as LoopStep).loop.steps = CamelApi.addStep(loopChildren, step, parentId, position);
                     break;
                 case 'interceptSendToEndpointStep':
                     const interceptSendToEndpointChildren = (el as InterceptSendToEndpointStep).interceptSendToEndpoint?.steps || [];
-                    if (el.uuid === parentId) interceptSendToEndpointChildren.push(step)
-                    else (el as InterceptSendToEndpointStep).interceptSendToEndpoint.steps = CamelApi.addStep(interceptSendToEndpointChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? interceptSendToEndpointChildren.splice(position, 0, step) : interceptSendToEndpointChildren.push(step);
+                    else (el as InterceptSendToEndpointStep).interceptSendToEndpoint.steps = CamelApi.addStep(interceptSendToEndpointChildren, step, parentId, position);
                     break;
                 case 'doTryStep':
                     const doTryChildren = (el as DoTryStep).doTry?.steps || [];
-                    if (el.uuid === parentId) doTryChildren.push(step)
-                    else (el as DoTryStep).doTry.steps = CamelApi.addStep(doTryChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? doTryChildren.splice(position, 0, step) : doTryChildren.push(step);
+                    else (el as DoTryStep).doTry.steps = CamelApi.addStep(doTryChildren, step, parentId, position);
                     break;
                 case 'resequenceStep':
                     const resequenceChildren = (el as ResequenceStep).resequence?.steps || [];
-                    if (el.uuid === parentId) resequenceChildren.push(step)
-                    else (el as ResequenceStep).resequence.steps = CamelApi.addStep(resequenceChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? resequenceChildren.splice(position, 0, step) : resequenceChildren.push(step);
+                    else (el as ResequenceStep).resequence.steps = CamelApi.addStep(resequenceChildren, step, parentId, position);
                     break;
                 case 'pipelineStep':
                     const pipelineChildren = (el as PipelineStep).pipeline?.steps || [];
-                    if (el.uuid === parentId) pipelineChildren.push(step)
-                    else (el as PipelineStep).pipeline.steps = CamelApi.addStep(pipelineChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? pipelineChildren.splice(position, 0, step) : pipelineChildren.push(step);
+                    else (el as PipelineStep).pipeline.steps = CamelApi.addStep(pipelineChildren, step, parentId, position);
                     break;
                 case 'sagaStep':
                     const sagaChildren = (el as SagaStep).saga?.steps || [];
-                    if (el.uuid === parentId) sagaChildren.push(step)
-                    else (el as SagaStep).saga.steps = CamelApi.addStep(sagaChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? sagaChildren.splice(position, 0, step) : sagaChildren.push(step);
+                    else (el as SagaStep).saga.steps = CamelApi.addStep(sagaChildren, step, parentId, position);
                     break;
                 case 'when':
                     const whenChildren = (el as When).steps || [];
-                    if (el.uuid === parentId) whenChildren.push(step)
-                    else (el as When).steps = CamelApi.addStep(whenChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? whenChildren.splice(position, 0, step) : whenChildren.push(step);
+                    else (el as When).steps = CamelApi.addStep(whenChildren, step, parentId, position);
                     break;
                 case 'doFinallyStep':
                     const doFinallyChildren = (el as DoFinallyStep).doFinally?.steps || [];
-                    if (el.uuid === parentId) doFinallyChildren.push(step)
-                    else (el as DoFinallyStep).doFinally.steps = CamelApi.addStep(doFinallyChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? doFinallyChildren.splice(position, 0, step) : doFinallyChildren.push(step);
+                    else (el as DoFinallyStep).doFinally.steps = CamelApi.addStep(doFinallyChildren, step, parentId, position);
                     break;
                 case 'filterStep':
                     const filterChildren = (el as FilterStep).filter?.steps || [];
-                    if (el.uuid === parentId) filterChildren.push(step)
-                    else (el as FilterStep).filter.steps = CamelApi.addStep(filterChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? filterChildren.splice(position, 0, step) : filterChildren.push(step);
+                    else (el as FilterStep).filter.steps = CamelApi.addStep(filterChildren, step, parentId, position);
                     break;
                 case 'aggregateStep':
                     const aggregateChildren = (el as AggregateStep).aggregate?.steps || [];
-                    if (el.uuid === parentId) aggregateChildren.push(step)
-                    else (el as AggregateStep).aggregate.steps = CamelApi.addStep(aggregateChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? aggregateChildren.splice(position, 0, step) : aggregateChildren.push(step);
+                    else (el as AggregateStep).aggregate.steps = CamelApi.addStep(aggregateChildren, step, parentId, position);
                     break;
                 case 'idempotentConsumerStep':
                     const idempotentConsumerChildren = (el as IdempotentConsumerStep).idempotentConsumer?.steps || [];
-                    if (el.uuid === parentId) idempotentConsumerChildren.push(step)
-                    else (el as IdempotentConsumerStep).idempotentConsumer.steps = CamelApi.addStep(idempotentConsumerChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? idempotentConsumerChildren.splice(position, 0, step) : idempotentConsumerChildren.push(step);
+                    else (el as IdempotentConsumerStep).idempotentConsumer.steps = CamelApi.addStep(idempotentConsumerChildren, step, parentId, position);
                     break;
             }
             result.push(el);
@@ -1040,6 +1043,105 @@ export class CamelApi {
         return result
     }
 
+    static findStep = (steps: ProcessorStep[] | undefined, uuid: string, parentUuid?: string, result?: ProcessorStepMeta): ProcessorStepMeta => {
+        if (result?.step !== undefined) return result;
+        if (steps !== undefined){
+            for (let index = 0, step; step = steps[index]; index++) {
+                if (step.uuid !== uuid) {
+                    switch (step.dslName) {
+                        case 'policyStep':
+                            result = CamelApi.findStep((step as PolicyStep).policy.steps, uuid, step.uuid, result);
+                            break;
+                        case 'choiceStep':
+                            const o = (step as ChoiceStep).choice.otherwise;
+                            const w = (step as ChoiceStep).choice.when;
+                            const s: ProcessorStep[] = [];
+                            if (o) s.push(o);
+                            if (w) s.push(...w);
+                            result = CamelApi.findStep(s, uuid, step.uuid, result);
+                            break;
+                        case 'otherwise':
+                            result = CamelApi.findStep((step as Otherwise).steps, uuid, step.uuid, result);
+                            break;
+                        case 'fromStep':
+                            result = CamelApi.findStep((step as FromStep).from.steps, uuid, step.uuid, result);
+                            break;
+                        case 'onCompletionStep':
+                            result = CamelApi.findStep((step as OnCompletionStep).onCompletion.steps, uuid, step.uuid, result);
+                            break;
+                        case 'splitStep':
+                            result = CamelApi.findStep((step as SplitStep).split.steps, uuid, step.uuid, result);
+                            break;
+                        case 'transactedStep':
+                            result = CamelApi.findStep((step as TransactedStep).transacted.steps, uuid, step.uuid, result);
+                            break;
+                        case 'interceptFromStep':
+                            result = CamelApi.findStep((step as InterceptFromStep).interceptFrom.steps, uuid, step.uuid, result);
+                            break;
+                        case 'doCatchStep':
+                            result = CamelApi.findStep((step as DoCatchStep).doCatch.steps, uuid, step.uuid, result);
+                            break;
+                        case 'circuitBreakerStep':
+                            result = CamelApi.findStep((step as CircuitBreakerStep).circuitBreaker.steps, uuid, step.uuid, result);
+                            break;
+                        case 'interceptStep':
+                            result = CamelApi.findStep((step as InterceptStep).intercept.steps, uuid, step.uuid, result);
+                            break;
+                        case 'onFallbackStep':
+                            result = CamelApi.findStep((step as OnFallbackStep).onFallback.steps, uuid, step.uuid, result);
+                            break;
+                        case 'multicastStep':
+                            result = CamelApi.findStep((step as MulticastStep).multicast.steps, uuid, step.uuid, result);
+                            break;
+                        case 'loadBalanceStep':
+                            result = CamelApi.findStep((step as LoadBalanceStep).loadBalance.steps, uuid, step.uuid, result);
+                            break;
+                        case 'whenSkipSendToEndpointStep':
+                            result = CamelApi.findStep((step as WhenSkipSendToEndpointStep).whenSkipSendToEndpoint.steps, uuid, step.uuid, result);
+                            break;
+                        case 'loopStep':
+                            result = CamelApi.findStep((step as LoopStep).loop.steps, uuid, step.uuid, result);
+                            break;
+                        case 'interceptSendToEndpointStep':
+                            result = CamelApi.findStep((step as InterceptSendToEndpointStep).interceptSendToEndpoint.steps, uuid, step.uuid, result);
+                            break;
+                        case 'doTryStep':
+                            result = CamelApi.findStep((step as DoTryStep).doTry.steps, uuid, step.uuid, result);
+                            break;
+                        case 'resequenceStep':
+                            result = CamelApi.findStep((step as ResequenceStep).resequence.steps, uuid, step.uuid, result);
+                            break;
+                        case 'pipelineStep':
+                            result = CamelApi.findStep((step as PipelineStep).pipeline.steps, uuid, step.uuid, result);
+                            break;
+                        case 'sagaStep':
+                            result = CamelApi.findStep((step as SagaStep).saga.steps, uuid, step.uuid, result);
+                            break;
+                        case 'when':
+                            result = CamelApi.findStep((step as When).steps, uuid, step.uuid, result);
+                            break;
+                        case 'doFinallyStep':
+                            result = CamelApi.findStep((step as DoFinallyStep).doFinally.steps, uuid, step.uuid, result);
+                            break;
+                        case 'filterStep':
+                            result = CamelApi.findStep((step as FilterStep).filter.steps, uuid, step.uuid, result);
+                            break;
+                        case 'aggregateStep':
+                            result = CamelApi.findStep((step as AggregateStep).aggregate.steps, uuid, step.uuid, result);
+                            break;
+                        case 'idempotentConsumerStep':
+                            result = CamelApi.findStep((step as IdempotentConsumerStep).idempotentConsumer.steps, uuid, step.uuid, result);
+                            break;
+                    }
+                } else {
+                    result = new  ProcessorStepMeta(step, parentUuid, index);
+                    break;
+                }
+            }
+        }
+        return new ProcessorStepMeta(result?.step, result?.parentUuid, result?.position);
+    }
+
     static getExpressionLanguage = (init?: Partial<Expression>): string | undefined => {
         if (init?.constant) return 'constant'
         if (init?.csimple) return 'csimple'
@@ -1062,5 +1164,4 @@ export class CamelApi {
         if (init?.xtokenize) return 'xtokenize'
         return undefined;
     }
-}
-
+}
\ No newline at end of file
diff --git a/karavan-designer/src/designer/api/CamelApiExt.tsx b/karavan-designer/src/designer/api/CamelApiExt.tsx
index e97dbb9..d0bf432 100644
--- a/karavan-designer/src/designer/api/CamelApiExt.tsx
+++ b/karavan-designer/src/designer/api/CamelApiExt.tsx
@@ -21,16 +21,38 @@ import {ComponentApi} from "./ComponentApi";
 
 export class CamelApiExt {
 
-    static addStepToIntegration = (integration: Integration, step: CamelElement, parentId: string): Integration => {
+    static addStepToIntegration = (integration: Integration, step: CamelElement, parentId: string, position?: number): Integration => {
         if (step.dslName === 'fromStep') {
             integration.spec.flows.push(step as FromStep);
         } else {
-            const flows = CamelApi.addStep(integration.spec.flows, step, parentId);
+            const flows = CamelApi.addStep(integration.spec.flows, step, parentId, position);
             integration.spec.flows = flows as FromStep[];
         }
         return integration;
     }
 
+    static moveElement = (integration: Integration, source: string, target: string) => {
+        const sourceFindStep = CamelApi.findStep(integration.spec.flows, source, undefined);
+        const sourceStep = sourceFindStep.step;
+        const sourceUuid = sourceStep?.uuid;
+        const targetFindStep = CamelApi.findStep(integration.spec.flows, target, undefined);
+        const parentUuid = targetFindStep.parentUuid;
+        if (sourceUuid && parentUuid) {
+            CamelApiExt.deleteStepFromIntegration(integration, sourceUuid);
+            switch (targetFindStep.step?.dslName) {
+                case 'when':
+                    CamelApiExt.addStepToIntegration(integration, sourceStep, targetFindStep.step?.uuid, undefined);
+                    break;
+                case 'otherwise':
+                    CamelApiExt.addStepToIntegration(integration, sourceStep, targetFindStep.step?.uuid, undefined);
+                    break;
+                default:
+                    CamelApiExt.addStepToIntegration(integration, sourceStep, parentUuid, targetFindStep.position);
+                    break;
+            }
+        }
+    }
+
     static deleteStepFromIntegration = (integration: Integration, uuidToDelete: string): Integration => {
         const flows = CamelApi.deleteStep(integration.spec.flows, uuidToDelete);
         integration.spec.flows = flows as FromStep[];
@@ -96,7 +118,7 @@ export class CamelApiExt {
         if (name) {
             CamelMetadataApi.getElementMeta(name)?.properties
                 .filter(p => p.name !== 'steps' && p.name !== 'inheritErrorHandler')
-                .filter(p => (name == 'to' && p.name !== 'pattern') || name !='to')
+                .filter(p => (name == 'to' && p.name !== 'pattern') || name != 'to')
                 .filter(p => !p.isObject || (p.isObject && p.name === 'expression'))
                 .forEach(p => {
                     switch (p.name) {
@@ -121,7 +143,7 @@ export class CamelApiExt {
     }
 
     static getParametersValue = (element: CamelElement | undefined, propertyName: string, pathParameter?: boolean): any => {
-        if (pathParameter){
+        if (pathParameter) {
             const uri = (element as any).uri;
             return ComponentApi.getPathParameterValue(uri, propertyName);
         } else {
@@ -160,7 +182,7 @@ export class CamelApiExt {
 
     static getStepsFromSteps = (steps: CamelElement[], level: number, parallel: boolean): [CamelElement, number][] => {
         const result: [CamelElement, number][] = [];
-        steps.forEach((step,index) => {
+        steps.forEach((step, index) => {
             const steps = CamelApiExt.getOutgoingStepsFromStep(step, level + (parallel ? 1 : index));
             result.push(...steps);
         })
diff --git a/karavan-designer/src/designer/model/CamelModel.tsx b/karavan-designer/src/designer/model/CamelModel.tsx
index 4372750..f4d8dd7 100644
--- a/karavan-designer/src/designer/model/CamelModel.tsx
+++ b/karavan-designer/src/designer/model/CamelModel.tsx
@@ -52,6 +52,20 @@ export class CamelElement {
 
 export class ProcessorStep extends CamelElement {
 }
+
+export class ProcessorStepMeta {
+    step?: ProcessorStep
+    parentUuid?: string
+    position: number = 0;
+
+
+    constructor(step?: ProcessorStep, parentUuid?: string, position?: number) {
+        this.step = step;
+        this.parentUuid = parentUuid;
+        this.position = position || 0;
+    }
+}
+
 export class Policy extends CamelElement { 
     inheritErrorHandler?: boolean
     ref?: string
diff --git a/karavan-designer/src/designer/ui/DslElement.tsx b/karavan-designer/src/designer/ui/DslElement.tsx
index 4080083..1f33e66 100644
--- a/karavan-designer/src/designer/ui/DslElement.tsx
+++ b/karavan-designer/src/designer/ui/DslElement.tsx
@@ -31,6 +31,7 @@ interface Props {
     deleteElement: any
     selectElement: any
     openSelector: any
+    moveElement: (source: string, target: string) => void
     selectedUuid: string
     borderColor: string
     borderColorSelected: string
@@ -42,6 +43,8 @@ interface State {
     showSelector: boolean
     tabIndex: string | number
     selectedUuid: string
+    isDragging: boolean
+    isDraggedOver: boolean
 }
 
 export class DslElement extends React.Component<Props, State> {
@@ -51,7 +54,9 @@ export class DslElement extends React.Component<Props, State> {
         element: this.props.step.dslName === 'otherwise' ? this.props.step : CamelApi.elementFromStep(this.props.step),
         showSelector: false,
         tabIndex: 0,
-        selectedUuid: this.props.selectedUuid
+        selectedUuid: this.props.selectedUuid,
+        isDragging: false,
+        isDraggedOver: false
     };
 
     componentDidUpdate = (prevProps: Readonly<Props>, prevState: Readonly<State>, snapshot?: any) => {
@@ -62,7 +67,7 @@ export class DslElement extends React.Component<Props, State> {
 
     openSelector = (evt: React.MouseEvent) => {
         evt.stopPropagation();
-        this.props.openSelector.call(this, this.state.step.uuid, this.state.element.dslName)
+        this.props.openSelector.call(this, this.state.step.uuid, this.state.element.dslName);
     }
 
     closeDslSelector = () => {
@@ -87,6 +92,11 @@ export class DslElement extends React.Component<Props, State> {
         return (this.state.element as any).steps
     }
 
+    hasSteps = (): boolean => {
+        const steps = this.getSteps();
+        return steps !== undefined && steps.length > 0;
+    }
+
     getWhens = (): When[] => {
         return (this.state.element as any).when
     }
@@ -154,7 +164,10 @@ export class DslElement extends React.Component<Props, State> {
 
     getElementHeader = () => {
         const tooltip = this.getHeaderTooltip();
-        return tooltip === undefined ? this.getHeader() : this.getHeaderWithTooltip(tooltip);
+        if (tooltip !== undefined && !this.state.isDragging) {
+            return this.getHeaderWithTooltip(tooltip);
+        }
+        return this.getHeader();
     }
 
     render() {
@@ -164,13 +177,54 @@ export class DslElement extends React.Component<Props, State> {
                     ? "step-element step-element-with-steps"
                     : "step-element step-element-without-steps"}
                  style={{
-                     borderStyle: this.isSelected() ? "dashed" : "dotted",
+                     borderStyle: this.isSelected() ? "dashed" : (this.hasSteps() ? "dotted" : "none"),
                      borderColor: this.isSelected() ? this.props.borderColorSelected : this.props.borderColor,
                      marginTop: this.isRoot() ? "16px" : "",
-                     zIndex: this.state.step.dslName === 'toStep' ? 20 : 10
+                     zIndex: this.state.step.dslName === 'toStep' ? 20 : 10,
+                     boxShadow: this.state.isDraggedOver ? "0px 0px 1px 2px " + this.props.borderColor : "none",
                  }}
                  onClick={event => this.selectElement(event)}
+                 onDragStart={event => {
+                     event.stopPropagation();
+                     event.dataTransfer.setData("text/plain", this.state.step.uuid);
+                     (event.target as any).style.opacity = .5;
+                     this.setState({isDragging: true});
+                 }}
+                 onDragEnd={event => {
+                     (event.target as any).style.opacity = '';
+                     this.setState({isDragging: false});
+                 }}
+                 onDragOver={event => {
+                     event.preventDefault();
+                     event.stopPropagation();
+                     if (this.state.element.dslName !== 'from' && !this.state.isDragging) {
+                         this.setState({isDraggedOver: true});
+                     }
+                 }}
+                 onDragEnter={event => {
+                     event.preventDefault();
+                     event.stopPropagation();
+                     if (this.state.element.dslName !== 'from') {
+                         this.setState({isDraggedOver: true});
+                     }
+                 }}
+                 onDragLeave={event => {
+                     event.preventDefault();
+                     event.stopPropagation();
+                     this.setState({isDraggedOver: false});
 
+                 }}
+                 onDrop={event => {
+                     event.preventDefault();
+                     event.stopPropagation();
+                     this.setState({isDraggedOver: false});
+                     const sourceUuid = event.dataTransfer.getData("text/plain");
+                     const targetUuid = this.state.step.uuid;
+                     if (sourceUuid !== targetUuid) {
+                         this.props.moveElement?.call(this, sourceUuid, targetUuid);
+                     }
+                 }}
+                 draggable={!['from', 'when', 'otherwise'].includes(this.state.element.dslName)}
             >
                 {this.getElementHeader()}
                 {this.state.element.hasSteps() && !this.horizontal() && this.getArrow()}
@@ -185,6 +239,7 @@ export class DslElement extends React.Component<Props, State> {
                                     openSelector={this.props.openSelector}
                                     deleteElement={this.props.deleteElement}
                                     selectElement={this.props.selectElement}
+                                    moveElement={this.props.moveElement}
                                     selectedUuid={this.state.selectedUuid}
                                     borderColor={this.props.borderColor}
                                     borderColorSelected={this.props.borderColorSelected}
@@ -212,7 +267,8 @@ export class DslElement extends React.Component<Props, State> {
                     </Tooltip>
                     }
                     {this.state.element.dslName === 'choice' &&
-                    <div className={this.getWhens().length > 0 ? "whens" : ""} style={this.horizontal() ? {display: "flex", flexDirection: "row"} : {}}>
+                    <div className={this.getWhens().length > 0 ? "whens" : ""}
+                         style={this.horizontal() ? {display: "flex", flexDirection: "row"} : {}}>
                         {this.getWhens().map((when, index) => (
                             <div key={when.uuid} style={{marginLeft: (index !== 0) ? "6px" : "0"}}>
                                 {this.getArrow()}
@@ -220,6 +276,7 @@ export class DslElement extends React.Component<Props, State> {
                                     openSelector={this.props.openSelector}
                                     deleteElement={this.props.deleteElement}
                                     selectElement={this.props.selectElement}
+                                    moveElement={this.props.moveElement}
                                     selectedUuid={this.state.selectedUuid}
                                     borderColor={this.props.borderColor}
                                     borderColorSelected={this.props.borderColorSelected}
@@ -234,6 +291,7 @@ export class DslElement extends React.Component<Props, State> {
                                 openSelector={this.props.openSelector}
                                 deleteElement={this.props.deleteElement}
                                 selectElement={this.props.selectElement}
+                                moveElement={this.props.moveElement}
                                 selectedUuid={this.state.selectedUuid}
                                 borderColor={this.props.borderColor}
                                 borderColorSelected={this.props.borderColorSelected}
diff --git a/karavan-designer/src/designer/ui/KaravanDesigner.tsx b/karavan-designer/src/designer/ui/KaravanDesigner.tsx
index 0f594ee..3541482 100644
--- a/karavan-designer/src/designer/ui/KaravanDesigner.tsx
+++ b/karavan-designer/src/designer/ui/KaravanDesigner.tsx
@@ -125,7 +125,6 @@ export class KaravanDesigner extends React.Component<Props, State> {
     }
 
     onDslSelect = (dsl: DslMetaModel, parentId: string) => {
-        console.log(dsl)
         switch (dsl.dsl) {
             case 'from' :
                 const from = CamelApi.createStep(dsl.dsl, {from: {uri: dsl.uri}});
@@ -164,7 +163,11 @@ export class KaravanDesigner extends React.Component<Props, State> {
 
     onIntegrationUpdate = (i: Integration) => {
         this.setState({integration: i, showSelector: false, key: Math.random().toString()});
-    };
+    }
+
+    moveElement = (source: string, target: string) => {
+        CamelApiExt.moveElement(this.state.integration, source, target);
+    }
 
     render() {
         return (
@@ -184,6 +187,7 @@ export class KaravanDesigner extends React.Component<Props, State> {
                                         openSelector={this.openSelector}
                                         deleteElement={this.deleteElement}
                                         selectElement={this.selectElement}
+                                        moveElement={this.moveElement}
                                         selectedUuid={this.state.selectedUuid}
                                         borderColor={this.props.borderColor}
                                         borderColorSelected={this.props.borderColorSelected}
diff --git a/karavan-generator/src/main/java/org/apache/camel/karavan/generator/CamelModelGenerator.java b/karavan-generator/src/main/java/org/apache/camel/karavan/generator/CamelModelGenerator.java
index 2b52154..825047e 100644
--- a/karavan-generator/src/main/java/org/apache/camel/karavan/generator/CamelModelGenerator.java
+++ b/karavan-generator/src/main/java/org/apache/camel/karavan/generator/CamelModelGenerator.java
@@ -113,9 +113,10 @@ public final class CamelModelGenerator {
                 "/**\n" +
                         " * Generated by karavan build tools - do NOT edit this file!\n" +
                         " */\n");
-        camelApi.append("import {");
+        camelApi.append("import {\n");
         camelApi.append("    CamelElement, \n");
         camelApi.append("    ProcessorStep, \n");
+        camelApi.append("    ProcessorStepMeta, \n");
         camelApi.append("    FromStep, \n");
         camelApi.append("    Expression, \n");
         processors.values().forEach(s -> {
@@ -183,11 +184,11 @@ public final class CamelModelGenerator {
         camelApi.append(
                 "            default : return new CamelElement('')\n" +
                         "        }\n" +
-                        "    }\n");
+                        "    }\n\n");
 
         // addStep functions
         camelApi.append(
-                "    static addStep = (steps: ProcessorStep[], step: ProcessorStep, parentId: string): ProcessorStep[] => {\n" +
+                "    static addStep = (steps: ProcessorStep[], step: ProcessorStep, parentId: string, position?: number): ProcessorStep[] => {\n" +
                         "        const result: ProcessorStep[] = [];\n" +
                         "        steps.forEach(el => {\n" +
                         "            switch (el.dslName) {\n" );
@@ -206,8 +207,8 @@ public final class CamelModelGenerator {
                 camelApi.append(String.format(
                         "                case '%1$s':\n" +
                                 "                    const %3$sChildren = (el as %2$s).%3$s?.steps || [];\n" +
-                                "                    if (el.uuid === parentId) %3$sChildren.push(step)\n" +
-                                "                    else (el as %2$s).%3$s.steps = CamelApi.addStep(%3$sChildren, step, parentId);\n" +
+                                "                    if (el.uuid === parentId) position !== undefined ? %3$sChildren.splice(position, 0, step) : %3$sChildren.push(step);\n" +
+                                "                    else (el as %2$s).%3$s.steps = CamelApi.addStep(%3$sChildren, step, parentId, position);\n" +
                                 "                    break;\n",
                         stepField, stepClass, name));
             }
@@ -262,6 +263,30 @@ public final class CamelModelGenerator {
                         "    }\n\n");
         camelApi.append(getTemplateFile("CamelApi.deleteWhen.tx").concat("\n\n"));
 
+
+        // findStep functions
+        camelApi.append(getTemplateFile("CamelApi.findStep.header.tx").concat("\n"));
+        models.entrySet().forEach(s -> {
+            String name = deCapitalize(s.getKey());
+            String stepClass = capitalize(s.getKey()).concat("Step");
+            String stepField = deCapitalize(s.getKey()).concat("Step");
+
+            if (name.equals("choice")){
+                camelApi.append(getTemplateFile("CamelApi.findStep.choiceStep.tx").concat("\n"));
+            } else if (name.equals("otherwise")){
+                camelApi.append(getTemplateFile("CamelApi.findStep.otherwise.tx").concat("\n"));
+            } else if (name.equals("when")){
+                camelApi.append(getTemplateFile("CamelApi.findStep.when.tx").concat("\n"));
+            } else if (s.getValue().stream().filter(e -> e.name.equals("steps")).count() > 0) {
+                camelApi.append(String.format(
+                        "                        case '%1$s':\n" +
+                                "                            result = CamelApi.findStep((step as %2$s).%3$s.steps, uuid, step.uuid, result);\n" +
+                                "                            break;\n",
+                        stepField, stepClass, name));
+            }
+        });
+        camelApi.append(getTemplateFile("CamelApi.findStep.footer.tx").concat("\n\n"));
+
         // Expression language finder
         camelApi.append("    static getExpressionLanguage = (init?: Partial<Expression>): string | undefined => {\n");
         models.get("expression").forEach(el -> {
diff --git a/karavan-generator/src/main/resources/CamelApi.addStep.choiceStep.tx b/karavan-generator/src/main/resources/CamelApi.addStep.choiceStep.tx
index e10f484..0c5c408 100644
--- a/karavan-generator/src/main/resources/CamelApi.addStep.choiceStep.tx
+++ b/karavan-generator/src/main/resources/CamelApi.addStep.choiceStep.tx
@@ -6,14 +6,14 @@
                     }  else if (el.uuid === parentId && step.dslName === 'otherwise' && !(el as ChoiceStep).choice.otherwise) {
                         (el as ChoiceStep).choice.otherwise = step;
                     } else {
-                        (el as ChoiceStep).choice.when = CamelApi.addStep(choiceChildren, step, parentId) as When[];
+                        (el as ChoiceStep).choice.when = CamelApi.addStep(choiceChildren, step, parentId, position) as When[];
                         const otherwise = (el as ChoiceStep).choice.otherwise;
                         if (otherwise?.uuid === parentId){
                             otherwise.steps = otherwise.steps ? [...otherwise.steps] : [];
                             otherwise.steps.push(step);
                             (el as ChoiceStep).choice.otherwise = otherwise
                         } else if (otherwise && otherwise.steps && otherwise.steps.length > 0){
-                            otherwise.steps = CamelApi.addStep(otherwise.steps, step, parentId);
+                            otherwise.steps = CamelApi.addStep(otherwise.steps, step, parentId, position);
                             (el as ChoiceStep).choice.otherwise = otherwise;
                         }
                     }
diff --git a/karavan-generator/src/main/resources/CamelApi.addStep.otherwise.tx b/karavan-generator/src/main/resources/CamelApi.addStep.otherwise.tx
index 01592bd..822a84f 100644
--- a/karavan-generator/src/main/resources/CamelApi.addStep.otherwise.tx
+++ b/karavan-generator/src/main/resources/CamelApi.addStep.otherwise.tx
@@ -1,5 +1,5 @@
                 case 'otherwise':
                     const otherwiseChildren = (el as Otherwise).steps || [];
-                    if (el.uuid === parentId) otherwiseChildren.push(step)
-                    else (el as Otherwise).steps = CamelApi.addStep(otherwiseChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? otherwiseChildren.splice(position, 0, step) : otherwiseChildren.push(step);
+                    else (el as Otherwise).steps = CamelApi.addStep(otherwiseChildren, step, parentId, position);
                     break;
diff --git a/karavan-generator/src/main/resources/CamelApi.addStep.when.tx b/karavan-generator/src/main/resources/CamelApi.addStep.when.tx
index 69b6907..d3e248c 100644
--- a/karavan-generator/src/main/resources/CamelApi.addStep.when.tx
+++ b/karavan-generator/src/main/resources/CamelApi.addStep.when.tx
@@ -1,5 +1,5 @@
                 case 'when':
                     const whenChildren = (el as When).steps || [];
-                    if (el.uuid === parentId) whenChildren.push(step)
-                    else (el as When).steps = CamelApi.addStep(whenChildren, step, parentId);
+                    if (el.uuid === parentId) position !== undefined ? whenChildren.splice(position, 0, step) : whenChildren.push(step);
+                    else (el as When).steps = CamelApi.addStep(whenChildren, step, parentId, position);
                     break;
diff --git a/karavan-generator/src/main/resources/CamelApi.findStep.choiceStep.tx b/karavan-generator/src/main/resources/CamelApi.findStep.choiceStep.tx
new file mode 100644
index 0000000..1d3733b
--- /dev/null
+++ b/karavan-generator/src/main/resources/CamelApi.findStep.choiceStep.tx
@@ -0,0 +1,8 @@
+                        case 'choiceStep':
+                            const o = (step as ChoiceStep).choice.otherwise;
+                            const w = (step as ChoiceStep).choice.when;
+                            const s: ProcessorStep[] = [];
+                            if (o) s.push(o);
+                            if (w) s.push(...w);
+                            result = CamelApi.findStep(s, uuid, step.uuid, result);
+                            break;
\ No newline at end of file
diff --git a/karavan-generator/src/main/resources/CamelApi.findStep.footer.tx b/karavan-generator/src/main/resources/CamelApi.findStep.footer.tx
new file mode 100644
index 0000000..ab5a672
--- /dev/null
+++ b/karavan-generator/src/main/resources/CamelApi.findStep.footer.tx
@@ -0,0 +1,9 @@
+                    }
+                } else {
+                    result = new  ProcessorStepMeta(step, parentUuid, index);
+                    break;
+                }
+            }
+        }
+        return new ProcessorStepMeta(result?.step, result?.parentUuid, result?.position);
+    }
\ No newline at end of file
diff --git a/karavan-generator/src/main/resources/CamelApi.findStep.header.tx b/karavan-generator/src/main/resources/CamelApi.findStep.header.tx
new file mode 100644
index 0000000..10694a8
--- /dev/null
+++ b/karavan-generator/src/main/resources/CamelApi.findStep.header.tx
@@ -0,0 +1,6 @@
+    static findStep = (steps: ProcessorStep[] | undefined, uuid: string, parentUuid?: string, result?: ProcessorStepMeta): ProcessorStepMeta => {
+        if (result?.step !== undefined) return result;
+        if (steps !== undefined){
+            for (let index = 0, step; step = steps[index]; index++) {
+                if (step.uuid !== uuid) {
+                    switch (step.dslName) {
\ No newline at end of file
diff --git a/karavan-generator/src/main/resources/CamelApi.findStep.otherwise.tx b/karavan-generator/src/main/resources/CamelApi.findStep.otherwise.tx
new file mode 100644
index 0000000..f93bf05
--- /dev/null
+++ b/karavan-generator/src/main/resources/CamelApi.findStep.otherwise.tx
@@ -0,0 +1,3 @@
+                        case 'otherwise':
+                            result = CamelApi.findStep((step as Otherwise).steps, uuid, step.uuid, result);
+                            break;
\ No newline at end of file
diff --git a/karavan-generator/src/main/resources/CamelApi.findStep.when.tx b/karavan-generator/src/main/resources/CamelApi.findStep.when.tx
new file mode 100644
index 0000000..34d6508
--- /dev/null
+++ b/karavan-generator/src/main/resources/CamelApi.findStep.when.tx
@@ -0,0 +1,3 @@
+                        case 'when':
+                            result = CamelApi.findStep((step as When).steps, uuid, step.uuid, result);
+                            break;
\ No newline at end of file
diff --git a/karavan-generator/src/main/resources/camel-model.template b/karavan-generator/src/main/resources/camel-model.template
index aaf49f5..dde3167 100644
--- a/karavan-generator/src/main/resources/camel-model.template
+++ b/karavan-generator/src/main/resources/camel-model.template
@@ -52,3 +52,17 @@ export class CamelElement {
 
 export class ProcessorStep extends CamelElement {
 }
+
+export class ProcessorStepMeta {
+    step?: ProcessorStep
+    parentUuid?: string
+    position: number = 0;
+
+
+    constructor(step?: ProcessorStep, parentUuid?: string, position?: number) {
+        this.step = step;
+        this.parentUuid = parentUuid;
+        this.position = position || 0;
+    }
+}
+