Add required fields + validation step, headers checkbox can be toggled

This commit is contained in:
Samuel Georges 2015-07-21 07:56:55 +10:00
parent f99f838faf
commit 5a40c54f3c
8 changed files with 160 additions and 39 deletions

View File

@ -5,6 +5,7 @@ use Backend\Classes\ControllerBehavior;
use League\Csv\Writer as CsvWrtier;
use League\Csv\Reader as CsvReader;
use ApplicationException;
use Exception;
/**
* Import/Export Controller Behavior
@ -79,8 +80,61 @@ class ImportExportController extends ControllerBehavior
// TBA
}
//
// Importing AJAX
//
public function onImport()
{
// traceLog(post());
}
public function onImportLoadForm()
{
try {
$this->checkRequiredImportColumns();
}
catch (Exception $ex) {
$this->controller->handleError($ex);
}
return $this->importExportMakePartial('import_form');
}
public function onImportLoadColumnSampleForm()
{
if (($columnId = post('file_column_id', false)) === false) {
throw new ApplicationException('Missing column identifier');
}
$columns = $this->getImportFileColumns();
if (!array_key_exists($columnId, $columns)) {
throw new ApplicationException('Unknown column');
}
$path = $this->getImportFilePath();
$reader = CsvReader::createFromPath($path);
if (post('first_row_titles')) {
$reader->setOffset(1);
}
$data = $reader->setLimit(20)->fetchColumn((int) $columnId);
/*
* Clean up data
*/
foreach ($data as $index => $sample) {
$data[$index] = Str::limit($sample, 100);
if (!strlen($data[$index])) {
unset($data[$index]);
}
}
$this->vars['columnName'] = array_get($columns, $columnId);
$this->vars['columnData'] = $data;
return $this->importExportMakePartial('column_sample_form');
}
//
@ -173,40 +227,34 @@ class ImportExportController extends ControllerBehavior
return $file->getLocalPath();
}
public function onImportLoadColumnSamplePopup()
public function importIsColumnRequired($columnName)
{
if (($columnId = post('file_column_id', false)) === false) {
throw new ApplicationException('Missing column identifier');
$model = $this->importGetModel();
return $model->isAttributeRequired($columnName);
}
protected function checkRequiredImportColumns()
{
if (!$matches = post('column_match', [])) {
throw new ApplicationException('Please match some columns first.');
}
$columns = $this->getImportFileColumns();
if (!array_key_exists($columnId, $columns)) {
throw new ApplicationException('Unknown column');
}
$dbColumns = $this->getImportDbColumns();
foreach ($dbColumns as $column => $label) {
if (!$this->importIsColumnRequired($column)) continue;
$path = $this->getImportFilePath();
$reader = CsvReader::createFromPath($path);
$found = false;
foreach ($matches as $matchedColumns) {
if (in_array($column, $matchedColumns)) {
$found = true;
break;
}
}
if (post('first_row_titles')) {
$reader->setOffset(1);
}
$data = $reader->setLimit(20)->fetchColumn((int) $columnId);
/*
* Clean up data
*/
foreach ($data as $index => $sample) {
$data[$index] = Str::limit($sample, 100);
if (!strlen($data[$index])) {
unset($data[$index]);
if (!$found) {
throw new ApplicationException('Please specify a match for the required field '.$label.'.');
}
}
$this->vars['columnName'] = array_get($columns, $columnId);
$this->vars['columnData'] = $data;
return $this->importExportMakePartial('column_sample_popup');
}
//

View File

@ -62,6 +62,9 @@
.import-behavior .import-db-columns > ul > li:hover .column-icon {
color: #4da7e8;
}
.import-behavior .import-db-columns > ul > li.is-required .column-icon {
color: #ab2a1c;
}
.import-behavior .import-file-columns > ul > li:before,
.import-behavior .import-file-columns > ul > li:after {
content: " ";
@ -70,7 +73,7 @@
.import-behavior .import-file-columns > ul > li:after {
clear: both;
}
.import-behavior .import-file-columns > ul > li.column-ignored {
.import-behavior .import-file-columns > ul > li.is-ignored {
display: none;
}
.import-behavior .import-file-columns > ul > li .column-success-icon {
@ -79,10 +82,10 @@
left: -2px;
width: 15px;
}
.import-behavior .import-file-columns > ul > li.column-matched .column-success-icon {
.import-behavior .import-file-columns > ul > li.is-matched .column-success-icon {
display: inline-block;
}
.import-behavior .import-file-columns > ul > li.column-matched .column-ignore-button {
.import-behavior .import-file-columns > ul > li.is-matched .column-ignore-button {
display: none !important;
}
.import-behavior .import-file-columns > ul div.import-column-name {

View File

@ -69,19 +69,19 @@
this.toggleMatchState = function ($container) {
var hasItems = !!$('.import-column-bindings li', $container).length
$container.toggleClass('column-matched', hasItems)
$container.toggleClass('is-matched', hasItems)
}
this.ignoreFileColumn = function(el) {
var $el = $(el),
$column = $el.closest('[data-column-id]')
$column.addClass('column-ignored')
$column.addClass('is-ignored')
$('#showIgnoredColumnsButton').removeClass('disabled')
}
this.showIgnoredColumns = function(el) {
$('#importFileColumns li.column-ignored').removeClass('column-ignored')
$('#importFileColumns li.is-ignored').removeClass('is-ignored')
$('#showIgnoredColumnsButton').addClass('disabled')
}
@ -91,12 +91,18 @@
columnId = $column.data('column-id')
$el.popup({
handler: 'onImportLoadColumnSamplePopup',
handler: 'onImportLoadColumnSampleForm',
extraData: {
file_column_id: columnId
}
})
}
this.processImport = function () {
var $form = $('#importFileColumns').closest('form')
$form.request('onImport')
}
}
$.oc.importBehavior = new ImportBehavior;

View File

@ -79,6 +79,12 @@
&:hover .column-icon {
color: #4da7e8;
}
&.is-required {
.column-icon {
color: #ab2a1c;
}
}
}
}
@ -86,7 +92,7 @@
> li {
.clearfix;
&.column-ignored {
&.is-ignored {
display: none;
}
@ -97,7 +103,7 @@
width: 15px;
}
&.column-matched {
&.is-matched {
.column-success-icon {
display: inline-block;
}

View File

@ -1,9 +1,15 @@
<div class="import-db-columns" id="importDbColumns">
<ul>
<?php foreach ($importDbColumns as $column => $label): ?>
<li data-column-name="<?= e($column) ?>">
<?php
$isRequired = $this->importIsColumnRequired($column);
$iconName = $isRequired ? 'icon-asterisk' : 'icon-link';
?>
<li
class="<?= $isRequired ? 'is-required' : '' ?>"
data-column-name="<?= e($column) ?>">
<span>
<i class="column-icon icon-link"></i>
<i class="column-icon <?= $iconName ?>"></i>
<?= e($label) ?>
</span>
<input type="hidden" data-column-match-input />

View File

@ -0,0 +1,51 @@
<div id="importFormPopup">
<?php if (!$this->fatalError): ?>
<?= Form::open(['id' => 'importForm']) ?>
<div class="modal-header">
<h4 class="modal-title">Import progress</h4>
</div>
<div id="importContainer">
<div class="modal-body">
<div class="loading-indicator-container">
<p>&nbsp;</p>
<div class="loading-indicator transparent">
<div>Processing</div>
<span></span>
</div>
</div>
<p>&nbsp;</p>
</div>
</div>
<?= Form::close() ?>
<script>
$('#importFormPopup').on('popupComplete', function() {
$.oc.importBehavior.processImport()
})
</script>
<?php else: ?>
<div class="modal-header">
<button type="button" class="close" data-dismiss="popup">&times;</button>
<h4 class="modal-title">Import error</h4>
</div>
<div class="modal-body">
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-default"
data-dismiss="popup">
<?= e(trans('backend::lang.form.close')) ?>
</button>
</div>
<?php endif ?>
</div>

View File

@ -33,13 +33,14 @@ fields:
label: File columns
type: partial
path: ~/modules/backend/behaviors/importexportcontroller/partials/_import_file_columns.htm
dependsOn: import_file
dependsOn: [import_file, first_row_titles]
span: left
import_db_columns:
label: Database fields
type: partial
path: ~/modules/backend/behaviors/importexportcontroller/partials/_import_db_columns.htm
dependsOn: [import_file, first_row_titles]
span: right
step3_section: