editing
Ondřej Hruška 6 years ago
parent a4103e7084
commit 06fb01d146
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 14
      app/Http/Controllers/TableEditController.php
  2. 31
      app/Tables/Changeset.php
  3. 25
      app/helpers.php
  4. 3
      resources/assets/js/components/Icon.vue
  5. 36
      resources/assets/js/components/RowEditor.vue
  6. 4
      resources/assets/sass/_helpers.scss

@ -79,7 +79,19 @@ class TableEditController extends Controller
]); ]);
} }
// TODO other tab handlers /** @noinspection PhpUnusedPrivateMethodInspection */
private function addRows(Changeset $changeset)
{
$columns = $changeset->fetchAndTransformColumns();
$rows = $changeset->getAddedRows(25);
return view('table.propose.add-rows', [
'changeset' => $changeset,
'table' => $changeset->table,
'columns' => collect($columns),
'rows' => $rows,
]);
}
public function draftUpdate(User $user, string $table, Request $request) public function draftUpdate(User $user, string $table, Request $request)
{ {

@ -6,6 +6,7 @@ namespace App\Tables;
use App\Models\Revision; use App\Models\Revision;
use App\Models\Row; use App\Models\Row;
use App\Models\Table; use App\Models\Table;
use Illuminate\Pagination\Paginator;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use MightyPork\Exceptions\NotExistException; use MightyPork\Exceptions\NotExistException;
@ -186,7 +187,7 @@ class Changeset
$row->_orig = []; $row->_orig = [];
} }
// Removed rows // Removed rows - return as null
if (in_array($row->_id, $this->removedRows)) { if (in_array($row->_id, $this->removedRows)) {
if ($decorate) { if ($decorate) {
$row->_remove = true; $row->_remove = true;
@ -195,6 +196,8 @@ class Changeset
} }
} }
// if marked for removal, hide changes
if (!$row->_remove) {
// Changed values // Changed values
if (isset($this->rowUpdates[$row->_id])) { if (isset($this->rowUpdates[$row->_id])) {
$newVals = $this->rowUpdates[$row->_id]; $newVals = $this->rowUpdates[$row->_id];
@ -206,6 +209,7 @@ class Changeset
$row = (object)array_merge((array)$row, $newVals); $row = (object)array_merge((array)$row, $newVals);
} }
}
// Drop deleted columns // Drop deleted columns
if (!$decorate) { if (!$decorate) {
@ -300,8 +304,16 @@ class Changeset
return (object)$r->getAttributes(); return (object)$r->getAttributes();
} }
/**
* Apply a row update, adding the row to the list of changes, or removing it
* if all differences were undone.
*
* @param array|object $newVals
*/
public function rowUpdate($newVals) public function rowUpdate($newVals)
{ {
$newVals = (object)$newVals;
$_id = $newVals->_id; $_id = $newVals->_id;
$origRow = $this->fetchRow($_id); $origRow = $this->fetchRow($_id);
@ -309,8 +321,6 @@ class Changeset
$cols = collect($this->fetchAndTransformColumns())->keyBy('id'); $cols = collect($this->fetchAndTransformColumns())->keyBy('id');
$updateObj = []; $updateObj = [];
\Debugbar::addMessage(json_encode($cols));
\Debugbar::addMessage(var_export($newVals, true));
foreach ($newVals as $colId => $value) { foreach ($newVals as $colId => $value) {
if (starts_with($colId, '_')) continue; // internals if (starts_with($colId, '_')) continue; // internals
@ -320,10 +330,6 @@ class Changeset
} }
} }
\Debugbar::addMessage("New: ".json_encode($newVals));
\Debugbar::addMessage("Orig: ".json_encode($origRow));
\Debugbar::addMessage("UpdateObj: ".json_encode($updateObj));
if (!empty($updateObj)) { if (!empty($updateObj)) {
$this->rowUpdates[$_id] = $updateObj; $this->rowUpdates[$_id] = $updateObj;
} else { } else {
@ -331,4 +337,15 @@ class Changeset
unset($this->rowUpdates[$_id]); unset($this->rowUpdates[$_id]);
} }
} }
/**
* Get a page of added rows for display in the editor
*
* @param int $perPage
* @return \Illuminate\Pagination\LengthAwarePaginator|Collection|array
*/
public function getAddedRows(int $perPage = 25)
{
return collection_paginate($this->newRows, $perPage);
}
} }

@ -95,3 +95,28 @@ function toJSON($object) {
function fromJSON($object, $assoc=false) { function fromJSON($object, $assoc=false) {
return \GuzzleHttp\json_decode($object, $assoc); return \GuzzleHttp\json_decode($object, $assoc);
} }
/**
* @param \Illuminate\Support\Collection|array $items
* @param int $per_page
* @param null|\Closure $mapFn
* @return \Illuminate\Pagination\LengthAwarePaginator
*/
function collection_paginate($items, $per_page, $mapFn = null)
{
if (!$items instanceof \Illuminate\Support\Collection) {
$items = collect($items);
}
$page = Request::get('page', 1);
$pageItems = $items->forPage($page, $per_page)->values();
return new Illuminate\Pagination\LengthAwarePaginator(
$mapFn ? $pageItems->map($mapFn) : $pageItems,
$items->count(),
$per_page,
Illuminate\Pagination\Paginator::resolveCurrentPage(),
['path' => Illuminate\Pagination\Paginator::resolveCurrentPath()]
);
}

@ -1,12 +1,11 @@
<template> <template>
<i :title="tooltipText"> <i :title="tooltipText" @click="$emit('click')">
<span class="sr-only" v-html=srHtml></span> <span class="sr-only" v-html=srHtml></span>
</i> </i>
</template> </template>
<script> <script>
export default { export default {
inheritAttrs: false,
props: { props: {
alt: String, alt: String,
srOnly: Boolean srOnly: Boolean

@ -32,7 +32,12 @@
<template v-else> <template v-else>
<td v-for="col in columns"> <td v-for="col in columns">
{{ row[col.id] || '' }} <span class="text-danger strike" title="Original value" v-if="isChanged(row, col.id)">{{row._orig[col.id]}}</span>
<span>{{ row[col.id] || '' }}</span>
<v-icon v-if="isChanged(row, col.id)"
@click="revertCell(row, col.id)"
class="fa-undo text-danger pointer"
alt="Revert Change" />
</td> </td>
</template> </template>
@ -47,6 +52,8 @@
</style> </style>
<script> <script>
import { merge } from 'lodash';
export default { export default {
props: { props: {
route: String, route: String,
@ -72,27 +79,30 @@ export default {
}) })
}, },
toggleRowDelete(_id) { toggleRowDelete(_id) {
let remove = !this.rows[_id]._remove; let remove = !this.rows[_id]._remove
this.query({ this.query({
action: remove ? 'row.remove' : 'row.restore', action: remove ? 'row.remove' : 'row.restore',
id: _id id: _id
}, (resp) => { }, (resp) => {
this.$set(this.rows, _id, resp.data); this.$set(this.rows, _id, resp.data)
})
},
submitRowChange(row) {
this.query({
action: 'row.update',
data: row
}, (resp) => {
this.$set(this.rows, resp.data._id, resp.data);
}) })
}, },
toggleRowEditing(_id) { toggleRowEditing(_id) {
if (this.rows[_id]._remove) return false; // can't edit row marked for removal if (this.rows[_id]._remove) return false; // can't edit row marked for removal
let editing = !this.rows[_id]._editing; let editing = !this.rows[_id]._editing
if (!editing) { if (!editing) {
this.query({ this.submitRowChange(this.rows[_id])
action: 'row.update',
data: this.rows[_id]
}, (resp) => {
this.$set(this.rows, _id, resp.data);
})
} else { } else {
this.$set(this.rows[_id], '_editing', true); this.$set(this.rows[_id], '_editing', true);
} }
@ -113,6 +123,12 @@ export default {
backgroundColor: row._remove? '#FFC4CC': 'transparent' backgroundColor: row._remove? '#FFC4CC': 'transparent'
} }
}, },
isChanged (row, colId) {
return row._changed.indexOf(colId) > -1
},
revertCell(row, colId) {
this.submitRowChange(merge({}, row, { [colId]: row._orig[colId] }))
}
} }
} }
</script> </script>

@ -25,3 +25,7 @@
.opacity-fade { .opacity-fade {
transition: opacity .3s ease-in-out; transition: opacity .3s ease-in-out;
} }
.pointer {
cursor: pointer;
}

Loading…
Cancel
Save