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 7b921b7  Some improvements (#202)
7b921b7 is described below

commit 7b921b790b4dbd7f506e7cd91a749c4fe7b00ad3
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Fri Feb 25 18:37:57 2022 -0500

    Some improvements (#202)
    
    * Rest database example
    
    * Bean resign sync
    
    * Dependency design sync
    
    * Dependency design sync
    
    * Experiments
    
    * Remove MultiValueObjectField button
---
 karavan-core/src/core/api/CamelDefinitionApiExt.ts |   2 +-
 karavan-demo/integrations/README.MD                |   9 --
 .../integrations/{ => experiments}/Example.java    |   0
 .../{ => experiments}/docker-compose.yml           |  20 ---
 .../{ => experiments}/http-to-kafka.yaml           |   0
 .../integrations/{ => experiments}/postgres_db.sql |   0
 .../integrations/{ => experiments}/rest-dsl.yaml   |   0
 .../{ => experiments}/sql-to-log-int.yaml          |   0
 .../integrations/{ => experiments}/sql-to-log.yaml |   0
 .../integrations/{ => experiments}/xxx.groovy      |   0
 .../integrations/{ => experiments}/zzz-int.yaml    |   2 +-
 .../integrations/{ => experiments}/zzz.yaml        |   0
 karavan-demo/integrations/rest-database/README.MD  |  28 ++++
 .../integrations/rest-database/docker-compose.yml  |  27 ++++
 .../{ => rest-database}/postgres_db.sql            |   0
 .../integrations/rest-database/rest-database.yaml  |  51 +++++++
 karavan-demo/integrations/xxx.yaml                 |  12 ++
 karavan-designer/src/App.tsx                       |   6 +-
 karavan-designer/src/designer/KaravanDesigner.tsx  |   4 +-
 karavan-designer/src/designer/beans/BeanCard.tsx   |  65 ++++++++
 .../src/designer/beans/BeansDesigner.tsx           |  65 +++-----
 .../designer/dependencies/DependenciesDesigner.tsx |  67 +++------
 .../src/designer/dependencies/DependencyCard.tsx   |  63 ++++++++
 karavan-designer/src/designer/karavan.css          | 165 +++++----------------
 .../src/designer/route/DslProperties.tsx           |   2 +-
 .../designer/route/property/DslPropertyField.tsx   |  11 +-
 karavan-designer/src/designer/utils/CamelUi.ts     |   5 +-
 27 files changed, 344 insertions(+), 260 deletions(-)

diff --git a/karavan-core/src/core/api/CamelDefinitionApiExt.ts 
b/karavan-core/src/core/api/CamelDefinitionApiExt.ts
index 7fc1fff..d151748 100644
--- a/karavan-core/src/core/api/CamelDefinitionApiExt.ts
+++ b/karavan-core/src/core/api/CamelDefinitionApiExt.ts
@@ -438,7 +438,7 @@ export class CamelDefinitionApiExt {
         let expression: any = undefined;
         let parameters: any = undefined;
         if (className) {
-            const properties = className.endsWith("Definition")
+            const properties = (className.endsWith("Definition") || 
className.endsWith("BuilderRef"))
                 ? 
CamelMetadataApi.getCamelModelMetadataByClassName(className)?.properties
                 : (className.endsWith("DataFormat")
                         ? 
CamelMetadataApi.getCamelDataFormatMetadataByClassName(className)?.properties
diff --git a/karavan-demo/integrations/README.MD 
b/karavan-demo/integrations/README.MD
deleted file mode 100644
index 70c04cc..0000000
--- a/karavan-demo/integrations/README.MD
+++ /dev/null
@@ -1,9 +0,0 @@
-# Examples
-
-1. Http to Kafka
-```
-curl -X POST -H "Content-Type: application/json" --data 
'{"clientId":1,"amount":1000, "description":"some data"}' 
http://0.0.0.0:8080/demo
-```
-```
-curl -X POST -H "Content-Type: application/json" --data 
'{"clientId":2,"amount":10000, "description":"some data"}' 
http://0.0.0.0:8080/demo
-```
\ No newline at end of file
diff --git a/karavan-demo/integrations/Example.java 
b/karavan-demo/integrations/experiments/Example.java
similarity index 100%
rename from karavan-demo/integrations/Example.java
rename to karavan-demo/integrations/experiments/Example.java
diff --git a/karavan-demo/integrations/docker-compose.yml 
b/karavan-demo/integrations/experiments/docker-compose.yml
similarity index 87%
rename from karavan-demo/integrations/docker-compose.yml
rename to karavan-demo/integrations/experiments/docker-compose.yml
index ad027df..4b88e47 100644
--- a/karavan-demo/integrations/docker-compose.yml
+++ b/karavan-demo/integrations/experiments/docker-compose.yml
@@ -11,8 +11,6 @@ services:
     environment:
       MONGO_INITDB_ROOT_USERNAME: root
       MONGO_INITDB_ROOT_PASSWORD: example
-    networks:
-      - karavan-demo
 
   zookeeper:
     container_name: zookeeper
@@ -22,8 +20,6 @@ services:
     environment:
       ZOOKEEPER_CLIENT_PORT: 2181
       ZOOKEEPER_TICK_TIME: 2000
-    networks:
-      - karavan-demo
 
   kafka:
     container_name: kafka
@@ -40,8 +36,6 @@ services:
       KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
       KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
       KAFKA_CREATE_TOPICS: "events:1:1"
-    networks:
-      - karavan-demo
 
   activemq:
     image: registry.redhat.io/amq7/amq-broker:latest
@@ -52,8 +46,6 @@ services:
     ports:
       - "61616:61616"
       - "8161:8161"  
-    networks:
-      - karavan-demo
   
   postgres:
     image: postgres
@@ -68,8 +60,6 @@ services:
     volumes:
       - ./postgres_db.sql:/docker-entrypoint-initdb.d/postgres_db.sql
     command: 'postgres --max_prepared_transactions=100'
-    networks:
-      - karavan-demo
 
   pgadmin:
     container_name: pgadmin
@@ -80,8 +70,6 @@ services:
       PGADMIN_DEFAULT_PASSWORD: root
     ports:
       - "5050:80"
-    networks:
-      - karavan-demo
 
   mysql:
     image: mysql
@@ -98,8 +86,6 @@ services:
       - '3306:3306'
     expose:
       - '3306'
-    networks:
-      - karavan-demo
 
   adminer:
     image: adminer
@@ -107,9 +93,3 @@ services:
     restart: always
     ports:
       - 6060:8080
-    networks:
-      - karavan-demo
-
-networks:
-  karavan-demo:
-    name: karavan-demo
diff --git a/karavan-demo/integrations/http-to-kafka.yaml 
b/karavan-demo/integrations/experiments/http-to-kafka.yaml
similarity index 100%
rename from karavan-demo/integrations/http-to-kafka.yaml
rename to karavan-demo/integrations/experiments/http-to-kafka.yaml
diff --git a/karavan-demo/integrations/postgres_db.sql 
b/karavan-demo/integrations/experiments/postgres_db.sql
similarity index 100%
copy from karavan-demo/integrations/postgres_db.sql
copy to karavan-demo/integrations/experiments/postgres_db.sql
diff --git a/karavan-demo/integrations/rest-dsl.yaml 
b/karavan-demo/integrations/experiments/rest-dsl.yaml
similarity index 100%
rename from karavan-demo/integrations/rest-dsl.yaml
rename to karavan-demo/integrations/experiments/rest-dsl.yaml
diff --git a/karavan-demo/integrations/sql-to-log-int.yaml 
b/karavan-demo/integrations/experiments/sql-to-log-int.yaml
similarity index 100%
rename from karavan-demo/integrations/sql-to-log-int.yaml
rename to karavan-demo/integrations/experiments/sql-to-log-int.yaml
diff --git a/karavan-demo/integrations/sql-to-log.yaml 
b/karavan-demo/integrations/experiments/sql-to-log.yaml
similarity index 100%
rename from karavan-demo/integrations/sql-to-log.yaml
rename to karavan-demo/integrations/experiments/sql-to-log.yaml
diff --git a/karavan-demo/integrations/xxx.groovy 
b/karavan-demo/integrations/experiments/xxx.groovy
similarity index 100%
rename from karavan-demo/integrations/xxx.groovy
rename to karavan-demo/integrations/experiments/xxx.groovy
diff --git a/karavan-demo/integrations/zzz-int.yaml 
b/karavan-demo/integrations/experiments/zzz-int.yaml
similarity index 89%
rename from karavan-demo/integrations/zzz-int.yaml
rename to karavan-demo/integrations/experiments/zzz-int.yaml
index ab35d5d..31007cf 100644
--- a/karavan-demo/integrations/zzz-int.yaml
+++ b/karavan-demo/integrations/experiments/zzz-int.yaml
@@ -16,7 +16,7 @@ spec:
     - content: |-
         beans {
             myProcessor = processor { 
-                it.in.body = 'Hello Camel K!'
+                it.in.body = 'Hello World!'
             }
         }
       name: xxx.groovy
diff --git a/karavan-demo/integrations/zzz.yaml 
b/karavan-demo/integrations/experiments/zzz.yaml
similarity index 100%
rename from karavan-demo/integrations/zzz.yaml
rename to karavan-demo/integrations/experiments/zzz.yaml
diff --git a/karavan-demo/integrations/rest-database/README.MD 
b/karavan-demo/integrations/rest-database/README.MD
new file mode 100644
index 0000000..271c1f2
--- /dev/null
+++ b/karavan-demo/integrations/rest-database/README.MD
@@ -0,0 +1,28 @@
+## REST service to store/retrieve data to/from database (Postgres)
+Localhost Integration prototype with Camel & Jbang
+
+## Prerequisites
+Docker, docker-compose, jbang, VSCode with Camel Karavan extension installed
+
+## How to
+
+1. Start Docker compose (Postgres and PgAdmin)
+```
+docker-compose up
+```
+
+2. Start Camel integration
+```
+jbang camel@apache/camel run rest-database.yaml --logging-level=info
+```
+
+3. Store data to database
+```
+curl -X POST -H "Content-Type: application/json" --data '{"id":1,"name":"John 
Doe"}' http://0.0.0.0:8080/client
+curl -X POST -H "Content-Type: application/json" --data '{"id":2,"name":"Jane 
Doe"}' http://0.0.0.0:8080/client
+```
+
+4. Retrieve data from database
+```
+curl -X GET -H "Content-Type: application/json" http://0.0.0.0:8080/client
+```
\ No newline at end of file
diff --git a/karavan-demo/integrations/rest-database/docker-compose.yml 
b/karavan-demo/integrations/rest-database/docker-compose.yml
new file mode 100644
index 0000000..50a0394
--- /dev/null
+++ b/karavan-demo/integrations/rest-database/docker-compose.yml
@@ -0,0 +1,27 @@
+---
+version: '3.8'
+services:
+
+  postgres:
+    image: postgres
+    container_name: postgres
+    restart: always
+    environment:
+      - POSTGRES_USER=postgres
+      - POSTGRES_PASSWORD=postgres
+      - POSTGRES_DB=demo
+    ports:
+      - '5432:5432'
+    volumes:
+      - ./postgres_db.sql:/docker-entrypoint-initdb.d/postgres_db.sql
+    command: 'postgres --max_prepared_transactions=100'
+
+  pgadmin:
+    container_name: pgadmin
+    image: dpage/pgadmin4
+    restart: always
+    environment:
+      PGADMIN_DEFAULT_EMAIL: [email protected]
+      PGADMIN_DEFAULT_PASSWORD: root
+    ports:
+      - "5050:80"
\ No newline at end of file
diff --git a/karavan-demo/integrations/postgres_db.sql 
b/karavan-demo/integrations/rest-database/postgres_db.sql
similarity index 100%
rename from karavan-demo/integrations/postgres_db.sql
rename to karavan-demo/integrations/rest-database/postgres_db.sql
diff --git a/karavan-demo/integrations/rest-database/rest-database.yaml 
b/karavan-demo/integrations/rest-database/rest-database.yaml
new file mode 100644
index 0000000..8fd9a52
--- /dev/null
+++ b/karavan-demo/integrations/rest-database/rest-database.yaml
@@ -0,0 +1,51 @@
+- rest:
+    post:
+      - path: client
+        to: direct:post
+    get:
+      - path: client
+        to: direct:get
+    consumes: application/json
+    produces: application/json
+    bindingMode: 'off'
+- route:
+    from:
+      uri: direct:get
+      steps:
+        - setBody:
+            expression:
+              simple:
+                expression: '" "'
+                resultType: String
+        - kamelet:
+            name: postgresql-sink
+            parameters:
+              serverName: localhost
+              serverPort: '5432'
+              username: postgres
+              password: postgres
+              query: SELECT * FROM table1
+              databaseName: demo
+        - marshal:
+            json:
+              library: jackson
+    id: get
+- route:
+    from:
+      uri: direct:post
+      steps:
+        - kamelet:
+            name: postgresql-sink
+            parameters:
+              serverName: localhost
+              serverPort: '5432'
+              username: postgres
+              password: postgres
+              databaseName: demo
+              query: >-
+                INSERT INTO table1 (id,name) VALUES (:#id,:#name) ON CONFLICT
+                (id) DO UPDATE SET name = :#name 
+        - marshal:
+            json:
+              library: jackson
+    id: post
diff --git a/karavan-demo/integrations/xxx.yaml 
b/karavan-demo/integrations/xxx.yaml
new file mode 100644
index 0000000..e5196d9
--- /dev/null
+++ b/karavan-demo/integrations/xxx.yaml
@@ -0,0 +1,12 @@
+- route:
+    from:
+      uri: as2
+      steps:
+        - filter:
+            expression:
+              simple:
+                expression: ${body} != null
+            steps:
+              - unmarshal:
+                  json:
+                    library: jackson
diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index 2c8ac9e..7693d24 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -41,9 +41,9 @@ class App extends React.Component<Props, State> {
             'metadata:\n' +
             '  name: demo.yaml \n' +
             'spec:\n' +
-            '  dependencies:\n' +
-            '    - "mvn:org.apache.commons:commons-dbcp2:2.9.0" \n' +
-            '    - "mvn:org.postgresql:postgresql:42.2.14" \n' +
+            // '  dependencies:\n' +
+            // '    - "mvn:org.apache.commons:commons-dbcp2:2.9.0" \n' +
+            // '    - "mvn:org.postgresql:postgresql:42.2.14" \n' +
             '  flows:\n' +
             // '    - route:\n' +
             // '        from:\n' +
diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx 
b/karavan-designer/src/designer/KaravanDesigner.tsx
index 427645b..dda7bf8 100644
--- a/karavan-designer/src/designer/KaravanDesigner.tsx
+++ b/karavan-designer/src/designer/KaravanDesigner.tsx
@@ -75,13 +75,15 @@ export class KaravanDesigner extends React.Component<Props, 
State> {
 
     getTab(title: string, tooltip: string, icon: string) {
         const counts = CamelUi.getFlowCounts(this.state.integration);
+        const count =  counts.has(icon) && counts.get(icon) ? counts.get(icon) 
: undefined;
+        const showCount = count && count > 0;
         return (
             <Tooltip position={"bottom"}
                      content={<div>{tooltip}</div>}>
                 <div className="top-menu-item">
                     <TabTitleIcon>{this.getIcon(icon)}</TabTitleIcon>
                     <TabTitleText>{title}</TabTitleText>
-                    {counts.has(icon) && <Badge isRead 
className="count">{counts.get(icon)}</Badge>}
+                    {showCount && <Badge isRead 
className="count">{counts.get(icon)}</Badge>}
                 </div>
             </Tooltip>
 
diff --git a/karavan-designer/src/designer/beans/BeanCard.tsx 
b/karavan-designer/src/designer/beans/BeanCard.tsx
new file mode 100644
index 0000000..803272f
--- /dev/null
+++ b/karavan-designer/src/designer/beans/BeanCard.tsx
@@ -0,0 +1,65 @@
+/*
+ * 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 React from 'react';
+import {
+    Button
+} from '@patternfly/react-core';
+import '../karavan.css';
+import {Integration} from "karavan-core/lib/model/IntegrationDefinition";
+import {NamedBeanDefinition} from "karavan-core/lib/model/CamelDefinition";
+import DeleteIcon from 
"@patternfly/react-icons/dist/js/icons/times-circle-icon";
+
+interface Props {
+    bean: NamedBeanDefinition
+    selectedStep?: NamedBeanDefinition
+    integration: Integration
+    selectElement: (element: NamedBeanDefinition) => void
+    deleteElement: (element: NamedBeanDefinition) => void
+}
+
+export class BeanCard extends React.Component<Props, any> {
+
+    selectElement = (evt: React.MouseEvent) => {
+        evt.stopPropagation();
+        this.props.selectElement.call(this, this.props.bean);
+    }
+
+    delete = (evt: React.MouseEvent) => {
+        evt.stopPropagation();
+        this.props.deleteElement.call(this, this.props.bean);
+    }
+
+    render() {
+        const bean = this.props.bean;
+        return (
+            <div className={this.props.selectedStep?.uuid === bean.uuid ? 
"rest-card rest-card-selected" : "rest-card rest-card-unselected"} onClick={e 
=> this.selectElement(e)}>
+                <div className="header">
+                    <div className="title">BEAN</div>
+                    <div className="title">{bean.name}</div>
+                    <div className="description">{bean.type}</div>
+                    {/*<Tooltip position={"bottom"} content={<div>Add REST 
method</div>}>*/}
+                        {/*<Button variant={"link"} icon={<AddIcon/>} 
aria-label="Add" onClick={e => this.selectMethod(e)} className="add-button">Add 
method</Button>*/}
+                    {/*</Tooltip>*/}
+                    <Button variant="link" className="delete-button" 
onClick={e => this.delete(e)}><DeleteIcon/></Button>
+                </div>
+                <div className="rest-content" key={Math.random().toString()}>
+
+                </div>
+            </div>
+        );
+    }
+}
diff --git a/karavan-designer/src/designer/beans/BeansDesigner.tsx 
b/karavan-designer/src/designer/beans/BeansDesigner.tsx
index 33bcf57..99bafba 100644
--- a/karavan-designer/src/designer/beans/BeansDesigner.tsx
+++ b/karavan-designer/src/designer/beans/BeansDesigner.tsx
@@ -16,7 +16,7 @@
  */
 import React from 'react';
 import {
-    Button, Card, CardBody, CardFooter, CardHeader, CardTitle, Gallery, Modal, 
PageSection
+    Button, Modal, PageSection
 } from '@patternfly/react-core';
 import '../karavan.css';
 import {NamedBeanDefinition} from "karavan-core/lib/model/CamelDefinition";
@@ -24,10 +24,9 @@ import {Integration} from 
"karavan-core/lib/model/IntegrationDefinition";
 import {CamelUi} from "../utils/CamelUi";
 import PlusIcon from "@patternfly/react-icons/dist/esm/icons/plus-icon";
 import {CamelDefinitionApiExt} from 
"karavan-core/lib/api/CamelDefinitionApiExt";
-import DeleteIcon from 
"@patternfly/react-icons/dist/js/icons/times-circle-icon";
-import {BeanIcon} from "../utils/KaravanIcons";
 import {BeanProperties} from "./BeanProperties";
 import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
+import {BeanCard} from "./BeanCard";
 
 interface Props {
     onSave?: (integration: Integration) => void
@@ -54,26 +53,13 @@ export class BeansDesigner extends React.Component<Props, 
State> {
         showBeanEditor: false,
     };
 
-    componentDidMount() {
-        window.addEventListener('resize', this.handleResize);
-    }
-
-    componentWillUnmount() {
-        window.removeEventListener('resize', this.handleResize);
-    }
-
-    handleResize = () => {
-        this.setState({key: Math.random().toString()});
-    }
-
     componentDidUpdate = (prevProps: Readonly<Props>, prevState: 
Readonly<State>, snapshot?: any) => {
         if (prevState.key !== this.state.key) {
             this.props.onSave?.call(this, this.state.integration);
         }
     }
 
-    showDeleteConfirmation = (e: React.MouseEvent, bean: NamedBeanDefinition) 
=> {
-        e.stopPropagation();
+    showDeleteConfirmation = (bean: NamedBeanDefinition) => {
         this.setState({selectedBean: bean, showDeleteConfirmation: true});
     }
 
@@ -130,36 +116,27 @@ export class BeansDesigner extends React.Component<Props, 
State> {
         this.changeBean(new NamedBeanDefinition());
     }
 
-    getCard(bean: NamedBeanDefinition, index: number) {
-        return (
-            <Card key={bean.dslName + index} isHoverable isCompact
-                  className={this.state.selectedBean?.uuid === bean.uuid ? 
"bean-card bean-card-selected" : "bean-card bean-card-unselected"}
-                  onClick={e => this.selectBean(bean)}>
-                <Button variant="link" className="delete-button" onClick={e => 
this.showDeleteConfirmation(e, bean)}><DeleteIcon/></Button>
-                <CardHeader>
-                    <div className="header-icon"><BeanIcon/></div>
-                </CardHeader>
-                <CardTitle>{bean.name}</CardTitle>
-                <CardBody>{bean.type}</CardBody>
-                <CardFooter className="">
-                </CardFooter>
-            </Card>
-        )
-    }
-
     render() {
         const beans = CamelUi.getBeans(this.state.integration);
         return (
-            <PageSection className="beans-page" isFilled padding={{default: 
'noPadding'}}>
-                <div className="beans-page-columns" data-click="BEANS" 
onClick={event => this.unselectBean(event)}>
-                    <div className="beans-panel">
-                        <Gallery hasGutter className="beans-gallery" 
data-click="BEANS" onClick={event => this.unselectBean(event)}>
-                            {beans.map((bean: NamedBeanDefinition, index: 
number) => this.getCard(bean, index))}
-                        </Gallery>
-                        <div className="add-button-div" data-click="BEANS" 
onClick={event => this.unselectBean(event)}>
-                            <Button icon={<PlusIcon/>} variant={beans.length 
=== 0 ? "primary" : "secondary"} onClick={e => this.createBean()} 
className="add-bean-button">
-                                Create new bean
-                            </Button>
+            <PageSection className="rest-page" isFilled padding={{default: 
'noPadding'}}>
+                <div className="rest-page-columns">
+                    <div className="graph" data-click="REST"  onClick={event 
=> this.unselectBean(event)}>
+                        <div className="flows">
+                            {beans?.map(bean => <BeanCard key={bean.uuid + 
this.state.key}
+                                                          
selectedStep={this.state.selectedBean}
+                                                          bean={bean}
+                                                          
integration={this.props.integration}
+                                                          
selectElement={this.selectBean}
+                                                          
deleteElement={this.showDeleteConfirmation}/>)}
+                            <div className="add-rest">
+                                <Button
+                                    variant={beans?.length === 0 ? "primary" : 
"secondary"}
+                                    data-click="ADD_REST"
+                                    icon={<PlusIcon/>}
+                                    onClick={e => this.createBean()}>Create 
new bean
+                                </Button>
+                            </div>
                         </div>
                     </div>
                     <BeanProperties integration={this.props.integration}
diff --git 
a/karavan-designer/src/designer/dependencies/DependenciesDesigner.tsx 
b/karavan-designer/src/designer/dependencies/DependenciesDesigner.tsx
index 877b132..e4c4f79 100644
--- a/karavan-designer/src/designer/dependencies/DependenciesDesigner.tsx
+++ b/karavan-designer/src/designer/dependencies/DependenciesDesigner.tsx
@@ -16,17 +16,16 @@
  */
 import React from 'react';
 import {
-    Button, Card, CardFooter, CardHeader, CardTitle, Gallery, Modal, 
PageSection
+    Button, Modal, PageSection
 } from '@patternfly/react-core';
 import '../karavan.css';
 import {CamelUi} from "../utils/CamelUi";
 import PlusIcon from "@patternfly/react-icons/dist/esm/icons/plus-icon";
-import DeleteIcon from 
"@patternfly/react-icons/dist/js/icons/times-circle-icon";
-import {DependencyIcon} from "../utils/KaravanIcons";
 import {DependencyProperties} from "./DependencyProperties";
 import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
 import {Integration, Dependency} from 
"karavan-core/lib/model/IntegrationDefinition";
 import {CamelDefinitionApiExt} from 
"karavan-core/lib/api/CamelDefinitionApiExt";
+import {DependencyCard} from "./DependencyCard";
 
 interface Props {
     onSave?: (integration: Integration) => void
@@ -53,26 +52,13 @@ export class DependenciesDesigner extends 
React.Component<Props, State> {
         showDepEditor: false,
     };
 
-    componentDidMount() {
-        window.addEventListener('resize', this.handleResize);
-    }
-
-    componentWillUnmount() {
-        window.removeEventListener('resize', this.handleResize);
-    }
-
-    handleResize = () => {
-        this.setState({key: Math.random().toString()});
-    }
-
     componentDidUpdate = (prevProps: Readonly<Props>, prevState: 
Readonly<State>, snapshot?: any) => {
         if (prevState.key !== this.state.key) {
             this.props.onSave?.call(this, this.state.integration);
         }
     }
 
-    showDeleteConfirmation = (e: React.MouseEvent, dependency: Dependency) => {
-        e.stopPropagation();
+    showDeleteConfirmation = (dependency: Dependency) => {
         this.setState({selectedDep: dependency, showDeleteConfirmation: true});
     }
 
@@ -133,36 +119,28 @@ export class DependenciesDesigner extends 
React.Component<Props, State> {
         this.changeDep(new Dependency());
     }
 
-    getCard(dep: Dependency, index: number) {
-        return (
-            <Card key={dep.uuid + index} isHoverable isCompact
-                  className={this.state.selectedDep?.uuid === dep.uuid ? 
"bean-card bean-card-selected" : "bean-card bean-card-unselected"}
-                  onClick={e => this.selectDep(dep)}>
-                <Button variant="link" className="delete-button" onClick={e => 
this.showDeleteConfirmation(e, dep)}><DeleteIcon/></Button>
-                <CardHeader>
-                    <div className="header-icon"><DependencyIcon/></div>
-                </CardHeader>
-                <CardTitle>{dep.getFullName()}</CardTitle>
-                {/*<CardBody>{dep}</CardBody>*/}
-                <CardFooter className="">
-                </CardFooter>
-            </Card>
-        )
-    }
-
     render() {
         const deps = CamelUi.getDependencies(this.state.integration).sort((a, 
b) => a.getFullName() > b.getFullName() ? 1 : -1 );
         return (
-            <PageSection className="beans-page" isFilled padding={{default: 
'noPadding'}}>
-                <div className="beans-page-columns" data-click="BEANS" 
onClick={event => this.unselectDep(event)}>
-                    <div className="beans-panel">
-                        <Gallery hasGutter className="beans-gallery" 
data-click="BEANS" onClick={event => this.unselectDep(event)}>
-                            {deps.map((dep: Dependency, index: number) => 
this.getCard(dep, index))}
-                        </Gallery>
-                        <div className="add-button-div" data-click="BEANS" 
onClick={event => this.unselectDep(event)}>
-                            <Button icon={<PlusIcon/>} variant={deps.length 
=== 0 ? "primary" : "secondary"} onClick={e => this.createDep()} 
className="add-bean-button">
-                                Create new dependency
-                            </Button>
+            <PageSection className="rest-page" isFilled padding={{default: 
'noPadding'}}>
+                <div className="rest-page-columns">
+                    <div className="graph" data-click="REST"  onClick={event 
=> this.unselectDep(event)}>
+                        <div className="flows">
+                            {deps?.map(dep => <DependencyCard key={dep.uuid + 
this.state.key}
+                                                              
selectedDep={this.state.selectedDep}
+                                                              dep={dep}
+                                                              
integration={this.props.integration}
+                                                              
selectElement={this.selectDep}
+                                                              
deleteElement={this.showDeleteConfirmation}/>)
+                            }
+                            <div className="add-rest">
+                                <Button
+                                    variant={deps?.length === 0 ? "primary" : 
"secondary"}
+                                    data-click="ADD_DEPENDENCY"
+                                    icon={<PlusIcon/>}
+                                    onClick={e => this.createDep()}>Create new 
dependency
+                                </Button>
+                            </div>
                         </div>
                     </div>
                     <DependencyProperties integration={this.props.integration}
@@ -172,6 +150,7 @@ export class DependenciesDesigner extends 
React.Component<Props, State> {
                 </div>
                 {this.getDeleteConfirmation()}
             </PageSection>
+
         );
     }
 }
diff --git a/karavan-designer/src/designer/dependencies/DependencyCard.tsx 
b/karavan-designer/src/designer/dependencies/DependencyCard.tsx
new file mode 100644
index 0000000..e6bf983
--- /dev/null
+++ b/karavan-designer/src/designer/dependencies/DependencyCard.tsx
@@ -0,0 +1,63 @@
+/*
+ * 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 React from 'react';
+import {
+    Button
+} from '@patternfly/react-core';
+import '../karavan.css';
+import {Dependency, Integration} from 
"karavan-core/lib/model/IntegrationDefinition";
+import DeleteIcon from 
"@patternfly/react-icons/dist/js/icons/times-circle-icon";
+
+interface Props {
+    dep: Dependency
+    selectedDep?: Dependency
+    integration: Integration
+    selectElement: (element: Dependency) => void
+    deleteElement: (element: Dependency) => void
+}
+
+export class DependencyCard extends React.Component<Props, any> {
+
+    selectElement = (evt: React.MouseEvent) => {
+        evt.stopPropagation();
+        this.props.selectElement.call(this, this.props.dep);
+    }
+
+    delete = (evt: React.MouseEvent) => {
+        evt.stopPropagation();
+        this.props.deleteElement.call(this, this.props.dep);
+    }
+
+    render() {
+        const dep = this.props.dep;
+        return (
+            <div className={this.props.selectedDep?.uuid === dep.uuid ? 
"rest-card rest-card-selected" : "rest-card rest-card-unselected"} onClick={e 
=> this.selectElement(e)}>
+                <div className="header">
+                    <div className="title">DEPENDENCY</div>
+                    <div className="title">{dep.getFullName()}</div>
+                    {/*<Tooltip position={"bottom"} content={<div>Add REST 
method</div>}>*/}
+                        {/*<Button variant={"link"} icon={<AddIcon/>} 
aria-label="Add" onClick={e => this.selectMethod(e)} className="add-button">Add 
method</Button>*/}
+                    {/*</Tooltip>*/}
+                    <Button variant="link" className="delete-button" 
onClick={e => this.delete(e)}><DeleteIcon/></Button>
+                </div>
+                <div className="rest-content" key={Math.random().toString()}>
+
+                </div>
+            </div>
+        );
+    }
+}
diff --git a/karavan-designer/src/designer/karavan.css 
b/karavan-designer/src/designer/karavan.css
index c8aa7dd..aeba6a4 100644
--- a/karavan-designer/src/designer/karavan.css
+++ b/karavan-designer/src/designer/karavan.css
@@ -367,6 +367,19 @@
     border-style: solid;
 }
 
+.karavan .properties .object-value {
+    display: flex;
+    flex-direction: row;
+    margin-bottom: 3px;
+}
+
+.karavan .properties .object-value .delete-button {
+    margin: 0;
+    padding: 5px 3px 0px 6px;
+    height: 16px;
+    color: #909090;
+}
+
 .karavan .properties .expression,
 .karavan .properties .object,
 .karavan .properties .dataformat,
@@ -375,6 +388,7 @@
     padding-left: 16px;
     row-gap: 6px;
     display: grid;
+    width: 100%;
 }
 
 .karavan .properties .expression .pf-c-form__group-label,
@@ -803,138 +817,6 @@
     background-color: #fca338;
 }
 
-/*Beans*/
-.karavan .beans-page {
-    flex: 1 1;
-    overflow: auto;
-}
-.karavan .beans-page-columns {
-    height: 100%;
-    background: #fafafa;
-    display: flex;
-    flex-direction: row;
-}
-
-.karavan .beans-panel {
-    padding: 16px;
-    display: block;
-    flex-direction: column;
-    height: 100%;
-    width: 100%;
-    position: relative;
-    overflow-y: auto;
-}
-.karavan .beans-page .add-button-div {
-    width: 100%;
-    margin-top: 16px;
-    display: flex;
-}
-
-.karavan .beans-page .add-bean-button {
-    margin: auto;
-}
-
-.karavan .beans-page .bean-card-selected {
-    border-color: rgb(48, 50, 132);
-    background-color: rgb(171, 172, 224, 0.1);
-}
-
-.karavan .beans-page .bean-card-unselected {
-    border-color: #fb8824;
-    background-color: transparent;
-}
-
-.karavan .beans-page .bean-card,
-.karavan .beans-page .bean-card:hover {
-    border-radius: 16px;
-    border-width: 1px;
-    border-style: dotted;
-    box-shadow: none;
-}
-
-.karavan .beans-page .bean-card .pf-c-card__header {
-    padding-right: 6px;
-    word-wrap:anywhere;
-    width: 100%;
-}
-
-.karavan .beans-page .bean-card .pf-c-card__title {
-    text-align: center;
-    font-size: 14px;
-}
-
-.karavan .beans-page .bean-card .pf-c-card__body {
-    word-wrap:anywhere;
-    text-align: center;
-    font-size: 14px;
-}
-
-.karavan .beans-page .bean-card .header-icon {
-    border-style: solid;
-    border-radius: 30px;
-    border-width: 1px;
-    width: 30px;
-    height: 30px;
-    margin: 6px auto auto auto;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-}
-
-.karavan .beans-page .bean-card-unselected .header-icon {
-    border-color: #fb8824;
-    background: transparent;
-    border-width: 1px;
-}
-
-.karavan .beans-page .bean-card-selected .header-icon {
-    border-color: rgb(48, 50, 132);
-    background-color: rgb(171, 172, 224);
-    border-width: 2px;
-}
-
-.karavan .beans-page .bean-card .icon {
-    height: 20px;
-    width: auto;
-    border: none;
-}
-
-.karavan .beans-page .bean-card .delete-button {
-    position: absolute;
-    top: 4px;
-    right: 4px;
-    font-size: 14px;
-    line-height: 1;
-    border: 0;
-    padding: 0;
-    margin: 0;
-    background: transparent;
-    color: #909090;
-    visibility: hidden;
-}
-
-.karavan .beans-page .bean-card:hover .delete-button {
-    visibility: visible;
-}
-
-.karavan .beans-page .properties .bean-properties .pf-c-form__group-control {
-    display: flex;
-    flex-direction: column;
-    gap: 6px;
-}
-
-.karavan .beans-page .properties .bean-property {
-    display: flex;
-    flex-direction: row;
-    gap: 3px;
-}
-
-.karavan .beans-page .properties .bean-property .delete-button {
-    padding: 3px;
-    color: #b1b1b7;
-    font-size: 14px;
-}
-
 /*REST Page*/
 .karavan .rest-page {
     flex: 1;
@@ -1084,6 +966,25 @@
     margin-top: 16px;
 }
 
+/*Beans*/
+.karavan .rest-page .properties .bean-properties .pf-c-form__group-control {
+    display: flex;
+    flex-direction: column;
+    gap: 6px;
+}
+
+.karavan .rest-page .properties .bean-property {
+    display: flex;
+    flex-direction: row;
+    gap: 3px;
+}
+
+.karavan .rest-page .properties .bean-property .delete-button {
+    padding: 3px;
+    color: #b1b1b7;
+    font-size: 14px;
+}
+
 /*Exception*/
 /*Template*/
 /*Error*/
diff --git a/karavan-designer/src/designer/route/DslProperties.tsx 
b/karavan-designer/src/designer/route/DslProperties.tsx
index 3e25b92..d709a76 100644
--- a/karavan-designer/src/designer/route/DslProperties.tsx
+++ b/karavan-designer/src/designer/route/DslProperties.tsx
@@ -131,7 +131,7 @@ export class DslProperties extends React.Component<Props, 
State> {
             .filter((p: PropertyMeta) => (showAdvanced && 
p.label.includes('advanced')) || (!showAdvanced && 
!p.label.includes('advanced')))
             .filter((p: PropertyMeta) => !p.isObject || (p.isObject && 
!CamelUi.dslHasSteps(p.type)) || (dslName === 'CatchDefinition' && p.name === 
'onWhen'))
             .filter((p: PropertyMeta) => !(dslName === 'RestDefinition' && 
['get', 'post', 'put', 'patch', 'delete', 'head'].includes(p.name)))
-            .filter((p: PropertyMeta) => dslName && !(['RestDefinition', 
'GetDefinition', 'PostDefinition', 'PutDefinition', 'PatchDefinition', 
'DeleteDefinition', 'HeadDefinition'].includes(dslName) && ['param', 
'responseMessage', 'security'].includes(p.name))) // TODO: configure this 
properties
+            .filter((p: PropertyMeta) => dslName && !(['RestDefinition', 
'GetDefinition', 'PostDefinition', 'PutDefinition', 'PatchDefinition', 
'DeleteDefinition', 'HeadDefinition'].includes(dslName) && ['param', 
'responseMessage'].includes(p.name))) // TODO: configure this properties
     }
 
     getPropertyFields = (showAdvanced: boolean) => {
diff --git a/karavan-designer/src/designer/route/property/DslPropertyField.tsx 
b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
index 5749147..9ef0872 100644
--- a/karavan-designer/src/designer/route/property/DslPropertyField.tsx
+++ b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
@@ -23,7 +23,7 @@ import {
     Select,
     SelectVariant,
     SelectDirection,
-    SelectOption, ExpandableSection, TextArea, Chip, TextInputGroup, 
TextInputGroupMain, TextInputGroupUtilities, ChipGroup, Button, Text, Tooltip
+    SelectOption, ExpandableSection, TextArea, Chip, TextInputGroup, 
TextInputGroupMain, TextInputGroupUtilities, ChipGroup, Button, Text, Tooltip, 
Card
 } from '@patternfly/react-core';
 import '../../karavan.css';
 import "@patternfly/patternfly/patternfly.css";
@@ -334,11 +334,16 @@ export class DslPropertyField extends 
React.Component<Props, State> {
         return (
             <div>
                 {value && Array.from(value).map((v: any, index: number) => (
-                    <div key={property + "-" + index}>
+                    <Card key={property + "-" + index} 
className="object-value">
                         <div className="object">
                             {value && <ObjectField property={property} 
value={v} onPropertyUpdate={(f, v) => this.onMultiValueObjectUpdate(index, f, 
v)} integration={this.props.integration} />}
                         </div>
-                    </div>
+                        <Button variant="link" className="delete-button" 
onClick={e => {
+                            const v = Array.from(value);
+                            v.splice(index, 1);
+                            this.propertyChanged(property.name,v);
+                        }}><DeleteIcon/></Button>
+                    </Card>
                 ))}
                 <Button variant="link" className="add-button" onClick={e => 
this.propertyChanged(property.name, [...value, 
CamelDefinitionApi.createStep(property.type, {})])}><AddIcon/>{"Add " + 
property.displayName}</Button>
             </div>
diff --git a/karavan-designer/src/designer/utils/CamelUi.ts 
b/karavan-designer/src/designer/utils/CamelUi.ts
index 2003e3d..fa1996a 100644
--- a/karavan-designer/src/designer/utils/CamelUi.ts
+++ b/karavan-designer/src/designer/utils/CamelUi.ts
@@ -19,7 +19,7 @@ import {KameletModel, Property} from 
"karavan-core/lib/model/KameletModels";
 import {DslMetaModel} from "./DslMetaModel";
 import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
 import {ComponentProperty} from "karavan-core/lib/model/ComponentModels";
-import {CamelMetadataApi, PropertyMeta} from 
"karavan-core/lib/model/CamelMetadata";
+import {CamelMetadataApi} from "karavan-core/lib/model/CamelMetadata";
 import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
 import {CamelDefinitionApiExt} from 
"karavan-core/lib/api/CamelDefinitionApiExt";
 import {KameletDefinition, NamedBeanDefinition, RouteDefinition, 
SagaDefinition} from "karavan-core/lib/model/CamelDefinition";
@@ -33,6 +33,7 @@ const StepElements: string[] = [
     "ConvertBodyDefinition",
     "DynamicRouterDefinition",
     "EnrichDefinition",
+    "ErrorHandlerBuilderRef",
     "FilterDefinition",
     "LogDefinition",
     "LoopDefinition",
@@ -428,6 +429,8 @@ export class CamelUi {
                 return "data:image/svg+xml,%3Csvg 
xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' 
version='1.1' id='Capa_1' x='0px' y='0px' width='235.506px' height='235.506px' 
viewBox='0 0 235.506 235.506' style='enable-background:new 0 0 235.506 
235.506;' xml:space='preserve'%3E%3Cg%3E%3Cpath 
d='M234.099,29.368c-3.025-4.861-10.303-7.123-22.915-7.123c-13.492,0-28.304,2.661-28.625,2.733
 c-20.453,2.098-27.254,26.675-32.736,46.436c-1.924,6.969-3.755,13.549-5.8 [...]
             case "DynamicRouterDefinition":
                 return "data:image/svg+xml,%3Csvg width='32' height='32' 
xmlns='http://www.w3.org/2000/svg' 
xmlns:svg='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D%3C/style%3E%3C/defs%3E%3Ctitle%3Einsert%3C/title%3E%3Cg
 class='layer'%3E%3Ctitle%3ELayer 1%3C/title%3E%3Crect class='cls-1' 
data-name='&lt;Transparent Rectangle&gt;' height='32' 
id='_Transparent_Rectangle_' width='31.94228' x='0' y='0'/%3E%3Cg id='svg_5' 
transform='matrix(1 0 0 1 0 0) rotate(180 16 [...]
+            case "ErrorHandlerBuilderRef":
+                return "data:image/svg+xml,%3Csvg 
xmlns='http://www.w3.org/2000/svg' class='top-icon' width='36px' height='36px' 
viewBox='0 0 36 36' version='1.1' preserveAspectRatio='xMidYMid 
meet'%3E%3Ccircle class='clr-i-outline clr-i-outline-path-1' cx='18' cy='26.06' 
r='1.33'%3E%3C/circle%3E%3Cpath class='clr-i-outline clr-i-outline-path-2' 
d='M18,22.61a1,1,0,0,1-1-1v-12a1,1,0,1,1,2,0v12A1,1,0,0,1,18,22.61Z'%3E%3C/path%3E%3Cpath
 class='clr-i-outline clr-i-outline-path-3' d='M18,34A1 [...]
             default:
                 return camelIcon;
         }

Reply via email to