This commit is contained in:
Stan
2026-04-19 21:14:16 +02:00
parent 0c74a75126
commit 28d167f11f
42 changed files with 5681 additions and 55 deletions
+676
View File
@@ -0,0 +1,676 @@
# Project Files Guide
This document explains the role of the main files in this project in a way that should be easy to follow for a junior developer.
The project is split into a few clear parts:
- server code in [src/app.js](src/app.js) and the rest of [src](src)
- browser frontend files in [public](public)
- database structure and example data in [sql](sql)
- environment and local development helpers in the root folder and [scripts](scripts)
## How The Application Works At A High Level
The project has two big sides:
- the backend, which provides templates, lookups, configuration, report storage, and audit logging through REST API endpoints
- the frontend, which runs in the browser, stores drafts locally, and uses the backend for centrally managed configuration and report submission
In simple terms:
1. Express starts the server.
2. The server exposes API endpoints under `/api/v1/...`.
3. The server also serves the frontend files from the [public](public) folder.
4. The browser loads the frontend entry point [public/app.js](public/app.js) which imports modules from [public/js/](public/js).
5. The frontend downloads templates and config from the API using a single batch request.
6. The frontend stores reports and images locally in IndexedDB.
7. Reports can be submitted to the server via `POST /api/v1/reports`.
## Root Files
### [package.json](package.json)
Role:
Defines the Node.js project itself.
What it contains:
- project name and version
- npm scripts such as `start`, `dev`, and `test:environment`
- dependency list such as `express`, `mariadb`, and `dotenv`
Why it matters:
When you run `npm install` or `npm start`, Node uses this file to know how the project should behave.
### [README.md](README.md)
Role:
Main entry document for developers.
What it contains:
- project purpose
- setup steps
- available endpoints
- development notes
Why it matters:
This is the first file a new developer should read before touching the code.
### [docker-compose.yml](docker-compose.yml)
Role:
Starts the full local development environment.
What it contains:
- the application container
- the MariaDB container
- the phpMyAdmin container
- port mappings and volume configuration
Why it matters:
Instead of installing and configuring everything manually, you can start the full stack with one command.
### [.env.example](.env.example)
Role:
Example environment configuration.
What it contains:
- default port values
- database host, name, user, and password placeholders
Why it matters:
It shows which environment variables the application expects.
### [.env](.env)
Role:
Real environment file used on the current machine.
What it contains:
- actual local values for ports and database credentials
Why it matters:
The backend reads this file during startup through `dotenv`.
## Public Folder
The [public](public) folder contains files that are sent directly to the browser.
### [public/user.html](public/user.html)
Role:
Operator workspace HTML shell.
What it contains:
- shared sidebar with template selector, sync button, report list, and search/filter
- report editor main area with hero, summary cards, form, inspector panel
- report list item `<template>` for runtime rendering
When you edit it:
- when you need to change the report editing layout
- when adding new user-facing controls or sections
### [public/admin.html](public/admin.html)
Role:
Administrator workspace HTML shell.
What it contains:
- simplified sidebar with template selector and sync button (no report list)
- admin main area with image policy editor form and admin summary panel
When you edit it:
- when adding new admin configuration panels
- when changing the image policy form fields
### [public/index.html](public/index.html)
Role:
Legacy combined app shell (no longer served by routes).
Note:
This file has been superseded by [user.html](public/user.html) and [admin.html](public/admin.html).
It remains in the repository for reference but is not routed to by the Express server.
### [public/portal.html](public/portal.html)
Role:
Simple chooser page that lets the user open either the user area or the admin area.
What it contains:
- a short explanation of the two entry points
- a link to `/user`
- a link to `/admin`
What it does:
It is the landing page served at `/`. It does not contain complex logic. Its job is only to separate the entry points.
### [public/app.js](public/app.js)
Role:
Thin orchestrator entry point for the frontend.
What it contains:
- imports from all ES modules under `public/js/`
- startup flow (`init()`, `cacheElements()`, `bindEvents()`)
- report CRUD operations (create, open, delete, submit)
- sync logic with the API using batch template fetch
- dirty-flag autosave loop
- admin image-policy save
- event delegation for the report list
- search/filter event wiring
- null guards for page-specific elements (user vs admin)
What changed:
This file was originally a monolithic ~1700-line file. It has been split into modules (A1)
and now acts as a controller. It is shared between user.html and admin.html — it detects
which DOM elements exist and only binds behavior for the current page.
### [public/styles.css](public/styles.css)
Role:
Main styling file for the frontend.
What it contains:
- color variables
- layout rules
- sidebar and panel styles
- form field styles
- admin and user page styles
- responsive behavior for smaller screens
What it does:
It controls how the application looks on desktop and mobile.
When you edit it:
- when spacing or sizing is wrong
- when a section needs a new visual style
- when mobile layout needs improvement
### [public/sw.js](public/sw.js)
Role:
Service worker for offline behavior.
What it contains:
- cache name
- app shell file list (including all new JS modules)
- install, activate, and fetch event handlers
- LRU cache trimming for dynamic entries (P5)
What it does:
It tells the browser how to cache frontend files and API responses.
Important behavior:
- static files use cache-first strategy
- API calls use network-first strategy
- dynamic cache is bounded to prevent unbounded storage growth
### [public/icon.svg](public/icon.svg)
Role:
SVG icon used by the PWA manifest (F5).
### Frontend ES Modules (public/js/)
These modules were extracted from the original monolithic `app.js` (A1).
All render functions include null guards so the shared `app.js` can safely run on
both user.html (operator workspace) and admin.html (administrator workspace).
### [public/js/constants.js](public/js/constants.js)
Role:
Shared constants used across frontend modules.
What it contains:
- IndexedDB name, version, and store names
- API base path (`/api/v1`)
- autosave interval, render debounce timing, cache limits
### [public/js/state.js](public/js/state.js)
Role:
Centralized state management for the frontend.
What it contains:
- `state` object with all application state (including dirty flag, search query, filter)
- `elements` object for cached DOM references
- `getCurrentReport()` and `getTemplateRecord()` helpers
- `stateHelpers` bundle used by other modules to avoid circular imports
### [public/js/i18n.js](public/js/i18n.js)
Role:
Internationalization locale extraction (F7).
What it contains:
- English locale with ~80 UI string keys
- `t(key, ...params)` translation function with placeholder replacement
- `setLocale()` for future language support
### [public/js/utils.js](public/js/utils.js)
Role:
Pure utility and formatting functions.
What it contains:
- `prettifyStatus()`, `formatDateTime()`, `formatTime()`, `formatRelativeTime()`, `formatFileSize()`
- `sanitizeForFilename()`, `generateReportNumber()`, `buildGeneratedFilename()`
- `makeTemplateKey()`, `deriveTemplateCatalog()`
- `debounce()` helper for rate-limiting function calls (P2)
### [public/js/db.js](public/js/db.js)
Role:
IndexedDB operations with multi-store transaction support.
What it contains:
- `openDatabase()` with schema version 2
- CRUD helpers: `dbGetAll()`, `dbGet()`, `dbPut()`, `dbDelete()`, `dbGetAllByIndex()`
- `dbTransaction()` for atomic multi-store operations (A5)
- `saveSetting()` and `loadSetting()` for UI preferences
### [public/js/api.js](public/js/api.js)
Role:
API communication layer with versioned base path (A3).
What it contains:
- `fetchJson(path, options)` that prepends the API base path automatically
- `registerServiceWorker()`
### [public/js/validation.js](public/js/validation.js)
Role:
Shared validation logic for reports and admin forms (A7).
What it contains:
- `validateReport()` — checks required fields, number ranges, attachment counts
- `validateImageRulesPayload()` — validates image policy form submissions
- `evaluateRequiredWhen()` — conditional field requirement logic
- `isBlankValue()` — blank check by field type
### [public/js/images.js](public/js/images.js)
Role:
Image optimization with Web Worker support (P1).
What it contains:
- `optimizeImage(file, imageRules)` — automatically detects Web Worker support
- Worker path: delegates to `image-worker.js` via `OffscreenCanvas`
- Falls back to main-thread canvas when OffscreenCanvas is unavailable
### [public/js/image-worker.js](public/js/image-worker.js)
Role:
Web Worker for background image processing (P1).
What it contains:
- `self.onmessage` handler using `createImageBitmap` and `OffscreenCanvas`
- Sends optimized blob back to main thread with matching message ID
### [public/js/forms.js](public/js/forms.js)
Role:
Dynamic form field creation from template JSON.
What it contains:
- `createFieldNode(field, report, callbacks)` — renders fields with callback pattern
- `createAttachmentFieldNode()` with IntersectionObserver for lazy-loading thumbnails (P3)
- `escapeHtml()` for XSS prevention
### [public/js/renderer.js](public/js/renderer.js)
Role:
All DOM render functions with search and filter support (F4).
What it contains:
- `render()` orchestrator — conditionally calls user or admin renders
- `renderReportList()` — filters by search query and status
- `renderCurrentReport(fieldCallbacks)` — accepts callbacks for field changes
- `renderTemplateSelector()`, `renderTemplateSummary()`
- `renderSyncSummary()`, `renderImagePolicy()`, `renderAdminImageRules()`
- `updateConnectionBadge()`, `updateSaveBadge()`
- Uses `t()` for all user-visible strings
- Null guards on all page-specific functions for safe user/admin coexistence
### [public/js/export.js](public/js/export.js)
Role:
Report data export functionality (F2).
What it contains:
- `exportReportCSV()` — generates CSV from template fields and report answers
- `exportReportAttachments()` — triggers download for each attachment blob
- `csvEscape()` and `downloadBlob()` helper functions
### [public/manifest.webmanifest](public/manifest.webmanifest)
Role:
Basic PWA metadata file.
What it contains:
- app name
- short name
- theme color
- start URL
What it does:
Helps the browser treat the app more like an installable web application.
## Source Folder
The [src](src) folder contains backend code.
### [src/server.js](src/server.js)
Role:
Real server startup file.
What it contains:
- startup function
- database connection check
- Express app startup
- graceful shutdown logic
What it does:
This is the file Node runs when the backend starts.
Simple mental model:
- load the Express app
- make sure MariaDB is reachable
- start listening on a port
- close cleanly when the process is stopped
### [src/app.js](src/app.js)
Role:
Express application configuration file.
What it contains:
- middleware registration
- API v1 route registration under `/api/v1/` prefix (A3)
- static file serving
- frontend entry page routes
- global error handling
Important routes:
- `/api/v1/...` for versioned backend endpoints
- `/` for the chooser page
- `/user` and `/admin` for the frontend app shell
## Source Subfolders
### [src/config/env.js](src/config/env.js)
Role:
Loads and validates environment variables.
What it contains:
- `dotenv` setup
- required environment key checks
- normalized `env` object export
What it does:
It reads raw values from `.env` and converts them into a safer object the rest of the code can use.
Why this is useful:
Instead of reading `process.env` everywhere, the app reads from one clean place.
### [src/db/pool.js](src/db/pool.js)
Role:
Creates and manages the MariaDB connection pool.
What it contains:
- one shared database pool
- `query()` helper
- `closePool()` helper
What it does:
It gives the service layer a standard way to run SQL queries.
Why it matters:
Without this file, each route or service would have to manage its own connections, which would be messy and error-prone.
### [src/middleware/errorHandler.js](src/middleware/errorHandler.js)
Role:
Handles not-found routes and server errors.
What it contains:
- `notFoundHandler`
- `errorHandler`
What it does:
When a route does not exist, or when code throws an error, this file creates a JSON response instead of letting the app fail in an uncontrolled way.
### [src/middleware/validateParams.js](src/middleware/validateParams.js)
Role:
URL parameter validation middleware (A7).
What it contains:
- `validateParam(name)` — checks route params against safe patterns (code or UUID)
- `validateNumericParam(name)` — validates numeric route parameters
What it does:
It rejects malformed URL parameters at the middleware level before they reach route handlers.
### [src/routes/healthRoutes.js](src/routes/healthRoutes.js)
Role:
Defines the health-check endpoint.
What it contains:
- `GET /api/health`
What it does:
Checks whether the server and database are working.
Why it matters:
This endpoint is used by tests and is also useful when debugging container problems.
### [src/routes/templateRoutes.js](src/routes/templateRoutes.js)
Role:
Defines template-related API endpoints.
What it contains:
- list endpoint for active templates
- batch endpoint with `?include=definitions` for single-request sync (A2)
- endpoint for one active template
- endpoint for a specific template version
- version listing for a template (F3)
- version publishing endpoint (F3)
- parameter validation middleware
- LRU cache integration (P4)
### [src/routes/lookupRoutes.js](src/routes/lookupRoutes.js)
Role:
Defines lookup-related API endpoints.
What it contains:
- list endpoint for lookup sets
- endpoint for one lookup set
- parameter validation and LRU cache integration
### [src/routes/configRoutes.js](src/routes/configRoutes.js)
Role:
Defines configuration-related API endpoints.
What it contains:
- image rule read and update endpoints
- export profile endpoint
- general app config endpoint
- LRU cache read-through and invalidation (P4)
- audit trail logging on image rules update (F6)
### [src/routes/reportRoutes.js](src/routes/reportRoutes.js)
Role:
Defines report submission API endpoints (F1).
What it contains:
- `GET /` — list submitted reports with filters (status, templateCode, limit, offset)
- `GET /:reportId` — single report by UUID
- `POST /` — submit or update a report (UPSERT by UUID, audit-logged)
### [src/services/templateService.js](src/services/templateService.js)
Role:
Handles template-related database queries.
What it contains:
- SQL for active template list
- `getAllActiveTemplates()` — batch query returning all templates with definitions (A2)
- `listTemplateVersions()` — all versions of a given template (F3)
- `publishTemplateVersion()` — retire current active, activate specified version (F3)
- template row mapping logic
### [src/services/lookupService.js](src/services/lookupService.js)
Role:
Handles lookup-related database queries.
### [src/services/configService.js](src/services/configService.js)
Role:
Handles configuration-related database queries.
### [src/services/reportService.js](src/services/reportService.js)
Role:
Handles report submission and retrieval (F1).
What it contains:
- `submitReport(report)` — UPSERT by report UUID
- `getReport(uuid)` — fetch single report
- `listReports({ status, templateCode, limit, offset })` — filtered listing
### [src/services/auditService.js](src/services/auditService.js)
Role:
Audit trail logging for admin mutations (F6).
What it contains:
- `logAuditEvent({ entityType, entityCode, action, oldValue, newValue })` — writes to audit_log table
- `getAuditLog()` — reads audit entries with optional filters
### [src/services/cacheService.js](src/services/cacheService.js)
Role:
In-memory LRU cache with TTL for server-side data (P4).
What it contains:
- `createCache({ maxEntries, ttlMs })` factory function
- Pre-configured singletons: `templateCache`, `lookupCache`, `configCache`
- Each cache instance has `get()`, `set()`, `delete()`, and `clear()` methods
### [src/utils/asyncHandler.js](src/utils/asyncHandler.js)
Role:
Small helper for async Express routes.
What it contains:
- `asyncHandler()` wrapper
What it does:
It catches rejected async route errors and forwards them to Express error middleware.
Why it matters:
Without it, every async route would need repetitive `try/catch` blocks.
### [src/utils/json.js](src/utils/json.js)
Role:
Small helper for parsing JSON values coming from MariaDB.
What it contains:
- `parseJsonColumn()`
What it does:
It safely converts JSON strings into objects and arrays.
Why it matters:
Several database columns store JSON text, and this helper prevents the same parsing logic from being repeated in multiple files.
## SQL Folder
### [sql/schema.sql](sql/schema.sql)
Role:
Creates the database structure.
What it contains:
- database creation
- table definitions
- keys and foreign keys
What it does:
It defines how templates, lookups, image rules, export profiles, and app config are stored.
### [sql/seed.sql](sql/seed.sql)
Role:
Inserts example data.
What it contains:
- one example checklist template
- lookup values
- one image policy
- one export profile
- app config values
What it does:
It gives the frontend and API something real to work with immediately after startup.
## Scripts Folder
### [scripts/test-environment.js](scripts/test-environment.js)
Role:
Simple smoke test for the local environment.
What it contains:
- API health checks
- template endpoint checks
- direct database checks
- phpMyAdmin checks
What it does:
It verifies that the main development services are working together.
When to use it:
- after starting Docker containers
- after changing infrastructure-related code
- after big refactors when you want a quick confidence check
## Recommended Reading Order For A Junior Developer
If you are new to this project, a good reading order is:
1. [README.md](README.md)
2. [PROJECT_FILES_GUIDE.md](PROJECT_FILES_GUIDE.md)
3. [src/server.js](src/server.js)
4. [src/app.js](src/app.js)
5. [src/routes/templateRoutes.js](src/routes/templateRoutes.js)
6. [src/services/templateService.js](src/services/templateService.js)
7. [public/js/constants.js](public/js/constants.js) and [public/js/state.js](public/js/state.js)
8. [public/app.js](public/app.js) — the thin orchestrator that wires everything together
9. [public/js/renderer.js](public/js/renderer.js) and [public/js/forms.js](public/js/forms.js)
7. [public/index.html](public/index.html)
8. [public/app.js](public/app.js)
9. [sql/schema.sql](sql/schema.sql)
10. [sql/seed.sql](sql/seed.sql)
That order helps because it moves from the high-level entry points into the deeper details.
## Practical Rule Of Thumb
When you are trying to change something, use this shortcut:
- if the browser layout looks wrong, check [public/index.html](public/index.html) and [public/styles.css](public/styles.css)
- if browser behavior is wrong, check [public/app.js](public/app.js)
- if an API endpoint is wrong, check [src/routes](src/routes) first and then [src/services](src/services)
- if database data is wrong, check [sql/schema.sql](sql/schema.sql), [sql/seed.sql](sql/seed.sql), and the service file that runs the query
- if the app does not start, check [src/server.js](src/server.js), [src/config/env.js](src/config/env.js), and [docker-compose.yml](docker-compose.yml)
This simple rule is often enough to help you find the right file quickly.