Skip to content

Latest commit

 

History

History
267 lines (198 loc) · 8.97 KB

File metadata and controls

267 lines (198 loc) · 8.97 KB

r.avaflow · web-app

Angular 15 + NestJS 9 full-stack application that drives the r.avaflow simulation engine.

Frontend (src/) and backend (server/) ship together as a single Docker image exposing a browser UI on port 3000.

Angular NestJS Ant Design Socket.IO Playwright Node

🇷🇺 Русская версия · ⬅ Back to top-level README


Table of contents


At a glance

Layer Technology
Frontend Angular 15.2 · ng-zorro-antd 15 (Ant Design) · TypeScript 4.8 · SCSS
Backend NestJS 9 · Express · Socket.IO 4.6 · Multer · Archiver
Real-time WebSocket (Socket.IO) — simulation logs, status, events
Testing Playwright (E2E) · Karma + Jasmine (Angular unit) · Jest (NestJS)
i18n @ngx-translate/core — English, Russian
Runtime Node ≥ 18.10 · Docker (to actually run simulations)

The NestJS backend serves the compiled Angular bundle via @nestjs/serve-static, so in production everything lives behind a single port (:3000). No reverse proxy, no separate frontend host.


Directory layout

web-app/
├── src/                              # Angular SPA
│   ├── app/
│   │   ├── home/                     # Main feature module
│   │   │   ├── simulation-wizard/    # 7-step parameter form
│   │   │   ├── simulation-status/    # Live log panel, CPU/RAM gauges
│   │   │   ├── simulation-results/   # Image grid, file browser, ZIP export
│   │   │   └── project-form/         # Project CRUD sidebar
│   │   ├── core/services/            # ThemeService, WebSocketService
│   │   └── shared/                   # Shared components
│   ├── assets/i18n/                  # en.json, ru.json translations
│   └── environments/                 # environment.ts / .prod.ts / .web.ts
│
├── server/                           # NestJS backend
│   └── src/
│       ├── app.controller.ts         # REST: /projects, /run, /upload, /health
│       ├── app.gateway.ts            # WebSocket: simulationLog, simulationDone, ...
│       ├── app.service.ts            # Business logic: script gen, engine spawn
│       └── storage-options.ts        # Multer disk-storage config
│
├── e2e/                              # Playwright specs
│   ├── simulation-wizard.spec.ts
│   ├── simulation-status.spec.ts
│   ├── project-management.spec.ts
│   └── playwright.config.ts
│
├── Dockerfile                        # Local build image
├── PARAMETER_REFERENCE.md            # Every parameter · tooltip · validation rule
├── FORM_COMPARISON_REPORT.md         # Coverage vs. original r.avaflow form
├── KOLKA_CALIBRATION_REPORT.md       # Ice-rock avalanche calibration recipe
└── QA_REPORT.md                      # Bug-fix history

Quick start

Prerequisites

  • Node.js ≥ 18.10 (tested against 18 / 20)
  • npm (bundled with Node)
  • Docker — required to actually run simulations (the backend spawns a GRASS-GIS container)

Install

cd web-app
npm install
npm install --prefix server

Develop (hot-reload, both processes)

npm run start:dev

Two processes start concurrently:

Process URL Purpose
NestJS backend http://localhost:3000 /api REST + WebSocket
Angular dev server http://localhost:4200 SPA with hot-reload, proxies to :3000

Open http://localhost:4200 in your browser.

Run backend or frontend alone

npm --prefix server run start:dev    # backend only
npm run ng:serve                     # frontend only (-c web profile)

Build & deploy

Production build

npm run web:build                    # Angular → dist/
npm --prefix server run build        # NestJS → server/dist/

In production, NestJS serves dist/ statically — a single container on port 3000 is enough.

Docker (from repository root)

docker build -f Dockerfile.prod -t r-avaflow:webapp .
docker run -p 3000:3000 \
  -e OMP_NUM_THREADS=8 \
  -v avaflow-data:/data/projects \
  r-avaflow:webapp

Pre-built image: ghcr.io/kostyanp95/r-avaflow:webapp-latest.


Environment variables

Variable Default Purpose
PORT 3000 HTTP + WebSocket port
NODE_ENV production enables optimizations
AVAFLOW_PROJECTS_PATH projects/ Where per-project data is stored (mount this as a volume)
OMP_NUM_THREADS (auto) CPU thread count for the OpenMP-parallelized core

Testing

Angular unit tests — Karma + Jasmine

npm test               # headless, single run
npm run test:watch     # watch mode

NestJS unit + e2e — Jest

npm --prefix server test
npm --prefix server run test:e2e

Full end-to-end — Playwright

npm run e2e            # builds prod bundle, then runs e2e/*.spec.ts
npm run e2e:show-trace # inspect the latest trace

E2E specs boot a real NestJS + Angular instance and walk through the 7-step wizard, file uploads, live simulation status and project CRUD.

Lint

npm run lint

HTTP API

All REST endpoints are mounted under /api, except the /health liveness probe.

Method Path Purpose
GET /health Liveness probe (no /api prefix)
GET /api/projects List projects
GET /api/project?projectName=… Project config + file tree
POST /api/project Create project
DELETE /api/project/:name Delete project
POST /api/upload Raster upload (Multer: field files, body projectName)
POST /api/run Start simulation (spawns engine process)
POST /api/run/stop Kill running simulation
GET /api/project/:name/download Stream project ZIP (via archiver)

WebSocket events

Socket.IO connects to the same origin (no separate port). Server-emitted events:

Event Payload Fired when
simulationLog { projectName, line } Every stdout / stderr line from the engine
simulationDone { projectName, exitStatus } Engine process exits
filesUploaded { projectName, files } Upload completes
projectData { projectName, config, files } Project state refresh

How it works end-to-end

Browser (Angular SPA)
   │   HTTP /api/upload, /api/run, /api/projects, …
   │   WebSocket: simulationLog / simulationDone
   ▼
NestJS (port 3000)
   │   - Serves Angular bundle (@nestjs/serve-static)
   │   - REST controllers, WebSocket gateway
   │   - Generates r.avaflow shell script from wizard parameters
   │   - Spawns `docker run` with mounted project volume
   ▼
r.avaflow engine (GRASS GIS + C core)
   │   - Reads rasters + param.txt
   │   - OpenMP-parallelized NOC-TVD time loop
   │   - Writes outputs (ASCII rasters, PNG, GIF, CSV)
   ▼
Results viewer (back in the browser)

The wizard collects parameters, the backend diffs them against defaults and emits only what changed into the generated script (see PARAMETER_REFERENCE.md). Live logs stream over WebSocket while the simulation runs; on exit, the results viewer picks up generated PNGs/GIFs from the project volume.


Reports & references


License

Inherits GNU GPLv2+ from the r.avaflow core — see the top-level README.