Compare commits

...

33 Commits

Author SHA1 Message Date
pacnpal
bb9d7607fb Merge branch 'main' into dependabot/pip/whitenoise-6.9.0 2025-02-10 17:19:54 -05:00
pacnpal
433f860fd2 Merge pull request #28 from pacnpal/dependabot/pip/django-htmx-1.22.0
[DEPENDABOT] Update: Bump django-htmx from 1.21.0 to 1.22.0
2025-02-10 17:19:15 -05:00
pacnpal
9c448a52ce Merge pull request #29 from pacnpal/dependabot/pip/django-allauth-65.4.1
[DEPENDABOT] Update: Bump django-allauth from 65.4.0 to 65.4.1
2025-02-10 17:19:04 -05:00
pacnpal
e2089ac76d Merge pull request #26 from pacnpal/dependabot/github_actions/actions/setup-python-5
[DEPENDABOT] Update Actions: Bump actions/setup-python from 4 to 5
2025-02-10 17:18:53 -05:00
pacnpal
19a5640615 Merge pull request #30 from pacnpal/dependabot/pip/django-tailwind-cli-4.0.1
[DEPENDABOT] Update: Bump django-tailwind-cli from 2.21.1 to 4.0.1
2025-02-10 17:18:27 -05:00
pacnpal
2b81681e46 Merge pull request #31 from pacnpal/dependabot/pip/pytest-django-4.10.0
[DEPENDABOT] Update: Bump pytest-django from 4.9.0 to 4.10.0
2025-02-10 17:16:37 -05:00
pacnpal
6bc412a325 Merge pull request #32 from pacnpal/dependabot/pip/django-pghistory-3.5.2
[DEPENDABOT] Update: Bump django-pghistory from 2.9.0 to 3.5.2
2025-02-10 17:16:13 -05:00
pacnpal
c2a7a98840 Merge pull request #37 from pacnpal/pacnpal-patch-3
Update README.md
2025-02-10 17:11:34 -05:00
pacnpal
e35470f193 Update README.md 2025-02-10 17:10:13 -05:00
pacnpal
88f7643c4e Merge pull request #35 from pacnpal/pacnpal-patch-2
Create README.md
2025-02-10 16:31:52 -05:00
pacnpal
c011f2edec Create README.md 2025-02-10 16:20:31 -05:00
pacnpal
b1eac7a356 Merge pull request #33 from pacnpal/dependabot/pip/django-cors-headers-4.7.0
[DEPENDABOT] Update: Bump django-cors-headers from 4.6.0 to 4.7.0
2025-02-10 16:12:25 -05:00
pacnpal
76ffdd7a20 Update review.yml 2025-02-10 15:03:59 -05:00
pacnpal
2fb975caba Update review.yml 2025-02-10 15:02:47 -05:00
pacnpal
c78299bc69 Update review.yml 2025-02-10 14:59:00 -05:00
pacnpal
dcb49b5611 Add ParkContextRequired mixin to enforce park context in ride views; update URLs and templates for global ride listing 2025-02-10 14:48:29 -05:00
pacnpal
b253be1aed Update review.yml 2025-02-10 13:36:58 -05:00
pacnpal
057a9ed70a Update review.yml 2025-02-10 13:36:34 -05:00
pacnpal
f5cdace56b Update review.yml 2025-02-10 13:36:19 -05:00
pacnpal
ed17b46ab4 Update review.yml 2025-02-10 13:36:06 -05:00
pacnpal
e140f66c39 Update review.yml 2025-02-10 13:35:29 -05:00
pacnpal
55c4456010 Update review.yml 2025-02-10 13:35:03 -05:00
pacnpal
a8b2661c2c Update review.yml 2025-02-10 13:32:21 -05:00
pacnpal
0713aea03f Update review.yml 2025-02-10 13:31:16 -05:00
pacnpal
0430d6941d Update review.yml 2025-02-10 13:28:58 -05:00
pacnpal
db29e822bb Add links to ride names in ride list template for improved navigation 2025-02-10 12:45:45 -05:00
dependabot[bot]
f4b806da68 [DEPENDABOT] Update: Bump django-cors-headers from 4.6.0 to 4.7.0
Bumps [django-cors-headers](https://github.com/adamchainz/django-cors-headers) from 4.6.0 to 4.7.0.
- [Changelog](https://github.com/adamchainz/django-cors-headers/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/adamchainz/django-cors-headers/compare/4.6.0...4.7.0)

---
updated-dependencies:
- dependency-name: django-cors-headers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 16:50:51 +00:00
dependabot[bot]
e2f99f42eb [DEPENDABOT] Update: Bump django-pghistory from 2.9.0 to 3.5.2
Bumps [django-pghistory](https://github.com/AmbitionEng/django-pghistory) from 2.9.0 to 3.5.2.
- [Release notes](https://github.com/AmbitionEng/django-pghistory/releases)
- [Changelog](https://github.com/AmbitionEng/django-pghistory/blob/main/CHANGELOG.md)
- [Commits](https://github.com/AmbitionEng/django-pghistory/compare/2.9.0...3.5.2)

---
updated-dependencies:
- dependency-name: django-pghistory
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 16:50:38 +00:00
dependabot[bot]
fcd1f725eb [DEPENDABOT] Update: Bump pytest-django from 4.9.0 to 4.10.0
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.9.0 to 4.10.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.9.0...v4.10.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 16:50:33 +00:00
dependabot[bot]
c284070d74 [DEPENDABOT] Update: Bump django-tailwind-cli from 2.21.1 to 4.0.1
Bumps [django-tailwind-cli](https://github.com/django-commons/django-tailwind-cli) from 2.21.1 to 4.0.1.
- [Release notes](https://github.com/django-commons/django-tailwind-cli/releases)
- [Changelog](https://github.com/django-commons/django-tailwind-cli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/django-commons/django-tailwind-cli/compare/2.21.1...4.0.1)

---
updated-dependencies:
- dependency-name: django-tailwind-cli
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 16:50:31 +00:00
dependabot[bot]
77e7cbc8f8 [DEPENDABOT] Update: Bump django-allauth from 65.4.0 to 65.4.1
Bumps [django-allauth](https://github.com/sponsors/pennersr) from 65.4.0 to 65.4.1.
- [Commits](https://github.com/sponsors/pennersr/commits)

---
updated-dependencies:
- dependency-name: django-allauth
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 16:50:27 +00:00
dependabot[bot]
d1fded7191 [DEPENDABOT] Update: Bump django-htmx from 1.21.0 to 1.22.0
Bumps [django-htmx](https://github.com/adamchainz/django-htmx) from 1.21.0 to 1.22.0.
- [Changelog](https://github.com/adamchainz/django-htmx/blob/main/docs/changelog.rst)
- [Commits](https://github.com/adamchainz/django-htmx/compare/1.21.0...1.22.0)

---
updated-dependencies:
- dependency-name: django-htmx
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 16:50:22 +00:00
dependabot[bot]
a17fa9a58a [DEPENDABOT] Update Actions: Bump actions/setup-python from 4 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 16:41:58 +00:00
8 changed files with 49 additions and 58 deletions

View File

@@ -27,7 +27,7 @@ jobs:
run: brew install gdal
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

View File

@@ -27,7 +27,7 @@ jobs:
fetch-depth: 0
- name: Run Claude Review
uses: pacnpal/claude-code-review@v1.0.7
uses: pacnpal/claude-code-review@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
anthropic-key: ${{ secrets.ANTHROPIC_API_KEY }}

1
README.md Normal file
View File

@@ -0,0 +1 @@
ThrillWiki.com

View File

@@ -1,10 +1,10 @@
# Django and REST framework
Django==5.1.6
djangorestframework==3.15.2
django-cors-headers==4.6.0
django-cors-headers==4.7.0
# Authentication
django-allauth==65.4.0
django-allauth==65.4.1
django-oauth-toolkit==3.0.1
dj-rest-auth==7.0.1 # Added for REST authentication endpoints
pyjwt==2.10.1
@@ -12,7 +12,7 @@ pyjwt==2.10.1
# Database
psycopg2-binary==2.9.10
dj-database-url==2.3.0
django-pghistory==2.9.0 # For model history tracking
django-pghistory==3.5.2 # For model history tracking
# Email
requests==2.32.3 # For ForwardEmail.net API
@@ -26,7 +26,7 @@ Pillow==11.1.0 # For image handling
django-cleanup==9.0.0 # Automatically delete files
piexif==1.1.3 # For image EXIF metadata handling
django-filter==24.3
django-htmx==1.21.0
django-htmx==1.22.0
whitenoise==6.9.0 # Static file serving
pycountry==24.6.1
@@ -34,7 +34,7 @@ pycountry==24.6.1
black==25.1.0
flake8==7.1.1
pytest==8.3.4
pytest-django==4.9.0
pytest-django==4.10.0
# WebSocket Support
channels==4.2.0
@@ -42,4 +42,4 @@ channels-redis==4.2.1
daphne==4.1.2
# React and Material UI will be handled via npm in the frontend directory
django-tailwind-cli==2.21.1
django-tailwind-cli==4.0.1

View File

@@ -7,7 +7,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from django.contrib.contenttypes.models import ContentType
from django.contrib import messages
from django.http import HttpRequest, HttpResponse
from django.http import HttpRequest, HttpResponse, Http404
from django.db.models import Count
from .models import (
Ride, RollerCoasterStats, RideModel, RideEvent,
@@ -21,6 +21,13 @@ from moderation.models import EditSubmission
from companies.models import Manufacturer
from designers.models import Designer
class ParkContextRequired:
"""Mixin to require park context for views"""
def dispatch(self, request, *args, **kwargs):
if 'park_slug' not in self.kwargs:
raise Http404("Park context is required")
return super().dispatch(request, *args, **kwargs)
def show_coaster_fields(request: HttpRequest) -> HttpResponse:
"""Show roller coaster specific fields based on category selection"""
category = request.GET.get('category')
@@ -61,7 +68,7 @@ class RideDetailView(HistoryMixin, DetailView):
return context
class RideCreateView(LoginRequiredMixin, CreateView):
class RideCreateView(LoginRequiredMixin, ParkContextRequired, CreateView):
"""View for creating a new ride"""
model = Ride
form_class = RideForm
@@ -69,17 +76,14 @@ class RideCreateView(LoginRequiredMixin, CreateView):
def get_success_url(self):
"""Get URL to redirect to after successful creation"""
if hasattr(self, 'park'):
return reverse('parks:rides:ride_detail', kwargs={
'park_slug': self.park.slug,
'ride_slug': self.object.slug
})
return reverse('rides:ride_detail', kwargs={'ride_slug': self.object.slug})
def get_form_kwargs(self):
"""Pass park to the form"""
kwargs = super().get_form_kwargs()
if 'park_slug' in self.kwargs:
self.park = get_object_or_404(Park, slug=self.kwargs['park_slug'])
kwargs['park'] = self.park
return kwargs
@@ -87,7 +91,6 @@ class RideCreateView(LoginRequiredMixin, CreateView):
def get_context_data(self, **kwargs):
"""Add park and park_slug to context"""
context = super().get_context_data(**kwargs)
if hasattr(self, 'park'):
context['park'] = self.park
context['park_slug'] = self.park.slug
context['is_edit'] = False
@@ -131,7 +134,7 @@ class RideCreateView(LoginRequiredMixin, CreateView):
return super().form_valid(form)
class RideUpdateView(LoginRequiredMixin, EditSubmissionMixin, UpdateView):
class RideUpdateView(LoginRequiredMixin, ParkContextRequired, EditSubmissionMixin, UpdateView):
"""View for updating an existing ride"""
model = Ride
form_class = RideForm
@@ -140,37 +143,25 @@ class RideUpdateView(LoginRequiredMixin, EditSubmissionMixin, UpdateView):
def get_success_url(self):
"""Get URL to redirect to after successful update"""
if hasattr(self, 'park'):
return reverse('parks:rides:ride_detail', kwargs={
'park_slug': self.park.slug,
'ride_slug': self.object.slug
})
return reverse('rides:ride_detail', kwargs={'ride_slug': self.object.slug})
def get_queryset(self):
"""Get ride for the specific park if park_slug is provided"""
queryset = Ride.objects.all()
if 'park_slug' in self.kwargs:
queryset = queryset.filter(park__slug=self.kwargs['park_slug'])
return queryset
"""Get ride for the specific park"""
return Ride.objects.filter(park__slug=self.kwargs['park_slug'])
def get_form_kwargs(self):
"""Pass park to the form"""
kwargs = super().get_form_kwargs()
# For park-specific URLs, use the park from the URL
if 'park_slug' in self.kwargs:
self.park = get_object_or_404(Park, slug=self.kwargs['park_slug'])
kwargs['park'] = self.park
# For global URLs, use the ride's park
else:
self.park = self.get_object().park
kwargs['park'] = self.park
return kwargs
def get_context_data(self, **kwargs):
"""Add park and park_slug to context"""
context = super().get_context_data(**kwargs)
if hasattr(self, 'park'):
context['park'] = self.park
context['park_slug'] = self.park.slug
context['is_edit'] = True

View File

@@ -99,7 +99,7 @@
<i class="fas fa-map-marker-alt"></i>
<span>Parks</span>
</a>
<a href="{% url 'rides:ride_list' %}" class="nav-link">
<a href="{% url 'rides:global_ride_list' %}" class="nav-link">
<i class="fas fa-rocket"></i>
<span>Rides</span>
</a>

View File

@@ -18,7 +18,7 @@
class="px-8 py-3 text-lg btn-primary">
Explore Parks
</a>
<a href="{% url 'rides:ride_list' %}"
<a href="{% url 'rides:global_ride_list' %}"
class="px-8 py-3 text-lg btn-secondary">
View Rides
</a>
@@ -40,7 +40,7 @@
</a>
<!-- Total Attractions -->
<a href="{% url 'rides:ride_list' %}"
<a href="{% url 'rides:global_ride_list' %}"
class="flex flex-col items-center justify-center p-6 text-center transition-transform transform bg-white rounded-lg shadow-lg dark:bg-gray-800 hover:-translate-y-1 hover:shadow-xl">
<div class="mb-2 text-4xl font-bold text-blue-600 dark:text-blue-400">
{{ stats.ride_count }}
@@ -51,7 +51,7 @@
</a>
<!-- Total Roller Coasters -->
<a href="{% url 'rides:roller_coasters' %}"
<a href="{% url 'rides:global_roller_coasters' %}"
class="flex flex-col items-center justify-center p-6 text-center transition-transform transform bg-white rounded-lg shadow-lg dark:bg-gray-800 hover:-translate-y-1 hover:shadow-xl">
<div class="mb-2 text-4xl font-bold text-blue-600 dark:text-blue-400">
{{ stats.coaster_count }}
@@ -108,7 +108,7 @@
</h2>
<div class="space-y-4">
{% for ride in popular_rides %}
<a href="{% url 'rides:ride_detail' ride.slug %}"
<a href="{% url 'parks:rides:ride_detail' ride.park.slug ride.slug %}"
class="relative block h-48 overflow-hidden transition-all rounded-lg group hover:-translate-y-1 hover:shadow-xl"
{% if ride.photos.first %}
style="background: linear-gradient(rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.7)), url('{{ ride.photos.first.image.url }}') center/cover no-repeat;"
@@ -147,7 +147,7 @@
{% for item in highest_rated %}
{% if item.park %}
<!-- This is a ride -->
<a href="{% url 'rides:ride_detail' item.slug %}"
<a href="{% url 'parks:rides:ride_detail' item.park.slug item.slug %}"
class="relative block h-48 overflow-hidden transition-all rounded-lg group hover:-translate-y-1 hover:shadow-xl"
{% if item.photos.first %}
style="background: linear-gradient(rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.7)), url('{{ item.photos.first.image.url }}') center/cover no-repeat;"

View File

@@ -32,12 +32,7 @@
Add Ride
</a>
{% else %}
<a href="{% url 'rides:ride_create' %}" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
</svg>
Add Ride
</a>
<!-- No add ride button in global view - rides must be added from park pages -->
{% endif %}
{% endif %}
</div>
@@ -45,7 +40,7 @@
<!-- Filters -->
<div class="p-4 mb-6 bg-white rounded-lg shadow dark:bg-gray-800">
<form class="grid grid-cols-1 gap-4 md:grid-cols-3"
hx-get="{% if park %}{% url 'parks:rides:ride_list' park.slug %}{% else %}{% url 'rides:ride_list' %}{% endif %}"
hx-get="{% if park %}{% url 'parks:rides:ride_list' park.slug %}{% else %}{% url 'rides:global_ride_list' %}{% endif %}"
hx-trigger="change from:select, input from:input[type='text']"
hx-target="#rides-grid"
hx-push-url="true">
@@ -90,6 +85,9 @@
{% for ride in rides %}
<div class="overflow-hidden transition-transform transform bg-white rounded-lg shadow-lg dark:bg-gray-800 hover:-translate-y-1">
<div class="aspect-w-16 aspect-h-9">
<a href="{% url 'parks:rides:ride_detail' ride.park.slug ride.slug %}"
class="text-gray-900 hover:text-blue-600 dark:text-white dark:hover:text-blue-400">
{{ ride.name }}
{% if ride.photos.exists %}
<img src="{{ ride.photos.first.image.url }}"
alt="{{ ride.name }}"
@@ -99,6 +97,7 @@
alt="{{ ride.name }}"
class="object-cover w-full">
{% endif %}
</a>
</div>
<div class="p-4">
<h2 class="mb-2 text-xl font-bold">