acklen-keystone
Version:
Web Application Framework and Admin GUI / Content Management System built on Express.js and Mongoose
201 lines (173 loc) • 4.57 kB
JavaScript
import Field from '../Field';
import React from 'react';
import ckeditor from 'ckeditor';
import ckfinder from 'ckfinder';
import { FormInput } from '../../../admin/client/App/elemental';
import evalDependsOn from '../../utils/evalDependsOn';
var lastId = 0;
function getId () {
return 'keystone-html-' + lastId++;
}
function removeEditorInstance (id) {
if (ckeditor.instances[id]) {
ckeditor.instances[id].destroy();
}
}
module.exports = Field.create({
displayName: 'HtmlField',
statics: {
type: 'Html',
},
getInitialState () {
return {
id: getId(),
isFocused: false,
editorActive: false,
};
},
initEditor () {
if (!this.props.wysiwyg) return;
if (!ckeditor.instances[this.state.id]) {
var opts = this.getOptions();
this._currentValue = this.props.value;
this.editor = ckeditor.replace(this.state.id, {
contentsCss: opts.content_css || '',
allowedContent: true,
});
ckfinder.setupCKEditor(this.editor);
this.editor.on('change', this.valueChanged);
if (evalDependsOn(this.props.dependsOn, this.props.values)) {
this.setState({ editorActive: true });
}
}
},
removeEditor (state) {
removeEditorInstance(state.id);
this.setState({ editorActive: false });
},
componentDidUpdate (prevProps, prevState) {
if (prevState.isCollapsed && !this.state.isCollapsed) {
this.initEditor();
}
if (this.props.wysiwyg) {
if (evalDependsOn(this.props.dependsOn, this.props.values)) {
if (!this.state.editorActive) {
this.initEditor();
}
} else if (this.state.editorActive) {
this.removeEditor(prevState);
}
}
},
componentWillReceiveProps (nextProps) {
if (this.editor && this._currentValue !== nextProps.value) {
this.editor.setData(nextProps.value);
}
},
componentWillUnmount () {
this.removeEditor(this.state);
},
valueChanged (event) {
var content;
if (event.editor) {
content = event.editor.getData();
} else {
content = event.target.value;
}
this._currentValue = content;
this.props.onChange({
path: this.props.path,
value: content,
});
},
getOptions () {
var plugins = ['code', 'link'];
var options = Object.assign(
{},
Keystone.wysiwyg.options,
this.props.wysiwyg
);
var toolbar = options.overrideToolbar ? '' : 'bold italic | alignleft aligncenter alignright | bullist numlist | outdent indent | removeformat | link ';
var i;
if (options.enableImages) {
plugins.push('image');
toolbar += ' | image';
}
if (options.enableCloudinaryUploads || options.enableS3Uploads) {
plugins.push('uploadimage');
toolbar += options.enableImages ? ' uploadimage' : ' | uploadimage';
}
if (options.additionalButtons) {
var additionalButtons = options.additionalButtons.split(',');
for (i = 0; i < additionalButtons.length; i++) {
toolbar += (' | ' + additionalButtons[i]);
}
}
if (options.additionalPlugins) {
var additionalPlugins = options.additionalPlugins.split(',');
for (i = 0; i < additionalPlugins.length; i++) {
plugins.push(additionalPlugins[i]);
}
}
if (options.importcss) {
plugins.push('importcss');
var importcssOptions = {
content_css: options.importcss,
importcss_append: true,
importcss_merge_classes: true,
};
Object.assign(options.additionalOptions, importcssOptions);
}
if (!options.overrideToolbar) {
toolbar += ' | code';
}
var opts = {
selector: '#' + this.state.id,
toolbar: toolbar,
plugins: plugins,
menubar: options.menubar || false,
skin: options.skin || 'keystone',
};
if (this.shouldRenderField()) {
opts.uploadimage_form_url = options.enableS3Uploads ? Keystone.adminPath + '/api/s3/upload' : Keystone.adminPath + '/api/cloudinary/upload';
} else {
Object.assign(opts, {
mode: 'textareas',
readonly: true,
menubar: false,
toolbar: 'code',
statusbar: false,
});
}
if (options.additionalOptions) {
Object.assign(opts, options.additionalOptions);
}
return opts;
},
renderField () {
var className = this.state.isFocused ? 'is-focused' : '';
var style = {
height: this.props.height,
};
return (
<div className={className}>
<FormInput
id={this.state.id}
multiline
name={this.getInputName(this.props.path)}
onChange={this.valueChanged}
className={this.props.wysiwyg ? 'wysiwyg' : 'code'}
style={style}
value={this.props.value}
/>
</div>
);
},
renderValue () {
return (
<FormInput multiline noedit>
{this.props.value}
</FormInput>
);
},
});