Skip to content

Commit

Permalink
Fixed reordering feature (#108)
Browse files Browse the repository at this point in the history
* Fixed [reordering feature](/README.md#allow-columns-to-be-reordered-from-drag-and-drop-action) that was not compatible with packages like [spatie/eloquent-sortable](https://github.com/spatie/eloquent-sortable) (which authorize several model entries to have the same position when the sorting does group models from a query => [example](https://github.com/spatie/eloquent-sortable#grouping))
  • Loading branch information
Okipa authored Oct 26, 2022
1 parent fe6a3dc commit 0544fb4
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 59 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [5.1.1](https://github.com/Okipa/laravel-table/compare/5.1.0...5.1.1)

2022-10-26

* Fixed [reordering feature](/README.md#allow-columns-to-be-reordered-from-drag-and-drop-action) that was not compatible with packages like [spatie/eloquent-sortable](https://github.com/spatie/eloquent-sortable) (which authorize several model entries to have the same position when the sorting does group models from a query => [example](https://github.com/spatie/eloquent-sortable#grouping))

## [5.1.0](https://github.com/Okipa/laravel-table/compare/5.0.2...5.1.0)

2022-10-25
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,8 @@ class UsersTable extends AbstractTableConfiguration
}
```

Tip: if you are using packages like [spatie/eloquent-sortable](https://github.com/spatie/eloquent-sortable) to handle your Eloquent models sorting behaviour with a [grouping query](https://github.com/spatie/eloquent-sortable#grouping), you'll have to also set this grouping query in the [table query instruction](#add-query-instructions-on-tables).

### Declare results on tables

To display results, you'll have to return an array of result instances from the `results` method available in your generated table configuration.
Expand Down
2 changes: 2 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ parameters:
ignoreErrors:
- '#Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Factories\\Factory<Illuminate\\Database\\Eloquent\\Model>::afterCreating\(\)#'
- '#Access to an undefined property Tests\\Models\\User::\$active#'
- '#Access to an undefined property Tests\\Models\\UserCategory::\$position#'
- '#Access to an undefined property Tests\\Models\\Company::\$position#'
- '#Call to an undefined method Faker\\Generator::catchphrase\(\)#'
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$laravel_table_unique_identifier#'

Expand Down
2 changes: 0 additions & 2 deletions src/Filters/ValueFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Okipa\LaravelTable\Abstracts\AbstractFilter;
use Tests\Models\User;

class ValueFilter extends AbstractFilter
{
Expand Down Expand Up @@ -41,6 +40,5 @@ protected function options(): array
public function filter(Builder $query, mixed $selected): void
{
$query->whereIn($this->attribute, Arr::wrap($selected));
// dd($query->toSql(), $selected, User::pluck('name')->toArray());
}
}
45 changes: 19 additions & 26 deletions src/Livewire/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ protected function buildTable(AbstractTableConfiguration $config): array
// Column actions
$this->tableColumnActionsArray = $table->generateColumnActionsArray();
// Reorder config
$this->reorderConfig = $table->getReorderConfig($this->sortDir);
$this->reorderConfig = $table->getReorderConfig($table->getRows()->getCollection(), $this->sortDir);

return [
'columns' => $table->getColumns(),
Expand All @@ -184,36 +184,29 @@ public function reorder(array $list): void
{
[
'modelClass' => $modelClass,
'modelPrimaryAttribute' => $modelPrimaryAttribute,
'reorderAttribute' => $reorderAttribute,
'sortDir' => $sortDir,
'beforeReorderAllModelKeys' => $beforeReorderAllModelKeys,
'beforeReorderModelKeysWithPosition' => $beforeReorderModelKeysWithPosition,
] = $this->reorderConfig;
$beforeReorderAllModelKeys = collect($beforeReorderAllModelKeys)->sortKeys(descending: $sortDir === 'desc')
->values()
->toArray();
$afterReorderDisplayedModelKeys = collect($list)->sortBy('order')
->pluck('value')
->mapWithKeys(fn (string $modelKey) => [
array_search($modelKey, $beforeReorderAllModelKeys, true) => $modelKey,
$beforeReorderPaginatedModelKeysWithPosition = collect($beforeReorderModelKeysWithPosition)
->sortKeys(descending: $sortDir === 'desc');
$afterReorderPaginatedModelKeysWithPosition = collect($list)
->sortBy('order')
->pluck('value', 'order')
->mapWithKeys(fn ($modelKey) => [
array_search($modelKey, $beforeReorderModelKeysWithPosition, true) => $modelKey,
]);
$beforeReorderDisplayedModelKeys = $afterReorderDisplayedModelKeys->sortKeys()->values();
$afterReorderDisplayedModelKeys = $afterReorderDisplayedModelKeys->values();
$afterReorderAllModelKeys = collect($beforeReorderAllModelKeys);
foreach ($beforeReorderDisplayedModelKeys as $beforeReorderIndex => $beforeReorderDisplayedModelKey) {
$afterReorderIndex = $afterReorderDisplayedModelKeys->search($beforeReorderDisplayedModelKey);
if ($beforeReorderIndex !== $afterReorderIndex) {
$modelKeyNewIndex = array_search(
$beforeReorderDisplayedModelKeys->get($afterReorderIndex),
$beforeReorderAllModelKeys,
true
);
$afterReorderAllModelKeys->put($modelKeyNewIndex, $beforeReorderDisplayedModelKey);
}
$beforeReorderPaginatedModelKeysWithIndex = $beforeReorderPaginatedModelKeysWithPosition->values();
$afterReorderPaginatedModelKeysWithIndex = $afterReorderPaginatedModelKeysWithPosition->values();
$reorderedPaginatedModelKeys = collect();
foreach ($beforeReorderPaginatedModelKeysWithIndex as $beforeReorderPaginatedModelKey) {
$afterReorderModelKeyIndex = $afterReorderPaginatedModelKeysWithIndex->search($beforeReorderPaginatedModelKey);
$beforeReorderModelKeyIndex = $beforeReorderPaginatedModelKeysWithIndex->get($afterReorderModelKeyIndex);
$modelKeyNewPosition = $beforeReorderPaginatedModelKeysWithPosition->search($beforeReorderModelKeyIndex);
$reorderedPaginatedModelKeys->put($modelKeyNewPosition, $beforeReorderPaginatedModelKey);
}
$startPosition = 1;
foreach ($afterReorderAllModelKeys->sortKeys(descending: $sortDir === 'desc')->values() as $modelKey) {
app($modelClass)->where($modelPrimaryAttribute, $modelKey)->update([$reorderAttribute => $startPosition++]);
foreach ($reorderedPaginatedModelKeys as $position => $modelKey) {
app($modelClass)->find($modelKey)->update([$reorderAttribute => $position]);
}
$this->emit('laraveltable:action:feedback', __('The list has been reordered.'));
}
Expand Down
11 changes: 3 additions & 8 deletions src/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,23 +113,18 @@ public function getColumns(): Collection
return $this->columns;
}

public function getReorderConfig(string|null $sortDir): array
public function getReorderConfig(Collection $rows, string|null $sortDir): array
{
if (! $this->getOrderColumn()) {
return [];
}

return [
'modelClass' => $this->model::class,
'modelPrimaryAttribute' => $this->model->getKeyName(),
'reorderAttribute' => $this->getOrderColumn()->getAttribute(),
'sortDir' => $sortDir,
'beforeReorderAllModelKeys' => $this->model
->query()
->get()
->mapWithKeys(fn (Model $model) => [
$model->{$this->getOrderColumn()->getAttribute()} => (string) $model->getKey(),
])
'beforeReorderModelKeysWithPosition' => $rows
->pluck($this->model->getKeyName(), $this->getOrderColumn()->getAttribute())
->toArray(),
];
}
Expand Down
Loading

0 comments on commit 0544fb4

Please sign in to comment.