freealberta/influence/instruct.md

9.3 KiB

Instructions

Welcome to BNKops Influence, a tool for creating political change by targeting influential individuals within a community. This application is designed to help campaigns identify and engage with key figures who can sway public opinion and mobilize support.

Environment Setup

We want to deploy using a docker container. We use the new docker compose format. We use a .env file for environment variables. The developer likes to down, build, and up the container for testing / new features.

Wej are using NocoDB as a no-code database solution. You will need to set up a NocoDB instance and create the necessary tables for your application. Refer to the build-nocodb.sh file for the schema setup.

Project Overview

  • Purpose: Create influence campaigns by identifying and engaging with key community figures over email, text, or phone.
  • Backend: Node.js/Express, with NocoDB as the database (REST API).
  • Frontend: Vanilla JS, Leaflet.js for mapping, modular code in /public/js.
  • Admin Panel: Accessible via /admin.html for managing campaigns, users, and settings.

Campaign Settings Overview

The application supports flexible campaign configuration through the admin panel:

Available Campaign Settings

  1. Show Email Count (show_email_count) - Default: ON

    • Displays total emails sent on campaign landing pages
    • Provides social proof and engagement metrics
    • Toggle via checkbox: "📊 Show Email Count" in admin panel
    • Database: Boolean field in campaigns table
    • Backend: Conditionally fetches count via getCampaignEmailCount()
    • Frontend: Shows/hides stats banner in campaign.js
  2. Allow SMTP Email (allow_smtp_email) - Default: ON

    • Enables server-side email sending through configured SMTP
    • Full logging and tracking of email delivery
  3. Allow Mailto Link (allow_mailto_link) - Default: ON

    • Enables browser-based email client launching
    • Useful fallback for users without SMTP
  4. Collect User Info (collect_user_info) - Default: ON

    • Requests user name and email before participation
    • Enables campaign tracking and follow-up
  5. Allow Email Editing (allow_email_editing) - Default: OFF

    • Lets users customize email templates before sending
    • Increases personalization but may dilute messaging
  6. Cover Photo (cover_photo) - Optional

    • Hero image for campaign landing pages
    • Max 5MB, JPEG/PNG/GIF/WebP formats
  7. Target Government Levels (target_government_levels) - MultiSelect

    • Federal, Provincial, Municipal, School Board
    • Filters which representatives are shown
  8. Campaign Status (status) - Required

    • Draft: Testing only, hidden from public
    • Active: Visible on main page
    • Paused: Temporarily disabled
    • Archived: Completed campaigns

Using Campaign Settings in Code

When creating new campaign features:

  • Add field to build-nocodb.sh campaigns table schema
  • Add field mapping in nocodb.js service (createCampaign, updateCampaign)
  • Add field normalization in campaigns.js controller
  • Add checkbox/input in admin.html create and edit forms
  • Add form handling in admin.js (read/write form data)
  • Implement frontend logic in campaign.js based on setting value
  • Update README.MD and files-explainer.md with new setting documentation

Example: Accessing settings in frontend:

// In campaign.js after loading campaign data
if (this.campaign.show_email_count && this.campaign.emailCount !== null) {
    document.getElementById('email-count').textContent = this.campaign.emailCount;
    document.getElementById('campaign-stats').style.display = 'block';
}

Example: Setting default values in backend:

// In campaigns.js createCampaign()
const campaignData = {
    show_email_count: req.body.show_email_count ?? true,  // Default ON
    allow_email_editing: req.body.allow_email_editing ?? false,  // Default OFF
    // ... other fields
};

Key Principles

  • Separation of Concerns: Keep logic for API, UI, and data management in their respective files/modules.
  • Security: Never expose sensitive credentials. All API calls to NocoDB go through the backend.
  • Scalability: Write code that is easy to extend (e.g., adding new location fields, new admin features).
  • User Experience: Prioritize clear feedback, error handling, and mobile responsiveness.
  • Documentation: Keep code well-documented and maintain the Instructions.md, README.md and files-explainer.md files.
  • Modularity: Use modular JavaScript to keep code organized and reusable; try to avoid large monolithic scripts keeping functionality separated by feature with files no longer than 500 lines.

Directory Structure

  • app/ - Node.js backend (Express server, routes, controllers, services, utils)
  • app/public/ - Frontend static files (HTML, CSS, JS)
  • app/public/js/ - Modular JavaScript for map, UI, auth, etc.
  • app/controllers/ - Express controllers for business logic
  • app/routes/ - Express routers for API endpoints
  • app/services/ - Backend services (NocoDB, geocoding, QR code)
  • app/utils/ - Shared backend utilities

Development Rules

  • No inline event handlers. Always use addEventListener in JS files.
  • Update documentation. Always update README.md and files-explainer.md when adding features or files.
  • Consistent style. Follow the existing code style and naming conventions.
  • Error handling. Always provide user feedback for errors (both backend and frontend).
  • Environment variables. Use .env for secrets/config, never hardcode sensitive data.
  • Testing. Test new features locally and ensure they do not break existing functionality.
  • Pagination Use pagination for API endpoints returning large datasets to avoid performance issues. For example, getAll should be getAllPaginated

NocoDB Development Best Practices

Field Naming and Access

  • Use Column Titles, Not Column Names: NocoDB expects column titles (e.g., "Campaign Slug") in API calls, not column names (e.g., "slug")
  • Consistent Mapping: Always map between your application's field names and NocoDB's column titles in the service layer
  • Where Clauses: Use column titles in where conditions: (Campaign Slug,eq,value) not (slug,eq,value)

System Fields

  • Avoid System Field Conflicts: Never create user-defined fields with names like created_at, updated_at as they conflict with NocoDB system fields
  • Use System Fields: Leverage NocoDB's automatic system fields (CreatedAt, UpdatedAt, CreatedBy, etc.) instead of creating your own
  • Sorting: Sort by system field titles: -CreatedAt not -created_at

Select Field Configuration

  • Use colOptions: For SingleSelect and MultiSelect fields, always use colOptions with an options array
  • Never use dtxp: The dtxp parameter is deprecated and causes corrupted select options
  • Example Structure:
    {
      "uidt": "SingleSelect",
      "colOptions": {
        "options": [
          {"title": "draft", "color": "#d0f1fd"},
          {"title": "active", "color": "#c2f5e8"}
        ]
      }
    }
    

Table Management

  • Clean Recreation: When fixing table schema issues, delete and recreate tables rather than trying to modify corrupted structures
  • Environment Cleanup: Remove duplicate table IDs from .env files to avoid using old/deleted tables
  • Restart After Changes: Always restart the application after table recreation to pick up new table IDs

API Endpoints

  • Use Correct API Versions:
    • Data operations: /db/data/v1/{projectId}/{tableId}
    • Meta operations: /db/meta/tables/{tableId}
  • Field Validation: Test field access directly via NocoDB API before implementing in application logic
  • Error Handling: NocoDB returns specific error codes like FIELD_NOT_FOUND, TABLE_NOT_FOUND - handle these appropriately

Debugging Tips

  • Direct API Testing: Use curl to test NocoDB API directly before implementing in application
  • Check Table Metadata: Use /db/meta/tables/{tableId} to inspect actual column names and titles
  • Verify System Fields: Check which fields are marked as "system": true to avoid conflicts
  • Log API Responses: Always log NocoDB API responses during development to understand the exact data structure returned

How to Add a Feature

First look through the existing codebase to understand where similar logic is implemented. You can find a full listing of the files in the files-explainer.md file.

When adding a new feature, follow these steps:

  1. Plan: Decide where your logic belongs (backend controller, frontend JS, etc).
  2. Backend: Add/modify controllers, services, and routes as needed. Use NocoDB API via the service layer.
  3. Frontend: Add/modify JS modules in /public/js. Update HTML/CSS as needed.
  4. Document: Update README.md and files-explainer.md.
  5. Test: Manually test your feature in both desktop and mobile views.
  6. Pull Request: Submit your changes for review.

Visuals

We want a clean modern look. We use Leaflet.js for mapping. We use vanilla JS for the frontend. We want a responsive design that works well on both desktop and mobile. We want clear feedback for user actions (loading spinners, success/error messages). We want error handling to provide appropriate feedback when errors occur (both backend and frontend).