From 6615d3d3bf637c7ca18758cc86358410cedb086a Mon Sep 17 00:00:00 2001 From: samithkavishke Date: Tue, 24 Feb 2026 09:38:35 +0530 Subject: [PATCH 1/4] Add refresh when the lsitener changes --- .../ServiceDesigner/ServiceConfigureView.tsx | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx index d34907103c..91abbf54b6 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx @@ -214,6 +214,7 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { const [currentIdentifier, setCurrentIdentifier] = useState(null); const [isSaving, setIsSaving] = useState(false); + const [position, setPosition] = useState(props.position); const [existingListenerType, setExistingListenerType] = useState(""); // Example: "Listener", "CdcListener" const [selectedListener, setSelectedListener] = useState(null); @@ -296,8 +297,8 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { }, []); useEffect(() => { - fetchService(props.position); - }, [props.position]); + fetchService(position); + }, [position]); useEffect(() => { if (props.listenerName) { @@ -475,6 +476,10 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { // Set the service model setServiceModel(res.service); setConfigTitle(`${getDisplayServiceName(res.service)} Configuration`); + // Set the current identifier from the service name + if (res.service.name && !currentIdentifier) { + setCurrentIdentifier(res.service.name); + } // Set the service listeners setServiceListeners(res.service); // Find the listener type @@ -656,6 +661,7 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { console.error("No artifact returned after detaching listener"); return; } + setPosition(updatedArtifact.position); setCurrentIdentifier(updatedArtifact.name); await fetchService(updatedArtifact.position); setChangeMap({}); @@ -691,6 +697,31 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { setIsSaving(false); } + const refreshServicePosition = async () => { + if (!currentIdentifier) { + console.error("No current identifier available for refreshing service position"); + return; + } + + try { + const projectStructureResponse = await rpcClient.getBIDiagramRpcClient().getProjectStructure(); + const project = projectStructureResponse.projects.find(p => p.projectPath === props.projectPath); + + if (!project) { + console.error("Project not found in structure response"); + return; + } + + const entryPoint = project + .directoryMap[DIRECTORY_MAP.SERVICE] + .find((service: ProjectStructureArtifactResponse) => service.name === currentIdentifier); + + setPosition(entryPoint.position); + } catch (error) { + console.error('Error refreshing service position:', error); + } + }; + const handleSave = async () => { setIsSaving(true); const changes = Object.values(changeMap); @@ -700,6 +731,13 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { for (const change of listenerChanges) { await rpcClient.getServiceDesignerRpcClient().updateListenerSourceCode({ filePath: change.filePath, listener: change.data as ListenerModel }); } + + // Re-fetch service position after listener changes + if (listenerChanges.length > 0 && serviceChanges.length === 0) { + await refreshServicePosition(); + } + + // Update service changes for (const change of serviceChanges) { const res = await rpcClient.getServiceDesignerRpcClient().updateServiceSourceCode({ filePath: change.filePath, service: change.data as ServiceModel }); const updatedArtifact = res.artifacts.at(0); @@ -708,6 +746,7 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { continue; } setCurrentIdentifier(updatedArtifact.name); + setPosition(updatedArtifact.position); await fetchService(updatedArtifact.position); } setChangeMap({}); From 3d6073d6df22fc56ea67be30c5cf845db2e6df35 Mon Sep 17 00:00:00 2001 From: samithkavishke Date: Wed, 25 Feb 2026 09:30:26 +0530 Subject: [PATCH 2/4] Address listner not showing issue --- .../ServiceDesigner/ServiceConfigureView.tsx | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx index 91abbf54b6..def2f5d8ed 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx @@ -1052,14 +1052,6 @@ function ServiceConfigureListenerEditView(props: ServiceConfigureListenerEditVie onDirtyChange?.(isDirty, filePath, position); } - // Check if this is a legacy listener (legacy FTP listeners carry path/folderPath in listener properties) - const isLegacyListener = - listenerModel?.properties?.folderPath !== undefined || - listenerModel?.properties?.path !== undefined; - - // For attached listeners in new system (no folderPath in listener), show only monitoring path - const showMinimalConfig = isAttachedListener && !isLegacyListener; - return ( {!listenerModel && @@ -1068,7 +1060,7 @@ function ServiceConfigureListenerEditView(props: ServiceConfigureListenerEditVie Loading... } - {listenerModel && !showMinimalConfig && + {listenerModel && } - {listenerModel && showMinimalConfig && - - } ); }; From 2686afef01490dad494998c2a522694b61f616ab Mon Sep 17 00:00:00 2001 From: samithkavishke Date: Wed, 25 Feb 2026 11:56:36 +0530 Subject: [PATCH 3/4] Address rerender issue --- .../service-designer/rpc-manager.ts | 2 +- .../ServiceDesigner/ServiceConfigureView.tsx | 38 ++++--------------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/workspaces/ballerina/ballerina-extension/src/rpc-managers/service-designer/rpc-manager.ts b/workspaces/ballerina/ballerina-extension/src/rpc-managers/service-designer/rpc-manager.ts index 3b1d9b53be..c743ef98db 100644 --- a/workspaces/ballerina/ballerina-extension/src/rpc-managers/service-designer/rpc-manager.ts +++ b/workspaces/ballerina/ballerina-extension/src/rpc-managers/service-designer/rpc-manager.ts @@ -171,7 +171,7 @@ export class ServiceDesignerRpcManager implements ServiceDesignerAPI { this.ensureFileExists(targetFile); params.filePath = targetFile; const res: ListenerSourceCodeResponse = await context.langClient.updateListenerSourceCode(params); - const artifacts = await updateSourceCode({ textEdits: res.textEdits, artifactData: { artifactType: DIRECTORY_MAP.LISTENER }, description: params.listener.name + ' Update' }); + const artifacts = await updateSourceCode({ textEdits: res.textEdits, description: params.listener.name + ' Update' }); const result: UpdatedArtifactsResponse = { artifacts: artifacts }; diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx index def2f5d8ed..744fdcb9b4 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx @@ -697,31 +697,6 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { setIsSaving(false); } - const refreshServicePosition = async () => { - if (!currentIdentifier) { - console.error("No current identifier available for refreshing service position"); - return; - } - - try { - const projectStructureResponse = await rpcClient.getBIDiagramRpcClient().getProjectStructure(); - const project = projectStructureResponse.projects.find(p => p.projectPath === props.projectPath); - - if (!project) { - console.error("Project not found in structure response"); - return; - } - - const entryPoint = project - .directoryMap[DIRECTORY_MAP.SERVICE] - .find((service: ProjectStructureArtifactResponse) => service.name === currentIdentifier); - - setPosition(entryPoint.position); - } catch (error) { - console.error('Error refreshing service position:', error); - } - }; - const handleSave = async () => { setIsSaving(true); const changes = Object.values(changeMap); @@ -729,12 +704,13 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { const serviceChanges = changes.filter((c) => c.isService); // Listeners first, then service last for (const change of listenerChanges) { - await rpcClient.getServiceDesignerRpcClient().updateListenerSourceCode({ filePath: change.filePath, listener: change.data as ListenerModel }); - } - - // Re-fetch service position after listener changes - if (listenerChanges.length > 0 && serviceChanges.length === 0) { - await refreshServicePosition(); + const listnerResponse = await rpcClient.getServiceDesignerRpcClient().updateListenerSourceCode({ filePath: change.filePath, listener: change.data as ListenerModel }); + const updatedServiceArtifact = listnerResponse.artifacts.filter(artifact => artifact.name ===currentIdentifier).at(0); + if (!updatedServiceArtifact) { + console.error("No service artifact returned after updating listener"); + continue; + } + setPosition(updatedServiceArtifact.position); } // Update service changes From c631cfbcbf57b85417426874de1f6e76416ba578 Mon Sep 17 00:00:00 2001 From: samithkavishke Date: Wed, 25 Feb 2026 13:00:37 +0530 Subject: [PATCH 4/4] Address listener detail loss issue --- .../BI/ServiceDesigner/ServiceConfigureView.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx index 744fdcb9b4..feb7a34dba 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/ServiceConfigureView.tsx @@ -715,7 +715,19 @@ export function ServiceConfigureView(props: ServiceConfigureProps) { // Update service changes for (const change of serviceChanges) { - const res = await rpcClient.getServiceDesignerRpcClient().updateServiceSourceCode({ filePath: change.filePath, service: change.data as ServiceModel }); + // TODO: The backend needs to be refactored to support this types model + const service = change.data as ServiceModel; + const updatedService = { + ...serviceModel, + properties: { + ...serviceModel.properties, + listener: { + ...serviceModel.properties.listener, + value: service.properties.listener?.values[0] || service.properties.listener?.value || "", + } + } + }; + const res = await rpcClient.getServiceDesignerRpcClient().updateServiceSourceCode({ filePath: change.filePath, service: updatedService }); const updatedArtifact = res.artifacts.at(0); if (!updatedArtifact) { console.error("No artifact returned after saving service changes");