mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-07-27 09:38:28 -06:00
Migrated from CRA to Vite for Building
This commit is contained in:
@ -126,6 +126,18 @@ class RegionLauncher(QtCore.QObject):
|
|||||||
overlay_widgets[self.node_id] = widget
|
overlay_widgets[self.node_id] = widget
|
||||||
widget.show()
|
widget.show()
|
||||||
|
|
||||||
|
# ---------------- GUI Thread Helpers ----------------
|
||||||
|
def gui_create_launcher(node_id, x, y, w, h):
|
||||||
|
launcher = RegionLauncher(node_id)
|
||||||
|
region_launchers[node_id] = launcher
|
||||||
|
launcher.handle(x, y, w, h)
|
||||||
|
|
||||||
|
def gui_update_widget(node_id, x, y, w, h, visible):
|
||||||
|
widget = overlay_widgets.get(node_id)
|
||||||
|
if widget:
|
||||||
|
widget.setGeometry(x, y, w, h)
|
||||||
|
widget.setVisible(visible)
|
||||||
|
|
||||||
# ---------------- Role Management ----------------
|
# ---------------- Role Management ----------------
|
||||||
def stop_all_roles():
|
def stop_all_roles():
|
||||||
for node_id, thread in running_threads.items():
|
for node_id, thread in running_threads.items():
|
||||||
@ -134,7 +146,6 @@ def stop_all_roles():
|
|||||||
running_roles.clear()
|
running_roles.clear()
|
||||||
running_threads.clear()
|
running_threads.clear()
|
||||||
|
|
||||||
|
|
||||||
def start_role_thread(role_cfg):
|
def start_role_thread(role_cfg):
|
||||||
role = role_cfg.get("role")
|
role = role_cfg.get("role")
|
||||||
node_id = role_cfg.get("node_id")
|
node_id = role_cfg.get("node_id")
|
||||||
@ -158,25 +169,21 @@ def run_screenshot_loop(node_id, cfg):
|
|||||||
interval = cfg.get("interval", 1000)
|
interval = cfg.get("interval", 1000)
|
||||||
visible = cfg.get("visible", True)
|
visible = cfg.get("visible", True)
|
||||||
x = cfg.get("x", 100)
|
x = cfg.get("x", 100)
|
||||||
y = cfg.get("y", 100)
|
y = cfg.get("y", 100)
|
||||||
w = cfg.get("w", 300)
|
w = cfg.get("w", 300)
|
||||||
h = cfg.get("h", 200)
|
h = cfg.get("h", 200)
|
||||||
|
|
||||||
|
# Schedule launcher creation in GUI thread
|
||||||
if node_id not in region_launchers:
|
if node_id not in region_launchers:
|
||||||
launcher = RegionLauncher(node_id)
|
QtCore.QTimer.singleShot(0, lambda nid=node_id, xx=x, yy=y, ww=w, hh=h: gui_create_launcher(nid, xx, yy, ww, hh))
|
||||||
region_launchers[node_id] = launcher
|
|
||||||
QtCore.QTimer.singleShot(0, lambda: launcher.trigger.emit(x, y, w, h))
|
|
||||||
|
|
||||||
widget = overlay_widgets.get(node_id)
|
|
||||||
if widget:
|
|
||||||
widget.setGeometry(x, y, w, h)
|
|
||||||
widget.setVisible(visible)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
# Use current widget geometry if available (after user moves/resizes)
|
||||||
if node_id in overlay_widgets:
|
if node_id in overlay_widgets:
|
||||||
widget = overlay_widgets[node_id]
|
widget = overlay_widgets[node_id]
|
||||||
x, y, w, h = widget.get_geometry()
|
x, y, w, h = widget.get_geometry()
|
||||||
|
|
||||||
print(f"[Capture] Screenshot task {node_id} at ({x},{y},{w},{h})")
|
print(f"[Capture] Screenshot task {node_id} at ({x},{y},{w},{h})")
|
||||||
img = ImageGrab.grab(bbox=(x, y, x + w, y + h))
|
img = ImageGrab.grab(bbox=(x, y, x + w, y + h))
|
||||||
buffer = BytesIO()
|
buffer = BytesIO()
|
||||||
@ -188,6 +195,12 @@ def run_screenshot_loop(node_id, cfg):
|
|||||||
"node_id": node_id,
|
"node_id": node_id,
|
||||||
"image_base64": encoded
|
"image_base64": encoded
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Schedule any visibility or geometry updates in GUI thread
|
||||||
|
QtCore.QTimer.singleShot(
|
||||||
|
0,
|
||||||
|
lambda nid=node_id, xx=x, yy=y, ww=w, hh=h, vis=visible: gui_update_widget(nid, xx, yy, ww, hh, vis)
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] Screenshot task {node_id} failed: {e}")
|
print(f"[ERROR] Screenshot task {node_id} failed: {e}")
|
||||||
|
|
||||||
|
22
Data/Server/WebUI/index.html
Normal file
22
Data/Server/WebUI/index.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<!-- Vite serves everything in /public at the site root -->
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta name="description" content="Borealis — Workflow Automation Tool" />
|
||||||
|
<link rel="apple-touch-icon" href="/logo192.png" />
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
|
||||||
|
<title>Borealis</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
|
||||||
|
<!-- Vite entrypoint; adjust to main.tsx if you switch to TS -->
|
||||||
|
<script type="module" src="/src/index.jsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -3,21 +3,27 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "react-scripts build",
|
"dev": "vite",
|
||||||
"start": "react-scripts start"
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mui/material": "7.0.2",
|
|
||||||
"@mui/icons-material": "7.0.2",
|
|
||||||
"@emotion/react": "11.14.0",
|
"@emotion/react": "11.14.0",
|
||||||
"@emotion/styled": "11.14.0",
|
"@emotion/styled": "11.14.0",
|
||||||
"react-resizable": "3.0.5",
|
"@mui/icons-material": "7.0.2",
|
||||||
"react-color": "2.19.3",
|
"@mui/material": "7.0.2",
|
||||||
"reactflow": "11.11.4",
|
|
||||||
"socket.io-client": "4.8.1",
|
|
||||||
"react-simple-keyboard": "3.8.62",
|
|
||||||
"normalize.css": "8.0.1",
|
"normalize.css": "8.0.1",
|
||||||
"react-scripts": "5.0.1"
|
"react": "19.1.0",
|
||||||
|
"react-color": "2.19.3",
|
||||||
|
"react-dom": "19.1.0",
|
||||||
|
"react-resizable": "3.0.5",
|
||||||
|
"reactflow": "11.11.4",
|
||||||
|
"react-simple-keyboard": "3.8.62",
|
||||||
|
"socket.io-client": "4.8.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-react": "^4.0.0",
|
||||||
|
"vite": "^5.0.0"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<meta
|
|
||||||
name="Borealis"
|
|
||||||
content="Workflow Automation Tool"
|
|
||||||
/>
|
|
||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
||||||
|
|
||||||
<title>Borealis</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<div id="root"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -62,25 +62,25 @@ import React, {
|
|||||||
window.BorealisUpdateRate = 200;
|
window.BorealisUpdateRate = 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamically load all node components
|
// Dynamically load all node components via Vite
|
||||||
const nodeContext = require.context("./nodes", true, /\.jsx$/);
|
const modules = import.meta.glob('./nodes/**/*.jsx', { eager: true });
|
||||||
const nodeTypes = {};
|
const nodeTypes = {};
|
||||||
const categorizedNodes = {};
|
const categorizedNodes = {};
|
||||||
|
|
||||||
nodeContext.keys().forEach((path) => {
|
Object.entries(modules).forEach(([path, mod]) => {
|
||||||
const mod = nodeContext(path);
|
const comp = mod.default;
|
||||||
if (!mod.default) return;
|
if (!comp) return;
|
||||||
const { type, label, component } = mod.default;
|
const { type, component } = comp;
|
||||||
if (!type || !component) return;
|
if (!type || !component) return;
|
||||||
|
|
||||||
const pathParts = path.replace("./", "").split("/");
|
// derive category folder name from path: "./nodes/<Category>/File.jsx"
|
||||||
if (pathParts.length < 2) return;
|
const parts = path.replace('./nodes/', '').split('/');
|
||||||
const category = pathParts[0];
|
const category = parts[0];
|
||||||
|
|
||||||
if (!categorizedNodes[category]) {
|
if (!categorizedNodes[category]) {
|
||||||
categorizedNodes[category] = [];
|
categorizedNodes[category] = [];
|
||||||
}
|
}
|
||||||
categorizedNodes[category].push(mod.default);
|
categorizedNodes[category].push(comp);
|
||||||
nodeTypes[type] = component;
|
nodeTypes[type] = component;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import React from 'react';
|
|||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
|
|
||||||
// Global Styles
|
// Global Styles
|
||||||
import './index.css';
|
|
||||||
import "normalize.css/normalize.css";
|
import "normalize.css/normalize.css";
|
||||||
import './Borealis.css'; // Global Theming for All of Borealis
|
import './Borealis.css'; // Global Theming for All of Borealis
|
||||||
|
|
25
Data/Server/WebUI/tsconfig.json
Normal file
25
Data/Server/WebUI/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
|
"allowJs": false,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules", "build", "dist"]
|
||||||
|
}
|
||||||
|
|
17
Data/Server/WebUI/vite.config.ts
Normal file
17
Data/Server/WebUI/vite.config.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: <ProjectRoot>/Data/Server/WebUI/vite.config.ts
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
build: {
|
||||||
|
outDir: 'build',
|
||||||
|
emptyOutDir: true
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, 'src')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -18,9 +18,6 @@
|
|||||||
# ---------------------- Common Initialization & Visuals ----------------------
|
# ---------------------- Common Initialization & Visuals ----------------------
|
||||||
Clear-Host
|
Clear-Host
|
||||||
|
|
||||||
<#
|
|
||||||
Section: Progress Symbols & Helpers
|
|
||||||
#>
|
|
||||||
$symbols = @{
|
$symbols = @{
|
||||||
Success = [char]0x2705
|
Success = [char]0x2705
|
||||||
Running = [char]0x23F3
|
Running = [char]0x23F3
|
||||||
@ -38,7 +35,7 @@ function Write-ProgressStep {
|
|||||||
|
|
||||||
function Run-Step {
|
function Run-Step {
|
||||||
param (
|
param (
|
||||||
[string] $Message,
|
[string] $Message,
|
||||||
[scriptblock]$Script
|
[scriptblock]$Script
|
||||||
)
|
)
|
||||||
Write-ProgressStep -Message $Message -Status "$($symbols.Running)"
|
Write-ProgressStep -Message $Message -Status "$($symbols.Running)"
|
||||||
@ -107,16 +104,8 @@ switch ($choice) {
|
|||||||
New-Item -Path $dataDestination -ItemType Directory -Force | Out-Null
|
New-Item -Path $dataDestination -ItemType Directory -Force | Out-Null
|
||||||
Copy-Item "$dataSource\Server\Python_API_Endpoints" $dataDestination -Recurse
|
Copy-Item "$dataSource\Server\Python_API_Endpoints" $dataDestination -Recurse
|
||||||
Copy-Item "$dataSource\Server\Sounds" $dataDestination -Recurse
|
Copy-Item "$dataSource\Server\Sounds" $dataDestination -Recurse
|
||||||
Copy-Item "$dataSource\Server\Workflows" $dataDestination -Recurse
|
|
||||||
Copy-Item "$dataSource\Server\server.py" $dataDestination
|
Copy-Item "$dataSource\Server\server.py" $dataDestination
|
||||||
}
|
}
|
||||||
if (-not (Test-Path $webUIDestination)) {
|
|
||||||
& $npxCmd --yes create-react-app $webUIDestination | Out-Null
|
|
||||||
}
|
|
||||||
if (Test-Path $customUIPath) {
|
|
||||||
Copy-Item "$customUIPath\*" $webUIDestination -Recurse -Force
|
|
||||||
}
|
|
||||||
Remove-Item "$webUIDestination\build" -Recurse -Force -ErrorAction SilentlyContinue
|
|
||||||
. "$venvFolder\Scripts\Activate"
|
. "$venvFolder\Scripts\Activate"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,20 +116,27 @@ switch ($choice) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# NPM Install for WebUI
|
# Copy Vite WebUI assets (no CRA)
|
||||||
Run-Step "ReactJS Web Frontend: Install NPM Packages" {
|
Run-Step "Setup Vite WebUI assets" {
|
||||||
if (Test-Path "$webUIDestination\package.json") {
|
if (Test-Path $webUIDestination) {
|
||||||
Push-Location $webUIDestination
|
Remove-Item $webUIDestination -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
$env:npm_config_loglevel = "silent"
|
|
||||||
& $npmCmd install --silent --no-fund --audit=false | Out-Null
|
|
||||||
Pop-Location
|
|
||||||
}
|
}
|
||||||
|
New-Item -Path $webUIDestination -ItemType Directory -Force | Out-Null
|
||||||
|
Copy-Item "$customUIPath\*" $webUIDestination -Recurse -Force
|
||||||
}
|
}
|
||||||
|
|
||||||
# Build React App
|
# NPM Install for WebUI
|
||||||
Run-Step "ReactJS Web Frontend: Build" {
|
Run-Step "Vite Web Frontend: Install NPM Packages" {
|
||||||
Push-Location $webUIDestination
|
Push-Location $webUIDestination
|
||||||
& $npmCmd run build
|
$env:npm_config_loglevel = "silent"
|
||||||
|
& $npmCmd install --silent --no-fund --audit=false | Out-Null
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build with Vite
|
||||||
|
Run-Step "Vite Web Frontend: Build" {
|
||||||
|
Push-Location $webUIDestination
|
||||||
|
& $npmCmd run build --silent
|
||||||
Pop-Location
|
Pop-Location
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,10 +220,10 @@ switch ($choice) {
|
|||||||
Copy-Item "$electronSource\package.json" "$electronDestination" -Force
|
Copy-Item "$electronSource\package.json" "$electronDestination" -Force
|
||||||
Copy-Item "$electronSource\main.js" "$electronDestination" -Force
|
Copy-Item "$electronSource\main.js" "$electronDestination" -Force
|
||||||
|
|
||||||
# Copy CRA build into renderer
|
# Copy built WebUI into renderer
|
||||||
$staticBuild = Join-Path $scriptDir 'Server\web-interface\build'
|
$staticBuild = Join-Path $scriptDir 'Server\web-interface\build'
|
||||||
if (-not (Test-Path $staticBuild)) {
|
if (-not (Test-Path $staticBuild)) {
|
||||||
throw "React build not found - run choice 1 to build WebUI first."
|
throw "WebUI build not found - run choice 1 to build WebUI first."
|
||||||
}
|
}
|
||||||
Copy-Item "$staticBuild\*" "$electronDestination\renderer" -Recurse -Force
|
Copy-Item "$staticBuild\*" "$electronDestination\renderer" -Recurse -Force
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user