add grapesjs editor

This commit is contained in:
Simon Vieille 2022-04-12 22:41:27 +02:00
parent 7052d8ccc1
commit c6bafeda19
Signed by: deblan
GPG key ID: 03383D15A1D31745
7 changed files with 221 additions and 7 deletions

View 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']),
);
}
}

View 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';
}
}

View file

@ -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');
}

View file

@ -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
}

View 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()
})
}

View file

@ -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">

View 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] ?? '';
}
}