-
Notifications
You must be signed in to change notification settings - Fork 67
Improve file integration funcitonality #887
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughFTP file integration support added with a new GeneralPayloadContext interface enabling protocol-aware payload handling. Boolean GraphQL flags replaced by payloadContext objects, FTP-specific form components and type-filtering logic were introduced, plus UI and icon updates to surface FTP/file integrations. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ServiceDesigner
participant FTPConfigForm
participant FTPForm
participant ParamEditor
participant TypeEditor
participant Project
User->>ServiceDesigner: Click "Add File Handler"
ServiceDesigner->>FTPConfigForm: Render list of non-enabled handlers
User->>FTPConfigForm: Select event (onCreate/onDelete)
FTPConfigForm->>ServiceDesigner: onSubmit(selectedHandler)
ServiceDesigner->>FTPForm: Render FTPForm with selected handler
rect rgb(220,240,220)
Note over FTPForm,TypeEditor: FTP Form → Define Content Schema flow
User->>FTPForm: Choose file format (JSON/XML/CSV)
FTPForm->>TypeEditor: Open EntryPointTypeCreator / FormTypeEditor with payloadContext {protocol:"FTP", filterType:"..."}
TypeEditor->>Project: Create/submit payload type
FTPForm->>FTPForm: Attach created type to DATA_BINDING parameter
end
User->>FTPForm: Edit parameter
FTPForm->>ParamEditor: Open ParamEditor
ParamEditor->>TypeEditor: Render FormGeneratorNew with payloadContext
User->>TypeEditor: Select filtered type
ParamEditor->>FTPForm: Return updated parameter
User->>FTPForm: Save
FTPForm->>ServiceDesigner: handleFunctionSubmit
ServiceDesigner->>Project: Persist configuration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ 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 |
7961bce to
b5ebf99
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx (1)
153-153: Remove debug console log.This debug log should be removed before merging to production.
Apply this diff:
- console.log("Choice Form Index:", Number(e.target.value))
🧹 Nitpick comments (13)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx (2)
118-135: RecordTypeField creation logic is correct.The logic correctly creates RecordTypeField entries when typeMembers are present, and the structure matches the expected type definition.
Optionally, you could simplify the property construction by reusing expression properties:
const recordTypeField: RecordTypeField = { key: key, property: { - metadata: expression.metadata || { label: "", description: "" }, - valueType: expression.valueType || "EXPRESSION", - value: expression.value || "", - optional: expression.optional || false, - editable: expression.editable !== undefined ? expression.editable : true, - valueTypeConstraint: expression.valueTypeConstraint, - typeMembers: expression.typeMembers + ...expression, + metadata: expression.metadata || { label: "", description: "" }, + valueType: expression.valueType || "EXPRESSION", + value: expression.value || "" }, recordTypeMembers: expression.typeMembers };
164-176: Move recordTypeFields merge outside the map function.The merging of
recordTypeFieldswithdynamicRecordTypeFieldsis currently performed on every iteration of the map, which is inefficient. Since the merged array is identical for all iterations, it should be computed once before the map.Apply this diff to improve performance:
+ {(() => { + // Merge parent recordTypeFields with dynamically generated ones + const mergedRecordTypeFields = [ + ...(recordTypeFields || []), + ...dynamicRecordTypeFields + ]; + + return dynamicFields.map((dfield, index) => { - <FormSection> - {dynamicFields.map((dfield, index) => { - // Merge parent recordTypeFields with dynamically generated ones - const mergedRecordTypeFields = [ - ...(recordTypeFields || []), - ...dynamicRecordTypeFields - ]; - return ( <EditorFactory key={dfield.key} field={dfield} autoFocus={index === 0 ? true : false} recordTypeFields={mergedRecordTypeFields} /> ); - })} + }); + })()} </FormSection>Alternatively, use
useMemofor a cleaner approach:const mergedRecordTypeFields = React.useMemo(() => [ ...(recordTypeFields || []), ...dynamicRecordTypeFields ], [recordTypeFields, dynamicRecordTypeFields]); // Then in JSX: <FormSection> {dynamicFields.map((dfield, index) => ( <EditorFactory key={dfield.key} field={dfield} autoFocus={index === 0} recordTypeFields={mergedRecordTypeFields} /> ))} </FormSection>workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/ContextTypeEditor.tsx (1)
141-143: Minor formatting inconsistency in conditional.The FTP-specific initial tab logic is correct. However, there's a minor formatting inconsistency with the missing space after
if.- if( payloadContext?.protocol === "FTP"){ + if (payloadContext?.protocol === "FTP") { return "create-from-scratch"; }workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx (1)
1023-1023: Inline object creation on every render.The migration from
isGraphqltopayloadContextaligns with the PR's context-based approach. However, creating the object inline{{protocol: "GRAPHQL"}}will produce a new object reference on every render, which could cause unnecessary re-renders in child components that use reference equality checks.Consider extracting to a constant if this causes performance issues:
const GRAPHQL_PAYLOAD_CONTEXT = { protocol: "GRAPHQL" } as const; // Then use: payloadContext={GRAPHQL_PAYLOAD_CONTEXT}workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/FTPConfigForm.tsx (1)
33-33: Minor formatting nit.Missing space after comma in destructuring.
- const { onBack, onSubmit,isSaving } = props; + const { onBack, onSubmit, isSaving } = props;workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/ParamEditor.tsx (2)
48-53: Missing dependency in useEffect causes stale closure.The effect uses
rpcClientbut doesn't include it in the dependency array. Also,updateFormFieldsis called here and again via the effect on line 75-77, causing redundant initialization.useEffect(() => { rpcClient.getVisualizerRpcClient().joinProjectPath({ segments: ['main.bal'] }).then((response) => { setFilePath(response.filePath); }); - updateFormFields(); - }, []); + }, [rpcClient]);The
updateFormFields()call can be removed since the effect at lines 75-77 will handle it whenparam.typechanges.
75-77: Missingparamin dependency array.The effect depends on
param.typebut only listsparam.typewhich may not trigger re-runs correctly in all cases. SinceupdateFormFieldsreads fromparam, the fullparamobject or a more stable reference should be considered.useEffect(() => { updateFormFields(); - }, [param.type]); + }, [param]);workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsx (1)
182-184: Stale closure risk: MissingisGraphqlin dependency array.The
debouncedSearchTypeHelpercallback usesisGraphql(line 113) but the dependency array doesn't include it. SinceisGraphqlis derived frompayloadContext, consider addingpayloadContextorisGraphqlto the dependencies.}, 150), - [basicTypes, filePath, targetLineRange, rpcClient] + [basicTypes, filePath, targetLineRange, rpcClient, isGraphql, payloadContext] );workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx (1)
1012-1022: EmptygoToSourcecallback is a no-op.Passing an empty function
() => { }forgoToSourcemeans clicking to view source does nothing. If this functionality isn't supported for FTP handlers, consider either hiding the button inResourceAccordionor implementing the navigation.{enabledHandlers.map((functionModel, index) => ( <ResourceAccordion key={`${index}-${functionModel.name.value}`} method={functionModel.metadata.label} functionModel={functionModel} - goToSource={() => { }} + goToSource={handleOpenDiagram} onEditResource={handleFunctionEdit} onDeleteResource={handleFunctionDelete} onResourceImplement={handleOpenDiagram} /> ))}workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx (1)
65-74: DuplicateHeaderLabelstyled component.
HeaderLabelis already imported from../../../styles(visible in relevant_code_snippets) but is redefined here with slightly different styling (margin instead of margin-top). This creates inconsistency. Consider either using the imported one or renaming this local variant.-const HeaderLabel = styled.div<CSSObject>` +const ParameterHeaderLabel = styled.div<CSSObject>` display: flex; background: var(--vscode-editor-background); border: 1px solid ${(props: { haveErrors: boolean; }) => props.haveErrors ? "red" : "var(--vscode-dropdown-border)"}; margin: 8px 0; - display: flex; width: 100%; height: 32px; align-items: center; `;Note: There's also a duplicate
display: flexdeclaration that can be removed.workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx (3)
26-26: Unused import:hasfrom lodash.The
hasfunction is imported but never used in this file.-import { has } from 'lodash';
86-95: Consider memoizingnonEnabledFunctions.This filtering logic runs on every render. Since it depends on
serviceModel.functionsandselectedHandler, it should be memoized withuseMemo.+import { useMemo } from 'react'; - // Filter non-enabled functions for dropdown options based on selected handler - const nonEnabledFunctions = serviceModel.functions?.filter(fn => { + const nonEnabledFunctions = useMemo(() => serviceModel.functions?.filter(fn => { if (!fn.enabled && selectedHandler && fn.metadata?.label === selectedHandler) { return true; } - // If no selectedHandler is provided, default to onCreate for backward compatibility if (!fn.enabled && !selectedHandler && fn.metadata?.label === "onCreate") { return true; } return false; - }) || []; + }) || [], [serviceModel.functions, selectedHandler]);
98-120: Stale closure and dependency issues in useEffect hooks.The effects at lines 98-111 and 114-120 have dependency issues:
- Both depend on
nonEnabledFunctionswhich is recalculated every render but not in the dependency array.isNewis used but not in the dependency array of the first effect.Since the ESLint rule is disabled, these issues are hidden. After memoizing
nonEnabledFunctions, add it to the dependency arrays.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
workspaces/ballerina/ballerina-core/src/interfaces/service.ts(1 hunks)workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx(4 hunks)workspaces/ballerina/ballerina-visualizer/src/components/EntryPointTypeCreator/index.tsx(0 hunks)workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx(2 hunks)workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx(1 hunks)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/FTPConfigForm.tsx(1 hunks)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/ParamEditor.tsx(1 hunks)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx(1 hunks)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx(1 hunks)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx(16 hunks)workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsx(2 hunks)workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsx(5 hunks)workspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx(2 hunks)workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/ContextTypeEditor.tsx(1 hunks)workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/GenericImportTab.tsx(3 hunks)
💤 Files with no reviewable changes (1)
- workspaces/ballerina/ballerina-visualizer/src/components/EntryPointTypeCreator/index.tsx
🧰 Additional context used
🧠 Learnings (15)
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.tsx : Use React 18.2.0 features including concurrent rendering and automatic batching; avoid class components in favor of functional components with hooks
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/ParamEditor.tsxworkspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/GenericImportTab.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsxworkspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/FTPConfigForm.tsxworkspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.{ts,tsx} : Define all constants (node types, sizing, spacing) in src/resources/constants.ts and import them where needed instead of hardcoding values
Applied to files:
workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/GenericImportTab.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/GenericImportTab.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.tsx : Use Emotion for CSS-in-JS styling instead of inline styles or external CSS files
Applied to files:
workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/GenericImportTab.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx
📚 Learning: 2025-11-24T22:16:28.380Z
Learnt from: dan-niles
Repo: wso2/vscode-extensions PR: 980
File: workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/RichTextTemplateEditor/RichTextTemplateEditor.tsx:384-412
Timestamp: 2025-11-24T22:16:28.380Z
Learning: In the RichTextTemplateEditor component (workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/RichTextTemplateEditor/RichTextTemplateEditor.tsx), token fetching on external `value` prop changes is intentionally disabled. Users cannot edit both the minimized and expanded editors simultaneously, so tokens only need to be generated based on user typing in the expanded editor view, not on external prop updates.
Applied to files:
workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/GenericImportTab.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.{ts,tsx} : Use TypeScript 5.8.3 with strict type checking enabled for all source files
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx
📚 Learning: 2025-12-12T08:55:43.437Z
Learnt from: dan-niles
Repo: wso2/vscode-extensions PR: 1080
File: workspaces/ballerina/ballerina-visualizer/src/views/BI/AIChatAgent/AddMcpServer.tsx:269-281
Timestamp: 2025-12-12T08:55:43.437Z
Learning: In `FormGenerator` component used in AddMcpServer.tsx, the component automatically triggers `onChange` callbacks with saved field values during initialization when a `node` prop is provided, so manual state setter calls (e.g., setServerUrl, setAuth) are not needed in initialization logic like initializeEditMode.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/resources/icons/**/*.tsx : Create separate SVG icon components in src/resources/icons/ for all diagram icons and import them as React components
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx
📚 Learning: 2025-11-27T07:59:33.534Z
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.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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 proper error boundaries around the Diagram component to gracefully handle rendering errors without crashing the parent application
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/index.ts : Export the main Diagram component as the default export from the package entry point (index.ts)
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx
🧬 Code graph analysis (6)
workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/GenericImportTab.tsx (1)
workspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
GeneralPayloadContext(127-131)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx (2)
workspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
ParameterModel(186-192)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/styles.tsx (6)
HeaderLabel(124-133)disabledHeaderLabel(117-122)headerLabelStyles(102-108)ActionIconWrapper(135-141)EditIconWrapper(62-69)DeleteIconWrapper(71-79)
workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsx (3)
workspaces/ballerina/ballerina-core/src/interfaces/extended-lang-client.ts (1)
VisibleTypeItem(1165-1174)workspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
GeneralPayloadContext(127-131)workspaces/ballerina/type-editor/src/TypeHelper/index.tsx (1)
TypeHelperCategory(51-56)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx (4)
workspaces/ballerina/ballerina-core/src/interfaces/bi.ts (1)
RecordTypeField(154-158)workspaces/ballerina/ballerina-visualizer/src/utils/bi.tsx (1)
convertConfig(961-980)workspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
PropertyModel(159-184)workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx (1)
EditorFactory(70-239)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/FTPConfigForm.tsx (2)
workspaces/common-libs/rpc-generator/index.js (1)
handlerName(316-316)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx (1)
EditorContentColumn(49-55)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx (3)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/components/ResourceAccordion.tsx (1)
ResourceAccordion(138-234)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/utils.tsx (1)
canDataBind(76-78)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx (1)
FTPForm(68-539)
🔇 Additional comments (12)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx (3)
61-61: LGTM!The new state variable appropriately tracks dynamic record type fields generated from choice selections.
67-69: LGTM!The destructuring and state updates correctly handle the refactored convertConfig return value.
79-81: LGTM!The refactored return type improves clarity by explicitly returning both form fields and record type fields as a structured object.
workspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
127-133: LGTM - New GeneralPayloadContext interface extends payload handling.The addition of
GeneralPayloadContextwith a flexibleprotocol: stringfield provides a generic mechanism for FTP and other protocols without needing dedicated interfaces for each. The optionalfilterTypeandhideJsonTypeFallbackfields support the FTP-specific type filtering behavior seen in downstream components.Consider documenting the expected protocol values (e.g., "FTP", "GRAPHQL") to help consumers understand the contract.
workspaces/ballerina/type-editor/src/TypeEditor/ContextBasedTypeEditor/GenericImportTab.tsx (1)
552-559: Type assertion approach is acceptable but could be cleaner.The conditional rendering based on
hideJsonTypeFallbackcorrectly hides the JSON fallback UI for FTP flows. The type assertion(payloadContext as GeneralPayloadContext)?.hideJsonTypeFallbackis safe due to optional chaining, but repeated casting is verbose.For future maintainability, consider adding a type guard helper:
const isGeneralPayloadContext = (ctx?: PayloadContext): ctx is GeneralPayloadContext => ctx !== undefined && ctx.protocol !== "HTTP" && ctx.protocol !== "MESSAGE_BROKER";Also applies to: 587-604
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/FTPConfigForm.tsx (1)
31-67: Clean component implementation with minor observations.The
FunctionConfigFormcomponent is well-structured. A few observations:
The file is named
FTPConfigForm.tsxbut exportsFunctionConfigForm- consider aligning the naming for discoverability.The
eventsarray is hardcoded inside the component. If these events are FTP-specific constants, consider extracting them:const FTP_EVENTS = [ { name: 'onCreate', description: 'Triggered when a new file is created' }, { name: 'onDelete', description: 'Triggered when a file is deleted' } ] as const;workspaces/ballerina/ballerina-visualizer/src/views/GraphQLDiagram/index.tsx (1)
478-478: Consistent migration to payloadContext pattern.Both
FormTypeEditorusages have been correctly updated fromisGraphql={true}topayloadContext={{protocol: "GRAPHQL"}}, maintaining consistency with the broader PR changes.Also applies to: 512-512
workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx (2)
1578-1578: Consistent payloadContext usage in default form modal.The default form's type editor modal correctly uses the GraphQL payload context without additional filtering.
1447-1452: filterType: "INPUT" is GraphQL-specific context for variable declarations.The
payloadContextfor the VariableForm includesfilterType: "INPUT", which is intentionally used for GraphQL variable type declarations. This value prevents the inclusion of JSON/XML/CSV-specific data type categories that are added for other protocols, keeping the type editor focused on GraphQL input types appropriate for variable declarations.workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsx (1)
47-47: Function signature extended to support payload context.The
getTypesfunction now accepts an optionalpayloadContextparameter, enabling protocol-aware type filtering. This is a backward-compatible change.workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsx (1)
59-61: Good refactor: DerivingisGraphqlfrompayloadContext.This change correctly centralizes protocol detection logic, making the component more flexible for supporting different payload contexts (GraphQL, FTP, etc.) without requiring separate boolean props.
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx (1)
1355-1373: Panel title logic appears inverted.The condition
selectedFTPHandler !== "onDelete"shows "On Create Handler Configuration" when the handler is NOT "onDelete", but this seems backwards. WhenselectedFTPHandlerisundefinedor any value other than "onDelete", it shows "On Create", which may not be correct for all cases.Please verify the title logic is correct. Consider using a more explicit condition:
<PanelContainer - title={selectedFTPHandler !=="onDelete" ? "On Create Handler Configuration" : "On Delete Handler Configuration"} + title={selectedFTPHandler === "onDelete" ? "On Delete Handler Configuration" : `${selectedFTPHandler || 'On Create'} Handler Configuration`} show={showForm}
| console.log(`>>> Processing property: ${key}`, { | ||
| valueType: expression.valueType, | ||
| valueTypeConstraint: expression.valueTypeConstraint, | ||
| hasTypeMembers: !!expression.typeMembers, | ||
| typeMembersLength: expression.typeMembers?.length || 0, | ||
| typeMembers: expression.typeMembers | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove debug console logs.
These verbose console logs should be removed before merging to production. If logging is needed for troubleshooting, consider using a proper logging framework that can be controlled via environment variables.
Apply this diff to remove the debug logs:
- console.log(`>>> Processing property: ${key}`, {
- valueType: expression.valueType,
- valueTypeConstraint: expression.valueTypeConstraint,
- hasTypeMembers: !!expression.typeMembers,
- typeMembersLength: expression.typeMembers?.length || 0,
- typeMembers: expression.typeMembers
- });
-📝 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.
| console.log(`>>> Processing property: ${key}`, { | |
| valueType: expression.valueType, | |
| valueTypeConstraint: expression.valueTypeConstraint, | |
| hasTypeMembers: !!expression.typeMembers, | |
| typeMembersLength: expression.typeMembers?.length || 0, | |
| typeMembers: expression.typeMembers | |
| }); |
🤖 Prompt for AI Agents
In
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx
around lines 86 to 92, remove the debug console.log that prints expression
details; delete the entire console.log(...) call and related interim object, or
replace it with a controlled logger (e.g., use an existing logging utility or
wrap with if (process.env.NODE_ENV !== 'production' && debugEnabled)
logger.debug(...)) so no verbose console output reaches production.
| console.log(">>> Final Dynamic Form Fields:", formFields) | ||
| console.log(">>> Final Dynamic Record Type Fields:", recordTypeFieldsForChoice) | ||
| return { formFields, recordTypeFieldsForChoice }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove debug console logs.
These debug logs should also be removed before merging to production.
Apply this diff to remove the debug logs:
- console.log(">>> Final Dynamic Form Fields:", formFields)
- console.log(">>> Final Dynamic Record Type Fields:", recordTypeFieldsForChoice)📝 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.
| console.log(">>> Final Dynamic Form Fields:", formFields) | |
| console.log(">>> Final Dynamic Record Type Fields:", recordTypeFieldsForChoice) | |
| return { formFields, recordTypeFieldsForChoice }; | |
| return { formFields, recordTypeFieldsForChoice }; |
🤖 Prompt for AI Agents
In
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx
around lines 137 to 139, remove the two debug console.log statements that print
">>> Final Dynamic Form Fields:" and ">>> Final Dynamic Record Type Fields:" so
the function returns only the computed values; simply delete those console.log
lines and keep the existing return { formFields, recordTypeFieldsForChoice }
unchanged.
| @@ -0,0 +1,539 @@ | |||
| /* eslint-disable react-hooks/exhaustive-deps */ | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Avoid blanket ESLint disable for hooks rules.
Disabling react-hooks/exhaustive-deps for the entire file hides legitimate dependency issues. Instead, fix the actual dependency problems or add targeted disable comments with explanations for specific cases.
Remove the blanket disable and address the underlying issues in the useEffect hooks.
🤖 Prompt for AI Agents
In
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
around line 1, remove the top-line blanket ESLint disable for
react-hooks/exhaustive-deps and instead resolve each useEffect dependency issue:
review every useEffect, add missing dependencies (or memoize functions/values
with useCallback/useMemo), and if a dependency is intentionally omitted, add a
single-line eslint-disable-next-line comment immediately above that useEffect
with a brief justification comment; after changes, run the linter to confirm no
remaining hook dependency warnings.
| const handleTypeCreated = (type: Type | string) => { | ||
| // When a type is created, set it as the payload type for the DATA_BINDING parameter | ||
| const defaultParamIndex = functionModel.parameters.findIndex(param => param.kind === "REQUIRED" && param.name.value === "content"); | ||
| const defaultParam = functionModel.parameters?.find(param => param.kind === "REQUIRED" && param.name.value === "content"); | ||
| const payloadParam = functionModel.parameters?.find(param => param.kind === "DATA_BINDING"); | ||
| if (payloadParam) { | ||
| const defaultParamModel = { ...defaultParam }; | ||
| const updatedPayloadModel = { ...payloadParam }; | ||
| updatedPayloadModel.name.value = "content"; | ||
| const typeValue = typeof type === 'string' ? type : type.name; | ||
| updatedPayloadModel.type.value = selectType(typeValue, functionModel.properties.stream?.enabled); | ||
| updatedPayloadModel.enabled = true; | ||
|
|
||
| defaultParamModel.enabled = false; // Disable the default content parameter | ||
|
|
||
| // Find the index of the payload parameter | ||
| const index = functionModel.parameters.findIndex(param => param.kind === "DATA_BINDING"); | ||
| if (index >= 0) { | ||
| const updatedParameters = [...functionModel.parameters]; | ||
| updatedParameters[index] = updatedPayloadModel; | ||
|
|
||
| // Update canDataBind property to enabled | ||
| const updatedFunctionModel = { | ||
| ...functionModel, | ||
| parameters: updatedParameters | ||
| }; | ||
| setFunctionModel(updatedFunctionModel); | ||
| } | ||
|
|
||
| // Find the index of the payload parameter | ||
|
|
||
| if (defaultParamIndex >= 0) { | ||
| const updatedParameters = [...functionModel.parameters]; | ||
| updatedParameters[defaultParamIndex] = updatedPayloadModel; | ||
|
|
||
| // Update canDataBind property to enabled | ||
| const updatedFunctionModel = { | ||
| ...functionModel, | ||
| parameters: updatedParameters | ||
| }; | ||
| setFunctionModel(updatedFunctionModel); | ||
| } | ||
| } | ||
| // Close the modal | ||
| setIsTypeEditorOpen(false); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logic issue in handleTypeCreated: Confusing dual updates and mutations.
This function has several issues:
- Direct mutation of
updatedPayloadModel.name.value(line 240) anddefaultParamModel.enabled(line 245) instead of immutable updates. - Overwriting state twice: Lines 249-258 update state, then lines 263-273 update it again, but the second update uses
updatedPayloadModelinstead ofdefaultParamModel, effectively ignoring the changes todefaultParamModel. - Sequential
setFunctionModelcalls will be batched in React 18, so only the last one takes effect.
Consider consolidating the logic:
const handleTypeCreated = (type: Type | string) => {
- // When a type is created, set it as the payload type for the DATA_BINDING parameter
- const defaultParamIndex = functionModel.parameters.findIndex(param => param.kind === "REQUIRED" && param.name.value === "content");
- const defaultParam = functionModel.parameters?.find(param => param.kind === "REQUIRED" && param.name.value === "content");
const payloadParam = functionModel.parameters?.find(param => param.kind === "DATA_BINDING");
+
if (payloadParam) {
- const defaultParamModel = { ...defaultParam };
- const updatedPayloadModel = { ...payloadParam };
- updatedPayloadModel.name.value = "content";
const typeValue = typeof type === 'string' ? type : type.name;
- updatedPayloadModel.type.value = selectType(typeValue, functionModel.properties.stream?.enabled);
- updatedPayloadModel.enabled = true;
-
- defaultParamModel.enabled = false; // Disable the default content parameter
-
- // Find the index of the payload parameter
- const index = functionModel.parameters.findIndex(param => param.kind === "DATA_BINDING");
- if (index >= 0) {
- const updatedParameters = [...functionModel.parameters];
- updatedParameters[index] = updatedPayloadModel;
-
- // Update canDataBind property to enabled
- const updatedFunctionModel = {
- ...functionModel,
- parameters: updatedParameters
- };
- setFunctionModel(updatedFunctionModel);
- }
-
- // Find the index of the payload parameter
-
- if (defaultParamIndex >= 0) {
- const updatedParameters = [...functionModel.parameters];
- updatedParameters[defaultParamIndex] = updatedPayloadModel;
-
- // Update canDataBind property to enabled
- const updatedFunctionModel = {
- ...functionModel,
- parameters: updatedParameters
- };
- setFunctionModel(updatedFunctionModel);
- }
+ const updatedParameters = functionModel.parameters.map(param => {
+ if (param.kind === "DATA_BINDING") {
+ return {
+ ...param,
+ name: { ...param.name, value: "content" },
+ type: { ...param.type, value: selectType(typeValue, functionModel.properties.stream?.enabled) },
+ enabled: true
+ };
+ }
+ return param;
+ });
+
+ setFunctionModel({
+ ...functionModel,
+ parameters: updatedParameters
+ });
}
- // Close the modal
setIsTypeEditorOpen(false);
};
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
Show resolved
Hide resolved
| const handleNewFTPFunction = (selectedHandler: string) => { | ||
| // rpcClient | ||
| // .getServiceDesignerRpcClient() | ||
| // .getFunctionModel({ type: "ftp", functionName: "remote" }) | ||
| // .then((res) => { | ||
| // console.log("New Function Model: ", res.function); | ||
| // setFunctionModel(res.function); | ||
| // setIsNew(true); | ||
| // setShowForm(true); | ||
| // }); | ||
| setShowForm(true); | ||
| // handleNewFunctionClose(); | ||
| handleFunctionConfigClose(); | ||
| setIsSaving(false); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Dead/commented code should be removed or implemented.
This function contains substantial commented-out code that appears to be placeholder implementation. The function currently just shows the form without fetching any model data, which may cause issues.
Either implement the RPC call or remove the commented code:
const handleNewFTPFunction = (selectedHandler: string) => {
- // rpcClient
- // .getServiceDesignerRpcClient()
- // .getFunctionModel({ type: "ftp", functionName: "remote" })
- // .then((res) => {
- // console.log("New Function Model: ", res.function);
- // setFunctionModel(res.function);
- // setIsNew(true);
- // setShowForm(true);
- // });
+ setSelectedFTPHandler(selectedHandler);
+ setIsNew(true);
setShowForm(true);
- // handleNewFunctionClose();
handleFunctionConfigClose();
setIsSaving(false);
};🤖 Prompt for AI Agents
In
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx
around lines 440-454, the function handleNewFTPFunction contains large
commented-out RPC code that is either dead or unfinished; remove the commented
block or fully implement the RPC call. If implementing: call
rpcClient.getServiceDesignerRpcClient().getFunctionModel({ type: "ftp",
functionName: "remote" }), await the result, setFunctionModel(res.function),
setIsNew(true), setShowForm(true), setIsSaving(false), close any config modals,
and add error handling and a loading state. If removing: delete the commented
code and keep the minimal logic (setShowForm, handleFunctionConfigClose,
setIsSaving(false)) or add a clear TODO comment indicating RPC implementation
required.
| const handleFunctionEdit = (value: FunctionModel) => { | ||
| setFunctionModel(value); | ||
| setSelectedFTPHandler(value.metadata.label); | ||
| setIsNew(false); | ||
| setShowForm(true); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting selectedFTPHandler on edit but not on new handler creation.
selectedFTPHandler is set in handleFunctionEdit but handleNewFTPFunction doesn't set it, even though it receives selectedHandler as a parameter. This may cause the FTP form panel title (line 1357) to display incorrectly.
The selectedHandler parameter in handleNewFTPFunction should be used to set state:
const handleNewFTPFunction = (selectedHandler: string) => {
+ setSelectedFTPHandler(selectedHandler);
setShowForm(true);📝 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.
| const handleFunctionEdit = (value: FunctionModel) => { | |
| setFunctionModel(value); | |
| setSelectedFTPHandler(value.metadata.label); | |
| setIsNew(false); | |
| setShowForm(true); | |
| }; | |
| const handleNewFTPFunction = (selectedHandler: string) => { | |
| setSelectedFTPHandler(selectedHandler); | |
| setShowForm(true); | |
| }; |
🤖 Prompt for AI Agents
In
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx
around lines 550-555, handleFunctionEdit sets selectedFTPHandler but
handleNewFTPFunction (which receives selectedHandler) does not—causing the FTP
form panel title to be wrong; update handleNewFTPFunction to
setSelectedFTPHandler(selectedHandler) (and ensure it still sets isNew true,
setFunctionModel appropriately, and setShowForm(true)) so the form title and
state are consistent for new handler creation.
| <Button appearance="primary" tooltip="Add Handler" onClick={onSelectAddHandler}> | ||
| <Codicon name="add" sx={{ marginRight: 8 }} /> <ButtonText>Resource</ButtonText> | ||
| </Button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Button text inconsistency: "Resource" should be "Handler" for FTP.
The button label says "Resource" but this is the FTP File Handlers section where "Handler" would be more appropriate and consistent with the section title.
{!haveServiceTypeName && enabledHandlers.length > 0 && (
<Button appearance="primary" tooltip="Add Handler" onClick={onSelectAddHandler}>
- <Codicon name="add" sx={{ marginRight: 8 }} /> <ButtonText>Resource</ButtonText>
+ <Codicon name="add" sx={{ marginRight: 8 }} /> <ButtonText>Handler</ButtonText>
</Button>
)}📝 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.
| <Button appearance="primary" tooltip="Add Handler" onClick={onSelectAddHandler}> | |
| <Codicon name="add" sx={{ marginRight: 8 }} /> <ButtonText>Resource</ButtonText> | |
| </Button> | |
| <Button appearance="primary" tooltip="Add Handler" onClick={onSelectAddHandler}> | |
| <Codicon name="add" sx={{ marginRight: 8 }} /> <ButtonText>Handler</ButtonText> | |
| </Button> |
🤖 Prompt for AI Agents
In
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx
around lines 986 to 988, the button label currently reads "Resource" but should
read "Handler" to match the FTP File Handlers section; update the ButtonText
content to "Handler" so the UI is consistent with the section title and other
handler-related controls.
| {/* {enabledHandlers | ||
| .filter((resource) => { | ||
| const search = searchValue.toLowerCase(); | ||
| const nameMatch = resource.name && resource.name.toLowerCase().includes(search); | ||
| const iconMatch = resource.icon && resource.icon.toLowerCase().includes(search); | ||
| return nameMatch || iconMatch; | ||
| }) | ||
| .filter((resource) => resource.type === DIRECTORY_MAP.RESOURCE) | ||
| .map((resource, index) => ( | ||
| <ResourceAccordionV2 | ||
| key={`${index}-${resource.name}`} | ||
| resource={resource} | ||
| readOnly={serviceModel.properties.hasOwnProperty('serviceTypeName')} | ||
| onEditResource={handleFunctionEdit} | ||
| onDeleteResource={handleFunctionDelete} | ||
| onResourceImplement={handleOpenDiagram} | ||
| /> | ||
| ))} */} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Remove commented-out code block.
This large commented-out code block adds noise and should be removed. If this represents planned functionality, consider tracking it in a separate issue instead.
🤖 Prompt for AI Agents
In
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx
around lines 994 to 1011, there is a large commented-out JSX block that should
be removed to reduce noise; delete the entire commented block (including the
surrounding {/* ... */} markers) and, if this represents planned functionality,
create or reference a tracker/issue instead of leaving commented code in the
file so the codebase stays clean.
| if (payloadContext?.protocol === "FTP") { | ||
|
|
||
| categories = categories | ||
| .filter((category) => category.category === "User-Defined") | ||
| .map((category) => ({ | ||
| ...category, | ||
| items: category.items.filter((item) => item.labelDetails?.description === "Record") | ||
| })) | ||
| .filter((category) => category.items.length > 0); | ||
|
|
||
| if (payloadContext?.filterType === "JSON") { | ||
| categories = [...categories, | ||
| { | ||
| category: "Data Types", | ||
| sortText: "2", | ||
| items: [ | ||
| { | ||
| name: "json", | ||
| insertText: "json", | ||
| type: "type-parameter", | ||
| labelDetails: { | ||
| detail: "Data Types", | ||
| description: "Built-in JSON type" | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ]; | ||
| } else if (payloadContext?.filterType === "XML") { | ||
| categories = [...categories, | ||
| { | ||
| category: "Data Types", | ||
| sortText: "2", | ||
| items: [ | ||
| { | ||
| name: "xml", | ||
| insertText: "xml", | ||
| type: "type-parameter", | ||
| labelDetails: { | ||
| detail: "Data Types", | ||
| description: "Built-in XML type" | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ]; | ||
| } else if (payloadContext?.filterType === "CSV") { | ||
| categories = [...categories, | ||
| { | ||
| category: "Structural Types", | ||
| sortText: "3", | ||
| items: [ | ||
| { | ||
| name: "string[]", | ||
| insertText: "string[]", | ||
| type: "type-parameter", | ||
| labelDetails: { | ||
| detail: "Structural Types", | ||
| description: "Built-in string array type" | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ]; | ||
|
|
||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FTP-specific type filtering logic is functional but has potential issues.
The FTP handling logic correctly:
- Filters to User-Defined Records only
- Injects built-in types based on
filterType
However, there are a few concerns:
-
Potential runtime error on line 144: After FTP filtering,
sortTextcould beundefinedfor categories, causinga.sortText.localeCompare(b.sortText)to throw. The injected categories have explicitsortText, but filtered categories useTYPE_CATEGORY_ORDER.find()which may return undefined. -
Code duplication: The category object structures for JSON, XML, and CSV are very similar.
Consider adding a null check in the sort comparator:
- return categories.sort((a, b) => a.sortText.localeCompare(b.sortText));
+ return categories.sort((a, b) => (a.sortText ?? "z").localeCompare(b.sortText ?? "z"));And optionally consolidate the built-in type injection:
const BUILTIN_FTP_TYPES: Record<string, { category: string; sortText: string; name: string; description: string }> = {
JSON: { category: "Data Types", sortText: "2", name: "json", description: "Built-in JSON type" },
XML: { category: "Data Types", sortText: "2", name: "xml", description: "Built-in XML type" },
CSV: { category: "Structural Types", sortText: "3", name: "string[]", description: "Built-in string array type" }
};🤖 Prompt for AI Agents
In workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsx
around lines 77-143, the FTP branch injects built-in categories but later
sorting can throw because some categories may have undefined sortText; also the
JSON/XML/CSV injection blocks are duplicated. Fix by (1) making the comparator
null-safe: coerce undefined sortText to a stable fallback (e.g., empty string or
a high/low sentinel) before calling localeCompare, and (2) replace the three
nearly-identical injection blocks with a single lookup map (keyed by
payloadContext.filterType) that provides category, sortText, item name and
description, then conditionally push the mapped category when present. Ensure
filtered categories also get an explicit sortText (from TYPE_CATEGORY_ORDER or
the fallback) so no undefined values remain.
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
workspaces/common-libs/font-wso2-vscode/src/icons/bi-file.svgis excluded by!**/*.svgworkspaces/common-libs/font-wso2-vscode/src/icons/bi-ftp.svgis excluded by!**/*.svg
📒 Files selected for processing (2)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx(3 hunks)workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
workspaces/ballerina/component-diagram/src/components/nodes/**/*.{ts,tsx}
📄 CodeRabbit inference engine (workspaces/ballerina/component-diagram/AGENTS.md)
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
Files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
📄 CodeRabbit inference engine (workspaces/ballerina/component-diagram/AGENTS.md)
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
Files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
workspaces/ballerina/component-diagram/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (workspaces/ballerina/component-diagram/AGENTS.md)
workspaces/ballerina/component-diagram/src/**/*.{ts,tsx}: Use TypeScript 5.8.3 with strict type checking enabled for all source files
Define all constants (node types, sizing, spacing) in src/resources/constants.ts and import them where needed instead of hardcoding values
All async operations and promise handling in diagram utilities should use async/await syntax instead of .then() callbacks
Files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
workspaces/ballerina/component-diagram/src/components/**/*.tsx
📄 CodeRabbit inference engine (workspaces/ballerina/component-diagram/AGENTS.md)
workspaces/ballerina/component-diagram/src/components/**/*.tsx: Use Emotion for CSS-in-JS styling instead of inline styles or external CSS files
Use React 18.2.0 features including concurrent rendering and automatic batching; avoid class components in favor of functional components with hooks
Files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/**/*.tsx
📄 CodeRabbit inference engine (workspaces/ballerina/component-diagram/AGENTS.md)
Implement lazy expansion of functions: only render function items when they are visible to improve performance for large function lists
Files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
🧠 Learnings (13)
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/resources/icons/**/*.tsx : Create separate SVG icon components in src/resources/icons/ for all diagram icons and import them as React components
Applied to files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.{ts,tsx} : Define all constants (node types, sizing, spacing) in src/resources/constants.ts and import them where needed instead of hardcoding values
Applied to files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.test.{ts,tsx} : Create snapshot tests for all node widgets and verify visual consistency across renders
Applied to files:
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.tsx : Use React 18.2.0 features including concurrent rendering and automatic batching; avoid class components in favor of functional components with hooks
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.tsx : Use Emotion for CSS-in-JS styling instead of inline styles or external CSS files
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.config.{js,ts} : Use minimatch-compatible glob patterns for file matching in build and test configuration files
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx
📚 Learning: 2025-11-10T15:05:11.309Z
Learnt from: madushajg
Repo: wso2/vscode-extensions PR: 868
File: workspaces/bi/bi-extension/src/utils.ts:224-242
Timestamp: 2025-11-10T15:05:11.309Z
Learning: The workspaces/bi/bi-extension and workspaces/ballerina/ballerina-extension are separate VS Code extensions that are packaged and distributed independently, so they cannot share code via imports and must maintain their own implementations of common utilities.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx
🔇 Additional comments (3)
workspaces/ballerina/component-diagram/src/components/nodes/EntryNode/components/GeneralWidget.tsx (1)
123-126: Pattern and icons confirmed.The FTP and file icon cases correctly follow the established pattern in the switch statement and are consistent with existing protocol icon mappings. The icon names
bi-ftpandbi-fileare already validated through their use in other components (FileIntegrationPanel.tsx, project-artifacts.ts), confirming they exist in the ui-toolkit library.workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx (2)
19-19: LGTM: Standardized icon component usage.Replacing Codicon with the Icon component from @wso2/ui-toolkit aligns with best practices for using centralized UI components.
63-70: Verify whether FTP triggers have the expectedtypefield value.The code filters items by
type === "file"but distinguishes icon display bymoduleName("ftp" or "file"). This pattern suggests FTP triggers should havetype="file"withmoduleName="ftp". However, the actualtypevalue assigned to FTP trigger items cannot be confirmed from the codebase. Verify with backend code or test data that FTP triggers are assignedtype="file"to ensure they're properly included in the filtered list.
| // TODO: This should be removed once the new icons are added to the BE API. | ||
| export function getFileIntegrationIcon(item: ServiceModel) { | ||
| return getCustomFileIntegrationIcon(item.moduleName) || <img src={item.icon} alt={item.name} style={{ width: "38px" }} />; | ||
| } | ||
|
|
||
| // INFO: This is a temporary function to get the custom icon for the file integration triggers. | ||
| // TODO: This should be removed once the new icons are added to the BE API. | ||
| export function getCustomFileIntegrationIcon(type: string) { | ||
| switch (type) { | ||
| case "ftp": | ||
| return <Icon name="bi-ftp" />; | ||
| case "file": | ||
| return <Icon name="bi-file" />; | ||
| default: | ||
| return null; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
fd -type f -name "FileIntegrationPanel.tsx" -o -name "FileIntegrationPanel.ts"Repository: wso2/vscode-extensions
Length of output: 236
🏁 Script executed:
fd "FileIntegrationPanel.tsx"Repository: wso2/vscode-extensions
Length of output: 163
🏁 Script executed:
cat -n workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx | sed -n '80,105p'Repository: wso2/vscode-extensions
Length of output: 946
🏁 Script executed:
# Check where Icon component comes from and how it's imported
head -50 workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxRepository: wso2/vscode-extensions
Length of output: 2122
🏁 Script executed:
# Search for usages of getFileIntegrationIcon throughout the codebase
rg "getFileIntegrationIcon" -B 2 -A 2Repository: wso2/vscode-extensions
Length of output: 1586
🏁 Script executed:
# Check ButtonCard component to see what it expects for the icon prop
rg "interface ButtonCardProps|type ButtonCardProps" -A 10Repository: wso2/vscode-extensions
Length of output: 1204
🏁 Script executed:
# Check how ButtonCard renders the icon
cat -n workspaces/ballerina/ballerina-visualizer/src/components/ButtonCard/index.tsx | head -100Repository: wso2/vscode-extensions
Length of output: 3855
🏁 Script executed:
cat -n workspaces/ballerina/ballerina-visualizer/src/components/ButtonCard/index.tsx | sed -n '100,150p'Repository: wso2/vscode-extensions
Length of output: 1720
🏁 Script executed:
# Search for Icon component definition in @wso2/ui-toolkit
rg "Icon" node_modules/@wso2/ui-toolkit -l | head -5Repository: wso2/vscode-extensions
Length of output: 135
🏁 Script executed:
# Check package.json to see ui-toolkit dependency
find . -name "package.json" -type f | xargs grep -l "@wso2/ui-toolkit" | head -3Repository: wso2/vscode-extensions
Length of output: 242
🏁 Script executed:
# Check the ui-toolkit version
cat workspaces/ballerina/ballerina-visualizer/package.json | grep -A 2 -B 2 "@wso2/ui-toolkit"Repository: wso2/vscode-extensions
Length of output: 274
🏁 Script executed:
# Find the ui-toolkit workspace package
find . -path "*/node_modules" -prune -o -name "ui-toolkit" -type d -printRepository: wso2/vscode-extensions
Length of output: 101
🏁 Script executed:
# Check Icon component in ui-toolkit
find workspaces/common-libs/ui-toolkit -name "*.tsx" -o -name "*.ts" | xargs rg "export.*Icon" | head -20Repository: wso2/vscode-extensions
Length of output: 2741
🏁 Script executed:
# Check the Icon component implementation
cat workspaces/common-libs/ui-toolkit/src/components/Icon/Icon.tsxRepository: wso2/vscode-extensions
Length of output: 1683
🏁 Script executed:
# Check the font-wso2-vscode package
find . -path "*/node_modules" -prune -o -name "*font*wso2*" -type d -print | grep -v node_modulesRepository: wso2/vscode-extensions
Length of output: 107
🏁 Script executed:
# Check what icons are available in the font
ls -la workspaces/common-libs/font-wso2-vscode/dist/Repository: wso2/vscode-extensions
Length of output: 158
Clarify parameter naming and verify icon availability.
The helper functions have issues that need attention:
-
Parameter naming inconsistency:
getCustomFileIntegrationIcon(type: string)uses parameter nametype, but it's called withitem.moduleName(line 86). Rename the parameter tomoduleNamefor clarity. -
Icon name verification: The Icon component references
"bi-ftp"and"bi-file". Verify these icon names exist in the font-wso2-vscode package or consider using SVG icon components from src/resources/icons/. -
Sizing inconsistency: The Icon component renders at 16×14px, but the fallback img uses hardcoded
width: "38px"(line 86), causing visual inconsistency. Align the sizing.
Rename the parameter for clarity:
-export function getCustomFileIntegrationIcon(type: string) {
- switch (type) {
+export function getCustomFileIntegrationIcon(moduleName: string) {
+ switch (moduleName) {There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx (1)
150-150: Remove debug console log.This console log should be removed before merging to production. If logging is needed for troubleshooting, consider using a proper logging framework that can be controlled via environment variables.
🔎 Proposed fix
- console.log("Choice Form Index:", Number(e.target.value))workspaces/ballerina/ballerina-extension/package.json (1)
1164-1169: Confirm the intentional duplication of the icon glyph.The
distro-design-viewicon now usesfontCharacter\f175, which is identical todistro-agent-view(line 1038). This appears to be a deliberate change from the previous value (\f16eto\f175).The two icons are used in distinctly different contexts:
distro-agent-view: Used for visualization and viewing operations (Show Visualizer, View Type Diagram, View Configurations)distro-design-view: Used for design and editing operations (Open Service Designer, Edit test suite, Edit test case)Please confirm whether sharing the same glyph is intentional, as the different naming and usage patterns suggest they may have been intended to have distinct visual representations.
♻️ Duplicate comments (8)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx (2)
93-107: Remove unusedformatParameterLabelfunction.This function is defined but never called (the only usage is commented out on lines 119-124). Either use it or remove it to reduce code complexity.
🔎 Proposed fix
- const formatParameterLabel = (typeValue: string, hasStreamProperty: boolean, isStreamEnabled: boolean, hasDataBinding: boolean) => { - if (!hasStreamProperty || !hasDataBinding) { - return typeValue; - } - - if (isStreamEnabled) { - const value = typeValue.endsWith("[]") ? typeValue.slice(0, -2) : typeValue; - const value2 = value.startsWith("stream<") && value.endsWith(", error>") ? value.slice(7, -8) : value; - return `stream<${value2}>`; - } else { - const value = typeValue.endsWith("[]") ? typeValue.slice(0, -2) : typeValue; - const value2 = value.startsWith("stream<") && value.endsWith(", error>") ? value.slice(7, -8) : value; - return `${value2}[]`; - } - }; -
139-146: Potential runtime error whenonEditClickis undefined.
onEditClickis optional in the props interface but is called without a null check on lines 139 and 146. Use optional chaining to prevent runtime errors.🔎 Proposed fix
<div data-test-id={`${param.name.value}-param`} className={readonly ? disabledHeaderLabel : headerLabelStyles} - onClick={() => !readonly && onEditClick(param)} + onClick={() => !readonly && onEditClick?.(param)} > {label} </div> <ActionIconWrapper> {!readonly && ( <EditIconWrapper> - <Codicon name="edit" onClick={() => onEditClick(param)} /> + <Codicon name="edit" onClick={() => onEditClick?.(param)} /> </EditIconWrapper> )}workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx (2)
86-92: Remove commented-out debug code.This commented-out debug code was flagged in previous reviews and should be removed before merging.
134-135: Remove debug console logs.These debug logs were flagged in previous reviews and should be removed before merging to production.
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx (1)
84-99: Icon helper naming and sizing could be tightened up.
getCustomFileIntegrationIconis passeditem.moduleNamebut the parameter is namedtype, and the fallback<img>uses a much larger width (38px) than theIconcomponent. Consider renaming the parameter tomoduleName(or similar) and aligning the bitmap size with the vector icon for consistent visuals. Also double‑check that"bi-ftp"/"bi-file"exist infont-wso2-vscode.Please verify icon names and sizing against
@wso2/ui-toolkit/font-wso2-vscodedocs or by checking the rendered UI.workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsx (1)
47-145: Guard against undefinedsortTextand consider consolidating FTP injection logic.
sortTextis looked up viaTYPE_CATEGORY_ORDER.find(...)?.sortTextand then used unconditionally incategories.sort((a, b) => a.sortText.localeCompare(b.sortText)). If the LS ever introduces a category label that’s not inTYPE_CATEGORY_ORDER,sortTextwill beundefinedandlocaleComparewill throw.You can make this robust by normalizing to a fallback string:
- return categories.sort((a, b) => a.sortText.localeCompare(b.sortText)); + return categories.sort((a, b) => (a.sortText ?? "z").localeCompare(b.sortText ?? "z"));Optionally, the three FTP blocks that append JSON/XML/CSV categories can be collapsed into a small lookup map keyed by
payloadContext.filterTypeto remove duplication and keep category metadata in one place.Please re‑run the TypeEditor UI (HTTP/GraphQL/FTP flows) after changing the comparator to ensure categories still appear in the intended order.
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/ParamEditor.tsx (1)
28-46: Guard optionalonCancelto avoid runtime errors.
onCancelis optional inParamPropsbuthandleOnCancelcalls it unconditionally. If the parent omits this prop, clicking “Back” will throw.Use optional chaining (or a default no‑op) when invoking it:
- const handleOnCancel = () => { - onCancel(param); - }; + const handleOnCancel = () => { + onCancel?.(param); + };Please verify all current
ParamEditorcall sites either provideonCancelor that this guard is added before merging.workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx (1)
224-291: Avoid mutating parameter objects inhandleTypeCreated/handleDeleteContentSchema.
handleTypeCreatedandhandleDeleteContentSchemaboth mutate nested state:
updatedPayloadModel.name.value = "content";updatedPayloadModel.type.value = …;defaultParamModel.enabled = false;p.type.value = p.type.placeholder;and then perform multiple
setFunctionModelcalls with partially updated arrays. This mixes mutation with immutable updates and makes the final parameter state harder to reason about (React may batch the set calls, and you also overwrite the same parameter twice inhandleTypeCreated).Refactor these to build new parameter objects and a single updated
functionModel, e.g.:- const handleTypeCreated = (type: Type | string) => { - // When a type is created, set it as the payload type for the DATA_BINDING parameter - const defaultParamIndex = functionModel.parameters.findIndex(param => param.kind === "REQUIRED" && param.name.value === "content"); - const defaultParam = functionModel.parameters?.find(param => param.kind === "REQUIRED" && param.name.value === "content"); - const payloadParam = functionModel.parameters?.find(param => param.kind === "DATA_BINDING"); - if (payloadParam) { - const defaultParamModel = { ...defaultParam }; - const updatedPayloadModel = { ...payloadParam }; - updatedPayloadModel.name.value = "content"; - const typeValue = typeof type === 'string' ? type : type.name; - updatedPayloadModel.type.value = selectType(typeValue, functionModel.properties.stream?.enabled) ; - updatedPayloadModel.enabled = true; - - defaultParamModel.enabled = false; // Disable the default content parameter - - // ... two separate updatedParameters/setFunctionModel blocks ... - } - setIsTypeEditorOpen(false); - }; + const handleTypeCreated = (type: Type | string) => { + if (!functionModel) { + setIsTypeEditorOpen(false); + return; + } + const typeValue = typeof type === "string" ? type : type.name; + const updatedParameters = functionModel.parameters.map((param) => { + if (param.kind === "DATA_BINDING") { + return { + ...param, + name: { ...param.name, value: "content" }, + type: { + ...param.type, + value: selectType(typeValue, functionModel.properties?.stream?.enabled), + }, + enabled: true, + }; + } + if (param.kind === "REQUIRED" && param.name?.value === "content") { + return { ...param, enabled: false }; + } + return param; + }); + + setFunctionModel({ ...functionModel, parameters: updatedParameters }); + setIsTypeEditorOpen(false); + };and for
handleDeleteContentSchema:- const updatedParameters = functionModel.parameters.map((p) => { - if (p.kind === "DATA_BINDING") { - p.type.value = p.type.placeholder; - return { ...p, enabled: true }; - } - return p; - }); + const updatedParameters = functionModel.parameters.map((p) => { + if (p.kind === "DATA_BINDING") { + return { + ...p, + type: { ...p.type, value: p.type.placeholder }, + enabled: true, + }; + } + return p; + });This keeps updates immutable and removes the duplicate
setFunctionModelcalls.After refactoring, retest creating, editing, and deleting the Content Schema to confirm parameter lists and stream wrapping behave as before.
🧹 Nitpick comments (5)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx (3)
65-74: Remove duplicate CSS property.Line 70 duplicates the
display: flex;declaration from line 66.🔎 Proposed fix
const HeaderLabel = styled.div<CSSObject>` display: flex; background: var(--vscode-editor-background); border: 1px solid ${(props: { haveErrors: boolean; }) => props.haveErrors ? "red" : "var(--vscode-dropdown-border)"}; margin: 8px 0; - display: flex; width: 100%; height: 32px; align-items: center; `;
76-81: Remove unusedParamDefaultstyled component.The
ParamDefaultcomponent is defined but never used in the rendering logic.🔎 Proposed fix
-const ParamDefault = styled.span` - font-size: 13px; - color: var(--vscode-editorHint-foreground, #b0b0b0); - margin-left: 8px; - font-style: italic; -`; - export function Parameters(props: ParametersProps) {
115-125: Remove unused variable calculations.Variables
hasStreamProperty,isStreamEnabled, andhasDataBindingare calculated but only used in the commented-out code. Remove them along with the commented-out code and the unusedformatParameterLabelfunction.🔎 Proposed fix
{parameters.map((param: ParameterModel, index) => { const readonly = param.editable === false; - const hasStreamProperty = streamEnabled !== undefined; - const isStreamEnabled = streamEnabled === true; - const hasDataBinding = param.kind === "DATA_BINDING"; - // const formattedTypeValue = formatParameterLabel( - // param.type.value, - // hasStreamProperty, - // isStreamEnabled, - // hasDataBinding - // ); const formattedTypeValue = param.type.value;workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx (1)
162-166: Move merged array creation outside the map callback.The
mergedRecordTypeFieldsarray is recreated on every iteration. Move it outside themapcallback to avoid unnecessary re-creation.🔎 Proposed refactor
+ // Merge parent recordTypeFields with dynamically generated ones + const mergedRecordTypeFields = [ + ...(recordTypeFields || []), + ...dynamicRecordTypeFields + ]; + <FormSection> {dynamicFields.map((dfield, index) => { - // Merge parent recordTypeFields with dynamically generated ones - const mergedRecordTypeFields = [ - ...(recordTypeFields || []), - ...dynamicRecordTypeFields - ]; - return ( <EditorFactoryworkspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
127-133: Be careful:GeneralPayloadContextmay breakPayloadContextdiscriminated union.By adding
GeneralPayloadContextwithprotocol: stringintoPayloadContext, theprotocolfield is no longer a pure string‑literal discriminant ("HTTP" | "MESSAGE_BROKER"). Any existing code that relies onswitch (ctx.protocol)orif (ctx.protocol === "HTTP")for exhaustive narrowing overPayloadContextmay now lose type‑safety and fall back to a generic union.If the only new protocols are known (e.g.
"GRAPHQL","FTP"), consider tightening this to a union of literals instead ofstring, or keepingGeneralPayloadContextseparate fromPayloadContextwhere full generality is needed.Please run a TypeScript type‑check focusing on usages of
PayloadContext(e.g.rg "PayloadContext") to ensure no narrowed control‑flow was degraded.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
workspaces/ballerina/ballerina-core/src/interfaces/service.tsworkspaces/ballerina/ballerina-extension/package.jsonworkspaces/ballerina/ballerina-extension/src/rpc-managers/bi-diagram/rpc-manager.tsworkspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsxworkspaces/ballerina/ballerina-visualizer/src/components/EntryPointTypeCreator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/FTPConfigForm.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/ParamEditor.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsx
💤 Files with no reviewable changes (1)
- workspaces/ballerina/ballerina-visualizer/src/components/EntryPointTypeCreator/index.tsx
✅ Files skipped from review due to trivial changes (1)
- workspaces/ballerina/ballerina-extension/src/rpc-managers/bi-diagram/rpc-manager.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx
- workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/index.tsx
🧰 Additional context used
🧠 Learnings (22)
📚 Learning: 2025-12-16T13:47:11.133Z
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.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/resources/icons/**/*.tsx : Create separate SVG icon components in src/resources/icons/ for all diagram icons and import them as React components
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-extension/package.json
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.tsx : Use React 18.2.0 features including concurrent rendering and automatic batching; avoid class components in favor of functional components with hooks
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/ParamEditor.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/FTPConfigForm.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.{ts,tsx} : Define all constants (node types, sizing, spacing) in src/resources/constants.ts and import them where needed instead of hardcoding values
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/ParamEditor.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsxworkspaces/ballerina/ballerina-extension/package.jsonworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.tsx : Use Emotion for CSS-in-JS styling instead of inline styles or external CSS files
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.config.{js,ts} : Use minimatch-compatible glob patterns for file matching in build and test configuration files
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-extension/package.json
📚 Learning: 2025-11-10T15:05:11.309Z
Learnt from: madushajg
Repo: wso2/vscode-extensions PR: 868
File: workspaces/bi/bi-extension/src/utils.ts:224-242
Timestamp: 2025-11-10T15:05:11.309Z
Learning: The workspaces/bi/bi-extension and workspaces/ballerina/ballerina-extension are separate VS Code extensions that are packaged and distributed independently, so they cannot share code via imports and must maintain their own implementations of common utilities.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-extension/package.json
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx
📚 Learning: 2025-11-26T06:35:19.217Z
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 653
File: workspaces/bi/bi-extension/src/test/e2e-playwright-tests/data-mapper/DataMapperUtils.ts:173-178
Timestamp: 2025-11-26T06:35:19.217Z
Learning: In workspaces/bi/bi-extension/src/test/e2e-playwright-tests/data-mapper/DataMapperUtils.ts, the commented-out debugging block in the verifyFileContent function (lines 172-177 containing console.log, page.pause, and updateDataFileSync) is intentionally kept as a developer utility for updating test data files when needed. It should not be removed.
Applied to files:
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-27T07:59:33.534Z
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.
Applied to files:
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/ParamEditor.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-24T14:51:49.267Z
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.
Applied to files:
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/ParamEditor.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx
📚 Learning: 2025-12-12T08:55:43.437Z
Learnt from: dan-niles
Repo: wso2/vscode-extensions PR: 1080
File: workspaces/ballerina/ballerina-visualizer/src/views/BI/AIChatAgent/AddMcpServer.tsx:269-281
Timestamp: 2025-12-12T08:55:43.437Z
Learning: In `FormGenerator` component used in AddMcpServer.tsx, the component automatically triggers `onChange` callbacks with saved field values during initialization when a `node` prop is provided, so manual state setter calls (e.g., setServerUrl, setAuth) are not needed in initialization logic like initializeEditMode.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx
📚 Learning: 2025-12-13T14:58:12.691Z
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 1069
File: workspaces/ballerina/ballerina-visualizer/src/views/DataMapper/index.tsx:43-52
Timestamp: 2025-12-13T14:58:12.691Z
Learning: In workspaces/ballerina/ballerina-visualizer/src/views/DataMapper/index.tsx, the goToSource function does not need to guard against undefined lineRange. When lineRange is undefined, the RPC client will still open/show the file but won't select the relevant part.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx
📚 Learning: 2025-11-26T07:49:56.428Z
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 653
File: workspaces/bi/bi-extension/src/test/e2e-playwright-tests/data-mapper/DataMapperUtils.ts:136-141
Timestamp: 2025-11-26T07:49:56.428Z
Learning: In workspaces/bi/bi-extension/src/test/e2e-playwright-tests/data-mapper/DataMapperUtils.ts, the goPrevViewBackButton() method is only called when in a focused view, ensuring breadcrumbs are always present. No guard for empty breadcrumbs is needed.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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 proper error boundaries around the Diagram component to gracefully handle rendering errors without crashing the parent application
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx
📚 Learning: 2025-11-24T22:16:28.380Z
Learnt from: dan-niles
Repo: wso2/vscode-extensions PR: 980
File: workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/RichTextTemplateEditor/RichTextTemplateEditor.tsx:384-412
Timestamp: 2025-11-24T22:16:28.380Z
Learning: In the RichTextTemplateEditor component (workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/RichTextTemplateEditor/RichTextTemplateEditor.tsx), token fetching on external `value` prop changes is intentionally disabled. Users cannot edit both the minimized and expanded editors simultaneously, so tokens only need to be generated based on user typing in the expanded editor view, not on external prop updates.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx
📚 Learning: 2025-11-26T06:34:09.752Z
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 653
File: workspaces/bi/bi-extension/src/test/e2e-playwright-tests/data-mapper/DataMapperUtils.ts:128-134
Timestamp: 2025-11-26T06:34:09.752Z
Learning: In workspaces/bi/bi-extension/src/test/e2e-playwright-tests/data-mapper/DataMapperUtils.ts, the goPrevViewBreadcrumb() method is only called when in a focused view, ensuring breadcrumbs are always present. No guard for empty breadcrumbs is needed.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx
📚 Learning: 2025-11-20T11:04:33.712Z
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 898
File: workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx:38-38
Timestamp: 2025-11-20T11:04:33.712Z
Learning: In workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx, the use of `useDMQueryClausesPanelStore.getState()` to access `clauseToAdd` and `setClauseToAdd` (instead of the hook subscription pattern) is intentional to prevent re-renders when these state values change.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
🧬 Code graph analysis (7)
workspaces/ballerina/ballerina-visualizer/src/views/BI/TypeEditor/utils.tsx (2)
workspaces/ballerina/ballerina-core/src/interfaces/extended-lang-client.ts (1)
VisibleTypeItem(1174-1183)workspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
GeneralPayloadContext(127-130)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ComponentListView/FileIntegrationPanel.tsx (1)
workspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
ServiceModel(39-54)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx (4)
workspaces/ballerina/ballerina-core/src/interfaces/bi.ts (1)
RecordTypeField(203-207)workspaces/ballerina/ballerina-side-panel/src/components/Form/types.ts (1)
FormField(38-73)workspaces/ballerina/ballerina-core/src/utils/form-property-utils.ts (1)
getPrimaryInputType(21-24)workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx (1)
EditorFactory(70-247)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx (3)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/components/ResourceAccordion.tsx (1)
ResourceAccordion(138-234)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/utils.tsx (1)
canDataBind(76-78)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx (1)
FTPForm(68-520)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx (2)
workspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
ParameterModel(183-189)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/styles.tsx (6)
HeaderLabel(124-133)disabledHeaderLabel(117-122)headerLabelStyles(102-108)ActionIconWrapper(135-141)EditIconWrapper(62-69)DeleteIconWrapper(71-79)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/FTPConfigForm.tsx (3)
workspaces/ballerina/ballerina-core/src/interfaces/service.ts (1)
ServiceModel(39-54)workspaces/common-libs/rpc-generator/index.js (1)
handlerName(316-316)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx (1)
EditorContentColumn(49-55)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx (5)
workspaces/ballerina/ballerina-core/src/interfaces/service.ts (4)
FunctionModel(74-94)ServiceModel(39-54)GeneralPayloadContext(127-130)ParameterModel(183-189)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceFunctionForm/utils.ts (1)
handleParamChange(171-188)workspaces/wso2-platform/wso2-platform-webviews/src/components/FormElements/Dropdown/Dropdown.tsx (1)
Dropdown(37-78)workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx (1)
Parameters(83-161)workspaces/ballerina/ballerina-visualizer/src/components/EntryPointTypeCreator/index.tsx (1)
EntryPointTypeCreator(52-323)
🔇 Additional comments (6)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ChoiceForm.tsx (4)
61-61: LGTM!The new state for tracking dynamic record type fields is well-typed and follows React conventions.
67-70: LGTM!The destructuring and state updates correctly handle the new return structure from
convertConfig.
79-81: LGTM!The explicit return type and initialization of
recordTypeFieldsForChoiceimprove code clarity and correctness.
117-132: LGTM!The logic correctly creates
RecordTypeFieldobjects for properties with type members, properly filtering for record types.workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx (1)
1454-1463: GraphQL payloadContext wiring looks consistent; just ensure FormTypeEditor matches.Passing
payloadContext={{ protocol: "GRAPHQL", filterType: "INPUT" }}in the variable declaration flow andpayloadContext={{ protocol: "GRAPHQL" }}in the default flow aligns with the new context‑based API. As long asFormTypeEditorand its internal type‑fetching logic now rely solely onpayloadContext(and no longer onisGraphql), this should behave as intended.Please run the type checker and quickly exercise both GraphQL type‑editor entry points (variable form + default form) to confirm expected filtering/behavior.
Also applies to: 1585-1591
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/FTPConfigForm.tsx (1)
33-80: FTP handler selection logic looks sound.Filtering events to only those with at least one non‑enabled function (
metadata.labelmatch and!fn.enabled) is correct and protects against offering exhausted handlers. TheonSubmitcallback is safely guarded, and disabling viaisSavingis appropriate. Any cleanup of the unusedonBackprop or event constants can be deferred.
| export function FTPForm(props: FTPFormProps) { | ||
| const { model, isSaving, onSave, onClose, isNew, selectedHandler } = props; | ||
|
|
||
| const payloadContext = { | ||
| protocol: "FTP", | ||
| filterType: props.functionModel?.name.metadata.label || "JSON" | ||
| } as GeneralPayloadContext; | ||
|
|
||
| const [serviceModel, setserviceModel] = useState<ServiceModel>(model); | ||
| const [functionModel, setFunctionModel] = useState<FunctionModel | null>(props.functionModel || null); | ||
| const [selectedFileFormat, setSelectedFileFormat] = useState<string>(''); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find . -name "index.tsx" -path "*/FTPForm/*" 2>/dev/null | head -5Repository: wso2/vscode-extensions
Length of output: 162
🏁 Script executed:
cat -n ./workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx | head -200Repository: wso2/vscode-extensions
Length of output: 8051
🏁 Script executed:
cat -n ./workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx | sed -n '200,400p'Repository: wso2/vscode-extensions
Length of output: 11257
🏁 Script executed:
cat -n ./workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx | sed -n '400,500p'Repository: wso2/vscode-extensions
Length of output: 6796
🏁 Script executed:
cat -n ./workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx | sed -n '500,600p'Repository: wso2/vscode-extensions
Length of output: 944
🏁 Script executed:
find ./workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms -name "index.tsx" -type fRepository: wso2/vscode-extensions
Length of output: 569
🏁 Script executed:
grep -n "payloadContext" ./workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/*/index.tsxRepository: wso2/vscode-extensions
Length of output: 1884
🏁 Script executed:
# Check if there are similar issues in McpToolForm
grep -A 10 "payloadContext" ./workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/McpToolForm/index.tsx | head -20Repository: wso2/vscode-extensions
Length of output: 48
🏁 Script executed:
# Let me check if there are similar payloadContext patterns in other files that might need the same fix
grep -B 5 -A 5 "payloadContext.*=.*{" ./workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/*/index.tsxRepository: wso2/vscode-extensions
Length of output: 7902
🏁 Script executed:
# Verify that lines 152-160 don't contain payloadContext issues
sed -n '152,160p' ./workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsxRepository: wso2/vscode-extensions
Length of output: 343
Fix payloadContext to avoid null access and keep it in sync with the selected file format.
payloadContext is currently computed as:
const payloadContext = {
protocol: "FTP",
filterType: props.functionModel?.name.metadata.label || "JSON"
} as GeneralPayloadContext;Two problems:
- When creating a new handler,
props.functionModelisundefined, soprops.functionModel?.nameevaluates toundefinedand.metadatais then accessed onundefined→ potential runtime error. payloadContext.filterTypenever updates whenfunctionModelchanges (e.g. user picks a different file format), so the EntryPointTypeCreator may get the wrongfilterType(e.g. stuck on"JSON").
Compute payloadContext from the local functionModel state (with full optional chaining) and after the state is declared, e.g.:
- const { model, isSaving, onSave, onClose, isNew, selectedHandler } = props;
-
- const payloadContext = {
- protocol: "FTP",
- filterType: props.functionModel?.name.metadata.label || "JSON"
- } as GeneralPayloadContext;
-
- const [serviceModel, setserviceModel] = useState<ServiceModel>(model);
- const [functionModel, setFunctionModel] = useState<FunctionModel | null>(props.functionModel || null);
+ const { model, isSaving, onSave, onClose, isNew, selectedHandler } = props;
+
+ const [serviceModel, setserviceModel] = useState<ServiceModel>(model);
+ const [functionModel, setFunctionModel] = useState<FunctionModel | null>(props.functionModel || null);
+
+ const payloadContext: GeneralPayloadContext = {
+ protocol: "FTP",
+ filterType: functionModel?.name?.metadata?.label || "JSON",
+ };This removes the null‑access risk and keeps filterType aligned with the currently selected function/file format.
🤖 Prompt for AI Agents
In
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
around lines 68 to 79, payloadContext is built using props.functionModel and is
defined before local state, causing null-access risk when creating new handlers
and making filterType stale when functionModel state changes; fix it by moving
payloadContext construction to after the useState declarations and derive it
from the local functionModel state (use optional chaining like
functionModel?.name?.metadata?.label and default to "JSON"), or wrap the
computation in a useMemo that depends on [functionModel], so filterType always
reflects the current selection and avoids runtime errors.
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/index.tsx
Show resolved
Hide resolved
There was a problem hiding this 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
♻️ Duplicate comments (3)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx (3)
1-1: Avoid blanket ESLint disable for hooks rules.This issue has already been flagged in a previous review. The blanket disable for
react-hooks/exhaustive-depshides legitimate dependency issues throughout the file.
72-75: FixpayloadContextto avoid null access and keep it in sync with the selected file format.This issue has already been flagged in a previous review. The
payloadContextis computed fromprops.functionModelbefore state initialization, causing null-access risk and stalefilterTypewhen the function model changes.
225-270: Logic issue inhandleTypeCreated: Confusing dual updates and mutations.This issue has already been flagged in a previous review. The function has direct mutation problems and overwrites state twice with conflicting updates.
🧹 Nitpick comments (2)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx (2)
26-27: Remove unused imports.The imports
hasfrom lodash andDescriptionfrom @headlessui/react are not used anywhere in this file.🔎 Proposed fix
import { FunctionModel, ParameterModel, GeneralPayloadContext, Type, ServiceModel } from '@wso2/ballerina-core'; import { EntryPointTypeCreator } from '../../../../../components/EntryPointTypeCreator'; import { Parameters } from './Parameters/Parameters'; -import { has } from 'lodash'; -import { Description } from '@headlessui/react';
163-223: Consider relocating helper functions for better code organization.The
selectTypeandwithoutStreamTypefunctions referencehasStreamPropertywhich is defined later at line 345. While this works due to function declaration hoisting, it can impact readability whenhasStreamPropertyisn't visible nearby.Consider moving these helper functions after
hasStreamPropertyis defined, or moving thehasStreamPropertycomputation closer to the top of the component.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsxworkspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/Parameters/Parameters.tsx
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.tsx : Use React 18.2.0 features including concurrent rendering and automatic batching; avoid class components in favor of functional components with hooks
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-25T06:34:10.812Z
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/**/*.tsx : Use Emotion for CSS-in-JS styling instead of inline styles or external CSS files
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-27T07:59:33.534Z
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.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-12-12T08:55:43.437Z
Learnt from: dan-niles
Repo: wso2/vscode-extensions PR: 1080
File: workspaces/ballerina/ballerina-visualizer/src/views/BI/AIChatAgent/AddMcpServer.tsx:269-281
Timestamp: 2025-12-12T08:55:43.437Z
Learning: In `FormGenerator` component used in AddMcpServer.tsx, the component automatically triggers `onChange` callbacks with saved field values during initialization when a `node` prop is provided, so manual state setter calls (e.g., setServerUrl, setAuth) are not needed in initialization logic like initializeEditMode.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-26T06:35:19.217Z
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 653
File: workspaces/bi/bi-extension/src/test/e2e-playwright-tests/data-mapper/DataMapperUtils.ts:173-178
Timestamp: 2025-11-26T06:35:19.217Z
Learning: In workspaces/bi/bi-extension/src/test/e2e-playwright-tests/data-mapper/DataMapperUtils.ts, the commented-out debugging block in the verifyFileContent function (lines 172-177 containing console.log, page.pause, and updateDataFileSync) is intentionally kept as a developer utility for updating test data files when needed. It should not be removed.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-20T11:04:33.712Z
Learnt from: KCSAbeywickrama
Repo: wso2/vscode-extensions PR: 898
File: workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx:38-38
Timestamp: 2025-11-20T11:04:33.712Z
Learning: In workspaces/ballerina/data-mapper/src/components/DataMapper/SidePanel/QueryClauses/ClausesPanel.tsx, the use of `useDMQueryClausesPanelStore.getState()` to access `clauseToAdd` and `setClauseToAdd` (instead of the hook subscription pattern) is intentional to prevent re-renders when these state values change.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
📚 Learning: 2025-11-24T14:51:49.267Z
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.
Applied to files:
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
| <CheckBoxGroup direction="vertical"> | ||
| <CheckBox | ||
| label={parameterConfig.fileInfo.label} | ||
| checked={fileInfoParameter.enabled} | ||
| onChange={(checked) => { | ||
| const updatedParameters = functionModel.parameters.map((p) => { | ||
| if (p === fileInfoParameter) { | ||
| return { ...p, enabled: checked }; | ||
| } | ||
| return p; | ||
| }); | ||
| handleParamChange(updatedParameters); | ||
| }} | ||
| sx={{ marginTop: 0 , description: parameterConfig.fileInfo.description}} | ||
| /> | ||
| </CheckBoxGroup> | ||
| </> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect description prop usage in CheckBox components.
The description property is being passed inside the sx prop at lines 467 and 489, which is incorrect. The sx prop is for styling only and won't render the description text. This results in users not seeing helpful contextual information for the File Metadata and FTP Connection options.
Compare with the stream checkbox (lines 406-442) which correctly wraps the CheckBox in a Tooltip to display the description.
🔎 Proposed fix
{/* File Metadata Section */}
{fileInfoParameter && (
<>
-
+ <Tooltip content={parameterConfig.fileInfo.description} position="right">
<CheckBoxGroup direction="vertical">
<CheckBox
label={parameterConfig.fileInfo.label}
checked={fileInfoParameter.enabled}
onChange={(checked) => {
const updatedParameters = functionModel.parameters.map((p) => {
if (p === fileInfoParameter) {
return { ...p, enabled: checked };
}
return p;
});
handleParamChange(updatedParameters);
}}
- sx={{ marginTop: 0 , description: parameterConfig.fileInfo.description}}
+ sx={{ marginTop: 0 }}
/>
</CheckBoxGroup>
+ </Tooltip>
</>
)}
{/* FTP Connection Section */}
{callerParameter && (
<>
+ <Tooltip content={parameterConfig.caller.description} position="right">
<CheckBoxGroup direction="vertical">
<CheckBox
label={parameterConfig.caller.label}
checked={callerParameter.enabled}
onChange={(checked) => {
const updatedParameters = functionModel.parameters.map((p) => {
if (p === callerParameter) {
return { ...p, enabled: checked };
}
return p;
});
handleParamChange(updatedParameters);
}}
- sx={{ marginTop: 0, description: parameterConfig.caller.description }}
+ sx={{ marginTop: 0 }}
/>
</CheckBoxGroup>
+ </Tooltip>
</>
)}Also applies to: 476-492
🤖 Prompt for AI Agents
In
workspaces/ballerina/ballerina-visualizer/src/views/BI/ServiceDesigner/Forms/FTPForm/index.tsx
around lines 454-470 (and similarly 476-492 / specific occurrences at ~467 and
~489), the CheckBox components incorrectly place description text inside the sx
prop; remove the description from sx and wrap each CheckBox with the same
Tooltip pattern used by the stream checkbox (pass
parameterConfig.xxx.description as the Tooltip content), so the description is
rendered to users instead of being treated as styling metadata.
Purpose
wso2/product-ballerina-integrator#1684
Goals
Approach
UI Component Development
npm run storybookfrom the root directory to view current components.Manage Icons
User stories
Release note
Documentation
Training
Certification
Marketing
Automation tests
Security checks
Samples
Related PRs
Migrations (if applicable)
Test environment
Learning
Summary by CodeRabbit
New Features
UI/UX Improvements
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.