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 2022/03/18 18:29:16 UTC

[camel-karavan] branch main updated: Drag drop issue (#221)

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 74b3713  Drag drop issue (#221)
74b3713 is described below

commit 74b3713ea97fc1071872cb8c688a523f255c88e6
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Mar 18 14:26:26 2022 -0400

    Drag drop issue (#221)
    
    * Useless backward removed
    
    * Useless backward removed
    
    * Fix drag drop
---
 karavan-core/src/core/api/CamelDefinitionApiExt.ts |   5 +-
 karavan-core/src/core/api/CamelDefinitionYaml.ts   |  39 +--
 karavan-core/test/backward.spec.ts                 |  75 ------
 karavan-core/test/backward.yaml                    |  47 ----
 karavan-core/test/backward2.yaml                   |  32 ---
 karavan-core/test/expression.spec.ts               |   4 +-
 karavan-core/test/traits.spec.ts                   |   2 +-
 karavan-designer/src/App.tsx                       | 269 ++++++++++-----------
 karavan-designer/src/designer/KaravanDesigner.tsx  |   6 +-
 karavan-designer/src/designer/karavan.css          |   7 -
 karavan-vscode/src/extension.ts                    |   4 -
 karavan-vscode/webview/App.tsx                     |   7 -
 12 files changed, 141 insertions(+), 356 deletions(-)

diff --git a/karavan-core/src/core/api/CamelDefinitionApiExt.ts b/karavan-core/src/core/api/CamelDefinitionApiExt.ts
index 9d16f2f..535430e 100644
--- a/karavan-core/src/core/api/CamelDefinitionApiExt.ts
+++ b/karavan-core/src/core/api/CamelDefinitionApiExt.ts
@@ -55,7 +55,7 @@ export class CamelDefinitionApiExt {
         return integration;
     }
 
-    static addStepToStep = (step: CamelElement, stepAdded: CamelElement, parentId: string, position?: number): CamelElement => {
+    static addStepToStep = (step: CamelElement, stepAdded: CamelElement, parentId: string, position: number = -1): CamelElement => {
         const result = CamelUtil.cloneStep(step);
         const children = CamelDefinitionApiExt.getElementChildrenDefinition(result.dslName);
         let added = false;
@@ -76,7 +76,8 @@ export class CamelDefinitionApiExt {
         // Then steps
         const steps = children.filter(child => child.name === 'steps');
         if (!added && steps && result.uuid === parentId) {
-            (result as any).steps.push(stepAdded);
+            if (position > -1) (result as any).steps.splice(position, 0, stepAdded);
+            else (result as any).steps.push(stepAdded);
         } else if (!added && steps && (result as any).steps) {
             (result as any).steps = CamelDefinitionApiExt.addStepToSteps((result as any).steps, stepAdded, parentId, position);
         }
diff --git a/karavan-core/src/core/api/CamelDefinitionYaml.ts b/karavan-core/src/core/api/CamelDefinitionYaml.ts
index 5547554..d48dd28 100644
--- a/karavan-core/src/core/api/CamelDefinitionYaml.ts
+++ b/karavan-core/src/core/api/CamelDefinitionYaml.ts
@@ -23,7 +23,7 @@ import {Trait, TraitApi} from "../model/TraitDefinition";
 
 export class CamelDefinitionYaml {
 
-    static integrationToYaml = (integration: Integration, backward: boolean = false): string => {
+    static integrationToYaml = (integration: Integration): string => {
         const clone: any = CamelUtil.cloneIntegration(integration);
         const flows = integration.spec.flows
         clone.spec.flows = flows?.map((f: any) => CamelDefinitionYaml.cleanupElement(f)).filter(x => Object.keys(x).length !== 0);
@@ -38,11 +38,11 @@ export class CamelDefinitionYaml {
         if (integration.crd) {
             delete clone.crd
             const i = JSON.parse(JSON.stringify(clone, null, 3)); // fix undefined in string attributes
-            const text = CamelDefinitionYaml.yamlDump(i, backward);
+            const text = CamelDefinitionYaml.yamlDump(i);
             return text;
         } else {
             const f = JSON.parse(JSON.stringify(clone.spec.flows, null, 3));
-            const text = CamelDefinitionYaml.yamlDump(f, backward);
+            const text = CamelDefinitionYaml.yamlDump(f);
             if (clone.spec.dependencies && clone.spec.dependencies.length > 0) {
                 const modeline = this.generateModeline(clone.spec.dependencies);
                 return modeline.concat('\n', text);
@@ -120,7 +120,7 @@ export class CamelDefinitionYaml {
         return result
     }
 
-    static yamlDump = (integration: Integration, backward: boolean = false): string => {
+    static yamlDump = (integration: Integration): string => {
         return yaml.dump(integration,
             {
                 noRefs: false,
@@ -135,21 +135,17 @@ export class CamelDefinitionYaml {
                     else if (a > b) return 1
                     else return 0;
                 },
-                replacer: (key, value) => this.replacer(key, value, backward)
+                replacer: (key, value) => this.replacer(key, value)
             });
     }
 
-    static replacer = (key: string, value: any, backward: boolean = false): any => {
+    static replacer = (key: string, value: any): any => {
         if (typeof value === 'object' && (value.hasOwnProperty('stepName') || value.hasOwnProperty('inArray')  || value.hasOwnProperty('inSteps'))) {
             const stepNameField = value.hasOwnProperty('stepName') ? 'stepName' : 'step-name';
             const stepName = value[stepNameField];
             const dslName = value.dslName;
             let newValue: any = JSON.parse(JSON.stringify(value));
             delete newValue.dslName;
-            if (backward && stepName === 'route'){
-                newValue.steps = newValue.from.steps;
-                delete newValue.from.steps;
-            }
             delete newValue[stepNameField];
             if ((value.inArray && !value.inSteps)
                 || dslName === 'ExpressionSubElementDefinition'
@@ -181,20 +177,20 @@ export class CamelDefinitionYaml {
         }
     }
 
-    static yamlToIntegration = (filename: string, text: string, backward: boolean = false): Integration => {
+    static yamlToIntegration = (filename: string, text: string): Integration => {
         const integration: Integration = Integration.createNew(filename);
         const fromYaml: any = yaml.load(text);
         const camelized: any = CamelUtil.camelizeObject(fromYaml);
         if (Array.isArray(camelized)) {
             integration.crd = false;
             const flows: any[] = camelized;
-            integration.spec.flows?.push(...this.flowsToCamelElements(flows, backward));
+            integration.spec.flows?.push(...this.flowsToCamelElements(flows));
             integration.spec.dependencies = this.modelineToDependency(text);
             // integration.spec.traits = this.traitsToCamelElements(flows); // TODO: Plain yaml Trait ???
         } else {
             integration.crd = true;
             const int: Integration = new Integration({...camelized});
-            integration.spec.flows?.push(...this.flowsToCamelElements(int.spec.flows || [], backward));
+            integration.spec.flows?.push(...this.flowsToCamelElements(int.spec.flows || []));
             integration.spec.dependencies = this.dependenciesToDependency(int.spec.dependencies);
             if (int.spec.traits) integration.spec.traits = TraitApi.traitsFromYaml(int.spec.traits);
         }
@@ -223,27 +219,14 @@ export class CamelDefinitionYaml {
         return result;
     }
 
-    static flowsToCamelElements = (flows: any[], backward: boolean = false): any[] => {
+    static flowsToCamelElements = (flows: any[]): any[] => {
         const result: any[] = [];
         flows.filter((e: any) => e.hasOwnProperty('restConfiguration'))
             .forEach((f: any) => result.push(CamelDefinitionYamlStep.readRestConfigurationDefinition(f.restConfiguration)));
         flows.filter((e: any) => e.hasOwnProperty('rest'))
             .forEach((f: any) => result.push(CamelDefinitionYamlStep.readRestDefinition(f.rest)));
         flows.filter((e: any) => e.hasOwnProperty('route'))
-            .forEach((f: any) => {
-                if (backward){
-                    const route = f.route;
-                    if (route.from.steps && Array.isArray(route.from.steps)){
-                        route.from.steps.push(...route.steps);
-                    } else {
-                        route.from.steps = [...route.steps];
-                    }
-                    delete route.steps;
-                    result.push(CamelDefinitionYamlStep.readRouteDefinition(route));
-                } else {
-                    result.push(CamelDefinitionYamlStep.readRouteDefinition(f.route));
-                }
-            });
+            .forEach((f: any) => result.push(CamelDefinitionYamlStep.readRouteDefinition(f.route)));
         flows.filter((e: any) => e.hasOwnProperty('from'))
             .forEach((f: any) =>  result.push(CamelDefinitionYamlStep.readRouteDefinition(new RouteDefinition({from: f.from}))));
         flows.filter((e: any) => e.hasOwnProperty('beans'))
diff --git a/karavan-core/test/backward.spec.ts b/karavan-core/test/backward.spec.ts
deleted file mode 100644
index 1d20fbd..0000000
--- a/karavan-core/test/backward.spec.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {expect} from 'chai';
-import * as fs from 'fs';
-import 'mocha';
-import {CamelDefinitionYaml} from "../src/core/api/CamelDefinitionYaml";
-import {
-    ChoiceDefinition,
-    ExpressionDefinition,
-    FromDefinition,
-    LogDefinition,
-    OtherwiseDefinition,
-    SimpleExpression,
-    ToDefinition,
-    WhenDefinition
-} from "../src/core/model/CamelDefinition";
-import { RouteDefinition} from "../src/core/model/CamelDefinition";
-import {Integration} from "../src/core/model/IntegrationDefinition";
-
-describe('Backward for Camel version < 3.16.x', () => {
-
-    it('Object -> YAML', () => {
-        const i1 = Integration.createNew("test")
-
-        const when1 = new WhenDefinition({
-            expression: new ExpressionDefinition({simple: new SimpleExpression({expression:'${body} != null'})}),
-            steps: [new LogDefinition({logName: 'log11', message: "hello11"})]
-        })
-        const when2 = new WhenDefinition({
-            expression: new ExpressionDefinition({simple: new SimpleExpression({expression:'${body} == null'})}),
-            steps: [new LogDefinition({logName: 'log22', message: "hello22"})]
-        })
-        const otherwise = new OtherwiseDefinition({steps: [new LogDefinition({logName: 'logX', message: "helloX"})]})
-        const choice = new ChoiceDefinition({when: [when1, when2], otherwise: otherwise})
-
-        const flow1 = new FromDefinition({uri: "direct1"});
-        flow1.steps?.push(choice);
-        flow1.steps?.push(new ToDefinition({uri: 'kamelet:kamelet2'}));
-        flow1.steps?.push(new ToDefinition({uri: 'kamelet:kamelet2'}));
-        flow1.parameters = {httpMethodRestrict: 'POST'}
-        i1.spec.flows?.push(new RouteDefinition({from: flow1}));
-
-        const flow2 = new FromDefinition({uri: "direct2"});
-        flow2.steps?.push(new LogDefinition({logName: 'log1', message: "hello1"}));
-        flow2.steps?.push(new LogDefinition({logName: 'log2', message: "hello2"}));
-
-        i1.spec.flows?.push(new RouteDefinition({from: flow2}));
-        const yaml1 = CamelDefinitionYaml.integrationToYaml(i1, true);
-        const yaml2 = fs.readFileSync('test/backward.yaml',{encoding:'utf8', flag:'r'});
-        console.log(yaml1)
-        expect(yaml1).to.equal(yaml2);
-    });
-
-    it('YAML -> Object', () => {
-        const yaml2 = fs.readFileSync('test/backward2.yaml',{encoding:'utf8', flag:'r'});
-        const i = CamelDefinitionYaml.yamlToIntegration("kafka2trinobatch.yaml", yaml2, true);
-        expect(i.spec.flows?.[0].from.steps.length).to.equal(2);
-    });
-
-
-});
\ No newline at end of file
diff --git a/karavan-core/test/backward.yaml b/karavan-core/test/backward.yaml
deleted file mode 100644
index 0426c19..0000000
--- a/karavan-core/test/backward.yaml
+++ /dev/null
@@ -1,47 +0,0 @@
-apiVersion: camel.apache.org/v1
-kind: Integration
-metadata:
-  name: test
-spec:
-  flows:
-    - route:
-        steps:
-          - choice:
-              when:
-                - expression:
-                    simple:
-                      expression: ${body} != null
-                  steps:
-                    - log:
-                        message: hello11
-                        logName: log11
-                - expression:
-                    simple:
-                      expression: ${body} == null
-                  steps:
-                    - log:
-                        message: hello22
-                        logName: log22
-              otherwise:
-                steps:
-                  - log:
-                      message: helloX
-                      logName: logX
-          - to:
-              uri: kamelet:kamelet2
-          - to:
-              uri: kamelet:kamelet2
-        from:
-          uri: direct1
-          parameters:
-            httpMethodRestrict: POST
-    - route:
-        steps:
-          - log:
-              message: hello1
-              logName: log1
-          - log:
-              message: hello2
-              logName: log2
-        from:
-          uri: direct2
diff --git a/karavan-core/test/backward2.yaml b/karavan-core/test/backward2.yaml
deleted file mode 100644
index 3da42fe..0000000
--- a/karavan-core/test/backward2.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-apiVersion: camel.apache.org/v1
-kind: Integration
-metadata:
-  name: kafka2trinobatch.yaml
-spec:
-  flows:
-    - route:
-        from:
-          uri: kafka:dynamic-pnc-logs
-        steps:
-          - log:
-              message: '"Processing ${body}'
-              loggingLevel: INFO
-          - aggregate:
-              steps:
-                - to:
-                    uri: >-
-                      sql:insert into iceberg.kafka.pnc_logs (message,
-                      timestamp) values (:#${body}, current_timestamp)
-                    parameters:
-                      batch: true
-                      useMessageBodyForSql: false
-              correlationExpression: {}
-              strategyRef: >-
-                #class:org.apache.camel.processor.aggregate.GroupedBodyAggregationStrategy
-              expression:
-                constant: {}
-              completionSize: 20
-              completionTimeout: '10000'
-  dependencies:
-    - mvn:io.trino:trino-jdbc:368
-    - mvn:org.apache.commons:commons-dbcp2:2.9.0
diff --git a/karavan-core/test/expression.spec.ts b/karavan-core/test/expression.spec.ts
index 04647e0..f310e7b 100644
--- a/karavan-core/test/expression.spec.ts
+++ b/karavan-core/test/expression.spec.ts
@@ -49,8 +49,8 @@ describe('Expression to yaml', () => {
         flow1.steps?.push(agg);
         i1.spec.flows?.push(new RouteDefinition({from: flow1}));
 
-        const yaml1 = CamelDefinitionYaml.integrationToYaml(i1, false);
-        console.log(yaml1)
+        const yaml1 = CamelDefinitionYaml.integrationToYaml(i1);
+        // console.log(yaml1)
     });
 
 });
\ No newline at end of file
diff --git a/karavan-core/test/traits.spec.ts b/karavan-core/test/traits.spec.ts
index 3b14b52..6cab79f 100644
--- a/karavan-core/test/traits.spec.ts
+++ b/karavan-core/test/traits.spec.ts
@@ -33,7 +33,7 @@ describe('Traits', () => {
         const yaml1 = CamelDefinitionYaml.integrationToYaml(i1);
         const yaml2 = fs.readFileSync('test/trait.yaml',{encoding:'utf8', flag:'r'});
         expect(yaml1).to.equal(yaml2);
-        console.log(yaml1)
+        // console.log(yaml1)
     });
 
     it('YAML to Trait', () => {
diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index bc92ad4..48a8e42 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -39,160 +39,136 @@ class App extends React.Component<Props, State> {
         yaml: 'apiVersion: camel.apache.org/v1\n' +
             'kind: Integration\n' +
             'metadata:\n' +
-            '  name: demo.yaml \n' +
+            '  name: postman.yaml\n' +
             'spec:\n' +
-            // '  dependencies:\n' +
-            // '    - "mvn:org.apache.commons:commons-dbcp2:2.9.0" \n' +
-            // '    - "mvn:org.postgresql:postgresql:42.2.14" \n' +
             '  flows:\n' +
+            '    - rest:\n' +
+            '        post:\n' +
+            '          - to: direct:post\n' +
+            '        path: /parcels\n' +
+            '        consumes: application/json\n' +
+            '        produces: application/json\n' +
             '    - route:\n' +
             '        from:\n' +
-            '          uri: kamelet:http-secured-source\n' +
+            '          uri: direct:post\n' +
             '          steps:\n' +
-            '            - saga:\n' +
+            '            - log:\n' +
+            '                message: \'Received: ${body}\'\n' +
+            '            - multicast:\n' +
             '                steps:\n' +
             '                  - kamelet:\n' +
-            '                      name: http-sink\n' +
+            '                      name: kafka-not-secured-sink\n' +
+            '                      parameters:\n' +
+            '                        topic: parcels\n' +
+            '                        bootstrapServers: localhost:9092\n' +
             '                  - kamelet:\n' +
-            '                      name: kafka-sink\n' +
-            '            - wireTap: {}\n' +
+            '                      name: postgresql-sink\n' +
+            '                      parameters:\n' +
+            '                        serverName: localhost\n' +
+            '                        serverPort: \'5432\'\n' +
+            '                        username: postgres\n' +
+            '                        password: postgres\n' +
+            '                        databaseName: demo\n' +
+            '                        query: >-\n' +
+            '                          INSERT INTO parcels (id,address) VALUES\n' +
+            '                          (:#id,:#address) ON CONFLICT (id)  DO NOTHING\n' +
+            '                aggregationStrategy: >-\n' +
+            '                  #class:org.apache.camel.processor.aggregate.UseOriginalAggregationStrategy\n' +
+            '                parallelProcessing: false\n' +
+            '                streaming: false\n' +
+            '        id: post\n' +
+            '    - route:\n' +
+            '        from:\n' +
+            '          uri: kamelet:jms-apache-artemis-source\n' +
+            '          steps:\n' +
             '            - to:\n' +
-            '                uri: seda\n' +
-            '        id: Main Route\n' +
-            // '    - route:\n' +
-            // '        from:\n' +
-            // '          uri: direct:completion\n' +
-            // '        id: Completion\n' +
-            // '    - route:\n' +
-            // '        from:\n' +
-            // '          uri: direct:compensation\n' +
-            // '        id: Compensation\n' +
-            // '    - route:\n' +
-            // '        from:\n' +
-            // '          uri: seda:demo\n' +
-            // '        id: seda\n' +
-            // '            - choice:\n' +
-            // '                when:\n' +
-            // '                  - expression:\n' +
-            // '                      simple:\n' +
-            // '                        expression: hello world\n' +
-            // '                    steps:\n' +
-            // '                      - to:\n' +
-            // '                          uri: direct:demo1\n' +
-            // '                  - expression:\n' +
-            // '                      simple:\n' +
-            // '                        expression: hello world\n' +
-            // '                    steps:\n' +
-            // '                      - to:\n' +
-            // '                          uri: direct:demo1\n' +
-            // '                  - expression:\n' +
-            // '                      simple:\n' +
-            // '                        expression: hello world\n' +
-            // '                    steps:\n' +
-            // '                      - to:\n' +
-            // '                          uri: direct:demo1\n' +
-            // '                  - expression:\n' +
-            // '                      simple:\n' +
-            // '                        expression: hello world\n' +
-            // '                    steps:\n' +
-            // '                      - wireTap:\n' +
-            // '                otherwise:\n' +
-            // '                  steps:\n' +
-            // '                    - to:\n' +
-            // '                        uri: direct:demo1\n' +
-            // '                    - to:\n' +
-            // '                        uri: direct\n' +
-            // '                    - kamelet:\n' +
-            // '                        name: insert-header-action\n' +
-            // '                    - kamelet:\n' +
-            // '                        name: http-sink\n' +
-            // '    - route:\n' +
-            // '       from:\n' +
-            // '         uri: direct:demo2\n' +
-            // '         steps:\n' +
-            // '           - saga: \n' +
-            // '               option:\n' +
-            // '                 - option-name: o1\n' +
-            // '                   expression:\n' +
-            // '                     simple: "${body}" \n' +
-            // '                 - option-name: o2\n' +
-            // '                   expression:\n' +
-            // '                     simple: "${body}" \n' +
-            // '           - do-try:\n' +
-            // '                steps:\n' +
-            // '                  - to: "direct:direct1"\n' +
-            // '                  - to: "direct:direct2"\n' +
-            // '                  - log: "log1"\n' +
-            // '                do-catch:\n' +
-            // '                  - exception:\n' +
-            // '                      - "java.io.FileNotFoundException"\n' +
-            // '                      - "java.io.IOException"\n' +
-            // '                    steps:\n' +
-            // '                      - log: "log1"\n' +
-            // '                      - kamelet: \n' +
-            // '                           name: kafka-sink \n' +
-            // '                  - exception:\n' +
-            // '                      - "java.io.FileNotFoundException"\n' +
-            // '                      - "java.io.IOException"\n' +
-            // '                    steps:\n' +
-            // '                      - log: "log1"\n' +
-            // '                      - kamelet: \n' +
-            // '                           name: http-sink \n' +
-            // '            - choice:\n' +
-            // '                when:\n' +
-            // '                  - simple: "hello world"\n' +
-            // '                    steps:\n' +
-            // '                      - log:\n' +
-            // '                           message: hello22s\n' +
-            // '                           logName: log22\n' +
-            // '                otherwise: {}\n'+
-            '    - restConfiguration:\n' +
-            '        component: "platform-http"\n' +
-            '        contextPath: "/base"  \n' +
-            '        port: 8081\n' +
-            '    - rest:\n' +
-            '        path: "/"\n' +
-            '        post:\n' +
-            '          - path: "/foo"\n' +
-            '            to: "direct:foo"\n' +
-            '            description: "POST demo service"\n' +
-            // '          - path: "/bar"\n' +
-            // '            to: "direct:bar"  \n' +
-            // '        get:\n' +
-            // '          - path: "/getFoo"\n' +
-            // '            to: "direct:foo"        \n' +
-            // '          - path: "/getBar"\n' +
-            // '            to: "direct:foo"    \n' +
-            // '    - rest:\n' +
-            // '        path: "/demo"\n' +
-            // '        description: "REST API to demonstrate Karavan feature"\n' +
-            // '        post:\n' +
-            // '          - path: "/foo"\n' +
-            // '            to: "direct:foo"\n' +
-            // '          - path: "/bar"\n' +
-            // '            to: "direct:bar"  \n' +
-            // '        get:\n' +
-            // '          - path: "/getFoo"\n' +
-            // '            to: "direct:foo"        \n' +
-            // '          - path: "/getBar"\n' +
-            // '            to: "direct:foo"    \n' +
-            // '    - from:\n' +
-            // '        uri: \'direct:foo\'\n' +
-            // '        steps:\n' +
-            // '          - log: \'${body}\'\n' +
-            // '          - log: \'${headers}\'\n' +
-            // '          - setBody:\n' +
-            // '              constant: "Hello world"  \n' +
-            // '    - beans:\n' +
-            // '      - name: datasource\n' +
-            // '        type: org.apache.commons.dbcp2.BasicDataSource\n' +
-            // '        properties:\n' +
-            // '          driverClassName: org.postgresql.Driver\n' +
-            // '          password: postgres\n' +
-            // '          url: "jdbc:postgresql:localhost:5432:demo"\n' +
-            // '          username: postgres\n'+
-            // '      - name: myAggregatorStrategy \n' +
-            // '        type: org.apache.camel.processor.aggregate.UseLatestAggregationStrategy\n' +
+            '                uri: xj:identity\n' +
+            '                parameters:\n' +
+            '                  transformDirection: XML2JSON\n' +
+            '            - kamelet:\n' +
+            '                name: kafka-not-secured-sink\n' +
+            '                parameters:\n' +
+            '                  topic: payments\n' +
+            '                  bootstrapServers: localhost:9092\n' +
+            '          parameters:\n' +
+            '            destinationType: queue\n' +
+            '            destinationName: payments\n' +
+            '            brokerURL: tcp://localhost:61616\n' +
+            '        id: payment\n' +
+            '    - route:\n' +
+            '        from:\n' +
+            '          uri: kamelet:kafka-not-secured-source\n' +
+            '          steps:\n' +
+            '            - log:\n' +
+            '                message: \'Aggegating: ${body}\'\n' +
+            '            - unmarshal:\n' +
+            '                json:\n' +
+            '                  library: jackson\n' +
+            '            - aggregate:\n' +
+            '                steps:\n' +
+            '                  - choice:\n' +
+            '                      when:\n' +
+            '                        - expression:\n' +
+            '                            groovy:\n' +
+            '                              expression: >-\n' +
+            '                                body.find { it.containsKey(\'status\') }.status ==\n' +
+            '                                \'confirmed\'\n' +
+            '                          steps:\n' +
+            '                            - marshal:\n' +
+            '                                json:\n' +
+            '                                  library: jackson\n' +
+            '                            - log:\n' +
+            '                                message: \'Send to MQTT : ${body}\'\n' +
+            '                            - kamelet:\n' +
+            '                                name: mqtt-sink\n' +
+            '                                parameters:\n' +
+            '                                  topic: deliveries\n' +
+            '                                  brokerUrl: tcp://localhost:1883\n' +
+            '                      otherwise:\n' +
+            '                        steps:\n' +
+            '                          - setBody:\n' +
+            '                              expression:\n' +
+            '                                groovy:\n' +
+            '                                  expression: \'body.find { it.containsKey(\'\'status\'\') } \'\n' +
+            '                          - marshal:\n' +
+            '                              json:\n' +
+            '                                library: jackson\n' +
+            '                          - log:\n' +
+            '                              message: \'Send to database: ${body}\'\n' +
+            '                          - kamelet:\n' +
+            '                              name: postgresql-sink\n' +
+            '                              parameters:\n' +
+            '                                serverName: localhost\n' +
+            '                                serverPort: \'5432\'\n' +
+            '                                username: postgres\n' +
+            '                                password: postgres\n' +
+            '                                databaseName: demo\n' +
+            '                                query: >-\n' +
+            '                                  UPDATE parcels set status = \'CANCELED\' WHERE\n' +
+            '                                  id = :#id\n' +
+            '                aggregationStrategy: aggregator\n' +
+            '                completionSize: 2\n' +
+            '                correlationExpression:\n' +
+            '                  groovy:\n' +
+            '                    expression: body.get(\'id\')\n' +
+            '          parameters:\n' +
+            '            topic: parcels,payments\n' +
+            '            bootstrapServers: localhost:9092\n' +
+            '            autoCommitEnable: true\n' +
+            '            consumerGroup: postman\n' +
+            '        id: aggregator\n' +
+            '    - route:\n' +
+            '        from:\n' +
+            '          uri: kamelet:mqtt-source\n' +
+            '          steps:\n' +
+            '            - log:\n' +
+            '                message: \'Delivery: ${body}\'\n' +
+            '          parameters:\n' +
+            '            topic: deliveries\n' +
+            '            brokerUrl: tcp://localhost:1883\n' +
+            '    - beans:\n' +
+            '        - name: aggregator\n' +
+            '          type: org.apache.camel.processor.aggregate.GroupedBodyAggregationStrategy\n' +
             ''
     };
 
@@ -237,7 +213,7 @@ class App extends React.Component<Props, State> {
 
     save(filename: string, yaml: string) {
         // console.log(filename);
-        console.log(yaml);
+        // console.log(yaml);
     }
 
     public render() {
@@ -247,7 +223,6 @@ class App extends React.Component<Props, State> {
                                  onSave={(filename, yaml) => this.save(filename, yaml)}
                                  borderColor="#fb8824"
                                  borderColorSelected="#303284"
-                                 backward={true}
                                  dark={document.body.className.includes('vscode-dark')}
                 />
             </Page>
diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx b/karavan-designer/src/designer/KaravanDesigner.tsx
index e28766d..91ee15e 100644
--- a/karavan-designer/src/designer/KaravanDesigner.tsx
+++ b/karavan-designer/src/designer/KaravanDesigner.tsx
@@ -40,7 +40,6 @@ interface Props {
     borderColor: string
     borderColorSelected: string
     dark: boolean
-    backward?: boolean
 }
 
 interface State {
@@ -54,7 +53,7 @@ export class KaravanDesigner extends React.Component<Props, State> {
     public state: State = {
         tab: 'routes',
         integration: this.props.yaml
-            ? CamelDefinitionYaml.yamlToIntegration(this.props.filename, this.props.yaml, this.props.backward)
+            ? CamelDefinitionYaml.yamlToIntegration(this.props.filename, this.props.yaml)
             : Integration.createNew(this.props.filename),
         key: "",
     };
@@ -71,7 +70,7 @@ export class KaravanDesigner extends React.Component<Props, State> {
 
     getCode = (integration: Integration): string => {
         const clone = CamelUtil.cloneIntegration(integration);
-        return CamelDefinitionYaml.integrationToYaml(clone, this.props.backward);
+        return CamelDefinitionYaml.integrationToYaml(clone);
     }
 
     getTab(title: string, tooltip: string, icon: string) {
@@ -217,7 +216,6 @@ export class KaravanDesigner extends React.Component<Props, State> {
         const tab = this.state.tab;
         return (
             <PageSection className="page" isFilled padding={{default: 'noPadding'}}>
-                {this.props.backward && <Label className="backward" variant="outline" color="orange" isCompact={true} icon={<InfoCircleIcon/>}>Backward</Label>}
                 <Tabs className="main-tabs" activeKey={tab} onSelect={(event, tabIndex) => this.setState({tab: tabIndex.toString()})} style={{width: "100%"}}>
                     <Tab eventKey='routes' title={this.getTab("Routes", "Integration flows", "routes")}></Tab>
                     <Tab eventKey='rest' title={this.getTab("REST", "REST services", "rest")}></Tab>
diff --git a/karavan-designer/src/designer/karavan.css b/karavan-designer/src/designer/karavan.css
index 8997bf0..ae7bb67 100644
--- a/karavan-designer/src/designer/karavan.css
+++ b/karavan-designer/src/designer/karavan.css
@@ -22,13 +22,6 @@
     height: 36px;
 }
 
-.karavan .backward {
-    position: absolute;
-    top: 10px;
-    right: 10px;
-    z-index: 100;
-}
-
 .karavan .header-button {
     margin-left: var(--pf-c-page__header-tools--MarginRight);
 }
diff --git a/karavan-vscode/src/extension.ts b/karavan-vscode/src/extension.ts
index 7eee2d1..31460b9 100644
--- a/karavan-vscode/src/extension.ts
+++ b/karavan-vscode/src/extension.ts
@@ -147,10 +147,6 @@ function openKaravanWebView(context: vscode.ExtensionContext, webviewContent: st
 
 function sendData(context: vscode.ExtensionContext, panel: vscode.WebviewPanel, filename: string, relativePath: string, yaml?: string){
 
-    // Send backward compatibility
-    const backward = vscode.workspace.getConfiguration().get("camel.backward");
-    if (backward) panel.webview.postMessage({ command: 'backward' });
-
     // Read and send Kamelets
     console.log("Kamelets sent");
     panel.webview.postMessage({ command: 'kamelets', kamelets: readKamelets(context) });
diff --git a/karavan-vscode/webview/App.tsx b/karavan-vscode/webview/App.tsx
index 496d57b..0e381b6 100644
--- a/karavan-vscode/webview/App.tsx
+++ b/karavan-vscode/webview/App.tsx
@@ -32,7 +32,6 @@ interface State {
   relativePath: string
   yaml: string
   key: string
-  backward: boolean
   loaded: boolean
 }
 
@@ -43,7 +42,6 @@ class App extends React.Component<Props, State> {
     relativePath: '',
     yaml: '',
     key: '',
-    backward: false,
     loaded: false,
   };
 
@@ -62,10 +60,6 @@ class App extends React.Component<Props, State> {
     const message = event.data;
     console.log("Message received", message);
     switch (message.command) {
-      case 'backward':
-        console.log("backward", message);
-        this.setState({ backward: true });
-        break;
       case 'kamelets':
         console.log("Kamelets saving");
         KameletApi.saveKamelets(message.kamelets);
@@ -105,7 +99,6 @@ class App extends React.Component<Props, State> {
         {this.state.loaded &&
           <KaravanDesigner
             key={this.state.key}
-            backward={this.state.backward}
             filename={this.state.filename}
             yaml={this.state.yaml}
             onSave={(filename, yaml) => this.save(filename, yaml)}