Merge pull request #12708 from uberbrady/livewire_importer_no_subcomponent
Livewire importer without subcomponent
This commit is contained in:
@@ -1,15 +1,13 @@
|
||||
<span> {{-- This <span> doesn't seem to fix it, neither does a div? --}}
|
||||
<div class="form-group{{ $errors->has('custom_fieldset') ? ' has-error' : '' }}">
|
||||
<label for="custom_fieldset" class="col-md-3 control-label">{{ trans('admin/models/general.fieldset') }}</label>
|
||||
<span wire:ignore> {{-- wire:ignore is because Select 2 mangles the dom in many awful ways, and so does iCheckbox --}}
|
||||
<div class="col-md-9">
|
||||
{{ Form::select('custom_fieldset', Helper::customFieldsetList(), old('custom_fieldset', $fieldset_id), array('class'=>'select2 js-fieldset-field', 'style'=>'width:350px', 'aria-label'=>'custom_fieldset', 'wire:model' => 'fieldset_id', 'id' => 'glooobits')) }} {{-- when we have this wrapped in 'ignore', the wire:model won't work --}}
|
||||
{{ Form::select('fieldset_id', Helper::customFieldsetList(), old('fieldset_id', $fieldset_id), array('class'=>'select2 js-fieldset-field livewire-select2', 'style'=>'width:350px', 'aria-label'=>'custom_fieldset', 'data-livewire-component' => $_instance->id)) }}
|
||||
{!! $errors->first('custom_fieldset', '<span class="alert-msg" aria-hidden="true"><br><i class="fas fa-times"></i> :message</span>') !!}
|
||||
<label class="m-l-xs">
|
||||
{{ Form::checkbox('add_default_values', 1, Request::old('add_default_values', $add_default_values), ['class' => 'minimal', 'wire:model' => "add_default_values", 'id' => 'add_default_values']) }}
|
||||
<label class="m-l-xs" wire:ignore>
|
||||
{{ Form::checkbox('add_default_values', 1, Request::old('add_default_values', $add_default_values), ['class' => 'minimal livewire-icheck', 'data-livewire-component' => $_instance->id, 'id' => 'add_default_values']) }}
|
||||
{{ trans('admin/models/general.add_default_values') }}
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@if ($this->add_default_values ) {{-- 'if the checkbox is enabled *AND* there are more than 0 fields in the fieldsset' --}}
|
||||
@@ -63,34 +61,4 @@
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<script>
|
||||
// *still* haven't figured out why this doesn't seem to work at all...
|
||||
// And even if it did, I hate having $(function () {}) as my DOM-ready checker in some places, and
|
||||
// DOMContentLoaded in another...
|
||||
/* document.addEventListener("DOMContentLoaded", function () {
|
||||
Livewire.hook('component.initialized', function (component) {
|
||||
$('#glooobits').on('select2:select',function (event) { //'change' seems to be the jquery-compatible version but I think the select2 versions might be nicer.
|
||||
console.log("Select2 has changed!!!!!")
|
||||
console.dir(event)
|
||||
@this.set('fieldset_id',event.params.data.id)
|
||||
// Livewire.first().set('fieldset_id',event.params.data.id) // I still don't know why @this does'nt work here?
|
||||
})
|
||||
|
||||
})
|
||||
}) */
|
||||
|
||||
</script>
|
||||
@push('js')
|
||||
<script>
|
||||
$(function () {
|
||||
$('#glooobits').on('select2:select',function (event) { //'change' seems to be the jquery-compatible version but I think the select2 versions might be nicer.
|
||||
{{-- @this.set('fieldset_id',event.params.data.id) --}}
|
||||
Livewire.first().set('fieldset_id',event.params.data.id) // I still don't know why @this does'nt work here?
|
||||
})
|
||||
$('#add_default_values').on('ifToggled',function (event) {
|
||||
Livewire.first().set('add_default_values',event.target.checked)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
@endpush
|
||||
</span>
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
@section('title')
|
||||
{{ trans('general.import') }}
|
||||
@parent
|
||||
@stop
|
||||
<div>
|
||||
{{-- Livewire requires a 'master' <div>, above --}}
|
||||
<div class="row">
|
||||
|
||||
{{-- alert --}}
|
||||
@if($message != '')
|
||||
<div class="col-md-12" class="{{ $message_type }}">
|
||||
<div class="alert alert-{{ $this->message_type }} ">
|
||||
<button type="button" class="close" wire:click="$set('message','')">×</button>
|
||||
@if($message_type == 'success')
|
||||
<i class="fas fa-check faa-pulse animated" aria-hidden="true"></i>
|
||||
@endif
|
||||
<strong>{{-- title --}} </strong>
|
||||
{{ $message }}
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($import_errors)
|
||||
<div class="box">
|
||||
<div class="box-body">
|
||||
<div class="alert alert-warning">
|
||||
<strong>Warning</strong> Some Errors occurred while importing {{-- TODO: hardcoded string --}}
|
||||
</div>
|
||||
|
||||
<div class="errors-table">
|
||||
<table class="table table-striped table-bordered" id="errors-table">
|
||||
<thead>
|
||||
<th>{{ trans('general.item') }}</th>
|
||||
<th>{{ trans('general.error') }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
@php \Log::error("import errors are: ".print_r($import_errors,true)); @endphp
|
||||
@foreach($import_errors AS $key => $actual_import_errors)
|
||||
@php \Log::error("Key is: $key"); @endphp
|
||||
@foreach($actual_import_errors AS $table => $error_bag)
|
||||
@php \Log::error("Table is: $table"); @endphp
|
||||
@foreach($error_bag as $field => $error_list)
|
||||
@php \Log::error("Field is: $field"); @endphp
|
||||
<tr>
|
||||
<td>{{ $activeFile->file_path ?? "Unknown File" }}</td>
|
||||
<td>
|
||||
<b>{{ $field }}:</b>
|
||||
<span>{{ implode(", ",$error_list) }}</span>
|
||||
<br />
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@endforeach
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="col-md-9">
|
||||
<div class="box">
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
@if($progress != -1)
|
||||
<div class="col-md-9" style="padding-bottom:20px" id='progress-container'>
|
||||
<div class="progress progress-striped-active" style="margin-top: 8px"> {{-- so someof these values are in importer.vue! --}}
|
||||
<div id='progress-bar' class="progress-bar {{ $progress_bar_class }}" role="progressbar" style="width: {{ $progress }}%">
|
||||
<span id='progress-text'>{{ $progress_message }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="col-md-3 text-right pull-right">
|
||||
|
||||
<!-- The fileinput-button span is used to style the file input field as button -->
|
||||
@if (!config('app.lock_passwords'))
|
||||
<span class="btn btn-primary fileinput-button">
|
||||
<span>{{ trans('button.select_file') }}</span>
|
||||
<!-- The file input field used as target for the file upload widget -->
|
||||
<label for="files[]"><span class="sr-only">{{ trans('admin/importer/general.select_file') }}</span></label>
|
||||
<input id="fileupload" type="file" name="files[]" data-url="{{ route('api.imports.index') }}" accept="text/csv" aria-label="files[]">
|
||||
</span>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 table-responsive" style="padding-top: 30px;">
|
||||
<table data-pagination="true"
|
||||
data-id-table="upload-table"
|
||||
data-search="true"
|
||||
data-side-pagination="client"
|
||||
id="upload-table"
|
||||
class="col-md-12 table table-striped snipe-table">
|
||||
|
||||
<tr>
|
||||
<th class="col-md-6">
|
||||
{{ trans('general.file_name') }}
|
||||
</th>
|
||||
<th class="col-md-3">
|
||||
{{ trans('general.created_at') }}
|
||||
</th>
|
||||
<th class="col-md-1">
|
||||
{{ trans('general.filesize') }}
|
||||
</th>
|
||||
<th class="col-md-1 text-right">
|
||||
<span class="sr-only">{{ trans('general.actions') }}</span>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
@foreach($files as $currentFile)
|
||||
|
||||
<tr style="{{ ($activeFile && ($currentFile->id == $activeFile->id)) ? 'font-weight: bold' : '' }}" class="{{ ($activeFile && ($currentFile->id == $activeFile->id)) ? 'warning' : '' }}">
|
||||
<td class="col-md-6">{{ $currentFile->file_path }}</td>
|
||||
<td class="col-md-3">{{ Helper::getFormattedDateObject($currentFile->created_at, 'datetime', false) }}</td>
|
||||
<td class="col-md-1">{{ Helper::formatFilesizeUnits($currentFile->filesize) }}</td>
|
||||
<td class="col-md-1 text-right">
|
||||
<button class="btn btn-sm btn-info" wire:click="selectFile({{ $currentFile->id }})">
|
||||
<i class="fas fa-retweet fa-fw" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.import') }}</span>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-danger" wire:click="destroy({{ $currentFile->id }})">
|
||||
<i class="fas fa-trash icon-white" aria-hidden="true"></i><span class="sr-only"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@if( $currentFile && $activeFile && ($currentFile->id == $activeFile->id))
|
||||
<tr class="warning">
|
||||
<td colspan="4">
|
||||
|
||||
<div class="col-md-12">
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
|
||||
<label for="activeFile.import_type" class="col-md-3 col-xs-12 text-right">
|
||||
Import Type
|
||||
</label>
|
||||
|
||||
<div class="col-md-9 col-xs-12">
|
||||
{{ Form::select('activeFile.import_type', $importTypes, $activeFile->import_type, [
|
||||
'id' => 'import_type',
|
||||
'class' => 'livewire-select2',
|
||||
'style' => 'min-width: 350px',
|
||||
'data-placeholder' => trans('general.select_var', ['thing' => trans('general.import_type')]), /* TODO: translate me */
|
||||
'placeholder' => '', //needed so that the form-helper will put an empty option first
|
||||
'data-minimum-results-for-search' => '-1', // Remove this if the list gets long enough that we need to search
|
||||
'data-livewire-component' => $_instance->id
|
||||
]) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="update" class="col-md-9 col-md-offset-3 col-xs-12" wire:ignore>
|
||||
<input type="checkbox" class="minimal livewire-icheck" name="update" data-livewire-component="{{ $_instance->id }}">
|
||||
Update Existing Values?
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="send_welcome" class="col-md-9 col-md-offset-3 col-xs-12" wire:ignore>
|
||||
<input type="checkbox" class="minimal livewire-icheck" name="send_welcome" data-livewire-component="{{ $_instance->id }}">
|
||||
Send Welcome Email for new Users?
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="run_backup" class="col-md-9 col-md-offset-3 col-xs-12" wire:ignore>
|
||||
<input type="checkbox" class="minimal livewire-icheck" name="run_backup" data-livewire-component="{{ $_instance->id }}">
|
||||
Backup before importing?
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
@if ($statusText)
|
||||
<div class="form-group">
|
||||
<div class="alert col-md-8 col-md-offset-2 {{ $statusType == 'success' ? 'alert-success' : ($statusType == 'error' ? 'alert-danger' : 'alert-info') }}" style="text-align:left">
|
||||
{{ $statusText }}
|
||||
</div><!-- /alert -->
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
@if ($activeFile->import_type)
|
||||
<div class="form-group col-md-12">
|
||||
<hr style="border-top: 1px solid lightgray">
|
||||
<h3><i class="{{ Helper::iconTypeByItem($activeFile->import_type) }}"></i> Map {{ ucwords($activeFile->import_type) }} Import Fields</h3>
|
||||
<hr style="border-top: 1px solid lightgray">
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<div class="col-md-3 text-right">
|
||||
<strong>CSV Header Field</strong>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<strong>Import Field</strong>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<strong>Sample Value</strong>
|
||||
</div>
|
||||
</div><!-- /div row -->
|
||||
|
||||
@if($activeFile->header_row)
|
||||
|
||||
@foreach($activeFile->header_row as $index => $header)
|
||||
|
||||
<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">
|
||||
|
||||
{{ Form::select('field_map.'.$index, $columnOptions[$activeFile->import_type], @$field_map[$index],
|
||||
[
|
||||
'class' => 'mappings livewire-select2',
|
||||
'placeholder' => 'Do Not Import',
|
||||
'style' => 'min-width: 100%',
|
||||
'data-livewire-component' => $_instance->id
|
||||
],[
|
||||
'-' => ['disabled' => true] // this makes the "-----" line unclickable
|
||||
])
|
||||
}}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<p class="form-control-static">{{ str_limit($activeFile->first_row[$index], 50, '...') }}</p>
|
||||
</div>
|
||||
</div><!-- /div row -->
|
||||
@endforeach
|
||||
@else
|
||||
No Columns Found!
|
||||
@endif
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<div class="col-md-3 text-left">
|
||||
<a href="#" wire:click="$set('activeFile',null)">{{ trans('general.cancel') }}</a>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<button type="submit" class="btn btn-primary col-md-5" id="import">Import</button>
|
||||
<br><br>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($statusText)
|
||||
<div class="alert col-md-12 col-md-offset-2 {{ $statusType == 'success' ? 'alert-success' : ($statusType == 'error' ? 'alert-danger' : 'alert-info') }}" style="padding-top: 20px;">
|
||||
{{ $statusText }}
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="form-group col-md-12">
|
||||
<div class="col-md-3 text-left">
|
||||
<a href="#" wire:click="$set('activeFile',null)"><?php echo e(trans('general.cancel')); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
@endif {{-- end of if ... activeFile->import_type --}}
|
||||
|
||||
</div><!-- /div v-show --> </td>
|
||||
</tr>
|
||||
@endif
|
||||
</tr>
|
||||
@endforeach
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h2>{{ trans('general.importing') }}</h2>
|
||||
<p>{!! trans('general.importing_help') !!}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@push('js')
|
||||
<script>
|
||||
|
||||
{{-- TODO: Maybe change this to the file upload thing that's baked-in to Livewire? --}}
|
||||
$('#fileupload').fileupload({
|
||||
dataType: 'json',
|
||||
done: function(e, data) {
|
||||
@this.progress_bar_class = 'progress-bar-success';
|
||||
@this.progress_message = '{{ trans('general.notification_success') }}'; // TODO - we're already round-tripping to the server here - I'd love it if we could get internationalized text here
|
||||
@this.progress = 100;
|
||||
},
|
||||
add: function(e, data) {
|
||||
data.headers = {
|
||||
"X-Requested-With": 'XMLHttpRequest',
|
||||
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr('content')
|
||||
};
|
||||
data.process().done( function () {data.submit();});
|
||||
@this.progress = 0;
|
||||
},
|
||||
progress: function(e, data) {
|
||||
@this.progress = parseInt((data.loaded / data.total * 100, 10));
|
||||
@this.progress_message = @this.progress+'% Complete'; // TODO - this should come from server (so it can be internationalized)
|
||||
},
|
||||
fail: function(e, data) {
|
||||
@this.progress_bar_class = "progress-bar-danger";
|
||||
@this.progress = 100;
|
||||
|
||||
var error_message = ''
|
||||
for(var i in data.jqXHR.responseJSON.messages) {
|
||||
error_message += i+": "+data.jqXHR.responseJSON.messages[i].join(", ")
|
||||
}
|
||||
@this.progress_message = error_message;
|
||||
}
|
||||
})
|
||||
|
||||
// For the importFile part:
|
||||
$(function () {
|
||||
// initialize iCheck for use with livewire
|
||||
$('.minimal.livewire-icheck').iCheck({
|
||||
checkboxClass: 'icheckbox_minimal-blue',
|
||||
})
|
||||
|
||||
// we have to hook up to the `<tr id='importer-file'>` at the root of this display,
|
||||
// because the #import button isn't visible until you click an import_type
|
||||
$('#upload-table').on('click', '#import', function () {
|
||||
if(!@this.activeFile.import_type) {
|
||||
@this.statusType='error';
|
||||
@this.statusText= "An import type is required... "; //TODO: translate?
|
||||
return;
|
||||
}
|
||||
@this.statusType ='pending';
|
||||
@this.statusText = "{{ trans('admin/hardware/form.processing_spinner') }}";
|
||||
@this.generate_field_map().then(function (mappings_raw) {
|
||||
var mappings = JSON.parse(mappings_raw)
|
||||
// console.warn("Here is the mappings:")
|
||||
// console.dir(mappings)
|
||||
// console.warn("Uh, active file id is, I guess: "+@this.activeFile.id)
|
||||
var this_file = @this.file_id; // okay, I actually don't know what I'm doing here.
|
||||
$.post({
|
||||
{{-- I want to do something like: route('api.imports.importFile', $activeFile->id) }} --}}
|
||||
url: "api/v1/imports/process/"+this_file, // maybe? Good a guess as any..FIXME. HARDCODED DUMB FILE
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
'import-update': !!@this.update,
|
||||
'send-welcome': !!@this.send_welcome,
|
||||
'import-type': @this.activeFile.import_type,
|
||||
'run-backup': !!@this.run_backup,
|
||||
'column-mappings': mappings
|
||||
}),
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr('content')
|
||||
}
|
||||
}).done( function (body) {
|
||||
// Success
|
||||
@this.statusType="success";
|
||||
@this.statusText = "Success... Redirecting.";
|
||||
// console.dir(body)
|
||||
window.location.href = body.messages.redirect_url;
|
||||
}).fail( function (jqXHR, textStatus, error) {
|
||||
// Failure
|
||||
var body = jqXHR.responseJSON
|
||||
if(body.status == 'import-errors') {
|
||||
@this.emit('importError', body.messages);
|
||||
@this.import_errors = body.messages
|
||||
|
||||
@this.statusType='error';
|
||||
@this.statusText = "Error";
|
||||
} else {
|
||||
console.warn("Not import-errors, just regular errors")
|
||||
console.dir(body)
|
||||
{{-- @this.emit('alert', body.error)--}}
|
||||
@this.message_type="danger"
|
||||
@this.message = body.error
|
||||
}
|
||||
@this.activeFile = null; //@this.set('hideDetails')
|
||||
});
|
||||
})
|
||||
return false;
|
||||
});})
|
||||
|
||||
</script>
|
||||
@endpush
|
||||
Reference in New Issue
Block a user