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 63e20dc0d688946921947a6b1fee1ae1ac264aaa Author: Marat Gubaidullin <[email protected]> AuthorDate: Thu Sep 12 10:57:29 2024 -0400 Fixed #1402 --- .../webui/src/designer/property/DslProperties.tsx | 70 ++++++++++++++++++-- .../property/property/ComponentPropertyField.tsx | 8 +-- .../property/property/DslPropertyField.tsx | 74 +++++++++++++++++----- .../property/property/KameletPropertyField.tsx | 1 - karavan-designer/public/example/demo.camel.yaml | 3 + .../src/designer/property/DslProperties.tsx | 70 ++++++++++++++++++-- .../src/designer/property/PropertyStore.ts | 42 ++++++++++++ .../property/property/ComponentPropertyField.tsx | 8 +-- .../property/property/DslPropertyField.tsx | 74 +++++++++++++++++----- .../designer/property/property/PropertyUtil.tsx | 40 ++++++++++++ .../src/designer/property/DslProperties.tsx | 70 ++++++++++++++++++-- .../property/property/ComponentPropertyField.tsx | 8 +-- .../property/property/DslPropertyField.tsx | 74 +++++++++++++++++----- .../property/property/KameletPropertyField.tsx | 1 - 14 files changed, 451 insertions(+), 92 deletions(-) diff --git a/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx b/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx index 993f825f..afd0eb76 100644 --- a/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx +++ b/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx @@ -22,7 +22,7 @@ import { TextVariants, ExpandableSection, Button, - Tooltip, + Tooltip, ToggleGroupItem, ToggleGroup, TextInput, } from '@patternfly/react-core'; import '../karavan.css'; import './DslProperties.css'; @@ -39,6 +39,8 @@ import {shallow} from "zustand/shallow"; import {usePropertiesHook} from "./usePropertiesHook"; import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil"; import {PropertiesHeader} from "./PropertiesHeader"; +import {PropertyUtil} from "./property/PropertyUtil"; +import {usePropertiesStore} from "./PropertyStore"; interface Props { designerType: 'routes' | 'rest' | 'beans' @@ -60,6 +62,9 @@ export function DslProperties(props: Props) { const [selectedStep, dark] = useDesignerStore((s) => [s.selectedStep, s.dark], shallow) + const [propertyFilter, changedOnly, requiredOnly, setChangedOnly, setPropertyFilter, setRequiredOnly] + = usePropertiesStore((s) => [s.propertyFilter, s.changedOnly, s.requiredOnly, s.setChangedOnly, s.setPropertyFilter, s.setRequiredOnly], shallow) + const [showAdvanced, setShowAdvanced] = useState<boolean>(false); function getClonableElementHeader(): React.JSX.Element { @@ -89,7 +94,7 @@ export function DslProperties(props: Props) { const dslName = selectedStep?.dslName; return CamelDefinitionApiExt.getElementProperties(dslName) .filter((p: PropertyMeta) => !(p.name === 'uri' && dslName !== 'ToDynamicDefinition')) // show uri only to Dynamic To - // .filter((p: PropertyMeta) => (showAdvanced && p.label.includes('advanced')) || (!showAdvanced && !p.label.includes('advanced'))) + // .filer((p: PropertyMeta) => (showAdvanced && p.label.includes('advanced')) || (!showAdvanced && !p.label.includes('advanced'))) .filter((p: PropertyMeta) => !p.isObject || (p.isObject && !CamelUi.dslHasSteps(p.type)) || (dslName === 'CatchDefinition' && p.name === 'onWhen')) .filter((p: PropertyMeta) => !(dslName === 'RestDefinition' && ['get', 'post', 'put', 'patch', 'delete', 'head'].includes(p.name))); // .filter((p: PropertyMeta) => dslName && !(['RestDefinition', 'GetDefinition', 'PostDefinition', 'PutDefinition', 'PatchDefinition', 'DeleteDefinition', 'HeadDefinition'].includes(dslName) && ['param', 'responseMessage'].includes(p.name))) // TODO: configure this properties @@ -101,7 +106,7 @@ export function DslProperties(props: Props) { <DslPropertyField key={property.name} property={property} element={selectedStep} - value={selectedStep ? (selectedStep as any)[property.name] : undefined} + value={getPropertyValue(property)} onExpressionChange={onExpressionChange} onParameterChange={onParametersChange} onDataFormatChange={onDataFormatChange} @@ -111,26 +116,77 @@ export function DslProperties(props: Props) { </>) } + function getPropertyValue(property: PropertyMeta) { + return selectedStep ? (selectedStep as any)[property.name] : undefined; + } + + function getFilteredProperties(): PropertyMeta[] { + let props = !dataFormatElement ? getProperties() : getProperties().filter(p => !dataFormats.includes(p.name)); + const filter = propertyFilter.toLocaleLowerCase() + props = props.filter(p => p.name === 'parameters' || p.name.toLocaleLowerCase().includes(filter) || p.label.toLocaleLowerCase().includes(filter) || p.displayName.toLocaleLowerCase().includes(filter)); + if (requiredOnly) { + props = props.filter(p => p.name === 'parameters' || p.required); + } + if (changedOnly) { + props = props.filter(p =>p.name === 'parameters' || PropertyUtil.hasDslPropertyValueChanged(p, getPropertyValue(p))); + } + return props + } + const dataFormats = DataFormats.map(value => value[0]); const dataFormatElement = selectedStep !== undefined && ['MarshalDefinition', 'UnmarshalDefinition'].includes(selectedStep.dslName); - const properties = !dataFormatElement - ? getProperties() - : getProperties().filter(p => !dataFormats.includes(p.name)); + const properties = getFilteredProperties(); const propertiesMain = properties.filter(p => !p.label.includes("advanced")); const propertiesAdvanced = properties.filter(p => p.label.includes("advanced")); + + function getPropertySelector() { + return ( + <div style={{display: 'flex', flexDirection: 'row', alignItems: 'center', gap: '3px'}}> + <ToggleGroup aria-label="properties selctor"> + <ToggleGroupItem + text="Required" + buttonId="requiredOnly" + isSelected={requiredOnly} + onChange={(_, selected) => setRequiredOnly(selected)} + /> + <ToggleGroupItem + text="Changed" + buttonId="changedOnly" + isSelected={changedOnly} + onChange={(_, selected) => setChangedOnly(selected)} + /> + </ToggleGroup> + <TextInput + placeholder="filter by name" + value={propertyFilter} + onChange={(_, value) => setPropertyFilter(value)} + /> + </div> + ) + } + + function getPropertySelectorChanged(): boolean { + return requiredOnly || changedOnly || propertyFilter?.trim().length > 0; + } + + function getShowExpanded(): boolean { + return showAdvanced || getPropertySelectorChanged(); + } + return ( <div key={selectedStep ? selectedStep.uuid : 'integration'} className='properties'> <Form autoComplete="off" onSubmit={event => event.preventDefault()}> {selectedStep === undefined && <IntegrationHeader/>} {selectedStep && getComponentHeader()} + {selectedStep !== undefined && getPropertySelector()} {getPropertyFields(propertiesMain)} {selectedStep && !['MarshalDefinition', 'UnmarshalDefinition'].includes(selectedStep.dslName) && propertiesAdvanced.length > 0 && <ExpandableSection toggleText={'EIP advanced properties'} onToggle={(_event, isExpanded) => setShowAdvanced(!showAdvanced)} - isExpanded={showAdvanced}> + isExpanded={getShowExpanded()}> <div className="parameters"> {getPropertyFields(propertiesAdvanced)} </div> diff --git a/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyField.tsx b/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyField.tsx index 7669a114..262e2eb5 100644 --- a/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyField.tsx +++ b/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyField.tsx @@ -56,6 +56,7 @@ import EditorIcon from "@patternfly/react-icons/dist/js/icons/code-icon"; import {ExpressionModalEditor} from "../../../expression/ExpressionModalEditor"; import {PropertyPlaceholderDropdown} from "./PropertyPlaceholderDropdown"; import {INTERNAL_COMPONENTS} from "karavan-core/lib/api/ComponentApi"; +import {PropertyUtil} from "./PropertyUtil"; const prefix = "parameters"; const beanPrefix = "#bean:"; @@ -414,14 +415,9 @@ export function ComponentPropertyField(props: Props) { ) } - function hasValueChanged(property: ComponentProperty, value: any): boolean { - const isSet = value !== undefined; - const isDefault = property.defaultValue !== undefined && value?.toString() === property.defaultValue?.toString(); - return isSet && !isDefault; - } function getLabel(property: ComponentProperty, value: any) { - const bgColor = hasValueChanged(property, value) ? 'yellow' : 'transparent'; + const bgColor = PropertyUtil.hasComponentPropertyValueChanged(property, value) ? 'yellow' : 'transparent'; return ( <div style={{display: "flex", flexDirection: 'row', alignItems: 'center', gap: '3px'}}> <Text style={{backgroundColor: bgColor}}>{property.displayName}</Text> diff --git a/karavan-app/src/main/webui/src/designer/property/property/DslPropertyField.tsx b/karavan-app/src/main/webui/src/designer/property/property/DslPropertyField.tsx index b35ca3be..09f259f6 100644 --- a/karavan-app/src/main/webui/src/designer/property/property/DslPropertyField.tsx +++ b/karavan-app/src/main/webui/src/designer/property/property/DslPropertyField.tsx @@ -80,6 +80,9 @@ import {VariablesDropdown} from "./VariablesDropdown"; import {ROUTE, GLOBAL} from "karavan-core/lib/api/VariableUtil"; import {SpiBeanApi} from "karavan-core/lib/api/SpiBeanApi"; import {SelectField} from "./SelectField"; +import {PropertyUtil} from "./PropertyUtil"; +import {usePropertiesStore} from "../PropertyStore"; +import {Property} from "karavan-core/lib/model/KameletModels"; const beanPrefix = "#bean:"; const classPrefix = "#class:"; @@ -100,6 +103,7 @@ export function DslPropertyField(props: Props) { const [integration, setIntegration, addVariable, files] = useIntegrationStore((s) => [s.integration, s.setIntegration, s.addVariable, s.files], shallow) const [dark, setSelectedStep, beans] = useDesignerStore((s) => [s.dark, s.setSelectedStep, s.beans], shallow) + const [propertyFilter, changedOnly, requiredOnly] = usePropertiesStore((s) => [s.propertyFilter, s.changedOnly, s.requiredOnly], shallow) const [isShowAdvanced, setIsShowAdvanced] = useState<string[]>([]); const [arrayValues, setArrayValues] = useState<Map<string, string>>(new Map<string, string>()); @@ -204,14 +208,8 @@ export function DslPropertyField(props: Props) { return property.name === 'parameters' && property.description === 'parameters'; } - function hasValueChanged(property: PropertyMeta, value: any): boolean { - const isSet = value !== undefined && !['id', 'uri'].includes(property.name); - const isDefault = property.defaultValue !== undefined && value?.toString() === property.defaultValue?.toString(); - return isSet && !isDefault; - } - function getLabel(property: PropertyMeta, value: any, isKamelet: boolean) { - const bgColor = hasValueChanged(property, value) ? 'yellow' : 'transparent'; + const bgColor = PropertyUtil.hasDslPropertyValueChanged(property, value) ? 'yellow' : 'transparent'; if (!isMultiValueField(property) && property.isObject && !property.isArray && !["ExpressionDefinition"].includes(property.type)) { const tooltip = value ? "Delete " + property.name : "Add " + property.name; const className = value ? "change-button delete-button" : "change-button add-button"; @@ -906,32 +904,55 @@ export function DslPropertyField(props: Props) { ) } + function getKameletPropertyValue(property: Property) { + const element = props.element; + return CamelDefinitionApiExt.getParametersValue(element, property.id) + } + + function getFilteredKameletProperties(): Property[] { + const element = props.element; + const requiredParameters = CamelUtil.getKameletRequiredParameters(element); + let properties = CamelUtil.getKameletProperties(element) + const filter = propertyFilter.toLocaleLowerCase() + properties = properties.filter(p => p.title?.toLocaleLowerCase().includes(filter) || p.id?.toLocaleLowerCase().includes(filter)); + if (requiredOnly) { + properties = properties.filter(p => requiredParameters.includes(p.id)); + } + if (changedOnly) { + properties = properties.filter(p => PropertyUtil.hasKameletPropertyValueChanged(p, getKameletPropertyValue(p))); + } + return properties; + } + function getKameletParameters() { const element = props.element; const requiredParameters = CamelUtil.getKameletRequiredParameters(element); return ( <div className="parameters"> - {CamelUtil.getKameletProperties(element).map(property => + {getFilteredKameletProperties().map(property => <KameletPropertyField key={property.id} property={property} - value={CamelDefinitionApiExt.getParametersValue(element, property.id)} + value={getKameletPropertyValue(property)} required={requiredParameters?.includes(property.id)} />)} </div> ) } - function getMainComponentParameters(properties: ComponentProperty[]) { + function getComponentPropertyValue(kp: ComponentProperty) { const element = props.element; + return CamelDefinitionApiExt.getParametersValue(element, kp.name, kp.kind === 'path'); + } + + function getMainComponentParameters(properties: ComponentProperty[]) { return ( <div className="parameters"> {properties.map(kp => { - const value = CamelDefinitionApiExt.getParametersValue(element, kp.name, kp.kind === 'path'); return (<ComponentPropertyField key={kp.name} property={kp} - value={value} + value={getComponentPropertyValue(kp)} element={props.element} onParameterChange={props.onParameterChange} />) @@ -941,8 +962,6 @@ export function DslPropertyField(props: Props) { } function getExpandableComponentProperties(properties: ComponentProperty[], label: string) { - const element = props.element; - return ( <ExpandableSection toggleText={label} @@ -956,13 +975,13 @@ export function DslPropertyField(props: Props) { return prevState; }) }} - isExpanded={isShowAdvanced.includes(label)}> + isExpanded={getShowExpanded(label)}> <div className="parameters"> {properties.map(kp => <ComponentPropertyField key={kp.name} property={kp} - value={CamelDefinitionApiExt.getParametersValue(element, kp.name, kp.kind === 'path')} + value={getComponentPropertyValue(kp)} onParameterChange={props.onParameterChange} /> )} @@ -1012,9 +1031,30 @@ export function DslPropertyField(props: Props) { return ['string'].includes(property.type) && property.name !== 'expression' && property.isArray && !property.enumVals; } + function getFilteredComponentProperties(): ComponentProperty[] { + let props = CamelUtil.getComponentProperties(element); + const filter = propertyFilter.toLocaleLowerCase() + props = props.filter(p => p.name?.toLocaleLowerCase().includes(filter) || p.label.toLocaleLowerCase().includes(filter) || p.displayName.toLocaleLowerCase().includes(filter)); + if (requiredOnly) { + props = props.filter(p => p.required); + } + if (changedOnly) { + props = props.filter(p => PropertyUtil.hasComponentPropertyValueChanged(p, getComponentPropertyValue(p))); + } + return props + } + + function getPropertySelectorChanged(): boolean { + return requiredOnly || changedOnly || propertyFilter?.trim().length > 0; + } + + function getShowExpanded(label: string): boolean { + return isShowAdvanced.includes(label) || getPropertySelectorChanged(); + } + function getComponentParameters(property: PropertyMeta) { const element = props.element; - const properties = CamelUtil.getComponentProperties(element); + const properties = getFilteredComponentProperties(); 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")); diff --git a/karavan-app/src/main/webui/src/designer/property/property/KameletPropertyField.tsx b/karavan-app/src/main/webui/src/designer/property/property/KameletPropertyField.tsx index fe52431c..f9f1bf87 100644 --- a/karavan-app/src/main/webui/src/designer/property/property/KameletPropertyField.tsx +++ b/karavan-app/src/main/webui/src/designer/property/property/KameletPropertyField.tsx @@ -38,7 +38,6 @@ import EditorIcon from "@patternfly/react-icons/dist/js/icons/code-icon"; import {ExpressionModalEditor} from "../../../expression/ExpressionModalEditor"; import {useDesignerStore} from "../../DesignerStore"; import {shallow} from "zustand/shallow"; -import {ComponentProperty} from "../../../../../karavan-core/src/core/model/ComponentModels"; interface Props { property: Property, diff --git a/karavan-designer/public/example/demo.camel.yaml b/karavan-designer/public/example/demo.camel.yaml index 25bd3079..136dc156 100644 --- a/karavan-designer/public/example/demo.camel.yaml +++ b/karavan-designer/public/example/demo.camel.yaml @@ -12,3 +12,6 @@ - to: id: to-7baa uri: jms + - to: + id: to-7f8a + uri: kamelet:aws-kinesis-firehose-sink diff --git a/karavan-designer/src/designer/property/DslProperties.tsx b/karavan-designer/src/designer/property/DslProperties.tsx index 993f825f..afd0eb76 100644 --- a/karavan-designer/src/designer/property/DslProperties.tsx +++ b/karavan-designer/src/designer/property/DslProperties.tsx @@ -22,7 +22,7 @@ import { TextVariants, ExpandableSection, Button, - Tooltip, + Tooltip, ToggleGroupItem, ToggleGroup, TextInput, } from '@patternfly/react-core'; import '../karavan.css'; import './DslProperties.css'; @@ -39,6 +39,8 @@ import {shallow} from "zustand/shallow"; import {usePropertiesHook} from "./usePropertiesHook"; import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil"; import {PropertiesHeader} from "./PropertiesHeader"; +import {PropertyUtil} from "./property/PropertyUtil"; +import {usePropertiesStore} from "./PropertyStore"; interface Props { designerType: 'routes' | 'rest' | 'beans' @@ -60,6 +62,9 @@ export function DslProperties(props: Props) { const [selectedStep, dark] = useDesignerStore((s) => [s.selectedStep, s.dark], shallow) + const [propertyFilter, changedOnly, requiredOnly, setChangedOnly, setPropertyFilter, setRequiredOnly] + = usePropertiesStore((s) => [s.propertyFilter, s.changedOnly, s.requiredOnly, s.setChangedOnly, s.setPropertyFilter, s.setRequiredOnly], shallow) + const [showAdvanced, setShowAdvanced] = useState<boolean>(false); function getClonableElementHeader(): React.JSX.Element { @@ -89,7 +94,7 @@ export function DslProperties(props: Props) { const dslName = selectedStep?.dslName; return CamelDefinitionApiExt.getElementProperties(dslName) .filter((p: PropertyMeta) => !(p.name === 'uri' && dslName !== 'ToDynamicDefinition')) // show uri only to Dynamic To - // .filter((p: PropertyMeta) => (showAdvanced && p.label.includes('advanced')) || (!showAdvanced && !p.label.includes('advanced'))) + // .filer((p: PropertyMeta) => (showAdvanced && p.label.includes('advanced')) || (!showAdvanced && !p.label.includes('advanced'))) .filter((p: PropertyMeta) => !p.isObject || (p.isObject && !CamelUi.dslHasSteps(p.type)) || (dslName === 'CatchDefinition' && p.name === 'onWhen')) .filter((p: PropertyMeta) => !(dslName === 'RestDefinition' && ['get', 'post', 'put', 'patch', 'delete', 'head'].includes(p.name))); // .filter((p: PropertyMeta) => dslName && !(['RestDefinition', 'GetDefinition', 'PostDefinition', 'PutDefinition', 'PatchDefinition', 'DeleteDefinition', 'HeadDefinition'].includes(dslName) && ['param', 'responseMessage'].includes(p.name))) // TODO: configure this properties @@ -101,7 +106,7 @@ export function DslProperties(props: Props) { <DslPropertyField key={property.name} property={property} element={selectedStep} - value={selectedStep ? (selectedStep as any)[property.name] : undefined} + value={getPropertyValue(property)} onExpressionChange={onExpressionChange} onParameterChange={onParametersChange} onDataFormatChange={onDataFormatChange} @@ -111,26 +116,77 @@ export function DslProperties(props: Props) { </>) } + function getPropertyValue(property: PropertyMeta) { + return selectedStep ? (selectedStep as any)[property.name] : undefined; + } + + function getFilteredProperties(): PropertyMeta[] { + let props = !dataFormatElement ? getProperties() : getProperties().filter(p => !dataFormats.includes(p.name)); + const filter = propertyFilter.toLocaleLowerCase() + props = props.filter(p => p.name === 'parameters' || p.name.toLocaleLowerCase().includes(filter) || p.label.toLocaleLowerCase().includes(filter) || p.displayName.toLocaleLowerCase().includes(filter)); + if (requiredOnly) { + props = props.filter(p => p.name === 'parameters' || p.required); + } + if (changedOnly) { + props = props.filter(p =>p.name === 'parameters' || PropertyUtil.hasDslPropertyValueChanged(p, getPropertyValue(p))); + } + return props + } + const dataFormats = DataFormats.map(value => value[0]); const dataFormatElement = selectedStep !== undefined && ['MarshalDefinition', 'UnmarshalDefinition'].includes(selectedStep.dslName); - const properties = !dataFormatElement - ? getProperties() - : getProperties().filter(p => !dataFormats.includes(p.name)); + const properties = getFilteredProperties(); const propertiesMain = properties.filter(p => !p.label.includes("advanced")); const propertiesAdvanced = properties.filter(p => p.label.includes("advanced")); + + function getPropertySelector() { + return ( + <div style={{display: 'flex', flexDirection: 'row', alignItems: 'center', gap: '3px'}}> + <ToggleGroup aria-label="properties selctor"> + <ToggleGroupItem + text="Required" + buttonId="requiredOnly" + isSelected={requiredOnly} + onChange={(_, selected) => setRequiredOnly(selected)} + /> + <ToggleGroupItem + text="Changed" + buttonId="changedOnly" + isSelected={changedOnly} + onChange={(_, selected) => setChangedOnly(selected)} + /> + </ToggleGroup> + <TextInput + placeholder="filter by name" + value={propertyFilter} + onChange={(_, value) => setPropertyFilter(value)} + /> + </div> + ) + } + + function getPropertySelectorChanged(): boolean { + return requiredOnly || changedOnly || propertyFilter?.trim().length > 0; + } + + function getShowExpanded(): boolean { + return showAdvanced || getPropertySelectorChanged(); + } + return ( <div key={selectedStep ? selectedStep.uuid : 'integration'} className='properties'> <Form autoComplete="off" onSubmit={event => event.preventDefault()}> {selectedStep === undefined && <IntegrationHeader/>} {selectedStep && getComponentHeader()} + {selectedStep !== undefined && getPropertySelector()} {getPropertyFields(propertiesMain)} {selectedStep && !['MarshalDefinition', 'UnmarshalDefinition'].includes(selectedStep.dslName) && propertiesAdvanced.length > 0 && <ExpandableSection toggleText={'EIP advanced properties'} onToggle={(_event, isExpanded) => setShowAdvanced(!showAdvanced)} - isExpanded={showAdvanced}> + isExpanded={getShowExpanded()}> <div className="parameters"> {getPropertyFields(propertiesAdvanced)} </div> diff --git a/karavan-designer/src/designer/property/PropertyStore.ts b/karavan-designer/src/designer/property/PropertyStore.ts new file mode 100644 index 00000000..b9d0e511 --- /dev/null +++ b/karavan-designer/src/designer/property/PropertyStore.ts @@ -0,0 +1,42 @@ +/* + * 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 {createWithEqualityFn} from "zustand/traditional"; +import {shallow} from "zustand/shallow"; + +interface PropertiesState { + propertyFilter: string; + setPropertyFilter: (propertyFilter: string) => void + requiredOnly: boolean; + setRequiredOnly: (requiredOnly: boolean) => void + changedOnly: boolean; + setChangedOnly: (changedOnly: boolean) => void +} + +export const usePropertiesStore = createWithEqualityFn<PropertiesState>((set, get) => ({ + requiredOnly: false, + changedOnly: false, + propertyFilter: '', + setPropertyFilter: (propertyFilter: string) => { + set({propertyFilter: propertyFilter}); + }, + setRequiredOnly: (requiredOnly: boolean) => { + set({requiredOnly: requiredOnly}); + }, + setChangedOnly: (changedOnly: boolean) => { + set({changedOnly: changedOnly}); + }, +}), shallow) diff --git a/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx b/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx index 7669a114..262e2eb5 100644 --- a/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx +++ b/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx @@ -56,6 +56,7 @@ import EditorIcon from "@patternfly/react-icons/dist/js/icons/code-icon"; import {ExpressionModalEditor} from "../../../expression/ExpressionModalEditor"; import {PropertyPlaceholderDropdown} from "./PropertyPlaceholderDropdown"; import {INTERNAL_COMPONENTS} from "karavan-core/lib/api/ComponentApi"; +import {PropertyUtil} from "./PropertyUtil"; const prefix = "parameters"; const beanPrefix = "#bean:"; @@ -414,14 +415,9 @@ export function ComponentPropertyField(props: Props) { ) } - function hasValueChanged(property: ComponentProperty, value: any): boolean { - const isSet = value !== undefined; - const isDefault = property.defaultValue !== undefined && value?.toString() === property.defaultValue?.toString(); - return isSet && !isDefault; - } function getLabel(property: ComponentProperty, value: any) { - const bgColor = hasValueChanged(property, value) ? 'yellow' : 'transparent'; + const bgColor = PropertyUtil.hasComponentPropertyValueChanged(property, value) ? 'yellow' : 'transparent'; return ( <div style={{display: "flex", flexDirection: 'row', alignItems: 'center', gap: '3px'}}> <Text style={{backgroundColor: bgColor}}>{property.displayName}</Text> diff --git a/karavan-designer/src/designer/property/property/DslPropertyField.tsx b/karavan-designer/src/designer/property/property/DslPropertyField.tsx index b35ca3be..09f259f6 100644 --- a/karavan-designer/src/designer/property/property/DslPropertyField.tsx +++ b/karavan-designer/src/designer/property/property/DslPropertyField.tsx @@ -80,6 +80,9 @@ import {VariablesDropdown} from "./VariablesDropdown"; import {ROUTE, GLOBAL} from "karavan-core/lib/api/VariableUtil"; import {SpiBeanApi} from "karavan-core/lib/api/SpiBeanApi"; import {SelectField} from "./SelectField"; +import {PropertyUtil} from "./PropertyUtil"; +import {usePropertiesStore} from "../PropertyStore"; +import {Property} from "karavan-core/lib/model/KameletModels"; const beanPrefix = "#bean:"; const classPrefix = "#class:"; @@ -100,6 +103,7 @@ export function DslPropertyField(props: Props) { const [integration, setIntegration, addVariable, files] = useIntegrationStore((s) => [s.integration, s.setIntegration, s.addVariable, s.files], shallow) const [dark, setSelectedStep, beans] = useDesignerStore((s) => [s.dark, s.setSelectedStep, s.beans], shallow) + const [propertyFilter, changedOnly, requiredOnly] = usePropertiesStore((s) => [s.propertyFilter, s.changedOnly, s.requiredOnly], shallow) const [isShowAdvanced, setIsShowAdvanced] = useState<string[]>([]); const [arrayValues, setArrayValues] = useState<Map<string, string>>(new Map<string, string>()); @@ -204,14 +208,8 @@ export function DslPropertyField(props: Props) { return property.name === 'parameters' && property.description === 'parameters'; } - function hasValueChanged(property: PropertyMeta, value: any): boolean { - const isSet = value !== undefined && !['id', 'uri'].includes(property.name); - const isDefault = property.defaultValue !== undefined && value?.toString() === property.defaultValue?.toString(); - return isSet && !isDefault; - } - function getLabel(property: PropertyMeta, value: any, isKamelet: boolean) { - const bgColor = hasValueChanged(property, value) ? 'yellow' : 'transparent'; + const bgColor = PropertyUtil.hasDslPropertyValueChanged(property, value) ? 'yellow' : 'transparent'; if (!isMultiValueField(property) && property.isObject && !property.isArray && !["ExpressionDefinition"].includes(property.type)) { const tooltip = value ? "Delete " + property.name : "Add " + property.name; const className = value ? "change-button delete-button" : "change-button add-button"; @@ -906,32 +904,55 @@ export function DslPropertyField(props: Props) { ) } + function getKameletPropertyValue(property: Property) { + const element = props.element; + return CamelDefinitionApiExt.getParametersValue(element, property.id) + } + + function getFilteredKameletProperties(): Property[] { + const element = props.element; + const requiredParameters = CamelUtil.getKameletRequiredParameters(element); + let properties = CamelUtil.getKameletProperties(element) + const filter = propertyFilter.toLocaleLowerCase() + properties = properties.filter(p => p.title?.toLocaleLowerCase().includes(filter) || p.id?.toLocaleLowerCase().includes(filter)); + if (requiredOnly) { + properties = properties.filter(p => requiredParameters.includes(p.id)); + } + if (changedOnly) { + properties = properties.filter(p => PropertyUtil.hasKameletPropertyValueChanged(p, getKameletPropertyValue(p))); + } + return properties; + } + function getKameletParameters() { const element = props.element; const requiredParameters = CamelUtil.getKameletRequiredParameters(element); return ( <div className="parameters"> - {CamelUtil.getKameletProperties(element).map(property => + {getFilteredKameletProperties().map(property => <KameletPropertyField key={property.id} property={property} - value={CamelDefinitionApiExt.getParametersValue(element, property.id)} + value={getKameletPropertyValue(property)} required={requiredParameters?.includes(property.id)} />)} </div> ) } - function getMainComponentParameters(properties: ComponentProperty[]) { + function getComponentPropertyValue(kp: ComponentProperty) { const element = props.element; + return CamelDefinitionApiExt.getParametersValue(element, kp.name, kp.kind === 'path'); + } + + function getMainComponentParameters(properties: ComponentProperty[]) { return ( <div className="parameters"> {properties.map(kp => { - const value = CamelDefinitionApiExt.getParametersValue(element, kp.name, kp.kind === 'path'); return (<ComponentPropertyField key={kp.name} property={kp} - value={value} + value={getComponentPropertyValue(kp)} element={props.element} onParameterChange={props.onParameterChange} />) @@ -941,8 +962,6 @@ export function DslPropertyField(props: Props) { } function getExpandableComponentProperties(properties: ComponentProperty[], label: string) { - const element = props.element; - return ( <ExpandableSection toggleText={label} @@ -956,13 +975,13 @@ export function DslPropertyField(props: Props) { return prevState; }) }} - isExpanded={isShowAdvanced.includes(label)}> + isExpanded={getShowExpanded(label)}> <div className="parameters"> {properties.map(kp => <ComponentPropertyField key={kp.name} property={kp} - value={CamelDefinitionApiExt.getParametersValue(element, kp.name, kp.kind === 'path')} + value={getComponentPropertyValue(kp)} onParameterChange={props.onParameterChange} /> )} @@ -1012,9 +1031,30 @@ export function DslPropertyField(props: Props) { return ['string'].includes(property.type) && property.name !== 'expression' && property.isArray && !property.enumVals; } + function getFilteredComponentProperties(): ComponentProperty[] { + let props = CamelUtil.getComponentProperties(element); + const filter = propertyFilter.toLocaleLowerCase() + props = props.filter(p => p.name?.toLocaleLowerCase().includes(filter) || p.label.toLocaleLowerCase().includes(filter) || p.displayName.toLocaleLowerCase().includes(filter)); + if (requiredOnly) { + props = props.filter(p => p.required); + } + if (changedOnly) { + props = props.filter(p => PropertyUtil.hasComponentPropertyValueChanged(p, getComponentPropertyValue(p))); + } + return props + } + + function getPropertySelectorChanged(): boolean { + return requiredOnly || changedOnly || propertyFilter?.trim().length > 0; + } + + function getShowExpanded(label: string): boolean { + return isShowAdvanced.includes(label) || getPropertySelectorChanged(); + } + function getComponentParameters(property: PropertyMeta) { const element = props.element; - const properties = CamelUtil.getComponentProperties(element); + const properties = getFilteredComponentProperties(); 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")); diff --git a/karavan-designer/src/designer/property/property/PropertyUtil.tsx b/karavan-designer/src/designer/property/property/PropertyUtil.tsx new file mode 100644 index 00000000..57ba1a3c --- /dev/null +++ b/karavan-designer/src/designer/property/property/PropertyUtil.tsx @@ -0,0 +1,40 @@ +/* + * 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 {PropertyMeta} from "karavan-core/lib/model/CamelMetadata"; +import {ComponentProperty} from "karavan-core/lib/model/ComponentModels"; +import {Property} from "karavan-core/lib/model/KameletModels"; + +export class PropertyUtil { + + static hasDslPropertyValueChanged(property: PropertyMeta, value: any): boolean { + const isSet = value !== undefined && !['id', 'uri', 'nodePrefixId'].includes(property.name); + const isDefault = property.defaultValue !== undefined && value?.toString() === property.defaultValue?.toString(); + return isSet && !isDefault; + } + + static hasComponentPropertyValueChanged(property: ComponentProperty, value: any): boolean { + const isSet = value !== undefined; + const isDefault = property.defaultValue !== undefined && value?.toString() === property.defaultValue?.toString(); + return isSet && !isDefault; + } + + static hasKameletPropertyValueChanged(property: Property, value: any): boolean { + const isSet = value !== undefined; + const isDefault = property.default !== undefined && value?.toString() === property.default?.toString(); + return isSet && !isDefault; + } +} \ No newline at end of file diff --git a/karavan-space/src/designer/property/DslProperties.tsx b/karavan-space/src/designer/property/DslProperties.tsx index 993f825f..afd0eb76 100644 --- a/karavan-space/src/designer/property/DslProperties.tsx +++ b/karavan-space/src/designer/property/DslProperties.tsx @@ -22,7 +22,7 @@ import { TextVariants, ExpandableSection, Button, - Tooltip, + Tooltip, ToggleGroupItem, ToggleGroup, TextInput, } from '@patternfly/react-core'; import '../karavan.css'; import './DslProperties.css'; @@ -39,6 +39,8 @@ import {shallow} from "zustand/shallow"; import {usePropertiesHook} from "./usePropertiesHook"; import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil"; import {PropertiesHeader} from "./PropertiesHeader"; +import {PropertyUtil} from "./property/PropertyUtil"; +import {usePropertiesStore} from "./PropertyStore"; interface Props { designerType: 'routes' | 'rest' | 'beans' @@ -60,6 +62,9 @@ export function DslProperties(props: Props) { const [selectedStep, dark] = useDesignerStore((s) => [s.selectedStep, s.dark], shallow) + const [propertyFilter, changedOnly, requiredOnly, setChangedOnly, setPropertyFilter, setRequiredOnly] + = usePropertiesStore((s) => [s.propertyFilter, s.changedOnly, s.requiredOnly, s.setChangedOnly, s.setPropertyFilter, s.setRequiredOnly], shallow) + const [showAdvanced, setShowAdvanced] = useState<boolean>(false); function getClonableElementHeader(): React.JSX.Element { @@ -89,7 +94,7 @@ export function DslProperties(props: Props) { const dslName = selectedStep?.dslName; return CamelDefinitionApiExt.getElementProperties(dslName) .filter((p: PropertyMeta) => !(p.name === 'uri' && dslName !== 'ToDynamicDefinition')) // show uri only to Dynamic To - // .filter((p: PropertyMeta) => (showAdvanced && p.label.includes('advanced')) || (!showAdvanced && !p.label.includes('advanced'))) + // .filer((p: PropertyMeta) => (showAdvanced && p.label.includes('advanced')) || (!showAdvanced && !p.label.includes('advanced'))) .filter((p: PropertyMeta) => !p.isObject || (p.isObject && !CamelUi.dslHasSteps(p.type)) || (dslName === 'CatchDefinition' && p.name === 'onWhen')) .filter((p: PropertyMeta) => !(dslName === 'RestDefinition' && ['get', 'post', 'put', 'patch', 'delete', 'head'].includes(p.name))); // .filter((p: PropertyMeta) => dslName && !(['RestDefinition', 'GetDefinition', 'PostDefinition', 'PutDefinition', 'PatchDefinition', 'DeleteDefinition', 'HeadDefinition'].includes(dslName) && ['param', 'responseMessage'].includes(p.name))) // TODO: configure this properties @@ -101,7 +106,7 @@ export function DslProperties(props: Props) { <DslPropertyField key={property.name} property={property} element={selectedStep} - value={selectedStep ? (selectedStep as any)[property.name] : undefined} + value={getPropertyValue(property)} onExpressionChange={onExpressionChange} onParameterChange={onParametersChange} onDataFormatChange={onDataFormatChange} @@ -111,26 +116,77 @@ export function DslProperties(props: Props) { </>) } + function getPropertyValue(property: PropertyMeta) { + return selectedStep ? (selectedStep as any)[property.name] : undefined; + } + + function getFilteredProperties(): PropertyMeta[] { + let props = !dataFormatElement ? getProperties() : getProperties().filter(p => !dataFormats.includes(p.name)); + const filter = propertyFilter.toLocaleLowerCase() + props = props.filter(p => p.name === 'parameters' || p.name.toLocaleLowerCase().includes(filter) || p.label.toLocaleLowerCase().includes(filter) || p.displayName.toLocaleLowerCase().includes(filter)); + if (requiredOnly) { + props = props.filter(p => p.name === 'parameters' || p.required); + } + if (changedOnly) { + props = props.filter(p =>p.name === 'parameters' || PropertyUtil.hasDslPropertyValueChanged(p, getPropertyValue(p))); + } + return props + } + const dataFormats = DataFormats.map(value => value[0]); const dataFormatElement = selectedStep !== undefined && ['MarshalDefinition', 'UnmarshalDefinition'].includes(selectedStep.dslName); - const properties = !dataFormatElement - ? getProperties() - : getProperties().filter(p => !dataFormats.includes(p.name)); + const properties = getFilteredProperties(); const propertiesMain = properties.filter(p => !p.label.includes("advanced")); const propertiesAdvanced = properties.filter(p => p.label.includes("advanced")); + + function getPropertySelector() { + return ( + <div style={{display: 'flex', flexDirection: 'row', alignItems: 'center', gap: '3px'}}> + <ToggleGroup aria-label="properties selctor"> + <ToggleGroupItem + text="Required" + buttonId="requiredOnly" + isSelected={requiredOnly} + onChange={(_, selected) => setRequiredOnly(selected)} + /> + <ToggleGroupItem + text="Changed" + buttonId="changedOnly" + isSelected={changedOnly} + onChange={(_, selected) => setChangedOnly(selected)} + /> + </ToggleGroup> + <TextInput + placeholder="filter by name" + value={propertyFilter} + onChange={(_, value) => setPropertyFilter(value)} + /> + </div> + ) + } + + function getPropertySelectorChanged(): boolean { + return requiredOnly || changedOnly || propertyFilter?.trim().length > 0; + } + + function getShowExpanded(): boolean { + return showAdvanced || getPropertySelectorChanged(); + } + return ( <div key={selectedStep ? selectedStep.uuid : 'integration'} className='properties'> <Form autoComplete="off" onSubmit={event => event.preventDefault()}> {selectedStep === undefined && <IntegrationHeader/>} {selectedStep && getComponentHeader()} + {selectedStep !== undefined && getPropertySelector()} {getPropertyFields(propertiesMain)} {selectedStep && !['MarshalDefinition', 'UnmarshalDefinition'].includes(selectedStep.dslName) && propertiesAdvanced.length > 0 && <ExpandableSection toggleText={'EIP advanced properties'} onToggle={(_event, isExpanded) => setShowAdvanced(!showAdvanced)} - isExpanded={showAdvanced}> + isExpanded={getShowExpanded()}> <div className="parameters"> {getPropertyFields(propertiesAdvanced)} </div> diff --git a/karavan-space/src/designer/property/property/ComponentPropertyField.tsx b/karavan-space/src/designer/property/property/ComponentPropertyField.tsx index 7669a114..262e2eb5 100644 --- a/karavan-space/src/designer/property/property/ComponentPropertyField.tsx +++ b/karavan-space/src/designer/property/property/ComponentPropertyField.tsx @@ -56,6 +56,7 @@ import EditorIcon from "@patternfly/react-icons/dist/js/icons/code-icon"; import {ExpressionModalEditor} from "../../../expression/ExpressionModalEditor"; import {PropertyPlaceholderDropdown} from "./PropertyPlaceholderDropdown"; import {INTERNAL_COMPONENTS} from "karavan-core/lib/api/ComponentApi"; +import {PropertyUtil} from "./PropertyUtil"; const prefix = "parameters"; const beanPrefix = "#bean:"; @@ -414,14 +415,9 @@ export function ComponentPropertyField(props: Props) { ) } - function hasValueChanged(property: ComponentProperty, value: any): boolean { - const isSet = value !== undefined; - const isDefault = property.defaultValue !== undefined && value?.toString() === property.defaultValue?.toString(); - return isSet && !isDefault; - } function getLabel(property: ComponentProperty, value: any) { - const bgColor = hasValueChanged(property, value) ? 'yellow' : 'transparent'; + const bgColor = PropertyUtil.hasComponentPropertyValueChanged(property, value) ? 'yellow' : 'transparent'; return ( <div style={{display: "flex", flexDirection: 'row', alignItems: 'center', gap: '3px'}}> <Text style={{backgroundColor: bgColor}}>{property.displayName}</Text> diff --git a/karavan-space/src/designer/property/property/DslPropertyField.tsx b/karavan-space/src/designer/property/property/DslPropertyField.tsx index b35ca3be..09f259f6 100644 --- a/karavan-space/src/designer/property/property/DslPropertyField.tsx +++ b/karavan-space/src/designer/property/property/DslPropertyField.tsx @@ -80,6 +80,9 @@ import {VariablesDropdown} from "./VariablesDropdown"; import {ROUTE, GLOBAL} from "karavan-core/lib/api/VariableUtil"; import {SpiBeanApi} from "karavan-core/lib/api/SpiBeanApi"; import {SelectField} from "./SelectField"; +import {PropertyUtil} from "./PropertyUtil"; +import {usePropertiesStore} from "../PropertyStore"; +import {Property} from "karavan-core/lib/model/KameletModels"; const beanPrefix = "#bean:"; const classPrefix = "#class:"; @@ -100,6 +103,7 @@ export function DslPropertyField(props: Props) { const [integration, setIntegration, addVariable, files] = useIntegrationStore((s) => [s.integration, s.setIntegration, s.addVariable, s.files], shallow) const [dark, setSelectedStep, beans] = useDesignerStore((s) => [s.dark, s.setSelectedStep, s.beans], shallow) + const [propertyFilter, changedOnly, requiredOnly] = usePropertiesStore((s) => [s.propertyFilter, s.changedOnly, s.requiredOnly], shallow) const [isShowAdvanced, setIsShowAdvanced] = useState<string[]>([]); const [arrayValues, setArrayValues] = useState<Map<string, string>>(new Map<string, string>()); @@ -204,14 +208,8 @@ export function DslPropertyField(props: Props) { return property.name === 'parameters' && property.description === 'parameters'; } - function hasValueChanged(property: PropertyMeta, value: any): boolean { - const isSet = value !== undefined && !['id', 'uri'].includes(property.name); - const isDefault = property.defaultValue !== undefined && value?.toString() === property.defaultValue?.toString(); - return isSet && !isDefault; - } - function getLabel(property: PropertyMeta, value: any, isKamelet: boolean) { - const bgColor = hasValueChanged(property, value) ? 'yellow' : 'transparent'; + const bgColor = PropertyUtil.hasDslPropertyValueChanged(property, value) ? 'yellow' : 'transparent'; if (!isMultiValueField(property) && property.isObject && !property.isArray && !["ExpressionDefinition"].includes(property.type)) { const tooltip = value ? "Delete " + property.name : "Add " + property.name; const className = value ? "change-button delete-button" : "change-button add-button"; @@ -906,32 +904,55 @@ export function DslPropertyField(props: Props) { ) } + function getKameletPropertyValue(property: Property) { + const element = props.element; + return CamelDefinitionApiExt.getParametersValue(element, property.id) + } + + function getFilteredKameletProperties(): Property[] { + const element = props.element; + const requiredParameters = CamelUtil.getKameletRequiredParameters(element); + let properties = CamelUtil.getKameletProperties(element) + const filter = propertyFilter.toLocaleLowerCase() + properties = properties.filter(p => p.title?.toLocaleLowerCase().includes(filter) || p.id?.toLocaleLowerCase().includes(filter)); + if (requiredOnly) { + properties = properties.filter(p => requiredParameters.includes(p.id)); + } + if (changedOnly) { + properties = properties.filter(p => PropertyUtil.hasKameletPropertyValueChanged(p, getKameletPropertyValue(p))); + } + return properties; + } + function getKameletParameters() { const element = props.element; const requiredParameters = CamelUtil.getKameletRequiredParameters(element); return ( <div className="parameters"> - {CamelUtil.getKameletProperties(element).map(property => + {getFilteredKameletProperties().map(property => <KameletPropertyField key={property.id} property={property} - value={CamelDefinitionApiExt.getParametersValue(element, property.id)} + value={getKameletPropertyValue(property)} required={requiredParameters?.includes(property.id)} />)} </div> ) } - function getMainComponentParameters(properties: ComponentProperty[]) { + function getComponentPropertyValue(kp: ComponentProperty) { const element = props.element; + return CamelDefinitionApiExt.getParametersValue(element, kp.name, kp.kind === 'path'); + } + + function getMainComponentParameters(properties: ComponentProperty[]) { return ( <div className="parameters"> {properties.map(kp => { - const value = CamelDefinitionApiExt.getParametersValue(element, kp.name, kp.kind === 'path'); return (<ComponentPropertyField key={kp.name} property={kp} - value={value} + value={getComponentPropertyValue(kp)} element={props.element} onParameterChange={props.onParameterChange} />) @@ -941,8 +962,6 @@ export function DslPropertyField(props: Props) { } function getExpandableComponentProperties(properties: ComponentProperty[], label: string) { - const element = props.element; - return ( <ExpandableSection toggleText={label} @@ -956,13 +975,13 @@ export function DslPropertyField(props: Props) { return prevState; }) }} - isExpanded={isShowAdvanced.includes(label)}> + isExpanded={getShowExpanded(label)}> <div className="parameters"> {properties.map(kp => <ComponentPropertyField key={kp.name} property={kp} - value={CamelDefinitionApiExt.getParametersValue(element, kp.name, kp.kind === 'path')} + value={getComponentPropertyValue(kp)} onParameterChange={props.onParameterChange} /> )} @@ -1012,9 +1031,30 @@ export function DslPropertyField(props: Props) { return ['string'].includes(property.type) && property.name !== 'expression' && property.isArray && !property.enumVals; } + function getFilteredComponentProperties(): ComponentProperty[] { + let props = CamelUtil.getComponentProperties(element); + const filter = propertyFilter.toLocaleLowerCase() + props = props.filter(p => p.name?.toLocaleLowerCase().includes(filter) || p.label.toLocaleLowerCase().includes(filter) || p.displayName.toLocaleLowerCase().includes(filter)); + if (requiredOnly) { + props = props.filter(p => p.required); + } + if (changedOnly) { + props = props.filter(p => PropertyUtil.hasComponentPropertyValueChanged(p, getComponentPropertyValue(p))); + } + return props + } + + function getPropertySelectorChanged(): boolean { + return requiredOnly || changedOnly || propertyFilter?.trim().length > 0; + } + + function getShowExpanded(label: string): boolean { + return isShowAdvanced.includes(label) || getPropertySelectorChanged(); + } + function getComponentParameters(property: PropertyMeta) { const element = props.element; - const properties = CamelUtil.getComponentProperties(element); + const properties = getFilteredComponentProperties(); 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")); diff --git a/karavan-space/src/designer/property/property/KameletPropertyField.tsx b/karavan-space/src/designer/property/property/KameletPropertyField.tsx index fe52431c..f9f1bf87 100644 --- a/karavan-space/src/designer/property/property/KameletPropertyField.tsx +++ b/karavan-space/src/designer/property/property/KameletPropertyField.tsx @@ -38,7 +38,6 @@ import EditorIcon from "@patternfly/react-icons/dist/js/icons/code-icon"; import {ExpressionModalEditor} from "../../../expression/ExpressionModalEditor"; import {useDesignerStore} from "../../DesignerStore"; import {shallow} from "zustand/shallow"; -import {ComponentProperty} from "../../../../../karavan-core/src/core/model/ComponentModels"; interface Props { property: Property,
