Angular Dashboard
sql-dashboard/ is the front-end for the SQL Performance Lab. It is an Angular 21 SPA that visualises all 6 benchmark scenarios โ showing timing, row counts, and the speedup factor for every bad-vs-fixed stored procedure pair.
What It Shows
| Area | Detail |
|---|---|
| Scenario cards | One card per scenario โ run individually and see bad/fixed timing side-by-side |
| Run All | Fires all 6 scenarios in a single request and populates every card at once |
| Summary table | Sortable overview of all 6 results: bad time, fixed time, speedup factor, row count |
| Health indicator | Live status badge in the toolbar that hits GET /health on the API |
Running Locally (dev server)
The dev server proxies /health and /scenarios to the API running in Kubernetes so there are no CORS issues.
# The k8s API must already be running at localhost:30080
cd sql-dashboard
npm install # first time only
npm start # ng serve on http://localhost:4200
Open http://localhost:4200 in your browser.
API must be up first
The dev server proxy forwards API calls to http://localhost:30080. Make sure the Kubernetes stack is running (terraform apply) before starting the dev server, or the health check will show "API unreachable".
The proxy is configured in proxy.conf.json:
{
"/scenarios": { "target": "http://localhost:30080", ... },
"/health": { "target": "http://localhost:30080", ... }
}
Kubernetes Deployment
terraform apply builds the Docker image and deploys the dashboard alongside the API. Once up, open:
How it works in-cluster
Browser โ NodePort 30081 โ nginx pod
โโ GET / โ serves index.html (SPA)
โโ GET /health โ proxy_pass โ sql-demos-api:80
โโ GET /scenarios/* โ proxy_pass โ sql-demos-api:80
nginx proxies all API routes to the sql-demos-api Kubernetes Service using in-cluster DNS (sql-demos-api short name resolves within the same namespace). The Angular build uses an empty apiBaseUrl so all requests are relative โ nginx handles routing them to the right backend. No CORS headers are needed.
Build
The Dockerfile is a two-stage build:
Stage 1 (node:22-alpine) npm ci + ng build --configuration production
Stage 2 (nginx:alpine) copies dist/sql-dashboard/browser โ /usr/share/nginx/html
The nginx default.conf is not baked into the image โ it is injected at runtime via a Kubernetes ConfigMap (see helm/sql-dashboard/templates/configmap.yaml). This makes it easy to change the upstream API host without rebuilding the image.
Project Structure
sql-dashboard/
โโโ Dockerfile Multi-stage build (node build โ nginx runtime)
โโโ proxy.conf.json Dev-server proxy: /health + /scenarios โ localhost:30080
โโโ angular.json Build config; swaps environment files per configuration
โโโ src/
โ โโโ index.html Shell; links favicon.svg + Google Fonts
โ โโโ environments/
โ โ โโโ environment.ts Production: apiBaseUrl = '' (relative, nginx proxies)
โ โ โโโ environment.development.ts Dev: apiBaseUrl = '' (Angular proxy handles routing)
โ โโโ app/
โ โโโ services/
โ โ โโโ benchmark.service.ts HTTP calls to /health, /scenarios, /scenarios/all
โ โโโ models/
โ โ โโโ scenario.models.ts TypeScript interfaces matching API JSON
โ โโโ components/
โ โโโ dashboard/ Main page โ toolbar, hero, scenario grid, summary table
โ โโโ scenario-card/ Individual scenario card with run button + result display
helm/sql-dashboard/
โโโ Chart.yaml
โโโ values.yaml image, nodePort (30081), apiServiceHost
โโโ templates/
โโโ _helpers.tpl
โโโ configmap.yaml nginx default.conf โ proxies /health + /scenarios to API
โโโ deployment.yaml Mounts ConfigMap; liveness/readiness on GET /
โโโ service.yaml NodePort 30081
Terraform Integration
The dashboard is deployed as the last step in terraform apply, after the API is ready:
null_resource "build_dashboard_image" docker build -t sql-dashboard:latest sql-dashboard/
โ (depends_on)
helm_release "sql_demos_api"
โ (depends_on)
helm_release "sql_dashboard" deploys helm/sql-dashboard/ at NodePort 30081
Terraform re-triggers the Docker build automatically when sql-dashboard/Dockerfile or any file under sql-dashboard/src/ changes. No manual docker build needed.
| Variable | Default | Description |
|---|---|---|
dashboard_node_port |
30081 |
NodePort exposed on Docker Desktop |
Output after terraform apply:
Troubleshooting
Dashboard loads but shows "API unreachable"
The health check failed. Confirm the API pod is running and the service is reachable:
If the API pod is Running but health fails, check API logs:
Dashboard pod stuck in ErrImageNeverPull
The Docker image wasn't built before Terraform deployed the chart. Force a rebuild:
Page loads but spinning / blank after teardown
There is a brief window between terraform destroy completing and terraform apply finishing where nothing is listening on port 30081. The browser will spin until the pod is ready. Wait for:
Dev server shows "API unreachable" (npm start)
The dev proxy needs the API running at localhost:30080. Either:
- Run
terraform applyfirst to bring up the k8s stack, or - Start the API locally:
cd src/SqlDemosApi && dotnet run(it binds tolocalhost:5000by default โ updateproxy.conf.jsontarget tohttp://localhost:5000if using the local dev server)