12 KiB
Phase 1 Frontend Feature Parity - Implementation Status
Date: November 9, 2025
Status: PARTIALLY COMPLETE (30% - 6 of 20 hours completed)
Overview
Phase 1 addresses critical missing features identified in the comprehensive frontend-backend audit to achieve 100% feature parity between the Django backend and the Supabase schema that the frontend expects.
✅ COMPLETED WORK (6 hours)
Task 1: Fixed Park Coordinate Update Bug (2 hours) ✅ COMPLETE
Problem: Park location coordinates couldn't be updated via API because the latitude and longitude parameters were passed to ParkSubmissionService.update_entity_submission() but never used.
Solution Implemented:
- File:
django/apps/entities/services/park_submission.py - Added override method that extracts and handles coordinates
- Coordinates now properly update when moderators bypass the Sacred Pipeline
- Full tracking through ContentSubmission for audit trail
Files Modified:
django/apps/entities/services/park_submission.py
Task 2: Implemented Ride Name History Model & API (4 hours) ✅ COMPLETE
Frontend Usage: Used in 34+ places across 6 files (RideDetail.tsx, FormerNamesSection.tsx, FormerNamesEditor.tsx, etc.)
Completed:
- ✅ Created
RideNameHistorymodel indjango/apps/entities/models.py - ✅ Generated migration
django/apps/entities/migrations/0007_add_ride_name_history.py - ✅ Added admin interface with
RideNameHistoryInlineindjango/apps/entities/admin.py - ✅ Created
RideNameHistoryOutschema indjango/api/v1/schemas.py - ✅ Added API endpoint
GET /api/v1/rides/{ride_id}/name-history/indjango/api/v1/endpoints/rides.py
Model Features:
@pghistory.track()
class RideNameHistory(BaseModel):
ride = models.ForeignKey('Ride', on_delete=models.CASCADE, related_name='name_history')
former_name = models.CharField(max_length=255, db_index=True)
from_year = models.IntegerField(null=True, blank=True)
to_year = models.IntegerField(null=True, blank=True)
date_changed = models.DateField(null=True, blank=True)
date_changed_precision = models.CharField(max_length=20, null=True, blank=True)
reason = models.TextField(null=True, blank=True)
order_index = models.IntegerField(null=True, blank=True, db_index=True)
API Endpoint:
- URL:
GET /api/v1/rides/{ride_id}/name-history/ - Response: List of historical names with date ranges
- Authentication: Not required for read access
Files Modified:
django/apps/entities/models.pydjango/apps/entities/migrations/0007_add_ride_name_history.pydjango/apps/entities/admin.pydjango/api/v1/schemas.pydjango/api/v1/endpoints/rides.py
🔄 IN PROGRESS WORK
Task 3: Implement Entity Timeline Events (Started - 0 of 6 hours)
Frontend Usage: 5 files actively use this: EntityTimelineManager.tsx, entitySubmissionHelpers.ts, systemActivityService.ts
Progress:
- ✅ Created timeline app structure (
django/apps/timeline/) - ✅ Created
__init__.pyandapps.py - ⏳ NEXT: Create EntityTimelineEvent model
- ⏳ Generate and run migration
- ⏳ Add admin interface
- ⏳ Create timeline API endpoints
- ⏳ Update settings.py
Required Model Structure:
@pghistory.track()
class EntityTimelineEvent(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
entity_id = models.UUIDField(db_index=True)
entity_type = models.CharField(max_length=50, db_index=True)
event_type = models.CharField(max_length=100)
event_date = models.DateField()
event_date_precision = models.CharField(max_length=20, null=True)
title = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
# Event details
from_entity_id = models.UUIDField(null=True, blank=True)
to_entity_id = models.UUIDField(null=True, blank=True)
from_location = models.ForeignKey('entities.Location', null=True, on_delete=models.SET_NULL, related_name='+')
to_location = models.ForeignKey('entities.Location', null=True, on_delete=models.SET_NULL, related_name='+')
from_value = models.TextField(null=True, blank=True)
to_value = models.TextField(null=True, blank=True)
# Moderation
is_public = models.BooleanField(default=True)
display_order = models.IntegerField(null=True, blank=True)
# Tracking
created_by = models.ForeignKey('users.User', null=True, on_delete=models.SET_NULL)
approved_by = models.ForeignKey('users.User', null=True, on_delete=models.SET_NULL, related_name='+')
submission = models.ForeignKey('moderation.ContentSubmission', null=True, on_delete=models.SET_NULL)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-event_date', '-created_at']
indexes = [
models.Index(fields=['entity_type', 'entity_id', '-event_date']),
models.Index(fields=['event_type', '-event_date']),
]
Required API Endpoints:
GET /api/v1/timeline/entity/{entity_type}/{entity_id}/- Get timeline for entityGET /api/v1/timeline/recent/- Get recent timeline eventsPOST /api/v1/timeline/- Create timeline event (moderators)PATCH /api/v1/timeline/{id}/- Update timeline event (moderators)DELETE /api/v1/timeline/{id}/- Delete timeline event (moderators)
⏳ PENDING WORK (14 hours remaining)
Task 4: Implement Reports System (8 hours) - NOT STARTED
Frontend Usage: 7 files actively use reporting: ReportButton.tsx, ReportsQueue.tsx, RecentActivity.tsx, useModerationStats.ts, systemActivityService.ts
Required Implementation:
-
Create reports app (
django/apps/reports/)__init__.py,apps.py,models.py,admin.py,services.py
-
Create Report model:
@pghistory.track()
class Report(models.Model):
STATUS_CHOICES = [
('pending', 'Pending'),
('reviewing', 'Under Review'),
('resolved', 'Resolved'),
('dismissed', 'Dismissed'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
report_type = models.CharField(max_length=50)
reported_entity_id = models.UUIDField(db_index=True)
reported_entity_type = models.CharField(max_length=50, db_index=True)
reporter = models.ForeignKey('users.User', on_delete=models.CASCADE, related_name='reports_filed')
reason = models.TextField(null=True, blank=True)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', db_index=True)
reviewed_by = models.ForeignKey('users.User', null=True, on_delete=models.SET_NULL, related_name='reports_reviewed')
reviewed_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
-
Create API endpoints:
POST /api/v1/reports/- Create reportGET /api/v1/reports/- List reports (moderators only)GET /api/v1/reports/{id}/- Get report detailPATCH /api/v1/reports/{id}/- Update status (moderators)GET /api/v1/reports/stats/- Statistics (moderators)
-
Implement permissions:
- Users can create reports
- Only moderators can view/review reports
- Moderators can update status and add review notes
-
Add admin interface with Unfold theme
-
Update settings.py to include 'apps.reports'
📋 IMPLEMENTATION CHECKLIST
Immediate Next Steps (Task 3 Completion)
- Create
django/apps/timeline/models.pywith EntityTimelineEvent model - Generate migration:
python manage.py makemigrations timeline - Run migration:
python manage.py migrate timeline - Create
django/apps/timeline/admin.pywith EntityTimelineEventAdmin - Add 'apps.timeline' to
config/settings/base.pyINSTALLED_APPS - Create timeline API schemas in
django/api/v1/schemas.py - Create
django/api/v1/endpoints/timeline.pywith endpoints - Add timeline router to
django/api/v1/api.py - Test timeline functionality
Task 4 Steps (Reports System)
- Create
django/apps/reports/directory - Create reports app files: init.py, apps.py, models.py, admin.py
- Create Report model with pghistory tracking
- Generate and run migration
- Add 'apps.reports' to settings INSTALLED_APPS
- Create report API schemas
- Create
django/api/v1/endpoints/reports.py - Implement permissions (users create, moderators review)
- Add reports router to API
- Create admin interface
- Test reporting functionality
- Document usage
Final Steps
- Run all pending migrations
- Test all new endpoints with curl/Postman
- Update API documentation
- Create completion document
- Mark Phase 1 as complete
🔧 Key Technical Patterns to Follow
1. All Models Must Use @pghistory.track()
import pghistory
@pghistory.track()
class MyModel(models.Model):
# fields here
2. Use Django Ninja for API Endpoints
from ninja import Router
router = Router(tags=["Timeline"])
@router.get("/{entity_type}/{entity_id}/", response={200: List[TimelineEventOut]})
def get_entity_timeline(request, entity_type: str, entity_id: UUID):
# implementation
3. Register in Admin with Unfold Theme
from unfold.admin import ModelAdmin
@admin.register(EntityTimelineEvent)
class EntityTimelineEventAdmin(ModelAdmin):
list_display = ['event_type', 'entity_type', 'entity_id', 'event_date']
4. Add Proper Database Indexes
class Meta:
indexes = [
models.Index(fields=['entity_type', 'entity_id', '-event_date']),
models.Index(fields=['status', 'created_at']),
]
5. Use BaseModel or VersionedModel for Timestamps
from apps.core.models import BaseModel
class MyModel(BaseModel):
# Automatically includes created_at, updated_at
📊 Progress Summary
Total Estimated: 20 hours
Completed: 6 hours (30%)
Remaining: 14 hours (70%)
- Task 1: ✅ Complete (2 hours)
- Task 2: ✅ Complete (4 hours)
- Task 3: 🔄 Started (0 of 6 hours completed)
- Task 4: ⏳ Not started (8 hours)
🚀 Recommendations
Option A: Complete Phase 1 Incrementally
Continue with Task 3 and Task 4 implementation. This is the original plan and provides full feature parity.
Pros:
- Complete feature parity with frontend
- All frontend code can function as expected
- No technical debt
Cons:
- Requires 14 more hours of development
- More complex to test all at once
Option B: Deploy What's Complete, Continue Later
Deploy Tasks 1 & 2 now, continue with Tasks 3 & 4 in Phase 2.
Pros:
- Immediate value from completed work
- Ride name history (heavily used feature) available now
- Can gather feedback before continuing
Cons:
- Frontend timeline features won't work until Task 3 complete
- Frontend reporting features won't work until Task 4 complete
- Requires two deployment cycles
Option C: Focus on High-Impact Features
Prioritize Task 3 (Timeline Events) which is used in 5 files, defer Task 4 (Reports) which could be implemented as an enhancement.
Pros:
- Balances completion time vs. impact
- Timeline is more core to entity tracking
- Reports could be a nice-to-have
Cons:
- Still leaves reporting incomplete
- Frontend reporting UI won't function
📝 Notes
- All implementations follow the "Sacred Pipeline" pattern for user-submitted data
- Timeline and Reports apps are independent and can be implemented in any order
- Migration
0007_add_ride_name_historyis ready to run - Timeline app structure is in place, ready for model implementation
📚 Reference Documentation
django/COMPREHENSIVE_FRONTEND_BACKEND_AUDIT.md- Original audit identifying these gapsdjango/PHASE_1_FRONTEND_PARITY_PARTIAL_COMPLETE.md- Previous progress documentationdjango/SACRED_PIPELINE_AUDIT_AND_IMPLEMENTATION_PLAN.md- Sacred Pipeline patternsdjango/API_GUIDE.md- API implementation patternsdjango/ADMIN_GUIDE.md- Admin interface patterns