From a9ffd378a0ac7761b3219aa3336c16d65391f562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 21 Jul 2018 19:24:00 +0200 Subject: [PATCH] form improvements --- .../Controllers/Auth/RegisterController.php | 3 +- app/Http/Controllers/TableController.php | 24 ++- app/Models/User.php | 3 +- app/View/CheckboxWidget.php | 14 ++ app/View/Widget.php | 36 +++-- app/View/WidgetFactory.php | 33 +++- .../2014_10_12_000000_create_users_table.php | 3 +- .../2018_07_08_193700_create_tables_table.php | 1 + resources/assets/sass/_bst-modules.scss | 2 +- resources/assets/sass/app.scss | 5 + resources/views/auth/login.blade.php | 148 +++++++----------- resources/views/auth/register.blade.php | 55 +------ resources/views/form/_help.blade.php | 2 +- resources/views/form/checkbox.blade.php | 22 +++ resources/views/form/input.blade.php | 4 +- resources/views/form/textarea.blade.php | 4 +- resources/views/table/create.blade.php | 31 ++-- 17 files changed, 208 insertions(+), 182 deletions(-) create mode 100644 app/View/CheckboxWidget.php create mode 100644 resources/views/form/checkbox.blade.php diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index f9ce290..8973825 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -49,7 +49,7 @@ class RegisterController extends Controller protected function validator(array $data) { return Validator::make($data, [ - 'name' => 'required|string|max:255', + 'name' => 'required|string|max:255|regex:/^[a-zA-Z0-9_.-]+$/', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:6|confirmed', ]); @@ -65,6 +65,7 @@ class RegisterController extends Controller { return User::create([ 'name' => $data['name'], + 'title' => $data['name'], // display name - by default, init to name 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); diff --git a/app/Http/Controllers/TableController.php b/app/Http/Controllers/TableController.php index fcfcf4e..b27fb56 100644 --- a/app/Http/Controllers/TableController.php +++ b/app/Http/Controllers/TableController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Models\Table; use Illuminate\Http\Request; class TableController extends Controller @@ -13,7 +14,7 @@ class TableController extends Controller */ public function create() { - $exampleColSpec = + $exampleColumns = "latin, string, Latin Name\n". "common, string, Common Name\n". "lifespan, int, Lifespan (years)"; @@ -24,21 +25,32 @@ class TableController extends Controller "Patella vulgata, common limpet, 20"; return view('table.create', - compact('exampleColSpec', 'exampleData') + compact('exampleColumns', 'exampleData') ); } public function storeNew(Request $request) { + $u = \Auth::user(); + $this->validate($request, [ - 'table-name' => 'required', - 'table-descr' => 'string|nullable', + 'name' => 'required', + 'title' => 'string|nullable', + 'description' => 'string|nullable', 'license' => 'string|nullable', 'upstream' => 'string|nullable', - 'col-spec' => 'required', - 'row-data' => 'string|nullable', + 'columns' => 'required', + 'data' => 'string|nullable', ]); + // Check if table name is unique for user + $name = $request->get('name'); + if ($u->tables()->where('name', $name)->exists()) { + return back()->withErrors([ + 'title' => "A table called \"$name\" already exists in your account.", + ]); + } + return "Ok."; } } diff --git a/app/Models/User.php b/app/Models/User.php index 1ade1b6..60c9b37 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -16,6 +16,7 @@ use Illuminate\Notifications\Notification; * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at * @property string $name - unique, for vanity URL + * @property string $title - for display * @property string $email - unique, for login and social auth chaining * @property string $password - hashed pw * @property Proposal[]|Collection $proposals @@ -40,7 +41,7 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'name', 'email', 'password', + 'name', 'title', 'email', 'password', ]; /** diff --git a/app/View/CheckboxWidget.php b/app/View/CheckboxWidget.php new file mode 100644 index 0000000..adff517 --- /dev/null +++ b/app/View/CheckboxWidget.php @@ -0,0 +1,14 @@ +value = (bool)$condition; + return $this; + } +} diff --git a/app/View/Widget.php b/app/View/Widget.php index 41527ab..f983a5d 100644 --- a/app/View/Widget.php +++ b/app/View/Widget.php @@ -12,14 +12,17 @@ namespace App\View; * @property-read string|null $help * @property-read string|null $value * @property-read string $attributes + * @property-read int $labelCols + * @property-read int $fieldCols */ class Widget { - private $attributes = [], + protected $attributesArray = [], $id, $name, $label, $value, $viewName, $help, - $style = []; + $labelCols, $fieldCols, + $styleArray = []; public function __construct($viewName, $name, $label) { @@ -36,7 +39,7 @@ class Widget 'height', 'minHeight', 'maxHeight' ]; - if (empty($args)) $args = ['']; + if (empty($args)) $args = [null]; $arg = $args[0]; @@ -50,7 +53,7 @@ class Widget $this->$method = $arg; } else { - $this->attributes[$method] = $arg; + $this->attributesArray[$method] = $arg; } return $this; @@ -58,7 +61,15 @@ class Widget public function css($prop, $val) { - $this->style[$prop] = $val; + $this->styleArray[$prop] = $val; + return $this; + } + + /** Apply a given layout (bootstrap grid, 12 cols total) */ + public function layout($labelCols, $fieldCols) + { + $this->labelCols = $labelCols; + $this->fieldCols = $fieldCols; return $this; } @@ -82,14 +93,19 @@ class Widget public function compileAttribs() { // compile attribs string - $attribs_s = array_reduce(array_keys($this->attributes), function ($carry, $key) { - return $carry . ' ' . $key . '="' . e($this->attributes[$key]) . '"'; + $attribs_s = array_reduce(array_keys($this->attributesArray), function ($carry, $key) { + if ($this->attributesArray[$key] === null) { + // simple attribs like 'required' + return $carry . ' ' . $key; + } else { + return $carry . ' ' . $key . '="' . e($this->attributesArray[$key]) . '"'; + } }, ''); // add a compiled list of styles - if (!empty($this->style)) { - $attribs_s .= 'style="'.trim(e(array_reduce(array_keys($this->style), function ($carry, $key) { - return $carry . $key . ': ' . $this->style[$key] . '; '; + if (!empty($this->styleArray)) { + $attribs_s .= 'style="'.trim(e(array_reduce(array_keys($this->styleArray), function ($carry, $key) { + return $carry . $key . ': ' . $this->styleArray[$key] . '; '; }, ''))).'"'; } diff --git a/app/View/WidgetFactory.php b/app/View/WidgetFactory.php index 6d08ef7..77a244f 100644 --- a/app/View/WidgetFactory.php +++ b/app/View/WidgetFactory.php @@ -5,23 +5,48 @@ namespace App\View; class WidgetFactory { + private $labelCols = 3, $fieldCols = 8; + + /** Configure layout used for future elements */ + public function setLayout($labelCols, $fieldCols) + { + $this->labelCols = $labelCols; + $this->fieldCols = $fieldCols; + } + + private function baseWidget($view, $name, $label) + { + return (new Widget($view, $name, $label))->layout($this->labelCols, $this->fieldCols); + } + public function text($name, $label) { - return new Widget('input', $name, $label); + return $this->baseWidget('input', $name, $label); + } + + public function password($name, $label) + { + return $this->baseWidget('input', $name, $label)->type('password'); } public function number($name, $label) { - return new Widget('number', $name, $label); + return $this->baseWidget('input', $name, $label)->type('number'); } public function email($name, $label) { - return new Widget('email', $name, $label); + return $this->baseWidget('input', $name, $label)->type('email'); + } + + public function checkbox($name, $label) + { + return (new CheckboxWidget('checkbox', $name, $label)) + ->layout($this->labelCols, $this->fieldCols); } public function textarea($name, $label) { - return (new Widget('textarea', $name, $label))->minHeight('4em'); + return $this->baseWidget('textarea', $name, $label)->minHeight('4em'); } } diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 2fed394..cf7f107 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -17,7 +17,8 @@ class CreateUsersTable extends Migration $table->increments('id'); $table->timestamps(); $table->string('name')->unique(); - $table->string('email')->unique()->nullable(); + $table->string('title')->index(); + $table->string('email')->unique(); // would have to be nullable if we supported login via providers that don't give us e-mail $table->string('password')->nullable(); $table->rememberToken(); }); diff --git a/database/migrations/2018_07_08_193700_create_tables_table.php b/database/migrations/2018_07_08_193700_create_tables_table.php index 40cda76..9738fd0 100644 --- a/database/migrations/2018_07_08_193700_create_tables_table.php +++ b/database/migrations/2018_07_08_193700_create_tables_table.php @@ -19,6 +19,7 @@ class CreateTablesTable extends Migration $table->unsignedInteger('owner_id'); $table->unsignedInteger('ancestor_id')->index()->nullable(); $table->unsignedInteger('revision_id')->index(); // active revision + $table->string('name')->index(); // indexable $table->string('title')->index(); // indexable $table->text('description'); $table->text('license'); diff --git a/resources/assets/sass/_bst-modules.scss b/resources/assets/sass/_bst-modules.scss index 0ee0f65..e2397dd 100644 --- a/resources/assets/sass/_bst-modules.scss +++ b/resources/assets/sass/_bst-modules.scss @@ -11,7 +11,7 @@ @import "~bootstrap/scss/dropdown"; @import "~bootstrap/scss/button-group"; //@import "~bootstrap/scss/input-group"; -//@import "~bootstrap/scss/custom-forms"; +@import "~bootstrap/scss/custom-forms"; //@import "~bootstrap/scss/nav"; @import "~bootstrap/scss/navbar"; @import "~bootstrap/scss/card"; diff --git a/resources/assets/sass/app.scss b/resources/assets/sass/app.scss index 1e6f7bb..9530fda 100644 --- a/resources/assets/sass/app.scss +++ b/resources/assets/sass/app.scss @@ -11,6 +11,11 @@ html { overflow-y: scroll; } +.form-help { + display: inline-block; + margin-top: $form-text-margin-top; +} + .tooltip-inner { text-align: left; } diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 6f62a57..e101dd4 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -1,102 +1,62 @@ @extends('layouts.app') @section('content') -
+
-
-
-
{{ __('Login') }}
- -
-
- @csrf - -
- - -
- - - @if ($errors->has('email')) - - {{ $errors->first('email') }} - - @endif -
-
- -
- - -
- - - @if ($errors->has('password')) - - {{ $errors->first('password') }} - - @endif -
-
- -
-
-
- -
-
-
- -
-
- {{-- - - --}} - {{ __('Forgot Your Password?') }} - {{-- - - --}} - {{ __('Register') }} - -
-
-
-
- - +
+
+
{{ __('Login') }}
+ +
+
+ @csrf + + @php(Widget::setLayout(4, 6)) + + {!! Widget::email('email', 'E-Mail Address')->required()->autofocus() !!} + {!! Widget::password('password', 'Password')->required() !!} + {!! Widget::checkbox('remember', 'Remember Me')->checked(false) !!} + +
+
+ {{-- + --}}{{ __('Forgot Your Password?') }}{{-- + --}}{{ __('Register') }} +
+
+
+
+ +
+
-
+
@endsection diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index abb4241..f73732f 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -11,55 +11,16 @@
@csrf -
- + @php(Widget::setLayout(4, 6)) -
- + {!! Widget::text('name', 'Name')->required()->autofocus() + ->help('This will be part of your vanity URL; only letters, digits and + some symbols are allowed. You can always change this later, and even + set a different Display Name.') !!} - @if ($errors->has('name')) - - {{ $errors->first('name') }} - - @endif -
-
- -
- - -
- - - @if ($errors->has('email')) - - {{ $errors->first('email') }} - - @endif -
-
- -
- - -
- - - @if ($errors->has('password')) - - {{ $errors->first('password') }} - - @endif -
-
- -
- - -
- -
-
+ {!! Widget::email('email', 'E-Mail Address')->required()->autofocus() !!} + {!! Widget::password('password', 'Password')->required() !!} + {!! Widget::password('password_confirmation', 'Confirm Password')->required() !!}
diff --git a/resources/views/form/_help.blade.php b/resources/views/form/_help.blade.php index fc2cb46..33105c4 100644 --- a/resources/views/form/_help.blade.php +++ b/resources/views/form/_help.blade.php @@ -1,6 +1,6 @@
@if($w->help) - help, '<')) diff --git a/resources/views/form/checkbox.blade.php b/resources/views/form/checkbox.blade.php new file mode 100644 index 0000000..6070442 --- /dev/null +++ b/resources/views/form/checkbox.blade.php @@ -0,0 +1,22 @@ +@php +/** @var \App\View\Widget $w */ +@endphp + +
+
+
+ value?'checked':''}} + name="{{ $w->name }}"> + +
+ + @if ($errors->has($w->name)) + + {{ $errors->first($w->name) }} + + @endif +
+ @include('form._help') +
diff --git a/resources/views/form/input.blade.php b/resources/views/form/input.blade.php index 2867fbd..4a592a0 100644 --- a/resources/views/form/input.blade.php +++ b/resources/views/form/input.blade.php @@ -3,8 +3,8 @@ @endphp
- -
+ +
- -
+ +