354 lines
10 KiB
Markdown
354 lines
10 KiB
Markdown
# Map Module
|
|
|
|
The Map module provides comprehensive location management, geographic organization, volunteer coordination, and door-to-door canvassing capabilities. It combines GIS features with volunteer management for effective ground campaigns.
|
|
|
|
## Overview
|
|
|
|
The Map module consists of ten integrated components:
|
|
|
|
1. **[Locations](locations.md)** - Location database with geocoding
|
|
2. **[Geocoding](geocoding.md)** - Multi-provider address → coordinate conversion
|
|
3. **[NAR Import](nar-import.md)** - Canadian electoral data import
|
|
4. **[Cuts](cuts.md)** - Geographic polygon organization
|
|
5. **[Shifts](shifts.md)** - Volunteer shift scheduling
|
|
6. **[Canvassing](canvassing.md)** - Door-to-door canvassing system
|
|
7. **[Tracking](tracking.md)** - GPS tracking sessions
|
|
8. **[Walk Sheets](walk-sheets.md)** - Printable canvass materials
|
|
9. **[Data Quality](data-quality.md)** - Geocoding quality monitoring
|
|
10. **Map Features Status** - Feature completion tracking
|
|
|
|
## Features
|
|
|
|
### Location Management
|
|
|
|
- Location CRUD with address, coordinates, metadata
|
|
- CSV import/export (100,000+ records supported)
|
|
- Multi-provider geocoding (6 providers)
|
|
- Bulk geocoding with queue
|
|
- NAR 2025 server-side import (Canadian electoral data)
|
|
- Address standardization
|
|
- Visit tracking integration
|
|
|
|
### Geographic Organization
|
|
|
|
- Polygon-based geographic cuts
|
|
- GeoJSON import/export
|
|
- Point-in-polygon queries
|
|
- Cut-based location assignment
|
|
- Spatial bounds calculation
|
|
- Map visualization
|
|
|
|
### Volunteer Coordination
|
|
|
|
- Shift scheduling with cut assignment
|
|
- Volunteer signup (authenticated + anonymous)
|
|
- Email confirmations
|
|
- Temp user creation for walk-ins
|
|
- Shift capacity tracking
|
|
|
|
### Canvassing System
|
|
|
|
- GPS-enabled mobile interface
|
|
- Walking route algorithm (nearest-neighbor)
|
|
- Visit outcome recording (7 outcomes)
|
|
- Session management (start/end/abandon)
|
|
- Real-time progress tracking
|
|
- Admin monitoring dashboard
|
|
- Printable walk sheets with QR codes
|
|
|
|
### Map Display
|
|
|
|
- Public interactive Leaflet map
|
|
- Color-coded markers by visit status
|
|
- Polygon overlays for cuts
|
|
- Geolocate button
|
|
- Fullscreen mode
|
|
- Legend and controls
|
|
|
|
## User Flow
|
|
|
|
### Admin Experience
|
|
|
|
1. **Import Locations** (`/app/map/locations`)
|
|
- Upload CSV or NAR data
|
|
- Geocode addresses
|
|
- Review quality metrics
|
|
- Bulk operations
|
|
|
|
2. **Create Cuts** (`/app/map/cuts`)
|
|
- Draw polygons on map
|
|
- Name and describe cut
|
|
- Assign locations (automatic)
|
|
- Export for printing
|
|
|
|
3. **Schedule Shifts** (`/app/map/shifts`)
|
|
- Create shift with cut assignment
|
|
- Set date/time/capacity
|
|
- Email all volunteers
|
|
- Monitor signups
|
|
|
|
4. **Monitor Canvassing** (`/app/canvass/dashboard`)
|
|
- View active sessions
|
|
- Track visit progress
|
|
- Check leaderboard
|
|
- Review activity feed
|
|
|
|
5. **Print Materials** (`/app/canvass/walk-sheet`)
|
|
- Select cut
|
|
- Generate walk sheet PDF
|
|
- QR codes for quick access
|
|
- Browser print
|
|
|
|
### Volunteer Experience
|
|
|
|
1. **View Assignments** (`/volunteer/assignments`)
|
|
- See upcoming shifts
|
|
- Cut information
|
|
- Start canvass button
|
|
|
|
2. **Canvass** (`/volunteer/canvass/:cutId`)
|
|
- Full-screen map with GPS
|
|
- Follow walking route
|
|
- Click markers to record visits
|
|
- Select outcomes + notes
|
|
- Track progress
|
|
|
|
3. **Review Activity** (`/volunteer/activity`)
|
|
- Visit history
|
|
- Outcome breakdown
|
|
- Session statistics
|
|
|
|
### Public Experience
|
|
|
|
1. **View Map** (`/map`)
|
|
- Browse locations
|
|
- View cuts
|
|
- See visit status (color-coded)
|
|
- Geolocate self
|
|
|
|
2. **Sign Up for Shifts** (`/shifts`)
|
|
- Browse available shifts
|
|
- Signup with email
|
|
- Receive confirmation
|
|
|
|
## Architecture
|
|
|
|
### Backend Components
|
|
|
|
**Modules:**
|
|
- `api/src/modules/map/locations/` - Location CRUD + geocoding + NAR import
|
|
- `api/src/modules/map/geocoding/` - Multi-provider geocoding service
|
|
- `api/src/modules/map/cuts/` - Polygon CRUD + spatial queries
|
|
- `api/src/modules/map/shifts/` - Shift CRUD + signups
|
|
- `api/src/modules/map/canvass/` - Session + visit tracking
|
|
- `api/src/modules/map/tracking/` - GPS tracking (future)
|
|
- `api/src/modules/map/settings/` - Map settings singleton
|
|
|
|
**Services:**
|
|
- `api/src/services/geocoding.service.ts` - Geocoding abstraction
|
|
- `api/src/services/geocode-queue.service.ts` - Async geocoding
|
|
|
|
**Utilities:**
|
|
- `api/src/utils/spatial.ts` - Point-in-polygon, haversine, bounds, centroid
|
|
|
|
**Database Models:**
|
|
- `Location` - Address, coordinates, metadata, visit tracking
|
|
- `Cut` - Name, GeoJSON polygon
|
|
- `Shift` - Date/time, cut, capacity, signups
|
|
- `CanvassSession` - Session tracking, start/end times
|
|
- `CanvassVisit` - Visit outcomes, notes, GPS
|
|
- `MapSettings` - Map center/zoom, walk sheet config
|
|
|
|
### Frontend Components
|
|
|
|
**Admin Pages:**
|
|
- `admin/src/pages/LocationsPage.tsx` - Location management
|
|
- `admin/src/pages/CutsPage.tsx` - Cut management
|
|
- `admin/src/pages/ShiftsPage.tsx` - Shift management
|
|
- `admin/src/pages/CanvassDashboardPage.tsx` - Canvass monitoring
|
|
- `admin/src/pages/WalkSheetPage.tsx` - Printable materials
|
|
- `admin/src/pages/DataQualityDashboardPage.tsx` - Quality metrics
|
|
|
|
**Public Pages:**
|
|
- `admin/src/pages/public/MapPage.tsx` - Public map
|
|
- `admin/src/pages/public/ShiftsPage.tsx` - Shift signup
|
|
|
|
**Volunteer Pages:**
|
|
- `admin/src/pages/volunteer/VolunteerMapPage.tsx` - GPS canvass map
|
|
- `admin/src/pages/volunteer/VolunteerShiftsPage.tsx` - Assignments
|
|
- `admin/src/pages/volunteer/MyActivityPage.tsx` - Activity history
|
|
|
|
**Map Components:**
|
|
- `admin/src/components/map/MapControls.tsx` - Control buttons
|
|
- `admin/src/components/map/AddLocationMode.tsx` - Click-to-add
|
|
- `admin/src/components/map/CutDrawingMode.tsx` - Polygon drawing
|
|
- `admin/src/components/map/CutOverlays.tsx` - GeoJSON rendering
|
|
|
|
**Canvass Components:**
|
|
- `admin/src/components/canvass/GPSTracker.tsx` - GPS tracking
|
|
- `admin/src/components/canvass/WalkingRouteLine.tsx` - Route display
|
|
- `admin/src/components/canvass/VisitRecordingForm.tsx` - Outcome form
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
|
|
```bash
|
|
# Geocoding Providers
|
|
MAPBOX_ACCESS_TOKEN=pk_...
|
|
GOOGLE_GEOCODE_API_KEY=...
|
|
PELIAS_API_URL=http://pelias:4000
|
|
|
|
# NAR Import
|
|
NAR_DATA_DIR=/data # NAR file directory (Docker volume)
|
|
|
|
# Map Settings
|
|
MAP_DEFAULT_LAT=43.65 # Default map center
|
|
MAP_DEFAULT_LNG=-79.38
|
|
MAP_DEFAULT_ZOOM=12
|
|
```
|
|
|
|
### Map Settings
|
|
|
|
Configurable via admin UI (`/app/map/settings`):
|
|
- Default map center (lat/lng)
|
|
- Default zoom level
|
|
- Walk sheet header/footer
|
|
- Display preferences
|
|
|
|
## Geocoding
|
|
|
|
### Supported Providers
|
|
|
|
1. **Nominatim** (OpenStreetMap) - Free, rate limited
|
|
2. **ArcGIS** - Free tier available
|
|
3. **Photon** - Free, self-hosted option
|
|
4. **Mapbox** - API key required
|
|
5. **Google Geocoding** - API key required
|
|
6. **Pelias** - Self-hosted option
|
|
|
|
### Geocoding Strategy
|
|
|
|
1. Try provider 1 (Nominatim)
|
|
2. If fails, try provider 2 (ArcGIS)
|
|
3. Continue through providers
|
|
4. Cache successful results
|
|
5. Track quality metrics
|
|
|
|
### Bulk Geocoding
|
|
|
|
- BullMQ queue for async processing
|
|
- Batch processing (100 locations/batch)
|
|
- Provider rotation to avoid rate limits
|
|
- Progress tracking
|
|
- Error handling and retry
|
|
|
|
## NAR Import
|
|
|
|
Canadian electoral data (NAR 2025 format):
|
|
|
|
- **Address files** - Civic addresses with coordinates (EPSG:3347)
|
|
- **Location files** - Building locations with lat/lng
|
|
- **Join on LOC_GUID** - Combine address + coordinates
|
|
- **Server-side streaming** - Memory-efficient for large files
|
|
- **Filters** - Province, city, postal code, cut, residential-only
|
|
|
|
**Import Flow:**
|
|
1. Scan NAR data directory
|
|
2. List available provinces
|
|
3. Stream Address + Location files
|
|
4. Join on LOC_GUID
|
|
5. Transform coordinates (proj4)
|
|
6. Filter and insert locations
|
|
|
|
## Spatial Algorithms
|
|
|
|
### Point-in-Polygon
|
|
|
|
Ray-casting algorithm:
|
|
- Count ray intersections with polygon edges
|
|
- Odd count = inside, even count = outside
|
|
- Supports holes in polygons
|
|
- Used for cut assignment
|
|
|
|
### Walking Route
|
|
|
|
Nearest-neighbor algorithm:
|
|
1. Start at closest location to shift start point
|
|
2. For each location:
|
|
- Find nearest unvisited location
|
|
- Add to route
|
|
- Mark as visited
|
|
3. Return ordered list
|
|
|
|
### Haversine Distance
|
|
|
|
Great-circle distance between coordinates:
|
|
- Returns distance in kilometers
|
|
- Used for proximity sorting
|
|
- Route optimization
|
|
|
|
## API Endpoints
|
|
|
|
### Locations
|
|
|
|
```
|
|
GET /api/locations # List locations
|
|
POST /api/locations # Create location
|
|
GET /api/locations/:id # Get location
|
|
PATCH /api/locations/:id # Update location
|
|
DELETE /api/locations/:id # Delete location
|
|
POST /api/locations/import # CSV import
|
|
GET /api/locations/export # CSV export
|
|
POST /api/locations/geocode # Bulk geocode
|
|
```
|
|
|
|
### Cuts
|
|
|
|
```
|
|
GET /api/cuts # List cuts
|
|
POST /api/cuts # Create cut
|
|
GET /api/cuts/:id # Get cut
|
|
PATCH /api/cuts/:id # Update cut
|
|
DELETE /api/cuts/:id # Delete cut
|
|
POST /api/cuts/:id/assign-locations # Assign locations
|
|
```
|
|
|
|
### Shifts
|
|
|
|
```
|
|
GET /api/shifts # List shifts
|
|
POST /api/shifts # Create shift
|
|
GET /api/shifts/:id # Get shift
|
|
PATCH /api/shifts/:id # Update shift
|
|
DELETE /api/shifts/:id # Delete shift
|
|
POST /api/shifts/:id/signup # Signup for shift
|
|
```
|
|
|
|
### Canvassing
|
|
|
|
```
|
|
POST /api/canvass/session/start # Start session
|
|
POST /api/canvass/session/end # End session
|
|
GET /api/canvass/session # Get active session
|
|
POST /api/canvass/visit # Record visit
|
|
GET /api/canvass/route/:cutId # Get walking route
|
|
GET /api/canvass/dashboard # Dashboard stats
|
|
```
|
|
|
|
## Related Documentation
|
|
|
|
- [Locations](locations.md)
|
|
- [Geocoding](geocoding.md)
|
|
- [NAR Import](nar-import.md)
|
|
- [Cuts](cuts.md)
|
|
- [Shifts](shifts.md)
|
|
- [Canvassing](canvassing.md)
|
|
- [Walk Sheets](walk-sheets.md)
|
|
- [Data Quality](data-quality.md)
|
|
- [Backend Locations Module](../../backend/modules/locations.md)
|
|
- [Backend Canvass Module](../../backend/modules/canvass.md)
|
|
- [Spatial Utilities](../../backend/utilities/index.md)
|
|
- [Map Organizer Guide](../../user-guides/map-organizer-guide.md)
|
|
- [Volunteer Guide](../../user-guides/volunteer-guide.md)
|