area17 / twill

Twill is an open source CMS toolkit for Laravel that helps developers rapidly create a custom admin console that is intuitive, powerful and flexible. Chat with us on Discord at https://discord.gg/cnWk7EFv8R.
https://twillcms.com
Apache License 2.0
3.75k stars 571 forks source link

Block previews don't update when browser items are added or changed #2308

Open zltn opened 1 year ago

zltn commented 1 year ago

Description

Changes to blocks with a browser don't update in the editor even after clicking done and update. The preview on the right flashes insinuating a refresh but the changes don't show up. If I open up the preview I do see the changes. Only once I exit out of the editor, refresh the edit page and open the editor again I see the changes in the previews.

Some other things I've noticed in the previews:

Steps to reproduce

Create a simple block with a browser fields, see below for my setup:

public function getForm(): Form
{
    return Form::make([
        Browser::make()
            ->modules([Customer::class])
            ->name('Customers')
            ->sortable(true)
            ->max(8)
    ]);
}

Create a preview blade template that includes

$block->getRelated('Customers')

Expected result

If I make changes in the browser field using the editor I would expect those changes to be directly reflected in the preview on the right.

Actual result

Changes don't show directly, only after refreshing the page, even closing and opening the editor don't make a difference

Versions

Twill version: 3.0.2 Laravel version: 10 PHP version: 8 Database engine: PG 14

zltn commented 1 year ago

Did some digging myself and it looks like this is not something that's currently supported. There's two flows that will need some updating:

  1. Browsers are not passed along in vendor/area17/twill/src/Helpers/BlockRenderer.php function getNestedBlocksForData(). This could be fixed by adding something like:

        //include browser data in content field
        if( count($data['browsers']) > 0 ) {
    
            $browsers = [];
            foreach ($data['browsers'] as $name => $elements){
                $browsers[$name] =  Arr::pluck($elements, 'id');
            }
            $data['content']['browsers'] = $browsers;
        }
  2. Now you'll have the updated browser data in the block but when rendering the block you call $block->getRelated() which will get the related fields directly from the DB or cache vs using the revision data. If I'd have the above data available I could add an inEditor flow that would to omit the cache/query and attach the new items from the browser. I can now just replace the RelatedItems in my blade template for previews:

        // needed to make the editor auto update
        $block->relatedItems = new \Illuminate\Database\Eloquent\Collection();

        foreach ($block->content['browsers'] as $browser => $relatedItems) {
            foreach ($relatedItems as $key => $value) {
                $related = new \A17\Twill\Models\RelatedItem([
                                'subject_id' => $block->id,
                                'subject_type' => 'block',
                                'related_id' => $value,
                                'related_type' => $browser, //might need be converted to something like \App\Models\ModelName
                                'browser_name' => $browser,
                                'position' => $key,
                ]);
                $block->relatedItems[] = $related;
            }
        }

Happy to provide a PR for the first part if this is going to be helpful for others or to extend further to make it fit the architecture. For now will keep a fork running for our implementation

zltn commented 1 year ago

Let me know if the above approach works and I can create a PR for it

ifox commented 8 months ago

Hi @zltn, sorry for the delay... A PR is welcome for this!