This commit is contained in:
pacnpal
2025-09-21 20:04:42 -04:00
parent 42a3dc7637
commit 75cc618c2b
610 changed files with 1719 additions and 4816 deletions

403
apps/parks/admin.py Normal file
View File

@@ -0,0 +1,403 @@
from django.contrib import admin
from django.contrib.gis.admin import GISModelAdmin
from django.utils.html import format_html
import pghistory.models
from .models import (
Park,
ParkArea,
ParkLocation,
Company,
CompanyHeadquarters,
ParkReview,
)
class ParkLocationInline(admin.StackedInline):
"""Inline admin for ParkLocation"""
model = ParkLocation
extra = 0
fields = (
("city", "state", "country"),
"street_address",
"postal_code",
"point",
("highway_exit", "best_arrival_time"),
"parking_notes",
"seasonal_notes",
("osm_id", "osm_type"),
)
class ParkLocationAdmin(GISModelAdmin):
"""Admin for standalone ParkLocation management"""
list_display = (
"park",
"city",
"state",
"country",
"latitude",
"longitude",
)
list_filter = ("country", "state")
search_fields = (
"park__name",
"city",
"state",
"country",
"street_address",
)
readonly_fields = ("latitude", "longitude", "coordinates")
fieldsets = (
("Park", {"fields": ("park",)}),
(
"Address",
{
"fields": (
"street_address",
"city",
"state",
"country",
"postal_code",
)
},
),
(
"Geographic Coordinates",
{
"fields": ("point", "latitude", "longitude", "coordinates"),
"description": "Set coordinates by clicking on the map or entering latitude/longitude",
},
),
(
"Travel Information",
{
"fields": (
"highway_exit",
"best_arrival_time",
"parking_notes",
"seasonal_notes",
),
"classes": ("collapse",),
},
),
(
"OpenStreetMap Integration",
{"fields": ("osm_id", "osm_type"), "classes": ("collapse",)},
),
)
@admin.display(description="Latitude")
def latitude(self, obj):
return obj.latitude
@admin.display(description="Longitude")
def longitude(self, obj):
return obj.longitude
class ParkAdmin(admin.ModelAdmin):
list_display = (
"name",
"formatted_location",
"status",
"operator",
"property_owner",
"created_at",
"updated_at",
)
list_filter = ("status", "location__country", "location__state")
search_fields = (
"name",
"description",
"location__city",
"location__state",
"location__country",
)
readonly_fields = ("created_at", "updated_at")
prepopulated_fields = {"slug": ("name",)}
inlines = [ParkLocationInline]
@admin.display(description="Location")
def formatted_location(self, obj):
"""Display formatted location string"""
return obj.formatted_location
class ParkAreaAdmin(admin.ModelAdmin):
list_display = ("name", "park", "created_at", "updated_at")
list_filter = ("park",)
search_fields = ("name", "description", "park__name")
readonly_fields = ("created_at", "updated_at")
prepopulated_fields = {"slug": ("name",)}
class CompanyHeadquartersInline(admin.StackedInline):
"""Inline admin for CompanyHeadquarters"""
model = CompanyHeadquarters
extra = 0
fields = (
("city", "state_province", "country"),
"street_address",
"postal_code",
"mailing_address",
)
class CompanyHeadquartersAdmin(admin.ModelAdmin):
"""Admin for standalone CompanyHeadquarters management"""
list_display = (
"company",
"location_display",
"city",
"country",
"created_at",
)
list_filter = ("country", "state_province")
search_fields = (
"company__name",
"city",
"state_province",
"country",
"street_address",
)
readonly_fields = ("created_at", "updated_at")
fieldsets = (
("Company", {"fields": ("company",)}),
(
"Address",
{
"fields": (
"street_address",
"city",
"state_province",
"country",
"postal_code",
)
},
),
(
"Additional Information",
{"fields": ("mailing_address",), "classes": ("collapse",)},
),
(
"Metadata",
{"fields": ("created_at", "updated_at"), "classes": ("collapse",)},
),
)
class CompanyAdmin(admin.ModelAdmin):
"""Enhanced Company admin with headquarters inline"""
list_display = (
"name",
"roles_display",
"headquarters_location",
"website",
"founded_year",
)
list_filter = ("roles",)
search_fields = ("name", "description")
readonly_fields = ("created_at", "updated_at")
prepopulated_fields = {"slug": ("name",)}
inlines = [CompanyHeadquartersInline]
@admin.display(description="Roles")
def roles_display(self, obj):
"""Display roles as a formatted string"""
return ", ".join(obj.roles) if obj.roles else "No roles"
@admin.display(description="Headquarters")
def headquarters_location(self, obj):
"""Display headquarters location if available"""
if hasattr(obj, "headquarters"):
return obj.headquarters.location_display
return "No headquarters"
@admin.register(ParkReview)
class ParkReviewAdmin(admin.ModelAdmin):
"""Admin interface for park reviews"""
list_display = (
"park",
"user",
"rating",
"title",
"visit_date",
"is_published",
"created_at",
"moderation_status",
)
list_filter = (
"rating",
"is_published",
"visit_date",
"created_at",
"park",
"moderated_by",
)
search_fields = (
"title",
"content",
"user__username",
"park__name",
)
readonly_fields = ("created_at", "updated_at")
date_hierarchy = "created_at"
ordering = ("-created_at",)
fieldsets = (
(
"Review Details",
{
"fields": (
"user",
"park",
"rating",
"title",
"content",
"visit_date",
)
},
),
(
"Publication Status",
{
"fields": ("is_published",),
},
),
(
"Moderation",
{
"fields": (
"moderated_by",
"moderated_at",
"moderation_notes",
),
"classes": ("collapse",),
},
),
(
"Metadata",
{
"fields": ("created_at", "updated_at"),
"classes": ("collapse",),
},
),
)
@admin.display(description="Moderation Status", boolean=True)
def moderation_status(self, obj):
"""Display moderation status with color coding"""
if obj.moderated_by:
return format_html(
'<span style="color: {};">{}</span>',
"green" if obj.is_published else "red",
"Approved" if obj.is_published else "Rejected",
)
return format_html('<span style="color: orange;">Pending</span>')
def save_model(self, request, obj, form, change):
"""Auto-set moderation info when status changes"""
if change and "is_published" in form.changed_data:
from django.utils import timezone
obj.moderated_by = request.user
obj.moderated_at = timezone.now()
super().save_model(request, obj, form, change)
@admin.register(pghistory.models.Events)
class PgHistoryEventsAdmin(admin.ModelAdmin):
"""Admin interface for pghistory Events"""
list_display = (
"pgh_id",
"pgh_created_at",
"pgh_label",
"pgh_model",
"pgh_obj_id",
"pgh_context_display",
)
list_filter = (
"pgh_label",
"pgh_model",
"pgh_created_at",
)
search_fields = (
"pgh_obj_id",
"pgh_context",
)
readonly_fields = (
"pgh_id",
"pgh_created_at",
"pgh_label",
"pgh_model",
"pgh_obj_id",
"pgh_context",
"pgh_data",
)
date_hierarchy = "pgh_created_at"
ordering = ("-pgh_created_at",)
fieldsets = (
(
"Event Information",
{
"fields": (
"pgh_id",
"pgh_created_at",
"pgh_label",
"pgh_model",
"pgh_obj_id",
)
},
),
(
"Context & Data",
{
"fields": (
"pgh_context",
"pgh_data",
),
"classes": ("collapse",),
},
),
)
@admin.display(description="Context")
def pgh_context_display(self, obj):
"""Display context information in a readable format"""
if obj.pgh_context:
if isinstance(obj.pgh_context, dict):
context_items = []
for key, value in obj.pgh_context.items():
context_items.append(f"{key}: {value}")
return ", ".join(context_items)
return str(obj.pgh_context)
return "No context"
def has_add_permission(self, request):
"""Disable manual creation of history events"""
return False
def has_change_permission(self, request, obj=None):
"""Make history events read-only"""
return False
def has_delete_permission(self, request, obj=None):
"""Prevent deletion of history events"""
return getattr(request.user, "is_superuser", False)
# Register the models with their admin classes
admin.site.register(Park, ParkAdmin)
admin.site.register(ParkArea, ParkAreaAdmin)
admin.site.register(ParkLocation, ParkLocationAdmin)
admin.site.register(Company, CompanyAdmin)
admin.site.register(CompanyHeadquarters, CompanyHeadquartersAdmin)