diff --git a/features/admin/adding_block.feature b/features/admin/adding_block.feature index 61550185..29dd78df 100644 --- a/features/admin/adding_block.feature +++ b/features/admin/adding_block.feature @@ -180,3 +180,16 @@ Feature: Adding blocks And I try to add it Then I should be notified that "Code, Name" fields are too long + @ui @javascript + Scenario: Adding block with template + Given there is an existing template named "Homepage" with "Block" type that contains "Textarea, Single media" content elements + When I go to the create block page + And I fill the code with "intro" + And I fill the name with "Intro" + And I select "Homepage" template + And I click button to use this template + And I confirm that I want to use this template + And I add it + Then I should be notified that the block has been created + And I should see newly created "Textarea" content element in Content elements section + And I should see newly created "Single media" content element in Content elements section diff --git a/features/admin/adding_template.feature b/features/admin/adding_template.feature index ef850a27..3197fb24 100644 --- a/features/admin/adding_template.feature +++ b/features/admin/adding_template.feature @@ -9,13 +9,21 @@ Feature: Adding cms templates And I am logged in as an administrator @ui - Scenario: Creating template + Scenario: Creating template with type page When I go to the create template page And I fill the name with "Test template" And I choose "Page" in Type field And I add it Then I should be notified that the template has been created + @ui + Scenario: Creating template with type block + When I go to the create template page + And I fill the name with "Test template" + And I choose "Block" in Type field + And I add it + Then I should be notified that the template has been created + @ui @javascript Scenario: Creating template with content elements When I go to the create template page diff --git a/spec/Menu/ContentManagementMenuBuilderSpec.php b/spec/Menu/ContentManagementMenuBuilderSpec.php index 19273075..c964b651 100755 --- a/spec/Menu/ContentManagementMenuBuilderSpec.php +++ b/spec/Menu/ContentManagementMenuBuilderSpec.php @@ -65,6 +65,11 @@ public function it_build_menu( $cmsRootMenuItem->setLabel('bitbag_sylius_cms_plugin.ui.media')->willReturn($cmsRootMenuItem); $cmsRootMenuItem->setLabelAttribute('icon', 'file')->shouldBeCalled(); + $menu->getChildren()->willReturn(['marketing' => $cmsRootMenuItem]); + $menu->getChild('bitbag_cms')->willReturn($cmsRootMenuItem); + + $menu->setChildren(['marketing' => $cmsRootMenuItem, 'bitbag_cms' => $cmsRootMenuItem])->willReturn($menu); + $this->buildMenu($menuBuilderEvent); } } diff --git a/src/Entity/Page.php b/src/Entity/Page.php index afad49de..d7854eba 100755 --- a/src/Entity/Page.php +++ b/src/Entity/Page.php @@ -29,11 +29,11 @@ class Page implements PageInterface __construct as protected initializeTranslationsCollection; } - protected ?int $id; + protected ?int $id = null; protected ?string $code = null; - protected ?string $name; + protected ?string $name = null; protected ?\DateTimeImmutable $publishAt; diff --git a/src/Entity/PageTranslation.php b/src/Entity/PageTranslation.php index 245e23ac..303355a3 100755 --- a/src/Entity/PageTranslation.php +++ b/src/Entity/PageTranslation.php @@ -18,7 +18,7 @@ class PageTranslation extends AbstractTranslation implements PageTranslationInte protected ?string $slug = null; - protected ?string $title; + protected ?string $title = null; protected ?string $metaKeywords; diff --git a/src/Form/Type/BlockType.php b/src/Form/Type/BlockType.php index d2472dc3..6713a45c 100755 --- a/src/Form/Type/BlockType.php +++ b/src/Form/Type/BlockType.php @@ -72,6 +72,10 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'multiple' => true, 'help' => 'bitbag_sylius_cms_plugin.ui.display_for_taxons.help', ]) + ->add('template', TemplateBlockAutocompleteChoiceType::class, [ + 'label' => false, + 'mapped' => false, + ]) ; } diff --git a/src/Form/Type/TemplateBlockAutocompleteChoiceType.php b/src/Form/Type/TemplateBlockAutocompleteChoiceType.php new file mode 100644 index 00000000..c0737319 --- /dev/null +++ b/src/Form/Type/TemplateBlockAutocompleteChoiceType.php @@ -0,0 +1,19 @@ + 'bitbag_sylius_cms_plugin.ui.type', 'choices' => [ 'bitbag_sylius_cms_plugin.ui.page' => 'page', + 'bitbag_sylius_cms_plugin.ui.block' => 'block', ], ]) ->add('contentElements', CollectionType::class, [ diff --git a/src/Menu/ContentManagementMenuBuilder.php b/src/Menu/ContentManagementMenuBuilder.php index 8862823f..c0e25f11 100755 --- a/src/Menu/ContentManagementMenuBuilder.php +++ b/src/Menu/ContentManagementMenuBuilder.php @@ -10,6 +10,7 @@ namespace BitBag\SyliusCmsPlugin\Menu; +use Knp\Menu\ItemInterface; use Sylius\Bundle\UiBundle\Menu\Event\MenuBuilderEvent; final class ContentManagementMenuBuilder @@ -62,5 +63,29 @@ public function buildMenu(MenuBuilderEvent $menuBuilderEvent): void ->setLabel('bitbag_sylius_cms_plugin.ui.media') ->setLabelAttribute('icon', 'file') ; + + $this->reorderMenu($menu, 'bitbag_cms', 'marketing'); + } + + private function reorderMenu(ItemInterface $menu, string $newItemKey, string $targetItemKey): void + { + $menuItems = $menu->getChildren(); + + $newMenuItem = $menu->getChild($newItemKey); + unset($menuItems[$newItemKey]); + + $targetPosition = array_search($targetItemKey, array_keys($menuItems), true); + + if (null !== $newMenuItem && false !== $targetPosition) { + $menuItems = array_slice($menuItems, 0, $targetPosition + 1, true) + + [$newItemKey => $newMenuItem] + + array_slice($menuItems, $targetPosition + 1, null, true); + + $menuItems = array_filter($menuItems, static function ($item) { + return $item instanceof ItemInterface; + }); + + $menu->setChildren($menuItems); + } } } diff --git a/src/Renderer/ContentElement/ProductsCarouselByTaxonContentElementRenderer.php b/src/Renderer/ContentElement/ProductsCarouselByTaxonContentElementRenderer.php index 59d8c573..14a47edb 100644 --- a/src/Renderer/ContentElement/ProductsCarouselByTaxonContentElementRenderer.php +++ b/src/Renderer/ContentElement/ProductsCarouselByTaxonContentElementRenderer.php @@ -35,8 +35,12 @@ public function render(ContentConfigurationInterface $contentConfiguration): str { $taxonCode = $contentConfiguration->getConfiguration()['products_carousel_by_taxon']; - /** @var TaxonInterface $taxon */ + /** @var TaxonInterface|null $taxon */ $taxon = $this->taxonRepository->findOneBy(['code' => $taxonCode]); + if (null === $taxon) { + return ''; + } + $products = $this->productRepository->findByTaxon($taxon); return $this->twig->render('@BitBagSyliusCmsPlugin/Shop/ContentElement/index.html.twig', [ diff --git a/src/Renderer/ContentElement/ProductsCarouselContentElementRenderer.php b/src/Renderer/ContentElement/ProductsCarouselContentElementRenderer.php index 83d014e5..180290e9 100644 --- a/src/Renderer/ContentElement/ProductsCarouselContentElementRenderer.php +++ b/src/Renderer/ContentElement/ProductsCarouselContentElementRenderer.php @@ -33,6 +33,9 @@ public function render(ContentConfigurationInterface $contentConfiguration): str $configuration = $contentConfiguration->getConfiguration(); $productsCodes = $configuration['products_carousel']['products']; $products = $this->productRepository->findBy(['code' => $productsCodes]); + if (empty($products)) { + return ''; + } return $this->twig->render('@BitBagSyliusCmsPlugin/Shop/ContentElement/index.html.twig', [ 'content_element' => '@BitBagSyliusCmsPlugin/Shop/ContentElement/_products_carousel.html.twig', diff --git a/src/Renderer/ContentElement/ProductsGridByTaxonContentElementRenderer.php b/src/Renderer/ContentElement/ProductsGridByTaxonContentElementRenderer.php index 3877ddda..c704ae08 100644 --- a/src/Renderer/ContentElement/ProductsGridByTaxonContentElementRenderer.php +++ b/src/Renderer/ContentElement/ProductsGridByTaxonContentElementRenderer.php @@ -35,8 +35,12 @@ public function render(ContentConfigurationInterface $contentConfiguration): str { $taxonCode = $contentConfiguration->getConfiguration()['products_grid_by_taxon']; - /** @var TaxonInterface $taxon */ + /** @var TaxonInterface|null $taxon */ $taxon = $this->taxonRepository->findOneBy(['code' => $taxonCode]); + if (null === $taxon) { + return ''; + } + $products = $this->productRepository->findByTaxon($taxon); return $this->twig->render('@BitBagSyliusCmsPlugin/Shop/ContentElement/index.html.twig', [ diff --git a/src/Renderer/ContentElement/SingleMediaContentElementRenderer.php b/src/Renderer/ContentElement/SingleMediaContentElementRenderer.php index 1b61dbdb..348b705e 100644 --- a/src/Renderer/ContentElement/SingleMediaContentElementRenderer.php +++ b/src/Renderer/ContentElement/SingleMediaContentElementRenderer.php @@ -33,6 +33,10 @@ public function supports(ContentConfigurationInterface $contentConfiguration): b public function render(ContentConfigurationInterface $contentConfiguration): string { $code = $contentConfiguration->getConfiguration()['single_media']; + if (null === $code) { + return ''; + } + $media = [ 'renderedContent' => $this->renderMediaRuntime->renderMedia($code), 'entity' => $this->mediaRepository->findOneBy(['code' => $code]), diff --git a/src/Resources/assets/admin/js/bitbag/bitbag-template.js b/src/Resources/assets/admin/js/bitbag/bitbag-template.js index aeea6ac5..6ca7984b 100644 --- a/src/Resources/assets/admin/js/bitbag/bitbag-template.js +++ b/src/Resources/assets/admin/js/bitbag/bitbag-template.js @@ -9,19 +9,20 @@ export class HandleTemplate { $(document).ready(() => { const cmsLoadTemplate = $('[data-bb-cms-load-template]'); const cmsPageTemplate = $('#bitbag_sylius_cms_plugin_page_template'); + const cmsBlockTemplate = $('#bitbag_sylius_cms_plugin_block_template'); cmsLoadTemplate.on('click', function (e) { e.preventDefault(); - if (!cmsPageTemplate.val()) { + if (!cmsPageTemplate.val() && !cmsBlockTemplate.val()) { return; } $('#load-template-confirmation-modal').modal('show'); }); - $('#load-template-confirmation-button').on('click', function (e) { - const templateId = cmsPageTemplate.val(); + $('#load-template-confirmation-button').on('click', function () { + const templateId = cmsPageTemplate.val() ?? cmsBlockTemplate.val(); if (!templateId) { return; } @@ -34,9 +35,6 @@ export class HandleTemplate { $.ajax({ url: endpointUrl, type: 'GET', - headers: { - 'X-Requested-With': 'XMLHttpRequest' - }, success: function(data) { if (data.status === 'success') { $('[id^="bitbag_sylius_cms_plugin_"][id$="contentElements"]') @@ -47,7 +45,9 @@ export class HandleTemplate { $('[data-form-collection="add"]').trigger('click'); }); - const elements = $('[id^="bitbag_sylius_cms_plugin_page_contentElements_"][id$="_type"]'); + const elements = $('[id^="bitbag_sylius_cms_plugin_"][id*="_contentElements_"][id$="_type"]').filter(function() { + return /_page_|_block_/.test(this.id); + }); $.each(data.content, function (index, element) { elements.eq(index).val(element.type); diff --git a/src/Resources/config/routing/admin/template.yml b/src/Resources/config/routing/admin/template.yml index 129cd1bb..9013de97 100755 --- a/src/Resources/config/routing/admin/template.yml +++ b/src/Resources/config/routing/admin/template.yml @@ -16,7 +16,7 @@ bitbag_sylius_cms_plugin_admin_template: type: sylius.resource bitbag_sylius_cms_plugin_admin_ajax_template_page_by_name_phrase: - path: /ajax/templates/search + path: /ajax/templates/page/search methods: [GET] defaults: _format: json @@ -30,7 +30,22 @@ bitbag_sylius_cms_plugin_admin_ajax_template_page_by_name_phrase: phrase: $phrase type: page -bitbag_sylius_cms_plugin_admin_ajax_template_page_by_id: +bitbag_sylius_cms_plugin_admin_ajax_template_block_by_name_phrase: + path: /ajax/templates/block/search + methods: [GET] + defaults: + _format: json + _controller: bitbag_sylius_cms_plugin.controller.template::indexAction + _sylius: + serialization_groups: [Autocomplete] + permission: true + repository: + method: findTemplatesByNamePart + arguments: + phrase: $phrase + type: block + +bitbag_sylius_cms_plugin_admin_ajax_template_by_id: path: /ajax/templates/id methods: [GET] defaults: @@ -43,7 +58,7 @@ bitbag_sylius_cms_plugin_admin_ajax_template_page_by_id: method: find arguments: [id: $id] -bitbag_sylius_cms_plugin_admin_ajax_template_page_content_by_id: +bitbag_sylius_cms_plugin_admin_ajax_template_content_by_id: path: /ajax/templates/content/{id} methods: [GET] defaults: diff --git a/src/Resources/views/Block/Crud/_form.html.twig b/src/Resources/views/Block/Crud/_form.html.twig index d53d42d7..e2905386 100755 --- a/src/Resources/views/Block/Crud/_form.html.twig +++ b/src/Resources/views/Block/Crud/_form.html.twig @@ -1,5 +1,6 @@ {% from '@BitBagSyliusCmsPlugin/Macro/translationForm.html.twig' import translationForm %} {% form_theme form '@BitBagSyliusCmsPlugin/Form/theme.html.twig' %} +{% include '@BitBagSyliusCmsPlugin/Modal/_loadTemplateConfirmation.html.twig' %}