mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-23 02:11:08 -05:00
- Introduced reusable test utilities in `backend/tests/utils` for FSM transitions, HTMX interactions, and common scenarios. - Added factory functions for creating test submissions, parks, rides, and photo submissions. - Implemented assertion helpers for verifying state changes, toast notifications, and transition logs. - Created comprehensive state machine diagrams for all FSM-enabled models in `docs/STATE_DIAGRAMS.md`, detailing states, transitions, and guard conditions.
363 lines
10 KiB
Markdown
363 lines
10 KiB
Markdown
# System Patterns
|
|
|
|
## High-Level Architecture
|
|
|
|
### Backend Architecture
|
|
- Django-based MVT (Model-View-Template) architecture
|
|
- Modular app structure for domain separation
|
|
- HTMX for dynamic server-side rendering
|
|
- AlpineJS for client-side interactivity
|
|
|
|
### Core Apps
|
|
1. Parks & Rides
|
|
- parks/ - Park management
|
|
- rides/ - Ride information
|
|
- designers/ - Ride designer profiles
|
|
- companies/ - Park operator profiles
|
|
|
|
2. User Content
|
|
- reviews/ - User reviews
|
|
- media/ - Media management
|
|
- moderation/ - Content moderation
|
|
|
|
3. Supporting Systems
|
|
- accounts/ - User management
|
|
- analytics/ - Usage tracking
|
|
- location/ - Geographic services
|
|
- email_service/ - Communication
|
|
- history_tracking/ - Change tracking
|
|
|
|
## Core Technical Patterns
|
|
|
|
### Data Flow
|
|
1. Request Handling
|
|
- Django URL routing
|
|
- View processing
|
|
- HTMX partial updates
|
|
- Template rendering
|
|
|
|
2. Content Management
|
|
- Moderated submission flow
|
|
- Media processing pipeline
|
|
- Review validation system
|
|
- History tracking
|
|
|
|
3. User Interactions
|
|
- HTMX for dynamic updates
|
|
- AlpineJS for UI state
|
|
- Partial template loading
|
|
- Progressive enhancement
|
|
|
|
### Database Patterns
|
|
- Django ORM for data access
|
|
- Related models for complex relationships
|
|
- Signals for cross-model updates
|
|
- History tracking for changes
|
|
|
|
## Key Technical Decisions
|
|
|
|
### Frontend Strategy
|
|
1. Server-Side Rendering
|
|
- Django templates as base
|
|
- HTMX for dynamic updates
|
|
- Partial templates by model
|
|
- AlpineJS for client state
|
|
|
|
2. Styling
|
|
- Tailwind CSS
|
|
- Component-based design
|
|
- Responsive layouts
|
|
|
|
### Backend Organization
|
|
1. App Separation
|
|
- Domain-driven design
|
|
- Clear responsibility boundaries
|
|
- Modular functionality
|
|
- Reusable components
|
|
|
|
2. Code Structure
|
|
- Models for data definition
|
|
- Views for business logic
|
|
- Templates for presentation
|
|
- URLs for routing
|
|
- Signals for cross-cutting concerns
|
|
|
|
### Integration Patterns
|
|
1. External Services
|
|
- Email service integration
|
|
- Media storage handling
|
|
- Analytics tracking
|
|
- Location services
|
|
|
|
2. Internal Communication
|
|
- Django signals
|
|
- Context processors
|
|
- Middleware
|
|
- Template tags
|
|
|
|
## Data Flow Patterns
|
|
|
|
### Content Creation
|
|
1. User Input
|
|
- Form submission
|
|
- Media upload
|
|
- Review creation
|
|
- Park/ride updates
|
|
|
|
2. Processing
|
|
- Validation
|
|
- Moderation queue
|
|
- Media processing
|
|
- History tracking
|
|
|
|
3. Publication
|
|
- Approval workflow
|
|
- Public visibility
|
|
- Notification system
|
|
- Cache updates
|
|
|
|
### Query Patterns
|
|
1. Efficient Loading
|
|
- Select related
|
|
- Prefetch related
|
|
- Cached queries
|
|
- Optimized indexes
|
|
|
|
2. Search Operations
|
|
- Location-based queries
|
|
- Full-text search
|
|
- Filtered results
|
|
- Sorted listings
|
|
|
|
## FSM State Machine Integration with HTMX
|
|
|
|
### Overview
|
|
The codebase implements a reusable FSM (Finite State Machine) infrastructure using django-fsm, integrated with HTMX for seamless state transitions without full page reloads.
|
|
|
|
### Core Components
|
|
|
|
1. **FSMTransitionView** (`apps/core/views/views.py`)
|
|
- Generic view for handling FSM state transitions via HTMX POST requests
|
|
- Validates permissions using `can_proceed` from django-fsm
|
|
- Executes transitions and returns updated HTML partials
|
|
- Sends HX-Trigger headers for toast notifications
|
|
|
|
2. **FSM Template Tags** (`apps/core/templatetags/fsm_tags.py`)
|
|
- `get_available_transitions`: Returns available transitions for an object/user
|
|
- `get_state_value`: Gets current state value
|
|
- `get_state_display`: Gets human-readable state display
|
|
- `default_target_id`: Generates HTMX target IDs
|
|
- `app_label`, `model_name`: Model metadata filters
|
|
|
|
3. **Reusable Partials** (`templates/htmx/`)
|
|
- `status_with_actions.html`: Combined status badge with action buttons
|
|
- `state_actions.html`: Standalone action buttons
|
|
- `updated_row.html`: Generic fallback for row updates
|
|
|
|
### Integration Pattern
|
|
|
|
```django
|
|
{% load fsm_tags %}
|
|
|
|
<!-- Include FSM status and actions -->
|
|
{% include 'htmx/status_with_actions.html' with object=submission user=user show_badge=True %}
|
|
```
|
|
|
|
### FSM Transition Flow with HTMX
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant User
|
|
participant Browser
|
|
participant HTMX
|
|
participant FSMTransitionView
|
|
participant Model
|
|
participant Template
|
|
|
|
User->>Browser: Click "Approve" button
|
|
Browser->>HTMX: hx-post to FSM transition URL
|
|
HTMX->>FSMTransitionView: POST /moderation/submissions/<pk>/transition/transition_to_approved/
|
|
FSMTransitionView->>FSMTransitionView: Validate permissions (can_proceed)
|
|
FSMTransitionView->>Model: Execute transition
|
|
Model->>Model: Update status field + save
|
|
Model-->>FSMTransitionView: Return updated object
|
|
FSMTransitionView->>Template: Render model-specific partial
|
|
FSMTransitionView-->>HTMX: HTTP 200 + HX-Trigger: showToast
|
|
HTMX->>Browser: Swap target element with new HTML
|
|
HTMX->>Browser: Trigger showToast event
|
|
Browser->>User: Display updated row + success toast
|
|
```
|
|
|
|
### URL Pattern Configuration
|
|
|
|
FSM transitions use a consistent URL pattern:
|
|
```
|
|
/api/moderation/<model_plural>/<pk>/transition/<transition_name>/
|
|
```
|
|
|
|
Example URL patterns in `apps/moderation/urls.py`:
|
|
```python
|
|
path(
|
|
"submissions/<int:pk>/transition/<str:transition_name>/",
|
|
FSMTransitionView.as_view(),
|
|
{"app_label": "moderation", "model_name": "editsubmission"},
|
|
name="submission_transition",
|
|
)
|
|
```
|
|
|
|
### Template Resolution
|
|
|
|
FSMTransitionView automatically resolves model-specific templates:
|
|
1. `{app_label}/partials/{model_name}_row.html`
|
|
2. `{app_label}/partials/{model_name}_item.html`
|
|
3. `{app_label}/partials/{model_name}.html`
|
|
4. `htmx/updated_row.html` (fallback)
|
|
|
|
### Toast Notifications
|
|
|
|
The FSMTransitionView includes HX-Trigger headers for toast notifications:
|
|
```python
|
|
response["HX-Trigger"] = json.dumps({
|
|
"showToast": {
|
|
"message": "Submission approved successfully",
|
|
"type": "success"
|
|
}
|
|
})
|
|
```
|
|
|
|
Dashboard templates listen for these events with Alpine.js:
|
|
```javascript
|
|
@show-toast.window="showToast($event.detail)"
|
|
```
|
|
|
|
### Status Badge Styling
|
|
|
|
The `status_with_actions.html` partial includes automatic styling based on state:
|
|
- `PENDING` - Yellow (warning)
|
|
- `APPROVED` - Green (success)
|
|
- `REJECTED` - Red (danger)
|
|
- `ESCALATED` - Orange (caution)
|
|
- `IN_PROGRESS` - Blue (info)
|
|
|
|
### Flash Animations
|
|
|
|
Successful transitions include a flash animation class:
|
|
```css
|
|
.animate-flash-success {
|
|
animation: flash-success 1s ease-in-out;
|
|
}
|
|
```
|
|
|
|
### Error Handling Flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant User
|
|
participant Browser
|
|
participant HTMX
|
|
participant FSMTransitionView
|
|
participant PermissionGuard
|
|
|
|
User->>Browser: Click "Approve" button
|
|
Browser->>HTMX: hx-post with HX-Request header
|
|
HTMX->>FSMTransitionView: POST /transition/approve/
|
|
FSMTransitionView->>PermissionGuard: Check can_proceed(user)
|
|
|
|
alt Permission Denied
|
|
PermissionGuard-->>FSMTransitionView: False
|
|
FSMTransitionView-->>HTMX: 403 + HX-Trigger: showToast (error)
|
|
HTMX->>Browser: Trigger error toast event
|
|
Browser->>User: Display red error toast
|
|
else Permission Granted
|
|
PermissionGuard-->>FSMTransitionView: True
|
|
FSMTransitionView->>FSMTransitionView: Execute transition
|
|
alt Transition Success
|
|
FSMTransitionView-->>HTMX: 200 + HTML + HX-Trigger: showToast (success)
|
|
HTMX->>Browser: Swap HTML + trigger success toast
|
|
Browser->>User: Display updated row + green toast
|
|
else Transition Failed
|
|
FSMTransitionView-->>HTMX: 400 + HX-Trigger: showToast (error)
|
|
HTMX->>Browser: Trigger error toast event
|
|
Browser->>User: Display red error toast
|
|
end
|
|
end
|
|
```
|
|
|
|
### Error Response Types
|
|
|
|
| Status | Scenario | Toast Type | Message |
|
|
|--------|----------|------------|---------|
|
|
| 200 | Success | success | "{Model} has been {action}d successfully" |
|
|
| 400 | Invalid transition | error | "Transition not allowed from current state" |
|
|
| 403 | Permission denied | error | "You don't have permission for this action" |
|
|
| 404 | Object not found | error | "Object not found" |
|
|
| 500 | Server error | error | "An unexpected error occurred" |
|
|
|
|
### Testing FSM HTMX Transitions
|
|
|
|
#### Unit Tests
|
|
Backend unit tests in `apps/moderation/tests.py`, `apps/parks/tests.py`, and `apps/rides/tests.py` cover:
|
|
- FSM transition logic and state changes
|
|
- Permission guards and role-based access
|
|
- Transition history logging with django-fsm-log
|
|
- Callback execution and side effects
|
|
|
|
#### Integration Tests
|
|
Integration tests in `backend/tests/integration/test_fsm_transition_view.py` verify:
|
|
- FSMTransitionView handles HTMX requests correctly
|
|
- HX-Trigger headers contain proper toast data
|
|
- Correct partial templates rendered for each model
|
|
- Permission validation before transition execution
|
|
- StateLog entries created for each transition
|
|
|
|
#### E2E Tests
|
|
End-to-end tests using Playwright in `backend/tests/e2e/` validate:
|
|
- Complete user interaction flow from button click to UI update
|
|
- Toast notifications appear and auto-dismiss
|
|
- Loading indicators show during transitions
|
|
- Error handling displays user-friendly messages
|
|
- Permission guards prevent unauthorized transitions
|
|
- Cross-browser compatibility (Chrome, Firefox, Safari)
|
|
|
|
Test files:
|
|
- `test_moderation_fsm.py` - EditSubmission, PhotoSubmission transitions
|
|
- `test_park_ride_fsm.py` - Park and Ride status changes
|
|
- `test_fsm_permissions.py` - Permission guard verification
|
|
- `test_fsm_error_handling.py` - Error scenarios and loading states
|
|
|
|
#### Running Tests
|
|
```bash
|
|
# Run all FSM tests
|
|
pytest -k fsm
|
|
|
|
# Run e2e FSM tests
|
|
pytest backend/tests/e2e/test_moderation_fsm.py
|
|
pytest backend/tests/e2e/test_park_ride_fsm.py
|
|
pytest backend/tests/e2e/test_fsm_permissions.py
|
|
|
|
# Run with specific browser
|
|
pytest --browser firefox backend/tests/e2e/test_moderation_fsm.py
|
|
|
|
# Run with headed mode (see browser)
|
|
pytest --headed backend/tests/e2e/test_moderation_fsm.py
|
|
|
|
# Run integration tests (faster, no browser)
|
|
pytest backend/tests/integration/test_fsm_transition_view.py
|
|
```
|
|
|
|
#### Browser Testing Checklist
|
|
For comprehensive manual testing, see `backend/tests/e2e/BROWSER_TESTING_CHECKLIST.md`.
|
|
|
|
## Error Handling
|
|
- Django middleware
|
|
- Custom error pages
|
|
- Logging system
|
|
- User notifications
|
|
|
|
## Security Patterns
|
|
- Django authentication
|
|
- Permission mixins
|
|
- CSRF protection
|
|
- XSS prevention
|
|
- Input validation
|