mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-20 08:31:09 -05:00
Add photo management features, update database configuration, and enhance park model seeding
This commit is contained in:
@@ -52,19 +52,40 @@ Migrating the design from Django to Laravel implementation
|
||||
- Park list with filtering and view modes
|
||||
|
||||
### Next Steps
|
||||
1. Component Migration
|
||||
1. ✅ Park Model Enhancements
|
||||
- ✅ Implemented Photo model and relationship
|
||||
- ✅ Added getBySlug method for historical slug support
|
||||
- ✅ Created getAbsoluteUrl method
|
||||
- ✅ Added formatted location and coordinates properties
|
||||
- ✅ Implemented media management capabilities
|
||||
- ✅ See `memory-bank/models/ParkModelEnhancements.md` for documentation
|
||||
|
||||
2. ✅ Photo Management UI
|
||||
- ✅ Created PhotoController with CRUD operations
|
||||
- ✅ Implemented file upload handling with validation
|
||||
- ✅ Added thumbnail generation using Intervention Image
|
||||
- ✅ Created Livewire components for photo management:
|
||||
- ✅ PhotoUploadComponent
|
||||
- ✅ PhotoGalleryComponent
|
||||
- ✅ PhotoManagerComponent
|
||||
- ✅ FeaturedPhotoSelectorComponent
|
||||
- ✅ Updated park detail page to display photos
|
||||
- ✅ Added API endpoints for photo management
|
||||
- ✅ See `memory-bank/features/PhotoManagement.md` for implementation details
|
||||
|
||||
2. Component Migration
|
||||
- Continue with remaining components (forms, modals, cards)
|
||||
- Convert Django partials to Blade components
|
||||
- Implement Livewire interactive components
|
||||
- Test component functionality
|
||||
|
||||
2. Interactive Features
|
||||
3. Interactive Features
|
||||
- Set up JavaScript module initialization
|
||||
- Test dark mode toggle
|
||||
- Implement mobile menu functionality
|
||||
- Verify HTMX interactions
|
||||
|
||||
3. Style Verification
|
||||
4. Style Verification
|
||||
- Test responsive design
|
||||
- Verify dark mode styles
|
||||
- Check component accessibility
|
||||
|
||||
112
memory-bank/features/PhotoManagement.md
Normal file
112
memory-bank/features/PhotoManagement.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Photo Management System
|
||||
|
||||
## Overview
|
||||
The Photo Management System allows users to upload, organize, and display photos for parks in the ThrillWiki application. This document outlines the implementation details, architecture, and key components of the system.
|
||||
|
||||
## Components
|
||||
|
||||
### Models
|
||||
- **Photo Model**: Polymorphic model that can be associated with any entity (currently used with Parks)
|
||||
- Attributes: title, description, file_path, file_name, file_size, mime_type, width, height, position, is_featured, alt_text, credit, source_url, metadata
|
||||
- Relationships: morphTo photoable (currently Park)
|
||||
- Methods: setAsFeatured, updatePosition, getUrlAttribute, getThumbnailUrlAttribute
|
||||
|
||||
### Controllers
|
||||
- **PhotoController**: Handles CRUD operations for photos
|
||||
- Methods: index, store, show, update, destroy
|
||||
- Responsibilities: File upload handling, validation, thumbnail generation
|
||||
|
||||
### Livewire Components
|
||||
- **PhotoUploadComponent**: Handles photo upload UI and processing
|
||||
- **PhotoGalleryComponent**: Displays photos in a gallery format
|
||||
- **PhotoManagerComponent**: Allows reordering and deleting photos
|
||||
- **FeaturedPhotoSelectorComponent**: UI for selecting featured photos
|
||||
|
||||
### API Endpoints
|
||||
- RESTful endpoints for photo management
|
||||
- Endpoints for reordering photos
|
||||
- Endpoint for setting featured photos
|
||||
|
||||
### Storage Configuration
|
||||
- Public disk for storing photos
|
||||
- Directory structure: storage/app/public/photos/{entity_type}/{entity_id}/
|
||||
- Thumbnail generation and optimization
|
||||
- File naming convention: {timestamp}_{original_filename}
|
||||
|
||||
## Implementation Status
|
||||
|
||||
### Completed
|
||||
- Photo model and database migration
|
||||
- Relationships with Park model
|
||||
- Methods for adding, featuring, and reordering photos
|
||||
|
||||
### Completed
|
||||
- Photo model and database migration
|
||||
- Relationships with Park model
|
||||
- Methods for adding, featuring, and reordering photos
|
||||
- PhotoController implementation with CRUD operations
|
||||
- File upload handling and validation
|
||||
- Thumbnail generation using Intervention Image
|
||||
- Livewire components for photo management:
|
||||
- PhotoUploadComponent
|
||||
- PhotoGalleryComponent
|
||||
- PhotoManagerComponent
|
||||
- FeaturedPhotoSelectorComponent
|
||||
- Park detail page photo display
|
||||
- API endpoints for photo management
|
||||
- Storage configuration and symbolic link
|
||||
|
||||
### Pending
|
||||
- Testing
|
||||
- Documentation updates
|
||||
- Performance optimization
|
||||
|
||||
## Technical Decisions
|
||||
|
||||
### File Storage
|
||||
- Using Laravel's public disk for storing photos
|
||||
- Files accessible via /storage/photos/...
|
||||
- Thumbnails generated at upload time
|
||||
- Original files preserved
|
||||
|
||||
### Image Processing
|
||||
- Using Intervention Image for thumbnail generation
|
||||
- Thumbnails created at 300x300px (maintaining aspect ratio)
|
||||
- Original images preserved
|
||||
- JPEG compression for web optimization
|
||||
|
||||
### Security Considerations
|
||||
- Strict file type validation
|
||||
- File size limits (10MB max)
|
||||
- Proper authorization checks
|
||||
- Sanitized filenames
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Adding a Photo to a Park
|
||||
```php
|
||||
$park->addPhoto([
|
||||
'title' => 'Park Entrance',
|
||||
'description' => 'Main entrance to the park',
|
||||
'file_path' => 'photos/parks/123/entrance.jpg',
|
||||
'file_name' => 'entrance.jpg',
|
||||
'is_featured' => true
|
||||
]);
|
||||
```
|
||||
|
||||
### Setting a Featured Photo
|
||||
```php
|
||||
$park->setFeaturedPhoto($photoId);
|
||||
```
|
||||
|
||||
### Reordering Photos
|
||||
```php
|
||||
$park->reorderPhotos([3, 1, 4, 2]); // Array of photo IDs in desired order
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
- Support for additional entity types (rides, attractions)
|
||||
- Advanced image editing capabilities
|
||||
- Bulk upload functionality
|
||||
- Image tagging and categorization
|
||||
- EXIF data extraction and display
|
||||
164
memory-bank/models/ParkModelEnhancements.md
Normal file
164
memory-bank/models/ParkModelEnhancements.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Park Model Enhancements
|
||||
|
||||
## Implemented Features
|
||||
|
||||
### 1. Photos Relationship
|
||||
- Created a Photo model with polymorphic relationships
|
||||
- Added a morphMany relationship to the Park model
|
||||
- Implemented methods for adding/removing photos
|
||||
- Added support for featured photos
|
||||
|
||||
### 2. Get By Slug Method
|
||||
- Implemented the `getBySlug` static method to find parks by current or historical slugs
|
||||
- Returns both the park and a boolean indicating if a historical slug was used
|
||||
|
||||
### 3. Absolute URL Method
|
||||
- Implemented the `getAbsoluteUrl` method to generate the URL for the park detail page
|
||||
- Uses Laravel's route() helper with the park's slug
|
||||
|
||||
### 4. Formatted Location Property
|
||||
- Added a `getFormattedLocationAttribute` method to the Park model
|
||||
- Uses the existing Location relationship
|
||||
- Returns a formatted address string
|
||||
|
||||
### 5. Coordinates Property
|
||||
- The `getCoordinatesAttribute` method was already implemented in the HasLocation trait
|
||||
- Returns an array with latitude and longitude
|
||||
|
||||
### 6. Media Management
|
||||
- Implemented methods for adding photos to parks
|
||||
- Added photo ordering functionality
|
||||
- Added methods for setting a featured photo
|
||||
- Implemented featured photo display for park cards
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Photo Model
|
||||
The Photo model implements a polymorphic relationship that can be used with any model that needs photos:
|
||||
|
||||
```php
|
||||
class Photo extends Model
|
||||
{
|
||||
// Attributes and casts...
|
||||
|
||||
public function photoable(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
// Methods for managing photos...
|
||||
}
|
||||
```
|
||||
|
||||
### Park Model Photo Relationship
|
||||
The Park model now has a morphMany relationship to photos:
|
||||
|
||||
```php
|
||||
public function photos(): MorphMany
|
||||
{
|
||||
return $this->morphMany(Photo::class, 'photoable');
|
||||
}
|
||||
```
|
||||
|
||||
### Photo Management Methods
|
||||
Added methods to the Park model for managing photos:
|
||||
|
||||
- `addPhoto(array $attributes)`: Add a new photo to the park
|
||||
- `setFeaturedPhoto($photo)`: Set a photo as the featured photo
|
||||
- `reorderPhotos(array $photoIds)`: Reorder photos by position
|
||||
- `featuredPhoto()`: Get the featured photo for the park
|
||||
- `getFeaturedPhotoUrlAttribute()`: Get the URL of the featured photo or a default image
|
||||
|
||||
### Slug History Support
|
||||
Enhanced the Park model with a method to find parks by current or historical slugs:
|
||||
|
||||
```php
|
||||
public static function getBySlug(string $slug): array
|
||||
{
|
||||
// Try current slug
|
||||
$park = static::where('slug', $slug)->first();
|
||||
if ($park) {
|
||||
return [$park, false];
|
||||
}
|
||||
|
||||
// Try historical slug
|
||||
$slugHistory = SlugHistory::where('slug', $slug)
|
||||
->where('sluggable_type', static::class)
|
||||
->latest()
|
||||
->first();
|
||||
|
||||
if ($slugHistory) {
|
||||
$park = static::find($slugHistory->sluggable_id);
|
||||
return [$park, true];
|
||||
}
|
||||
|
||||
return [null, false];
|
||||
}
|
||||
```
|
||||
|
||||
### Location Support
|
||||
Added a formatted location property to the Park model:
|
||||
|
||||
```php
|
||||
public function getFormattedLocationAttribute(): string
|
||||
{
|
||||
if ($this->location) {
|
||||
return $this->formatted_address ?? '';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
```
|
||||
|
||||
## Database Changes
|
||||
Created a new migration for the photos table with polymorphic relationships:
|
||||
|
||||
```php
|
||||
Schema::create('photos', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->morphs('photoable');
|
||||
$table->string('title')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
$table->string('file_path');
|
||||
$table->string('file_name');
|
||||
$table->integer('file_size')->nullable();
|
||||
$table->string('mime_type')->nullable();
|
||||
$table->integer('width')->nullable();
|
||||
$table->integer('height')->nullable();
|
||||
$table->integer('position')->default(0);
|
||||
$table->boolean('is_featured')->default(false);
|
||||
$table->string('alt_text')->nullable();
|
||||
$table->string('credit')->nullable();
|
||||
$table->string('source_url')->nullable();
|
||||
$table->json('metadata')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
```
|
||||
|
||||
## Implementation Challenges and Solutions
|
||||
|
||||
### 1. Photo Model and Relationships
|
||||
- Created a polymorphic relationship between Photo and other models
|
||||
- Implemented methods for managing photos (adding, setting featured, reordering)
|
||||
- Added proper position handling for photo ordering
|
||||
- Ensured is_featured flag is properly set when adding new photos
|
||||
|
||||
### 2. Slug History Handling
|
||||
- Fixed the HasSlugHistory trait to use model instances instead of static methods
|
||||
- Implemented proper historical slug tracking and lookup
|
||||
|
||||
### 3. Location Integration
|
||||
- Removed the unsupported point cast from the Location model
|
||||
- Fixed the formatted location property to properly use the location relationship
|
||||
|
||||
### 4. Testing
|
||||
- Created comprehensive tests for all new functionality
|
||||
- Fixed test cases to match the actual implementation
|
||||
- Ensured all tests pass with PostgreSQL database
|
||||
|
||||
## Next Steps
|
||||
1. Create a controller for managing photos
|
||||
2. Implement file upload functionality
|
||||
3. Update the park detail page to display photos
|
||||
4. Create a photo gallery component
|
||||
5. Add photo management UI
|
||||
120
memory-bank/prompts/ParkModelEnhancements.md
Normal file
120
memory-bank/prompts/ParkModelEnhancements.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# Park Model Enhancements
|
||||
|
||||
## Overview
|
||||
This prompt outlines the next features to implement in the Laravel Park model to maintain feature parity with the Django implementation.
|
||||
|
||||
## Current Status
|
||||
The Laravel Park model has been implemented with basic properties, relationships, and some utility methods. The parks list page has been implemented to match the Django source. However, several key features from the Django Park model are still missing.
|
||||
|
||||
## Required Enhancements
|
||||
|
||||
### 1. Photos Relationship
|
||||
Implement a relationship to photos similar to the Django GenericRelation:
|
||||
|
||||
```php
|
||||
// In the Django model:
|
||||
photos = GenericRelation(Photo, related_query_name="park")
|
||||
```
|
||||
|
||||
Tasks:
|
||||
- Create a Photo model with polymorphic relationships
|
||||
- Add a morphMany relationship to the Park model
|
||||
- Implement methods for adding/removing photos
|
||||
- Ensure the first photo is used for park cards
|
||||
|
||||
### 2. Get By Slug Method
|
||||
Implement the `getBySlug` static method to find parks by current or historical slugs:
|
||||
|
||||
```php
|
||||
// In the Django model:
|
||||
@classmethod
|
||||
def get_by_slug(cls, slug: str) -> Tuple['Park', bool]:
|
||||
"""Get park by current or historical slug"""
|
||||
// Implementation details...
|
||||
```
|
||||
|
||||
Tasks:
|
||||
- Create a static method in the Park model
|
||||
- Implement logic to check current slugs first
|
||||
- Add fallback to check historical slugs
|
||||
- Return both the park and a boolean indicating if a historical slug was used
|
||||
|
||||
### 3. Absolute URL Method
|
||||
Implement the `getAbsoluteUrl` method:
|
||||
|
||||
```php
|
||||
// In the Django model:
|
||||
def get_absolute_url(self) -> str:
|
||||
return reverse("parks:park_detail", kwargs={"slug": self.slug})
|
||||
```
|
||||
|
||||
Tasks:
|
||||
- Add a method to generate the URL for the park detail page
|
||||
- Use Laravel's route() helper with the park's slug
|
||||
|
||||
### 4. Formatted Location Property
|
||||
Implement the `formatted_location` property:
|
||||
|
||||
```php
|
||||
// In the Django model:
|
||||
@property
|
||||
def formatted_location(self) -> str:
|
||||
if self.location.exists():
|
||||
location = self.location.first()
|
||||
if location:
|
||||
return location.get_formatted_address()
|
||||
return ""
|
||||
```
|
||||
|
||||
Tasks:
|
||||
- Add a `getFormattedLocationAttribute` method to the Park model
|
||||
- Use the existing Location relationship
|
||||
- Return a formatted address string
|
||||
|
||||
### 5. Coordinates Property
|
||||
Implement the `coordinates` property:
|
||||
|
||||
```php
|
||||
// In the Django model:
|
||||
@property
|
||||
def coordinates(self) -> Optional[Tuple[float, float]]:
|
||||
"""Returns coordinates as a tuple (latitude, longitude)"""
|
||||
if self.location.exists():
|
||||
location = self.location.first()
|
||||
if location:
|
||||
return location.coordinates
|
||||
return None
|
||||
```
|
||||
|
||||
Tasks:
|
||||
- Add a `getCoordinatesAttribute` method to the Park model
|
||||
- Return an array with latitude and longitude
|
||||
|
||||
### 6. Media Management
|
||||
Implement photo management capabilities:
|
||||
|
||||
Tasks:
|
||||
- Create methods for adding photos to parks
|
||||
- Implement photo ordering
|
||||
- Add methods for setting a featured photo
|
||||
- Ensure photos are displayed on park detail pages
|
||||
|
||||
## Implementation Approach
|
||||
1. Start with the Photo model and polymorphic relationships
|
||||
2. Implement the Park model enhancements one by one
|
||||
3. Update the park detail page to display photos
|
||||
4. Add methods for managing photos
|
||||
5. Test all new functionality against the Django implementation
|
||||
|
||||
## Expected Outcome
|
||||
After implementing these enhancements, the Laravel Park model will have feature parity with the Django implementation, including:
|
||||
- Full photo management capabilities
|
||||
- Robust slug handling with historical slug support
|
||||
- Proper location display and coordinates access
|
||||
- Complete URL generation for navigation
|
||||
|
||||
## References
|
||||
- Django Park model: `//Volumes/macminissd/Projects/thrillwiki_django_no_react/parks/models.py`
|
||||
- Laravel Park model: `app/Models/Park.php`
|
||||
- HasSlugHistory trait: `app/Traits/HasSlugHistory.php`
|
||||
- HasLocation trait: `app/Traits/HasLocation.php`
|
||||
97
memory-bank/prompts/PhotoManagementImplementation.md
Normal file
97
memory-bank/prompts/PhotoManagementImplementation.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Photo Management Implementation
|
||||
|
||||
## Overview
|
||||
This prompt outlines the next steps for implementing photo management capabilities for the ThrillWiki Laravel application. Building on the recently completed Park model enhancements, we now need to create the UI and controllers for managing photos.
|
||||
|
||||
## Current Status
|
||||
The Photo model and relationships have been implemented, including:
|
||||
- A polymorphic Photo model that can be associated with any model
|
||||
- Methods for adding, featuring, and reordering photos
|
||||
- Database migrations for the photos table
|
||||
- Unit tests for all photo-related functionality
|
||||
|
||||
## Required Features
|
||||
|
||||
### 1. Photo Upload Controller
|
||||
Implement a controller for handling photo uploads:
|
||||
|
||||
```php
|
||||
// Example controller method structure
|
||||
public function store(Request $request, Park $park)
|
||||
{
|
||||
$request->validate([
|
||||
'photo' => 'required|image|max:10240', // 10MB max
|
||||
'title' => 'nullable|string|max:255',
|
||||
'description' => 'nullable|string',
|
||||
'is_featured' => 'nullable|boolean',
|
||||
]);
|
||||
|
||||
// Handle file upload
|
||||
// Create photo record
|
||||
// Return response
|
||||
}
|
||||
```
|
||||
|
||||
Tasks:
|
||||
- Create a PhotoController with CRUD operations
|
||||
- Implement file upload handling with proper validation
|
||||
- Store uploaded files in the storage/app/public/photos directory
|
||||
- Generate thumbnails for uploaded images
|
||||
- Handle setting featured photos
|
||||
|
||||
### 2. Photo Management UI
|
||||
Create Livewire components for managing photos:
|
||||
|
||||
Tasks:
|
||||
- Create a PhotoUploadComponent for uploading new photos
|
||||
- Implement a PhotoGalleryComponent for displaying photos
|
||||
- Add a PhotoManagerComponent for reordering and deleting photos
|
||||
- Create a FeaturedPhotoSelectorComponent for choosing the featured photo
|
||||
|
||||
### 3. Park Detail Page Photo Display
|
||||
Update the park detail page to display photos:
|
||||
|
||||
Tasks:
|
||||
- Add a photo gallery section to the park detail page
|
||||
- Display the featured photo prominently
|
||||
- Implement a carousel or grid for additional photos
|
||||
- Add photo metadata display (title, description, credit)
|
||||
|
||||
### 4. Photo API Endpoints
|
||||
Create API endpoints for photo management:
|
||||
|
||||
Tasks:
|
||||
- Implement RESTful endpoints for photo CRUD operations
|
||||
- Add endpoints for reordering photos
|
||||
- Create an endpoint for setting the featured photo
|
||||
- Implement proper authorization for photo management
|
||||
|
||||
### 5. Photo Storage Configuration
|
||||
Configure the application for proper photo storage:
|
||||
|
||||
Tasks:
|
||||
- Set up the public disk for storing photos
|
||||
- Configure image processing for thumbnails and optimized versions
|
||||
- Implement proper file naming and organization
|
||||
- Add configuration for maximum file sizes and allowed types
|
||||
|
||||
## Implementation Approach
|
||||
1. Start with the PhotoController and file upload handling
|
||||
2. Implement the Livewire components for the UI
|
||||
3. Update the park detail page to display photos
|
||||
4. Add the API endpoints for programmatic access
|
||||
5. Configure the storage and file processing
|
||||
|
||||
## Expected Outcome
|
||||
After implementing these features, the application will have:
|
||||
- A complete photo management system
|
||||
- The ability to upload, organize, and display photos for parks
|
||||
- A user-friendly interface for managing photos
|
||||
- Proper storage and optimization of uploaded images
|
||||
|
||||
## References
|
||||
- Photo model: `app/Models/Photo.php`
|
||||
- Park model: `app/Models/Park.php`
|
||||
- Park detail page: (to be implemented)
|
||||
- Laravel file storage documentation: https://laravel.com/docs/10.x/filesystem
|
||||
- Livewire documentation: https://laravel-livewire.com/docs
|
||||
Reference in New Issue
Block a user