saade / filament-adjacency-list

A Filament package to manage adjacency lists (aka trees).
https://filamentphp.com/plugins/saade-adjacency-list
MIT License
76 stars 13 forks source link

[Bug]: Can't reorder #36

Open RibesAlexandre opened 1 month ago

RibesAlexandre commented 1 month ago

What happened?

Hi,

I'm using Adjency list to make a menu builder, without relationships. I'm using it in a custom private package with dynamics itemTypes (dependants of subpackages installed). All works file, but the reorder method don't save the new result in database.

I made the modal form dynamic, dependant of type selected, like this :

AdjacencyList::make('items')
                            ->label(__('filament-starter::translations.labels.items'))
                            ->orderColumn('order')
                            ->reorderable(true)
                            ->maxDepth(6) // TODO: Make this configurable
                            ->label('Elements')
                            ->form([
                                Forms\Components\TextInput::make('label')
                                    ->label('Label')
                                    ->required(),

                                Forms\Components\Select::make('type')
                                    ->label('Type')
                                    ->live()
                                    ->searchable()
                                    ->options(function() {
                                        return array_combine(array_keys(FilamentStarter::getNavigationItemTypes()), Arr::pluck(FilamentStarter::getNavigationItemTypes(), 'name'));
                                    })
                                    ->afterStateUpdated(function ($state, Forms\Components\Select $component): void {
                                        if (! $state) {
                                            return;
                                        }

                                        $component
                                            ->getContainer()
                                            ->getComponent(fn (Forms\Components\Component $component) => $component instanceof Forms\Components\Group)
                                            ->live()
                                            ->getChildComponentContainer()
                                            ->fill();
                                    })
                                    ->live(),

                                Forms\Components\Group::make()
                                    ->statePath('data')
                                    ->whenTruthy('type')
                                    ->live()
                                    ->schema(function (Forms\Get $get) {
                                        $type = $get('type');

                                        return FilamentStarter::getNavigationItemTypes()[$type]['fields'] ?? [];
                                    }),
                            ])

And this is how i get the FilamentTypes :

public function getNavigationItemTypes(): array
    {
        return array_merge(
            [
                'external-link' => [
                    'name' =>  __('filament-starter::translations.labels.external-link'),
                    'fields' => [
                        Forms\Components\TextInput::make('url')
                            ->label(__('filament-starter::translations.labels.url'))
                            ->required(),
                        Forms\Components\Select::make('target')
                            ->label(__('filament-starter::translations.navigation.select-options.target'))
                            ->options([
                                '' => __('filament-starter::translations.navigation.select-options.same-tab'),
                                '_blank' => __('filament-starter::translations.navigation.select-options.new-tab'),
                            ])
                            ->live()
                            ->default(''),
                    ],
                ],
                'page'      =>  [
                    'name'      =>  __('filament-starter::translations.labels.page'),
                    'fields' => [
                        Forms\Components\Select::make('page_id')
                            ->label(__('filament-starter::translations.labels.page'))
                            ->required()
                            ->searchable()
                            ->preload()
                            ->live()
                            ->options(function () {
                                return config('filament-starter.models.page')::all()->pluck('title', 'id');
                            })
                            ->afterStateUpdated(function (?string $state, Forms\Set $set) {
                                if (! $state) {
                                    return;
                                }
                                $page = config('filament-starter.models.page')::select('id', 'slug')->findOrFail($state);
                                $set('page_slug', $page->slug);
                            })
                            ->live(debounce:500)
                            ->default(''),

                        Forms\Components\Hidden::class::make('page_slug'),
                    ],
                ],
                'post-category' =>  [
                    'name'  =>  __('filament-starter::translations.labels.postCategory'),
                    'fields' => [
                        Forms\Components\Select::make('post_category_id')
                            ->label(__('filament-starter::translations.labels.postCategory'))
                            ->required()
                            ->searchable()
                            ->live()
                            ->preload()
                            ->options(function () {
                                return config('filament-starter.models.postCategory')::all()->pluck('name', 'id');
                            })
                            ->live(debounce:500)
                            ->afterStateUpdated(function (?string $state, Forms\Set $set) {
                                if (! $state) {
                                    return;
                                }
                                $category = config('filament-starter.models.postCategory')::select('id', 'slug')->findOrFail($state);
                                $set('post_category_slug', $category->slug);
                            })
                            ->default(''),

                        Forms\Components\Hidden::class::make('post_category_slug'),
                    ],
                ]
            ],
            $this->navigationItemsType // Empty array by default
        );
    }

This is my snapshot after a reorder :

Capture d’écran 2024-09-28 à 11 29 03

"{\"data\":{\"data\":[{\"id\":2,\"name\":\"Header\",\"slug\":\"header\",\"position\":\"header\",\"items\":[{\"a9b3ced3-71dc-4140-af38-aa56cdea479e\":[{\"data\":[{\"url\":\"https:\\/\\/laboiteacode.fr\",\"target\":null},{\"s\":\"arr\"}],\"type\":\"external-link\",\"label\":\"LBAC\",\"children\":[[],{\"s\":\"arr\"}]},{\"s\":\"arr\"}],\"1d8ec347-0bc4-45d4-8bd1-968ea2c74bf5\":[{\"data\":[{\"page_id\":\"1\",\"page_slug\":\"accueil\"},{\"s\":\"arr\"}],\"type\":\"page\",\"label\":\"Accueil\",\"children\":[[],{\"s\":\"arr\"}]},{\"s\":\"arr\"}]},{\"s\":\"arr\"}],\"created_at\":\"2024-09-28T08:59:10.000000Z\",\"updated_at\":\"2024-09-28T09:10:47.000000Z\",\"order\":null},{\"s\":\"arr\"}],\"previousUrl\":\"http:\\/\\/filamentstarterdev.test\\/admin\\/navigations\\/create\",\"mountedActions\":[[],{\"s\":\"arr\"}],\"mountedActionsArguments\":[[],{\"s\":\"arr\"}],\"mountedActionsData\":[[],{\"s\":\"arr\"}],\"defaultAction\":null,\"defaultActionArguments\":null,\"componentFileAttachments\":[[],{\"s\":\"arr\"}],\"mountedFormComponentActions\":[[],{\"s\":\"arr\"}],\"mountedFormComponentActionsArguments\":[[],{\"s\":\"arr\"}],\"mountedFormComponentActionsData\":[[],{\"s\":\"arr\"}],\"mountedFormComponentActionsComponents\":[[],{\"s\":\"arr\"}],\"mountedInfolistActions\":[[],{\"s\":\"arr\"}],\"mountedInfolistActionsData\":[[],{\"s\":\"arr\"}],\"mountedInfolistActionsComponent\":null,\"mountedInfolistActionsInfolist\":null,\"activeRelationManager\":null,\"record\":[null,{\"class\":\"HyperCoeur\\\\FilamentStarter\\\\Models\\\\Navigation\",\"key\":2,\"s\":\"mdl\"}],\"savedDataHash\":null},\"memo\":{\"id\":\"PkV13qtndzrWkuoCLJne\",\"name\":\"hyper-coeur.filament-starter.filament.resources.navigation-resource.pages.edit-navigation\",\"path\":\"admin\\/navigations\\/2\\/create\",\"method\":\"GET\",\"children\":[],\"scripts\":[],\"assets\":[],\"errors\":[],\"locale\":\"fr\"},\"checksum\":\"6b9c2f3f54243051c012ad5de1391c38aa31e4e2242267cd8b7733b4ef94f720\"}"

We can see that the exernal link is first, as expected, but after save changes aren't be applied.

Is it a bug or a default config ? On the previous version, before relationships, it worked very well.

Thanks you

How to reproduce the bug

You could try to use dynamic form type on select.

Package Version

3.2.1

PHP Version

8.2.0

Laravel Version

^11.0

Which operating systems does with happen with?

macOS

Notes

No response

saade commented 1 month ago

Hey, can you setup a little reproduction repo? I'm using it without relationships in my project and its working as expected

RibesAlexandre commented 1 month ago

Hi,

I'll do it later this day. Actually I'm trying to use it with relationships, and I have some mistakes. I make an other issue.