diff --git a/Data/WebUI/public/index.html b/Data/WebUI/public/index.html
new file mode 100644
index 0000000..da117a9
--- /dev/null
+++ b/Data/WebUI/public/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Borealis
+
+
+
+
+
+
+
diff --git a/Data/WebUI/src/App.js b/Data/WebUI/src/App.js
index 87576be..a26f26b 100644
--- a/Data/WebUI/src/App.js
+++ b/Data/WebUI/src/App.js
@@ -1,118 +1,139 @@
import React from "react";
import FlowEditor from "./components/FlowEditor";
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
-
import {
- AppBar,
- Toolbar,
- Typography,
- Box,
- Menu,
- MenuItem,
- Button,
- CssBaseline,
- ThemeProvider,
- createTheme
+ AppBar,
+ Toolbar,
+ Typography,
+ Box,
+ Menu,
+ MenuItem,
+ Button,
+ CssBaseline,
+ ThemeProvider,
+ createTheme
} from "@mui/material";
const darkTheme = createTheme({
- palette: {
- mode: "dark",
- background: {
- default: "#121212",
- paper: "#1e1e1e"
- },
- text: {
- primary: "#ffffff"
- }
+ palette: {
+ mode: "dark",
+ background: {
+ default: "#121212",
+ paper: "#1e1e1e"
+ },
+ text: {
+ primary: "#ffffff"
}
+ }
});
export default function App() {
- // Separate menu state for each dropdown
- const [workflowsAnchorEl, setWorkflowsAnchorEl] = React.useState(null);
- const [aboutAnchorEl, setAboutAnchorEl] = React.useState(null);
+ const [workflowsAnchorEl, setWorkflowsAnchorEl] = React.useState(null);
+ const [aboutAnchorEl, setAboutAnchorEl] = React.useState(null);
- const handleWorkflowsMenuOpen = (event) => {
- setWorkflowsAnchorEl(event.currentTarget);
- };
+ const handleWorkflowsMenuOpen = (event) => {
+ setWorkflowsAnchorEl(event.currentTarget);
+ };
- const handleAboutMenuOpen = (event) => {
- setAboutAnchorEl(event.currentTarget);
- };
+ const handleAboutMenuOpen = (event) => {
+ setAboutAnchorEl(event.currentTarget);
+ };
- const handleWorkflowsMenuClose = () => {
- setWorkflowsAnchorEl(null);
- };
+ const handleWorkflowsMenuClose = () => {
+ setWorkflowsAnchorEl(null);
+ };
- const handleAboutMenuClose = () => {
- setAboutAnchorEl(null);
- };
+ const handleAboutMenuClose = () => {
+ setAboutAnchorEl(null);
+ };
- return (
-
-
-
- {/* Top Menu Bar */}
-
-
-
- Borealis - Workflow Automation Tool
-
+ return (
+
+
+ {/*
+ Main container that:
+ - fills 100% viewport height
+ - organizes content with flexbox (vertical)
+ */}
+
+ {/* --- TOP BAR --- */}
+
+
+
+ Borealis - Workflow Automation Tool
+
- {/* Workflows Menu */}
- }
- >
- Workflows
-
-
+ {/* Workflows Menu */}
+ }
+ >
+ Workflows
+
+
- {/* About Menu */}
- }
- >
- About
-
-
-
-
+ {/* About Menu */}
+ }
+ >
+ About
+
+
+
+
- {/* Main Content - React Flow */}
-
- {
- document.getElementById("nodeCount").innerText = count;
- }} />
-
+ {/* --- REACT FLOW EDITOR --- */}
+ {/*
+ flexGrow={1} ⇒ This box expands to fill remaining vertical space
+ overflow="hidden" ⇒ No scroll bars, so React Flow does internal panning
+ mt: 1 ⇒ Add top margin so the gradient starts closer to the AppBar.
+ */}
+
+ {
+ document.getElementById("nodeCount").innerText = count;
+ }}
+ />
+
- {/* Status Bar */}
-
- Nodes: 0 | Update Rate: 500ms | Flask API Server:
- http://127.0.0.1:5000/data
-
-
-
- );
+ {/* --- STATUS BAR at BOTTOM --- */}
+
+ Nodes: 0 | Update Rate: 500ms | Flask API Server:{" "}
+
+ http://127.0.0.1:5000/data/api/nodes
+
+
+
+
+ );
}
diff --git a/Data/WebUI/src/components/FlowEditor.css b/Data/WebUI/src/components/FlowEditor.css
index 576bfe8..fbc6a2f 100644
--- a/Data/WebUI/src/components/FlowEditor.css
+++ b/Data/WebUI/src/components/FlowEditor.css
@@ -14,10 +14,10 @@
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 */
+ background: linear-gradient( to bottom, rgba(9, 44, 68, 0.9) 0%, /* Deep blue at the top */
+ rgba(30, 30, 30, 0) 45%, /* 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 */
+ rgba(9, 44, 68, 0.7) 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 b341d84..4c72a61 100644
--- a/Data/WebUI/src/components/FlowEditor.jsx
+++ b/Data/WebUI/src/components/FlowEditor.jsx
@@ -1,52 +1,68 @@
import React, { useState, useEffect, useCallback } from "react";
import ReactFlow, {
- addEdge,
- Controls,
- Background,
+ addEdge,
+ Controls,
+ Background,
} from "reactflow";
import "reactflow/dist/style.css";
-import "./FlowEditor.css";
+import "./FlowEditor.css";
const fetchNodes = async () => {
- const response = await fetch("/api/workflow");
- return response.json();
+ const response = await fetch("/api/workflow");
+ return response.json();
};
const saveWorkflow = async (workflow) => {
- await fetch("/api/workflow", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(workflow),
- });
+ await fetch("/api/workflow", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(workflow),
+ });
};
export default function FlowEditor() {
- const [elements, setElements] = useState([]);
+ const [elements, setElements] = useState([]);
- useEffect(() => {
- fetchNodes().then((data) => setElements([...data.nodes, ...data.edges]));
- }, []);
+ useEffect(() => {
+ fetchNodes().then((data) => {
+ // Data should contain nodes and edges arrays
+ const newElements = [...data.nodes, ...data.edges];
+ setElements(newElements);
+ });
+ }, []);
- const onConnect = useCallback(
- (params) => {
- const newEdge = { id: `e${params.source}-${params.target}`, ...params };
- setElements((els) => [...els, newEdge]);
- saveWorkflow({ nodes: elements.filter(e => e.type), edges: [...elements.filter(e => !e.type), newEdge] });
- },
- [elements]
- );
+ const onConnect = useCallback(
+ (params) => {
+ const newEdge = { id: `e${params.source}-${params.target}`, ...params };
+ setElements((els) => [...els, newEdge]);
- return (
-
-
-
-
-
-
- );
+ // Separate nodes/edges for saving:
+ const nodes = elements.filter((el) => el.type);
+ const edges = elements.filter((el) => !el.type);
+
+ saveWorkflow({
+ nodes,
+ edges: [...edges, newEdge],
+ });
+ },
+ [elements]
+ );
+
+ return (
+
+
+
+
+
+
+ );
}
diff --git a/Launch-Borealis.sh b/Launch-Borealis.sh
new file mode 100644
index 0000000..d6eb4c2
--- /dev/null
+++ b/Launch-Borealis.sh
@@ -0,0 +1,185 @@
+#!/usr/bin/env bash
+# --------------------------------------------------------------------
+# Deploying Borealis - Workflow Automation Tool
+#
+# This script deploys the Borealis Workflow Automation Tool by:
+# - Detecting the Linux distro and installing required system dependencies.
+# - Creating a Python virtual environment.
+# - Copying server data.
+# - Setting up a React UI application.
+# - Installing Python and Node dependencies.
+# - Building the React app.
+# - Launching the Flask server.
+#
+# Usage:
+# chmod +x deploy_borealis.sh
+# ./deploy_borealis.sh
+# --------------------------------------------------------------------
+
+# ---------------------- Initialization & Visuals ----------------------
+GREEN="\033[0;32m"
+YELLOW="\033[1;33m"
+RED="\033[0;31m"
+RESET="\033[0m"
+CHECKMARK="✅"
+HOURGLASS="⏳"
+CROSSMARK="❌"
+INFO="ℹ️"
+
+# Function to run a step with progress visuals and error checking
+run_step() {
+ local message="$1"
+ shift
+ echo -ne "${HOURGLASS} ${message}... "
+ if "$@"; then
+ echo -e "\r${CHECKMARK} ${message}"
+ else
+ echo -e "\r${CROSSMARK} ${message} - Failed${RESET}"
+ exit 1
+ fi
+}
+
+echo -e "${GREEN}Deploying Borealis - Workflow Automation Tool...${RESET}"
+echo "===================================================================================="
+
+# ---------------------- Detect Linux Distribution ----------------------
+detect_distro() {
+ # This function detects the Linux distribution by sourcing /etc/os-release.
+ if [ -f /etc/os-release ]; then
+ . /etc/os-release
+ DISTRO_ID=$ID
+ else
+ DISTRO_ID="unknown"
+ fi
+ echo -e "${INFO} Detected OS: ${DISTRO_ID}"
+}
+detect_distro
+
+# ---------------------- Install System Dependencies ----------------------
+install_core_dependencies() {
+ # Install required packages based on detected Linux distribution.
+ case "$DISTRO_ID" in
+ ubuntu|debian)
+ sudo apt update -qq
+ sudo apt install -y python3 python3-venv python3-pip nodejs npm git curl
+ ;;
+ rhel|centos|fedora|rocky)
+ # For Fedora and similar distributions, the venv module is built-in so we omit python3-venv.
+ sudo dnf install -y python3 python3-pip nodejs npm git curl
+ ;;
+ arch)
+ sudo pacman -Sy --noconfirm python python-venv python-pip nodejs npm git curl
+ ;;
+ *)
+ echo -e "${RED}${CROSSMARK} Unsupported Linux distribution: ${DISTRO_ID}${RESET}"
+ exit 1
+ ;;
+ esac
+}
+run_step "Install System Dependencies" install_core_dependencies
+
+# ---------------------- Path Setup ----------------------
+# Variables and path definitions
+venvFolder="Borealis-Workflow-Automation-Tool"
+dataSource="Data"
+dataDestination="${venvFolder}/Borealis"
+customUIPath="${dataSource}/WebUI"
+webUIDestination="${venvFolder}/web-interface"
+
+# ---------------------- Create Python Virtual Environment ----------------------
+run_step "Create Virtual Python Environment" bash -c "
+ # Check if virtual environment already exists; if not, create one.
+ if [ ! -f '${venvFolder}/bin/activate' ]; then
+ python3 -m venv '${venvFolder}'
+ fi
+"
+
+# ---------------------- Copy Borealis Data ----------------------
+run_step "Copy Borealis Server Data into Virtual Python Environment" bash -c "
+ # If the Data folder exists, remove any existing server data folder and copy fresh data.
+ if [ -d \"$dataSource\" ]; then
+ rm -rf \"$dataDestination\"
+ mkdir -p \"$dataDestination\"
+ cp -r \"$dataSource/\"* \"$dataDestination\"
+ else
+ echo -e \"\r${INFO} Warning: Data folder not found, skipping copy.${RESET}\"
+ fi
+ true
+"
+
+# ---------------------- React UI Setup ----------------------
+run_step "Create a new ReactJS App in ${webUIDestination}" bash -c "
+ # Create a React app if the destination folder does not exist.
+ if [ ! -d \"$webUIDestination\" ]; then
+ # Set CI=true and add --loglevel=error to suppress funding and audit messages
+ CI=true npx create-react-app \"$webUIDestination\" --silent --use-npm --loglevel=error
+ fi
+"
+
+run_step "Overwrite React App with Custom Files" bash -c "
+ # If custom UI files exist, copy them into the React app folder.
+ if [ -d \"$customUIPath\" ]; then
+ cp -r \"$customUIPath/\"* \"$webUIDestination\"
+ else
+ echo -e \"\r${INFO} No custom UI found, using default React app.${RESET}\"
+ fi
+ true
+"
+
+run_step "Remove Existing React Build (if any)" bash -c "
+ # Remove the build folder if it exists to ensure a fresh build.
+ if [ -d \"$webUIDestination/build\" ]; then
+ rm -rf \"$webUIDestination/build\"
+ fi
+ true
+"
+
+# ---------------------- Activate Python Virtual Environment ----------------------
+# Activate the Python virtual environment for subsequent commands.
+source "${venvFolder}/bin/activate"
+
+# ---------------------- Install Python Dependencies ----------------------
+run_step "Install Python Dependencies into Virtual Python Environment" bash -c "
+ # Install Python packages if a requirements.txt file is present.
+ if [ -f \"requirements.txt\" ]; then
+ pip install -q -r requirements.txt
+ else
+ echo -e \"\r${INFO} No requirements.txt found, skipping Python packages.${RESET}\"
+ fi
+ true
+"
+
+# ---------------------- Install Node Dependencies & Build React UI ----------------------
+run_step "Install React App Dependencies" bash -c "
+ # Install npm dependencies if package.json exists.
+ if [ -f \"$webUIDestination/package.json\" ]; then
+ cd \"$webUIDestination\"
+ # Add --loglevel=error to suppress npm's funding and audit messages
+ npm install --silent --no-fund --audit=false --loglevel=error
+ cd -
+ fi
+"
+
+run_step "Install React Flow and UI Libraries" bash -c "
+ # Install additional React libraries.
+ cd \"$webUIDestination\"
+ npm install reactflow --silent --no-fund --audit=false --loglevel=error
+ npm install --silent @mui/material @mui/icons-material @emotion/react @emotion/styled --no-fund --audit=false --loglevel=error
+ cd -
+"
+
+run_step "Build React App" bash -c "
+ # Build the React app to create production-ready files.
+ cd \"$webUIDestination\"
+ npm run build --silent --loglevel=error
+ cd -
+"
+
+# ---------------------- Launch Flask Server ----------------------
+cd "${venvFolder}"
+echo -e "\n${GREEN}Launching Borealis...${RESET}"
+echo "===================================================================================="
+echo -ne "${HOURGLASS} Starting Flask server... "
+python3 Borealis/server.py
+echo -e "\r${CHECKMARK} Borealis Launched Successfully!"
+
diff --git a/Start_Linux.sh b/Start_Linux.sh
deleted file mode 100644
index 879b809..0000000
--- a/Start_Linux.sh
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/bin/bash
-#
-# Start_Linux.sh
-# -----------------------------------------------
-# Bootstrap Borealis Virtual Python Environment
-# Usage: chmod +x Start_Linux.sh && ./Start_Linux.sh
-#
-
-: '
----------------------------------------------------
-SECTION 1: Script Initialization & Path Definitions
----------------------------------------------------
-This section defines all necessary paths and variables to be used
-throughout the script, ensuring clarity and maintainability.
-'
-
-# Define paths
-venvPath="Borealis-Workflow-Automation-Tool"
-dataSource="Data"
-dataDestination="$venvPath/Borealis"
-
-
-: '
----------------------------------------------------
-SECTION 2: Virtual Environment Creation
----------------------------------------------------
-In this section, we check if the virtual environment already exists
-by verifying the presence of the "activate" script. If it doesn�t
-exist, we create it.
-'
-
-if [ ! -f "$venvPath/bin/activate" ]; then
- echo "Creating virtual environment '$venvPath'..."
- python3 -m venv "$venvPath"
-else
- echo "Virtual environment '$venvPath' already exists."
-fi
-
-
-: '
----------------------------------------------------
-SECTION 3: Copy Data Folder
----------------------------------------------------
-If the "Data" folder is present, we remove any previously copied data
-in the virtual environment�s "Borealis" directory, create a new
-"Borealis" folder, and then copy the "Data" folder into it.
-'
-
-if [ -d "$dataSource" ]; then
- echo "Copying Data folder into virtual environment..."
-
- # Remove old data if it exists
- if [ -d "$dataDestination" ]; then
- rm -rf "$dataDestination"
- fi
-
- # Create the Borealis directory inside the virtual environment
- mkdir -p "$dataDestination"
-
- # Copy Data into the virtual environment under Borealis
- cp -r "$dataSource/"* "$dataDestination/"
-else
- echo "Warning: Data folder not found, skipping copy."
-fi
-
-
-: '
----------------------------------------------------
-SECTION 4: Activate Environment & Install Dependencies
----------------------------------------------------
-This section activates the newly created (or existing) virtual
-environment and installs required dependencies based on the
-"requirements.txt" file if it exists.
-'
-
-echo "Activating virtual environment..."
-source "$venvPath/bin/activate"
-
-if [ -f "requirements.txt" ]; then
- echo "Installing dependencies..."
-
- pip install -q -r requirements.txt
-else
- echo "No requirements.txt found, skipping installation."
-fi
-
-
-: '
----------------------------------------------------
-SECTION 5: Run Main Script
----------------------------------------------------
-Run the main Python script from within the copied Data folder
-inside the virtual environment.
-'
-
-if [ -f "$dataDestination/borealis.py" ]; then
- echo "Starting Borealis Workflow Automation Tool..."
- python "$dataDestination/borealis.py"
-else
- echo "borealis.py not found in $dataDestination. Skipping execution."
-fi
-
-
-: '
----------------------------------------------------
-SECTION 6: Deactivate Environment
----------------------------------------------------
-After the main script completes execution, the virtual environment
-is deactivated.
-'
-
-echo "Deactivating virtual environment..."
-deactivate