extpoint-yii2
Version:
JavaScript part for projects on ExtPoint Yii2 Boilerplate and yii2-core
205 lines (187 loc) • 6.73 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import 'ckeditor';
import 'ckeditor/lang/ru';
import 'ckeditor/styles';
import 'ckeditor/plugins/widget/plugin';
import 'ckeditor/plugins/widget/lang/ru';
import 'ckeditor/plugins/widgetselection/plugin';
import 'ckeditor/plugins/lineutils/plugin';
import 'ckeditor/plugins/filetools/plugin';
import 'ckeditor/plugins/filetools/lang/ru';
import 'ckeditor/plugins/notificationaggregator/plugin';
import 'ckeditor/plugins/uploadwidget/plugin';
import 'ckeditor/plugins/uploadwidget/lang/ru';
import 'ckeditor/plugins/link/dialogs/link';
import 'ckeditor/plugins/pastefromword/filter/default';
import FileUp from 'fileup-core';
import QueueCollection from 'fileup-core/lib/models/QueueCollection';
import {types, view} from 'components';
import iconsPath from './images/icons.png';
const CKEDITOR = window.CKEDITOR;
// Do not load js and css
CKEDITOR.document.appendStyleSheet = () => {};
CKEDITOR.config.plugins = CKEDITOR.config.plugins.replace(/tableselection,?/, '');
CKEDITOR.config.customConfig = '';
CKEDITOR.config.contentsCss = '';
CKEDITOR.plugins.loaded = {
widget: 1,
widgetselection: 1,
lineutils: 1,
filetools: 1,
notification: 1,
notificationaggregator: 1,
uploadwidget: 1,
pastefromword: 1,
};
CKEDITOR.lang.languages = {
ru: 1,
en: 1,
};
// Replace icons path
Object.keys(CKEDITOR.skin.icons).forEach(name => {
CKEDITOR.skin.icons[name].path = iconsPath;
});
// Add FileUp plugin
CKEDITOR.plugins.add('fileup', {
requires: 'uploadwidget',
init: function (editor) {
// Do not execute this paste listener if it will not be possible to upload file.
if (!CKEDITOR.plugins.clipboard.isFileApiSupported) {
return;
}
const uploadUrl = CKEDITOR.fileTools.getUploadUrl(editor.config, 'image');
if (!uploadUrl) {
CKEDITOR.error('fileup-config');
return;
}
editor.addCommand('image', {
exec: function () {
const uploader = new FileUp({
backendUrl: uploadUrl,
});
const element = new CKEDITOR.dom.element('div');
element.setStyles({
padding: '50px',
textAlign: 'center',
background: '#eee'
});
uploader.queue.on(QueueCollection.EVENT_ADD, () => {
editor.insertElement(element);
});
uploader.queue.on(QueueCollection.EVENT_ITEM_STATUS, file => {
if (file.isStatusEnd()) {
if (file.isResultSuccess()) {
const url = file.getResultHttpMessage() && file.getResultHttpMessage().url;
if (url) {
element.setStyles({
padding: '',
textAlign: '',
background: ''
});
element.setHtml('<img src="' + url + '" width="100%" alt="" />');
editor.fire('change');
return;
}
}
element.setStyles({
color: 'red'
});
element.setHtml(editor.lang.filetools.httpError.replace('%1', file.getResultHttpStatus()));
editor.fire('change');
}
});
uploader.queue.on(QueueCollection.EVENT_ITEM_PROGRESS, file => {
element.setText(editor.lang.common.upload + '...' + file.progress.getPercent() + '%');
});
uploader.browse();
}
});
}
});
export default class HtmlField extends React.Component {
static propTypes = {
metaItem: PropTypes.object.isRequired,
editorConfig: PropTypes.object,
input: PropTypes.shape({
name: PropTypes.string,
value: PropTypes.any,
onChange: PropTypes.func,
}),
};
static idCounter = 0;
// TODO Format button, need css bundle for load it in iframe. Wait migration to webpack 2/3
static CKEditorConfig = {
toolbar: [
/*{
'name': 'styles',
'items': [
'Format'
]
},*/
{
'name': 'basicstyles', 'groups': ['basicstyles', 'cleanup'],
'items': [
'Bold',
'Italic',
'Underline',
'-',
'RemoveFormat',
]
},
{
'name': 'paragraph', 'groups': ['list', 'blocks', 'align'],
'items': [
'NumberedList',
'BulletedList',
'-',
'Blockquote',
'-',
'JustifyLeft',
'JustifyCenter',
'JustifyRight',
]
},
{
'name': 'links',
'items': [
'Link'
]
},
{
'name': 'insert',
'items': [
'Image'
]
},
],
language: 'ru',
defaultLanguage: 'ru',
stylesSet: false,
allowedContent: 'p h1[text-align]; a[!href]; strong em; p(tip); img[alt,width,!src]; blockquote; ul ol; li',
extraPlugins: 'fileup',
uploadUrl: types.fileEditorUrl,
};
constructor() {
super(...arguments);
this._editorId = `editor-${++HtmlField.idCounter}`;
}
render() {
const {input, ...props} = this.props;
const HtmlFieldView = this.props.view || view.getFormView('HtmlFieldView');
return (
<HtmlFieldView
{...props}
editorId={this._editorId}
editorConfig={{
...HtmlField.CKEditorConfig,
...this.props.editorConfig,
}}
inputProps={{
id: this._editorId,
...input,
}}
/>
);
}
}