Quellcode durchsuchen

Merge branch 'dev'

jqh vor 6 Jahren
Ursprung
Commit
2bb48dccbb
43 geänderte Dateien mit 781 neuen und 289 gelöschten Zeilen
  1. 38 0
      resources/assets/dcat-admin/main.css
  2. 1 1
      resources/assets/dcat-admin/main.js
  3. 0 0
      resources/assets/dcat-admin/main.min.css
  4. 0 0
      resources/assets/dcat-admin/main.min.js
  5. 1 1
      resources/assets/dcat-admin/modal-form.js
  6. 0 0
      resources/views/contents/modal-form.blade.php
  7. 1 1
      resources/views/filter/container.blade.php
  8. 24 7
      resources/views/grid/quick-search.blade.php
  9. 74 68
      resources/views/grid/table.blade.php
  10. 2 2
      resources/views/tree.blade.php
  11. 16 6
      src/Controllers/ExtensionController.php
  12. 11 1
      src/Controllers/LogController.php
  13. 2 1
      src/Controllers/MenuController.php
  14. 42 49
      src/Controllers/RoleController.php
  15. 21 24
      src/Controllers/UserController.php
  16. 39 26
      src/Form.php
  17. 3 2
      src/Form/Builder.php
  18. 34 7
      src/Form/Condition.php
  19. 7 4
      src/Form/Field.php
  20. 0 23
      src/Form/Field/Tags.php
  21. 7 10
      src/Grid.php
  22. 1 1
      src/Grid/Actions/QuickEdit.php
  23. 109 20
      src/Grid/Column.php
  24. 134 0
      src/Grid/Column/Condition.php
  25. 25 0
      src/Grid/Column/Filter/Between.php
  26. 26 0
      src/Grid/Column/HasDisplayers.php
  27. 2 0
      src/Grid/Concerns/HasElementNames.php
  28. 3 0
      src/Grid/Concerns/HasFilter.php
  29. 57 7
      src/Grid/Concerns/HasQuickSearch.php
  30. 1 1
      src/Grid/Displayers/Actions.php
  31. 1 1
      src/Grid/Displayers/Expand.php
  32. 1 1
      src/Grid/Displayers/RowSelector.php
  33. 25 0
      src/Grid/Filter/Between.php
  34. 1 1
      src/Grid/Tools/CreateButton.php
  35. 57 4
      src/Grid/Tools/QuickSearch.php
  36. 0 4
      src/MiniGrid.php
  37. 2 2
      src/Models/Repositories/Role.php
  38. 3 3
      src/Models/Role.php
  39. 1 1
      src/Show/Panel.php
  40. 1 1
      src/Show/Tools.php
  41. 3 3
      src/Tree.php
  42. 3 6
      src/Widgets/ModalForm.php
  43. 2 0
      tests/CreatesApplication.php

+ 38 - 0
resources/assets/dcat-admin/main.css

@@ -2125,6 +2125,44 @@ div.layui-layer-btn{
     content:"\f107"!important;
 }
 
+.material .box-header,.material .card-header {
+    padding: 13px 12px;
+}
+.material .box-header .btn, .material .card-header .btn {
+    /*text-transform: uppercase;*/
+    background-color: transparent !important;
+    border-color: transparent !important;
+    box-shadow:none!important;
+    color:var(--80)!important;
+    font-weight: bold;
+    font-size: 13px;
+}
+.material .box-header .btn:hover,.material .card-header .btn:hover {
+    background-color:var(--40)!important;
+    border-radius:2px!important;
+}
+.material .box-header .btn-group, .material .card-header .btn-group {
+    box-shadow:none!important;
+}
+
+.material .box-header .btn.btn-danger, .material .card-header .btn.btn-danger {
+    color:var(--danger-dark)!important;
+}
+
+.quick-search-clear {
+    color:transparent;
+    display:none;
+    font-weight: bold;
+    position:absolute;
+    top:8px;
+    cursor:pointer;
+    z-index:100;
+}
+
+.quick-search:hover .quick-search-clear{
+    display:inline!important;
+}
+
 
 /*!
  * Waves v0.7.6

+ 1 - 1
resources/assets/dcat-admin/main.js

@@ -988,7 +988,7 @@ window.require = window.define = window.exports = window.module = undefined;
      * @param opt
      * @constructor
      */
-    LA.DialogForm = function (opt) {
+    LA.ModalForm = function (opt) {
         var number = 1,
             defUrl = opt.defaultUrl,
             btn = opt.buttonSelector,

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
resources/assets/dcat-admin/main.min.css


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
resources/assets/dcat-admin/main.min.js


+ 1 - 1
resources/assets/dcat-admin/dialog-form.js → resources/assets/dcat-admin/modal-form.js

@@ -4,7 +4,7 @@
      * @param opt
      * @constructor
      */
-    LA.DialogForm = function (opt) {
+    LA.ModalForm = function (opt) {
         var number = 1,
             defUrl = opt.defaultUrl,
             btn = opt.buttonSelector,

+ 0 - 0
resources/views/contents/dialog-form.blade.php → resources/views/contents/modal-form.blade.php


+ 1 - 1
resources/views/filter/container.blade.php

@@ -1,5 +1,5 @@
 <div class=" panel-collapse collapse {{ $expand?'in':'' }} {{$containerClass}}" style="{{$border}}padding:0;">
-    <div style="{!! $style !!}" class="box-header " id="{{ $filterID }}">
+    <div style="{!! $style !!}"  id="{{ $filterID }}">
         <form action="{!! $action !!}" class="form-horizontal" pjax-container method="get">
             @foreach($layout->columns() as $column)
                 @foreach($column->filters() as $filter)

+ 24 - 7
resources/views/grid/quick-search.blade.php

@@ -1,9 +1,26 @@
-<form action="{!! $action !!}" pjax-container style="display: inline-block;margin-right:5px;">
-    <div class="input-group input-group-sm quick-search" style="display: inline-block;">
-        <input type="text" placeholder="{{ $placeholder }}" name="{{ $key }}" class="form-control " style="width:200px;" value="{{ $value }}">
+<form action="{!! $action !!}" class="input-no-border" pjax-container style="display:inline-block;margin:0 5px 13px 0;">
+    <div class="input-group quick-search" style="width:24.75rem;">
 
-        <div class="input-group-btn" style="display: inline-block;">
-            <button type="submit" class="btn btn-primary"><i class="fa fa-search"></i></button>
-        </div>
+        <input type="text"
+               placeholder="{{ $placeholder }}"
+               name="{{ $key }}"
+               class="form-control quick-search-input"
+               style="margin-left:-1px;padding:0 1.5rem 0 3.48rem;height:36px;line-height:36px;"
+               value="{{ $value }}"
+        >
+        <a onclick="$(this).submit()" style="overflow:hidden;position:absolute;top:8px;margin-left:-23.85rem;cursor:pointer;z-index:100">
+            <svg xmlns="http://www.w3.org/2000/svg"
+                 width="20"
+                 height="20"
+                 viewBox="0 0 20 20"
+                 aria-labelledby="search"
+                 role="presentation"
+                 class="text-70"
+                 style="fill: currentColor;"
+            >
+                <path fill-rule="nonzero" d="M14.32 12.906l5.387 5.387a1 1 0 0 1-1.414 1.414l-5.387-5.387a8 8 0 1 1 1.414-1.414zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"></path>
+            </svg>
+        </a>
+        <span class="quick-search-clear" style="margin-left:-1.45rem;{{$value ? 'color:#333' : ''}}">×</span>
     </div>
-</form>
+</form>

+ 74 - 68
resources/views/grid/table.blade.php

@@ -1,80 +1,86 @@
-@if ($grid->allowToolbar())
-    <div class="box-header " >
-        @if(!empty($title))
-            <h4 class="pull-left" style="margin:5px 10px 0;">
-                {!! $title !!}&nbsp;
-                @if(!empty($description))
-                    <small>{!! $description!!}</small>
-                @endif
-            </h4>
-            <div class="pull-right" data-responsive-table-toolbar="{{$tableId}}">
-                {!! $grid->renderTools() !!} {!! $grid->renderCreateButton() !!} {!! $grid->renderExportButton() !!}
-            </div>
-        @else
-            <div class="pull-right" data-responsive-table-toolbar="{{$tableId}}">
-                {!! $grid->renderCreateButton() !!} {!! $grid->renderExportButton() !!}
-            </div>
+{!! $grid->renderQuickSearch() !!}
 
-            {!! $grid->renderTools() !!}
-        @endif
+<div class="card material">
 
-    </div>
-@endif
+    @if ($grid->allowToolbar())
+        <div class="box-header">
+            @if(!empty($title))
+                <h4 class="pull-left" style="margin:5px 10px 0;">
+                    {!! $title !!}&nbsp;
+                    @if(!empty($description))
+                        <small>{!! $description!!}</small>
+                    @endif
+                </h4>
+                <div class="pull-right" data-responsive-table-toolbar="{{$tableId}}">
+                    {!! $grid->renderTools() !!} {!! $grid->renderCreateButton() !!} {!! $grid->renderExportButton() !!}
+                </div>
+            @else
+                <div class="pull-right" data-responsive-table-toolbar="{{$tableId}}">
+                    {!! $grid->renderCreateButton() !!} {!! $grid->renderExportButton() !!}
+                </div>
+
+                {!! $grid->renderTools() !!}
+            @endif
 
-{!! $grid->renderFilter() !!}
+        </div>
+    @endif
 
-{!! $grid->renderHeader() !!}
+    {!! $grid->renderFilter() !!}
 
-<div class="card-body panel-collapse collapse in table-responsive" {!! $grid->option('show_bordered') ? 'style="padding:3px 10px 10px"' : '' !!}>
-    <table class=" table table-hover responsive {{ $grid->option('show_bordered') ? 'table-bordered' : $grid->option('table_header_style') }} " id="{{$tableId}}">
-        <thead>
-        @if ($headers = $grid->getMutipleHeaders())
+    {!! $grid->renderHeader() !!}
+
+    <div class="card-body panel-collapse collapse in table-responsive" {!! $grid->option('show_bordered') ? 'style="padding:3px 10px 10px"' : '' !!}>
+        <table class=" table table-hover responsive {{ $grid->option('show_bordered') ? 'table-bordered' : $grid->option('table_header_style') }} " id="{{$tableId}}">
+            <thead>
+            @if ($headers = $grid->getMutipleHeaders())
+                <tr>
+                    @foreach($headers as $header)
+                        {!! $header->render() !!}
+                    @endforeach
+                </tr>
+            @endif
             <tr>
-                @foreach($headers as $header)
-                    {!! $header->render() !!}
+                @foreach($grid->getColumns() as $column)
+                    <th {!! $column->formatTitleAttributes() !!}>{!! $column->getLabel() !!}{!! $column->renderHeader() !!}</th>
                 @endforeach
             </tr>
-        @endif
-        <tr>
-            @foreach($grid->getColumns() as $column)
-                <th {!! $column->formatTitleAttributes() !!}>{!! $column->getLabel() !!}{!! $column->renderHeader() !!}</th>
-            @endforeach
-        </tr>
-        </thead>
+            </thead>
 
-        <tbody>
-        @foreach($grid->rows() as $row)
-            <tr {!! $row->getRowAttributes() !!}>
-                @foreach($grid->getColumnNames() as $name)
-                    <td {!! $row->getColumnAttributes($name) !!}>
-                        {!! $row->column($name) !!}
+            <tbody>
+            @foreach($grid->rows() as $row)
+                <tr {!! $row->getRowAttributes() !!}>
+                    @foreach($grid->getColumnNames() as $name)
+                        <td {!! $row->getColumnAttributes($name) !!}>
+                            {!! $row->column($name) !!}
+                        </td>
+                    @endforeach
+                </tr>
+            @endforeach
+            @if ($grid->rows()->isEmpty())
+                <tr>
+                    <td colspan="{!! count($grid->getColumnNames()) !!}">
+                        <div style="margin:5px 0 0 10px;"><span class="help-block" style="margin-bottom:0"><i class="fa fa-info-circle"></i>&nbsp;{{ trans('admin.no_data') }}</span></div>
                     </td>
-                @endforeach
-            </tr>
-        @endforeach
-        @if ($grid->rows()->isEmpty())
-            <tr>
-                <td colspan="{!! count($grid->getColumnNames()) !!}">
-                    <div style="margin:5px 0 0 10px;"><span class="help-block" style="margin-bottom:0"><i class="fa fa-info-circle"></i>&nbsp;{{ trans('admin.no_data') }}</span></div>
-                </td>
-            </tr>
-        @endif
-        </tbody>
-    </table>
-</div>
+                </tr>
+            @endif
+            </tbody>
+        </table>
+    </div>
 
-{!! $grid->renderFooter() !!}
+    {!! $grid->renderFooter() !!}
 
-@if ($paginator = $grid->paginator())
-    <div class="box-footer clearfix " style="padding-bottom:5px;">
-        {!! $paginator !!}
-    </div>
-@else
-    <div class="box-footer clearfix text-80 " style="height:48px;line-height:25px;">
-        @if ($grid->rows()->isEmpty())
-            {!! trans('admin.pagination.range', ['first' => '<b>0</b>', 'last' => '<b>'.$grid->rows()->count().'</b>', 'total' => '<b>'.$grid->rows()->count().'</b>',]) !!}
-        @else
-            {!! trans('admin.pagination.range', ['first' => '<b>1</b>', 'last' => '<b>'.$grid->rows()->count().'</b>', 'total' => '<b>'.$grid->rows()->count().'</b>',]) !!}
-        @endif
-    </div>
-@endif
+    @if ($paginator = $grid->paginator())
+        <div class="box-footer clearfix " style="padding-bottom:5px;">
+            {!! $paginator !!}
+        </div>
+    @else
+        <div class="box-footer clearfix text-80 " style="height:48px;line-height:25px;">
+            @if ($grid->rows()->isEmpty())
+                {!! trans('admin.pagination.range', ['first' => '<b>0</b>', 'last' => '<b>'.$grid->rows()->count().'</b>', 'total' => '<b>'.$grid->rows()->count().'</b>',]) !!}
+            @else
+                {!! trans('admin.pagination.range', ['first' => '<b>1</b>', 'last' => '<b>'.$grid->rows()->count().'</b>', 'total' => '<b>'.$grid->rows()->count().'</b>',]) !!}
+            @endif
+        </div>
+    @endif
+
+</div>

+ 2 - 2
resources/views/tree.blade.php

@@ -1,4 +1,4 @@
-<div class="card-header" style="border-bottom:0">
+<div class="card-header">
 
     <div class="btn-group" style="margin-right:3px">
         <a class="btn btn-primary btn-sm {{ $id }}-tree-tools" data-action="expand">
@@ -32,7 +32,7 @@
 </div>
 
 <div class="card-body table-responsive">
-    <div class="dd" id="{{ $id }}" style="margin:8px 15px 15px">
+    <div class="dd" id="{{ $id }}" style="margin:18px">
         <ol class="dd-list">
             @foreach($items as $branch)
                 @include($branchView)

+ 16 - 6
src/Controllers/ExtensionController.php

@@ -106,13 +106,18 @@ class ExtensionController extends Controller
         $grid->name;
         $grid->version;
         $grid->alias;
-        $grid->description->expand(function ($expand) {
-            if (!$this->description) return;
 
-            $expand->button(trans('admin.view'));
+        $grid->description
+            ->if(function () {
+                return mb_strlen($this->description) > 14;
+            })
+            ->limit(14)
+            ->expand(function ($expand) {
+                if (!$this->description) return;
+
+                return "<div style='padding:10px 20px'>{$this->description}</div>";
+            });
 
-            return "<div style='padding:10px 20px'>{$this->description}</div>";
-        });
         $grid->authors;
 
         $grid->enable->switch();
@@ -122,8 +127,13 @@ class ExtensionController extends Controller
         $view = ucfirst(trans('admin.view'));
 
         $grid->config
+            ->if(function () {
+                return $this->config ? true : false;
+            })
             ->display($view)
-            ->expand($this->getExpandHandler('config'));
+            ->expand($this->getExpandHandler('config'))
+            ->else()
+            ->showEmpty();
 
         $grid->require
             ->display($view)

+ 11 - 1
src/Controllers/LogController.php

@@ -75,9 +75,19 @@ class LogController extends Controller
                     return $userModel::findOrFail($v)->pluck('name', 'id');
                 });
 
-            $filter->equal('method', trans('admin.method'))->select(array_combine(OperationLogModel::$methods, OperationLogModel::$methods));
+            $filter->equal('method', trans('admin.method'))
+                ->select(
+                    array_combine(OperationLogModel::$methods, OperationLogModel::$methods)
+                );
+
             $filter->like('path', trans('admin.uri'));
+
             $filter->equal('ip', 'IP');
+
+            $filter->between('created_at')
+                ->width(4)
+                ->datetime();
+
         });
 
         return $grid;

+ 2 - 1
src/Controllers/MenuController.php

@@ -9,6 +9,7 @@ use Dcat\Admin\Layout\Content;
 use Dcat\Admin\Layout\Row;
 use Dcat\Admin\Tree;
 use Dcat\Admin\Widgets\Box;
+use Dcat\Admin\Widgets\Card;
 use Illuminate\Routing\Controller;
 
 class MenuController extends Controller
@@ -51,7 +52,7 @@ class MenuController extends Controller
 
                     $form->setWidth(9, 2);
 
-                    $column->append(Box::make(trans('admin.new'), $form)->style('success'));
+                    $column->append(Card::make(trans('admin.new'), $form)->class('card material'));
                 });
             });
     }

+ 42 - 49
src/Controllers/RoleController.php

@@ -2,6 +2,7 @@
 
 namespace Dcat\Admin\Controllers;
 
+use Dcat\Admin\Admin;
 use Dcat\Admin\Auth\Permission;
 use Dcat\Admin\Models\Repositories\Role;
 use Dcat\Admin\Models\Role as RoleModel;
@@ -63,7 +64,7 @@ class RoleController extends Controller
         return $content
             ->header(trans('admin.roles'))
             ->description(trans('admin.edit'))
-            ->body($this->form($id)->edit($id));
+            ->body($this->form()->edit($id));
     }
 
     /**
@@ -96,6 +97,11 @@ class RoleController extends Controller
 
         $grid->disableBatchDelete();
         $grid->disableCreateButton();
+        $grid->showQuickCreateButton();
+        $grid->disableEditButton();
+        $grid->showQuickEditButton();
+        $grid->disableFilterButton();
+        $grid->quickSearch(['id', 'name', 'slug']);
 
         $grid->id('ID')->bold()->sortable();
         $grid->slug->label('primary');
@@ -113,12 +119,6 @@ class RoleController extends Controller
             }
         });
 
-        $grid->filter(function (Grid\Filter $filter) {
-            $filter->equal('id')->width('270px');
-            $filter->like('slug')->width('270px');
-            $filter->like('name')->width('270px');
-        });
-
         return $grid;
     }
 
@@ -131,28 +131,25 @@ class RoleController extends Controller
      */
     protected function detail($id)
     {
-        $show = new Show(new Role());
-
-        $show->setId($id);
-
-        $show->id;
-        $show->slug;
-        $show->name;
+        return Admin::show($id, new Role('permissions'), function (Show $show) {
+            $show->id;
+            $show->slug;
+            $show->name;
 
-        $show->permissions->width(12)->as(function ($permission) {
-            return collect($permission)->pluck('name');
-        })->label('primary');
+            $show->permissions->width(12)->as(function ($permission) {
+                return collect($permission)->pluck('name');
+            })->label('primary');
 
-        $show->divider();
+            $show->divider();
 
-        $show->created_at;
-        $show->updated_at;
+            $show->created_at;
+            $show->updated_at;
 
-        if ($id == RoleModel::ADMINISTRATOR_ID) {
-            $show->disableDeleteButton();
-        }
+            if ($show->getId() == RoleModel::ADMINISTRATOR_ID) {
+                $show->disableDeleteButton();
+            }
 
-        return $show;
+        });
     }
 
     /**
@@ -160,38 +157,34 @@ class RoleController extends Controller
      *
      * @return Form
      */
-    public function form($id = null)
+    public function form()
     {
-        $form = new Form(new Role());
+        return Admin::form(new Role('permissions'), function (Form $form) {
+            $form->display('id', 'ID');
 
-        $form->display('id', 'ID');
+            $form->text('slug', trans('admin.slug'))->required();
+            $form->text('name', trans('admin.name'))->required();
 
-        $form->text('slug', trans('admin.slug'))->required()->prepareForSave(function ($value) {
-            return $value;
-        });
-        $form->text('name', trans('admin.name'))->required();
-
-        $form->tree('permissions')
-            ->nodes(function () {
-                $permissionModel = config('admin.database.permissions_model');
-                $permissionModel = new $permissionModel;
-
-                return $permissionModel->allNodes();
-            })
-            ->customFormat(function ($v) {
-                if (!$v) return [];
+            $form->tree('permissions')
+                ->nodes(function () {
+                    $permissionModel = config('admin.database.permissions_model');
+                    $permissionModel = new $permissionModel;
 
-                return array_column($v, 'id');
-            });
+                    return $permissionModel->allNodes();
+                })
+                ->customFormat(function ($v) {
+                    if (!$v) return [];
 
-        $form->display('created_at', trans('admin.created_at'));
-        $form->display('updated_at', trans('admin.updated_at'));
+                    return array_column($v, 'id');
+                });
 
-        if ($id == RoleModel::ADMINISTRATOR_ID) {
-            $form->disableDeleteButton();
-        }
+            $form->display('created_at', trans('admin.created_at'));
+            $form->display('updated_at', trans('admin.updated_at'));
 
-        return $form;
+            if ($form->getKey() == RoleModel::ADMINISTRATOR_ID) {
+                $form->disableDeleteButton();
+            }
+        });
     }
 
     /**

+ 21 - 24
src/Controllers/UserController.php

@@ -90,9 +90,6 @@ class UserController extends Controller
     protected function grid()
     {
         return Admin::grid(new Administrator('roles'), function (Grid $grid) {
-            $grid->disableBatchDelete();
-            $grid->disableCreateButton();
-
             $grid->id('ID')->bold()->sortable();
             $grid->username;
             $grid->name;
@@ -101,11 +98,11 @@ class UserController extends Controller
             $permissionModel = config('admin.database.permissions_model');
             $roleModel = config('admin.database.roles_model');
             $nodes = (new $permissionModel)->allNodes();
-            $grid->permissions->display(function ($v, $column) use (&$nodes, $roleModel) {
-                if (empty($this->roles)) {
-                    return;
-                }
-                return $column->tree(function (Grid\Displayers\Tree $tree) use (&$nodes, $roleModel) {
+            $grid->permissions
+                ->if(function () {
+                    return ! empty($this->roles);
+                })
+                ->tree(function (Grid\Displayers\Tree $tree) use (&$nodes, $roleModel) {
                     $tree->nodes($nodes);
 
                     foreach (array_column($this->roles, 'slug') as $slug) {
@@ -113,23 +110,27 @@ class UserController extends Controller
                             $tree->checkedAll();
                         }
                     }
-                });
-            });
+                })
+                ->else()
+                ->showEmpty();
+
 
             $grid->created_at;
             $grid->updated_at->sortable();
 
+            $grid->disableBatchDelete();
+            $grid->disableCreateButton();
+            $grid->showQuickCreateButton();
+            $grid->showQuickEditButton();
+            $grid->disableFilterButton();
+            $grid->quickSearch(['id', 'name', 'username']);
+
             $grid->actions(function (Grid\Displayers\Actions $actions) {
                 if ($actions->getKey() == AdministratorModel::DEFAULT_ID) {
                     $actions->disableDelete();
                 }
             });
 
-            $grid->filter(function (Grid\Filter $filter) {
-                $filter->equal('id');
-                $filter->like('username');
-                $filter->like('name');
-            });
         });
     }
 
@@ -140,17 +141,13 @@ class UserController extends Controller
     {
         $grid = new MiniGrid(new Administrator());
 
-        $grid->id->bold()->sortable()->filter(
-            Grid\Column\Filter\Equal::make('ID')
-        );
+        $grid->quickSearch(['id', 'name', 'username']);
+
+        $grid->id->bold()->sortable();
 
-        $grid->username->filter(
-            Grid\Column\Filter\StartWith::make(__('admin.username'))
-        );
+        $grid->username;
 
-        $grid->name->filter(
-            Grid\Column\Filter\StartWith::make(__('admin.name'))
-        );
+        $grid->name;
 
         $grid->created_at;
 

+ 39 - 26
src/Form.php

@@ -10,7 +10,7 @@ use Dcat\Admin\Form\Row;
 use Dcat\Admin\Form\Tab;
 use Dcat\Admin\Contracts\Repository;
 use Dcat\Admin\Traits\HasBuilderEvents;
-use Dcat\Admin\Widgets\DialogForm;
+use Dcat\Admin\Widgets\ModalForm;
 use Illuminate\Contracts\Support\MessageProvider;
 use Illuminate\Contracts\Support\Renderable;
 use Illuminate\Support\Arr;
@@ -179,7 +179,7 @@ class Form implements Renderable
     /**
      * @var Closure
      */
-    protected $fieldBuilder;
+    protected $callback;
 
     /**
      * @var bool
@@ -268,7 +268,7 @@ class Form implements Renderable
     {
         $this->repository = Admin::createRepository($repository);
 
-        $this->fieldBuilder = $callback;
+        $this->callback = $callback;
 
         $this->builder = new Builder($this);
 
@@ -276,7 +276,7 @@ class Form implements Renderable
 
         $this->setModel(new Fluent());
 
-        $this->prepareDialogForm();
+        $this->prepareModalForm();
 
         $this->callResolving();
     }
@@ -513,7 +513,7 @@ class Form implements Renderable
 
             $this->setModel(new Fluent($data));
 
-            $this->buildField();
+            $this->build();
 
             if (($response = $this->callDeleting()) instanceof Response) {
                 return $response;
@@ -553,6 +553,8 @@ class Form implements Renderable
     {
         $data = $data ?: request()->all();
 
+        $this->build();
+
         if (($response = $this->callSubmitted())) {
             return $response;
         }
@@ -724,7 +726,7 @@ class Form implements Renderable
         $this->builder->setResourceId($id);
         $this->builder->setMode(Builder::MODE_EDIT);
 
-        $this->buildField();
+        $this->build();
 
         if (($response = $this->callSubmitted())) {
             return $response;
@@ -789,20 +791,24 @@ class Form implements Renderable
             $message = $options;
             $options = [];
         } else {
-            $message = $options['message'] ?? trans('admin.save_succeeded');
+            $message = $options['message'] ?? null;
         }
 
         $status = (bool) ($options['status'] ?? true);
 
         // 判断是否是ajax请求
-        if ($response = $this->ajaxResponse($message, $url, $status)) {
-            return $response;
+        if ($this->isAjaxRequest()) {
+            $message = $message ?: trans('admin.save_succeeded');
+
+            return $this->ajaxResponse($message, $url, $status);
         }
 
         // 非ajax请求
         $status = (int) ($options['status_code'] ?? 302);
 
-        admin_alert($message);
+        if ($message) {
+            admin_alert($message);
+        }
 
         return redirect($url, $status);
 
@@ -1108,17 +1114,17 @@ class Form implements Renderable
 
     /**
      * @example
-     *     $form->if(true)->next(function (Form $form) {
+     *     $form->if(true)->then(function (Form $form) {
      *          $form->text('name');
      *     });
      *
      *     $form->if(function (Form $form) {
      *         return $form->model()->id > 5;
-     *     })->next(function (Form $form) {
+     *     })->then(function (Form $form) {
      *         $form->text('name');
      *     });
      *
-     *     $form->if(true)->then(function (Form $form) {
+     *     $form->if(true)->now(function (Form $form) {
      *         $form->text('name');
      *     });
      *
@@ -1144,7 +1150,7 @@ class Form implements Renderable
             $this->setModel(new Fluent($this->repository->edit($this)));
         }
 
-        $this->buildField();
+        $this->build();
 
         if ($isEditing) {
             $this->setFieldValue();
@@ -1156,14 +1162,14 @@ class Form implements Renderable
     /**
      * @return void
      */
-    protected function buildField()
+    protected function build()
     {
-        if ($callback = $this->fieldBuilder) {
+        if ($callback = $this->callback) {
             $callback($this);
         }
 
         foreach ($this->conditions as $condition) {
-            $condition->then();
+            $condition->process();
         }
     }
 
@@ -1580,30 +1586,37 @@ class Form implements Renderable
     /**
      * @return $this
      */
-    protected function prepareDialogForm()
+    protected function prepareModalForm()
     {
-        DialogForm::prepare($this);
+        ModalForm::prepare($this);
 
         return $this;
     }
 
     /**
-     * @return bool
+     * @param Closure $callback
+     * @return bool|void
      */
-    public static function inDialog()
+    public function inModal(\Closure $callback = null)
     {
-        return DialogForm::is();
+        if (! $callback) {
+            return ModalForm::is();
+        }
+
+        if (ModalForm::is()) {
+            $callback($this);
+        }
     }
 
     /**
-     * Create a dialog form.
+     * Create a modal form.
      *
      * @param string|null $title
-     * @return DialogForm
+     * @return ModalForm
      */
-    public static function popup(?string $title = null)
+    public static function modal(?string $title = null)
     {
-        return new DialogForm($title);
+        return new ModalForm($title);
     }
 
     /**

+ 3 - 2
src/Form/Builder.php

@@ -688,7 +688,8 @@ class Builder
         ];
 
         $this->fields = $this->fields()->reject(function (Field $field) use (&$reservedColumns) {
-            return in_array($field->column(), $reservedColumns);
+            return in_array($field->column(), $reservedColumns)
+                && $field instanceof Form\Field\Display;
         });
     }
 
@@ -766,7 +767,7 @@ EOF;
 
         $style = $this->isCreating() ? 'success' : 'default';
 
-        return "<div class='box box-{$style}'>{$view->render()}</div>";
+        return "<div class='card material'>{$view->render()}</div>";
     }
 
     protected function setupSubmitScript()

+ 34 - 7
src/Form/Condition.php

@@ -15,6 +15,8 @@ class Condition
 
     protected $condition;
 
+    protected $result;
+
     /**
      * @var \Closure[]
      */
@@ -26,14 +28,34 @@ class Condition
         $this->form = $form;
     }
 
-    public function next(\Closure $closure)
+    public function then(\Closure $closure)
     {
         $this->next[] = $closure;
 
         return $this;
     }
 
-    public function then(\Closure $next = null)
+    public function now(\Closure $next = null)
+    {
+        $this->process($next);
+    }
+
+    public function else(\Closure $next = null)
+    {
+        $self = $this;
+
+        $condition = $this->form->if(function () use ($self) {
+            return ! $self->getResult();
+        });
+
+        if ($next) {
+            $condition->then($next);
+        }
+
+        return $condition;
+    }
+
+    public function process(\Closure $next = null)
     {
         if ($this->done) {
             return;
@@ -45,7 +67,7 @@ class Condition
         }
 
         if ($next) {
-            $this->next($next);
+            $this->then($next);
         }
 
         foreach ($this->next as $callback) {
@@ -59,7 +81,12 @@ class Condition
             $this->condition = $this->call($this->condition);
         }
 
-        return $this->condition ? true : false;
+        return $this->result = $this->condition ? true : false;
+    }
+
+    public function getResult()
+    {
+        return $this->result;
     }
 
     protected function call(\Closure $callback)
@@ -69,11 +96,11 @@ class Condition
 
     public function __call($name, $arguments)
     {
-        if (! method_exists($this->form, $name)) {
-            return $this;
+        if ($name == 'if') {
+            return $this->form->if(...$arguments);
         }
 
-        return $this->next(function (Form $form) use ($name, &$arguments) {
+        return $this->then(function (Form $form) use ($name, &$arguments) {
             return $form->$name(...$arguments);
         });
     }

+ 7 - 4
src/Form/Field.php

@@ -754,7 +754,7 @@ class Field implements Renderable
      * @param \Closure $closure
      * @return $this
      */
-    public function prepareForSave(\Closure $closure)
+    public function saving(\Closure $closure)
     {
         $this->prepare = $closure;
 
@@ -900,13 +900,16 @@ class Field implements Renderable
     }
 
     /**
-     * Remove the field in dialog.
+     * Remove the field in modal.
      *
      * @return $this
      */
-    public function hideInDialog()
+    public function hideInModal()
     {
-        if (Form::inDialog()) {
+        if (
+            $this->form instanceof Form
+            && $this->form->inModal()
+        ) {
             $this->setDisplay(false);
         }
 

+ 0 - 23
src/Form/Field/Tags.php

@@ -31,11 +31,6 @@ class Tags extends Field
      */
     protected $key = null;
 
-    /**
-     * @var \Closure
-     */
-    protected $saveAction = null;
-
     /**
      * {@inheritdoc}
      */
@@ -102,20 +97,6 @@ class Tags extends Field
         return $this;
     }
 
-    /**
-     * Set save Action.
-     *
-     * @param \Closure $saveAction
-     *
-     * @return $this
-     */
-    public function saving(\Closure $saveAction)
-    {
-        $this->saveAction = $saveAction;
-
-        return $this;
-    }
-
     /**
      * {@inheritdoc}
      */
@@ -123,10 +104,6 @@ class Tags extends Field
     {
         $value = array_filter($value, 'strlen');
 
-        if ($this->keyAsValue) {
-            return is_null($this->saveAction) ? $value : ($this->saveAction)($value);
-        }
-
         if (is_array($value) && !Arr::isAssoc($value)) {
             $value = implode(',', $value);
         }

+ 7 - 10
src/Grid.php

@@ -150,20 +150,20 @@ class Grid
         'show_pagination'        => true,
         'show_filter'            => true,
         'show_actions'           => true,
-        'show_quick_edit_button' => true,
+        'show_quick_edit_button' => false,
         'show_edit_button'       => true,
         'show_view_button'       => true,
         'show_delete_button'     => true,
         'show_row_selector'      => true,
         'show_create_btn'        => true,
-        'show_quick_create_btn'  => true,
+        'show_quick_create_btn'  => false,
         'show_bordered'          => false,
         'show_toolbar'           => true,
 
         'row_selector_style'      => 'primary',
         'row_selector_circle'     => true,
         'row_selector_clicktr'    => false,
-        'row_selector_label_name' => null,
+        'row_selector_label_key' => null,
         'row_selector_bg'         => 'var(--20)',
 
         'show_exporter'             => false,
@@ -357,8 +357,8 @@ class Grid
         if (isset($options['clicktr'])) {
             $this->options['row_selector_clicktr'] = $options['clicktr'];
         }
-        if (isset($options['label_name'])) {
-            $this->options['row_selector_label_name'] = $options['label_name'];
+        if (isset($options['label'])) {
+            $this->options['row_selector_label_key'] = $options['label_name'];
         }
         if (isset($options['bg'])) {
             $this->options['row_selector_bg'] = $options['bg'];
@@ -414,9 +414,6 @@ HTML
             return;
         }
 
-        $this->applyQuickSearch();
-        $this->applyColumnFilter();
-
         $collection = $this->processFilter(false);
 
         $data = $collection->toArray();
@@ -503,7 +500,7 @@ HTML
      * @param string $height
      * @return $this
      */
-    public function setDialogFormDimensions(string $width, string $height)
+    public function setModalFormDimensions(string $width, string $height)
     {
         $this->options['dialog_form_area'] = [$width, $height];
 
@@ -918,7 +915,7 @@ HTML;
         $view = view($this->view, $this->variables());
 
         if (!$wrapper = $this->wrapper) {
-            return "<div class='box box-default'>{$view->render()}</div>";
+            return $view->render();
         }
 
         return $wrapper($view);

+ 1 - 1
src/Grid/Actions/QuickEdit.php

@@ -24,7 +24,7 @@ class QuickEdit extends RowAction
 
             list($width, $height) = $this->parent->option('dialog_form_area');
 
-            Form::popup(trans('admin.edit'))
+            Form::modal(trans('admin.edit'))
                 ->click(".{$this->getElementClass()}")
                 ->dimensions($width, $height)
                 ->success('LA.reload()')

+ 109 - 20
src/Grid/Column.php

@@ -36,7 +36,6 @@ use Illuminate\Support\Str;
  * @method $this copyable()
  * @method $this orderable()
  *
- * @method $this limit($limit = 100, $end = '...')
  * @method $this ascii()
  * @method $this camel()
  * @method $this finish($cap)
@@ -118,6 +117,11 @@ class Column
      */
     protected $label;
 
+    /**
+     * @var Fluent
+     */
+    protected $originalModel;
+
     /**
      * Original value of column.
      *
@@ -164,6 +168,11 @@ class Column
      */
     protected static $model;
 
+    /**
+     * @var Grid\Column\Condition
+     */
+    protected $conditions = [];
+
     /**
      * @param string $name
      * @param string $label
@@ -236,6 +245,37 @@ class Column
         return $this;
     }
 
+    /**
+     *
+     * @example
+     *     $grid->config
+     *         ->if(function () {
+     *             return $this->config ? true : false;
+     *         })
+     *         ->display($view)
+     *         ->expand(...)
+     *         ->else()
+     *         ->showEmpty()
+     *
+     *    $grid->config
+     *         ->if(function () {
+     *             return $this->config ? true : false;
+     *         })
+     *         ->then(function (Column $column) {
+     *             $column ->display($view)->expand(...);
+     *         })
+     *         ->else(function (Column $column) {
+     *             $column->showEmpty();
+     *         })
+     *
+     * @param \Closure $condition
+     * @return Column\Condition|$this
+     */
+    public function if(\Closure $condition)
+    {
+        return $this->conditions[] = new Grid\Column\Condition($condition, $this);
+    }
+
     /**
      * Set column attributes.
      *
@@ -321,6 +361,26 @@ class Column
         return $this->name;
     }
 
+    /**
+     * @param array|Model $model
+     */
+    public function setOriginalModel($model)
+    {
+        if (is_array($model)) {
+            $model = new Fluent($model);
+        }
+
+        $this->originalModel = $model;
+    }
+
+    /**
+     * @return Fluent|Model
+     */
+    public function getOriginalModel()
+    {
+        return $this->originalModel;
+    }
+
     /**
      * @return mixed
      */
@@ -435,20 +495,37 @@ class Column
      *
      * @return bool
      */
-    protected function hasDisplayCallbacks()
+    public function hasDisplayCallbacks()
+    {
+        return ! empty($this->displayCallbacks);
+    }
+
+    /**
+     * @param array $callbacks
+     *
+     * @return void
+     */
+    public function setDisplayCallbacks(array $callbacks)
     {
-        return !empty($this->displayCallbacks);
+        $this->displayCallbacks = $callbacks;
+    }
+
+    /**
+     * @return \Closure[]
+     */
+    public function getDisplayCallbacks()
+    {
+        return $this->displayCallbacks;
     }
 
     /**
      * Call all of the "display" callbacks column.
      *
      * @param mixed $value
-     * @param int   $key
      *
      * @return mixed
      */
-    protected function callDisplayCallbacks($value, $key)
+    protected function callDisplayCallbacks($value)
     {
         foreach ($this->displayCallbacks as $callback) {
             list($callback, $params) = $callback;
@@ -460,14 +537,15 @@ class Column
 
             $previous = $value;
 
-            $callback = $this->bindOriginalRowModel($callback, $key);
+            $callback = $this->bindOriginalRowModel($callback);
             $value = $callback($value, $this, ...$params);
 
-            if (($value instanceof static) &&
-                ($last = array_pop($this->displayCallbacks))
+            if (
+                $value instanceof static
+                && ($last = array_pop($this->displayCallbacks))
             ) {
                 list($last, $params) = $last;
-                $last = $this->bindOriginalRowModel($last, $key);
+                $last = $this->bindOriginalRowModel($last);
                 $value = call_user_func($last, $previous, $this, ...$params);
             }
         }
@@ -479,19 +557,12 @@ class Column
      * Set original grid data to column.
      *
      * @param Closure $callback
-     * @param int     $key
      *
      * @return Closure
      */
-    protected function bindOriginalRowModel(Closure $callback, $key)
+    protected function bindOriginalRowModel(Closure $callback)
     {
-        $rowModel = static::$originalGridModels[$key];
-
-        if (is_array($rowModel)) {
-            $rowModel = new Fluent($rowModel);
-        }
-
-        return $callback->bindTo($rowModel);
+        return $callback->bindTo($this->getOriginalModel());
     }
 
     /**
@@ -508,7 +579,7 @@ class Column
         $i = 0;
         foreach ($data as $key => &$row) {
             $i++;
-            if (!isset($row['#'])) {
+            if (! isset($row['#'])) {
                 $row['#'] = $i;
             }
 
@@ -516,10 +587,14 @@ class Column
 
             $this->value = $value = $this->htmlEntityEncode($value);
 
+            $this->setOriginalModel(static::$originalGridModels[$key]);
+
+            $this->processConditions();
+
             Arr::set($row, $this->name, $value);
 
             if ($this->hasDisplayCallbacks()) {
-                $value = $this->callDisplayCallbacks($this->original, $key);
+                $value = $this->callDisplayCallbacks($this->original);
                 Arr::set($row, $this->name, $value);
             }
         }
@@ -527,6 +602,20 @@ class Column
         $this->value = $value ?? null;
     }
 
+    /**
+     * @return void
+     */
+    protected function processConditions()
+    {
+        foreach ($this->conditions as $condition) {
+            $condition->reset();
+        }
+
+        foreach ($this->conditions as $condition) {
+            $condition->process();
+        }
+    }
+
     /**
      * Use a defined column.
      *

+ 134 - 0
src/Grid/Column/Condition.php

@@ -0,0 +1,134 @@
+<?php
+
+namespace Dcat\Admin\Grid\Column;
+
+use Dcat\Admin\Grid\Column;
+
+class Condition
+{
+    /**
+     * @var Column
+     */
+    protected $original;
+
+    /**
+     * @var Column
+     */
+    protected $column;
+
+    /**
+     * @var mixed
+     */
+    protected $condition;
+
+    /**
+     * @var bool
+     */
+    protected $result;
+
+    /**
+     * @var \Closure[]
+     */
+    protected $next = [];
+
+    public function __construct($condition, Column $column)
+    {
+        $this->condition = $condition;
+        $this->original = clone $column;
+        $this->column = $column;
+    }
+
+    public function then(\Closure $closure)
+    {
+        $this->next[] = $closure;
+
+        return $this;
+    }
+
+    public function else(\Closure $next = null)
+    {
+        $self = $this;
+
+        $condition = $this->column->if(function () use ($self) {
+            return ! $self->getResult();
+        });
+
+        if ($next) {
+            $condition->then($next);
+        }
+
+        return $condition;
+    }
+
+    public function process()
+    {
+        if ($this->is()) {
+            $this->callCallbacks($this->next);
+        }
+    }
+
+    protected function callCallbacks(array $callbacks)
+    {
+        if (! $callbacks) {
+            return;
+        }
+
+        $column = $this->copy();
+
+        foreach ($callbacks as $callback) {
+            $this->call($callback, $column);
+        }
+
+        $this->setColumnDisplayers($column->getDisplayCallbacks());
+    }
+
+    public function reset()
+    {
+        $this->setColumnDisplayers($this->original->getDisplayCallbacks());
+    }
+
+    public function setColumnDisplayers(array $callbacks)
+    {
+        $this->column->setDisplayCallbacks($callbacks);
+    }
+
+    protected function copy()
+    {
+        return clone $this->original;
+    }
+
+    public function is()
+    {
+        $condition = $this->condition;
+
+        if ($condition instanceof \Closure) {
+            $condition = $this->call($condition);
+        }
+
+        return $this->result = $condition ? true : false;
+    }
+
+    public function getResult()
+    {
+        return $this->result;
+    }
+
+    protected function call(\Closure $callback, $column = null)
+    {
+        $column = $column ?: $this->column;
+
+        return $callback->call($this->column->getOriginalModel(), $column);
+    }
+
+    public function __call($name, $arguments)
+    {
+        if ($name == 'if') {
+            return $this->column->if(...$arguments);
+        }
+
+        return $this->then(function ($column) use ($name, &$arguments) {
+            return $column->$name(...$arguments);
+        });
+    }
+
+}

+ 25 - 0
src/Grid/Column/Filter/Between.php

@@ -10,6 +10,11 @@ class Between extends Filter
 {
     protected $dateFormat = null;
 
+    /**
+     * @var bool
+     */
+    protected $timestamp = false;
+
     public function __construct()
     {
         $this->class = [
@@ -18,6 +23,18 @@ class Between extends Filter
         ];
     }
 
+    /**
+     * Convert the datetime into unix timestamp.
+     *
+     * @return $this
+     */
+    public function toTimestamp()
+    {
+        $this->timestamp = true;
+
+        return $this;
+    }
+
     /**
      * Date filter.
      *
@@ -75,6 +92,14 @@ class Between extends Filter
             return;
         }
 
+        if ($this->timestamp) {
+            $value = array_map(function ($v) {
+                if ($v) {
+                    return strtotime($v);
+                }
+            }, $value);
+        }
+
         if (!isset($value['start'])) {
             return $model->where($this->getColumnName(), '<=', $value['end']);
         }

+ 26 - 0
src/Grid/Column/HasDisplayers.php

@@ -172,4 +172,30 @@ trait HasDisplayers
         });
     }
 
+    /**
+     * Limit the number of characters in a string.
+     *
+     * @param  int     $limit
+     * @param  string  $end
+     * @return $this
+     */
+    public function limit($limit = 100, $end = '...')
+    {
+        return $this->display(function ($value) use ($limit, $end) {
+            if (mb_strlen($value, 'UTF-8') <= $limit) {
+                return $value;
+            }
+
+            return mb_substr($value, 0, $limit).$end;
+        });
+    }
+
+    /**
+     * @return $this
+     */
+    public function showEmpty()
+    {
+        return $this->display('');
+    }
+
 }

+ 2 - 0
src/Grid/Concerns/HasElementNames.php

@@ -52,6 +52,8 @@ trait HasElementNames
 
         $this->setExporterQueryName($name);
 
+        $this->setQuickSearchQueryName($name);
+
         return $this;
     }
 

+ 3 - 0
src/Grid/Concerns/HasFilter.php

@@ -48,6 +48,9 @@ trait HasFilter
             call_user_func($this->builder, $this);
         }
 
+        $this->applyQuickSearch();
+        $this->applyColumnFilter();
+
         return $this->filter->execute($toArray);
     }
 

+ 57 - 7
src/Grid/Concerns/HasQuickSearch.php

@@ -17,14 +17,14 @@ use Illuminate\Support\Str;
 trait HasQuickSearch
 {
     /**
-     * @var string
+     * @var array|string|\Closure
      */
-    public static $searchKey = '__search__';
+    protected $search;
 
     /**
-     * @var array|string|\Closure
+     * @var Tools\QuickSearch
      */
-    protected $search;
+    protected $quickSearch;
 
     /**
      * @param array|string|\Closure
@@ -39,11 +39,47 @@ trait HasQuickSearch
             $this->search = $search;
         }
 
+        if ($this->quickSearch) {
+            return $this->quickSearch;
+        }
+
         return tap(new Tools\QuickSearch(), function ($search) {
-            $this->tools->append($search);
+            $search->setGrid($this);
+
+            $this->quickSearch = $search;
         });
     }
 
+    /**
+     * @param string $gridName
+     */
+    protected function setQuickSearchQueryName($gridName)
+    {
+        if ($this->quickSearch) {
+            $this->quickSearch->setQueryName($gridName.'__search');
+        }
+    }
+
+    /**
+     * @return Tools\QuickSearch
+     */
+    public function getQuickSearch()
+    {
+        return $this->quickSearch;
+    }
+
+    /**
+     * @return \Illuminate\View\View|string
+     */
+    public function renderQuickSearch()
+    {
+        if (! $this->quickSearch) {
+            return '';
+        }
+
+        return $this->quickSearch->render();
+    }
+
     /**
      * Apply the search query to the query.
      *
@@ -51,7 +87,11 @@ trait HasQuickSearch
      */
     public function applyQuickSearch()
     {
-        if (!$query = request()->get(static::$searchKey)) {
+        if (! $this->quickSearch) {
+            return;
+        }
+
+        if (! $query = request()->get($this->quickSearch->getQueryName())) {
             return;
         }
 
@@ -83,8 +123,13 @@ trait HasQuickSearch
     protected function addWhereBindings($query)
     {
         $queries = preg_split('/\s(?=([^"]*"[^"]*")*[^"]*$)/', trim($query));
+        if (! $queries = $this->parseQueryBindings($queries)) {
+            $this->addWhereBasicBinding($this->getKeyName(), false, '=', '___');
+
+            return;
+        }
 
-        foreach ($this->parseQueryBindings($queries) as list($column, $condition, $or)) {
+        foreach ($queries as list($column, $condition, $or)) {
             if (preg_match('/(?<not>!?)\((?<values>.+)\)/', $condition, $match) !== 0) {
                 $this->addWhereInBinding($column, $or, (bool)$match['not'], $match['values']);
                 continue;
@@ -105,6 +150,11 @@ trait HasQuickSearch
                 continue;
             }
 
+            if (preg_match('/(?<pattern>[^%]+%)/', $condition, $match) !== 0) {
+                $this->addWhereLikeBinding($column, $or, $match['pattern']);
+                continue;
+            }
+
             if (preg_match('/\/(?<value>.*)\//', $condition, $match) !== 0) {
                 $this->addWhereBasicBinding($column, $or, 'REGEXP', $match['value']);
                 continue;

+ 1 - 1
src/Grid/Displayers/Actions.php

@@ -218,7 +218,7 @@ EOT;
 
             list($width, $height) = $this->grid->option('dialog_form_area');
 
-            Form::popup(trans('admin.edit'))
+            Form::modal(trans('admin.edit'))
                 ->click(".{$this->grid->getGridRowName()}-edit")
                 ->dimensions($width, $height)
                 ->success('LA.reload()')

+ 1 - 1
src/Grid/Displayers/Expand.php

@@ -37,7 +37,7 @@ class Expand extends AbstractDisplayer
 
         $key = $this->getDataKey();
 
-        $button = $this->button ?? $this->value;
+        $button = is_null($this->button) ? $this->value : $this->button;
 
         return <<<EOT
 <span class="grid-expand" data-inserted="0" data-key="{$key}" data-toggle="collapse" data-target="#grid-collapse-{$key}">

+ 1 - 1
src/Grid/Displayers/RowSelector.php

@@ -37,7 +37,7 @@ EOT;
      */
     protected function getLabel()
     {
-        if ($column = $this->grid->option('row_selector_label_name')) {
+        if ($column = $this->grid->option('row_selector_label_key')) {
             $label = $this->row->{$column};
             if ($label !== null && $label !== '') {
                 return $label;

+ 25 - 0
src/Grid/Filter/Between.php

@@ -13,6 +13,23 @@ class Between extends AbstractFilter
      */
     protected $view = 'admin::filter.between';
 
+    /**
+     * @var bool
+     */
+    protected $timestamp = false;
+
+    /**
+     * Convert the datetime into unix timestamp.
+     *
+     * @return $this
+     */
+    public function toTimestamp()
+    {
+        $this->timestamp = true;
+
+        return $this;
+    }
+
     /**
      * Format id.
      *
@@ -73,6 +90,14 @@ class Between extends AbstractFilter
             return $val !== '';
         });
 
+        if ($this->timestamp) {
+            $value = array_map(function ($v) {
+                if ($v) {
+                    return strtotime($v);
+                }
+            }, $value);
+        }
+
         if (empty($value)) {
             return;
         }

+ 1 - 1
src/Grid/Tools/CreateButton.php

@@ -28,7 +28,7 @@ class CreateButton
 
         list($width, $height) = $this->grid->option('dialog_form_area');
 
-        Form::popup($new)
+        Form::modal($new)
             ->click(".{$this->grid->getGridRowName()}-create")
             ->success('LA.reload()')
             ->dimensions($width, $height)

+ 57 - 4
src/Grid/Tools/QuickSearch.php

@@ -3,7 +3,6 @@
 namespace Dcat\Admin\Grid\Tools;
 
 use Dcat\Admin\Admin;
-use Dcat\Admin\Grid\Concerns\HasQuickSearch as QuickSearchConcerns;
 use Illuminate\Support\Arr;
 
 class QuickSearch extends AbstractTool
@@ -18,6 +17,30 @@ class QuickSearch extends AbstractTool
      */
     protected $placeholder = null;
 
+    /**
+     * @var string
+     */
+    protected $queryName = '__search__';
+
+    /**
+     * @param string|null $name
+     * @return $this
+     */
+    public function setQueryName(?string $name)
+    {
+        $this->queryName = $name;
+
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getQueryName()
+    {
+        return $this->queryName;
+    }
+
     /**
      * Set placeholder.
      *
@@ -37,22 +60,52 @@ class QuickSearch extends AbstractTool
      */
     public function render()
     {
+        $this->setupScript();
+
         $request = request();
         $query = $request->query();
 
         Arr::forget($query, [
-            QuickSearchConcerns::$searchKey,
+            $this->queryName,
             $this->grid->model()->getPageName(),
             '_pjax',
         ]);
 
         $vars = [
             'action' => $request->url() . '?' . http_build_query($query),
-            'key' => QuickSearchConcerns::$searchKey,
-            'value' => request(QuickSearchConcerns::$searchKey),
+            'key' => $this->queryName,
+            'value' => request($this->queryName),
             'placeholder' => $this->placeholder ?: trans('admin.search'),
         ];
 
         return view($this->view, $vars);
     }
+
+    protected function setupScript()
+    {
+        $script = <<<JS
+var show = function () {
+    var t = $(this),
+        clear = t.parent().find('.quick-search-clear');
+
+    if (t.val()) {
+        clear.css({color: '#333'});
+    } else {
+        clear.css({color: '#fff'});
+    }
+    return false;
+};
+
+$('input.quick-search-input').on('focus', show).on('keyup', show);
+
+$('.quick-search-clear').click(function () {
+    $(this).parent().find('.quick-search-input').val('');
+
+    $(this).closest('form').submit();
+});
+JS;
+
+        Admin::script($script);
+    }
+
 }

+ 0 - 4
src/MiniGrid.php

@@ -20,10 +20,6 @@ class MiniGrid extends Grid
         $this->option('row_selector_clicktr', true);
 
         $this->tools->disableBatchActions();
-
-        $this->wrap(function ($view) {
-            return "<div class='box'>$view</div>";
-        });
     }
 
     protected function setupFilter()

+ 2 - 2
src/Models/Repositories/Role.php

@@ -6,10 +6,10 @@ use Dcat\Admin\Repositories\EloquentRepository;
 
 class Role extends EloquentRepository
 {
-    public function __construct()
+    public function __construct($relations = [])
     {
         $this->eloquentClass = config('admin.database.roles_model');
 
-        parent::__construct();
+        parent::__construct($relations);
     }
 }

+ 3 - 3
src/Models/Role.php

@@ -65,7 +65,7 @@ class Role extends Model
      *
      * @return bool
      */
-    public function can(string $permission) : bool
+    public function can(?string $permission) : bool
     {
         return $this->permissions()->where('slug', $permission)->exists();
     }
@@ -77,7 +77,7 @@ class Role extends Model
      *
      * @return bool
      */
-    public function cannot(string $permission) : bool
+    public function cannot(?string $permission) : bool
     {
         return !$this->can($permission);
     }
@@ -115,7 +115,7 @@ class Role extends Model
      * @param string $slug
      * @return bool
      */
-    public static function isAdministrator(string $slug)
+    public static function isAdministrator(?string $slug)
     {
         return $slug === static::ADMINISTRATOR;
     }

+ 1 - 1
src/Show/Panel.php

@@ -213,7 +213,7 @@ class Panel implements Renderable
         $view = view($this->view, $this->data);
 
         if (!$wrapper = $this->wrapper) {
-            return "<div class='box box-{$this->data['style']}'>{$view->render()}</div>";
+            return "<div class='card material'>{$view->render()}</div>";
         }
 
         return $wrapper($view);

+ 1 - 1
src/Show/Tools.php

@@ -274,7 +274,7 @@ EOF;
             $id = 'show-edit-'.Str::random(8);
             list($width, $height) = $this->dialogFormDimensions;
 
-            Form::popup($edit)
+            Form::modal($edit)
                 ->click(".$id")
                 ->dimensions($width, $height)
                 ->success('LA.reload()')

+ 3 - 3
src/Tree.php

@@ -475,7 +475,7 @@ JS;
         if ($this->useQuickEdit) {
             list($width, $height) = $this->dialogFormDimensions;
 
-            Form::popup(trans('admin.edit'))
+            Form::modal(trans('admin.edit'))
                 ->click('.tree-quick-edit')
                 ->success('LA.reload()')
                 ->dimensions($width, $height)
@@ -491,7 +491,7 @@ JS;
         if ($this->useQuickCreate) {
             list($width, $height) = $this->dialogFormDimensions;
 
-            Form::popup(trans('admin.new'))
+            Form::modal(trans('admin.new'))
                 ->click('.tree-quick-create')
                 ->success('LA.reload()')
                 ->dimensions($width, $height)
@@ -537,7 +537,7 @@ JS;
         $view = view($this->view['tree'], $this->variables());
 
         if (!$wrapper = $this->wrapper) {
-            return "<div class='box box-default'>{$view->render()}</div>";
+            return "<div class='card material'>{$view->render()}</div>";
         }
 
         return $wrapper($view);

+ 3 - 6
src/Widgets/DialogForm.php → src/Widgets/ModalForm.php

@@ -7,16 +7,15 @@ use Dcat\Admin\Form;
 use Dcat\Admin\Layout\Content;
 use Dcat\Admin\Support\Helper;
 use Illuminate\Contracts\Support\Arrayable;
-use Illuminate\Support\Facades\URL;
 
-class DialogForm
+class ModalForm
 {
     const QUERY_NAME = '_form_win_';
 
     /**
      * @var string
      */
-    public static $contentView = 'admin::contents.dialog-form';
+    public static $contentView = 'admin::contents.modal-form';
 
     /**
      * @var array
@@ -239,7 +238,7 @@ class DialogForm
         {$this->handlers['saved']}
     };
     
-    LA.DialogForm(opts);
+    LA.ModalForm(opts);
 })();
 JS
         );
@@ -267,8 +266,6 @@ JS
     }
 
     /**
-     * 对弹窗要渲染的表单对象进行前置处理
-     *
      * @param Form $form
      */
     public static function prepare(Form $form)

+ 2 - 0
tests/CreatesApplication.php

@@ -19,6 +19,8 @@ trait CreatesApplication
 
         $app->register('Dcat\Admin\AdminServiceProvider');
 
+        $app->make('config')->set('app.locale', 'en');
+
         return $app;
 
     }

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.