This is an automated email from the ASF dual-hosted git repository.
marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
The following commit(s) were added to refs/heads/main by this push:
new a9d79f19 Route Template Parameters Placeholder
a9d79f19 is described below
commit a9d79f19edf0c350c568f0917dc5eaa51d2b4fa4
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Wed Nov 27 10:58:52 2024 -0500
Route Template Parameters Placeholder
---
.../src/main/webui/src/designer/DesignerStore.ts | 10 ++++
.../webui/src/designer/property/DslProperties.tsx | 16 +++++-
.../property/PropertyPlaceholderDropdown.css | 5 ++
.../property/PropertyPlaceholderDropdown.tsx | 34 +++++++----
.../src/main/webui/src/designer/utils/CamelUi.tsx | 2 +-
karavan-core/src/core/api/CamelDefinitionApiExt.ts | 17 ++++++
karavan-core/src/core/api/CamelDefinitionYaml.ts | 2 +-
karavan-designer/public/example/demo.camel.yaml | 65 ++++++++--------------
karavan-designer/src/designer/DesignerStore.ts | 10 ++++
.../src/designer/property/DslProperties.tsx | 16 +++++-
.../property/PropertyPlaceholderDropdown.css | 5 ++
.../property/PropertyPlaceholderDropdown.tsx | 34 +++++++----
karavan-designer/src/designer/utils/CamelUi.tsx | 2 +-
karavan-space/src/designer/DesignerStore.ts | 10 ++++
.../src/designer/property/DslProperties.tsx | 16 +++++-
.../property/PropertyPlaceholderDropdown.css | 5 ++
.../property/PropertyPlaceholderDropdown.tsx | 34 +++++++----
karavan-space/src/designer/utils/CamelUi.tsx | 2 +-
18 files changed, 200 insertions(+), 85 deletions(-)
diff --git a/karavan-app/src/main/webui/src/designer/DesignerStore.ts
b/karavan-app/src/main/webui/src/designer/DesignerStore.ts
index cd610c0f..7535b93b 100644
--- a/karavan-app/src/main/webui/src/designer/DesignerStore.ts
+++ b/karavan-app/src/main/webui/src/designer/DesignerStore.ts
@@ -213,6 +213,7 @@ type DesignerState = {
left: number,
moveElements: [string | undefined, string | undefined],
propertyPlaceholders: string[],
+ parameterPlaceholders: [string, string][], // route template parameters
beans: BeanFactoryDefinition[]
}
@@ -232,6 +233,7 @@ const designerState: DesignerState = {
left: 0,
moveElements: [undefined, undefined],
propertyPlaceholders: [],
+ parameterPlaceholders: [],
beans: []
};
@@ -249,6 +251,7 @@ type DesignerAction = {
setNotification: (notificationBadge: boolean, notificationMessage:
[string, string]) => void;
setMoveElements: (moveElements: [string | undefined, string | undefined])
=> void;
setPropertyPlaceholders: (propertyPlaceholders: string[]) => void;
+ setParameterPlaceholders: (parameterPlaceholders: [string, string][]) =>
void;
setBeans: (beans: BeanFactoryDefinition[]) => void;
}
@@ -309,6 +312,13 @@ export const useDesignerStore =
createWithEqualityFn<DesignerState & DesignerAct
return state;
})
},
+ setParameterPlaceholders: (parameterPlaceholders: [string, string][]) => {
+ set((state: DesignerState) => {
+ state.parameterPlaceholders.length = 0;
+ state.parameterPlaceholders.push(...parameterPlaceholders);
+ return state;
+ })
+ },
setBeans: (beans: BeanFactoryDefinition[]) => {
set((state: DesignerState) => {
return {beans: [...beans]};
diff --git a/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx
b/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx
index dd2376ee..52b36ef7 100644
--- a/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx
+++ b/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx
@@ -47,6 +47,7 @@ import {PropertiesHeader} from "./PropertiesHeader";
import {PropertyUtil} from "./property/PropertyUtil";
import {usePropertiesStore} from "./PropertyStore";
import TimesIcon from "@patternfly/react-icons/dist/esm/icons/times-icon";
+import {RouteTemplateDefinition} from "karavan-core/lib/model/CamelDefinition";
interface Props {
designerType: 'routes' | 'rest' | 'beans'
@@ -65,8 +66,8 @@ export function DslProperties(props: Props) {
} =
usePropertiesHook(props.designerType);
- const [selectedStep, dark]
- = useDesignerStore((s) => [s.selectedStep, s.dark], shallow)
+ const [selectedStep, dark, setParameterPlaceholders]
+ = useDesignerStore((s) => [s.selectedStep, s.dark,
s.setParameterPlaceholders], shallow)
const [propertyFilter, changedOnly, requiredOnly, setChangedOnly,
sensitiveOnly, setSensitiveOnly, setPropertyFilter, setRequiredOnly]
= usePropertiesStore((s) => [s.propertyFilter, s.changedOnly,
s.requiredOnly, s.setChangedOnly, s.sensitiveOnly, s.setSensitiveOnly,
s.setPropertyFilter, s.setRequiredOnly], shallow)
@@ -78,8 +79,19 @@ export function DslProperties(props: Props) {
setChangedOnly(false);
setSensitiveOnly(false);
setPropertyFilter('');
+ getRouteTemplateParameters()
}, [selectedStep?.uuid])
+ function getRouteTemplateParameters() {
+ if (selectedStep) {
+ const root =
CamelDefinitionApiExt.findTopRouteElement(integration, selectedStep.uuid);
+ if ('RouteTemplateDefinition' === root?.dslName) {
+ const paramPlaceholders: [string, string][] = (root as
RouteTemplateDefinition).parameters?.map(p => [p.name, p.description ||'']) ||
[];
+ setParameterPlaceholders(paramPlaceholders);
+ }
+ }
+ }
+
function getClonableElementHeader(): React.JSX.Element {
const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep);
const description = selectedStep?.dslName ?
CamelMetadataApi.getCamelModelMetadataByClassName(selectedStep?.dslName)?.description
: title;
diff --git
a/karavan-app/src/main/webui/src/designer/property/property/PropertyPlaceholderDropdown.css
b/karavan-app/src/main/webui/src/designer/property/property/PropertyPlaceholderDropdown.css
index 43991634..3984ae02 100644
---
a/karavan-app/src/main/webui/src/designer/property/property/PropertyPlaceholderDropdown.css
+++
b/karavan-app/src/main/webui/src/designer/property/property/PropertyPlaceholderDropdown.css
@@ -28,6 +28,11 @@
display: none;
}
+.karavan .properties .property-placeholder-dropdown .pf-v5-c-menu__group-title
{
+ font-weight: bold;
+ font-size: 13px;
+}
+
.pf-v5-c-popover .property-placeholder-toggle-form {
width: 300px;
}
diff --git
a/karavan-app/src/main/webui/src/designer/property/property/PropertyPlaceholderDropdown.tsx
b/karavan-app/src/main/webui/src/designer/property/property/PropertyPlaceholderDropdown.tsx
index e920ce0a..ec532b55 100644
---
a/karavan-app/src/main/webui/src/designer/property/property/PropertyPlaceholderDropdown.tsx
+++
b/karavan-app/src/main/webui/src/designer/property/property/PropertyPlaceholderDropdown.tsx
@@ -59,8 +59,8 @@ interface Props {
export function PropertyPlaceholderDropdown(props: Props) {
- const [propertyPlaceholders, setPropertyPlaceholders] =
useDesignerStore((s) =>
- [s.propertyPlaceholders, s.setPropertyPlaceholders], shallow)
+ const [propertyPlaceholders, setPropertyPlaceholders,
parameterPlaceholders] = useDesignerStore((s) =>
+ [s.propertyPlaceholders, s.setPropertyPlaceholders,
s.parameterPlaceholders], shallow)
const [isOpenPlaceholdersDropdown, setOpenPlaceholdersDropdown] =
useState<boolean>(false);
const [propValue, setPropValue] = useState<string>('');
const [isVisible, setIsVisible] = React.useState(false);
@@ -72,13 +72,15 @@ export function PropertyPlaceholderDropdown(props: Props) {
const {property, value} = props;
const valueIsPlaceholder: boolean = value &&
value.toString().startsWith('{{') && value.toString().endsWith('}}');
const placeholderValue = valueIsPlaceholder ?
value.toString().replace('{{', '').replace('}}', '') : undefined;
+ const isRouteTemplateParameter = parameterPlaceholders.map(p =>
p[0]).includes(placeholderValue);
const showAddButton = valueIsPlaceholder
+ && !isRouteTemplateParameter
&& !propertyPlaceholders.includes(placeholderValue)
- && !SYNTAX_EXAMPLES.map(se=>
se.value).includes(removeBrackets(placeholderValue))
- && SYNTAX_EXAMPLES.findIndex(se=>
removeBrackets(placeholderValue).startsWith(se.key)) === -1;
+ && !SYNTAX_EXAMPLES.map(se =>
se.value).includes(removeBrackets(placeholderValue))
+ && SYNTAX_EXAMPLES.findIndex(se =>
removeBrackets(placeholderValue).startsWith(se.key)) === -1;
const popoverId = "popover-selector-" + property.hasOwnProperty('name') ?
(property as any).name : (property as any).id;
- const hasPlaceholders = (propertyPlaceholders &&
propertyPlaceholders.length > 0 );
+ const hasPlaceholders = (propertyPlaceholders &&
propertyPlaceholders.length > 0);
function parametersChanged(value: string | number | boolean | any) {
if (property instanceof ComponentProperty) {
@@ -167,13 +169,23 @@ export function PropertyPlaceholderDropdown(props: Props)
{
shouldFocusToggleOnSelect
>
<DropdownList>
- {hasPlaceholders && <DropdownGroup label="Application
Properties">
- {propertyPlaceholders.map((pp, index) =>
- <DropdownItem value={pp}
key={index}>{pp}</DropdownItem>
- )}
- </DropdownGroup>}
+ {parameterPlaceholders &&
+ <DropdownGroup label="Template Parameters"
className='property-placeholder-dropdown'>
+ {parameterPlaceholders.map((pp, index) =>
+ <DropdownItem value={pp[0]} key={index}
description={pp[1]}>{pp[0]}</DropdownItem>
+ )}
+ </DropdownGroup>
+ }
+ {parameterPlaceholders && <Divider component="li"/>}
+ {hasPlaceholders &&
+ <DropdownGroup label="Application Properties"
className='property-placeholder-dropdown'>
+ {propertyPlaceholders.map((pp, index) =>
+ <DropdownItem value={pp}
key={index}>{pp}</DropdownItem>
+ )}
+ </DropdownGroup>
+ }
{hasPlaceholders && <Divider component="li"/>}
- <DropdownGroup label="Syntax examples">
+ <DropdownGroup label="Syntax examples"
className='property-placeholder-dropdown'>
{SYNTAX_EXAMPLES.map(se =>
<DropdownItem value={se.value} key={se.key}
description={se.description}>
{se.value}
diff --git a/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
b/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
index f89c8e85..a12e19d6 100644
--- a/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
+++ b/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
@@ -821,7 +821,7 @@ export class CamelUi {
static getFlowCounts = (i: Integration): Map<string, number> => {
const result = new Map<string, number>();
- result.set('routes', i.spec.flows?.filter((e: any) => e.dslName ===
'RouteDefinition').length || 0);
+ result.set('routes', i.spec.flows?.filter((e: any) =>
['RouteDefinition', 'RouteTemplateDefinition'].includes(e.dslName)).length ||
0);
result.set('rest', i.spec.flows?.filter((e: any) => e.dslName ===
'RestDefinition').length || 0);
result.set('routeConfiguration', i.spec.flows?.filter((e: any) =>
e.dslName === 'RouteConfigurationDefinition').length || 0);
const beans = i.spec.flows?.filter((e: any) => e.dslName === 'Beans');
diff --git a/karavan-core/src/core/api/CamelDefinitionApiExt.ts
b/karavan-core/src/core/api/CamelDefinitionApiExt.ts
index f542253d..36c2032b 100644
--- a/karavan-core/src/core/api/CamelDefinitionApiExt.ts
+++ b/karavan-core/src/core/api/CamelDefinitionApiExt.ts
@@ -174,6 +174,23 @@ export class CamelDefinitionApiExt {
return result;
};
+ static findTopRouteElement = (integration: Integration, uuid: string):
CamelElement | undefined => {
+ const result: string[] = [];
+ let meta =
CamelDefinitionApiExt.findElementMetaInIntegration(integration, uuid);
+ if (meta) {
+ while (meta.parentUuid !== undefined) {
+ if (meta.parentUuid) {
+ result.push(meta.parentUuid);
+ meta =
CamelDefinitionApiExt.findElementMetaInIntegration(integration,
meta.parentUuid);
+ } else {
+ break;
+ }
+ }
+ }
+ const last = result.at(-1);
+ return last ?
CamelDefinitionApiExt.findElementInIntegration(integration, last): undefined
+ };
+
static findElementInElements = (steps: CamelElement[] | undefined, uuid:
string, result: CamelElementMeta = new CamelElementMeta(undefined, undefined,
undefined),
parentUuid?: string,): CamelElementMeta =>
{
if (result?.step !== undefined) {
diff --git a/karavan-core/src/core/api/CamelDefinitionYaml.ts
b/karavan-core/src/core/api/CamelDefinitionYaml.ts
index d82020fb..93ca86f3 100644
--- a/karavan-core/src/core/api/CamelDefinitionYaml.ts
+++ b/karavan-core/src/core/api/CamelDefinitionYaml.ts
@@ -19,7 +19,7 @@ import { Beans, CamelElement, Integration } from
'../model/IntegrationDefinition
import {
BeanFactoryDefinition,
RouteConfigurationDefinition,
- RouteDefinition, RouteTemplateDefinition,
+ RouteDefinition,
} from '../model/CamelDefinition';
import { CamelUtil } from './CamelUtil';
import { CamelDefinitionYamlStep } from './CamelDefinitionYamlStep';
diff --git a/karavan-designer/public/example/demo.camel.yaml
b/karavan-designer/public/example/demo.camel.yaml
index b60f1af7..6c655d36 100644
--- a/karavan-designer/public/example/demo.camel.yaml
+++ b/karavan-designer/public/example/demo.camel.yaml
@@ -1,24 +1,9 @@
-- routeTemplate:
- id: routeFileReaderTemplate
- description: File reader
- route:
- id: routeFileReader
- description: File reader
- from:
- id: from-4101
- uri: sftp
- steps:
- - to:
- id: to-1234
- uri: sql
- parameters:
- - name: folderName
- routeTemplate:
id: routeFileReaderTemplate2
- description: File reader 2
+ description: File reader template
route:
id: routeFileReader 2
- description: File reader 2
+ description: File reader route
from:
id: from-4101
uri: sftp
@@ -26,29 +11,25 @@
- to:
id: to-1234
uri: sql
+ parameters:
+ query: "{{folderName}}"
+ - loadBalance:
+ id: loadBalance-8172
+ - log:
+ id: log-7fa8
+ message: ${body}
+ - loop:
+ id: loop-6068
+ expression:
+ groovy:
+ id: groovy-4e44
+ steps:
+ - marshal:
+ id: marshal-930d
+ json:
+ id: json-135e
parameters:
- - name: folderName
-- route:
- id: route-dummy
- description: Dummy route
- autoStartup: false
- from:
- id: from-b6a5
- uri: kamelet:aws-kinesis-source
- parameters:
- secretKey: asasdasd
- accessKey: asdasd
- steps:
- - log:
- id: log-b47b
- message: DUMMY
-- route:
- id: route-file
- description: File consumer
- from:
- id: from-file
- uri: file
- steps:
- - log:
- id: log-file
- message: DUMMY
+ - description: Folder with files
+ name: folderName
+ - description: Server Hostname
+ name: serverName
diff --git a/karavan-designer/src/designer/DesignerStore.ts
b/karavan-designer/src/designer/DesignerStore.ts
index cd610c0f..7535b93b 100644
--- a/karavan-designer/src/designer/DesignerStore.ts
+++ b/karavan-designer/src/designer/DesignerStore.ts
@@ -213,6 +213,7 @@ type DesignerState = {
left: number,
moveElements: [string | undefined, string | undefined],
propertyPlaceholders: string[],
+ parameterPlaceholders: [string, string][], // route template parameters
beans: BeanFactoryDefinition[]
}
@@ -232,6 +233,7 @@ const designerState: DesignerState = {
left: 0,
moveElements: [undefined, undefined],
propertyPlaceholders: [],
+ parameterPlaceholders: [],
beans: []
};
@@ -249,6 +251,7 @@ type DesignerAction = {
setNotification: (notificationBadge: boolean, notificationMessage:
[string, string]) => void;
setMoveElements: (moveElements: [string | undefined, string | undefined])
=> void;
setPropertyPlaceholders: (propertyPlaceholders: string[]) => void;
+ setParameterPlaceholders: (parameterPlaceholders: [string, string][]) =>
void;
setBeans: (beans: BeanFactoryDefinition[]) => void;
}
@@ -309,6 +312,13 @@ export const useDesignerStore =
createWithEqualityFn<DesignerState & DesignerAct
return state;
})
},
+ setParameterPlaceholders: (parameterPlaceholders: [string, string][]) => {
+ set((state: DesignerState) => {
+ state.parameterPlaceholders.length = 0;
+ state.parameterPlaceholders.push(...parameterPlaceholders);
+ return state;
+ })
+ },
setBeans: (beans: BeanFactoryDefinition[]) => {
set((state: DesignerState) => {
return {beans: [...beans]};
diff --git a/karavan-designer/src/designer/property/DslProperties.tsx
b/karavan-designer/src/designer/property/DslProperties.tsx
index dd2376ee..52b36ef7 100644
--- a/karavan-designer/src/designer/property/DslProperties.tsx
+++ b/karavan-designer/src/designer/property/DslProperties.tsx
@@ -47,6 +47,7 @@ import {PropertiesHeader} from "./PropertiesHeader";
import {PropertyUtil} from "./property/PropertyUtil";
import {usePropertiesStore} from "./PropertyStore";
import TimesIcon from "@patternfly/react-icons/dist/esm/icons/times-icon";
+import {RouteTemplateDefinition} from "karavan-core/lib/model/CamelDefinition";
interface Props {
designerType: 'routes' | 'rest' | 'beans'
@@ -65,8 +66,8 @@ export function DslProperties(props: Props) {
} =
usePropertiesHook(props.designerType);
- const [selectedStep, dark]
- = useDesignerStore((s) => [s.selectedStep, s.dark], shallow)
+ const [selectedStep, dark, setParameterPlaceholders]
+ = useDesignerStore((s) => [s.selectedStep, s.dark,
s.setParameterPlaceholders], shallow)
const [propertyFilter, changedOnly, requiredOnly, setChangedOnly,
sensitiveOnly, setSensitiveOnly, setPropertyFilter, setRequiredOnly]
= usePropertiesStore((s) => [s.propertyFilter, s.changedOnly,
s.requiredOnly, s.setChangedOnly, s.sensitiveOnly, s.setSensitiveOnly,
s.setPropertyFilter, s.setRequiredOnly], shallow)
@@ -78,8 +79,19 @@ export function DslProperties(props: Props) {
setChangedOnly(false);
setSensitiveOnly(false);
setPropertyFilter('');
+ getRouteTemplateParameters()
}, [selectedStep?.uuid])
+ function getRouteTemplateParameters() {
+ if (selectedStep) {
+ const root =
CamelDefinitionApiExt.findTopRouteElement(integration, selectedStep.uuid);
+ if ('RouteTemplateDefinition' === root?.dslName) {
+ const paramPlaceholders: [string, string][] = (root as
RouteTemplateDefinition).parameters?.map(p => [p.name, p.description ||'']) ||
[];
+ setParameterPlaceholders(paramPlaceholders);
+ }
+ }
+ }
+
function getClonableElementHeader(): React.JSX.Element {
const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep);
const description = selectedStep?.dslName ?
CamelMetadataApi.getCamelModelMetadataByClassName(selectedStep?.dslName)?.description
: title;
diff --git
a/karavan-designer/src/designer/property/property/PropertyPlaceholderDropdown.css
b/karavan-designer/src/designer/property/property/PropertyPlaceholderDropdown.css
index 43991634..3984ae02 100644
---
a/karavan-designer/src/designer/property/property/PropertyPlaceholderDropdown.css
+++
b/karavan-designer/src/designer/property/property/PropertyPlaceholderDropdown.css
@@ -28,6 +28,11 @@
display: none;
}
+.karavan .properties .property-placeholder-dropdown .pf-v5-c-menu__group-title
{
+ font-weight: bold;
+ font-size: 13px;
+}
+
.pf-v5-c-popover .property-placeholder-toggle-form {
width: 300px;
}
diff --git
a/karavan-designer/src/designer/property/property/PropertyPlaceholderDropdown.tsx
b/karavan-designer/src/designer/property/property/PropertyPlaceholderDropdown.tsx
index e920ce0a..ec532b55 100644
---
a/karavan-designer/src/designer/property/property/PropertyPlaceholderDropdown.tsx
+++
b/karavan-designer/src/designer/property/property/PropertyPlaceholderDropdown.tsx
@@ -59,8 +59,8 @@ interface Props {
export function PropertyPlaceholderDropdown(props: Props) {
- const [propertyPlaceholders, setPropertyPlaceholders] =
useDesignerStore((s) =>
- [s.propertyPlaceholders, s.setPropertyPlaceholders], shallow)
+ const [propertyPlaceholders, setPropertyPlaceholders,
parameterPlaceholders] = useDesignerStore((s) =>
+ [s.propertyPlaceholders, s.setPropertyPlaceholders,
s.parameterPlaceholders], shallow)
const [isOpenPlaceholdersDropdown, setOpenPlaceholdersDropdown] =
useState<boolean>(false);
const [propValue, setPropValue] = useState<string>('');
const [isVisible, setIsVisible] = React.useState(false);
@@ -72,13 +72,15 @@ export function PropertyPlaceholderDropdown(props: Props) {
const {property, value} = props;
const valueIsPlaceholder: boolean = value &&
value.toString().startsWith('{{') && value.toString().endsWith('}}');
const placeholderValue = valueIsPlaceholder ?
value.toString().replace('{{', '').replace('}}', '') : undefined;
+ const isRouteTemplateParameter = parameterPlaceholders.map(p =>
p[0]).includes(placeholderValue);
const showAddButton = valueIsPlaceholder
+ && !isRouteTemplateParameter
&& !propertyPlaceholders.includes(placeholderValue)
- && !SYNTAX_EXAMPLES.map(se=>
se.value).includes(removeBrackets(placeholderValue))
- && SYNTAX_EXAMPLES.findIndex(se=>
removeBrackets(placeholderValue).startsWith(se.key)) === -1;
+ && !SYNTAX_EXAMPLES.map(se =>
se.value).includes(removeBrackets(placeholderValue))
+ && SYNTAX_EXAMPLES.findIndex(se =>
removeBrackets(placeholderValue).startsWith(se.key)) === -1;
const popoverId = "popover-selector-" + property.hasOwnProperty('name') ?
(property as any).name : (property as any).id;
- const hasPlaceholders = (propertyPlaceholders &&
propertyPlaceholders.length > 0 );
+ const hasPlaceholders = (propertyPlaceholders &&
propertyPlaceholders.length > 0);
function parametersChanged(value: string | number | boolean | any) {
if (property instanceof ComponentProperty) {
@@ -167,13 +169,23 @@ export function PropertyPlaceholderDropdown(props: Props)
{
shouldFocusToggleOnSelect
>
<DropdownList>
- {hasPlaceholders && <DropdownGroup label="Application
Properties">
- {propertyPlaceholders.map((pp, index) =>
- <DropdownItem value={pp}
key={index}>{pp}</DropdownItem>
- )}
- </DropdownGroup>}
+ {parameterPlaceholders &&
+ <DropdownGroup label="Template Parameters"
className='property-placeholder-dropdown'>
+ {parameterPlaceholders.map((pp, index) =>
+ <DropdownItem value={pp[0]} key={index}
description={pp[1]}>{pp[0]}</DropdownItem>
+ )}
+ </DropdownGroup>
+ }
+ {parameterPlaceholders && <Divider component="li"/>}
+ {hasPlaceholders &&
+ <DropdownGroup label="Application Properties"
className='property-placeholder-dropdown'>
+ {propertyPlaceholders.map((pp, index) =>
+ <DropdownItem value={pp}
key={index}>{pp}</DropdownItem>
+ )}
+ </DropdownGroup>
+ }
{hasPlaceholders && <Divider component="li"/>}
- <DropdownGroup label="Syntax examples">
+ <DropdownGroup label="Syntax examples"
className='property-placeholder-dropdown'>
{SYNTAX_EXAMPLES.map(se =>
<DropdownItem value={se.value} key={se.key}
description={se.description}>
{se.value}
diff --git a/karavan-designer/src/designer/utils/CamelUi.tsx
b/karavan-designer/src/designer/utils/CamelUi.tsx
index f89c8e85..a12e19d6 100644
--- a/karavan-designer/src/designer/utils/CamelUi.tsx
+++ b/karavan-designer/src/designer/utils/CamelUi.tsx
@@ -821,7 +821,7 @@ export class CamelUi {
static getFlowCounts = (i: Integration): Map<string, number> => {
const result = new Map<string, number>();
- result.set('routes', i.spec.flows?.filter((e: any) => e.dslName ===
'RouteDefinition').length || 0);
+ result.set('routes', i.spec.flows?.filter((e: any) =>
['RouteDefinition', 'RouteTemplateDefinition'].includes(e.dslName)).length ||
0);
result.set('rest', i.spec.flows?.filter((e: any) => e.dslName ===
'RestDefinition').length || 0);
result.set('routeConfiguration', i.spec.flows?.filter((e: any) =>
e.dslName === 'RouteConfigurationDefinition').length || 0);
const beans = i.spec.flows?.filter((e: any) => e.dslName === 'Beans');
diff --git a/karavan-space/src/designer/DesignerStore.ts
b/karavan-space/src/designer/DesignerStore.ts
index cd610c0f..7535b93b 100644
--- a/karavan-space/src/designer/DesignerStore.ts
+++ b/karavan-space/src/designer/DesignerStore.ts
@@ -213,6 +213,7 @@ type DesignerState = {
left: number,
moveElements: [string | undefined, string | undefined],
propertyPlaceholders: string[],
+ parameterPlaceholders: [string, string][], // route template parameters
beans: BeanFactoryDefinition[]
}
@@ -232,6 +233,7 @@ const designerState: DesignerState = {
left: 0,
moveElements: [undefined, undefined],
propertyPlaceholders: [],
+ parameterPlaceholders: [],
beans: []
};
@@ -249,6 +251,7 @@ type DesignerAction = {
setNotification: (notificationBadge: boolean, notificationMessage:
[string, string]) => void;
setMoveElements: (moveElements: [string | undefined, string | undefined])
=> void;
setPropertyPlaceholders: (propertyPlaceholders: string[]) => void;
+ setParameterPlaceholders: (parameterPlaceholders: [string, string][]) =>
void;
setBeans: (beans: BeanFactoryDefinition[]) => void;
}
@@ -309,6 +312,13 @@ export const useDesignerStore =
createWithEqualityFn<DesignerState & DesignerAct
return state;
})
},
+ setParameterPlaceholders: (parameterPlaceholders: [string, string][]) => {
+ set((state: DesignerState) => {
+ state.parameterPlaceholders.length = 0;
+ state.parameterPlaceholders.push(...parameterPlaceholders);
+ return state;
+ })
+ },
setBeans: (beans: BeanFactoryDefinition[]) => {
set((state: DesignerState) => {
return {beans: [...beans]};
diff --git a/karavan-space/src/designer/property/DslProperties.tsx
b/karavan-space/src/designer/property/DslProperties.tsx
index dd2376ee..52b36ef7 100644
--- a/karavan-space/src/designer/property/DslProperties.tsx
+++ b/karavan-space/src/designer/property/DslProperties.tsx
@@ -47,6 +47,7 @@ import {PropertiesHeader} from "./PropertiesHeader";
import {PropertyUtil} from "./property/PropertyUtil";
import {usePropertiesStore} from "./PropertyStore";
import TimesIcon from "@patternfly/react-icons/dist/esm/icons/times-icon";
+import {RouteTemplateDefinition} from "karavan-core/lib/model/CamelDefinition";
interface Props {
designerType: 'routes' | 'rest' | 'beans'
@@ -65,8 +66,8 @@ export function DslProperties(props: Props) {
} =
usePropertiesHook(props.designerType);
- const [selectedStep, dark]
- = useDesignerStore((s) => [s.selectedStep, s.dark], shallow)
+ const [selectedStep, dark, setParameterPlaceholders]
+ = useDesignerStore((s) => [s.selectedStep, s.dark,
s.setParameterPlaceholders], shallow)
const [propertyFilter, changedOnly, requiredOnly, setChangedOnly,
sensitiveOnly, setSensitiveOnly, setPropertyFilter, setRequiredOnly]
= usePropertiesStore((s) => [s.propertyFilter, s.changedOnly,
s.requiredOnly, s.setChangedOnly, s.sensitiveOnly, s.setSensitiveOnly,
s.setPropertyFilter, s.setRequiredOnly], shallow)
@@ -78,8 +79,19 @@ export function DslProperties(props: Props) {
setChangedOnly(false);
setSensitiveOnly(false);
setPropertyFilter('');
+ getRouteTemplateParameters()
}, [selectedStep?.uuid])
+ function getRouteTemplateParameters() {
+ if (selectedStep) {
+ const root =
CamelDefinitionApiExt.findTopRouteElement(integration, selectedStep.uuid);
+ if ('RouteTemplateDefinition' === root?.dslName) {
+ const paramPlaceholders: [string, string][] = (root as
RouteTemplateDefinition).parameters?.map(p => [p.name, p.description ||'']) ||
[];
+ setParameterPlaceholders(paramPlaceholders);
+ }
+ }
+ }
+
function getClonableElementHeader(): React.JSX.Element {
const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep);
const description = selectedStep?.dslName ?
CamelMetadataApi.getCamelModelMetadataByClassName(selectedStep?.dslName)?.description
: title;
diff --git
a/karavan-space/src/designer/property/property/PropertyPlaceholderDropdown.css
b/karavan-space/src/designer/property/property/PropertyPlaceholderDropdown.css
index 43991634..3984ae02 100644
---
a/karavan-space/src/designer/property/property/PropertyPlaceholderDropdown.css
+++
b/karavan-space/src/designer/property/property/PropertyPlaceholderDropdown.css
@@ -28,6 +28,11 @@
display: none;
}
+.karavan .properties .property-placeholder-dropdown .pf-v5-c-menu__group-title
{
+ font-weight: bold;
+ font-size: 13px;
+}
+
.pf-v5-c-popover .property-placeholder-toggle-form {
width: 300px;
}
diff --git
a/karavan-space/src/designer/property/property/PropertyPlaceholderDropdown.tsx
b/karavan-space/src/designer/property/property/PropertyPlaceholderDropdown.tsx
index e920ce0a..ec532b55 100644
---
a/karavan-space/src/designer/property/property/PropertyPlaceholderDropdown.tsx
+++
b/karavan-space/src/designer/property/property/PropertyPlaceholderDropdown.tsx
@@ -59,8 +59,8 @@ interface Props {
export function PropertyPlaceholderDropdown(props: Props) {
- const [propertyPlaceholders, setPropertyPlaceholders] =
useDesignerStore((s) =>
- [s.propertyPlaceholders, s.setPropertyPlaceholders], shallow)
+ const [propertyPlaceholders, setPropertyPlaceholders,
parameterPlaceholders] = useDesignerStore((s) =>
+ [s.propertyPlaceholders, s.setPropertyPlaceholders,
s.parameterPlaceholders], shallow)
const [isOpenPlaceholdersDropdown, setOpenPlaceholdersDropdown] =
useState<boolean>(false);
const [propValue, setPropValue] = useState<string>('');
const [isVisible, setIsVisible] = React.useState(false);
@@ -72,13 +72,15 @@ export function PropertyPlaceholderDropdown(props: Props) {
const {property, value} = props;
const valueIsPlaceholder: boolean = value &&
value.toString().startsWith('{{') && value.toString().endsWith('}}');
const placeholderValue = valueIsPlaceholder ?
value.toString().replace('{{', '').replace('}}', '') : undefined;
+ const isRouteTemplateParameter = parameterPlaceholders.map(p =>
p[0]).includes(placeholderValue);
const showAddButton = valueIsPlaceholder
+ && !isRouteTemplateParameter
&& !propertyPlaceholders.includes(placeholderValue)
- && !SYNTAX_EXAMPLES.map(se=>
se.value).includes(removeBrackets(placeholderValue))
- && SYNTAX_EXAMPLES.findIndex(se=>
removeBrackets(placeholderValue).startsWith(se.key)) === -1;
+ && !SYNTAX_EXAMPLES.map(se =>
se.value).includes(removeBrackets(placeholderValue))
+ && SYNTAX_EXAMPLES.findIndex(se =>
removeBrackets(placeholderValue).startsWith(se.key)) === -1;
const popoverId = "popover-selector-" + property.hasOwnProperty('name') ?
(property as any).name : (property as any).id;
- const hasPlaceholders = (propertyPlaceholders &&
propertyPlaceholders.length > 0 );
+ const hasPlaceholders = (propertyPlaceholders &&
propertyPlaceholders.length > 0);
function parametersChanged(value: string | number | boolean | any) {
if (property instanceof ComponentProperty) {
@@ -167,13 +169,23 @@ export function PropertyPlaceholderDropdown(props: Props)
{
shouldFocusToggleOnSelect
>
<DropdownList>
- {hasPlaceholders && <DropdownGroup label="Application
Properties">
- {propertyPlaceholders.map((pp, index) =>
- <DropdownItem value={pp}
key={index}>{pp}</DropdownItem>
- )}
- </DropdownGroup>}
+ {parameterPlaceholders &&
+ <DropdownGroup label="Template Parameters"
className='property-placeholder-dropdown'>
+ {parameterPlaceholders.map((pp, index) =>
+ <DropdownItem value={pp[0]} key={index}
description={pp[1]}>{pp[0]}</DropdownItem>
+ )}
+ </DropdownGroup>
+ }
+ {parameterPlaceholders && <Divider component="li"/>}
+ {hasPlaceholders &&
+ <DropdownGroup label="Application Properties"
className='property-placeholder-dropdown'>
+ {propertyPlaceholders.map((pp, index) =>
+ <DropdownItem value={pp}
key={index}>{pp}</DropdownItem>
+ )}
+ </DropdownGroup>
+ }
{hasPlaceholders && <Divider component="li"/>}
- <DropdownGroup label="Syntax examples">
+ <DropdownGroup label="Syntax examples"
className='property-placeholder-dropdown'>
{SYNTAX_EXAMPLES.map(se =>
<DropdownItem value={se.value} key={se.key}
description={se.description}>
{se.value}
diff --git a/karavan-space/src/designer/utils/CamelUi.tsx
b/karavan-space/src/designer/utils/CamelUi.tsx
index f89c8e85..a12e19d6 100644
--- a/karavan-space/src/designer/utils/CamelUi.tsx
+++ b/karavan-space/src/designer/utils/CamelUi.tsx
@@ -821,7 +821,7 @@ export class CamelUi {
static getFlowCounts = (i: Integration): Map<string, number> => {
const result = new Map<string, number>();
- result.set('routes', i.spec.flows?.filter((e: any) => e.dslName ===
'RouteDefinition').length || 0);
+ result.set('routes', i.spec.flows?.filter((e: any) =>
['RouteDefinition', 'RouteTemplateDefinition'].includes(e.dslName)).length ||
0);
result.set('rest', i.spec.flows?.filter((e: any) => e.dslName ===
'RestDefinition').length || 0);
result.set('routeConfiguration', i.spec.flows?.filter((e: any) =>
e.dslName === 'RouteConfigurationDefinition').length || 0);
const beans = i.spec.flows?.filter((e: any) => e.dslName === 'Beans');