mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-24 10:11:08 -05:00
Add secret management guide, client-side performance monitoring, and search accessibility enhancements
- Introduced a comprehensive Secret Management Guide detailing best practices, secret classification, development setup, production management, rotation procedures, and emergency protocols. - Implemented a client-side performance monitoring script to track various metrics including page load performance, paint metrics, layout shifts, and memory usage. - Enhanced search accessibility with keyboard navigation support for search results, ensuring compliance with WCAG standards and improving user experience.
This commit is contained in:
@@ -165,6 +165,8 @@ class RideModel(TrackedModel):
|
||||
url = models.URLField(blank=True, help_text="Frontend URL for this ride model")
|
||||
|
||||
class Meta(TrackedModel.Meta):
|
||||
verbose_name = "Ride Model"
|
||||
verbose_name_plural = "Ride Models"
|
||||
ordering = ["manufacturer__name", "name"]
|
||||
constraints = [
|
||||
# Unique constraints (replacing unique_together for better error messages)
|
||||
@@ -330,7 +332,10 @@ class RideModelVariant(TrackedModel):
|
||||
"""
|
||||
|
||||
ride_model = models.ForeignKey(
|
||||
RideModel, on_delete=models.CASCADE, related_name="variants"
|
||||
RideModel,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="variants",
|
||||
help_text="Base ride model this variant belongs to",
|
||||
)
|
||||
name = models.CharField(max_length=255, help_text="Name of this variant")
|
||||
description = models.TextField(
|
||||
@@ -339,16 +344,32 @@ class RideModelVariant(TrackedModel):
|
||||
|
||||
# Variant-specific specifications
|
||||
min_height_ft = models.DecimalField(
|
||||
max_digits=6, decimal_places=2, null=True, blank=True
|
||||
max_digits=6,
|
||||
decimal_places=2,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Minimum height for this variant",
|
||||
)
|
||||
max_height_ft = models.DecimalField(
|
||||
max_digits=6, decimal_places=2, null=True, blank=True
|
||||
max_digits=6,
|
||||
decimal_places=2,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Maximum height for this variant",
|
||||
)
|
||||
min_speed_mph = models.DecimalField(
|
||||
max_digits=5, decimal_places=2, null=True, blank=True
|
||||
max_digits=5,
|
||||
decimal_places=2,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Minimum speed for this variant",
|
||||
)
|
||||
max_speed_mph = models.DecimalField(
|
||||
max_digits=5, decimal_places=2, null=True, blank=True
|
||||
max_digits=5,
|
||||
decimal_places=2,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Maximum speed for this variant",
|
||||
)
|
||||
|
||||
# Distinguishing features
|
||||
@@ -357,6 +378,8 @@ class RideModelVariant(TrackedModel):
|
||||
)
|
||||
|
||||
class Meta(TrackedModel.Meta):
|
||||
verbose_name = "Ride Model Variant"
|
||||
verbose_name_plural = "Ride Model Variants"
|
||||
ordering = ["ride_model", "name"]
|
||||
unique_together = ["ride_model", "name"]
|
||||
|
||||
@@ -369,15 +392,22 @@ class RideModelPhoto(TrackedModel):
|
||||
"""Photos associated with ride models for catalog/promotional purposes."""
|
||||
|
||||
ride_model = models.ForeignKey(
|
||||
RideModel, on_delete=models.CASCADE, related_name="photos"
|
||||
RideModel,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="photos",
|
||||
help_text="Ride model this photo belongs to",
|
||||
)
|
||||
image = models.ForeignKey(
|
||||
'django_cloudflareimages_toolkit.CloudflareImage',
|
||||
on_delete=models.CASCADE,
|
||||
help_text="Photo of the ride model stored on Cloudflare Images"
|
||||
)
|
||||
caption = models.CharField(max_length=500, blank=True)
|
||||
alt_text = models.CharField(max_length=255, blank=True)
|
||||
caption = models.CharField(
|
||||
max_length=500, blank=True, help_text="Photo caption or description"
|
||||
)
|
||||
alt_text = models.CharField(
|
||||
max_length=255, blank=True, help_text="Alternative text for accessibility"
|
||||
)
|
||||
|
||||
# Photo metadata
|
||||
photo_type = RichChoiceField(
|
||||
@@ -393,11 +423,17 @@ class RideModelPhoto(TrackedModel):
|
||||
)
|
||||
|
||||
# Attribution
|
||||
photographer = models.CharField(max_length=255, blank=True)
|
||||
source = models.CharField(max_length=255, blank=True)
|
||||
copyright_info = models.CharField(max_length=255, blank=True)
|
||||
photographer = models.CharField(
|
||||
max_length=255, blank=True, help_text="Name of the photographer"
|
||||
)
|
||||
source = models.CharField(max_length=255, blank=True, help_text="Source of the photo")
|
||||
copyright_info = models.CharField(
|
||||
max_length=255, blank=True, help_text="Copyright information"
|
||||
)
|
||||
|
||||
class Meta(TrackedModel.Meta):
|
||||
verbose_name = "Ride Model Photo"
|
||||
verbose_name_plural = "Ride Model Photos"
|
||||
ordering = ["-is_primary", "-created_at"]
|
||||
|
||||
def __str__(self) -> str:
|
||||
@@ -420,7 +456,10 @@ class RideModelTechnicalSpec(TrackedModel):
|
||||
"""
|
||||
|
||||
ride_model = models.ForeignKey(
|
||||
RideModel, on_delete=models.CASCADE, related_name="technical_specs"
|
||||
RideModel,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="technical_specs",
|
||||
help_text="Ride model this specification belongs to",
|
||||
)
|
||||
|
||||
spec_category = RichChoiceField(
|
||||
@@ -442,6 +481,8 @@ class RideModelTechnicalSpec(TrackedModel):
|
||||
)
|
||||
|
||||
class Meta(TrackedModel.Meta):
|
||||
verbose_name = "Ride Model Technical Specification"
|
||||
verbose_name_plural = "Ride Model Technical Specifications"
|
||||
ordering = ["spec_category", "spec_name"]
|
||||
unique_together = ["ride_model", "spec_category", "spec_name"]
|
||||
|
||||
@@ -563,6 +604,8 @@ class Ride(StateMachineMixin, TrackedModel):
|
||||
)
|
||||
|
||||
class Meta(TrackedModel.Meta):
|
||||
verbose_name = "Ride"
|
||||
verbose_name_plural = "Rides"
|
||||
ordering = ["name"]
|
||||
unique_together = ["park", "slug"]
|
||||
constraints = [
|
||||
@@ -949,20 +992,41 @@ class RollerCoasterStats(models.Model):
|
||||
|
||||
|
||||
ride = models.OneToOneField(
|
||||
Ride, on_delete=models.CASCADE, related_name="coaster_stats"
|
||||
Ride,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="coaster_stats",
|
||||
help_text="Ride these statistics belong to",
|
||||
)
|
||||
height_ft = models.DecimalField(
|
||||
max_digits=6, decimal_places=2, null=True, blank=True
|
||||
max_digits=6,
|
||||
decimal_places=2,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Maximum height in feet",
|
||||
)
|
||||
length_ft = models.DecimalField(
|
||||
max_digits=7, decimal_places=2, null=True, blank=True
|
||||
max_digits=7,
|
||||
decimal_places=2,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Track length in feet",
|
||||
)
|
||||
speed_mph = models.DecimalField(
|
||||
max_digits=5, decimal_places=2, null=True, blank=True
|
||||
max_digits=5,
|
||||
decimal_places=2,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Maximum speed in mph",
|
||||
)
|
||||
inversions = models.PositiveIntegerField(
|
||||
default=0, help_text="Number of inversions"
|
||||
)
|
||||
ride_time_seconds = models.PositiveIntegerField(
|
||||
null=True, blank=True, help_text="Duration of the ride in seconds"
|
||||
)
|
||||
track_type = models.CharField(
|
||||
max_length=255, blank=True, help_text="Type of track (e.g., tubular steel, wooden)"
|
||||
)
|
||||
inversions = models.PositiveIntegerField(default=0)
|
||||
ride_time_seconds = models.PositiveIntegerField(null=True, blank=True)
|
||||
track_type = models.CharField(max_length=255, blank=True)
|
||||
track_material = RichChoiceField(
|
||||
choice_group="track_materials",
|
||||
domain="rides",
|
||||
@@ -980,7 +1044,11 @@ class RollerCoasterStats(models.Model):
|
||||
help_text="Roller coaster type classification"
|
||||
)
|
||||
max_drop_height_ft = models.DecimalField(
|
||||
max_digits=6, decimal_places=2, null=True, blank=True
|
||||
max_digits=6,
|
||||
decimal_places=2,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Maximum drop height in feet",
|
||||
)
|
||||
propulsion_system = RichChoiceField(
|
||||
choice_group="propulsion_systems",
|
||||
@@ -989,14 +1057,23 @@ class RollerCoasterStats(models.Model):
|
||||
default="CHAIN",
|
||||
help_text="Propulsion or lift system type"
|
||||
)
|
||||
train_style = models.CharField(max_length=255, blank=True)
|
||||
trains_count = models.PositiveIntegerField(null=True, blank=True)
|
||||
cars_per_train = models.PositiveIntegerField(null=True, blank=True)
|
||||
seats_per_car = models.PositiveIntegerField(null=True, blank=True)
|
||||
train_style = models.CharField(
|
||||
max_length=255, blank=True, help_text="Style of train (e.g., floorless, inverted)"
|
||||
)
|
||||
trains_count = models.PositiveIntegerField(
|
||||
null=True, blank=True, help_text="Number of trains"
|
||||
)
|
||||
cars_per_train = models.PositiveIntegerField(
|
||||
null=True, blank=True, help_text="Number of cars per train"
|
||||
)
|
||||
seats_per_car = models.PositiveIntegerField(
|
||||
null=True, blank=True, help_text="Number of seats per car"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Roller Coaster Statistics"
|
||||
verbose_name_plural = "Roller Coaster Statistics"
|
||||
ordering = ["ride"]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Stats for {self.ride.name}"
|
||||
|
||||
Reference in New Issue
Block a user