diff --git a/Data/WebUI/src/App.js b/Data/WebUI/src/App.js index 0e60f10..87576be 100644 --- a/Data/WebUI/src/App.js +++ b/Data/WebUI/src/App.js @@ -1,6 +1,19 @@ import React from "react"; import FlowEditor from "./components/FlowEditor"; -import { AppBar, Toolbar, Typography, Box, Menu, MenuItem, Button, CssBaseline, ThemeProvider, createTheme } from "@mui/material"; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; + +import { + AppBar, + Toolbar, + Typography, + Box, + Menu, + MenuItem, + Button, + CssBaseline, + ThemeProvider, + createTheme +} from "@mui/material"; const darkTheme = createTheme({ palette: { @@ -16,14 +29,24 @@ const darkTheme = createTheme({ }); export default function App() { - const [anchorEl, setAnchorEl] = React.useState(null); + // Separate menu state for each dropdown + const [workflowsAnchorEl, setWorkflowsAnchorEl] = React.useState(null); + const [aboutAnchorEl, setAboutAnchorEl] = React.useState(null); - const handleMenuOpen = (event) => { - setAnchorEl(event.currentTarget); + const handleWorkflowsMenuOpen = (event) => { + setWorkflowsAnchorEl(event.currentTarget); }; - const handleMenuClose = () => { - setAnchorEl(null); + const handleAboutMenuOpen = (event) => { + setAboutAnchorEl(event.currentTarget); + }; + + const handleWorkflowsMenuClose = () => { + setWorkflowsAnchorEl(null); + }; + + const handleAboutMenuClose = () => { + setAboutAnchorEl(null); }; return ( @@ -36,15 +59,40 @@ export default function App() { Borealis - Workflow Automation Tool - - } > - Save Workflow - Load Workflow - Close Workflow + Workflows + + + Save Workflow + Load Workflow + Close Workflow + + + {/* About Menu */} + + + Gitea Project + Credits diff --git a/Data/WebUI/src/components/FlowEditor.css b/Data/WebUI/src/components/FlowEditor.css new file mode 100644 index 0000000..576bfe8 --- /dev/null +++ b/Data/WebUI/src/components/FlowEditor.css @@ -0,0 +1,23 @@ +/* FlowEditor background container */ +.flow-editor-container { + position: relative; + width: 100vw; + height: 100vh; +} + + /* Gradient Overlay */ + .flow-editor-container::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; /* Ensures grid and nodes remain fully interactive */ + background: linear-gradient( to bottom, rgba(9, 44, 68, 0.8) 0%, /* Deep blue at the top */ + rgba(30, 30, 30, 0) 25%, /* Fade out towards center */ + rgba(30, 30, 30, 0) 75%, /* No gradient in the middle */ + rgba(9, 44, 68, 0.8) 100% /* Deep blue at the bottom */ + ); + z-index: -1; /* Ensures it stays behind the React Flow elements */ + } diff --git a/Data/WebUI/src/components/FlowEditor.jsx b/Data/WebUI/src/components/FlowEditor.jsx index 0de34ca..b341d84 100644 --- a/Data/WebUI/src/components/FlowEditor.jsx +++ b/Data/WebUI/src/components/FlowEditor.jsx @@ -5,6 +5,7 @@ import ReactFlow, { Background, } from "reactflow"; import "reactflow/dist/style.css"; +import "./FlowEditor.css"; const fetchNodes = async () => { const response = await fetch("/api/workflow"); @@ -36,10 +37,15 @@ export default function FlowEditor() { ); return ( -
+
- +
); diff --git a/Data/server.py b/Data/server.py index 04db7ee..377227e 100644 --- a/Data/server.py +++ b/Data/server.py @@ -53,7 +53,7 @@ def serve_frontend(): index_path = os.path.join(build_folder, "index.html") if os.path.exists(index_path): return send_from_directory(app.static_folder, "index.html") - return "

React App Not Found

Please build the web-interface application.

", 404 + return "

Borealis React App Code Not Found

Please re-deploy Borealis Workflow Automation Tool

", 404 @app.route("/api/nodes", methods=["GET"]) def get_available_nodes(): @@ -128,4 +128,4 @@ def delete_edge(edge_id): return jsonify({"status": "success", "deletedEdge": edge_id}) if __name__ == "__main__": - app.run(host="0.0.0.0", port=5000, debug=True) + app.run(host="0.0.0.0", port=5000, debug=False) diff --git a/Launch-Borealis.ps1 b/Launch-Borealis.ps1 index f264d3e..36a0b1b 100644 --- a/Launch-Borealis.ps1 +++ b/Launch-Borealis.ps1 @@ -2,113 +2,148 @@ # Run this script with: # Set-ExecutionPolicy Unrestricted -Scope Process; .\Start_Windows -WebServer.ps1 -Write-Output " =============================== " -Write-Output " Deploying Borealis " -Write-Output " =============================== " +# ---------------------- Initialization & Visuals ---------------------- +$symbols = @{ + Success = [char]0x2705 + Running = [char]0x23F3 + Fail = [char]0x274C + Info = [char]0x2139 +} -# --- Check for Node.js --- +function Write-ProgressStep { + param ( + [string]$Message, + [string]$Status = $symbols["Info"] # Ensure proper lookup + ) + Write-Host "`r$Status $Message... " -NoNewline +} + +function Run-Step { + param ( + [string]$Message, + [scriptblock]$Script + ) + Write-ProgressStep -Message $Message -Status "$($symbols.Running)" + try { + & $Script + if ($LASTEXITCODE -eq 0 -or $?) { + Write-Host "`r$($symbols.Success) $Message " # Fix symbol lookup + } else { + throw "Non-zero exit code" + } + } catch { + Write-Host "`r$($symbols.Fail) $Message - Failed: $_ " -ForegroundColor Red + exit 1 + } +} + +Clear-Host +Write-Host "Deploying Borealis - Workflow Automation Tool..." -ForegroundColor Green +Write-Host "====================================================================================" + +# ---------------------- Node.js Check ---------------------- if (-not (Get-Command node -ErrorAction SilentlyContinue)) { - Write-Error "Node.js is not installed. Please install Node.js and try again." + Write-Host "`r$($symbols.Fail) Node.js is not installed. Please install Node.js and try again." -ForegroundColor Red exit 1 } -# --- Define paths --- -$venvFolder = "Borealis-Workflow-Automation-Tool" # Virtual environment root. -$dataSource = "Data" # Contains server.py and optionally WebUI. -$dataDestination = "$venvFolder\Borealis" # Data folder copy destination in the venv. -$customUIPath = "$dataSource\WebUI" # Custom UI folder source in the project root. -$webUIDestination = "$venvFolder\web-interface" # Destination for the React UI in the venv. +# ---------------------- Path Definitions ---------------------- +$venvFolder = "Borealis-Workflow-Automation-Tool" +$dataSource = "Data" +$dataDestination = "$venvFolder\Borealis" +$customUIPath = "$dataSource\WebUI" +$webUIDestination = "$venvFolder\web-interface" -# --- Create virtual environment if needed --- -if (!(Test-Path "$venvFolder\Scripts\Activate")) { - Write-Output "Creating Virtual Python Environment in '$venvFolder'..." - python -m venv $venvFolder -} - -# --- Copy Data folder (includes server.py) --- -if (Test-Path $dataSource) { - Write-Output "Copying Borealis Server Data into Virtual Environment..." - if (Test-Path $dataDestination) { - Remove-Item -Recurse -Force $dataDestination +# ---------------------- Create Python Virtual Environment ---------------------- +Run-Step "Create Virtual Python Environment" { + if (!(Test-Path "$venvFolder\Scripts\Activate")) { + python -m venv $venvFolder | Out-Null } - New-Item -Path $dataDestination -ItemType Directory -Force | Out-Null - Copy-Item -Path "$dataSource\*" -Destination $dataDestination -Recurse -} else { - Write-Output "Warning: Data folder not found, skipping copy. Fix whatever you broke." } -# --- React UI Deployment --- -# Check if the React UI folder exists in the virtual environment root. -if (-not (Test-Path $webUIDestination)) { - Write-Output "ReactJS App Not Found. Generating Default ReactJS App..." - npx create-react-app $webUIDestination -} else { - Write-Output "React UI folder '$webUIDestination' already exists." +# ---------------------- Copy Server Data ---------------------- +Run-Step "Copy Borealis Server Data into Virtual Python Environment" { + if (Test-Path $dataSource) { + if (Test-Path $dataDestination) { + Remove-Item -Recurse -Force $dataDestination | Out-Null + } + New-Item -Path $dataDestination -ItemType Directory -Force | Out-Null + Copy-Item -Path "$dataSource\*" -Destination $dataDestination -Recurse + } else { + Write-Host "`r$($symbols.Info) Warning: Data folder not found, skipping copy." -ForegroundColor Yellow + } } -# If a custom UI folder exists at \Data\WebUI, copy its contents over (overwrite defaults). -if (Test-Path $customUIPath) { - Write-Output "Borealis ReactJS Data Found at '$customUIPath'. Overwriting ReactJS App Files..." - Copy-Item -Path "$customUIPath\*" -Destination $webUIDestination -Recurse -Force -} else { - Write-Output "No custom UI folder found at '$customUIPath'. Using default ReactJS app." +# ---------------------- React UI Deployment ---------------------- +Run-Step "Create a new ReactJS App in $webUIDestination" { + if (-not (Test-Path $webUIDestination)) { + npx create-react-app $webUIDestination | Out-Null + } } -# --- Activate virtual environment --- -Write-Output "Activating Virtual Python Environment..." -. "$venvFolder\Scripts\Activate" - -# --- Install Python dependencies --- -if (Test-Path "requirements.txt") { - Write-Output "Installing Python Dependencies..." - pip install -q -r requirements.txt -} else { - Write-Output "No requirements.txt found, skipping Python dependency installation." +Run-Step "Overwrite ReactJS App Files with Borealis ReactJS Files" { + if (Test-Path $customUIPath) { + Copy-Item -Path "$customUIPath\*" -Destination $webUIDestination -Recurse -Force + } else { + Write-Host "`r$($symbols.Info) No custom UI found, using default React app." -ForegroundColor Yellow + } } -# --- Build the React (UI) app in the web-interface folder if needed --- -$packageJsonPath = Join-Path $webUIDestination "package.json" -$buildFolder = Join-Path $webUIDestination "build" -if (-not (Test-Path $buildFolder)) { +Run-Step "Remove Existing ReactJS Build Folder (If Exists)" { + if (Test-Path "$webUIDestination\build") { + Remove-Item -Path "$webUIDestination\build" -Recurse -Force + } +} + +# ---------------------- Activate Python Virtual Environment ---------------------- +Run-Step "Activate Virtual Python Environment" { + . "$venvFolder\Scripts\Activate" +} + +# ---------------------- Install Python Dependencies ---------------------- +Run-Step "Install Python Dependencies into Virtual Python Environment" { + if (Test-Path "requirements.txt") { + pip install -q -r requirements.txt 2>&1 | Out-Null + } else { + Write-Host "`r$($symbols.Info) No requirements.txt found, skipping Python packages." -ForegroundColor Yellow + } +} + +# ---------------------- Build React App ---------------------- +Run-Step "Install NPM into ReactJS App" { + $packageJsonPath = Join-Path $webUIDestination "package.json" if (Test-Path $packageJsonPath) { - Write-Output "React UI build not found in '$webUIDestination'. Installing dependencies and building the React app..." Push-Location $webUIDestination - Write-Output " =============================== " - Write-Output " Installing NPM Packages " - Write-Output " =============================== " - npm install --no-fund --audit=false - - # Ensure react-flow-renderer is installed - Write-Output "Installing React Flow..." - npm install reactflow --no-fund --audit=false - - # Install Material UI Library - Write-Output "Installing Material UI Library..." - npm install @mui/material @emotion/react @emotion/styled --no-fund --audit=false - - npm run build + $env:npm_config_loglevel = "silent" + npm install --silent --no-fund --audit=false 2>&1 | Out-Null Pop-Location } - else { - Write-Output "No package.json found in '$webUIDestination'; skipping npm install/build." - } -} else { - Write-Output "React UI build found. Skipping npm install/build." } -# --- Change directory to the virtual environment root --- +Run-Step "Install React Flow into ReactJS App" { + Push-Location $webUIDestination + npm install reactflow --no-fund --audit=false | Out-Null + Pop-Location +} + +Run-Step "Install Material UI Libraries into ReactJS App" { + Push-Location $webUIDestination + $env:npm_config_loglevel = "silent" # Force NPM to be completely silent + npm install --silent @mui/material @mui/icons-material @emotion/react @emotion/styled --no-fund --audit=false 2>&1 | Out-Null + Pop-Location +} + +Run-Step "Build ReactJS App" { + Push-Location $webUIDestination + npm run build | Out-Null + Pop-Location +} + +# ---------------------- Launch Flask Server ---------------------- Push-Location $venvFolder -Write-Output "Current working directory: $(Get-Location)" -$expectedBuildPath = Join-Path (Get-Location) "web-interface\build" -Write-Output "Looking for build folder at: $expectedBuildPath" - -# --- Start the Flask server (server.py is inside Borealis folder) --- -Write-Output " =============================== " -Write-Output " Launching Borealis " -Write-Output " =============================== " -Write-Output "Starting the Flask server..." +Write-Host "`nLaunching Borealis..." -ForegroundColor Green +Write-Host "====================================================================================" +Write-Host "$($symbols.Running) Starting the Python Flask server..." -NoNewline python "Borealis\server.py" - -# --- Return to original directory and deactivate virtual environment --- +Write-Host "`r$($symbols.Success) Borealis Launched Successfully!" Pop-Location -deactivate diff --git a/Rebuild_ReactJS_App.ps1 b/Rebuild_ReactJS_App.ps1 deleted file mode 100644 index 37064f7..0000000 --- a/Rebuild_ReactJS_App.ps1 +++ /dev/null @@ -1,78 +0,0 @@ -# Start_Windows - WebServer.ps1 -# Run this script with: -# Set-ExecutionPolicy Unrestricted -Scope Process; .\Start_Windows -WebServer.ps1 - -Write-Output " =============================== " -Write-Output " Re-Building ReactJS App " -Write-Output " =============================== " - -# --- Define paths --- -$venvFolder = "Borealis-Workflow-Automation-Tool" # Virtual environment root. -$dataSource = "Data" # Contains server.py and optionally WebUI. -$dataDestination = "$venvFolder\Borealis" # Data folder copy destination in the venv. -$customUIPath = "$dataSource\WebUI" # Custom UI folder source in the project root. -$webUIDestination = "$venvFolder\web-interface" # Destination for the React UI in the venv. - -# If a custom UI folder exists at \Data\WebUI, copy its contents over (overwrite defaults). -if (Test-Path $customUIPath) { - Write-Output "Borealis ReactJS Data Found at '$customUIPath'. Overwriting ReactJS App Files..." - Copy-Item -Path "$customUIPath\*" -Destination $webUIDestination -Recurse -Force -} else { - Write-Output "No custom UI folder found at '$customUIPath'. Using default ReactJS app." -} - -# --- Activate virtual environment --- -Write-Output "Activating Virtual Python Environment..." -. "$venvFolder\Scripts\Activate" - -# --- Remove Existing / Previous ReactJS App Build folder --- -if (Test-Path $dataDestination) { - Remove-Item -Recurse -Force $venvFolder\web-interface\build -} - -# --- Build the React (UI) app in the web-interface folder if needed --- -$packageJsonPath = Join-Path $webUIDestination "package.json" -$buildFolder = Join-Path $webUIDestination "build" -if (-not (Test-Path $buildFolder)) { - if (Test-Path $packageJsonPath) { - Write-Output "React UI build not found in '$webUIDestination'. Installing dependencies and building the React app..." - Push-Location $webUIDestination - Write-Output " =============================== " - Write-Output " Installing NPM Packages " - Write-Output " =============================== " - npm install --no-fund --audit=false - - # Ensure react-flow-renderer is installed - Write-Output "Installing React Flow..." - npm install reactflow --no-fund --audit=false - - # Install Material UI Library - Write-Output "Installing Material UI Library..." - npm install @mui/material @emotion/react @emotion/styled --no-fund --audit=false - - npm run build - Pop-Location - } - else { - Write-Output "No package.json found in '$webUIDestination'; skipping npm install/build." - } -} else { - Write-Output "React UI build found. Skipping npm install/build." -} - -# --- Change directory to the virtual environment root --- -Push-Location $venvFolder -Write-Output "Current working directory: $(Get-Location)" -$expectedBuildPath = Join-Path (Get-Location) "web-interface\build" -Write-Output "Looking for build folder at: $expectedBuildPath" - -# --- Start the Flask server (server.py is inside Borealis folder) --- -Write-Output " =============================== " -Write-Output " Launching Borealis " -Write-Output " =============================== " -Write-Output "Starting the Flask server..." -python "Borealis\server.py" - -# --- Return to original directory and deactivate virtual environment --- -Pop-Location -deactivate