Skip to content

SunbirdAI/Noise-Portal-Map-Box

Repository files navigation

Sunbird AI Noise Dashboard

Modern public frontend for monitoring environmental noise sensors across Kampala and Entebbe. The app is a static React/Vite dashboard that uses the existing Sunbird noise backend and renders an interactive Mapbox GL map with clustered, color-coded sensor markers.

Stack

  • React + Vite + TypeScript
  • Mapbox GL JS for the main clustered map
  • TanStack Query for API fetching, caching, retries, and partial failure handling
  • React Router for dashboard/detail/404 routes
  • Tailwind CSS for the responsive UI
  • Recharts for detail-page charts
  • Vitest + React Testing Library for tests

Setup

Install dependencies:

npm install

Create a local environment file:

cp .env.example .env.local

Set the environment values:

VITE_API_BASE_URL=/api
VITE_MAPBOX_ACCESS_TOKEN=your_mapbox_public_token

Run the development server:

npm run dev

Build for production:

npm run build

Run tests:

npm test

Environment Variables

VITE_API_BASE_URL

Backend API base URL. Defaults to https://noise-sensors-dashboard.herokuapp.com when unset.

For local development, use VITE_API_BASE_URL=/api. Vite proxies /api/* to https://noise-sensors-dashboard.herokuapp.com/*, which avoids browser CORS blocking while keeping frontend code pointed at a configurable API base.

VITE_MAPBOX_ACCESS_TOKEN

Public Mapbox token used by Mapbox GL JS. The token is read only from the environment and is not hardcoded in source. If it is missing, the app keeps the dashboard usable and shows a clear map configuration state.

Backend API

The frontend uses the existing backend endpoints:

  • GET /devices/locations/?page=1
  • GET /devices/location_metrics/:locationId/
  • GET /analysis
  • GET /devices/devices/by-device-id/:deviceName/
  • GET /device_metrics/sound-inference-data/by-device-id/:deviceName/
  • GET /device_metrics/environmental-parameters/by-device-id/:deviceName/
  • GET /device_metrics/device/by-device-id/:deviceName/history/
  • GET /device_metrics/device/by-device-id/:deviceName/aggregates/
  • GET /device_metrics/environmental-parameters/by-device-id/:deviceName/history/
  • GET /device_metrics/sound-inference-data/by-device-id/:deviceName/history/

The client centralizes request handling in src/lib/api/client.ts. Dynamic URL values are encoded, location pagination is followed through next, and backend responses are normalized into typed frontend models in src/lib/api/normalizers.ts.

Device detail date ranges use backend-supported start_date, end_date, page, and page_size parameters. Generic MCU/mobile-style devices use the aggregate endpoint for hourly and daily chart buckets with timezone=Africa/Kampala. SEAS AI sensors keep their latest live endpoints for popups and latest telemetry, while the detail page uses the environmental and sound-inference history endpoints for selected-range data. The app does not send unsupported range aliases such as days, from, or to.

SEAS environmental history can be very dense, so the frontend requests the latest stable page of readings for the selected range and shows a notice when the backend reports more records than were loaded. A future AI aggregate endpoint would allow complete long-range SEAS charts without loading thousands of raw readings.

CORS

The Heroku API does not currently return Access-Control-Allow-Origin for browser requests from localhost, so direct frontend calls to https://noise-sensors-dashboard.herokuapp.com are blocked by CORS.

Local development uses the Vite proxy:

VITE_API_BASE_URL=/api

For production, choose one of these:

  • Enable CORS on the backend for the deployed frontend origin.
  • Deploy a same-origin reverse proxy or edge/serverless function at /api and build with VITE_API_BASE_URL=/api.
  • If the backend later returns the correct CORS headers, build with VITE_API_BASE_URL=https://noise-sensors-dashboard.herokuapp.com.

A static frontend cannot bypass CORS by itself; either the backend or a same-origin proxy must provide the browser-readable response.

Dashboard Behavior

  • Filters invalid GPS coordinates, including 0,0 and out-of-range latitude/longitude.
  • Prefers mobile coordinates when the backend supplies valid mobile coordinate fields.
  • Fetches device metrics per sensor without failing the whole dashboard if one device request fails.
  • Uses real backend values only; missing values are shown as No data.
  • Detects sensor type as MCU, MOBILE, AI, or Unknown from device metadata and naming conventions.
  • Supports direct refresh on /locations/:locationId by fetching data from the route param instead of relying on router state.

Deployment

This is a static frontend. Any static host that supports SPA fallback routing can serve the dist directory generated by npm run build.

GitHub Pages

The repo now includes a GitHub Actions workflow at .github/workflows/deploy.yml that builds and deploys the app from main.

Before enabling it in GitHub, set these repository settings:

  • Turn on Pages deployment from GitHub Actions in the repository settings.
  • Add VITE_MAPBOX_ACCESS_TOKEN as a repository secret.

The app is configured for the custom domain root https://noise.sunbird.ai/, with VITE_BASE_PATH=/ and public/CNAME. If you move back to a repository project URL, update the base path in vite.config.ts, .github/workflows/deploy.yml, and the redirect script in public/404.html.

For production hosting, configure:

  • Static asset root: dist
  • SPA fallback: route unknown paths to dist/index.html
  • Environment variables at build time: VITE_API_BASE_URL, VITE_MAPBOX_ACCESS_TOKEN
  • If the backend CORS policy is unchanged, deploy a same-origin /api proxy and set VITE_API_BASE_URL=/api.

Key Improvements

  • Cleaner typed API layer with pagination, timeouts, normalization, and partial failure handling.
  • Mapbox GL clustered map with dB labels, color-coded noise bands, and detail popups.
  • Direct-load location detail pages with metric cards, daily/hourly charts, heatmap, and AI/environmental panels.
  • Responsive dashboard layout with real loading, empty, error, and missing-configuration states.
  • Lazy-loaded map and route chunks to keep the initial app bundle focused.
  • Test coverage for normalization, sensor type detection, coordinate validation, dashboard states, and direct detail routing.

About

Modern public frontend for monitoring environmental noise sensors across Kampala and Entebbe. The app is a static React/Vite dashboard that uses the existing Sunbird noise backend and renders an interactive Mapbox GL map with clustered, color-coded sensor markers.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages