Skip to content

Comments

[BI Data Mapper] Improve data mapper converted-variable UI#1545

Open
KCSAbeywickrama wants to merge 5 commits intowso2:release/bi-1.8.xfrom
KCSAbeywickrama:bi-dm-side-panel-txt-update
Open

[BI Data Mapper] Improve data mapper converted-variable UI#1545
KCSAbeywickrama wants to merge 5 commits intowso2:release/bi-1.8.xfrom
KCSAbeywickrama:bi-dm-side-panel-txt-update

Conversation

@KCSAbeywickrama
Copy link
Contributor

@KCSAbeywickrama KCSAbeywickrama commented Feb 24, 2026

Results

image

Summary by CodeRabbit

  • New Features

    • JSON and XML types are now expandable in data mapper diagrams.
  • Bug Fixes & Improvements

    • Category actions now respect the current panel title, improving contextual actions.
    • Distinct controls and tooltips for converted variables; updated icons and edit flow.
    • Payload widget text, spacing and size refined ( clearer guidance and larger click targets ).
    • Nested converted-field rendering simplified for clearer, more consistent visuals.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

📝 Walkthrough

Walkthrough

Propagates 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

Cohort / File(s) Summary
getCategoryActions API Update
workspaces/ballerina/ballerina-side-panel/src/components/NodeList/index.tsx, workspaces/ballerina/ballerina-side-panel/src/components/NodeList/categoryConfig
Changed calls to pass title through; updated exported signature getCategoryActions(groupTitle: string)getCategoryActions(groupTitle: string, title: string).
Input field count logic
workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts
Adjusted numeric increments used to compute numberOfFields for ConvertedField and non-converted payload branches (2 → 0.2; 6 → 4.8).
Converted variables UI rendering (Input & Output)
workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsx, workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx
For ConvertedVariable category: replaced expand/collapse control with distinct indicator button, changed FieldActionButton icon from settings-gear to edit, removed ArrowWidget wrappers for nested converted-field rendering, and updated tooltips/labels and payload click behavior.
PayloadWidget props & copy + styles
workspaces/ballerina/data-mapper/src/components/Diagram/Node/commons/PayloadWidget.tsx, workspaces/ballerina/data-mapper/src/components/styles.ts
Made typeName required, changed messaging to payloadNote, swapped action icon to new-file, capitalized action label, increased widget height, adjusted spacing and padding, and updated visual styles (background, border-left, border-radius).
Type expandability util
workspaces/ballerina/data-mapper/src/components/Diagram/utils/common-utils.ts
Updated isExpandable(field) to treat Json and Xml TypeKind values as expandable in addition to Record/Array/Enum; cached field.kind locally.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

"I hopped through code and made it neat,
Converted fields wear a different seat,
Payloads glow with a styled new note,
JSON and XML can now expand and float,
Icons changed — a merry little feat!" 🐇✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete, containing only a Results section with an image but missing all required template sections (Purpose, Goals, Approach, UI Component Development, etc.) despite the template being clearly defined. Complete the PR description by filling in all required template sections including Purpose, Goals, Approach, UI Component Development checklist, Release Notes, and other mandatory documentation sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: improving the data mapper converted-variable UI, which aligns with the substantial UI modifications across multiple components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.2 and 4.8 are calibration offsets tied to the rendered heights in styles.ts (IO_NODE_FIELD_HEIGHT * 5 for the payload widget, plus header gaps). If either the style or IO_NODE_FIELD_HEIGHT changes, 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

📥 Commits

Reviewing files that changed from the base of the PR and between ebf8a66 and 0a00baf.

⛔ Files ignored due to path filters (2)
  • workspaces/common-libs/font-wso2-vscode/src/icons/arrow-down-right.svg is excluded by !**/*.svg
  • workspaces/common-libs/font-wso2-vscode/src/icons/arrow-left-up.svg is excluded by !**/*.svg
📒 Files selected for processing (7)
  • workspaces/ballerina/ballerina-side-panel/src/components/NodeList/index.tsx
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNode.ts
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsx
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/ObjectOutput/ObjectOutputWidget.tsx
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/commons/PayloadWidget.tsx
  • workspaces/ballerina/data-mapper/src/components/Diagram/utils/common-utils.ts
  • workspaces/ballerina/data-mapper/src/components/styles.ts

Comment on lines +227 to +230
<PayloadWidget
onClick={async () => await context.createConvertedVariable(headerLabel, true, undefined, dmType.typeName)}
typeName={dmType.typeName.toUpperCase()}
/>
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Suggested change
<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).

Copy link
Contributor Author

@KCSAbeywickrama KCSAbeywickrama Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeName is a required field, interfaces will be refactored in a separate PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Comment on lines 219 to 224
{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()}
/>
}
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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 -5

Repository: 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 -50

Repository: 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.

Suggested change
{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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeName is a required field, interfaces will be refactored in a separate PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.svg and arrow-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={() => { }}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
onClick={() => { }}

Copilot uses AI. Check for mistakes.
id={"converted-icon-" + id}
appearance="icon"
tooltip="Type defined variable"
onClick={() => { }}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
onClick={() => { }}

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0a00baf and 9dca054.

📒 Files selected for processing (2)
  • workspaces/ballerina/data-mapper/src/components/Diagram/Node/Input/InputNodeWidget.tsx
  • workspaces/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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants