diff --git a/app/Actions/UpdateEtude.php b/app/Actions/UpdateEtude.php new file mode 100644 index 0000000..8803811 --- /dev/null +++ b/app/Actions/UpdateEtude.php @@ -0,0 +1,40 @@ +name.' '.$instrument->instrument.' Set '.$set.'.pdf'; + $filename = str_replace(' ', '_', $filename); + $path = $file->storeAs('/etudes', $filename, 'public'); + $originalFilename = $file->getClientOriginalName(); + $fileSize = $file->getSize(); + + AuditionEtude::updateOrCreate( + [ + 'ensemble_id' => $ensemble->id, + 'instrument_id' => $instrument->id, + 'set' => $set, + ], + [ + 'ensemble_id' => $ensemble->id, + 'instrument_id' => $instrument->id, + 'set' => $set, + 'file_path' => $path, + 'original_filename' => $originalFilename, + 'file_size' => $fileSize, + ] + ); + } +} diff --git a/app/Console/Commands/EtudesCleanup.php b/app/Console/Commands/EtudesCleanup.php new file mode 100644 index 0000000..25f416b --- /dev/null +++ b/app/Console/Commands/EtudesCleanup.php @@ -0,0 +1,92 @@ +option('dry-run'); + + if ($dryRun) { + $this->info('Running in dry-run mode - no changes will be made'); + } + + $this->info('Starting etudes cleanup...'); + $this->newLine(); + + // Part 1: Remove database records with missing PDF files + $this->info('Checking for database records with missing PDF files...'); + $orphanedRecords = 0; + + AuditionEtude::chunk(100, function ($etudes) use (&$orphanedRecords, $dryRun) { + foreach ($etudes as $etude) { + if (! Storage::disk('public')->exists($etude->file_path)) { + $this->warn("Missing file: {$etude->file_path} (Record ID: {$etude->id})"); + $orphanedRecords++; + + if (! $dryRun) { + $etude->delete(); + } + } + } + }); + + if ($orphanedRecords > 0) { + $action = $dryRun ? 'would be' : 'were'; + $this->info("✓ {$orphanedRecords} orphaned database record(s) {$action} removed"); + } else { + $this->info('✓ No orphaned database records found'); + } + + $this->newLine(); + + // Part 2: Remove PDF files not referenced in the database + $this->info('Checking for PDF files not referenced in the database...'); + + $referencedPaths = AuditionEtude::pluck('file_path')->toArray(); + $allFiles = Storage::disk('public')->files('etudes'); + $orphanedFiles = array_diff($allFiles, $referencedPaths); + + if (count($orphanedFiles) > 0) { + foreach ($orphanedFiles as $file) { + $this->warn("Orphaned file: {$file}"); + + if (! $dryRun) { + Storage::disk('public')->delete($file); + } + } + + $action = $dryRun ? 'would be' : 'were'; + $this->info('✓ '.count($orphanedFiles)." orphaned file(s) {$action} removed"); + } else { + $this->info('✓ No orphaned files found'); + } + + $this->newLine(); + $this->info('Cleanup completed!'); + + return Command::SUCCESS; + } +} diff --git a/app/Http/Controllers/Admin/AuditionEtudeController.php b/app/Http/Controllers/Admin/AuditionEtudeController.php index 8fcc886..cdc0dfc 100644 --- a/app/Http/Controllers/Admin/AuditionEtudeController.php +++ b/app/Http/Controllers/Admin/AuditionEtudeController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Admin; +use App\Actions\UpdateEtude; use App\Http\Controllers\Controller; use App\Http\Requests\EtudeUploadRequest; use App\Models\AuditionEtude; @@ -39,25 +40,14 @@ class AuditionEtudeController extends Controller /** * Store a newly created resource in storage. */ - public function store(EtudeUploadRequest $request) + public function store(EtudeUploadRequest $request, UpdateEtude $updater) { - $instrument = Instrument::find($request->instrument_id); - $ensemble = Ensemble::find($request->ensemble_id); - $filename = $ensemble->name.' '.$instrument->instrument.' Set '.$request->set.'.pdf'; - $filename = str_replace(' ', '_', $filename); - - $path = $request->file('file_upload')->storeAs('etudes', $filename, 'public'); - $originalFilename = $request->file('file_upload')->getClientOriginalName(); - $fileSize = $request->file('file_upload')->getSize(); - - AuditionEtude::create([ - 'instrument_id' => $request->instrument_id, - 'ensemble_id' => $request->ensemble_id, - 'set' => $request->set, - 'file_path' => $path, - 'original_filename' => $originalFilename, - 'file_size' => $fileSize, - ]); + $updater( + Ensemble::find($request->ensemble_id), + Instrument::find($request->instrument_id), + $request->set, + $request->file('file_upload') + ); session([ 'previous_instrument_id' => $request->instrument_id, diff --git a/app/Http/Controllers/Admin/AuditionEtudeGridController.php b/app/Http/Controllers/Admin/AuditionEtudeGridController.php index 51777ea..148de60 100644 --- a/app/Http/Controllers/Admin/AuditionEtudeGridController.php +++ b/app/Http/Controllers/Admin/AuditionEtudeGridController.php @@ -2,9 +2,14 @@ namespace App\Http\Controllers\Admin; +use App\Actions\UpdateEtude; use App\Http\Controllers\Controller; +use App\Http\Requests\EtudeUploadRequest; +use App\Models\AuditionEtude; use App\Models\Ensemble; use App\Models\Instrument; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; class AuditionEtudeGridController extends Controller { @@ -15,4 +20,29 @@ class AuditionEtudeGridController extends Controller return view('admin.audition_etude.grid', compact('ensembles', 'instruments')); } + + public function store(EtudeUploadRequest $request, UpdateEtude $updater) + { + $updater( + Ensemble::find($request->ensemble_id), + Instrument::find($request->instrument_id), + $request->set, + $request->file('file_upload') + ); + + return redirect()->route('admin.etude-grid')->with('success', 'Etude updated successfully.'); + + } + + public function destroy(Request $request) + { + $validated = $request->validate([ + 'etude_id' => 'required|integer|exists:audition_etudes,id', + ]); + $etude = AuditionEtude::findOrFail($validated['etude_id']); + + $etude->delete(); + + return redirect()->route('admin.etude-grid')->with('success', 'Etude deleted successfully.'); + } } diff --git a/app/Models/AuditionEtude.php b/app/Models/AuditionEtude.php index f97b39b..3ca9028 100644 --- a/app/Models/AuditionEtude.php +++ b/app/Models/AuditionEtude.php @@ -5,6 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Support\Facades\Storage; class AuditionEtude extends Model { @@ -12,6 +13,15 @@ class AuditionEtude extends Model 'instrument_id', 'ensemble_id', 'set', 'original_filename', 'file_path', 'file_size', ]; + protected static function booted(): void + { + static::deleting(function (AuditionEtude $etude) { + if ($etude->file_path) { + Storage::disk('public')->delete($etude->file_path); + } + }); + } + public function instrument(): BelongsTo { return $this->belongsTo(Instrument::class); @@ -22,6 +32,11 @@ class AuditionEtude extends Model return $this->belongsTo(Ensemble::class); } + public function getLinkToPDF() + { + return Storage::url($this->file_path); + } + protected function humanReadableFileSize(): Attribute { return Attribute::make( diff --git a/resources/views/admin/audition_etude/create.blade.php b/resources/views/admin/audition_etude/create.blade.php index d2c09d3..bf37b95 100644 --- a/resources/views/admin/audition_etude/create.blade.php +++ b/resources/views/admin/audition_etude/create.blade.php @@ -30,7 +30,7 @@
- + Ensemble @foreach($ensembles as $ensemble) diff --git a/resources/views/admin/audition_etude/grid.blade.php b/resources/views/admin/audition_etude/grid.blade.php index 967fb0e..b8a308f 100644 --- a/resources/views/admin/audition_etude/grid.blade.php +++ b/resources/views/admin/audition_etude/grid.blade.php @@ -1,49 +1,11 @@ - - - - - - -
- - - - - -
-
-

- Update Etude

-
- - - -
- -
-
-
- -
-
- -
-
-
-
-
-
+ + @include('admin.audition_etude.grid_update_form') + @if($errors->any()) + @foreach($errors->all() as $error) + {{ $error }} + @endforeach + @endif @foreach($ensembles as $ensemble) @@ -71,10 +33,13 @@ ensemble_id = '{{ $ensemble->id }}'; instrument = '{{ $instrument->instrument }}'; instrument_id = '{{ $instrument->id }}'; - set = {{ $n }}" + set = {{ $n }}; + etude_link = '{{ $ensemble->getEtude($instrument, $n)->getLinkToPDF() }}'; + existing_etude_id = '{{ $ensemble->getEtude($instrument, $n)->id }}';" > {{ $ensemble->abbreviation }} - {{ $instrument->instrument }} - Set {{ $n }}
+

Updated: {{ $ensemble->getEtude($instrument, $n)->updated_at->format('m/d/Y') }}

@else @@ -88,8 +53,11 @@ ensemble_id = '{{ $ensemble->id }}'; instrument = '{{ $instrument->instrument }}'; instrument_id = '{{ $instrument->id }}'; - set = {{ $n }}" + set = {{ $n }}; + etude_link = ''; + existing_etude_id = '';" > + {{ $ensemble->abbreviation }} - {{ $instrument->instrument }} - Set {{ $n }}
No Etude diff --git a/resources/views/admin/audition_etude/grid_update_form.blade.php b/resources/views/admin/audition_etude/grid_update_form.blade.php new file mode 100644 index 0000000..87632a9 --- /dev/null +++ b/resources/views/admin/audition_etude/grid_update_form.blade.php @@ -0,0 +1,56 @@ + + + + +
+ + + + + +
+
+

+ Update Etude +

+ + +
+
+
+ + +
+
+ +
+
+
+ + + + +
+
+
+
+
diff --git a/resources/views/admin/audition_etude/index.blade.php b/resources/views/admin/audition_etude/index.blade.php index 4b6cf3c..69a286c 100644 --- a/resources/views/admin/audition_etude/index.blade.php +++ b/resources/views/admin/audition_etude/index.blade.php @@ -15,7 +15,7 @@ @foreach($etudes as $etude) - {{ $etude->auditionedEnsemble->name }} + {{ $etude->ensemble->name }} {{ $etude->set }} {{ $etude->instrument->instrument }} diff --git a/routes/web.php b/routes/web.php index a995b81..9af818f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -29,4 +29,6 @@ Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () Route::resource('/etudes', AuditionEtudeController::class)->names('etudes'); Route::resource('/news', NewsStoryController::class)->except(['show'])->names('news'); Route::get('/etude-grid', [AuditionEtudeGridController::class, 'index'])->name('etude-grid'); + Route::post('/etude-grid', [AuditionEtudeGridController::class, 'store'])->name('etude-grid.store'); + Route::delete('/etude-grid', [AuditionEtudeGridController::class, 'destroy'])->name('etude-grid.delete'); });