This commit is contained in:
Thomas Peterson 2026-03-24 17:00:50 +01:00
parent 51d935d28d
commit 965f56e0d4
22 changed files with 478 additions and 137 deletions

View File

@ -21,23 +21,23 @@ use PSC\Shop\CmsBundle\Form\Backend\CmsType;
use PSC\Shop\CmsBundle\PSCShopCmsBundle; use PSC\Shop\CmsBundle\PSCShopCmsBundle;
use PSC\Shop\EntityBundle\Entity\Cms; use PSC\Shop\EntityBundle\Entity\Cms;
use PSC\Shop\EntityBundle\Entity\Motiv; use PSC\Shop\EntityBundle\Entity\Motiv;
use PSC\Shop\SettingsBundle\Service\Routing;
use PSC\Shop\ShippingBundle\Form\Backend\DeleteType; use PSC\Shop\ShippingBundle\Form\Backend\DeleteType;
use PSC\Shop\ThemeBundle\Core\Config\Cms\Position; use PSC\Shop\ThemeBundle\Core\Config\Cms\Position;
use PSC\System\PluginBundle\Form\Chain\Field; use PSC\System\PluginBundle\Form\Chain\Field;
use PSC\System\SettingsBundle\Document\LogEntry; use PSC\System\SettingsBundle\Document\LogEntry;
use PSC\System\SettingsBundle\Service\History; use PSC\System\SettingsBundle\Service\History;
use PSC\System\SettingsBundle\Service\Log; use PSC\System\SettingsBundle\Service\Log;
use PSC\Shop\SettingsBundle\Service\Routing;
use PSC\System\SettingsBundle\Service\Shop; use PSC\System\SettingsBundle\Service\Shop;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Http\Attribute\IsGranted;
/** /**
* EditController fürs Backend * EditController fürs Backend
@ -81,12 +81,10 @@ class EditController extends AbstractController
EntityManagerInterface $entityManager, EntityManagerInterface $entityManager,
DocumentManager $documentManager, DocumentManager $documentManager,
Routing $routing, Routing $routing,
Shop $shopService Shop $shopService,
) { ) {
$customFields = $fieldService->getFields(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms); $customFields = $fieldService->getFields(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms);
$customGroups = $fieldService->getGroups(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms); $customGroups = $fieldService->getGroups(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms);
$selectedShop = $shopService->getSelectedShop(); $selectedShop = $shopService->getSelectedShop();
$cms = new Cms(); $cms = new Cms();
@ -108,19 +106,26 @@ class EditController extends AbstractController
$cmsDoc->setExtraSettings($cms->getExtraSettings()); $cmsDoc->setExtraSettings($cms->getExtraSettings());
$cmsDoc->setPluginSettings($cms->getPluginSettings()); $cmsDoc->setPluginSettings($cms->getPluginSettings());
$cmsDoc->setNoIndex($cms->isNoIndex()); $cmsDoc->setNoIndex($cms->isNoIndex());
$cmsDoc->setRawText($cms->isRawText()); $cmsDoc->setEditorMode($cms->getEditorMode());
$documentManager->persist($cmsDoc); $documentManager->persist($cmsDoc);
$documentManager->flush(); $documentManager->flush();
$this->logService->createLogEntry($selectedShop, $this->getUser(), LogEntry::INFO, PSCShopCmsBundle::class, $cms->getTitle(), "CMS Site saved"); $this->logService->createLogEntry(
$selectedShop,
$this->getUser(),
LogEntry::INFO,
PSCShopCmsBundle::class,
$cms->getTitle(),
'CMS Site saved',
);
return $this->redirectToRoute('psc_shop_cms_backend_list'); return $this->redirectToRoute('psc_shop_cms_backend_list');
} }
return array( return array(
'form' => $form->createView(), 'form' => $form->createView(),
'customFields' => $customFields, 'customFields' => $customFields,
'customGroups' => $customGroups 'customGroups' => $customGroups,
); );
} }
@ -146,16 +151,17 @@ class EditController extends AbstractController
EntityManagerInterface $entityManager, EntityManagerInterface $entityManager,
DocumentManager $documentManager, DocumentManager $documentManager,
Routing $routing, Routing $routing,
$uid $uid,
) { ) {
$customFields = $fieldService->getFields(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms); $customFields = $fieldService->getFields(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms);
$customGroups = $fieldService->getGroups(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms); $customGroups = $fieldService->getGroups(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms);
dump($customGroups);
$selectedShop = $shopService->getSelectedShop(); $selectedShop = $shopService->getSelectedShop();
/** @var Cms $cms */ /** @var Cms $cms */
$cms = $entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Cms')->findOneBy(array('shop' => $selectedShop, 'uid' => $uid)); $cms = $entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Cms')
->findOneBy(array('shop' => $selectedShop, 'uid' => $uid));
/** @var \PSC\Shop\EntityBundle\Document\Cms $cmsDoc */ /** @var \PSC\Shop\EntityBundle\Document\Cms $cmsDoc */
$cmsDoc = $documentManager $cmsDoc = $documentManager
@ -166,17 +172,17 @@ class EditController extends AbstractController
$cms->setExtraSettings($cmsDoc->getExtraSettings()); $cms->setExtraSettings($cmsDoc->getExtraSettings());
$cms->setPluginSettings($cmsDoc->getPluginSettings()); $cms->setPluginSettings($cmsDoc->getPluginSettings());
$cms->setNoIndex($cmsDoc->isNoIndex()); $cms->setNoIndex($cmsDoc->isNoIndex());
$cms->setRawText($cmsDoc->isRawText()); $cms->setEditorMode($cmsDoc->getEditorMode());
} elseif (!$cmsDoc) { } elseif (!$cmsDoc) {
$cmsDoc = new \PSC\Shop\EntityBundle\Document\Cms(); $cmsDoc = new \PSC\Shop\EntityBundle\Document\Cms();
$cmsDoc->setUid($cms->getUid()); $cmsDoc->setUid($cms->getUid());
$cmsDoc->setExtraSettings($cms->getExtraSettings()); $cmsDoc->setExtraSettings($cms->getExtraSettings());
$cmsDoc->setNoIndex($cms->isNoIndex()); $cmsDoc->setNoIndex($cms->isNoIndex());
$cmsDoc->setRawText($cms->isRawText()); $cmsDoc->setEditorMode($cms->getEditorMode());
$documentManager->persist($cmsDoc); $documentManager->persist($cmsDoc);
$documentManager->flush(); $documentManager->flush();
} elseif ($request->isMethod('POST') && $cmsDoc && isset($request->get('cms')['rawText'])) { } elseif ($request->isMethod('POST') && $cmsDoc && isset($request->get('cms')['editorMode'])) {
$cms->setRawText($request->get('cms')['rawText']); $cms->setEditorMode($request->get('cms')['editorMode']);
} }
$form = $this->createForm(CmsType::class, $cms); $form = $this->createForm(CmsType::class, $cms);
@ -188,25 +194,30 @@ class EditController extends AbstractController
$cmsDoc->setPluginSettings($cms->getPluginSettings()); $cmsDoc->setPluginSettings($cms->getPluginSettings());
$cmsDoc->setExtraSettings($cms->getExtraSettings()); $cmsDoc->setExtraSettings($cms->getExtraSettings());
$cmsDoc->setNoIndex($cms->isNoIndex()); $cmsDoc->setNoIndex($cms->isNoIndex());
$cmsDoc->setRawText($cms->isRawText()); $cmsDoc->setEditorMode($cms->getEditorMode());
$this->historyService->createHistoryEntry(new PSCHistory((string)$cms->getUid()), $cms, $cmsDoc); $this->historyService->createHistoryEntry(new PSCHistory((string) $cms->getUid()), $cms, $cmsDoc);
$entityManager->persist($cms); $entityManager->persist($cms);
$entityManager->flush(); $entityManager->flush();
$documentManager->persist($cmsDoc); $documentManager->persist($cmsDoc);
$documentManager->flush(); $documentManager->flush();
$this->logService->createLogEntry($selectedShop, $this->getUser(), LogEntry::INFO, PSCShopCmsBundle::class, $cms->getTitle(), "CMS Site saved"); $this->logService->createLogEntry(
$selectedShop,
$this->getUser(),
LogEntry::INFO,
PSCShopCmsBundle::class,
$cms->getTitle(),
'CMS Site saved',
);
} }
return array( return array(
'cms' => $cms, 'cms' => $cms,
'form' => $form->createView(), 'form' => $form->createView(),
'customFields' => $customFields, 'customFields' => $customFields,
'customGroups' => $customGroups, 'customGroups' => $customGroups,
'changes' => $this->historyService->getHistory(new PSCHistory(), (string)$cms->getUid()) 'changes' => $this->historyService->getHistory(new PSCHistory(), (string) $cms->getUid()),
); );
} }
@ -227,9 +238,8 @@ class EditController extends AbstractController
EntityManagerInterface $entityManager, EntityManagerInterface $entityManager,
SessionInterface $session, SessionInterface $session,
Shop $shopService, Shop $shopService,
$uid $uid,
) { ) {
$cms = $entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Cms')->findOneBy(['uid' => $uid]); $cms = $entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Cms')->findOneBy(['uid' => $uid]);
$selectedShop = $shopService->getSelectedShop(); $selectedShop = $shopService->getSelectedShop();
@ -242,11 +252,15 @@ class EditController extends AbstractController
$title = $cms->getTitle(); $title = $cms->getTitle();
$entityManager->remove($cms); $entityManager->remove($cms);
$entityManager->flush(); $entityManager->flush();
$session->getFlashBag()->add( $session->getFlashBag()->add('success', 'Site \'' . $title . '\' has been deleted!');
'success', $this->logService->createLogEntry(
'Site \'' . $title . '\' has been deleted!' $selectedShop,
$this->getUser(),
LogEntry::INFO,
PSCShopCmsBundle::class,
$title,
'CMS Site deleted',
); );
$this->logService->createLogEntry($selectedShop, $this->getUser(), LogEntry::INFO, PSCShopCmsBundle::class, $title, "CMS Site deleted");
return $this->redirectToRoute('psc_shop_cms_backend_list'); return $this->redirectToRoute('psc_shop_cms_backend_list');
} }
return $this->redirectToRoute('psc_shop_cms_backend_list'); return $this->redirectToRoute('psc_shop_cms_backend_list');
@ -254,7 +268,7 @@ class EditController extends AbstractController
return array( return array(
'cms' => $cms, 'cms' => $cms,
'form' => $form->createView() 'form' => $form->createView(),
); );
} }
} }

View File

@ -72,7 +72,7 @@ class CmsType extends AbstractType
$this->entityManager = $entityManager; $this->entityManager = $entityManager;
} }
private function buildCmsTree(array $tmp = [], null|Cms $cms = null, $level = ''): array private function buildCmsTree(array $tmp = [], ?Cms $cms = null, $level = ''): array
{ {
if ($cms) { if ($cms) {
$sites = $this->entityManager $sites = $this->entityManager
@ -112,7 +112,14 @@ class CmsType extends AbstractType
->add('enable', CheckboxType::class, ['label' => 'psc_shop_cms.Active', 'required' => false]) ->add('enable', CheckboxType::class, ['label' => 'psc_shop_cms.Active', 'required' => false])
->add('notInMenu', CheckboxType::class, ['label' => 'psc_shop_cms.NotInMenu', 'required' => false]) ->add('notInMenu', CheckboxType::class, ['label' => 'psc_shop_cms.NotInMenu', 'required' => false])
->add('noIndex', CheckboxType::class, ['label' => 'psc_shop_cms.NoIndex', 'required' => false]) ->add('noIndex', CheckboxType::class, ['label' => 'psc_shop_cms.NoIndex', 'required' => false])
->add('rawText', CheckboxType::class, ['label' => 'psc_shop_cms.rawText', 'required' => false]) ->add('editorMode', ChoiceType::class, [
'label' => 'psc_shop_cms.editorMode',
'choices' => [
'psc_shop_cms.editorMode.wysiwyg' => 'wysiwyg',
'psc_shop_cms.editorMode.html' => 'html',
],
'required' => true,
])
->add('displayTitle', CheckboxType::class, ['label' => 'psc_shop_cms.DisplayTitle', 'required' => false]) ->add('displayTitle', CheckboxType::class, ['label' => 'psc_shop_cms.DisplayTitle', 'required' => false])
->add('sort', IntegerType::class, ['label' => 'psc_shop_cms.Sort', 'required' => false]) ->add('sort', IntegerType::class, ['label' => 'psc_shop_cms.Sort', 'required' => false])
->add('url', TextType::class, ['label' => 'psc_shop_cms.Url', 'required' => true]) ->add('url', TextType::class, ['label' => 'psc_shop_cms.Url', 'required' => true])
@ -127,29 +134,6 @@ class CmsType extends AbstractType
->getPositionsAsArray(); ->getPositionsAsArray();
}), }),
]); ]);
if ($options['data']->isRawText()) {
$builder->add('text', AceEditorType::class, [
'label' => 'psc_shop_cms.Text',
'wrapper_attr' => [], // aceeditor wrapper html attributes.
'width' => '90%',
'height' => '500',
'font_size' => 14,
'mode' => 'ace/mode/html', // every single default mode must have ace/mode/* prefix
'theme' => 'ace/theme/monokai', // every single default theme must have ace/theme/* prefix
'tab_size' => null,
'read_only' => null,
'use_soft_tabs' => null,
'use_wrap_mode' => null,
'show_print_margin' => null,
'required' => false,
'highlight_active_line' => null,
]);
} else {
$builder->add('text', TextareaType::class, [
'label' => 'psc_shop_cms.Text',
'required' => false,
]);
}
$builder $builder
->add('metaAuthor', TextType::class, ['label' => 'psc_shop_cms.MetaAuthor', 'required' => false]) ->add('metaAuthor', TextType::class, ['label' => 'psc_shop_cms.MetaAuthor', 'required' => false])
->add('metaKeywords', TextAreaType::class, ['label' => 'psc_shop_cms.MetaKeywords', 'required' => false]) ->add('metaKeywords', TextAreaType::class, ['label' => 'psc_shop_cms.MetaKeywords', 'required' => false])
@ -177,12 +161,12 @@ class CmsType extends AbstractType
]); ]);
/** @var \PSC\System\PluginBundle\Form\Interfaces\Field $field */ /** @var \PSC\System\PluginBundle\Form\Interfaces\Field $field */
foreach ($this->fields->getFields(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms) as $field) { foreach ($this->fields->getFields(\PSC\System\PluginBundle\Form\Interfaces\Field::Cms) as $field) {
$builder->add($field->buildForm($this->formFactory->createNamedBuilder( $var = $field->buildForm($this->formFactory->createNamedBuilder($field->getGroup(), FormType::class, null, [
$field->getGroup(), 'mapped' => false,
FormType::class, ]), $options);
null, if ($var->count() > 0) {
['mapped' => false], $builder->add($var);
), $options)); }
} }
$builder->add('save', SubmitType::class, ['label' => 'psc_shop_cms.Save']); $builder->add('save', SubmitType::class, ['label' => 'psc_shop_cms.Save']);

View File

@ -0,0 +1,73 @@
<?php
namespace PSC\Shop\CmsBundle\Form\Field;
use PSC\Libraries\AceEditorBundle\Form\Extension\AceEditorType;
use PSC\System\PluginBundle\Form\Interfaces\Field;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
#[AutoconfigureTag('psc.backend.custom.fields')]
class HtmlTextContent implements Field
{
public function getModule(): int
{
return Field::Cms;
}
public function getGroup(): string
{
return 'html';
}
public function getTemplate(): string
{
return '@PSCShopCms/backend/edit/fields/html_content.html.twig';
}
public function buildForm(FormBuilderInterface $builder, array $options): FormBuilderInterface
{
if ($options['data']->getEditorMode() == 'html') {
$builder->add('text', AceEditorType::class, [
'label' => 'psc_shop_cms.Text',
'wrapper_attr' => [], // aceeditor wrapper html attributes.
'width' => '90%',
'height' => '500',
'font_size' => 14,
'mode' => 'ace/mode/html', // every single default mode must have ace/mode/* prefix
'theme' => 'ace/theme/monokai', // every single default theme must have ace/theme/* prefix
'tab_size' => null,
'read_only' => null,
'use_soft_tabs' => null,
'use_wrap_mode' => null,
'show_print_margin' => null,
'required' => false,
'highlight_active_line' => null,
]);
}
return $builder;
}
public function formPreSetData(FormEvent $event): void {}
public function formPostSetData(FormEvent $event): void
{
$data = $event->getData();
if ($data->getEditorMode() == 'html') {
$event->getForm()->get('html')->get('text')->setData($data->getText());
}
}
public function formPreSubmit(FormEvent $event): void {}
public function formPostSubmit(FormEvent $event): void {}
public function formSubmit(FormEvent $event): void
{
$data = $event->getData();
if ($data->getEditorMode() == 'html') {
$data->setText($event->getForm()->get('html')->get('text')->getData());
}
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace PSC\Shop\CmsBundle\Form\Field;
use PSC\System\PluginBundle\Form\Interfaces\Field;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
#[AutoconfigureTag('psc.backend.custom.fields')]
class WysiwygTextContent implements Field
{
public function getModule(): int
{
return Field::Cms;
}
public function getGroup(): string
{
return 'wysiwyg';
}
public function getTemplate(): string
{
return '@PSCShopCms/backend/edit/fields/text_content.html.twig';
}
public function buildForm(FormBuilderInterface $builder, array $options): FormBuilderInterface
{
if ($options['data']->getEditorMode() == 'wysiwyg') {
$builder->add('text', TextareaType::class, [
'label' => 'psc_shop_cms.Text',
'required' => false,
]);
}
return $builder;
}
public function formPreSetData(FormEvent $event): void {}
public function formPostSetData(FormEvent $event): void
{
$data = $event->getData();
if ($data->getEditorMode() == 'wysiwyg') {
$event->getForm()->get('wysiwyg')->get('text')->setData($data->getText());
}
}
public function formPreSubmit(FormEvent $event): void {}
public function formPostSubmit(FormEvent $event): void {}
public function formSubmit(FormEvent $event): void
{
$data = $event->getData();
if ($data->getEditorMode() == 'wysiwyg') {
$data->setText($event->getForm()->get('wysiwyg')->get('text')->getData());
}
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace PSC\Shop\CmsBundle\Form\Group;
use PSC\System\PluginBundle\Form\Group;
use PSC\System\PluginBundle\Form\Interfaces\Group as GroupInterface;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('psc.backend.custom.groups')]
class HtmlText extends Group
{
protected $title = 'psc_shop_cms.Html';
public function getId(): string
{
return 'html';
}
public function getModule()
{
return GroupInterface::Cms;
}
public function getEditorMode(): string
{
return 'html';
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace PSC\Shop\CmsBundle\Form\Group;
use PSC\System\PluginBundle\Form\Group;
use PSC\System\PluginBundle\Form\Interfaces\Group as GroupInterface;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('psc.backend.custom.groups')]
class WysiwygText extends Group
{
protected $title = 'psc_shop_cms.Text';
public function getId(): string
{
return 'wysiwyg';
}
public function getModule()
{
return GroupInterface::Cms;
}
public function getEditorMode(): string
{
return 'wysiwyg';
}
}

View File

@ -6,9 +6,6 @@ services:
PSC\Shop\CmsBundle\: PSC\Shop\CmsBundle\:
resource: '../../*/*' resource: '../../*/*'
PSC\Shop\CmsBundle\Form\Backend\CmsType:
tags:
- { name: form.type }
PSC\Shop\CmsBundle\EventListener\ConfigureMenuListener: PSC\Shop\CmsBundle\EventListener\ConfigureMenuListener:
tags: tags:
- { name: kernel.event_listener, event: psc.backend.main, method: onMenuConfigureMain } - { name: kernel.event_listener, event: psc.backend.main, method: onMenuConfigureMain }

View File

@ -2,6 +2,14 @@ psc_shop_cms:
List: Liste List: Liste
Filter: Filter Filter: Filter
rawText: Visuellen Editor ausschalten? rawText: Visuellen Editor ausschalten?
editorMode: Editor Modus
editorMode.wysiwyg: WYSIWYG
Wysiwyg: WYSIWYG
editorMode.html: HTML
Html: HTML
HTML: HTML
editorMode.formbuilder: FormBuilder
formbuilderInfo: Der Inhalt dieser Seite wird über den FormBuilder verwaltet.
Search: Suche Search: Suche
Active: Aktiv Active: Aktiv
Title: Titel Title: Titel

View File

@ -10,6 +10,11 @@ psc_shop_cms:
addSite: Add Site addSite: Add Site
Yes: Yes Yes: Yes
No: No No: No
editorMode: Editor Mode
editorMode.wysiwyg: WYSIWYG
editorMode.html: HTML
editorMode.formbuilder: FormBuilder
formbuilderInfo: The content of this page is managed via the FormBuilder.
Site: Site Site: Site
Create: Create Create: Create
Common: Common Common: Common

View File

@ -33,12 +33,6 @@
</svg> </svg>
{{ 'psc_shop_cms.Common'|trans }} {{ 'psc_shop_cms.Common'|trans }}
</a> </a>
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="text">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />
</svg>
{{ 'psc_shop_cms.Text'|trans }}
</a>
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="seo"> <a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="seo">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" /> <path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
@ -53,7 +47,7 @@
{{ 'psc_shop_cms.Extended'|trans }} {{ 'psc_shop_cms.Extended'|trans }}
</a> </a>
{% for customGroup in customGroups %} {% for customGroup in customGroups %}
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="{{ customGroup.id }}"> <a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="{{ customGroup.id }}"{% if customGroup.editorMode is defined and customGroup.editorMode %} data-cms-editor-mode="{{ customGroup.editorMode }}"{% if 'wysiwyg' not in customGroup.editorMode|split(',') %} style="display:none"{% endif %}{% endif %}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@ -103,19 +97,8 @@
<div class="w-full lg:w-4/12 px-4"> <div class="w-full lg:w-4/12 px-4">
{{ form_row(form.displayOnlyWhenLoggedIn) }} {{ form_row(form.displayOnlyWhenLoggedIn) }}
</div> </div>
</div>
</div>
<div id="text" class="tab-content w-full text-stone-500 text-sm hidden">
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{ 'psc_shop_cms.Text'|trans }}</h6>
<div class="flex flex-wrap">
<div class="w-full lg:w-4/12 px-4"> <div class="w-full lg:w-4/12 px-4">
{{ form_row(form.rawText) }} {{ form_row(form.editorMode) }}
</div>
</div>
<div class="flex flex-wrap">
<div class="w-full px-4">
{{ form_row(form.text, {attr: {'class': 'form-control summernote'}}) }}
</div> </div>
</div> </div>
</div> </div>
@ -183,7 +166,7 @@
</div> </div>
{% for customGroup in customGroups %} {% for customGroup in customGroups %}
<div id="{{ customGroup.id }}" class="tab-content w-full text-stone-500 text-sm hidden"> <div id="{{ customGroup.id }}" class="tab-content w-full text-stone-500 text-sm hidden"{% if customGroup.editorMode is defined and customGroup.editorMode %} data-cms-editor-mode="{{ customGroup.editorMode }}"{% endif %}>
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{ customGroup.title }}</h6> <h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{ customGroup.title }}</h6>
{% for customField in customFields %} {% for customField in customFields %}
{% if customField.group == customGroup.id and customField.getTemplate %} {% if customField.group == customGroup.id and customField.getTemplate %}

View File

@ -33,12 +33,6 @@
</svg> </svg>
{{ 'psc_shop_cms.Common'|trans }} {{ 'psc_shop_cms.Common'|trans }}
</a> </a>
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="text">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />
</svg>
{{ 'psc_shop_cms.Text'|trans }}
</a>
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="seo"> <a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="seo">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" /> <path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
@ -53,12 +47,12 @@
{{ 'psc_shop_cms.Extended'|trans }} {{ 'psc_shop_cms.Extended'|trans }}
</a> </a>
{% for customGroup in customGroups %} {% for customGroup in customGroups %}
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="{{ customGroup.id }}"> <a href="#" class="tab-link flex items-center text-sm px-4 py-2 relative" data-dui-tab-target="{{ customGroup.id }}"{% if customGroup.editorMode is defined and customGroup.editorMode %} data-cms-editor-mode="{{ customGroup.editorMode }}"{% if cms.editorMode not in customGroup.editorMode|split(',') %} style="display:none"{% endif %}{% endif %}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg> </svg>
{{ customGroup.title }} {{ customGroup.title|trans }}
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
@ -103,23 +97,8 @@
<div class="w-full lg:w-4/12 px-4"> <div class="w-full lg:w-4/12 px-4">
{{ form_row(form.displayOnlyWhenLoggedIn) }} {{ form_row(form.displayOnlyWhenLoggedIn) }}
</div> </div>
</div>
</div>
<div id="text" class="tab-content w-full text-stone-500 text-sm hidden">
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{ 'psc_shop_cms.Text'|trans }}</h6>
<div class="flex flex-wrap">
<div class="w-full lg:w-4/12 px-4"> <div class="w-full lg:w-4/12 px-4">
{{ form_row(form.rawText) }} {{ form_row(form.editorMode) }}
</div>
</div>
<div class="flex flex-wrap">
<div class="w-full px-4">
{% if cms.rawText %}
{{ form_row(form.text) }}
{% else %}
{{ form_row(form.text, {attr: {'class': 'form-control summernote'}}) }}
{% endif %}
</div> </div>
</div> </div>
</div> </div>
@ -187,24 +166,32 @@
</div> </div>
{% for customGroup in customGroups %} {% for customGroup in customGroups %}
<div id="{{ customGroup.id }}" class="tab-content w-full text-stone-500 text-sm hidden"> {% if customGroup.editorMode is defined and customGroup.editorMode %}
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{ customGroup.title }}</h6> {% if cms.editorMode in customGroup.editorMode|split(',') %}
{% for customField in customFields %} <div id="{{ customGroup.id }}" class="tab-content w-full text-stone-500 text-sm hidden"{% if customGroup.editorMode is defined and customGroup.editorMode %} data-cms-editor-mode="{{ customGroup.editorMode }}"{% endif %}>
{% if customField.group == customGroup.id and customField.getTemplate %} <h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{ customGroup.title|trans }}</h6>
{{ include(customField.getTemplate, { 'form': form }) }} {% for customField in customFields %}
{% endif %} {% if customField.group == customGroup.id and customField.getTemplate %}
{% endfor %} {{ include(customField.getTemplate, { 'form': form }) }}
</div> {% endif %}
{% endfor %}
</div>
{% endif %}
{% else %}
<div id="{{ customGroup.id }}" class="tab-content w-full text-stone-500 text-sm hidden">
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">{{ customGroup.title }}</h6>
{% for customField in customFields %}
{% if customField.group == customGroup.id and customField.getTemplate %}
{% dump(customField) %}
{{ include(customField.getTemplate, { 'form': form }) }}
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
{% for customField in customFields %}
{% if customField.group == 'general' and customField.getTemplate %}
{{ include(customField.getTemplate, { 'form': form }) }}
{% endif %}
{% endfor %}
<div class="text-end my-2"> <div class="text-end my-2">
<button type="submit" name="{{ form.save.vars.full_name }}" class="inline-flex items-center justify-center py-1 gap-1 font-medium rounded-sm px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem]"> <button type="submit" name="{{ form.save.vars.full_name }}" class="inline-flex items-center justify-center py-1 gap-1 font-medium rounded-sm px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem]">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">

View File

@ -0,0 +1,5 @@
<div class="flex flex-wrap">
<div class="w-full px-4">
{{ form_row(form.html.text, {attr: {'class': 'form-control'}}) }}
</div>
</div>

View File

@ -0,0 +1,5 @@
<div class="flex flex-wrap">
<div class="w-full px-4">
{{ form_row(form.wysiwyg.text, {attr: {'class': 'form-control summernote'}}) }}
</div>
</div>

View File

@ -30,8 +30,8 @@ class Cms
#[Field(type: 'boolean')] #[Field(type: 'boolean')]
protected bool $noIndex = false; protected bool $noIndex = false;
#[Field(type: 'boolean')] #[Field(type: 'string')]
protected bool $rawText = false; protected string $editorMode = 'wysiwyg';
#[Field(type: 'hash')] #[Field(type: 'hash')]
protected $pluginSettings = []; protected $pluginSettings = [];
@ -124,12 +124,22 @@ class Cms
public function isRawText(): bool public function isRawText(): bool
{ {
return (bool)$this->rawText; return $this->editorMode === 'html';
} }
public function setRawText(bool $var): void public function setRawText(bool $var): void
{ {
$this->rawText = $var; $this->editorMode = $var ? 'html' : 'wysiwyg';
}
public function getEditorMode(): string
{
return $this->editorMode ?: 'wysiwyg';
}
public function setEditorMode(string $editorMode): void
{
$this->editorMode = $editorMode;
} }
} }

View File

@ -30,7 +30,7 @@ class Cms
protected $extraSettings; protected $extraSettings;
protected $noIndex = false; protected $noIndex = false;
protected $rawText = false; protected $editorMode = 'wysiwyg';
protected $pluginSettings = []; protected $pluginSettings = [];
public function __toString(): string public function __toString(): string
@ -697,11 +697,21 @@ class Cms
public function isRawText(): bool public function isRawText(): bool
{ {
return (bool)$this->rawText; return $this->editorMode === 'html';
} }
public function setRawText(bool $rawText): void public function setRawText(bool $rawText): void
{ {
$this->rawText = $rawText; $this->editorMode = $rawText ? 'html' : 'wysiwyg';
}
public function getEditorMode(): string
{
return $this->editorMode ?: 'wysiwyg';
}
public function setEditorMode(string $editorMode): void
{
$this->editorMode = $editorMode;
} }
} }

View File

@ -29,4 +29,9 @@ abstract class Group implements \PSC\System\PluginBundle\Form\Interfaces\Group
{ {
return md5($this->title); return md5($this->title);
} }
public function getEditorMode(): string
{
return '';
}
} }

View File

@ -29,4 +29,5 @@ interface Group
public function getTitle(); public function getTitle();
public function getId(); public function getId();
public function getModule(); public function getModule();
public function getEditorMode(): string;
} }

View File

@ -0,0 +1,56 @@
<?php
namespace Plugin\Custom\PSC\FormBuilder\Form\Field;
use PSC\System\PluginBundle\Form\Interfaces\Field;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
#[AutoconfigureTag('psc.backend.custom.fields')]
class CmsEditorMode implements Field
{
public function getModule(): int
{
return Field::Cms;
}
public function getGroup(): string
{
return Field::GroupGeneral;
}
public function getTemplate(): string
{
return '';
}
public function buildForm(FormBuilderInterface $builder, array $options): FormBuilderInterface
{
return $builder;
}
public function formPreSetData(FormEvent $event): void
{
$form = $event->getForm();
if ($form->has('editorMode')) {
$editorModeField = $form->get('editorMode');
$config = $editorModeField->getConfig();
$options = $config->getOptions();
$options['choices']['psc_shop_cms.editorMode.formbuilder'] = 'formbuilder';
$form->add('editorMode', ChoiceType::class, $options);
}
}
public function formPostSetData(FormEvent $event): void {}
public function formPreSubmit(FormEvent $event): void {}
public function formPostSubmit(FormEvent $event): void {}
public function formSubmit(FormEvent $event): void {}
}

View File

@ -0,0 +1,42 @@
<?php
namespace Plugin\Custom\PSC\FormBuilder\Form\Field;
use PSC\System\PluginBundle\Form\Interfaces\Field;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
#[AutoconfigureTag('psc.backend.custom.fields')]
class CmsFormBuilderContent implements Field
{
public function getModule(): int
{
return Field::Cms;
}
public function getGroup(): string
{
return 'formbuilder';
}
public function getTemplate(): string
{
return '@PluginCustomPSCFormBuilder/form/cms_formbuilder.html.twig';
}
public function buildForm(FormBuilderInterface $builder, array $options): FormBuilderInterface
{
return $builder;
}
public function formPreSetData(FormEvent $event): void {}
public function formPostSetData(FormEvent $event): void {}
public function formPreSubmit(FormEvent $event): void {}
public function formPostSubmit(FormEvent $event): void {}
public function formSubmit(FormEvent $event): void {}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Plugin\Custom\PSC\FormBuilder\Form\Group;
use PSC\System\PluginBundle\Form\Group;
use PSC\System\PluginBundle\Form\Interfaces\Group as GroupInterface;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('psc.backend.custom.groups')]
class CmsFormBuilder extends Group
{
protected $title = 'FormBuilder';
public function getId(): string
{
return 'formbuilder';
}
public function getModule()
{
return GroupInterface::Cms;
}
public function getEditorMode(): string
{
return 'formbuilder';
}
}

View File

@ -5,7 +5,3 @@ services:
Plugin\Custom\PSC\FormBuilder\: Plugin\Custom\PSC\FormBuilder\:
resource: '../../*/*' resource: '../../*/*'
Plugin\Custom\PSC\FormBuilder\Ui\OpenButton:
tags:
- { name: psc.backend.custom.buttons, productType: 6 }

View File

@ -0,0 +1,15 @@
<div class="rounded-md border border-gray-200 bg-gray-50 p-4 dark:border-strokedark dark:bg-boxdark-2">
<div class="flex items-center justify-between">
<p class="text-sm text-gray-600 dark:text-gray-400">{{ 'psc_shop_cms.formbuilderInfo'|trans }}</p>
{% if cms is defined and cms.uid %}
<a target="_blank" href="{{ path('psc_plugin_formbuilder_edit') }}?mode=cms&uuid={{ cms.uid }}&shop={{ cms.shop.uuid }}" class="inline-flex items-center justify-center py-2 gap-2 font-medium rounded-md px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
</svg>
FormBuilder
</a>
{% else %}
<span class="text-sm text-gray-400">{{ 'psc_shop_cms.formbuilderInfo'|trans }}</span>
{% endif %}
</div>
</div>