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 103ed157c454fde4b3bc1f7248e2b3ecda164e54 Author: Marat Gubaidullin <ma...@talismancloud.io> AuthorDate: Wed Feb 14 16:40:19 2024 -0500 Incoming navigation for #1109 --- karavan-designer/src/DesignerPage.tsx | 4 +- karavan-designer/src/designer/KaravanDesigner.tsx | 2 +- .../src/designer/route/DslConnections.tsx | 4 +- .../src/designer/utils/InfrastructureAPI.ts | 4 +- karavan-vscode/src/designerView.ts | 62 ++++++++++++++-------- karavan-vscode/src/topologyView.ts | 9 +--- karavan-vscode/src/utils.ts | 47 ++++++++++------ karavan-vscode/webview/App.tsx | 9 ++-- karavan-vscode/webview/topology/TopologyApi.tsx | 2 +- karavan-vscode/webview/topology/TopologyStore.ts | 9 ---- karavan-vscode/webview/topology/TopologyTab.tsx | 5 +- .../main/webui/src/designer/KaravanDesigner.tsx | 2 +- .../webui/src/designer/route/DslConnections.tsx | 4 +- .../webui/src/designer/utils/InfrastructureAPI.ts | 4 +- .../src/main/webui/src/project/FileEditor.tsx | 17 +++--- 15 files changed, 101 insertions(+), 83 deletions(-) diff --git a/karavan-designer/src/DesignerPage.tsx b/karavan-designer/src/DesignerPage.tsx index d3586927..36a2dbef 100644 --- a/karavan-designer/src/DesignerPage.tsx +++ b/karavan-designer/src/DesignerPage.tsx @@ -78,8 +78,8 @@ export const DesignerPage = (props: Props) => { ]} onSavePropertyPlaceholder={(key, value) => console.log("onSavePropertyPlaceholder", key, value)} beans={[]} - onInternalConsumerClick={(uri, name, direction: 'from' | 'to') => { - console.log("onInternalConsumerClick", uri, name, direction) + onInternalConsumerClick={(uri, name, routeId) => { + console.log("onInternalConsumerClick", uri, name, routeId) }} files={[new IntegrationFile("demo.camel.yaml", yaml)]} /> diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx b/karavan-designer/src/designer/KaravanDesigner.tsx index 58dbbf6d..9fbe3864 100644 --- a/karavan-designer/src/designer/KaravanDesigner.tsx +++ b/karavan-designer/src/designer/KaravanDesigner.tsx @@ -48,7 +48,7 @@ interface Props { onSaveCustomCode: (name: string, code: string) => void onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined> onSavePropertyPlaceholder: (key: string, value: string) => void - onInternalConsumerClick: (uri: string, name: string, direction: 'from' | 'to') => void + onInternalConsumerClick: (uri?: string, name?: string, routeId?: string) => void filename: string yaml: string dark: boolean diff --git a/karavan-designer/src/designer/route/DslConnections.tsx b/karavan-designer/src/designer/route/DslConnections.tsx index 072aaac9..99339f7c 100644 --- a/karavan-designer/src/designer/route/DslConnections.tsx +++ b/karavan-designer/src/designer/route/DslConnections.tsx @@ -157,7 +157,7 @@ export function DslConnections() { <Button style={{position: 'absolute', left: 27, top: (index * 16) + (12), whiteSpace: 'nowrap', zIndex: 300, padding: 0}} variant={'link'} aria-label="Goto" - onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, 'to')}> + onClick={_ => InfrastructureAPI.onInternalConsumerClick(undefined, undefined, routeId)}> {routeId} </Button> </Tooltip> @@ -255,7 +255,7 @@ export function DslConnections() { <Button style={{position: 'absolute', right: 27, top: -12, whiteSpace: 'nowrap', zIndex: 300, padding: 0}} variant={'link'} aria-label="Goto" - onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, 'from')}> + onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, undefined)}> {name} </Button> </Tooltip> diff --git a/karavan-designer/src/designer/utils/InfrastructureAPI.ts b/karavan-designer/src/designer/utils/InfrastructureAPI.ts index 2acd5d54..c386d6fc 100644 --- a/karavan-designer/src/designer/utils/InfrastructureAPI.ts +++ b/karavan-designer/src/designer/utils/InfrastructureAPI.ts @@ -21,7 +21,7 @@ export class InfrastructureAPI { static onSaveCustomCode: (name: string, code: string) => void; static onSave: (filename: string, yaml: string, propertyOnly: boolean) => void; static onSavePropertyPlaceholder: (key: string, value: string) => void; - static onInternalConsumerClick: (uri: string, name: string, direction: 'from' | 'to') => void; + static onInternalConsumerClick: (uri?: string, name?: string, routeId?: string) => void; static setOnGetCustomCode(onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined>){ this.onGetCustomCode = onGetCustomCode @@ -39,7 +39,7 @@ export class InfrastructureAPI { this.onSavePropertyPlaceholder = onSavePropertyPlaceholder } - static setOnInternalConsumerClick(onInternalConsumerClick:(uri: string, name: string, direction: 'from' | 'to') => void){ + static setOnInternalConsumerClick(onInternalConsumerClick:(uri?: string, name?: string, routeId?: string) => void){ this.onInternalConsumerClick = onInternalConsumerClick } diff --git a/karavan-vscode/src/designerView.ts b/karavan-vscode/src/designerView.ts index 572a54e8..822ef7dc 100644 --- a/karavan-vscode/src/designerView.ts +++ b/karavan-vscode/src/designerView.ts @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {Uri, window, commands, WebviewPanel, ExtensionContext, ViewColumn, WebviewPanelOnDidChangeViewStateEvent } from "vscode"; +import { Uri, window, commands, WebviewPanel, ExtensionContext, ViewColumn, WebviewPanelOnDidChangeViewStateEvent } from "vscode"; import * as path from "path"; import * as utils from "./utils"; import { CamelDefinitionYaml } from "core/api/CamelDefinitionYaml"; @@ -32,7 +32,7 @@ export class DesignerView { } karavanOpen(fullPath: string, tab?: string) { utils.readFile(path.resolve(fullPath)).then(readData => { - + const yaml = Buffer.from(readData).toString('utf8'); const filename = path.basename(fullPath); const relativePath = utils.getRalativePath(fullPath); @@ -76,7 +76,7 @@ export class DesignerView { .showInputBox({ title: type === 'kamelet' ? 'Create Kamelet' : "Create Integration", ignoreFocusOut: true, - prompt: type === 'kamelet' ? 'Kamelet Name' : "Integration name", + prompt: type === 'kamelet' ? 'Kamelet Name' : "Integration name", validateInput: (text: string): string | undefined => { if (!text || text.length === 0) { return 'Name should not be empty'; @@ -88,9 +88,9 @@ export class DesignerView { if (value) { const name = utils.nameFromTitle(type, value, kameletType); const filename = utils.fileNameFromName(type, name, kameletType); - const i:Integration = Integration.createNew(name, type); + const i: Integration = Integration.createNew(name, type); if (type === 'kamelet' && i.metadata && kameletType) { - i.metadata.labels = new MetadataLabels({"camel.apache.org/kamelet.type": kameletType}); + i.metadata.labels = new MetadataLabels({ "camel.apache.org/kamelet.type": kameletType }); } i.type = type; const yaml = CamelDefinitionYaml.integrationToYaml(i); @@ -136,12 +136,12 @@ export class DesignerView { break; case 'savePropertyPlaceholder': utils.savePropertyPlaceholder(message.key, message.value); - break; + break; case 'getData': this.sendData(panel, filename, relativePath, fullPath, message.reread === true, yaml, tab); break; case 'internalConsumerClick': - this.internalConsumerClick(panel, fullPath, message.uri, message.name); + this.internalConsumerClick(panel, fullPath, message.uri, message.name, message.routeId); break; } }, @@ -188,7 +188,9 @@ export class DesignerView { // Read property placeholders utils.readPropertyPlaceholders(this.context), // Read beans - utils.readBeans(fullPath) + utils.readBeans(fullPath), + // Read integration + utils.readCamelYamlFiles(path.dirname(fullPath)) ]).then(results => { // Send Kamelets panel.webview.postMessage({ command: 'kamelets', kamelets: results[0] }); @@ -199,15 +201,16 @@ export class DesignerView { // Send java code panel.webview.postMessage({ command: 'javaCode', javaCode: Object.fromEntries(results[3]) }); // Send supported components - if (results[4]) panel.webview.postMessage({ command: 'supportedComponents', components: results[4]}); - if (results[5] === true) panel.webview.postMessage({ command: 'supportedOnly'}); + if (results[4]) panel.webview.postMessage({ command: 'supportedComponents', components: results[4] }); + if (results[5] === true) panel.webview.postMessage({ command: 'supportedOnly' }); // Send integration + panel.webview.postMessage({ command: 'files', files: results[8] }); this.sendIntegrationData(panel, filename, relativePath, fullPath, reread, yaml, tab, results[6], results[7]); - + }).catch(err => console.log(err)); } - sendIntegrationData(panel: WebviewPanel, filename: string, relativePath: string, + sendIntegrationData(panel: WebviewPanel, filename: string, relativePath: string, fullPath: string, reread: boolean, yaml?: string, tab?: string, propertyPlaceholders?: string[], beans?: RegistryBeanDefinition[]) { // Read file if required if (reread) { @@ -215,14 +218,18 @@ export class DesignerView { const yaml = Buffer.from(readData).toString('utf8'); // Send integration panel.webview.postMessage( - { command: 'open', page: "designer", filename: filename, relativePath: relativePath, - fullPath:fullPath, yaml: yaml, tab: tab, propertyPlaceholders: propertyPlaceholders, beans: beans }); + { + command: 'open', page: "designer", filename: filename, relativePath: relativePath, + fullPath: fullPath, yaml: yaml, tab: tab, propertyPlaceholders: propertyPlaceholders, beans: beans + }); }); } else { // Send integration panel.webview.postMessage( - { command: 'open', page: "designer", filename: filename, relativePath: relativePath, - fullPath:fullPath, yaml: yaml, tab: tab, propertyPlaceholders: propertyPlaceholders, beans: beans }); + { + command: 'open', page: "designer", filename: filename, relativePath: relativePath, + fullPath: fullPath, yaml: yaml, tab: tab, propertyPlaceholders: propertyPlaceholders, beans: beans + }); } } @@ -237,12 +244,21 @@ export class DesignerView { } } - internalConsumerClick(panel: WebviewPanel, fullPath: string, uri: string, name: string) { - utils.getFileWithIntegralConsumer(fullPath, uri, name).then((filename) => { - if (filename !== undefined) { - commands.executeCommand("karavan.open", { fsPath: filename }) - } - }).catch(err => window.showErrorMessage("Error: " + err?.reason)); - + internalConsumerClick(panel: WebviewPanel, fullPath: string, uri?: string, name?: string, routeId?: string) { + console.log(uri, name, routeId) + if (uri && name) { + utils.getFileWithIntegnalConsumer(fullPath, uri, name).then((filename) => { + if (filename !== undefined) { + commands.executeCommand("karavan.open", { fsPath: filename }) + } + }).catch(err => window.showErrorMessage("Error: " + err?.reason)); + } else if(routeId) { + utils.getFileWithInternalProducer(fullPath, routeId).then((filename) => { + if (filename !== undefined) { + commands.executeCommand("karavan.open", { fsPath: filename }) + } + }).catch(err => window.showErrorMessage("Error: " + err?.reason)); + } + } } \ No newline at end of file diff --git a/karavan-vscode/src/topologyView.ts b/karavan-vscode/src/topologyView.ts index 55cfee6a..b8f7476f 100644 --- a/karavan-vscode/src/topologyView.ts +++ b/karavan-vscode/src/topologyView.ts @@ -97,13 +97,8 @@ export class TopologyView { panel.webview.postMessage({ command: 'components', components: components }); }).finally(() => { // Read and send Integrations - let fullPath = fsPath; - if (fsPath.endsWith(".camel.yaml")) { - const parts = fsPath.split(path.sep); - parts.pop(); - fullPath = parts.join(path.sep); - } - utils.readCamelYamlFiles(fullPath).then((files) => { + const dir = fsPath.endsWith('camel.yaml') ? path.dirname(fsPath) : fsPath; + utils.readCamelYamlFiles(dir).then((files) => { panel.webview.postMessage({ command: 'files', files: files }); }).finally(() => { // Open diff --git a/karavan-vscode/src/utils.ts b/karavan-vscode/src/utils.ts index 008fd092..17e999a0 100644 --- a/karavan-vscode/src/utils.ts +++ b/karavan-vscode/src/utils.ts @@ -271,7 +271,7 @@ export async function readCamelYamlFiles(dir: string) { const readData = await readFile(path.resolve(filename)); const yaml = Buffer.from(readData).toString('utf8'); if (CamelDefinitionYaml.yamlIsIntegration(yaml)) { - const basename = filename.replace(dir, ''); + const basename = filename.replace(dir, '').substring(1); result[basename] = yaml; } } @@ -458,23 +458,38 @@ function setMinikubeEnvVariables(env: string): Map<string, string> { return map; } -export async function getFileWithIntegralConsumer(fullPath: string, uri: string, name: string) { +export async function getIntegrations(dir: string) { + const files = await readCamelYamlFiles(dir); + const integrations: Integration[] = []; + Object.getOwnPropertyNames(files).forEach(n => { + const i = CamelDefinitionYaml.yamlToIntegration(n, files[n]); + integrations.push(i); + }); + return integrations; +} + +export async function getFileWithIntegnalConsumer(fullPath: string, uri: string, name: string) { try { - const codePath = path.dirname(fullPath); - const integrations: Integration[] = []; - const files = await getCamelYamlFiles(codePath); - for (let x in files) { - const filename = files[x]; - const readData = await readFile(filename); - const code = Buffer.from(readData).toString('utf8'); - const i = CamelDefinitionYaml.yamlToIntegration(filename, code); - integrations.push(i); + const integrations = await getIntegrations(path.dirname(fullPath)); + const route = TopologyUtils.findTopologyRouteNodes(integrations) + .filter(t => t?.from?.uri === uri && t?.from?.parameters?.name === name).at(0); + if (route) { + return path.join(path.dirname(fullPath), route.fileName); } - const routes = TopologyUtils.findTopologyRouteNodes(integrations); - for (const route of routes) { - if (route?.from?.uri === uri && route?.from?.parameters?.name === name) { - return route.fileName; - } + } + catch (e) { + console.log((e as Error).message); + } + return undefined; +} + +export async function getFileWithInternalProducer(fullPath: string, routeId: string) { + try { + const integrations = await getIntegrations(path.dirname(fullPath)) + const route = TopologyUtils.findTopologyOutgoingNodes(integrations) + .filter(t => t.routeId === routeId).at(0); + if (route) { + return path.join(path.dirname(fullPath), route.fileName); } } catch (e) { diff --git a/karavan-vscode/webview/App.tsx b/karavan-vscode/webview/App.tsx index 7bd0e75e..dec9683b 100644 --- a/karavan-vscode/webview/App.tsx +++ b/karavan-vscode/webview/App.tsx @@ -26,8 +26,8 @@ import { TemplateApi } from "./core/api/TemplateApi"; import { EventBus } from "./designer/utils/EventBus"; import { KnowledgebasePage } from "./knowledgebase/KnowledgebasePage"; import { TopologyTab } from "./topology/TopologyTab"; -import { IntegrationFile } from "./topology/TopologyStore"; import {RegistryBeanDefinition} from "core/model/CamelDefinition"; +import { IntegrationFile } from "core/model/IntegrationDefinition"; interface Props { dark: boolean @@ -232,9 +232,10 @@ class App extends React.Component<Props, State> { propertyPlaceholders={this.state.propertyPlaceholders} onSavePropertyPlaceholder={(key, value) => this.savePropertyPlaceholder(key, value)} beans={this.state.beans} - onInternalConsumerClick={(uri, name) => { - vscode.postMessage({ command: 'internalConsumerClick', uri: uri, name: name }); - }} + onInternalConsumerClick={(uri, name, routeId) => { + vscode.postMessage({ command: 'internalConsumerClick', uri: uri, name: name, routeId: routeId }); + }} + files={this.state.files.map(f => new IntegrationFile(f.name, f.code))} /> } {loaded && page === "knowledgebase" && <KnowledgebasePage dark={dark} />} diff --git a/karavan-vscode/webview/topology/TopologyApi.tsx b/karavan-vscode/webview/topology/TopologyApi.tsx index edff33e8..a00ac286 100644 --- a/karavan-vscode/webview/topology/TopologyApi.tsx +++ b/karavan-vscode/webview/topology/TopologyApi.tsx @@ -39,7 +39,7 @@ import { TopologyRouteNode } from "core/model/TopologyDefinition"; import CustomEdge from "./CustomEdge"; -import {IntegrationFile} from "./TopologyStore"; +import {IntegrationFile} from "core/model/IntegrationDefinition"; import CustomGroup from "./CustomGroup"; const NODE_DIAMETER = 60; diff --git a/karavan-vscode/webview/topology/TopologyStore.ts b/karavan-vscode/webview/topology/TopologyStore.ts index 4e9ee643..517e2794 100644 --- a/karavan-vscode/webview/topology/TopologyStore.ts +++ b/karavan-vscode/webview/topology/TopologyStore.ts @@ -18,15 +18,6 @@ import {createWithEqualityFn} from "zustand/traditional"; import {shallow} from "zustand/shallow"; -export class IntegrationFile { - name: string = ''; - code: string = ''; - - constructor(name: string, code: string) { - this.name = name; - this.code = code; - } -} interface TopologyState { selectedIds: string [] diff --git a/karavan-vscode/webview/topology/TopologyTab.tsx b/karavan-vscode/webview/topology/TopologyTab.tsx index 1f2d165e..35f8629f 100644 --- a/karavan-vscode/webview/topology/TopologyTab.tsx +++ b/karavan-vscode/webview/topology/TopologyTab.tsx @@ -31,10 +31,11 @@ import { } from '@patternfly/react-topology'; import {customComponentFactory, getModel} from "./TopologyApi"; import {shallow} from "zustand/shallow"; -import {IntegrationFile, useTopologyStore} from "./TopologyStore"; +import {useTopologyStore} from "./TopologyStore"; import {TopologyPropertiesPanel} from "./TopologyPropertiesPanel"; import {TopologyToolbar} from "./TopologyToolbar"; import {useDesignerStore} from "../designer/DesignerStore"; +import {IntegrationFile} from "core/model/IntegrationDefinition"; interface Props { files: IntegrationFile[], @@ -137,7 +138,7 @@ export function TopologyTab(props: Props) { }); }, [ranker, controller, setRanker]); - return ( + return ( <TopologyView className="topology-panel" contextToolbar={!props.hideToolbar 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 58dbbf6d..9fbe3864 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 @@ -48,7 +48,7 @@ interface Props { onSaveCustomCode: (name: string, code: string) => void onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined> onSavePropertyPlaceholder: (key: string, value: string) => void - onInternalConsumerClick: (uri: string, name: string, direction: 'from' | 'to') => void + onInternalConsumerClick: (uri?: string, name?: string, routeId?: string) => void filename: string yaml: string dark: boolean diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx b/karavan-web/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx index 072aaac9..99339f7c 100644 --- a/karavan-web/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx @@ -157,7 +157,7 @@ export function DslConnections() { <Button style={{position: 'absolute', left: 27, top: (index * 16) + (12), whiteSpace: 'nowrap', zIndex: 300, padding: 0}} variant={'link'} aria-label="Goto" - onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, 'to')}> + onClick={_ => InfrastructureAPI.onInternalConsumerClick(undefined, undefined, routeId)}> {routeId} </Button> </Tooltip> @@ -255,7 +255,7 @@ export function DslConnections() { <Button style={{position: 'absolute', right: 27, top: -12, whiteSpace: 'nowrap', zIndex: 300, padding: 0}} variant={'link'} aria-label="Goto" - onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, 'from')}> + onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, undefined)}> {name} </Button> </Tooltip> 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 2acd5d54..c386d6fc 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 @@ -21,7 +21,7 @@ export class InfrastructureAPI { static onSaveCustomCode: (name: string, code: string) => void; static onSave: (filename: string, yaml: string, propertyOnly: boolean) => void; static onSavePropertyPlaceholder: (key: string, value: string) => void; - static onInternalConsumerClick: (uri: string, name: string, direction: 'from' | 'to') => void; + static onInternalConsumerClick: (uri?: string, name?: string, routeId?: string) => void; static setOnGetCustomCode(onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined>){ this.onGetCustomCode = onGetCustomCode @@ -39,7 +39,7 @@ export class InfrastructureAPI { this.onSavePropertyPlaceholder = onSavePropertyPlaceholder } - static setOnInternalConsumerClick(onInternalConsumerClick:(uri: string, name: string, direction: 'from' | 'to') => void){ + static setOnInternalConsumerClick(onInternalConsumerClick:(uri?: string, name?: string, routeId?: string) => void){ this.onInternalConsumerClick = onInternalConsumerClick } 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 ce4504fb..2d891f46 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 @@ -81,10 +81,10 @@ export function FileEditor(props: Props) { } } - function internalConsumerClick(uri: string, name: string, direction: 'from' | 'to') { + function internalConsumerClick(uri?: string, name?: string, routeId?: string) { const integrations = files.filter(f => f.name.endsWith(".camel.yaml")) .map(f => CamelDefinitionYaml.yamlToIntegration(f.name, f.code)); - if (direction === 'from') { + if (uri && name) { const routes = TopologyUtils.findTopologyRouteNodes(integrations); for (const route of routes) { if (route?.from?.uri === uri && route?.from?.parameters?.name === name) { @@ -96,14 +96,13 @@ export function FileEditor(props: Props) { } } } else { - const nodes = TopologyUtils.findTopologyOutgoingNodes(integrations).filter(t => t.type === 'internal'); + const nodes = TopologyUtils.findTopologyOutgoingNodes(integrations) + .filter(t => t.routeId === routeId); for (const node of nodes) { - if ((node?.step as any)?.uri === uri && (node?.step as any)?.parameters?.name === name) { - const switchToFile = files.filter(f => f.name === node.fileName).at(0); - if (switchToFile) { - setFile('select', switchToFile); - setKey(Math.random().toString()) - } + const switchToFile = files.filter(f => f.name === node.fileName).at(0); + if (switchToFile) { + setFile('select', switchToFile); + setKey(Math.random().toString()) } } }