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 f57f88aa8cc26845ca8942a6e3671c0bb1de8e55 Author: Marat Gubaidullin <[email protected]> AuthorDate: Fri Feb 27 19:01:01 2026 -0500 Fron-end fixes for 4.18.0 --- .../project/designer/editor/CodeEditor.tsx | 69 ------------- .../project/designer/kamelet/KameletDesigner.tsx | 3 - .../project/designer/rest/RestMethodSelector.tsx | 2 - .../project/designer/selector/DslFastCard.tsx | 8 +- .../features/project/developer/DeveloperEditor.tsx | 7 +- .../developer/MonacoEditorWrapperStateless.tsx | 113 --------------------- .../project/project-topology/TopologyApi.tsx | 68 ------------- .../karavan/features/projects/SettingsToolbar.tsx | 3 +- .../webui/src/karavan/services/ProjectService.ts | 1 - .../webui/src/karavan/shared/ui/PlatformLogos.tsx | 13 --- .../src/karavan/shared/ui/SideBarFormWrapper.tsx | 84 --------------- .../src/main/webui/src/karavan/util/CodeUtils.ts | 105 ------------------- 12 files changed, 3 insertions(+), 473 deletions(-) diff --git a/karavan-app/src/main/webui/src/karavan/features/project/designer/editor/CodeEditor.tsx b/karavan-app/src/main/webui/src/karavan/features/project/designer/editor/CodeEditor.tsx deleted file mode 100644 index 3be551c9..00000000 --- a/karavan-app/src/main/webui/src/karavan/features/project/designer/editor/CodeEditor.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 React, {useEffect, useState} from 'react'; -import '@shared/monaco-setup'; -import Editor from "@monaco-editor/react"; -import {shallow} from "zustand/shallow"; -import {useDesignerStore, useIntegrationStore} from "../DesignerStore"; -import {CamelDefinitionYaml} from "@karavan-core/api/CamelDefinitionYaml"; -import {CamelUtil} from "@karavan-core/api/CamelUtil"; - -export function CodeEditor () { - - const [integration, setIntegration] = useIntegrationStore((s) => [s.integration, s.setIntegration], shallow); - const [setNotification, badge] = useDesignerStore((s) => [s.setNotification, s.notificationBadge], shallow) - const [code, setCode] = useState<string>(''); - - useEffect(() => { - try { - const clone = CamelUtil.cloneIntegration(integration); - const c = CamelDefinitionYaml.integrationToYaml(clone); - setCode(c); - } catch (e: any) { - const message: string = e?.message ? e.message : e.reason; - setNotification(true, ['Error in YAML, Integration can not be saved!', message]); - } - return () => { - setNotification(false, ['', '']); - } - }, []); - - function onChange(value: string | undefined) { - if (value) { - try { - const i = CamelDefinitionYaml.yamlToIntegration(integration.metadata.name, value); - setIntegration(i, false); - setNotification(false, ['', '']); - } catch (e: any) { - const message: string = e?.message ? e.message : e.reason; - setNotification(true, ['Error in YAML, Integration can not be saved!' ,message]); - } - } - } - - return ( - <Editor - height="100vh" - defaultLanguage={'yaml'} - theme={'light'} - value={code} - className={'code-editor'} - defaultValue={code} - onChange={(value, ev) => onChange(value)} - /> - ) -} diff --git a/karavan-app/src/main/webui/src/karavan/features/project/designer/kamelet/KameletDesigner.tsx b/karavan-app/src/main/webui/src/karavan/features/project/designer/kamelet/KameletDesigner.tsx index 728d4689..f045f8b4 100644 --- a/karavan-app/src/main/webui/src/karavan/features/project/designer/kamelet/KameletDesigner.tsx +++ b/karavan-app/src/main/webui/src/karavan/features/project/designer/kamelet/KameletDesigner.tsx @@ -15,9 +15,6 @@ * limitations under the License. */ import React from 'react'; -import { - PageSection, -} from '@patternfly/react-core'; import '@features/project/designer/karavan.css'; import './kamelet.css'; import {KameletAnnotationsPanel} from "./KameletAnnotationsPanel"; diff --git a/karavan-app/src/main/webui/src/karavan/features/project/designer/rest/RestMethodSelector.tsx b/karavan-app/src/main/webui/src/karavan/features/project/designer/rest/RestMethodSelector.tsx index 1702925f..a4e525ea 100644 --- a/karavan-app/src/main/webui/src/karavan/features/project/designer/rest/RestMethodSelector.tsx +++ b/karavan-app/src/main/webui/src/karavan/features/project/designer/rest/RestMethodSelector.tsx @@ -18,8 +18,6 @@ import React from 'react'; import {Badge, Card, CardBody, CardFooter, CardHeader, Content, Gallery} from '@patternfly/react-core'; import {CamelUi} from "../utils/CamelUi"; import {DslMetaModel} from "../utils/DslMetaModel"; -import {useDesignerStore} from "../DesignerStore"; -import {shallow} from "zustand/shallow"; interface Props { onMethodSelect: (method: DslMetaModel) => void diff --git a/karavan-app/src/main/webui/src/karavan/features/project/designer/selector/DslFastCard.tsx b/karavan-app/src/main/webui/src/karavan/features/project/designer/selector/DslFastCard.tsx index be3d1ae8..2ecd0161 100644 --- a/karavan-app/src/main/webui/src/karavan/features/project/designer/selector/DslFastCard.tsx +++ b/karavan-app/src/main/webui/src/karavan/features/project/designer/selector/DslFastCard.tsx @@ -15,13 +15,7 @@ * limitations under the License. */ import React from 'react'; -import { - Button, - Card, - CardBody, - CardHeader, - Content, -} from '@patternfly/react-core'; +import {Button, Content,} from '@patternfly/react-core'; import './DslSelector.css'; import {CamelUi} from "../utils/CamelUi"; import {DslMetaModel} from "../utils/DslMetaModel"; diff --git a/karavan-app/src/main/webui/src/karavan/features/project/developer/DeveloperEditor.tsx b/karavan-app/src/main/webui/src/karavan/features/project/developer/DeveloperEditor.tsx index 28edfdbc..93e847e3 100644 --- a/karavan-app/src/main/webui/src/karavan/features/project/developer/DeveloperEditor.tsx +++ b/karavan-app/src/main/webui/src/karavan/features/project/developer/DeveloperEditor.tsx @@ -4,13 +4,10 @@ import {MarkdownEditor} from "@features/project/developer/MarkdownEditor"; import './DeveloperManager.css' import {EditorErrorBoundaryWrapper} from "@features/project/developer/EditorErrorBoundaryWrapper"; import {EditorType} from "@features/project/developer/EditorConfig"; -import {useFilesStore, useFileStore} from "@stores/ProjectStore"; +import {useFileStore} from "@stores/ProjectStore"; import {shallow} from "zustand/shallow"; import {useDesignerStore} from "@features/project/designer/DesignerStore"; import {ProjectService} from "@services/ProjectService"; -import type * as monaco from "monaco-editor"; -import {useNavigate} from "react-router-dom"; -import {ROUTES} from "@app/navigation/Routes"; export interface DeveloperEditorProps { editorType: EditorType; @@ -21,9 +18,7 @@ export function DeveloperEditor(props: DeveloperEditorProps): JSX.Element { const {editorType} = props const [setDesignerSwitch] = useDesignerStore((s) => [s.setDesignerSwitch], shallow) const [file, setFile] = useFileStore((s) => [s.file, s.setFile], shallow) - const [files] = useFilesStore((s) => [s.files], shallow); const [code, setCode] = useState<string>(""); - const navigate = useNavigate(); useEffect(() => { setDesignerSwitch(false); diff --git a/karavan-app/src/main/webui/src/karavan/features/project/developer/MonacoEditorWrapperStateless.tsx b/karavan-app/src/main/webui/src/karavan/features/project/developer/MonacoEditorWrapperStateless.tsx deleted file mode 100644 index 6bd874ee..00000000 --- a/karavan-app/src/main/webui/src/karavan/features/project/developer/MonacoEditorWrapperStateless.tsx +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 React, {useEffect, useRef, useState} from "react"; -import '@shared/monaco-setup'; -import type * as monaco from "monaco-editor"; -import Editor, {OnMount} from "@monaco-editor/react"; -import {useTheme} from "@app/theme/ThemeContext"; -import {useDebounceValue} from "usehooks-ts"; -import {defaultEditorOptions} from "@features/project/developer/EditorConfig"; - -const MIN_HEIGHT = 100; // px -const MAX_HEIGHT = 400; // px - -export interface MonacoEditorProps { - language: string; - onChange?: (value: string | undefined) => void; - onDidBlurEditorText?: () => void; - editorOptions?: monaco.editor.IStandaloneEditorConstructionOptions; - height?: string; - width?: string; - initialCode: string; - completionProvider?: monaco.languages.CompletionItemProvider; -} - -export const MonacoEditorWrapperStateless: React.FC<MonacoEditorProps> = ({ - language, - onChange, - editorOptions, - height, - width = "100%", - completionProvider, initialCode,onDidBlurEditorText - }) => { - const {isDark} = useTheme(); - const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null); - const providerRefCompletionItem = useRef<monaco.IDisposable | null>(null); - const [autoHeight, setAutoHeight] = useState(MIN_HEIGHT); - const [code, setCode] = useState<string | undefined>(initialCode); - const [debouncedCode] = useDebounceValue(code, 300); - - useEffect(() => { - return () => disposeRefs(); - }, []) - - useEffect(() => { - onChange?.(debouncedCode); - }, [debouncedCode]); - - useEffect(() => { - return () => disposeRefs(); - }, []) - - function disposeRefs() { - providerRefCompletionItem.current?.dispose(); - } - - const handleEditorWillMount = (monacoInstance: typeof monaco) => { - if (completionProvider) { - disposeRefs(); - monacoInstance.languages.registerCompletionItemProvider(language, completionProvider); - } - }; - - const handleEditorDidMount: OnMount = (editor, monacoInstance) => { - editorRef.current = editor; - resizeEditor(); - - editor.onDidContentSizeChange(() => { - resizeEditor(); - }); - - editor.onDidBlurEditorText(() => { - onDidBlurEditorText?.() - }); - }; - - const resizeEditor = () => { - if (!editorRef.current) return; - - const contentHeight = editorRef.current.getContentHeight(); - const newHeight = Math.max(MIN_HEIGHT, Math.min(MAX_HEIGHT, contentHeight)); - - setAutoHeight(newHeight); - editorRef.current.layout({width: editorRef.current.getLayoutInfo().width, height: newHeight}); - }; - - return ( - <Editor className={'monaco-editor-wrapper-stateless'} - defaultLanguage={language} - value={code} - onChange={(value, ev) => setCode(value)} - options={editorOptions || defaultEditorOptions} - height={height ?? autoHeight} - width={width} - theme={isDark ? 'vs-dark' : 'light'} - beforeMount={handleEditorWillMount} - onMount={handleEditorDidMount} - /> - ); -}; diff --git a/karavan-app/src/main/webui/src/karavan/features/project/project-topology/TopologyApi.tsx b/karavan-app/src/main/webui/src/karavan/features/project/project-topology/TopologyApi.tsx index cfb80842..f5d87cba 100644 --- a/karavan-app/src/main/webui/src/karavan/features/project/project-topology/TopologyApi.tsx +++ b/karavan-app/src/main/webui/src/karavan/features/project/project-topology/TopologyApi.tsx @@ -361,74 +361,6 @@ export function getOpenApiNodes(topenapis: TopologyOpenApiNode[], showStats?: bo }); } -export function getAsyncApiNodes(tasyncapis: TopologyAsyncApiNode[]): NodeModel[] { - const result: NodeModel[] = []; - tasyncapis.forEach(tasyncapi => { - // const node = { - // id: tasyncapi.fileName, - // type: 'node', - // label: tasyncapi.title, - // width: NODE_DIAMETER_ROUTE, - // height: NODE_DIAMETER_ROUTE, - // shape: NodeShape.circle, - // status: NodeStatus.default, - // data: { - // isAlternate: false, - // badge: 'AsyncAPI', - // icon: 'asyncapi', - // type: 'asyncapi', - // // step: tin.rest, - // fileName: tasyncapi.fileName, - // secondaryLabel: tasyncapi.title, - // } - // } as NodeModel; - // result.push(node); - - tasyncapi.operations.forEach(operation => { - const operationNode = { - id: `asyncapi-operation-${operation.operationId}`, - type: 'node', - label: operation.operationId, - width: NODE_DIAMETER_ROUTE, - height: NODE_DIAMETER_ROUTE, - shape: NodeShape.rect, - status: NodeStatus.default, - data: { - isAlternate: false, - badge: 'AsyncAPI', - type: operation.action, - icon: operation.action, - // step: tin.rest, - fileName: tasyncapi.fileName, - secondaryLabel: tasyncapi.title, - } - } as NodeModel; - result.push(operationNode); - }) - }); - return result; -} - -export function getAsyncApiEdges(tasyncapis: TopologyAsyncApiNode[]): EdgeModel[] { - const result: EdgeModel[] = []; - tasyncapis.forEach(tasyncapi => { - tasyncapi.operations.forEach(operation => { - const edge: EdgeModel = { - id: `${operation.action}-${operation.operationId}`, - type: 'edge', - source: operation.action === 'send' ? `asyncapi-operation-${operation.operationId}` : tasyncapi.fileName, - target: operation.action === 'send' ? tasyncapi.fileName: `asyncapi-operation-${operation.operationId}`, - edgeStyle: EdgeStyle.dashed, - animationSpeed: EdgeAnimationSpeed.medium, - data: { - label: `${operation.action}` - } - } - // result.push(edge); - }) - }); - return result; -} export function getOpenApiEdges(topenapis: TopologyOpenApiNode[], tins: TopologyIncomingNode[], trcs: TopologyRestNode[]): EdgeModel[] { const result: EdgeModel[] = []; diff --git a/karavan-app/src/main/webui/src/karavan/features/projects/SettingsToolbar.tsx b/karavan-app/src/main/webui/src/karavan/features/projects/SettingsToolbar.tsx index 560c958d..b1c226c0 100644 --- a/karavan-app/src/main/webui/src/karavan/features/projects/SettingsToolbar.tsx +++ b/karavan-app/src/main/webui/src/karavan/features/projects/SettingsToolbar.tsx @@ -1,10 +1,9 @@ import React, {useState} from 'react'; -import {Button, Flex, FlexItem, Modal, ModalBody, ModalFooter, ModalHeader,} from '@patternfly/react-core'; +import {Button, Flex, Modal, ModalBody, ModalFooter, ModalHeader,} from '@patternfly/react-core'; import {useAppConfigStore, useFileStore, useProjectStore} from "@stores/ProjectStore"; import {shallow} from "zustand/shallow"; import {ProjectType} from "@models/ProjectModels"; import {KaravanApi} from "@api/KaravanApi"; -import {CatalogIcon} from '@patternfly/react-icons'; import {EditorToolbar} from "@features/project/developer/EditorToolbar"; export function SettingsToolbar() { diff --git a/karavan-app/src/main/webui/src/karavan/services/ProjectService.ts b/karavan-app/src/main/webui/src/karavan/services/ProjectService.ts index 6bbfe1f9..1bcebdf3 100644 --- a/karavan-app/src/main/webui/src/karavan/services/ProjectService.ts +++ b/karavan-app/src/main/webui/src/karavan/services/ProjectService.ts @@ -26,7 +26,6 @@ import {EventBus} from "@features/project/designer/utils/EventBus"; import {KameletApi} from "@karavan-core/api/KameletApi"; import {getCurrentUser} from "@api/auth/AuthApi"; import {AxiosResponse} from "axios"; -import {KARAVAN_DOT_EXTENSION} from "@karavan-core/contants"; import {useLogStore} from "@stores/LogStore"; import {useContainerStatusesStore} from "@stores/ContainerStatusesStore"; diff --git a/karavan-app/src/main/webui/src/karavan/shared/ui/PlatformLogos.tsx b/karavan-app/src/main/webui/src/karavan/shared/ui/PlatformLogos.tsx index 46cd3c01..213123ce 100644 --- a/karavan-app/src/main/webui/src/karavan/shared/ui/PlatformLogos.tsx +++ b/karavan-app/src/main/webui/src/karavan/shared/ui/PlatformLogos.tsx @@ -61,19 +61,6 @@ export function PlatformVersionWithName() { </div>) } -export function PlatformNameForToolbar() { - return (<div style={{ - height: '100%', - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - gap: '3px', - }}> - {PlatformName()} - </div>) -} - export const PlatformName = (height: number | string = 20, width: number | string = 292.797) => ( <Content component={'h1'}>KARAVAN</Content> ) diff --git a/karavan-app/src/main/webui/src/karavan/shared/ui/SideBarFormWrapper.tsx b/karavan-app/src/main/webui/src/karavan/shared/ui/SideBarFormWrapper.tsx deleted file mode 100644 index 257610a3..00000000 --- a/karavan-app/src/main/webui/src/karavan/shared/ui/SideBarFormWrapper.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React from 'react'; -import {Button, Form} from "@patternfly/react-core"; -import {UseFormReturn} from "react-hook-form"; - -interface AsyncFormWrapperProps { - children: React.ReactNode; - formContext: UseFormReturn<any>; // Accepts any form context - selectedId: string | null; - onSave?: (data: any) => void; - onCancel?: () => void; - onDelete?: () => void; - showDelete?: boolean; - isSubmitDisabled?: boolean; - footer?: React.ReactNode; -} - -export function SideBarFormWrapper({ - children, - formContext, - selectedId, - onSave, - onCancel, - onDelete, - showDelete = false, - isSubmitDisabled = false, - footer - }: AsyncFormWrapperProps) { - - const {formState: {errors}, handleSubmit, getValues} = formContext; - - function onKeyDown(event: React.KeyboardEvent<HTMLFormElement>): void { - event.stopPropagation(); - if (event.key === 'Enter') { - event.preventDefault(); - handleSubmit(onSave)(); - } - } - - // Common Footer Logic - function getFooter() { - const isDisabled = Object.getOwnPropertyNames(errors).length > 0 || isSubmitDisabled; - return ( - <div style={{display: "flex", flexDirection: "row", gap: 8, justifyContent: "space-between", marginTop: 16}}> - <div style={{flexGrow: 1}}> - {showDelete && - <Button - key="delete" - variant={"danger"} - isDanger - isDisabled={isDisabled} - onClick={onDelete} - > - Delete - </Button> - } - </div> - <Button - key="confirm" - variant={"primary"} - isDisabled={isDisabled} - onClick={handleSubmit(onSave)} - > - Save - </Button> - <Button - key="cancel" - variant="link" // Standardized to "link" or "secondary" as you prefer - onClick={onCancel} - > - Cancel - </Button> - </div> - ) - } - - return ( - <Form isHorizontal={true} autoComplete="off" noValidate onKeyDown={onKeyDown}> - <div style={{display: "flex", flexDirection: "column", gap: 16}}> - {children} - </div> - {footer || getFooter()} - </Form> - ); -} \ No newline at end of file diff --git a/karavan-app/src/main/webui/src/karavan/util/CodeUtils.ts b/karavan-app/src/main/webui/src/karavan/util/CodeUtils.ts index 94cb2d90..648fbf9a 100644 --- a/karavan-app/src/main/webui/src/karavan/util/CodeUtils.ts +++ b/karavan-app/src/main/webui/src/karavan/util/CodeUtils.ts @@ -23,8 +23,6 @@ import {CamelUi} from "@features/project/designer/utils/CamelUi"; import {KameletApi} from "@karavan-core/api/KameletApi"; import {CamelUtil} from "@karavan-core/api/CamelUtil"; import {EventBus} from "@features/project/designer/utils/EventBus"; -import {ApplicationProperty} from "@karavan-core/model/MainConfigurationModel"; -import {MainConfigurationApi} from "@karavan-core/api/MainConfigurationApi"; export class CodeUtils { @@ -100,107 +98,4 @@ export class CodeUtils { return ''; } } - - static getApplicationPropertiesCurrentValues(code: string): ApplicationProperty[] { - if (!code) return []; // Add a guard for null or undefined code - return code.split(/\r?\n/) - .filter((p: string) => p.trim() !== '' && p.indexOf('#') !== 0) // Skip empty/whitespace lines and comments - .map((p: string) => { - const i = p.indexOf("="); - // Handle lines that might not contain '=' - if (i === -1) { - return {name: p.trim(), value: ''}; - } - const key = p.substring(0, i).trim(); - const value = p.substring(i + 1).trim(); - return {name: key, value: value}; - }); - } - - - /** - * Replaces all deprecated property keys in a given .properties string with their new names. - * - * @param code The input string containing properties in .ini format. - * @returns A new string with deprecated keys replaced. - */ - static getReplaceAllPropertiesNames(code: string): string { - // 1. Split the input text into an array of lines. - const lines = code.split('\n'); - - // 2. Process each line to check for and replace keys. - const updatedLines = lines.map(line => { - const trimmedLine = line.trim(); - - // 3. Ignore comments (starting with # or !) and empty lines. - if (trimmedLine.startsWith('#') || trimmedLine.startsWith('!') || trimmedLine === '') { - return line; - } - - // 4. Find the first separator (= or :) to isolate the key. - const separatorIndex = trimmedLine.search(/[=:]/); - - // If no separator is found or the line starts with it, it's not a valid key-value pair. - if (separatorIndex <= 0) { - return line; - } - - // Extract the key, trimming any whitespace around it. - const key = trimmedLine.substring(0, separatorIndex).trim(); - - // 5. Use the API to check if the key is deprecated. - const change = MainConfigurationApi.findChangeByPropertyName(key); - - // 6. If a new name is found, replace the old key in the original line. - // This replacement preserves leading whitespace and the value part of the string. - if (change && change.replaced) { - return line.replace(key, change.replaced); - } - - // 7. If no change is needed, return the original line. - return line; - }); - - // 8. Join the updated lines back into a single string. - return updatedLines.join('\n'); - } - - static sortApplicationProperties(input: string): string { - // Define priority order for prefixes - const priorities = [ - 'camel.karavan.', - 'camel.jbang.', - 'camel.context', - 'camel.', - 'jib.', - 'jkube.' - ]; - - // Function to determine the priority of each line - const getPriority = (line: string): number => { - for (let i = 0; i < priorities.length; i++) { - if (line.startsWith(priorities[i])) { - return i; // Return the index as priority - } - } - return priorities.length; // Return a default priority for lines not matching any prefix - }; - - // Split input string into lines, sort them by priority and return the sorted result - return input - .split('\n') - .sort((a, b) => { - const priorityA = getPriority(a); - const priorityB = getPriority(b); - - // If priorities are equal, use lexicographical order - if (priorityA === priorityB) { - return a.localeCompare(b); - } - - // Otherwise, sort by priority - return priorityA - priorityB; - }) - .join('\n'); - } } \ No newline at end of file
