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 a86356a8 Change for the issue - #979, to configure allowed components 
and kamelets (#1113)
a86356a8 is described below

commit a86356a84b6c003927778297483180bcd82ea429
Author: Vidhya Sagar <36588343+vidhyasag...@users.noreply.github.com>
AuthorDate: Tue Feb 20 05:32:50 2024 +0800

    Change for the issue - #979, to configure allowed components and kamelets 
(#1113)
    
    * fix#979 - implementation of blocked components and kamelets
    
    * fix#979 -removed debugger
    
    * Block list save in file implemented
    
    * removed  space changes by format.
    
    * space changes reverted
    
    * infinispan spaces reverted
    
    * Vs code changes to save blocked lists in file .
    
    * review comments fixed in designer and space
    
    * block lists moved to settings folder
    
    ---------
    
    Co-authored-by: induja <induja.b...@gmail.com>
---
 karavan-core/src/core/api/ComponentApi.ts          | 25 ++++++++++++-
 karavan-core/src/core/api/KameletApi.ts            | 22 +++++++++++-
 karavan-designer/src/App.tsx                       | 21 +++++++----
 karavan-designer/src/KnowledgebaseHome.tsx         | 23 ++++++++++++
 karavan-designer/src/designer/karavan.css          |  9 +++--
 .../src/designer/route/DslSelector.tsx             |  9 ++++-
 .../src/knowledgebase/KnowledgebasePage.tsx        |  5 +--
 .../src/knowledgebase/components/ComponentCard.tsx | 28 +++++++++++----
 .../src/knowledgebase/components/ComponentsTab.tsx |  3 +-
 .../src/knowledgebase/kamelets/KameletCard.tsx     | 26 ++++++++++----
 .../src/knowledgebase/kamelets/KameletsTab.tsx     |  8 ++---
 karavan-space/src/App.tsx                          | 22 ++++++++++--
 karavan-space/src/designer/karavan.css             | 11 +++++-
 karavan-space/src/designer/route/DslSelector.tsx   |  9 ++++-
 .../src/knowledgebase/KnowledgebasePage.tsx        |  5 +--
 .../src/knowledgebase/components/ComponentCard.tsx | 28 +++++++++++----
 .../src/knowledgebase/components/ComponentsTab.tsx |  3 +-
 .../src/knowledgebase/kamelets/KameletCard.tsx     | 26 ++++++++++----
 .../src/knowledgebase/kamelets/KameletsTab.tsx     |  8 ++---
 karavan-vscode/package.json                        | 13 +++++--
 karavan-vscode/settings/components-blocklist.txt   |  0
 karavan-vscode/settings/kamelets-blocklist.txt     |  0
 karavan-vscode/src/designerView.ts                 |  4 +++
 karavan-vscode/src/helpView.ts                     |  9 ++++-
 karavan-vscode/src/utils.ts                        | 25 ++++++++++++-
 karavan-vscode/webview/App.tsx                     | 27 +++++++++++++-
 .../camel/karavan/api/ComponentResources.java      |  2 +-
 .../org/apache/camel/karavan/code/CodeService.java |  2 ++
 .../resources/snippets/components-blocklist.txt    |  0
 .../main/resources/snippets/kamelets-blocklist.txt |  0
 .../src/main/webui/src/api/ProjectService.ts       | 17 +++++++--
 .../src/main/webui/src/designer/karavan.css        | 11 +++++-
 .../main/webui/src/designer/route/DslSelector.tsx  |  9 ++++-
 .../webui/src/knowledgebase/KnowledgebaseHome.tsx  | 41 ++++++++++++++++++++++
 .../webui/src/knowledgebase/KnowledgebasePage.tsx  |  5 +--
 .../src/knowledgebase/components/ComponentCard.tsx | 28 +++++++++++----
 .../src/knowledgebase/components/ComponentsTab.tsx |  3 +-
 .../src/knowledgebase/kamelets/KameletCard.tsx     | 26 ++++++++++----
 .../src/knowledgebase/kamelets/KameletsTab.tsx     |  8 ++---
 .../src/main/webui/src/main/MainRoutes.tsx         |  4 +--
 .../src/main/webui/src/main/useMainHook.tsx        |  4 ++-
 41 files changed, 434 insertions(+), 95 deletions(-)

diff --git a/karavan-core/src/core/api/ComponentApi.ts 
b/karavan-core/src/core/api/ComponentApi.ts
index da9b9be1..3a390c6c 100644
--- a/karavan-core/src/core/api/ComponentApi.ts
+++ b/karavan-core/src/core/api/ComponentApi.ts
@@ -20,7 +20,7 @@ import { CamelElement } from '../model/IntegrationDefinition';
 const Components: Component[] = [];
 const SupportedComponents: SupportedComponent[] = [];
 let SupportedOnly: boolean = false;
-
+const BlockedComponents: string[] = [];
 export class ComponentApi {
     private constructor() {}
 
@@ -339,4 +339,27 @@ export class ComponentApi {
         }
         return Array.from(new Map(properties.map(item => [item.name, 
item])).values());
     };
+
+
+    static saveBlockedComponentNames = (componentNames: string[]) => {
+        BlockedComponents.length = 0;
+        BlockedComponents.push(...componentNames);
+    }
+
+
+    static saveBlockedComponentName = (componentName: string, checked 
:boolean) => {
+        const index = BlockedComponents.indexOf(componentName);
+        if (!checked && index === -1) {
+            BlockedComponents.push(componentName);
+        }
+        else if (checked && index > -1) {
+            BlockedComponents.splice(index, 1);
+        }
+        return BlockedComponents;
+    }
+
+
+    static getBlockedComponentNames = () => {
+        return BlockedComponents;
+    }
 }
diff --git a/karavan-core/src/core/api/KameletApi.ts 
b/karavan-core/src/core/api/KameletApi.ts
index 62ecb4f2..acccea33 100644
--- a/karavan-core/src/core/api/KameletApi.ts
+++ b/karavan-core/src/core/api/KameletApi.ts
@@ -19,7 +19,7 @@ import * as yaml from 'js-yaml';
 
 const Kamelets: KameletModel[] = [];
 const CustomNames: string[] = [];
-
+const BlockedKamelets: string[] = [];
 export class KameletApi {
     private constructor() {}
 
@@ -99,4 +99,24 @@ export class KameletApi {
             Kamelets.push(kamelet);
         }
     };
+    
+    static saveBlockedKameletNames = (names: string[]): void => {
+        BlockedKamelets.length = 0;
+        BlockedKamelets.push(...names);
+    }
+
+    static saveBlockedKameletName = (name: string, checked: boolean) => {
+        const index = BlockedKamelets.indexOf(name);
+        if ( !checked && index === -1) {
+            BlockedKamelets.push(name);
+        }
+        else if ( checked && index > -1) {
+            BlockedKamelets.splice(index, 1);
+        }
+        return BlockedKamelets;
+    }
+    
+    static getBlockedKameletNames = () => {
+        return BlockedKamelets;
+    }
 }
diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index 46894d94..e2d9803c 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -37,10 +37,10 @@ import {KaravanIcon} from "./designer/icons/KaravanIcons";
 import './designer/karavan.css';
 import {DesignerPage} from "./DesignerPage";
 import {TemplateApi} from "karavan-core/lib/api/TemplateApi";
-import {KnowledgebasePage} from "./knowledgebase/KnowledgebasePage";
 import {Notification} from "./designer/utils/Notification";
 import {EventBus} from "./designer/utils/EventBus";
 import {TopologyTab} from "./topology/TopologyTab";
+import {KnowledgebaseHome} from "./KnowledgebaseHome";
 import {useEffect, useState} from "react";
 import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition";
 
@@ -70,10 +70,13 @@ export function App() {
             fetch("components/components.json"),
             fetch("snippets/org.apache.camel.AggregationStrategy"),
             fetch("snippets/org.apache.camel.Processor"),
-            fetch("example/demo.camel.yaml")
+            fetch("example/demo.camel.yaml"),
+            fetch("components/blocked-components.properties"),
+            fetch("kamelets/blocked-kamelets.properties")
             // fetch("example/aws-cloudwatch-sink.kamelet.yaml")
             // fetch("example/aws-s3-cdc-source.kamelet.yaml")
-            // fetch("components/supported-components.json"),
+            //fetch("components/supported-components.json"),
+            
         ]).then(responses =>
             Promise.all(responses.map(response => response.text()))
         ).then(data => {
@@ -94,11 +97,17 @@ export function App() {
                 setYaml(data[4]);
                 setName("demo.camel.yaml");
             }
-
             if (data[5]) {
-                ComponentApi.saveSupportedComponents(data[4]);
+                ComponentApi.saveBlockedComponentNames(data[5].split('\r\n'));
+            }
+            if (data[6]) {
+                KameletApi.saveBlockedKameletNames(data[6].split('\n'));
+            }
+               if (data[7]) {
+                ComponentApi.saveSupportedComponents(data[7]);
                 ComponentApi.setSupportedOnly(true);
             }
+           
         }).catch(err =>
             EventBus.sendAlert("Error", err.text, 'danger')
         );
@@ -159,7 +168,7 @@ export function App() {
                 )
             case "knowledgebase":
                 return (
-                    <KnowledgebasePage dark={dark}/>
+                    <KnowledgebaseHome dark={dark}/>
                 )
             case "topology":
                 return (
diff --git a/karavan-designer/src/KnowledgebaseHome.tsx 
b/karavan-designer/src/KnowledgebaseHome.tsx
new file mode 100644
index 00000000..7c8719ca
--- /dev/null
+++ b/karavan-designer/src/KnowledgebaseHome.tsx
@@ -0,0 +1,23 @@
+import { useEffect, useState } from "react";
+import { KnowledgebasePage } from "./knowledgebase/KnowledgebasePage"
+import { ComponentApi } from "karavan-core/lib/api/ComponentApi";
+import { KameletApi } from "karavan-core/lib/api/KameletApi";
+interface Props {
+    dark: boolean,
+}
+export const KnowledgebaseHome = (props: Props) => {
+   
+
+    const onchangeBlockedList = (type: string, name: string, checked: boolean) 
=> {
+        if (type === 'kamelet') {
+
+            const blockedKamelet = KameletApi.saveBlockedKameletName(name, 
checked);
+        }
+        else if (type === 'component') {
+            const blockedComponent = 
ComponentApi.saveBlockedComponentName(name, checked);
+        }
+    }
+    return (
+        <KnowledgebasePage dark={props.dark} changeBlockList={(type: string, 
name: string, checked: boolean) => onchangeBlockedList(type, name, checked)}  />
+    );
+}
\ No newline at end of file
diff --git a/karavan-designer/src/designer/karavan.css 
b/karavan-designer/src/designer/karavan.css
index 4d9a7162..78b2a135 100644
--- a/karavan-designer/src/designer/karavan.css
+++ b/karavan-designer/src/designer/karavan.css
@@ -189,7 +189,12 @@
     padding: 5px;
     display: flex;
     flex-direction: row;
-    justify-content: flex-end;
+    justify-content:flex-end;
+}
+.kamelets-page .kamelet-card .header-labels .pf-v5-c-card__header-main{
+    display: flex;
+    flex-direction: row;
+    justify-content:space-between;
 }
 
 .kamelets-page .kamelet-card .footer-labels {
@@ -813,4 +818,4 @@
 }
 .karavan .knowledbase-eip-section .pf-v5-c-toggle-group{
     margin:16px;
-}
\ No newline at end of file
+}
diff --git a/karavan-designer/src/designer/route/DslSelector.tsx 
b/karavan-designer/src/designer/route/DslSelector.tsx
index a80525ba..27093f25 100644
--- a/karavan-designer/src/designer/route/DslSelector.tsx
+++ b/karavan-designer/src/designer/route/DslSelector.tsx
@@ -27,6 +27,8 @@ import {DslMetaModel} from "../utils/DslMetaModel";
 import {useDesignerStore, useIntegrationStore, useSelectorStore} from 
"../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {useRouteDesignerHook} from "./useRouteDesignerHook";
+import { ComponentApi } from 'karavan-core/lib/api/ComponentApi';
+import { KameletApi } from 'karavan-core/lib/api/KameletApi';
 
 interface Props {
     tabIndex?: string | number
@@ -119,9 +121,14 @@ export function DslSelector (props: Props) {
     const isEip = selectorTabIndex === 'eip';
     const title = parentDsl === undefined ? "Select source" : "Select step";
     const navigation: string = selectorTabIndex ? selectorTabIndex.toString() 
: '';
+    const blockedComponents = ComponentApi.getBlockedComponentNames();
+    const blockedKamelets = KameletApi.getBlockedKameletNames();
     const elements = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
navigation, showSteps);
+    const allowedElements = selectorTabIndex === 'component' ?
+        elements.filter(dsl => (!blockedComponents.includes(dsl.uri || 
dsl.name))) :
+        (selectorTabIndex === 'kamelet' ? elements.filter(dsl => 
(!blockedKamelets.includes(dsl.name))) : elements);
     const eipLabels = [...new Set(elements.map(e => 
e.labels).join(",").split(",").filter(e => e !== 'eip'))];
-    const filteredElement = elements
+    const filteredElement = allowedElements
         .filter((dsl: DslMetaModel) => CamelUi.checkFilter(dsl, filter))
         .filter((dsl: DslMetaModel) => {
             if (!isEip || selectedLabels.length === 0) {
diff --git a/karavan-designer/src/knowledgebase/KnowledgebasePage.tsx 
b/karavan-designer/src/knowledgebase/KnowledgebasePage.tsx
index 02c6b641..66eae532 100644
--- a/karavan-designer/src/knowledgebase/KnowledgebasePage.tsx
+++ b/karavan-designer/src/knowledgebase/KnowledgebasePage.tsx
@@ -24,6 +24,7 @@ import {ComponentsTab} from "./components/ComponentsTab";
 
 interface Props {
     dark: boolean,
+    changeBlockList: (type: string, name: string, checked: boolean) => void,
 }
 
 export const KnowledgebasePage = (props: Props) => {
@@ -76,9 +77,9 @@ export const KnowledgebasePage = (props: Props) => {
                 </Flex>
             </PageSection>
             <>
-                {tab === 'kamelets' && <KameletsTab dark={props.dark} 
filter={filter} customOnly={customOnly}/>}
+                {tab === 'kamelets' && <KameletsTab dark={props.dark} 
filter={filter} customOnly={customOnly} onChange={(name: string, checked: 
boolean) => props.changeBlockList('kamelet', name, checked)}  />}
                 {tab === 'eip' && <EipTab dark={props.dark} filter={filter}/>}
-                {tab === 'components' && <ComponentsTab dark={props.dark} 
filter={filter}/>}
+                {tab === 'components' && <ComponentsTab dark={props.dark} 
filter={filter} onChange={(name: string, checked: boolean) => 
props.changeBlockList('component', name, checked)}  />}
             </>
         </PageSection>
     )
diff --git a/karavan-designer/src/knowledgebase/components/ComponentCard.tsx 
b/karavan-designer/src/knowledgebase/components/ComponentCard.tsx
index 338dc3b9..f99d8136 100644
--- a/karavan-designer/src/knowledgebase/components/ComponentCard.tsx
+++ b/karavan-designer/src/knowledgebase/components/ComponentCard.tsx
@@ -14,32 +14,45 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 import {
-    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge
+    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox
 } from '@patternfly/react-core';
 import '../../designer/karavan.css';
 import {CamelUi} from "../../designer/utils/CamelUi";
 import {Component} from "karavan-core/lib/model/ComponentModels";
 import {useKnowledgebaseStore} from "../KnowledgebaseStore";
 import {shallow} from "zustand/shallow";
+import { ComponentApi } from 'karavan-core/lib/api/ComponentApi';
 
 interface Props {
     component: Component,
+    onChange: (name: string, checked: boolean) => void
 }
 
 export function ComponentCard(props: Props) {
 
     const [setComponent, setModalOpen] = useKnowledgebaseStore((s) =>
         [s.setComponent, s.setModalOpen], shallow)
-
     const component = props.component;
+    const [blockedComponents, setBlockedComponents] = useState<string[]>();
+    useEffect(() => {
+        setBlockedComponents(ComponentApi.getBlockedComponentNames());
+    }, []);
+    
 
-    function click (event: React.MouseEvent) {
-        setComponent(component)
-        setModalOpen(true);
+    function click(event: React.MouseEvent) {
+        const { target } = event;
+        if (!(target as 
HTMLElement).parentElement?.className.includes("block-checkbox")) {
+            setComponent(component)
+            setModalOpen(true);
+        }
     }
-
+    function selectComponent(event: React.FormEvent, checked: boolean) {
+        props.onChange(component.component.name, checked);
+         setBlockedComponents([...ComponentApi.getBlockedComponentNames()]);
+    }
+    const isBlockedComponent = blockedComponents ? 
blockedComponents.findIndex(r => r === component.component.name) > -1 : false;
     return (
         <Card isCompact key={component.component.name} className="kamelet-card"
               onClick={event => click(event)}
@@ -47,6 +60,7 @@ export function ComponentCard(props: Props) {
             <CardHeader className="header-labels">
                 {component.component.supportType === 'Supported' && <Badge 
isRead className="support-type 
labels">{component.component.supportType}</Badge>}
                 <Badge isRead className="support-level 
labels">{component.component.supportLevel}</Badge>
+                <Checkbox id={component.component.name} 
className="block-checkbox labels" isChecked={!isBlockedComponent} onChange={(_, 
checked) => selectComponent(_, checked)} />
             </CardHeader>
             <CardHeader>
                 {CamelUi.getIconForComponent(component.component.title, 
component.component.label)}
diff --git a/karavan-designer/src/knowledgebase/components/ComponentsTab.tsx 
b/karavan-designer/src/knowledgebase/components/ComponentsTab.tsx
index 708b04bd..9e9fb470 100644
--- a/karavan-designer/src/knowledgebase/components/ComponentsTab.tsx
+++ b/karavan-designer/src/knowledgebase/components/ComponentsTab.tsx
@@ -29,6 +29,7 @@ import {useKnowledgebaseStore} from "../KnowledgebaseStore";
 interface Props {
     dark: boolean,
     filter: string,
+    onChange: (name: string, checked: boolean) => void,
 }
 
 export function ComponentsTab(props: Props) {
@@ -49,7 +50,7 @@ export function ComponentsTab(props: Props) {
             <PageSection isFilled className="kamelets-page" 
variant={props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                 <Gallery hasGutter>
                     {components.map(c => (
-                        <ComponentCard key={c.component.name} component={c}/>
+                        <ComponentCard key={c.component.name} component={c} 
onChange={props.onChange}  />
                     ))}
                 </Gallery>
             </PageSection>
diff --git a/karavan-designer/src/knowledgebase/kamelets/KameletCard.tsx 
b/karavan-designer/src/knowledgebase/kamelets/KameletCard.tsx
index 045846e9..1dff9f2c 100644
--- a/karavan-designer/src/knowledgebase/kamelets/KameletCard.tsx
+++ b/karavan-designer/src/knowledgebase/kamelets/KameletCard.tsx
@@ -14,9 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 import {
-    CardHeader, Card, CardTitle, CardBody, CardFooter,Badge
+    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox
 } from '@patternfly/react-core';
 import '../../designer/karavan.css';
 import {KameletModel} from "karavan-core/lib/model/KameletModels";
@@ -27,21 +27,34 @@ import {shallow} from "zustand/shallow";
 
 interface Props {
     kamelet: KameletModel,
+    onChange: (name: string, checked: boolean) => void
 }
 
 export function KameletCard(props: Props) {
 
     const [setKamelet, setModalOpen] = useKnowledgebaseStore((s) =>
         [s.setKamelet, s.setModalOpen], shallow)
-
+    const [blockedKamelets, setBlockedKamelets] = useState<string[]>();
+    useEffect(() => {
+        setBlockedKamelets(KameletApi.getBlockedKameletNames());
+    }, []);
+    
     const kamelet = props.kamelet;
     const isCustom = 
KameletApi.getCustomKameletNames().includes(kamelet.metadata.name);
 
-    function click (event: React.MouseEvent) {
-        setKamelet(kamelet)
-        setModalOpen(true);
+    function click(event: React.MouseEvent) {
+        const { target } = event;
+        if (!(target as 
HTMLElement).parentElement?.className.includes("block-checkbox")) {
+            setKamelet(kamelet)
+            setModalOpen(true);
+        }
 
     }
+    function selectKamelet(event: React.FormEvent, checked: boolean) {
+        props.onChange(kamelet.metadata.name, checked );
+        setBlockedKamelets([...KameletApi.getBlockedKameletNames()]);
+    }
+    const isblockedKamelet = blockedKamelets ? blockedKamelets.findIndex(r => 
r === kamelet.metadata.name) > -1 : false;
     return (
         <Card  isCompact key={kamelet.metadata.name} className="kamelet-card"
                onClick={event => click(event)}
@@ -49,6 +62,7 @@ export function KameletCard(props: Props) {
             <CardHeader className="header-labels">
                 {isCustom && <Badge className="custom">custom</Badge>}
                 <Badge isRead className="support-level 
labels">{kamelet.metadata.annotations["camel.apache.org/kamelet.support.level"]}</Badge>
+                <Checkbox id={kamelet.metadata.name} className="block-checkbox 
labels" isChecked={!isblockedKamelet} onChange={(_, checked) => 
selectKamelet(_, checked)} />
             </CardHeader>
             <CardHeader>
                 {CamelUi.getIconFromSource(kamelet.icon())}
diff --git a/karavan-designer/src/knowledgebase/kamelets/KameletsTab.tsx 
b/karavan-designer/src/knowledgebase/kamelets/KameletsTab.tsx
index fb8df6df..353819e4 100644
--- a/karavan-designer/src/knowledgebase/kamelets/KameletsTab.tsx
+++ b/karavan-designer/src/knowledgebase/kamelets/KameletsTab.tsx
@@ -31,11 +31,7 @@ interface Props {
     dark: boolean,
     filter: string,
     customOnly: boolean,
-}
-
-interface Props {
-    dark: boolean,
-    filter: string,
+    onChange: (name: string, checked: boolean) => void
 }
 
 export function KameletsTab(props: Props) {
@@ -55,7 +51,7 @@ export function KameletsTab(props: Props) {
                          variant={dark ? PageSectionVariants.darker : 
PageSectionVariants.light}>
                 <Gallery hasGutter>
                     {kameletList.map(k => (
-                        <KameletCard key={k.metadata.name} kamelet={k}/>
+                        <KameletCard key={k.metadata.name} kamelet={k} 
onChange={props.onChange} />
                     ))}
                 </Gallery>
             </PageSection>
diff --git a/karavan-space/src/App.tsx b/karavan-space/src/App.tsx
index 2adec90f..5a723404 100644
--- a/karavan-space/src/App.tsx
+++ b/karavan-space/src/App.tsx
@@ -74,7 +74,9 @@ class App extends React.Component<Props, State> {
             fetch("kamelets/kamelets.yaml"),
             fetch("components/components.json"),
             fetch("snippets/org.apache.camel.AggregationStrategy"),
-            fetch("snippets/org.apache.camel.Processor")
+            fetch("snippets/org.apache.camel.Processor"),
+            fetch("components/blocked-components.properties"),
+            fetch("kamelets/blocked-kamelets.properties")
         ]).then(responses =>
             Promise.all(responses.map(response => response.text()))
         ).then(data => {
@@ -91,6 +93,12 @@ class App extends React.Component<Props, State> {
 
             TemplateApi.saveTemplate("org.apache.camel.AggregationStrategy", 
data[2]);
             TemplateApi.saveTemplate("org.apache.camel.Processor", data[3]);
+            if (data[4]) {
+                ComponentApi.saveBlockedComponentNames(data[4].split('\r\n'));
+            }
+            if (data[5]) {
+                KameletApi.saveBlockedKameletNames(data[5].split('\n'));
+            }
         }).catch(err =>
             EventBus.sendAlert("Error", err.text, 'danger')
         );
@@ -100,6 +108,16 @@ class App extends React.Component<Props, State> {
         this.setState({name: filename, yaml: yaml});
         // console.log(yaml);
     }
+    
+    onchangeBlockedList(type: string, name: string, checked: boolean){
+        if (type === 'kamelet') {
+
+            const blockedKamelet = KameletApi.saveBlockedKameletName(name, 
checked);
+        }
+        else if (type === 'component') {
+            const blockedComponent = 
ComponentApi.saveBlockedComponentName(name, checked);
+        }
+    }
 
     closeGithubModal() {
         this.setState({githubModalIsOpen: false})
@@ -167,7 +185,7 @@ class App extends React.Component<Props, State> {
                 )
             case "knowledgebase":
                 return (
-                    <KnowledgebasePage dark={dark}/>
+                    <KnowledgebasePage dark={dark} changeBlockList={(type: 
string, name: string, checked: boolean) => this.onchangeBlockedList(type, name, 
checked)}/>
                 )
             case "topology":
                 return (
diff --git a/karavan-space/src/designer/karavan.css 
b/karavan-space/src/designer/karavan.css
index 4d9a7162..82f75a51 100644
--- a/karavan-space/src/designer/karavan.css
+++ b/karavan-space/src/designer/karavan.css
@@ -189,7 +189,12 @@
     padding: 5px;
     display: flex;
     flex-direction: row;
-    justify-content: flex-end;
+    justify-content:flex-end;
+}
+.kamelets-page .kamelet-card .header-labels .pf-v5-c-card__header-main{
+    display: flex;
+    flex-direction: row;
+    justify-content:space-between;
 }
 
 .kamelets-page .kamelet-card .footer-labels {
@@ -813,4 +818,8 @@
 }
 .karavan .knowledbase-eip-section .pf-v5-c-toggle-group{
     margin:16px;
+}
+.karavan .kamelet-section .kamelet-card .block-checkbox input{
+    width:18px;
+    height:18px
 }
\ No newline at end of file
diff --git a/karavan-space/src/designer/route/DslSelector.tsx 
b/karavan-space/src/designer/route/DslSelector.tsx
index a80525ba..27093f25 100644
--- a/karavan-space/src/designer/route/DslSelector.tsx
+++ b/karavan-space/src/designer/route/DslSelector.tsx
@@ -27,6 +27,8 @@ import {DslMetaModel} from "../utils/DslMetaModel";
 import {useDesignerStore, useIntegrationStore, useSelectorStore} from 
"../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {useRouteDesignerHook} from "./useRouteDesignerHook";
+import { ComponentApi } from 'karavan-core/lib/api/ComponentApi';
+import { KameletApi } from 'karavan-core/lib/api/KameletApi';
 
 interface Props {
     tabIndex?: string | number
@@ -119,9 +121,14 @@ export function DslSelector (props: Props) {
     const isEip = selectorTabIndex === 'eip';
     const title = parentDsl === undefined ? "Select source" : "Select step";
     const navigation: string = selectorTabIndex ? selectorTabIndex.toString() 
: '';
+    const blockedComponents = ComponentApi.getBlockedComponentNames();
+    const blockedKamelets = KameletApi.getBlockedKameletNames();
     const elements = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
navigation, showSteps);
+    const allowedElements = selectorTabIndex === 'component' ?
+        elements.filter(dsl => (!blockedComponents.includes(dsl.uri || 
dsl.name))) :
+        (selectorTabIndex === 'kamelet' ? elements.filter(dsl => 
(!blockedKamelets.includes(dsl.name))) : elements);
     const eipLabels = [...new Set(elements.map(e => 
e.labels).join(",").split(",").filter(e => e !== 'eip'))];
-    const filteredElement = elements
+    const filteredElement = allowedElements
         .filter((dsl: DslMetaModel) => CamelUi.checkFilter(dsl, filter))
         .filter((dsl: DslMetaModel) => {
             if (!isEip || selectedLabels.length === 0) {
diff --git a/karavan-space/src/knowledgebase/KnowledgebasePage.tsx 
b/karavan-space/src/knowledgebase/KnowledgebasePage.tsx
index 02c6b641..66eae532 100644
--- a/karavan-space/src/knowledgebase/KnowledgebasePage.tsx
+++ b/karavan-space/src/knowledgebase/KnowledgebasePage.tsx
@@ -24,6 +24,7 @@ import {ComponentsTab} from "./components/ComponentsTab";
 
 interface Props {
     dark: boolean,
+    changeBlockList: (type: string, name: string, checked: boolean) => void,
 }
 
 export const KnowledgebasePage = (props: Props) => {
@@ -76,9 +77,9 @@ export const KnowledgebasePage = (props: Props) => {
                 </Flex>
             </PageSection>
             <>
-                {tab === 'kamelets' && <KameletsTab dark={props.dark} 
filter={filter} customOnly={customOnly}/>}
+                {tab === 'kamelets' && <KameletsTab dark={props.dark} 
filter={filter} customOnly={customOnly} onChange={(name: string, checked: 
boolean) => props.changeBlockList('kamelet', name, checked)}  />}
                 {tab === 'eip' && <EipTab dark={props.dark} filter={filter}/>}
-                {tab === 'components' && <ComponentsTab dark={props.dark} 
filter={filter}/>}
+                {tab === 'components' && <ComponentsTab dark={props.dark} 
filter={filter} onChange={(name: string, checked: boolean) => 
props.changeBlockList('component', name, checked)}  />}
             </>
         </PageSection>
     )
diff --git a/karavan-space/src/knowledgebase/components/ComponentCard.tsx 
b/karavan-space/src/knowledgebase/components/ComponentCard.tsx
index 338dc3b9..f99d8136 100644
--- a/karavan-space/src/knowledgebase/components/ComponentCard.tsx
+++ b/karavan-space/src/knowledgebase/components/ComponentCard.tsx
@@ -14,32 +14,45 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 import {
-    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge
+    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox
 } from '@patternfly/react-core';
 import '../../designer/karavan.css';
 import {CamelUi} from "../../designer/utils/CamelUi";
 import {Component} from "karavan-core/lib/model/ComponentModels";
 import {useKnowledgebaseStore} from "../KnowledgebaseStore";
 import {shallow} from "zustand/shallow";
+import { ComponentApi } from 'karavan-core/lib/api/ComponentApi';
 
 interface Props {
     component: Component,
+    onChange: (name: string, checked: boolean) => void
 }
 
 export function ComponentCard(props: Props) {
 
     const [setComponent, setModalOpen] = useKnowledgebaseStore((s) =>
         [s.setComponent, s.setModalOpen], shallow)
-
     const component = props.component;
+    const [blockedComponents, setBlockedComponents] = useState<string[]>();
+    useEffect(() => {
+        setBlockedComponents(ComponentApi.getBlockedComponentNames());
+    }, []);
+    
 
-    function click (event: React.MouseEvent) {
-        setComponent(component)
-        setModalOpen(true);
+    function click(event: React.MouseEvent) {
+        const { target } = event;
+        if (!(target as 
HTMLElement).parentElement?.className.includes("block-checkbox")) {
+            setComponent(component)
+            setModalOpen(true);
+        }
     }
-
+    function selectComponent(event: React.FormEvent, checked: boolean) {
+        props.onChange(component.component.name, checked);
+         setBlockedComponents([...ComponentApi.getBlockedComponentNames()]);
+    }
+    const isBlockedComponent = blockedComponents ? 
blockedComponents.findIndex(r => r === component.component.name) > -1 : false;
     return (
         <Card isCompact key={component.component.name} className="kamelet-card"
               onClick={event => click(event)}
@@ -47,6 +60,7 @@ export function ComponentCard(props: Props) {
             <CardHeader className="header-labels">
                 {component.component.supportType === 'Supported' && <Badge 
isRead className="support-type 
labels">{component.component.supportType}</Badge>}
                 <Badge isRead className="support-level 
labels">{component.component.supportLevel}</Badge>
+                <Checkbox id={component.component.name} 
className="block-checkbox labels" isChecked={!isBlockedComponent} onChange={(_, 
checked) => selectComponent(_, checked)} />
             </CardHeader>
             <CardHeader>
                 {CamelUi.getIconForComponent(component.component.title, 
component.component.label)}
diff --git a/karavan-space/src/knowledgebase/components/ComponentsTab.tsx 
b/karavan-space/src/knowledgebase/components/ComponentsTab.tsx
index 708b04bd..9e9fb470 100644
--- a/karavan-space/src/knowledgebase/components/ComponentsTab.tsx
+++ b/karavan-space/src/knowledgebase/components/ComponentsTab.tsx
@@ -29,6 +29,7 @@ import {useKnowledgebaseStore} from "../KnowledgebaseStore";
 interface Props {
     dark: boolean,
     filter: string,
+    onChange: (name: string, checked: boolean) => void,
 }
 
 export function ComponentsTab(props: Props) {
@@ -49,7 +50,7 @@ export function ComponentsTab(props: Props) {
             <PageSection isFilled className="kamelets-page" 
variant={props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                 <Gallery hasGutter>
                     {components.map(c => (
-                        <ComponentCard key={c.component.name} component={c}/>
+                        <ComponentCard key={c.component.name} component={c} 
onChange={props.onChange}  />
                     ))}
                 </Gallery>
             </PageSection>
diff --git a/karavan-space/src/knowledgebase/kamelets/KameletCard.tsx 
b/karavan-space/src/knowledgebase/kamelets/KameletCard.tsx
index 045846e9..1dff9f2c 100644
--- a/karavan-space/src/knowledgebase/kamelets/KameletCard.tsx
+++ b/karavan-space/src/knowledgebase/kamelets/KameletCard.tsx
@@ -14,9 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 import {
-    CardHeader, Card, CardTitle, CardBody, CardFooter,Badge
+    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox
 } from '@patternfly/react-core';
 import '../../designer/karavan.css';
 import {KameletModel} from "karavan-core/lib/model/KameletModels";
@@ -27,21 +27,34 @@ import {shallow} from "zustand/shallow";
 
 interface Props {
     kamelet: KameletModel,
+    onChange: (name: string, checked: boolean) => void
 }
 
 export function KameletCard(props: Props) {
 
     const [setKamelet, setModalOpen] = useKnowledgebaseStore((s) =>
         [s.setKamelet, s.setModalOpen], shallow)
-
+    const [blockedKamelets, setBlockedKamelets] = useState<string[]>();
+    useEffect(() => {
+        setBlockedKamelets(KameletApi.getBlockedKameletNames());
+    }, []);
+    
     const kamelet = props.kamelet;
     const isCustom = 
KameletApi.getCustomKameletNames().includes(kamelet.metadata.name);
 
-    function click (event: React.MouseEvent) {
-        setKamelet(kamelet)
-        setModalOpen(true);
+    function click(event: React.MouseEvent) {
+        const { target } = event;
+        if (!(target as 
HTMLElement).parentElement?.className.includes("block-checkbox")) {
+            setKamelet(kamelet)
+            setModalOpen(true);
+        }
 
     }
+    function selectKamelet(event: React.FormEvent, checked: boolean) {
+        props.onChange(kamelet.metadata.name, checked );
+        setBlockedKamelets([...KameletApi.getBlockedKameletNames()]);
+    }
+    const isblockedKamelet = blockedKamelets ? blockedKamelets.findIndex(r => 
r === kamelet.metadata.name) > -1 : false;
     return (
         <Card  isCompact key={kamelet.metadata.name} className="kamelet-card"
                onClick={event => click(event)}
@@ -49,6 +62,7 @@ export function KameletCard(props: Props) {
             <CardHeader className="header-labels">
                 {isCustom && <Badge className="custom">custom</Badge>}
                 <Badge isRead className="support-level 
labels">{kamelet.metadata.annotations["camel.apache.org/kamelet.support.level"]}</Badge>
+                <Checkbox id={kamelet.metadata.name} className="block-checkbox 
labels" isChecked={!isblockedKamelet} onChange={(_, checked) => 
selectKamelet(_, checked)} />
             </CardHeader>
             <CardHeader>
                 {CamelUi.getIconFromSource(kamelet.icon())}
diff --git a/karavan-space/src/knowledgebase/kamelets/KameletsTab.tsx 
b/karavan-space/src/knowledgebase/kamelets/KameletsTab.tsx
index fb8df6df..353819e4 100644
--- a/karavan-space/src/knowledgebase/kamelets/KameletsTab.tsx
+++ b/karavan-space/src/knowledgebase/kamelets/KameletsTab.tsx
@@ -31,11 +31,7 @@ interface Props {
     dark: boolean,
     filter: string,
     customOnly: boolean,
-}
-
-interface Props {
-    dark: boolean,
-    filter: string,
+    onChange: (name: string, checked: boolean) => void
 }
 
 export function KameletsTab(props: Props) {
@@ -55,7 +51,7 @@ export function KameletsTab(props: Props) {
                          variant={dark ? PageSectionVariants.darker : 
PageSectionVariants.light}>
                 <Gallery hasGutter>
                     {kameletList.map(k => (
-                        <KameletCard key={k.metadata.name} kamelet={k}/>
+                        <KameletCard key={k.metadata.name} kamelet={k} 
onChange={props.onChange} />
                     ))}
                 </Gallery>
             </PageSection>
diff --git a/karavan-vscode/package.json b/karavan-vscode/package.json
index 2ac85771..c9e24eb3 100644
--- a/karavan-vscode/package.json
+++ b/karavan-vscode/package.json
@@ -457,6 +457,13 @@
           "description": "application.properties template for camel-main on 
Kubernetes",
           "scope": "machine",
           "order": 95
+        },
+        "Karavan.settingsPath": {
+          "type": "string",
+          "default": "settings",
+          "description": "Blocked kamelets/components Path",
+          "scope": "machine",
+          "order": 96
         }
       }
     },
@@ -719,7 +726,7 @@
     "replace-import": "run-script-os",
     "replace-import:darwin": "find webview -type f -name '*.ts*' -exec sed -i 
'' 's!karavan-core/lib!core!g' {} +",
     "replace-import:linux": "find webview -type f -name '*.ts*' -exec sed -i 
's!karavan-core/lib!core!g' {} +",
-    "copy-karavan": "npm run copy-core && npm run copy-designer && npm run 
replace-import",
+        "copy-karavan": "npm run copy-core && npm run copy-designer && npm run 
replace-import",
     "vscode:prepublish": "npm run copy-karavan && npm run package",
     "compile": "npm run copy-karavan && cross-env NODE_ENV=development webpack 
--progress --stats-error-details",
     "watch": "npm run copy-karavan && cross-env NODE_ENV=development webpack 
--progress --watch",
@@ -742,9 +749,9 @@
     "@types/js-yaml": "4.0.9",
     "@types/node": "20.11.16",
     "@types/uuid": "9.0.8",
-    "html-to-image": "1.11.11",
+        "html-to-image": "1.11.11",
     "js-yaml": "^4.1.0",
-    "path-browserify": "^1.0.1",
+        "path-browserify": "^1.0.1",
     "react": "18.2.0",
     "react-dom": "18.2.0",
     "rxjs": "7.8.1",
diff --git a/karavan-vscode/settings/components-blocklist.txt 
b/karavan-vscode/settings/components-blocklist.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/karavan-vscode/settings/kamelets-blocklist.txt 
b/karavan-vscode/settings/kamelets-blocklist.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/karavan-vscode/src/designerView.ts 
b/karavan-vscode/src/designerView.ts
index 822ef7dc..612a093c 100644
--- a/karavan-vscode/src/designerView.ts
+++ b/karavan-vscode/src/designerView.ts
@@ -189,6 +189,8 @@ export class DesignerView {
             utils.readPropertyPlaceholders(this.context),
             // Read beans
             utils.readBeans(fullPath),
+            //Read BlockList
+            utils.readBlockTemplates(this.context),
             // Read integration
             utils.readCamelYamlFiles(path.dirname(fullPath))
         ]).then(results => {
@@ -206,6 +208,8 @@ export class DesignerView {
             // Send integration
             panel.webview.postMessage({ command: 'files', files: results[8] });
             this.sendIntegrationData(panel, filename, relativePath, fullPath, 
reread, yaml, tab, results[6], results[7]);
+            // Send block list
+            panel.webview.postMessage({ command: 'blockList', blockList: 
Object.fromEntries(results[8]) });
 
         }).catch(err => console.log(err));
     }
diff --git a/karavan-vscode/src/helpView.ts b/karavan-vscode/src/helpView.ts
index c1d11236..435281d5 100644
--- a/karavan-vscode/src/helpView.ts
+++ b/karavan-vscode/src/helpView.ts
@@ -71,6 +71,10 @@ export class HelpView implements 
vscode.TreeDataProvider<HelpItem> {
                                                case 'getData':
                                                        this.sendData(panel, 
page);
                                                        break;
+                                               
+                                               case 'saveBlockedList':
+                                                       
utils.saveBlockList(message.key,message.value);
+                                                       break;
                                        }
                                },
                                undefined,
@@ -102,7 +106,10 @@ export class HelpView implements 
vscode.TreeDataProvider<HelpItem> {
                        utils.readComponents(this.context).then(components => {
                                // Read and send Components
                                panel.webview.postMessage({ command: 
'components', components: components });
-                       }).finally(() => {
+                       }).finally(() => 
{utils.readBlockTemplates(this.context).then(list => {
+                               // Read and send block lists
+                               panel.webview.postMessage({ command: 
'blockList', blockList: Object.fromEntries(list) });
+                       }) }).finally(() => {
                                // Send integration
                                panel.webview.postMessage({ command: 'open', 
page: page });
                        })
diff --git a/karavan-vscode/src/utils.ts b/karavan-vscode/src/utils.ts
index 17e999a0..985544b0 100644
--- a/karavan-vscode/src/utils.ts
+++ b/karavan-vscode/src/utils.ts
@@ -49,6 +49,16 @@ export async function savePropertyPlaceholder(key: string, 
value: string) {
     }
 }
 
+export function saveBlockList(key: string, value: string) {
+    if (workspace.workspaceFolders) {
+        const uriFolder: Uri = workspace.workspaceFolders[0].uri;
+        const settingsPath: string | undefined = 
workspace.getConfiguration().get("Karavan.settingsPath");
+        const name = key+"s-blocklist.txt";
+        write(path.join(uriFolder.path, settingsPath+"/"+name), value);
+    }
+}
+
+
 export function deleteFile(fullPath: string) {
     if (workspace.workspaceFolders) {
         const uriFile: Uri = Uri.file(path.resolve(fullPath));
@@ -64,7 +74,7 @@ export function getRalativePath(fullPath: string): string {
 }
 
 export async function readKamelets(context: ExtensionContext) {
-    const yamls: string[] = await readBuildInKamelets(context);
+   const yamls: string[] = await readBuildInKamelets(context);
     const kameletsPath: string | undefined = 
workspace.getConfiguration().get("Karavan.kameletsPath");
     if (kameletsPath && kameletsPath.trim().length > 0) {
         const kameletsDir = path.isAbsolute(kameletsPath) ? kameletsPath : 
path.resolve(kameletsPath);
@@ -179,6 +189,19 @@ export async function readTemplates(context: 
ExtensionContext) {
     })
     return result;
 }
+export async function readBlockTemplates(context: ExtensionContext) {
+    const result = new Map<string, string>();
+  
+    const blockedListDir: string | undefined = 
workspace.getConfiguration().get("Karavan.settingsPath");
+    if (blockedListDir && blockedListDir.trim().length > 0) {
+        const files = await 
readFilesInDirByExtension(path.join(context.extensionPath, blockedListDir), 
"txt");
+        files.forEach((v, k) => {
+                    result.set(k,v);
+            })
+    }
+    return result;
+}
+
 
 export async function readJavaCode(fullPath: string) {
     const result = new Map<string, string>();
diff --git a/karavan-vscode/webview/App.tsx b/karavan-vscode/webview/App.tsx
index dec9683b..f46b71d0 100644
--- a/karavan-vscode/webview/App.tsx
+++ b/karavan-vscode/webview/App.tsx
@@ -173,6 +173,21 @@ class App extends React.Component<Props, State> {
       case 'downloadImage':
         EventBus.sendCommand("downloadImage");
         break;
+      case 'blockList':
+          const blockList = message.blockList;
+        const blockListMap = new Map(Object.keys(blockList).map(key => [key, 
blockList[key]])).forEach((list,key) => {
+          if (key === 'components-blocklist.txt') {
+            ComponentApi.saveBlockedComponentNames(list.split(/\r?\n/));
+          }
+          else if (key === 'kamelets-blocklist.txt') {
+            KameletApi.saveBlockedKameletNames(list.split(/\r?\n/));
+          }
+        });
+          this.setState((prevState: State) => {
+            prevState.loadingMessages.push("block lists loaded");
+            return { loadingMessages: prevState.loadingMessages }
+          });
+          break;
     }
   };
 
@@ -202,6 +217,16 @@ class App extends React.Component<Props, State> {
 
   }
 
+ onchangeBlockedList(type: string, name: string, checked: boolean) {
+  let fileContent = '';
+  if (type === "component") {
+      fileContent = ComponentApi.saveBlockedComponentName(name, 
checked).join('\n');
+  } else {
+      fileContent =KameletApi.saveBlockedKameletName(name, checked).join('\n');
+  }
+  vscode.postMessage({ command: 'saveBlockedList', key: type, value: 
fileContent });
+  }
+
   public render() {
     const { loadingMessages, filename, key, yaml, page, loaded, tab } = 
this.state;
     const { dark } = this.props;
@@ -238,7 +263,7 @@ class App extends React.Component<Props, State> {
             files={this.state.files.map(f => new IntegrationFile(f.name, 
f.code))}
           />
         }
-        {loaded && page === "knowledgebase" && <KnowledgebasePage dark={dark} 
/>}
+        {loaded && page === "knowledgebase" && <KnowledgebasePage dark={dark}  
changeBlockList={(type: string, name: string, checked: boolean) => 
this.onchangeBlockedList(type, name, checked)}/>}
         {loaded && page === "topology" &&
           <TopologyTab
             hideToolbar={true}
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ComponentResources.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ComponentResources.java
index 4388b4e4..d763fefb 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ComponentResources.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ComponentResources.java
@@ -25,7 +25,7 @@ import org.apache.camel.karavan.code.CodeService;
 
 @Path("/api/component")
 public class ComponentResources {
-
+    
     @Inject
     CodeService codeService;
 
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
index de039b83..eece054f 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
@@ -87,6 +87,7 @@ public class CodeService {
     @Inject
     Vertx vertx;
 
+    List<String> blockList = List.of("components-blocklist.txt", 
"kamelets-blocklist.txt");
     List<String> beansTemplates = List.of("database", "messaging");
     List<String> targets = List.of("openshift", "kubernetes", "docker");
     List<String> interfaces = 
List.of("org.apache.camel.AggregationStrategy.java", 
"org.apache.camel.Processor.java");
@@ -197,6 +198,7 @@ public class CodeService {
         List<String> files = new ArrayList<>(interfaces);
         files.addAll(targets.stream().map(target -> target + "-" + 
APPLICATION_PROPERTIES_FILENAME).toList());
         files.addAll(targets.stream().map(target ->  target + "-" + 
BUILD_SCRIPT_FILENAME).toList());
+        files.addAll(blockList);
 
         files.addAll(getBeanTemplateNames());
 
diff --git 
a/karavan-web/karavan-app/src/main/resources/snippets/components-blocklist.txt 
b/karavan-web/karavan-app/src/main/resources/snippets/components-blocklist.txt
new file mode 100644
index 00000000..e69de29b
diff --git 
a/karavan-web/karavan-app/src/main/resources/snippets/kamelets-blocklist.txt 
b/karavan-web/karavan-app/src/main/resources/snippets/kamelets-blocklist.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts 
b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
index 9a1b5f21..df52aa72 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
@@ -30,6 +30,7 @@ import {
 import {ProjectEventBus} from './ProjectEventBus';
 import {EventBus} from "../designer/utils/EventBus";
 import {KameletApi} from "karavan-core/lib/api/KameletApi";
+import { ComponentApi } from 'karavan-core/lib/api/ComponentApi';
 
 export class ProjectService {
 
@@ -129,14 +130,13 @@ export class ProjectService {
     public static reloadKamelets() {
         KaravanApi.getKamelets(yamls => {
             const kamelets: string[] = [];
-            yamls.split("\n---\n").map(c => c.trim()).forEach(z => 
kamelets.push(z));
+            yamls.split(/\n?---\n?/).map(c => c.trim()).forEach(z => 
kamelets.push(z));
             KameletApi.saveKamelets(kamelets, true);
         })
         KaravanApi.getCustomKameletNames(names => {
             KameletApi.saveCustomKameletNames(names);
         })
     }
-
     public static updateFile(file: ProjectFile, active: boolean) {
         KaravanApi.putProjectFile(file, res => {
             if (res.status === 200) {
@@ -297,4 +297,17 @@ export class ProjectService {
             useProjectStore.setState({images: images})
         });
     }
+    
+    public static reloadBlockedTemplates() {
+      KaravanApi.getTemplatesFiles((files: ProjectFile[]) => {
+            files.filter(f => f.name.endsWith('blocklist.txt')).forEach(file 
=> {
+                if (file.name === 'components-blocklist.txt') {
+                    
ComponentApi.saveBlockedComponentNames(file.code.split(/\r?\n/));
+                }
+                else if (file.name === "kamelets-blocklist.txt") {
+                    
KameletApi.saveBlockedKameletNames(file.code.split(/\r?\n/));
+                }
+            });
+       });
+    }
 }
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/karavan.css 
b/karavan-web/karavan-app/src/main/webui/src/designer/karavan.css
index 4d9a7162..82f75a51 100644
--- a/karavan-web/karavan-app/src/main/webui/src/designer/karavan.css
+++ b/karavan-web/karavan-app/src/main/webui/src/designer/karavan.css
@@ -189,7 +189,12 @@
     padding: 5px;
     display: flex;
     flex-direction: row;
-    justify-content: flex-end;
+    justify-content:flex-end;
+}
+.kamelets-page .kamelet-card .header-labels .pf-v5-c-card__header-main{
+    display: flex;
+    flex-direction: row;
+    justify-content:space-between;
 }
 
 .kamelets-page .kamelet-card .footer-labels {
@@ -813,4 +818,8 @@
 }
 .karavan .knowledbase-eip-section .pf-v5-c-toggle-group{
     margin:16px;
+}
+.karavan .kamelet-section .kamelet-card .block-checkbox input{
+    width:18px;
+    height:18px
 }
\ No newline at end of file
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx 
b/karavan-web/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
index a80525ba..27093f25 100644
--- a/karavan-web/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
@@ -27,6 +27,8 @@ import {DslMetaModel} from "../utils/DslMetaModel";
 import {useDesignerStore, useIntegrationStore, useSelectorStore} from 
"../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {useRouteDesignerHook} from "./useRouteDesignerHook";
+import { ComponentApi } from 'karavan-core/lib/api/ComponentApi';
+import { KameletApi } from 'karavan-core/lib/api/KameletApi';
 
 interface Props {
     tabIndex?: string | number
@@ -119,9 +121,14 @@ export function DslSelector (props: Props) {
     const isEip = selectorTabIndex === 'eip';
     const title = parentDsl === undefined ? "Select source" : "Select step";
     const navigation: string = selectorTabIndex ? selectorTabIndex.toString() 
: '';
+    const blockedComponents = ComponentApi.getBlockedComponentNames();
+    const blockedKamelets = KameletApi.getBlockedKameletNames();
     const elements = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
navigation, showSteps);
+    const allowedElements = selectorTabIndex === 'component' ?
+        elements.filter(dsl => (!blockedComponents.includes(dsl.uri || 
dsl.name))) :
+        (selectorTabIndex === 'kamelet' ? elements.filter(dsl => 
(!blockedKamelets.includes(dsl.name))) : elements);
     const eipLabels = [...new Set(elements.map(e => 
e.labels).join(",").split(",").filter(e => e !== 'eip'))];
-    const filteredElement = elements
+    const filteredElement = allowedElements
         .filter((dsl: DslMetaModel) => CamelUi.checkFilter(dsl, filter))
         .filter((dsl: DslMetaModel) => {
             if (!isEip || selectedLabels.length === 0) {
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/KnowledgebaseHome.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/KnowledgebaseHome.tsx
new file mode 100644
index 00000000..d9a50a9a
--- /dev/null
+++ 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/KnowledgebaseHome.tsx
@@ -0,0 +1,41 @@
+import { KameletApi } from "karavan-core/lib/api/KameletApi";
+import { KnowledgebasePage } from "./KnowledgebasePage"
+import { ComponentApi } from "karavan-core/lib/api/ComponentApi";
+import { KaravanApi } from "../api/KaravanApi";
+import { useState, useEffect } from "react";
+import { ProjectFile } from "../api/ProjectModels";
+import { ProjectService } from "../api/ProjectService";
+interface Props {
+    dark: boolean,
+}
+export const KnowledgebaseHome = (props: Props) => {
+
+    const [blockList, setBlockList] = useState<ProjectFile[]>();
+
+    useEffect(() => {
+        KaravanApi.getTemplatesFiles((files:ProjectFile[]) => {
+            setBlockList([...(files.filter(f => 
f.name.endsWith('blocklist.txt')))]);
+        });
+    }, []);
+
+    const onChangeBlockedList = async (type: string, name: string, checked: 
boolean) => {
+
+        let file: ProjectFile | undefined;
+        let fileContent = '';
+        if (type === "component") {
+            file = blockList?.find(obj => obj.name === 
'components-blocklist.txt');
+            fileContent = ComponentApi.saveBlockedComponentName(name, 
checked).join('\n');
+        } else {
+            file = blockList?.find(obj => obj.name === 
'kamelets-blocklist.txt');
+            fileContent = KameletApi.saveBlockedKameletName(name, 
checked).join('\n');
+        }
+        if (file) {
+            file.code = fileContent;
+            ProjectService.updateFile(file, false);
+        }
+    }
+
+    return (
+        <KnowledgebasePage dark={props.dark} changeBlockList={(type: string, 
name: string, checked: boolean) => onChangeBlockedList(type, name, checked)} />
+    );
+}
\ No newline at end of file
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/KnowledgebasePage.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/KnowledgebasePage.tsx
index 02c6b641..66eae532 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/KnowledgebasePage.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/KnowledgebasePage.tsx
@@ -24,6 +24,7 @@ import {ComponentsTab} from "./components/ComponentsTab";
 
 interface Props {
     dark: boolean,
+    changeBlockList: (type: string, name: string, checked: boolean) => void,
 }
 
 export const KnowledgebasePage = (props: Props) => {
@@ -76,9 +77,9 @@ export const KnowledgebasePage = (props: Props) => {
                 </Flex>
             </PageSection>
             <>
-                {tab === 'kamelets' && <KameletsTab dark={props.dark} 
filter={filter} customOnly={customOnly}/>}
+                {tab === 'kamelets' && <KameletsTab dark={props.dark} 
filter={filter} customOnly={customOnly} onChange={(name: string, checked: 
boolean) => props.changeBlockList('kamelet', name, checked)}  />}
                 {tab === 'eip' && <EipTab dark={props.dark} filter={filter}/>}
-                {tab === 'components' && <ComponentsTab dark={props.dark} 
filter={filter}/>}
+                {tab === 'components' && <ComponentsTab dark={props.dark} 
filter={filter} onChange={(name: string, checked: boolean) => 
props.changeBlockList('component', name, checked)}  />}
             </>
         </PageSection>
     )
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/components/ComponentCard.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/components/ComponentCard.tsx
index 338dc3b9..f99d8136 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/components/ComponentCard.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/components/ComponentCard.tsx
@@ -14,32 +14,45 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 import {
-    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge
+    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox
 } from '@patternfly/react-core';
 import '../../designer/karavan.css';
 import {CamelUi} from "../../designer/utils/CamelUi";
 import {Component} from "karavan-core/lib/model/ComponentModels";
 import {useKnowledgebaseStore} from "../KnowledgebaseStore";
 import {shallow} from "zustand/shallow";
+import { ComponentApi } from 'karavan-core/lib/api/ComponentApi';
 
 interface Props {
     component: Component,
+    onChange: (name: string, checked: boolean) => void
 }
 
 export function ComponentCard(props: Props) {
 
     const [setComponent, setModalOpen] = useKnowledgebaseStore((s) =>
         [s.setComponent, s.setModalOpen], shallow)
-
     const component = props.component;
+    const [blockedComponents, setBlockedComponents] = useState<string[]>();
+    useEffect(() => {
+        setBlockedComponents(ComponentApi.getBlockedComponentNames());
+    }, []);
+    
 
-    function click (event: React.MouseEvent) {
-        setComponent(component)
-        setModalOpen(true);
+    function click(event: React.MouseEvent) {
+        const { target } = event;
+        if (!(target as 
HTMLElement).parentElement?.className.includes("block-checkbox")) {
+            setComponent(component)
+            setModalOpen(true);
+        }
     }
-
+    function selectComponent(event: React.FormEvent, checked: boolean) {
+        props.onChange(component.component.name, checked);
+         setBlockedComponents([...ComponentApi.getBlockedComponentNames()]);
+    }
+    const isBlockedComponent = blockedComponents ? 
blockedComponents.findIndex(r => r === component.component.name) > -1 : false;
     return (
         <Card isCompact key={component.component.name} className="kamelet-card"
               onClick={event => click(event)}
@@ -47,6 +60,7 @@ export function ComponentCard(props: Props) {
             <CardHeader className="header-labels">
                 {component.component.supportType === 'Supported' && <Badge 
isRead className="support-type 
labels">{component.component.supportType}</Badge>}
                 <Badge isRead className="support-level 
labels">{component.component.supportLevel}</Badge>
+                <Checkbox id={component.component.name} 
className="block-checkbox labels" isChecked={!isBlockedComponent} onChange={(_, 
checked) => selectComponent(_, checked)} />
             </CardHeader>
             <CardHeader>
                 {CamelUi.getIconForComponent(component.component.title, 
component.component.label)}
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/components/ComponentsTab.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/components/ComponentsTab.tsx
index 708b04bd..9e9fb470 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/components/ComponentsTab.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/components/ComponentsTab.tsx
@@ -29,6 +29,7 @@ import {useKnowledgebaseStore} from "../KnowledgebaseStore";
 interface Props {
     dark: boolean,
     filter: string,
+    onChange: (name: string, checked: boolean) => void,
 }
 
 export function ComponentsTab(props: Props) {
@@ -49,7 +50,7 @@ export function ComponentsTab(props: Props) {
             <PageSection isFilled className="kamelets-page" 
variant={props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                 <Gallery hasGutter>
                     {components.map(c => (
-                        <ComponentCard key={c.component.name} component={c}/>
+                        <ComponentCard key={c.component.name} component={c} 
onChange={props.onChange}  />
                     ))}
                 </Gallery>
             </PageSection>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/kamelets/KameletCard.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/kamelets/KameletCard.tsx
index 045846e9..1dff9f2c 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/kamelets/KameletCard.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/kamelets/KameletCard.tsx
@@ -14,9 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 import {
-    CardHeader, Card, CardTitle, CardBody, CardFooter,Badge
+    CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox
 } from '@patternfly/react-core';
 import '../../designer/karavan.css';
 import {KameletModel} from "karavan-core/lib/model/KameletModels";
@@ -27,21 +27,34 @@ import {shallow} from "zustand/shallow";
 
 interface Props {
     kamelet: KameletModel,
+    onChange: (name: string, checked: boolean) => void
 }
 
 export function KameletCard(props: Props) {
 
     const [setKamelet, setModalOpen] = useKnowledgebaseStore((s) =>
         [s.setKamelet, s.setModalOpen], shallow)
-
+    const [blockedKamelets, setBlockedKamelets] = useState<string[]>();
+    useEffect(() => {
+        setBlockedKamelets(KameletApi.getBlockedKameletNames());
+    }, []);
+    
     const kamelet = props.kamelet;
     const isCustom = 
KameletApi.getCustomKameletNames().includes(kamelet.metadata.name);
 
-    function click (event: React.MouseEvent) {
-        setKamelet(kamelet)
-        setModalOpen(true);
+    function click(event: React.MouseEvent) {
+        const { target } = event;
+        if (!(target as 
HTMLElement).parentElement?.className.includes("block-checkbox")) {
+            setKamelet(kamelet)
+            setModalOpen(true);
+        }
 
     }
+    function selectKamelet(event: React.FormEvent, checked: boolean) {
+        props.onChange(kamelet.metadata.name, checked );
+        setBlockedKamelets([...KameletApi.getBlockedKameletNames()]);
+    }
+    const isblockedKamelet = blockedKamelets ? blockedKamelets.findIndex(r => 
r === kamelet.metadata.name) > -1 : false;
     return (
         <Card  isCompact key={kamelet.metadata.name} className="kamelet-card"
                onClick={event => click(event)}
@@ -49,6 +62,7 @@ export function KameletCard(props: Props) {
             <CardHeader className="header-labels">
                 {isCustom && <Badge className="custom">custom</Badge>}
                 <Badge isRead className="support-level 
labels">{kamelet.metadata.annotations["camel.apache.org/kamelet.support.level"]}</Badge>
+                <Checkbox id={kamelet.metadata.name} className="block-checkbox 
labels" isChecked={!isblockedKamelet} onChange={(_, checked) => 
selectKamelet(_, checked)} />
             </CardHeader>
             <CardHeader>
                 {CamelUi.getIconFromSource(kamelet.icon())}
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/kamelets/KameletsTab.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/kamelets/KameletsTab.tsx
index fb8df6df..353819e4 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/knowledgebase/kamelets/KameletsTab.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/knowledgebase/kamelets/KameletsTab.tsx
@@ -31,11 +31,7 @@ interface Props {
     dark: boolean,
     filter: string,
     customOnly: boolean,
-}
-
-interface Props {
-    dark: boolean,
-    filter: string,
+    onChange: (name: string, checked: boolean) => void
 }
 
 export function KameletsTab(props: Props) {
@@ -55,7 +51,7 @@ export function KameletsTab(props: Props) {
                          variant={dark ? PageSectionVariants.darker : 
PageSectionVariants.light}>
                 <Gallery hasGutter>
                     {kameletList.map(k => (
-                        <KameletCard key={k.metadata.name} kamelet={k}/>
+                        <KameletCard key={k.metadata.name} kamelet={k} 
onChange={props.onChange} />
                     ))}
                 </Gallery>
             </PageSection>
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/MainRoutes.tsx 
b/karavan-web/karavan-app/src/main/webui/src/main/MainRoutes.tsx
index 0434dcef..91956b2c 100644
--- a/karavan-web/karavan-app/src/main/webui/src/main/MainRoutes.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/main/MainRoutes.tsx
@@ -21,9 +21,9 @@ import {ProjectsPage} from "../projects/ProjectsPage";
 import {ProjectPage} from "../project/ProjectPage";
 import {ServicesPage} from "../services/ServicesPage";
 import {ContainersPage} from "../containers/ContainersPage";
-import {KnowledgebasePage} from "../knowledgebase/KnowledgebasePage";
 import {TemplatesPage} from "../templates/TemplatesPage";
 import {ConfigurationPage} from "../config/ConfigurationPage";
+import { KnowledgebaseHome } from '../knowledgebase/KnowledgebaseHome';
 
 export function MainRoutes() {
 
@@ -34,7 +34,7 @@ export function MainRoutes() {
             <Route path="/templates" element={<TemplatesPage 
key={'templates'}/>}/>
             <Route path="/services" element={<ServicesPage key="services"/>}/>
             <Route path="/containers" element={<ContainersPage 
key="services"/>}/>
-            <Route path="/knowledgebase" element={<KnowledgebasePage 
dark={false}/>}/>
+            <Route path="/knowledgebase" element={<KnowledgebaseHome 
dark={false}/>}/>
             <Route path="/configuration" element={<ConfigurationPage 
dark={false}/>}/>
             <Route path="*" element={<Navigate to="/projects" replace/>}/>
         </Routes>
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/useMainHook.tsx 
b/karavan-web/karavan-app/src/main/webui/src/main/useMainHook.tsx
index ed8b5fce..5508002f 100644
--- a/karavan-web/karavan-app/src/main/webui/src/main/useMainHook.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/main/useMainHook.tsx
@@ -50,6 +50,7 @@ export function useMainHook () {
             });
             updateKamelets();
             updateComponents();
+            ProjectService.reloadBlockedTemplates();
             // updateSupportedComponents(); // not implemented yet
         }
     }
@@ -59,7 +60,8 @@ export function useMainHook () {
             ProjectService.reloadKamelets();
         });
     }
-
+ 
+   
     async function updateComponents(): Promise<void> {
         await new Promise(resolve => {
             KaravanApi.getComponents(code => {

Reply via email to