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 8b5fb5bec65be6cadb835a0af4efc1e37c4b3cb5 Author: Marat Gubaidullin <ma...@talismancloud.io> AuthorDate: Wed Feb 26 14:13:32 2025 -0500 Support dynamic Kamelets --- .../main/webui/src/designer/property/PropertiesHeader.tsx | 12 ++++++------ .../src/main/webui/src/designer/utils/ValidatorUtils.ts | 4 ++++ karavan-core/src/core/api/CamelUtil.ts | 4 ++-- karavan-designer/src/designer/property/PropertiesHeader.tsx | 12 ++++++------ karavan-designer/src/designer/utils/ValidatorUtils.ts | 4 ++++ karavan-space/src/designer/property/PropertiesHeader.tsx | 12 ++++++------ karavan-space/src/designer/utils/ValidatorUtils.ts | 4 ++++ 7 files changed, 32 insertions(+), 20 deletions(-) diff --git a/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx b/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx index 4e99422c..b876adbd 100644 --- a/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx +++ b/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx @@ -29,7 +29,7 @@ import { } from '@patternfly/react-core'; import './DslProperties.css'; import "@patternfly/patternfly/patternfly.css"; -import {CamelUi, RouteToCreate} from "../utils/CamelUi"; +import {CamelUi} from "../utils/CamelUi"; import {useDesignerStore} from "../DesignerStore"; import {shallow} from "zustand/shallow"; import {usePropertiesHook} from "./usePropertiesHook"; @@ -243,7 +243,7 @@ export function PropertiesHeader(props: Props) { const component = ComponentApi.findStepComponent(selectedStep); const groups = (isFrom || isPoll) ? ['consumer', 'common'] : ['producer', 'common']; const isKamelet = CamelUi.isKamelet(selectedStep); - const isStepComponent = !isFrom && selectedStep !== undefined && !isKamelet && ['ToDefinition', 'PollDefinition', 'ToDynamicDefinition'].includes(selectedStep?.dslName); + const showSwitchers = !isFrom && selectedStep !== undefined && ['ToDefinition', 'PollDefinition', 'ToDynamicDefinition'].includes(selectedStep?.dslName); function changeStepType(poll: boolean, dynamic: boolean) { if (selectedStep) { @@ -263,7 +263,7 @@ export function PropertiesHeader(props: Props) { } } - function getComponentStepTypeSwitch() { + function getStepTypeSwitch() { const pollSupported = !component?.component.producerOnly; return (<div style={{display: 'flex', flexDirection: 'row', justifyContent: 'end', width: '100%', gap: '10px'}}> <Tooltip content='Send messages to a dynamic endpoint evaluated on-demand' position='top-end'> @@ -279,7 +279,7 @@ export function PropertiesHeader(props: Props) { isReversed /> </Tooltip> - {pollSupported && + {pollSupported && !isKamelet && <Tooltip content='Simple Polling Consumer to obtain the additional data' position='top-end'> <Switch id="step-type-poll" @@ -303,7 +303,7 @@ export function PropertiesHeader(props: Props) { (selectedStep as any)?.id !== undefined ? <Label isEditable color='blue' isCompact onEditComplete={(event, newText) => onPropertyChange("id", newText)}> {(selectedStep as any)?.id || ''} - </Label> + </Label> : <Button variant="link" onClick={event => onPropertyChange("id", "rc-" + Math.floor(1000 + Math.random() * 9000).toString())}> Add Id </Button> @@ -316,7 +316,7 @@ export function PropertiesHeader(props: Props) { <Title headingLevel="h1" size="md">{title}</Title> {getIdInput()} {getHeaderMenu()} - {isStepComponent && getComponentStepTypeSwitch()} + {showSwitchers && getStepTypeSwitch()} </div> <Text component={TextVariants.p}>{descriptionLines.at(0)}</Text> {descriptionLines.length > 1 && getDescriptionSection()} diff --git a/karavan-app/src/main/webui/src/designer/utils/ValidatorUtils.ts b/karavan-app/src/main/webui/src/designer/utils/ValidatorUtils.ts index b9240dad..89d97e55 100644 --- a/karavan-app/src/main/webui/src/designer/utils/ValidatorUtils.ts +++ b/karavan-app/src/main/webui/src/designer/utils/ValidatorUtils.ts @@ -23,6 +23,10 @@ export function isSensitiveFieldValid(field: string): boolean { const content = field.slice(2, -2).trim(); return content !== ""; } + if (field.startsWith("${") && field.endsWith("}")) { + const content = field.slice(2, -1).trim(); + return content !== ""; + } return false; } diff --git a/karavan-core/src/core/api/CamelUtil.ts b/karavan-core/src/core/api/CamelUtil.ts index ff148a5b..691e8b83 100644 --- a/karavan-core/src/core/api/CamelUtil.ts +++ b/karavan-core/src/core/api/CamelUtil.ts @@ -152,7 +152,7 @@ export class CamelUtil { static isKameletComponent = (element: CamelElement | undefined): boolean => { if (element?.dslName === 'KameletDefinition') { return true; - } else if (element?.dslName === 'FromDefinition' || element?.dslName === 'ToDefinition') { + } else if (element?.dslName === 'FromDefinition' || element?.dslName === 'ToDefinition' || element?.dslName === 'ToDynamicDefinition') { const uri: string = (element as any).uri; return uri !== undefined && uri.startsWith('kamelet:'); } else { @@ -166,7 +166,7 @@ export class CamelUtil { } else if (element.dslName === 'ToDefinition' && (element as ToDefinition).uri?.startsWith('kamelet:')) { const kameletName = (element as ToDefinition).uri?.replace('kamelet:', ''); return KameletApi.findKameletByName(kameletName); - } else if (['FromDefinition', 'FromDefinition', 'ToDefinition'].includes(element.dslName)) { + } else if (['FromDefinition', 'ToDynamicDefinition', 'ToDefinition'].includes(element.dslName)) { const uri: string = (element as any).uri; return uri !== undefined ? KameletApi.findKameletByUri(uri) : undefined; } else { diff --git a/karavan-designer/src/designer/property/PropertiesHeader.tsx b/karavan-designer/src/designer/property/PropertiesHeader.tsx index 4e99422c..b876adbd 100644 --- a/karavan-designer/src/designer/property/PropertiesHeader.tsx +++ b/karavan-designer/src/designer/property/PropertiesHeader.tsx @@ -29,7 +29,7 @@ import { } from '@patternfly/react-core'; import './DslProperties.css'; import "@patternfly/patternfly/patternfly.css"; -import {CamelUi, RouteToCreate} from "../utils/CamelUi"; +import {CamelUi} from "../utils/CamelUi"; import {useDesignerStore} from "../DesignerStore"; import {shallow} from "zustand/shallow"; import {usePropertiesHook} from "./usePropertiesHook"; @@ -243,7 +243,7 @@ export function PropertiesHeader(props: Props) { const component = ComponentApi.findStepComponent(selectedStep); const groups = (isFrom || isPoll) ? ['consumer', 'common'] : ['producer', 'common']; const isKamelet = CamelUi.isKamelet(selectedStep); - const isStepComponent = !isFrom && selectedStep !== undefined && !isKamelet && ['ToDefinition', 'PollDefinition', 'ToDynamicDefinition'].includes(selectedStep?.dslName); + const showSwitchers = !isFrom && selectedStep !== undefined && ['ToDefinition', 'PollDefinition', 'ToDynamicDefinition'].includes(selectedStep?.dslName); function changeStepType(poll: boolean, dynamic: boolean) { if (selectedStep) { @@ -263,7 +263,7 @@ export function PropertiesHeader(props: Props) { } } - function getComponentStepTypeSwitch() { + function getStepTypeSwitch() { const pollSupported = !component?.component.producerOnly; return (<div style={{display: 'flex', flexDirection: 'row', justifyContent: 'end', width: '100%', gap: '10px'}}> <Tooltip content='Send messages to a dynamic endpoint evaluated on-demand' position='top-end'> @@ -279,7 +279,7 @@ export function PropertiesHeader(props: Props) { isReversed /> </Tooltip> - {pollSupported && + {pollSupported && !isKamelet && <Tooltip content='Simple Polling Consumer to obtain the additional data' position='top-end'> <Switch id="step-type-poll" @@ -303,7 +303,7 @@ export function PropertiesHeader(props: Props) { (selectedStep as any)?.id !== undefined ? <Label isEditable color='blue' isCompact onEditComplete={(event, newText) => onPropertyChange("id", newText)}> {(selectedStep as any)?.id || ''} - </Label> + </Label> : <Button variant="link" onClick={event => onPropertyChange("id", "rc-" + Math.floor(1000 + Math.random() * 9000).toString())}> Add Id </Button> @@ -316,7 +316,7 @@ export function PropertiesHeader(props: Props) { <Title headingLevel="h1" size="md">{title}</Title> {getIdInput()} {getHeaderMenu()} - {isStepComponent && getComponentStepTypeSwitch()} + {showSwitchers && getStepTypeSwitch()} </div> <Text component={TextVariants.p}>{descriptionLines.at(0)}</Text> {descriptionLines.length > 1 && getDescriptionSection()} diff --git a/karavan-designer/src/designer/utils/ValidatorUtils.ts b/karavan-designer/src/designer/utils/ValidatorUtils.ts index b9240dad..89d97e55 100644 --- a/karavan-designer/src/designer/utils/ValidatorUtils.ts +++ b/karavan-designer/src/designer/utils/ValidatorUtils.ts @@ -23,6 +23,10 @@ export function isSensitiveFieldValid(field: string): boolean { const content = field.slice(2, -2).trim(); return content !== ""; } + if (field.startsWith("${") && field.endsWith("}")) { + const content = field.slice(2, -1).trim(); + return content !== ""; + } return false; } diff --git a/karavan-space/src/designer/property/PropertiesHeader.tsx b/karavan-space/src/designer/property/PropertiesHeader.tsx index 4e99422c..b876adbd 100644 --- a/karavan-space/src/designer/property/PropertiesHeader.tsx +++ b/karavan-space/src/designer/property/PropertiesHeader.tsx @@ -29,7 +29,7 @@ import { } from '@patternfly/react-core'; import './DslProperties.css'; import "@patternfly/patternfly/patternfly.css"; -import {CamelUi, RouteToCreate} from "../utils/CamelUi"; +import {CamelUi} from "../utils/CamelUi"; import {useDesignerStore} from "../DesignerStore"; import {shallow} from "zustand/shallow"; import {usePropertiesHook} from "./usePropertiesHook"; @@ -243,7 +243,7 @@ export function PropertiesHeader(props: Props) { const component = ComponentApi.findStepComponent(selectedStep); const groups = (isFrom || isPoll) ? ['consumer', 'common'] : ['producer', 'common']; const isKamelet = CamelUi.isKamelet(selectedStep); - const isStepComponent = !isFrom && selectedStep !== undefined && !isKamelet && ['ToDefinition', 'PollDefinition', 'ToDynamicDefinition'].includes(selectedStep?.dslName); + const showSwitchers = !isFrom && selectedStep !== undefined && ['ToDefinition', 'PollDefinition', 'ToDynamicDefinition'].includes(selectedStep?.dslName); function changeStepType(poll: boolean, dynamic: boolean) { if (selectedStep) { @@ -263,7 +263,7 @@ export function PropertiesHeader(props: Props) { } } - function getComponentStepTypeSwitch() { + function getStepTypeSwitch() { const pollSupported = !component?.component.producerOnly; return (<div style={{display: 'flex', flexDirection: 'row', justifyContent: 'end', width: '100%', gap: '10px'}}> <Tooltip content='Send messages to a dynamic endpoint evaluated on-demand' position='top-end'> @@ -279,7 +279,7 @@ export function PropertiesHeader(props: Props) { isReversed /> </Tooltip> - {pollSupported && + {pollSupported && !isKamelet && <Tooltip content='Simple Polling Consumer to obtain the additional data' position='top-end'> <Switch id="step-type-poll" @@ -303,7 +303,7 @@ export function PropertiesHeader(props: Props) { (selectedStep as any)?.id !== undefined ? <Label isEditable color='blue' isCompact onEditComplete={(event, newText) => onPropertyChange("id", newText)}> {(selectedStep as any)?.id || ''} - </Label> + </Label> : <Button variant="link" onClick={event => onPropertyChange("id", "rc-" + Math.floor(1000 + Math.random() * 9000).toString())}> Add Id </Button> @@ -316,7 +316,7 @@ export function PropertiesHeader(props: Props) { <Title headingLevel="h1" size="md">{title}</Title> {getIdInput()} {getHeaderMenu()} - {isStepComponent && getComponentStepTypeSwitch()} + {showSwitchers && getStepTypeSwitch()} </div> <Text component={TextVariants.p}>{descriptionLines.at(0)}</Text> {descriptionLines.length > 1 && getDescriptionSection()} diff --git a/karavan-space/src/designer/utils/ValidatorUtils.ts b/karavan-space/src/designer/utils/ValidatorUtils.ts index b9240dad..89d97e55 100644 --- a/karavan-space/src/designer/utils/ValidatorUtils.ts +++ b/karavan-space/src/designer/utils/ValidatorUtils.ts @@ -23,6 +23,10 @@ export function isSensitiveFieldValid(field: string): boolean { const content = field.slice(2, -2).trim(); return content !== ""; } + if (field.startsWith("${") && field.endsWith("}")) { + const content = field.slice(2, -1).trim(); + return content !== ""; + } return false; }