Skip to content

Commit

Permalink
fix(Entities): Connect from with route object
Browse files Browse the repository at this point in the history
Currently, the `from` object is disconnected from the `route` object,
and in order to make the `VisualizationNodes` IDs static, we need to
connect the entire tree.
  • Loading branch information
lordrip committed Oct 17, 2024
1 parent a8a532d commit 2e6d8e6
Show file tree
Hide file tree
Showing 23 changed files with 401 additions and 340 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ describe('CanvasForm', () => {
fireEvent.click(closeSideBarButton);
});

expect(camelRouteVisualEntity.route.description).toBeUndefined();
expect(camelRouteVisualEntity.entityDef.route.description).toBeUndefined();
});

it("should serialize empty strings(with space characters) `' '` as `undefined`", async () => {
Expand Down Expand Up @@ -209,7 +209,7 @@ describe('CanvasForm', () => {
fireEvent.click(closeSideBarButton);
});

expect(camelRouteVisualEntity.route.description).toBeUndefined();
expect(camelRouteVisualEntity.entityDef.route.description).toBeUndefined();
});

it('should allow consumers to update the Camel Route ID', async () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/hooks/entities.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CamelResource, SourceSchemaType } from '../models/camel';
import { CamelRouteVisualEntity } from '../models/visualization/flows';
import { camelRouteJson, camelRouteYaml } from '../stubs/camel-route';
import { camelRouteYaml_1_1_original, camelRouteYaml_1_1_updated } from '../stubs/camel-route-yaml-1.1';
import { EventNotifier, setValue } from '../utils';
import { EventNotifier } from '../utils';
import { useEntities } from './entities';

describe('useEntities', () => {
Expand Down Expand Up @@ -52,7 +52,7 @@ describe('useEntities', () => {
});

act(() => {
setValue(result.current.visualEntities[0], 'route.from.parameters.bindingMode', 'off');
result.current.visualEntities[0].updateModel('route.from.parameters.bindingMode', 'off');
result.current.updateSourceCodeFromEntities();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,26 @@
exports[`createCamelResource should create an empty KameletResource if no args is specified 1`] = `
[
{
"route": {
"from": {
"id": "from-1234",
"parameters": {
"period": "{{period}}",
"timerName": "user",
},
"steps": [
{
"to": {
"parameters": {
"httpUri": "random-data-api.com/api/v2/users",
},
"uri": "https",
"from": {
"id": "from-1234",
"parameters": {
"period": "{{period}}",
"timerName": "user",
},
"steps": [
{
"to": {
"parameters": {
"httpUri": "random-data-api.com/api/v2/users",
},
"uri": "https",
},
{
"to": "kamelet:sink",
},
],
"uri": "timer",
},
"id": "kamelet-1234",
},
{
"to": "kamelet:sink",
},
],
"uri": "timer",
},
},
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,29 +176,26 @@ exports[`KameletResource should create a new KameletResource with a kamelet 1`]
exports[`KameletResource should get the visual entities (Camel Route Visual Entity) 1`] = `
[
{
"route": {
"from": {
"id": "from-1234",
"parameters": {
"period": "{{period}}",
"timerName": "user",
},
"steps": [
{
"to": {
"parameters": {
"httpUri": "random-data-api.com/api/v2/users",
},
"uri": "https",
"from": {
"id": "from-1234",
"parameters": {
"period": "{{period}}",
"timerName": "user",
},
"steps": [
{
"to": {
"parameters": {
"httpUri": "random-data-api.com/api/v2/users",
},
"uri": "https",
},
{
"to": "kamelet:sink",
},
],
"uri": "timer",
},
"id": "kamelet-1234",
},
{
"to": "kamelet:sink",
},
],
"uri": "timer",
},
},
]
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/models/camel/camel-resource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('createCamelResource', () => {
expect(resource.getType()).toEqual(SourceSchemaType.Route);
expect(resource.getVisualEntities().length).toEqual(1);
const vis = resource.getVisualEntities()[0] as CamelRouteVisualEntity;
expect(vis.route.from?.uri).toBeDefined();
expect(vis.entityDef.route.from?.uri).toBeDefined();
});

// TODO
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/models/camel/kamelet-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class KameletResource extends CamelKResource implements RouteTemplateBean
* the CamelRouteVisualEntity.
*/
set(this.resource, 'metadata.name', this.flow.getId());
set(this.resource, 'spec.template.from', this.flow.route.from);
set(this.resource, 'spec.template.from', this.flow.entityDef.template.from);
set(this.resource, 'spec.template.beans', this.beans?.parent.beans);
return this.resource as IKameletDefinition;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/ui/src/models/visualization/base-visual-entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export interface BaseVisualCamelEntity extends BaseCamelEntity {
id: string;
type: EntityType;

/** Return the root path of the entity */
getRootPath: () => string;

getId: () => string;

setId: (id: string) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ describe('AbstractCamelVisualEntity', () => {
describe('updateModel', () => {
it('should update the model with the new value', () => {
const newUri = 'timer';
abstractVisualEntity.updateModel('from', { uri: newUri });
abstractVisualEntity.updateModel('route.from', { uri: newUri });

expect(abstractVisualEntity.route.from.uri).toEqual(newUri);
expect(abstractVisualEntity.entityDef.route.from.uri).toEqual(newUri);
});

it('should delegate the serialization to the `CamelComponentSchemaService`', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ProcessorDefinition } from '@kaoto/camel-catalog/types';
import { SchemaService } from '../../../components/Form/schema.service';
import { ROOT_PATH, getArrayProperty, getValue, setValue } from '../../../utils';
import { getArrayProperty, getValue, setValue } from '../../../utils';
import { NodeIconResolver, NodeIconType } from '../../../utils/node-icon-resolver';
import { DefinedComponent } from '../../camel-catalog-index';
import { EntityType } from '../../camel/entities';
Expand All @@ -21,10 +21,11 @@ import { CamelProcessorStepsProperties, CamelRouteVisualEntityData } from './sup
import { ModelValidationService } from './support/validators/model-validation.service';

export abstract class AbstractCamelVisualEntity<T extends object> implements BaseVisualCamelEntity {
constructor(public route: T) {}
constructor(public entityDef: T) {}

abstract id: string;
abstract type: EntityType;
abstract getRootPath(): string;
abstract setId(id: string): void;
abstract toJSON(): unknown;
protected abstract getRootUri(): string | undefined;
Expand All @@ -35,8 +36,8 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas

getNodeLabel(path?: string, labelType?: NodeLabelType): string {
if (!path) return '';
const componentModel = getValue(this.entityDef, path);

const componentModel = getValue(this.route, path);
const label = CamelComponentSchemaService.getNodeLabel(
CamelComponentSchemaService.getCamelComponentLookup(path, componentModel),
componentModel,
Expand All @@ -48,7 +49,7 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas

getTooltipContent(path?: string): string {
if (!path) return '';
const componentModel = getValue(this.route, path);
const componentModel = getValue(this.entityDef, path);

const content = CamelComponentSchemaService.getTooltipContent(
CamelComponentSchemaService.getCamelComponentLookup(path, componentModel),
Expand All @@ -60,7 +61,7 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
getComponentSchema(path?: string): VisualComponentSchema | undefined {
if (!path) return undefined;

const componentModel = getValue(this.route, path);
const componentModel = getValue(this.entityDef, path);
const visualComponentSchema = CamelComponentSchemaService.getVisualComponentSchema(path, componentModel);

/** Overriding parameters with an empty object When the parameters property is mistakenly set to null */
Expand All @@ -79,21 +80,21 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
if (!path) return;
const updatedValue = CamelComponentSchemaService.getMultiValueSerializedDefinition(path, value);

setValue(this.route, path, updatedValue);
setValue(this.entityDef, path, updatedValue);
}

/**
* Add a step to the route
*
* path examples:
* from
* from.steps.0.setHeader
* from.steps.1.choice.when.0
* from.steps.1.choice.when.0.steps.0.setHeader
* from.steps.1.choice.otherwise
* from.steps.1.choice.otherwise.steps.0.setHeader
* from.steps.2.doTry.doCatch.0
* from.steps.2.doTry.doCatch.0.steps.0.setHeader
* route.from
* route.from.steps.0.setHeader
* route.from.steps.1.choice.when.0
* route.from.steps.1.choice.when.0.steps.0.setHeader
* route.from.steps.1.choice.otherwise
* route.from.steps.1.choice.otherwise.steps.0.setHeader
* route.from.steps.2.doTry.doCatch.0
* route.from.steps.2.doTry.doCatch.0.steps.0.setHeader
*/
addStep(options: {
definedComponent: DefinedComponent;
Expand All @@ -120,7 +121,7 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
* If the last segment is a string and the penultimate is a number, it means the target is member of an array
* therefore we need to look for the array and insert the element at the given index + 1
*
* f.i. from.steps.0.setHeader
* f.i. route.from.steps.0.setHeader
* penultimate: 0
* last: setHeader
*/
Expand All @@ -131,7 +132,7 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
/** If we're in Replace mode, we need to delete the existing step */
const deleteCount = options.mode === AddStepMode.ReplaceStep ? 1 : 0;

const stepsArray: ProcessorDefinition[] = getValue(this.route, pathArray.slice(0, -2), []);
const stepsArray: ProcessorDefinition[] = getValue(this.entityDef, pathArray.slice(0, -2), []);
stepsArray.splice(desiredStartIndex, deleteCount, defaultValue);

return;
Expand All @@ -148,10 +149,10 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
* If the last segment is a number, it means the target object is a member of an array
* therefore we need to look for the array and remove the element at the given index
*
* f.i. from.steps.1.choice.when.0
* f.i. route.from.steps.1.choice.when.0
* last: 0
*/
let array = getValue(this.route, pathArray.slice(0, -1), []);
let array = getValue(this.entityDef, pathArray.slice(0, -1), []);
if (Number.isInteger(Number(last)) && Array.isArray(array)) {
array.splice(Number(last), 1);

Expand All @@ -162,11 +163,11 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
* If the last segment is a word and the penultimate is a number, it means the target is an object
* potentially a Processor, that belongs to an array, therefore we remove it entirely
*
* f.i. from.steps.1.choice
* f.i. route.from.steps.1.choice
* last: choice
* penultimate: 1
* penultimate: 1`
*/
array = getValue(this.route, pathArray.slice(0, -2), []);
array = getValue(this.entityDef, pathArray.slice(0, -2), []);
if (!Number.isInteger(Number(last)) && Number.isInteger(Number(penultimate)) && Array.isArray(array)) {
array.splice(Number(penultimate), 1);

Expand All @@ -177,11 +178,11 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
* If both the last and penultimate segment are words, it means the target is a property of an object
* therefore we delete it
*
* f.i. from.steps.1.choice.otherwise
* f.i. route.from.steps.1.choice.otherwise
* last: otherwise
* penultimate: choice
*/
const object = getValue(this.route, pathArray.slice(0, -1), {});
const object = getValue(this.entityDef, pathArray.slice(0, -1), {});
if (!Number.isInteger(Number(last)) && !Number.isInteger(Number(penultimate)) && typeof object === 'object') {
delete object[last];
}
Expand All @@ -195,7 +196,7 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
const canHaveSpecialChildren = Object.keys(stepsProperties).length > 1;
const canReplaceStep = CamelComponentSchemaService.canReplaceStep(processorName);
const canRemoveStep = !CamelComponentSchemaService.DISABLED_REMOVE_STEPS.includes(processorName);
const canRemoveFlow = data.path === ROOT_PATH;
const canRemoveFlow = data.path === this.getRootPath();
const canBeDisabled = CamelComponentSchemaService.canBeDisabled(processorName);

return {
Expand All @@ -218,21 +219,21 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
}

toVizNode(): IVisualizationNode {
const routeGroupNode = createVisualizationNode('route', {
path: ROOT_PATH,
const routeGroupNode = createVisualizationNode(this.getRootPath(), {
path: this.getRootPath(),
entity: this,
isGroup: true,
icon: NodeIconResolver.getIcon(this.type, NodeIconType.VisualEntity),
processorName: 'route',
});

const fromNode = NodeMapperService.getVizNode(
'from',
`${this.getRootPath()}.from`,
{
processorName: 'from' as keyof ProcessorDefinition,
componentName: CamelComponentSchemaService.getComponentNameFromUri(this.getRootUri()!),
},
this.route,
this.entityDef,
);

if (!this.getRootUri()) {
Expand Down Expand Up @@ -270,9 +271,9 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
if (property === undefined) return;

if (property.type === 'single-clause') {
setValue(this.route, `${options.data.path}.${property.name}`, defaultValue);
setValue(this.entityDef, `${options.data.path}.${property.name}`, defaultValue);
} else {
const arrayPath = getArrayProperty(this.route, `${options.data.path}.${property.name}`);
const arrayPath = getArrayProperty(this.entityDef, `${options.data.path}.${property.name}`);
arrayPath.unshift(defaultValue);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { NodeMapperService } from './nodes/node-mapper.service';
export class CamelErrorHandlerVisualEntity implements BaseVisualCamelEntity {
id: string;
readonly type = EntityType.ErrorHandler;
static readonly ROOT_PATH = 'errorHandler';

constructor(public errorHandlerDef: { errorHandler: ErrorHandlerDeserializer } = { errorHandler: {} }) {
const id = getCamelRandomId('errorHandler');
Expand All @@ -34,6 +35,10 @@ export class CamelErrorHandlerVisualEntity implements BaseVisualCamelEntity {
);
}

getRootPath(): string {
return CamelErrorHandlerVisualEntity.ROOT_PATH;
}

getId(): string {
return this.id;
}
Expand Down Expand Up @@ -125,7 +130,7 @@ export class CamelErrorHandlerVisualEntity implements BaseVisualCamelEntity {

toVizNode(): IVisualizationNode<IVisualizationNodeData> {
const errorHandlerGroupNode = NodeMapperService.getVizNode(
'errorHandler',
this.getRootPath(),
{ processorName: 'errorHandler' as keyof ProcessorDefinition },
this.errorHandlerDef,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export class CamelInterceptFromVisualEntity
);
}

getRootPath(): string {
return CamelInterceptFromVisualEntity.ROOT_PATH;
}

getId(): string {
return this.id;
}
Expand Down
Loading

0 comments on commit 2e6d8e6

Please sign in to comment.