From 8f69cb7f3df70c40cbae47a5661dc9ae67aae728 Mon Sep 17 00:00:00 2001
From: Sam Light <samlight1994@gmail.com>
Date: Mon, 6 Nov 2023 00:06:39 +0000
Subject: Lots of table improvments

---
 src/Columns/Column.php | 55 +++++++++++++++++++++++++++---------------
 src/TableComponent.php | 65 +++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 93 insertions(+), 27 deletions(-)

(limited to 'src')

diff --git a/src/Columns/Column.php b/src/Columns/Column.php
index 7b9f248..f3fe811 100644
--- a/src/Columns/Column.php
+++ b/src/Columns/Column.php
@@ -2,40 +2,48 @@
 
 namespace Lightscale\LaralightTables\Columns;
 
+use Lightscale\LaralightTables\TableComponent;
+
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\View\ComponentAttributeBag;
+use Illuminate\Support\HtmlString;
 
 use Closure;
 
 class Column {
 
     private TableComponent $table;
+    private bool $showInSelect;
 
-    private Closure $displayFn;
+    private ?Closure $slotFn = null;
     private ?Closure $sortFn = null;
-    private ?Closure $searchFn = null;
-    private ?Closure $attributesFn = null;
+    private ?Closure $tdAttributesFn = null;
 
     public function __construct(
         public string $name,
-        public string $title
+        public ?string $title = null
     ) {
-        $this->displayFn = Closure::fromCallable([$this, 'defaultDisplay']);
+        $this->showInSelect = $this->title !== null;
     }
 
-    public static function make(string $name, $title) : static
+    public static function make(string $name, ?string $title = null) : static
     {
         return new static($name, $title);
     }
 
-    private function defaultDisplay(Model $row, Column $column)
+    public function setTable(TableComponent $table) : void
+    {
+        $this->table = $table;
+    }
+
+    private function defaultSlot(Model $row)
     {
-        return $row->{$column->name};
+        return $row->{$this->name};
     }
 
-    public function display(callable $fn) : static
+    public function slot(callable $fn) : static
     {
-        $this->displayFn = Closure::fromCallable($fn);
+        $this->slotFn = Closure::fromCallable($fn);
         return $this;
     }
 
@@ -45,24 +53,33 @@ class Column {
         return $this;
     }
 
-    public function searchable(callable $fn) : static
+    public function tdAttributes(callable $fn) : static
     {
-        $this->searchFn = Closure::fromCallable($fn);
+        $this->tdAttributesFn = Closure::fromCallable($fn);
         return $this;
     }
 
-    public function attributes(callable $fn) : static
+    public function showInSelect($show = true)
     {
-        $this->attributesFn = Closure::fromCallable($fn);
-        return $this;
+        $this->showInSelect = $show;
+    }
+
+    public function getShowInSelect()
+    {
+        return $this->showInSelect;
+    }
+
+    protected function getContent(Model $row)
+    {
+        return $this->slotFn?->call($this, $row, $this) ?? $this->defaultSlot($row);
     }
 
     public function view(Model $row)
     {
-        $attributes = $this->attributesFn?->call($this, $row) ?? [];
-        $attributes = new ComponentAttributeBag($attributes);
-        $content = $this->displayFn->call($this, $row, $this);
-        return view('laralight-tables::column', compact('attributes', 'content'));
+        $attributes = $this->tdAttributesFn?->call($this, $row) ?? [];
+        $attributes = (new ComponentAttributeBag($attributes))->toHtml();
+        $content = $this->getContent($row);
+        return new HtmlString("<td {$attributes}>{$content}</td>");
     }
 
 }
diff --git a/src/TableComponent.php b/src/TableComponent.php
index e530415..04d457e 100644
--- a/src/TableComponent.php
+++ b/src/TableComponent.php
@@ -6,7 +6,7 @@ use Livewire\Component;
 use Livewire\WithPagination;
 
 use Illuminate\Database\Eloquent\Builder;
-use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Str;
 
 use Exception;
 
@@ -14,10 +14,34 @@ abstract class TableComponent extends Component
 {
     use WithPagination;
 
+    // Config
     protected $paginationTheme = 'bootstrap';
     protected bool $searchable = true;
+    protected int $searchMinLength = 2;
+    protected int $searchDebounce = 250;
+    protected bool $showPageSizeSelect = true;
+    protected bool $showColumnSelect = true;
 
-    protected Model $model = null;
+    protected array $pageSizes = [10, 25, 50];
+
+    protected $model = null;
+
+    // Properties
+    public string $search = '';
+    public int $pageSize = 0;
+    public array $activeColumns = [];
+
+    public function __construct()
+    {
+        $this->pageSize = $this->pageSizes[0] ?? 0;
+    }
+
+    public function mount()
+    {
+        foreach($this->getColumns() as $column) {
+            $this->activeColumns[] = $column->name;
+        }
+    }
 
     protected function query() : Builder
     {
@@ -37,19 +61,44 @@ abstract class TableComponent extends Component
         return [];
     }
 
-    protected buildQuery() : Builder
+    protected function buildQuery() : Builder
     {
         $query = $this->query();
+
+        if($this->searchable && (Str::length($this->search) >= $this->searchMinLength)) {
+            $this->search($query, $this->search);
+        }
+
+        return $query;
+    }
+
+    protected function getColumns()
+    {
+        static $columns = null;
+
+        if($columns === null) {
+            $columns = collect($this->columns())->each(
+                fn($c) => $c->setTable($this)
+            );
+        }
+
+        return $columns;
     }
 
     public function render()
     {
-        $this->buildQuery()->paginate();
-        $data = $query->paginate($this->pageSize);
-        $columns = $this->columns();
+        $data = $this->buildQuery()->paginate($this->pageSize);
+        $allColumns = $this->getColumns();
+        $columns = $allColumns->filter(fn($c) => in_array($c->name,$this->activeColumns));
 
-        return view('laralight-tables::table', compact(
-            'data', 'columns'
+        return view('laralight-tables::table', [
+            'searchable' => $this->searchable,
+            'searchDebounce' => $this->searchDebounce,
+            'showPageSizeSelect' => $this->showPageSizeSelect,
+            'showColumnSelect' => $this->showColumnSelect,
+            'pageSizes' => $this->pageSizes,
+        ] + compact(
+            'data', 'allColumns', 'columns'
         ));
     }
 }
-- 
cgit v1.2.3