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 2023/08/08 15:58:53 UTC

[camel-karavan] 01/03: Fix connectors and icons for #484

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

commit c72e1bef0111977b09051e78f89e213bb225eb37
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Tue Aug 8 11:42:56 2023 -0400

    Fix connectors and icons for #484
---
 .../src/designer/route/DslConnections.tsx          |   7 +-
 .../src/designer/route/DslProperties.tsx           |   2 +-
 .../src/designer/route/DslSelector.tsx             |   2 +-
 .../src/designer/route/RouteDesignerLogic.tsx      |   2 +-
 .../route/property/ComponentParameterField.tsx     |  10 +-
 .../designer/route/property/DslPropertyField.tsx   |   2 +-
 karavan-designer/src/designer/utils/CamelUi.tsx    | 172 ++++++++++++---------
 .../src/designer/utils/KaravanIcons.tsx            |  89 +++++++++++
 .../src/knowledgebase/components/ComponentsTab.tsx |   6 +-
 9 files changed, 206 insertions(+), 86 deletions(-)

diff --git a/karavan-designer/src/designer/route/DslConnections.tsx b/karavan-designer/src/designer/route/DslConnections.tsx
index 4e4f9f53..5280bc12 100644
--- a/karavan-designer/src/designer/route/DslConnections.tsx
+++ b/karavan-designer/src/designer/route/DslConnections.tsx
@@ -60,7 +60,10 @@ export class DslConnections extends React.Component<Props, State> {
             this.setState(prevState => ({steps: prevState.steps.set(evt.step.uuid, evt)}));
         }
         else if (evt.command === "delete") this.setState(prevState => {
-            // prevState.steps.clear();
+            prevState.steps.clear();
+            Array.from(prevState.steps.entries())
+                .filter(value => value[1]?.parent?.uuid !== evt.step.uuid)
+                .forEach(value => prevState.steps.set(value[0], value[1]));
             prevState.steps.delete(evt.step.uuid);
             return {steps: prevState.steps};
         });
@@ -456,7 +459,7 @@ export class DslConnections extends React.Component<Props, State> {
                 {steps.map(pos => this.getArrow(pos))}
                 {this.getIncomings().map(p => this.getIncoming(p))}
                 {this.getOutgoings().map(p => this.getOutgoing(p))}
-                {this.getInternals().map((p) => this.getInternalLines(p)).flat()}
+                {/*{this.getInternals().map((p) => this.getInternalLines(p)).flat()}*/}
             </svg>
         )
     }
diff --git a/karavan-designer/src/designer/route/DslProperties.tsx b/karavan-designer/src/designer/route/DslProperties.tsx
index 53ae4bde..435480de 100644
--- a/karavan-designer/src/designer/route/DslProperties.tsx
+++ b/karavan-designer/src/designer/route/DslProperties.tsx
@@ -93,7 +93,7 @@ export class DslProperties extends React.Component<Props, State> {
             parameters[parameter] = value;
             (clone as any).parameters = parameters;
             this.setStep(clone);
-            this.props.onPropertyUpdate?.call(this, clone);
+            this.props.onPropertyUpdate?.call(this, clone, newRoute);
         }
     }
 
diff --git a/karavan-designer/src/designer/route/DslSelector.tsx b/karavan-designer/src/designer/route/DslSelector.tsx
index 64dc73a7..8c6d741a 100644
--- a/karavan-designer/src/designer/route/DslSelector.tsx
+++ b/karavan-designer/src/designer/route/DslSelector.tsx
@@ -121,7 +121,7 @@ export class DslSelector extends React.Component<Props, State> {
 
     render() {
         const {parentDsl, isOpen} = this.props;
-        const title = parentDsl === undefined ? "Select source/from" : "Select step";
+        const title = parentDsl === undefined ? "Select source" : "Select step";
         const labelText: string = this.state.tabIndex ? this.state.tabIndex.toString() : "";
         return (
             <Modal
diff --git a/karavan-designer/src/designer/route/RouteDesignerLogic.tsx b/karavan-designer/src/designer/route/RouteDesignerLogic.tsx
index 782b4b29..809ad9fb 100644
--- a/karavan-designer/src/designer/route/RouteDesignerLogic.tsx
+++ b/karavan-designer/src/designer/route/RouteDesignerLogic.tsx
@@ -147,7 +147,7 @@ export class RouteDesignerLogic {
     onPropertyUpdate = debounce((element: CamelElement, newRoute?: RouteToCreate) => {
         if (newRoute) {
             let i = CamelDefinitionApiExt.updateIntegrationRouteElement(this.routeDesigner.state.integration, element);
-            const f = CamelDefinitionApi.createFromDefinition({uri: newRoute.componentName + ":" + newRoute.name})
+            const f = CamelDefinitionApi.createFromDefinition({uri: newRoute.componentName, parameters: {name: newRoute.name}});
             const r = CamelDefinitionApi.createRouteDefinition({from: f, id: newRoute.name})
             i = CamelDefinitionApiExt.addStepToIntegration(i, r, '');
             const clone = CamelUtil.cloneIntegration(i);
diff --git a/karavan-designer/src/designer/route/property/ComponentParameterField.tsx b/karavan-designer/src/designer/route/property/ComponentParameterField.tsx
index e0a6f99f..2a7996df 100644
--- a/karavan-designer/src/designer/route/property/ComponentParameterField.tsx
+++ b/karavan-designer/src/designer/route/property/ComponentParameterField.tsx
@@ -144,7 +144,7 @@ export class ComponentParameterField extends React.Component<Props, State> {
         }
         if (uris && uris.length > 0) {
             selectOptions.push(...uris.map((value: string) =>
-                <SelectOption key={value} value={value.trim()}/>));
+                <SelectOption key={value} value={value ? value.trim() : value}/>));
         }
         return <InputGroup id={this.state.id} name={this.state.id}>
             <Select
@@ -169,9 +169,11 @@ export class ComponentParameterField extends React.Component<Props, State> {
                 {selectOptions}
             </Select>
             <Tooltip position="bottom-end" content={"Create route"}>
-                <Button variant="control" onClick={e => {
-                    const newRoute = !internalUris.includes(value.toString()) ? new RouteToCreate(componentName, value.toString()) : undefined;
-                    this.parametersChanged(property.name, value, property.kind === 'path', newRoute);
+                <Button isDisabled={value === undefined} variant="control" onClick={e => {
+                    if (value) {
+                        const newRoute = !internalUris.includes(value.toString()) ? new RouteToCreate(componentName, value.toString()) : undefined;
+                        this.parametersChanged(property.name, value, property.kind === 'path', newRoute);
+                    }
                 }}>
                     {<PlusIcon/>}
                 </Button>
diff --git a/karavan-designer/src/designer/route/property/DslPropertyField.tsx b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
index d17a26c3..63ff380f 100644
--- a/karavan-designer/src/designer/route/property/DslPropertyField.tsx
+++ b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
@@ -274,7 +274,7 @@ export class DslPropertyField extends React.Component<Props, State> {
                 value={value?.toString()}
                 onChange={e => this.propertyChanged(property.name, CamelUtil.capitalizeName(e?.replace(/\s/g, '')))}/>
             <Tooltip position="bottom-end" content={"Create Java Class"}>
-                <Button variant="control" onClick={e => this.showCode(value, property.javaType)}>
+                <Button isDisabled={value?.length === 0} variant="control" onClick={e => this.showCode(value, property.javaType)}>
                     <PlusIcon/>
                 </Button>
             </Tooltip>
diff --git a/karavan-designer/src/designer/utils/CamelUi.tsx b/karavan-designer/src/designer/utils/CamelUi.tsx
index cb3e988d..05705c39 100644
--- a/karavan-designer/src/designer/utils/CamelUi.tsx
+++ b/karavan-designer/src/designer/utils/CamelUi.tsx
@@ -35,7 +35,7 @@ import {
     ApiIcon,
     AwsIcon,
     AzureIcon,
-    BlockchainIcon,
+    BlockchainIcon, CassandraIcon,
     ChatIcon,
     ChoiceIcon,
     CloudIcon,
@@ -159,18 +159,18 @@ export class RouteToCreate {
 
 export class CamelUi {
 
-    static getSelectorModelTypes = (parentDsl: string | undefined, showSteps: boolean = true, filter:string|undefined = undefined): [string, number][] => {
-        const navs =  CamelUi.getSelectorModelsForParent(parentDsl, showSteps).map(dsl => dsl.navigation.split(","))
+    static getSelectorModelTypes = (parentDsl: string | undefined, showSteps: boolean = true, filter: string | undefined = undefined): [string, number][] => {
+        const navs = CamelUi.getSelectorModelsForParent(parentDsl, showSteps).map(dsl => dsl.navigation.split(","))
             .reduce((accumulator, value) => accumulator.concat(value), [])
             .filter((nav, i, arr) => arr.findIndex(l => l === nav) === i)
-            .filter((nav, i, arr) => ![ 'dataformat'].includes(nav));
+            .filter((nav, i, arr) => !['dataformat'].includes(nav));
         const connectorNavs = ['routing', "transformation", "error", "configuration", "endpoint", "kamelet", "component"];
         const eipLabels = connectorNavs.filter(n => navs.includes(n));
         return eipLabels.map(label => [label, this.getSelectorModelsForParentFiltered(parentDsl, label, true)
             .filter((dsl: DslMetaModel) => filter === undefined ? true : CamelUi.checkFilter(dsl, filter)).length]);
     }
 
-    static checkFilter = (dsl: DslMetaModel, filter:string|undefined = undefined): boolean => {
+    static checkFilter = (dsl: DslMetaModel, filter: string | undefined = undefined): boolean => {
         if (filter !== undefined && filter !== "") {
             return dsl.title.toLowerCase().includes(filter.toLowerCase())
                 || dsl.description.toLowerCase().includes(filter.toLowerCase());
@@ -188,14 +188,15 @@ export class CamelUi {
         return ['GetDefinition', 'PostDefinition', 'PutDefinition', 'PatchDefinition', 'DeleteDefinition', 'HeadDefinition'].map(method => this.getDslMetaModel(method));
     }
 
-    static getSelectorModelsForParentFiltered = (parentDsl: string | undefined, navigation: string,  showSteps: boolean = true): DslMetaModel[] => {
-        const models =  CamelUi.getSelectorModelsForParent(parentDsl, showSteps)
+    static getSelectorModelsForParentFiltered = (parentDsl: string | undefined, navigation: string, showSteps: boolean = true): DslMetaModel[] => {
+        const models = CamelUi.getSelectorModelsForParent(parentDsl, showSteps)
             .filter(dsl => dsl.navigation.includes(navigation));
         return models;
-        }
+    }
+
     static getSelectorModelsForParent = (parentDsl: string | undefined, showSteps: boolean = true): DslMetaModel[] => {
         const result: DslMetaModel[] = [];
-        if (!parentDsl){
+        if (!parentDsl) {
             result.push(...CamelUi.getComponentsDslMetaModel("consumer"));
             result.push(...CamelUi.getKameletDslMetaModel("source"));
         } else {
@@ -222,7 +223,15 @@ export class CamelUi {
 
     static getDslMetaModel = (className: string): DslMetaModel => {
         const el = CamelMetadataApi.getCamelModelMetadataByClassName(className);
-        return  new DslMetaModel({dsl: className, name: el?.name, title: el?.title, description: el?.description, labels: el?.labels, navigation: el?.labels, type: "DSL"})
+        return new DslMetaModel({
+            dsl: className,
+            name: el?.name,
+            title: el?.title,
+            description: el?.description,
+            labels: el?.labels,
+            navigation: el?.labels,
+            type: "DSL"
+        })
     }
 
     static getComponentsDslMetaModel = (type: 'consumer' | "producer"): DslMetaModel[] => {
@@ -282,17 +291,17 @@ export class CamelUi {
     }
 
     static hasDirectUri = (element: CamelElement): boolean => {
-        return this.hasUriStartWith(element,'direct');
+        return this.hasUriStartWith(element, 'direct');
     }
 
     static hasSedaUri = (element: CamelElement): boolean => {
-        return this.hasUriStartWith(element,'seda');
+        return this.hasUriStartWith(element, 'seda');
     }
 
     static hasUriStartWith = (element: CamelElement, text: string): boolean => {
         if ((element as any).uri && typeof (element as any).uri === 'string') {
             return (element as any).uri.startsWith(text);
-        } else if (element.dslName === 'SagaDefinition'){
+        } else if (element.dslName === 'SagaDefinition') {
             const completion = (element as SagaDefinition).completion || '';
             const compensation = (element as SagaDefinition).compensation || '';
             return completion.startsWith(text) || compensation.startsWith(text);
@@ -302,7 +311,7 @@ export class CamelUi {
     }
 
     static getInternalRouteUris = (integration: Integration, componentName: string, showComponentName: boolean = true): string[] => {
-        const result:string[] = [];
+        const result: string[] = [];
         integration.spec.flows?.filter(f => f.dslName === 'RouteDefinition')
             .filter((r: RouteDefinition) => r.from.uri.startsWith(componentName))
             .forEach((r: RouteDefinition) => {
@@ -373,7 +382,7 @@ export class CamelUi {
     }
 
     static isShowExpressionTooltip = (element: CamelElement): boolean => {
-        if (element.hasOwnProperty("expression")){
+        if (element.hasOwnProperty("expression")) {
             const exp = CamelDefinitionApiExt.getExpressionValue((element as any).expression);
             return (exp !== undefined && (exp as any)?.expression?.trim().length > 0);
         }
@@ -382,7 +391,7 @@ export class CamelUi {
 
     static isShowUriTooltip = (element: CamelElement): boolean => {
         const uri: string = (element as any).uri;
-        if (uri !== undefined && !uri.startsWith("kamelet")){
+        if (uri !== undefined && !uri.startsWith("kamelet")) {
             return ComponentApi.getComponentNameFromUri(uri) !== uri;
         }
         return false;
@@ -509,7 +518,7 @@ export class CamelUi {
                 return "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIGlkPSJpY29uIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO308L3N0eWxlPjwvZGVmcz48dGl0bGU+d2FybmluZzwvdGl0bGU+PHBhdGggZD0iTTE2LDJBMTQsMTQsMCwxLDAsMzAsMTYsMTQsMTQsMCwwLDAsMTYsMlptMCwyNkExMiwxMiwwLDEsMSwyOCwxNiwxMiwxMiwwLDAsMSwxNiwyOFoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgMCkiLz48cmVjdCB4PSIxNSIgeT0iOCIgd2lkdGg9IjIiIGhlaWdodD0iMTEiLz48cG [...]
             case "ScriptDefinition":
                 return "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjU2cHgiIGhlaWdodD0iMjU2cHgiIHZpZXdCb3g9IjAgMCAyNTYgMjU2IiBpZD0iRmxhdCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cGF0aCBkPSJNNDMuMTc1MjksMTI4YTI5Ljc4NTIsMjkuNzg1MiwwLDAsMSw4LjAyMywxMC4yNTk3N0M1NiwxNDguMTYzMDksNTYsMTYwLjI4MTI1LDU2LDE3MmMwLDI0LjMxMzQ4LDEuMDE5NTMsMzYsMjQsMzZhOCw4LDAsMCwxLDAsMTZjLTE3LjQ4MTQ1LDAtMjkuMzI0MjItNi4xNDM1NS0zNS4xOTgyNC0xOC4yNTk3N0M0MCwxOTUuODM2OTEsNDAsMTgzLjcxODc1LDQwLDE3MmMwLTI0LjMxMzQ4LT [...]
-           case "PausableDefinition":
+            case "PausableDefinition":
                 return "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIGlkPSJpY29uIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO308L3N0eWxlPjwvZGVmcz48dGl0bGU+cGF1c2UtLWZpbGxlZDwvdGl0bGU+PHBhdGggZD0iTTEyLDZIMTBBMiwyLDAsMCwwLDgsOFYyNGEyLDIsMCwwLDAsMiwyaDJhMiwyLDAsMCwwLDItMlY4YTIsMiwwLDAsMC0yLTJaIi8+PHBhdGggZD0iTTIyLDZIMjBhMiwyLDAsMCwwLTIsMlYyNGEyLDIsMCwwLDAsMiwyaDJhMiwyLDAsMCwwLDItMlY4YTIsMiwwLDAsMC [...]
             case "StopDefinition":
                 return "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIGlkPSJpY29uIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO308L3N0eWxlPjwvZGVmcz48dGl0bGU+c3RvcC0tZmlsbGVkPC90aXRsZT48cGF0aCBkPSJNMjQsNkg4QTIsMiwwLDAsMCw2LDhWMjRhMiwyLDAsMCwwLDIsMkgyNGEyLDIsMCwwLDAsMi0yVjhhMiwyLDAsMCwwLTItMloiLz48cmVjdCBpZD0iX1RyYW5zcGFyZW50X1JlY3RhbmdsZV8iIGRhdGEtbmFtZT0iJmx0O1RyYW5zcGFyZW50IFJlY3RhbmdsZSZndDsiIG [...]
@@ -530,20 +539,20 @@ export class CamelUi {
         }
     }
 
-    static getIconForDsl = (dsl: DslMetaModel):JSX.Element => {
+    static getIconForDsl = (dsl: DslMetaModel): JSX.Element => {
         if (dsl.dsl && (dsl.dsl === "KameletDefinition" || dsl.navigation === 'kamelet')) {
             return this.getIconFromSource(CamelUi.getKameletIconByName(dsl.name));
         } else if ((dsl.dsl && dsl.dsl === "FromDefinition")
             && dsl.uri?.startsWith("kamelet")) {
             return this.getIconFromSource(CamelUi.getKameletIconByUri(dsl.uri));
-        } else if (dsl.navigation === 'component' ){
+        } else if (dsl.navigation === 'component') {
             return CamelUi.getIconForComponent(dsl.title, dsl.labels);
         } else {
             return CamelUi.getIconForDslName(dsl.dsl);
         }
     }
 
-    static getIconForComponent = (title: string, label: string):JSX.Element => {
+    static getIconForComponent = (title: string, label: string): JSX.Element => {
         const labels = label.split(",");
         if (title === "Ref") {
             return RefIcon();
@@ -583,86 +592,88 @@ export class CamelUi {
             return GithubIcon();
         } else if (title.startsWith("Git")) {
             return GitIcon();
+        } else if (title.startsWith("Cassandra")) {
+            return CassandraIcon();
         } else if (title.startsWith("Hazelcast")) {
             return HazelcastIcon();
         } else if (title.startsWith("FHIR") || title.startsWith("MLLP")) {
             return HealthIcon();
         } else if (labels.includes('transformation')) {
             return TransformationIcon();
-        } else if (labels.includes("validation")){
+        } else if (labels.includes("validation")) {
             return ValidationIcon();
-        } else if (labels.includes("scheduling")){
+        } else if (labels.includes("scheduling")) {
             return SchedulingIcon();
-        } else if (labels.includes("database")){
+        } else if (labels.includes("database")) {
             return DatabaseIcon();
-        } else if (labels.includes("cloud")){
+        } else if (labels.includes("cloud")) {
             return CloudIcon();
-        } else if (labels.includes("chat")){
+        } else if (labels.includes("chat")) {
             return ChatIcon();
-        } else if (labels.includes("messaging")){
+        } else if (labels.includes("messaging")) {
             return MessagingIcon();
-        } else if (labels.includes("script")){
+        } else if (labels.includes("script")) {
             return ScriptIcon();
-        } else if (labels.includes("file")){
+        } else if (labels.includes("file")) {
             return FileIcon();
-        } else if (labels.includes("monitoring")){
+        } else if (labels.includes("monitoring")) {
             return MonitoringIcon();
-        } else if (labels.includes("iot")){
+        } else if (labels.includes("iot")) {
             return IotIcon();
-        } else if (labels.includes("mail")){
+        } else if (labels.includes("mail")) {
             return MailIcon();
-        } else if (labels.includes("http")){
+        } else if (labels.includes("http")) {
             return HttpIcon();
-        } else if (labels.includes("document")){
+        } else if (labels.includes("document")) {
             return DocumentIcon();
-        } else if (labels.includes("social")){
+        } else if (labels.includes("social")) {
             return SocialIcon();
-        } else if (labels.includes("networking")){
+        } else if (labels.includes("networking")) {
             return NetworkingIcon();
-        } else if (labels.includes("api")){
+        } else if (labels.includes("api")) {
             return ApiIcon();
-        } else if (labels.includes("testing")){
+        } else if (labels.includes("testing")) {
             return TestingIcon();
-        } else if (labels.includes("clustering")){
+        } else if (labels.includes("clustering")) {
             return ClusterIcon();
-        } else if (labels.includes("mobile")){
+        } else if (labels.includes("mobile")) {
             return MobileIcon();
-        } else if (labels.includes("workflow")){
+        } else if (labels.includes("workflow")) {
             return WorkflowIcon();
-        } else if (labels.includes("webservice") || labels.includes("rest")){
+        } else if (labels.includes("webservice") || labels.includes("rest")) {
             return WebserviceIcon();
-        } else if (labels.includes("search")){
+        } else if (labels.includes("search")) {
             return SearchIcon();
-        } else if (labels.includes("blockchain")){
+        } else if (labels.includes("blockchain")) {
             return BlockchainIcon();
-        } else if (labels.includes("ai")){
+        } else if (labels.includes("ai")) {
             return MachineLearningIcon();
-        } else if (labels.includes("rpc")){
+        } else if (labels.includes("rpc")) {
             return RpcIcon();
         } else {
             return this.getIconFromSource(camelIcon);
         }
     }
 
-    static isElementInternalComponent = (element: CamelElement):boolean => {
+    static isElementInternalComponent = (element: CamelElement): boolean => {
         const uri = (element as any).uri;
         const component = ComponentApi.findByName(uri);
         return component !== undefined && CamelUi.isComponentInternal(component.component.label);
     }
 
-    static isComponentInternal = (label: string):boolean => {
+    static isComponentInternal = (label: string): boolean => {
         const labels = label.split(",");
         if (labels.includes('core') && (
-                labels.includes('transformation')
-                || labels.includes('testing')
-                || labels.includes('scheduling')
-                || labels.includes('monitoring')
-                || labels.includes('transformation')
-                || labels.includes('java')
-                || labels.includes('endpoint')
-                || labels.includes('script')
-                || labels.includes('validation')
-            )) {
+            labels.includes('transformation')
+            || labels.includes('testing')
+            || labels.includes('scheduling')
+            || labels.includes('monitoring')
+            || labels.includes('transformation')
+            || labels.includes('java')
+            || labels.includes('endpoint')
+            || labels.includes('script')
+            || labels.includes('validation')
+        )) {
             return true;
         } else if (label === 'transformation') {
             return true;
@@ -670,7 +681,7 @@ export class CamelUi {
         return false;
     }
 
-    static getIconForElement = (element: CamelElement):JSX.Element => {
+    static getIconForElement = (element: CamelElement): JSX.Element => {
         const uri = (element as any).uri;
         const component = ComponentApi.findByName(uri);
         const k: KameletModel | undefined = CamelUtil.getKamelet(element);
@@ -686,34 +697,45 @@ export class CamelUi {
             return this.getIconForDslName(element.dslName);
         }
     }
-    static getIconForDslName = (dslName: string):JSX.Element => {
+    static getIconForDslName = (dslName: string): JSX.Element => {
         switch (dslName) {
-            case 'AggregateDefinition': return <AggregateIcon/>;
-            case 'ChoiceDefinition' :return <ChoiceIcon/>;
-            case 'SplitDefinition' :return <SplitIcon/>;
-            case 'SagaDefinition' :return <SagaIcon/>;
-            case 'FilterDefinition' :return <FilterIcon/>;
-            case 'SortDefinition' :return <SortIcon/>;
-            case 'OnCompletionDefinition' :return <OnCompletion/>;
-            case 'InterceptDefinition' :return <Intercept/>;
-            case 'InterceptFromDefinition' :return <InterceptFrom/>;
-            case 'InterceptSendToEndpointDefinition' :return <InterceptSendToEndpoint/>;
-            default: return this.getIconFromSource(CamelUi.getIconSrcForName(dslName))
+            case 'AggregateDefinition':
+                return <AggregateIcon/>;
+            case 'ChoiceDefinition' :
+                return <ChoiceIcon/>;
+            case 'SplitDefinition' :
+                return <SplitIcon/>;
+            case 'SagaDefinition' :
+                return <SagaIcon/>;
+            case 'FilterDefinition' :
+                return <FilterIcon/>;
+            case 'SortDefinition' :
+                return <SortIcon/>;
+            case 'OnCompletionDefinition' :
+                return <OnCompletion/>;
+            case 'InterceptDefinition' :
+                return <Intercept/>;
+            case 'InterceptFromDefinition' :
+                return <InterceptFrom/>;
+            case 'InterceptSendToEndpointDefinition' :
+                return <InterceptSendToEndpoint/>;
+            default:
+                return this.getIconFromSource(CamelUi.getIconSrcForName(dslName))
         }
     }
 
-    static getIconFromSource = (src: string):JSX.Element => {
+    static getIconFromSource = (src: string): JSX.Element => {
         return <img draggable={false} src={src} className="icon" alt="icon"/>
     }
 
-    static getConnectionIcon = (element: CamelElement): JSX.Element  => {
+    static getConnectionIcon = (element: CamelElement): JSX.Element => {
         const k: KameletModel | undefined = CamelUtil.getKamelet(element);
         const uri = (element as any).uri;
         const component = ComponentApi.findByName(uri);
         if (component) {
             return CamelUi.getIconForComponent(component.component.title, component.component.label);
-        } else  if (["FromDefinition", "KameletDefinition"].includes(element.dslName)) {
-            const icon =  k ? k.icon() : externalIcon;
+        } else if (["FromDefinition", "KameletDefinition"].includes(element.dslName)) {
+            const icon = k ? k.icon() : externalIcon;
             return <img src={icon} className="icon"/>
         } else if (element.dslName === "ToDefinition" && (element as ToDefinition).uri?.startsWith("kamelet:")) {
             const icon = k ? k.icon() : CamelUi.getIconSrcForName(element.dslName);
@@ -740,7 +762,7 @@ export class CamelUi {
         result.set('rest', i.spec.flows?.filter((e: any) => e.dslName === 'RestDefinition').length || 0);
         result.set('routeConfiguration', i.spec.flows?.filter((e: any) => e.dslName === 'RouteConfigurationDefinition').length || 0);
         const beans = i.spec.flows?.filter((e: any) => e.dslName === 'Beans');
-        if (beans && beans.length > 0 && beans[0].beans && beans[0].beans.length > 0){
+        if (beans && beans.length > 0 && beans[0].beans && beans[0].beans.length > 0) {
             result.set('beans', Array.from(beans[0].beans).length);
         }
         return result;
diff --git a/karavan-designer/src/designer/utils/KaravanIcons.tsx b/karavan-designer/src/designer/utils/KaravanIcons.tsx
index 3e0b6953..b7228640 100644
--- a/karavan-designer/src/designer/utils/KaravanIcons.tsx
+++ b/karavan-designer/src/designer/utils/KaravanIcons.tsx
@@ -936,6 +936,95 @@ export function GithubIcon() {
             <path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16. [...]
         </svg>
     );
+}export function CassandraIcon() {
+    return (
+        <svg
+            xmlns="http://www.w3.org/2000/svg"
+            xmlnsXlink="http://www.w3.org/1999/xlink"
+            width={113.636}
+            height={58.899}
+            viewBox="0 0 113.63554 58.899029"
+            className="icon">
+            <defs>
+                <path id="a" d="M24.216.082v24.141H.053V.082z" />
+            </defs>
+            <g
+                style={{
+                    fill: "none",
+                    fillRule: "evenodd",
+                    stroke: "none",
+                    strokeWidth: 1,
+                }}
+            >
+                <path
+                    fill="#bbe6fb"
+                    d="M90.565 20.787C91.4 30.202 76.112 39.163 56.422 40.8c-19.69 1.638-36.329-4.669-37.162-14.083C18.426 17.3 33.713 8.34 53.404 6.702c19.69-1.636 36.329 4.669 37.161 14.085"
+                />
+                <path
+                    fill="#fff"
+                    d="M53.334 6.75c-4.16-.255-11.326 1.915-17.302 4.08a17.762 17.762 0 0 0-1.413 6.948c0 10.096 9.154 18.28 18.837 18.28 9.62 0 18.13-8.197 18.836-18.28.23-3.283-.9-6.377-2.47-9.044-6.196-1.091-12.771-1.758-16.488-1.984"
+                />
+                <image
+                    xlinkHref="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUwAAADqCAYAAADJXHwYAAAABGdBTUEAALGOfPtRkwAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAABTKADAAQAAAABAAAA6gAAAAAGjBs3AAAWs0lEQVR4Ae2d+dPctAGG+SABQkI5AyFQ7hZaekA7nbbT0v7J/bkz7bRQGGDKGaCcIRAg5CBAIBchJH3fjfxh79q78q4P2X40o3hty7b02N8T2ZLlrasIEGiIwOXLl7e0qxtCvF7Ta0K8Ovc7W1Y2XZbO6y4pXlT8Pkzzv7Nl2bTuuotbW1uXtV8CBCoJ+AInQCCKgIR4rRJaiLvDNP/by3YpDvmamhdyJt9sWiZhL3P8NsTzYXoBAYvEyMKQL+6RnYp+i5O [...]
+                    width={43.164}
+                    height={31.532}
+                    x={31.672}
+                    y={6.587}
+                    opacity={0.596}
+                />
+                <path
+                    fill="#373535"
+                    d="M42.663 16.453c.51-1.13 1.282-1.683 2.031-2.63-.083-.224-.265-.958-.265-1.212 0-1.128.928-2.056 2.056-2.056.26 0 .517.05.758.146a14.985 14.985 0 0 1 13.597-2.39c-4.45-.617-9.466.96-12.878 3.713.104.246.393.949.393 1.232 0 1.135-.735 1.411-1.87 1.411-.258 0-.504-.05-.732-.136-.771 1.035-1.715 3.006-2.178 4.239 1.887 1.687 3.592 2.299 5.813 3.13-.006-.106.076-.205.076-.312 0-3.424 3.014-6.206 6.438-6.206a6.195 6.195 0 0 1 6.105 5.158c1.53-.974 3.01-1.72 4.139-3.164-. [...]
+                />
+                <path
+                    fill="#373535"
+                    d="M68.25 14.909c.303.265.555.58.748.932.502.9-.503 1.724-1.533 1.724a1.846 1.846 0 0 1-.306-.031c-1.161 1.814-3.194 4.14-5 5.311 2.769.454 5.38 1.563 7.46 3.277 1.513-2.711 2.673-6.627 2.673-9.953 0-2.532-1.117-4.387-2.804-5.748-.089 1.356-.813 3.252-1.236 4.488M45.77 32.084c.922-2.549 3.192-4.524 5.34-6.26-.315-.43-.786-1.496-.982-2a15.027 15.027 0 0 1-6.733-4.261l-.044.17a13.62 13.62 0 0 0-.232 4.52 2.709 2.709 0 0 1 2.203 2.654c0 .783-.687 1.92-1.22 2.414.58 1.25. [...]
+                />
+                <path
+                    fill="#373535"
+                    d="M45.607 34.222c-1.1-1.094-1.862-3.277-2.576-4.648a2.707 2.707 0 0 1-.41.035c-1.494 0-3.058-1.253-2.704-2.702.196-.803.75-1.327 1.652-1.765-.206-1.662-.261-4.051.124-5.78.111-.494.345-.726.5-1.196-1.647-2.41-2.711-5.574-2.711-8.713 0-.115.005-.228.008-.342-2.783 1.396-4.87 3.595-4.87 7.058 0 7.659 4.41 15.171 10.973 18.116l.014-.062m16.138-10.588a6.196 6.196 0 0 1-5.843 4.145 6.167 6.167 0 0 1-3.826-1.327c-2.173 1.692-4.143 4.664-5.145 7.242.45.484.763.882 1.267 1.3 [...]
+                />
+                <path
+                    fill="#1287b1"
+                    d="M42.493 17.348a14.975 14.975 0 0 1 1.898-3.122 2.057 2.057 0 0 1-.132-.72c0-1.127.929-2.056 2.056-2.056.26 0 .517.05.758.147A14.985 14.985 0 0 1 59.46 8.879c.407.093.811.202 1.21.328-4.45-.617-9.048.747-12.46 3.5.107.253.162.525.162.799a2.066 2.066 0 0 1-2.056 2.056 2.05 2.05 0 0 1-.733-.136 13.841 13.841 0 0 0-1.863 3.412c1.62 1.746 3.61 3.127 5.83 3.957-.005-.106-.016-.21-.016-.319a6.195 6.195 0 0 1 12.303-1.04 16.065 16.065 0 0 0 4.019-3.669 1.843 1.843 0 0 1-.4 [...]
+                />
+                <path
+                    fill="#1287b1"
+                    d="M68.54 15.214c.394.35.62.852.622 1.38a1.876 1.876 0 0 1-1.866 1.866 1.85 1.85 0 0 1-.307-.032 15.102 15.102 0 0 1-4.506 4.533 15.09 15.09 0 0 1 7.261 3.263 18.739 18.739 0 0 0 2.379-9.16c0-2.532-1.118-4.387-2.805-5.748a15.01 15.01 0 0 1-.778 3.898M46.054 32.696a15.04 15.04 0 0 1 4.674-6.572 6.186 6.186 0 0 1-.77-1.406 15.025 15.025 0 0 1-6.733-4.26c-.013.057-.03.113-.043.17a13.593 13.593 0 0 0-.232 4.52 2.71 2.71 0 0 1 2.203 2.653c0 .754-.316 1.473-.87 1.984a16.22  [...]
+                />
+                <path
+                    fill="#1287b1"
+                    d="M45.6 34.192a15.07 15.07 0 0 1-2.739-3.722 2.704 2.704 0 0 1-.41.034h-.004c-1.482 0-2.7-1.219-2.7-2.7 0-1.035.594-1.983 1.526-2.432-.273-2.209-.05-4.45.651-6.561a14.95 14.95 0 0 1-2.612-8.463c0-.115.006-.228.008-.341-2.783 1.395-4.87 3.595-4.87 7.057 0 7.659 4.573 14.245 11.136 17.19l.014-.062m15.976-9.661a6.198 6.198 0 0 1-5.843 4.144 6.17 6.17 0 0 1-3.826-1.327c-2.173 1.692-3.813 3.998-4.814 6.577.45.484.929.941 1.433 1.369 1.555.404 3.154.608 4.76.607 6.617 0 12 [...]
+                />
+                <g transform="translate(43.304 10.642)">
+                    <mask id="b" fill="#fff">
+                        <use xlinkHref="#a" />
+                    </mask>
+                    <path
+                        fill="#fff"
+                        d="M14.783 6.242 14.704.147l-2.251 5.43L10.576.081l.101 6.472L7.433.753l1.755 6.16-5.262-3.827 4.122 5.18-6.533-2.403 5.156 3.815-6.612.203 6.76 1.745L.053 13.09l6.68.484L1.1 17.18l5.8-2.103-4.024 5.097 5.085-4.101-1.832 6.838 3.926-5.565-.55 6.573 2.228-5.958 1.897 6.262.461-6.281 2.815 5.36-1.663-6.131 5.155 3.993-3.328-5.091 5.656 2.203-4.325-4.25 5.8.456-5.712-2.192 5.727-1.366-5.748-.293 4.678-3.575-5.309 1.903 3.608-5-4.983 3.312 1.743-5.852z"
+                        mask="url(#b)"
+                    />
+                </g>
+                <image
+                    xlinkHref="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAx4AAADpCAYAAACqReECAAAABGdBTUEAALGOfPtRkwAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAADHqADAAQAAAABAAAA6QAAAADa02YqAABAAElEQVR4Ae292XcT19ruq6qS5B4bm76zMQYSDAZ34AYSyPedMc4a5+Jc5a/M7R5f9l5NFknArYwNiUnnhU2T0BuDbdlqStrPKyQjy2qqpKpSSXpqDLBUzWx+s1Q13/l2Hg83EiABEiABEiABEqhRAn19fU1ff/21VqPdZ7dJgARIgARIgARIgARIgATsJjA4ONg4MjLSZXc9LJ8ESIAESIAESIAESIAESMABAjdv3vSiGsWBqgxX0dvb67969eoNXKAavog [...]
+                    width={111.814}
+                    height={32.542}
+                    x={1.822}
+                    y={1.682}
+                    opacity={0.487}
+                />
+                <path
+                    fill="#373535"
+                    d="M46.372 6.794c1.704-.331 2.026-4.053 2.026-4.053s.238 2.743 1.43 3.1c1.193.357 2.742-4.291 2.742-4.291s-1.43 4.172 0 4.41c1.43.238 4.053-4.053 4.053-4.053s-1.072 3.695-.358 3.933c.715.239 4.291-5.364 4.291-5.364s-2.145 3.695-.119 4.053c2.027.358 4.984-2.521 4.984-2.521s-2.325 2.634-1.289 2.998c4.412 1.55 7.98-4.183 7.98-4.183s-.827 2.514-2.972 5.256C73.788 7.27 77.24.267 77.24.267L73.788 7.27C75.576 8.224 82.728 0 82.728 0s-3.694 6.436-5.84 7.747c1.192.954 5.483-2. [...]
+                />
+                <path
+                    fill="#373535"
+                    d="M0 34.76c9.388 4.71 17.97-.714 28.788 2.334 8.224 2.318 18.239 5.176 31.828 3.209 13.589-1.967 25.21-7.867 30.755-18.416 1.728-4.709 8.76 1.072 8.76 1.072s-5.125-2.145-5.006-1.132c.12 1.013 7.689 4.53 7.689 4.53s-6.855-2.146-6.437-.536c.417 1.608 8.583 8.045 8.583 8.045s-9.239-7.033-10.013-6.079c-.775.953 3.933 4.828 3.933 4.828s-7.808-4.828-10.55-3.405c-1.972 1.024 8.106 7.637 8.106 7.637S89.88 31.84 88.33 33.15c-1.55 1.312 7.391 12.04 7.391 12.04S85.588 34.223 84 [...]
+                />
+            </g>
+        </svg>
+    );
 }
 export function ActivemqIcon() {
     return (
diff --git a/karavan-designer/src/knowledgebase/components/ComponentsTab.tsx b/karavan-designer/src/knowledgebase/components/ComponentsTab.tsx
index 171efc5c..c2a75b7a 100644
--- a/karavan-designer/src/knowledgebase/components/ComponentsTab.tsx
+++ b/karavan-designer/src/knowledgebase/components/ComponentsTab.tsx
@@ -59,7 +59,11 @@ export class ComponentsTab extends React.Component<Props, State> {
     render() {
         const component = this.state.component;
         const {filter} = this.props;
-        const components = ComponentApi.getComponents().filter(c => c.component.name.toLowerCase().includes(filter.toLowerCase()));
+        const components = ComponentApi.getComponents().filter(c => {
+            return c.component.name.toLowerCase().includes(filter.toLowerCase())
+            || c.component.title.toLowerCase().includes(filter.toLowerCase())
+            || c.component.description.toLowerCase().includes(filter.toLowerCase())
+        }).sort((a, b) => (a.component.title?.toLowerCase() > b.component.title?.toLowerCase() ? 1 : -1)) ;
         return (
             <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
                 <ComponentModal key={component?.component.name + this.state.isModalOpen.toString()}