You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2023/10/23 19:57:41 UTC
[camel-karavan] branch main updated: #905
This is an automated email from the ASF dual-hosted git repository.
marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
The following commit(s) were added to refs/heads/main by this push:
new 56ed9809 #905
56ed9809 is described below
commit 56ed9809965f9419d048eaaad3a106863eead58c
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Mon Oct 23 15:57:32 2023 -0400
#905
---
karavan-core/src/core/api/CamelDefinitionYaml.ts | 2 +-
karavan-core/test/beans.spec.ts | 37 +++++-
karavan-core/test/beans3.yaml | 7 +
.../src/designer/beans/BeanProperties.tsx | 145 +++++++++++++++++----
.../src/designer/beans/BeansDesigner.tsx | 5 +-
.../src/designer/beans/BeanProperties.tsx | 145 +++++++++++++++++----
karavan-space/src/designer/beans/BeansDesigner.tsx | 5 +-
.../webui/src/designer/beans/BeanProperties.tsx | 145 +++++++++++++++++----
.../webui/src/designer/beans/BeansDesigner.tsx | 5 +-
9 files changed, 401 insertions(+), 95 deletions(-)
diff --git a/karavan-core/src/core/api/CamelDefinitionYaml.ts b/karavan-core/src/core/api/CamelDefinitionYaml.ts
index aa6f425b..7916801a 100644
--- a/karavan-core/src/core/api/CamelDefinitionYaml.ts
+++ b/karavan-core/src/core/api/CamelDefinitionYaml.ts
@@ -120,7 +120,7 @@ export class CamelDefinitionYaml {
return result;
};
- static yamlDump = (integration: Integration): string => {
+ static yamlDump = (integration: any): string => {
return yaml.dump(integration, {
noRefs: false,
noArrayIndent: false,
diff --git a/karavan-core/test/beans.spec.ts b/karavan-core/test/beans.spec.ts
index 8a4ff26b..7e372f34 100644
--- a/karavan-core/test/beans.spec.ts
+++ b/karavan-core/test/beans.spec.ts
@@ -14,17 +14,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import {expect} from 'chai';
+import { expect } from 'chai';
import * as fs from 'fs';
import 'mocha';
-import {CamelDefinitionYaml} from "../src/core/api/CamelDefinitionYaml";
+import { CamelDefinitionYaml } from '../src/core/api/CamelDefinitionYaml';
+import { Integration } from '../lib/model/IntegrationDefinition';
+import { RegistryBeanDefinition } from '../src/core/model/CamelDefinition';
+import * as yaml from 'js-yaml';
describe('bean configuration', () => {
it('Read beans from plain YAML', () => {
- const yaml = fs.readFileSync('test/beans1.yaml', {encoding: 'utf8', flag: 'r'});
- const i = CamelDefinitionYaml.yamlToIntegration("beans.yaml", yaml);
+ const yaml = fs.readFileSync('test/beans1.yaml', { encoding: 'utf8', flag: 'r' });
+ const i = CamelDefinitionYaml.yamlToIntegration('beans.yaml', yaml);
expect(i.metadata.name).to.equal('beans.yaml');
expect(i.kind).to.equal('Integration');
expect(i.spec.flows?.length).to.equal(3);
@@ -38,12 +41,12 @@ describe('bean configuration', () => {
});
it('Read beans from Integration', () => {
- const yaml = fs.readFileSync('test/beans2.yaml',{encoding:'utf8', flag:'r'});
- const i = CamelDefinitionYaml.yamlToIntegration("beans.yaml", yaml);
+ const yaml = fs.readFileSync('test/beans2.yaml', { encoding: 'utf8', flag: 'r' });
+ const i = CamelDefinitionYaml.yamlToIntegration('beans.yaml', yaml);
expect(i.metadata.name).to.equal('Beans');
expect(i.kind).to.equal('Integration');
expect(i.spec.flows?.length).to.equal(3);
- expect(i.type).to.equal("crd");
+ expect(i.type).to.equal('crd');
if (i.spec.flows) {
expect(i.spec.flows[2].beans[0].name).to.equal('myNested');
expect(i.spec.flows[2].beans[0].type).to.equal('${MyBean.class.name}');
@@ -52,4 +55,24 @@ describe('bean configuration', () => {
}
});
+ class Val {
+
+ }
+
+ it('Bean constructor', () => {
+ const text = fs.readFileSync('test/beans3.yaml', { encoding: 'utf8', flag: 'r' });
+ const i = CamelDefinitionYaml.yamlToIntegration('beans.yaml', text);
+
+ const b = Integration.createNew('beans');
+ const bean = new RegistryBeanDefinition({
+ name: 'Name', type: 'Type', constructors: {
+ 0: 'zero',
+ 1: 'one',
+ 2: 'two',
+ },
+ });
+ b.spec.flows?.push(bean);
+ // console.log(CamelDefinitionYaml.integrationToYaml(b))
+ });
+
});
diff --git a/karavan-core/test/beans3.yaml b/karavan-core/test/beans3.yaml
new file mode 100644
index 00000000..1f3a137a
--- /dev/null
+++ b/karavan-core/test/beans3.yaml
@@ -0,0 +1,7 @@
+- beans:
+ - constructors:
+ 0: zero
+ 1: one
+ 2: two
+ name: Name
+ type: Type
\ No newline at end of file
diff --git a/karavan-designer/src/designer/beans/BeanProperties.tsx b/karavan-designer/src/designer/beans/BeanProperties.tsx
index 455291c4..df72edca 100644
--- a/karavan-designer/src/designer/beans/BeanProperties.tsx
+++ b/karavan-designer/src/designer/beans/BeanProperties.tsx
@@ -58,9 +58,11 @@ export function BeanProperties (props: Props) {
const [infrastructureSelectorProperty, setInfrastructureSelectorProperty] = useState<string | undefined>(undefined);
const [infrastructureSelectorUuid, setInfrastructureSelectorUuid] = useState<string | undefined>(undefined);
const [properties, setProperties] = useState<Map<string, [string, string, boolean]>>(new Map<string, [string, string, boolean]>());
+ const [constructors, setConstructors] = useState<Map<string, [number, string, boolean]>>(new Map<string, [number, string, boolean]>());
useEffect(()=> {
setProperties(preparePropertiesMap((selectedStep as RegistryBeanDefinition)?.properties))
+ setConstructors(prepareConstructorsMap((selectedStep as RegistryBeanDefinition)?.constructors))
}, [selectedStep?.uuid])
function preparePropertiesMap (properties: any): Map<string, [string, string, boolean]> {
@@ -71,6 +73,14 @@ export function BeanProperties (props: Props) {
return result;
}
+ function prepareConstructorsMap (constructors: any): Map<string, [number, string, boolean]> {
+ const result = new Map<string, [number, string, boolean]>();
+ if (constructors) {
+ Object.keys(constructors).forEach((k, i, a) => result.set(uuidv4(), [parseInt(k), constructors[k], false]));
+ }
+ return result;
+ }
+
function onBeanPropertyUpdate () {
if (selectedStep) {
const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
@@ -81,6 +91,16 @@ export function BeanProperties (props: Props) {
}
}
+ function onBeanConstructorsUpdate () {
+ if (selectedStep) {
+ const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
+ const beanConstructors: any = {};
+ constructors.forEach((p: any) => beanConstructors[p[0]] = p[1]);
+ bean.constructors = beanConstructors;
+ props.onChange(bean);
+ }
+ }
+
function beanFieldChanged (fieldId: string, value: string) {
if (selectedStep) {
const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
@@ -97,6 +117,14 @@ export function BeanProperties (props: Props) {
onBeanPropertyUpdate();
}
+ function constructorChanged (uuid: string, key: number, value: string, showPassword: boolean) {
+ setConstructors(prevState => {
+ prevState.set(uuid, [key, value, showPassword]);
+ return prevState;
+ });
+ onBeanConstructorsUpdate();
+ }
+
function propertyDeleted (uuid: string) {
setProperties(prevState => {
prevState.delete(uuid);
@@ -105,6 +133,14 @@ export function BeanProperties (props: Props) {
onBeanPropertyUpdate();
}
+ function constructorDeleted (uuid: string) {
+ setConstructors(prevState => {
+ prevState.delete(uuid);
+ return prevState;
+ })
+ onBeanConstructorsUpdate();
+ }
+
function selectInfrastructure (value: string) {
const propertyId = infrastructureSelectorProperty;
const uuid = infrastructureSelectorUuid;
@@ -163,26 +199,57 @@ export function BeanProperties (props: Props) {
</Popover>
)
}
- function getBeanForm() {
- const bean = (selectedStep as RegistryBeanDefinition);
+
+ function getBeanConstructors() {
+ return (
+ <FormGroup label="Constructors" fieldId="constructors" className="bean-properties">
+ {Array.from(constructors.entries()).map((v, index, array) => {
+ const i = v[0];
+ const key = v[1][0];
+ const value = v[1][1];
+ const showPassword = v[1][2];
+ const isSecret = false;
+ return (
+ <div key={"key-" + i} className="bean-property">
+ <TextInput placeholder="Argument Index" className="text-field" isRequired type="text" id={"key-" + i}
+ name={"key-" + i} value={key}
+ onChange={(_, beanFieldName) => {
+ constructorChanged(i, parseInt(beanFieldName) , value, showPassword)
+ }}/>
+ <InputGroup>
+ <InputGroupItem isFill>
+ <TextInput
+ placeholder="Argument Value"
+ type={isSecret && !showPassword ? "password" : "text"}
+ className="text-field"
+ isRequired
+ id={"value-" + i}
+ name={"value-" + i}
+ value={value}
+ onChange={(_, value) => {
+ constructorChanged(i, key, value, showPassword)
+ }}/>
+ </InputGroupItem>
+ {isSecret && <Tooltip position="bottom-end" content={showPassword ? "Hide" : "Show"}>
+ <Button variant="control" onClick={e => constructorChanged(i, key, value, !showPassword)}>
+ {showPassword ? <ShowIcon/> : <HideIcon/>}
+ </Button>
+ </Tooltip>}
+ </InputGroup>
+ <Button variant="link" className="delete-button" onClick={e => constructorDeleted(i)}>
+ <DeleteIcon/>
+ </Button>
+ </div>
+ )
+ })}
+ <Button variant="link" className="add-button" onClick={e => constructorChanged(uuidv4(), constructors.size, '', false)}>
+ <AddIcon/>Add argument</Button>
+ </FormGroup>
+ )
+ }
+
+ function getBeanProperties() {
return (
- <>
- <div className="headers">
- <div className="top">
- <Title headingLevel="h1" size="md">Bean</Title>
- <Tooltip content="Clone bean" position="bottom">
- <Button variant="link" onClick={() => cloneBean()} icon={<CloneIcon/>}/>
- </Tooltip>
- </div>
- </div>
- <FormGroup label="Name" fieldId="name" isRequired labelIcon={getLabelIcon("Name", "Bean name used as a reference ex: myBean")}>
- <TextInput className="text-field" isRequired type="text" id="name" name="name" value={bean?.name}
- onChange={(_, value)=> beanFieldChanged("name", value)}/>
- </FormGroup>
- <FormGroup label="Type" fieldId="type" isRequired labelIcon={getLabelIcon("Type", "Bean class Canonical Name ex: org.demo.MyBean")}>
- <TextInput className="text-field" isRequired type="text" id="type" name="type" value={bean?.type}
- onChange={(_, value) => beanFieldChanged("type", value)}/>
- </FormGroup>
<FormGroup label="Properties" fieldId="properties" className="bean-properties">
{Array.from(properties.entries()).map((v, index, array) => {
const i = v[0];
@@ -196,16 +263,16 @@ export function BeanProperties (props: Props) {
<div key={"key-" + i} className="bean-property">
<TextInput placeholder="Bean Field Name" className="text-field" isRequired type="text" id={"key-" + i}
name={"key-" + i} value={key}
- onChange={(_, beanFieldName) => {
- propertyChanged(i, beanFieldName, value, showPassword)
- }}/>
+ onChange={(_, beanFieldName) => {
+ propertyChanged(i, beanFieldName, value, showPassword)
+ }}/>
<InputGroup>
{inInfrastructure &&
<Tooltip position="bottom-end" content="Select value from Infrastructure">
- <Button variant="control" onClick={e => openInfrastructureSelector(i, key)}>
- {icon}
- </Button>
- </Tooltip>}
+ <Button variant="control" onClick={e => openInfrastructureSelector(i, key)}>
+ {icon}
+ </Button>
+ </Tooltip>}
<InputGroupItem isFill>
<TextInput
placeholder="Bean Field Value"
@@ -232,6 +299,32 @@ export function BeanProperties (props: Props) {
<Button variant="link" className="add-button" onClick={e => propertyChanged(uuidv4(), '', '', false)}>
<AddIcon/>Add property</Button>
</FormGroup>
+ )
+ }
+
+
+ function getBeanForm() {
+ const bean = (selectedStep as RegistryBeanDefinition);
+ return (
+ <>
+ <div className="headers">
+ <div className="top">
+ <Title headingLevel="h1" size="md">Bean</Title>
+ <Tooltip content="Clone bean" position="bottom">
+ <Button variant="link" onClick={() => cloneBean()} icon={<CloneIcon/>}/>
+ </Tooltip>
+ </div>
+ </div>
+ <FormGroup label="Name" fieldId="name" isRequired labelIcon={getLabelIcon("Name", "Bean name used as a reference ex: myBean")}>
+ <TextInput className="text-field" isRequired type="text" id="name" name="name" value={bean?.name}
+ onChange={(_, value)=> beanFieldChanged("name", value)}/>
+ </FormGroup>
+ <FormGroup label="Type" fieldId="type" isRequired labelIcon={getLabelIcon("Type", "Bean class Canonical Name ex: org.demo.MyBean")}>
+ <TextInput className="text-field" isRequired type="text" id="type" name="type" value={bean?.type}
+ onChange={(_, value) => beanFieldChanged("type", value)}/>
+ </FormGroup>
+ {getBeanConstructors()}
+ {getBeanProperties()}
</>
)
}
diff --git a/karavan-designer/src/designer/beans/BeansDesigner.tsx b/karavan-designer/src/designer/beans/BeansDesigner.tsx
index 8cd99f25..2e7b67e0 100644
--- a/karavan-designer/src/designer/beans/BeansDesigner.tsx
+++ b/karavan-designer/src/designer/beans/BeansDesigner.tsx
@@ -123,9 +123,8 @@ export function BeansDesigner() {
}}
>
{beans?.map((bean, index) => (
- <GalleryItem>
- <BeanCard key={bean.uuid + index}
- bean={bean}
+ <GalleryItem key={bean.uuid + index}>
+ <BeanCard bean={bean}
selectElement={selectBean}
deleteElement={onShowDeleteConfirmation}
/>
diff --git a/karavan-space/src/designer/beans/BeanProperties.tsx b/karavan-space/src/designer/beans/BeanProperties.tsx
index 455291c4..df72edca 100644
--- a/karavan-space/src/designer/beans/BeanProperties.tsx
+++ b/karavan-space/src/designer/beans/BeanProperties.tsx
@@ -58,9 +58,11 @@ export function BeanProperties (props: Props) {
const [infrastructureSelectorProperty, setInfrastructureSelectorProperty] = useState<string | undefined>(undefined);
const [infrastructureSelectorUuid, setInfrastructureSelectorUuid] = useState<string | undefined>(undefined);
const [properties, setProperties] = useState<Map<string, [string, string, boolean]>>(new Map<string, [string, string, boolean]>());
+ const [constructors, setConstructors] = useState<Map<string, [number, string, boolean]>>(new Map<string, [number, string, boolean]>());
useEffect(()=> {
setProperties(preparePropertiesMap((selectedStep as RegistryBeanDefinition)?.properties))
+ setConstructors(prepareConstructorsMap((selectedStep as RegistryBeanDefinition)?.constructors))
}, [selectedStep?.uuid])
function preparePropertiesMap (properties: any): Map<string, [string, string, boolean]> {
@@ -71,6 +73,14 @@ export function BeanProperties (props: Props) {
return result;
}
+ function prepareConstructorsMap (constructors: any): Map<string, [number, string, boolean]> {
+ const result = new Map<string, [number, string, boolean]>();
+ if (constructors) {
+ Object.keys(constructors).forEach((k, i, a) => result.set(uuidv4(), [parseInt(k), constructors[k], false]));
+ }
+ return result;
+ }
+
function onBeanPropertyUpdate () {
if (selectedStep) {
const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
@@ -81,6 +91,16 @@ export function BeanProperties (props: Props) {
}
}
+ function onBeanConstructorsUpdate () {
+ if (selectedStep) {
+ const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
+ const beanConstructors: any = {};
+ constructors.forEach((p: any) => beanConstructors[p[0]] = p[1]);
+ bean.constructors = beanConstructors;
+ props.onChange(bean);
+ }
+ }
+
function beanFieldChanged (fieldId: string, value: string) {
if (selectedStep) {
const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
@@ -97,6 +117,14 @@ export function BeanProperties (props: Props) {
onBeanPropertyUpdate();
}
+ function constructorChanged (uuid: string, key: number, value: string, showPassword: boolean) {
+ setConstructors(prevState => {
+ prevState.set(uuid, [key, value, showPassword]);
+ return prevState;
+ });
+ onBeanConstructorsUpdate();
+ }
+
function propertyDeleted (uuid: string) {
setProperties(prevState => {
prevState.delete(uuid);
@@ -105,6 +133,14 @@ export function BeanProperties (props: Props) {
onBeanPropertyUpdate();
}
+ function constructorDeleted (uuid: string) {
+ setConstructors(prevState => {
+ prevState.delete(uuid);
+ return prevState;
+ })
+ onBeanConstructorsUpdate();
+ }
+
function selectInfrastructure (value: string) {
const propertyId = infrastructureSelectorProperty;
const uuid = infrastructureSelectorUuid;
@@ -163,26 +199,57 @@ export function BeanProperties (props: Props) {
</Popover>
)
}
- function getBeanForm() {
- const bean = (selectedStep as RegistryBeanDefinition);
+
+ function getBeanConstructors() {
+ return (
+ <FormGroup label="Constructors" fieldId="constructors" className="bean-properties">
+ {Array.from(constructors.entries()).map((v, index, array) => {
+ const i = v[0];
+ const key = v[1][0];
+ const value = v[1][1];
+ const showPassword = v[1][2];
+ const isSecret = false;
+ return (
+ <div key={"key-" + i} className="bean-property">
+ <TextInput placeholder="Argument Index" className="text-field" isRequired type="text" id={"key-" + i}
+ name={"key-" + i} value={key}
+ onChange={(_, beanFieldName) => {
+ constructorChanged(i, parseInt(beanFieldName) , value, showPassword)
+ }}/>
+ <InputGroup>
+ <InputGroupItem isFill>
+ <TextInput
+ placeholder="Argument Value"
+ type={isSecret && !showPassword ? "password" : "text"}
+ className="text-field"
+ isRequired
+ id={"value-" + i}
+ name={"value-" + i}
+ value={value}
+ onChange={(_, value) => {
+ constructorChanged(i, key, value, showPassword)
+ }}/>
+ </InputGroupItem>
+ {isSecret && <Tooltip position="bottom-end" content={showPassword ? "Hide" : "Show"}>
+ <Button variant="control" onClick={e => constructorChanged(i, key, value, !showPassword)}>
+ {showPassword ? <ShowIcon/> : <HideIcon/>}
+ </Button>
+ </Tooltip>}
+ </InputGroup>
+ <Button variant="link" className="delete-button" onClick={e => constructorDeleted(i)}>
+ <DeleteIcon/>
+ </Button>
+ </div>
+ )
+ })}
+ <Button variant="link" className="add-button" onClick={e => constructorChanged(uuidv4(), constructors.size, '', false)}>
+ <AddIcon/>Add argument</Button>
+ </FormGroup>
+ )
+ }
+
+ function getBeanProperties() {
return (
- <>
- <div className="headers">
- <div className="top">
- <Title headingLevel="h1" size="md">Bean</Title>
- <Tooltip content="Clone bean" position="bottom">
- <Button variant="link" onClick={() => cloneBean()} icon={<CloneIcon/>}/>
- </Tooltip>
- </div>
- </div>
- <FormGroup label="Name" fieldId="name" isRequired labelIcon={getLabelIcon("Name", "Bean name used as a reference ex: myBean")}>
- <TextInput className="text-field" isRequired type="text" id="name" name="name" value={bean?.name}
- onChange={(_, value)=> beanFieldChanged("name", value)}/>
- </FormGroup>
- <FormGroup label="Type" fieldId="type" isRequired labelIcon={getLabelIcon("Type", "Bean class Canonical Name ex: org.demo.MyBean")}>
- <TextInput className="text-field" isRequired type="text" id="type" name="type" value={bean?.type}
- onChange={(_, value) => beanFieldChanged("type", value)}/>
- </FormGroup>
<FormGroup label="Properties" fieldId="properties" className="bean-properties">
{Array.from(properties.entries()).map((v, index, array) => {
const i = v[0];
@@ -196,16 +263,16 @@ export function BeanProperties (props: Props) {
<div key={"key-" + i} className="bean-property">
<TextInput placeholder="Bean Field Name" className="text-field" isRequired type="text" id={"key-" + i}
name={"key-" + i} value={key}
- onChange={(_, beanFieldName) => {
- propertyChanged(i, beanFieldName, value, showPassword)
- }}/>
+ onChange={(_, beanFieldName) => {
+ propertyChanged(i, beanFieldName, value, showPassword)
+ }}/>
<InputGroup>
{inInfrastructure &&
<Tooltip position="bottom-end" content="Select value from Infrastructure">
- <Button variant="control" onClick={e => openInfrastructureSelector(i, key)}>
- {icon}
- </Button>
- </Tooltip>}
+ <Button variant="control" onClick={e => openInfrastructureSelector(i, key)}>
+ {icon}
+ </Button>
+ </Tooltip>}
<InputGroupItem isFill>
<TextInput
placeholder="Bean Field Value"
@@ -232,6 +299,32 @@ export function BeanProperties (props: Props) {
<Button variant="link" className="add-button" onClick={e => propertyChanged(uuidv4(), '', '', false)}>
<AddIcon/>Add property</Button>
</FormGroup>
+ )
+ }
+
+
+ function getBeanForm() {
+ const bean = (selectedStep as RegistryBeanDefinition);
+ return (
+ <>
+ <div className="headers">
+ <div className="top">
+ <Title headingLevel="h1" size="md">Bean</Title>
+ <Tooltip content="Clone bean" position="bottom">
+ <Button variant="link" onClick={() => cloneBean()} icon={<CloneIcon/>}/>
+ </Tooltip>
+ </div>
+ </div>
+ <FormGroup label="Name" fieldId="name" isRequired labelIcon={getLabelIcon("Name", "Bean name used as a reference ex: myBean")}>
+ <TextInput className="text-field" isRequired type="text" id="name" name="name" value={bean?.name}
+ onChange={(_, value)=> beanFieldChanged("name", value)}/>
+ </FormGroup>
+ <FormGroup label="Type" fieldId="type" isRequired labelIcon={getLabelIcon("Type", "Bean class Canonical Name ex: org.demo.MyBean")}>
+ <TextInput className="text-field" isRequired type="text" id="type" name="type" value={bean?.type}
+ onChange={(_, value) => beanFieldChanged("type", value)}/>
+ </FormGroup>
+ {getBeanConstructors()}
+ {getBeanProperties()}
</>
)
}
diff --git a/karavan-space/src/designer/beans/BeansDesigner.tsx b/karavan-space/src/designer/beans/BeansDesigner.tsx
index 8cd99f25..2e7b67e0 100644
--- a/karavan-space/src/designer/beans/BeansDesigner.tsx
+++ b/karavan-space/src/designer/beans/BeansDesigner.tsx
@@ -123,9 +123,8 @@ export function BeansDesigner() {
}}
>
{beans?.map((bean, index) => (
- <GalleryItem>
- <BeanCard key={bean.uuid + index}
- bean={bean}
+ <GalleryItem key={bean.uuid + index}>
+ <BeanCard bean={bean}
selectElement={selectBean}
deleteElement={onShowDeleteConfirmation}
/>
diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/beans/BeanProperties.tsx b/karavan-web/karavan-app/src/main/webui/src/designer/beans/BeanProperties.tsx
index 455291c4..df72edca 100644
--- a/karavan-web/karavan-app/src/main/webui/src/designer/beans/BeanProperties.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/designer/beans/BeanProperties.tsx
@@ -58,9 +58,11 @@ export function BeanProperties (props: Props) {
const [infrastructureSelectorProperty, setInfrastructureSelectorProperty] = useState<string | undefined>(undefined);
const [infrastructureSelectorUuid, setInfrastructureSelectorUuid] = useState<string | undefined>(undefined);
const [properties, setProperties] = useState<Map<string, [string, string, boolean]>>(new Map<string, [string, string, boolean]>());
+ const [constructors, setConstructors] = useState<Map<string, [number, string, boolean]>>(new Map<string, [number, string, boolean]>());
useEffect(()=> {
setProperties(preparePropertiesMap((selectedStep as RegistryBeanDefinition)?.properties))
+ setConstructors(prepareConstructorsMap((selectedStep as RegistryBeanDefinition)?.constructors))
}, [selectedStep?.uuid])
function preparePropertiesMap (properties: any): Map<string, [string, string, boolean]> {
@@ -71,6 +73,14 @@ export function BeanProperties (props: Props) {
return result;
}
+ function prepareConstructorsMap (constructors: any): Map<string, [number, string, boolean]> {
+ const result = new Map<string, [number, string, boolean]>();
+ if (constructors) {
+ Object.keys(constructors).forEach((k, i, a) => result.set(uuidv4(), [parseInt(k), constructors[k], false]));
+ }
+ return result;
+ }
+
function onBeanPropertyUpdate () {
if (selectedStep) {
const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
@@ -81,6 +91,16 @@ export function BeanProperties (props: Props) {
}
}
+ function onBeanConstructorsUpdate () {
+ if (selectedStep) {
+ const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
+ const beanConstructors: any = {};
+ constructors.forEach((p: any) => beanConstructors[p[0]] = p[1]);
+ bean.constructors = beanConstructors;
+ props.onChange(bean);
+ }
+ }
+
function beanFieldChanged (fieldId: string, value: string) {
if (selectedStep) {
const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
@@ -97,6 +117,14 @@ export function BeanProperties (props: Props) {
onBeanPropertyUpdate();
}
+ function constructorChanged (uuid: string, key: number, value: string, showPassword: boolean) {
+ setConstructors(prevState => {
+ prevState.set(uuid, [key, value, showPassword]);
+ return prevState;
+ });
+ onBeanConstructorsUpdate();
+ }
+
function propertyDeleted (uuid: string) {
setProperties(prevState => {
prevState.delete(uuid);
@@ -105,6 +133,14 @@ export function BeanProperties (props: Props) {
onBeanPropertyUpdate();
}
+ function constructorDeleted (uuid: string) {
+ setConstructors(prevState => {
+ prevState.delete(uuid);
+ return prevState;
+ })
+ onBeanConstructorsUpdate();
+ }
+
function selectInfrastructure (value: string) {
const propertyId = infrastructureSelectorProperty;
const uuid = infrastructureSelectorUuid;
@@ -163,26 +199,57 @@ export function BeanProperties (props: Props) {
</Popover>
)
}
- function getBeanForm() {
- const bean = (selectedStep as RegistryBeanDefinition);
+
+ function getBeanConstructors() {
+ return (
+ <FormGroup label="Constructors" fieldId="constructors" className="bean-properties">
+ {Array.from(constructors.entries()).map((v, index, array) => {
+ const i = v[0];
+ const key = v[1][0];
+ const value = v[1][1];
+ const showPassword = v[1][2];
+ const isSecret = false;
+ return (
+ <div key={"key-" + i} className="bean-property">
+ <TextInput placeholder="Argument Index" className="text-field" isRequired type="text" id={"key-" + i}
+ name={"key-" + i} value={key}
+ onChange={(_, beanFieldName) => {
+ constructorChanged(i, parseInt(beanFieldName) , value, showPassword)
+ }}/>
+ <InputGroup>
+ <InputGroupItem isFill>
+ <TextInput
+ placeholder="Argument Value"
+ type={isSecret && !showPassword ? "password" : "text"}
+ className="text-field"
+ isRequired
+ id={"value-" + i}
+ name={"value-" + i}
+ value={value}
+ onChange={(_, value) => {
+ constructorChanged(i, key, value, showPassword)
+ }}/>
+ </InputGroupItem>
+ {isSecret && <Tooltip position="bottom-end" content={showPassword ? "Hide" : "Show"}>
+ <Button variant="control" onClick={e => constructorChanged(i, key, value, !showPassword)}>
+ {showPassword ? <ShowIcon/> : <HideIcon/>}
+ </Button>
+ </Tooltip>}
+ </InputGroup>
+ <Button variant="link" className="delete-button" onClick={e => constructorDeleted(i)}>
+ <DeleteIcon/>
+ </Button>
+ </div>
+ )
+ })}
+ <Button variant="link" className="add-button" onClick={e => constructorChanged(uuidv4(), constructors.size, '', false)}>
+ <AddIcon/>Add argument</Button>
+ </FormGroup>
+ )
+ }
+
+ function getBeanProperties() {
return (
- <>
- <div className="headers">
- <div className="top">
- <Title headingLevel="h1" size="md">Bean</Title>
- <Tooltip content="Clone bean" position="bottom">
- <Button variant="link" onClick={() => cloneBean()} icon={<CloneIcon/>}/>
- </Tooltip>
- </div>
- </div>
- <FormGroup label="Name" fieldId="name" isRequired labelIcon={getLabelIcon("Name", "Bean name used as a reference ex: myBean")}>
- <TextInput className="text-field" isRequired type="text" id="name" name="name" value={bean?.name}
- onChange={(_, value)=> beanFieldChanged("name", value)}/>
- </FormGroup>
- <FormGroup label="Type" fieldId="type" isRequired labelIcon={getLabelIcon("Type", "Bean class Canonical Name ex: org.demo.MyBean")}>
- <TextInput className="text-field" isRequired type="text" id="type" name="type" value={bean?.type}
- onChange={(_, value) => beanFieldChanged("type", value)}/>
- </FormGroup>
<FormGroup label="Properties" fieldId="properties" className="bean-properties">
{Array.from(properties.entries()).map((v, index, array) => {
const i = v[0];
@@ -196,16 +263,16 @@ export function BeanProperties (props: Props) {
<div key={"key-" + i} className="bean-property">
<TextInput placeholder="Bean Field Name" className="text-field" isRequired type="text" id={"key-" + i}
name={"key-" + i} value={key}
- onChange={(_, beanFieldName) => {
- propertyChanged(i, beanFieldName, value, showPassword)
- }}/>
+ onChange={(_, beanFieldName) => {
+ propertyChanged(i, beanFieldName, value, showPassword)
+ }}/>
<InputGroup>
{inInfrastructure &&
<Tooltip position="bottom-end" content="Select value from Infrastructure">
- <Button variant="control" onClick={e => openInfrastructureSelector(i, key)}>
- {icon}
- </Button>
- </Tooltip>}
+ <Button variant="control" onClick={e => openInfrastructureSelector(i, key)}>
+ {icon}
+ </Button>
+ </Tooltip>}
<InputGroupItem isFill>
<TextInput
placeholder="Bean Field Value"
@@ -232,6 +299,32 @@ export function BeanProperties (props: Props) {
<Button variant="link" className="add-button" onClick={e => propertyChanged(uuidv4(), '', '', false)}>
<AddIcon/>Add property</Button>
</FormGroup>
+ )
+ }
+
+
+ function getBeanForm() {
+ const bean = (selectedStep as RegistryBeanDefinition);
+ return (
+ <>
+ <div className="headers">
+ <div className="top">
+ <Title headingLevel="h1" size="md">Bean</Title>
+ <Tooltip content="Clone bean" position="bottom">
+ <Button variant="link" onClick={() => cloneBean()} icon={<CloneIcon/>}/>
+ </Tooltip>
+ </div>
+ </div>
+ <FormGroup label="Name" fieldId="name" isRequired labelIcon={getLabelIcon("Name", "Bean name used as a reference ex: myBean")}>
+ <TextInput className="text-field" isRequired type="text" id="name" name="name" value={bean?.name}
+ onChange={(_, value)=> beanFieldChanged("name", value)}/>
+ </FormGroup>
+ <FormGroup label="Type" fieldId="type" isRequired labelIcon={getLabelIcon("Type", "Bean class Canonical Name ex: org.demo.MyBean")}>
+ <TextInput className="text-field" isRequired type="text" id="type" name="type" value={bean?.type}
+ onChange={(_, value) => beanFieldChanged("type", value)}/>
+ </FormGroup>
+ {getBeanConstructors()}
+ {getBeanProperties()}
</>
)
}
diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/beans/BeansDesigner.tsx b/karavan-web/karavan-app/src/main/webui/src/designer/beans/BeansDesigner.tsx
index 8cd99f25..2e7b67e0 100644
--- a/karavan-web/karavan-app/src/main/webui/src/designer/beans/BeansDesigner.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/designer/beans/BeansDesigner.tsx
@@ -123,9 +123,8 @@ export function BeansDesigner() {
}}
>
{beans?.map((bean, index) => (
- <GalleryItem>
- <BeanCard key={bean.uuid + index}
- bean={bean}
+ <GalleryItem key={bean.uuid + index}>
+ <BeanCard bean={bean}
selectElement={selectBean}
deleteElement={onShowDeleteConfirmation}
/>