parent
e17548e5e7
commit
bb8bc459dc
@ -0,0 +1,17 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* Interface RowData |
||||
* |
||||
* @property int $_id |
||||
*/ |
||||
interface RowData {} |
||||
|
||||
/** |
||||
* Interface DecoratedRow |
||||
* |
||||
* @property bool $_remove - marked to be removed |
||||
* @property mixed[] $_orig - original values before transformation, key by CID |
||||
* @property string[] $_changed - values that were changed |
||||
*/ |
||||
interface DecoratedRow extends RowData {} |
@ -0,0 +1,66 @@ |
||||
<?php |
||||
|
||||
|
||||
namespace App\Http\Controllers; |
||||
|
||||
use App\Models\Table; |
||||
use App\Models\User; |
||||
use App\Tables\Changeset; |
||||
use App\Tables\Column; |
||||
use Illuminate\Http\Request; |
||||
use Illuminate\Support\Facades\Input; |
||||
|
||||
class TableEditController extends Controller |
||||
{ |
||||
/** |
||||
* Initialize the session-stored changeset, if not set yet |
||||
* |
||||
* @param Table $table |
||||
* @return Changeset |
||||
*/ |
||||
private function getChangeset(Table $table) |
||||
{ |
||||
$session_key = "proposal_{$table->id}"; |
||||
|
||||
if (Input::has('reset')) { |
||||
session()->forget($session_key); |
||||
} |
||||
|
||||
/** @var Changeset $changeset */ |
||||
return session()->remember($session_key, function () use ($table) { |
||||
$changeset = new Changeset(); |
||||
$changeset->table = $table; |
||||
$changeset->revision = $table->revision; |
||||
return $changeset; |
||||
}); |
||||
} |
||||
|
||||
public function draft(User $user, string $table, $tab = null) |
||||
{ |
||||
/** @var Table $tableModel */ |
||||
$tableModel = $user->tables()->where('name', $table)->first(); |
||||
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"); |
||||
|
||||
$changeset = $this->getChangeset($tableModel); |
||||
|
||||
return $this->{camel_case($tab)}($changeset); |
||||
} |
||||
|
||||
private function editRows(Changeset $changeset) |
||||
{ |
||||
$revision = $changeset->revision; |
||||
$columns = $changeset->transformColumns(); |
||||
$rows = $revision->rowsData($columns, true, false)->paginate(25, []); |
||||
|
||||
return view('table.propose.edit-rows', [ |
||||
'changeset' => $changeset, |
||||
'table' => $changeset->table, |
||||
'columns' => collect($columns), |
||||
'rows' => $rows, |
||||
]); |
||||
} |
||||
} |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 22 KiB |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,86 @@ |
||||
<template> |
||||
<table class="table table-hover table-sm table-fixed td-va-middle"> |
||||
<thead> |
||||
<tr> |
||||
<th style="width:3rem" class="border-top-0"></th> |
||||
<th style="width:3rem" class="border-top-0"></th> |
||||
<th v-for="col in columns" :class="colClasses(col)">{{col.title}}</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr v-for="row in rows" :style="rowStyle(row)"> |
||||
<td> |
||||
<a href="" :class="['btn','btn-outline-danger',{'active': row._remove}]" |
||||
@click.prevent="toggleRowDelete(row._id)"> |
||||
<v-icon :class="row._remove ? 'fa-undo' : 'fa-trash-o'" |
||||
:alt="row._remove ? 'Undo Remove' : 'Remove'" /> |
||||
</a> |
||||
</td> |
||||
<td> |
||||
<a href="" class="btn btn-outline-secondary" |
||||
@click.prevent="toggleRowEditing(row._id)"> |
||||
<v-icon :class="row._editing ? 'fa-save' : 'fa-pencil'" |
||||
:alt="row._editing ? 'Save' : 'Edit'" /> |
||||
</a> |
||||
</td> |
||||
|
||||
<template v-if="row._editing"> |
||||
<td v-for="col in columns" class="pr-0"> |
||||
<input v-model="row[col.id]" class="form-control" type="text"> |
||||
</td> |
||||
</template> |
||||
|
||||
<template v-else> |
||||
<td v-for="col in columns"> |
||||
{{ row[col.id] || '' }} |
||||
</td> |
||||
</template> |
||||
|
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
@import "base"; |
||||
|
||||
</style> |
||||
|
||||
<script> |
||||
export default { |
||||
props: { |
||||
route: String, |
||||
xRows: Object, // key'd by _id |
||||
columns: Array, |
||||
}, |
||||
data: function() { |
||||
return { |
||||
rows: this.xRows, |
||||
} |
||||
}, |
||||
methods: { |
||||
toggleRowDelete(_id) { |
||||
this.$set(this.rows[_id], '_remove', !this.rows[_id]._remove); |
||||
}, |
||||
toggleRowEditing(_id) { |
||||
this.$set(this.rows[_id], '_editing', !this.rows[_id]._editing); |
||||
}, |
||||
colClasses(col) { |
||||
return [ |
||||
'border-top-0', |
||||
{ |
||||
'text-danger': col._remove, |
||||
'strike': col._remove, |
||||
'text-success': col._new |
||||
} |
||||
] |
||||
}, |
||||
rowStyle(row) { |
||||
return { |
||||
opacity: row._remove? .8 : 1, |
||||
backgroundColor: row._remove? '#FFC4CC': 'transparent' |
||||
} |
||||
}, |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,9 @@ |
||||
.table-fixed { |
||||
table-layout: fixed; |
||||
} |
||||
|
||||
.td-va-middle { |
||||
td, th { |
||||
vertical-align: middle !important; |
||||
} |
||||
} |
@ -0,0 +1,6 @@ |
||||
@php($tab='add-rows') |
||||
@extends('table.propose.layout') |
||||
|
||||
@section('tab-content') |
||||
... |
||||
@stop |
@ -0,0 +1,43 @@ |
||||
@php |
||||
$tab = 'edit-rows'; |
||||
/** @var \App\Tables\Column[] $columns */ |
||||
/** @var \App\Tables\Changeset $changeset */ |
||||
/** @var \App\Models\Row[]|Illuminate\Pagination\Paginator $rows */ |
||||
/** @var \App\Models\Table $table */ |
||||
@endphp |
||||
|
||||
@extends('table.propose.layout') |
||||
|
||||
@section('tab-content') |
||||
|
||||
@if($rows->hasPages()) |
||||
<div class="col-md-12 d-flex"> |
||||
<nav class="text-center" aria-label="Pages of the table"> |
||||
{{ $rows->links(null, ['ulClass' => 'mb-0']) }} |
||||
</nav> |
||||
</div> |
||||
@endif |
||||
|
||||
<div class="col-12"> |
||||
@php |
||||
$transformed = $rows->keyBy('_id')->map(function($r) use ($changeset) { |
||||
/** @var \App\Tables\Changeset $changeset */ |
||||
return $changeset->transformRow($r, true); |
||||
}); |
||||
@endphp |
||||
|
||||
<table is="row-editor" |
||||
route="{{$table->getDraftRoute('update')}}" |
||||
:columns="{{toJSON($columns)}}" |
||||
:x-rows="{{toJSON($transformed)}}"> |
||||
</table> |
||||
</div> |
||||
|
||||
@if($rows->hasPages()) |
||||
<div class="col-md-12 d-flex"> |
||||
<nav class="text-center" aria-label="Pages of the table"> |
||||
{{ $rows->links(null, ['ulClass' => 'mb-0']) }} |
||||
</nav> |
||||
</div> |
||||
@endif |
||||
@stop |
@ -0,0 +1,58 @@ |
||||
{{-- Basic table view --}} |
||||
|
||||
@extends('layouts.app') |
||||
|
||||
@php |
||||
/** @var \App\Models\Table $table */ |
||||
|
||||
if (!isset($tab) || $tab == '') $tab = 'edit-rows'; |
||||
@endphp |
||||
|
||||
@section('content') |
||||
<div class="row justify-content-start px-3"> |
||||
<div class="d-flex w-100 align-items-center"> |
||||
<small class="flex-grow-1" style="font-size: 120%;"> |
||||
<a href="{{ route('profile.view', $table->owner->name) }}" class="link-no-color">{{ $table->owner->handle }}</a>{{-- |
||||
--}}<span class="px-1">/</span>{{-- |
||||
--}}<b>{{ $table->name }}</b> |
||||
</small> |
||||
|
||||
<h1 class="mx-3">{{ $table->title }}</h1> |
||||
<a href="" class="btn btn-outline-danger mr-2" @tooltip(Discard changes)> |
||||
@icon(fa-close, sr:Discard) |
||||
</a> |
||||
@if(user()->ownsTable($table)) |
||||
<a href="" class="btn btn-outline-success" @tooltip(Save the changes and apply them as a new table revision)> |
||||
@icon(fa-save fa-pr)Commit |
||||
</a> |
||||
@else |
||||
<a href="" class="btn btn-outline-success" @tooltip(Submit your changes for review by the table owner)> |
||||
@icon(fa-save fa-pr)Submit |
||||
</a> |
||||
@endif |
||||
</div> |
||||
</div> |
||||
|
||||
<ul class="nav nav-tabs"> |
||||
<li class="nav-item"> |
||||
<a class="nav-link{{ $tab=='edit-rows'?' active':'' }}" href="{{ $table->getDraftRoute('edit-rows') }}">Edit Rows</a> |
||||
</li> |
||||
<li class="nav-item"> |
||||
<a class="nav-link{{ $tab=='add-rows'?' active':'' }}" href="{{ $table->getDraftRoute('add-rows') }}">Add Rows</a> |
||||
</li> |
||||
<li class="nav-item"> |
||||
<a class="nav-link{{ $tab=='manage-columns'?' active':'' }}" href="{{ $table->getDraftRoute('manage-columns') }}">Columns</a> |
||||
</li> |
||||
<li class="nav-item"> |
||||
<a class="nav-link{{ $tab=='review'?' active':'' }}" href="{{ $table->getDraftRoute('review') }}">Note & Review</a> |
||||
</li> |
||||
<li class="nav-item ml-auto pt-2 pr-2 opacity-fade" style="opacity:0" id="draft-busy"> |
||||
@icon(fa-hourglass, Working...) |
||||
</li> |
||||
</ul> |
||||
|
||||
<div class="row justify-content-center mb-2"> |
||||
@yield('tab-content') |
||||
</div>{{-- End of row --}} |
||||
|
||||
@endsection |
@ -0,0 +1,6 @@ |
||||
@php($tab='manage-columns') |
||||
@extends('table.propose.layout') |
||||
|
||||
@section('tab-content') |
||||
... |
||||
@stop |
@ -0,0 +1,6 @@ |
||||
@php($tab='review') |
||||
@extends('table.propose.layout') |
||||
|
||||
@section('tab-content') |
||||
... |
||||
@stop |
Loading…
Reference in new issue