Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 14 additions & 2 deletions workspaces/ballerina/ballerina-extension/src/stateMachine.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import { ExtendedLangClient } from './core';
import { ballerinaExtInstance, ExtendedLangClient } from './core';
import { createMachine, assign, interpret } from 'xstate';
import { activateBallerina } from './extension';
import { EVENT_TYPE, SyntaxTree, History, HistoryEntry, MachineStateValue, STByRangeRequest, SyntaxTreeResponse, UndoRedoManager, VisualizerLocation, webviewReady, MACHINE_VIEW, DIRECTORY_MAP, SCOPE, ProjectStructureResponse, ArtifactData, ProjectStructureArtifactResponse } from "@wso2/ballerina-core";
Expand Down Expand Up @@ -67,7 +67,7 @@ const stateMachine = createMachine<MachineContext>(
invoke: {
src: checkForProjects,
onDone: {
target: "activateLS",
target: "renderInitialView",
actions: assign({
isBI: (context, event) => event.data.isBI,
projectUri: (context, event) => event.data.projectPath,
Expand All @@ -76,6 +76,17 @@ const stateMachine = createMachine<MachineContext>(
package: (context, event) => event.data.packageName,
})
},
onError: {
target: "renderInitialView"
}
}
},
renderInitialView: {
invoke: {
src: 'openWebView',
onDone: {
target: "activateLS"
},
onError: {
target: "activateLS"
}
Expand Down Expand Up @@ -256,6 +267,7 @@ const stateMachine = createMachine<MachineContext>(
// Get context values from the project storage so that we can restore the earlier state when user reopens vscode
return new Promise((resolve, reject) => {
if (!VisualizerWebview.currentPanel) {
ballerinaExtInstance.setContext(extension.context);
VisualizerWebview.currentPanel = new VisualizerWebview();
RPCLayer._messenger.onNotification(webviewReady, () => {
history = new History();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,16 @@ export class VisualizerWebview {
private getWebviewContent(webView: Webview) {
const body = `<div class="container" id="webview-container">
<div class="loader-wrapper">
<div class="loader" /></div>
<div class="welcome-content">
<div class="logo-container">
<div class="loader"></div>
</div>
<h1 class="welcome-title">Welcome to WSO2 Integrator: BI</h1>
<p class="welcome-subtitle">Setting up your workspace and tools</p>
<div class="loading-text">
<span class="loading-dots">Loading</span>
</div>
</div>
</div>
</div>`;
const bodyCss = ``;
Expand All @@ -123,9 +132,10 @@ export class VisualizerWebview {
.loader-wrapper {
display: flex;
justify-content: center;
align-items: center;
align-items: flex-start;
height: 100%;
width: 100%;
padding-top: 30vh;
}
.loader {
width: 32px;
Expand All @@ -151,6 +161,56 @@ export class VisualizerWebview {
50% {transform:scaleY(-1) rotate(0deg)}
100% {transform:scaleY(-1) rotate(-135deg)}
}
/* New welcome view styles */
.welcome-content {
text-align: center;
max-width: 500px;
padding: 2rem;
animation: fadeIn 1s ease-in-out;
font-family: var(--vscode-font-family);
}
.logo-container {
margin-bottom: 2rem;
display: flex;
justify-content: center;
}
.welcome-title {
color: var(--vscode-foreground);
margin: 0 0 0.5rem 0;
letter-spacing: -0.02em;
font-size: 1.5em;
font-weight: 400;
line-height: normal;
}
.welcome-subtitle {
color: var(--vscode-descriptionForeground);
font-size: 13px;
margin: 0 0 2rem 0;
opacity: 0.8;
}
.loading-text {
color: var(--vscode-foreground);
font-size: 13px;
font-weight: 500;
}
.loading-dots::after {
content: '';
animation: dots 1.5s infinite;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes dots {
0%, 20% { content: ''; }
40% { content: '.'; }
60% { content: '..'; }
80%, 100% { content: '...'; }
}
`;
const scripts = `
function loadedScript() {
Expand Down
86 changes: 86 additions & 0 deletions workspaces/ballerina/ballerina-visualizer/src/MainPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,41 @@ import { ServiceClassConfig } from "./views/BI/ServiceClassEditor/ServiceClassCo
import { AIAgentDesigner } from "./views/BI/AIChatAgent";
import { AIChatAgentWizard } from "./views/BI/AIChatAgent/AIChatAgentWizard";
import { BallerinaUpdateView } from "./views/BI/BallerinaUpdateView";
import { VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react";

const globalStyles = css`
*,
*::before,
*::after {
box-sizing: border-box;
}

@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}

.loading-dots::after {
content: '';
animation: dots 1.5s infinite;
}

@keyframes dots {
0%, 20% { content: ''; }
40% { content: '.'; }
60% { content: '..'; }
80%, 100% { content: '...'; }
}
`;

const ProgressRing = styled(VSCodeProgressRing)`
height: 50px;
width: 50px;
margin: 1.5rem;
`;

const VisualizerContainer = styled.div`
Expand All @@ -98,6 +126,50 @@ const PopUpContainer = styled.div`
z-index: 2000;
`;

const LoadingViewContainer = styled.div`
background-color: var(--vscode-editor-background);
height: 100vh;
width: 100%;
display: flex;
font-family: var(--vscode-font-family);
`;

const LoadingContent = styled.div`
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
height: 100%;
width: 100%;
padding-top: 30vh;
text-align: center;
max-width: 500px;
margin: 0 auto;
animation: fadeIn 1s ease-in-out;
`;

const LoadingTitle = styled.h1`
color: var(--vscode-foreground);
font-size: 1.5em;
font-weight: 400;
margin: 0;
letter-spacing: -0.02em;
line-height: normal;
`;

const LoadingSubtitle = styled.p`
color: var(--vscode-descriptionForeground);
font-size: 13px;
margin: 0.5rem 0 2rem 0;
opacity: 0.8;
`;

const LoadingText = styled.div`
color: var(--vscode-foreground);
font-size: 13px;
font-weight: 500;
`;

const MainPanel = () => {
const { rpcClient } = useRpcContext();
const { sidePanel, setSidePanel, popupMessage, setPopupMessage, activePanel } = useVisualizerContext();
Expand Down Expand Up @@ -376,6 +448,20 @@ const MainPanel = () => {
<VisualizerContainer>
{/* {navActive && <NavigationBar showHome={showHome} />} */}
{viewComponent && <ComponentViewWrapper>{viewComponent}</ComponentViewWrapper>}
{!viewComponent && (
<ComponentViewWrapper>
<LoadingViewContainer>
<LoadingContent>
<ProgressRing />
<LoadingTitle>Loading Integration</LoadingTitle>
<LoadingSubtitle>Setting up your integration environment</LoadingSubtitle>
<LoadingText>
<span className="loading-dots">Please wait</span>
</LoadingText>
</LoadingContent>
</LoadingViewContainer>
</ComponentViewWrapper>
)}
{sidePanel !== "EMPTY" && sidePanel === "ADD_CONNECTION" && (
<ConnectorList applyModifications={applyModifications} />
)}
Expand Down
92 changes: 90 additions & 2 deletions workspaces/ballerina/ballerina-visualizer/src/Visualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,71 @@ import React, { useEffect } from "react";
import { useRpcContext } from "@wso2/ballerina-rpc-client";
import { AIMachineStateValue, MachineStateValue } from "@wso2/ballerina-core";
import MainPanel from "./MainPanel";
import styled from '@emotion/styled';
import { LoadingRing } from "./components/Loader";
import AIPanel from "./views/AIPanel/AIPanel";
import { AgentChat } from "./views/AgentChatPanel/AgentChat";
import { VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react";
import { Global, css } from '@emotion/react';

const ProgressRing = styled(VSCodeProgressRing)`
height: 50px;
width: 50px;
margin: 1.5rem;
`;

const LoadingContent = styled.div`
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
height: 100%;
width: 100%;
padding-top: 30vh;
text-align: center;
max-width: 500px;
margin: 0 auto;
animation: fadeIn 1s ease-in-out;
`;

const LoadingTitle = styled.h1`
color: var(--vscode-foreground);
font-size: 1.5em;
font-weight: 400;
margin: 0;
letter-spacing: -0.02em;
line-height: normal;
`;

const LoadingSubtitle = styled.p`
color: var(--vscode-descriptionForeground);
font-size: 13px;
margin: 0.5rem 0 2rem 0;
opacity: 0.8;
`;

const LoadingText = styled.div`
color: var(--vscode-foreground);
font-size: 13px;
font-weight: 500;
`;

const globalStyles = css`
@keyframes fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}
.loading-dots::after {
content: '';
animation: dots 1.5s infinite;
}
@keyframes dots {
0%, 20% { content: ''; }
40% { content: '.'; }
60% { content: '..'; }
80%, 100% { content: '...'; }
}
`;

const MODES = {
VISUALIZER: "visualizer",
Expand Down Expand Up @@ -61,7 +123,7 @@ export function Visualizer({ mode }: { mode: string }) {
case MODES.VISUALIZER:
return <VisualizerComponent state={state} />
case MODES.AI:
return <AIPanel state={aiState} />
return <AIPanel state={aiState} />
case MODES.AGENT_CHAT:
return <AgentChat />
}
Expand All @@ -75,6 +137,32 @@ const VisualizerComponent = React.memo(({ state }: { state: MachineStateValue })
case typeof state === 'object' && 'viewActive' in state && state.viewActive === "viewReady":
return <MainPanel />;
default:
return <LoadingRing />;
return <LanguageServerLoadingView />;
}
});

const LanguageServerLoadingView = () => {
return (
<div style={{
backgroundColor: 'var(--vscode-editor-background)',
height: '100vh',
width: '100%',
display: 'flex',
fontFamily: 'var(--vscode-font-family)'
}}>
<Global styles={globalStyles} />
<LoadingContent>
<ProgressRing />
<LoadingTitle>
Activating Language Server
</LoadingTitle>
<LoadingSubtitle>
Preparing your Ballerina development environment
</LoadingSubtitle>
<LoadingText>
<span className="loading-dots">Initializing</span>
</LoadingText>
</LoadingContent>
</div>
);
};
Loading