Skip to content

Commit

Permalink
[project-base] fixed GrapesJS bug (#2927)
Browse files Browse the repository at this point in the history
  • Loading branch information
tvikito authored Dec 12, 2023
1 parent 469da6c commit 3cccf9b
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 194 deletions.
19 changes: 10 additions & 9 deletions app/assets/js/admin/grapesjs/initGrapesJs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import grapesjs from 'grapesjs';
import webPagePlugin from 'grapesjs-preset-webpage';
import ckeditorPlugin from 'grapesjs-plugin-ckeditor';
import newsletterPlugin from 'grapesjs-preset-newsletter';
import countDownPlugin from 'grapesjs-component-countdown';
import './grapesjs-non-editable-page';
import './plugins/grapesjs-custom-buttons-plugin';
import './plugins/grapesjs-products-plugin';
Expand Down Expand Up @@ -63,7 +62,6 @@ export default class InitGrapesJs {
const plugins = [
webPagePlugin,
ckeditorPlugin,
countDownPlugin,
'nonEditablePage',
'customButtons',
'text-with-image',
Expand All @@ -73,6 +71,7 @@ export default class InitGrapesJs {
'custom-image-file',
'custom-iframe'
];

if (allowProducts) {
plugins.push('products');
}
Expand Down Expand Up @@ -112,13 +111,6 @@ export default class InitGrapesJs {
blocks: [''],
useCustomTheme: false
},
[countDownPlugin]: {
block: {
label: 'Countdown',
category: 'Extra',
attributes: { class: 'fa fa-clock-o' }
}
},
customButtons: {
textareaId: textareaId
}
Expand Down Expand Up @@ -157,6 +149,15 @@ export default class InitGrapesJs {
}
});

editor.TraitManager.addType('textarea', {
createInput () {
return document.createElement('textarea');
},
onUpdate ({ elInput, _, trait }) {
elInput.value = trait.changed.value;
}
});

CKEDITOR.on('instanceReady', function (e) {
editor.RichTextEditor.updatePosition();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ export default grapesjs.plugins.add('custom-blocks', (editor, options) => {
label: 'Video',
category: 'Basic',
attributes: { class: 'fa fa-youtube-play' },
content: `
<div class="video">
<video src="img/video2.webm" />
</div>
`
content: {
type: 'video'
}
});

editor.Blocks.add('map', {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@

import grapesjs from 'grapesjs';

const IFRAME_WIDTH_ATTRIBUTE = 'width';
const IFRAME_HEIGHT_ATTRIBUTE = 'height';

export default grapesjs.plugins.add('custom-iframe', (editor) => {
editor.DomComponents.addType('iframe', {
isComponent: el => el.tagName === 'IFRAME',
model: {
init () {
this.on(`change:attributes:${IFRAME_WIDTH_ATTRIBUTE}`, this.handleWidthChange);
this.on(`change:attributes:${IFRAME_HEIGHT_ATTRIBUTE}`, this.handleHeightChange);
},
handleWidthChange (component) {
console.log('Input width changed to: ', this.getAttributes()[IFRAME_WIDTH_ATTRIBUTE], component.getStyle(), component);
component.setStyle({ ...component.getStyle(), width: this.getAttributes()[IFRAME_WIDTH_ATTRIBUTE] });
// component.setStyle({ ...component.getStyle(), id: 'width', 'data-key': this.getAttributes()[IFRAME_WIDTH_ATTRIBUTE] });
},
handleHeightChange (component) {
console.log('Input height changed to: ', this.getAttributes()[IFRAME_HEIGHT_ATTRIBUTE], component);
component.setStyle({ ...component.getStyle(), height: this.getAttributes()[IFRAME_HEIGHT_ATTRIBUTE] });
// component.setAttributes({ height: this.getAttributes()[IFRAME_HEIGHT_ATTRIBUTE] });
},
defaults: {
type: 'iframe',
traits: [
Expand All @@ -16,13 +33,13 @@ export default grapesjs.plugins.add('custom-iframe', (editor) => {
{
type: 'text',
label: 'Width',
name: 'width',
value: '100%'
name: IFRAME_WIDTH_ATTRIBUTE,
placeholder: '100%'
},
{
type: 'text',
label: 'Height',
name: 'height'
name: IFRAME_HEIGHT_ATTRIBUTE
}
]
}
Expand All @@ -32,7 +49,7 @@ export default grapesjs.plugins.add('custom-iframe', (editor) => {
editor.BlockManager.add('iframe', {
label: 'Iframe',
type: 'iframe',
content: '<iframe> </iframe>',
content: '<iframe class="gjs-iframe" style="width: 100%"> </iframe>',
category: 'Basic',
selectable: true,
attributes: { class: 'fa fa-crop' }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export default grapesjs.plugins.add('products', editor => {
`,
traits: [
{
type: 'text',
type: 'textarea',
name: dataProducts,
label: Translator.trans('Catalog numbers delimited by comma')
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,62 @@
import grapesjs from 'grapesjs';
import Translator from 'bazinga-translator';

const IMAGE_POSITION_DATA_ATTRIBUTE = 'data-image-position';
const IMAGE_TYPE_DATA_ATTRIBUTE = 'data-image-type';

const TEXT_WITH_IMAGE_TYPE = 'text-with-image';

const IMAGE_CLASS = 'gjs-text-with-image';
const IMAGE_CLASS_INNER = 'gjs-text-with-image-inner';
const IMAGE_CLASS_TYPE = 'gjs-text-with-image-type';
const IMAGE_CLASS_FLOAT = 'gjs-text-with-image-float';

const IMAGE_POSITION_LEFT = 'left';
const IMAGE_POSITION_RIGHT = 'right';

const IMAGE_FLOAT_INSIDE = 'inside-layout';
const IMAGE_FLOAT_OUTSIDE = 'outside-layout';

export default grapesjs.plugins.add('text-with-image', editor => {
editor.Blocks.add('textWithImage', {
id: 'text-with-image',
label: Translator.trans('Text with image'),
category: 'Basic',
media: '<svg xmlns="http://www.w3.org/2000/svg" width="48px" height="48px" viewBox="0 0 576 512"><path d="M528 32h-480C21.49 32 0 53.49 0 80V96h576V80C576 53.49 554.5 32 528 32zM0 432C0 458.5 21.49 480 48 480h480c26.51 0 48-21.49 48-48V128H0V432zM368 192h128C504.8 192 512 199.2 512 208S504.8 224 496 224h-128C359.2 224 352 216.8 352 208S359.2 192 368 192zM368 256h128C504.8 256 512 263.2 512 272S504.8 288 496 288h-128C359.2 288 352 280.8 352 272S359.2 256 368 256zM368 320h128c8.836 0 16 7.164 16 16S504.8 352 496 352h-128c-8.836 0-16-7.164-16-16S359.2 320 368 320zM176 192c35.35 0 64 28.66 64 64s-28.65 64-64 64s-64-28.66-64-64S140.7 192 176 192zM112 352h128c26.51 0 48 21.49 48 48c0 8.836-7.164 16-16 16h-192C71.16 416 64 408.8 64 400C64 373.5 85.49 352 112 352z"/></svg>',
content: {
type: 'text-with-image'
type: TEXT_WITH_IMAGE_TYPE
}
});

editor.DomComponents.addType('text-with-image', {
isComponent: element => element.classList && element.classList.contains('gjs-text-with-image'),
editor.DomComponents.addType(TEXT_WITH_IMAGE_TYPE, {
isComponent: element => element.classList && element.classList.contains(IMAGE_CLASS),
model: {
defaults: {
attributes: {
class: ['gjs-text-with-image']
class: [IMAGE_CLASS]
},
droppable: false,
components: `
<div class="gjs-text-with-image-inner inner left">
<div class="${IMAGE_CLASS_INNER} ${IMAGE_CLASS_FLOAT}-left ${IMAGE_CLASS_TYPE}-outside-layout">
<img class="image">
<div class="gjs-text-ckeditor text">Insert your text here</div>
<div class="clear" />
</div>
`
}
}
});

const imagePositionDataAttribute = 'data-image-position';
const imageTypeDataAttribute = 'data-image-type';

editor.DomComponents.addType('text-with-image-inner', {
isComponent: element => element.classList && element.classList.contains('gjs-text-with-image-inner'),
isComponent: element => element.classList && element.classList.contains(IMAGE_CLASS_INNER),
model: {
init () {
this.on(`change:attributes:${imagePositionDataAttribute}`, this.handleTypeChange);
this.on(`change:attributes:${imageTypeDataAttribute}`, this.handleTypeChange);
this.on(`change:attributes:${IMAGE_POSITION_DATA_ATTRIBUTE}`, this.handleTypeChange);
this.on(`change:attributes:${IMAGE_TYPE_DATA_ATTRIBUTE}`, this.handleTypeChange);
},

handleTypeChange (element) {
element.setClass(['gjs-text-with-image-inner', 'inner', `text-with-image-float-${this.getAttributes()[imagePositionDataAttribute]}`,
`text-with-image-type-${this.getAttributes()[imageTypeDataAttribute]}`
element.setClass([IMAGE_CLASS_INNER, `${IMAGE_CLASS_FLOAT}-${this.getAttributes()[IMAGE_POSITION_DATA_ATTRIBUTE]}`,
`${IMAGE_CLASS_TYPE}-${this.getAttributes()[IMAGE_TYPE_DATA_ATTRIBUTE]}`
]);
},
defaults: {
Expand All @@ -54,37 +66,37 @@ export default grapesjs.plugins.add('text-with-image', editor => {
droppable: false,
propagate: ['removable', 'draggable', 'copyable', 'droppable'],
attributes: {
[imagePositionDataAttribute]: 'left',
[imageTypeDataAttribute]: 'outside-layout',
class: ['gjs-text-with-image-inner', 'inner', 'left']
[IMAGE_POSITION_DATA_ATTRIBUTE]: IMAGE_POSITION_LEFT,
[IMAGE_TYPE_DATA_ATTRIBUTE]: IMAGE_FLOAT_OUTSIDE,
class: [IMAGE_CLASS_INNER]
},
traits: [
{
type: 'select',
name: imagePositionDataAttribute,
name: IMAGE_POSITION_DATA_ATTRIBUTE,
label: Translator.trans('Position of image'),
options: [
{
id: 'left',
id: IMAGE_POSITION_LEFT,
label: 'Left'
},
{
id: 'right',
id: IMAGE_POSITION_RIGHT,
label: 'Right'
}
]
},
{
type: 'select',
name: imageTypeDataAttribute,
name: IMAGE_TYPE_DATA_ATTRIBUTE,
label: Translator.trans('Type of image'),
options: [
{
id: 'outside-layout',
id: IMAGE_FLOAT_OUTSIDE,
label: Translator.trans('Outside layout')
},
{
id: 'inside-layout',
id: IMAGE_FLOAT_INSIDE,
label: Translator.trans('Inside layout')
}
]
Expand Down
1 change: 0 additions & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
"codemirror": "^5.60.0",
"counterup2": "^1.0.4",
"grapesjs": "^0.20.3",
"grapesjs-component-countdown": "^1.0.1",
"grapesjs-plugin-ckeditor": "^0.0.10",
"grapesjs-preset-newsletter": "^0.2.21",
"grapesjs-preset-webpage": "^1.0.2",
Expand Down
1 change: 0 additions & 1 deletion app/src/Component/GrapesJs/GrapesJsParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ private function getConfiguredSanitizer(): HtmlSanitizer
->allowSafeElements()
->allowStaticElements()
->allowRelativeLinks()
->dropAttribute('style', 'div')
->allowElement('iframe', '*')
->withMaxInputLength(25000);

Expand Down
4 changes: 2 additions & 2 deletions storefront/components/Basic/UserText/GrapesJs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ type GrapesJsProps = {

export const GrapesJs: FC<GrapesJsProps> = ({ dataTestId, content, className }) => (
<section
className={twMergeCustom('grapesjs-text user-text', className)}
dangerouslySetInnerHTML={{ __html: content !== undefined ? content : '' }}
className={twMergeCustom('user-text', className)}
dangerouslySetInnerHTML={{ __html: content || '' }}
data-gjs-type="editable"
data-testid={dataTestId}
/>
Expand Down
76 changes: 0 additions & 76 deletions storefront/components/Basic/UserText/UserText.module.sass

This file was deleted.

9 changes: 1 addition & 8 deletions storefront/components/Basic/UserText/UserText.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { GrapesJs } from './GrapesJs';
import styles from './UserText.module.sass';

type UserTextProps = {
htmlContent: string;
Expand All @@ -11,11 +10,5 @@ export const UserText: FC<UserTextProps> = ({ dataTestId, htmlContent, isGrapesJ
return <GrapesJs content={htmlContent} dataTestId={dataTestId} />;
}

return (
<section
className={styles.userTextBasic}
dangerouslySetInnerHTML={{ __html: htmlContent }}
data-testid={dataTestId}
/>
);
return <section dangerouslySetInnerHTML={{ __html: htmlContent }} data-testid={dataTestId} />;
};
6 changes: 0 additions & 6 deletions storefront/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ address,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
h6,
img,
table,
tr,
Expand Down
Loading

0 comments on commit 3cccf9b

Please sign in to comment.