add grapesjs editor
This commit is contained in:
parent
7052d8ccc1
commit
c6bafeda19
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');
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
}
|
|
@ -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">
|
||||
|
|
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