Second Commit
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +0,0 @@ | ||||
| .vs/ | ||||
| Borealis-Workflow-Automation-Tool/ | ||||
| @@ -1,43 +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" /> | ||||
|     <!-- | ||||
|       manifest.json provides metadata used when your web app is installed on a | ||||
|       user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ | ||||
|     --> | ||||
|     <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> | ||||
|     <!-- | ||||
|       Notice the use of %PUBLIC_URL% in the tags above. | ||||
|       It will be replaced with the URL of the `public` folder during the build. | ||||
|       Only files inside the `public` folder can be referenced from the HTML. | ||||
|  | ||||
|       Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will | ||||
|       work correctly both with client-side routing and a non-root public URL. | ||||
|       Learn how to configure a non-root public URL by running `npm run build`. | ||||
|     --> | ||||
|     <title>Borealis</title> | ||||
|   </head> | ||||
|   <body> | ||||
|     <noscript>You need to enable JavaScript to run this app.</noscript> | ||||
|     <div id="root"></div> | ||||
|     <!-- | ||||
|       This HTML file is a template. | ||||
|       If you open it directly in the browser, you will see an empty page. | ||||
|  | ||||
|       You can add webfonts, meta tags, or analytics to this file. | ||||
|       The build step will place the bundled scripts into the <body> tag. | ||||
|  | ||||
|       To begin the development, run `npm start` or `yarn start`. | ||||
|       To create a production bundle, use `npm run build` or `yarn build`. | ||||
|     --> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,139 +0,0 @@ | ||||
| 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 | ||||
| } from "@mui/material"; | ||||
|  | ||||
| const darkTheme = createTheme({ | ||||
|   palette: { | ||||
|     mode: "dark", | ||||
|     background: { | ||||
|       default: "#121212", | ||||
|       paper: "#1e1e1e" | ||||
|     }, | ||||
|     text: { | ||||
|       primary: "#ffffff" | ||||
|     } | ||||
|   } | ||||
| }); | ||||
|  | ||||
| export default function App() { | ||||
|   const [workflowsAnchorEl, setWorkflowsAnchorEl] = React.useState(null); | ||||
|   const [aboutAnchorEl, setAboutAnchorEl] = React.useState(null); | ||||
|  | ||||
|   const handleWorkflowsMenuOpen = (event) => { | ||||
|     setWorkflowsAnchorEl(event.currentTarget); | ||||
|   }; | ||||
|  | ||||
|   const handleAboutMenuOpen = (event) => { | ||||
|     setAboutAnchorEl(event.currentTarget); | ||||
|   }; | ||||
|  | ||||
|   const handleWorkflowsMenuClose = () => { | ||||
|     setWorkflowsAnchorEl(null); | ||||
|   }; | ||||
|  | ||||
|   const handleAboutMenuClose = () => { | ||||
|     setAboutAnchorEl(null); | ||||
|   }; | ||||
|  | ||||
|   return ( | ||||
|     <ThemeProvider theme={darkTheme}> | ||||
|       <CssBaseline /> | ||||
|       {/* | ||||
|         Main container that: | ||||
|           - fills 100% viewport height | ||||
|           - organizes content with flexbox (vertical) | ||||
|       */} | ||||
|       <Box display="flex" flexDirection="column" height="100vh"> | ||||
|         {/* --- TOP BAR --- */} | ||||
|         <AppBar position="static" sx={{ bgcolor: "#092c44" }}> | ||||
|           <Toolbar> | ||||
|             <Typography variant="h6" sx={{ flexGrow: 1 }}> | ||||
|               Borealis - Workflow Automation Tool | ||||
|             </Typography> | ||||
|  | ||||
|             {/* Workflows Menu */} | ||||
|             <Button | ||||
|               color="inherit" | ||||
|               onClick={handleWorkflowsMenuOpen} | ||||
|               endIcon={<KeyboardArrowDownIcon />} | ||||
|             > | ||||
|               Workflows | ||||
|             </Button> | ||||
|             <Menu | ||||
|               anchorEl={workflowsAnchorEl} | ||||
|               open={Boolean(workflowsAnchorEl)} | ||||
|               onClose={handleWorkflowsMenuClose} | ||||
|             > | ||||
|               <MenuItem onClick={handleWorkflowsMenuClose}>Save Workflow</MenuItem> | ||||
|               <MenuItem onClick={handleWorkflowsMenuClose}>Load Workflow</MenuItem> | ||||
|               <MenuItem onClick={handleWorkflowsMenuClose}>Close Workflow</MenuItem> | ||||
|             </Menu> | ||||
|  | ||||
|             {/* About Menu */} | ||||
|             <Button | ||||
|               color="inherit" | ||||
|               onClick={handleAboutMenuOpen} | ||||
|               endIcon={<KeyboardArrowDownIcon />} | ||||
|             > | ||||
|               About | ||||
|             </Button> | ||||
|             <Menu | ||||
|               anchorEl={aboutAnchorEl} | ||||
|               open={Boolean(aboutAnchorEl)} | ||||
|               onClose={handleAboutMenuClose} | ||||
|             > | ||||
|               <MenuItem onClick={handleAboutMenuClose}>Gitea Project</MenuItem> | ||||
|               <MenuItem onClick={handleAboutMenuClose}>Credits</MenuItem> | ||||
|             </Menu> | ||||
|           </Toolbar> | ||||
|         </AppBar> | ||||
|  | ||||
|         {/* --- 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. | ||||
|         */} | ||||
|         <Box flexGrow={1} overflow="hidden" sx={{ mt: 0 }}> | ||||
|           <FlowEditor | ||||
|             updateNodeCount={(count) => { | ||||
|               document.getElementById("nodeCount").innerText = count; | ||||
|             }} | ||||
|           /> | ||||
|         </Box> | ||||
|  | ||||
|         {/* --- STATUS BAR at BOTTOM --- */} | ||||
|         <Box | ||||
|           component="footer" | ||||
|           sx={{ | ||||
|             bgcolor: "#1e1e1e", | ||||
|             color: "white", | ||||
|             px: 2, | ||||
|             py: 1, | ||||
|             textAlign: "left" | ||||
|           }} | ||||
|         > | ||||
|           <b>Nodes</b>: <span id="nodeCount">0</span> | <b>Update Rate</b>: 500ms | <b>Flask API Server:</b>{" "} | ||||
|           <a | ||||
|             href="http://127.0.0.1:5000/api/nodes" | ||||
|             style={{ color: "#3c78b4" }} | ||||
|           > | ||||
|             http://127.0.0.1:5000/data/api/nodes | ||||
|           </a> | ||||
|         </Box> | ||||
|       </Box> | ||||
|     </ThemeProvider> | ||||
|   ); | ||||
| } | ||||
| @@ -1,23 +0,0 @@ | ||||
| /* FlowEditor background container */ | ||||
| .flow-editor-container { | ||||
|     position: relative; | ||||
|     width: 100vw; | ||||
|     height: 100vh; | ||||
| } | ||||
|  | ||||
|     /* Blue 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.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.7) 100% /* Deep blue at the bottom */ | ||||
|         ); | ||||
|         z-index: -1; /* Ensures it stays behind the React Flow elements */ | ||||
|     } | ||||
| @@ -1,68 +0,0 @@ | ||||
| import React, { useState, useEffect, useCallback } from "react"; | ||||
| import ReactFlow, { | ||||
|   addEdge, | ||||
|   Controls, | ||||
|   Background, | ||||
| } from "reactflow"; | ||||
| import "reactflow/dist/style.css"; | ||||
| import "./FlowEditor.css"; | ||||
|  | ||||
| const fetchNodes = async () => { | ||||
|   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), | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export default function FlowEditor() { | ||||
|   const [elements, setElements] = useState([]); | ||||
|  | ||||
|   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]); | ||||
|  | ||||
|       // 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 ( | ||||
|     <div className="flow-editor-container"> | ||||
|       <ReactFlow | ||||
|         proOptions={{ hideAttribution: true }}  // Remove the React Flow watermark | ||||
|         elements={elements} | ||||
|         onConnect={onConnect} | ||||
|       > | ||||
|         <Controls /> | ||||
|         <Background | ||||
|           variant="lines" | ||||
|           gap={100} | ||||
|           size={1} | ||||
|           color="rgba(255, 255, 255, 0.2)" // White grid lines at 20% opacity | ||||
|         /> | ||||
|       </ReactFlow> | ||||
|     </div> | ||||
|   ); | ||||
| } | ||||
							
								
								
									
										131
									
								
								Data/server.py
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								Data/server.py
									
									
									
									
									
								
							| @@ -1,131 +0,0 @@ | ||||
| from flask import Flask, send_from_directory, jsonify, request, abort | ||||
| import os | ||||
| import importlib | ||||
| import inspect | ||||
| import uuid | ||||
| from OdenGraphQt import BaseNode | ||||
|  | ||||
| # Determine the absolute path for the React build folder | ||||
| build_folder = os.path.join(os.getcwd(), "web-interface", "build") | ||||
| if not os.path.exists(build_folder): | ||||
|     print("WARNING: web-interface build folder not found. Please build your React app.") | ||||
|  | ||||
| app = Flask(__name__, static_folder=build_folder, static_url_path="/") | ||||
|  | ||||
| # Directory where nodes are stored | ||||
| NODES_PACKAGE = "Nodes" | ||||
|  | ||||
| # In-memory workflow storage | ||||
| workflow_data = { | ||||
|     "nodes": [], | ||||
|     "edges": []  # Store connections separately | ||||
| } | ||||
|  | ||||
| def import_nodes_from_folder(package_name): | ||||
|     """Dynamically import node classes from the given package and list them.""" | ||||
|     nodes_by_category = {} | ||||
|     package = importlib.import_module(package_name) | ||||
|     package_path = package.__path__[0] | ||||
|  | ||||
|     for root, _, files in os.walk(package_path): | ||||
|         rel_path = os.path.relpath(root, package_path).replace(os.sep, ".") | ||||
|         module_prefix = f"{package_name}.{rel_path}" if rel_path != "." else package_name | ||||
|         category_name = os.path.basename(root) | ||||
|  | ||||
|         for file in files: | ||||
|             if file.endswith(".py") and file != "__init__.py": | ||||
|                 module_name = f"{module_prefix}.{file[:-3]}" | ||||
|                 try: | ||||
|                     module = importlib.import_module(module_name) | ||||
|                     for name, obj in inspect.getmembers(module, inspect.isclass): | ||||
|                         if issubclass(obj, BaseNode) and obj.__module__ == module.__name__: | ||||
|                             if category_name not in nodes_by_category: | ||||
|                                 nodes_by_category[category_name] = [] | ||||
|                             nodes_by_category[category_name].append(obj.NODE_NAME) | ||||
|                 except Exception as e: | ||||
|                     print(f"Failed to import {module_name}: {e}") | ||||
|  | ||||
|     return nodes_by_category | ||||
|  | ||||
| @app.route("/") | ||||
| def serve_frontend(): | ||||
|     """Serve the React app.""" | ||||
|     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 "<h1>Borealis React App Code Not Found</h1><p>Please re-deploy Borealis Workflow Automation Tool</p>", 404 | ||||
|  | ||||
| @app.route("/api/nodes", methods=["GET"]) | ||||
| def get_available_nodes(): | ||||
|     """Return available node types.""" | ||||
|     nodes = import_nodes_from_folder(NODES_PACKAGE) | ||||
|     return jsonify(nodes) | ||||
|  | ||||
| @app.route("/api/workflow", methods=["GET", "POST"]) | ||||
| def handle_workflow(): | ||||
|     """Retrieve or update the workflow.""" | ||||
|     global workflow_data | ||||
|     if request.method == "GET": | ||||
|         return jsonify(workflow_data) | ||||
|     elif request.method == "POST": | ||||
|         data = request.get_json() | ||||
|         if not data: | ||||
|             abort(400, "Invalid workflow data") | ||||
|         workflow_data = data | ||||
|         return jsonify({"status": "success", "workflow": workflow_data}) | ||||
|  | ||||
| @app.route("/api/node", methods=["POST"]) | ||||
| def create_node(): | ||||
|     """Create a new node with a unique UUID.""" | ||||
|     data = request.get_json() | ||||
|     if not data or "nodeType" not in data: | ||||
|         abort(400, "Invalid node data") | ||||
|  | ||||
|     node_id = str(uuid.uuid4())  # Generate a unique ID | ||||
|     node = { | ||||
|         "id": node_id, | ||||
|         "type": data["nodeType"], | ||||
|         "position": data.get("position", {"x": 100, "y": 100}), | ||||
|         "properties": data.get("properties", {}) | ||||
|     } | ||||
|     workflow_data["nodes"].append(node) | ||||
|     return jsonify({"status": "success", "node": node}) | ||||
|  | ||||
| @app.route("/api/node/<string:node_id>", methods=["PUT", "DELETE"]) | ||||
| def modify_node(node_id): | ||||
|     """Update or delete a node.""" | ||||
|     global workflow_data | ||||
|     if request.method == "PUT": | ||||
|         data = request.get_json() | ||||
|         for node in workflow_data["nodes"]: | ||||
|             if node["id"] == node_id: | ||||
|                 node["position"] = data.get("position", node["position"]) | ||||
|                 node["properties"] = data.get("properties", node["properties"]) | ||||
|                 return jsonify({"status": "success", "node": node}) | ||||
|         abort(404, "Node not found") | ||||
|  | ||||
|     elif request.method == "DELETE": | ||||
|         workflow_data["nodes"] = [n for n in workflow_data["nodes"] if n["id"] != node_id] | ||||
|         return jsonify({"status": "success", "deletedNode": node_id}) | ||||
|  | ||||
| @app.route("/api/edge", methods=["POST"]) | ||||
| def create_edge(): | ||||
|     """Create a new connection (edge) between nodes.""" | ||||
|     data = request.get_json() | ||||
|     if not data or "source" not in data or "target" not in data: | ||||
|         abort(400, "Invalid edge data") | ||||
|  | ||||
|     edge_id = str(uuid.uuid4()) | ||||
|     edge = {"id": edge_id, "source": data["source"], "target": data["target"]} | ||||
|     workflow_data["edges"].append(edge) | ||||
|     return jsonify({"status": "success", "edge": edge}) | ||||
|  | ||||
| @app.route("/api/edge/<string:edge_id>", methods=["DELETE"]) | ||||
| def delete_edge(edge_id): | ||||
|     """Delete an edge by ID.""" | ||||
|     global workflow_data | ||||
|     workflow_data["edges"] = [e for e in workflow_data["edges"] if e["id"] != edge_id] | ||||
|     return jsonify({"status": "success", "deletedEdge": edge_id}) | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     app.run(host="0.0.0.0", port=5000, debug=False) | ||||
| @@ -1,149 +0,0 @@ | ||||
| # Start_Windows - WebServer.ps1 | ||||
| # Run this script with: | ||||
| #   Set-ExecutionPolicy Unrestricted -Scope Process; .\Start_Windows -WebServer.ps1 | ||||
|  | ||||
| # ---------------------- Initialization & Visuals ---------------------- | ||||
| $symbols = @{ | ||||
|     Success = [char]0x2705 | ||||
|     Running = [char]0x23F3 | ||||
|     Fail    = [char]0x274C | ||||
|     Info    = [char]0x2139 | ||||
| } | ||||
|  | ||||
| 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-Host "`r$($symbols.Fail) Node.js is not installed. Please install Node.js and try again." -ForegroundColor Red | ||||
|     exit 1 | ||||
| } | ||||
|  | ||||
| # ---------------------- 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" { | ||||
|     if (!(Test-Path "$venvFolder\Scripts\Activate")) { | ||||
|         python -m venv $venvFolder | Out-Null | ||||
|     } | ||||
| } | ||||
|  | ||||
| # ---------------------- 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 | ||||
|     } | ||||
| } | ||||
|  | ||||
| # ---------------------- React UI Deployment ---------------------- | ||||
| Run-Step "Create a new ReactJS App in $webUIDestination" { | ||||
|     if (-not (Test-Path $webUIDestination)) { | ||||
|         npx create-react-app $webUIDestination | Out-Null | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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 | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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) { | ||||
|         Push-Location $webUIDestination | ||||
|         $env:npm_config_loglevel = "silent" | ||||
|         npm install --silent --no-fund --audit=false 2>&1 | Out-Null | ||||
|         Pop-Location | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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-Host "`nLaunching Borealis..." -ForegroundColor Green | ||||
| Write-Host "====================================================================================" | ||||
| Write-Host "$($symbols.Running) Starting the Python Flask server..." -NoNewline | ||||
| python "Borealis\server.py" | ||||
| Write-Host "`r$($symbols.Success) Borealis Launched Successfully!" | ||||
| Pop-Location | ||||
| @@ -1,185 +0,0 @@ | ||||
| #!/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!" | ||||
|  | ||||
| @@ -1,21 +0,0 @@ | ||||
| # PyTorch and related deep learning libraries (GPU Supported Functionality) | ||||
| torch --index-url https://download.pytorch.org/whl/cu121 | ||||
| torchvision --index-url https://download.pytorch.org/whl/cu121 | ||||
| torchaudio --index-url https://download.pytorch.org/whl/cu121 | ||||
|  | ||||
| # Flask for API handling | ||||
| Flask | ||||
| requests | ||||
|  | ||||
| # GUI-related dependencies (Qt for GUI components) | ||||
| Qt.py | ||||
| qtpy | ||||
| OdenGraphQt | ||||
| PyQt5 | ||||
|  | ||||
| # Computer Vision & OCR dependencies | ||||
| numpy                  # Numerical operations | ||||
| opencv-python          # Computer vision processing | ||||
| pytesseract            # OCR engine | ||||
| easyocr                # Deep-learning-based OCR | ||||
| Pillow                 # Image processing | ||||
		Reference in New Issue
	
	Block a user