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 7ae5077 Preparations for Traits (#265)
7ae5077 is described below
commit 7ae5077cfdc70f632e7d7991c072d2479540d478
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Thu Mar 31 13:23:37 2022 -0400
Preparations for Traits (#265)
---
karavan-core/src/core/model/TraitDefinition.ts | 105 ++++++++++++++++++++
karavan-designer/src/App.tsx | 25 ++++-
.../src/designer/beans/BeansDesigner.tsx | 2 -
karavan-designer/src/designer/traits/TraitCard.tsx | 40 +++++---
.../src/designer/traits/TraitProperties.tsx | 108 ++++++++++-----------
.../src/designer/traits/TraitsDesigner.tsx | 100 +++++++++++--------
karavan-designer/src/designer/utils/CamelUi.ts | 7 ++
.../generator/TraitDefinitionGenerator.java | 10 ++
.../src/main/resources/TraitDefinition.header.ts | 29 ++++++
9 files changed, 313 insertions(+), 113 deletions(-)
diff --git a/karavan-core/src/core/model/TraitDefinition.ts
b/karavan-core/src/core/model/TraitDefinition.ts
index 906fbb6..73a39db 100644
--- a/karavan-core/src/core/model/TraitDefinition.ts
+++ b/karavan-core/src/core/model/TraitDefinition.ts
@@ -3,6 +3,35 @@
*/
import {CamelElement} from "./IntegrationDefinition";
+export class TraitPropertyMeta {
+ name: string
+ type: string
+ description: string
+
+ constructor(name: string, type: string, description: string) {
+ this.name = name;
+ this.type = type;
+ this.description = description;
+ }
+}
+
+export class TraitMeta {
+ name: string
+ platform: boolean
+ profiles: string
+ description: string
+ properties: TraitPropertyMeta[]
+
+
+ constructor(name: string, platform:boolean, profiles: string, description:
string, properties: TraitPropertyMeta[]) {
+ this.name = name;
+ this.platform = platform;
+ this.profiles = profiles;
+ this.description = description;
+ this.properties = properties;
+ }
+}
+
export class Trait extends CamelElement {
affinity?: AffinityTrait;
builder?: BuilderTrait;
@@ -596,3 +625,79 @@ export class TraitApi {
}
}
+export const CamelTraitMetadata: TraitMeta[] = [ new TraitMeta("affinity",
false, "Kubernetes, Knative, OpenShift", "Allows constraining which nodes the
integration pod(s) are eligible to be scheduled on, based on labels on the
node, or with inter-pod affinity and anti-affinity, based on labels on pods
that are already running on the nodes. It's disabled by default.", [
+ ]),
+ new TraitMeta("builder", false, "Kubernetes, Knative, OpenShift", "The
builder trait is internally used to determine the best strategy to build and
configure IntegrationKits.", [
+ ]),
+ new TraitMeta("camel", false, "Kubernetes, Knative, OpenShift", "The Camel
trait can be used to configure versions of Apache Camel K runtime and related
libraries, it cannot be disabled.", [
+ ]),
+ new TraitMeta("container", false, "Kubernetes, Knative, OpenShift", "The
Container trait can be used to configure properties of the container where the
integration will run. It also provides configuration for Services associated to
the container.", [
+ ]),
+ new TraitMeta("cron", false, "Kubernetes, Knative, OpenShift", "The Cron
trait can be used to customize the behaviour of periodic timer/cron based
integrations. While normally an integration requires a pod to be always up and
running, some periodic tasks, such as batch jobs, require to be activated at
specific hours of the day or with a periodic delay of minutes. For such tasks,
the cron trait can materialize the integration as a Kubernetes CronJob instead
of a standard deployment, i [...]
+ ]),
+ new TraitMeta("dependencies", false, "Kubernetes, Knative, OpenShift",
"The Dependencies trait is internally used to automatically add runtime
dependencies based on the integration that the user wants to run.", [
+ ]),
+ new TraitMeta("deployer", false, "Kubernetes, Knative, OpenShift", "The
deployer trait is responsible for deploying the resources owned by the
integration, and can be used to explicitly select the underlying controller
that will manage the integration pods.", [
+ ]),
+ new TraitMeta("deployment", false, "Kubernetes, Knative, OpenShift", "The
Deployment trait is responsible for generating the Kubernetes deployment that
will make sure the integration will run in the cluster.", [
+ ]),
+ new TraitMeta("environment", false, "Kubernetes, Knative, OpenShift", "The
environment trait is used internally to inject standard environment variables
in the integration container, such as `NAMESPACE`, `POD_NAME` and others.", [
+ ]),
+ new TraitMeta("error-handler", false, "Kubernetes, Knative, OpenShift",
"The error-handler is a platform trait used to inject Error Handler source into
the integration runtime.", [
+ ]),
+ new TraitMeta("gc", false, "Kubernetes, Knative, OpenShift", "The GC Trait
garbage-collects all resources that are no longer necessary upon integration
updates.", [
+ ]),
+ new TraitMeta("health", false, "Kubernetes, Knative, OpenShift", "The
health trait is responsible for configuring the health probes on the
integration container. It's disabled by default.", [
+ ]),
+ new TraitMeta("ingress", false, "Kubernetes", "The Ingress trait can be
used to expose the service associated with the integration to the outside world
with a Kubernetes Ingress. It's enabled by default whenever a Service is added
to the integration (through the `service` trait).", [
+ ]),
+ new TraitMeta("istio", false, "Kubernetes, Knative, OpenShift", "The Istio
trait allows configuring properties related to the Istio service mesh, such as
sidecar injection and outbound IP ranges.", [
+ ]),
+ new TraitMeta("jolokia", false, "Kubernetes, Knative, OpenShift", "The
Jolokia trait activates and configures the Jolokia Java agent. See
https://jolokia.org/reference/html/agents.html", [
+ ]),
+ new TraitMeta("jvm", false, "Kubernetes, Knative, OpenShift", "The JVM
trait is used to configure the JVM that runs the integration.", [
+ ]),
+ new TraitMeta("kamelets", false, "Kubernetes, Knative, OpenShift", "The
kamelets trait is a platform trait used to inject Kamelets into the integration
runtime.", [
+ ]),
+ new TraitMeta("keda", false, "Kubernetes, Knative, OpenShift", "The KEDA
trait can be used for automatic integration with KEDA autoscalers. The trait
can be either manually configured using the `triggers` option or automatically
configured via markers in the Kamelets. For information on how to use KEDA
enabled Kamelets with the KEDA trait, refer to
xref:ROOT:kamelets/kamelets-user.adoc#kamelet-keda-user[the KEDA section in the
Kamelets user guide]. If you want to create Kamelets that [...]
+ ]),
+ new TraitMeta("knative-service", false, "Knative", "The Knative Service
trait allows configuring options when running the Integration as a Knative
service, instead of a standard Kubernetes Deployment. Running an Integration as
a Knative Service enables auto-scaling (and scaling-to-zero), but those
features are only relevant when the Camel route(s) use(s) an HTTP endpoint
consumer.", [
+ ]),
+ new TraitMeta("knative", false, "Knative", "The Knative trait
automatically discovers addresses of Knative resources and inject them into the
running integration. The full Knative configuration is injected in the
CAMEL_KNATIVE_CONFIGURATION in JSON format. The Camel Knative component will
then use the full configuration to configure the routes. The trait is enabled
by default when the Knative profile is active.", [
+ ]),
+ new TraitMeta("logging", false, "Kubernetes, Knative, OpenShift", "The
Logging trait is used to configure Integration runtime logging options (such as
color and format). The logging backend is provided by Quarkus, whose
configuration is documented at https://quarkus.io/guides/logging.", [
+ ]),
+ new TraitMeta("master", false, "Kubernetes, Knative, OpenShift", "The
Master trait allows to configure the integration to automatically leverage
Kubernetes resources for doing leader election and starting *master* routes
only on certain instances. It's activated automatically when using the master
endpoint in a route, e.g. `from(\"master:lockname:telegram:bots\")...`. NOTE:
this trait adds special permissions to the integration service account in order
to read/write configmaps and re [...]
+ ]),
+ new TraitMeta("mount", false, "Kubernetes, Knative, OpenShift", "The Mount
trait can be used to configure volumes mounted on the Integration Pods.", [
+ ]),
+ new TraitMeta("openapi", false, "Kubernetes, Knative, OpenShift", "The
OpenAPI DSL trait is internally used to allow creating integrations from a
OpenAPI specs.", [
+ ]),
+ new TraitMeta("owner", false, "Kubernetes, Knative, OpenShift", "The Owner
trait ensures that all created resources belong to the integration being
created and transfers annotations and labels on the integration onto these
owned resources.", [
+ ]),
+ new TraitMeta("pdb", false, "Kubernetes, Knative, OpenShift", "The PDB
trait allows to configure the PodDisruptionBudget resource for the Integration
pods.", [
+ ]),
+ new TraitMeta("platform", false, "Kubernetes, Knative, OpenShift", "The
platform trait is a base trait that is used to assign an integration platform
to an integration. In case the platform is missing, the trait is allowed to
create a default platform. This feature is especially useful in contexts where
there's no need to provide a custom configuration for the platform (e.g. on
OpenShift the default settings work, since there's an embedded container image
registry).", [
+ ]),
+ new TraitMeta("pod", false, "Kubernetes, Knative, OpenShift", "The pod
trait allows the customization of the Integration pods. It applies the
`PodSpecTemplate` struct contained in the Integration `.spec.podTemplate`
field, into the Integration deployment Pods template, using strategic merge
patch. This can be used to customize the container where Camel routes execute,
by using the `integration` container name.", [
+ ]),
+ new TraitMeta("prometheus", false, "Kubernetes, Knative, OpenShift", "The
Prometheus trait configures a Prometheus-compatible endpoint. It also creates a
`PodMonitor` resource, so that the endpoint can be scraped automatically, when
using the Prometheus operator. The metrics are exposed using MicroProfile
Metrics. WARNING: The creation of the `PodMonitor` resource requires the
https://github.com/coreos/prometheus-operator[Prometheus Operator] custom
resource definition to be installe [...]
+ ]),
+ new TraitMeta("pull-secret", false, "Kubernetes, Knative, OpenShift", "The
Pull Secret trait sets a pull secret on the pod, to allow Kubernetes to
retrieve the container image from an external registry. The pull secret can be
specified manually or, in case you've configured authentication for an external
container registry on the `IntegrationPlatform`, the same secret is used to
pull images. It's enabled by default whenever you configure authentication for
an external container regis [...]
+ ]),
+ new TraitMeta("quarkus", false, "Kubernetes, Knative, OpenShift", "The
Quarkus trait configures the Quarkus runtime. It's enabled by default. NOTE:
Compiling to a native executable, i.e. when using `package-type=native`, is
only supported for kamelets, as well as YAML and XML integrations. It also
requires at least 4GiB of memory, so the Pod running the native build, that is
either the operator Pod, or the build Pod (depending on the build strategy
configured for the platform), must [...]
+ ]),
+ new TraitMeta("route", false, "OpenShift", "The Route trait can be used to
configure the creation of OpenShift routes for the integration. The certificate
and key contents may be sourced either from the local filesystem or in a
Openshift `secret` object. The user may use the parameters ending in `-secret`
(example: `tls-certificate-secret`) to reference a certificate stored in a
`secret`. Parameters ending in `-secret` have higher priorities and in case the
same route parameter is se [...]
+ ]),
+ new TraitMeta("service-binding", false, "Kubernetes, Knative, OpenShift",
"The Service Binding trait allows users to connect to Services in Kubernetes:
https://github.com/k8s-service-bindings/spec#service-binding As the
specification is still evolving this is subject to change", [
+ ]),
+ new TraitMeta("service", false, "Kubernetes, OpenShift", "The Service
trait exposes the integration with a Service resource so that it can be
accessed by other applications (or integrations) in the same namespace. It's
enabled by default if the integration depends on a Camel component that can
expose a HTTP endpoint.", [
+ ]),
+ new TraitMeta("3scale", false, "Kubernetes, Knative, OpenShift", "The
3scale trait can be used to automatically create annotations that allow 3scale
to discover the generated service and make it available for API management. The
3scale trait is disabled by default.", [
+ ]),
+ new TraitMeta("toleration", false, "Kubernetes, Knative, OpenShift", "This
trait sets Tolerations over Integration pods. Tolerations allow (but do not
require) the pods to schedule onto nodes with matching taints. See
https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
for more details. The toleration should be expressed in a similar manner that
of taints, i.e., `Key[=Value]:Effect[:Seconds]`, where values in square
brackets are optional. For examples: - `no [...]
+ ]),
+ new TraitMeta("tracing", false, "Kubernetes, Knative, OpenShift", "The
Tracing trait can be used to automatically publish tracing information to an
OpenTracing compatible collector. The trait is able to automatically discover
the tracing endpoint available in the namespace (supports **Jaeger**). The
Tracing trait is disabled by default.", [
+ ]),
+]
+
diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index 35f5a3a..ab3b931 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -53,7 +53,30 @@ class App extends React.Component<Props, State> {
' parameters:\n' +
' topic: topic1\n' +
' id: post\n' +
- ''
+ ' traits:\n' +
+ ' camel:\n' +
+ ' configuration:\n' +
+ ' runtimeVersion: 3.16.0\n' +
+ ' properties:\n' +
+ ' - camel.component.seda.queueSize = 10\n' +
+ ' - camel.component.seda.enabled = false\n' +
+ ' jvm:\n' +
+ ' configuration:\n' +
+ ' debug: true\n' +
+ ' options:\n' +
+ ' - option1\n' +
+ ' - option2\n' +
+ ' classpath:
/path/to/my-dependency.jar:/path/to/another-dependency.jar\n' +
+ ' threeScale:\n' +
+ ' configuration:\n' +
+ ' enabled: true\n' +
+ ' auto: true\n' +
+ ' path: /\n' +
+ ' 3scale:\n' +
+ ' configuration:\n' +
+ ' enabled: true\n' +
+ ' auto: true\n' +
+ ' path: / \n'
};
componentDidMount() {
diff --git a/karavan-designer/src/designer/beans/BeansDesigner.tsx
b/karavan-designer/src/designer/beans/BeansDesigner.tsx
index b61e8f6..d48ea68 100644
--- a/karavan-designer/src/designer/beans/BeansDesigner.tsx
+++ b/karavan-designer/src/designer/beans/BeansDesigner.tsx
@@ -39,7 +39,6 @@ interface State {
showDeleteConfirmation: boolean
selectedBean?: NamedBeanDefinition
key: string
- showBeanEditor: boolean
propertyOnly: boolean
}
@@ -49,7 +48,6 @@ export class BeansDesigner extends React.Component<Props,
State> {
integration: this.props.integration,
showDeleteConfirmation: false,
key: "",
- showBeanEditor: false,
propertyOnly: false
};
diff --git a/karavan-designer/src/designer/traits/TraitCard.tsx
b/karavan-designer/src/designer/traits/TraitCard.tsx
index 3ba38a8..20e3a47 100644
--- a/karavan-designer/src/designer/traits/TraitCard.tsx
+++ b/karavan-designer/src/designer/traits/TraitCard.tsx
@@ -19,45 +19,55 @@ import {
Button
} from '@patternfly/react-core';
import '../karavan.css';
-import {Integration} from "karavan-core/lib/model/IntegrationDefinition";
-import {NamedBeanDefinition} from "karavan-core/lib/model/CamelDefinition";
+import {CamelElement, Integration} from
"karavan-core/lib/model/IntegrationDefinition";
import DeleteIcon from
"@patternfly/react-icons/dist/js/icons/times-circle-icon";
interface Props {
- bean: NamedBeanDefinition
- selectedStep?: NamedBeanDefinition
+ trait: CamelElement
+ selectedTrait?: CamelElement
integration: Integration
- selectElement: (element: NamedBeanDefinition) => void
- deleteElement: (element: NamedBeanDefinition) => void
+ // selectMethod: (element: CamelElement) => void
+ // selectElement: (element: CamelElement) => void
+ // deleteElement: (element: CamelElement) => void
}
export class TraitCard extends React.Component<Props, any> {
selectElement = (evt: React.MouseEvent) => {
evt.stopPropagation();
- this.props.selectElement.call(this, this.props.bean);
+ // this.props.selectElement.call(this, this.props.rest);
+ }
+
+ selectMethod = (evt: React.MouseEvent) => {
+ evt.stopPropagation();
+ // this.props.selectMethod.call(this, this.props.rest);
}
delete = (evt: React.MouseEvent) => {
evt.stopPropagation();
- this.props.deleteElement.call(this, this.props.bean);
+ // this.props.deleteElement.call(this, this.props.rest);
}
render() {
- const bean = this.props.bean;
+ const trait = this.props.trait;
return (
- <div className={this.props.selectedStep?.uuid === bean.uuid ?
"rest-card rest-card-selected" : "rest-card rest-card-unselected"} onClick={e
=> this.selectElement(e)}>
+ <div className={this.props.selectedTrait?.uuid === trait.uuid ?
"rest-card rest-card-selected" : "rest-card rest-card-unselected"} onClick={e
=> this.selectElement(e)}>
<div className="header">
- <div className="title">BEAN</div>
- <div className="title">{bean.name}</div>
- <div className="description">{bean.type}</div>
+ <div className="title">Trait</div>
+ <div className="title">{trait.dslName.replace("Trait",
"")}</div>
+ {/*<div
className="description">{trait.description}</div>*/}
{/*<Tooltip position={"bottom"} content={<div>Add REST
method</div>}>*/}
- {/*<Button variant={"link"} icon={<AddIcon/>}
aria-label="Add" onClick={e => this.selectMethod(e)} className="add-button">Add
method</Button>*/}
+ {/* <Button variant={"link"} icon={<AddIcon/>}
aria-label="Add" onClick={e => this.selectMethod(e)} className="add-button">Add
method</Button>*/}
{/*</Tooltip>*/}
<Button variant="link" className="delete-button"
onClick={e => this.delete(e)}><DeleteIcon/></Button>
</div>
<div className="rest-content" key={Math.random().toString()}>
-
+ {/*{trait.get?.map(get => <RestMethodCard key={get.uuid}
method={get} selectedStep={this.props.selectedStep}
integration={this.props.integration} selectElement={this.props.selectElement}
deleteElement={this.props.deleteElement}/>)}*/}
+ {/*{trait.post?.map(post => <RestMethodCard
key={post.uuid} method={post} selectedStep={this.props.selectedStep}
integration={this.props.integration} selectElement={this.props.selectElement}
deleteElement={this.props.deleteElement}/>)}*/}
+ {/*{trait.put?.map(put => <RestMethodCard key={put.uuid}
method={put} selectedStep={this.props.selectedStep}
integration={this.props.integration} selectElement={this.props.selectElement}
deleteElement={this.props.deleteElement}/>)}*/}
+ {/*{trait.patch?.map(patch => <RestMethodCard
key={patch.uuid} method={patch} selectedStep={this.props.selectedStep}
integration={this.props.integration} selectElement={this.props.selectElement}
deleteElement={this.props.deleteElement}/>)}*/}
+ {/*{trait.delete?.map(del => <RestMethodCard
key={del.uuid} method={del} selectedStep={this.props.selectedStep}
integration={this.props.integration} selectElement={this.props.selectElement}
deleteElement={this.props.deleteElement}/>)}*/}
+ {/*{trait.head?.map(head => <RestMethodCard
key={head.uuid} method={head} selectedStep={this.props.selectedStep}
integration={this.props.integration} selectElement={this.props.selectElement}
deleteElement={this.props.deleteElement}/>)}*/}
</div>
</div>
);
diff --git a/karavan-designer/src/designer/traits/TraitProperties.tsx
b/karavan-designer/src/designer/traits/TraitProperties.tsx
index 9852744..dc3effd 100644
--- a/karavan-designer/src/designer/traits/TraitProperties.tsx
+++ b/karavan-designer/src/designer/traits/TraitProperties.tsx
@@ -25,7 +25,7 @@ import "@patternfly/patternfly/patternfly.css";
import {
NamedBeanDefinition,
} from "karavan-core/lib/model/CamelDefinition";
-import {Integration} from "karavan-core/lib/model/IntegrationDefinition";
+import {CamelElement, Integration} from
"karavan-core/lib/model/IntegrationDefinition";
import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
import {v4 as uuidv4} from "uuid";
import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon";
@@ -34,14 +34,14 @@ import {IntegrationHeader} from
"../utils/KaravanComponents";
interface Props {
integration: Integration
- bean?: NamedBeanDefinition
+ trait?: CamelElement
dark: boolean
- onChange: (bean: NamedBeanDefinition) => void
+ onChange: (trait: CamelElement) => void
}
interface State {
- bean?: NamedBeanDefinition
- properties: Map<string, [string, string]>
+ trait?: CamelElement
+ // properties: Map<string, [string, string]>
key: string
}
@@ -54,91 +54,91 @@ export class TraitProperties extends React.Component<Props,
State> {
}
public state: State = {
- bean: this.props.bean,
+ trait: this.props.trait,
key: '',
- properties: this.props.bean?.properties ?
this.preparePropertiesMap(this.props.bean?.properties) : new Map<string,
[string, string]>()
+ // properties: this.props.trait?.properties ?
this.preparePropertiesMap(this.props.trait?.properties) : new Map<string,
[string, string]>()
};
componentDidUpdate = (prevProps: Readonly<Props>, prevState:
Readonly<State>, snapshot?: any) => {
- if (prevProps.bean?.uuid !== this.props.bean?.uuid) {
- this.setBean(this.props.bean);
- }
- if (prevState.key !== this.state.key && this.state.bean) {
- const bean = CamelUtil.cloneBean(this.state.bean);
- const properties: any = {};
- this.state.properties.forEach(p => properties[p[0]] = p[1]);
- bean.properties = properties;
- this.setState({bean: bean});
- this.props.onChange?.call(this, bean);
+ if (prevProps.trait?.uuid !== this.props.trait?.uuid) {
+ // this.setBean(this.props.trait);
}
+ // if (prevState.key !== this.state.key && this.state.bean) {
+ // const bean = CamelUtil.cloneBean(this.state.bean);
+ // const properties: any = {};
+ // this.state.properties.forEach(p => properties[p[0]] = p[1]);
+ // bean.properties = properties;
+ // this.setState({bean: bean});
+ // this.props.onChange?.call(this, bean);
+ // }
}
- setBean = (bean?: NamedBeanDefinition) => {
+ setBean = (trait?: CamelElement) => {
this.setState({
- bean: bean,
- properties: bean?.properties ?
this.preparePropertiesMap(bean.properties) : new Map<string, [string, string]>()
+ trait: trait,
+ // properties: bean?.properties ?
this.preparePropertiesMap(bean.properties) : new Map<string, [string, string]>()
});
}
beanChanged = (fieldId: string, value: string) => {
- if (this.state.bean) {
- const bean = CamelUtil.cloneBean(this.state.bean);
- (bean as any)[fieldId] = value;
- this.setState({bean: bean});
- this.props.onChange?.call(this, bean);
- }
+ // if (this.state.bean) {
+ // const bean = CamelUtil.cloneBean(this.state.bean);
+ // (bean as any)[fieldId] = value;
+ // this.setState({bean: bean});
+ // this.props.onChange?.call(this, bean);
+ // }
}
propertyChanged = (uuid: string, key: string, value: string) => {
- this.setState(state => {
- state.properties.set(uuid, [key, value]);
- return {properties: state.properties, key:
Math.random().toString()};
- })
+ // this.setState(state => {
+ // state.properties.set(uuid, [key, value]);
+ // return {properties: state.properties, key:
Math.random().toString()};
+ // })
}
propertyDeleted = (uuid: string) => {
this.setState(state => {
- state.properties.delete(uuid);
- return {properties: state.properties, key:
Math.random().toString()};
+ // state.properties.delete(uuid);
+ // return {properties: state.properties, key:
Math.random().toString()};
})
}
getBeanForm() {
- const bean = this.state.bean;
+ const trait = this.state.trait;
return (
<>
<FormGroup label="Name" fieldId="name" isRequired>
- <TextInput className="text-field" isRequired type="text"
id="name" name="name" value={bean?.name}
- onChange={e => this.beanChanged("name", e)}/>
+ {/*<TextInput className="text-field" isRequired
type="text" id="name" name="name" value={trait?.name}*/}
+ {/* onChange={e => this.beanChanged("name",
e)}/>*/}
</FormGroup>
<FormGroup label="Type" fieldId="type" isRequired>
- <TextInput className="text-field" isRequired type="text"
id="type" name="type" value={bean?.type} onChange={e =>
this.beanChanged("type", e)}/>
- </FormGroup>
- <FormGroup label="Properties" fieldId="properties"
className="bean-properties">
- {Array.from(this.state.properties.entries()).map((v,
index, array) => {
- const i = v[0];
- const key = v[1][0];
- const value = v[1][1];
- return (
- <div key={"key-" + i} className="bean-property">
- <TextInput className="text-field" isRequired
type="text" id="key" name="key" value={key} onChange={e =>
this.propertyChanged(i, e, value)}/>
- <TextInput className="text-field" isRequired
type="text" id="value" name="value" value={value} onChange={e =>
this.propertyChanged(i, key, e)}/>
- <Button variant="link"
className="delete-button" onClick={e =>
this.propertyDeleted(i)}><DeleteIcon/></Button>
- </div>
- )
- })}
- <Button variant="link" className="add-button" onClick={e
=> this.propertyChanged(uuidv4(), '', '')}><AddIcon/>Add property</Button>
+ {/*<TextInput className="text-field" isRequired
type="text" id="type" name="type" value={bean?.type} onChange={e =>
this.beanChanged("type", e)}/>*/}
</FormGroup>
+ {/*<FormGroup label="Properties" fieldId="properties"
className="bean-properties">*/}
+ {/* {Array.from(this.state.properties.entries()).map((v,
index, array) => {*/}
+ {/* const i = v[0];*/}
+ {/* const key = v[1][0];*/}
+ {/* const value = v[1][1];*/}
+ {/* return (*/}
+ {/* <div key={"key-" + i}
className="bean-property">*/}
+ {/* <TextInput className="text-field"
isRequired type="text" id="key" name="key" value={key} onChange={e =>
this.propertyChanged(i, e, value)}/>*/}
+ {/* <TextInput className="text-field"
isRequired type="text" id="value" name="value" value={value} onChange={e =>
this.propertyChanged(i, key, e)}/>*/}
+ {/* <Button variant="link"
className="delete-button" onClick={e =>
this.propertyDeleted(i)}><DeleteIcon/></Button>*/}
+ {/* </div>*/}
+ {/* )*/}
+ {/* })}*/}
+ {/* <Button variant="link" className="add-button"
onClick={e => this.propertyChanged(uuidv4(), '', '')}><AddIcon/>Add
property</Button>*/}
+ {/*</FormGroup>*/}
</>
)
}
render() {
return (
- <div className='properties' key={this.state.bean ?
this.state.bean.uuid : 'integration'}>
+ <div className='properties' key={this.state.trait ?
this.state.trait.uuid : 'integration'}>
<Form autoComplete="off" onSubmit={event =>
event.preventDefault()}>
- {this.state.bean === undefined && <IntegrationHeader
integration={this.props.integration}/>}
- {this.state.bean !== undefined && this.getBeanForm()}
+ {this.state.trait === undefined && <IntegrationHeader
integration={this.props.integration}/>}
+ {this.state.trait !== undefined && this.getBeanForm()}
</Form>
</div>
)
diff --git a/karavan-designer/src/designer/traits/TraitsDesigner.tsx
b/karavan-designer/src/designer/traits/TraitsDesigner.tsx
index 056da09..f06df3a 100644
--- a/karavan-designer/src/designer/traits/TraitsDesigner.tsx
+++ b/karavan-designer/src/designer/traits/TraitsDesigner.tsx
@@ -16,7 +16,7 @@
*/
import React from 'react';
import {
- Button, EmptyState, EmptyStateBody, EmptyStateIcon, Modal, PageSection,
Title
+ Button, Drawer, DrawerContent, DrawerContentBody, DrawerPanelContent,
EmptyState, EmptyStateBody, EmptyStateIcon, Modal, PageSection, Title
} from '@patternfly/react-core';
import '../karavan.css';
import {NamedBeanDefinition} from "karavan-core/lib/model/CamelDefinition";
@@ -28,6 +28,8 @@ import {TraitProperties} from "./TraitProperties";
import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
import {TraitCard} from "./TraitCard";
import CubesIcon from "@patternfly/react-icons/dist/esm/icons/cubes-icon";
+import {CamelElement} from
"../../../../karavan-core/src/core/model/IntegrationDefinition";
+import {DslProperties} from "../route/DslProperties";
interface Props {
onSave?: (integration: Integration, propertyOnly: boolean) => void
@@ -38,7 +40,7 @@ interface Props {
interface State {
integration: Integration
showDeleteConfirmation: boolean
- selectedBean?: NamedBeanDefinition
+ selectedTrait?: CamelElement
key: string
showBeanEditor: boolean
propertyOnly: boolean
@@ -60,8 +62,8 @@ export class TraitsDesigner extends React.Component<Props,
State> {
}
}
- showDeleteConfirmation = (bean: NamedBeanDefinition) => {
- this.setState({selectedBean: bean, showDeleteConfirmation: true});
+ showDeleteConfirmation = (trait: CamelElement) => {
+ this.setState({selectedTrait: trait, showDeleteConfirmation: true});
}
onIntegrationUpdate = (i: Integration) => {
@@ -69,19 +71,19 @@ export class TraitsDesigner extends React.Component<Props,
State> {
}
deleteBean = () => {
- const i =
CamelDefinitionApiExt.deleteBeanFromIntegration(this.state.integration,
this.state.selectedBean);
- this.setState({
- integration: i,
- showDeleteConfirmation: false,
- key: Math.random().toString(),
- selectedBean: new NamedBeanDefinition()
- });
+ // const i =
CamelDefinitionApiExt.deleteTraitFromIntegration(this.state.integration,
this.state.selectedTrait);
+ // this.setState({
+ // integration: i,
+ // showDeleteConfirmation: false,
+ // key: Math.random().toString(),
+ // selectedBean: new NamedBeanDefinition()
+ // });
}
- changeBean = (bean: NamedBeanDefinition) => {
- const clone = CamelUtil.cloneIntegration(this.state.integration);
- const i = CamelDefinitionApiExt.addBeanToIntegration(clone, bean);
- this.setState({integration: i, key: Math.random().toString(),
selectedBean: bean});
+ changeTrait = (trait: CamelElement) => {
+ // const clone = CamelUtil.cloneIntegration(this.state.integration);
+ // const i = CamelDefinitionApiExt.addBeanToIntegration(clone, bean);
+ // this.setState({integration: i, key: Math.random().toString(),
selectedBean: bean});
}
getDeleteConfirmation() {
@@ -103,25 +105,38 @@ export class TraitsDesigner extends
React.Component<Props, State> {
}
selectBean = (bean?: NamedBeanDefinition) => {
- this.setState({selectedBean: bean})
+ // this.setState({selectedBean: bean})
}
unselectBean = (evt: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
if ((evt.target as any).dataset.click === 'BEANS') {
evt.stopPropagation()
- this.setState({selectedBean: undefined})
+ // this.setState({selectedBean: undefined})
}
};
createBean = () => {
- this.changeBean(new NamedBeanDefinition());
+ this.changeTrait(new NamedBeanDefinition());
+ }
+
+ getPropertiesPanel() {
+ return (
+ <DrawerPanelContent isResizable hasNoBorder defaultSize={'400px'}
maxSize={'800px'} minSize={'300px'}>
+ <TraitProperties integration={this.props.integration}
+ trait={this.state.selectedTrait}
+ dark={this.props.dark}
+ onChange={this.changeTrait}/>
+ </DrawerPanelContent>
+ )
}
render() {
- const beans = CamelUi.getBeans(this.state.integration);
+ const traits = CamelUi.getBeans(this.state.integration);
return (
<PageSection className="exception-page" isFilled
padding={{default: 'noPadding'}}>
<div className="exception-page-columns">
+ {/*<PageSection className="rest-page" isFilled padding={{default:
'noPadding'}}>*/}
+ {/* <div className="rest-page-columns">*/}
<EmptyState>
<EmptyStateIcon icon={CubesIcon} />
<Title headingLevel="h4" size="lg">
@@ -131,28 +146,31 @@ export class TraitsDesigner extends
React.Component<Props, State> {
Traits not implemented yet
</EmptyStateBody>
</EmptyState>
- {/*<div className="graph" data-click="REST"
onClick={event => this.unselectBean(event)}>*/}
- {/* <div className="flows">*/}
- {/* {beans?.map(bean => <TraitCard key={bean.uuid +
this.state.key}*/}
- {/*
selectedStep={this.state.selectedBean}*/}
- {/* bean={bean}*/}
- {/*
integration={this.props.integration}*/}
- {/*
selectElement={this.selectBean}*/}
- {/*
deleteElement={this.showDeleteConfirmation}/>)}*/}
- {/* <div className="add-rest">*/}
- {/* <Button*/}
- {/* variant={beans?.length === 0 ?
"primary" : "secondary"}*/}
- {/* data-click="ADD_TRAIT"*/}
- {/* icon={<PlusIcon/>}*/}
- {/* onClick={e => this.createBean()}>Create
new bean*/}
- {/* </Button>*/}
- {/* </div>*/}
- {/* </div>*/}
- {/*</div>*/}
- {/*<TraitProperties integration={this.props.integration}*/}
- {/* bean={this.state.selectedBean}*/}
- {/* dark={this.props.dark}*/}
- {/* onChange={this.changeBean}/>*/}
+ {/*<Drawer isExpanded isInline>*/}
+ {/* <DrawerContent
panelContent={this.getPropertiesPanel()}>*/}
+ {/* <DrawerContentBody>*/}
+ {/* <div className="graph" data-click="REST"
onClick={event => this.unselectBean(event)}>*/}
+ {/* <div className="flows">*/}
+ {/* {traits?.map(trait => <TraitCard
key={trait.uuid + this.state.key}*/}
+ {/*
selectedTrait={this.state.selectedTrait}*/}
+ {/*
integration={this.props.integration}*/}
+ {/*
trait={trait}*/}
+ {/* //
selectElement={this.selectBean}*/}
+ {/* //
deleteElement={this.showDeleteConfirmation}*/}
+ {/* />)}*/}
+ {/* <div className="add-rest">*/}
+ {/* <Button*/}
+ {/* variant={traits?.length ===
0 ? "primary" : "secondary"}*/}
+ {/* data-click="ADD_TRAIT"*/}
+ {/* icon={<PlusIcon/>}*/}
+ {/* onClick={e =>
this.createBean()}>Create new trait*/}
+ {/* </Button>*/}
+ {/* </div>*/}
+ {/* </div>*/}
+ {/* </div>*/}
+ {/* </DrawerContentBody>*/}
+ {/* </DrawerContent>*/}
+ {/*</Drawer>*/}
</div>
{this.getDeleteConfirmation()}
</PageSection>
diff --git a/karavan-designer/src/designer/utils/CamelUi.ts
b/karavan-designer/src/designer/utils/CamelUi.ts
index 7d919df..04c20ce 100644
--- a/karavan-designer/src/designer/utils/CamelUi.ts
+++ b/karavan-designer/src/designer/utils/CamelUi.ts
@@ -24,6 +24,7 @@ import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
import {CamelDefinitionApiExt} from
"karavan-core/lib/api/CamelDefinitionApiExt";
import {KameletDefinition, NamedBeanDefinition, RouteDefinition,
SagaDefinition, ToDefinition} from "karavan-core/lib/model/CamelDefinition";
import {CamelElement, Dependency, Integration} from
"karavan-core/lib/model/IntegrationDefinition";
+import {Trait} from "../../../../karavan-core/src/core/model/TraitDefinition";
const StepElements: string[] = [
"AggregateDefinition",
@@ -465,6 +466,7 @@ export class CamelUi {
const result = new Map<string, number>();
result.set('routes', i.spec.flows?.filter((e: any) => e.dslName ===
'RouteDefinition').length || 0);
result.set('rest', i.spec.flows?.filter((e: any) => e.dslName ===
'RestDefinition').length || 0);
+ result.set('traits', this.getTraitCounts(i.spec.traits));
const beans = i.spec.flows?.filter((e: any) => e.dslName === 'Beans');
if (beans && beans.length > 0 && beans[0].beans &&
beans[0].beans.length > 0){
result.set('beans', Array.from(beans[0].beans).length);
@@ -475,6 +477,11 @@ export class CamelUi {
return result;
}
+ static getTraitCounts = (t?: Trait): number => {
+ if (t) return Object.getOwnPropertyNames(t).filter(name => name !==
'dslName' && name !== "uuid" && (t as any)[name]).length;
+ return 0;
+ }
+
static getRoutes = (integration: Integration): CamelElement[] => {
const result: CamelElement[] = [];
integration.spec.flows?.filter((e: any) => e.dslName ===
'RouteDefinition')
diff --git
a/karavan-generator/src/main/java/org/apache/camel/karavan/generator/TraitDefinitionGenerator.java
b/karavan-generator/src/main/java/org/apache/camel/karavan/generator/TraitDefinitionGenerator.java
index 5da1695..a9e0c6a 100644
---
a/karavan-generator/src/main/java/org/apache/camel/karavan/generator/TraitDefinitionGenerator.java
+++
b/karavan-generator/src/main/java/org/apache/camel/karavan/generator/TraitDefinitionGenerator.java
@@ -96,6 +96,16 @@ public final class TraitDefinitionGenerator extends
AbstractGenerator {
" return traits;\n" +
" }\n" +
"}\n\n");
+
+ // Generate Metadata
+ camelModel.append("export const CamelTraitMetadata: TraitMeta[] = [");
+ getTraits().forEach(trait -> {
+
+ camelModel.append(String.format(" new TraitMeta(\"%s\", %s,
\"%s\", \"%s\", [\n", trait.name, trait.platform, trait.profiles,
trait.description.replace("\"", "\\\"")));
+ camelModel.append(String.format(" ]),\n"));
+ });
+ camelModel.append("] \n\n");
+
writeFileText(targetModel, camelModel.toString());
}
diff --git a/karavan-generator/src/main/resources/TraitDefinition.header.ts
b/karavan-generator/src/main/resources/TraitDefinition.header.ts
index 3cb3775..c6470fb 100644
--- a/karavan-generator/src/main/resources/TraitDefinition.header.ts
+++ b/karavan-generator/src/main/resources/TraitDefinition.header.ts
@@ -3,3 +3,32 @@
*/
import {CamelElement} from "./IntegrationDefinition";
+export class TraitPropertyMeta {
+ name: string
+ type: string
+ description: string
+
+ constructor(name: string, type: string, description: string) {
+ this.name = name;
+ this.type = type;
+ this.description = description;
+ }
+}
+
+export class TraitMeta {
+ name: string
+ platform: boolean
+ profiles: string
+ description: string
+ properties: TraitPropertyMeta[]
+
+
+ constructor(name: string, platform:boolean, profiles: string, description:
string, properties: TraitPropertyMeta[]) {
+ this.name = name;
+ this.platform = platform;
+ this.profiles = profiles;
+ this.description = description;
+ this.properties = properties;
+ }
+}
+