Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
066b789
fix helperpane clickable issue
senithkay Sep 9, 2025
3f05037
add max-wdith and change colors
senithkay Sep 9, 2025
ece40db
fix variable trimming
senithkay Sep 9, 2025
1e0265d
Fix issues in BI tests
tharindulak Sep 9, 2025
7c0fd58
Merge branch 'main' of https://github.com/wso2/vscode-extensions into…
tharindulak Sep 9, 2025
ec221b6
Create a context based general popup component | fix helpers not clos…
senithkay Sep 9, 2025
4459c9f
Fix form title
senithkay Sep 9, 2025
0f3a7c5
Merge pull request #425 from wso2/main
kanushka Sep 10, 2025
89e08c3
Fix fillTypeField issue
tharindulak Sep 10, 2025
61f770e
Fix type-editor type edit issues
senithkay Sep 10, 2025
fa730b9
Change file sorting priority to handle creating custom functions from…
KCSAbeywickrama Sep 10, 2025
4b27734
Fix connector view double scrollbar issue
kaumini Sep 10, 2025
3166bd8
Merge pull request #426 from KCSAbeywickrama/bi-ru-dm-map-with-custom…
madushajg Sep 10, 2025
788b4d8
Fix tests isues
tharindulak Sep 10, 2025
337aeca
Merge branch 'main' of https://github.com/wso2/vscode-extensions into…
tharindulak Sep 10, 2025
182e09a
fix type creation in formGenerator and FormgeneratorNew
senithkay Sep 10, 2025
e88116f
Merge branch 'main' of https://github.com/wso2/vscode-extensions into…
senithkay Sep 10, 2025
5b826fe
Fix defaultValue issue in graphQL
senithkay Sep 10, 2025
34ee37a
remove console log
senithkay Sep 10, 2025
9cdce47
fix no EOF
senithkay Sep 10, 2025
91bf438
Merge branch 'main' of https://github.com/wso2/vscode-extensions into…
senithkay Sep 10, 2025
e8436e0
Merge branch 'main' into configEditorLibIssue
kaumini Sep 10, 2025
7263263
Merge branch 'main' into fix-type-editor-fix-new
kanushka Sep 10, 2025
94386d3
fix modal not closing when submit
senithkay Sep 10, 2025
8032e8d
Merge branch 'main' of https://github.com/wso2/vscode-extensions into…
senithkay Sep 10, 2025
03130ac
Merge pull request #429 from senithkay/fix-type-editor-fix-new
kanushka Sep 10, 2025
58c28df
Merge pull request #414 from senithkay/fix-helperpane-click
kanushka Sep 10, 2025
3dbe541
Apply suggestion from @Copilot
kanushka Sep 10, 2025
b4e23a0
Merge pull request #427 from kaumini/configEditorLibIssue
kanushka Sep 10, 2025
3bb04aa
add license header
senithkay Sep 10, 2025
e218a2d
Merge branch 'modal-rework' of https://github.com/senithkay/vscode-ex…
senithkay Sep 10, 2025
135703a
Merge pull request #421 from senithkay/modal-rework
kanushka Sep 10, 2025
488a779
Merge branch 'main' into fix-bi-tests
kanushka Sep 10, 2025
3776b5c
Merge pull request #428 from tharindulak/fix-bi-tests
kanushka Sep 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,18 @@ export async function updateSourceCodeIteratively(updateSourceCodeRequest: Updat
return await updateSourceCode(updateSourceCodeRequest);
}

// need to prioritize if file path ends with functions.bal or data_mappings.bal
// TODO: Remove this once the designModelService/publishArtifacts API supports simultaneous file changes
filePaths.sort((a, b) => {
// Prioritize files ending with functions.bal or data_mappings.bal
const aEndsWithFunctions = (a.endsWith("functions.bal") || a.endsWith("data_mappings.bal")) ? 1 : 0;
const bEndsWithFunctions = (b.endsWith("functions.bal") || b.endsWith("data_mappings.bal")) ? 1 : 0;
return bEndsWithFunctions - aEndsWithFunctions; // Sort descending
// Priority: functions.bal > data_mappings.bal > any other file
const getPriority = (filePath: string): number => {
if (filePath.endsWith("functions.bal")) return 2;
if (filePath.endsWith("data_mappings.bal")) return 1;
return 0;
};

const aPriority = getPriority(a);
const bPriority = getPriority(b);
return bPriority - aPriority; // Sort descending (highest priority first)
});

const requests: UpdateSourceCodeRequest[] = filePaths.map(filePath => ({
Expand Down
50 changes: 50 additions & 0 deletions workspaces/ballerina/ballerina-visualizer/src/Context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,53 @@ export function VisualizerContextProvider({ children }: { children: ReactNode })
}

export const useVisualizerContext = () => useContext(VisualizerContext);

export const POPUP_IDS = {
VARIABLE: "VARIABLE",
FUNCTION: "FUNCTION",
CONFIGURABLES: "CONFIGURABLES",
} as const;

type ModalStackItem = {
modal: ReactNode;
id: string;
title: string;
height?: number;
width?: number;
}

interface ModalStackContext {
modalStack: ModalStackItem[];
addModal: (modal: ReactNode, id: string, title: string, height?: number, width?: number) => void;
popModal: () => void;
closeModal: (id: string) => void;
}

export const ModalStackContext = createContext({
modalStack: [],
addModal: (modal: ReactNode, id: string, title: string, height?: number, width?: number) => { },
popModal: () => { },
closeModal: (id: string) => { },
} as ModalStackContext);

export const ModalStackProvider = ({children}: {children: ReactNode}) => {
const [modalStack, setModalStack] = useState<ModalStackItem[]>([]);

const addModal = (modal: ReactNode, id: string, title: string, height?: number, width?: number) => {
setModalStack((prevStack) => [...prevStack, { modal, id, title, height, width }]);
};

const popModal = () => {
setModalStack((prevStack) => prevStack.slice(0, -1));
};

const closeModal = (id: string) => {
setModalStack((prevStack) => prevStack.filter((item) => item.id !== id));
};

return <ModalStackContext.Provider value={{ modalStack, addModal, popModal, closeModal }}>
{children}
</ModalStackContext.Provider>;
}

export const useModalStack = () => useContext(ModalStackContext);
19 changes: 15 additions & 4 deletions workspaces/ballerina/ballerina-visualizer/src/MainPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { handleRedo, handleUndo } from "./utils/utils";
import { STKindChecker } from "@wso2/syntax-tree";
import { URI, Utils } from "vscode-uri";
import { ThemeColors, Typography } from "@wso2/ui-toolkit";
import { PanelType, useVisualizerContext } from "./Context";
import { PanelType, useModalStack, useVisualizerContext } from "./Context";
import { ConstructPanel } from "./views/ConstructPanel";
import { EditPanel } from "./views/EditPanel";
import { RecordEditor } from "./views/RecordEditor/RecordEditor";
Expand All @@ -76,6 +76,7 @@ import { BallerinaUpdateView } from "./views/BI/BallerinaUpdateView";
import { VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react";
import { DataMapper } from "./views/DataMapper";
import { ImportIntegration } from "./views/BI/ImportIntegration";
import Popup from "./components/Popup";

const globalStyles = css`
*,
Expand Down Expand Up @@ -189,6 +190,7 @@ const LoadingText = styled.div`
const MainPanel = () => {
const { rpcClient } = useRpcContext();
const { sidePanel, setSidePanel, popupMessage, setPopupMessage, activePanel, showOverlay, setShowOverlay } = useVisualizerContext();
const {modalStack, closeModal} = useModalStack()
const [viewComponent, setViewComponent] = useState<React.ReactNode>();
const [navActive, setNavActive] = useState<boolean>(true);
const [showHome, setShowHome] = useState<boolean>(true);
Expand Down Expand Up @@ -415,7 +417,7 @@ const MainPanel = () => {
case MACHINE_VIEW.GraphQLDiagram:
const getProjectStructure = await rpcClient.getBIDiagramRpcClient().getProjectStructure();
const entryPoint = getProjectStructure.directoryMap[DIRECTORY_MAP.SERVICE].find((service: ProjectStructureArtifactResponse) => service.name === value?.identifier);
setViewComponent(<GraphQLDiagram serviceIdentifier={value?.identifier} filePath={value?.documentUri} position={entryPoint?.position} projectUri={value?.projectUri} />);
setViewComponent(<GraphQLDiagram serviceIdentifier={value?.identifier} filePath={value?.documentUri} position={entryPoint?.position ?? value?.position} projectUri={value?.projectUri} />);
break;
case MACHINE_VIEW.BallerinaUpdateView:
setNavActive(false);
Expand Down Expand Up @@ -558,12 +560,16 @@ const MainPanel = () => {
.openView({ type: EVENT_TYPE.CLOSE_VIEW, location: { view: null, recentIdentifier: parent?.recentIdentifier, artifactType: parent?.artifactType }, isPopup: true });
};

const handlePopupClose = (id: string) => {
closeModal(id);
}

return (
<>
<Global styles={globalStyles} />
<VisualizerContainer>
{/* {navActive && <NavigationBar showHome={showHome} />} */}
{showOverlay && <Overlay onClick={() => setShowOverlay(false)} />}
{(showOverlay || modalStack.length > 0) && <Overlay/>}
{viewComponent && <ComponentViewWrapper>{viewComponent}</ComponentViewWrapper>}
{!viewComponent && (
<ComponentViewWrapper>
Expand Down Expand Up @@ -609,9 +615,14 @@ const MainPanel = () => {
{sidePanel !== "EMPTY" && sidePanel === "ADD_ACTION" && (
<EndpointList stSymbolInfo={getSymbolInfo()} applyModifications={applyModifications} />
)}
{
modalStack.map((modal) => (
<Popup title={modal.title} onClose={() => handlePopupClose(modal.id)} key={modal.id} width={modal.width} height={modal.height}>{modal.modal}</Popup>
))
}
</VisualizerContainer>
</>
);
};
};

export default MainPanel;
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com) All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import styled from "@emotion/styled";
import { Codicon, Divider, Typography } from "@wso2/ui-toolkit";
import { ThemeColors } from "@wso2/ui-toolkit/lib/styles/Theme";

const PopupFormContainer = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 30000;
display: flex;
justify-content: center;
align-items: center;
`;

const PopupFormBox = styled.div<{ width?: number; height?: number }>`
width: ${({ width }: { width?: number }) => (width ? `${width}px` : 'auto')};
height: ${({ height }: { height?: number }) => (height ? `${height}px` : 'auto')};
position: relative;
display: flex;
flex-direction: column;
overflow-y: hidden;
padding: 16px;
border-radius: 3px;
background-color: ${ThemeColors.SURFACE_DIM};
box-shadow: 0 3px 8px rgb(0 0 0 / 0.2);
z-index: 30001;
`;

const PopupFormHeader = styled.header`
display: flex;
align-items: center;
justify-content: space-between;
padding-inline: 16px;
`;

export type PopupFormProps = {
width?: number;
height?: number;
title: string;
children: React.ReactNode;
onClose?: () => void;
};

export const PopupForm = (props: PopupFormProps) => {
const { width, height, title, children, onClose } = props;

return (
<PopupFormContainer>
<PopupFormBox width={width} height={height}>
<PopupFormHeader>
<Typography variant="h2" sx={{ margin: 0 }}>
{title}
</Typography>
<Codicon name="close" onClick={onClose} />
</PopupFormHeader>
<Divider />
<div>{children}</div>
</PopupFormBox>
</PopupFormContainer>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com) All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import React, { ReactNode } from "react";
import styled from "@emotion/styled";
import { PopupForm } from "./Form";

export type PopupProps = {
children: ReactNode;
onClose?: () => void;
width?: number;
height?: number;
title: string;
};

const PopupContentContainer = styled.div`
position: relative;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 30000;
display: flex;
justify-content: center;
align-items: center;
`;



const Popup: React.FC<PopupProps> = ({
children,
onClose,
width,
height,
title
}) => {


return (
<PopupContentContainer>
<PopupForm onClose={onClose} height={height} width={width} title={title}>
{children}
</PopupForm>
</PopupContentContainer>
);
};

export default Popup;
14 changes: 8 additions & 6 deletions workspaces/ballerina/ballerina-visualizer/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import React from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { createRoot } from "react-dom/client";
import { Visualizer } from "./Visualizer";
import { VisualizerContextProvider, RpcContextProvider } from "./Context";
import { VisualizerContextProvider, RpcContextProvider, ModalStackProvider } from "./Context";
import { clearDiagramZoomAndPosition } from "./utils/bi";

const queryClient = new QueryClient({
Expand All @@ -41,11 +41,13 @@ export function renderWebview(mode: string, target: HTMLElement) {
const root = createRoot(target);
root.render(
<VisualizerContextProvider>
<RpcContextProvider>
<QueryClientProvider client={queryClient}>
<Visualizer mode={mode} />
</QueryClientProvider>
</RpcContextProvider>
<ModalStackProvider>
<RpcContextProvider>
<QueryClientProvider client={queryClient}>
<Visualizer mode={mode} />
</QueryClientProvider>
</RpcContextProvider>
</ModalStackProvider>
</VisualizerContextProvider>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ export function AddConnectionWizard(props: AddConnectionWizardProps) {
onSelectConnector={handleOnSelectConnector}
onAddGeneratedConnector={handleOnAddGeneratedConnector}
onClose={onClose}
isPopupView={true}
/>
</PopupContainer>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,13 @@ const Container = styled.div`
flex-direction: column;
`;

const ListContainer = styled.div<{ isHalfView?: boolean }>`
const ListContainer = styled.div<{ isPopupView?: boolean }>`
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 16px;
margin-left: 20px;
height: ${(props: { isHalfView: boolean }) => (props.isHalfView ? "30vh" : "calc(100vh - 200px)")};
overflow-y: scroll;
height: ${(props: { isPopupView: boolean }) => (props.isPopupView ? "30vh" : "calc(100vh - 200px)")};
`;

const GridContainer = styled.div<{ isHalfView?: boolean }>`
Expand Down Expand Up @@ -99,6 +98,7 @@ interface ConnectorViewProps {
onClose?: () => void;
hideTitle?: boolean;
openCustomConnectorView?: boolean;
isPopupView?: boolean;
}

export function ConnectorView(props: ConnectorViewProps) {
Expand All @@ -110,6 +110,7 @@ export function ConnectorView(props: ConnectorViewProps) {
onClose,
hideTitle,
openCustomConnectorView,
isPopupView
} = props;
const { rpcClient } = useRpcContext();

Expand Down Expand Up @@ -401,7 +402,7 @@ export function ConnectorView(props: ConnectorViewProps) {
</TreeViewItemContent>
</TreeViewItem>
</div>
<ListContainer isHalfView={hideTitle}>
<ListContainer isPopupView={isPopupView}>
{selectedConnectorCategory === "CurrentOrg" && (
<LabelRow>
<Typography variant="h3">{'Organization\'s Connectors'}</Typography>
Expand Down
Loading
Loading