Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions karavan-designer/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,19 @@ class App extends React.Component<Props, State> {
' - from:\n' +
' uri: \'kamelet:http-secured-source\'\n' +
' steps:\n' +
// ' - set-body:\n' +
// ' expression: \n' +
// ' constant: "Hello Yaml !!!"\n' +
// ' - set-body:\n' +
// ' constant: "Hello Yaml !!!"\n' +
// ' - pollEnrich:\n' +
// ' expression: {}\n' +
// ' - to: \n' +
// ' uri: "log:info"\n' +
' - to: "log:info"\n'
' - set-body:\n' +
' expression: \n' +
' constant: "Hello Yaml !!!"\n' +
' - pollEnrich:\n' +
' expression: {}\n' +
' - to: \n' +
' uri: "log:info"\n' +
' - choice:\n' +
' otherwise: {}\n' +
' when:\n' +
' - expression: {}\n' +
' steps:\n' +
' - to-d: {}\n'
,
key: ''
};
Expand Down
213 changes: 157 additions & 56 deletions karavan-designer/src/designer/api/CamelApi.tsx

Large diffs are not rendered by default.

32 changes: 27 additions & 5 deletions karavan-designer/src/designer/api/CamelApiExt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,38 @@ import {ComponentApi} from "./ComponentApi";

export class CamelApiExt {

static addStepToIntegration = (integration: Integration, step: CamelElement, parentId: string): Integration => {
static addStepToIntegration = (integration: Integration, step: CamelElement, parentId: string, position?: number): Integration => {
if (step.dslName === 'fromStep') {
integration.spec.flows.push(step as FromStep);
} else {
const flows = CamelApi.addStep(integration.spec.flows, step, parentId);
const flows = CamelApi.addStep(integration.spec.flows, step, parentId, position);
integration.spec.flows = flows as FromStep[];
}
return integration;
}

static moveElement = (integration: Integration, source: string, target: string) => {
const sourceFindStep = CamelApi.findStep(integration.spec.flows, source, undefined);
const sourceStep = sourceFindStep.step;
const sourceUuid = sourceStep?.uuid;
const targetFindStep = CamelApi.findStep(integration.spec.flows, target, undefined);
const parentUuid = targetFindStep.parentUuid;
if (sourceUuid && parentUuid) {
CamelApiExt.deleteStepFromIntegration(integration, sourceUuid);
switch (targetFindStep.step?.dslName) {
case 'when':
CamelApiExt.addStepToIntegration(integration, sourceStep, targetFindStep.step?.uuid, undefined);
break;
case 'otherwise':
CamelApiExt.addStepToIntegration(integration, sourceStep, targetFindStep.step?.uuid, undefined);
break;
default:
CamelApiExt.addStepToIntegration(integration, sourceStep, parentUuid, targetFindStep.position);
break;
}
}
}

static deleteStepFromIntegration = (integration: Integration, uuidToDelete: string): Integration => {
const flows = CamelApi.deleteStep(integration.spec.flows, uuidToDelete);
integration.spec.flows = flows as FromStep[];
Expand Down Expand Up @@ -96,7 +118,7 @@ export class CamelApiExt {
if (name) {
CamelMetadataApi.getElementMeta(name)?.properties
.filter(p => p.name !== 'steps' && p.name !== 'inheritErrorHandler')
.filter(p => (name == 'to' && p.name !== 'pattern') || name !='to')
.filter(p => (name == 'to' && p.name !== 'pattern') || name != 'to')
.filter(p => !p.isObject || (p.isObject && p.name === 'expression'))
.forEach(p => {
switch (p.name) {
Expand All @@ -121,7 +143,7 @@ export class CamelApiExt {
}

static getParametersValue = (element: CamelElement | undefined, propertyName: string, pathParameter?: boolean): any => {
if (pathParameter){
if (pathParameter) {
const uri = (element as any).uri;
return ComponentApi.getPathParameterValue(uri, propertyName);
} else {
Expand Down Expand Up @@ -160,7 +182,7 @@ export class CamelApiExt {

static getStepsFromSteps = (steps: CamelElement[], level: number, parallel: boolean): [CamelElement, number][] => {
const result: [CamelElement, number][] = [];
steps.forEach((step,index) => {
steps.forEach((step, index) => {
const steps = CamelApiExt.getOutgoingStepsFromStep(step, level + (parallel ? 1 : index));
result.push(...steps);
})
Expand Down
14 changes: 14 additions & 0 deletions karavan-designer/src/designer/model/CamelModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ export class CamelElement {

export class ProcessorStep extends CamelElement {
}

export class ProcessorStepMeta {
step?: ProcessorStep
parentUuid?: string
position: number = 0;


constructor(step?: ProcessorStep, parentUuid?: string, position?: number) {
this.step = step;
this.parentUuid = parentUuid;
this.position = position || 0;
}
}

export class Policy extends CamelElement {
inheritErrorHandler?: boolean
ref?: string
Expand Down
70 changes: 64 additions & 6 deletions karavan-designer/src/designer/ui/DslElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface Props {
deleteElement: any
selectElement: any
openSelector: any
moveElement: (source: string, target: string) => void
selectedUuid: string
borderColor: string
borderColorSelected: string
Expand All @@ -42,6 +43,8 @@ interface State {
showSelector: boolean
tabIndex: string | number
selectedUuid: string
isDragging: boolean
isDraggedOver: boolean
}

export class DslElement extends React.Component<Props, State> {
Expand All @@ -51,7 +54,9 @@ export class DslElement extends React.Component<Props, State> {
element: this.props.step.dslName === 'otherwise' ? this.props.step : CamelApi.elementFromStep(this.props.step),
showSelector: false,
tabIndex: 0,
selectedUuid: this.props.selectedUuid
selectedUuid: this.props.selectedUuid,
isDragging: false,
isDraggedOver: false
};

componentDidUpdate = (prevProps: Readonly<Props>, prevState: Readonly<State>, snapshot?: any) => {
Expand All @@ -62,7 +67,7 @@ export class DslElement extends React.Component<Props, State> {

openSelector = (evt: React.MouseEvent) => {
evt.stopPropagation();
this.props.openSelector.call(this, this.state.step.uuid, this.state.element.dslName)
this.props.openSelector.call(this, this.state.step.uuid, this.state.element.dslName);
}

closeDslSelector = () => {
Expand All @@ -87,6 +92,11 @@ export class DslElement extends React.Component<Props, State> {
return (this.state.element as any).steps
}

hasSteps = (): boolean => {
const steps = this.getSteps();
return steps !== undefined && steps.length > 0;
}

getWhens = (): When[] => {
return (this.state.element as any).when
}
Expand Down Expand Up @@ -154,7 +164,10 @@ export class DslElement extends React.Component<Props, State> {

getElementHeader = () => {
const tooltip = this.getHeaderTooltip();
return tooltip === undefined ? this.getHeader() : this.getHeaderWithTooltip(tooltip);
if (tooltip !== undefined && !this.state.isDragging) {
return this.getHeaderWithTooltip(tooltip);
}
return this.getHeader();
}

render() {
Expand All @@ -164,13 +177,54 @@ export class DslElement extends React.Component<Props, State> {
? "step-element step-element-with-steps"
: "step-element step-element-without-steps"}
style={{
borderStyle: this.isSelected() ? "dashed" : "dotted",
borderStyle: this.isSelected() ? "dashed" : (this.hasSteps() ? "dotted" : "none"),
borderColor: this.isSelected() ? this.props.borderColorSelected : this.props.borderColor,
marginTop: this.isRoot() ? "16px" : "",
zIndex: this.state.step.dslName === 'toStep' ? 20 : 10
zIndex: this.state.step.dslName === 'toStep' ? 20 : 10,
boxShadow: this.state.isDraggedOver ? "0px 0px 1px 2px " + this.props.borderColor : "none",
}}
onClick={event => this.selectElement(event)}
onDragStart={event => {
event.stopPropagation();
event.dataTransfer.setData("text/plain", this.state.step.uuid);
(event.target as any).style.opacity = .5;
this.setState({isDragging: true});
}}
onDragEnd={event => {
(event.target as any).style.opacity = '';
this.setState({isDragging: false});
}}
onDragOver={event => {
event.preventDefault();
event.stopPropagation();
if (this.state.element.dslName !== 'from' && !this.state.isDragging) {
this.setState({isDraggedOver: true});
}
}}
onDragEnter={event => {
event.preventDefault();
event.stopPropagation();
if (this.state.element.dslName !== 'from') {
this.setState({isDraggedOver: true});
}
}}
onDragLeave={event => {
event.preventDefault();
event.stopPropagation();
this.setState({isDraggedOver: false});

}}
onDrop={event => {
event.preventDefault();
event.stopPropagation();
this.setState({isDraggedOver: false});
const sourceUuid = event.dataTransfer.getData("text/plain");
const targetUuid = this.state.step.uuid;
if (sourceUuid !== targetUuid) {
this.props.moveElement?.call(this, sourceUuid, targetUuid);
}
}}
draggable={!['from', 'when', 'otherwise'].includes(this.state.element.dslName)}
>
{this.getElementHeader()}
{this.state.element.hasSteps() && !this.horizontal() && this.getArrow()}
Expand All @@ -185,6 +239,7 @@ export class DslElement extends React.Component<Props, State> {
openSelector={this.props.openSelector}
deleteElement={this.props.deleteElement}
selectElement={this.props.selectElement}
moveElement={this.props.moveElement}
selectedUuid={this.state.selectedUuid}
borderColor={this.props.borderColor}
borderColorSelected={this.props.borderColorSelected}
Expand Down Expand Up @@ -212,14 +267,16 @@ export class DslElement extends React.Component<Props, State> {
</Tooltip>
}
{this.state.element.dslName === 'choice' &&
<div className={this.getWhens().length > 0 ? "whens" : ""} style={this.horizontal() ? {display: "flex", flexDirection: "row"} : {}}>
<div className={this.getWhens().length > 0 ? "whens" : ""}
style={this.horizontal() ? {display: "flex", flexDirection: "row"} : {}}>
{this.getWhens().map((when, index) => (
<div key={when.uuid} style={{marginLeft: (index !== 0) ? "6px" : "0"}}>
{this.getArrow()}
<DslElement
openSelector={this.props.openSelector}
deleteElement={this.props.deleteElement}
selectElement={this.props.selectElement}
moveElement={this.props.moveElement}
selectedUuid={this.state.selectedUuid}
borderColor={this.props.borderColor}
borderColorSelected={this.props.borderColorSelected}
Expand All @@ -234,6 +291,7 @@ export class DslElement extends React.Component<Props, State> {
openSelector={this.props.openSelector}
deleteElement={this.props.deleteElement}
selectElement={this.props.selectElement}
moveElement={this.props.moveElement}
selectedUuid={this.state.selectedUuid}
borderColor={this.props.borderColor}
borderColorSelected={this.props.borderColorSelected}
Expand Down
8 changes: 6 additions & 2 deletions karavan-designer/src/designer/ui/KaravanDesigner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ export class KaravanDesigner extends React.Component<Props, State> {
}

onDslSelect = (dsl: DslMetaModel, parentId: string) => {
console.log(dsl)
switch (dsl.dsl) {
case 'from' :
const from = CamelApi.createStep(dsl.dsl, {from: {uri: dsl.uri}});
Expand Down Expand Up @@ -164,7 +163,11 @@ export class KaravanDesigner extends React.Component<Props, State> {

onIntegrationUpdate = (i: Integration) => {
this.setState({integration: i, showSelector: false, key: Math.random().toString()});
};
}

moveElement = (source: string, target: string) => {
CamelApiExt.moveElement(this.state.integration, source, target);
}

render() {
return (
Expand All @@ -184,6 +187,7 @@ export class KaravanDesigner extends React.Component<Props, State> {
openSelector={this.openSelector}
deleteElement={this.deleteElement}
selectElement={this.selectElement}
moveElement={this.moveElement}
selectedUuid={this.state.selectedUuid}
borderColor={this.props.borderColor}
borderColorSelected={this.props.borderColorSelected}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ private void createModels(String source, String template, String metadataTemplat
"/**\n" +
" * Generated by karavan build tools - do NOT edit this file!\n" +
" */\n");
camelApi.append("import {");
camelApi.append("import {\n");
camelApi.append(" CamelElement, \n");
camelApi.append(" ProcessorStep, \n");
camelApi.append(" ProcessorStepMeta, \n");
camelApi.append(" FromStep, \n");
camelApi.append(" Expression, \n");
processors.values().forEach(s -> {
Expand Down Expand Up @@ -183,11 +184,11 @@ private void createModels(String source, String template, String metadataTemplat
camelApi.append(
" default : return new CamelElement('')\n" +
" }\n" +
" }\n");
" }\n\n");

// addStep functions
camelApi.append(
" static addStep = (steps: ProcessorStep[], step: ProcessorStep, parentId: string): ProcessorStep[] => {\n" +
" static addStep = (steps: ProcessorStep[], step: ProcessorStep, parentId: string, position?: number): ProcessorStep[] => {\n" +
" const result: ProcessorStep[] = [];\n" +
" steps.forEach(el => {\n" +
" switch (el.dslName) {\n" );
Expand All @@ -206,8 +207,8 @@ private void createModels(String source, String template, String metadataTemplat
camelApi.append(String.format(
" case '%1$s':\n" +
" const %3$sChildren = (el as %2$s).%3$s?.steps || [];\n" +
" if (el.uuid === parentId) %3$sChildren.push(step)\n" +
" else (el as %2$s).%3$s.steps = CamelApi.addStep(%3$sChildren, step, parentId);\n" +
" if (el.uuid === parentId) position !== undefined ? %3$sChildren.splice(position, 0, step) : %3$sChildren.push(step);\n" +
" else (el as %2$s).%3$s.steps = CamelApi.addStep(%3$sChildren, step, parentId, position);\n" +
" break;\n",
stepField, stepClass, name));
}
Expand Down Expand Up @@ -262,6 +263,30 @@ private void createModels(String source, String template, String metadataTemplat
" }\n\n");
camelApi.append(getTemplateFile("CamelApi.deleteWhen.tx").concat("\n\n"));


// findStep functions
camelApi.append(getTemplateFile("CamelApi.findStep.header.tx").concat("\n"));
models.entrySet().forEach(s -> {
String name = deCapitalize(s.getKey());
String stepClass = capitalize(s.getKey()).concat("Step");
String stepField = deCapitalize(s.getKey()).concat("Step");

if (name.equals("choice")){
camelApi.append(getTemplateFile("CamelApi.findStep.choiceStep.tx").concat("\n"));
} else if (name.equals("otherwise")){
camelApi.append(getTemplateFile("CamelApi.findStep.otherwise.tx").concat("\n"));
} else if (name.equals("when")){
camelApi.append(getTemplateFile("CamelApi.findStep.when.tx").concat("\n"));
} else if (s.getValue().stream().filter(e -> e.name.equals("steps")).count() > 0) {
camelApi.append(String.format(
" case '%1$s':\n" +
" result = CamelApi.findStep((step as %2$s).%3$s.steps, uuid, step.uuid, result);\n" +
" break;\n",
stepField, stepClass, name));
}
});
camelApi.append(getTemplateFile("CamelApi.findStep.footer.tx").concat("\n\n"));

// Expression language finder
camelApi.append(" static getExpressionLanguage = (init?: Partial<Expression>): string | undefined => {\n");
models.get("expression").forEach(el -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
} else if (el.uuid === parentId && step.dslName === 'otherwise' && !(el as ChoiceStep).choice.otherwise) {
(el as ChoiceStep).choice.otherwise = step;
} else {
(el as ChoiceStep).choice.when = CamelApi.addStep(choiceChildren, step, parentId) as When[];
(el as ChoiceStep).choice.when = CamelApi.addStep(choiceChildren, step, parentId, position) as When[];
const otherwise = (el as ChoiceStep).choice.otherwise;
if (otherwise?.uuid === parentId){
otherwise.steps = otherwise.steps ? [...otherwise.steps] : [];
otherwise.steps.push(step);
(el as ChoiceStep).choice.otherwise = otherwise
} else if (otherwise && otherwise.steps && otherwise.steps.length > 0){
otherwise.steps = CamelApi.addStep(otherwise.steps, step, parentId);
otherwise.steps = CamelApi.addStep(otherwise.steps, step, parentId, position);
(el as ChoiceStep).choice.otherwise = otherwise;
}
}
Expand Down
Loading