CSV import, also from file, and more UX improvements

This commit is contained in:
2018-08-10 20:19:16 +02:00
parent 1e183f5059
commit a3df7a724c
18 changed files with 371 additions and 155 deletions
+47 -12
View File
@@ -60,8 +60,9 @@ class TableEditController extends Controller
if ($tableModel === null) abort(404, "No such table.");
if ($tab == null) $tab = 'edit-rows';
$tabs = ['edit-rows', 'add-rows', 'manage-columns', 'review'];
if (!in_array($tab, $tabs)) abort(404, "No such tab: $tab");
$method = camel_case($tab);
if (!method_exists($this, $method)) abort(404, "No such tab: $tab");
$changeset = $this->getChangeset($tableModel);
@@ -69,7 +70,7 @@ class TableEditController extends Controller
dd($changeset);
}
return $this->{camel_case($tab)}($changeset);
return $this->$method($changeset);
}
/** @noinspection PhpUnusedPrivateMethodInspection */
@@ -101,6 +102,18 @@ class TableEditController extends Controller
]);
}
/** @noinspection PhpUnusedPrivateMethodInspection */
private function addRowsCsv(Changeset $changeset)
{
$columns = $changeset->fetchAndTransformColumns();
return view('table.propose.add-rows-csv', [
'changeset' => $changeset,
'table' => $changeset->table,
'columns' => collect($columns),
]);
}
/** @noinspection PhpUnusedPrivateMethodInspection */
private function manageColumns(Changeset $changeset)
{
@@ -143,13 +156,43 @@ class TableEditController extends Controller
$resp = $updated;
break;
case 'row.add-csv':
$fname = 'csv-file';
if ($request->hasFile($fname)) {
try {
$file = $request->file($fname);
if ($file->isValid() && $file->isReadable()) {
$handle = $file->openFile();
$csv = Utils::csvToArray($handle);
if (empty($csv)) throw new \Exception("Failed to parse CSV file.");
$changeset->addFilledRows($csv);
$handle = null;
} else {
throw new \Exception("File not valid.");
}
} catch (\Exception $e) {
return $this->backWithErrors(['csv-file' => $e->getMessage()]);
}
}
else {
try {
$text = trim($input->data);
if (empty($text)) throw new \Exception("Empty CSV field and no file uploaded.");
$changeset->addFilledRows(Utils::csvToArray($text));
} catch (\Exception $e) {
return $this->backWithErrors(['data' => $e->getMessage()]);
}
}
break;
case 'row.remove':
$isNew = $changeset->isNewRow($input->id);
$changeset->rowRemove($input->id);
$resp = $isNew ? null : $changeset->fetchAndTransformRow($input->id);
break;
case 'rows.remove-empty-new':
case 'row.remove-empty-new':
$changeset->removeEmptyNewRows();
break;
@@ -162,14 +205,6 @@ class TableEditController extends Controller
$changeset->addBlankRows($input->count);
break;
case 'rows.add-csv':
try {
$changeset->addFilledRows(Utils::csvToArray($input->data));
} catch (\Exception $e) {
return $this->backWithErrors(['data' => $e->getMessage()]);
}
break;
case 'col.update':
$data = (object)$input->data;
$resp = $changeset->columnUpdate($data);
+21 -7
View File
@@ -188,16 +188,19 @@ class Changeset
$row->_orig = [];
}
if ($decorate) {
$row->_orig = array_diff((array)$row, []);
// remove junk
unset($row->_orig['_id']);
unset($row->_orig['_new']);
unset($row->_orig['_remove']);
unset($row->_orig['_changed']);
unset($row->_orig['_orig']);
}
if ($this->isNewRow($row->_id)) {
if ($decorate) {
$row->_new = true;
$row->_orig = array_diff((array)$row, []);
// remove junk
unset($row->_orig['_id']);
unset($row->_orig['_new']);
unset($row->_orig['_remove']);
unset($row->_orig['_changed']);
unset($row->_orig['_orig']);
}
return $row;
}
@@ -235,6 +238,16 @@ class Changeset
unset($row->_row_pivot);
if ($decorate) {
$row->_loadvals = array_diff((array)$row, []);
// remove junk
unset($row->_loadvals['_id']);
unset($row->_loadvals['_new']);
unset($row->_loadvals['_remove']);
unset($row->_loadvals['_changed']);
unset($row->_loadvals['_orig']);
}
return $row;
}
@@ -582,6 +595,7 @@ class Changeset
'type' => "string",
'title' => "Column {$num}",
'id' => $cid,
'_new' => true,
];
$this->newColumns[$cid] = $col;
+18
View File
@@ -38,6 +38,19 @@ class WidgetFactory
"</div>";
}
public function labeledPar($label, $text, $extraClasses='', $escape=true)
{
if (false === strpos($extraClasses, 'mb-')) $extraClasses .= ' mb-2';
return
"<div class=\"row\">".
"<label class=\"text-md-right col-form-label col-md-$this->labelCols\">".e($label)."</label>".
"<p class=\"form-control-plaintext col-md-$this->fieldCols".e($extraClasses)."\">".
($escape ? e($text) : $text) .
"</p>".
"</div>";
}
/**
* Convert the given string to a-href if it is a link.
*
@@ -85,6 +98,11 @@ class WidgetFactory
return $this->baseWidget('input', $name, $label)->type('email');
}
public function file($name, $label)
{
return $this->baseWidget('input', $name, $label)->type('file');
}
public function checkbox($name, $label)
{
return (new CheckboxWidget('checkbox', $name, $label))