Skip to content

Commit fe42daa

Browse files
committed
Add custom fields for Citrus Endpoints and MessageBody
1 parent 5b3a80c commit fe42daa

11 files changed

Lines changed: 1442 additions & 0 deletions

File tree

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { FieldProps, FieldWrapper, SchemaContext, Typeahead, TypeaheadItem, useFieldValue } from '@kaoto/forms';
2+
import { FunctionComponent, useCallback, useContext, useMemo, useState } from 'react';
3+
4+
import { CitrusTestResource } from '../../../../../../models/citrus/citrus-test-resource';
5+
import { EndpointsEntityHandler } from '../../../../../../models/visualization/metadata/citrus/endpoints-entity-handler';
6+
import { EntitiesContext } from '../../../../../../providers';
7+
import { EndpointModal } from './EndpointModal';
8+
9+
export const EndpointField: FunctionComponent<FieldProps> = ({ propName, required }) => {
10+
const { schema } = useContext(SchemaContext);
11+
const { value = '', onChange, disabled } = useFieldValue<string | undefined>(propName);
12+
const entitiesContext = useContext(EntitiesContext);
13+
const testResource = entitiesContext?.camelResource as CitrusTestResource | undefined;
14+
const endpointReference = value;
15+
const endpointsHandler = useMemo(() => new EndpointsEntityHandler(testResource), [testResource]);
16+
const endpointsSchema = useMemo(() => endpointsHandler.getEndpointsSchema(), [endpointsHandler]);
17+
const [isOpen, setIsOpen] = useState<boolean>(false);
18+
const [lastUpdated, setLastUpdated] = useState<number>(Date.now());
19+
20+
const items = useMemo(() => {
21+
return (
22+
endpointsHandler.getAllEndpointsNameAndType().map((item) => ({
23+
name: item.name,
24+
description: String(item.type),
25+
value: String(item.name),
26+
})) ?? []
27+
);
28+
29+
// eslint-disable-next-line react-hooks/exhaustive-deps
30+
}, [endpointsHandler, lastUpdated]);
31+
32+
const selectedItem = useMemo(() => {
33+
if (!value) {
34+
return undefined;
35+
}
36+
// Object values are stringified. Double check later different approach.
37+
if (typeof value === 'object') {
38+
return {
39+
value: JSON.stringify(value),
40+
name: JSON.stringify(value),
41+
description: '',
42+
};
43+
}
44+
return items.find((item) => item.name === value) ?? { value: value, name: value, description: '' };
45+
}, [items, value]);
46+
47+
const onItemChange = useCallback(
48+
(item?: TypeaheadItem<string>) => {
49+
onChange(item!.name);
50+
},
51+
[onChange],
52+
);
53+
54+
const onCleanInput = useCallback(() => {
55+
onChange(undefined);
56+
setLastUpdated(Date.now());
57+
setIsOpen(false);
58+
}, [onChange]);
59+
60+
const onSelect = useCallback((value: string | undefined, _filterValue: string | undefined) => {
61+
if (value) {
62+
setIsOpen(true);
63+
}
64+
}, []);
65+
66+
const handleCreate = useCallback(
67+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
68+
(type: string, model: any) => {
69+
if (!type || model === undefined || typeof model !== 'object' || model?.name === undefined) {
70+
return;
71+
}
72+
73+
endpointsHandler.addNewEndpoint(type, model as unknown as Record<string, unknown>);
74+
75+
setIsOpen(false);
76+
onChange(model.name);
77+
setLastUpdated(Date.now());
78+
},
79+
[endpointsHandler, onChange],
80+
);
81+
82+
const handleCancel = useCallback(() => {
83+
onChange(endpointReference);
84+
setIsOpen(false);
85+
}, [endpointReference, onChange]);
86+
87+
return (
88+
<>
89+
<FieldWrapper
90+
propName={propName}
91+
required={required}
92+
title={schema.title}
93+
type="string"
94+
description={schema.description}
95+
defaultValue={schema.default?.toString()}
96+
>
97+
<Typeahead
98+
aria-label={schema.title ?? propName}
99+
data-testid={propName}
100+
selectedItem={selectedItem}
101+
items={items}
102+
placeholder={schema.default?.toString()}
103+
id={propName}
104+
onChange={onItemChange}
105+
onCleanInput={onCleanInput}
106+
onCreate={onSelect}
107+
disabled={disabled}
108+
allowCustomInput={true}
109+
/>
110+
</FieldWrapper>
111+
112+
{isOpen && (
113+
<EndpointModal
114+
mode={'Create'}
115+
endpointsSchema={endpointsSchema}
116+
onConfirm={handleCreate}
117+
onCancel={handleCancel}
118+
/>
119+
)}
120+
</>
121+
);
122+
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { isDefined } from '@kaoto/forms';
2+
import { ArrayFieldWrapper, FieldProps, KaotoForm, OneOfSchemas, SchemaList, useOneOfField } from '@kaoto/forms';
3+
import { FunctionComponent, useEffect } from 'react';
4+
5+
interface EndpointFieldProps extends FieldProps {
6+
model: unknown;
7+
endpointType?: string;
8+
setEndpointType: (value: string) => void;
9+
onModelChange: (value: unknown) => void;
10+
}
11+
12+
export const EndpointFieldInner: FunctionComponent<EndpointFieldProps> = ({
13+
propName,
14+
model,
15+
endpointType,
16+
setEndpointType,
17+
onModelChange,
18+
}) => {
19+
const { selectedOneOfSchema, oneOfSchemas, onSchemaChange, shouldRender } = useOneOfField(propName);
20+
21+
useEffect(() => {
22+
if (model !== undefined && endpointType !== undefined) {
23+
const selectedSchema = oneOfSchemas.find((schema) => schema.schema.name === endpointType);
24+
if (selectedSchema !== selectedOneOfSchema) {
25+
onSchemaChange(selectedSchema);
26+
onModelChange(model);
27+
}
28+
}
29+
}, [endpointType, model, oneOfSchemas, onSchemaChange, onModelChange, selectedOneOfSchema]);
30+
31+
const onCleanInput = () => {
32+
onSchemaChange();
33+
onModelChange({});
34+
};
35+
36+
const onHandleSchemaChange = (schema?: OneOfSchemas) => {
37+
setEndpointType(schema?.schema.name || '');
38+
onSchemaChange(schema);
39+
};
40+
41+
if (!shouldRender) {
42+
return null;
43+
}
44+
45+
return (
46+
<ArrayFieldWrapper
47+
propName={propName}
48+
type="object"
49+
title={selectedOneOfSchema?.name ?? 'Endpoint'}
50+
description={selectedOneOfSchema?.description}
51+
actions={
52+
<SchemaList
53+
aria-label="endpoint type list"
54+
data-testid="endpoint-type-list"
55+
propName={propName}
56+
selectedSchema={selectedOneOfSchema}
57+
schemas={oneOfSchemas}
58+
onChange={onHandleSchemaChange}
59+
onCleanInput={onCleanInput}
60+
placeholder="Select an endpoint type"
61+
/>
62+
}
63+
>
64+
{isDefined(selectedOneOfSchema?.schema.properties) && (
65+
<KaotoForm
66+
data-testid="new-endpoint-form"
67+
schema={selectedOneOfSchema?.schema}
68+
model={model}
69+
onChange={onModelChange}
70+
/>
71+
)}
72+
</ArrayFieldWrapper>
73+
);
74+
};

0 commit comments

Comments
 (0)