[BI Data Mapper] Improve data mapper converted-variable UI#1545
[BI Data Mapper] Improve data mapper converted-variable UI#1545KCSAbeywickrama wants to merge 5 commits intowso2:release/bi-1.8.xfrom
Conversation
…t integration actions
…ality and styling
… and improve gap handling
📝 WalkthroughWalkthroughPropagates title into getCategoryActions, refines field-count math for InputNode, adjusts rendering and action icons for converted variables in input/output widgets, makes PayloadWidget.typeName required and restyles the payload widget, and treats JSON/XML as expandable types. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts (1)
129-131: Magic fractional field-count offsets are fragile — consider documenting their derivation.
0.2and4.8are calibration offsets tied to the rendered heights instyles.ts(IO_NODE_FIELD_HEIGHT * 5for the payload widget, plus header gaps). If either the style orIO_NODE_FIELD_HEIGHTchanges, these need to be updated in tandem with no compile-time safety net.At minimum, a comment linking them to the corresponding style constant (e.g.,
// = IO_NODE_FIELD_HEIGHT * 5 / IO_NODE_FIELD_HEIGHT − header_row_fraction) would prevent silent drift.Also applies to: 148-150
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts` around lines 129 - 131, The fractional magic numbers (0.2 and 4.8) used in InputNode (when adjusting parentPort/this.numberOfFields) are fragile; replace them with named, derived constants computed from the authoritative IO_NODE_FIELD_HEIGHT in styles.ts (or import that constant) — e.g., compute PAYLOAD_FIELD_COUNT_OFFSET = (IO_NODE_FIELD_HEIGHT * 5) / IO_NODE_FIELD_HEIGHT - HEADER_ROW_FRACTION or define HEADER_GAP_FRACTION and PAYLOAD_ROWS and use PAYLOAD_OFFSET = PAYLOAD_ROWS - HEADER_GAP_FRACTION — then use those constants in the same places (the adjustments inside InputNode where parentPort.attributes.collapsed is checked and the other spot around lines 148-150) and add a single-line comment referencing styles.ts and IO_NODE_FIELD_HEIGHT to explain the derivation so changes to styles automatically keep the math correct.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsx`:
- Around line 227-230: PayloadWidget is calling dmType.typeName.toUpperCase()
which can throw if dmType.typeName is undefined; update the render in
InputNodeWidget (the PayloadWidget props) to use a safe fallback: use
(dmType.typeName ?? dmType.typeKind) and then call .toUpperCase() so when
isConvertibleType guarantees TypeKind.Json or TypeKind.Xml you still show a
valid label; ensure the same safe expression is used for typeName prop and any
other places referencing dmType.typeName (e.g., the onClick
createConvertedVariable call if it relies on typeName).
In
`@workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx`:
- Around line 219-224: In ObjectOutputWidget.tsx the render for PayloadWidget
calls outputType.typeName.toUpperCase() which can throw if typeName is undefined
(IOType.typeName is optional); change the call in the JSX where PayloadWidget is
created (the block that checks expanded && isConvertibleType &&
!outputType.convertedField) to safely handle missing typeName by using optional
chaining and a fallback (e.g., outputType.typeName?.toUpperCase() ?? 'UNKNOWN'
or similar) so the UI never calls .toUpperCase() on undefined; update any
related props or labels passed to PayloadWidget to accept the fallback string.
---
Nitpick comments:
In
`@workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts`:
- Around line 129-131: The fractional magic numbers (0.2 and 4.8) used in
InputNode (when adjusting parentPort/this.numberOfFields) are fragile; replace
them with named, derived constants computed from the authoritative
IO_NODE_FIELD_HEIGHT in styles.ts (or import that constant) — e.g., compute
PAYLOAD_FIELD_COUNT_OFFSET = (IO_NODE_FIELD_HEIGHT * 5) / IO_NODE_FIELD_HEIGHT -
HEADER_ROW_FRACTION or define HEADER_GAP_FRACTION and PAYLOAD_ROWS and use
PAYLOAD_OFFSET = PAYLOAD_ROWS - HEADER_GAP_FRACTION — then use those constants
in the same places (the adjustments inside InputNode where
parentPort.attributes.collapsed is checked and the other spot around lines
148-150) and add a single-line comment referencing styles.ts and
IO_NODE_FIELD_HEIGHT to explain the derivation so changes to styles
automatically keep the math correct.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
workspaces/common-libs/font-wso2-vscode/src/icons/arrow-down-right.svgis excluded by!**/*.svgworkspaces/common-libs/font-wso2-vscode/src/icons/arrow-left-up.svgis excluded by!**/*.svg
📒 Files selected for processing (7)
workspaces/ballerina/ballerina-side-panel/src/components/NodeList/index.tsxworkspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.tsworkspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsxworkspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsxworkspaces/ballerina/data-mapper/src/components/Diagram/Node/commons/PayloadWidget.tsxworkspaces/ballerina/data-mapper/src/components/Diagram/utils/common-utils.tsworkspaces/ballerina/data-mapper/src/components/styles.ts
| <PayloadWidget | ||
| onClick={async () => await context.createConvertedVariable(headerLabel, true, undefined, dmType.typeName)} | ||
| typeName={dmType.typeName.toUpperCase()} | ||
| /> |
There was a problem hiding this comment.
Same typeName.toUpperCase() null-safety risk as in ObjectOutputWidget.
dmType.typeName may be undefined; if so, this line throws before the PayloadWidget can render. Since isConvertibleType guarantees the kind is TypeKind.Json or TypeKind.Xml, using typeKind as a fallback is always valid.
🛡️ Proposed fix
- <PayloadWidget
- onClick={async () => await context.createConvertedVariable(headerLabel, true, undefined, dmType.typeName)}
- typeName={dmType.typeName.toUpperCase()}
- />
+ <PayloadWidget
+ onClick={async () => await context.createConvertedVariable(headerLabel, true, undefined, dmType.typeName)}
+ typeName={(dmType.typeName ?? typeKind).toUpperCase()}
+ />📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <PayloadWidget | |
| onClick={async () => await context.createConvertedVariable(headerLabel, true, undefined, dmType.typeName)} | |
| typeName={dmType.typeName.toUpperCase()} | |
| /> | |
| <PayloadWidget | |
| onClick={async () => await context.createConvertedVariable(headerLabel, true, undefined, dmType.typeName)} | |
| typeName={(dmType.typeName ?? typeKind).toUpperCase()} | |
| /> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsx`
around lines 227 - 230, PayloadWidget is calling dmType.typeName.toUpperCase()
which can throw if dmType.typeName is undefined; update the render in
InputNodeWidget (the PayloadWidget props) to use a safe fallback: use
(dmType.typeName ?? dmType.typeKind) and then call .toUpperCase() so when
isConvertibleType guarantees TypeKind.Json or TypeKind.Xml you still show a
valid label; ensure the same safe expression is used for typeName prop and any
other places referencing dmType.typeName (e.g., the onClick
createConvertedVariable call if it relies on typeName).
There was a problem hiding this comment.
typeName is a required field, interfaces will be refactored in a separate PR
There was a problem hiding this comment.
@KCSAbeywickrama, thank you for the clarification! If typeName is a required field in the interface, then the null-safety concern doesn't apply and the code is safe as-is. I appreciate you noting that the interface definitions will be updated in a separate PR to properly reflect this requirement.
🐰✨
✏️ Learnings added
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 1545
File: workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsx:227-230
Timestamp: 2026-02-24T07:15:29.377Z
Learning: In workspaces/ballerina/data-mapper, the `typeName` property on the `IOType` interface is a required field and will never be undefined, even though the TypeScript interface definition may not currently reflect this constraint.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: sachiniSam
Repo: wso2/vscode-extensions PR: 1143
File: workspaces/ballerina/component-diagram/src/components/nodes/ConnectionNode/ConnectionNodeWidget.tsx:204-204
Timestamp: 2025-12-17T08:04:30.603Z
Learning: In workspaces/ballerina/component-diagram/src/components/nodes/ConnectionNode/ConnectionNodeWidget.tsx, the model.node object does not have a metadata field in its interface yet. It's intentionally accessed via `(model.node as any).metadata` because the metadata structure is expected to change with the edit flow implementation.
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/EntryNodeWidget.tsx : Route EntryNode rendering to specialized widgets based on service type: use AIServiceWidget for 'ai:Service', GraphQLServiceWidget for 'graphql:Service', and GeneralWidget for HTTP and other services
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/**/!(*Widget|*Model).tsx : Implement the factory pattern for node instantiation: each node type (Listener, Entry, Connection) must have a corresponding Factory class that extends the appropriate factory interface
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Keep node widgets focused on visual representation; move complex business logic to utility functions and context providers
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 998
File: workspaces/ballerina/data-mapper/src/components/DataMapper/Header/ExpressionBar.tsx:113-132
Timestamp: 2025-11-24T14:51:49.267Z
Learning: In workspaces/ballerina/data-mapper/src/components/DataMapper/Header/ExpressionBar.tsx, if `textFieldRef.current` is not undefined, `textFieldRef.current.inputElement` is guaranteed to exist. If `inputElement` doesn't exist when `current` exists, it's a fatal error that should reach the error boundary rather than being handled with defensive null checks.
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx : For regular services with more than 3 functions, show only the first 2 functions with a 'View All' button; for services with 3 or fewer functions, show all functions
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/**/*.tsx : Implement lazy expansion of functions: only render function items when they are visible to improve performance for large function lists
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/**/*.{ts,tsx} : Each node type must have a Model class extending NodeModel, a Factory class implementing the factory pattern, and a Widget React component for visual representation
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/DiagramContext.tsx : Use DiagramContext (React Context API) for state management across the diagram component, including expandedNodes and graphQLGroupOpen state
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GraphQLServiceWidget.tsx : For GraphQL services, group functions by type (Query, Subscription, Mutation) and allow independent expand/collapse of each group. Default state: Query group open, Subscription/Mutation groups collapsed
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/Diagram.tsx : Implement input validation for CDModel structure: verify that all required properties (connections, listeners, services) are present and properly typed
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 897
File: workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx:50-59
Timestamp: 2025-11-27T07:59:33.534Z
Learning: In workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx, the `clause.properties.expression` property in the `fillDefaults` function does not require defensive null/undefined checks because it's a required property enforced by form validation in ClauseEditor.
| {expanded && isConvertibleType && !outputType.convertedField && | ||
| <> | ||
| <ArrowWidget direction="up" /> | ||
| <PayloadWidget | ||
| onClick={async () => await context.createConvertedVariable(valueLabel, false, undefined, outputType.typeName)} | ||
| typeName={outputType.typeName} | ||
| /> | ||
| </> | ||
| <PayloadWidget | ||
| onClick={async () => await context.createConvertedVariable(valueLabel, false, undefined, outputType.typeName)} | ||
| typeName={outputType.typeName.toUpperCase()} | ||
| /> | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find IOType definition and typeName property
fd ".*\.(ts|tsx)$" workspaces/ballerina/data-mapper --type f | head -20 | xargs grep -l "IOType" | head -5Repository: wso2/vscode-extensions
Length of output: 48
🏁 Script executed:
#!/bin/bash
# Search for IOType interface/type definition
rg "type IOType|interface IOType" --type ts -A 5 workspaces/ballerina/Repository: wso2/vscode-extensions
Length of output: 1139
🏁 Script executed:
#!/bin/bash
# Get context around lines 219-224 in the target file
cat -n workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx | sed -n '210,235p'Repository: wso2/vscode-extensions
Length of output: 732
🏁 Script executed:
#!/bin/bash
# Find type of outputType and understand the isConvertibleType guard
cat -n workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx | sed -n '75,95p'Repository: wso2/vscode-extensions
Length of output: 804
🏁 Script executed:
#!/bin/bash
# Check the broader context to understand typeKind
cat -n workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx | sed -n '1,50p'Repository: wso2/vscode-extensions
Length of output: 2599
🏁 Script executed:
#!/bin/bash
# Check TypeKind enum definition
rg "export enum TypeKind|export const TypeKind" --type ts -A 10 workspaces/ballerina/ballerina-core/Repository: wso2/vscode-extensions
Length of output: 1104
🏁 Script executed:
#!/bin/bash
# Check if there are any usages or initialization patterns for outputType.typeName
rg "outputType\.typeName" --type ts -B 2 -A 2 workspaces/ballerina/data-mapper/src/components/Diagram/ | head -50Repository: wso2/vscode-extensions
Length of output: 1578
outputType.typeName?.toUpperCase() can throw if typeName is undefined.
IOType.typeName is optional (typeName?: string). The isConvertibleType guard at line 85 ensures kind is Json or Xml, but does not guarantee typeName is defined. Calling .toUpperCase() on undefined will raise a TypeError at runtime.
Use optional chaining or provide a safe fallback:
💡 Suggested approach
- typeName={outputType.typeName.toUpperCase()}
+ typeName={outputType.typeName?.toUpperCase()}Or with explicit fallback:
- typeName={outputType.typeName.toUpperCase()}
+ typeName={(outputType.typeName ?? typeKind).toUpperCase()}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {expanded && isConvertibleType && !outputType.convertedField && | |
| <> | |
| <ArrowWidget direction="up" /> | |
| <PayloadWidget | |
| onClick={async () => await context.createConvertedVariable(valueLabel, false, undefined, outputType.typeName)} | |
| typeName={outputType.typeName} | |
| /> | |
| </> | |
| <PayloadWidget | |
| onClick={async () => await context.createConvertedVariable(valueLabel, false, undefined, outputType.typeName)} | |
| typeName={outputType.typeName.toUpperCase()} | |
| /> | |
| } | |
| {expanded && isConvertibleType && !outputType.convertedField && | |
| <PayloadWidget | |
| onClick={async () => await context.createConvertedVariable(valueLabel, false, undefined, outputType.typeName)} | |
| typeName={outputType.typeName?.toUpperCase()} | |
| /> | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx`
around lines 219 - 224, In ObjectOutputWidget.tsx the render for PayloadWidget
calls outputType.typeName.toUpperCase() which can throw if typeName is undefined
(IOType.typeName is optional); change the call in the JSX where PayloadWidget is
created (the block that checks expanded && isConvertibleType &&
!outputType.convertedField) to safely handle missing typeName by using optional
chaining and a fallback (e.g., outputType.typeName?.toUpperCase() ?? 'UNKNOWN'
or similar) so the UI never calls .toUpperCase() on undefined; update any
related props or labels passed to PayloadWidget to accept the fallback string.
There was a problem hiding this comment.
typeName is a required field, interfaces will be refactored in a separate PR
There was a problem hiding this comment.
@KCSAbeywickrama, thank you for the clarification! If typeName is guaranteed to be present at runtime, then the optional chaining isn't necessary. I appreciate you noting that the interface will be updated in a separate PR to reflect this requirement.
✏️ Learnings added
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 1545
File: workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx:219-224
Timestamp: 2026-02-24T07:15:43.238Z
Learning: In workspaces/ballerina/data-mapper, IOType.typeName is marked as optional in the TypeScript interface (typeName?: string), but it is guaranteed to be a required field at runtime. The interface will be refactored in a future PR to reflect this requirement.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: sachiniSam
Repo: wso2/vscode-extensions PR: 1143
File: workspaces/ballerina/component-diagram/src/components/nodes/ConnectionNode/ConnectionNodeWidget.tsx:204-204
Timestamp: 2025-12-17T08:04:30.603Z
Learning: In workspaces/ballerina/component-diagram/src/components/nodes/ConnectionNode/ConnectionNodeWidget.tsx, the model.node object does not have a metadata field in its interface yet. It's intentionally accessed via `(model.node as any).metadata` because the metadata structure is expected to change with the edit flow implementation.
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/EntryNodeWidget.tsx : Route EntryNode rendering to specialized widgets based on service type: use AIServiceWidget for 'ai:Service', GraphQLServiceWidget for 'graphql:Service', and GeneralWidget for HTTP and other services
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/**/!(*Widget|*Model).tsx : Implement the factory pattern for node instantiation: each node type (Listener, Entry, Connection) must have a corresponding Factory class that extends the appropriate factory interface
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx : For regular services with more than 3 functions, show only the first 2 functions with a 'View All' button; for services with 3 or fewer functions, show all functions
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/**/*.{ts,tsx} : Each node type must have a Model class extending NodeModel, a Factory class implementing the factory pattern, and a Widget React component for visual representation
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Keep node widgets focused on visual representation; move complex business logic to utility functions and context providers
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 897
File: workspaces/ballerina/data-mapper/src/components/Diagram/Label/MappingOptionsWidget.tsx:102-107
Timestamp: 2025-11-27T07:58:16.698Z
Learning: In workspaces/ballerina/data-mapper/src/components/Diagram/Label/MappingOptionsWidget.tsx, the `inProgress` state in `wrapWithProgress` intentionally doesn't reset to `false`. The component unmounts when the onClick operation finishes, and resetting the state would cause the mapping options menu to briefly reappear while the data mapper loads new content from file changes.
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/**/*.tsx : Implement lazy expansion of functions: only render function items when they are visible to improve performance for large function lists
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 998
File: workspaces/ballerina/data-mapper/src/components/DataMapper/Header/ExpressionBar.tsx:113-132
Timestamp: 2025-11-24T14:51:49.267Z
Learning: In workspaces/ballerina/data-mapper/src/components/DataMapper/Header/ExpressionBar.tsx, if `textFieldRef.current` is not undefined, `textFieldRef.current.inputElement` is guaranteed to exist. If `inputElement` doesn't exist when `current` exists, it's a fatal error that should reach the error boundary rather than being handled with defensive null checks.
Learnt from: kanushka
Repo: wso2/vscode-extensions PR: 1117
File: workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx:1183-1184
Timestamp: 2025-12-16T13:47:11.133Z
Learning: In workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx, the findMatchedType function intentionally uses module?.split('.').pop() to handle simple cases where the last segment of the module name is used for matching. Wildcard imports should be used for collision cases (when different modules have the same last segment), but this is not currently implemented as the code only handles the simple case for now.
Learnt from: pasindufernando1
Repo: wso2/vscode-extensions PR: 1307
File: workspaces/ballerina/data-mapper/src/components/Diagram/Node/commons/DataMapperNode.ts:273-306
Timestamp: 2026-01-26T07:30:11.584Z
Learning: In workspaces/ballerina/data-mapper, tuple member names (field.name) are always set because they are generated from the member index in the backend (processTuple function), so defensive null/undefined checks for fieldName in tuple-specific FQN branches are not required.
Learnt from: CR
Repo: wso2/vscode-extensions PR: 0
File: workspaces/ballerina/component-diagram/AGENTS.md:0-0
Timestamp: 2025-11-25T06:34:10.812Z
Learning: Applies to workspaces/ballerina/component-diagram/src/components/Diagram.tsx : Implement input validation for CDModel structure: verify that all required properties (connections, listeners, services) are present and properly typed
There was a problem hiding this comment.
Pull request overview
This PR enhances the UI for converted variables in the BI Data Mapper by improving visual indicators, icons, and messaging. The changes make JSON and XML types expandable and refine the user experience for creating sample payloads.
Changes:
- Added new arrow icons (
arrow-left-up.svgandarrow-down-right.svg) to visually indicate type-defined variables - Updated converted variable UI with new icons, tooltips, and improved spacing/sizing for payload widgets
- Made JSON and XML types expandable in data mapper diagrams
- Refined messaging for sample payload creation with clearer, more concise text
Reviewed changes
Copilot reviewed 7 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
workspaces/common-libs/font-wso2-vscode/src/icons/arrow-left-up.svg |
Added new arrow icon for output converted variables |
workspaces/common-libs/font-wso2-vscode/src/icons/arrow-down-right.svg |
Added new arrow icon for input converted variables |
workspaces/ballerina/data-mapper/src/components/styles.ts |
Updated payload widget styling with new height, spacing, and note styling |
workspaces/ballerina/data-mapper/src/components/Diagram/utils/common-utils.ts |
Extended isExpandable to include JSON and XML types |
workspaces/ballerina/data-mapper/src/components/Diagram/Node/commons/PayloadWidget.tsx |
Updated payload widget messaging and icon, made typeName required |
workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx |
Updated output widget with new converted variable icon, removed arrow widget, changed edit icon |
workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsx |
Updated input widget with new converted variable icon, removed arrow widget, changed edit icon |
workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts |
Adjusted numberOfFields calculations for proper spacing |
workspaces/ballerina/ballerina-side-panel/src/components/NodeList/index.tsx |
Added title parameter to getCategoryActions calls |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| onClick={handleExpand} | ||
| data-testid={`${id}-expand-icon-record-source-node`} | ||
| tooltip="Type defined variable" | ||
| onClick={() => { }} |
There was a problem hiding this comment.
Empty arrow function onClick handler should be replaced with undefined if no action is needed, or removed entirely if the button doesn't need to be clickable. Using an empty function is less clear about intent.
| onClick={() => { }} |
| id={"converted-icon-" + id} | ||
| appearance="icon" | ||
| tooltip="Type defined variable" | ||
| onClick={() => { }} |
There was a problem hiding this comment.
Empty arrow function onClick handler should be replaced with undefined if no action is needed, or removed entirely if the button doesn't need to be clickable. Using an empty function is less clear about intent.
| onClick={() => { }} |
…dget and ObjectOutputWidget buttons
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsx`:
- Around line 152-171: The ConvertedVariable branch removes the expand/collapse
Button but the component still computes expanded from
portOut.attributes.collapsed, causing converted nodes to stay collapsed with no
toggle; modify the logic in InputNodeWidget (where dmType.category is compared
to InputCategory.ConvertedVariable and expanded is derived from
portOut.attributes.collapsed) so that when dmType.category ===
InputCategory.ConvertedVariable you force expanded to true (ignore
portOut.attributes.collapsed) or otherwise always render the converted fields,
and ensure handleExpand/expand button logic is untouched for other categories.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsxworkspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx
Results
Summary by CodeRabbit
New Features
Bug Fixes & Improvements