diff --git a/app/Http/Controllers/TableEditController.php b/app/Http/Controllers/TableEditController.php index 04b1b1b..a3d6464 100644 --- a/app/Http/Controllers/TableEditController.php +++ b/app/Http/Controllers/TableEditController.php @@ -128,9 +128,7 @@ class TableEditController extends Controller switch ($input->action) { case 'row.update': $data = (object)$input->data; - $changeset->rowUpdate($data); - - $resp = $changeset->fetchAndTransformRow($data->_id); + $resp = $changeset->rowUpdate($data); break; case 'row.remove': @@ -170,6 +168,26 @@ class TableEditController extends Controller } break; + case 'col.update': + $data = (object)$input->data; + $resp = $changeset->columnUpdate($data); + break; + + case 'col.remove': + $isNew = $changeset->isNewColumn($input->id); + $changeset->columnRemove($input->id); + $resp = $isNew ? null : $changeset->fetchAndTransformColumn($input->id); + break; + + case 'col.restore': + $changeset->columnRestore($input->id); + $resp = $changeset->fetchAndTransformColumn($input->id); + break; + + case 'col.add': + $resp = $changeset->addBlankCol(); + break; + default: $resp = "Bad Action"; $code = 400; diff --git a/app/Tables/Changeset.php b/app/Tables/Changeset.php index 7e4fbdf..2b27708 100644 --- a/app/Tables/Changeset.php +++ b/app/Tables/Changeset.php @@ -276,6 +276,41 @@ class Changeset return $cachedColumns = $newOrder; } + /** + * @param string $id + * @return Column + */ + public function fetchColumn(string $id) + { + if ($this->isNewColumn($id)) { + $c = new Column($this->newColumns[$id]); + $c->markAsNew(); + return $c; + } else { + $columns = collect($this->revision->columns)->keyBy('id'); + return new Column($columns[$id]); + } + } + + /** + * @param string $id + * @return Column + */ + public function fetchAndTransformColumn(string $id) + { + $column = $this->fetchColumn($id); + + if (isset($this->columnUpdates[$column->id])) { + $column->modifyByChangeset($this->columnUpdates[$column->id]); + } + + if (in_array($column->id, $this->removedColumns)) { + $column->markForRemoval(); + } + + return $column; + } + public function rowRemove(int $id) { if ($this->isNewRow($id)) { @@ -296,6 +331,11 @@ class Changeset return isset($this->newRows[$id]); } + public function isNewColumn(string $id) + { + return isset($this->newColumns[$id]); + } + public function fetchAndTransformRow(int $id) { $r = $this->fetchRow($id); @@ -337,6 +377,7 @@ class Changeset * if all differences were undone. * * @param array|object $newVals - values of the new row + * @return object - updated column */ public function rowUpdate($newVals) { @@ -373,6 +414,56 @@ class Changeset unset($this->rowUpdates[$_id]); } } + + return $this->fetchAndTransformRow($_id); + } + + /** + * @param $newVals + * @return Column + */ + public function columnUpdate($newVals) + { + $id = $newVals->id; + $col = $this->fetchColumn($id); + + $updateObj = []; + foreach ($newVals as $field => $value) { + if (starts_with($field, '_')) continue; // internals + + if ($value !== $col->$field) { + $updateObj[$field] = $value; + } + } + + if ($this->isNewColumn($id)) { + $this->newColumns[$id] = array_merge($this->newColumns[$id], $updateObj); + } + else { + if (!empty($updateObj)) { + $this->columnUpdates[$id] = $updateObj; + } else { + // remove possible old update record for this row, if nothing changes now + unset($this->columnUpdates[$id]); + } + } + + return $this->fetchAndTransformColumn($id); + } + + public function columnRemove(string $id) + { + if ($this->isNewColumn($id)) { + unset($this->newColumns[$id]); + } + else { + $this->removedColumns[] = $id; + } + } + + public function columnRestore(string $id) + { + $this->removedColumns = array_diff($this->removedColumns, [$id]); } /** @@ -464,4 +555,22 @@ class Changeset $this->newRows = array_merge($this->newRows, $rows->all()); } + + public function addBlankCol() + { + $cid = (new ColumnNumerator(1))->next(); + + $allCols = $this->fetchAndTransformColumns(); + $num = count($allCols) + 1; + + $col = [ + 'name' => "col_{$num}", + 'type' => "string", + 'title' => "Column {$num}", + 'id' => $cid, + ]; + + $this->newColumns[$cid] = $col; + return $col; + } } diff --git a/app/Tables/Column.php b/app/Tables/Column.php index 4c24329..80530cd 100644 --- a/app/Tables/Column.php +++ b/app/Tables/Column.php @@ -71,7 +71,7 @@ class Column implements JsonSerializable, Arrayable foreach ((array)$columnObject as $key => $value) { if ($value != $this->$key) { $this->modified_attribs[] = $key; - $this->orig_attribs[] = $this->$key; + $this->orig_attribs[$key] = $this->$key; $this->$key = $value; } } @@ -123,16 +123,21 @@ class Column implements JsonSerializable, Arrayable /** * Create from object or array * - * @param $obj + * @param object|array $obj */ - public function __construct($obj) + public function __construct($obj, $allowEmptyName=false) { $b = objBag($obj); - if (!$b->has('name') || $b->name == '') throw new NotApplicableException('Missing name in column'); - if (!$b->has('type')) throw new NotApplicableException('Missing type in column'); + if (!$allowEmptyName && (!$b->has('name') || $b->name == '')) { + throw new NotApplicableException('Missing name in column'); + } + + if (!$b->has('type')) { + throw new NotApplicableException('Missing type in column'); + } - if ($b->name[0] == '_') { // global row ID + if ($b->name[0] == '_') { // would cause problems with selects (see: _id / GRID) throw new NotApplicableException("Column name can't start with underscore."); } @@ -156,6 +161,10 @@ class Column implements JsonSerializable, Arrayable 'name' => $this->name, 'title' => $this->title, 'type' => $this->type, + '_new' => $this->isNew, + '_remove' => $this->toRemove, + '_changed' => $this->modified_attribs, + '_orig' => $this->orig_attribs, ]; } diff --git a/resources/assets/js/components/ColumnEditor.vue b/resources/assets/js/components/ColumnEditor.vue index f91217d..6a13171 100644 --- a/resources/assets/js/components/ColumnEditor.vue +++ b/resources/assets/js/components/ColumnEditor.vue @@ -16,7 +16,7 @@ Complex animated column editor for the table edit page - +