diff --git a/packages/tables/src/Concerns/CanSortRecords.php b/packages/tables/src/Concerns/CanSortRecords.php index 123afce35f..b21fb52d82 100644 --- a/packages/tables/src/Concerns/CanSortRecords.php +++ b/packages/tables/src/Concerns/CanSortRecords.php @@ -92,6 +92,8 @@ trait CanSortRecords $column->applySort($query, $sortDirection); + $this->applyDefaultKeySortToTableQuery($query); + return $query; } @@ -105,25 +107,52 @@ trait CanSortRecords ($sortColumn = $this->getTable()->getSortableVisibleColumn($defaultSort)) ) { $sortColumn->applySort($query, $sortDirection); - - return $query; - } - - if (is_string($defaultSort)) { - return $query->orderBy($defaultSort, $sortDirection); + } elseif (is_string($defaultSort)) { + $query->orderBy($defaultSort, $sortDirection); } if ($defaultSort instanceof Builder) { - return $defaultSort; + $query = $defaultSort; } if (filled($query->toBase()->orders)) { + $this->applyDefaultKeySortToTableQuery($query); + return $query; } return $query->orderBy($query->getModel()->getQualifiedKeyName()); } + protected function applyDefaultKeySortToTableQuery(Builder $query): Builder + { + if (! $this->getTable()->hasDefaultKeySort()) { + return $query; + } + + $qualifiedKeyName = $query->getModel()->getQualifiedKeyName(); + + foreach ($query->toBase()->orders ?? [] as $order) { /** @phpstan-ignore nullCoalesce.property */ + if (($order['column'] ?? null) === $qualifiedKeyName) { + return $query; + } + + if ( + is_string($order['column'] ?? null) && + str($order['column'] ?? null)->contains('.') && + str($order['column'] ?? null)->afterLast('.')->is( + str($qualifiedKeyName)->afterLast('.') + ) + ) { + return $query; + } + } + + $query->orderBy($qualifiedKeyName); + + return $query; + } + /** * @deprecated Override the `table()` method to configure the table. */ diff --git a/packages/tables/src/Table/Concerns/CanSortRecords.php b/packages/tables/src/Table/Concerns/CanSortRecords.php index 4c364c1896..798e555e61 100644 --- a/packages/tables/src/Table/Concerns/CanSortRecords.php +++ b/packages/tables/src/Table/Concerns/CanSortRecords.php @@ -18,6 +18,8 @@ trait CanSortRecords protected string | Htmlable | Closure | null $defaultSortOptionLabel = null; + protected bool | Closure $hasDefaultKeySort = false; + public function defaultSort(string | Closure | null $column, string | Closure | null $direction = 'asc'): static { $this->defaultSort = $column; @@ -40,6 +42,13 @@ trait CanSortRecords return $this; } + public function defaultKeySort(bool | Closure $condition = true): static + { + $this->hasDefaultKeySort = $condition; + + return $this; + } + public function getSortableVisibleColumn(string $name): ?Column { $column = $this->getColumn($name); @@ -121,4 +130,9 @@ trait CanSortRecords { return $this->evaluate($this->defaultSortOptionLabel) ?? '-'; } + + public function hasDefaultKeySort(): bool + { + return (bool) $this->evaluate($this->hasDefaultKeySort); + } } diff --git a/tests/src/Panels/Resources/Pages/ListRecordsTest.php b/tests/src/Panels/Resources/Pages/ListRecordsTest.php index c7ecc24b4e..26e743007d 100644 --- a/tests/src/Panels/Resources/Pages/ListRecordsTest.php +++ b/tests/src/Panels/Resources/Pages/ListRecordsTest.php @@ -65,6 +65,23 @@ it('can sort posts by author', function () { ->assertCanSeeTableRecords($posts->sortByDesc('author.name'), inOrder: true); }); +it('can sort posts with default sort key', function () { + + $faker = fake()->unique(); + $posts = Post::factory()->count(10)->state(function () use ($faker) { + return [ + 'id' => $faker->randomDigit(), + 'title' => 'Lorem Ipsum', + ]; + })->create(); + + livewire(ListPosts::class) + ->sortTable('title') + ->assertCanSeeTableRecords($posts->sortBy([['title', 'asc'], ['id', 'asc']]), inOrder: true) + ->sortTable('title', 'desc') + ->assertCanSeeTableRecords($posts->sortBy([['title', 'desc'], ['id', 'asc']]), inOrder: true); +}); + it('can search posts by title', function () { $posts = Post::factory()->count(10)->create();