Skip to content

Commit

Permalink
Route Template Parameters Placeholder
Browse files Browse the repository at this point in the history
  • Loading branch information
mgubaidullin committed Nov 27, 2024
1 parent 19e6624 commit a9d79f1
Show file tree
Hide file tree
Showing 18 changed files with 200 additions and 85 deletions.
10 changes: 10 additions & 0 deletions karavan-app/src/main/webui/src/designer/DesignerStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ type DesignerState = {
left: number,
moveElements: [string | undefined, string | undefined],
propertyPlaceholders: string[],
parameterPlaceholders: [string, string][], // route template parameters
beans: BeanFactoryDefinition[]
}

Expand All @@ -232,6 +233,7 @@ const designerState: DesignerState = {
left: 0,
moveElements: [undefined, undefined],
propertyPlaceholders: [],
parameterPlaceholders: [],
beans: []
};

Expand All @@ -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;
}

Expand Down Expand Up @@ -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]};
Expand Down
16 changes: 14 additions & 2 deletions karavan-app/src/main/webui/src/designer/property/DslProperties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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)
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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}
Expand Down
2 changes: 1 addition & 1 deletion karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
17 changes: 17 additions & 0 deletions karavan-core/src/core/api/CamelDefinitionApiExt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion karavan-core/src/core/api/CamelDefinitionYaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
65 changes: 23 additions & 42 deletions karavan-designer/public/example/demo.camel.yaml
Original file line number Diff line number Diff line change
@@ -1,54 +1,35 @@
- 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
steps:
- 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
10 changes: 10 additions & 0 deletions karavan-designer/src/designer/DesignerStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ type DesignerState = {
left: number,
moveElements: [string | undefined, string | undefined],
propertyPlaceholders: string[],
parameterPlaceholders: [string, string][], // route template parameters
beans: BeanFactoryDefinition[]
}

Expand All @@ -232,6 +233,7 @@ const designerState: DesignerState = {
left: 0,
moveElements: [undefined, undefined],
propertyPlaceholders: [],
parameterPlaceholders: [],
beans: []
};

Expand All @@ -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;
}

Expand Down Expand Up @@ -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]};
Expand Down
16 changes: 14 additions & 2 deletions karavan-designer/src/designer/property/DslProperties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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)
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Loading

0 comments on commit a9d79f1

Please sign in to comment.