summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--resources/views/table.blade.php39
-rw-r--r--resources/views/toolbar.blade.php17
-rw-r--r--resources/views/toolbar/column-select.blade.php16
-rw-r--r--resources/views/toolbar/page-size.blade.php5
-rw-r--r--resources/views/toolbar/search.blade.php3
-rw-r--r--src/Columns/Column.php19
-rw-r--r--src/TableComponent.php78
-rw-r--r--src/Toolbar.php88
-rw-r--r--src/Toolbar/ColumnSelect.php17
-rw-r--r--src/Toolbar/Filter.php8
-rw-r--r--src/Toolbar/Item.php32
-rw-r--r--src/Toolbar/PageSize.php19
-rw-r--r--src/Toolbar/Search.php25
-rw-r--r--workbench/app/Livewire/CategoriesTable.php3
-rw-r--r--workbench/app/Livewire/OrdersTable.php3
-rw-r--r--workbench/app/Livewire/ProductsTable.php17
-rw-r--r--workbench/app/Livewire/Table.php16
-rw-r--r--workbench/resources/views/components/layouts/app.blade.php1
18 files changed, 324 insertions, 82 deletions
diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php
index 783255e..bcefe57 100644
--- a/resources/views/table.blade.php
+++ b/resources/views/table.blade.php
@@ -1,42 +1,5 @@
<div>
- @if($searchable || $showColumnSelect || $showPageSizeSelect)
- <div class="table-controls pb-2 d-flex justify-content-between align-items-center">
- <div>
- @if($searchable)
- <input class="form-control border-secondary" type="search"
- wire:model.live.debounce.{{ $searchDebounce}}="search"
- placeholder="{{ __('Search') }}..." />
- @endif
- </div>
- <div class="d-flex gap-3">
- @if($showColumnSelect)
- <div class="dropdown">
- <button type="button" class="btn btn-outline-secondary border-secondary"
- data-bs-toggle="dropdown" aria-expanded="false"
- data-bs-auto-close="outside">
- {{ __('Columns') }}
- </button>
- <div class="dropdown-menu p-4">
- @foreach($allColumns->filter(fn($c) => $c->getShowInSelect()) as $column)
- <label class="d-block">
- <input type="checkbox" wire:model.live="activeColumns"
- value="{{ $column->name }}" />
- {{ $column->getTitle() }}
- </label>
- @endforeach
- </div>
- </div>
- @endif
- @if($showPageSizeSelect)
- <select wire:model.live="pageSize" class="form-select border-secondary">
- @foreach($pageSizes as $size)
- <option value="{{ $size }}">{{ $size }}</option>
- @endforeach
- </select>
- @endif
- </div>
- </div>
- @endif
+ {{ $toolbar?->render() }}
<table class="table">
<colgroup>
@foreach($columns as $column)
diff --git a/resources/views/toolbar.blade.php b/resources/views/toolbar.blade.php
new file mode 100644
index 0000000..fee00b4
--- /dev/null
+++ b/resources/views/toolbar.blade.php
@@ -0,0 +1,17 @@
+<div class="table-controls pb-2 d-flex justify-content-between align-items-center">
+ <div class="d-flex gap-3">
+ @foreach ($startItems as $item)
+ {{ $item->render() }}
+ @endforeach
+ </div>
+ <div class="d-flex gap-3">
+ @foreach ($midItems as $item)
+ {{ $item->render() }}
+ @endforeach
+ </div>
+ <div class="d-flex gap-3">
+ @foreach ($endItems as $item)
+ {{ $item->render() }}
+ @endforeach
+ </div>
+</div>
diff --git a/resources/views/toolbar/column-select.blade.php b/resources/views/toolbar/column-select.blade.php
new file mode 100644
index 0000000..6fa7474
--- /dev/null
+++ b/resources/views/toolbar/column-select.blade.php
@@ -0,0 +1,16 @@
+<div class="dropdown">
+ <button type="button" class="btn btn-outline-secondary border-secondary"
+ data-bs-toggle="dropdown" aria-expanded="false"
+ data-bs-auto-close="outside">
+ {{ __('Columns') }}
+ </button>
+ <div class="dropdown-menu p-4">
+ @foreach($allColumns->filter(fn($c) => $c->getShowInSelect()) as $column)
+ <label class="d-block">
+ <input type="checkbox" wire:model.live="activeColumns"
+ value="{{ $column->name }}" />
+ {{ $column->getTitle() }}
+ </label>
+ @endforeach
+ </div>
+</div>
diff --git a/resources/views/toolbar/page-size.blade.php b/resources/views/toolbar/page-size.blade.php
new file mode 100644
index 0000000..cc35ff4
--- /dev/null
+++ b/resources/views/toolbar/page-size.blade.php
@@ -0,0 +1,5 @@
+<select wire:model.live="pageSize" class="form-select border-secondary">
+ @foreach($pageSizes as $size)
+ <option value="{{ $size }}">{{ $size }}</option>
+ @endforeach
+</select>
diff --git a/resources/views/toolbar/search.blade.php b/resources/views/toolbar/search.blade.php
new file mode 100644
index 0000000..04fd000
--- /dev/null
+++ b/resources/views/toolbar/search.blade.php
@@ -0,0 +1,3 @@
+<input class="form-control border-secondary" type="search"
+ wire:model.live.debounce.{{ $debounce }}="search"
+ placeholder="{{ __('Search') }}..." />
diff --git a/src/Columns/Column.php b/src/Columns/Column.php
index 94e386f..895708f 100644
--- a/src/Columns/Column.php
+++ b/src/Columns/Column.php
@@ -28,24 +28,24 @@ class Column {
$this->showInSelect = $this->title !== null;
}
- public static function make(string $name, ?string $title = null) : static
+ public static function make(string $name, ?string $title = null): static
{
return new static($name, $title);
}
- public function setTable(TableComponent $table) : void
+ public function setTable(TableComponent $table): void
{
$this->table = $table;
}
- public function getTitle()
+ public function getTitle(): string
{
return $this->title;
}
- private function defaultSlot(Model $row)
+ private function defaultSlot(Model $row): string
{
- return $row->{$this->name};
+ return (string) $row->{$this->name};
}
public function slot(callable $fn) : static
@@ -77,22 +77,23 @@ class Column {
return $this;
}
- public function showInSelect($show = true)
+ public function showInSelect($show = true): static
{
$this->showInSelect = $show;
+ return $this;
}
- public function getShowInSelect()
+ public function getShowInSelect(): bool
{
return $this->showInSelect;
}
- protected function getContent(Model $row)
+ protected function getContent(Model $row): string
{
return $this->slotFn?->call($this, $row, $this) ?? $this->defaultSlot($row);
}
- public function view(Model $row)
+ public function view(Model $row): HtmlString
{
$attributes = $this->tdAttributesFn?->call($this, $row) ?? [];
$attributes = (new ComponentAttributeBag($attributes))->toHtml();
diff --git a/src/TableComponent.php b/src/TableComponent.php
index b8fae6a..0a55d5e 100644
--- a/src/TableComponent.php
+++ b/src/TableComponent.php
@@ -9,6 +9,7 @@ use Livewire\Attributes\Url;
use Illuminate\Pagination\Paginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
+use Illuminate\Support\Collection;
use Exception;
@@ -18,35 +19,65 @@ abstract class TableComponent extends Component
// 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 array $pageSizes = [10, 25, 50];
-
protected $model = null;
+ protected int $defaultPageSize = 10;
// Properties
+ #[Url]
public string $search = '';
#[Url]
- public int $pageSize = 0;
+ public int $pageSize;
public array $activeColumns = [];
- public function __construct()
+ public function mount()
{
- $this->pageSize = $this->pageSizes[0] ?? 0;
+ $this->setDefaultActiveColumns();
+ $this->setDefaultPageSize();
}
- public function mount()
+ protected function setDefaultPageSize(): void
+ {
+ if (!isset($this->pageSize)) {
+ $this->pageSize = $this->defaultPageSize;
+ }
+ }
+
+ protected function setDefaultActiveColumns(): void
{
foreach($this->getColumns() as $column) {
$this->activeColumns[] = $column->name;
}
}
+ protected function isSearching(): bool
+ {
+ $search = $this->getToolbar()->getSearch();
+ return $search !== null && Str::length($this->search) >= $search->getMinLength();
+ }
+
+ public function updatedSearch(): void
+ {
+ if ($this->isSearching()) {
+ $this->resetPage();
+ }
+ }
+
+ protected function toolbar(): ?Toolbar
+ {
+ return null;
+ }
+
+ private ?Toolbar $toolbarCache;
+
+ protected function getToolbar(): ?Toolbar
+ {
+ if (!isset($this->_toolbar)) {
+ $this->toolbar = $this->toolbar();
+ }
+ return $this->toolbar;
+ }
+
protected function query() : Builder
{
if($this->model === null) {
@@ -60,25 +91,19 @@ abstract class TableComponent extends Component
protected function search(Builder $builder, string $search) : void {}
- protected function filters() : array
- {
- return [];
- }
-
protected function buildQuery() : Builder
{
$query = $this->query();
- if($this->searchable && (Str::length($this->search) >= $this->searchMinLength)) {
+ if ($this->isSearching()) {
$this->search($query, $this->search);
}
return $query;
}
- private $columnsCache = null;
-
- protected function getColumns()
+ private ?Collection $columnsCache = null;
+ public function getColumns()
{
if($this->columnsCache === null) {
$this->columnsCache = collect($this->columns())->each(
@@ -94,17 +119,12 @@ abstract class TableComponent extends Component
$data = $this->buildQuery()->paginate($this->pageSize);
$allColumns = $this->getColumns();
$columns = $allColumns->filter(fn($c) => in_array($c->name,$this->activeColumns));
+ $toolbar = $this->toolbar();
Paginator::defaultView('laralight-tables::pagination');
- return view('laralight-tables::table', [
- 'searchable' => $this->searchable,
- 'searchDebounce' => $this->searchDebounce,
- 'showPageSizeSelect' => $this->showPageSizeSelect,
- 'showColumnSelect' => $this->showColumnSelect,
- 'pageSizes' => $this->pageSizes,
- ] + compact(
- 'data', 'allColumns', 'columns'
+ return view('laralight-tables::table', compact(
+ 'data', 'allColumns', 'columns', 'toolbar',
));
}
}
diff --git a/src/Toolbar.php b/src/Toolbar.php
new file mode 100644
index 0000000..2db39f5
--- /dev/null
+++ b/src/Toolbar.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace Lightscale\LaralightTables;
+
+use Lightscale\LaralightTables\Toolbar\Item as ToolbarItem;
+use Lightscale\LaralightTables\Toolbar\Search as SearchItem;
+use Lightscale\LaralightTables\Toolbar\PageSize as PageSizeItem;
+use Lightscale\LaralightTables\Toolbar\Filter as FitlerItem;
+
+use Illuminate\View\View;
+use Illuminate\Support\Collection;
+
+class Toolbar
+{
+ protected ?SearchItem $searchItem = null;
+ protected ?PageSizeItem $pageSizeItem = null;
+
+ protected Collection $startItems;
+ protected Collection $midItems;
+ protected Collection $endItems;
+
+ public function __construct(
+ private TableComponent $table
+ )
+ {
+ $this->startItems = collect();
+ $this->midItems = collect();
+ $this->endItems = collect();
+ }
+
+ private function addItem(Collection $list, ToolbarItem $item): static
+ {
+ $item->setToolbar($this);
+
+ if ($item instanceof FilterItem) {
+ $this->filterItems->push($item);
+ }
+ else if ($item instanceof PageSizeItem) {
+ $this->pageSizeItem = $item;
+ }
+ else if ($item instanceof SearchItem) {
+ $this->searchItem = $item;
+ }
+
+ $list->push($item);
+ return $this;
+ }
+
+ public function addStartItem(ToolbarItem $item): static
+ {
+ return $this->addItem($this->startItems, $item);
+ }
+
+ public function addMidItem(ToolbarItem $item): static
+ {
+ return $this->addItem($this->midItems, $item);
+ }
+
+ public function addEndItem(ToolbarItem $item): static
+ {
+ return $this->addItem($this->endItems, $item);
+ }
+
+ public function getTable(): TableComponent
+ {
+ return $this->table;
+ }
+
+ public function getSearch(): ?SearchItem
+ {
+ return $this->searchItem;
+ }
+
+ public function getPageSize(): ?PageSizeItem
+ {
+ return $this->pageSizeItem;
+ }
+
+ public function render(): View
+ {
+ return view('laralight-tables::toolbar', [
+ 'startItems' => $this->startItems,
+ 'midItems' => $this->midItems,
+ 'endItems' => $this->endItems,
+ ]);
+ }
+
+}
diff --git a/src/Toolbar/ColumnSelect.php b/src/Toolbar/ColumnSelect.php
new file mode 100644
index 0000000..a70c49a
--- /dev/null
+++ b/src/Toolbar/ColumnSelect.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Lightscale\LaralightTables\Toolbar;
+
+use Illuminate\View\View;
+
+class ColumnSelect extends Item
+{
+ public function __construct() {}
+
+ public function render(): View
+ {
+ return view('laralight-tables::toolbar.column-select', [
+ 'allColumns' => $this->getTable()->getColumns()
+ ]);
+ }
+}
diff --git a/src/Toolbar/Filter.php b/src/Toolbar/Filter.php
new file mode 100644
index 0000000..ebda2c6
--- /dev/null
+++ b/src/Toolbar/Filter.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Lightscale\LaralightTables\Toolbar;
+
+abstract class Filter extends Item
+{
+
+}
diff --git a/src/Toolbar/Item.php b/src/Toolbar/Item.php
new file mode 100644
index 0000000..168f877
--- /dev/null
+++ b/src/Toolbar/Item.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Lightscale\LaralightTables\Toolbar;
+
+use Lightscale\LaralightTables\TableComponent;
+use Lightscale\LaralightTables\Toolbar;
+
+use Illuminate\View\View;
+use Illuminate\Support\HtmlString;
+
+abstract class Item
+{
+ private Toolbar $toolbar;
+
+ public function setToolbar(Toolbar $toolbar): void
+ {
+ $this->toolbar = $toolbar;
+ }
+
+ public function getToolbar(): Toolbar
+ {
+ return $this->toolbar;
+ }
+
+ public function getTable(): TableComponent
+ {
+ return $this->getToolbar()->getTable();
+ }
+
+ abstract public function render(): View|HtmlString|string|null;
+
+}
diff --git a/src/Toolbar/PageSize.php b/src/Toolbar/PageSize.php
new file mode 100644
index 0000000..9c2821a
--- /dev/null
+++ b/src/Toolbar/PageSize.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Lightscale\LaralightTables\Toolbar;
+
+use Illuminate\View\View;
+
+class PageSize extends Item
+{
+ public function __construct(
+ private array $pageSizes = [10, 25, 50],
+ ) {}
+
+ public function render(): View
+ {
+ return view('laralight-tables::toolbar.page-size', [
+ 'pageSizes' => $this->pageSizes,
+ ]);
+ }
+}
diff --git a/src/Toolbar/Search.php b/src/Toolbar/Search.php
new file mode 100644
index 0000000..0b0dc37
--- /dev/null
+++ b/src/Toolbar/Search.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Lightscale\LaralightTables\Toolbar;
+
+use Illuminate\View\View;
+
+class Search extends Item
+{
+ public function __construct(
+ protected int $debounce = 250,
+ protected int $minLength = 2,
+ ) {}
+
+ public function getMinLength(): int
+ {
+ return $this->minLength;
+ }
+
+ public function render(): View
+ {
+ return view('laralight-tables::toolbar.search', [
+ 'debounce' => $this->debounce,
+ ]);
+ }
+}
diff --git a/workbench/app/Livewire/CategoriesTable.php b/workbench/app/Livewire/CategoriesTable.php
index 92287b9..14cd5a8 100644
--- a/workbench/app/Livewire/CategoriesTable.php
+++ b/workbench/app/Livewire/CategoriesTable.php
@@ -4,10 +4,9 @@ namespace Workbench\App\Livewire;
use Workbench\App\Models\Product;
-use Lightscale\LaralightTables\TableComponent;
use Lightscale\LaralightTables\Columns\Column;
-class CategoriesTable extends TableComponent
+class CategoriesTable extends Table
{
protected $model = Product::class;
diff --git a/workbench/app/Livewire/OrdersTable.php b/workbench/app/Livewire/OrdersTable.php
index 97ef195..bb909a3 100644
--- a/workbench/app/Livewire/OrdersTable.php
+++ b/workbench/app/Livewire/OrdersTable.php
@@ -4,10 +4,9 @@ namespace Workbench\App\Livewire;
use Workbench\App\Models\Product;
-use Lightscale\LaralightTables\TableComponent;
use Lightscale\LaralightTables\Columns\Column;
-class OrdersTable extends TableComponent
+class OrdersTable extends Table
{
protected $model = Product::class;
diff --git a/workbench/app/Livewire/ProductsTable.php b/workbench/app/Livewire/ProductsTable.php
index 3b327d9..e3fefc3 100644
--- a/workbench/app/Livewire/ProductsTable.php
+++ b/workbench/app/Livewire/ProductsTable.php
@@ -4,15 +4,28 @@ namespace Workbench\App\Livewire;
use Workbench\App\Models\Product;
-use Lightscale\LaralightTables\TableComponent;
use Lightscale\LaralightTables\Columns\Column;
+use Lightscale\LaralightTables\Toolbar;
+use Lightscale\LaralightTables\Toolbar\Search;
+use Lightscale\LaralightTables\Toolbar\PageSize;
+use Lightscale\LaralightTables\Toolbar\ColumnSelect;
use Illuminate\Database\Eloquent\Builder;
-class ProductsTable extends TableComponent
+class ProductsTable extends Table
{
protected $model = Product::class;
+ public function toolbar(): Toolbar
+ {
+ return parent::toolbar()
+ ->addStartItem(new Search())
+ ->addEndItem(new PageSize())
+ ->addEndItem(new ColumnSelect());
+
+ return $toolbar;
+ }
+
protected function search(Builder $q, string $s): void
{
$q->search($s);
diff --git a/workbench/app/Livewire/Table.php b/workbench/app/Livewire/Table.php
new file mode 100644
index 0000000..5bffaed
--- /dev/null
+++ b/workbench/app/Livewire/Table.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Workbench\App\Livewire;
+
+use Lightscale\LaralightTables\TableComponent;
+use Lightscale\LaralightTables\Toolbar;
+
+abstract class Table extends TableComponent
+{
+
+ public function toolbar(): Toolbar
+ {
+ return new Toolbar($this);
+ }
+
+}
diff --git a/workbench/resources/views/components/layouts/app.blade.php b/workbench/resources/views/components/layouts/app.blade.php
index 68016cd..599f5c4 100644
--- a/workbench/resources/views/components/layouts/app.blade.php
+++ b/workbench/resources/views/components/layouts/app.blade.php
@@ -38,6 +38,7 @@
</div>
</div>
</header>
+
<div class="container">
{{ $slot }}
</div>