# NocoDB Map Viewer

A containerized web application that visualizes geographic data from NocoDB on an interactive map using Leaflet.js.

## Features

- 🗺️ Interactive map visualization with OpenStreetMap
- 📍 Real-time geolocation support
- ➕ Add new locations directly from the map
- 🔄 Auto-refresh every 30 seconds
- 📱 Responsive design for mobile devices
- 🔒 Secure API proxy to protect credentials
- 👤 User authentication with login system
- ⚙️ Admin panel for system configuration
- 🎯 Configurable map start location
- 📋 Walk Sheet generator for door-to-door canvassing
- 🔗 QR code integration for digital resources
- 📅 Volunteer shift management system with calendar and grid views
- ✋ User shift signup and cancellation with color-coded calendar
- 👥 Admin shift creation and management
- 👨‍💼 User management panel for admin users (create, delete users)
- 🔐 Role-based access control (Admin vs User permissions)
- 🐳 Docker containerization for easy deployment
- 🆓 100% open source (no proprietary dependencies)

## Quick Start

### Prerequisites

- Docker and Docker Compose
- NocoDB instance with API access
- NocoDB API token

### Installation

1. **Get NocoDB API Token**

   1. Login to your NocoDB instance
   2. Click user icon → **Account Settings** → **API Tokens**
   3. Create new token with read/write permissions
   4. Copy the token for the next step

2. **Configure Environment**

   Edit the `.env` file with your NocoDB API and API Url:
   ```env
   # NocoDB API Configuration
   NOCODB_API_URL=https://db.cmlite.org/api/v1
   NOCODB_API_TOKEN=your-api-token-here

   # These will be populated after running build-nocodb.sh
   NOCODB_VIEW_URL=
   NOCODB_LOGIN_SHEET=
   NOCODB_SETTINGS_SHEET=
   NOCODB_SHIFTS_SHEET=
   NOCODB_SHIFT_SIGNUPS_SHEET=

   # Server Configuration
   PORT=3000
   NODE_ENV=production
   SESSION_SECRET=your-secure-random-string

   # Map Defaults (Edmonton, AB)
   DEFAULT_LAT=53.5461
   DEFAULT_LNG=-113.4938
   DEFAULT_ZOOM=11

   # Cloudflare Settings
   TRUST_PROXY=true
   COOKIE_DOMAIN=.cmlite.org

   # Allowed Origins
   ALLOWED_ORIGINS=https://map.cmlite.org,http://localhost:3000
   ```

3. **Auto-Create Database Structure**

   Run the build script to create required tables:
   ```bash
   chmod +x build-nocodb.sh
   ./build-nocodb.sh
   ```

   This creates five tables:
   - **Locations** - Main map data with geo-location, contact info, support levels
   - **Login** - User authentication (email, name, admin flag)
   - **Settings** - Admin configuration and QR codes
   - **Shifts** - Shift scheduling and management
   - **Shift Signups** - User shift registrations

4. **Get Table URLs**

   After the script completes:
   1. Login to your NocoDB instance at https://db.cmlite.org
   2. Navigate to your project ("Map Viewer Project - TIMESTAMP")
   3. Copy the view URLs for each table from your browser address bar
   4. URLs should look like: `https://db.cmlite.org/dashboard/#/nc/project-id/table-id`

5. **Update Environment with URLs**

   Edit your `.env` file and add the table URLs:
   ```env
   NOCODB_VIEW_URL=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/m6g7bkzv7s1w2ur
   NOCODB_LOGIN_SHEET=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/mizyc64e4r7ppzh
   NOCODB_SETTINGS_SHEET=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/mix06f2mlep7gqb
   NOCODB_SHIFTS_SHEET=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/mkx0tex0iquus1u
   NOCODB_SHIFT_SIGNUPS_SHEET=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/mi8jg1tn26mu8fj
   ```

6. **Build and Deploy**

   Build the Docker image and start the application:
   ```bash
   # Build the Docker image
   docker-compose build

   # Start the application
   docker-compose up -d
   ```

7. **Verify Installation**

   - Check container status: `docker-compose ps`
   - View logs: `docker-compose logs -f map-viewer`
   - Access the application at: http://localhost:3000
   - Access shift management at: http://localhost:3000/shifts.html
   - Access admin panel at: http://localhost:3000/admin.html (admin users only)

## Database Schema

The build script automatically creates the following table structure:

### Main Locations Table
- `Geo-Location` (Geo-Data): Format "latitude;longitude" 
- `latitude` (Decimal): Precision 10, Scale 8
- `longitude` (Decimal): Precision 11, Scale 8
- `First Name` (Single Line Text): Person's first name
- `Last Name` (Single Line Text): Person's last name
- `Email` (Email): Email address
- `Phone` (Single Line Text): Phone number
- `Unit Number` (Single Line Text): Unit or apartment number
- `Support Level` (Single Select): Options: "1", "2", "3", "4" (1=Strong Support/Green, 2=Moderate Support/Yellow, 3=Low Support/Orange, 4=No Support/Red)
- `Address` (Single Line Text): Street address
- `Sign` (Checkbox): Has campaign sign
- `Sign Size` (Single Select): Options: "Regular", "Large", "Unsure"
- `Notes` (Long Text): Additional details and comments
- `title` (Text): Location name (legacy field)
- `category` (Single Select): Classification (legacy field)

### Login Table
- `Email` (Email): User email address
- `Name` (Single Line Text): User display name  
- `Admin` (Checkbox): Admin privileges

### Settings Table
- `key` (Single Line Text): Setting identifier
- `title` (Single Line Text): Display name
- `value` (Long Text): Setting value
- `Geo-Location` (Text): Format "latitude;longitude"
- `latitude` (Decimal): Precision 10, Scale 8
- `longitude` (Decimal): Precision 11, Scale 8
- `zoom` (Number): Map zoom level
- `category` (Single Select): Setting category
- `updated_by` (Single Line Text): Last updater email
- `updated_at` (DateTime): Last update time
- `qr_code_1_image` (Attachment): QR code 1 image
- `qr_code_2_image` (Attachment): QR code 2 image
- `qr_code_3_image` (Attachment): QR code 3 image

### Shifts Table
- Standard NocoDB fields for shift scheduling and management
- Contains shift dates, times, locations, capacity limits
- Status tracking (Active, Cancelled, Full)
- Created automatically by build script with basic structure

### Shift Signups Table  
- Links users to shifts they've signed up for
- Tracks signup timestamps and user information
- Handles cancellations and waitlist management
- Created automatically by build script with basic structure

## API Endpoints

### Public Endpoints

- `GET /api/locations` - Fetch all locations (requires auth)
- `POST /api/locations` - Create new location (requires auth)
- `GET /api/locations/:id` - Get single location (requires auth)
- `PUT /api/locations/:id` - Update location (requires auth)
- `DELETE /api/locations/:id` - Delete location (requires auth)
- `GET /api/config/start-location` - Get map start location
- `GET /health` - Health check

### Shifts Endpoints (requires authentication)

- `GET /api/shifts` - Get all available shifts
- `GET /api/shifts/my-signups` - Get current user's shift signups
- `POST /api/shifts/:shiftId/signup` - Sign up for a shift
- `POST /api/shifts/:shiftId/cancel` - Cancel shift signup

### Shifts Admin Endpoints (requires admin privileges)

- `GET /api/shifts/admin` - Get all shifts including cancelled ones
- `POST /api/shifts/admin` - Create new shift
- `PUT /api/shifts/admin/:id` - Update existing shift
- `DELETE /api/shifts/admin/:id` - Delete shift

### Authentication Endpoints

- `POST /api/auth/login` - User login
- `GET /api/auth/check` - Check authentication status
- `POST /api/auth/logout` - User logout

### Admin Endpoints (requires admin privileges)

- `GET /api/admin/start-location` - Get start location with source info
- `POST /api/admin/start-location` - Update map start location
- `GET /api/admin/walk-sheet-config` - Get walk sheet configuration
- `POST /api/admin/walk-sheet-config` - Save walk sheet configuration

## Shifts Management

The application includes a comprehensive volunteer shift management system accessible at `/shifts.html`.

### User Features

- **Dual View Options**: Toggle between grid view and calendar view for shift display
- **Calendar View**: Interactive monthly calendar showing shifts with color-coded indicators:
  - Green: Shifts you've signed up for
  - Blue: Available shifts you can join
  - Gray: Full shifts (no spots available)
- **View Available Shifts**: See all upcoming shifts with date, time, and capacity information
- **Sign Up for Shifts**: One-click signup for available shifts (works in both views)
- **My Shifts Dashboard**: View all your current shift signups at the top of the page
- **Cancel Signups**: Cancel your shift signups when needed
- **Date Filtering**: Filter shifts by specific dates (applies to both views)
- **Real-time Updates**: Shift availability updates dynamically
- **Interactive Calendar**: Click on calendar shifts for detailed popup with signup options
- **Calendar Navigation**: Navigate between months to view future shifts

### Admin Features

Administrators have additional capabilities for managing shifts:

- **Create New Shifts**: Add new volunteer shifts with date, time, location, and capacity
- **Edit Existing Shifts**: Modify shift details, times, or capacity
- **Cancel Shifts**: Mark shifts as cancelled (they remain in system but hidden from users)
- **View All Signups**: See who has signed up for each shift
- **Manage Capacity**: Set maximum number of volunteers per shift

### Shift Status System

- **Active**: Available for signups
- **Full**: Capacity reached, no more signups accepted
- **Cancelled**: Hidden from public view but retained in database

## Admin Panel

Users with admin privileges can access the admin panel at `/admin.html` to configure system settings.

### Features

#### Start Location Configuration

- **Interactive Map**: Visual interface for selecting coordinates
- **Real-time Preview**: See changes immediately on the admin map
- **Validation**: Built-in coordinate and zoom level validation

#### Walk Sheet Generator

- **Printable Forms**: Generate 8.5x11 walk sheets for door-to-door canvassing
- **QR Code Integration**: Add up to 3 QR codes with custom URLs and labels
- **Form Field Matching**: Automatically matches fields from the main location form
- **Live Preview**: See changes as you type
- **Print Optimization**: Proper formatting for printing or PDF export
- **Persistent Storage**: All QR codes and settings saved to NocoDB

#### Shift Management

- **Create Shifts**: Set up volunteer shifts with dates, times, and capacity
- **Manage Volunteers**: View signups and manage shift participants
- **Real-time Updates**: See shift status changes immediately

#### User Management

- **Create Users**: Add new user accounts with email and password
- **Role Assignment**: Assign admin or user privileges
- **User List**: View all registered users with their details and creation dates
- **Delete Users**: Remove user accounts (with confirmation prompts)
- **Security**: Password validation and admin-only access

### Access Control

- Admin access is controlled via the `Admin` checkbox in the Login table
- Only authenticated users with admin privileges can access `/admin.html`
- Admin status is checked on every request to admin endpoints
- User management functions are restricted to admin users only

### Start Location Priority

The system uses a cascading fallback system for map start location:
1. **Database**: Admin-configured location stored in Settings table (highest priority)
2. **Environment**: Default values from .env file (medium priority)  
3. **Hardcoded**: Edmonton, Canada coordinates (lowest priority)

## Configuration

All configuration is done via environment variables:

| Variable | Description | Default |
|----------|-------------|---------|
| `NOCODB_API_URL` | NocoDB API base URL | Required |
| `NOCODB_API_TOKEN` | API authentication token | Required |
| `NOCODB_VIEW_URL` | Full NocoDB view URL for locations table | Required |
| `NOCODB_LOGIN_SHEET` | Login table URL for authentication | Required |
| `NOCODB_SETTINGS_SHEET` | Settings table URL for admin config | Required |
| `NOCODB_SHIFTS_SHEET` | Shifts table URL for shift management | Required |
| `NOCODB_SHIFT_SIGNUPS_SHEET` | Shift signups table URL for user registrations | Required |
| `PORT` | Server port | 3000 |
| `NODE_ENV` | Environment mode | production |
| `SESSION_SECRET` | Session encryption secret | Required |
| `DEFAULT_LAT` | Default map latitude | 53.5461 |
| `DEFAULT_LNG` | Default map longitude | -113.4938 |
| `DEFAULT_ZOOM` | Default map zoom level | 11 |
| `TRUST_PROXY` | Trust proxy headers (for Cloudflare) | true |
| `COOKIE_DOMAIN` | Cookie domain setting | .cmlite.org |
| `ALLOWED_ORIGINS` | CORS allowed origins | Multiple URLs |

## Maintenance Commands

### Update Application
```bash
docker-compose down
git pull origin main
docker-compose build
docker-compose up -d
```

### Development Mode
```bash
cd app
npm install
npm run dev
```

### Health Check
```bash
curl http://localhost:3000/health
```

## Development

To run in development mode:

1. Install dependencies:
   ```bash
   cd app
   npm install
   ```

2. Start with hot reload:
   ```bash
   npm run dev
   ```

## Security Considerations

- API tokens are kept server-side only
- CORS is configured for security
- Rate limiting prevents abuse
- Input validation on all endpoints
- Helmet.js for security headers

## Troubleshooting

### Locations not showing

- Verify table has `geodata`, `latitude`, and `longitude` columns
- Check that coordinates are valid numbers
- Ensure API token has read permissions

### Cannot add locations

- Verify API token has write permissions
- Check browser console for errors
- Ensure coordinates are within valid ranges

### Connection errors

- Verify NocoDB instance is accessible
- Check API URL format
- Confirm network connectivity

### Build Script Issues

- Ensure NocoDB instance is accessible
- Verify API token has admin permissions
- Check that the NocoDB database is clean (delete all bases before running)

## License

MIT License - See LICENSE file for details

## Support

For issues or questions:
1. Check the troubleshooting section
2. Review NocoDB documentation
3. Open an issue on GitHub

## Known Bugs 

- First load of page often fails, need to debug 
- Want UI for dots to have an edit button that then brings up the form