Compare commits
2
Commits
a4e479490b
...
be9a676d9d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be9a676d9d | ||
|
|
06e98a429b |
@@ -42,6 +42,14 @@ services:
|
||||
tags:
|
||||
- { name: form.type }
|
||||
|
||||
websmid.customhtml.form.type.customhtml_slide:
|
||||
public: true
|
||||
class: 'Websmid\CustomHtml\Form\Type\CustomHtmlSlideType'
|
||||
arguments:
|
||||
- '@translator'
|
||||
tags:
|
||||
- { name: form.type }
|
||||
|
||||
websmid.customhtml.form.type.customhtml_block:
|
||||
public: true
|
||||
class: 'Websmid\CustomHtml\Form\Type\CustomHtmlBlockType'
|
||||
|
||||
@@ -15,8 +15,25 @@ class Config
|
||||
'faq' => 'FAQ Accordion',
|
||||
'banner' => 'Banner',
|
||||
'alert' => 'Alert',
|
||||
'usp' => 'USP',
|
||||
'slider' => 'Slider',
|
||||
];
|
||||
|
||||
const SLIDER_DEFAULT_SLIDES_PER_VIEW_MOBILE = 1;
|
||||
|
||||
const SLIDER_DEFAULT_SLIDES_PER_VIEW_TABLET = 2;
|
||||
|
||||
const SLIDER_DEFAULT_SLIDES_PER_VIEW_DESKTOP = 3;
|
||||
|
||||
const SLIDER_MODES = [
|
||||
'always' => 'Always show as a slider',
|
||||
'responsive' => 'Slider on mobile/tablet, static grid on desktop',
|
||||
];
|
||||
|
||||
const SLIDER_DEFAULT_MODE = 'always';
|
||||
|
||||
const SLIDER_RESPONSIVE_BREAKPOINT = 480;
|
||||
|
||||
const ALERT_STYLES = [
|
||||
'success' => 'Success',
|
||||
'info' => 'Info',
|
||||
|
||||
@@ -6,6 +6,7 @@ use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataHandler\FormDataHandl
|
||||
use Websmid\CustomHtml\Config\Config;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlFaq;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlSlide;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Db;
|
||||
use Exception;
|
||||
@@ -27,8 +28,14 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
||||
$block->description = (string) ($formData['description'] ?? '');
|
||||
$block->extra_description = (string) ($formData['extra_description'] ?? '');
|
||||
$block->link = (string) ($formData['link'] ?? '');
|
||||
$block->link_text = (string) ($formData['link_text'] ?? '');
|
||||
$block->alert_type = (string) ($formData['alert_type'] ?? 'info');
|
||||
$block->timeout = (int) ($formData['timeout'] ?? 0);
|
||||
$block->slider_mode = (string) ($formData['slider_mode'] ?? Config::SLIDER_DEFAULT_MODE);
|
||||
$block->slides_per_view_mobile = (float) ($formData['slides_per_view_mobile'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_MOBILE);
|
||||
$block->slides_per_view_tablet = (float) ($formData['slides_per_view_tablet'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_TABLET);
|
||||
$block->slides_per_view_desktop = (float) ($formData['slides_per_view_desktop'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_DESKTOP);
|
||||
$block->autoplay_delay = (int) ($formData['autoplay_delay'] ?? 0);
|
||||
$block->image = $this->saveUploadedImage($formData['image'] ?? null, '');
|
||||
$block->active = (int) $formData['active'];
|
||||
$block->ordering = $this->getNextOrdering($idGroup);
|
||||
@@ -38,6 +45,7 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
||||
}
|
||||
|
||||
$this->saveFaqs((int) $block->id, $formData['faqs'] ?? []);
|
||||
$this->saveSlides((int) $block->id, $formData['slides'] ?? []);
|
||||
|
||||
return $block->id;
|
||||
}
|
||||
@@ -59,8 +67,14 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
||||
$block->description = (string) ($formData['description'] ?? '');
|
||||
$block->extra_description = (string) ($formData['extra_description'] ?? '');
|
||||
$block->link = (string) ($formData['link'] ?? '');
|
||||
$block->link_text = (string) ($formData['link_text'] ?? '');
|
||||
$block->alert_type = (string) ($formData['alert_type'] ?? 'info');
|
||||
$block->timeout = (int) ($formData['timeout'] ?? 0);
|
||||
$block->slider_mode = (string) ($formData['slider_mode'] ?? Config::SLIDER_DEFAULT_MODE);
|
||||
$block->slides_per_view_mobile = (float) ($formData['slides_per_view_mobile'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_MOBILE);
|
||||
$block->slides_per_view_tablet = (float) ($formData['slides_per_view_tablet'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_TABLET);
|
||||
$block->slides_per_view_desktop = (float) ($formData['slides_per_view_desktop'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_DESKTOP);
|
||||
$block->autoplay_delay = (int) ($formData['autoplay_delay'] ?? 0);
|
||||
$block->image = $this->saveUploadedImage($formData['image'] ?? null, $block->image);
|
||||
$block->active = (int) $formData['active'];
|
||||
|
||||
@@ -69,6 +83,7 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
||||
}
|
||||
|
||||
$this->saveFaqs((int) $id, $formData['faqs'] ?? []);
|
||||
$this->saveSlides((int) $id, $formData['slides'] ?? []);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -143,4 +158,37 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
||||
$faq->add();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Slides are fully replaced on every save, like FAQ items — except a
|
||||
* slide's image can't round-trip through its file input, so the previous
|
||||
* filename is looked up by the slide's hidden id and reused whenever no
|
||||
* new file was uploaded for that row.
|
||||
*/
|
||||
private function saveSlides(int $idBlock, array $slides): void
|
||||
{
|
||||
$existingImages = [];
|
||||
|
||||
foreach (CustomHtmlSlide::getByBlockId($idBlock) as $existingSlide) {
|
||||
$existingImages[(int) $existingSlide['id_ws_customhtml_slide']] = $existingSlide['image'];
|
||||
}
|
||||
|
||||
CustomHtmlSlide::deleteByBlockId($idBlock);
|
||||
|
||||
foreach (array_values($slides) as $position => $slideData) {
|
||||
$existingId = (int) ($slideData['id'] ?? 0);
|
||||
$existingImage = $existingImages[$existingId] ?? '';
|
||||
|
||||
$slide = new CustomHtmlSlide();
|
||||
$slide->id_ws_customhtml = $idBlock;
|
||||
$slide->title = (string) ($slideData['title'] ?? '');
|
||||
$slide->description = (string) ($slideData['description'] ?? '');
|
||||
$slide->extra_description = (string) ($slideData['extra_description'] ?? '');
|
||||
$slide->link = (string) ($slideData['link'] ?? '');
|
||||
$slide->link_text = (string) ($slideData['link_text'] ?? '');
|
||||
$slide->image = $this->saveUploadedImage($slideData['image'] ?? null, $existingImage);
|
||||
$slide->ordering = $position;
|
||||
$slide->add();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,11 @@ final class CustomHtmlGroupDataHandler implements FormDataHandlerInterface
|
||||
public function create(array $formData)
|
||||
{
|
||||
$group = new CustomHtmlGroup();
|
||||
$group->title = (string) $formData['title'];
|
||||
$group->hook_name = (string) $formData['hook_name'];
|
||||
$group->active = (int) $formData['active'];
|
||||
$group->ordering = $this->getNextOrdering();
|
||||
$group->title = (string) $formData['title'];
|
||||
$group->hook_name = (string) $formData['hook_name'];
|
||||
$group->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||
$group->active = (int) $formData['active'];
|
||||
$group->ordering = $this->getNextOrdering();
|
||||
|
||||
if (!$group->add()) {
|
||||
return false;
|
||||
@@ -46,9 +47,10 @@ final class CustomHtmlGroupDataHandler implements FormDataHandlerInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
$group->title = (string) $formData['title'];
|
||||
$group->hook_name = (string) $formData['hook_name'];
|
||||
$group->active = (int) $formData['active'];
|
||||
$group->title = (string) $formData['title'];
|
||||
$group->hook_name = (string) $formData['hook_name'];
|
||||
$group->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||
$group->active = (int) $formData['active'];
|
||||
|
||||
if (!$group->update()) {
|
||||
return false;
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
namespace Websmid\CustomHtml\Form\DataProvider;
|
||||
|
||||
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataProvider\FormDataProviderInterface;
|
||||
use Websmid\CustomHtml\Config\Config;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlFaq;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlSlide;
|
||||
use Validate;
|
||||
|
||||
final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
||||
@@ -28,9 +30,16 @@ final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
||||
'description' => $block->description,
|
||||
'extra_description' => $block->extra_description,
|
||||
'link' => $block->link,
|
||||
'link_text' => $block->link_text,
|
||||
'alert_type' => $block->alert_type,
|
||||
'timeout' => (int) $block->timeout,
|
||||
'slider_mode' => $block->slider_mode,
|
||||
'slides_per_view_mobile' => (float) $block->slides_per_view_mobile,
|
||||
'slides_per_view_tablet' => (float) $block->slides_per_view_tablet,
|
||||
'slides_per_view_desktop' => (float) $block->slides_per_view_desktop,
|
||||
'autoplay_delay' => (int) $block->autoplay_delay,
|
||||
'faqs' => $this->loadFaqs((int) $id),
|
||||
'slides' => $this->loadSlides((int) $id),
|
||||
'active' => (bool) $block->active,
|
||||
];
|
||||
}
|
||||
@@ -48,9 +57,16 @@ final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
||||
'description' => '',
|
||||
'extra_description' => '',
|
||||
'link' => '',
|
||||
'link_text' => '',
|
||||
'alert_type' => 'info',
|
||||
'timeout' => 0,
|
||||
'slider_mode' => Config::SLIDER_DEFAULT_MODE,
|
||||
'slides_per_view_mobile' => Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_MOBILE,
|
||||
'slides_per_view_tablet' => Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_TABLET,
|
||||
'slides_per_view_desktop' => Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_DESKTOP,
|
||||
'autoplay_delay' => 0,
|
||||
'faqs' => [],
|
||||
'slides' => [],
|
||||
'active' => true,
|
||||
];
|
||||
}
|
||||
@@ -64,4 +80,19 @@ final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
||||
];
|
||||
}, CustomHtmlFaq::getByBlockId($idBlock));
|
||||
}
|
||||
|
||||
private function loadSlides(int $idBlock): array
|
||||
{
|
||||
return array_map(static function (array $slide) {
|
||||
return [
|
||||
'id' => (int) $slide['id_ws_customhtml_slide'],
|
||||
'title' => $slide['title'],
|
||||
'description' => $slide['description'],
|
||||
'extra_description' => $slide['extra_description'],
|
||||
'link' => $slide['link'],
|
||||
'link_text' => $slide['link_text'],
|
||||
'image' => null,
|
||||
];
|
||||
}, CustomHtmlSlide::getByBlockId($idBlock));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,18 +17,20 @@ final class CustomHtmlGroupDataProvider implements FormDataProviderInterface
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => $group->title,
|
||||
'hook_name' => $group->hook_name,
|
||||
'active' => (bool) $group->active,
|
||||
'title' => $group->title,
|
||||
'hook_name' => $group->hook_name,
|
||||
'custom_class' => $group->custom_class,
|
||||
'active' => (bool) $group->active,
|
||||
];
|
||||
}
|
||||
|
||||
public function getDefaultData()
|
||||
{
|
||||
return [
|
||||
'title' => '',
|
||||
'hook_name' => '',
|
||||
'active' => true,
|
||||
'title' => '',
|
||||
'hook_name' => '',
|
||||
'custom_class' => '',
|
||||
'active' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use PrestaShop\PrestaShop\Core\Form\ConfigurableFormChoiceProviderInterface;
|
||||
@@ -58,9 +59,9 @@ class CustomHtmlBlockType extends AbstractType
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-html'],
|
||||
])
|
||||
->add('image', FileType::class, [
|
||||
'label' => $this->translator->trans('Banner image', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'label' => $this->translator->trans('Image', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-banner'],
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-banner customhtmlblock-type-usp'],
|
||||
])
|
||||
->add('faqs', CollectionType::class, [
|
||||
'entry_type' => CustomHtmlFaqType::class,
|
||||
@@ -70,6 +71,49 @@ class CustomHtmlBlockType extends AbstractType
|
||||
'prototype' => true,
|
||||
'required' => false,
|
||||
])
|
||||
->add('slides', CollectionType::class, [
|
||||
'entry_type' => CustomHtmlSlideType::class,
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
'by_reference' => false,
|
||||
'prototype' => true,
|
||||
'required' => false,
|
||||
])
|
||||
->add('slider_mode', ChoiceType::class, [
|
||||
'label' => $this->translator->trans('Slider mode', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'choices' => array_flip(Config::SLIDER_MODES),
|
||||
'required' => false,
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider'],
|
||||
])
|
||||
->add('slides_per_view_mobile', NumberType::class, [
|
||||
'label' => $this->translator->trans('Slides visible on mobile', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'scale' => 2,
|
||||
'attr' => ['min' => 0, 'step' => '0.05'],
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider col-4'],
|
||||
])
|
||||
->add('slides_per_view_tablet', NumberType::class, [
|
||||
'label' => $this->translator->trans('Slides visible on tablet', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'scale' => 2,
|
||||
'attr' => ['min' => 0, 'step' => '0.05'],
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider col-4'],
|
||||
])
|
||||
->add('slides_per_view_desktop', NumberType::class, [
|
||||
'label' => $this->translator->trans('Slides visible on desktop', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'scale' => 2,
|
||||
'attr' => ['min' => 0, 'step' => '0.05'],
|
||||
'help' => $this->translator->trans('In "static grid on desktop" mode this is rounded to the nearest whole number of columns.', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider col-4'],
|
||||
])
|
||||
->add('autoplay_delay', IntegerType::class, [
|
||||
'label' => $this->translator->trans('Autoplay delay (seconds)', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'attr' => ['min' => 0, 'placeholder' => '0'],
|
||||
'help' => $this->translator->trans('0 means the slider never auto-advances; visitors can still swipe or use the arrows.', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider'],
|
||||
])
|
||||
->add('alert_type', ChoiceType::class, [
|
||||
'label' => $this->translator->trans('Alert style', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'choices' => array_flip(Config::ALERT_STYLES),
|
||||
@@ -94,10 +138,16 @@ class CustomHtmlBlockType extends AbstractType
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-banner'],
|
||||
])
|
||||
->add('link', TextType::class, [
|
||||
'label' => $this->translator->trans('Link', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'label' => $this->translator->trans('Link URL', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'attr' => ['placeholder' => 'https://example.com or /internal-page'],
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-banner'],
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-banner customhtmlblock-type-usp customhtmlblock-type-alert col-6'],
|
||||
])
|
||||
->add('link_text', TextType::class, [
|
||||
'label' => $this->translator->trans('Link text', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'attr' => ['placeholder' => 'Learn more'],
|
||||
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-alert col-6'],
|
||||
])
|
||||
->add('custom_class', TextType::class, [
|
||||
'label' => $this->translator->trans('Custom classes', [], 'Modules.Wscustomhtml.Admin'),
|
||||
|
||||
@@ -28,6 +28,11 @@ class CustomHtmlGroupType extends AbstractType
|
||||
'label' => $this->translator->trans('Hook name', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => true,
|
||||
])
|
||||
->add('custom_class', TextType::class, [
|
||||
'label' => $this->translator->trans('Custom classes', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'attr' => ['placeholder' => 'col-md-6'],
|
||||
])
|
||||
->add('active', SwitchType::class, [
|
||||
'label' => $this->translator->trans('Active', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Websmid\CustomHtml\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class CustomHtmlSlideType extends AbstractType
|
||||
{
|
||||
private $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $formBuilder, array $options): void
|
||||
{
|
||||
$formBuilder
|
||||
->add('id', HiddenType::class, [
|
||||
'required' => false,
|
||||
])
|
||||
->add('title', TextType::class, [
|
||||
'label' => $this->translator->trans('Title', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
])
|
||||
->add('description', TextareaType::class, [
|
||||
'label' => $this->translator->trans('Description', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
])
|
||||
->add('extra_description', TextareaType::class, [
|
||||
'label' => $this->translator->trans('Extra description', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
])
|
||||
->add('link', TextType::class, [
|
||||
'label' => $this->translator->trans('Link URL', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'attr' => ['placeholder' => 'https://example.com or /internal-page'],
|
||||
])
|
||||
->add('link_text', TextType::class, [
|
||||
'label' => $this->translator->trans('Link text', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
'attr' => ['placeholder' => 'Learn more'],
|
||||
])
|
||||
->add('image', FileType::class, [
|
||||
'label' => $this->translator->trans('Image', [], 'Modules.Wscustomhtml.Admin'),
|
||||
'required' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,11 @@ final class CustomHtmlGroupGridDefinitionFactory extends AbstractGridDefinitionF
|
||||
->setName($this->trans('Hook', [], 'Modules.Wscustomhtml.Admin'))
|
||||
->setOptions(['field' => 'hook_name'])
|
||||
)
|
||||
->add(
|
||||
(new DataColumn('custom_class'))
|
||||
->setName($this->trans('Custom classes', [], 'Modules.Wscustomhtml.Admin'))
|
||||
->setOptions(['field' => 'custom_class'])
|
||||
)
|
||||
->add(
|
||||
(new DataColumn('blocks_count'))
|
||||
->setName($this->trans('Blocks', [], 'Modules.Wscustomhtml.Admin'))
|
||||
|
||||
@@ -32,6 +32,7 @@ final class CustomHtmlGroupQueryBuilder extends AbstractDoctrineQueryBuilder
|
||||
'wchg.`id_ws_customhtml_group`',
|
||||
'wchg.`title`',
|
||||
'wchg.`hook_name`',
|
||||
'wchg.`custom_class`',
|
||||
'wchg.`active`',
|
||||
'wchg.`ordering`',
|
||||
'wchg.`date_add`',
|
||||
|
||||
@@ -34,6 +34,9 @@ class CustomHtmlBlock extends ObjectModel
|
||||
/** @var string */
|
||||
public $link = '';
|
||||
|
||||
/** @var string */
|
||||
public $link_text = '';
|
||||
|
||||
/** @var string */
|
||||
public $image = '';
|
||||
|
||||
@@ -43,6 +46,21 @@ class CustomHtmlBlock extends ObjectModel
|
||||
/** @var int */
|
||||
public $timeout = 0;
|
||||
|
||||
/** @var string */
|
||||
public $slider_mode = 'always';
|
||||
|
||||
/** @var float */
|
||||
public $slides_per_view_mobile = 1;
|
||||
|
||||
/** @var float */
|
||||
public $slides_per_view_tablet = 2;
|
||||
|
||||
/** @var float */
|
||||
public $slides_per_view_desktop = 3;
|
||||
|
||||
/** @var int */
|
||||
public $autoplay_delay = 0;
|
||||
|
||||
/** @var int */
|
||||
public $active = 1;
|
||||
|
||||
@@ -70,9 +88,15 @@ class CustomHtmlBlock extends ObjectModel
|
||||
'description' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 1024],
|
||||
'extra_description' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 1024],
|
||||
'link' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 512],
|
||||
'link_text' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128],
|
||||
'image' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 255],
|
||||
'alert_type' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 16],
|
||||
'timeout' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => false],
|
||||
'slider_mode' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 16],
|
||||
'slides_per_view_mobile' => ['type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => false],
|
||||
'slides_per_view_tablet' => ['type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => false],
|
||||
'slides_per_view_desktop' => ['type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => false],
|
||||
'autoplay_delay' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => false],
|
||||
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'show_title' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||
@@ -105,7 +129,9 @@ class CustomHtmlBlock extends ObjectModel
|
||||
|
||||
$result = Db::getInstance()->executeS(
|
||||
'SELECT `id_ws_customhtml`, `id_ws_customhtml_group`, `title`, `type`, `content`, `custom_class`,
|
||||
`description`, `extra_description`, `link`, `image`, `alert_type`, `timeout`, `active`, `show_title`, `ordering`
|
||||
`description`, `extra_description`, `link`, `link_text`, `image`, `alert_type`, `timeout`,
|
||||
`slider_mode`, `slides_per_view_mobile`, `slides_per_view_tablet`, `slides_per_view_desktop`, `autoplay_delay`,
|
||||
`active`, `show_title`, `ordering`
|
||||
FROM `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||
WHERE `id_ws_customhtml_group` IN (' . implode(',', $groupIds) . ')
|
||||
AND `active` = 1
|
||||
|
||||
@@ -16,6 +16,9 @@ class CustomHtmlGroup extends ObjectModel
|
||||
/** @var string */
|
||||
public $title = '';
|
||||
|
||||
/** @var string */
|
||||
public $custom_class = '';
|
||||
|
||||
/** @var int */
|
||||
public $active = 1;
|
||||
|
||||
@@ -34,6 +37,7 @@ class CustomHtmlGroup extends ObjectModel
|
||||
'fields' => [
|
||||
'hook_name' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64],
|
||||
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 256],
|
||||
'custom_class' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128],
|
||||
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
@@ -44,7 +48,7 @@ class CustomHtmlGroup extends ObjectModel
|
||||
public static function getActiveByHookName(string $hookName): array
|
||||
{
|
||||
$result = Db::getInstance()->executeS(
|
||||
'SELECT `id_ws_customhtml_group`, `title`, `active`, `ordering`
|
||||
'SELECT `id_ws_customhtml_group`, `title`, `active`, `custom_class`, `ordering`
|
||||
FROM `' . _DB_PREFIX_ . 'ws_customhtml_group`
|
||||
WHERE `hook_name` = \'' . pSQL($hookName) . '\'
|
||||
AND `active` = 1
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Websmid\CustomHtml\Model;
|
||||
|
||||
use ObjectModel;
|
||||
use Db;
|
||||
|
||||
class CustomHtmlSlide extends ObjectModel
|
||||
{
|
||||
/** @var int */
|
||||
public $id;
|
||||
|
||||
/** @var int */
|
||||
public $id_ws_customhtml;
|
||||
|
||||
/** @var string */
|
||||
public $title = '';
|
||||
|
||||
/** @var string */
|
||||
public $description = '';
|
||||
|
||||
/** @var string */
|
||||
public $extra_description = '';
|
||||
|
||||
/** @var string */
|
||||
public $link = '';
|
||||
|
||||
/** @var string */
|
||||
public $link_text = '';
|
||||
|
||||
/** @var string */
|
||||
public $image = '';
|
||||
|
||||
/** @var int */
|
||||
public $ordering = 0;
|
||||
|
||||
/** @var string */
|
||||
public $date_add;
|
||||
|
||||
/** @var string */
|
||||
public $date_upd;
|
||||
|
||||
public static $definition = [
|
||||
'table' => 'ws_customhtml_slide',
|
||||
'primary' => 'id_ws_customhtml_slide',
|
||||
'fields' => [
|
||||
'id_ws_customhtml' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 256],
|
||||
'description' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 1024],
|
||||
'extra_description' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 1024],
|
||||
'link' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 512],
|
||||
'link_text' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128],
|
||||
'image' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 255],
|
||||
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
],
|
||||
];
|
||||
|
||||
public static function getByBlockId(int $idBlock): array
|
||||
{
|
||||
$result = Db::getInstance()->executeS(
|
||||
'SELECT `id_ws_customhtml_slide`, `title`, `description`, `extra_description`, `link`, `link_text`, `image`, `ordering`
|
||||
FROM `' . _DB_PREFIX_ . 'ws_customhtml_slide`
|
||||
WHERE `id_ws_customhtml` = ' . (int) $idBlock . '
|
||||
ORDER BY `ordering` ASC'
|
||||
);
|
||||
|
||||
return $result ?: [];
|
||||
}
|
||||
|
||||
public static function deleteByBlockId(int $idBlock): void
|
||||
{
|
||||
Db::getInstance()->delete('ws_customhtml_slide', '`id_ws_customhtml` = ' . (int) $idBlock);
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
namespace Websmid\CustomHtml\Module;
|
||||
|
||||
use Websmid\CustomHtml\Config\Config;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlFaq;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlGroup;
|
||||
use Websmid\CustomHtml\Model\CustomHtmlSlide;
|
||||
use Context;
|
||||
|
||||
trait DisplayHooks
|
||||
@@ -69,7 +71,8 @@ trait DisplayHooks
|
||||
|
||||
$blocksByGroup = CustomHtmlBlock::getActiveByGroupIds(array_column($groups, 'id_ws_customhtml_group'));
|
||||
$blocksByGroup = $this->attachFaqsToBlocks($blocksByGroup);
|
||||
$blocksByGroup = $this->attachBannerImageUrls($blocksByGroup);
|
||||
$blocksByGroup = $this->attachImageUrls($blocksByGroup);
|
||||
$blocksByGroup = $this->attachSlidesToBlocks($blocksByGroup);
|
||||
|
||||
$groups = array_map(static function (array $group) use ($blocksByGroup) {
|
||||
$group['blocks'] = $blocksByGroup[(int) $group['id_ws_customhtml_group']] ?? [];
|
||||
@@ -95,11 +98,11 @@ trait DisplayHooks
|
||||
}, $blocksByGroup);
|
||||
}
|
||||
|
||||
private function attachBannerImageUrls(array $blocksByGroup): array
|
||||
private function attachImageUrls(array $blocksByGroup): array
|
||||
{
|
||||
return array_map(static function (array $blocks) {
|
||||
return array_map(static function (array $block) {
|
||||
if ($block['type'] === 'banner') {
|
||||
if (in_array($block['type'], ['banner', 'usp'], true)) {
|
||||
$block['image_url'] = CustomHtmlBlock::getBannerImageUrl($block['image']);
|
||||
}
|
||||
|
||||
@@ -107,4 +110,67 @@ trait DisplayHooks
|
||||
}, $blocks);
|
||||
}, $blocksByGroup);
|
||||
}
|
||||
|
||||
private function attachSlidesToBlocks(array $blocksByGroup): array
|
||||
{
|
||||
return array_map(function (array $blocks) {
|
||||
return array_map(function (array $block) {
|
||||
if ($block['type'] === 'slider') {
|
||||
$block['slides'] = $this->loadSlidesForBlock((int) $block['id_ws_customhtml']);
|
||||
$block['slider_config'] = $this->buildSliderConfig($block);
|
||||
$block['slider_desktop_column_width'] = $this->buildSliderDesktopColumnWidth($block);
|
||||
}
|
||||
|
||||
return $block;
|
||||
}, $blocks);
|
||||
}, $blocksByGroup);
|
||||
}
|
||||
|
||||
private function loadSlidesForBlock(int $idBlock): array
|
||||
{
|
||||
return array_map(static function (array $slide) {
|
||||
$slide['image_url'] = CustomHtmlBlock::getBannerImageUrl($slide['image']);
|
||||
$slide['show_title'] = true;
|
||||
|
||||
return $slide;
|
||||
}, CustomHtmlSlide::getByBlockId($idBlock));
|
||||
}
|
||||
|
||||
private function buildSliderConfig(array $block): string
|
||||
{
|
||||
$config = [
|
||||
'slidesPerView' => (float) $block['slides_per_view_mobile'],
|
||||
'spaceBetween' => 16,
|
||||
'speed' => 500,
|
||||
'watchOverflow' => true,
|
||||
];
|
||||
|
||||
if ($block['slider_mode'] === 'responsive') {
|
||||
$config['breakpoints'] = [
|
||||
Config::SLIDER_RESPONSIVE_BREAKPOINT => ['slidesPerView' => (float) $block['slides_per_view_tablet']],
|
||||
];
|
||||
} else {
|
||||
$config['breakpoints'] = [
|
||||
768 => ['slidesPerView' => (float) $block['slides_per_view_tablet']],
|
||||
992 => ['slidesPerView' => (float) $block['slides_per_view_desktop']],
|
||||
];
|
||||
}
|
||||
|
||||
if ((int) $block['autoplay_delay'] > 0) {
|
||||
$config['loop'] = true;
|
||||
$config['autoplay'] = [
|
||||
'delay' => (int) $block['autoplay_delay'] * 1000,
|
||||
'disableOnInteraction' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return json_encode($config);
|
||||
}
|
||||
|
||||
private function buildSliderDesktopColumnWidth(array $block): string
|
||||
{
|
||||
$columns = max(1, (int) round((float) $block['slides_per_view_desktop']));
|
||||
|
||||
return round(100 / $columns, 4) . '%';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ trait Install
|
||||
`id_ws_customhtml_group` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`hook_name` VARCHAR(64) NOT NULL,
|
||||
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
||||
`custom_class` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||
`date_add` DATETIME NOT NULL,
|
||||
@@ -68,7 +69,15 @@ trait Install
|
||||
`description` TEXT,
|
||||
`extra_description` TEXT,
|
||||
`link` VARCHAR(512) NOT NULL DEFAULT \'\',
|
||||
`link_text` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||
`image` VARCHAR(255) NOT NULL DEFAULT \'\',
|
||||
`alert_type` VARCHAR(16) NOT NULL DEFAULT \'info\',
|
||||
`timeout` INT(11) NOT NULL DEFAULT 0,
|
||||
`slider_mode` VARCHAR(16) NOT NULL DEFAULT \'always\',
|
||||
`slides_per_view_mobile` DECIMAL(4,2) NOT NULL DEFAULT 1,
|
||||
`slides_per_view_tablet` DECIMAL(4,2) NOT NULL DEFAULT 2,
|
||||
`slides_per_view_desktop` DECIMAL(4,2) NOT NULL DEFAULT 3,
|
||||
`autoplay_delay` INT(11) NOT NULL DEFAULT 0,
|
||||
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`show_title` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||
@@ -91,6 +100,23 @@ trait Install
|
||||
);
|
||||
';
|
||||
|
||||
$sqlToExec[] = '
|
||||
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_slide (
|
||||
`id_ws_customhtml_slide` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`id_ws_customhtml` INT(11) NOT NULL,
|
||||
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
||||
`description` TEXT,
|
||||
`extra_description` TEXT,
|
||||
`link` VARCHAR(512) NOT NULL DEFAULT \'\',
|
||||
`link_text` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||
`image` VARCHAR(255) NOT NULL DEFAULT \'\',
|
||||
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||
`date_add` DATETIME NOT NULL,
|
||||
`date_upd` DATETIME NOT NULL,
|
||||
KEY `id_ws_customhtml` (`id_ws_customhtml`)
|
||||
);
|
||||
';
|
||||
|
||||
foreach ($sqlToExec as $sqlBlock) {
|
||||
Db::getInstance()->execute(trim($sqlBlock));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
function upgrade_module_1_13_0($module)
|
||||
{
|
||||
$existing = Db::getInstance()->executeS(
|
||||
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml_group` LIKE \'custom_class\''
|
||||
);
|
||||
|
||||
if (!empty($existing)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Db::getInstance()->execute(
|
||||
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml_group`
|
||||
ADD COLUMN `custom_class` VARCHAR(128) NOT NULL DEFAULT \'\' AFTER `title`'
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
function upgrade_module_1_15_0($module)
|
||||
{
|
||||
$existing = Db::getInstance()->executeS(
|
||||
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'link_text\''
|
||||
);
|
||||
|
||||
if (!empty($existing)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Db::getInstance()->execute(
|
||||
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||
ADD COLUMN `link_text` VARCHAR(128) NOT NULL DEFAULT \'\' AFTER `link`'
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
function upgrade_module_1_16_0($module)
|
||||
{
|
||||
$columnsToAdd = [
|
||||
'slides_per_view_mobile' => 'DECIMAL(4,2) NOT NULL DEFAULT 1',
|
||||
'slides_per_view_tablet' => 'DECIMAL(4,2) NOT NULL DEFAULT 2',
|
||||
'slides_per_view_desktop' => 'DECIMAL(4,2) NOT NULL DEFAULT 3',
|
||||
'autoplay_delay' => 'INT(11) NOT NULL DEFAULT 0',
|
||||
];
|
||||
|
||||
foreach ($columnsToAdd as $column => $definition) {
|
||||
$existing = Db::getInstance()->executeS(
|
||||
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'' . $column . '\''
|
||||
);
|
||||
|
||||
if (!empty($existing)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Db::getInstance()->execute(
|
||||
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml` ADD COLUMN `' . $column . '` ' . $definition
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return Db::getInstance()->execute(
|
||||
'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'ws_customhtml_slide` (
|
||||
`id_ws_customhtml_slide` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`id_ws_customhtml` INT(11) NOT NULL,
|
||||
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
||||
`description` TEXT,
|
||||
`extra_description` TEXT,
|
||||
`link` VARCHAR(512) NOT NULL DEFAULT \'\',
|
||||
`link_text` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||
`image` VARCHAR(255) NOT NULL DEFAULT \'\',
|
||||
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||
`date_add` DATETIME NOT NULL,
|
||||
`date_upd` DATETIME NOT NULL,
|
||||
KEY `id_ws_customhtml` (`id_ws_customhtml`)
|
||||
)'
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
function upgrade_module_1_17_0($module)
|
||||
{
|
||||
$existing = Db::getInstance()->executeS(
|
||||
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'slider_mode\''
|
||||
);
|
||||
|
||||
if (!empty($existing)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Db::getInstance()->execute(
|
||||
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||
ADD COLUMN `slider_mode` VARCHAR(16) NOT NULL DEFAULT \'always\' AFTER `timeout`'
|
||||
);
|
||||
}
|
||||
@@ -18,13 +18,13 @@
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.customhtml-banner-image--gradient {
|
||||
/* .customhtml-banner-image--gradient {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
background: transparent linear-gradient(180deg, #27272777 0%, #272727 100%)
|
||||
0% 0% no-repeat padding-box;
|
||||
}
|
||||
} */
|
||||
/* Alert */
|
||||
.customhtml-alert {
|
||||
max-height: 500px;
|
||||
@@ -48,6 +48,52 @@
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.customhtml-alert-btn {
|
||||
margin-left: 0.75rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.customhtml-usp {
|
||||
gap: 0.5rem;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.customhtml-usp-icon img {
|
||||
max-height: 32px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.customhtml-usp-text {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Slider */
|
||||
.customhtml-slider-grid-item {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Home banners slider (migrated from ws_extrabanner's home-banners section) */
|
||||
.displayHomeBannersSlider--container .customhtml-banner-image {
|
||||
min-height: 220px;
|
||||
background-color: #f2f0e9;
|
||||
}
|
||||
|
||||
.displayHomeBannersSlider--container .customhtml-banner-content * {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.displayHomeBannersSlider--container .customhtml-banner-description,
|
||||
.displayHomeBannersSlider--container .customhtml-banner-extra-description {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.displayHomeBannersSlider--container .customhtml-banner-extra-description {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* FAQ */
|
||||
.accordion-icon-minus {
|
||||
display: block;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
$(document).ready(function () {
|
||||
window.prestashop.component.initComponents([
|
||||
'TinyMCEEditor',
|
||||
]);
|
||||
|
||||
function toggleBlockTypeFields() {
|
||||
var type = $('#custom_html_block_type').val();
|
||||
|
||||
$('.customhtmlblock-type-html').hide();
|
||||
$('.customhtmlblock-type-faq').hide();
|
||||
$('.customhtmlblock-type-banner').hide();
|
||||
$('.customhtmlblock-type-alert').hide();
|
||||
$('.customhtmlblock-type-usp').hide();
|
||||
$('.customhtmlblock-type-slider').hide();
|
||||
$('.customhtmlblock-type-' + type).show();
|
||||
}
|
||||
|
||||
$('#custom_html_block_type').on('change', toggleBlockTypeFields);
|
||||
toggleBlockTypeFields();
|
||||
|
||||
function initRepeater(containerSelector, addButtonSelector, itemClass, removeButtonClass) {
|
||||
var container = $(containerSelector);
|
||||
var removeLabel = container.data('removeLabel');
|
||||
|
||||
$(addButtonSelector).on('click', function () {
|
||||
var index = container.data('index');
|
||||
var prototype = container.data('prototype').replace(/__name__/g, index);
|
||||
|
||||
var item = $('<div class="' + itemClass + ' card mb-2"><div class="card-body"></div></div>');
|
||||
item.find('.card-body')
|
||||
.append(prototype)
|
||||
.append(
|
||||
'<button type="button" class="btn btn-outline-danger btn-sm ' + removeButtonClass + '">' +
|
||||
'<i class="material-icons">delete</i> ' + removeLabel + '</button>'
|
||||
);
|
||||
|
||||
container.append(item);
|
||||
container.data('index', index + 1);
|
||||
});
|
||||
|
||||
container.on('click', '.' + removeButtonClass, function () {
|
||||
$(this).closest('.' + itemClass).remove();
|
||||
});
|
||||
}
|
||||
|
||||
initRepeater('#customhtmlblock-faq-items', '#customhtmlblock-add-faq', 'customhtmlblock-faq-item', 'customhtmlblock-remove-faq');
|
||||
initRepeater('#customhtmlblock-slide-items', '#customhtmlblock-add-slide', 'customhtmlblock-slide-item', 'customhtmlblock-remove-slide');
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
$(document).ready(function () {
|
||||
const customhtmlblockGrid = new window.prestashop.component.Grid('customhtmlblock');
|
||||
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension());
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.PositionExtension());
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
$(document).ready(function () {
|
||||
const customhtmlgroupGrid = new window.prestashop.component.Grid('customhtmlgroup');
|
||||
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension());
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.PositionExtension());
|
||||
});
|
||||
@@ -7,6 +7,17 @@
|
||||
{% endmacro %}
|
||||
{% import _self as faqMacros %}
|
||||
|
||||
{% macro slideFields(slideForm) %}
|
||||
{{ form_widget(slideForm.id) }}
|
||||
{{ form_row(slideForm.title) }}
|
||||
{{ form_row(slideForm.description) }}
|
||||
{{ form_row(slideForm.extra_description) }}
|
||||
{{ form_row(slideForm.link) }}
|
||||
{{ form_row(slideForm.link_text) }}
|
||||
{{ form_row(slideForm.image) }}
|
||||
{% endmacro %}
|
||||
{% import _self as slideMacros %}
|
||||
|
||||
{% block customhtmlblock_form_block %}
|
||||
<div class="card">
|
||||
{{ form_start(customHtmlBlockForm) }}
|
||||
@@ -27,7 +38,7 @@
|
||||
{{ form_row(customHtmlBlockForm.content) }}
|
||||
|
||||
{% if currentImageUrl is defined and currentImageUrl %}
|
||||
<div class="customhtmlblock-type-field customhtmlblock-type-banner customhtmlblock-current-image">
|
||||
<div class="customhtmlblock-type-field customhtmlblock-type-banner customhtmlblock-type-usp customhtmlblock-current-image">
|
||||
<label class="form-control-label">{{ 'Current image'|trans({}, 'Modules.Wscustomhtml.Admin') }}</label>
|
||||
<div><img src="{{ currentImageUrl }}" alt="" style="max-width: 200px; max-height: 200px;"></div>
|
||||
</div>
|
||||
@@ -42,6 +53,7 @@
|
||||
id="customhtmlblock-faq-items"
|
||||
data-prototype="{{ faqMacros.faqFields(customHtmlBlockForm.faqs.vars.prototype)|e('html_attr') }}"
|
||||
data-index="{{ customHtmlBlockForm.faqs|length }}"
|
||||
data-remove-label="{{ 'Remove'|trans({}, 'Admin.Actions')|e('html_attr') }}"
|
||||
>
|
||||
{% for faqRow in customHtmlBlockForm.faqs %}
|
||||
<div class="customhtmlblock-faq-item card mb-2">
|
||||
@@ -59,11 +71,48 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="customhtmlblock-type-field customhtmlblock-type-slider">
|
||||
<label class="form-control-label">
|
||||
{{ 'Slides'|trans({}, 'Modules.Wscustomhtml.Admin') }}
|
||||
</label>
|
||||
<div
|
||||
id="customhtmlblock-slide-items"
|
||||
data-prototype="{{ slideMacros.slideFields(customHtmlBlockForm.slides.vars.prototype)|e('html_attr') }}"
|
||||
data-index="{{ customHtmlBlockForm.slides|length }}"
|
||||
data-remove-label="{{ 'Remove'|trans({}, 'Admin.Actions')|e('html_attr') }}"
|
||||
>
|
||||
{% for slideRow in customHtmlBlockForm.slides %}
|
||||
<div class="customhtmlblock-slide-item card mb-2">
|
||||
<div class="card-body">
|
||||
{{ slideMacros.slideFields(slideRow) }}
|
||||
<button type="button" class="btn btn-outline-danger btn-sm customhtmlblock-remove-slide">
|
||||
<i class="material-icons">delete</i> {{ 'Remove'|trans({}, 'Admin.Actions') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<button type="button" id="customhtmlblock-add-slide" class="btn btn-outline-primary btn-sm">
|
||||
<i class="material-icons">add</i> {{ 'Add slide'|trans({}, 'Modules.Wscustomhtml.Admin') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{ form_row(customHtmlBlockForm.slider_mode) }}
|
||||
<div class="row">
|
||||
{{ form_row(customHtmlBlockForm.slides_per_view_mobile) }}
|
||||
{{ form_row(customHtmlBlockForm.slides_per_view_tablet) }}
|
||||
{{ form_row(customHtmlBlockForm.slides_per_view_desktop) }}
|
||||
</div>
|
||||
{{ form_row(customHtmlBlockForm.autoplay_delay) }}
|
||||
|
||||
{{ form_row(customHtmlBlockForm.alert_type) }}
|
||||
{{ form_row(customHtmlBlockForm.timeout) }}
|
||||
{{ form_row(customHtmlBlockForm.description) }}
|
||||
{{ form_row(customHtmlBlockForm.extra_description) }}
|
||||
{{ form_row(customHtmlBlockForm.link) }}
|
||||
<div class="row">
|
||||
{{ form_row(customHtmlBlockForm.link) }}
|
||||
{{ form_row(customHtmlBlockForm.link_text) }}
|
||||
</div>
|
||||
|
||||
{{ form_row(customHtmlBlockForm.custom_class) }}
|
||||
{{ form_row(customHtmlBlockForm.active) }}
|
||||
|
||||
@@ -8,47 +8,5 @@
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
window.prestashop.component.initComponents([
|
||||
'TinyMCEEditor',
|
||||
]);
|
||||
|
||||
function toggleBlockTypeFields() {
|
||||
var type = $('#custom_html_block_type').val();
|
||||
|
||||
$('.customhtmlblock-type-html').hide();
|
||||
$('.customhtmlblock-type-faq').hide();
|
||||
$('.customhtmlblock-type-banner').hide();
|
||||
$('.customhtmlblock-type-alert').hide();
|
||||
$('.customhtmlblock-type-' + type).show();
|
||||
}
|
||||
|
||||
$('#custom_html_block_type').on('change', toggleBlockTypeFields);
|
||||
toggleBlockTypeFields();
|
||||
|
||||
var removeFaqLabel = '{{ 'Remove'|trans({}, 'Admin.Actions')|e('js') }}';
|
||||
var faqContainer = $('#customhtmlblock-faq-items');
|
||||
|
||||
$('#customhtmlblock-add-faq').on('click', function () {
|
||||
var index = faqContainer.data('index');
|
||||
var prototype = faqContainer.data('prototype').replace(/__name__/g, index);
|
||||
|
||||
var item = $('<div class="customhtmlblock-faq-item card mb-2"><div class="card-body"></div></div>');
|
||||
item.find('.card-body')
|
||||
.append(prototype)
|
||||
.append(
|
||||
'<button type="button" class="btn btn-outline-danger btn-sm customhtmlblock-remove-faq">' +
|
||||
'<i class="material-icons">delete</i> ' + removeFaqLabel + '</button>'
|
||||
);
|
||||
|
||||
faqContainer.append(item);
|
||||
faqContainer.data('index', index + 1);
|
||||
});
|
||||
|
||||
faqContainer.on('click', '.customhtmlblock-remove-faq', function () {
|
||||
$(this).closest('.customhtmlblock-faq-item').remove();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlblock_form.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -8,47 +8,5 @@
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
window.prestashop.component.initComponents([
|
||||
'TinyMCEEditor',
|
||||
]);
|
||||
|
||||
function toggleBlockTypeFields() {
|
||||
var type = $('#custom_html_block_type').val();
|
||||
|
||||
$('.customhtmlblock-type-html').hide();
|
||||
$('.customhtmlblock-type-faq').hide();
|
||||
$('.customhtmlblock-type-banner').hide();
|
||||
$('.customhtmlblock-type-alert').hide();
|
||||
$('.customhtmlblock-type-' + type).show();
|
||||
}
|
||||
|
||||
$('#custom_html_block_type').on('change', toggleBlockTypeFields);
|
||||
toggleBlockTypeFields();
|
||||
|
||||
var removeFaqLabel = '{{ 'Remove'|trans({}, 'Admin.Actions')|e('js') }}';
|
||||
var faqContainer = $('#customhtmlblock-faq-items');
|
||||
|
||||
$('#customhtmlblock-add-faq').on('click', function () {
|
||||
var index = faqContainer.data('index');
|
||||
var prototype = faqContainer.data('prototype').replace(/__name__/g, index);
|
||||
|
||||
var item = $('<div class="customhtmlblock-faq-item card mb-2"><div class="card-body"></div></div>');
|
||||
item.find('.card-body')
|
||||
.append(prototype)
|
||||
.append(
|
||||
'<button type="button" class="btn btn-outline-danger btn-sm customhtmlblock-remove-faq">' +
|
||||
'<i class="material-icons">delete</i> ' + removeFaqLabel + '</button>'
|
||||
);
|
||||
|
||||
faqContainer.append(item);
|
||||
faqContainer.data('index', index + 1);
|
||||
});
|
||||
|
||||
faqContainer.on('click', '.customhtmlblock-remove-faq', function () {
|
||||
$(this).closest('.customhtmlblock-faq-item').remove();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlblock_form.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -12,15 +12,5 @@
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
const customhtmlblockGrid = new window.prestashop.component.Grid('customhtmlblock');
|
||||
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension());
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.PositionExtension());
|
||||
});
|
||||
</script>
|
||||
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlblock_grid.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -12,15 +12,5 @@
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
const customhtmlgroupGrid = new window.prestashop.component.Grid('customhtmlgroup');
|
||||
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension());
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.PositionExtension());
|
||||
});
|
||||
</script>
|
||||
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlgroup_grid.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
<strong class="customhtml-alert-title">{$block.title|escape:'html':'UTF-8'}</strong>
|
||||
{/if}
|
||||
<span class="customhtml-alert-text">{$block.description|escape:'html':'UTF-8'|nl2br}</span>
|
||||
{if !empty($block.link)}
|
||||
<a href="{$block.link|escape:'html':'UTF-8'}" class="btn btn-{$block.alert_type|escape:'html':'UTF-8'} customhtml-alert-btn">
|
||||
{if !empty($block.link_text)}{$block.link_text|escape:'html':'UTF-8'}{else}{l s='Learn more' d='Modules.Wscustomhtml.Shop'}{/if}
|
||||
</a>
|
||||
{/if}
|
||||
<button type="button" class="close customhtml-alert-close" aria-label="{l s='Close' d='Modules.Wscustomhtml.Shop'}">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
||||
@@ -3,9 +3,21 @@
|
||||
<div class="customhtml-banner-image--gradient"></div>
|
||||
{if !empty($block.image_url)}
|
||||
<img src="{$block.image_url|escape:'html':'UTF-8'}" alt="{$block.title|escape:'html':'UTF-8'}">
|
||||
{else}
|
||||
<img
|
||||
src="{$urls.img_ps_url}noimageavailable.jpg"
|
||||
alt="{$block.title|escape:'html':'UTF-8'}"
|
||||
width="100%"
|
||||
class="img-fluid rounded lazyload"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="customhtml-banner-content">
|
||||
{include file="module:ws_customhtml/views/templates/hook/_banner_content.tpl" block=$block}
|
||||
{assign var="customhtmlOverridePath" value="{$smarty.const._PS_THEME_DIR_}modules/ws_customhtml/views/templates/hook/{$hookName}/_banner_content.tpl"}
|
||||
{if file_exists($customhtmlOverridePath)}
|
||||
{include file="module:ws_customhtml/views/templates/hook/`$hookName`/_banner_content.tpl" block=$block}
|
||||
{else}
|
||||
{include file="module:ws_customhtml/views/templates/hook/_banner_content.tpl" block=$block}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -8,5 +8,7 @@
|
||||
<div class="customhtml-banner-extra-description">{$block.extra_description|escape:'html':'UTF-8'|nl2br}</div>
|
||||
{/if}
|
||||
{if !empty($block.link)}
|
||||
<a href="{$block.link|escape:'html':'UTF-8'}" class="btn btn-primary customhtml-banner-link">{l s='Learn more' d='Modules.Wscustomhtml.Shop'}</a>
|
||||
<a href="{$block.link|escape:'html':'UTF-8'}" class="btn btn-primary customhtml-banner-link">
|
||||
{if !empty($block.link_text)}{$block.link_text|escape:'html':'UTF-8'}{else}{l s='Learn more' d='Modules.Wscustomhtml.Shop'}{/if}
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
@@ -1,48 +1,57 @@
|
||||
{if !empty($block.faqs)}
|
||||
<div class="accordion customhtml-faq-accordion" id="customhtml-faq-{$block.id_ws_customhtml|intval}">
|
||||
{foreach from=$block.faqs item="faq" name="customhtmlFaqLoop"}
|
||||
<div class="card">
|
||||
<div class="card-header" id="customhtml-faq-heading-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}">
|
||||
<button
|
||||
class="btn btn-link col-12 d-flex text-left {if !$smarty.foreach.customhtmlFaqLoop.first} collapsed{/if}"
|
||||
type="button"
|
||||
data-toggle="collapse"
|
||||
data-target="#customhtml-faq-collapse-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||
aria-expanded="{if $smarty.foreach.customhtmlFaqLoop.first}true{else}false{/if}"
|
||||
aria-controls="customhtml-faq-collapse-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||
>
|
||||
<div class="col">
|
||||
{$faq.question|escape:'html':'UTF-8'}
|
||||
|
||||
</div>
|
||||
<div class="col-auto d-flex align-items-center ">
|
||||
<span class="accordion-icons accordion-icon-minus">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="2" viewBox="0 0 28 2">
|
||||
<line id="Line_18" data-name="Line 18" x2="26" transform="translate(1 1)" fill="none" stroke="#272727" stroke-linecap="round" stroke-width="2"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="accordion-icons accordion-icon-plus">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28">
|
||||
<g id="Group_31" data-name="Group 31" transform="translate(-1615 -4031.5)">
|
||||
<line id="Line_21" data-name="Line 21" x2="26" transform="translate(1616 4045.5)" fill="none" stroke="#272727" stroke-linecap="round" stroke-width="2"/>
|
||||
<line id="Line_22" data-name="Line 22" x2="26" transform="translate(1629 4032.5) rotate(90)" fill="none" stroke="#272727" stroke-linecap="round" stroke-width="2"/>
|
||||
</g>
|
||||
</svg>
|
||||
</span>
|
||||
<div class="accordion customhtml-faq-accordion" id="customhtml-faq-{$block.id_ws_customhtml|intval}">
|
||||
{foreach from=$block.faqs item="faq" name="customhtmlFaqLoop"}
|
||||
<div class="card">
|
||||
<div class="card-header" id="customhtml-faq-heading-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}">
|
||||
|
||||
{if !empty($faq.answer)}
|
||||
<button
|
||||
class="btn btn-link col-12 d-flex text-left{if !$smarty.foreach.customhtmlFaqLoop.first} collapsed{/if}"
|
||||
type="button"
|
||||
data-toggle="collapse"
|
||||
data-target="#customhtml-faq-collapse-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||
aria-expanded="{if $smarty.foreach.customhtmlFaqLoop.first}true{else}false{/if}"
|
||||
aria-controls="customhtml-faq-collapse-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||
>
|
||||
{/if}
|
||||
|
||||
<div class="faq-question col pl-0">
|
||||
{$faq.question|escape:'html':'UTF-8'}
|
||||
</div>
|
||||
|
||||
{if !empty($faq.answer)}
|
||||
<div class="col-auto d-flex align-items-center">
|
||||
<span class="accordion-icons accordion-icon-minus">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="2" viewBox="0 0 28 2">
|
||||
<line id="Line_18" data-name="Line 18" x2="26" transform="translate(1 1)" fill="none" stroke="#272727" stroke-linecap="round" stroke-width="2"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="accordion-icons accordion-icon-plus">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28">
|
||||
<g id="Group_31" data-name="Group 31" transform="translate(-1615 -4031.5)">
|
||||
<line id="Line_21" data-name="Line 21" x2="26" transform="translate(1616 4045.5)" fill="none" stroke="#272727" stroke-linecap="round" stroke-width="2"/>
|
||||
<line id="Line_22" data-name="Line 22" x2="26" transform="translate(1629 4032.5) rotate(90)" fill="none" stroke="#272727" stroke-linecap="round" stroke-width="2"/>
|
||||
</g>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
id="customhtml-faq-collapse-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||
class="collapse{if $smarty.foreach.customhtmlFaqLoop.first} show{/if}"
|
||||
aria-labelledby="customhtml-faq-heading-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||
data-parent="#customhtml-faq-{$block.id_ws_customhtml|intval}"
|
||||
>
|
||||
<div class="card-body">
|
||||
{$faq.answer nofilter}
|
||||
{if !empty($faq.answer)}
|
||||
<div
|
||||
id="customhtml-faq-collapse-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||
class="collapse{if $smarty.foreach.customhtmlFaqLoop.first} show{/if}"
|
||||
aria-labelledby="customhtml-faq-heading-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||
data-parent="#customhtml-faq-{$block.id_ws_customhtml|intval}"
|
||||
>
|
||||
<div class="card-body">
|
||||
{$faq.answer nofilter}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
{if !empty($block.slides)}
|
||||
{if $block.slider_mode == 'responsive'}
|
||||
{block name=slider_responsive}
|
||||
<div class="d-lg-none">
|
||||
<div id="customhtml-slider-{$block.id_ws_customhtml|intval}" class="swiper customhtml-slider" data-swiper="{$block.slider_config|escape:'html':'UTF-8'}">
|
||||
<div class="swiper-wrapper">
|
||||
{foreach from=$block.slides item="slide" name="slides"}
|
||||
<div class="swiper-slide">
|
||||
{assign var="customhtmlOverridePath" value="{$smarty.const._PS_THEME_DIR_}modules/ws_customhtml/views/templates/hook/{$hookName}/banner.tpl"}
|
||||
{if file_exists($customhtmlOverridePath)}
|
||||
{include file="module:ws_customhtml/views/templates/hook/`$hookName`/banner.tpl" block=$slide group=$group hookName=$hookName}
|
||||
{else}
|
||||
{include file="module:ws_customhtml/views/templates/hook/_banner.tpl" block=$slide}
|
||||
{/if}
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row d-none d-lg-flex customhtml-slider-grid">
|
||||
{foreach from=$block.slides item="slide" name="slides"}
|
||||
<div class="customhtml-slider-grid-item" style="flex: 0 0 {$block.slider_desktop_column_width|escape:'html':'UTF-8'}; max-width: {$block.slider_desktop_column_width|escape:'html':'UTF-8'};">
|
||||
{assign var="customhtmlOverridePath" value="{$smarty.const._PS_THEME_DIR_}modules/ws_customhtml/views/templates/hook/{$hookName}/banner.tpl"}
|
||||
{if file_exists($customhtmlOverridePath)}
|
||||
{include file="module:ws_customhtml/views/templates/hook/`$hookName`/banner.tpl" block=$slide group=$group hookName=$hookName}
|
||||
{else}
|
||||
{include file="module:ws_customhtml/views/templates/hook/_banner.tpl" block=$slide}
|
||||
{/if}
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
{/block}
|
||||
{/if}
|
||||
{if $block.slider_mode != 'responsive'}
|
||||
{block name=slider_always}
|
||||
<div id="customhtml-slider-{$block.id_ws_customhtml|intval}" class="swiper customhtml-slider" data-swiper="{$block.slider_config|escape:'html':'UTF-8'}">
|
||||
<div class="swiper-wrapper">
|
||||
{foreach from=$block.slides item="slide" name="slides"}
|
||||
<div class="swiper-slide">
|
||||
{assign var="customhtmlOverridePath" value="{$smarty.const._PS_THEME_DIR_}modules/ws_customhtml/views/templates/hook/{$hookName}/banner.tpl"}
|
||||
{if file_exists($customhtmlOverridePath)}
|
||||
{include file="module:ws_customhtml/views/templates/hook/`$hookName`/banner.tpl" block=$slide group=$group hookName=$hookName}
|
||||
{else}
|
||||
{include file="module:ws_customhtml/views/templates/hook/_banner.tpl" block=$slide}
|
||||
{/if}
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{if !empty($block.image_url) || ($block.show_title && !empty($block.title))}
|
||||
{if !empty($block.link)}
|
||||
<a href="{$block.link|escape:'html':'UTF-8'}" class="customhtml-usp d-flex align-items-center">
|
||||
{else}
|
||||
<div class="customhtml-usp d-flex align-items-center">
|
||||
{/if}
|
||||
{if !empty($block.image_url)}
|
||||
<span class="customhtml-usp-icon">
|
||||
<img src="{$block.image_url|escape:'html':'UTF-8'}" alt="">
|
||||
</span>
|
||||
{/if}
|
||||
{if $block.show_title && !empty($block.title)}
|
||||
<span class="customhtml-usp-text">{$block.title|escape:'html':'UTF-8'}</span>
|
||||
{/if}
|
||||
{if !empty($block.link)}
|
||||
</a>
|
||||
{else}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -1,7 +1,7 @@
|
||||
{if !empty($groupList)}
|
||||
<div class="customhtml-container {$hookName|escape:'html':'UTF-8'}--container">
|
||||
{foreach from=$groupList item="group"}
|
||||
<div class="customhtml-group customhtml-group-{$group.id_ws_customhtml_group|intval} row">
|
||||
<div class="customhtml-group customhtml-group-{$group.id_ws_customhtml_group|intval} row{if !empty($group.custom_class)} {$group.custom_class|escape:'html':'UTF-8'}{/if}">
|
||||
{foreach from=$group.blocks item="block"}
|
||||
<div class="customhtml-block col{if !empty($block.custom_class)} {$block.custom_class|escape:'html':'UTF-8'}{/if}">
|
||||
{assign var="customhtmlOverridePath" value="{$smarty.const._PS_THEME_DIR_}modules/ws_customhtml/views/templates/hook/{$hookName}/{$block.type}.tpl"}
|
||||
@@ -17,6 +17,13 @@
|
||||
{include file="module:ws_customhtml/views/templates/hook/_banner.tpl" block=$block}
|
||||
{elseif $block.type == 'alert'}
|
||||
{include file="module:ws_customhtml/views/templates/hook/_alert.tpl" block=$block}
|
||||
{elseif $block.type == 'usp'}
|
||||
{include file="module:ws_customhtml/views/templates/hook/_usp.tpl" block=$block}
|
||||
{elseif $block.type == 'slider'}
|
||||
{if $block.show_title && !empty($block.title)}
|
||||
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
||||
{/if}
|
||||
{include file="module:ws_customhtml/views/templates/hook/_slider.tpl" block=$block}
|
||||
{else}
|
||||
{if $block.show_title && !empty($block.title)}
|
||||
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ class Ws_CustomHtml extends Module implements WidgetInterface
|
||||
public function __construct()
|
||||
{
|
||||
$this->name = 'ws_customhtml';
|
||||
$this->version = '1.11.0';
|
||||
$this->version = '1.17.0';
|
||||
$this->author = 'Isabelle Oving-Anno | De Websmid BV';
|
||||
$this->need_instance = 0;
|
||||
$this->bootstrap = true;
|
||||
|
||||
Reference in New Issue
Block a user