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 b2736628 Fix #1093 b2736628 is described below commit b2736628f11e45b4ceeef74ed6272c2d32331151 Author: Marat Gubaidullin <ma...@talismancloud.io> AuthorDate: Thu Feb 1 15:51:06 2024 -0500 Fix #1093 --- karavan-designer/src/DesignerPage.tsx | 5 +- karavan-designer/src/designer/KaravanDesigner.tsx | 2 + .../property/property/ComponentPropertyField.tsx | 6 +- .../ComponentPropertyPlaceholderDropdown.css | 13 +++ .../ComponentPropertyPlaceholderDropdown.tsx | 96 ++++++++++++++++++---- .../src/designer/route/RouteDesigner.tsx | 8 +- .../src/designer/utils/InfrastructureAPI.ts | 5 ++ karavan-vscode/src/designerView.ts | 3 + karavan-vscode/src/utils.ts | 9 ++ karavan-vscode/webview/App.tsx | 5 ++ .../main/webui/src/designer/KaravanDesigner.tsx | 2 + .../property/property/ComponentPropertyField.tsx | 6 +- .../ComponentPropertyPlaceholderDropdown.css | 13 +++ .../ComponentPropertyPlaceholderDropdown.tsx | 96 ++++++++++++++++++---- .../webui/src/designer/route/RouteDesigner.tsx | 8 +- .../webui/src/designer/utils/InfrastructureAPI.ts | 5 ++ .../src/main/webui/src/project/FileEditor.tsx | 13 ++- .../src/main/webui/src/util/StringUtils.ts | 10 ++- 18 files changed, 246 insertions(+), 59 deletions(-) diff --git a/karavan-designer/src/DesignerPage.tsx b/karavan-designer/src/DesignerPage.tsx index 125e3626..16e4efd8 100644 --- a/karavan-designer/src/DesignerPage.tsx +++ b/karavan-designer/src/DesignerPage.tsx @@ -78,9 +78,10 @@ export const DesignerPage = (props: Props) => { console.log(name1, code) }} propertyPlaceholders={[ - "timer.delay", - "sql.query" + // "timer.delay", + // "sql.query" ]} + onSavePropertyPlaceholder={(key, value) => console.log("onSavePropertyPlaceholder", key, value)} /> ) } diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx b/karavan-designer/src/designer/KaravanDesigner.tsx index 349ae548..7f201e4c 100644 --- a/karavan-designer/src/designer/KaravanDesigner.tsx +++ b/karavan-designer/src/designer/KaravanDesigner.tsx @@ -46,6 +46,7 @@ interface Props { onSave: (filename: string, yaml: string, propertyOnly: boolean) => void onSaveCustomCode: (name: string, code: string) => void onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined> + onSavePropertyPlaceholder: (key: string, value: string) => void filename: string yaml: string dark: boolean @@ -70,6 +71,7 @@ export function KaravanDesigner(props: Props) { InfrastructureAPI.setOnSaveCustomCode(props.onSaveCustomCode); InfrastructureAPI.setOnGetCustomCode(props.onGetCustomCode); InfrastructureAPI.setOnSave(props.onSave); + InfrastructureAPI.setOnSavePropertyPlaceholder(props.onSavePropertyPlaceholder); setSelectedStep(undefined); const i = makeIntegration(props.yaml, props.filename); diff --git a/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx b/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx index a25acafc..402aaf8b 100644 --- a/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx +++ b/karavan-designer/src/designer/property/property/ComponentPropertyField.tsx @@ -269,7 +269,7 @@ export function ComponentPropertyField(props: Props) { </Tooltip> } <InputGroupItem> - <ComponentPropertyPlaceholderDropdown property={property}/> + <ComponentPropertyPlaceholderDropdown property={property} value={value}/> </InputGroupItem> </InputGroup> } @@ -289,7 +289,7 @@ export function ComponentPropertyField(props: Props) { }}/> </InputGroupItem> <InputGroupItem> - <ComponentPropertyPlaceholderDropdown property={property}/> + <ComponentPropertyPlaceholderDropdown property={property} value={value}/> </InputGroupItem> </InputGroup> ) @@ -347,7 +347,7 @@ export function ComponentPropertyField(props: Props) { /> </InputGroupItem> <InputGroupItem> - <ComponentPropertyPlaceholderDropdown property={property}/> + <ComponentPropertyPlaceholderDropdown property={property} value={value}/> </InputGroupItem> </TextInputGroup> ) diff --git a/karavan-designer/src/designer/property/property/ComponentPropertyPlaceholderDropdown.css b/karavan-designer/src/designer/property/property/ComponentPropertyPlaceholderDropdown.css index 7d5d2d43..43991634 100644 --- a/karavan-designer/src/designer/property/property/ComponentPropertyPlaceholderDropdown.css +++ b/karavan-designer/src/designer/property/property/ComponentPropertyPlaceholderDropdown.css @@ -19,6 +19,19 @@ padding-left: 6px; padding-right: 6px; } + +.karavan .properties .property-placeholder-toggle .pf-v5-c-button__icon.pf-m-start { + margin-inline-end: 0; +} + .karavan .properties .property-placeholder-toggle .pf-v5-c-menu-toggle__controls { display: none; +} + +.pf-v5-c-popover .property-placeholder-toggle-form { + width: 300px; +} + +.pf-v5-c-popover .property-placeholder-toggle-form .pf-v5-c-form__group { + grid-template-columns: 1fr 2fr; } \ No newline at end of file diff --git a/karavan-designer/src/designer/property/property/ComponentPropertyPlaceholderDropdown.tsx b/karavan-designer/src/designer/property/property/ComponentPropertyPlaceholderDropdown.tsx index 270f9549..136f90fb 100644 --- a/karavan-designer/src/designer/property/property/ComponentPropertyPlaceholderDropdown.tsx +++ b/karavan-designer/src/designer/property/property/ComponentPropertyPlaceholderDropdown.tsx @@ -19,7 +19,7 @@ import { Dropdown, MenuToggleElement, MenuToggle, - DropdownList, DropdownItem + DropdownList, DropdownItem, Popover, Badge, TextVariants, Text, Flex, TextInput, FormGroup, Form, Button, FlexItem } from '@patternfly/react-core'; import '../../karavan.css'; import './ComponentPropertyPlaceholderDropdown.css'; @@ -30,25 +30,99 @@ import {usePropertiesHook} from "../usePropertiesHook"; import {useDesignerStore} from "../../DesignerStore"; import {shallow} from "zustand/shallow"; import EllipsisVIcon from "@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon"; - +import AddIcon from "@patternfly/react-icons/dist/js/icons/plus-icon"; +import {InfrastructureAPI} from "../../utils/InfrastructureAPI"; interface Props { property: ComponentProperty, + value: any } export function ComponentPropertyPlaceholderDropdown(props: Props) { const {onParametersChange} = usePropertiesHook(); - const [propertyPlaceholders] = useDesignerStore((s) => [s.propertyPlaceholders], shallow) + const [propertyPlaceholders, setPropertyPlaceholders] = useDesignerStore((s) => + [s.propertyPlaceholders, s.setPropertyPlaceholders], shallow) const [isOpenPlaceholdersDropdown, setOpenPlaceholdersDropdown] = useState<boolean>(false); + const [propValue, setPropValue] = useState<string>(''); + const [isVisible, setIsVisible] = React.useState(false); + + const {property, value} = props; + const valueIsPlaceholder: boolean = value && value.toString().startsWith('{{') && value.toString().endsWith('}}'); + const placeholderValue = valueIsPlaceholder ? value.toString().replace('{{', '').replace('}}', '') : undefined; + const showAddButton = valueIsPlaceholder && !propertyPlaceholders.includes(placeholderValue); + const popoverId = "popover-selector-" + property.name; function parametersChanged(parameter: string, value: string | number | boolean | any, pathParameter?: boolean, newRoute?: RouteToCreate) { onParametersChange(parameter, value, pathParameter, newRoute); } - const property: ComponentProperty = props.property; + function onMenuToggleClick() { + if (!showAddButton) { + setOpenPlaceholdersDropdown(!isOpenPlaceholdersDropdown) + } + } + + function saveProperty() { + InfrastructureAPI.onSavePropertyPlaceholder(placeholderValue, propValue); + setIsVisible(false); + const p = [...propertyPlaceholders] + p.push(placeholderValue); + setPropertyPlaceholders(p); + } + + function getPopover() { + return ( + <Popover + isVisible={isVisible} + shouldOpen={(_event, _fn) => setIsVisible(true)} + shouldClose={(_event, _fn) => setIsVisible(false)} + aria-label="Add property" + headerContent={"Add property"} + bodyContent={ + <Form isHorizontal className="property-placeholder-toggle-form" autoComplete="off"> + <FormGroup isInline label="Property" isRequired fieldId="property"> + <TextInput id="property" readOnly value={placeholderValue}/> + </FormGroup> + <FormGroup isInline label="Value" isRequired fieldId="value"> + <TextInput id="value" isRequired value={propValue} + onChange={(_, value) => setPropValue(value)}/> + </FormGroup> + </Form> + } + footerContent={ + <Flex> + <FlexItem align={{default: "alignRight"}}> + <Button + onClick={() => saveProperty()}> + Save + </Button> + </FlexItem> + </Flex> + } + triggerRef={() => document.getElementById(popoverId) as HTMLButtonElement} + /> + ) + } + + function getToggle(toggleRef: React.Ref<MenuToggleElement>) { + return ( + <MenuToggle className="property-placeholder-toggle" + id={popoverId} + ref={toggleRef} + aria-label="placeholder menu" + variant="default" + onClick={() => onMenuToggleClick()} + isExpanded={isOpenPlaceholdersDropdown} + > + {showAddButton ? <AddIcon/> : <EllipsisVIcon/>} + {showAddButton && getPopover()} + </MenuToggle> + ) + } + return ( - propertyPlaceholders && propertyPlaceholders.length > 0 ? + (propertyPlaceholders && propertyPlaceholders.length > 0 ) || showAddButton ? <Dropdown popperProps={{position: "end"}} isOpen={isOpenPlaceholdersDropdown} @@ -57,17 +131,7 @@ export function ComponentPropertyPlaceholderDropdown(props: Props) { setOpenPlaceholdersDropdown(false); }} onOpenChange={(isOpen: boolean) => setOpenPlaceholdersDropdown(isOpen)} - toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( - <MenuToggle className="property-placeholder-toggle" - ref={toggleRef} - aria-label="placeholder menu" - variant="default" - onClick={() => setOpenPlaceholdersDropdown(!isOpenPlaceholdersDropdown)} - isExpanded={isOpenPlaceholdersDropdown} - > - <EllipsisVIcon/> - </MenuToggle> - )} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => getToggle(toggleRef)} shouldFocusToggleOnSelect > <DropdownList> diff --git a/karavan-designer/src/designer/route/RouteDesigner.tsx b/karavan-designer/src/designer/route/RouteDesigner.tsx index c2ebf292..7a36f814 100644 --- a/karavan-designer/src/designer/route/RouteDesigner.tsx +++ b/karavan-designer/src/designer/route/RouteDesigner.tsx @@ -40,7 +40,7 @@ import {DslElementMoveModal} from "./element/DslElementMoveModal"; export function RouteDesigner() { - const {openSelector, createRouteConfiguration, onCommand, handleKeyDown, handleKeyUp, unselectElement, onDslSelect, + const {openSelector, createRouteConfiguration, onCommand, unselectElement, onDslSelect, isSourceKamelet, isActionKamelet, isKamelet, isSinkKamelet} = useRouteDesignerHook(); const [integration] = useIntegrationStore((state) => [state.integration], shallow) @@ -72,12 +72,9 @@ export function RouteDesigner() { const flowRef = useRef<HTMLDivElement | null>(null); useEffect(()=> { - // window.addEventListener('resize', changeGraphSize); const interval = setInterval(() => { changeGraphSize(); }, 500); - window.addEventListener('keydown', handleKeyDown); - window.addEventListener('keyup', handleKeyUp); const commandSub = EventBus.onCommand()?.subscribe((command: Command) => onCommand(command, printerRef)); if (flowRef.current === null) { clearSteps(); @@ -86,9 +83,6 @@ export function RouteDesigner() { } return ()=> { clearInterval(interval) - // window.removeEventListener('resize', changeGraphSize); - window.removeEventListener('keydown', handleKeyDown); - window.removeEventListener('keyup', handleKeyUp); commandSub?.unsubscribe(); } }, [showSelector, integration]) diff --git a/karavan-designer/src/designer/utils/InfrastructureAPI.ts b/karavan-designer/src/designer/utils/InfrastructureAPI.ts index f0d8faef..c2d5ca7c 100644 --- a/karavan-designer/src/designer/utils/InfrastructureAPI.ts +++ b/karavan-designer/src/designer/utils/InfrastructureAPI.ts @@ -20,6 +20,7 @@ export class InfrastructureAPI { static onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined>; static onSaveCustomCode: (name: string, code: string) => void; static onSave: (filename: string, yaml: string, propertyOnly: boolean) => void; + static onSavePropertyPlaceholder: (key: string, value: string) => void; static setOnGetCustomCode(onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined>){ this.onGetCustomCode = onGetCustomCode @@ -33,6 +34,10 @@ export class InfrastructureAPI { this.onSave = onSave } + static setOnSavePropertyPlaceholder(onSavePropertyPlaceholder:(key: string, value: string) => void){ + this.onSavePropertyPlaceholder = onSavePropertyPlaceholder + } + // Kubernetes/Docker API static infrastructure: 'kubernetes' | 'docker' | 'local' = 'local'; static configMaps: string[] = []; diff --git a/karavan-vscode/src/designerView.ts b/karavan-vscode/src/designerView.ts index 1f6879de..2b4da788 100644 --- a/karavan-vscode/src/designerView.ts +++ b/karavan-vscode/src/designerView.ts @@ -133,6 +133,9 @@ export class DesignerView { case 'saveCode': utils.saveCode(message.name, message.yamlFullPath, message.yamFileName, message.code); break; + case 'savePropertyPlaceholder': + utils.savePropertyPlaceholder(message.key, message.value); + break; case 'getData': this.sendData(panel, filename, relativePath, fullPath, message.reread === true, yaml, tab); break; diff --git a/karavan-vscode/src/utils.ts b/karavan-vscode/src/utils.ts index 6cb7083b..8462cbc4 100644 --- a/karavan-vscode/src/utils.ts +++ b/karavan-vscode/src/utils.ts @@ -38,6 +38,15 @@ export function saveCode(name: string, yamlFullPath: string, yamFileName: string } } +export async function savePropertyPlaceholder(key: string, value: string) { + if (workspace.workspaceFolders) { + const uriFolder: Uri = workspace.workspaceFolders[0].uri; + const properties = await getProperties(); + const text = properties.concat('\n').concat(key).concat('=').concat(value); + write(path.join(uriFolder.path, "application.properties"), text); + } +} + export function deleteFile(fullPath: string) { if (workspace.workspaceFolders) { const uriFile: Uri = Uri.file(path.resolve(fullPath)); diff --git a/karavan-vscode/webview/App.tsx b/karavan-vscode/webview/App.tsx index e539d7f1..7611f8fb 100644 --- a/karavan-vscode/webview/App.tsx +++ b/karavan-vscode/webview/App.tsx @@ -189,6 +189,10 @@ class App extends React.Component<Props, State> { vscode.postMessage({ command: 'saveCode', name: name, yamlFullPath: this.state.fullPath, yamFileName: this.state.filename, code: code }); } + savePropertyPlaceholder(key: string, value: string) { + vscode.postMessage({ command: 'savePropertyPlaceholder', key: key, value: value }); + } + saveIntegrationFiles(files: any) { const f = Object.keys(files).map(key => new IntegrationFile(key, files[key])); this.setState({ files: f }); @@ -223,6 +227,7 @@ class App extends React.Component<Props, State> { return new Promise<string | undefined>(resolve => resolve(code)) }} propertyPlaceholders={this.state.propertyPlaceholders} + onSavePropertyPlaceholder={(key, value) => this.savePropertyPlaceholder(key, value)} /> } {loaded && page === "knowledgebase" && <KnowledgebasePage dark={dark} />} diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx b/karavan-web/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx index 349ae548..7f201e4c 100644 --- a/karavan-web/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx @@ -46,6 +46,7 @@ interface Props { onSave: (filename: string, yaml: string, propertyOnly: boolean) => void onSaveCustomCode: (name: string, code: string) => void onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined> + onSavePropertyPlaceholder: (key: string, value: string) => void filename: string yaml: string dark: boolean @@ -70,6 +71,7 @@ export function KaravanDesigner(props: Props) { InfrastructureAPI.setOnSaveCustomCode(props.onSaveCustomCode); InfrastructureAPI.setOnGetCustomCode(props.onGetCustomCode); InfrastructureAPI.setOnSave(props.onSave); + InfrastructureAPI.setOnSavePropertyPlaceholder(props.onSavePropertyPlaceholder); setSelectedStep(undefined); const i = makeIntegration(props.yaml, props.filename); diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyField.tsx b/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyField.tsx index a25acafc..402aaf8b 100644 --- a/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyField.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyField.tsx @@ -269,7 +269,7 @@ export function ComponentPropertyField(props: Props) { </Tooltip> } <InputGroupItem> - <ComponentPropertyPlaceholderDropdown property={property}/> + <ComponentPropertyPlaceholderDropdown property={property} value={value}/> </InputGroupItem> </InputGroup> } @@ -289,7 +289,7 @@ export function ComponentPropertyField(props: Props) { }}/> </InputGroupItem> <InputGroupItem> - <ComponentPropertyPlaceholderDropdown property={property}/> + <ComponentPropertyPlaceholderDropdown property={property} value={value}/> </InputGroupItem> </InputGroup> ) @@ -347,7 +347,7 @@ export function ComponentPropertyField(props: Props) { /> </InputGroupItem> <InputGroupItem> - <ComponentPropertyPlaceholderDropdown property={property}/> + <ComponentPropertyPlaceholderDropdown property={property} value={value}/> </InputGroupItem> </TextInputGroup> ) diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyPlaceholderDropdown.css b/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyPlaceholderDropdown.css index 7d5d2d43..43991634 100644 --- a/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyPlaceholderDropdown.css +++ b/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyPlaceholderDropdown.css @@ -19,6 +19,19 @@ padding-left: 6px; padding-right: 6px; } + +.karavan .properties .property-placeholder-toggle .pf-v5-c-button__icon.pf-m-start { + margin-inline-end: 0; +} + .karavan .properties .property-placeholder-toggle .pf-v5-c-menu-toggle__controls { display: none; +} + +.pf-v5-c-popover .property-placeholder-toggle-form { + width: 300px; +} + +.pf-v5-c-popover .property-placeholder-toggle-form .pf-v5-c-form__group { + grid-template-columns: 1fr 2fr; } \ No newline at end of file diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyPlaceholderDropdown.tsx b/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyPlaceholderDropdown.tsx index 270f9549..136f90fb 100644 --- a/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyPlaceholderDropdown.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/designer/property/property/ComponentPropertyPlaceholderDropdown.tsx @@ -19,7 +19,7 @@ import { Dropdown, MenuToggleElement, MenuToggle, - DropdownList, DropdownItem + DropdownList, DropdownItem, Popover, Badge, TextVariants, Text, Flex, TextInput, FormGroup, Form, Button, FlexItem } from '@patternfly/react-core'; import '../../karavan.css'; import './ComponentPropertyPlaceholderDropdown.css'; @@ -30,25 +30,99 @@ import {usePropertiesHook} from "../usePropertiesHook"; import {useDesignerStore} from "../../DesignerStore"; import {shallow} from "zustand/shallow"; import EllipsisVIcon from "@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon"; - +import AddIcon from "@patternfly/react-icons/dist/js/icons/plus-icon"; +import {InfrastructureAPI} from "../../utils/InfrastructureAPI"; interface Props { property: ComponentProperty, + value: any } export function ComponentPropertyPlaceholderDropdown(props: Props) { const {onParametersChange} = usePropertiesHook(); - const [propertyPlaceholders] = useDesignerStore((s) => [s.propertyPlaceholders], shallow) + const [propertyPlaceholders, setPropertyPlaceholders] = useDesignerStore((s) => + [s.propertyPlaceholders, s.setPropertyPlaceholders], shallow) const [isOpenPlaceholdersDropdown, setOpenPlaceholdersDropdown] = useState<boolean>(false); + const [propValue, setPropValue] = useState<string>(''); + const [isVisible, setIsVisible] = React.useState(false); + + const {property, value} = props; + const valueIsPlaceholder: boolean = value && value.toString().startsWith('{{') && value.toString().endsWith('}}'); + const placeholderValue = valueIsPlaceholder ? value.toString().replace('{{', '').replace('}}', '') : undefined; + const showAddButton = valueIsPlaceholder && !propertyPlaceholders.includes(placeholderValue); + const popoverId = "popover-selector-" + property.name; function parametersChanged(parameter: string, value: string | number | boolean | any, pathParameter?: boolean, newRoute?: RouteToCreate) { onParametersChange(parameter, value, pathParameter, newRoute); } - const property: ComponentProperty = props.property; + function onMenuToggleClick() { + if (!showAddButton) { + setOpenPlaceholdersDropdown(!isOpenPlaceholdersDropdown) + } + } + + function saveProperty() { + InfrastructureAPI.onSavePropertyPlaceholder(placeholderValue, propValue); + setIsVisible(false); + const p = [...propertyPlaceholders] + p.push(placeholderValue); + setPropertyPlaceholders(p); + } + + function getPopover() { + return ( + <Popover + isVisible={isVisible} + shouldOpen={(_event, _fn) => setIsVisible(true)} + shouldClose={(_event, _fn) => setIsVisible(false)} + aria-label="Add property" + headerContent={"Add property"} + bodyContent={ + <Form isHorizontal className="property-placeholder-toggle-form" autoComplete="off"> + <FormGroup isInline label="Property" isRequired fieldId="property"> + <TextInput id="property" readOnly value={placeholderValue}/> + </FormGroup> + <FormGroup isInline label="Value" isRequired fieldId="value"> + <TextInput id="value" isRequired value={propValue} + onChange={(_, value) => setPropValue(value)}/> + </FormGroup> + </Form> + } + footerContent={ + <Flex> + <FlexItem align={{default: "alignRight"}}> + <Button + onClick={() => saveProperty()}> + Save + </Button> + </FlexItem> + </Flex> + } + triggerRef={() => document.getElementById(popoverId) as HTMLButtonElement} + /> + ) + } + + function getToggle(toggleRef: React.Ref<MenuToggleElement>) { + return ( + <MenuToggle className="property-placeholder-toggle" + id={popoverId} + ref={toggleRef} + aria-label="placeholder menu" + variant="default" + onClick={() => onMenuToggleClick()} + isExpanded={isOpenPlaceholdersDropdown} + > + {showAddButton ? <AddIcon/> : <EllipsisVIcon/>} + {showAddButton && getPopover()} + </MenuToggle> + ) + } + return ( - propertyPlaceholders && propertyPlaceholders.length > 0 ? + (propertyPlaceholders && propertyPlaceholders.length > 0 ) || showAddButton ? <Dropdown popperProps={{position: "end"}} isOpen={isOpenPlaceholdersDropdown} @@ -57,17 +131,7 @@ export function ComponentPropertyPlaceholderDropdown(props: Props) { setOpenPlaceholdersDropdown(false); }} onOpenChange={(isOpen: boolean) => setOpenPlaceholdersDropdown(isOpen)} - toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( - <MenuToggle className="property-placeholder-toggle" - ref={toggleRef} - aria-label="placeholder menu" - variant="default" - onClick={() => setOpenPlaceholdersDropdown(!isOpenPlaceholdersDropdown)} - isExpanded={isOpenPlaceholdersDropdown} - > - <EllipsisVIcon/> - </MenuToggle> - )} + toggle={(toggleRef: React.Ref<MenuToggleElement>) => getToggle(toggleRef)} shouldFocusToggleOnSelect > <DropdownList> diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/route/RouteDesigner.tsx b/karavan-web/karavan-app/src/main/webui/src/designer/route/RouteDesigner.tsx index c2ebf292..7a36f814 100644 --- a/karavan-web/karavan-app/src/main/webui/src/designer/route/RouteDesigner.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/designer/route/RouteDesigner.tsx @@ -40,7 +40,7 @@ import {DslElementMoveModal} from "./element/DslElementMoveModal"; export function RouteDesigner() { - const {openSelector, createRouteConfiguration, onCommand, handleKeyDown, handleKeyUp, unselectElement, onDslSelect, + const {openSelector, createRouteConfiguration, onCommand, unselectElement, onDslSelect, isSourceKamelet, isActionKamelet, isKamelet, isSinkKamelet} = useRouteDesignerHook(); const [integration] = useIntegrationStore((state) => [state.integration], shallow) @@ -72,12 +72,9 @@ export function RouteDesigner() { const flowRef = useRef<HTMLDivElement | null>(null); useEffect(()=> { - // window.addEventListener('resize', changeGraphSize); const interval = setInterval(() => { changeGraphSize(); }, 500); - window.addEventListener('keydown', handleKeyDown); - window.addEventListener('keyup', handleKeyUp); const commandSub = EventBus.onCommand()?.subscribe((command: Command) => onCommand(command, printerRef)); if (flowRef.current === null) { clearSteps(); @@ -86,9 +83,6 @@ export function RouteDesigner() { } return ()=> { clearInterval(interval) - // window.removeEventListener('resize', changeGraphSize); - window.removeEventListener('keydown', handleKeyDown); - window.removeEventListener('keyup', handleKeyUp); commandSub?.unsubscribe(); } }, [showSelector, integration]) diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/utils/InfrastructureAPI.ts b/karavan-web/karavan-app/src/main/webui/src/designer/utils/InfrastructureAPI.ts index f0d8faef..c2d5ca7c 100644 --- a/karavan-web/karavan-app/src/main/webui/src/designer/utils/InfrastructureAPI.ts +++ b/karavan-web/karavan-app/src/main/webui/src/designer/utils/InfrastructureAPI.ts @@ -20,6 +20,7 @@ export class InfrastructureAPI { static onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined>; static onSaveCustomCode: (name: string, code: string) => void; static onSave: (filename: string, yaml: string, propertyOnly: boolean) => void; + static onSavePropertyPlaceholder: (key: string, value: string) => void; static setOnGetCustomCode(onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined>){ this.onGetCustomCode = onGetCustomCode @@ -33,6 +34,10 @@ export class InfrastructureAPI { this.onSave = onSave } + static setOnSavePropertyPlaceholder(onSavePropertyPlaceholder:(key: string, value: string) => void){ + this.onSavePropertyPlaceholder = onSavePropertyPlaceholder + } + // Kubernetes/Docker API static infrastructure: 'kubernetes' | 'docker' | 'local' = 'local'; static configMaps: string[] = []; diff --git a/karavan-web/karavan-app/src/main/webui/src/project/FileEditor.tsx b/karavan-web/karavan-app/src/main/webui/src/project/FileEditor.tsx index 6fe00b39..e5bece48 100644 --- a/karavan-web/karavan-app/src/main/webui/src/project/FileEditor.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/project/FileEditor.tsx @@ -24,7 +24,7 @@ import {KaravanDesigner} from "../designer/KaravanDesigner"; import {ProjectService} from "../api/ProjectService"; import {shallow} from "zustand/shallow"; import {KaravanApi} from "../api/KaravanApi"; -import {getPropertyPlaceholders} from "../util/StringUtils"; +import {getPropertyCode, getPropertyPlaceholders} from "../util/StringUtils"; interface Props { projectId: string @@ -59,10 +59,18 @@ export function FileEditor (props: Props) { } function onGetCustomCode (name: string, javaType: string): Promise<string | undefined> { - const files = useFilesStore.getState().files; return new Promise<string | undefined>(resolve => resolve(files.filter(f => f.name === name + ".java")?.at(0)?.code)); } + function onSavePropertyPlaceholder (key: string, value: string) { + const file = files.filter(f => f.name === 'application.properties')?.at(0); + const code = file?.code?.concat('\n').concat(key).concat('=').concat(value); + if (file && code) { + file.code = code; + ProjectService.updateFile(file, false); + } + } + function getDesigner () { return ( file !== undefined && @@ -77,6 +85,7 @@ export function FileEditor (props: Props) { ProjectService.updateFile(new ProjectFile(name + ".java", props.projectId, code, Date.now()), false)} onGetCustomCode={onGetCustomCode} propertyPlaceholders={propertyPlaceholders} + onSavePropertyPlaceholder={onSavePropertyPlaceholder} /> ) } diff --git a/karavan-web/karavan-app/src/main/webui/src/util/StringUtils.ts b/karavan-web/karavan-app/src/main/webui/src/util/StringUtils.ts index 6b8a8986..026dc7a1 100644 --- a/karavan-web/karavan-app/src/main/webui/src/util/StringUtils.ts +++ b/karavan-web/karavan-app/src/main/webui/src/util/StringUtils.ts @@ -6,9 +6,8 @@ export function isEmpty(str: string) { export function getPropertyPlaceholders(files: ProjectFile[]): string[] { const result: string[] = [] - const file = files.filter(f => f.name === 'application.properties')?.at(0); - if (file) { - const code = file.code; + const code = getPropertyCode(files); + if (code) { const lines = code.split('\n').map((line) => line.trim()); lines .filter(line => !line.startsWith("camel.") && !line.startsWith("jkube.") && !line.startsWith("jib.")) @@ -21,4 +20,9 @@ export function getPropertyPlaceholders(files: ProjectFile[]): string[] { }) } return result; +} + +export function getPropertyCode(files: ProjectFile[]) { + const file = files.filter(f => f.name === 'application.properties')?.at(0); + return file?.code; } \ No newline at end of file