orchidsoftware / platform

Orchid is a @laravel package that allows for rapid application development of back-office applications, admin/user panels, and dashboards.
https://orchid.software
MIT License
4.42k stars 647 forks source link

Drag to reorder table rows #2370

Open giant-robot opened 2 years ago

giant-robot commented 2 years ago

It is not an uncommon need to be able to reorder rows in a table layout. Since SortableJS is already a project dependency, it shouldn't be too hard to implement

I have put together a proof of concept that enables the feature with the minimum amount of changes in the platform.

It introduces a new action that can be added to a dedicated column. This is an example applied to the RoleListLayout:

public function columns(): array
{
    return [
        TD::make()
            ->cantHide()
            ->render(function (Role $role) {
                return ReorderHandle::make()
                    ->method('reorder')
                    ->key($role->getKey());
            }),

        ...
    ];
}

Not sure this is the best way to go about it, though. Thoughts?

tabuna commented 2 years ago

Hi, @giant-robot Can you help me understand the idea better? Because I'm looking at the above example and I don't understand. For example, I swapped positions 3 and 7. What value will come to the reorder method?

giant-robot commented 2 years ago

Hey @tabuna, the current implementation will not pass arguments to the reorder method. Instead, each change will result in a POST XHR request with a payload than contains a key and an offset parameter.

key is anything you specify in the action using the key method for the item that is being dragged. offset is the relative change in position for the same item.

You can access those directly from the request object inside the reorder method (it would be great if Request could be injected as an argument to the method when it is called).

So, for the code given above:

I hope that makes it clearer.

tabuna commented 2 years ago

I like the idea of having this in a package. But I think we need to decide a few things before we release it:

public function columns(): array
{
    return [
        Sortable::make('method', 'string or closure'),

        ...
    ];
}
public function reorder(Role $role, int $offset): array
{
   //...
}

I will try to work with you to improve these points in the near future.

giant-robot commented 2 years ago

I've converted the sorting handle from an action to a Cell, as you suggest. It actually needs to be an extension of TD because of the contraints of the Table::columns method, but it seems to work fine.

Extending TD also has the benefit of being able to guess the sort key from the column name or use the render method for more complex cases. You can use it like so:

public function columns(): array
{
    return [
        ReorderHandle::make('id')
            ->method('reorder'),
        ...
    ];
}

Running the reorder method as an async method will be great. Let me know how we can achieve this.

Regarding the actual change of the sort key of the reordered models, I see your point but it feels to me like an implementation detail. There are more than one ways to do it and it really depends on the model itself.

Cheers, George