From 6c47bfb5084b9c38bb022973352ed8e03f13e7f1 Mon Sep 17 00:00:00 2001 From: sachiniSam Date: Fri, 21 Nov 2025 16:32:15 +0530 Subject: [PATCH 1/7] Auto select first record by default --- .../HelperPaneNew/Views/RecordConfigModal.tsx | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/RecordConfigModal.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/RecordConfigModal.tsx index 677d2572d47..f1df0c28896 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/RecordConfigModal.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/RecordConfigModal.tsx @@ -26,6 +26,7 @@ import { ChipExpressionEditorComponent, Context as FormContext, HelperpaneOnChan import { useForm } from "react-hook-form"; import { debounce } from "lodash"; import ReactMarkdown from "react-markdown"; +import { updateFieldsSelection } from "../Components/RecordConstructView/utils"; type ConfigureRecordPageProps = { fileName: string; @@ -142,6 +143,7 @@ export function ConfigureRecordPage(props: ConfigureRecordPageProps) { const { rpcClient } = useRpcContext(); const [recordModel, setRecordModel] = useState([]); + const recordModelRef = useRef([]); const [selectedMemberName, setSelectedMemberName] = useState(""); const firstRender = useRef(true); const sourceCode = useRef(currentValue); @@ -260,6 +262,7 @@ export function ConfigureRecordPage(props: ConfigureRecordPageProps) { } setRecordModel([recordConfig]); + recordModelRef.current = [recordConfig]; setSelectedMemberName(newRecordModel.name); } @@ -270,6 +273,23 @@ export function ConfigureRecordPage(props: ConfigureRecordPageProps) { await fetchRecordModelFromSource(currentValue); }; + + // Helper function to auto-select the first record in the model. + // Also selects required fields recursively within that record. + const autoSelectFirstRecord = (model: TypeField[]) => { + if (!model || model.length === 0) return; + + const recordConfig = model[0]; + + // Select the first record itself + recordConfig.selected = true; + + // If the record has fields, recursively select required fields + if (recordConfig.fields && recordConfig.fields.length > 0) { + updateFieldsSelection(recordConfig.fields as any, true); + } + }; + const getNewRecordModel = async () => { setIsLoading(true); const defaultSelection = recordTypeField.recordTypeMembers[0]; @@ -312,7 +332,15 @@ export function ConfigureRecordPage(props: ConfigureRecordPageProps) { ...typeFieldResponse.recordConfig } - setRecordModel([recordConfig]); + const newModel = [recordConfig]; + setRecordModel(newModel); + recordModelRef.current = newModel; + + // Auto-select the first field for new models + autoSelectFirstRecord(newModel); + + // Generate source with the auto-selected field + await handleModelChange(newModel); } setIsLoading(false); } @@ -354,7 +382,15 @@ export function ConfigureRecordPage(props: ConfigureRecordPageProps) { ...typeFieldResponse.recordConfig } - setRecordModel([recordConfig]); + const newModel = [recordConfig]; + setRecordModel(newModel); + recordModelRef.current = newModel; + + // Auto-select the first field when union member changes + autoSelectFirstRecord(newModel); + + // Generate source with the auto-selected field + await handleModelChange(newModel); } } @@ -523,6 +559,33 @@ export function ConfigureRecordPage(props: ConfigureRecordPageProps) { // Update local expression value when user edits in the ExpressionEditor setLocalExpressionValue(updatedValue); + // If the expression is empty, deselect all checkboxes + if (updatedValue.trim() === '') { + // Use ref to get the latest recordModel value + const currentRecordModel = recordModelRef.current; + // Deselect all fields in the record model + if (currentRecordModel.length > 0 && currentRecordModel[0]) { + const recordConfig = currentRecordModel[0]; + // Deselect the record itself + recordConfig.selected = false; + // Deselect all fields recursively + if (recordConfig.fields && recordConfig.fields.length > 0) { + updateFieldsSelection(recordConfig.fields as any, false); + } + // Update source code to empty to prevent sync issues + sourceCode.current = ''; + // Update latest expression ref to prevent sync + latestExpressionToSyncRef.current = ''; + // Trigger re-render by updating recordModel state with a new array reference + const updatedModel = [...currentRecordModel]; + setRecordModel(updatedModel); + recordModelRef.current = updatedModel; + } + // Clear diagnostics when expression is empty + setFormDiagnostics([]); + return; + } + // Fetch diagnostics (debounced) - this will update formDiagnostics state // The sync will be triggered by the useEffect that watches localExpressionValue fetchDiagnostics(updatedValue); From 26fea4676d497631e25e6e669be51b5d255b5b69 Mon Sep 17 00:00:00 2001 From: sachiniSam Date: Sat, 22 Nov 2025 12:49:15 +0530 Subject: [PATCH 2/7] Fix optional button styling --- .../RecordConstructView/ParameterBranch.tsx | 38 ++++++++++------ .../Components/RecordConstructView/styles.ts | 43 ++++++++++++++----- 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx index 6ff47a25c4c..5addbdbdf03 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx @@ -18,7 +18,7 @@ import React, { useState } from "react"; import { TypeField } from "@wso2/ballerina-core"; -import { Button } from "@wso2/ui-toolkit"; +import { Button, Codicon } from "@wso2/ui-toolkit"; import { useHelperPaneStyles } from "./styles"; @@ -64,7 +64,10 @@ export function ParameterBranch(props: ParameterBranchProps) { } }); - function toggleOptionalParams(e: any) { + function toggleOptionalParams(e?: any) { + if (e) { + e.stopPropagation(); + } setShowOptionalParams(!showOptionalParams); } @@ -77,18 +80,29 @@ export function ParameterBranch(props: ParameterBranchProps) { <> {optionalParams.length > 0 && (
- {/*
Optional fields
*/} - +
+ +
Optional fields
+
)} - {showOptionalParams && optionalParams.length > 0 && optionalParams} +
+ {showOptionalParams && optionalParams.length > 0 && optionalParams} +
)} diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/styles.ts b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/styles.ts index eabf726c434..d8e3dd2bd2d 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/styles.ts +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/styles.ts @@ -16,6 +16,7 @@ * under the License. */ import { css } from "@emotion/css"; +import { ThemeColors } from "@wso2/ui-toolkit"; const removePadding = { @@ -296,22 +297,44 @@ export const useHelperPaneStyles = () => ({ listOptionalWrapper: css({ display: 'flex', alignItems: 'center', - height: '32px', - marginBottom: '12px' + marginTop: '8px', + marginBottom: '8px' + }), + listOptionalHeader: css({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'flex-start', + alignItems: 'center', + width: 'auto', + gap: '6px', + borderRadius: '5px', + cursor: 'pointer', + transition: 'all 0.2s ease', + border: '1px solid transparent', + '&:hover': { + backgroundColor: 'var(--vscode-list-hoverBackground)', + }, + '&:hover > div:last-of-type': { + opacity: 1, + color: ThemeColors.PRIMARY, + } + }), + listOptionalTitle: css({ + fontSize: '13px', + opacity: 0.7, + color: ThemeColors.ON_SURFACE_VARIANT, + transition: 'all 0.2s ease', + padding: '2px 4px', + borderRadius: '3px', + '&:hover': { + backgroundColor: 'var(--vscode-list-hoverBackground)', + } }), listOptionalBtn: css({ textTransform: 'none', minWidth: '32px', marginLeft: '8px' }), - listOptionalHeader: css({ - fontSize: '13px', - color: "gray", - fontWeight: 500, - letterSpacing: '0', - lineHeight: '14px', - paddingLeft: '0px', - }), }); From 9468c0544d6d824dffdb93edf827e07d312c947a Mon Sep 17 00:00:00 2001 From: sachiniSam Date: Sat, 22 Nov 2025 14:40:49 +0530 Subject: [PATCH 3/7] Fix width on first dropdown --- .../src/views/BI/HelperPaneNew/Views/RecordConfigModal.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/RecordConfigModal.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/RecordConfigModal.tsx index f1df0c28896..647f5b17484 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/RecordConfigModal.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/RecordConfigModal.tsx @@ -648,6 +648,8 @@ export function ConfigureRecordPage(props: ConfigureRecordPageProps) { label: member.type, value: member.type }))} + sx={{ width: '100%' }} + containerSx={{ width: '100%' }} onValueChange={(value) => handleMemberChange(value)} /> From 2dce1f1f93b6ef4ee2cdc7a2a2a5caa750dc9e7b Mon Sep 17 00:00:00 2001 From: sachiniSam Date: Sat, 22 Nov 2025 15:07:24 +0530 Subject: [PATCH 4/7] Open up optionalParams by default for first record --- .../RecordConstructView/ParameterBranch.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx index 5addbdbdf03..b7da81663ae 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx @@ -71,10 +71,13 @@ export function ParameterBranch(props: ParameterBranchProps) { setShowOptionalParams(!showOptionalParams); } + const shouldShowOptionalParamsDirectly = (optionalParams.length > 0 && depth === 1) || + (requiredParams.length === 0 && optionalParams.length > 0 && depth < 3); + return (
{requiredParams} - {(optionalParams.length > 0 && depth === 1) ? ( + {shouldShowOptionalParamsDirectly ? ( optionalParams ) : ( <> @@ -91,8 +94,8 @@ export function ParameterBranch(props: ParameterBranchProps) { }, }} > - @@ -101,7 +104,7 @@ export function ParameterBranch(props: ParameterBranchProps) {
)}
- {showOptionalParams && optionalParams.length > 0 && optionalParams} + {showOptionalParams && optionalParams.length > 0 && optionalParams}
)} From ae870b59c4f04408b9ebd7b260c85a1170c642a2 Mon Sep 17 00:00:00 2001 From: sachiniSam Date: Tue, 25 Nov 2025 13:37:46 +0530 Subject: [PATCH 5/7] Reset values when unchecking the fields --- .../Types/CustomType/index.tsx | 8 ++++- .../Types/InclusionType/index.tsx | 7 ++++- .../Types/RecordType/index.tsx | 7 ++++- .../Types/UnionType/index.tsx | 5 +-- .../RecordConstructView/utils/index.tsx | 31 ++++++++++++++++++- 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/CustomType/index.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/CustomType/index.tsx index 0ef73447d39..5df6b0efa63 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/CustomType/index.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/CustomType/index.tsx @@ -22,7 +22,7 @@ import { Codicon, Tooltip, Typography } from "@wso2/ui-toolkit"; import { TypeProps } from "../../ParameterBranch"; import { useHelperPaneStyles } from "../../styles"; -import { isRequiredParam } from "../../utils"; +import { isRequiredParam, resetFieldValues } from "../../utils"; export default function CustomType(props: TypeProps) { const { param, onChange } = props; @@ -38,6 +38,12 @@ export default function CustomType(props: TypeProps) { if (!requiredParam) { const newSelectedState = !paramSelected; param.selected = newSelectedState; + + // When unchecking, reset the field values + if (!newSelectedState) { + resetFieldValues(param); + } + setParamSelected(newSelectedState); onChange(); } diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/InclusionType/index.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/InclusionType/index.tsx index 37ec0427e5e..f3862395d82 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/InclusionType/index.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/InclusionType/index.tsx @@ -23,7 +23,7 @@ import { Codicon, Tooltip, Typography } from "@wso2/ui-toolkit"; import { TypeProps } from "../../ParameterBranch"; import { useHelperPaneStyles } from "../../styles"; import { ParameterBranch } from "../../ParameterBranch"; -import { isAllDefaultableFields, isRequiredParam, updateFieldsSelection } from "../../utils"; +import { isAllDefaultableFields, isRequiredParam, updateFieldsSelection, resetFieldValues } from "../../utils"; export default function InclusionType(props: TypeProps) { const { param, depth, onChange } = props; @@ -43,6 +43,11 @@ export default function InclusionType(props: TypeProps) { param.selected = newSelectedState; param.inclusionType.selected = newSelectedState; + // When unchecking, reset the field values + if (!newSelectedState) { + resetFieldValues(param); + } + // If the inclusion type has fields, update their selection state if (param.inclusionType?.fields && param.inclusionType.fields.length > 0) { updateFieldsSelection(param.inclusionType.fields, newSelectedState); diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/RecordType/index.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/RecordType/index.tsx index 750c7dcea01..31335b497e9 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/RecordType/index.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/RecordType/index.tsx @@ -23,7 +23,7 @@ import { Codicon, Tooltip, Typography } from "@wso2/ui-toolkit"; import { TypeProps } from "../../ParameterBranch"; import { useHelperPaneStyles } from "../../styles"; import { MemoizedParameterBranch } from "../../ParameterBranch"; -import { isRequiredParam, updateFieldsSelection } from "../../utils"; +import { isRequiredParam, updateFieldsSelection, resetFieldValues } from "../../utils"; export default function RecordType(props: TypeProps) { const { param, depth, onChange } = props; @@ -40,6 +40,11 @@ export default function RecordType(props: TypeProps) { const newSelectedState = !paramSelected; param.selected = newSelectedState; + // When unchecking, reset the field values + if (!newSelectedState) { + resetFieldValues(param); + } + // If the record has fields, update their selection state if (param.fields && param.fields.length > 0) { updateFieldsSelection(param.fields, newSelectedState); diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/UnionType/index.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/UnionType/index.tsx index e36af1b3179..503c9bf4019 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/UnionType/index.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/Types/UnionType/index.tsx @@ -24,7 +24,7 @@ import { Codicon, Dropdown, Tooltip, Typography } from "@wso2/ui-toolkit"; import { TypeProps } from "../../ParameterBranch"; import { useHelperPaneStyles } from "../../styles"; import { ParameterBranch } from "../../ParameterBranch"; -import { getSelectedUnionMember, isRequiredParam, updateFieldsSelection } from "../../utils"; +import { getSelectedUnionMember, isRequiredParam, updateFieldsSelection, resetFieldValues } from "../../utils"; export default function UnionType(props: TypeProps) { const { param, depth, onChange } = props; @@ -184,7 +184,8 @@ export default function UnionType(props: TypeProps) { } } } else { - // When unchecking, clear all member selections + // When unchecking, reset values and clear all member selections + resetFieldValues(param); param.members.forEach((field) => { field.selected = false; diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/utils/index.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/utils/index.tsx index f0fea56bb81..1eb1d26bd63 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/utils/index.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/utils/index.tsx @@ -64,12 +64,41 @@ export function checkFormFieldValue(field: FormField): boolean { return field.value !== undefined && field.value !== null; } +export function resetFieldValues(field: FormField): void { + if (!field) return; + + // Reset the field value + if (field.value !== undefined) { + field.value = undefined; + } + + // Reset nested fields + if (field.fields && field.fields.length > 0) { + field.fields.forEach(nestedField => { + resetFieldValues(nestedField); + }); + } + + // Reset union members + if (field.members && field.members.length > 0) { + field.members.forEach(member => { + resetFieldValues(member); + }); + } + + // Reset inclusion type fields + if (field.inclusionType?.fields && field.inclusionType.fields.length > 0) { + field.inclusionType.fields.forEach(inclusionField => { + resetFieldValues(inclusionField); + }); + } +} + export function updateFieldsSelection(fields: FormField[], selected: boolean): void { if (!fields || !fields.length) return; fields.forEach(field => { // When selecting: only select required fields - // When deselecting: deselect all fields (both required and optional) if (!selected || isRequiredParam(field)) { field.selected = selected; From 795ce37e3c30da83f590d15c69cd3f0305221afa Mon Sep 17 00:00:00 2001 From: sachiniSam Date: Tue, 25 Nov 2025 13:52:08 +0530 Subject: [PATCH 6/7] Format code --- .../Components/RecordConstructView/ParameterBranch.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx index b7da81663ae..2101a4f24e0 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx @@ -71,8 +71,8 @@ export function ParameterBranch(props: ParameterBranchProps) { setShowOptionalParams(!showOptionalParams); } - const shouldShowOptionalParamsDirectly = (optionalParams.length > 0 && depth === 1) || - (requiredParams.length === 0 && optionalParams.length > 0 && depth < 3); + const shouldShowOptionalParamsDirectly = (optionalParams.length > 0 && depth === 1) || + (requiredParams.length === 0 && optionalParams.length > 0 && depth < 3); return (
@@ -94,8 +94,8 @@ export function ParameterBranch(props: ParameterBranchProps) { }, }} > - @@ -104,7 +104,7 @@ export function ParameterBranch(props: ParameterBranchProps) {
)}
- {showOptionalParams && optionalParams.length > 0 && optionalParams} + {showOptionalParams && optionalParams.length > 0 && optionalParams}
)} From 46f478134b9b98fa267d9b7f55e92d3d30ef0c96 Mon Sep 17 00:00:00 2001 From: sachiniSam Date: Tue, 25 Nov 2025 15:59:59 +0530 Subject: [PATCH 7/7] Specify event type for toggleOptionalParams function --- .../Components/RecordConstructView/ParameterBranch.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx index 2101a4f24e0..79f4985bdc7 100644 --- a/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx +++ b/workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/RecordConstructView/ParameterBranch.tsx @@ -64,7 +64,7 @@ export function ParameterBranch(props: ParameterBranchProps) { } }); - function toggleOptionalParams(e?: any) { + function toggleOptionalParams(e?: React.MouseEvent) { if (e) { e.stopPropagation(); }