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 6375aae Fix #254 (#281)
6375aae is described below
commit 6375aaedc20d75adcebede05ecd500a52d2a2ae6
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Tue Apr 5 17:55:43 2022 -0400
Fix #254 (#281)
---
karavan-core/src/core/api/CamelUtil.ts | 98 +++++++++++++++++++++-
karavan-core/src/core/api/ComponentApi.ts | 1 +
karavan-core/test/checkRequired.spec.ts | 41 +++++++++
karavan-designer/src/designer/karavan.css | 5 ++
karavan-designer/src/designer/route/DslElement.tsx | 17 +++-
.../src/designer/route/DslProperties.tsx | 2 +-
.../route/property/ComponentParameterField.tsx | 7 +-
.../designer/route/property/DslPropertyField.tsx | 6 +-
karavan-designer/src/designer/utils/CamelUi.ts | 66 ++-------------
9 files changed, 179 insertions(+), 64 deletions(-)
diff --git a/karavan-core/src/core/api/CamelUtil.ts
b/karavan-core/src/core/api/CamelUtil.ts
index f78edff..bf948c1 100644
--- a/karavan-core/src/core/api/CamelUtil.ts
+++ b/karavan-core/src/core/api/CamelUtil.ts
@@ -19,8 +19,14 @@ import {
CamelElement, Beans, Dependency,
} from "../model/IntegrationDefinition";
import {CamelDefinitionApi} from "./CamelDefinitionApi";
-import {NamedBeanDefinition} from "../model/CamelDefinition";
+import {KameletDefinition, NamedBeanDefinition, ToDefinition} from
"../model/CamelDefinition";
import {TraitApi} from "../model/TraitDefinition";
+import {KameletApi} from "./KameletApi";
+import {KameletModel, Property} from "../model/KameletModels";
+import {ComponentProperty} from "../model/ComponentModels";
+import {ComponentApi} from "./ComponentApi";
+import {CamelMetadataApi} from "../model/CamelMetadata";
+import {CamelDefinitionApiExt} from "./CamelDefinitionApiExt";
export class CamelUtil {
@@ -117,4 +123,94 @@ export class CamelUtil {
return result;
}
}
+
+ static isKameletComponent = (element: CamelElement | undefined): boolean
=> {
+ if (element?.dslName === 'KameletDefinition') {
+ return true;
+ } else if (element && ["FromDefinition",
"ToDefinition"].includes(element.dslName)) {
+ const uri: string = (element as any).uri;
+ return uri !== undefined && uri.startsWith("kamelet:");
+ } else {
+ return false;
+ }
+ }
+
+ static getKamelet = (element: CamelElement): KameletModel | undefined => {
+ if (element.dslName === 'KameletDefinition') {
+ return KameletApi.findKameletByName((element as
KameletDefinition).name || '');
+ } else if (element.dslName === 'ToDefinition' && (element as
ToDefinition).uri?.startsWith("kamelet:")) {
+ const kameletName = (element as
ToDefinition).uri?.replace("kamelet:", "");
+ return KameletApi.findKameletByName(kameletName);
+ } else if (["FromDefinition", "FromDefinition",
"ToDefinition"].includes(element.dslName)) {
+ const uri: string = (element as any).uri;
+ const k =
+ uri !== undefined ? KameletApi.findKameletByUri(uri) :
undefined;
+ return k;
+ } else {
+ return undefined;
+ }
+ }
+
+ static getKameletProperties = (element: any): Property[] => {
+ const kamelet = this.getKamelet(element)
+ return kamelet
+ ? KameletApi.getKameletProperties(kamelet?.metadata.name)
+ : [];
+ }
+
+ static getComponentProperties = (element: any): ComponentProperty[] => {
+ const dslName: string = (element as any).dslName;
+ if (dslName === 'ToDynamicDefinition'){
+ const component = ComponentApi.findByName(dslName);
+ return component ?
ComponentApi.getComponentProperties(component?.component.name,'producer') : [];
+ } else {
+ const uri: string = (element as any).uri;
+ const name = ComponentApi.getComponentNameFromUri(uri);
+ if (name){
+ const component = ComponentApi.findByName(name);
+ return component ?
ComponentApi.getComponentProperties(component?.component.name, element.dslName
=== 'FromDefinition' ? 'consumer' : 'producer') : [];
+ } else {
+ return [];
+ }
+ }
+ }
+
+ static checkRequired = (element: CamelElement): [boolean, string []] => {
+ const result: [boolean, string []] = [true, []];
+ const className = element.dslName;
+ let elementMeta =
CamelMetadataApi.getCamelModelMetadataByClassName(className);
+ if (elementMeta === undefined && className.endsWith("Expression"))
elementMeta = CamelMetadataApi.getCamelLanguageMetadataByClassName(className);
+ elementMeta?.properties.filter(p => p.required).forEach(p => {
+ const value = (element as any)[p.name];
+ if (p.type === 'string' && (value === undefined ||
value.trim().length === 0)){
+ result[0] = false;
+ result[1].push("Property " + p.displayName + " is required");
+ } else if (p.type === 'ExpressionDefinition'){
+ const expressionMeta =
CamelMetadataApi.getCamelModelMetadataByClassName('ExpressionDefinition');
+ let expressionCheck = false;
+ expressionMeta?.properties.forEach(ep => {
+ const expValue = value[ep.name];
+ if (expValue){
+ const checkedExpression = this.checkRequired(expValue);
+ if (checkedExpression[0]) expressionCheck = true;
+ }
+ })
+ result[0] = expressionCheck;
+ if (!expressionCheck) result[1].push("Expression is not
defined");
+ }
+ })
+ if (['FromDefinition', 'ToDefinition'].includes(className)){
+ const isKamelet = this.isKameletComponent(element);
+ if (!isKamelet){
+ this.getComponentProperties(element).filter(p =>
p.required).forEach(p => {
+ const value =
CamelDefinitionApiExt.getParametersValue(element, p.name, p.kind === 'path');
+ if (value === undefined || value.trim().length === 0){
+ result[0] = false;
+ result[1].push("Property " + p.displayName + " is
required");
+ }
+ })
+ }
+ }
+ return result;
+ }
}
diff --git a/karavan-core/src/core/api/ComponentApi.ts
b/karavan-core/src/core/api/ComponentApi.ts
index 269a1a7..8cc9e69 100644
--- a/karavan-core/src/core/api/ComponentApi.ts
+++ b/karavan-core/src/core/api/ComponentApi.ts
@@ -196,6 +196,7 @@ export const ComponentApi = {
prop.secret = value.secret;
prop.enum = value.enum;
prop.kind = value.kind;
+ prop.required = value.required;
if (value.defaultValue) prop.defaultValue =
value.defaultValue
if (!value.deprecated) properties.push(prop);
})
diff --git a/karavan-core/test/checkRequired.spec.ts
b/karavan-core/test/checkRequired.spec.ts
new file mode 100644
index 0000000..cdd7cb6
--- /dev/null
+++ b/karavan-core/test/checkRequired.spec.ts
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {expect} from 'chai';
+import 'mocha';
+import {
+ LogDefinition, ExpressionDefinition, SplitDefinition, SimpleExpression
+} from "../src/core/model/CamelDefinition";
+import {CamelDefinitionApi} from "../src/core/api/CamelDefinitionApi";
+import {CamelUtil} from "../src/core/api/CamelUtil";
+
+describe('Check required properties', () => {
+
+ it('Check DSL', () => {
+ const log: LogDefinition = CamelDefinitionApi.createLogDefinition({});
+ expect(CamelUtil.checkRequired(log)[0]).to.equal(false);
+ log.message = '${body}'
+ expect(CamelUtil.checkRequired(log)[0]).to.equal(true);
+
+ const split: SplitDefinition =
CamelDefinitionApi.createSplitDefinition({});
+ expect(CamelUtil.checkRequired(split)[0]).to.equal(false);
+ split.expression = new ExpressionDefinition({simple: new
SimpleExpression()})
+ expect(CamelUtil.checkRequired(split)[0]).to.equal(false);
+ split.expression = new ExpressionDefinition({simple: new
SimpleExpression({expression: "${body} !== null"})})
+ expect(CamelUtil.checkRequired(split)[0]).to.equal(true);
+ });
+
+});
\ No newline at end of file
diff --git a/karavan-designer/src/designer/karavan.css
b/karavan-designer/src/designer/karavan.css
index c9daa62..931297c 100644
--- a/karavan-designer/src/designer/karavan.css
+++ b/karavan-designer/src/designer/karavan.css
@@ -656,6 +656,11 @@
text-align:start;
}
+.karavan .step-element .header .header-text-required {
+ color: var(--pf-global--danger-color--100);
+ font-weight: bold;
+}
+
.karavan .step-element .header-icon {
border-color: var(--pf-global--Color--200);
border-style: solid;
diff --git a/karavan-designer/src/designer/route/DslElement.tsx
b/karavan-designer/src/designer/route/DslElement.tsx
index b51cf81..875d928 100644
--- a/karavan-designer/src/designer/route/DslElement.tsx
+++ b/karavan-designer/src/designer/route/DslElement.tsx
@@ -27,6 +27,7 @@ import {CamelUi} from "../utils/CamelUi";
import {EventBus} from "../utils/EventBus";
import {ChildElement, CamelDefinitionApiExt} from
"karavan-core/lib/api/CamelDefinitionApiExt";
import ReactDOM from "react-dom";
+import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
interface Props {
step: CamelElement,
@@ -197,7 +198,7 @@ export class DslElement extends React.Component<Props,
State> {
}
<div className={this.hasWideChildrenElement() ? "header-text"
: ""}>
{this.hasWideChildrenElement() && <div
className="spacer"/>}
- <Text className={this.hasWideChildrenElement() ? "text
text-right" : "text
text-bottom"}>{CamelUi.getElementTitle(this.state.step)}</Text>
+ {this.getHeaderTextWithTooltip(step)}
</div>
{showInsertButton && this.getInsertElementButton()}
{this.state.step.dslName !== 'FromDefinition' &&
this.getDeleteButton()}
@@ -206,6 +207,20 @@ export class DslElement extends React.Component<Props,
State> {
)
}
+ getHeaderTextWithTooltip = (step: CamelElement) => {
+ const checkRequired = CamelUtil.checkRequired(step);
+ const title = CamelUi.getElementTitle(this.state.step);
+ let className = this.hasWideChildrenElement() ? "text text-right" :
"text text-bottom";
+ if (!checkRequired[0]) className = className + " header-text-required";
+ if (checkRequired[0]) return <Text className={className}>{title}</Text>
+ else return (
+ <Tooltip position={"right"}
+ content={checkRequired[1]}>
+ <Text className={className}>{title}</Text>
+ </Tooltip>
+ )
+ }
+
getHeaderWithTooltip = (tooltip: string | undefined) => {
return (
<Tooltip position={"left"}
diff --git a/karavan-designer/src/designer/route/DslProperties.tsx
b/karavan-designer/src/designer/route/DslProperties.tsx
index d7540b5..1c5edc6 100644
--- a/karavan-designer/src/designer/route/DslProperties.tsx
+++ b/karavan-designer/src/designer/route/DslProperties.tsx
@@ -135,7 +135,7 @@ export class DslProperties extends React.Component<Props,
State> {
getRouteHeader= (): JSX.Element => {
const title = this.state.step && CamelUi.getTitle(this.state.step)
- const kamelet = this.state.step && CamelUi.getKamelet(this.state.step)
+ const kamelet = this.state.step &&
CamelUtil.getKamelet(this.state.step)
const description = this.state.step && kamelet
? kamelet.spec.definition.description
: this.state.step?.dslName ?
CamelMetadataApi.getCamelModelMetadataByClassName(this.state.step?.dslName)?.description
: title;
diff --git
a/karavan-designer/src/designer/route/property/ComponentParameterField.tsx
b/karavan-designer/src/designer/route/property/ComponentParameterField.tsx
index 6253b83..0b59bb0 100644
--- a/karavan-designer/src/designer/route/property/ComponentParameterField.tsx
+++ b/karavan-designer/src/designer/route/property/ComponentParameterField.tsx
@@ -207,7 +207,12 @@ export class ComponentParameterField extends
React.Component<Props, State> {
position={"left"}
headerContent={property.displayName}
bodyContent={property.description}
- footerContent={property.defaultValue !== undefined ?
"Default: " + property.defaultValue : undefined}>
+ footerContent={
+ <div>
+ {property.defaultValue !== undefined &&
<div>{"Default: " + property.defaultValue}</div>}
+ {property.required === true &&
<div>{property.displayName + " is required"}</div>}
+ </div>
+ }>
<button type="button" aria-label="More info"
onClick={e => e.preventDefault()}
className="pf-c-form__group-label-help">
<HelpIcon noVerticalAlign/>
diff --git a/karavan-designer/src/designer/route/property/DslPropertyField.tsx
b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
index 3de7bc8..d39ed09 100644
--- a/karavan-designer/src/designer/route/property/DslPropertyField.tsx
+++ b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
@@ -401,7 +401,7 @@ export class DslPropertyField extends
React.Component<Props, State> {
getKameletParameters = () => {
return (
<div className="parameters">
- {CamelUi.getKameletProperties(this.props.element).map(property
=>
+
{CamelUtil.getKameletProperties(this.props.element).map(property =>
<KameletPropertyField
key={property.id}
property={property}
@@ -484,7 +484,7 @@ export class DslPropertyField extends
React.Component<Props, State> {
}
getComponentParameters (property: PropertyMeta) {
- const properties = CamelUi.getComponentProperties(this.props.element);
+ const properties =
CamelUtil.getComponentProperties(this.props.element);
const propertiesMain = properties.filter(p =>
!p.label.includes("advanced") && !p.label.includes("security") &&
!p.label.includes("scheduler"));
const propertiesAdvanced = properties.filter(p =>
p.label.includes("advanced"));
const propertiesScheduler = properties.filter(p =>
p.label.includes("scheduler"));
@@ -503,7 +503,7 @@ export class DslPropertyField extends
React.Component<Props, State> {
}
render() {
- const isKamelet = CamelUi.isKameletComponent(this.props.element);
+ const isKamelet = CamelUtil.isKameletComponent(this.props.element);
const property: PropertyMeta = this.props.property;
const value = this.props.value;
return (
diff --git a/karavan-designer/src/designer/utils/CamelUi.ts
b/karavan-designer/src/designer/utils/CamelUi.ts
index 70077e4..ad02ebb 100644
--- a/karavan-designer/src/designer/utils/CamelUi.ts
+++ b/karavan-designer/src/designer/utils/CamelUi.ts
@@ -184,35 +184,8 @@ export class CamelUi {
: name;
}
- static isKameletComponent = (element: CamelElement | undefined): boolean
=> {
- if (element?.dslName === 'KameletDefinition') {
- return true;
- } else if (element && ["FromDefinition",
"ToDefinition"].includes(element.dslName)) {
- const uri: string = (element as any).uri;
- return uri !== undefined && uri.startsWith("kamelet:");
- } else {
- return false;
- }
- }
-
- static getKamelet = (element: CamelElement): KameletModel | undefined => {
- if (element.dslName === 'KameletDefinition') {
- return KameletApi.findKameletByName((element as
KameletDefinition).name || '');
- } else if (element.dslName === 'ToDefinition' && (element as
ToDefinition).uri?.startsWith("kamelet:")) {
- const kameletName = (element as
ToDefinition).uri?.replace("kamelet:", "");
- return KameletApi.findKameletByName(kameletName);
- } else if (["FromDefinition", "FromDefinition",
"ToDefinition"].includes(element.dslName)) {
- const uri: string = (element as any).uri;
- const k =
- uri !== undefined ? KameletApi.findKameletByUri(uri) :
undefined;
- return k;
- } else {
- return undefined;
- }
- }
-
static isActionKamelet = (element: CamelElement): boolean => {
- const kamelet = this.getKamelet(element);
+ const kamelet = CamelUtil.getKamelet(element);
if (kamelet) return kamelet.type() === 'action'
else return false;
}
@@ -252,30 +225,6 @@ export class CamelUi {
return result;
}
- static getKameletProperties = (element: any): Property[] => {
- const kamelet = CamelUi.getKamelet(element)
- return kamelet
- ? KameletApi.getKameletProperties(kamelet?.metadata.name)
- : [];
- }
-
- static getComponentProperties = (element: any): ComponentProperty[] => {
- const dslName: string = (element as any).dslName;
- if (dslName === 'ToDynamicDefinition'){
- const component = ComponentApi.findByName(dslName);
- return component ?
ComponentApi.getComponentProperties(component?.component.name,'producer') : [];
- } else {
- const uri: string = (element as any).uri;
- const name = ComponentApi.getComponentNameFromUri(uri);
- if (name){
- const component = ComponentApi.findByName(name);
- return component ?
ComponentApi.getComponentProperties(component?.component.name, element.dslName
=== 'FromDefinition' ? 'consumer' : 'producer') : [];
- } else {
- return [];
- }
- }
- }
-
static getElementTitle = (element: CamelElement): string => {
if (element.dslName === 'RouteDefinition') {
const routeId = (element as RouteDefinition).id
@@ -291,7 +240,7 @@ export class CamelUi {
}
static getTitle = (element: CamelElement): string => {
- const k: KameletModel | undefined = CamelUi.getKamelet(element);
+ const k: KameletModel | undefined = CamelUtil.getKamelet(element);
if (k) {
return k.title();
} else if (element.dslName === 'RouteDefinition') {
@@ -307,7 +256,7 @@ export class CamelUi {
}
static getOutgoingTitle = (element: CamelElement): string => {
- const k: KameletModel | undefined = CamelUi.getKamelet(element);
+ const k: KameletModel | undefined = CamelUtil.getKamelet(element);
if (k) {
return k.title();
} else if (element.dslName === 'RouteDefinition') {
@@ -331,7 +280,10 @@ export class CamelUi {
static isShowUriTooltip = (element: CamelElement): boolean => {
const uri: string = (element as any).uri;
- return uri !== undefined && !uri.startsWith("kamelet");
+ if (uri !== undefined && !uri.startsWith("kamelet")){
+ return ComponentApi.getComponentNameFromUri(uri) !== uri;
+ }
+ return false;
}
static getExpressionTooltip = (element: CamelElement): string => {
@@ -441,7 +393,7 @@ export class CamelUi {
}
static getIcon = (element: CamelElement): string => {
- const k: KameletModel | undefined = CamelUi.getKamelet(element);
+ const k: KameletModel | undefined = CamelUtil.getKamelet(element);
if (["FromDefinition", "KameletDefinition"].includes(element.dslName))
{
return k ? k.icon() : CamelUi.getIconForName(element.dslName);
} else if (element.dslName === "ToDefinition" && (element as
ToDefinition).uri?.startsWith("kamelet:")) {
@@ -452,7 +404,7 @@ export class CamelUi {
}
static getConnectionIcon = (element: CamelElement): string => {
- const k: KameletModel | undefined = CamelUi.getKamelet(element);
+ const k: KameletModel | undefined = CamelUtil.getKamelet(element);
if (["FromDefinition", "KameletDefinition"].includes(element.dslName))
{
return k ? k.icon() : externalIcon;
} else if (element.dslName === "ToDefinition" && (element as
ToDefinition).uri?.startsWith("kamelet:")) {