Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch form PEL to SunEditor as default WYSIWYG editor #219

Merged
merged 6 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@
/.phpunit.result.cache
/node_modules
/yarn.lock

/src/Resources/public/js/*.txt
16 changes: 14 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ reset: ## Stop docker and remove dependencies
${MAKE} docker.down || true
rm -rf ${APP_DIR}/node_modules ${APP_DIR}/yarn.lock
rm -rf ${APP_DIR}
rm -rf vendor composer.lock
rm -rf vendor composer.lock node_modules yarn.lock
.PHONY: reset

dependencies: composer.lock node_modules ## Setup the dependencies
Expand Down Expand Up @@ -132,7 +132,7 @@ test.container: ## Lint the symfony container
${CONSOLE} lint:container

test.yaml: ## Lint the symfony Yaml files
${CONSOLE} lint:yaml ../../recipes ../../src/Resources/config
${CONSOLE} lint:yaml --parse-tags ../../recipes ../../src/Resources/config

test.schema: ## Validate MySQL Schema
${CONSOLE} doctrine:schema:validate
Expand Down Expand Up @@ -200,6 +200,18 @@ server.start: ## Run the local webserver using Symfony
server.stop: ## Stop the local webserver
${SYMFONY} local:server:stop

###
### THEMING
### ¯¯¯¯¯¯¯

.PHONY: sylius.theming.build
sylius.theming.build: yarn.install
${YARN} build

.PHONY: sylius.theming.watch
sylius.theming.watch: yarn.install
${YARN} watch

###
### HELP
### ¯¯¯¯
Expand Down
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,49 @@ In the YAML declaration of a UI Element, you can add the wireframe key with the
front_render: '@MonsieurBizSyliusRichEditorPlugin/Shop/UiElement/title.html.twig'
```

## Wysiwyg Type

The `WysiwygType` form type is a custom form type provided by the MonsieurBiz Sylius Rich Editor plugin. It extends the
Symfony's `TextareaType` and provides a rich text editor interface in the admin form. It will work only in admin.

### Basic Usage

To use the `WysiwygType` in your form, you can add it to your form builder like this:

```php
$builder->add('content', WysiwygType::class, [
'required' => false,
'label' => 'app.form.content',
]);
```
### Options

The `WysiwygType` form type accepts several options:

- `editor_type`: The type of the editor. Default is `SunEditor::TYPE`. At this time, the only supported editor type is `SunEditor::TYPE`.
- `editor_height`: The height of the editor in pixels. Default is `300`.
- `editor_locale`: The locale of the editor. Default is the current admin locale or 'en' if it cannot be determined.
- `editor_toolbar_type`: The type of the toolbar. It can be one of the following: `EditorInterface::TOOLBAR_TYPE_MINIMAL`, `EditorInterface::TOOLBAR_TYPE_BASIC`, `EditorInterface::TOOLBAR_TYPE_FULL`, `EditorInterface::TOOLBAR_TYPE_CUSTOM`. Default is `EditorInterface::TOOLBAR_TYPE_BASIC`.
- `editor_toolbar_buttons`: An array of buttons to be displayed in the toolbar when `editor_toolbar_type` is `EditorInterface::TOOLBAR_TYPE_CUSTOM`. Default is `null`.
- `editor_custom_config`: An array of custom configuration options for the editor. Default is `null`.

Here is an example of how to use these options:

```php
$builder->add('content', WysiwygType::class, [
'required' => false,
'label' => 'app.form.content',
'editor_height' => 500,
'editor_locale' => 'fr',
'editor_toolbar_type' => EditorInterface::TOOLBAR_TYPE_CUSTOM,
'editor_toolbar_buttons' => ['bold', 'italic', 'underline'],
'editor_custom_config' => ['option1' => 'value1', 'option2' => 'value2'],
]);
```

In this example, we have set a custom editor type, increased the height of the editor, set the locale to French, chosen
a full toolbar, specified the buttons to be displayed in the toolbar, and provided some custom configuration options for
the editor.

## Contributing

Expand Down
69 changes: 11 additions & 58 deletions assets/js/app.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,22 @@
import pell from 'pell';
import Dialog from 'a11y-dialog-component';
import Mustache from 'mustache';
import '../css/app.scss';

global.MonsieurBizRichEditorWysiwyg = class {
constructor(config) {
this.config = config; // {actions: []}
}

exec() {
return pell.exec(...arguments);
}
import suneditor from "./editors/editors/suneditor";

load(container) {
const targets = container.querySelectorAll('textarea.wysiwyg-enabled');
for (let target of targets) {
this.setupEditor(target);
}
}
const initEditors = (target) => {
suneditor.init(target);
}

setupEditor(target) {
target.setAttribute('hidden', 'true');

// Create container
const wysiwygContainer = document.createElement('div');
wysiwygContainer.classList.add('pell');
target.parentNode.appendChild(wysiwygContainer);

// Init pell wysiwyg
const editor = pell.init({
element: wysiwygContainer,
onChange: html => {
target.textContent = html
},
defaultParagraphSeparator: 'p',
actions: this.config.actions,
});

editor.addEventListener('paste', function (e) {
e.stopPropagation();
e.preventDefault();
let tempContainer = document.createElement('div');
let clipboardData = e.clipboardData || window.clipboardData;
tempContainer.innerHTML = clipboardData.getData('Text');
let text = tempContainer.textContent || tempContainer.innerText || "";
pell.exec('insertText', text);
return true;
});

// Populate wysiwyg with initial content
const initialContent = target.value;
editor.content.innerHTML = initialContent;
}

};
document.addEventListener('DOMContentLoaded', function () {
const target = document.querySelector('body');
initEditors(target);
});

global.MonsieurBizRichEditorConfig = class {
constructor(
input,
uielements,
wysiwyg,
containerHtml,
actionsHtml,
elementHtml,
Expand All @@ -76,7 +34,6 @@ global.MonsieurBizRichEditorConfig = class {
) {
this.input = input;
this.uielements = uielements;
this.wysiwyg = wysiwyg;
this.containerHtml = containerHtml;
this.actionsHtml = actionsHtml;
this.elementHtml = elementHtml;
Expand Down Expand Up @@ -400,10 +357,6 @@ global.MonsieurBizRichEditorManager = class {
return this.config.input;
}

get wysiwyg() {
return this.config.wysiwyg;
}

openSelectionPanel(position) {
this.selectionPanel.dialog.manager = this;
this.selectionPanel.dialog.position = position;
Expand Down Expand Up @@ -439,7 +392,7 @@ global.MonsieurBizRichEditorManager = class {
drawNewForm(formHtml, position) {
this.newPanel.dialog.innerHTML = formHtml;
let form = this.newPanel.dialog;
this.wysiwyg.load(form);
initEditors(form);
this.dispatchInitFormEvent(form, this);

// Form submit
Expand Down Expand Up @@ -506,7 +459,7 @@ global.MonsieurBizRichEditorManager = class {
this.editPanel.dialog.querySelector('.js-uie-content').innerHTML = formHtml;
let form = this.editPanel.dialog;

this.wysiwyg.load(form);
initEditors(form);
this.dispatchInitFormEvent(form, this);

// Form submit
Expand Down
49 changes: 49 additions & 0 deletions assets/js/editors/editors/suneditor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import 'suneditor/src/assets/css/suneditor.css'
import 'suneditor/src/assets/css/suneditor-contents.css'
import suneditor from 'suneditor'
import lang from 'suneditor/src/lang'
import suneditorPlugins from 'suneditor/src/plugins'
import CodeMirror from 'codemirror'
import 'codemirror/mode/htmlmixed/htmlmixed'
import 'codemirror/lib/codemirror.css'

const currentEditors = [];

const initEditor = () => {
return suneditor.init({
codeMirror: CodeMirror,
height: 'auto',
plugins: suneditorPlugins,
buttonList: []
});
}

export default {
init(target) {
const editorModel = initEditor();
target.querySelectorAll('[data-component="wysiwyg-editor"][data-editor-type="suneditor"]').forEach((component) => {

// SundEditor is ID based, so we need to make sure that the ID is unique
if (currentEditors.includes(component.id)) {
component.id = `${component.id}-${Math.random().toString(36).substring(7)}`;
}

const buttonList = JSON.parse(component.dataset.editorButtons);
const height = component.dataset.editorHeight;
const locale = component.dataset.editorLocale;
const customConfig = JSON.parse(component.dataset.editorCustomConfig);
const config = {
height,
buttonList,
lang: lang[locale],
...customConfig
};
const editor = editorModel.create(component, config);
editor.onChange = () => {
editor.save();
};

currentEditors.push(component.id);
})
}
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
},
"dependencies": {
"a11y-dialog-component": "^5.5.1",
"codemirror": "5",
"gulp": "^4.0.2",
"mustache": "^4.0.1",
"pell": "^1.0.6"
"suneditor": "^2.45.1"
}
}
6 changes: 4 additions & 2 deletions src/Form/Type/UiElement/HtmlType.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

namespace MonsieurBiz\SyliusRichEditorPlugin\Form\Type\UiElement;

use MonsieurBiz\SyliusRichEditorPlugin\Form\Type\WysiwygType;
use MonsieurBiz\SyliusRichEditorPlugin\WysiwygEditor\EditorInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;

class HtmlType extends AbstractType
Expand All @@ -25,8 +26,9 @@ class HtmlType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('content', TextareaType::class, [
->add('content', WysiwygType::class, [
'label' => 'monsieurbiz_richeditor_plugin.ui_element.monsieurbiz.html.field.content',
'editor_toolbar_type' => EditorInterface::TOOLBAR_TYPE_FULL,
])
;
}
Expand Down
2 changes: 2 additions & 0 deletions src/Form/Type/UiElement/TextType.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use MonsieurBiz\SyliusRichEditorPlugin\Form\Type\AlignmentType;
use MonsieurBiz\SyliusRichEditorPlugin\Form\Type\WysiwygType;
use MonsieurBiz\SyliusRichEditorPlugin\WysiwygEditor\EditorInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints as Assert;
Expand All @@ -30,6 +31,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
->add('content', WysiwygType::class, [
'required' => true,
'label' => 'monsieurbiz_richeditor_plugin.ui_element.monsieurbiz.text.field.content',
'editor_toolbar_type' => EditorInterface::TOOLBAR_TYPE_MINIMAL,
'constraints' => [
new Assert\NotBlank([]),
],
Expand Down
Loading
Loading