correctly sort by numeric columns

pull/35/head
Ondřej Hruška 6 years ago
parent 8d6ec7b47d
commit e1c7114bd4
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      app/Http/Controllers/TableController.php
  2. 4
      app/Http/Controllers/TableEditController.php
  3. 22
      app/Models/Row.php
  4. 2
      app/Tables/BaseExporter.php
  5. 77
      resources/assets/js/components/RowsEditor.vue
  6. 1
      resources/views/table/propose/edit-rows.blade.php

@ -46,7 +46,7 @@ class TableController extends Controller
$columns = Column::columnsFromJson($revision->columns); $columns = Column::columnsFromJson($revision->columns);
$rq = $revision->rowsData($columns); $rq = $revision->rowsData($columns);
if (count($columns)) $rq = $rq->orderByRaw("data->>'".$columns[0]->id."'"); if (count($columns)) $rq = $rq->sortByCol($columns[0]);
$rows = $rq->paginate(25, []); $rows = $rq->paginate(25, []);
return view('table.view', [ return view('table.view', [

@ -97,7 +97,9 @@ class TableEditController extends Controller
{ {
$revision = $changeset->revision; $revision = $changeset->revision;
$columns = $changeset->fetchAndTransformColumns(); $columns = $changeset->fetchAndTransformColumns();
$rows = $revision->rowsData($columns, true, false)->paginate(25, []); $rows = $revision->rowsData($columns, true, false)
->sortByCol($changeset->fetchRevisionColumns()[0])
->paginate(25, []);
return view('table.propose.edit-rows', [ return view('table.propose.edit-rows', [
'changeset' => $changeset, 'changeset' => $changeset,

@ -2,6 +2,9 @@
namespace App\Models; namespace App\Models;
use App\Tables\Column;
use Illuminate\Database\Eloquent\Builder;
/** /**
* Row in a data table * Row in a data table
* *
@ -25,6 +28,25 @@ class Row extends BaseModel
$this->data->_id = $value; $this->data->_id = $value;
} }
public function scopeSortByCol(Builder $query, Column $column, $dir="asc")
{
$q = "data->>'".$column->id."'";
if ($column->type == 'int' || $column->type == 'float') {
$q = "CAST($q AS INTEGER)";
}
else if ($column->type == 'float') {
$q = "CAST($q AS FLOAT)";
}
if ($dir == 'asc') {
$q .= ' ASC';
} else {
$q .= ' DESC';
}
return $query->orderByRaw($q);
}
/** /**
* Allocate a single Global Row ID, application-unique. * Allocate a single Global Row ID, application-unique.
* *

@ -132,7 +132,7 @@ abstract class BaseExporter
$columns = $this->columns; $columns = $this->columns;
// TODO raw query to allow selecting aggregates, column subsets, etc // TODO raw query to allow selecting aggregates, column subsets, etc
if (count($columns)) $rq = $rq->orderByRaw("data->>'".$columns[0]->id."'"); if (count($columns)) $rq = $rq->sortByCol($columns[0]);
while ($start < $count) { while ($start < $count) {
$rows = $rq->offset($start)->limit($chunkSize)->get()->toArray(); $rows = $rq->offset($start)->limit($chunkSize)->get()->toArray();

@ -68,7 +68,7 @@ Rows are identified by row._id, columns by col.id
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="row in rows" :class="row._remove ? 'remove' : ''"> <tr v-for="row in orderedRows" :class="row._remove ? 'remove' : ''">
<td class="text-nowrap"> <td class="text-nowrap">
<button :class="[ <button :class="[
'mr-1', 'btn', 'btn-outline-danger', 'mr-1', 'btn', 'btn-outline-danger',
@ -164,6 +164,7 @@ Rows are identified by row._id, columns by col.id
route: String, route: String,
/** Row objects */ /** Row objects */
xRows: Object, // key'd by _id xRows: Object, // key'd by _id
xRowOrder: Array,
/** Array of columns */ /** Array of columns */
columns: Array, columns: Array,
/** CSRF token */ /** CSRF token */
@ -182,6 +183,7 @@ Rows are identified by row._id, columns by col.id
return { return {
/** All rows */ /** All rows */
rows: this.xRows, rows: this.xRows,
rowOrder: this.xRowOrder,
/** Number of dirty rows */ /** Number of dirty rows */
dirtyRows: 0, dirtyRows: 0,
} }
@ -199,6 +201,17 @@ Rows are identified by row._id, columns by col.id
} }
} }
}, },
computed: {
// JS does not respect object keys order, so we have to fix it up a little
orderedRows: function () {
if (this.newRows) return Object.values(this.rows);
let arr = []
for(let id of this.rowOrder) {
arr.push(this.rows[id])
}
return arr;
}
},
methods: { methods: {
/** Send a query to the server */ /** Send a query to the server */
query (data, sucfn, erfn) { query (data, sucfn, erfn) {
@ -247,6 +260,35 @@ Rows are identified by row._id, columns by col.id
}) })
}, },
/** Save all changed rows */
saveAllChanges () {
let toChange = _.filter(this.rows, (r) => {
let changed = this.isRowChanged(r)
if (!changed && r._editing) {
this.rows[r._id]._editing = false
}
return changed;
})
if (toChange.length === 0) return;
this.query({
action: 'row.update-many',
data: toChange
}, (resp) => {
_.each(resp.data, (row) => {
this.$set(this.rows, row._id, row)
})
this.dirtyRows = 0
}, (er) => {
// TODO - also need to improve backend to properly report which row was bad
console.log(er)
// if (!_.isUndefined(er.errors)) {
// this.$set(this.rows[row._id], '_errors', er.errors)
// }
})
},
/** Toggle editing state - edit or save */ /** Toggle editing state - edit or save */
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
@ -321,35 +363,6 @@ Rows are identified by row._id, columns by col.id
row._dirty = isDirty row._dirty = isDirty
}, },
/** Save all changed rows */
saveAllChanges () {
let toChange = _.filter(this.rows, (r) => {
let changed = this.isRowChanged(r)
if (!changed && r._editing) {
this.rows[r._id]._editing = false
}
return changed;
})
if (toChange.length === 0) return;
this.query({
action: 'row.update-many',
data: toChange
}, (resp) => {
_.each(resp.data, (row) => {
this.$set(this.rows, row._id, row)
})
this.dirtyRows = 0
}, (er) => {
// TODO
console.log(er)
// if (!_.isUndefined(er.errors)) {
// this.$set(this.rows[row._id], '_errors', er.errors)
// }
})
},
discardEdit (row) { discardEdit (row) {
let wasDirty = this.isRowChanged(row) let wasDirty = this.isRowChanged(row)
@ -382,7 +395,7 @@ Rows are identified by row._id, columns by col.id
if (dir == -1) { if (dir == -1) {
// up // up
let last_editable_row = null let last_editable_row = null
for (let row of Object.values(this.rows)) { for (let row of this.orderedRows) {
if (row._id === row_id) { if (row._id === row_id) {
break break
} }
@ -398,7 +411,7 @@ Rows are identified by row._id, columns by col.id
// down // down
let first_editable_row = null let first_editable_row = null
let foundself = false let foundself = false
for (let row of Object.values(this.rows)) { for (let row of this.orderedRows) {
if (row._id === row_id) { if (row._id === row_id) {
foundself = true foundself = true
continue continue

@ -31,6 +31,7 @@
route: {!! toJSON($table->draftUpdateRoute) !!}, route: {!! toJSON($table->draftUpdateRoute) !!},
columns: {!! toJSON($columns) !!}, columns: {!! toJSON($columns) !!},
xRows: {!! toJSON($transformed, true) !!}, xRows: {!! toJSON($transformed, true) !!},
xRowOrder: @json($transformed->keys()),
}) })
}); });
</script> </script>

Loading…
Cancel
Save