Browse Source

Ticket #4667 - Ticket Intergrate Grapesjs for blocks. User end.

AntonLV 2 năm trước cách đây
mục cha
commit
8c78865fcf

+ 8 - 0
inc/classes/BxDolPageQuery.php

@@ -137,6 +137,14 @@ class BxDolPageQuery extends BxDolDb
         return $this->getOne($sQuery);
     }
 
+    public function setPageBlockContent($iId, $sContent)
+    {
+        return $this->query("UPDATE `sys_pages_blocks` SET `content`=:content WHERE `id`=:id", [
+            'id' => $iId,
+            'content' => $sContent
+        ]) !== false;
+    }
+
     public function getPageBlockContentPlaceholder($iId)
     {
         $sQuery = $this->prepare("SELECT `id`, `module`, `template` FROM `sys_pages_content_placeholders` WHERE `id` = ?", $iId);

+ 139 - 1
inc/js/classes/BxDolPage.js

@@ -16,6 +16,11 @@ function BxDolPage(oOptions) {
     this._isStickyColumns = oOptions.isStickyColumns == undefined ? false : oOptions.isStickyColumns;
     this._iLastSc = 0;
 
+    this._oCreativeEditor = null;
+    this._oCreativeStorage =  null;
+    this._sCreativeStorageData = 'bx-cs-data';
+    this._sCreativeStorageHtml = 'bx-cs-html';
+
     var $this = this;
     $(document).ready(function() {
         $this.init();
@@ -29,6 +34,7 @@ BxDolPage.prototype.init = function() {
             additionalMarginTop: 70
         });
     }
+
     // process embeds
     $(".bx-embed-link").each(function() {
         $(this).html($(this).attr('source'));
@@ -36,7 +42,6 @@ BxDolPage.prototype.init = function() {
     });
     
     bx_process_links();
-    
 };
 
 BxDolPage.prototype.embededCallback = function(item)
@@ -80,6 +85,139 @@ BxDolPage.prototype.showHelp = function(oLink, iBlockId)
         }
     });
 };
+
+//TODO: Continue from here.
+BxDolPage.prototype.creativeEdit = function(oLink, iBlockId)
+{
+    if(this._oCreativeEditor)
+        return;
+
+    var $this = this;
+
+    $(oLink).toggleClass('hidden').siblings('.bx-cc-save').toggleClass('hidden');
+
+    //--- Holdres
+    if(!$('#' + this._sCreativeStorageData).length)
+        $('body').prepend('<textarea id="' + this._sCreativeStorageData + '" class="hidden"></textarea>');
+    else
+        $('#' + this._sCreativeStorageData).val('');
+
+    if(!$('#' + this._sCreativeStorageHtml).length)
+        $('body').prepend('<textarea id="' + this._sCreativeStorageHtml + '" class="hidden"></textarea>');
+    else
+        $('#' + this._sCreativeStorageHtml).val('');
+
+    /*
+    //--- Panels
+    $('body').prepend('<div class="bx-cp-top"><div class="bx-cp bx-cp-devices"></div><div class="bx-cp bx-cp-options"></div><div class="bx-cp bx-cp-views"></div><div class="bx-cp bx-cp-views-container"><div class="bx-c-blocks"></div><div class="bx-c-styles"></div></div></div>');
+    */
+
+    //Load data to local storage
+    var oContent = $(oLink).parents('.bx-creative-controls:first').siblings('.bx-creative-content');
+    if(oContent.length) {
+        $('#' + this._sCreativeStorageData).val(JSON.stringify({pages: [{component: oContent.html()}]}));
+        $('#' + this._sCreativeStorageHtml).val(oContent.html());
+    }
+
+    const oStorage = (editor) => {
+        const oStorageData = document.getElementById($this._sCreativeStorageData);
+        const oStorageHtml = document.getElementById($this._sCreativeStorageHtml);
+
+        editor.Storage.add('inline', {
+            load() {
+                return JSON.parse(oStorageData.value || '{}');
+            },
+            store(data) {
+              const component = editor.Pages.getSelected().getMainComponent();
+
+              oStorageData.value = JSON.stringify(data);
+              oStorageHtml.value = `<style>${editor.getCss({ component })}</style>${editor.getHtml({ component })}`;
+            }
+        });
+    };  
+
+
+    var sContainer = 'bx-cc-' + iBlockId;
+    this._oCreativeEditor = grapesjs.init({
+        // Indicate where to init the editor. You can also pass an HTMLElement
+        container: '#' + sContainer,
+
+        plugins: [oStorage, 'gjs-blocks-basic', 'grapesjs-style-bg', 'grapesjs-preset-webpage'],
+        pluginsOpts: {
+            'gjs-blocks-basic': { flexGrid: true },
+            'grapesjs-preset-webpage': {}
+        },
+
+        height: $('#' + sContainer).height(),
+/*
+        blockManager: {
+            appendTo: '.bx-c-blocks',
+        },
+        styleManager: {
+            appendTo: '.bx-c-styles',
+        },
+*/
+        storageManager: { 
+            type: 'inline',
+            autosave: true,
+            autoload: true
+        }
+    });
+
+/*
+    const pm = this._oCreativeEditor.Panels;
+    pm.addPanel({id: 'panel-top', el: '.bx-cp-top'});
+    pm.addPanel({id: 'panel-devices', el: '.bx-cp-devices', buttons: pm.getPanel('devices-c').buttons.models});
+    pm.addPanel({id: 'panel-options', el: '.bx-cp-options', buttons: pm.getPanel('options').buttons.models});
+    pm.addPanel({id: 'panel-views', el: '.bx-cp-views', buttons: pm.getPanel('views').buttons.models});
+    pm.addPanel({id: 'panel-views', el: '.bx-cp-views-container'});
+*/
+};
+
+BxDolPage.prototype.creativeSave = function(oLink, iBlockId)
+{
+    if(!this._oCreativeEditor)
+        return;
+
+    this._loadingInButton($(oLink), true);
+
+    var $this = this;
+    var sContent = $('#' + this._sCreativeStorageHtml).val();
+
+    var oParams = $.extend({}, this._getDefaultParams(), {
+        a: 'creative_save',
+        b: iBlockId,
+        c: sContent
+    });
+
+    $.post (
+        this._sActionsUri,
+        oParams,
+        function() {
+            $this._loadingInButton($(oLink), false);
+
+            $(oLink).toggleClass('hidden').siblings('.bx-cc-edit').toggleClass('hidden');
+            $('.bx-cp-top').remove();
+
+            $this._oCreativeEditor.destroy();
+            $this._oCreativeEditor = null;
+
+            var oContent = $(oLink).parents('.bx-creative-controls:first').siblings('.bx-creative-content');
+            if(oContent.length)
+                oContent.attr('style', '').html(sContent);
+        },
+        'json'
+    );
+};
+
+BxDolPage.prototype._loadingInButton = function(e, bShow)
+{
+    if($(e).length)
+        bx_loading_btn($(e), bShow);
+    else
+        bx_loading($('body'), bShow);
+};
+
 BxDolPage.prototype._getDefaultParams = function() 
 {
     var oDate = new Date();

+ 1 - 1
modules/boonex/artificer/data/template/system/css/common.css

@@ -317,7 +317,7 @@ button.bx-btn:focus .bx-loading-ajax-btn {
     overflow: hidden;
 }
 .bx-overflow-ready.bx-or-cmt {
-    max-height: 5rem;
+    max-height: 10rem;
 }
 .bx-overflow:before {
     position: absolute;

+ 40 - 0
studio/template/bp_block_skeleton_creative.html

@@ -0,0 +1,40 @@
+<div class="bx-form-input-wrapper bx-form-input-wrapper-textarea">
+    <textarea id="__html_id__-html" class="hidden" name="content">__content_html__</textarea>
+    <textarea id="__html_id__-data" class="hidden">__content_data__</textarea>
+    <div id="__html_id__" class="bx-form-input-textarea"></div>
+</div>
+<script type="text/javascript">
+    var inlineStorage = null;
+    if(inlineStorage == undefined) {
+        inlineStorage = (editor) => {
+            const oStorageData = document.getElementById('__html_id__-data');
+            const oStorageHtml = document.getElementById('__html_id__-html');
+
+            editor.Storage.add('inline', {
+                load() {
+                  return JSON.parse(oStorageData.value || '{}');
+                },
+                store(data) {
+                  const component = editor.Pages.getSelected().getMainComponent();
+
+                  oStorageData.value = JSON.stringify(data);
+                  oStorageHtml.value = `<style>${editor.getCss({ component })}</style>${editor.getHtml({ component })}`;
+                }
+            });
+        };
+    }
+
+    var oBuilder = grapesjs.init({
+        container : '#__html_id__',
+        plugins: [inlineStorage, 'gjs-blocks-basic', 'grapesjs-style-bg', 'grapesjs-preset-webpage'],
+        pluginsOpts: {
+            'gjs-blocks-basic': { flexGrid: true },
+            'grapesjs-preset-webpage': {}
+        },
+        storageManager: { 
+            type: 'inline',
+            autosave: true,
+            autoload: true
+        }
+    });
+</script>

+ 9 - 0
template/block_creative.html

@@ -0,0 +1,9 @@
+<div class="bx-page-creative-container bx-def-vanilla-html max-w-none">
+    <div class="bx-creative-content" id="bx-cc-__block_id__">__content__</div>
+    <bx_if:show_controls>
+        <div class="bx-creative-controls flex justify-end w-full pt-4">
+            <a class="bx-btn bx-btn-small bx-cc-edit" href="javascript:void(0)" onclick="javascript:__onclick_edit__"><i class="sys-icon edit"></i></a>
+            <a class="bx-btn bx-btn-small ml-2 hidden bx-cc-save" href="javascript:void(0)" onclick="javascript:__onclick_save__"><i class="sys-icon check"></i></a>
+        </div>
+    </bx_if:show_controls>
+</div>

+ 33 - 1
template/css/page_layouts.css

@@ -21,4 +21,36 @@
 }
 .bx-layout-column-full .bx-def-full-col-hide{
     display: none;
-}
+}
+
+/* Grapesjs integration */
+/*
+.bx-cp-top.gjs-pn-panel {
+    position: fixed;
+    top: 0;
+    width: 100%;
+    z-index: 10000;
+
+    display: flex;
+    justify-content: space-between;   
+}
+.bx-cp-top .bx-cp {
+    position: relative;
+}
+.bx-cp-top .bx-cp.bx-cp-views-container {
+    width: 8rem;
+}
+*/
+
+.bx-creative-content.gjs-editor-cont {
+    min-height: 50rem;
+    border: 1px solid #dddddd;
+}
+
+/*
+.bx-creative-content .gjs-cv-canvas {
+    top: 0;
+    width: 100%;
+    height: 100%;
+}
+*/

+ 52 - 5
template/scripts/BxBasePage.php

@@ -120,6 +120,29 @@ class BxBasePage extends BxDolPage
         ));
     }
 
+    public function performActionCreativeSave()
+    {
+        if(!$this->isAllowedCreativeManage())
+            return echoJson(['code' => 1]);
+
+        $iId = 0;
+        $sContent = '';
+        if(($iId = bx_get('b')) === false || ($sContent = bx_get('c')) === false)
+            return echoJson(['code' => 2]);
+
+        $iId = bx_process_input($iId, BX_DATA_INT);
+        $sContent = bx_process_input($sContent, BX_DATA_HTML);
+        if(!$this->_oQuery->setPageBlockContent($iId, $sContent))
+            return echoJson(['code' => 3]);
+
+        return echoJson(['code' => 0]);
+    }
+
+    public function isAllowedCreativeManage()
+    {
+        return isAdmin();
+    }
+
     /**
      * Very similar to BxBasePage::getCode
      * but adds css and js files which are needed for the corect page display
@@ -944,14 +967,38 @@ class BxBasePage extends BxDolPage
      */
     protected function _getBlockCreative ($aBlock)
     {
-        if (bx_is_api()){
+        if(bx_is_api())
             return [bx_api_get_block('creative', ['title' => _t($aBlock['title']), 'content' => $aBlock['content']])];
-        }
 
-        $s = '<div class="bx-page-creative-container bx-def-vanilla-html max-w-none">' . $aBlock['content'] . '</div>';
-        $s = $this->_replaceMarkers($s, array('block_id' => $aBlock['id']));
+        $s = $this->_replaceMarkers($aBlock['content'], ['block_id' => $aBlock['id']]);
         $s = bx_process_macros($s);
-        return $s;
+
+        $bCanManage = $this->isAllowedCreativeManage();
+
+        if($bCanManage) {
+            $this->_oTemplate->addCss([
+                BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'grapesjs/|grapes.min.css',
+            ]);
+
+            $this->_oTemplate->addJs([
+                'grapesjs/grapes.min.js',
+                'grapesjs/grapesjs-blocks-basic.js',
+                'grapesjs/grapesjs-style-bg.js',
+                'grapesjs/grapesjs-preset-webpage.min.js',
+            ]);
+        }
+        
+        return $this->_oTemplate->parseHtmlByName('block_creative.html', [
+            'block_id' => $aBlock['id'],
+            'content' => $s,
+            'bx_if:show_controls' => [
+                'condition' => $bCanManage,
+                'content' => [
+                    'onclick_edit' => $this->_sJsObjectName . '.creativeEdit(this, ' . $aBlock['id'] . ')',
+                    'onclick_save' => $this->_sJsObjectName . '.creativeSave(this, ' . $aBlock['id'] . ')'
+                ]
+            ]
+        ]);
     }
 
     /**