feat(main): Add custom CSS classes to HTML blocks
This feature allows administrators to define custom CSS classes for individual HTML blocks. It enhances styling flexibility and integrates with common grid systems (e.g., Bootstrap `col-md-6`) by applying user-defined classes to the block's wrapper element. Includes: - A new `custom_class` field in the block model, form, and data handlers. - Database schema updates with an upgrade path to handle potential renames from `column_class`. - Frontend rendering to apply the classes. - Registration of `actionFrontControllerSetMedia` hook to load front-end CSS. - Basic responsive image styling for blocks.
This commit is contained in:
@@ -7,6 +7,7 @@ class Config
|
|||||||
const HOOKS = [
|
const HOOKS = [
|
||||||
'actionAdminControllerSetMedia',
|
'actionAdminControllerSetMedia',
|
||||||
'actionCustomhtmlblockGridDataModifier',
|
'actionCustomhtmlblockGridDataModifier',
|
||||||
|
'actionFrontControllerSetMedia',
|
||||||
];
|
];
|
||||||
|
|
||||||
const BLOCK_TYPES = [
|
const BLOCK_TYPES = [
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
|||||||
$block->title = (string) $formData['title'];
|
$block->title = (string) $formData['title'];
|
||||||
$block->type = (string) $formData['type'];
|
$block->type = (string) $formData['type'];
|
||||||
$block->show_title = (int) $formData['show_title'];
|
$block->show_title = (int) $formData['show_title'];
|
||||||
|
$block->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||||
$block->content = (string) $formData['content'];
|
$block->content = (string) $formData['content'];
|
||||||
$block->active = (int) $formData['active'];
|
$block->active = (int) $formData['active'];
|
||||||
$block->ordering = $this->getNextOrdering($idGroup);
|
$block->ordering = $this->getNextOrdering($idGroup);
|
||||||
@@ -44,6 +45,7 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
|||||||
$block->title = (string) $formData['title'];
|
$block->title = (string) $formData['title'];
|
||||||
$block->type = (string) $formData['type'];
|
$block->type = (string) $formData['type'];
|
||||||
$block->show_title = (int) $formData['show_title'];
|
$block->show_title = (int) $formData['show_title'];
|
||||||
|
$block->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||||
$block->content = (string) $formData['content'];
|
$block->content = (string) $formData['content'];
|
||||||
$block->active = (int) $formData['active'];
|
$block->active = (int) $formData['active'];
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
|||||||
'title' => $block->title,
|
'title' => $block->title,
|
||||||
'type' => $block->type,
|
'type' => $block->type,
|
||||||
'show_title' => (bool) $block->show_title,
|
'show_title' => (bool) $block->show_title,
|
||||||
|
'custom_class' => $block->custom_class,
|
||||||
'content' => $block->content,
|
'content' => $block->content,
|
||||||
'faqs' => $this->loadFaqs((int) $id),
|
'faqs' => $this->loadFaqs((int) $id),
|
||||||
'active' => (bool) $block->active,
|
'active' => (bool) $block->active,
|
||||||
@@ -35,6 +36,7 @@ final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
|||||||
'title' => '',
|
'title' => '',
|
||||||
'type' => 'html',
|
'type' => 'html',
|
||||||
'show_title' => false,
|
'show_title' => false,
|
||||||
|
'custom_class' => '',
|
||||||
'content' => '',
|
'content' => '',
|
||||||
'faqs' => [],
|
'faqs' => [],
|
||||||
'active' => true,
|
'active' => true,
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ class CustomHtmlBlockType extends AbstractType
|
|||||||
'label' => $this->translator->trans('Show title', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Show title', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
'required' => false,
|
'required' => false,
|
||||||
])
|
])
|
||||||
|
->add('custom_class', TextType::class, [
|
||||||
|
'label' => $this->translator->trans('Custom classes', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'attr' => ['placeholder' => 'col-md-6'],
|
||||||
|
])
|
||||||
->add('content', TextareaType::class, [
|
->add('content', TextareaType::class, [
|
||||||
'label' => $this->translator->trans('Content', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Content', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ class CustomHtmlBlock extends ObjectModel
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
public $content = '';
|
public $content = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $custom_class = '';
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $active = 1;
|
public $active = 1;
|
||||||
|
|
||||||
@@ -45,6 +48,7 @@ class CustomHtmlBlock extends ObjectModel
|
|||||||
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 256],
|
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 256],
|
||||||
'type' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32],
|
'type' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32],
|
||||||
'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'],
|
'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'],
|
||||||
|
'custom_class' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128],
|
||||||
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||||
'show_title' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
'show_title' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||||
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||||
@@ -62,7 +66,7 @@ class CustomHtmlBlock extends ObjectModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
$result = Db::getInstance()->executeS(
|
$result = Db::getInstance()->executeS(
|
||||||
'SELECT `id_ws_customhtml`, `id_ws_customhtml_group`, `title`, `type`, `content`, `active`, `show_title`, `ordering`
|
'SELECT `id_ws_customhtml`, `id_ws_customhtml_group`, `title`, `type`, `content`, `custom_class`, `active`, `show_title`, `ordering`
|
||||||
FROM `' . _DB_PREFIX_ . 'ws_customhtml`
|
FROM `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
WHERE `id_ws_customhtml_group` IN (' . implode(',', $groupIds) . ')
|
WHERE `id_ws_customhtml_group` IN (' . implode(',', $groupIds) . ')
|
||||||
AND `active` = 1
|
AND `active` = 1
|
||||||
|
|||||||
@@ -9,6 +9,14 @@ use Context;
|
|||||||
|
|
||||||
trait DisplayHooks
|
trait DisplayHooks
|
||||||
{
|
{
|
||||||
|
public function hookActionFrontControllerSetMedia(): void
|
||||||
|
{
|
||||||
|
$this->context->controller->registerStylesheet(
|
||||||
|
'ws_customhtml_front',
|
||||||
|
'/modules/' . $this->name . '/views/css/front/customhtml.css'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function renderWidget($hookName = null, array $configuration = [])
|
public function renderWidget($hookName = null, array $configuration = [])
|
||||||
{
|
{
|
||||||
if (empty($hookName)) {
|
if (empty($hookName)) {
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ trait Install
|
|||||||
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
||||||
`type` VARCHAR(32) NOT NULL DEFAULT \'html\',
|
`type` VARCHAR(32) NOT NULL DEFAULT \'html\',
|
||||||
`content` LONGTEXT,
|
`content` LONGTEXT,
|
||||||
|
`custom_class` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||||
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
`show_title` TINYINT(1) NOT NULL DEFAULT 0,
|
`show_title` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
`ordering` INT(11) NOT NULL DEFAULT 0,
|
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('_PS_VERSION_')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade_module_1_3_0($module)
|
||||||
|
{
|
||||||
|
$columns = Db::getInstance()->executeS(
|
||||||
|
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'column_class\''
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($columns)) {
|
||||||
|
if (!Db::getInstance()->execute(
|
||||||
|
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
|
ADD COLUMN `column_class` VARCHAR(128) NOT NULL DEFAULT \'col-12\' AFTER `content`'
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('_PS_VERSION_')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade_module_1_4_0($module)
|
||||||
|
{
|
||||||
|
if (!Hook::isModuleRegisteredOnHook($module, 'actionFrontControllerSetMedia', (int) Context::getContext()->shop->id)) {
|
||||||
|
return $module->registerHook('actionFrontControllerSetMedia');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('_PS_VERSION_')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade_module_1_5_0($module)
|
||||||
|
{
|
||||||
|
$newColumn = Db::getInstance()->executeS(
|
||||||
|
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'custom_class\''
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($newColumn)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oldColumn = Db::getInstance()->executeS(
|
||||||
|
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'column_class\''
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($oldColumn)) {
|
||||||
|
return Db::getInstance()->execute(
|
||||||
|
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
|
CHANGE `column_class` `custom_class` VARCHAR(128) NOT NULL DEFAULT \'\''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Db::getInstance()->execute(
|
||||||
|
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
|
ADD COLUMN `custom_class` VARCHAR(128) NOT NULL DEFAULT \'\' AFTER `content`'
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
.customhtml-block img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
{{ form_row(customHtmlBlockForm.title) }}
|
{{ form_row(customHtmlBlockForm.title) }}
|
||||||
{{ form_row(customHtmlBlockForm.type) }}
|
{{ form_row(customHtmlBlockForm.type) }}
|
||||||
{{ form_row(customHtmlBlockForm.show_title) }}
|
{{ form_row(customHtmlBlockForm.show_title) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.custom_class) }}
|
||||||
{{ form_row(customHtmlBlockForm.content) }}
|
{{ form_row(customHtmlBlockForm.content) }}
|
||||||
|
|
||||||
<div class="customhtmlblock-type-field customhtmlblock-type-faq">
|
<div class="customhtmlblock-type-field customhtmlblock-type-faq">
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
{if !empty($groupList)}
|
{if !empty($groupList)}
|
||||||
<div class="customhtml-container {$hookName|escape:'html':'UTF-8'}--container">
|
<div class="customhtml-container {$hookName|escape:'html':'UTF-8'}--container">
|
||||||
{foreach from=$groupList item="group"}
|
{foreach from=$groupList item="group"}
|
||||||
<div class="customhtml-group">
|
<div class="customhtml-group customhtml-group-{$group.id_ws_customhtml_group|intval} row">
|
||||||
{foreach from=$group.blocks item="block"}
|
{foreach from=$group.blocks item="block"}
|
||||||
<div class="customhtml-block">
|
<div class="customhtml-block col{if !empty($block.custom_class)} {$block.custom_class|escape:'html':'UTF-8'}{/if}">
|
||||||
{if $block.show_title && !empty($block.title)}
|
{if $block.show_title && !empty($block.title)}
|
||||||
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ class Ws_CustomHtml extends Module implements WidgetInterface
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->name = 'ws_customhtml';
|
$this->name = 'ws_customhtml';
|
||||||
$this->version = '1.2.0';
|
$this->version = '1.5.0';
|
||||||
$this->author = 'Isabelle Oving-Anno | De Websmid BV';
|
$this->author = 'Isabelle Oving-Anno | De Websmid BV';
|
||||||
$this->need_instance = 0;
|
$this->need_instance = 0;
|
||||||
$this->bootstrap = true;
|
$this->bootstrap = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user