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 4035e45861f2f89b117a8af3dc9f5de8dac22a79
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Wed Sep 11 12:33:54 2024 -0400

    Fix #1398
---
 .../src/main/webui/src/designer/DesignerStore.ts   |  15 +-
 .../webui/src/designer/selector/DslSelector.css    |  20 +-
 .../webui/src/designer/selector/DslSelector.tsx    | 291 +++++++++++----------
 .../main/webui/src/designer/utils/DslMetaModel.ts  |   1 -
 karavan-designer/src/designer/DesignerStore.ts     |  15 +-
 .../src/designer/selector/DslSelector.css          |  20 +-
 .../src/designer/selector/DslSelector.tsx          | 291 +++++++++++----------
 .../src/designer/utils/DslMetaModel.ts             |   1 -
 karavan-space/src/designer/DesignerStore.ts        |  15 +-
 .../src/designer/selector/DslSelector.css          |  20 +-
 .../src/designer/selector/DslSelector.tsx          | 291 +++++++++++----------
 karavan-space/src/designer/utils/DslMetaModel.ts   |   1 -
 12 files changed, 552 insertions(+), 429 deletions(-)

diff --git a/karavan-app/src/main/webui/src/designer/DesignerStore.ts 
b/karavan-app/src/main/webui/src/designer/DesignerStore.ts
index 79227bdb..24b5f03e 100644
--- a/karavan-app/src/main/webui/src/designer/DesignerStore.ts
+++ b/karavan-app/src/main/webui/src/designer/DesignerStore.ts
@@ -109,6 +109,9 @@ interface SelectorStateState {
     addSelectedLabel: (label: string) => void;
     deleteSelectedLabel: (label: string) => void;
     clearSelectedLabels: () => void;
+    selectedToggles: string [];
+    addSelectedToggle: (label: string) => void;
+    deleteSelectedToggle: (label: string) => void;
 }
 
 export const useSelectorStore = createWithEqualityFn<SelectorStateState>((set) 
=> ({
@@ -117,6 +120,7 @@ export const useSelectorStore = 
createWithEqualityFn<SelectorStateState>((set) =
     parentId: '',
     showSteps: true,
     selectedLabels: [],
+    selectedToggles: ['eip', 'components', 'kamelets'],
     addSelectedLabel: (label: string) => {
         set(state => ({
             selectedLabels: [...state.selectedLabels, label]
@@ -133,8 +137,15 @@ export const useSelectorStore = 
createWithEqualityFn<SelectorStateState>((set) =
             return {selectedLabels : [...state.selectedLabels]};
         })
     },
-    setSelectedLabels: (selectedLabels: string []) => {
-        set({selectedLabels: selectedLabels})
+    addSelectedToggle: (toggle: string) => {
+        set(state => ({
+            selectedToggles: [...state.selectedToggles, toggle]
+        }))
+    },
+    deleteSelectedToggle: (toggle: string) => {
+        set(state => ({
+            selectedToggles: [...state.selectedToggles.filter(x => x !== 
toggle)]
+        }))
     },
     setSelectorTabIndex: (selectorTabIndex?: string | number) => {
         set({selectorTabIndex: selectorTabIndex})
diff --git a/karavan-app/src/main/webui/src/designer/selector/DslSelector.css 
b/karavan-app/src/main/webui/src/designer/selector/DslSelector.css
index 9c7a35be..71bca27f 100644
--- a/karavan-app/src/main/webui/src/designer/selector/DslSelector.css
+++ b/karavan-app/src/main/webui/src/designer/selector/DslSelector.css
@@ -20,6 +20,16 @@
     color: var(--pf-v5-global--Color--100);
 }
 
+.dsl-modal .pf-v5-c-modal-box__header {
+    padding: 24px 0 24px 24px;
+    margin: 0;
+    border-bottom: 1px solid var(--pf-v5-global--BackgroundColor--light-300);
+}
+
+.dsl-modal .pf-v5-c-modal-box__body {
+    padding-top: 0;
+}
+
 .dsl-modal .dsl-card {
     cursor: pointer;
 }
@@ -50,11 +60,11 @@
 }
 
 .dsl-modal .search {
-    position: absolute;
-    top: 24px;
-    right: 72px;
-    display:flex;
-    justify-content:flex-end;
+    /*position: absolute;*/
+    /*top: 24px;*/
+    /*right: 72px;*/
+    /*display:flex;*/
+    /*justify-content:flex-end;*/
 }
 
 .dsl-modal .search .pf-v5-c-form__group-label {
diff --git a/karavan-app/src/main/webui/src/designer/selector/DslSelector.tsx 
b/karavan-app/src/main/webui/src/designer/selector/DslSelector.tsx
index 50424e8c..84f310e4 100644
--- a/karavan-app/src/main/webui/src/designer/selector/DslSelector.tsx
+++ b/karavan-app/src/main/webui/src/designer/selector/DslSelector.tsx
@@ -23,14 +23,10 @@ import {
     Modal,
     PageSection,
     Switch,
-    Tab,
-    Tabs,
-    TabTitleText,
     TextInputGroup,
-    TextInputGroupMain,
-    TextInputGroupUtilities,
+    TextInputGroupUtilities, TextVariants, Text,
     ToggleGroup,
-    ToggleGroupItem
+    ToggleGroupItem, TextContent, Badge, TextInput, Skeleton
 } from '@patternfly/react-core';
 import './DslSelector.css';
 import {CamelUi} from "../utils/CamelUi";
@@ -44,6 +40,7 @@ import TimesIcon from 
"@patternfly/react-icons/dist/esm/icons/times-icon";
 import {addPreferredElement, deletePreferredElement, getPreferredElements} 
from "./DslPreferences";
 import {DslFastCard} from "./DslFastCard";
 import {DslCard} from "./DslCard";
+import {useDebounceValue} from 'usehooks-ts';
 
 interface Props {
     tabIndex?: string | number
@@ -51,53 +48,161 @@ interface Props {
 
 export function DslSelector(props: Props) {
 
-    const [showSelector, showSteps, parentId, parentDsl, selectorTabIndex, 
setShowSelector, setSelectorTabIndex,
-        selectedPosition, selectedLabels, addSelectedLabel, 
deleteSelectedLabel, clearSelectedLabels] =
+    const [showSelector, showSteps, parentId, parentDsl, setShowSelector,
+        selectedPosition, selectedToggles, addSelectedToggle, 
deleteSelectedToggle] =
         useSelectorStore((s) =>
-            [s.showSelector, s.showSteps, s.parentId, s.parentDsl, 
s.selectorTabIndex, s.setShowSelector, s.setSelectorTabIndex,
-                s.selectedPosition, s.selectedLabels, s.addSelectedLabel, 
s.deleteSelectedLabel, s.clearSelectedLabels], shallow)
+            [s.showSelector, s.showSteps, s.parentId, s.parentDsl, 
s.setShowSelector,
+                s.selectedPosition, s.selectedToggles, s.addSelectedToggle, 
s.deleteSelectedToggle], shallow)
 
     const [dark] = useDesignerStore((s) => [s.dark], shallow)
 
     const {onDslSelect} = useRouteDesignerHook();
 
-    const [filter, setFilter] = useState<string>('');
+    const [filter, setFilter] = useDebounceValue('', 300)
     const [customOnly, setCustomOnly] = useState<boolean>(false);
-    const [preferredEip, setPreferredEip] = useState<string[]>([]);
-    const [preferredComponents, setPreferredComponents] = 
useState<string[]>([]);
-    const [preferredKamelets, setPreferredKamelets] = useState<string[]>([]);
+    const [elements, setElements] = useState<DslMetaModel[]>([]);
+    const [preferredElements, setPreferredElements] = useState<string[]>([]);
+    const [ready, setReady] = useState<boolean>(false);
 
     useEffect(() => {
+        setAllElements();
         setPreferences();
-    }, [selectedLabels]);
+        setReady(true);
+    }, []);
+
+    function setAllElements() {
+        const blockedComponents = ComponentApi.getBlockedComponentNames();
+        const blockedKamelets = KameletApi.getBlockedKameletNames();
+        const eipE = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'eip', showSteps);
+        const cE = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'component', showSteps)
+            .filter(dsl => (!blockedComponents.includes(dsl.uri || dsl.name)));
+        const kE = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'kamelet', showSteps)
+            .filter(dsl => (!blockedKamelets.includes(dsl.name)));
+        const e: DslMetaModel[] = [];
+        if (parentDsl !== undefined) {
+            e.push(...eipE)
+        }
+        e.push(...cE)
+        e.push(...kE)
+        setElements(e);
+    }
 
     function setPreferences() {
-        setPreferredEip(getPreferredElements('eip'));
-        setPreferredComponents(getPreferredElements('components'));
-        setPreferredKamelets(getPreferredElements('kamelets'));
+        const p: string[] = []
+        p.push(...getPreferredElements('kamelets'));
+        p.push(...getPreferredElements('components'));
+        p.push(...getPreferredElements('eip'));
+        setPreferredElements(p);
     }
 
-    function selectTab(evt: React.MouseEvent<HTMLElement, MouseEvent>, 
eventKey: string | number) {
-        setSelectorTabIndex(eventKey);
+    function getDslMetaModelType(dsl: DslMetaModel){
+        return ['ToDefinition', 'FromDefinition'].includes(dsl.type) ? 
'components' : (dsl.uri?.startsWith("kamelet:") ? "kamelets" : 'eip');
     }
 
     function selectDsl(evt: React.MouseEvent, dsl: any) {
+        console.log('selectDsl', dsl)
         evt.stopPropagation();
         setFilter('');
         setShowSelector(false);
         onDslSelect(dsl, parentId, selectedPosition);
-        addPreferredElement(type, dsl)
+        addPreferredElement(getDslMetaModelType(dsl), dsl)
     }
+
     function deleteFast(evt: React.MouseEvent, dsl: DslMetaModel) {
+        console.log('deleteFast', dsl)
         evt.stopPropagation();
-        deletePreferredElement(type, dsl);
+        deletePreferredElement(getDslMetaModelType(dsl), dsl);
         setPreferences();
     }
 
     function searchInput() {
         return (
-            <Flex className="search">
-                {selectorTabIndex === 'kamelets' && <FlexItem>
+            <TextInputGroup className="search">
+                <TextInput
+                    defaultValue={filter}
+                    type="text"
+                    autoComplete={"off"}
+                    autoFocus={true}
+                    onChange={(_event, value) => setFilter(value)}
+                    aria-label="text input example"
+                />
+                {/*<TextInputGroupMain className="text-field" type="text" 
autoComplete={"off"}*/}
+                {/*                    value={filter}*/}
+                {/*                    autoFocus={true}*/}
+                {/*                    onChange={(_, value) => 
setFilter(value)}/>*/}
+                <TextInputGroupUtilities>
+                    <Button variant="plain" onClick={_ => setFilter('')}>
+                        <TimesIcon/>
+                    </Button>
+                </TextInputGroupUtilities>
+            </TextInputGroup>
+        )
+    }
+
+    function getToggles() {
+        return (
+            <ToggleGroup aria-label="Default with single selectable">
+                {parentDsl !== undefined && <ToggleGroupItem
+                    text={
+                        <div style={{display: 'flex', flexDirection: 'row'}}>
+                            <div style={{marginRight: '6px'}}>EIP</div>
+                            {ready && <Badge 
isRead={!selectedToggles.includes('eip')}>{eCount}</Badge>}
+                        </div>
+                    }
+                    buttonId="eip"
+                    isSelected={selectedToggles.includes('eip')}
+                    onChange={(_, selected) => {
+                        if (selected) addSelectedToggle('eip')
+                        else deleteSelectedToggle('eip')
+                    }}
+                />}
+                <ToggleGroupItem
+                    text={
+                        <div style={{display: 'flex', flexDirection: 'row'}}>
+                            <div style={{marginRight: '6px'}}>Components</div>
+                            {ready && <Badge 
isRead={!selectedToggles.includes('components')}>{cCount}</Badge>}
+                        </div>
+                    }
+                    buttonId="components"
+                    isSelected={selectedToggles.includes('components')}
+                    onChange={(_, selected) => {
+                        if (selected) addSelectedToggle('components')
+                        else deleteSelectedToggle('components')
+                    }}
+                />
+                <ToggleGroupItem
+                    text={
+                        <div style={{display: 'flex', flexDirection: 'row'}}>
+                            <div style={{marginRight: '6px'}}>Kamelets</div>
+                            {ready && <Badge 
isRead={!selectedToggles.includes('kamelets')}>{kCount}</Badge>}
+                        </div>
+                    }
+                    buttonId="kamelets"
+                    isSelected={selectedToggles.includes('kamelets')}
+                    onChange={(_, selected) => {
+                        if (selected) addSelectedToggle('kamelets')
+                        else deleteSelectedToggle('kamelets')
+                    }}
+                />
+            </ToggleGroup>
+        )
+    }
+
+    function getHeader() {
+        return (
+            <Flex direction={{default: "row"}}>
+                <FlexItem>
+                    <TextContent>
+                        <Text component={TextVariants.h3}>{title}</Text>
+                    </TextContent>
+                </FlexItem>
+                <FlexItem>
+                    {searchInput()}
+                </FlexItem>
+                <FlexItem>
+                    {getToggles()}
+                </FlexItem>
+                {selectedToggles.includes('kamelets') && <FlexItem>
                     <Switch
                         label="Custom only"
                         id="switch"
@@ -105,18 +210,6 @@ export function DslSelector(props: Props) {
                         onChange={(_event, checked) => setCustomOnly(checked)}
                     />
                 </FlexItem>}
-                <FlexItem>
-                    <TextInputGroup>
-                        <TextInputGroupMain className="text-field" type="text" 
autoComplete={"off"}
-                                            value={filter}
-                                            onChange={(_, value) => 
setFilter(value)}/>
-                        <TextInputGroupUtilities>
-                            <Button variant="plain" onClick={_ => 
setFilter('')}>
-                                <TimesIcon/>
-                            </Button>
-                        </TextInputGroupUtilities>
-                    </TextInputGroup>
-                </FlexItem>
             </Flex>
         )
     }
@@ -126,69 +219,32 @@ export function DslSelector(props: Props) {
         setShowSelector(false);
     }
 
-    function selectLabel(eipLabel: string) {
-        if (!selectedLabels.includes(eipLabel)) {
-            addSelectedLabel(eipLabel);
-        } else {
-            deleteSelectedLabel(eipLabel);
-        }
-    }
-
-    function filterElements(elements: DslMetaModel[], type: 'eip' | 
'components' | 'kamelets'): DslMetaModel[] {
-        return elements.filter((dsl: DslMetaModel) => CamelUi.checkFilter(dsl, 
filter))
-            .filter((dsl: DslMetaModel) => {
-                if (type !== 'eip' || selectedLabels.length === 0) {
-                    return true;
-                } else {
-                    return dsl.labels.split(",").some(r => 
selectedLabels.includes(r));
-                }
-            });
-    }
-
-    const isEip = selectorTabIndex === 'eip';
-    const type = isEip ? 'eip' : (selectorTabIndex === 'components' ? 
'components' : 'kamelets');
-    const isRouteConfig = parentDsl === 'RouteConfigurationDefinition';
     const title = parentDsl === undefined ? "Select source" : "Select step";
-    const navigation: string = selectorTabIndex ? selectorTabIndex.toString() 
: '';
-    const blockedComponents = ComponentApi.getBlockedComponentNames();
-    const blockedKamelets = KameletApi.getBlockedKameletNames();
+    const filteredElements: DslMetaModel[] = elements
+        .filter(d => {
+            if (selectedToggles.includes('eip') && d.navigation === 'eip') 
return true
+            else if (selectedToggles.includes('components') && d.navigation 
=== 'component') return true
+            else if (selectedToggles.includes('kamelets') && d.navigation === 
'kamelet') return true
+            else return false;
+        })
+        .filter(d => CamelUi.checkFilter(d, filter));
 
-    const eipElements = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'eip', showSteps);
-    const componentElements = 
CamelUi.getSelectorModelsForParentFiltered(parentDsl, 'component', showSteps)
-        .filter(dsl => (!blockedComponents.includes(dsl.uri || dsl.name)));
-    let kameletElements = 
CamelUi.getSelectorModelsForParentFiltered(parentDsl, 'kamelet', showSteps)
-        .filter(dsl => (!blockedKamelets.includes(dsl.name)));
-    if (customOnly) kameletElements = kameletElements.filter(k => 
KameletApi.getCustomKameletNames().includes(k.name));
+    const eCount = filteredElements.filter(e => e.navigation === 'eip').length;
+    const cCount = filteredElements.filter(e => e.navigation === 
'component').length;
+    const kCount = filteredElements.filter(e => e.navigation === 
'kamelet').length;
 
-    const elements = navigation === 'components'
-        ? componentElements
-        : (navigation === 'kamelets' ? kameletElements : eipElements);
-
-    const preferredElements = navigation === 'components'
-        ? preferredComponents
-        : (navigation === 'kamelets' ? preferredKamelets : preferredEip);
-
-    const filteredEipElements = filterElements(eipElements, 'eip');
-    const filteredComponentElements = filterElements(componentElements, 
'components');
-    const filteredKameletElements = filterElements(kameletElements, 
'kamelets');
-
-    const eipLabels = [...new Set(eipElements.map(e => 
e.labels).join(",").split(",").filter(e => e !== 'eip'))];
-
-
-    const filteredElements = navigation === 'components'
-        ? filteredComponentElements
-        : (navigation === 'kamelets' ? filteredKameletElements : 
filteredEipElements);
-
-    const fastElements = elements.filter((d: DslMetaModel) => {
-        if (isEip) {
+    const fastElements: DslMetaModel[] = elements
+        .filter((d: DslMetaModel) => {
+        if (selectedToggles.includes('eip') && d.navigation === 'eip') {
             return preferredElements.includes(d.dsl);
-        } else if (navigation === 'components') {
+        } else if (d.navigation === 'component' && d.navigation === 
'component') {
             return d.uri && preferredElements.includes(d.uri)
         } else {
             return preferredElements.includes(d.name)
         }
-    }).filter((_, i) => i < 7)
-
+        })
+        .filter(d => CamelUi.checkFilter(d, filter))
+        .filter((_, i) => i < 7)
 
     return (
         <Modal
@@ -197,57 +253,22 @@ export function DslSelector(props: Props) {
             className='dsl-modal'
             isOpen={showSelector}
             onClose={() => close()}
-            header={
-                <Flex direction={{default: "column"}}>
-                    <FlexItem>
-                        <h3>{title}</h3>
-                        {searchInput()}
-                    </FlexItem>
-                    <FlexItem>
-                        <Tabs style={{overflow: 'hidden'}} 
activeKey={selectorTabIndex}
-                              onSelect={selectTab}>
-                            {parentDsl !== undefined &&
-                                <Tab eventKey={"eip"} key={"tab-eip"}
-                                     title={
-                                         <TabTitleText>{`Integration Patterns 
(${filteredEipElements?.length})`}</TabTitleText>}>
-                                </Tab>
-                            }
-                            {!isRouteConfig &&
-                                <Tab eventKey={'components'} 
key={'tab-component'}
-                                     title={
-                                         <TabTitleText>{`Components 
(${filteredComponentElements?.length})`}</TabTitleText>}>
-                                </Tab>
-                            }
-                            {!isRouteConfig &&
-                                <Tab eventKey={'kamelets'} key={"tab-kamelet"}
-                                     title={
-                                         <TabTitleText>{`Kamelets 
(${filteredKameletElements?.length})`}</TabTitleText>}>
-                                </Tab>
-                            }
-                        </Tabs>
-                    </FlexItem>
-                </Flex>
-            }
+            header={getHeader()}
             actions={{}}>
             <PageSection padding={{default: "noPadding"}} variant={dark ? 
"darker" : "light"}>
-                {isEip && <ToggleGroup aria-label="Labels" isCompact>
-                    {eipLabels.map(eipLabel =>
-                        <ToggleGroupItem key={eipLabel}
-                                         text={eipLabel}
-                                         buttonId={eipLabel}
-                                         
isSelected={selectedLabels.includes(eipLabel)}
-                                         onChange={selected => 
selectLabel(eipLabel)}
-                        />)}
-                    <ToggleGroupItem key='clean' buttonId='clean' 
isSelected={false} onChange={clearSelectedLabels}
-                                     icon={<TimesIcon/>}/>
-                </ToggleGroup>}
-                <Gallery key={"fast-gallery-" + navigation} hasGutter 
className="dsl-gallery"
+                {!ready && [1, 2, 3, 4, 5, 6, 7, 8, 9].map(i =>
+                    <React.Fragment>
+                        <Skeleton width={i * 10 + '%'} 
screenreaderText="Loading..."/>
+                        <br/>
+                    </React.Fragment>)
+                }
+                <Gallery key={"fast-gallery"} hasGutter className="dsl-gallery"
                          minWidths={{default: '150px'}}>
                     {showSelector && fastElements.map((dsl: DslMetaModel, 
index: number) =>
                         <DslFastCard dsl={dsl} index={index} 
onDslSelect={selectDsl} onDeleteFast={deleteFast}/>
                     )}
                 </Gallery>
-                <Gallery key={"gallery-" + navigation} hasGutter 
className="dsl-gallery" minWidths={{default: '200px'}}>
+                <Gallery key={"gallery"} hasGutter className="dsl-gallery" 
minWidths={{default: '200px'}}>
                     {showSelector && filteredElements.map((dsl: DslMetaModel, 
index: number) =>
                         <DslCard dsl={dsl} index={index} 
onDslSelect={selectDsl}/>
                     )}
diff --git a/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts 
b/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts
index 89edb33a..221e4c42 100644
--- a/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts
+++ b/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts
@@ -25,7 +25,6 @@ export class DslMetaModel {
     navigation: string = ''
     version: string = ''
     supportLevel: string = ''
-    supportType: string = ''
     remote: boolean = false
     properties: any;
 
diff --git a/karavan-designer/src/designer/DesignerStore.ts 
b/karavan-designer/src/designer/DesignerStore.ts
index 79227bdb..24b5f03e 100644
--- a/karavan-designer/src/designer/DesignerStore.ts
+++ b/karavan-designer/src/designer/DesignerStore.ts
@@ -109,6 +109,9 @@ interface SelectorStateState {
     addSelectedLabel: (label: string) => void;
     deleteSelectedLabel: (label: string) => void;
     clearSelectedLabels: () => void;
+    selectedToggles: string [];
+    addSelectedToggle: (label: string) => void;
+    deleteSelectedToggle: (label: string) => void;
 }
 
 export const useSelectorStore = createWithEqualityFn<SelectorStateState>((set) 
=> ({
@@ -117,6 +120,7 @@ export const useSelectorStore = 
createWithEqualityFn<SelectorStateState>((set) =
     parentId: '',
     showSteps: true,
     selectedLabels: [],
+    selectedToggles: ['eip', 'components', 'kamelets'],
     addSelectedLabel: (label: string) => {
         set(state => ({
             selectedLabels: [...state.selectedLabels, label]
@@ -133,8 +137,15 @@ export const useSelectorStore = 
createWithEqualityFn<SelectorStateState>((set) =
             return {selectedLabels : [...state.selectedLabels]};
         })
     },
-    setSelectedLabels: (selectedLabels: string []) => {
-        set({selectedLabels: selectedLabels})
+    addSelectedToggle: (toggle: string) => {
+        set(state => ({
+            selectedToggles: [...state.selectedToggles, toggle]
+        }))
+    },
+    deleteSelectedToggle: (toggle: string) => {
+        set(state => ({
+            selectedToggles: [...state.selectedToggles.filter(x => x !== 
toggle)]
+        }))
     },
     setSelectorTabIndex: (selectorTabIndex?: string | number) => {
         set({selectorTabIndex: selectorTabIndex})
diff --git a/karavan-designer/src/designer/selector/DslSelector.css 
b/karavan-designer/src/designer/selector/DslSelector.css
index 9c7a35be..71bca27f 100644
--- a/karavan-designer/src/designer/selector/DslSelector.css
+++ b/karavan-designer/src/designer/selector/DslSelector.css
@@ -20,6 +20,16 @@
     color: var(--pf-v5-global--Color--100);
 }
 
+.dsl-modal .pf-v5-c-modal-box__header {
+    padding: 24px 0 24px 24px;
+    margin: 0;
+    border-bottom: 1px solid var(--pf-v5-global--BackgroundColor--light-300);
+}
+
+.dsl-modal .pf-v5-c-modal-box__body {
+    padding-top: 0;
+}
+
 .dsl-modal .dsl-card {
     cursor: pointer;
 }
@@ -50,11 +60,11 @@
 }
 
 .dsl-modal .search {
-    position: absolute;
-    top: 24px;
-    right: 72px;
-    display:flex;
-    justify-content:flex-end;
+    /*position: absolute;*/
+    /*top: 24px;*/
+    /*right: 72px;*/
+    /*display:flex;*/
+    /*justify-content:flex-end;*/
 }
 
 .dsl-modal .search .pf-v5-c-form__group-label {
diff --git a/karavan-designer/src/designer/selector/DslSelector.tsx 
b/karavan-designer/src/designer/selector/DslSelector.tsx
index 50424e8c..84f310e4 100644
--- a/karavan-designer/src/designer/selector/DslSelector.tsx
+++ b/karavan-designer/src/designer/selector/DslSelector.tsx
@@ -23,14 +23,10 @@ import {
     Modal,
     PageSection,
     Switch,
-    Tab,
-    Tabs,
-    TabTitleText,
     TextInputGroup,
-    TextInputGroupMain,
-    TextInputGroupUtilities,
+    TextInputGroupUtilities, TextVariants, Text,
     ToggleGroup,
-    ToggleGroupItem
+    ToggleGroupItem, TextContent, Badge, TextInput, Skeleton
 } from '@patternfly/react-core';
 import './DslSelector.css';
 import {CamelUi} from "../utils/CamelUi";
@@ -44,6 +40,7 @@ import TimesIcon from 
"@patternfly/react-icons/dist/esm/icons/times-icon";
 import {addPreferredElement, deletePreferredElement, getPreferredElements} 
from "./DslPreferences";
 import {DslFastCard} from "./DslFastCard";
 import {DslCard} from "./DslCard";
+import {useDebounceValue} from 'usehooks-ts';
 
 interface Props {
     tabIndex?: string | number
@@ -51,53 +48,161 @@ interface Props {
 
 export function DslSelector(props: Props) {
 
-    const [showSelector, showSteps, parentId, parentDsl, selectorTabIndex, 
setShowSelector, setSelectorTabIndex,
-        selectedPosition, selectedLabels, addSelectedLabel, 
deleteSelectedLabel, clearSelectedLabels] =
+    const [showSelector, showSteps, parentId, parentDsl, setShowSelector,
+        selectedPosition, selectedToggles, addSelectedToggle, 
deleteSelectedToggle] =
         useSelectorStore((s) =>
-            [s.showSelector, s.showSteps, s.parentId, s.parentDsl, 
s.selectorTabIndex, s.setShowSelector, s.setSelectorTabIndex,
-                s.selectedPosition, s.selectedLabels, s.addSelectedLabel, 
s.deleteSelectedLabel, s.clearSelectedLabels], shallow)
+            [s.showSelector, s.showSteps, s.parentId, s.parentDsl, 
s.setShowSelector,
+                s.selectedPosition, s.selectedToggles, s.addSelectedToggle, 
s.deleteSelectedToggle], shallow)
 
     const [dark] = useDesignerStore((s) => [s.dark], shallow)
 
     const {onDslSelect} = useRouteDesignerHook();
 
-    const [filter, setFilter] = useState<string>('');
+    const [filter, setFilter] = useDebounceValue('', 300)
     const [customOnly, setCustomOnly] = useState<boolean>(false);
-    const [preferredEip, setPreferredEip] = useState<string[]>([]);
-    const [preferredComponents, setPreferredComponents] = 
useState<string[]>([]);
-    const [preferredKamelets, setPreferredKamelets] = useState<string[]>([]);
+    const [elements, setElements] = useState<DslMetaModel[]>([]);
+    const [preferredElements, setPreferredElements] = useState<string[]>([]);
+    const [ready, setReady] = useState<boolean>(false);
 
     useEffect(() => {
+        setAllElements();
         setPreferences();
-    }, [selectedLabels]);
+        setReady(true);
+    }, []);
+
+    function setAllElements() {
+        const blockedComponents = ComponentApi.getBlockedComponentNames();
+        const blockedKamelets = KameletApi.getBlockedKameletNames();
+        const eipE = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'eip', showSteps);
+        const cE = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'component', showSteps)
+            .filter(dsl => (!blockedComponents.includes(dsl.uri || dsl.name)));
+        const kE = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'kamelet', showSteps)
+            .filter(dsl => (!blockedKamelets.includes(dsl.name)));
+        const e: DslMetaModel[] = [];
+        if (parentDsl !== undefined) {
+            e.push(...eipE)
+        }
+        e.push(...cE)
+        e.push(...kE)
+        setElements(e);
+    }
 
     function setPreferences() {
-        setPreferredEip(getPreferredElements('eip'));
-        setPreferredComponents(getPreferredElements('components'));
-        setPreferredKamelets(getPreferredElements('kamelets'));
+        const p: string[] = []
+        p.push(...getPreferredElements('kamelets'));
+        p.push(...getPreferredElements('components'));
+        p.push(...getPreferredElements('eip'));
+        setPreferredElements(p);
     }
 
-    function selectTab(evt: React.MouseEvent<HTMLElement, MouseEvent>, 
eventKey: string | number) {
-        setSelectorTabIndex(eventKey);
+    function getDslMetaModelType(dsl: DslMetaModel){
+        return ['ToDefinition', 'FromDefinition'].includes(dsl.type) ? 
'components' : (dsl.uri?.startsWith("kamelet:") ? "kamelets" : 'eip');
     }
 
     function selectDsl(evt: React.MouseEvent, dsl: any) {
+        console.log('selectDsl', dsl)
         evt.stopPropagation();
         setFilter('');
         setShowSelector(false);
         onDslSelect(dsl, parentId, selectedPosition);
-        addPreferredElement(type, dsl)
+        addPreferredElement(getDslMetaModelType(dsl), dsl)
     }
+
     function deleteFast(evt: React.MouseEvent, dsl: DslMetaModel) {
+        console.log('deleteFast', dsl)
         evt.stopPropagation();
-        deletePreferredElement(type, dsl);
+        deletePreferredElement(getDslMetaModelType(dsl), dsl);
         setPreferences();
     }
 
     function searchInput() {
         return (
-            <Flex className="search">
-                {selectorTabIndex === 'kamelets' && <FlexItem>
+            <TextInputGroup className="search">
+                <TextInput
+                    defaultValue={filter}
+                    type="text"
+                    autoComplete={"off"}
+                    autoFocus={true}
+                    onChange={(_event, value) => setFilter(value)}
+                    aria-label="text input example"
+                />
+                {/*<TextInputGroupMain className="text-field" type="text" 
autoComplete={"off"}*/}
+                {/*                    value={filter}*/}
+                {/*                    autoFocus={true}*/}
+                {/*                    onChange={(_, value) => 
setFilter(value)}/>*/}
+                <TextInputGroupUtilities>
+                    <Button variant="plain" onClick={_ => setFilter('')}>
+                        <TimesIcon/>
+                    </Button>
+                </TextInputGroupUtilities>
+            </TextInputGroup>
+        )
+    }
+
+    function getToggles() {
+        return (
+            <ToggleGroup aria-label="Default with single selectable">
+                {parentDsl !== undefined && <ToggleGroupItem
+                    text={
+                        <div style={{display: 'flex', flexDirection: 'row'}}>
+                            <div style={{marginRight: '6px'}}>EIP</div>
+                            {ready && <Badge 
isRead={!selectedToggles.includes('eip')}>{eCount}</Badge>}
+                        </div>
+                    }
+                    buttonId="eip"
+                    isSelected={selectedToggles.includes('eip')}
+                    onChange={(_, selected) => {
+                        if (selected) addSelectedToggle('eip')
+                        else deleteSelectedToggle('eip')
+                    }}
+                />}
+                <ToggleGroupItem
+                    text={
+                        <div style={{display: 'flex', flexDirection: 'row'}}>
+                            <div style={{marginRight: '6px'}}>Components</div>
+                            {ready && <Badge 
isRead={!selectedToggles.includes('components')}>{cCount}</Badge>}
+                        </div>
+                    }
+                    buttonId="components"
+                    isSelected={selectedToggles.includes('components')}
+                    onChange={(_, selected) => {
+                        if (selected) addSelectedToggle('components')
+                        else deleteSelectedToggle('components')
+                    }}
+                />
+                <ToggleGroupItem
+                    text={
+                        <div style={{display: 'flex', flexDirection: 'row'}}>
+                            <div style={{marginRight: '6px'}}>Kamelets</div>
+                            {ready && <Badge 
isRead={!selectedToggles.includes('kamelets')}>{kCount}</Badge>}
+                        </div>
+                    }
+                    buttonId="kamelets"
+                    isSelected={selectedToggles.includes('kamelets')}
+                    onChange={(_, selected) => {
+                        if (selected) addSelectedToggle('kamelets')
+                        else deleteSelectedToggle('kamelets')
+                    }}
+                />
+            </ToggleGroup>
+        )
+    }
+
+    function getHeader() {
+        return (
+            <Flex direction={{default: "row"}}>
+                <FlexItem>
+                    <TextContent>
+                        <Text component={TextVariants.h3}>{title}</Text>
+                    </TextContent>
+                </FlexItem>
+                <FlexItem>
+                    {searchInput()}
+                </FlexItem>
+                <FlexItem>
+                    {getToggles()}
+                </FlexItem>
+                {selectedToggles.includes('kamelets') && <FlexItem>
                     <Switch
                         label="Custom only"
                         id="switch"
@@ -105,18 +210,6 @@ export function DslSelector(props: Props) {
                         onChange={(_event, checked) => setCustomOnly(checked)}
                     />
                 </FlexItem>}
-                <FlexItem>
-                    <TextInputGroup>
-                        <TextInputGroupMain className="text-field" type="text" 
autoComplete={"off"}
-                                            value={filter}
-                                            onChange={(_, value) => 
setFilter(value)}/>
-                        <TextInputGroupUtilities>
-                            <Button variant="plain" onClick={_ => 
setFilter('')}>
-                                <TimesIcon/>
-                            </Button>
-                        </TextInputGroupUtilities>
-                    </TextInputGroup>
-                </FlexItem>
             </Flex>
         )
     }
@@ -126,69 +219,32 @@ export function DslSelector(props: Props) {
         setShowSelector(false);
     }
 
-    function selectLabel(eipLabel: string) {
-        if (!selectedLabels.includes(eipLabel)) {
-            addSelectedLabel(eipLabel);
-        } else {
-            deleteSelectedLabel(eipLabel);
-        }
-    }
-
-    function filterElements(elements: DslMetaModel[], type: 'eip' | 
'components' | 'kamelets'): DslMetaModel[] {
-        return elements.filter((dsl: DslMetaModel) => CamelUi.checkFilter(dsl, 
filter))
-            .filter((dsl: DslMetaModel) => {
-                if (type !== 'eip' || selectedLabels.length === 0) {
-                    return true;
-                } else {
-                    return dsl.labels.split(",").some(r => 
selectedLabels.includes(r));
-                }
-            });
-    }
-
-    const isEip = selectorTabIndex === 'eip';
-    const type = isEip ? 'eip' : (selectorTabIndex === 'components' ? 
'components' : 'kamelets');
-    const isRouteConfig = parentDsl === 'RouteConfigurationDefinition';
     const title = parentDsl === undefined ? "Select source" : "Select step";
-    const navigation: string = selectorTabIndex ? selectorTabIndex.toString() 
: '';
-    const blockedComponents = ComponentApi.getBlockedComponentNames();
-    const blockedKamelets = KameletApi.getBlockedKameletNames();
+    const filteredElements: DslMetaModel[] = elements
+        .filter(d => {
+            if (selectedToggles.includes('eip') && d.navigation === 'eip') 
return true
+            else if (selectedToggles.includes('components') && d.navigation 
=== 'component') return true
+            else if (selectedToggles.includes('kamelets') && d.navigation === 
'kamelet') return true
+            else return false;
+        })
+        .filter(d => CamelUi.checkFilter(d, filter));
 
-    const eipElements = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'eip', showSteps);
-    const componentElements = 
CamelUi.getSelectorModelsForParentFiltered(parentDsl, 'component', showSteps)
-        .filter(dsl => (!blockedComponents.includes(dsl.uri || dsl.name)));
-    let kameletElements = 
CamelUi.getSelectorModelsForParentFiltered(parentDsl, 'kamelet', showSteps)
-        .filter(dsl => (!blockedKamelets.includes(dsl.name)));
-    if (customOnly) kameletElements = kameletElements.filter(k => 
KameletApi.getCustomKameletNames().includes(k.name));
+    const eCount = filteredElements.filter(e => e.navigation === 'eip').length;
+    const cCount = filteredElements.filter(e => e.navigation === 
'component').length;
+    const kCount = filteredElements.filter(e => e.navigation === 
'kamelet').length;
 
-    const elements = navigation === 'components'
-        ? componentElements
-        : (navigation === 'kamelets' ? kameletElements : eipElements);
-
-    const preferredElements = navigation === 'components'
-        ? preferredComponents
-        : (navigation === 'kamelets' ? preferredKamelets : preferredEip);
-
-    const filteredEipElements = filterElements(eipElements, 'eip');
-    const filteredComponentElements = filterElements(componentElements, 
'components');
-    const filteredKameletElements = filterElements(kameletElements, 
'kamelets');
-
-    const eipLabels = [...new Set(eipElements.map(e => 
e.labels).join(",").split(",").filter(e => e !== 'eip'))];
-
-
-    const filteredElements = navigation === 'components'
-        ? filteredComponentElements
-        : (navigation === 'kamelets' ? filteredKameletElements : 
filteredEipElements);
-
-    const fastElements = elements.filter((d: DslMetaModel) => {
-        if (isEip) {
+    const fastElements: DslMetaModel[] = elements
+        .filter((d: DslMetaModel) => {
+        if (selectedToggles.includes('eip') && d.navigation === 'eip') {
             return preferredElements.includes(d.dsl);
-        } else if (navigation === 'components') {
+        } else if (d.navigation === 'component' && d.navigation === 
'component') {
             return d.uri && preferredElements.includes(d.uri)
         } else {
             return preferredElements.includes(d.name)
         }
-    }).filter((_, i) => i < 7)
-
+        })
+        .filter(d => CamelUi.checkFilter(d, filter))
+        .filter((_, i) => i < 7)
 
     return (
         <Modal
@@ -197,57 +253,22 @@ export function DslSelector(props: Props) {
             className='dsl-modal'
             isOpen={showSelector}
             onClose={() => close()}
-            header={
-                <Flex direction={{default: "column"}}>
-                    <FlexItem>
-                        <h3>{title}</h3>
-                        {searchInput()}
-                    </FlexItem>
-                    <FlexItem>
-                        <Tabs style={{overflow: 'hidden'}} 
activeKey={selectorTabIndex}
-                              onSelect={selectTab}>
-                            {parentDsl !== undefined &&
-                                <Tab eventKey={"eip"} key={"tab-eip"}
-                                     title={
-                                         <TabTitleText>{`Integration Patterns 
(${filteredEipElements?.length})`}</TabTitleText>}>
-                                </Tab>
-                            }
-                            {!isRouteConfig &&
-                                <Tab eventKey={'components'} 
key={'tab-component'}
-                                     title={
-                                         <TabTitleText>{`Components 
(${filteredComponentElements?.length})`}</TabTitleText>}>
-                                </Tab>
-                            }
-                            {!isRouteConfig &&
-                                <Tab eventKey={'kamelets'} key={"tab-kamelet"}
-                                     title={
-                                         <TabTitleText>{`Kamelets 
(${filteredKameletElements?.length})`}</TabTitleText>}>
-                                </Tab>
-                            }
-                        </Tabs>
-                    </FlexItem>
-                </Flex>
-            }
+            header={getHeader()}
             actions={{}}>
             <PageSection padding={{default: "noPadding"}} variant={dark ? 
"darker" : "light"}>
-                {isEip && <ToggleGroup aria-label="Labels" isCompact>
-                    {eipLabels.map(eipLabel =>
-                        <ToggleGroupItem key={eipLabel}
-                                         text={eipLabel}
-                                         buttonId={eipLabel}
-                                         
isSelected={selectedLabels.includes(eipLabel)}
-                                         onChange={selected => 
selectLabel(eipLabel)}
-                        />)}
-                    <ToggleGroupItem key='clean' buttonId='clean' 
isSelected={false} onChange={clearSelectedLabels}
-                                     icon={<TimesIcon/>}/>
-                </ToggleGroup>}
-                <Gallery key={"fast-gallery-" + navigation} hasGutter 
className="dsl-gallery"
+                {!ready && [1, 2, 3, 4, 5, 6, 7, 8, 9].map(i =>
+                    <React.Fragment>
+                        <Skeleton width={i * 10 + '%'} 
screenreaderText="Loading..."/>
+                        <br/>
+                    </React.Fragment>)
+                }
+                <Gallery key={"fast-gallery"} hasGutter className="dsl-gallery"
                          minWidths={{default: '150px'}}>
                     {showSelector && fastElements.map((dsl: DslMetaModel, 
index: number) =>
                         <DslFastCard dsl={dsl} index={index} 
onDslSelect={selectDsl} onDeleteFast={deleteFast}/>
                     )}
                 </Gallery>
-                <Gallery key={"gallery-" + navigation} hasGutter 
className="dsl-gallery" minWidths={{default: '200px'}}>
+                <Gallery key={"gallery"} hasGutter className="dsl-gallery" 
minWidths={{default: '200px'}}>
                     {showSelector && filteredElements.map((dsl: DslMetaModel, 
index: number) =>
                         <DslCard dsl={dsl} index={index} 
onDslSelect={selectDsl}/>
                     )}
diff --git a/karavan-designer/src/designer/utils/DslMetaModel.ts 
b/karavan-designer/src/designer/utils/DslMetaModel.ts
index 89edb33a..221e4c42 100644
--- a/karavan-designer/src/designer/utils/DslMetaModel.ts
+++ b/karavan-designer/src/designer/utils/DslMetaModel.ts
@@ -25,7 +25,6 @@ export class DslMetaModel {
     navigation: string = ''
     version: string = ''
     supportLevel: string = ''
-    supportType: string = ''
     remote: boolean = false
     properties: any;
 
diff --git a/karavan-space/src/designer/DesignerStore.ts 
b/karavan-space/src/designer/DesignerStore.ts
index 79227bdb..24b5f03e 100644
--- a/karavan-space/src/designer/DesignerStore.ts
+++ b/karavan-space/src/designer/DesignerStore.ts
@@ -109,6 +109,9 @@ interface SelectorStateState {
     addSelectedLabel: (label: string) => void;
     deleteSelectedLabel: (label: string) => void;
     clearSelectedLabels: () => void;
+    selectedToggles: string [];
+    addSelectedToggle: (label: string) => void;
+    deleteSelectedToggle: (label: string) => void;
 }
 
 export const useSelectorStore = createWithEqualityFn<SelectorStateState>((set) 
=> ({
@@ -117,6 +120,7 @@ export const useSelectorStore = 
createWithEqualityFn<SelectorStateState>((set) =
     parentId: '',
     showSteps: true,
     selectedLabels: [],
+    selectedToggles: ['eip', 'components', 'kamelets'],
     addSelectedLabel: (label: string) => {
         set(state => ({
             selectedLabels: [...state.selectedLabels, label]
@@ -133,8 +137,15 @@ export const useSelectorStore = 
createWithEqualityFn<SelectorStateState>((set) =
             return {selectedLabels : [...state.selectedLabels]};
         })
     },
-    setSelectedLabels: (selectedLabels: string []) => {
-        set({selectedLabels: selectedLabels})
+    addSelectedToggle: (toggle: string) => {
+        set(state => ({
+            selectedToggles: [...state.selectedToggles, toggle]
+        }))
+    },
+    deleteSelectedToggle: (toggle: string) => {
+        set(state => ({
+            selectedToggles: [...state.selectedToggles.filter(x => x !== 
toggle)]
+        }))
     },
     setSelectorTabIndex: (selectorTabIndex?: string | number) => {
         set({selectorTabIndex: selectorTabIndex})
diff --git a/karavan-space/src/designer/selector/DslSelector.css 
b/karavan-space/src/designer/selector/DslSelector.css
index 9c7a35be..71bca27f 100644
--- a/karavan-space/src/designer/selector/DslSelector.css
+++ b/karavan-space/src/designer/selector/DslSelector.css
@@ -20,6 +20,16 @@
     color: var(--pf-v5-global--Color--100);
 }
 
+.dsl-modal .pf-v5-c-modal-box__header {
+    padding: 24px 0 24px 24px;
+    margin: 0;
+    border-bottom: 1px solid var(--pf-v5-global--BackgroundColor--light-300);
+}
+
+.dsl-modal .pf-v5-c-modal-box__body {
+    padding-top: 0;
+}
+
 .dsl-modal .dsl-card {
     cursor: pointer;
 }
@@ -50,11 +60,11 @@
 }
 
 .dsl-modal .search {
-    position: absolute;
-    top: 24px;
-    right: 72px;
-    display:flex;
-    justify-content:flex-end;
+    /*position: absolute;*/
+    /*top: 24px;*/
+    /*right: 72px;*/
+    /*display:flex;*/
+    /*justify-content:flex-end;*/
 }
 
 .dsl-modal .search .pf-v5-c-form__group-label {
diff --git a/karavan-space/src/designer/selector/DslSelector.tsx 
b/karavan-space/src/designer/selector/DslSelector.tsx
index 50424e8c..84f310e4 100644
--- a/karavan-space/src/designer/selector/DslSelector.tsx
+++ b/karavan-space/src/designer/selector/DslSelector.tsx
@@ -23,14 +23,10 @@ import {
     Modal,
     PageSection,
     Switch,
-    Tab,
-    Tabs,
-    TabTitleText,
     TextInputGroup,
-    TextInputGroupMain,
-    TextInputGroupUtilities,
+    TextInputGroupUtilities, TextVariants, Text,
     ToggleGroup,
-    ToggleGroupItem
+    ToggleGroupItem, TextContent, Badge, TextInput, Skeleton
 } from '@patternfly/react-core';
 import './DslSelector.css';
 import {CamelUi} from "../utils/CamelUi";
@@ -44,6 +40,7 @@ import TimesIcon from 
"@patternfly/react-icons/dist/esm/icons/times-icon";
 import {addPreferredElement, deletePreferredElement, getPreferredElements} 
from "./DslPreferences";
 import {DslFastCard} from "./DslFastCard";
 import {DslCard} from "./DslCard";
+import {useDebounceValue} from 'usehooks-ts';
 
 interface Props {
     tabIndex?: string | number
@@ -51,53 +48,161 @@ interface Props {
 
 export function DslSelector(props: Props) {
 
-    const [showSelector, showSteps, parentId, parentDsl, selectorTabIndex, 
setShowSelector, setSelectorTabIndex,
-        selectedPosition, selectedLabels, addSelectedLabel, 
deleteSelectedLabel, clearSelectedLabels] =
+    const [showSelector, showSteps, parentId, parentDsl, setShowSelector,
+        selectedPosition, selectedToggles, addSelectedToggle, 
deleteSelectedToggle] =
         useSelectorStore((s) =>
-            [s.showSelector, s.showSteps, s.parentId, s.parentDsl, 
s.selectorTabIndex, s.setShowSelector, s.setSelectorTabIndex,
-                s.selectedPosition, s.selectedLabels, s.addSelectedLabel, 
s.deleteSelectedLabel, s.clearSelectedLabels], shallow)
+            [s.showSelector, s.showSteps, s.parentId, s.parentDsl, 
s.setShowSelector,
+                s.selectedPosition, s.selectedToggles, s.addSelectedToggle, 
s.deleteSelectedToggle], shallow)
 
     const [dark] = useDesignerStore((s) => [s.dark], shallow)
 
     const {onDslSelect} = useRouteDesignerHook();
 
-    const [filter, setFilter] = useState<string>('');
+    const [filter, setFilter] = useDebounceValue('', 300)
     const [customOnly, setCustomOnly] = useState<boolean>(false);
-    const [preferredEip, setPreferredEip] = useState<string[]>([]);
-    const [preferredComponents, setPreferredComponents] = 
useState<string[]>([]);
-    const [preferredKamelets, setPreferredKamelets] = useState<string[]>([]);
+    const [elements, setElements] = useState<DslMetaModel[]>([]);
+    const [preferredElements, setPreferredElements] = useState<string[]>([]);
+    const [ready, setReady] = useState<boolean>(false);
 
     useEffect(() => {
+        setAllElements();
         setPreferences();
-    }, [selectedLabels]);
+        setReady(true);
+    }, []);
+
+    function setAllElements() {
+        const blockedComponents = ComponentApi.getBlockedComponentNames();
+        const blockedKamelets = KameletApi.getBlockedKameletNames();
+        const eipE = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'eip', showSteps);
+        const cE = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'component', showSteps)
+            .filter(dsl => (!blockedComponents.includes(dsl.uri || dsl.name)));
+        const kE = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'kamelet', showSteps)
+            .filter(dsl => (!blockedKamelets.includes(dsl.name)));
+        const e: DslMetaModel[] = [];
+        if (parentDsl !== undefined) {
+            e.push(...eipE)
+        }
+        e.push(...cE)
+        e.push(...kE)
+        setElements(e);
+    }
 
     function setPreferences() {
-        setPreferredEip(getPreferredElements('eip'));
-        setPreferredComponents(getPreferredElements('components'));
-        setPreferredKamelets(getPreferredElements('kamelets'));
+        const p: string[] = []
+        p.push(...getPreferredElements('kamelets'));
+        p.push(...getPreferredElements('components'));
+        p.push(...getPreferredElements('eip'));
+        setPreferredElements(p);
     }
 
-    function selectTab(evt: React.MouseEvent<HTMLElement, MouseEvent>, 
eventKey: string | number) {
-        setSelectorTabIndex(eventKey);
+    function getDslMetaModelType(dsl: DslMetaModel){
+        return ['ToDefinition', 'FromDefinition'].includes(dsl.type) ? 
'components' : (dsl.uri?.startsWith("kamelet:") ? "kamelets" : 'eip');
     }
 
     function selectDsl(evt: React.MouseEvent, dsl: any) {
+        console.log('selectDsl', dsl)
         evt.stopPropagation();
         setFilter('');
         setShowSelector(false);
         onDslSelect(dsl, parentId, selectedPosition);
-        addPreferredElement(type, dsl)
+        addPreferredElement(getDslMetaModelType(dsl), dsl)
     }
+
     function deleteFast(evt: React.MouseEvent, dsl: DslMetaModel) {
+        console.log('deleteFast', dsl)
         evt.stopPropagation();
-        deletePreferredElement(type, dsl);
+        deletePreferredElement(getDslMetaModelType(dsl), dsl);
         setPreferences();
     }
 
     function searchInput() {
         return (
-            <Flex className="search">
-                {selectorTabIndex === 'kamelets' && <FlexItem>
+            <TextInputGroup className="search">
+                <TextInput
+                    defaultValue={filter}
+                    type="text"
+                    autoComplete={"off"}
+                    autoFocus={true}
+                    onChange={(_event, value) => setFilter(value)}
+                    aria-label="text input example"
+                />
+                {/*<TextInputGroupMain className="text-field" type="text" 
autoComplete={"off"}*/}
+                {/*                    value={filter}*/}
+                {/*                    autoFocus={true}*/}
+                {/*                    onChange={(_, value) => 
setFilter(value)}/>*/}
+                <TextInputGroupUtilities>
+                    <Button variant="plain" onClick={_ => setFilter('')}>
+                        <TimesIcon/>
+                    </Button>
+                </TextInputGroupUtilities>
+            </TextInputGroup>
+        )
+    }
+
+    function getToggles() {
+        return (
+            <ToggleGroup aria-label="Default with single selectable">
+                {parentDsl !== undefined && <ToggleGroupItem
+                    text={
+                        <div style={{display: 'flex', flexDirection: 'row'}}>
+                            <div style={{marginRight: '6px'}}>EIP</div>
+                            {ready && <Badge 
isRead={!selectedToggles.includes('eip')}>{eCount}</Badge>}
+                        </div>
+                    }
+                    buttonId="eip"
+                    isSelected={selectedToggles.includes('eip')}
+                    onChange={(_, selected) => {
+                        if (selected) addSelectedToggle('eip')
+                        else deleteSelectedToggle('eip')
+                    }}
+                />}
+                <ToggleGroupItem
+                    text={
+                        <div style={{display: 'flex', flexDirection: 'row'}}>
+                            <div style={{marginRight: '6px'}}>Components</div>
+                            {ready && <Badge 
isRead={!selectedToggles.includes('components')}>{cCount}</Badge>}
+                        </div>
+                    }
+                    buttonId="components"
+                    isSelected={selectedToggles.includes('components')}
+                    onChange={(_, selected) => {
+                        if (selected) addSelectedToggle('components')
+                        else deleteSelectedToggle('components')
+                    }}
+                />
+                <ToggleGroupItem
+                    text={
+                        <div style={{display: 'flex', flexDirection: 'row'}}>
+                            <div style={{marginRight: '6px'}}>Kamelets</div>
+                            {ready && <Badge 
isRead={!selectedToggles.includes('kamelets')}>{kCount}</Badge>}
+                        </div>
+                    }
+                    buttonId="kamelets"
+                    isSelected={selectedToggles.includes('kamelets')}
+                    onChange={(_, selected) => {
+                        if (selected) addSelectedToggle('kamelets')
+                        else deleteSelectedToggle('kamelets')
+                    }}
+                />
+            </ToggleGroup>
+        )
+    }
+
+    function getHeader() {
+        return (
+            <Flex direction={{default: "row"}}>
+                <FlexItem>
+                    <TextContent>
+                        <Text component={TextVariants.h3}>{title}</Text>
+                    </TextContent>
+                </FlexItem>
+                <FlexItem>
+                    {searchInput()}
+                </FlexItem>
+                <FlexItem>
+                    {getToggles()}
+                </FlexItem>
+                {selectedToggles.includes('kamelets') && <FlexItem>
                     <Switch
                         label="Custom only"
                         id="switch"
@@ -105,18 +210,6 @@ export function DslSelector(props: Props) {
                         onChange={(_event, checked) => setCustomOnly(checked)}
                     />
                 </FlexItem>}
-                <FlexItem>
-                    <TextInputGroup>
-                        <TextInputGroupMain className="text-field" type="text" 
autoComplete={"off"}
-                                            value={filter}
-                                            onChange={(_, value) => 
setFilter(value)}/>
-                        <TextInputGroupUtilities>
-                            <Button variant="plain" onClick={_ => 
setFilter('')}>
-                                <TimesIcon/>
-                            </Button>
-                        </TextInputGroupUtilities>
-                    </TextInputGroup>
-                </FlexItem>
             </Flex>
         )
     }
@@ -126,69 +219,32 @@ export function DslSelector(props: Props) {
         setShowSelector(false);
     }
 
-    function selectLabel(eipLabel: string) {
-        if (!selectedLabels.includes(eipLabel)) {
-            addSelectedLabel(eipLabel);
-        } else {
-            deleteSelectedLabel(eipLabel);
-        }
-    }
-
-    function filterElements(elements: DslMetaModel[], type: 'eip' | 
'components' | 'kamelets'): DslMetaModel[] {
-        return elements.filter((dsl: DslMetaModel) => CamelUi.checkFilter(dsl, 
filter))
-            .filter((dsl: DslMetaModel) => {
-                if (type !== 'eip' || selectedLabels.length === 0) {
-                    return true;
-                } else {
-                    return dsl.labels.split(",").some(r => 
selectedLabels.includes(r));
-                }
-            });
-    }
-
-    const isEip = selectorTabIndex === 'eip';
-    const type = isEip ? 'eip' : (selectorTabIndex === 'components' ? 
'components' : 'kamelets');
-    const isRouteConfig = parentDsl === 'RouteConfigurationDefinition';
     const title = parentDsl === undefined ? "Select source" : "Select step";
-    const navigation: string = selectorTabIndex ? selectorTabIndex.toString() 
: '';
-    const blockedComponents = ComponentApi.getBlockedComponentNames();
-    const blockedKamelets = KameletApi.getBlockedKameletNames();
+    const filteredElements: DslMetaModel[] = elements
+        .filter(d => {
+            if (selectedToggles.includes('eip') && d.navigation === 'eip') 
return true
+            else if (selectedToggles.includes('components') && d.navigation 
=== 'component') return true
+            else if (selectedToggles.includes('kamelets') && d.navigation === 
'kamelet') return true
+            else return false;
+        })
+        .filter(d => CamelUi.checkFilter(d, filter));
 
-    const eipElements = CamelUi.getSelectorModelsForParentFiltered(parentDsl, 
'eip', showSteps);
-    const componentElements = 
CamelUi.getSelectorModelsForParentFiltered(parentDsl, 'component', showSteps)
-        .filter(dsl => (!blockedComponents.includes(dsl.uri || dsl.name)));
-    let kameletElements = 
CamelUi.getSelectorModelsForParentFiltered(parentDsl, 'kamelet', showSteps)
-        .filter(dsl => (!blockedKamelets.includes(dsl.name)));
-    if (customOnly) kameletElements = kameletElements.filter(k => 
KameletApi.getCustomKameletNames().includes(k.name));
+    const eCount = filteredElements.filter(e => e.navigation === 'eip').length;
+    const cCount = filteredElements.filter(e => e.navigation === 
'component').length;
+    const kCount = filteredElements.filter(e => e.navigation === 
'kamelet').length;
 
-    const elements = navigation === 'components'
-        ? componentElements
-        : (navigation === 'kamelets' ? kameletElements : eipElements);
-
-    const preferredElements = navigation === 'components'
-        ? preferredComponents
-        : (navigation === 'kamelets' ? preferredKamelets : preferredEip);
-
-    const filteredEipElements = filterElements(eipElements, 'eip');
-    const filteredComponentElements = filterElements(componentElements, 
'components');
-    const filteredKameletElements = filterElements(kameletElements, 
'kamelets');
-
-    const eipLabels = [...new Set(eipElements.map(e => 
e.labels).join(",").split(",").filter(e => e !== 'eip'))];
-
-
-    const filteredElements = navigation === 'components'
-        ? filteredComponentElements
-        : (navigation === 'kamelets' ? filteredKameletElements : 
filteredEipElements);
-
-    const fastElements = elements.filter((d: DslMetaModel) => {
-        if (isEip) {
+    const fastElements: DslMetaModel[] = elements
+        .filter((d: DslMetaModel) => {
+        if (selectedToggles.includes('eip') && d.navigation === 'eip') {
             return preferredElements.includes(d.dsl);
-        } else if (navigation === 'components') {
+        } else if (d.navigation === 'component' && d.navigation === 
'component') {
             return d.uri && preferredElements.includes(d.uri)
         } else {
             return preferredElements.includes(d.name)
         }
-    }).filter((_, i) => i < 7)
-
+        })
+        .filter(d => CamelUi.checkFilter(d, filter))
+        .filter((_, i) => i < 7)
 
     return (
         <Modal
@@ -197,57 +253,22 @@ export function DslSelector(props: Props) {
             className='dsl-modal'
             isOpen={showSelector}
             onClose={() => close()}
-            header={
-                <Flex direction={{default: "column"}}>
-                    <FlexItem>
-                        <h3>{title}</h3>
-                        {searchInput()}
-                    </FlexItem>
-                    <FlexItem>
-                        <Tabs style={{overflow: 'hidden'}} 
activeKey={selectorTabIndex}
-                              onSelect={selectTab}>
-                            {parentDsl !== undefined &&
-                                <Tab eventKey={"eip"} key={"tab-eip"}
-                                     title={
-                                         <TabTitleText>{`Integration Patterns 
(${filteredEipElements?.length})`}</TabTitleText>}>
-                                </Tab>
-                            }
-                            {!isRouteConfig &&
-                                <Tab eventKey={'components'} 
key={'tab-component'}
-                                     title={
-                                         <TabTitleText>{`Components 
(${filteredComponentElements?.length})`}</TabTitleText>}>
-                                </Tab>
-                            }
-                            {!isRouteConfig &&
-                                <Tab eventKey={'kamelets'} key={"tab-kamelet"}
-                                     title={
-                                         <TabTitleText>{`Kamelets 
(${filteredKameletElements?.length})`}</TabTitleText>}>
-                                </Tab>
-                            }
-                        </Tabs>
-                    </FlexItem>
-                </Flex>
-            }
+            header={getHeader()}
             actions={{}}>
             <PageSection padding={{default: "noPadding"}} variant={dark ? 
"darker" : "light"}>
-                {isEip && <ToggleGroup aria-label="Labels" isCompact>
-                    {eipLabels.map(eipLabel =>
-                        <ToggleGroupItem key={eipLabel}
-                                         text={eipLabel}
-                                         buttonId={eipLabel}
-                                         
isSelected={selectedLabels.includes(eipLabel)}
-                                         onChange={selected => 
selectLabel(eipLabel)}
-                        />)}
-                    <ToggleGroupItem key='clean' buttonId='clean' 
isSelected={false} onChange={clearSelectedLabels}
-                                     icon={<TimesIcon/>}/>
-                </ToggleGroup>}
-                <Gallery key={"fast-gallery-" + navigation} hasGutter 
className="dsl-gallery"
+                {!ready && [1, 2, 3, 4, 5, 6, 7, 8, 9].map(i =>
+                    <React.Fragment>
+                        <Skeleton width={i * 10 + '%'} 
screenreaderText="Loading..."/>
+                        <br/>
+                    </React.Fragment>)
+                }
+                <Gallery key={"fast-gallery"} hasGutter className="dsl-gallery"
                          minWidths={{default: '150px'}}>
                     {showSelector && fastElements.map((dsl: DslMetaModel, 
index: number) =>
                         <DslFastCard dsl={dsl} index={index} 
onDslSelect={selectDsl} onDeleteFast={deleteFast}/>
                     )}
                 </Gallery>
-                <Gallery key={"gallery-" + navigation} hasGutter 
className="dsl-gallery" minWidths={{default: '200px'}}>
+                <Gallery key={"gallery"} hasGutter className="dsl-gallery" 
minWidths={{default: '200px'}}>
                     {showSelector && filteredElements.map((dsl: DslMetaModel, 
index: number) =>
                         <DslCard dsl={dsl} index={index} 
onDslSelect={selectDsl}/>
                     )}
diff --git a/karavan-space/src/designer/utils/DslMetaModel.ts 
b/karavan-space/src/designer/utils/DslMetaModel.ts
index 89edb33a..221e4c42 100644
--- a/karavan-space/src/designer/utils/DslMetaModel.ts
+++ b/karavan-space/src/designer/utils/DslMetaModel.ts
@@ -25,7 +25,6 @@ export class DslMetaModel {
     navigation: string = ''
     version: string = ''
     supportLevel: string = ''
-    supportType: string = ''
     remote: boolean = false
     properties: any;
 

Reply via email to