From 64f68a2722c3f4728f87169e2f046c766ec15fd4 Mon Sep 17 00:00:00 2001 From: Tofandel Date: Fri, 1 Mar 2024 02:03:52 +0100 Subject: [PATCH] Refactor block list --- frontend/js/store/modules/blocks.js | 9 +- src/Facades/TwillBlocks.php | 11 ++ src/Facades/TwillCapsules.php | 6 + src/Helpers/Capsule.php | 3 +- src/Helpers/helpers.php | 52 +-------- .../Controllers/Admin/FeaturedController.php | 1 + .../Controllers/Admin/ModuleController.php | 2 + .../Controllers/Admin/SettingController.php | 2 + src/Http/Requests/Admin/Request.php | 21 ++-- src/Services/Blocks/Block.php | 13 ++- src/Services/Forms/Fields/BlockEditor.php | 28 ++++- src/TwillBlocks.php | 102 +++++++++++++++- src/TwillCapsules.php | 8 +- .../Components/Blocks/TwillBlockComponent.php | 13 ++- src/View/Components/Fields/BlockEditor.php | 22 ++-- tests/unit/Helpers/BlockHelpersTest.php | 110 ++++++++++++++++++ views/layouts/form.blade.php | 1 + 17 files changed, 317 insertions(+), 87 deletions(-) create mode 100644 tests/unit/Helpers/BlockHelpersTest.php diff --git a/frontend/js/store/modules/blocks.js b/frontend/js/store/modules/blocks.js index 033644ec1..324aed193 100644 --- a/frontend/js/store/modules/blocks.js +++ b/frontend/js/store/modules/blocks.js @@ -30,10 +30,15 @@ const state = { */ editorNames: window[process.env.VUE_APP_NAME].STORE.form.editorNames || [], /** - * An object with all the blocks available to add + * An object with all the blocks name available to add keyed by availibityId * @type {Object} */ available: window[process.env.VUE_APP_NAME].STORE.form.availableBlocks || {}, + /** + * An object with all the blocks available to add + * @type {Object} + */ + allAvailable: window[process.env.VUE_APP_NAME].STORE.form.allAvailableBlocks || {}, /** * An array with all the blocks created * @type {Object.Array} @@ -55,7 +60,7 @@ const state = { const getters = { previewsById: state => (id) => state.previews[id] ? state.previews[id] : '', blocks: state => editorName => state.blocks[editorName] || [], - availableBlocks: state => editorName => state.available[editorName] || [], + availableBlocks: state => editorName => state.available[editorName] && state.available[editorName].length ? state.available[editorName].map((k) => state.allAvailable[k]) : [], blockIndex: (state, getters) => (block, editorName) => getters.blocks(editorName).findIndex(b => b.id === block.id) } diff --git a/src/Facades/TwillBlocks.php b/src/Facades/TwillBlocks.php index af98174f6..1bcd35c3e 100644 --- a/src/Facades/TwillBlocks.php +++ b/src/Facades/TwillBlocks.php @@ -2,8 +2,19 @@ namespace A17\Twill\Facades; +use A17\Twill\Services\Blocks\Block; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Facade; +/** + * @method static void globallyExcludeBlocks(array|callable $blocks) + * @method static array getGloballyExcludedBlocks + * @method static CollectiongetBlocks + * @method static CollectiongetSettingsBlocks + * @method static CollectiongetRepeaters + * @method static registerManualBlock(string $blockClass, string $source = Block::SOURCE_APP) + * @method static CollectiongenerateListOfAvailableBlocks(?array $blocks = null, ?array $groups = null, bool $settingsOnly = false, array|callable $excludeBlocks = []) + */ class TwillBlocks extends Facade { protected static function getFacadeAccessor(): string diff --git a/src/Facades/TwillCapsules.php b/src/Facades/TwillCapsules.php index a5b4c6fcc..75e065aed 100644 --- a/src/Facades/TwillCapsules.php +++ b/src/Facades/TwillCapsules.php @@ -2,8 +2,14 @@ namespace A17\Twill\Facades; +use A17\Twill\Helpers\Capsule; use Illuminate\Support\Facades\Facade; +/** + * @method static string capsuleNamespace(string $capsuleName, string $type = null) + * @method static string capsuleNamespaceToPath(string $namespace, string $capsuleNamespace, string $rootPath) + * @method static Capsule registerPackageCapsule(string $name, string $namespace, string $path, string $singular = null, bool $enabled = true, bool $automaticNavigation = true) + */ class TwillCapsules extends Facade { protected static function getFacadeAccessor(): string diff --git a/src/Helpers/Capsule.php b/src/Helpers/Capsule.php index fb17fb8a4..a14141ddc 100644 --- a/src/Helpers/Capsule.php +++ b/src/Helpers/Capsule.php @@ -30,6 +30,7 @@ public function __construct( protected bool $automaticNavigation = true ) { $this->boot(); + $this->singular = $this->singular ?? Str::singular($this->name); } public function boot(): void @@ -128,7 +129,7 @@ public function getPlural(): string public function getSingular(): string { - return $this->singular ?? Str::singular($this->name); + return $this->singular; } public function getBaseNamespace(): string diff --git a/src/Helpers/helpers.php b/src/Helpers/helpers.php index 777f14255..99916ce2e 100644 --- a/src/Helpers/helpers.php +++ b/src/Helpers/helpers.php @@ -219,56 +219,14 @@ function twillModel($model): string if (! function_exists('generate_list_of_available_blocks')) { /** - * @param array $blocks - * @param array $groups - * @return array + * TODO remove in v4 + * @deprecated use TwillBlocks::generateListOfAvailableBlocks instead */ - function generate_list_of_available_blocks($blocks, $groups, bool $settingsOnly = false, array $excludeBlocks = []): array + function generate_list_of_available_blocks(?array $blocks = null, ?array $groups = null, bool $settingsOnly = false, array|callable $excludeBlocks = []): array { - if ($settingsOnly) { - $blockList = TwillBlocks::getSettingsBlocks(); - } else { - $blockList = TwillBlocks::getBlocks(); - } - - $appBlocksList = $blockList->filter(function (Block $block) { - return $block->source !== A17\Twill\Services\Blocks\Block::SOURCE_TWILL; - }); - - $finalBlockList = $blockList->filter( - function (Block $block) use ($blocks, $groups, $appBlocksList, $excludeBlocks) { - if ($block->group === A17\Twill\Services\Blocks\Block::SOURCE_TWILL) { - if (! collect(config('twill.block_editor.use_twill_blocks'))->contains($block->name)) { - return false; - } - - /** @var \Illuminate\Support\Collection $appBlocksList */ - if ( - count($appBlocksList) > 0 && $appBlocksList->contains( - function ($appBlock) use ($block) { - return $appBlock->name === $block->name; - } - ) - ) { - return false; - } - } - - if (in_array($block->name, $excludeBlocks)) { - return false; - } - - return (filled($blocks) ? collect($blocks)->contains($block->name) || collect($blocks)->contains(ltrim($block->componentClass, '\\')) : true) - && (filled($groups) ? collect($groups)->contains($block->group) : true); - } - ); + trigger_deprecation('area17/twill', '3.3', __FUNCTION__ . ' is deprecated and will be removed in 4.x, use TwillBlocks::generateListOfAvailableBlocks instead'); - // Sort them by the original definition - return $finalBlockList->sortBy(function (Block $b) use ($blocks) { - return collect($blocks)->search(function ($id, $key) use ($b) { - return $id == $b->name || $id == ltrim($b->componentClass, '\\'); - }); - })->values()->toArray(); + return TwillBlocks::generateListOfAvailableBlocks($blocks, $groups, $settingsOnly, $excludeBlocks)->all(); } } diff --git a/src/Http/Controllers/Admin/FeaturedController.php b/src/Http/Controllers/Admin/FeaturedController.php index 7c98401a8..55c0bae37 100644 --- a/src/Http/Controllers/Admin/FeaturedController.php +++ b/src/Http/Controllers/Admin/FeaturedController.php @@ -2,6 +2,7 @@ namespace A17\Twill\Http\Controllers\Admin; +use A17\Twill\Facades\TwillBlocks; use A17\Twill\Models\Feature; use A17\Twill\Repositories\Behaviors\HandleMedias; use A17\Twill\Repositories\Behaviors\HandleTranslations; diff --git a/src/Http/Controllers/Admin/ModuleController.php b/src/Http/Controllers/Admin/ModuleController.php index 08d06c728..18d7f4122 100644 --- a/src/Http/Controllers/Admin/ModuleController.php +++ b/src/Http/Controllers/Admin/ModuleController.php @@ -3,6 +3,7 @@ namespace A17\Twill\Http\Controllers\Admin; use A17\Twill\Exceptions\NoCapsuleFoundException; +use A17\Twill\Facades\TwillBlocks; use A17\Twill\Facades\TwillCapsules; use A17\Twill\Facades\TwillPermissions; use A17\Twill\Helpers\FlashLevel; @@ -2261,6 +2262,7 @@ protected function form(?int $id, ?TwillModelContract $item = null): array 'translateTitle' => $this->titleIsTranslatable(), 'permalink' => $this->getIndexOption('permalink', $item), 'createWithoutModal' => ! $itemId && $this->getIndexOption('skipCreateModal'), + 'allBlocks' => TwillBlocks::generateListOfAllBlocks()->keyBy('name'), 'form_fields' => $this->repository->getFormFields($item), 'baseUrl' => $baseUrl, 'localizedPermalinkBase' => $localizedPermalinkBase, diff --git a/src/Http/Controllers/Admin/SettingController.php b/src/Http/Controllers/Admin/SettingController.php index 7c3751844..2dc670667 100644 --- a/src/Http/Controllers/Admin/SettingController.php +++ b/src/Http/Controllers/Admin/SettingController.php @@ -2,6 +2,7 @@ namespace A17\Twill\Http\Controllers\Admin; +use A17\Twill\Facades\TwillBlocks; use A17\Twill\Repositories\SettingRepository; use A17\Twill\Services\Forms\Form; use Illuminate\Config\Repository as Config; @@ -77,6 +78,7 @@ public function index(string $section) 'editableTitle' => false, 'customTitle' => ucfirst($section) . ' settings', 'section' => $section, + 'allBlocks' => TwillBlocks::generateListOfAllBlocks()->keyBy('name'), 'form_fields' => $formFields, 'formBuilder' => Form::make(), 'saveUrl' => $this->urlGenerator->route(config('twill.admin_route_name_prefix') . 'settings.update', $section), diff --git a/src/Http/Requests/Admin/Request.php b/src/Http/Requests/Admin/Request.php index c2dda7b26..bfaf5a930 100644 --- a/src/Http/Requests/Admin/Request.php +++ b/src/Http/Requests/Admin/Request.php @@ -84,7 +84,7 @@ protected function rulesForTranslatedFields(array $existingRules, array $transla * @param bool $localeActive * @return array */ - private function updateRules($rules, $fields, $locale, $localeActive = true) + private function updateRules($rules, $fields, $locale, $localeActive = true): array { $fieldNames = array_keys($fields); @@ -93,25 +93,18 @@ private function updateRules($rules, $fields, $locale, $localeActive = true) $fieldRules = explode('|', $fieldRules); } - $fieldRules = Collection::make($fieldRules); + $fieldRules = collect($fieldRules); - // Remove required rules, when locale is not active + // Remove required rules and add nullable rules, when locale is not active if (! $localeActive) { - $hasRequiredRule = $fieldRules->contains(function ($rule) { - return $this->ruleStartsWith($rule, 'required'); - }); + $fieldRules = $fieldRules->reject(fn ($rule) => $this->ruleStartsWith($rule, 'required')); - $fieldRules = $fieldRules->reject(function ($rule) { - return $this->ruleStartsWith($rule, 'required'); - }); - - // @TODO: Can be replaced with doesntContain in twill 3.x - if ($hasRequiredRule && !in_array($fieldRules, $fieldRules->toArray())) { + if (!$fieldRules->contains(fn ($rule) => $this->ruleStartsWith($rule, 'nullable'))) { $fieldRules->add('nullable'); } } - $rules["{$field}.{$locale}"] = $fieldRules->map(function ($rule) use ($locale, $fieldNames) { + $rules["$field.$locale"] = $fieldRules->map(function ($rule) use ($locale, $fieldNames) { // allows using validation rule that references other fields even for translated fields if ($this->ruleStartsWith($rule, 'required_') && Str::contains($rule, $fieldNames)) { foreach ($fieldNames as $fieldName) { @@ -120,7 +113,7 @@ private function updateRules($rules, $fields, $locale, $localeActive = true) } return $rule; - })->toArray(); + })->all(); } return $rules; diff --git a/src/Services/Blocks/Block.php b/src/Services/Blocks/Block.php index 355117c89..6ba30ccc5 100644 --- a/src/Services/Blocks/Block.php +++ b/src/Services/Blocks/Block.php @@ -143,18 +143,19 @@ class Block public ?InlineRepeater $inlineRepeater = null; /** - * @param TwillBlockComponent $componentClass + * @param class-string $componentClass */ - public static function forComponent(string $componentClass): self + public static function forComponent(string $componentClass, string $source = self::SOURCE_APP): self { $class = new self( file: null, type: 'block', - source: $componentClass::getBlockGroup(), + source: $source, name: $componentClass::getBlockIdentifier(), componentClass: $componentClass ); + $class->group = $componentClass::getBlockGroup(); $class->title = $componentClass::getBlockTitle(); $class->icon = $componentClass::getBlockIcon(); $class->titleField = $componentClass::getBlockTitleField(); @@ -172,7 +173,6 @@ public static function forComponent(string $componentClass): self * @param $type * @param $source * @param $name - * @param string $renderNamespace * Mainly for packages, but this will get the preview/render view file from that namespace. * @return static */ @@ -206,6 +206,11 @@ public function newInstance(): static ); } + public function getPosition(): float|int|string + { + return $this->componentClass && is_callable([$this->componentClass, 'getPosition']) ? $this->componentClass::getPosition() : 0; + } + /** * Gets the first match being a block or repeater. */ diff --git a/src/Services/Forms/Fields/BlockEditor.php b/src/Services/Forms/Fields/BlockEditor.php index 85231b59e..09789f628 100644 --- a/src/Services/Forms/Fields/BlockEditor.php +++ b/src/Services/Forms/Fields/BlockEditor.php @@ -2,11 +2,14 @@ namespace A17\Twill\Services\Forms\Fields; +use A17\Twill\Services\Blocks\Block; + class BlockEditor extends BaseFormField { protected array $blocks = []; + protected array $groups = []; - protected array $excludeBlocks = []; + protected mixed $excludeBlocks = []; protected bool $isSettings = false; @@ -48,15 +51,36 @@ public function isSettings(bool $isSettings = true): static */ public function blocks(array $blocks): static { + // For backward compatibility, clear the list of excludeBlocks in case both ->excludeBlocks()->blocks() were called + $this->excludeBlocks = []; $this->blocks = $blocks; return $this; } + public function getBlocks(): array + { + return $this->blocks; + } + + public function groups(array $groups) + { + $this->groups = $groups; + + return $this; + } + + public function getGroups(): array + { + return $this->groups; + } + /** * Use this method if you want to exclude any block types + * + * @param array|callable $blocks */ - public function excludeBlocks(array $blocks): static + public function excludeBlocks(array|callable $blocks): static { $this->excludeBlocks = $blocks; diff --git a/src/TwillBlocks.php b/src/TwillBlocks.php index 0273bf21b..3fe4b8018 100644 --- a/src/TwillBlocks.php +++ b/src/TwillBlocks.php @@ -130,6 +130,20 @@ public function registerPackageRepeatersDirectory(string $path, string $renderNa } } + + protected array $globallyExcludedBlocks = []; + + /** Util method to be called in a service provider to prevent some of a package's block to be opt in */ + public function globallyExcludeBlocks(array|callable $blocks): void + { + $this->globallyExcludedBlocks[] = $blocks; + } + + public function getGloballyExcludedBlocks(): array + { + return $this->globallyExcludedBlocks; + } + /** * Only when the block collection is actually requested we parse all the information. */ @@ -192,9 +206,9 @@ public function getBlockCollection(): BlockCollection unset(self::$componentBlockNamespaces[$namespace]); } - foreach (self::$manualBlocks as $class) { + foreach (self::$manualBlocks as $class => $source) { $this->blockCollection->add( - Block::forComponent($class) + Block::forComponent($class, $source) ); unset(self::$manualBlocks[$class]); @@ -220,9 +234,9 @@ public function getBlockCollection(): BlockCollection return $this->blockCollection; } - public function registerManualBlock(string $blockClass): void + public function registerManualBlock(string $blockClass, string $source = Block::SOURCE_APP): void { - self::$manualBlocks[$blockClass] = $blockClass; + self::$manualBlocks[$blockClass] = $source; } public function findByName(string $name): ?Block @@ -327,4 +341,84 @@ public function getAllCropConfigs(): array return $this->cropConfigs; } + + public function generateListOfAllBlocks(bool $settingsOnly = false) + { + return once(function () use ($settingsOnly) { + /** @var Collection $blockList */ + if ($settingsOnly) { + $blockList = TwillBlocks::getSettingsBlocks(); + } else { + $blockList = TwillBlocks::getBlocks(); + } + + $appBlocksList = $blockList->filter(function (Block $block) { + return $block->source !== Block::SOURCE_TWILL; + }); + + return $blockList->filter(function (Block $block) use ($appBlocksList) { + if ($block->group === Block::SOURCE_TWILL) { + if (!collect(config('twill.block_editor.use_twill_blocks'))->contains($block->name)) { + return false; + } + + if ( + count($appBlocksList) > 0 && $appBlocksList->contains( + function ($appBlock) use ($block) { + return $appBlock->name === $block->name; + } + ) + ) { + return false; + } + } + return true; + })->sortBy(function (Block $b) { + // Blocks are by default sorted by the order they have been found in directories, but we can allow individual blocks to override this behavior + return $b->getPosition(); + })->values(); + }); + } + + public function generateListOfAvailableBlocks(?array $blocks = null, ?array $groups = null, bool $settingsOnly = false, array|callable $excludeBlocks = []): Collection + { + $globalExcludeBlocks = TwillBlocks::getGloballyExcludedBlocks(); + + $matchBlock = function ($matcher, $block, $someFn = null) { + if (is_callable($matcher)) { + return call_user_func($matcher, $block); + } elseif (!empty($matcher) && is_array($matcher)) { + $class = ltrim($block->componentClass, '\\'); + return collect($matcher)->some($someFn ?: fn($ex) => $ex == $block->name || $ex == $class); + } + return null; + }; + return $this->generateListOfAllBlocks($settingsOnly)->filter( + function (Block $block) use ($blocks, $groups, $excludeBlocks, $globalExcludeBlocks, $matchBlock) { + if ($matchBlock($excludeBlocks, $block)) { + return false; + } + + // Allow list of blocks and groups should have priority over globally excluded blocks (or there would be no way of allowing them) + if ($matchedBlock = $matchBlock($blocks, $block)) { + return true; + } + if ($matchedGroup = $matchBlock($groups, $block, fn($ex) => $ex === $block->group)) { + return true; + } + + if ($matchedBlock === false || $matchedGroup === false) { + return false; + } + + foreach ($globalExcludeBlocks as $excludeBlock) { + if ($matchBlock($excludeBlock, $block)) { + return false; + } + } + + return true; + } + ); + } } diff --git a/src/TwillCapsules.php b/src/TwillCapsules.php index c84e2c257..e76a67cc8 100644 --- a/src/TwillCapsules.php +++ b/src/TwillCapsules.php @@ -91,9 +91,11 @@ public function getCapsuleForModel(string|TwillModelContract $model): Capsule */ public function getRegisteredCapsules(): Collection { - $this->loadProjectCapsules(); + return once(function () { + $this->loadProjectCapsules(); - return collect($this->registeredCapsules); + return collect($this->registeredCapsules)->where('enabled', true); + }); } public function loadProjectCapsules(): void @@ -120,7 +122,7 @@ public function loadProjectCapsules(): void }); } - public function capsuleNamespace($capsuleName, $type = null): string + public function capsuleNamespace(string $capsuleName, string $type = null): string { // @todo: Read from capsules to get this data. $base = config('twill.capsules.namespaces.base'); diff --git a/src/View/Components/Blocks/TwillBlockComponent.php b/src/View/Components/Blocks/TwillBlockComponent.php index 480b83de9..db2d6a31b 100644 --- a/src/View/Components/Blocks/TwillBlockComponent.php +++ b/src/View/Components/Blocks/TwillBlockComponent.php @@ -60,8 +60,12 @@ public static function getCrops(): array */ public static function getBlockIdentifier(): string { - $class = Str::afterLast(static::class, '\\'); - return Str::slug(static::getBlockGroup() . '--' . $class); + return Str::slug(static::getBlockGroup() . '-' . static::getBlockName()); + } + + public static function getBlockName(): string + { + return Str::afterLast(static::class, '\\'); } /** @@ -108,6 +112,11 @@ public static function getBlockGroup(): string return Str::slug(Str::before(static::class, '\\')); } + public static function getPosition(): float|int|string + { + return 0; + } + public static function getBlockIcon(): string { return 'text'; diff --git a/src/View/Components/Fields/BlockEditor.php b/src/View/Components/Fields/BlockEditor.php index 9e0be88bf..0f66a764f 100644 --- a/src/View/Components/Fields/BlockEditor.php +++ b/src/View/Components/Fields/BlockEditor.php @@ -2,6 +2,7 @@ namespace A17\Twill\View\Components\Fields; +use A17\Twill\Facades\TwillBlocks; use Illuminate\Contracts\View\View; use Illuminate\Support\Str; @@ -14,7 +15,7 @@ public function __construct( bool $renderForModal = false, // Component specific public array $blocks = [], - public array $excludeBlocks = [], + public mixed $excludeBlocks = [], public array $groups = [], public bool $withoutSeparator = false, public ?string $group = null, @@ -31,7 +32,7 @@ public function __construct( $this->trigger = $trigger ?? $label ?? twillTrans('twill::lang.fields.block-editor.add-content'); } - public function render(): View + public function getAllowedBlocks(): array { $groups = []; if ($this->group) { @@ -40,15 +41,20 @@ public function render(): View $groups = $this->groups; } + return TwillBlocks::generateListOfAvailableBlocks( + $this->blocks ?? null, + $groups, + $this->isSettings, + $this->excludeBlocks ?? null, + )->pluck('name')->all(); + } + + public function render(): View + { return view( 'twill::partials.form._block_editor', array_merge($this->data(), [ - 'allowedBlocks' => generate_list_of_available_blocks( - $this->blocks ?? null, - $groups, - $this->isSettings, - $this->excludeBlocks ?? null, - ), + 'allowedBlocks' => $this->getAllowedBlocks(), 'editorName' => [ 'label' => $this->label, 'value' => $this->name, diff --git a/tests/unit/Helpers/BlockHelpersTest.php b/tests/unit/Helpers/BlockHelpersTest.php new file mode 100644 index 000000000..49daa9bd2 --- /dev/null +++ b/tests/unit/Helpers/BlockHelpersTest.php @@ -0,0 +1,110 @@ +pluck('componentClass')->all(); + $this->assertContains(GroupBlock::class, $blockClasses); + $this->assertContains(AppBlock::class, $blockClasses); + + $available = TwillBlocks::generateListOfAvailableBlocks()->pluck('componentClass'); + + $this->assertGreaterThanOrEqual(3, count($available)); + + // Ensure correct order + + $this->assertEquals(GroupBlock2::class, $available->pop()); + $this->assertEquals(AppBlock::class, $available->pop()); + + $available = TwillBlocks::generateListOfAvailableBlocks(['app-block', GroupBlock2::class])->pluck('componentClass'); + $this->assertCount(2, $available); + $this->assertContains(AppBlock::class, $available); + $this->assertContains(GroupBlock2::class, $available); + + $available = TwillBlocks::generateListOfAvailableBlocks([GroupBlock2::class], ['group'])->pluck('componentClass'); + $this->assertCount(2, $available); + $this->assertContains(GroupBlock::class, $available); + + $available = TwillBlocks::generateListOfAvailableBlocks(['app-block', GroupBlock2::class], excludeBlocks: ['app-block'])->pluck('componentClass'); + + $this->assertCount(1, $available); + $this->assertContains(GroupBlock2::class, $available); + + $available = TwillBlocks::generateListOfAvailableBlocks( + [AppBlock::class, GroupBlock::class, GroupBlock2::class], + excludeBlocks: fn (Block $block) => $block->componentClass && $block->componentClass::getBlockName() == 'block' + )->pluck('componentClass'); + + $this->assertCount(1, $available); + $this->assertContains(GroupBlock2::class, $available); + + TwillBlocks::globallyExcludeBlocks([GroupBlock::class]); + TwillBlocks::globallyExcludeBlocks(fn (Block $block) => $block->name == 'group-block2'); + + $available = TwillBlocks::generateListOfAvailableBlocks( + excludeBlocks: fn (Block $block) => $block->source == Block::SOURCE_TWILL + )->pluck('componentClass'); + $this->assertCount(1, $available); + $this->assertContains(AppBlock::class, $available); + } + +} diff --git a/views/layouts/form.blade.php b/views/layouts/form.blade.php index 3c4d1fdca..72785faf5 100644 --- a/views/layouts/form.blade.php +++ b/views/layouts/form.blade.php @@ -173,6 +173,7 @@ restoreUrl: '{{ $restoreUrl ?? '' }}', availableBlocks: {}, blocks: {}, + allAvailableBlocks: {!! json_encode($allBlocks ?? []) !!}, blockPreviewUrl: '{{ $blockPreviewUrl ?? '' }}', repeaters: {!! json_encode(($form_fields['repeaters'] ?? []) + ($form_fields['blocksRepeaters'] ?? [])) !!}, fields: [],