Skip to content

Commit 50c759e

Browse files
authored
Merge pull request #15 from pnnl/electron-upgrade
Electron upgrade
2 parents 9876afe + 019bed6 commit 50c759e

15 files changed

Lines changed: 527 additions & 143 deletions

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ Dockerfile
3434
*.njsproj
3535
*.sln
3636
*.sw?
37+
38+
# Electron / PyInstaller build outputs (build/ at repo root holds icons and IS tracked)
39+
release/
40+
local-server/build/

Dockerfile.backend

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,35 @@ RUN apt-get update \
1313

1414
# Install server deps (no pyinstaller). --prerelease=allow: cim-graph is 0.4.3a10.
1515
COPY local-server/requirements-server.txt ./requirements-server.txt
16-
RUN uv pip install --system --prerelease=allow -r requirements-server.txt \
17-
&& uv pip install --system glm
16+
RUN uv pip install --system --prerelease=allow -r requirements-server.txt
1817

19-
# CIM-Builder — installed without deps (it requires an older cim-graph).
20-
RUN git clone -b develop https://github.com/PNNL-CIM-Tools/CIM-Builder.git /tmp/CIM-Builder \
21-
&& uv pip install --system --no-deps /tmp/CIM-Builder
18+
# ---- Nim toolchain: build the glm parser into a Python wheel ----------------
19+
# glm (https://github.com/itsMando/glm) is a Nim project that exposes a Python
20+
# binary extension (lib/_glm.so). It needs Nim >= 2.0, a C compiler, and
21+
# choosenim to fetch the toolchain (Debian's packaged Nim is too old).
22+
RUN apt-get update \
23+
&& apt-get install -y --no-install-recommends build-essential curl xz-utils \
24+
&& rm -rf /var/lib/apt/lists/*
25+
26+
ENV CHOOSENIM_NO_ANALYTICS=1
27+
RUN curl -sSf https://nim-lang.org/choosenim/init.sh | sh -s -- -y
28+
ENV PATH="/root/.nimble/bin:${PATH}"
29+
30+
# setup.py builds the binary (non-pure) wheel; these are its build-backend deps.
31+
RUN uv pip install --system setuptools wheel
32+
33+
# Clone the glm fork and build the Nim shared library (lib/_glm.so), then install
34+
# straight from source into the system site-packages. setup.py copies the freshly
35+
# built _glm.so into the package and tags the wheel for whatever platform we are
36+
# building on, so this stays arch-agnostic (x86_64, arm64, ...) — unlike `nimble
37+
# package`, which hard-codes a manylinux2014_x86_64 tag. The install carries over
38+
# to the runtime stage via the /usr/local copy below.
39+
RUN git clone https://github.com/itsMando/glm.git /tmp/glm \
40+
&& cd /tmp/glm \
41+
&& nimble install -y --depsOnly \
42+
&& nimble release \
43+
&& uv pip install --system --no-build-isolation /tmp/glm \
44+
&& rm -rf /tmp/glm
2245

2346
# ---- runtime: slim image with only the installed packages + app ------------
2447
FROM python:3.12-slim

README.md

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ cd GLIMPSE/local-server/
6868
**Option A: UV (Recommended)**
6969

7070
```bash
71-
uv add -r requirements.txt --prerelease=allow
71+
uv sync
7272
```
7373

7474
**Option B: VENV**
@@ -108,35 +108,7 @@ If you used VENV or Conda, install requirements:
108108
pip install -r requirements.txt
109109
```
110110

111-
### Step 4: Install CIM-Builder (Required)
112-
113-
CIM-Builder is needed to export modified CIM/XML files.
114-
115-
In `GLIMPSE/local-server/`, clone CIM-Builder:
116-
117-
```bash
118-
git clone -b develop https://github.com/PNNL-CIM-Tools/CIM-Builder.git
119-
```
120-
121-
Navigate to the CIM-Builder directory and install it (without dependencies, as it requires an older version of cim-graph):
122-
123-
```bash
124-
cd CIM-Builder
125-
```
126-
127-
**With PIP:**
128-
129-
```bash
130-
python -m pip install . --no-deps
131-
```
132-
133-
**With UV:**
134-
135-
```bash
136-
uv pip install . --no-deps
137-
```
138-
139-
### Step 5: Install GLM Parser
111+
### Step 4: Install GLM Parser
140112

141113
#### Standard Installation (Windows, Linux, Intel/AMD Mac)
142114

@@ -156,14 +128,14 @@ uv pip install glm
156128

157129
You'll need to build the GLM parser from source using Nim.
158130

159-
Clone the GLM parser:
131+
Clone the glm parser repository i forked:
160132

161133
```bash
162134
cd GLIMPSE/local-server/
163135
```
164136

165137
```bash
166-
git clone https://github.com/NREL/glm.git
138+
git cone https://github.com/itsMando/glm.git
167139
```
168140

169141
```bash
@@ -173,29 +145,26 @@ cd glm
173145
Build the parser (ensure [Nim](https://nim-lang.org/) is installed and in your PATH):
174146

175147
```bash
176-
nim c -d:release --opt:size --passC:"-flto" --passL:"-flto" --app:lib --out:lib/_glm.so src/glm.nim
148+
nimble -v
177149
```
178150

179-
Create a wheel:
180-
181151
```bash
182-
python setup.py bdist_wheel
183-
# or
184-
python3 setup.py bdist_wheel
152+
nimble package
153+
nimble release
185154
```
186155

187-
Install the wheel from `dist/` folder:
156+
Install the python binary distributable from `dist/` folder:
188157

189158
**With PIP:**
190159

191160
```bash
192-
pip install dist/<whl-filename>.whl
161+
pip install dist/*.whl
193162
```
194163

195164
**With UV:**
196165

197166
```bash
198-
uv pip install dist/<whl-filename>.whl
167+
uv pip install dist/*.whl
199168
```
200169

201170
## Start GLIMPSE
@@ -208,6 +177,43 @@ npm run dev
208177

209178
The application will start in development mode. Open your browser and navigate to the provided local address (typically `http://localhost:5173/`) to access GLIMPSE.
210179

180+
## Desktop App (Electron)
181+
182+
GLIMPSE can also run as a standalone desktop application. The Electron shell starts the bundled local server automatically on launch and shuts it down (including all child processes) when the window is closed — no terminal or browser needed.
183+
184+
> [!NOTE]
185+
> These steps assume you have completed the **Build from Source** setup above (Node dependencies and the Python environment for `local-server/`). The Python environment must include `pyinstaller`, which is listed in both `local-server/requirements.txt` and `local-server/pyproject.toml`.
186+
187+
### Develop in a Desktop Window
188+
189+
Runs the Python backend, the Vite dev server, and Electron together (with hot reload). Closing the Electron window stops all three:
190+
191+
```bash
192+
npm run electron:dev
193+
```
194+
195+
### Build an Installer
196+
197+
Installers are built **on and for the OS you are running** (electron-builder cannot cross-compile, e.g. a Windows installer must be built on Windows):
198+
199+
```bash
200+
npm run dist # build for the current OS
201+
npm run dist:linux # AppImage + .deb (run on Linux)
202+
npm run dist:win # NSIS installer (run on Windows)
203+
npm run dist:mac # .dmg (run on macOS)
204+
```
205+
206+
Each `dist` command runs three steps:
207+
208+
1. `vite build` — bundles the React frontend into `dist/`
209+
2. `pyinstaller server.spec` — freezes the Python backend (with its Python runtime) into `local-server/dist/server/`
210+
3. `electron-builder` — packages both into an installer in `release/`
211+
212+
The finished installer is written to the `release/` directory. The installed app needs no Node or Python on the target machine — the backend is fully self-contained.
213+
214+
> [!TIP]
215+
> If `pyinstaller` is not on your PATH, activate the Python environment you created for `local-server/` first (or, with UV, run `uv run pyinstaller server.spec --noconfirm` inside `local-server/`).
216+
211217
## Run with Docker
212218

213219
The repository ships with a [Docker Compose](https://docs.docker.com/compose/) setup that builds and runs GLIMPSE as two containers — the React frontend (served by nginx) and the Flask + SocketIO backend — so you don't need to install Node, Python, or any of the plugins yourself.

build/icon.png

91.2 KB
Loading

electron-builder.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# electron-builder configuration for GLIMPSE desktop installers.
2+
#
3+
# Build the renderer (vite build) and the backend (pyinstaller) first —
4+
# the `dist`/`dist:*` npm scripts chain all three steps.
5+
#
6+
# Installers can only be built on (or for) the OS you are running on:
7+
# npm run dist:linux -> AppImage + .deb (build on Linux)
8+
# npm run dist:win -> NSIS installer (build on Windows)
9+
# npm run dist:mac -> .dmg (build on macOS)
10+
11+
appId: gov.pnnl.glimpse
12+
productName: GLIMPSE
13+
copyright: Copyright © 2026 Pacific Northwest National Laboratory
14+
15+
directories:
16+
output: release
17+
buildResources: build
18+
19+
# The frontend is fully bundled by Vite, so node_modules are not needed at runtime.
20+
files:
21+
- dist/**
22+
- electron/**
23+
- package.json
24+
- "!node_modules/**"
25+
26+
# PyInstaller onedir output for the Flask/SocketIO backend. Packaged into
27+
# <app>/resources/server/ and spawned by electron/main.js on startup.
28+
extraResources:
29+
- from: local-server/dist/server
30+
to: server
31+
32+
asar: true
33+
34+
win:
35+
target:
36+
- nsis
37+
38+
nsis:
39+
oneClick: false
40+
allowToChangeInstallationDirectory: true
41+
42+
mac:
43+
target:
44+
- dmg
45+
category: public.app-category.utilities
46+
47+
linux:
48+
target:
49+
- AppImage
50+
- deb
51+
category: Science
52+
synopsis: Power grid model visualization tool

0 commit comments

Comments
 (0)