Enhance moderation dashboard UI and UX:

- Add HTMX-powered filtering with instant updates
- Add smooth transitions and loading states
- Improve visual hierarchy and styling
- Add review notes functionality
- Add confirmation dialogs for actions
- Make navigation sticky
- Add hover effects and visual feedback
- Improve dark mode support
This commit is contained in:
pacnpal
2024-11-13 14:38:38 +00:00
parent d2c9d02523
commit 9ee380c3ea
98 changed files with 5073 additions and 3040 deletions

View File

@@ -1,5 +1,9 @@
from django.db import migrations, models
# Generated by Django 5.1.3 on 2024-11-12 18:07
import django.db.models.deletion
import simple_history.models
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
@@ -7,57 +11,228 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('companies', '0001_initial'),
("companies", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Park',
name="HistoricalPark",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('slug', models.SlugField(max_length=255, unique=True)),
('description', models.TextField(blank=True)),
('status', models.CharField(choices=[('OPERATING', 'Operating'), ('CLOSED_TEMP', 'Temporarily Closed'), ('CLOSED_PERM', 'Permanently Closed'), ('UNDER_CONSTRUCTION', 'Under Construction'), ('DEMOLISHED', 'Demolished'), ('RELOCATED', 'Relocated')], default='OPERATING', max_length=20)),
('opening_date', models.DateField(blank=True, null=True)),
('closing_date', models.DateField(blank=True, null=True)),
('operating_season', models.CharField(blank=True, max_length=255)),
('size_acres', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
('website', models.URLField(blank=True)),
('average_rating', models.DecimalField(blank=True, decimal_places=2, max_digits=3, null=True)),
('total_rides', models.IntegerField(blank=True, null=True)),
('total_roller_coasters', models.IntegerField(blank=True, null=True)),
('latitude', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
('longitude', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
('street_address', models.CharField(blank=True, max_length=255)),
('city', models.CharField(blank=True, max_length=255)),
('state', models.CharField(blank=True, max_length=255)),
('country', models.CharField(blank=True, max_length=255)),
('postal_code', models.CharField(blank=True, max_length=20)),
('created_at', models.DateTimeField(auto_now_add=True, null=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='parks', to='companies.company')),
("id", models.BigIntegerField(blank=True, db_index=True)),
("name", models.CharField(max_length=255)),
("slug", models.SlugField(max_length=255)),
("description", models.TextField(blank=True)),
(
"status",
models.CharField(
choices=[
("OPERATING", "Operating"),
("CLOSED_TEMP", "Temporarily Closed"),
("CLOSED_PERM", "Permanently Closed"),
("UNDER_CONSTRUCTION", "Under Construction"),
("DEMOLISHED", "Demolished"),
("RELOCATED", "Relocated"),
],
default="OPERATING",
max_length=20,
),
),
("opening_date", models.DateField(blank=True, null=True)),
("closing_date", models.DateField(blank=True, null=True)),
("operating_season", models.CharField(blank=True, max_length=255)),
(
"size_acres",
models.DecimalField(
blank=True, decimal_places=2, max_digits=10, null=True
),
),
("website", models.URLField(blank=True)),
(
"average_rating",
models.DecimalField(
blank=True, decimal_places=2, max_digits=3, null=True
),
),
("ride_count", models.IntegerField(blank=True, null=True)),
("coaster_count", models.IntegerField(blank=True, null=True)),
(
"created_at",
models.DateTimeField(blank=True, editable=False, null=True),
),
("updated_at", models.DateTimeField(blank=True, editable=False)),
("history_id", models.AutoField(primary_key=True, serialize=False)),
("history_date", models.DateTimeField(db_index=True)),
("history_change_reason", models.CharField(max_length=100, null=True)),
(
"history_type",
models.CharField(
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
max_length=1,
),
),
(
"history_user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to=settings.AUTH_USER_MODEL,
),
),
(
"owner",
models.ForeignKey(
blank=True,
db_constraint=False,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="companies.company",
),
),
],
options={
'ordering': ['name'],
"verbose_name": "historical park",
"verbose_name_plural": "historical parks",
"ordering": ("-history_date", "-history_id"),
"get_latest_by": ("history_date", "history_id"),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name="Park",
fields=[
("id", models.BigAutoField(primary_key=True, serialize=False)),
("name", models.CharField(max_length=255)),
("slug", models.SlugField(max_length=255, unique=True)),
("description", models.TextField(blank=True)),
(
"status",
models.CharField(
choices=[
("OPERATING", "Operating"),
("CLOSED_TEMP", "Temporarily Closed"),
("CLOSED_PERM", "Permanently Closed"),
("UNDER_CONSTRUCTION", "Under Construction"),
("DEMOLISHED", "Demolished"),
("RELOCATED", "Relocated"),
],
default="OPERATING",
max_length=20,
),
),
("opening_date", models.DateField(blank=True, null=True)),
("closing_date", models.DateField(blank=True, null=True)),
("operating_season", models.CharField(blank=True, max_length=255)),
(
"size_acres",
models.DecimalField(
blank=True, decimal_places=2, max_digits=10, null=True
),
),
("website", models.URLField(blank=True)),
(
"average_rating",
models.DecimalField(
blank=True, decimal_places=2, max_digits=3, null=True
),
),
("ride_count", models.IntegerField(blank=True, null=True)),
("coaster_count", models.IntegerField(blank=True, null=True)),
("created_at", models.DateTimeField(auto_now_add=True, null=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"owner",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="parks",
to="companies.company",
),
),
],
options={
"ordering": ["name"],
},
),
migrations.CreateModel(
name='ParkArea',
name="HistoricalParkArea",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('slug', models.SlugField(max_length=255)),
('description', models.TextField(blank=True)),
('opening_date', models.DateField(blank=True, null=True)),
('closing_date', models.DateField(blank=True, null=True)),
('created_at', models.DateTimeField(auto_now_add=True, null=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('park', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='areas', to='parks.park')),
("id", models.BigIntegerField(blank=True, db_index=True)),
("name", models.CharField(max_length=255)),
("slug", models.SlugField(max_length=255)),
("description", models.TextField(blank=True)),
("opening_date", models.DateField(blank=True, null=True)),
("closing_date", models.DateField(blank=True, null=True)),
(
"created_at",
models.DateTimeField(blank=True, editable=False, null=True),
),
("updated_at", models.DateTimeField(blank=True, editable=False)),
("history_id", models.AutoField(primary_key=True, serialize=False)),
("history_date", models.DateTimeField(db_index=True)),
("history_change_reason", models.CharField(max_length=100, null=True)),
(
"history_type",
models.CharField(
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
max_length=1,
),
),
(
"history_user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to=settings.AUTH_USER_MODEL,
),
),
(
"park",
models.ForeignKey(
blank=True,
db_constraint=False,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="parks.park",
),
),
],
options={
'ordering': ['name'],
'unique_together': {('park', 'slug')},
"verbose_name": "historical park area",
"verbose_name_plural": "historical park areas",
"ordering": ("-history_date", "-history_id"),
"get_latest_by": ("history_date", "history_id"),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name="ParkArea",
fields=[
("id", models.BigAutoField(primary_key=True, serialize=False)),
("name", models.CharField(max_length=255)),
("slug", models.SlugField(max_length=255)),
("description", models.TextField(blank=True)),
("opening_date", models.DateField(blank=True, null=True)),
("closing_date", models.DateField(blank=True, null=True)),
("created_at", models.DateTimeField(auto_now_add=True, null=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"park",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="areas",
to="parks.park",
),
),
],
options={
"ordering": ["name"],
"unique_together": {("park", "slug")},
},
),
]

View File

@@ -1,84 +0,0 @@
# Generated by Django 5.1.2 on 2024-11-03 03:44
import django.db.models.deletion
import simple_history.models
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('companies', '0004_add_total_parks'),
('parks', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='HistoricalPark',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('slug', models.SlugField(max_length=255)),
('description', models.TextField(blank=True)),
('status', models.CharField(choices=[('OPERATING', 'Operating'), ('CLOSED_TEMP', 'Temporarily Closed'), ('CLOSED_PERM', 'Permanently Closed'), ('UNDER_CONSTRUCTION', 'Under Construction'), ('DEMOLISHED', 'Demolished'), ('RELOCATED', 'Relocated')], default='OPERATING', max_length=20)),
('opening_date', models.DateField(blank=True, null=True)),
('closing_date', models.DateField(blank=True, null=True)),
('operating_season', models.CharField(blank=True, max_length=255)),
('size_acres', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
('website', models.URLField(blank=True)),
('average_rating', models.DecimalField(blank=True, decimal_places=2, max_digits=3, null=True)),
('total_rides', models.IntegerField(blank=True, null=True)),
('total_roller_coasters', models.IntegerField(blank=True, null=True)),
('latitude', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
('longitude', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
('street_address', models.CharField(blank=True, max_length=255)),
('city', models.CharField(blank=True, max_length=255)),
('state', models.CharField(blank=True, max_length=255)),
('country', models.CharField(blank=True, max_length=255)),
('postal_code', models.CharField(blank=True, max_length=20)),
('created_at', models.DateTimeField(blank=True, editable=False, null=True)),
('updated_at', models.DateTimeField(blank=True, editable=False)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('owner', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='companies.company')),
],
options={
'verbose_name': 'historical park',
'verbose_name_plural': 'historical parks',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalParkArea',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('slug', models.SlugField(max_length=255)),
('description', models.TextField(blank=True)),
('opening_date', models.DateField(blank=True, null=True)),
('closing_date', models.DateField(blank=True, null=True)),
('created_at', models.DateTimeField(blank=True, editable=False, null=True)),
('updated_at', models.DateTimeField(blank=True, editable=False)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('park', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='parks.park')),
],
options={
'verbose_name': 'historical park area',
'verbose_name_plural': 'historical park areas',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
]

View File

@@ -1,55 +0,0 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('parks', '0002_historicalpark_historicalparkarea'),
]
operations = [
migrations.AlterField(
model_name='park',
name='latitude',
field=models.DecimalField(
blank=True,
decimal_places=6,
max_digits=9, # Changed to 9 to handle -90.000000 to 90.000000
null=True,
help_text='Latitude coordinate (-90 to 90)',
),
),
migrations.AlterField(
model_name='park',
name='longitude',
field=models.DecimalField(
blank=True,
decimal_places=6,
max_digits=10, # Changed to 10 to handle -180.000000 to 180.000000
null=True,
help_text='Longitude coordinate (-180 to 180)',
),
),
migrations.AlterField(
model_name='historicalpark',
name='latitude',
field=models.DecimalField(
blank=True,
decimal_places=6,
max_digits=9, # Changed to 9 to handle -90.000000 to 90.000000
null=True,
help_text='Latitude coordinate (-90 to 90)',
),
),
migrations.AlterField(
model_name='historicalpark',
name='longitude',
field=models.DecimalField(
blank=True,
decimal_places=6,
max_digits=10, # Changed to 10 to handle -180.000000 to 180.000000
null=True,
help_text='Longitude coordinate (-180 to 180)',
),
),
]

View File

@@ -1,101 +0,0 @@
from django.db import migrations, models
from django.core.validators import MinValueValidator, MaxValueValidator
from decimal import Decimal
from django.core.exceptions import ValidationError
def validate_coordinate_digits(value, max_digits):
"""Validate total number of digits in a coordinate value"""
if value is not None:
# Convert to string and remove decimal point and sign
str_val = str(abs(value)).replace('.', '')
# Remove trailing zeros after decimal point
str_val = str_val.rstrip('0')
if len(str_val) > max_digits:
raise ValidationError(
f'Ensure that there are no more than {max_digits} digits in total.'
)
def validate_latitude_digits(value):
"""Validate total number of digits in latitude"""
validate_coordinate_digits(value, 9)
def validate_longitude_digits(value):
"""Validate total number of digits in longitude"""
validate_coordinate_digits(value, 10)
class Migration(migrations.Migration):
dependencies = [
('parks', '0003_update_coordinate_fields'),
]
operations = [
migrations.AlterField(
model_name='park',
name='latitude',
field=models.DecimalField(
blank=True,
decimal_places=6,
help_text='Latitude coordinate (-90 to 90)',
max_digits=9,
null=True,
validators=[
MinValueValidator(Decimal('-90')),
MaxValueValidator(Decimal('90')),
validate_latitude_digits,
],
),
),
migrations.AlterField(
model_name='park',
name='longitude',
field=models.DecimalField(
blank=True,
decimal_places=6,
help_text='Longitude coordinate (-180 to 180)',
max_digits=10,
null=True,
validators=[
MinValueValidator(Decimal('-180')),
MaxValueValidator(Decimal('180')),
validate_longitude_digits,
],
),
),
migrations.AlterField(
model_name='historicalpark',
name='latitude',
field=models.DecimalField(
blank=True,
decimal_places=6,
help_text='Latitude coordinate (-90 to 90)',
max_digits=9,
null=True,
validators=[
MinValueValidator(Decimal('-90')),
MaxValueValidator(Decimal('90')),
validate_latitude_digits,
],
),
),
migrations.AlterField(
model_name='historicalpark',
name='longitude',
field=models.DecimalField(
blank=True,
decimal_places=6,
help_text='Longitude coordinate (-180 to 180)',
max_digits=10,
null=True,
validators=[
MinValueValidator(Decimal('-180')),
MaxValueValidator(Decimal('180')),
validate_longitude_digits,
],
),
),
]

View File

@@ -1,58 +0,0 @@
from django.db import migrations
from decimal import Decimal, ROUND_DOWN
def normalize_coordinate(value, max_digits, decimal_places):
"""Normalize coordinate to have exactly 6 decimal places"""
try:
if value is None:
return None
# Convert to Decimal for precise handling
value = Decimal(str(value))
# Round to exactly 6 decimal places
value = value.quantize(Decimal('0.000001'), rounding=ROUND_DOWN)
return value
except (TypeError, ValueError):
return None
def normalize_existing_coordinates(apps, schema_editor):
Park = apps.get_model('parks', 'Park')
HistoricalPark = apps.get_model('parks', 'HistoricalPark')
# Normalize coordinates in current parks
for park in Park.objects.all():
if park.latitude is not None:
park.latitude = normalize_coordinate(park.latitude, 9, 6)
if park.longitude is not None:
park.longitude = normalize_coordinate(park.longitude, 10, 6)
park.save()
# Normalize coordinates in historical records
for record in HistoricalPark.objects.all():
if record.latitude is not None:
record.latitude = normalize_coordinate(record.latitude, 9, 6)
if record.longitude is not None:
record.longitude = normalize_coordinate(record.longitude, 10, 6)
record.save()
def reverse_normalize_coordinates(apps, schema_editor):
# No need to reverse normalization as it would only reduce precision
pass
class Migration(migrations.Migration):
dependencies = [
('parks', '0004_add_coordinate_validators'),
]
operations = [
migrations.RunPython(
normalize_existing_coordinates,
reverse_normalize_coordinates
),
]

View File

@@ -1,75 +0,0 @@
# Generated by Django 5.1.2 on 2024-11-03 19:59
import django.core.validators
from decimal import Decimal
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("parks", "0005_normalize_coordinates"),
]
operations = [
migrations.AlterField(
model_name="historicalpark",
name="latitude",
field=models.DecimalField(
blank=True,
decimal_places=6,
help_text="Latitude coordinate (-90 to 90)",
max_digits=9,
null=True,
validators=[
django.core.validators.MinValueValidator(Decimal("-90")),
django.core.validators.MaxValueValidator(Decimal("90")),
],
),
),
migrations.AlterField(
model_name="historicalpark",
name="longitude",
field=models.DecimalField(
blank=True,
decimal_places=6,
help_text="Longitude coordinate (-180 to 180)",
max_digits=10,
null=True,
validators=[
django.core.validators.MinValueValidator(Decimal("-180")),
django.core.validators.MaxValueValidator(Decimal("180")),
],
),
),
migrations.AlterField(
model_name="park",
name="latitude",
field=models.DecimalField(
blank=True,
decimal_places=6,
help_text="Latitude coordinate (-90 to 90)",
max_digits=9,
null=True,
validators=[
django.core.validators.MinValueValidator(Decimal("-90")),
django.core.validators.MaxValueValidator(Decimal("90")),
],
),
),
migrations.AlterField(
model_name="park",
name="longitude",
field=models.DecimalField(
blank=True,
decimal_places=6,
help_text="Longitude coordinate (-180 to 180)",
max_digits=10,
null=True,
validators=[
django.core.validators.MinValueValidator(Decimal("-180")),
django.core.validators.MaxValueValidator(Decimal("180")),
],
),
),
]

View File

@@ -1,27 +0,0 @@
# Generated by Django 5.1.2 on 2024-11-03 20:26
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("parks", "0006_alter_historicalpark_latitude_and_more"),
]
operations = [
migrations.RemoveField(
model_name="historicalparkarea",
name="history_user",
),
migrations.RemoveField(
model_name="historicalparkarea",
name="park",
),
migrations.DeleteModel(
name="HistoricalPark",
),
migrations.DeleteModel(
name="HistoricalParkArea",
),
]

View File

@@ -1,209 +0,0 @@
# Generated by Django 5.1.2 on 2024-11-03 20:38
import django.core.validators
import django.db.models.deletion
import history_tracking.mixins
import simple_history.models
from decimal import Decimal
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("companies", "0004_add_total_parks"),
("parks", "0007_remove_historicalparkarea_history_user_and_more"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="HistoricalPark",
fields=[
(
"id",
models.BigIntegerField(
auto_created=True, blank=True, db_index=True, verbose_name="ID"
),
),
("name", models.CharField(max_length=255)),
("slug", models.SlugField(max_length=255)),
("description", models.TextField(blank=True)),
(
"status",
models.CharField(
choices=[
("OPERATING", "Operating"),
("CLOSED_TEMP", "Temporarily Closed"),
("CLOSED_PERM", "Permanently Closed"),
("UNDER_CONSTRUCTION", "Under Construction"),
("DEMOLISHED", "Demolished"),
("RELOCATED", "Relocated"),
],
default="OPERATING",
max_length=20,
),
),
(
"latitude",
models.DecimalField(
blank=True,
decimal_places=6,
help_text="Latitude coordinate (-90 to 90)",
max_digits=9,
null=True,
validators=[
django.core.validators.MinValueValidator(Decimal("-90")),
django.core.validators.MaxValueValidator(Decimal("90")),
],
),
),
(
"longitude",
models.DecimalField(
blank=True,
decimal_places=6,
help_text="Longitude coordinate (-180 to 180)",
max_digits=10,
null=True,
validators=[
django.core.validators.MinValueValidator(Decimal("-180")),
django.core.validators.MaxValueValidator(Decimal("180")),
],
),
),
("street_address", models.CharField(blank=True, max_length=255)),
("city", models.CharField(blank=True, max_length=255)),
("state", models.CharField(blank=True, max_length=255)),
("country", models.CharField(blank=True, max_length=255)),
("postal_code", models.CharField(blank=True, max_length=20)),
("opening_date", models.DateField(blank=True, null=True)),
("closing_date", models.DateField(blank=True, null=True)),
("operating_season", models.CharField(blank=True, max_length=255)),
(
"size_acres",
models.DecimalField(
blank=True, decimal_places=2, max_digits=10, null=True
),
),
("website", models.URLField(blank=True)),
(
"average_rating",
models.DecimalField(
blank=True, decimal_places=2, max_digits=3, null=True
),
),
("total_rides", models.IntegerField(blank=True, null=True)),
("total_roller_coasters", models.IntegerField(blank=True, null=True)),
(
"created_at",
models.DateTimeField(blank=True, editable=False, null=True),
),
("updated_at", models.DateTimeField(blank=True, editable=False)),
("history_id", models.AutoField(primary_key=True, serialize=False)),
("history_date", models.DateTimeField(db_index=True)),
("history_change_reason", models.CharField(max_length=100, null=True)),
(
"history_type",
models.CharField(
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
max_length=1,
),
),
(
"history_user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to=settings.AUTH_USER_MODEL,
),
),
(
"owner",
models.ForeignKey(
blank=True,
db_constraint=False,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="companies.company",
),
),
],
options={
"verbose_name": "historical park",
"verbose_name_plural": "historical parks",
"ordering": ("-history_date", "-history_id"),
"get_latest_by": ("history_date", "history_id"),
},
bases=(
history_tracking.mixins.HistoricalChangeMixin,
simple_history.models.HistoricalChanges,
models.Model,
),
),
migrations.CreateModel(
name="HistoricalParkArea",
fields=[
(
"id",
models.BigIntegerField(
auto_created=True, blank=True, db_index=True, verbose_name="ID"
),
),
("name", models.CharField(max_length=255)),
("slug", models.SlugField(max_length=255)),
("description", models.TextField(blank=True)),
("opening_date", models.DateField(blank=True, null=True)),
("closing_date", models.DateField(blank=True, null=True)),
(
"created_at",
models.DateTimeField(blank=True, editable=False, null=True),
),
("updated_at", models.DateTimeField(blank=True, editable=False)),
("history_id", models.AutoField(primary_key=True, serialize=False)),
("history_date", models.DateTimeField(db_index=True)),
("history_change_reason", models.CharField(max_length=100, null=True)),
(
"history_type",
models.CharField(
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
max_length=1,
),
),
(
"history_user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to=settings.AUTH_USER_MODEL,
),
),
(
"park",
models.ForeignKey(
blank=True,
db_constraint=False,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="parks.park",
),
),
],
options={
"verbose_name": "historical park area",
"verbose_name_plural": "historical park areas",
"ordering": ("-history_date", "-history_id"),
"get_latest_by": ("history_date", "history_id"),
},
bases=(
history_tracking.mixins.HistoricalChangeMixin,
simple_history.models.HistoricalChanges,
models.Model,
),
),
]

View File

@@ -1,83 +0,0 @@
# Generated by Django 5.1.2 on 2024-11-04 22:21
from django.db import migrations, transaction
from django.contrib.contenttypes.models import ContentType
def forwards_func(apps, schema_editor):
"""Move park location data to Location model"""
Park = apps.get_model("parks", "Park")
Location = apps.get_model("location", "Location")
ContentType = apps.get_model("contenttypes", "ContentType")
db_alias = schema_editor.connection.alias
# Get or create content type for Park model
park_content_type, created = ContentType.objects.db_manager(db_alias).get_or_create(
app_label='parks',
model='park'
)
# Move location data for each park
with transaction.atomic():
for park in Park.objects.using(db_alias).all():
# Only create Location if park has coordinate data
if park.latitude is not None and park.longitude is not None:
Location.objects.using(db_alias).create(
content_type=park_content_type,
object_id=park.id,
name=park.name,
location_type='park',
latitude=park.latitude,
longitude=park.longitude,
street_address=park.street_address,
city=park.city,
state=park.state,
country=park.country,
postal_code=park.postal_code
)
def reverse_func(apps, schema_editor):
"""Move location data back to Park model"""
Park = apps.get_model("parks", "Park")
Location = apps.get_model("location", "Location")
ContentType = apps.get_model("contenttypes", "ContentType")
db_alias = schema_editor.connection.alias
# Get or create content type for Park model
park_content_type, created = ContentType.objects.db_manager(db_alias).get_or_create(
app_label='parks',
model='park'
)
# Move location data back to each park
with transaction.atomic():
locations = Location.objects.using(db_alias).filter(
content_type=park_content_type
)
for location in locations:
try:
park = Park.objects.using(db_alias).get(id=location.object_id)
park.latitude = location.latitude
park.longitude = location.longitude
park.street_address = location.street_address
park.city = location.city
park.state = location.state
park.country = location.country
park.postal_code = location.postal_code
park.save()
except Park.DoesNotExist:
continue
# Delete all park locations
locations.delete()
class Migration(migrations.Migration):
dependencies = [
('parks', '0008_historicalpark_historicalparkarea'),
('location', '0005_convert_coordinates_to_points'),
('contenttypes', '0002_remove_content_type_name'),
]
operations = [
migrations.RunPython(forwards_func, reverse_func, atomic=True),
]

View File

@@ -1,69 +0,0 @@
# Generated by Django 5.1.2 on 2024-11-04 22:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("parks", "0009_migrate_to_location_model"),
]
operations = [
migrations.RemoveField(
model_name="historicalpark",
name="latitude",
),
migrations.RemoveField(
model_name="historicalpark",
name="longitude",
),
migrations.RemoveField(
model_name="historicalpark",
name="street_address",
),
migrations.RemoveField(
model_name="historicalpark",
name="city",
),
migrations.RemoveField(
model_name="historicalpark",
name="state",
),
migrations.RemoveField(
model_name="historicalpark",
name="country",
),
migrations.RemoveField(
model_name="historicalpark",
name="postal_code",
),
migrations.RemoveField(
model_name="park",
name="latitude",
),
migrations.RemoveField(
model_name="park",
name="longitude",
),
migrations.RemoveField(
model_name="park",
name="street_address",
),
migrations.RemoveField(
model_name="park",
name="city",
),
migrations.RemoveField(
model_name="park",
name="state",
),
migrations.RemoveField(
model_name="park",
name="country",
),
migrations.RemoveField(
model_name="park",
name="postal_code",
),
]