github waadmawlood/filament-import-wizard v1.1.0

6 hours ago

Feat: Complete import wizard overhaul — reverse mapping UI, relation FK fixes, Eloquent events, Translatable support, and performance optimizations.

Issue #1

Resolve them.

split to 7 tasks from Issue #1, delivering a complete overhaul of the import wizard with a reversed mapping UI, critical bug fixes for relation foreign keys, Eloquent lifecycle support, Spatie Translatable integration, and performance optimizations for large datasets.

🔄 Task 1: Reverse Mapping UI

  • Replaced header-first loop with model-field-first layout in mapping.blade.php
  • Added $modelFieldMappings, $relationFieldMappings, $fieldTypes properties
  • Added initializeModelFieldMappings() with snake_case auto-matching (e.g., Titletitle, CategoryIdcategory_id)
  • Added syncMappingsToColumnMappings() to convert back to $columnMappings format for ProcessImportChunk
  • Added getUnmappedCsvColumns() to show leftover CSV headers
  • Added toggleMergeTranslation() for translatable field multi-column support
  • Added merge translation checkbox column in mapping table for translatable fields
  • Auto-detects locale from header names (e.g., title_en, name_ar)

🐛 Task 2: Fix Relation Foreign Key Not Saved

  • Fixed fillable check that skipped relations when model uses $guarded = []
  • Added resolveFillable() helper that falls back to Schema::getColumnListing()
  • Replaced wire:model.live with wire:change + hidden inputs for relation selects to avoid Livewire v3 dot-notation issues

🐛 Task 3: Fix SQL VALUES Length Mismatch

  • Added normalizeRecordKeys() to ensure all records have consistent column keys before bulk insert
  • Prevents VALUES lists must all be the same length errors when rows have varying columns

🐛 Task 4: Fix Model Boot/Observers Not Firing

  • Added insertRecordsAsModels() that uses Eloquent save() inside a transaction
  • Added addTimestampsToRecords() for upsert path
  • Non-upsert inserts now fire boot(), observers, and lifecycle hooks

✨ Task 5: Support Spatie Translatable / Composite Types

  • Replaced MySQL-specific where("field->locale", value) with Laravel's whereJsonContains()
  • Removed Spatie dependency; now detects JSON columns from database schema
  • Native JSON storage: $model->{$fieldName} = [$locale => $value]
  • Added getTranslatableFields() detection via schema inspection

🔧 Task 6: Excel Column Trimming

  • Added $cellIterator->setIterateOnlyExistingCells(true) in parseExcel()
  • Strips trailing empty Excel columns (no more 256-column UI)

⚡ Task 7: General Code Optimizations

  • 7.1: Added $cachedRelations and $cachedGroupedColumns to avoid duplicate reflection loops
  • 7.2: Added BOM stripping in parseCsv() using preg_replace('/^\xEF\xBB\xBF/', '', $h)
  • 7.3: Added column count guard in loadCsvChunk() before array_combine()
  • 7.4: Wrapped fallback chunked insert in try/catch with completed_with_errors status
  • 7.5: Changed Log::warning to Log::debug for production
  • 7.6: Added completed_with_errors UI handling in import.blade.php + translation key

Don't miss a new filament-import-wizard release

NewReleases is sending notifications on new releases.