From c29c690563593b54d070daa0fe9f3a4543539fb6 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 19 Feb 2025 15:39:02 +0000 Subject: [PATCH 01/42] :construction: Work in progress --- resources/views/group-table.blade.php | 220 ++++++++++++++++++++++ src/GroupsBuilder.php | 21 +++ src/Support/Concerns/WithGroupBuilder.php | 163 ++++++++++++++++ src/Support/Filters/SelectFilter.php | 8 +- 4 files changed, 408 insertions(+), 4 deletions(-) create mode 100644 resources/views/group-table.blade.php create mode 100755 src/GroupsBuilder.php create mode 100644 src/Support/Concerns/WithGroupBuilder.php diff --git a/resources/views/group-table.blade.php b/resources/views/group-table.blade.php new file mode 100644 index 0000000..ab96a29 --- /dev/null +++ b/resources/views/group-table.blade.php @@ -0,0 +1,220 @@ +
+ + @includeIf($this->headerView()) + + @if($this->availableColumns()) + @include('query-builder::report-editor') + @endif + + @if($this->columns()) + +
+ @if ($this->showQueryBuilder()) +
+ @include('query-builder::editor') + + @if(! $this->rows->count()) + + @endif +
+ @endif + + @if($this->isToolbarVisible()) +
+ +
+ @if($this->isSearchVisible()) + @include('query-builder::components.search') + @endif +
+ +
+ + @if($this->areActionsVisible()) + @include('query-builder::components.actions') + @endif + + @if($this->isColumnSelectorVisible()) + @include('query-builder::components.columns-selector') + @endif + + @if($this->isRowSelectorVisible()) + @include('query-builder::components.rows-selector') + @endif +
+
+ @endif + + @if($this->rows->count()) + +
+ + + + + @if($selectable) + + @endif + + @foreach ($this->columns() as $column) + @if(in_array($column->key, $displayColumns)) + + @endif + @endforeach + + + useLoadingIndicator()) wire:loading.delay.longest.class="{{ $this->loadingClass }}" + wire:target.except="exportReportBuilder, saveReportBuilder, loadReportBuilder" @endif> + @if($selectable && $selectPage && $this->rows->count() < $this->rows->total()) + + + + @endif + @foreach ($this->rows as $row) + + @if($this->rowPreview($row)) + {!! $this->injectRow($row) !!} + @endif + + isClickable()) + {!! $this->renderRowClick($row->id) !!} + @endif + wire:key="row-{{ $row->id }}" + @class([ + 'bg-white border-b', + 'hover:bg-gray-50 cursor-pointer' => $this->isClickable(), + ])> + + @if($selectable) + + @endif + + @foreach ($this->columns() as $column) + @if(in_array($column->key, $displayColumns)) + + @endif + @endforeach + + @endforeach + +
+
+ + +
+
isSortable()) wire:click="sort('{{ $column->key }}')" @endif> + @if ($column->showHeader) +
justify, + 'cursor-pointer' => $column->isSortable(), + ])> + {{ $column->label }} + + @if ($sortBy === $column->key) + @if ($sortDirection === 'asc') + + + + @else + + + + @endif + @endif + + @if($this->isSearchableIconVisible() && $column->isSearchable()) + + @endif + +
+ @endif +
+ @unless($selectAll) +
+ You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? + +
+ @else + You have selected all {{ $this->rows->total() }} {{ Str::of('row')->plural(count($selectedRows)) }}. + @endif +
+
+ + +
+
+
+ + +
+
+
+ + @if($this->isPaginated() && $this->rows->hasPages()) +
+ @if($this->scroll() === true) +
{{ $this->rows->links() }}
+ @else +
{{ $this->rows->links(data: ['scrollTo' => $this->scroll()]) }}
+ @endif +
+ @endif + @endif + + @if($this->useLoadingIndicator()) + {{-- Table loading spinners... --}} + @if($this->showOverlay) +
+
+ @endif + +
+ + + + +
+ @endif + + +
+ + @includeIf($this->footerView()) + @endif +
\ No newline at end of file diff --git a/src/GroupsBuilder.php b/src/GroupsBuilder.php new file mode 100755 index 0000000..0574add --- /dev/null +++ b/src/GroupsBuilder.php @@ -0,0 +1,21 @@ +findElementByKey($value, $targetValue); + if ($result !== null) { + return $result; + } + } + } + + return null; // Return null if no match is found + } + + public function updatedGroupBy(): void + { + $this->resetPage(); + $this->dispatch('refreshTable')->self(); + } + + public function availableColumns(): array + { + return []; + } + + public function configuredColumns(): array + { + $columns = []; + + foreach ($this->selectedColumns as $column) { + $columns[] = $this->findElementByKey($this->availableColumns(), $column); + } + + return $columns; + } + + public function buildColumns(): array + { + $columns = []; + + $counter = 0; + + foreach ($this->configuredColumns() as $column) { + $columnToAdd = match ($column['type'] ?? null) { + 'number' => Column::make($column['label'], $column['key'])->justify('right'), + 'boolean' => BooleanColumn::make($column['label'], $column['key'])->justify('center')->hideIf(false), + 'date' => DateColumn::make($column['label'], $column['key'])->format(config('settings.date.short-format'))->justify('right'), + default => Column::make($column['label'], $column['key']) + }; + + if ($column['view'] ?? false) { + $columnToAdd->component($column['view']); + } elseif ($counter === 0) { + $columnToAdd->component('columns.common.title'); + } + + if ($column['sortable'] ?? false) { + $columnToAdd->sortable(); + } + + if ($column['justify'] ?? false) { + $columnToAdd->justify($column['justify']); + } + + $columns[] = $columnToAdd; + + $counter++; + } + + return $columns; + } + + public function buildConditions(): array + { + $conditions = []; + + foreach ($this->configuredColumns() as $column) { + if ($column['skipCondition'] ?? false) { + continue; + } + + $conditions[] = match ($column['type'] ?? null) { + 'number' => NumberCondition::make($column['label'], $column['key']), + 'enum' => EnumCondition::make($column['label'], $column['key'], $column['options'] ?? []), + 'float' => FloatCondition::make($column['label'], $column['key']), + 'boolean' => BooleanCondition::make($column['label'], $column['key']), + 'date' => DateCondition::make($column['label'], $column['key']), + default => TextCondition::make($column['label'], $column['key']) + }; + + } + + return $conditions; + } + + public function removeCriteria($index): void + { + unset($this->criteria[$index]); + $this->criteria = array_values($this->criteria); + + $this->saveToSession(); + } + + public function resetReportBuilder(): void + { + $this->criteria = []; + $this->selectedColumns = []; + $this->saveToSession(); + } + + public function exportReportBuilder(): Response|BinaryFileResponse|null + { + return null; + } + + public function saveReportBuilder(): void + { + // + } + + public function loadReportBuilder(): void + { + // + } + + public function saveToSession(): void + { + // + } +} diff --git a/src/Support/Filters/SelectFilter.php b/src/Support/Filters/SelectFilter.php index 15e5473..f14f96e 100644 --- a/src/Support/Filters/SelectFilter.php +++ b/src/Support/Filters/SelectFilter.php @@ -4,20 +4,20 @@ class SelectFilter extends BaseFilter { - public $options = []; + public array $options = []; - public $optionsInGroups = []; + public array $optionsInGroups = []; public string $component = 'select'; private string $prompt = 'Select an option'; - public function options() + public function options(): array { return $this->options; } - public function optionsInGroups() + public function optionsInGroups(): array { return $this->optionsInGroups; } From 1e64a4fd6df8973801a645fc08205e6756632bf2 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 26 Feb 2025 13:57:48 +0000 Subject: [PATCH 02/42] :bug: fix sorting issue --- resources/views/group-table.blade.php | 2 +- resources/views/query-table.blade.php | 2 +- resources/views/report-table.blade.php | 2 +- resources/views/table.blade.php | 2 +- src/Support/Columns/BaseColumn.php | 6 ++++++ src/Support/Concerns/WithSorting.php | 24 +++++++++++++++++++++--- 6 files changed, 31 insertions(+), 7 deletions(-) diff --git a/resources/views/group-table.blade.php b/resources/views/group-table.blade.php index ab96a29..bb80dbd 100644 --- a/resources/views/group-table.blade.php +++ b/resources/views/group-table.blade.php @@ -78,7 +78,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">label }} @if ($sortBy === $column->key) - @if ($sortDirection === 'asc') + @if ($sortDirection === 'desc') diff --git a/resources/views/query-table.blade.php b/resources/views/query-table.blade.php index aa895c5..1f6a571 100644 --- a/resources/views/query-table.blade.php +++ b/resources/views/query-table.blade.php @@ -74,7 +74,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">label }} @if ($sortBy === $column->key) - @if ($sortDirection === 'asc') + @if ($sortDirection === 'desc') diff --git a/resources/views/report-table.blade.php b/resources/views/report-table.blade.php index ab96a29..bb80dbd 100644 --- a/resources/views/report-table.blade.php +++ b/resources/views/report-table.blade.php @@ -78,7 +78,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">label }} @if ($sortBy === $column->key) - @if ($sortDirection === 'asc') + @if ($sortDirection === 'desc') diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php index 89ba45c..6034fae 100644 --- a/resources/views/table.blade.php +++ b/resources/views/table.blade.php @@ -71,7 +71,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">label }} @if ($sortBy === $column->key) - @if ($sortDirection === 'asc') + @if ($sortDirection === 'desc') diff --git a/src/Support/Columns/BaseColumn.php b/src/Support/Columns/BaseColumn.php index 9d67641..a1c8b1d 100644 --- a/src/Support/Columns/BaseColumn.php +++ b/src/Support/Columns/BaseColumn.php @@ -126,4 +126,10 @@ public function getValue($row) return $value; } + + public function initialSort($direction = 'asc'): static + { + $this->setSort($this->key, $direction); + return $this; + } } diff --git a/src/Support/Concerns/WithSorting.php b/src/Support/Concerns/WithSorting.php index 4bd96d0..79530ec 100644 --- a/src/Support/Concerns/WithSorting.php +++ b/src/Support/Concerns/WithSorting.php @@ -10,7 +10,7 @@ trait WithSorting public string $sortDirection = 'asc'; - protected $sortable = false; + protected bool $sortable = false; public function isSortable(): bool { @@ -24,14 +24,32 @@ public function sortable(bool $sortable = true): static return $this; } + public function setSort($key, $direction = 'asc'): static + { + $this->sortBy = $key; + $this->sortDirection = $direction; + + return $this; + } + public function sort($key): void { $this->resetPage(); if ($this->sortBy === $key) { - $direction = $this->sortDirection === 'asc' ? 'desc' : 'asc'; - $this->sortDirection = $direction; + $direction = match ($this->sortDirection) { + 'asc' => 'desc', + 'desc' ,=> null, + default => 'asc', + }; + + if ($direction === null) { + $this->sortDirection = 'asc'; + $this->sortBy = ''; + } else { + $this->sortDirection = $direction; + } return; } From 518105c86b9fa4c33f72497a7362eab6fc66bd8e Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 26 Feb 2025 14:01:05 +0000 Subject: [PATCH 03/42] :bug: fix sorting issue --- src/Support/Columns/BaseColumn.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Support/Columns/BaseColumn.php b/src/Support/Columns/BaseColumn.php index a1c8b1d..9d67641 100644 --- a/src/Support/Columns/BaseColumn.php +++ b/src/Support/Columns/BaseColumn.php @@ -126,10 +126,4 @@ public function getValue($row) return $value; } - - public function initialSort($direction = 'asc'): static - { - $this->setSort($this->key, $direction); - return $this; - } } From db3ff365427de97c828a463f1abe95b3a1b5700a Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 26 Feb 2025 15:19:16 +0000 Subject: [PATCH 04/42] add code to sort a relationship --- src/Support/Concerns/WithSorting.php | 20 ++++++++++++++++++++ src/TableBuilder.php | 8 +++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Support/Concerns/WithSorting.php b/src/Support/Concerns/WithSorting.php index 79530ec..5ffd795 100644 --- a/src/Support/Concerns/WithSorting.php +++ b/src/Support/Concerns/WithSorting.php @@ -2,6 +2,8 @@ namespace ACTTraining\QueryBuilder\Support\Concerns; +use Illuminate\Database\Eloquent\Builder; + trait WithSorting { use WithPagination; @@ -56,4 +58,22 @@ public function sort($key): void $this->sortBy = $key; $this->sortDirection = 'asc'; } + + protected function orderByRelated(Builder $query, string $relationColumn, string $direction = 'asc'): Builder + { + [$relation, $column] = explode('.', $relationColumn, 2); + + $relatedModel = app($query->getModel()->$relation()->getRelated()); + + return $query->orderBy( + $relatedModel::select($column) + ->whereColumn( + $query->getModel()->$relation()->getForeignKeyName(), + "{$relatedModel->getTable()}.id" + ), + $direction + ); + } + + } diff --git a/src/TableBuilder.php b/src/TableBuilder.php index b3d33ea..3b62ebf 100755 --- a/src/TableBuilder.php +++ b/src/TableBuilder.php @@ -78,7 +78,13 @@ public function config(): void public function getRowsQueryProperty() { $query = $this->query()->when($this->sortBy !== '', function ($query) { - $query->orderBy($this->sortBy, $this->sortDirection); + if (Str::contains($this->sortBy, '.')) { + // If it's a relationship, use orderByRelated + $this->orderByRelated($query, $this->sortBy, $this->sortDirection); + } else { + // Otherwise, use regular orderBy + $query->orderBy($this->sortBy, $this->sortDirection); + } }); if ($this->searchBy && $this->searchBy !== '') { From 58e2b9e8cc12c7d646988334e55f975fd0ff2b0b Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 26 Feb 2025 15:30:52 +0000 Subject: [PATCH 05/42] :sparkles: allow for order by relationship --- src/Support/Concerns/WithSorting.php | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Support/Concerns/WithSorting.php b/src/Support/Concerns/WithSorting.php index 5ffd795..03e127d 100644 --- a/src/Support/Concerns/WithSorting.php +++ b/src/Support/Concerns/WithSorting.php @@ -3,6 +3,7 @@ namespace ACTTraining\QueryBuilder\Support\Concerns; use Illuminate\Database\Eloquent\Builder; +use InvalidArgumentException; trait WithSorting { @@ -42,7 +43,7 @@ public function sort($key): void $direction = match ($this->sortDirection) { 'asc' => 'desc', - 'desc' ,=> null, + 'desc' , => null, default => 'asc', }; @@ -52,6 +53,7 @@ public function sort($key): void } else { $this->sortDirection = $direction; } + return; } @@ -59,21 +61,25 @@ public function sort($key): void $this->sortDirection = 'asc'; } - protected function orderByRelated(Builder $query, string $relationColumn, string $direction = 'asc'): Builder + protected function orderByRelated(Builder $query, string $relationColumn, string $direction = 'asc'): void { + // Ensure only one dot is present + if (substr_count($relationColumn, '.') !== 1) { + throw new InvalidArgumentException("Invalid relation column: '{$relationColumn}'. Only single-level relationships are supported."); + } + [$relation, $column] = explode('.', $relationColumn, 2); - $relatedModel = app($query->getModel()->$relation()->getRelated()); + // Get the related model instance correctly + $relatedModel = $query->getModel()->{$relation}()->getRelated(); - return $query->orderBy( + $query->orderBy( $relatedModel::select($column) ->whereColumn( - $query->getModel()->$relation()->getForeignKeyName(), - "{$relatedModel->getTable()}.id" + "{$relatedModel->getTable()}.id", + $query->getModel()->{$relation}()->getForeignKeyName() ), $direction ); } - - } From f21bc540d309d8ff251b05149e52db205450cea6 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 26 Feb 2025 15:33:08 +0000 Subject: [PATCH 06/42] :sparkles: allow for order by relationship --- src/QueryBuilder.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index b7af190..0156ca2 100755 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -26,6 +26,7 @@ use Illuminate\Contracts\View\View; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Str; use Livewire\Component; /** @@ -119,6 +120,16 @@ public function getRowsQueryProperty() $query->orderBy($this->sortBy, $this->sortDirection); }); + $query->when($this->sortBy !== '', function ($query) { + if (Str::contains($this->sortBy, '.')) { + // If it's a relationship, use orderByRelated + $this->orderByRelated($query, $this->sortBy, $this->sortDirection); + } else { + // Otherwise, use regular orderBy + $query->orderBy($this->sortBy, $this->sortDirection); + } + }); + return $query; } From baa1b9016e590d352cfe5f40dd331811a675e587 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Mon, 3 Mar 2025 11:34:22 +0000 Subject: [PATCH 07/42] :construction: Work in progress --- src/Support/Concerns/WithFilters.php | 2 ++ src/Support/Concerns/WithSearch.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Support/Concerns/WithFilters.php b/src/Support/Concerns/WithFilters.php index bf06312..a34ebf3 100644 --- a/src/Support/Concerns/WithFilters.php +++ b/src/Support/Concerns/WithFilters.php @@ -3,11 +3,13 @@ namespace ACTTraining\QueryBuilder\Support\Concerns; use Livewire\Attributes\Session; +use Livewire\Attributes\Url; trait WithFilters { protected bool $displayFilters = false; + #[Url] public array $filterValues = []; public function areFiltersAvailable(): bool diff --git a/src/Support/Concerns/WithSearch.php b/src/Support/Concerns/WithSearch.php index b0555e0..b60f514 100644 --- a/src/Support/Concerns/WithSearch.php +++ b/src/Support/Concerns/WithSearch.php @@ -3,6 +3,7 @@ namespace ACTTraining\QueryBuilder\Support\Concerns; use Livewire\Attributes\Session; +use Livewire\Attributes\Url; trait WithSearch { @@ -12,6 +13,7 @@ trait WithSearch protected bool $displaySearchableIcon = true; + #[Url] public string $searchBy = ''; protected array $additionalSearchables = []; From 7ea68c38c82685985d2c3b6cd8fe77f08da2fb03 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Mon, 3 Mar 2025 11:36:38 +0000 Subject: [PATCH 08/42] :construction: Work in progress --- src/Support/Concerns/WithFilters.php | 1 - src/Support/Concerns/WithSearch.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Support/Concerns/WithFilters.php b/src/Support/Concerns/WithFilters.php index a34ebf3..23e9e5b 100644 --- a/src/Support/Concerns/WithFilters.php +++ b/src/Support/Concerns/WithFilters.php @@ -9,7 +9,6 @@ trait WithFilters { protected bool $displayFilters = false; - #[Url] public array $filterValues = []; public function areFiltersAvailable(): bool diff --git a/src/Support/Concerns/WithSearch.php b/src/Support/Concerns/WithSearch.php index b60f514..1682273 100644 --- a/src/Support/Concerns/WithSearch.php +++ b/src/Support/Concerns/WithSearch.php @@ -13,7 +13,6 @@ trait WithSearch protected bool $displaySearchableIcon = true; - #[Url] public string $searchBy = ''; protected array $additionalSearchables = []; From 71637e13228f90e4f80a1541a978467f925b745d Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Mon, 3 Mar 2025 11:36:53 +0000 Subject: [PATCH 09/42] :construction: Work in progress --- src/Support/Concerns/WithFilters.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Support/Concerns/WithFilters.php b/src/Support/Concerns/WithFilters.php index 23e9e5b..e30ae0a 100644 --- a/src/Support/Concerns/WithFilters.php +++ b/src/Support/Concerns/WithFilters.php @@ -2,9 +2,6 @@ namespace ACTTraining\QueryBuilder\Support\Concerns; -use Livewire\Attributes\Session; -use Livewire\Attributes\Url; - trait WithFilters { protected bool $displayFilters = false; From 23f71a5f901d8c853a8502ea7580d6ed27e23301 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Mon, 3 Mar 2025 11:50:05 +0000 Subject: [PATCH 10/42] :construction: Work in progress --- src/Support/Concerns/WithFilters.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Support/Concerns/WithFilters.php b/src/Support/Concerns/WithFilters.php index e30ae0a..5501608 100644 --- a/src/Support/Concerns/WithFilters.php +++ b/src/Support/Concerns/WithFilters.php @@ -2,10 +2,15 @@ namespace ACTTraining\QueryBuilder\Support\Concerns; +use Livewire\Attributes\Session; +use Livewire\Attributes\Url; + trait WithFilters { protected bool $displayFilters = false; + #[Session] + #[Url] public array $filterValues = []; public function areFiltersAvailable(): bool From f5d7d74025e73dad0e2c4b59bb95df7d5f072ab5 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Mon, 3 Mar 2025 11:51:43 +0000 Subject: [PATCH 11/42] :construction: Work in progress --- src/Support/Concerns/WithFilters.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Support/Concerns/WithFilters.php b/src/Support/Concerns/WithFilters.php index 5501608..23e9e5b 100644 --- a/src/Support/Concerns/WithFilters.php +++ b/src/Support/Concerns/WithFilters.php @@ -9,8 +9,6 @@ trait WithFilters { protected bool $displayFilters = false; - #[Session] - #[Url] public array $filterValues = []; public function areFiltersAvailable(): bool From 7c70dd60957c8f28ed3095ab3a1e1f97d5551c11 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Mon, 3 Mar 2025 11:53:00 +0000 Subject: [PATCH 12/42] :construction: Work in progress --- src/TableBuilder.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/TableBuilder.php b/src/TableBuilder.php index 3b62ebf..a3c2076 100755 --- a/src/TableBuilder.php +++ b/src/TableBuilder.php @@ -23,6 +23,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Str; +use Livewire\Attributes\Url; use Livewire\Component; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; @@ -53,6 +54,7 @@ abstract class TableBuilder extends Component abstract public function query(): Builder; + #[Url] protected function queryString(): array { return [ From a9ad26a2979db1f5e498e4b6faf6c96d2a289395 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Mon, 3 Mar 2025 12:35:53 +0000 Subject: [PATCH 13/42] :construction: Work in progress --- src/Support/Concerns/WithFilters.php | 2 +- src/TableBuilder.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Support/Concerns/WithFilters.php b/src/Support/Concerns/WithFilters.php index 23e9e5b..dedc2e0 100644 --- a/src/Support/Concerns/WithFilters.php +++ b/src/Support/Concerns/WithFilters.php @@ -2,13 +2,13 @@ namespace ACTTraining\QueryBuilder\Support\Concerns; -use Livewire\Attributes\Session; use Livewire\Attributes\Url; trait WithFilters { protected bool $displayFilters = false; + #[Url(as: 'f')] public array $filterValues = []; public function areFiltersAvailable(): bool diff --git a/src/TableBuilder.php b/src/TableBuilder.php index a3c2076..97ea940 100755 --- a/src/TableBuilder.php +++ b/src/TableBuilder.php @@ -54,7 +54,6 @@ abstract class TableBuilder extends Component abstract public function query(): Builder; - #[Url] protected function queryString(): array { return [ From 32cbe0c7d66a0764bee5e1475080c8e56157cf66 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Mon, 3 Mar 2025 12:36:21 +0000 Subject: [PATCH 14/42] :construction: Work in progress --- src/Support/Concerns/WithSearch.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Support/Concerns/WithSearch.php b/src/Support/Concerns/WithSearch.php index 1682273..8973877 100644 --- a/src/Support/Concerns/WithSearch.php +++ b/src/Support/Concerns/WithSearch.php @@ -13,6 +13,7 @@ trait WithSearch protected bool $displaySearchableIcon = true; + #[Url(as: 's')] public string $searchBy = ''; protected array $additionalSearchables = []; From 3d872cfe615c4c828ee41669f086725fa6b73447 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Tue, 11 Mar 2025 09:18:26 +0000 Subject: [PATCH 15/42] stop on checkbox click --- resources/views/table.blade.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php index 6034fae..b33f4dc 100644 --- a/resources/views/table.blade.php +++ b/resources/views/table.blade.php @@ -110,7 +110,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? - @@ -142,6 +142,7 @@ class="ml-2 text-blue-500 hover:text-blue-600">
From 8f963bc7785bb10cabe172ea59474c840eebd4ce Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Tue, 11 Mar 2025 11:40:57 +0000 Subject: [PATCH 16/42] :construction: Work in progress --- resources/views/query-table.blade.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/resources/views/query-table.blade.php b/resources/views/query-table.blade.php index 1f6a571..3aee177 100644 --- a/resources/views/query-table.blade.php +++ b/resources/views/query-table.blade.php @@ -1,6 +1,8 @@
- @includeIf($this->headerView()) +
+ @includeIf($this->headerView()) +
@if($this->columns()) @@ -210,6 +212,9 @@ class="flex justify-center items-center absolute inset-0"
+
@includeIf($this->footerView()) +
+ @endif
\ No newline at end of file From 75d4f44b184758e1803fd5f1e5bafe7d83af91bc Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Thu, 20 Mar 2025 11:43:48 +0000 Subject: [PATCH 17/42] :construction: Work in progress --- src/Support/Concerns/WithGroupBuilder.php | 2 ++ src/Support/Concerns/WithReportBuilder.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Support/Concerns/WithGroupBuilder.php b/src/Support/Concerns/WithGroupBuilder.php index 4865307..8e893ed 100644 --- a/src/Support/Concerns/WithGroupBuilder.php +++ b/src/Support/Concerns/WithGroupBuilder.php @@ -5,6 +5,7 @@ use ACTTraining\QueryBuilder\Support\Columns\BooleanColumn; use ACTTraining\QueryBuilder\Support\Columns\Column; use ACTTraining\QueryBuilder\Support\Columns\DateColumn; +use ACTTraining\QueryBuilder\Support\Columns\ViewColumn; use ACTTraining\QueryBuilder\Support\Conditions\BooleanCondition; use ACTTraining\QueryBuilder\Support\Conditions\DateCondition; use ACTTraining\QueryBuilder\Support\Conditions\EnumCondition; @@ -78,6 +79,7 @@ public function buildColumns(): array 'number' => Column::make($column['label'], $column['key'])->justify('right'), 'boolean' => BooleanColumn::make($column['label'], $column['key'])->justify('center')->hideIf(false), 'date' => DateColumn::make($column['label'], $column['key'])->format(config('settings.date.short-format'))->justify('right'), + 'view' => ViewColumn::make($column['label'])->justify($column['justify'] ?? 'left'), default => Column::make($column['label'], $column['key']) }; diff --git a/src/Support/Concerns/WithReportBuilder.php b/src/Support/Concerns/WithReportBuilder.php index ef384a9..e0ba88a 100644 --- a/src/Support/Concerns/WithReportBuilder.php +++ b/src/Support/Concerns/WithReportBuilder.php @@ -5,6 +5,7 @@ use ACTTraining\QueryBuilder\Support\Columns\BooleanColumn; use ACTTraining\QueryBuilder\Support\Columns\Column; use ACTTraining\QueryBuilder\Support\Columns\DateColumn; +use ACTTraining\QueryBuilder\Support\Columns\ViewColumn; use ACTTraining\QueryBuilder\Support\Conditions\BooleanCondition; use ACTTraining\QueryBuilder\Support\Conditions\DateCondition; use ACTTraining\QueryBuilder\Support\Conditions\EnumCondition; @@ -74,6 +75,7 @@ public function buildColumns(): array 'number' => Column::make($column['label'], $column['key'])->justify('right'), 'boolean' => BooleanColumn::make($column['label'], $column['key'])->justify('center')->hideIf(false), 'date' => DateColumn::make($column['label'], $column['key'])->format(config('settings.date.short-format'))->justify('right'), + 'view' => ViewColumn::make($column['label']), default => Column::make($column['label'], $column['key']) }; From 5edce29cb0a0021f5bdfa25769950ac76c551d36 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 26 Mar 2025 10:45:34 +0000 Subject: [PATCH 18/42] remove unused wire:model --- resources/views/components/actions.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/components/actions.blade.php b/resources/views/components/actions.blade.php index 52078b6..c8ee9c2 100644 --- a/resources/views/components/actions.blade.php +++ b/resources/views/components/actions.blade.php @@ -46,7 +46,7 @@ class="flex items-center gap-2 bg-white text-gray-600 text-sm border border-gray
Date: Wed, 26 Mar 2025 10:52:58 +0000 Subject: [PATCH 19/42] fix disabled issue --- resources/views/components/actions.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/components/actions.blade.php b/resources/views/components/actions.blade.php index c8ee9c2..8921b1d 100644 --- a/resources/views/components/actions.blade.php +++ b/resources/views/components/actions.blade.php @@ -70,7 +70,7 @@ class="flex items-center gap-1 w-full first-of-type:rounded-t-md last-of-type:ro @else + @else + + + + + - -
-
- @foreach ($this->actions() as $action) - @if($action->isStandalone()) - - @else - - @endif - @endforeach -
+ +
+
+ @foreach ($this->actions() as $action) + @if($action->isStandalone()) + + @else + + @endif + @endforeach +
+
- \ No newline at end of file +@endif \ No newline at end of file From 1d3f5d59d2ab69344f5e34940cfa002ec4859119 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Mon, 14 Apr 2025 16:41:04 +0200 Subject: [PATCH 24/42] improve wire key useage --- resources/views/query-table.blade.php | 4 ++-- resources/views/report-table.blade.php | 4 ++-- resources/views/table.blade.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/views/query-table.blade.php b/resources/views/query-table.blade.php index 3b95538..5ad0bf4 100644 --- a/resources/views/query-table.blade.php +++ b/resources/views/query-table.blade.php @@ -108,7 +108,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> useLoadingIndicator()) wire:loading.delay.longest.class="{{ $this->loadingClass }}" @endif> @if($selectable && $selectPage && $this->rows->count() < $this->rows->total()) - + @unless($selectAll)
@@ -134,7 +134,7 @@ class="ml-2 text-blue-500 hover:text-blue-600"> isClickable()) {!! $this->renderRowClick($row->id) !!} @endif - wire:key="row-{{ $row->id }}" + wire:key="{{ $this->identifier() }}-row-{{ $row->id }}" @class([ 'bg-white border-b', 'hover:bg-gray-50 cursor-pointer' => $this->isClickable(), diff --git a/resources/views/report-table.blade.php b/resources/views/report-table.blade.php index 3375eab..5f8f2a1 100644 --- a/resources/views/report-table.blade.php +++ b/resources/views/report-table.blade.php @@ -111,7 +111,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">useLoadingIndicator()) wire:loading.delay.longest.class="{{ $this->loadingClass }}" wire:target.except="exportReportBuilder, saveReportBuilder, loadReportBuilder" @endif> @if($selectable && $selectPage && $this->rows->count() < $this->rows->total()) - + @unless($selectAll)
@@ -137,7 +137,7 @@ class="ml-2 text-blue-500 hover:text-blue-600"> isClickable()) {!! $this->renderRowClick($row->id) !!} @endif - wire:key="row-{{ $row->id }}" + wire:key="{{ $this->identifier() }}-row-{{ $row->id }}" @class([ 'bg-white border-b', 'hover:bg-gray-50 cursor-pointer' => $this->isClickable(), diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php index bb88677..0df2677 100644 --- a/resources/views/table.blade.php +++ b/resources/views/table.blade.php @@ -104,7 +104,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> @if($this->areActionsVisible() && $selectable && $selectPage && $this->rows->count() < $this->rows->total()) - + @unless($selectAll)
@@ -132,7 +132,7 @@ class="ml-2 text-blue-500 hover:text-blue-600"> {!! $this->renderRowClick($row->id) !!} @endif - wire:key="row-{{ $row->id }}" + wire:key="{{ $this->identifier() }}-row-{{ $row->id }}" @class([ 'bg-white border-b group', 'hover:bg-gray-50 cursor-pointer' => $this->isClickable(), From 57db82dedc6123767b8ce41818a2f2fd5610b7f9 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 16 Apr 2025 14:32:17 +0200 Subject: [PATCH 25/42] Update DateCriteria.php --- src/Support/Criteria/DateCriteria.php | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/Support/Criteria/DateCriteria.php b/src/Support/Criteria/DateCriteria.php index 08f3f99..876675f 100644 --- a/src/Support/Criteria/DateCriteria.php +++ b/src/Support/Criteria/DateCriteria.php @@ -17,23 +17,8 @@ class DateCriteria extends BaseCriteria implements CriteriaInterface public function __construct(string $field, string|array $value, string $operator = '=') { - // Check if the date is in the 'd/m/Y' format and convert it to 'd-m-Y' - $date = \DateTime::createFromFormat('d/m/Y', $field); - - if ($date) { - // If the date is successfully parsed in the 'd/m/Y' format, convert it to 'd-m-Y' - $this->field = $date->format('d-m-Y'); - } else { - // If the date was not in 'd/m/Y', assume it's already in 'd-m-Y' format - // Optionally, you could check again if it's in the correct format - $date = \DateTime::createFromFormat('d-m-Y', $field); - - if ($date) { - $this->field = $field; // Already in 'd-m-Y', so just assign it - } - } - - $this->value = $value; + $this->field = $field; + $this->value = Carbon::parse($value)->startOfDay(); $this->operator = $operator; } From 6e9b36d50119346d894542923f912a86945cf75a Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 16 Apr 2025 14:44:18 +0200 Subject: [PATCH 26/42] :construction: wip --- src/Support/Criteria/DateCriteria.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Support/Criteria/DateCriteria.php b/src/Support/Criteria/DateCriteria.php index 876675f..7b84ada 100644 --- a/src/Support/Criteria/DateCriteria.php +++ b/src/Support/Criteria/DateCriteria.php @@ -18,7 +18,7 @@ class DateCriteria extends BaseCriteria implements CriteriaInterface public function __construct(string $field, string|array $value, string $operator = '=') { $this->field = $field; - $this->value = Carbon::parse($value)->startOfDay(); + $this->value = $value; $this->operator = $operator; } From 3f9d8923d401b5a992053d7fe06b49b4cd42ba82 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 16 Apr 2025 14:52:04 +0200 Subject: [PATCH 27/42] :construction: wip --- src/Support/Criteria/DateCriteria.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Support/Criteria/DateCriteria.php b/src/Support/Criteria/DateCriteria.php index 7b84ada..efdac97 100644 --- a/src/Support/Criteria/DateCriteria.php +++ b/src/Support/Criteria/DateCriteria.php @@ -18,7 +18,7 @@ class DateCriteria extends BaseCriteria implements CriteriaInterface public function __construct(string $field, string|array $value, string $operator = '=') { $this->field = $field; - $this->value = $value; + $this->value = Carbon::parse($value)->format('d-m-Y'); $this->operator = $operator; } From 2ec412059419b4130c8692c0940020ce46437fc1 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 16 Apr 2025 15:06:25 +0200 Subject: [PATCH 28/42] :construction: wip --- src/Support/Criteria/DateCriteria.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Support/Criteria/DateCriteria.php b/src/Support/Criteria/DateCriteria.php index efdac97..eecb224 100644 --- a/src/Support/Criteria/DateCriteria.php +++ b/src/Support/Criteria/DateCriteria.php @@ -18,7 +18,7 @@ class DateCriteria extends BaseCriteria implements CriteriaInterface public function __construct(string $field, string|array $value, string $operator = '=') { $this->field = $field; - $this->value = Carbon::parse($value)->format('d-m-Y'); + $this->value = Carbon::createFromFormat('Y-m-d', $value)->format('d-m-Y'); $this->operator = $operator; } From 1e578c23f9ffa3508064e589fa07bcb15d7d0bf8 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 30 Apr 2025 09:39:48 +0100 Subject: [PATCH 29/42] Add null filter --- src/Support/Filters/NullFilter.php | 45 ++++++++++++++++++++++++++++ src/TableBuilder.php | 47 ++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/Support/Filters/NullFilter.php diff --git a/src/Support/Filters/NullFilter.php b/src/Support/Filters/NullFilter.php new file mode 100644 index 0000000..a4c46f0 --- /dev/null +++ b/src/Support/Filters/NullFilter.php @@ -0,0 +1,45 @@ + 'Is set', + 'isNotSet' => 'Is not set', + ]; + } + + public function prompt(): string + { + return $this->prompt; + } + + public function apply($query, $value) + { + $key = $this->key(); + $isNegation = $value === 'isNotSet'; + + return $query->where(function ($q) use ($key, $isNegation) { + if ($isNegation) { + $q->whereNull($key) + ->orWhere($key, '') + ->orWhereJsonLength($key, 0); + } else { + $q->whereNotNull($key) + ->where($key, '!=', '') + ->whereJsonLength($key, '>', 0); + } + }); + } + + +} diff --git a/src/TableBuilder.php b/src/TableBuilder.php index 97ea940..40c9e34 100755 --- a/src/TableBuilder.php +++ b/src/TableBuilder.php @@ -17,6 +17,7 @@ use ACTTraining\QueryBuilder\Support\Concerns\WithSelecting; use ACTTraining\QueryBuilder\Support\Concerns\WithSorting; use ACTTraining\QueryBuilder\Support\Concerns\WithViews; +use ACTTraining\QueryBuilder\Support\Filters\NullFilter; use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\View; use Illuminate\Database\Eloquent\Builder; @@ -118,13 +119,55 @@ public function getRowsQueryProperty() $value = $dottedFilterValue[$filter->code()] ?? null; $query->when($value !== null, function ($query) use ($filter, $value) { + // Special case for NullFilter with isSet / isNotSet values + if ($filter instanceof NullFilter && in_array($value, ['isSet', 'isNotSet'])) { + $isNegation = $value === 'isNotSet'; + + if (Str::contains($filter->key(), '.')) { + $relation = Str::beforeLast($filter->key(), '.'); + $column = Str::afterLast($filter->key(), '.'); + + $query->whereHas($relation, function ($q) use ($column, $isNegation) { + $q->where(function ($q) use ($column, $isNegation) { + if ($isNegation) { + $q->whereNull($column) + ->orWhere($column, '') + ->orWhereJsonLength($column, 0); + } else { + $q->whereNotNull($column) + ->where($column, '!=', '') + ->whereJsonLength($column, '>', 0); + } + }); + }); + } else { + $query->where(function ($q) use ($filter, $isNegation) { + $key = $filter->key(); + + if ($isNegation) { + $q->whereNull($key) + ->orWhere($key, '') + ->orWhereJsonLength($key, 0); + } else { + $q->whereNotNull($key) + ->where($key, '!=', '') + ->whereJsonLength($key, '>', 0); + } + }); + } + + return; + } + + // Normal filters $value = $filter->parseValue($value); + if (Str::contains($filter->key(), '.')) { $relation = Str::beforeLast($filter->key(), '.'); $column = Str::afterLast($filter->key(), '.'); - $query->whereHas($relation, function ($query) use ($filter, $value, $column) { - $query->where($column, $filter->operator(), $value); + $query->whereHas($relation, function ($q) use ($filter, $value, $column) { + $q->where($column, $filter->operator(), $value); }); } else { $query->where($filter->key(), $filter->operator(), $value); From a1df4a43c6f08af9db329753bfc7c578dc8ba2c2 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 30 Apr 2025 09:43:27 +0100 Subject: [PATCH 30/42] Add null filter --- resources/views/filters/null.blade.php | 18 ++++++++++++++++++ src/Support/Filters/NullFilter.php | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 resources/views/filters/null.blade.php diff --git a/resources/views/filters/null.blade.php b/resources/views/filters/null.blade.php new file mode 100644 index 0000000..61c0312 --- /dev/null +++ b/resources/views/filters/null.blade.php @@ -0,0 +1,18 @@ +
+ @if($filter->options()) +
+ + +
+ @endif + @if(! $filter->options()) +
No options set.
+ @endif +
\ No newline at end of file diff --git a/src/Support/Filters/NullFilter.php b/src/Support/Filters/NullFilter.php index a4c46f0..4208b04 100644 --- a/src/Support/Filters/NullFilter.php +++ b/src/Support/Filters/NullFilter.php @@ -6,7 +6,7 @@ class NullFilter extends BaseFilter { public string $operator = ''; - public string $component = 'select'; + public string $component = 'null'; private string $prompt = 'Select an option'; From 11a8df26aa09a6258d684b6d8cac877316ab4eec Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 30 Apr 2025 16:12:40 +0100 Subject: [PATCH 31/42] add null condition --- src/Support/Concerns/WithReportBuilder.php | 2 ++ src/Support/Conditions/NullCondition.php | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/Support/Conditions/NullCondition.php diff --git a/src/Support/Concerns/WithReportBuilder.php b/src/Support/Concerns/WithReportBuilder.php index e0ba88a..d0dbbfb 100644 --- a/src/Support/Concerns/WithReportBuilder.php +++ b/src/Support/Concerns/WithReportBuilder.php @@ -10,6 +10,7 @@ use ACTTraining\QueryBuilder\Support\Conditions\DateCondition; use ACTTraining\QueryBuilder\Support\Conditions\EnumCondition; use ACTTraining\QueryBuilder\Support\Conditions\FloatCondition; +use ACTTraining\QueryBuilder\Support\Conditions\NullCondition; use ACTTraining\QueryBuilder\Support\Conditions\NumberCondition; use ACTTraining\QueryBuilder\Support\Conditions\TextCondition; use Illuminate\Http\Response; @@ -116,6 +117,7 @@ public function buildConditions(): array 'float' => FloatCondition::make($column['label'], $column['key']), 'boolean' => BooleanCondition::make($column['label'], $column['key']), 'date' => DateCondition::make($column['label'], $column['key']), + 'null' => NullCondition::make($column['label'], $column['key']), default => TextCondition::make($column['label'], $column['key']) }; diff --git a/src/Support/Conditions/NullCondition.php b/src/Support/Conditions/NullCondition.php new file mode 100644 index 0000000..8c60464 --- /dev/null +++ b/src/Support/Conditions/NullCondition.php @@ -0,0 +1,16 @@ + 'is set', + 'is_not_set' => 'is not set', + ]; + } +} From 7a93e743b8476eb84d0a70fbd986ed50f2080c5b Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 30 Apr 2025 16:22:28 +0100 Subject: [PATCH 32/42] add null condition --- src/Support/Conditions/NullCondition.php | 2 +- src/Support/Criteria/NullCriteria.php | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Support/Conditions/NullCondition.php b/src/Support/Conditions/NullCondition.php index 8c60464..3a46202 100644 --- a/src/Support/Conditions/NullCondition.php +++ b/src/Support/Conditions/NullCondition.php @@ -4,7 +4,7 @@ class NullCondition extends BaseCondition { - public string $inputType = 'number'; + public string $inputType = 'enum'; public function operations(): array { diff --git a/src/Support/Criteria/NullCriteria.php b/src/Support/Criteria/NullCriteria.php index 5140532..0544301 100644 --- a/src/Support/Criteria/NullCriteria.php +++ b/src/Support/Criteria/NullCriteria.php @@ -8,9 +8,9 @@ class NullCriteria extends BaseCriteria implements CriteriaInterface { public string $inputType = 'boolean'; - private $field; + private string $field; - private $operation; + private string $operation; public function __construct(string $field, string $operation) { @@ -22,9 +22,13 @@ public function apply($query): void { $this->applyWhereCondition($query, $this->field, function ($query, $field) { if ($this->operation === 'is_not_set') { - $query->whereNull($field); + $query->whereNull($field) + ->orWhere($field, '') + ->orWhereJsonLength($field, 0); } else { - $query->whereNotNull($field); + $query->whereNotNull($field) + ->where($field, '!=', '') + ->whereJsonLength($field, '>', 0); } }); } From 3ddb6ff1c27baddb1f307530e5e3ab88dae75c1d Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 30 Apr 2025 16:26:05 +0100 Subject: [PATCH 33/42] add null condition --- src/Support/Criteria/NullCriteria.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Support/Criteria/NullCriteria.php b/src/Support/Criteria/NullCriteria.php index 0544301..54a6b0f 100644 --- a/src/Support/Criteria/NullCriteria.php +++ b/src/Support/Criteria/NullCriteria.php @@ -24,11 +24,11 @@ public function apply($query): void if ($this->operation === 'is_not_set') { $query->whereNull($field) ->orWhere($field, '') - ->orWhereJsonLength($field, 0); + ->orWhereEmpty($field); } else { $query->whereNotNull($field) ->where($field, '!=', '') - ->whereJsonLength($field, '>', 0); + ->orWhereNotEmpty($field); } }); } From 7f393b3bf10c362748fb020e57a2cc098048dd1a Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 30 Apr 2025 16:28:31 +0100 Subject: [PATCH 34/42] add null condition --- src/Support/Criteria/NullCriteria.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Support/Criteria/NullCriteria.php b/src/Support/Criteria/NullCriteria.php index 54a6b0f..a9d5c8f 100644 --- a/src/Support/Criteria/NullCriteria.php +++ b/src/Support/Criteria/NullCriteria.php @@ -27,7 +27,7 @@ public function apply($query): void ->orWhereEmpty($field); } else { $query->whereNotNull($field) - ->where($field, '!=', '') + ->orWhere($field, '!=', '') ->orWhereNotEmpty($field); } }); From 1a2aaf10fa4c9fe5d152c764fcf845e941d4a936 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 30 Apr 2025 16:32:16 +0100 Subject: [PATCH 35/42] add null condition --- src/Support/Criteria/NullCriteria.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Support/Criteria/NullCriteria.php b/src/Support/Criteria/NullCriteria.php index a9d5c8f..0faa6d6 100644 --- a/src/Support/Criteria/NullCriteria.php +++ b/src/Support/Criteria/NullCriteria.php @@ -23,12 +23,10 @@ public function apply($query): void $this->applyWhereCondition($query, $this->field, function ($query, $field) { if ($this->operation === 'is_not_set') { $query->whereNull($field) - ->orWhere($field, '') - ->orWhereEmpty($field); + ->orWhere($field, ''); } else { $query->whereNotNull($field) - ->orWhere($field, '!=', '') - ->orWhereNotEmpty($field); + ->orWhere($field, '!=', ''); } }); } From e5126bb0042ee2f7c4bbb50cf618aec9b5229f29 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Tue, 24 Jun 2025 15:53:17 +0100 Subject: [PATCH 36/42] :construction: Work in progress --- resources/views/group-table.blade.php | 2 +- resources/views/query-table.blade.php | 8 ++++---- resources/views/report-table.blade.php | 2 +- resources/views/table.blade.php | 2 +- src/Support/Concerns/WithSelecting.php | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/resources/views/group-table.blade.php b/resources/views/group-table.blade.php index 3375eab..0348c07 100644 --- a/resources/views/group-table.blade.php +++ b/resources/views/group-table.blade.php @@ -117,7 +117,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? - diff --git a/resources/views/query-table.blade.php b/resources/views/query-table.blade.php index 5ad0bf4..2b8b780 100644 --- a/resources/views/query-table.blade.php +++ b/resources/views/query-table.blade.php @@ -114,7 +114,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? - @@ -212,9 +212,9 @@ class="flex justify-center items-center absolute inset-0"
-
- @includeIf($this->footerView()) -
+
+ @includeIf($this->footerView()) +
@endif
\ No newline at end of file diff --git a/resources/views/report-table.blade.php b/resources/views/report-table.blade.php index 5f8f2a1..7fee259 100644 --- a/resources/views/report-table.blade.php +++ b/resources/views/report-table.blade.php @@ -117,7 +117,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? - diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php index 0df2677..05fbd4d 100644 --- a/resources/views/table.blade.php +++ b/resources/views/table.blade.php @@ -110,7 +110,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? - diff --git a/src/Support/Concerns/WithSelecting.php b/src/Support/Concerns/WithSelecting.php index c121bb7..2e53866 100644 --- a/src/Support/Concerns/WithSelecting.php +++ b/src/Support/Concerns/WithSelecting.php @@ -33,7 +33,7 @@ public function updatedSelectedRows(): void $this->dispatch('refreshTable')->self(); } - public function selectAll(): void + public function toggleSelectAll(): void { $this->selectAll = ! $this->selectAll; $this->dispatch('refreshTable')->self(); From 977052055e8432f83a1de5b8034f79b7789f0a89 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Tue, 24 Jun 2025 16:10:12 +0100 Subject: [PATCH 37/42] fix for select all --- resources/views/group-table.blade.php | 2 +- resources/views/query-table.blade.php | 2 +- resources/views/report-table.blade.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/views/group-table.blade.php b/resources/views/group-table.blade.php index 0348c07..5959b7c 100644 --- a/resources/views/group-table.blade.php +++ b/resources/views/group-table.blade.php @@ -117,7 +117,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? - diff --git a/resources/views/query-table.blade.php b/resources/views/query-table.blade.php index 2b8b780..2bfe6e2 100644 --- a/resources/views/query-table.blade.php +++ b/resources/views/query-table.blade.php @@ -114,7 +114,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? - diff --git a/resources/views/report-table.blade.php b/resources/views/report-table.blade.php index 7fee259..f8eda59 100644 --- a/resources/views/report-table.blade.php +++ b/resources/views/report-table.blade.php @@ -117,7 +117,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? - From 9d6243ae5d299cf67913693a7a6b7eab673fa0b8 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Tue, 24 Jun 2025 16:22:02 +0100 Subject: [PATCH 38/42] fix for select all --- resources/views/table.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php index 05fbd4d..3932cab 100644 --- a/resources/views/table.blade.php +++ b/resources/views/table.blade.php @@ -110,7 +110,7 @@ class="sr-only ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"> You have selected {{ count($selectedRows) }} {{ Str::of('row')->plural(count($selectedRows)) }}. Do you want to select all {{ $this->rows->total() }}? - From 36d26f7b3f9b3cf219ddaa5a715d4db8b4848dd7 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Wed, 25 Jun 2025 08:00:09 +0100 Subject: [PATCH 39/42] fix for select all --- src/Support/Concerns/WithSelecting.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Support/Concerns/WithSelecting.php b/src/Support/Concerns/WithSelecting.php index 2e53866..27ba9c0 100644 --- a/src/Support/Concerns/WithSelecting.php +++ b/src/Support/Concerns/WithSelecting.php @@ -36,6 +36,10 @@ public function updatedSelectedRows(): void public function toggleSelectAll(): void { $this->selectAll = ! $this->selectAll; + + $this->selectedRows = $this->selectAll + ? $this->rows->pluck('id')->toArray() + : []; $this->dispatch('refreshTable')->self(); } From 1fe5e679d75a9e5b9caba40747d075af5302cea1 Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Thu, 26 Jun 2025 10:09:12 +0100 Subject: [PATCH 40/42] fix for select all --- src/Support/Concerns/WithSelecting.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Support/Concerns/WithSelecting.php b/src/Support/Concerns/WithSelecting.php index 27ba9c0..e632d96 100644 --- a/src/Support/Concerns/WithSelecting.php +++ b/src/Support/Concerns/WithSelecting.php @@ -38,7 +38,7 @@ public function toggleSelectAll(): void $this->selectAll = ! $this->selectAll; $this->selectedRows = $this->selectAll - ? $this->rows->pluck('id')->toArray() + ? $this->rowsQuery->pluck('id')->toArray() : []; $this->dispatch('refreshTable')->self(); } From 1e91d9b7cc61f8d5191ae3129ccbcbcb8b3a361b Mon Sep 17 00:00:00 2001 From: Simon Barrett Date: Fri, 29 Aug 2025 09:44:22 +0100 Subject: [PATCH 41/42] :bug: fix for null column --- src/Support/Concerns/WithReportBuilder.php | 61 ++++++++++++++-------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/src/Support/Concerns/WithReportBuilder.php b/src/Support/Concerns/WithReportBuilder.php index d0dbbfb..de65e80 100644 --- a/src/Support/Concerns/WithReportBuilder.php +++ b/src/Support/Concerns/WithReportBuilder.php @@ -68,34 +68,41 @@ public function configuredColumns(): array public function buildColumns(): array { $columns = []; - $counter = 0; - foreach ($this->configuredColumns() as $column) { - $columnToAdd = match ($column['type'] ?? null) { - 'number' => Column::make($column['label'], $column['key'])->justify('right'), + foreach (($this->configuredColumns() ?? []) as $column) { + // Skip nulls/invalid items early + if (!is_array($column) || !isset($column['label'], $column['key'])) { + continue; + } + + $type = $column['type'] ?? null; + + $columnToAdd = match ($type) { + 'number' => Column::make($column['label'], $column['key'])->justify('right'), 'boolean' => BooleanColumn::make($column['label'], $column['key'])->justify('center')->hideIf(false), - 'date' => DateColumn::make($column['label'], $column['key'])->format(config('settings.date.short-format'))->justify('right'), - 'view' => ViewColumn::make($column['label']), - default => Column::make($column['label'], $column['key']) + 'date' => DateColumn::make($column['label'], $column['key']) + ->format(config('settings.date.short-format')) + ->justify('right'), + 'view' => ViewColumn::make($column['label']), + default => Column::make($column['label'], $column['key']), }; - if ($column['view'] ?? false) { + if (!empty($column['view'])) { $columnToAdd->component($column['view']); } elseif ($counter === 0) { $columnToAdd->component('columns.common.title'); } - if ($column['sortable'] ?? false) { + if (!empty($column['sortable'])) { $columnToAdd->sortable(); } - if ($column['justify'] ?? false) { + if (!empty($column['justify'])) { $columnToAdd->justify($column['justify']); } $columns[] = $columnToAdd; - $counter++; } @@ -106,21 +113,33 @@ public function buildConditions(): array { $conditions = []; - foreach ($this->configuredColumns() as $column) { - if ($column['skipCondition'] ?? false) { + foreach (($this->configuredColumns() ?? []) as $column) { + // Skip nulls/garbage early + if (!is_array($column) || !isset($column['label'], $column['key'])) { continue; } - $conditions[] = match ($column['type'] ?? null) { - 'number' => NumberCondition::make($column['label'], $column['key']), - 'enum' => EnumCondition::make($column['label'], $column['key'], $column['options'] ?? []), - 'float' => FloatCondition::make($column['label'], $column['key']), + if (!empty($column['skipCondition'])) { + continue; + } + + $type = $column['type'] ?? null; + + // Normalise enum options + $options = $column['options'] ?? []; + if (!is_array($options)) { + $options = []; + } + + $conditions[] = match ($type) { + 'number' => NumberCondition::make($column['label'], $column['key']), + 'enum' => EnumCondition::make($column['label'], $column['key'], $options), + 'float' => FloatCondition::make($column['label'], $column['key']), 'boolean' => BooleanCondition::make($column['label'], $column['key']), - 'date' => DateCondition::make($column['label'], $column['key']), - 'null' => NullCondition::make($column['label'], $column['key']), - default => TextCondition::make($column['label'], $column['key']) + 'date' => DateCondition::make($column['label'], $column['key']), + 'null' => NullCondition::make($column['label'], $column['key']), + default => TextCondition::make($column['label'], $column['key']), }; - } return $conditions; From 586fd4055b2cc6ee2f8187f8febda3852d77c9a7 Mon Sep 17 00:00:00 2001 From: SimonBarrettACT Date: Thu, 20 Nov 2025 15:22:44 +0000 Subject: [PATCH 42/42] Fix styling --- src/Support/Concerns/WithGroupBuilder.php | 1 + src/Support/Concerns/WithPagination.php | 2 +- src/Support/Concerns/WithReportBuilder.php | 34 +++++++++++----------- src/Support/Concerns/WithSearch.php | 1 - src/Support/Criteria/DateCriteria.php | 2 +- src/Support/Filters/NullFilter.php | 2 -- src/TableBuilder.php | 1 - 7 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/Support/Concerns/WithGroupBuilder.php b/src/Support/Concerns/WithGroupBuilder.php index 8e893ed..dfc60a4 100644 --- a/src/Support/Concerns/WithGroupBuilder.php +++ b/src/Support/Concerns/WithGroupBuilder.php @@ -19,6 +19,7 @@ trait WithGroupBuilder { public string $aggregateColumn = 'id'; // Default column to aggregate + public string $aggregateFunction = 'COUNT'; // Default function (COUNT, SUM, AVG) // Default group by column diff --git a/src/Support/Concerns/WithPagination.php b/src/Support/Concerns/WithPagination.php index 825dc9b..2f83ae0 100644 --- a/src/Support/Concerns/WithPagination.php +++ b/src/Support/Concerns/WithPagination.php @@ -12,7 +12,7 @@ trait WithPagination private bool $paginate = true; - private bool|string $scrollTo = false; //false disables scroll on pagination + private bool|string $scrollTo = false; // false disables scroll on pagination public function usePagination($usePagination = true): static { diff --git a/src/Support/Concerns/WithReportBuilder.php b/src/Support/Concerns/WithReportBuilder.php index de65e80..6b465c3 100644 --- a/src/Support/Concerns/WithReportBuilder.php +++ b/src/Support/Concerns/WithReportBuilder.php @@ -72,33 +72,33 @@ public function buildColumns(): array foreach (($this->configuredColumns() ?? []) as $column) { // Skip nulls/invalid items early - if (!is_array($column) || !isset($column['label'], $column['key'])) { + if (! is_array($column) || ! isset($column['label'], $column['key'])) { continue; } $type = $column['type'] ?? null; $columnToAdd = match ($type) { - 'number' => Column::make($column['label'], $column['key'])->justify('right'), + 'number' => Column::make($column['label'], $column['key'])->justify('right'), 'boolean' => BooleanColumn::make($column['label'], $column['key'])->justify('center')->hideIf(false), - 'date' => DateColumn::make($column['label'], $column['key']) + 'date' => DateColumn::make($column['label'], $column['key']) ->format(config('settings.date.short-format')) ->justify('right'), - 'view' => ViewColumn::make($column['label']), - default => Column::make($column['label'], $column['key']), + 'view' => ViewColumn::make($column['label']), + default => Column::make($column['label'], $column['key']), }; - if (!empty($column['view'])) { + if (! empty($column['view'])) { $columnToAdd->component($column['view']); } elseif ($counter === 0) { $columnToAdd->component('columns.common.title'); } - if (!empty($column['sortable'])) { + if (! empty($column['sortable'])) { $columnToAdd->sortable(); } - if (!empty($column['justify'])) { + if (! empty($column['justify'])) { $columnToAdd->justify($column['justify']); } @@ -115,11 +115,11 @@ public function buildConditions(): array foreach (($this->configuredColumns() ?? []) as $column) { // Skip nulls/garbage early - if (!is_array($column) || !isset($column['label'], $column['key'])) { + if (! is_array($column) || ! isset($column['label'], $column['key'])) { continue; } - if (!empty($column['skipCondition'])) { + if (! empty($column['skipCondition'])) { continue; } @@ -127,18 +127,18 @@ public function buildConditions(): array // Normalise enum options $options = $column['options'] ?? []; - if (!is_array($options)) { + if (! is_array($options)) { $options = []; } $conditions[] = match ($type) { - 'number' => NumberCondition::make($column['label'], $column['key']), - 'enum' => EnumCondition::make($column['label'], $column['key'], $options), - 'float' => FloatCondition::make($column['label'], $column['key']), + 'number' => NumberCondition::make($column['label'], $column['key']), + 'enum' => EnumCondition::make($column['label'], $column['key'], $options), + 'float' => FloatCondition::make($column['label'], $column['key']), 'boolean' => BooleanCondition::make($column['label'], $column['key']), - 'date' => DateCondition::make($column['label'], $column['key']), - 'null' => NullCondition::make($column['label'], $column['key']), - default => TextCondition::make($column['label'], $column['key']), + 'date' => DateCondition::make($column['label'], $column['key']), + 'null' => NullCondition::make($column['label'], $column['key']), + default => TextCondition::make($column['label'], $column['key']), }; } diff --git a/src/Support/Concerns/WithSearch.php b/src/Support/Concerns/WithSearch.php index 8973877..10791da 100644 --- a/src/Support/Concerns/WithSearch.php +++ b/src/Support/Concerns/WithSearch.php @@ -2,7 +2,6 @@ namespace ACTTraining\QueryBuilder\Support\Concerns; -use Livewire\Attributes\Session; use Livewire\Attributes\Url; trait WithSearch diff --git a/src/Support/Criteria/DateCriteria.php b/src/Support/Criteria/DateCriteria.php index eecb224..dbe3fbb 100644 --- a/src/Support/Criteria/DateCriteria.php +++ b/src/Support/Criteria/DateCriteria.php @@ -17,7 +17,7 @@ class DateCriteria extends BaseCriteria implements CriteriaInterface public function __construct(string $field, string|array $value, string $operator = '=') { - $this->field = $field; + $this->field = $field; $this->value = Carbon::createFromFormat('Y-m-d', $value)->format('d-m-Y'); $this->operator = $operator; } diff --git a/src/Support/Filters/NullFilter.php b/src/Support/Filters/NullFilter.php index 4208b04..15f2998 100644 --- a/src/Support/Filters/NullFilter.php +++ b/src/Support/Filters/NullFilter.php @@ -40,6 +40,4 @@ public function apply($query, $value) } }); } - - } diff --git a/src/TableBuilder.php b/src/TableBuilder.php index 40c9e34..6b5cf8b 100755 --- a/src/TableBuilder.php +++ b/src/TableBuilder.php @@ -24,7 +24,6 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Str; -use Livewire\Attributes\Url; use Livewire\Component; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface;