Got duplicate-field mapping and minimum-mapping requirements implemented

This commit is contained in:
Brady Wetherington 2024-09-02 22:02:31 +01:00
parent e1fcfc8dc1
commit 9e573dfa50
2 changed files with 130 additions and 10 deletions

View file

@ -4,6 +4,7 @@ namespace App\Livewire;
use App\Models\CustomField;
use App\Models\Import;
use App\Models\Setting;
use Illuminate\Support\Facades\Storage;
use Livewire\Attributes\Computed;
use Livewire\Component;
@ -30,6 +31,8 @@ class Importer extends Component
public $send_welcome;
public $run_backup;
public $field_map; // we need a separate variable for the field-mapping, because the keys in the normal array are too complicated for Livewire to understand
public $mapping_errors = []; // helps keep track of duplicate mappings
public $enough_data_to_import = false;
// Make these variables public - we set the properties in the constructor so we can localize them (versus the old static arrays)
public $accessories_fields;
@ -107,6 +110,7 @@ class Importer extends Component
public function updatingTypeOfImport($type)
{
\Log::error("UPDATING TYPE OF IMPORT!!!!!! to: $type");
// go through each header, find a matching field to try and map it to.
foreach ($this->headerRow as $i => $header) {
// do we have something mapped already?
@ -148,6 +152,107 @@ class Importer extends Component
}
}
public function updatedFieldMap($value, $index)
{
\Log::error("Updated (past tense!) THE FIELD MAP! HERE's...something? $index - the value it's changing to is: $value");
//check first if you've tried to map two different things to the same field.
$already_mapped = [];
foreach ($this->field_map as $i => $mapping) {
if (!$mapping) {
//'Do Not Import' *can* be reused
continue;
}
if (array_key_exists($mapping, $already_mapped)) {
$this->mapping_errors[$i] = true;
} else {
$already_mapped[$mapping] = true;
}
}
//finally, check to see if you have enough to import this type of file
$this->enough_data_to_import = $this->check_minimum_mappings($already_mapped);
}
private function check_minimum_mappings($already_mapped)
{
/*****************************
* TODO (maybe more than that) -
* should we shrink this into some kind of language?
* When we allow for an 'update' - should we insist on getting *any* column so we
* can guarantee an update?
* If we're *not* doing an update, should we have a fuller list?
* And, again, is there a better way of doing this other than 'code'? I'm still not sure
* (Also, I hate the '@' signs everywhere, it's gross :/)
*******************************/
switch ($this->typeOfImport) {
case 'asset':
if ($this->update) {
//on *update* you need asset_tag, and something to update
return @$already_mapped['asset_tag'] && count($already_mapped) > 1;
} else {
//model is required on create.
if (!@$already_mapped['asset_model']) {
return false;
}
//on *create* we need either an asset tag, or we need autoincrement
return (Setting::getSetting()->auto_increment_assets || @$already_mapped['asset_tag']);
}
case 'user':
if ($this->update) {
//a username + one other field is a valid update.
if (@$already_mapped['username'] && count($already_mapped) > 1) {
return true;
}
//or, a full_name and one other field will do
if (@$already_mapped['full_name'] && count($already_mapped) > 1) {
return true;
}
//but just a first name isn't enough to update users - you don't have enough to import
return false;
} else {
// to create a new user in the importer, having any *one* of these things is enough to guess
// the rest (!)
return @$already_mapped['full_name'] || @$already_mapped['username'] || @$already_mapped['first_name'];
}
case 'accessory':
if ($this->update) {
return @$already_mapped['name'] && count($already_mapped) > 1;
} else {
return @$already_mapped['name'] && @$already_mapped['category'] && @$already_mapped['qty'];
}
case 'consumable':
// PHPStorm complains that this 'branch' is a dupe of accessory, and it kinda is,
// but it may not *always* be, so let's keep this as its own thing for now
if ($this->update) {
return @$already_mapped['name'] && count($already_mapped) > 1;
} else {
return @$already_mapped['name'] && @$already_mapped['category'] && @$already_mapped['qty'];
}
case 'component':
//similarly here for 'component'
if ($this->update) {
return (@$already_mapped['name'] && count($already_mapped) > 1);
} else {
return @$already_mapped['name'] && @$already_mapped['category'] && @$already_mapped['qty'];
}
case 'license':
if ($this->update) {
return @$already_mapped['name'] && count($already_mapped) > 1;
} else {
return @$already_mapped['name'] && @$already_mapped['seats'] && @$already_mapped['category'];
}
case 'location':
// Weird - this one is the only one where the update is _stricter_ than the insert!
if ($this->update) {
return @$already_mapped['name'] && count($already_mapped) > 1;
} else {
return @$already_mapped['name'];
}
}
return true; //go with a conservative option here, we can tighten this up later
}
public function mount()
{
$this->authorize('import');
@ -167,7 +272,7 @@ class Importer extends Component
$this->accessories_fields = [
'company' => trans('general.company'),
'location' => trans('general.location'),
'quantity' => trans('general.qty'),
'quantity' => trans('general.quantity'),
'item_name' => trans('general.item_name_var', ['item' => trans('general.accessory')]),
'model_number' => trans('general.model_no'),
'notes' => trans('general.notes'),
@ -229,7 +334,7 @@ class Importer extends Component
$this->consumables_fields = [
'company' => trans('general.company'),
'location' => trans('general.location'),
'quantity' => trans('general.qty'),
'quantity' => trans('general.quantity'),
'item_name' => trans('general.item_name_var', ['item' => trans('general.consumable')]),
'model_number' => trans('general.model_no'),
'notes' => trans('general.notes'),
@ -247,7 +352,7 @@ class Importer extends Component
$this->components_fields = [
'company' => trans('general.company'),
'location' => trans('general.location'),
'quantity' => trans('general.qty'),
'quantity' => trans('general.quantity'),
'item_name' => trans('general.item_name_var', ['item' => trans('general.component')]),
'model_number' => trans('general.model_no'),
'notes' => trans('general.notes'),
@ -434,7 +539,7 @@ class Importer extends Component
'Warranty',
'Warranty Months'
],
'qty' =>
'quantity' =>
[
'QTY',
'Quantity'
@ -493,6 +598,8 @@ class Importer extends Component
foreach ($this->importTypes as $type => $name) {
$this->columnOptions[$type] = $this->getColumns($type);
}
$this->mapping_errors = [];
}
public function selectFile($id)
@ -521,6 +628,8 @@ class Importer extends Component
}
$this->import_errors = null;
$this->statusText = null;
$this->mapping_errors = [];
$this->updatedFieldMap("x", -1); //force trigger the duplicate-fieldmapping (and minimum fieldmapping) code
}

View file

@ -147,7 +147,8 @@
{{ trans('general.import_type') }}
</label>
<div class="col-md-9 col-xs-12" wire:ignore>
<div class="col-md-9 col-xs-12"
wire:ignore> {{-- FIXME - this shouldn't be wire:ignore'd --}}
{{ Form::select('typeOfImport', $importTypes, $typeOfImport, [
'id' => 'import_type',
'class' => 'livewire-select2',
@ -207,7 +208,7 @@
<hr style="border-top: 1px solid lightgray">
</div>
<div class="form-group col-md-12">
<div class="col-md-3 text-right">
<div class="col-md-2 text-right">
<strong>{{ trans('general.csv_header_field') }}</strong>
</div>
<div class="col-md-4">
@ -216,6 +217,9 @@
<div class="col-md-5">
<strong>{{ trans('general.sample_value') }}</strong>
</div>
<div class="col-md-1">
<strong>Status</strong> {{-- FIXME - TRANSLATE ME! --}}
</div>
</div><!-- /div row -->
@if(! empty($headerRow))
@ -224,9 +228,9 @@
<div class="form-group col-md-12" wire:key="header-row-{{ $index }}">
<label for="field_map.{{ $index }}" class="col-md-3 control-label text-right">{{ $header }}</label>
<div class="col-md-4" wire:ignore>
<label for="field_map.{{ $index }}"
class="col-md-2 control-label text-right">{{ $header }}</label>
<div class="col-md-4">
{{ Form::select('field_map.'.$index, $columnOptions[$typeOfImport], @$field_map[$index],
[
'class' => 'mappings livewire-select2',
@ -242,6 +246,11 @@
<div class="col-md-5">
<p class="form-control-static">{{ str_limit($this->activeFile->first_row[$index], 50, '...') }}</p>
</div>
<div class="col-md-1">
@if(array_key_exists($index, $mapping_errors))
BAD MAPPING
@endif
</div>
@else
@php
$statusText = trans('help.empty_file');
@ -259,7 +268,9 @@
<a href="#" wire:click.prevent="$set('activeFileId',null)">{{ trans('general.cancel') }}</a>
</div>
<div class="col-md-9">
<button type="submit" class="btn btn-primary col-md-5" id="import">{{ trans('admin/hardware/message.import.import_button') }}</button>
<button type="submit"
class="btn btn-primary col-md-5"
{{ $enough_data_to_import ? '' : ' disabled="disabled"' }} id="import">{{ trans('admin/hardware/message.import.import_button') }}</button>
<br><br>
</div>
</div>