Merge branch 'feature/grapejs' into develop
This commit is contained in:
commit
f48041eacd
|
@ -101,6 +101,7 @@ class PageAdminController extends CrudController
|
|||
->setForm('edit', Type::class, [])
|
||||
->setForm('filter', FilterType::class)
|
||||
->setView('form', '@Core/site/page_admin/_form.html.twig')
|
||||
->setView('edit', '@Core/site/page_admin/edit.html.twig')
|
||||
|
||||
->setAction('index', 'new', false)
|
||||
->setAction('index', 'show', false)
|
||||
|
|
21
src/core/Form/Site/Page/GrapesJsBlockType.php
Normal file
21
src/core/Form/Site/Page/GrapesJsBlockType.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace App\Core\Form\Site\Page;
|
||||
|
||||
use App\Core\Form\Type\GrapesJsType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class GrapesJsBlockType extends TextareaBlockType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add(
|
||||
'value',
|
||||
GrapesJsType::class,
|
||||
array_merge([
|
||||
'required' => false,
|
||||
'label' => false,
|
||||
], $options['options']),
|
||||
);
|
||||
}
|
||||
}
|
30
src/core/Form/Type/GrapesJsType.php
Normal file
30
src/core/Form/Type/GrapesJsType.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Core\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
|
||||
class GrapesJsType extends TextareaType
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||
{
|
||||
if (!isset($view->vars['attr']['data-grapesjs'])) {
|
||||
$view->vars['attr']['data-grapesjs'] = '';
|
||||
}
|
||||
|
||||
return parent::buildView($view, $form, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'grapesjs';
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ $pagination-active-bg: #343a40 !default;
|
|||
@import "~@fortawesome/fontawesome-free/css/all.css";
|
||||
@import "~flag-icon-css/sass/flag-icon.scss";
|
||||
@import "~flag-icon-css/sass/flag-icon.scss";
|
||||
@import '~grapesjs/dist/css/grapes.min.css';
|
||||
|
||||
@for $i from 1 through 100 {
|
||||
.miw-#{$i*5} {
|
||||
|
@ -575,3 +576,12 @@ form {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.gjs-editor-cont {
|
||||
border-radius: 10px;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.gjs-one-bg {
|
||||
background: map-get($theme-colors, 'dark-blue');
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ require('./modules/password.js')()
|
|||
require('./modules/tooltip.js')()
|
||||
require('./modules/tinymce.js')()
|
||||
require('./modules/editorjs.js')()
|
||||
require('./modules/grapesjs.js')()
|
||||
require('./modules/panel.js')()
|
||||
require('./modules/choices.js')()
|
||||
require('./modules/checkbox-checker.js')()
|
||||
|
@ -25,3 +26,4 @@ require('./modules/batch.js')()
|
|||
require('./modules/file-manager.js')()
|
||||
require('./modules/file-picker.js')()
|
||||
require('./modules/analytics.js')()
|
||||
require('./modules/page.js')()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const $ = require('jquery')
|
||||
const EditorJS = require('@editorjs/editorjs')
|
||||
const InlineTools = require('editorjs-inline-tool')
|
||||
const Routing = require('../../../../../../../../friendsofsymfony/jsrouting-bundle/Resources/public/js/router.min.js')
|
||||
const Routing = require('../../../../../../../../friendsofsymfony/jsrouting-bundle/Resources/public/js/router.min.js')
|
||||
const routes = require('../../../../../../../../../public/js/fos_js_routes.json')
|
||||
|
||||
const UnderlineInlineTool = InlineTools.UnderlineInlineTool
|
||||
|
@ -84,24 +84,24 @@ const tools = {
|
|||
bold: {
|
||||
class: createGenericInlineTool({
|
||||
sanitize: {
|
||||
strong: {},
|
||||
strong: {}
|
||||
},
|
||||
shortcut: 'CMD+B',
|
||||
tagName: 'STRONG',
|
||||
toolboxIcon:
|
||||
'<svg class="icon icon--bold" width="12px" height="14px"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#bold"></use></svg>',
|
||||
}),
|
||||
'<svg class="icon icon--bold" width="12px" height="14px"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#bold"></use></svg>'
|
||||
})
|
||||
},
|
||||
italic: {
|
||||
class: createGenericInlineTool({
|
||||
sanitize: {
|
||||
em: {},
|
||||
em: {}
|
||||
},
|
||||
shortcut: 'CMD+I',
|
||||
tagName: 'EM',
|
||||
toolboxIcon:
|
||||
'<svg class="icon icon--italic" width="12px" height="14px"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#italic"></use></svg>',
|
||||
}),
|
||||
'<svg class="icon icon--italic" width="12px" height="14px"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#italic"></use></svg>'
|
||||
})
|
||||
},
|
||||
underline: UnderlineInlineTool
|
||||
}
|
||||
|
|
106
src/core/Resources/assets/js/modules/grapesjs.js
Normal file
106
src/core/Resources/assets/js/modules/grapesjs.js
Normal file
|
@ -0,0 +1,106 @@
|
|||
const $ = require('jquery')
|
||||
const GrapesJs = require('grapesjs')
|
||||
const bootstrap4 = require('grapesjs-blocks-bootstrap4').default
|
||||
|
||||
const makeId = () => {
|
||||
let result = ''
|
||||
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789'
|
||||
const charactersLength = characters.length
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength))
|
||||
}
|
||||
|
||||
return 'grapesjs-' + result
|
||||
}
|
||||
|
||||
const doInitEditor = () => {
|
||||
$('textarea[data-grapesjs]').each((i, v) => {
|
||||
const textarea = $(v)
|
||||
const element = textarea.parent().prev()
|
||||
const id = element.attr('id') ? element.attr('id') : makeId()
|
||||
|
||||
element.attr('id', id)
|
||||
|
||||
const editor = GrapesJs.init({
|
||||
container: '#' + id,
|
||||
fromElement: false,
|
||||
height: '900px',
|
||||
width: 'auto',
|
||||
storageManager: {
|
||||
autoload: false
|
||||
},
|
||||
noticeOnUnload: 0,
|
||||
showOffsets: 1,
|
||||
showDevices: false,
|
||||
plugins: ['grapesjs-blocks-bootstrap4'],
|
||||
colorPicker: {
|
||||
appendTo: 'parent',
|
||||
offset: {
|
||||
top: 26,
|
||||
left: -166
|
||||
}
|
||||
},
|
||||
pluginsOpts: {
|
||||
'grapesjs-blocks-bootstrap4': {
|
||||
blocks: {},
|
||||
blockCategories: {},
|
||||
labels: {},
|
||||
gridDevicesPanel: true,
|
||||
formPredefinedActions: [
|
||||
]
|
||||
}
|
||||
},
|
||||
canvas: {
|
||||
styles: [
|
||||
'https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css'
|
||||
],
|
||||
scripts: [
|
||||
'https://code.jquery.com/jquery-3.5.1.slim.min.js',
|
||||
'https://unpkg.com/@popperjs/core@2',
|
||||
'https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js'
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const deviceManager = editor.DeviceManager
|
||||
|
||||
const devices = [
|
||||
'Extra Small',
|
||||
'Small',
|
||||
'Medium',
|
||||
'Large',
|
||||
'Extra Large',
|
||||
'Desktop',
|
||||
'Tablet',
|
||||
'mobileLandscape',
|
||||
'mobilePortrait'
|
||||
]
|
||||
|
||||
for (const device of devices) {
|
||||
deviceManager.remove(device)
|
||||
}
|
||||
|
||||
deviceManager.add('All', '100%')
|
||||
|
||||
editor.Panels.getPanels().remove('devices-buttons')
|
||||
|
||||
editor.on('update', () => {
|
||||
textarea.val(JSON.stringify(editor.storeData()))
|
||||
})
|
||||
|
||||
console.log(textarea.val())
|
||||
|
||||
try {
|
||||
editor.loadData(JSON.parse(textarea.val()))
|
||||
} catch (e) {
|
||||
editor.loadData({ html: '' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = () => {
|
||||
$(() => {
|
||||
doInitEditor()
|
||||
})
|
||||
}
|
41
src/core/Resources/assets/js/modules/page.js
Normal file
41
src/core/Resources/assets/js/modules/page.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
const $ = require('jquery')
|
||||
|
||||
const doExpandCollapse = (stmt) => {
|
||||
stmt = (stmt == 1)
|
||||
|
||||
const button = $('#page-form-expand')
|
||||
const mainForm = $('#page-main-form')
|
||||
const metasForm = $('#page-metas-form')
|
||||
|
||||
mainForm
|
||||
.toggleClass('col-md-8', !stmt)
|
||||
.toggleClass('col-md-12', stmt)
|
||||
|
||||
metasForm
|
||||
.toggleClass('d-none', stmt)
|
||||
|
||||
button
|
||||
.children()
|
||||
.toggleClass('fa-expand-arrows-alt', !stmt)
|
||||
.toggleClass('fa-compress-arrows-alt', stmt)
|
||||
|
||||
localStorage.setItem('pageFormExpandStmt', stmt ? 1 : null)
|
||||
}
|
||||
|
||||
const initExpander = () => {
|
||||
const button = $('#page-form-expand')
|
||||
|
||||
if (button.length) {
|
||||
doExpandCollapse(localStorage.getItem('pageFormExpandStmt'))
|
||||
|
||||
button.click(() => {
|
||||
doExpandCollapse(button.children().hasClass('fa-expand-arrows-alt'))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = () => {
|
||||
$(() => {
|
||||
initExpander()
|
||||
})
|
||||
}
|
|
@ -1,5 +1,12 @@
|
|||
{% extends 'bootstrap_4_layout.html.twig' %}
|
||||
|
||||
{% block grapesjs_widget %}
|
||||
<div class="gjs"></div>
|
||||
<div class="d-none">
|
||||
<textarea {{ block('widget_attributes') }}>{{ value }}</textarea>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block file_widget -%}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
{% endset %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 p-2">
|
||||
<div class="col-md-8 p-2" id="page-main-form">
|
||||
{{ form_widget(form, {attr: {class: 'row'}}) }}
|
||||
</div>
|
||||
<div class="col-md-4 p-3">
|
||||
<div class="col-md-4 p-3" id="page-metas-form">
|
||||
<ul class="nav nav-pills">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="tab" href="#form-page-metas">{{ 'Meta datas'|trans }}</a>
|
||||
|
|
11
src/core/Resources/views/site/page_admin/edit.html.twig
Normal file
11
src/core/Resources/views/site/page_admin/edit.html.twig
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% extends '@Core/admin/crud/edit.html.twig' %}
|
||||
|
||||
{% block header %}
|
||||
{{ parent() }}
|
||||
|
||||
<div class="float-right">
|
||||
<button class="btn btn-sm btn-light mr-2 mt-2" id="page-form-expand">
|
||||
<span class="fa fa-expand-arrows-alt"></span>
|
||||
</button>
|
||||
</div>
|
||||
{% endblock %}
|
40
src/core/Twig/Extension/GrapesJsExtension.php
Normal file
40
src/core/Twig/Extension/GrapesJsExtension.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Core\Twig\Extension;
|
||||
|
||||
use App\Core\String\StringBuilder;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\Environment;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
|
||||
class GrapesJsExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new TwigFilter('grapesjs_html', [$this, 'getHtml']),
|
||||
new TwigFilter('grapesjs_css', [$this, 'getCss']),
|
||||
];
|
||||
}
|
||||
|
||||
public function getHtml(?string $value): ?string
|
||||
{
|
||||
return $this->extractData($value, 'html');
|
||||
}
|
||||
|
||||
public function getCss(?string $value): ?string
|
||||
{
|
||||
return $this->extractData($value, 'css');
|
||||
}
|
||||
|
||||
protected function extractData(?string $value, string $key): ?string
|
||||
{
|
||||
$data = json_decode($value, true);
|
||||
|
||||
return $data[$key] ?? '';
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue