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 16, 2024
1 parent 48146a9 commit 00142c8
Show file tree
Hide file tree
Showing 21 changed files with 336 additions and 282 deletions.
6 changes: 5 additions & 1 deletion packages/ui/src/components/Visualization/Canvas/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,15 @@ export const Canvas: FunctionComponent<PropsWithChildren<CanvasProps>> = ({ enti
},
};

controller.fromModel(model, true);
console.log(nodes.map((node) => node.id));
console.log(nodes.map((node) => node.data?.vizNode?.data.path));

controller.fromModel(model, false);
setInitialized(true);
}, [controller, entities, visibleFlows]);

const handleSelection = useCallback((selectedIds: string[]) => {
console.log('Selected ids:', selectedIds);

Check warning on line 101 in packages/ui/src/components/Visualization/Canvas/Canvas.tsx

View check run for this annotation

Codecov / codecov/patch

packages/ui/src/components/Visualization/Canvas/Canvas.tsx#L101

Added line #L101 was not covered by tests
setSelectedIds(selectedIds);
}, []);
useEventListener<SelectionEventListener>(SELECTION_EVENT, handleSelection);
Expand Down
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
2 changes: 1 addition & 1 deletion packages/ui/src/hooks/entities.test.tsx
Original file line number Diff line number Diff line change
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
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.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 @@ -36,7 +37,7 @@ export abstract class AbstractCamelVisualEntity<T extends object> implements Bas
getNodeLabel(path?: string, labelType?: NodeLabelType): string {
if (!path) return '';

const componentModel = getValue(this.route, path);
const componentModel = getValue(this.entityDef, 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), []);

Check warning on line 135 in packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts

View check run for this annotation

Codecov / codecov/patch

packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts#L135

Added line #L135 was not covered by tests
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',
'route.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);

Check warning on line 274 in packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts

View check run for this annotation

Codecov / codecov/patch

packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts#L274

Added line #L274 was not covered by tests
} else {
const arrayPath = getArrayProperty(this.route, `${options.data.path}.${property.name}`);
const arrayPath = getArrayProperty(this.entityDef, `${options.data.path}.${property.name}`);

Check warning on line 276 in packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts

View check run for this annotation

Codecov / codecov/patch

packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts#L276

Added line #L276 was not covered by tests
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;

Check warning on line 60 in packages/ui/src/models/visualization/flows/camel-intercept-from-visual-entity.ts

View check run for this annotation

Codecov / codecov/patch

packages/ui/src/models/visualization/flows/camel-intercept-from-visual-entity.ts#L59-L60

Added lines #L59 - L60 were not covered by tests
}

getId(): string {
return this.id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ export class CamelInterceptSendToEndpointVisualEntity
);
}

getRootPath(): string {
return CamelInterceptSendToEndpointVisualEntity.ROOT_PATH;

Check warning on line 72 in packages/ui/src/models/visualization/flows/camel-intercept-send-to-endpoint-visual-entity.ts

View check run for this annotation

Codecov / codecov/patch

packages/ui/src/models/visualization/flows/camel-intercept-send-to-endpoint-visual-entity.ts#L71-L72

Added lines #L71 - L72 were not covered by tests
}

getId(): string {
return this.id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export class CamelInterceptVisualEntity
return objectKeys.length === 1 && this.ROOT_PATH in interceptDef! && typeof interceptDef.intercept === 'object';
}

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

Check warning on line 45 in packages/ui/src/models/visualization/flows/camel-intercept-visual-entity.ts

View check run for this annotation

Codecov / codecov/patch

packages/ui/src/models/visualization/flows/camel-intercept-visual-entity.ts#L42-L45

Added lines #L42 - L45 were not covered by tests
getId(): string {
return this.id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export class CamelOnCompletionVisualEntity
);
}

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

getId(): string {
return this.id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export class CamelOnExceptionVisualEntity
);
}

getRootPath(): string {
return CamelOnExceptionVisualEntity.ROOT_PATH;

Check warning on line 45 in packages/ui/src/models/visualization/flows/camel-on-exception-visual-entity.ts

View check run for this annotation

Codecov / codecov/patch

packages/ui/src/models/visualization/flows/camel-on-exception-visual-entity.ts#L44-L45

Added lines #L44 - L45 were not covered by tests
}

getId(): string {
return this.id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { NodeMapperService } from './nodes/node-mapper.service';
export class CamelRestConfigurationVisualEntity implements BaseVisualCamelEntity {
id: string;
readonly type = EntityType.RestConfiguration;
static readonly ROOT_PATH = 'restConfiguration';
private schemaValidator: ValidateFunction<RestConfiguration> | undefined;

constructor(public restConfigurationDef: { restConfiguration: RestConfiguration } = { restConfiguration: {} }) {
Expand All @@ -39,11 +40,15 @@ export class CamelRestConfigurationVisualEntity implements BaseVisualCamelEntity

return (
objectKeys.length === 1 &&
'restConfiguration' in restConfigurationDef! &&
this.ROOT_PATH in restConfigurationDef! &&
typeof restConfigurationDef.restConfiguration === 'object'
);
}

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

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

toVizNode(): IVisualizationNode<IVisualizationNodeData> {
const restConfigurationGroupNode = NodeMapperService.getVizNode(
'restConfiguration',
this.getRootPath(),
{ processorName: 'restConfiguration' as keyof ProcessorDefinition },
this.restConfigurationDef,
);
Expand Down
Loading

0 comments on commit 00142c8

Please sign in to comment.