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

commit 621685f6edc3b4b7227c95704c8c15deeeed32e2
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Tue Feb 20 17:54:13 2024 -0500

    Less diagramm rendering on properties changes for #731
---
 karavan-designer/public/example/demo.camel.yaml    | 130 ++++++++++-----------
 karavan-designer/src/App.tsx                       |   2 +-
 .../property/property/ComponentPropertyField.tsx   |  94 +++++++++++----
 .../property/property/DslPropertyField.tsx         |  90 +++++++++-----
 4 files changed, 200 insertions(+), 116 deletions(-)

diff --git a/karavan-designer/public/example/demo.camel.yaml 
b/karavan-designer/public/example/demo.camel.yaml
index 28340ccf..f568f58b 100644
--- a/karavan-designer/public/example/demo.camel.yaml
+++ b/karavan-designer/public/example/demo.camel.yaml
@@ -1,68 +1,68 @@
-- route:
-    id: route-a947
-    nodePrefixId: route-a32
-    from:
-      id: from-c489
-      description: Receive Data
-      uri: kamelet:aws-ddb-streams-source
-      steps:
-        - setHeader:
-            id: setBody-4434
-            expression:
-              simple:
-                id: simple-abd8
-                expression: dddddd
-        - filter:
-            id: filter-929b
-            expression:
-              simple:
-                id: simple-d932
-                expression: Hello
-            steps:
-              - bean:
-                  id: bean-120b
-                  ref: xxx
-              - log:
-                  id: log-d86e
-                  message: ${body}!!!
-              - to:
-                  id: to-9f7d
-                  description: Send notification
-                  uri: kafka
-        - to:
-            id: to-53a3
-            description: Send payments
-            uri: amqp
-- route:
-    id: route-8609
-    nodePrefixId: route-ae2
-    from:
-      id: from-6aee
-      uri: timer
-      steps:
-        - to:
-            id: to-2df4
-            uri: direct
-            parameters:
-              name: second_direct
-        - to:
-            id: to-e017
-            uri: direct
-            parameters:
-              name: second_direct
-- route:
-    id: first-firect
-    from:
-      id: from-f155
-      uri: direct
-      parameters:
-        name: first-firect
-      steps:
-        - to:
-            id: to-5c86
-            uri: direct
-            parameters:
-              name: second_direct
+#- route:
+#    id: route-a947
+#    nodePrefixId: route-a32
+#    from:
+#      id: from-c489
+#      description: Receive Data
+#      uri: kamelet:aws-ddb-streams-source
+#      steps:
+#        - setHeader:
+#            id: setBody-4434
+#            expression:
+#              simple:
+#                id: simple-abd8
+#                expression: dddddd
+#        - filter:
+#            id: filter-929b
+#            expression:
+#              simple:
+#                id: simple-d932
+#                expression: Hello
+#            steps:
+#              - bean:
+#                  id: bean-120b
+#                  ref: xxx
+#              - log:
+#                  id: log-d86e
+#                  message: ${body}!!!
+#              - to:
+#                  id: to-9f7d
+#                  description: Send notification
+#                  uri: kafka
+#        - to:
+#            id: to-53a3
+#            description: Send payments
+#            uri: amqp
+#- route:
+#    id: route-8609
+#    nodePrefixId: route-ae2
+#    from:
+#      id: from-6aee
+#      uri: timer
+#      steps:
+#        - to:
+#            id: to-2df4
+#            uri: direct
+#            parameters:
+#              name: second_direct
+#        - to:
+#            id: to-e017
+#            uri: direct
+#            parameters:
+#              name: second_direct
+#- route:
+#    id: first-firect
+#    from:
+#      id: from-f155
+#      uri: direct
+#      parameters:
+#        name: first-firect
+#      steps:
+#        - to:
+#            id: to-5c86
+#            uri: direct
+#            parameters:
+#              name: second_direct
 - route:
     id: second_direct
     from:
diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index 331aa343..03046460 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -114,7 +114,7 @@ export function App() {
     });
 
     function save(filename: string, yaml: string, propertyOnly: boolean) {
-        // console.log(yaml);
+        console.log(yaml);
     }
 
     function getSpinner() {
diff --git 
a/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx 
b/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx
index 3798c4e4..3f13cb1e 100644
--- a/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx
+++ b/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, {useRef, useState} from 'react';
+import React, {useEffect, useRef, useState} from 'react';
 import {
     FormGroup,
     TextInput,
@@ -80,11 +80,27 @@ export function ComponentPropertyField(props: Props) {
     const [infrastructureSelector, setInfrastructureSelector] = 
useState<boolean>(false);
     const [infrastructureSelectorProperty, setInfrastructureSelectorProperty] 
= useState<string | undefined>(undefined);
     const [id, setId] = useState<string>(prefix + "-" + props.property.name);
-
+    const [textValue, setTextValue] = useState<any>();
     const ref = useRef<any>(null);
+    const [checkChanges, setCheckChanges] = useState<boolean>(false);
+
+    useEffect(()=> setTextValue(value), [])
 
+    useEffect(()=> {
+        if (checkChanges) {
+            const interval = setInterval(() => {
+                if (props.value !== textValue) {
+                    parametersChanged(property.name, textValue);
+                }
+            }, 3000);
+            return () => {
+                clearInterval(interval)
+            }
+        }
+    }, [checkChanges, textValue])
 
     function parametersChanged(parameter: string, value: string | number | 
boolean | any, pathParameter?: boolean, newRoute?: RouteToCreate) {
+        setCheckChanges(false);
         onParametersChange(parameter, value, pathParameter, newRoute);
         setSelectStatus(new Map<string, boolean>([[parameter, false]]))
     }
@@ -221,7 +237,7 @@ export function ComponentPropertyField(props: Props) {
                 onSelect={selectInfrastructure}/>)
     }
 
-    function getStringInput(property: ComponentProperty, value: any) {
+    function getStringInput(property: ComponentProperty) {
         const inInfrastructure = InfrastructureAPI.infrastructure !== 'local';
         const noInfraSelectorButton = ["uri", "id", "description", 
"group"].includes(property.name);
         const icon = InfrastructureAPI.infrastructure === 'kubernetes' ? 
KubernetesIcon("infra-button") : <DockerIcon/>
@@ -237,8 +253,14 @@ export function ComponentPropertyField(props: Props) {
                 <TextInput className="text-field" isRequired ref={ref}
                            type={property.secret && !showPassword ? "password" 
: "text"}
                            id={id} name={id}
-                           value={value !== undefined ? value : 
property.defaultValue}
-                           onChange={(e, value) => 
parametersChanged(property.name, value, property.kind === 'path')}/>}
+                           value={textValue !== undefined ? textValue : 
property.defaultValue}
+                           onBlur={_ => parametersChanged(property.name, 
textValue, property.kind === 'path')}
+                           onChange={(_, v) => {
+                               setTextValue(v);
+                               setCheckChanges(true);
+                           }}
+               />
+            }
             <InputGroupItem>
                 <Tooltip position="bottom-end" content={"Show Editor"}>
                     <Button variant="control" onClick={e => 
setShowEditor(!showEditor)}>
@@ -257,6 +279,7 @@ export function ComponentPropertyField(props: Props) {
                              onSave={(fieldId, value1) => {
                                  parametersChanged(property.name, value1, 
property.kind === 'path')
                                  setShowEditor(false);
+                                 setCheckChanges(false);
                              }}/>
             </InputGroupItem>}
             {property.secret &&
@@ -267,12 +290,16 @@ export function ComponentPropertyField(props: Props) {
                 </Tooltip>
             }
             <InputGroupItem>
-                <PropertyPlaceholderDropdown property={property} value={value} 
onComponentPropertyChange={onParametersChange}/>
+                <PropertyPlaceholderDropdown property={property} value={value} 
onComponentPropertyChange={(parameter, v) => {
+                    onParametersChange(parameter, v);
+                    setTextValue(v);
+                    setCheckChanges(false);
+                }}/>
             </InputGroupItem>
         </InputGroup>
     }
 
-    function getSpecialStringInput(property: ComponentProperty, value: any) {
+    function getSpecialStringInput(property: ComponentProperty) {
         return (
             <InputGroup>
                 <InputGroupItem isFill>
@@ -280,14 +307,21 @@ export function ComponentPropertyField(props: Props) {
                         className="text-field" isRequired
                         type={(property.secret ? "password" : "text")}
                         id={id} name={id}
-                        value={value !== undefined ? value : 
property.defaultValue}
+                        value={textValue !== undefined ? textValue : 
property.defaultValue}
+                        onBlur={_ => parametersChanged(property.name, 
textValue, property.kind === 'path')}
+                        onChange={(_, v) => {
+                            setTextValue(v);
+                            setCheckChanges(true);
+                        }}
                         customIcon={<Text 
component={TextVariants.p}>{property.type}</Text>}
-                        onChange={(_, value) => {
-                            parametersChanged(property.name, value, 
property.kind === 'path')
-                        }}/>
+                    />
                 </InputGroupItem>
                 <InputGroupItem>
-                    <PropertyPlaceholderDropdown property={property} 
value={value} onComponentPropertyChange={onParametersChange}/>
+                    <PropertyPlaceholderDropdown property={property} 
value={textValue} onComponentPropertyChange={(_, v) => {
+                        setTextValue(v);
+                        onParametersChange(property.name, v)
+                        setCheckChanges(true);
+                    }}/>
                 </InputGroupItem>
             </InputGroup>
         )
@@ -318,21 +352,25 @@ export function ComponentPropertyField(props: Props) {
         )
     }
 
-    function getSwitch(property: ComponentProperty, value: any) {
-        const isValueBoolean = (value === true || value === false);
-        const isDisabled = value !== undefined && !isValueBoolean;
-        const isChecked = value !== undefined ? Boolean(value) : 
(property.defaultValue !== undefined && ['true', 
true].includes(property.defaultValue))
+    function getSwitch(property: ComponentProperty) {
+        const isValueBoolean = (textValue?.toString() === 'true' || 
textValue?.toString() === 'false');
+        const isDisabled = textValue?.toString().includes("{") || 
textValue?.toString().includes("}")
+        const isChecked = textValue !== undefined ? Boolean(textValue) : 
(property.defaultValue !== undefined && ['true', 
true].includes(property.defaultValue))
         return (
             <TextInputGroup className="input-group">
                 <InputGroupItem>
                     <Switch
                         id={id} name={id}
-                        value={value?.toString()}
                         isDisabled={isDisabled}
                         className="switch-placeholder"
                         aria-label={id}
                         isChecked={isChecked}
-                        onChange={(e, checked) => 
parametersChanged(property.name, checked)}/>
+                        value={textValue?.toString()}
+                        onChange={(_, v) => {
+                            setTextValue(v);
+                            parametersChanged(property.name, v);
+                            setCheckChanges(true);
+                        }}/>
                 </InputGroupItem>
                 <InputGroupItem isFill>
                     <TextInput
@@ -340,12 +378,20 @@ export function ComponentPropertyField(props: Props) {
                         name={property.name + "-placeholder"}
                         type="text"
                         aria-label="placeholder"
-                        value={!isValueBoolean ? value?.toString() : undefined}
-                        onChange={(_, v) => parametersChanged(property.name, 
v)}
+                        value={!isValueBoolean ? textValue?.toString() : 
undefined}
+                        onBlur={_ => onParametersChange(property.name, 
textValue)}
+                        onChange={(_, v) => {
+                            setTextValue(v);
+                            setCheckChanges(true);
+                        }}
                     />
                 </InputGroupItem>
                 <InputGroupItem>
-                    <PropertyPlaceholderDropdown property={property} 
value={value} onComponentPropertyChange={onParametersChange}/>
+                    <PropertyPlaceholderDropdown property={property} 
value={value} onDslPropertyChange={(_, v) => {
+                        setTextValue(v);
+                        onParametersChange(property.name, v);
+                        setCheckChanges(false);
+                    }}/>
                 </InputGroupItem>
             </TextInputGroup>
         )
@@ -377,15 +423,15 @@ export function ComponentPropertyField(props: Props) {
             }>
             {canBeInternalUri(property) && getInternalUriSelect(property, 
value)}
             {property.type === 'string' && property.enum === undefined && 
!canBeInternalUri(property)
-                && getStringInput(property, value)}
+                && getStringInput(property)}
             {['duration', 'integer', 'int', 'number'].includes(property.type) 
&& property.enum === undefined && !canBeInternalUri(property)
-                && getSpecialStringInput(property, value)}
+                && getSpecialStringInput(property)}
             {['object'].includes(property.type) && !property.enum
                 && getSelectBean(property, value)}
             {['string', 'object'].includes(property.type) && property.enum
                 && getSelect(property, value)}
             {property.type === 'boolean'
-                && getSwitch(property, value)}
+                && getSwitch(property)}
             {getInfrastructureSelectorModal()}
         </FormGroup>
     )
diff --git 
a/karavan-designer/src/designer/property/property/DslPropertyField.tsx 
b/karavan-designer/src/designer/property/property/DslPropertyField.tsx
index 923b0e26..95bc3504 100644
--- a/karavan-designer/src/designer/property/property/DslPropertyField.tsx
+++ b/karavan-designer/src/designer/property/property/DslPropertyField.tsx
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, {useRef, useState} from 'react';
+import React, {useEffect, useRef, useState} from 'react';
 import {
     FormGroup,
     TextInput,
@@ -99,9 +99,25 @@ export function DslPropertyField(props: Props) {
     const [showEditor, setShowEditor] = useState<boolean>(false);
     const [infrastructureSelector, setInfrastructureSelector] = 
useState<boolean>(false);
     const [infrastructureSelectorProperty, setInfrastructureSelectorProperty] 
= useState<string | undefined>(undefined);
-    const [customCode, setCustomCode] = useState<string | 
undefined>(undefined);
-
+    const [customCode, setCustomCode] = useState<string>('');
+    const [textValue, setTextValue] = useState<any>();
     const ref = useRef<any>(null);
+    const [checkChanges, setCheckChanges] = useState<boolean>(false);
+
+    useEffect(()=> setTextValue(value), [])
+
+    useEffect(()=> {
+        if (checkChanges) {
+            const interval = setInterval(() => {
+                if (props.value !== textValue) {
+                    propertyChanged(property.name, textValue);
+                }
+            }, 3000);
+            return () => {
+                clearInterval(interval)
+            }
+        }
+    }, [checkChanges, textValue])
 
     function openSelect(propertyName: string, isExpanded: boolean) {
         setSelectStatus(new Map<string, boolean>([[propertyName, isExpanded]]))
@@ -116,6 +132,7 @@ export function DslPropertyField(props: Props) {
     }
 
     function propertyChanged(fieldId: string, value: string | number | boolean 
| any, newRoute?: RouteToCreate) {
+        setCheckChanges(false);
         if (fieldId === 'id' && 
CamelDefinitionApiExt.hasElementWithId(integration, value)) {
             value = props.element;
         }
@@ -224,14 +241,14 @@ export function DslPropertyField(props: Props) {
                 onSelect={selectInfrastructure}/>)
     }
 
-    function getStringInput(property: PropertyMeta, value: any) {
+    function getStringInput(property: PropertyMeta) {
         const inInfrastructure = InfrastructureAPI.infrastructure !== 'local';
         const noInfraSelectorButton = ["uri", "id", "description", 
"group"].includes(property.name);
         const icon = InfrastructureAPI.infrastructure === 'kubernetes' ? 
KubernetesIcon("infra-button") : <DockerIcon/>
         const isNumber = ['integer', 'number', 
'duration'].includes(property.type);
         const uriReadOnly = isUriReadOnly(property);
         const showEditorButton = !uriReadOnly && !isNumber && !property.secret 
&& !['id', 'description'].includes(property.name);
-        return (<InputGroup>
+        return <InputGroup>
             {inInfrastructure && !showEditor && !noInfraSelectorButton &&
                 <InputGroupItem>
                     <Tooltip position="bottom-end"
@@ -246,12 +263,16 @@ export function DslPropertyField(props: Props) {
                 <InputGroupItem isFill>
                     <TextInput ref={ref}
                                className="text-field" isRequired
-                               type={(property.secret ? "password" : "text")}
+                               type={property.secret ? "password" : "text"}
                                id={property.name} name={property.name}
-                               value={value?.toString()}
+                               value={textValue?.toString()}
                                customIcon={property.type !== 'string' ? <Text 
component={TextVariants.p}>{property.type}</Text> : undefined}
-                               onChange={(_, v) =>
-                                   propertyChanged(property.name, v)}
+                               onBlur={_ => propertyChanged(property.name, 
textValue)}
+                               onFocus={_ => setCheckChanges(true)}
+                               onChange={(_, v) => {
+                                   setTextValue(v);
+                                   setCheckChanges(true);
+                               }}
                                readOnlyVariant={uriReadOnly? "default" : 
undefined}/>
                 </InputGroupItem>
             }
@@ -275,14 +296,14 @@ export function DslPropertyField(props: Props) {
                                  setShowEditor(false);
                              }}/>
             </InputGroupItem>}
-        </InputGroup>)
+        </InputGroup>
     }
 
     function showCode(name: string, javaType: string) {
         const {property} = props;
         InfrastructureAPI.onGetCustomCode?.(name, 
property.javaType).then(value => {
             if (value === undefined) {
-                const code = TemplateApi.generateCode(property.javaType, name);
+                const code = TemplateApi.generateCode(property.javaType, name) 
|| '';
                 setCustomCode(code);
                 setShowEditor(true);
             } else {
@@ -343,8 +364,13 @@ export function DslPropertyField(props: Props) {
                         id={property.name}
                         name={property.name}
                         height={"100px"}
-                        value={value?.toString()}
-                        onChange={(_, v) => propertyChanged(property.name, 
v)}/>
+                        value={textValue?.toString()}
+                        onBlur={_ => propertyChanged(property.name, textValue)}
+                        onChange={(_, v) => {
+                            setTextValue(v);
+                            setCheckChanges(true);
+                        }}
+                    />
                 </InputGroupItem>
                 <InputGroupItem>
                     <Tooltip position="bottom-end" content={"Show Editor"}>
@@ -391,13 +417,13 @@ export function DslPropertyField(props: Props) {
         )
     }
 
-    function getBooleanInput(property: PropertyMeta, value: any) {
-        const isValueBoolean = (value === true || value === false);
-        const isDisabled = value !== undefined && !isValueBoolean;
+    function getBooleanInput(property: PropertyMeta) {
+        const isValueBoolean = (textValue?.toString() === 'true' || 
textValue?.toString() === 'false');
+        const isDisabled = textValue?.toString().includes("{") || 
textValue?.toString().includes("}")
         let isChecked = false;
-        if (value !== undefined && isValueBoolean) {
-            isChecked = Boolean(value);
-        } else if ((value === undefined || value.toString().length > 0) && 
property.defaultValue !== undefined) {
+        if (textValue !== undefined && isValueBoolean) {
+            isChecked = Boolean(textValue);
+        } else if ((textValue === undefined || textValue.toString().length > 
0) && property.defaultValue !== undefined) {
             isChecked = property.defaultValue === 'true';
         }
         return (
@@ -408,10 +434,14 @@ export function DslPropertyField(props: Props) {
                         id={property.name + "-switch"}
                         name={property.name + "-switch"}
                         className="switch-placeholder"
-                        value={value?.toString()}
+                        value={textValue?.toString()}
                         aria-label={property.name}
                         isChecked={isChecked}
-                        onChange={(_, v) => propertyChanged(property.name, 
v)}/>
+                        onChange={(_, v) => {
+                            setTextValue(v);
+                            propertyChanged(property.name, v);
+                            setCheckChanges(false);
+                        }}/>
                 </InputGroupItem>
                 <InputGroupItem isFill>
                     <TextInput
@@ -419,12 +449,20 @@ export function DslPropertyField(props: Props) {
                         name={property.name + "-placeholder"}
                         type="text"
                         aria-label="placeholder"
-                        value={!isValueBoolean ? value?.toString() : undefined}
-                        onChange={(_, v) => propertyChanged(property.name, v)}
+                        value={!isValueBoolean ? textValue?.toString() : 
undefined}
+                        onBlur={_ => propertyChanged(property.name, textValue)}
+                        onChange={(_, v) => {
+                            setTextValue(v);
+                            setCheckChanges(true);
+                        }}
                     />
                 </InputGroupItem>
                 <InputGroupItem>
-                    <PropertyPlaceholderDropdown property={property} 
value={value} onDslPropertyChange={propertyChanged}/>
+                    <PropertyPlaceholderDropdown property={property} 
value={value} onDslPropertyChange={(_, v, newRoute) => {
+                        setTextValue(v);
+                        propertyChanged(property.name, v, newRoute);
+                        setCheckChanges(false);
+                    }}/>
                 </InputGroupItem>
             </TextInputGroup>
         )
@@ -830,13 +868,13 @@ export function DslPropertyField(props: Props) {
                     && !canBeInternalUri(property, element)
                     && !canBeMediaType(property, element)
                     && !javaTypeGenerated(property)
-                    && getStringInput(property, value)}
+                    && getStringInput(property)}
                 {['string'].includes(property.type) && 
property.name.endsWith("Ref") && !property.isArray && !property.enumVals
                     && getSelectBean(property, value)}
                 {isMultiValueField(property)
                     && getMultiValueField(property, value)}
                 {property.type === 'boolean'
-                    && getBooleanInput(property, value)}
+                    && getBooleanInput(property)}
                 {property.enumVals
                     && getSelect(property, value)}
                 {isKamelet && property.name === 'parameters' && 
getKameletParameters()}

Reply via email to