implement column edit api, except sort

pull/35/head
Ondřej Hruška 6 years ago
parent e3a8616c68
commit 1fbd3384ce
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 24
      app/Http/Controllers/TableEditController.php
  2. 109
      app/Tables/Changeset.php
  3. 21
      app/Tables/Column.php
  4. 8
      resources/assets/js/components/ColumnEditor.vue
  5. 2
      resources/assets/js/components/RowsEditor.vue

@ -128,9 +128,7 @@ class TableEditController extends Controller
switch ($input->action) { switch ($input->action) {
case 'row.update': case 'row.update':
$data = (object)$input->data; $data = (object)$input->data;
$changeset->rowUpdate($data); $resp = $changeset->rowUpdate($data);
$resp = $changeset->fetchAndTransformRow($data->_id);
break; break;
case 'row.remove': case 'row.remove':
@ -170,6 +168,26 @@ class TableEditController extends Controller
} }
break; 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: default:
$resp = "Bad Action"; $resp = "Bad Action";
$code = 400; $code = 400;

@ -276,6 +276,41 @@ class Changeset
return $cachedColumns = $newOrder; 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) public function rowRemove(int $id)
{ {
if ($this->isNewRow($id)) { if ($this->isNewRow($id)) {
@ -296,6 +331,11 @@ class Changeset
return isset($this->newRows[$id]); return isset($this->newRows[$id]);
} }
public function isNewColumn(string $id)
{
return isset($this->newColumns[$id]);
}
public function fetchAndTransformRow(int $id) public function fetchAndTransformRow(int $id)
{ {
$r = $this->fetchRow($id); $r = $this->fetchRow($id);
@ -337,6 +377,7 @@ class Changeset
* if all differences were undone. * if all differences were undone.
* *
* @param array|object $newVals - values of the new row * @param array|object $newVals - values of the new row
* @return object - updated column
*/ */
public function rowUpdate($newVals) public function rowUpdate($newVals)
{ {
@ -373,6 +414,56 @@ class Changeset
unset($this->rowUpdates[$_id]); 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()); $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;
}
} }

@ -71,7 +71,7 @@ class Column implements JsonSerializable, Arrayable
foreach ((array)$columnObject as $key => $value) { foreach ((array)$columnObject as $key => $value) {
if ($value != $this->$key) { if ($value != $this->$key) {
$this->modified_attribs[] = $key; $this->modified_attribs[] = $key;
$this->orig_attribs[] = $this->$key; $this->orig_attribs[$key] = $this->$key;
$this->$key = $value; $this->$key = $value;
} }
} }
@ -123,16 +123,21 @@ class Column implements JsonSerializable, Arrayable
/** /**
* Create from object or array * Create from object or array
* *
* @param $obj * @param object|array $obj
*/ */
public function __construct($obj) public function __construct($obj, $allowEmptyName=false)
{ {
$b = objBag($obj); $b = objBag($obj);
if (!$b->has('name') || $b->name == '') throw new NotApplicableException('Missing name in column'); if (!$allowEmptyName && (!$b->has('name') || $b->name == '')) {
if (!$b->has('type')) throw new NotApplicableException('Missing type in column'); 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."); throw new NotApplicableException("Column name can't start with underscore.");
} }
@ -156,6 +161,10 @@ class Column implements JsonSerializable, Arrayable
'name' => $this->name, 'name' => $this->name,
'title' => $this->title, 'title' => $this->title,
'type' => $this->type, 'type' => $this->type,
'_new' => $this->isNew,
'_remove' => $this->toRemove,
'_changed' => $this->modified_attribs,
'_orig' => $this->orig_attribs,
]; ];
} }

@ -16,7 +16,7 @@ Complex animated column editor for the table edit page
</tr> </tr>
</thead> </thead>
<transition-group name="col-list" tag="tbody" ref="col-list"> <transition-group name="col-list" tag="tbody" ref="col-list">
<tr v-for="(col, i) in columns" :key="col.id" :ref="`col${i}`" :class="{dragging: col._dragging}"> <tr v-for="(col, i) in columns" :key="col.id" :ref="`col${i}`" :class="{dragging: col._dragging, 'text-success': col._new}">
<td v-if="sortable"> <td v-if="sortable">
<span class="btn-group"> <span class="btn-group">
<button type="button" class="btn btn-outline-secondary drag-btn" <button type="button" class="btn btn-outline-secondary drag-btn"
@ -187,7 +187,7 @@ export default {
name: { type: String, required: true }, name: { type: String, required: true },
xColumns: { type: Array, required: true }, xColumns: { type: Array, required: true },
}, },
data: function () { data () {
return { return {
newColNum: 0, newColNum: 0,
columns: this.xColumns, columns: this.xColumns,
@ -335,7 +335,7 @@ export default {
// if response is null, this was a New col // if response is null, this was a New col
// and it was discarded without a way back - hard drop // and it was discarded without a way back - hard drop
if (_.isEmpty(resp.data)) { if (_.isEmpty(resp.data)) {
this.$delete(this.col, n) this.$delete(this.columns, n)
} }
else { else {
this.$set(this.columns, n, resp.data) this.$set(this.columns, n, resp.data)
@ -369,7 +369,7 @@ export default {
}, },
tdWidthStyle(cell) { tdWidthStyle(cell) {
let w = 100; let w = 10;
if (cell == 'name') w = '14' if (cell == 'name') w = '14'
if (cell == 'type') w = '12' if (cell == 'type') w = '12'
if (cell == 'title') w = '14' if (cell == 'title') w = '14'

@ -73,7 +73,7 @@ Rows are identified by row._id, columns by col.id
xRows: Object, // key'd by _id xRows: Object, // key'd by _id
columns: Array, columns: Array,
}, },
data: function () { data () {
return { return {
rows: this.xRows, rows: this.xRows,
} }

Loading…
Cancel
Save