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;
