diff --git a/client/package.json b/client/package.json index 33138075..21e3f053 100644 --- a/client/package.json +++ b/client/package.json @@ -70,6 +70,7 @@ "react-redux": "^4.4.5", "react-router": "^2.4.0", "react-router-redux": "^4.0.5", + "react-rte-browserify": "^0.5.0", "redux": "^3.5.2", "redux-promise-middleware": "^3.3.2" } diff --git a/client/src/core-components/__tests__/form-field-test.js b/client/src/core-components/__tests__/form-field-test.js index 43fece59..0d84c0a2 100644 --- a/client/src/core-components/__tests__/form-field-test.js +++ b/client/src/core-components/__tests__/form-field-test.js @@ -3,7 +3,7 @@ const Checkbox = ReactMock(); const DropDown = ReactMock(); const TextEditor = ReactMock(); -const {EditorState} = require('draft-js'); +const RichTextEditor = require('react-rte-browserify'); const FormField = requireUnit('core-components/form-field', { 'core-components/input': Input, @@ -35,7 +35,7 @@ describe('FormField component', function () { expect(FormField.getDefaultValue('input')).to.equal(''); expect(FormField.getDefaultValue('checkbox')).to.equal(false); expect(FormField.getDefaultValue('select')).to.equal(0); - expect(FormField.getDefaultValue('textarea') instanceof EditorState).to.equal(true); + expect(FormField.getDefaultValue('textarea') instanceof RichTextEditor.EditorValue).to.equal(true); }); }); diff --git a/client/src/core-components/__tests__/form-test.js b/client/src/core-components/__tests__/form-test.js index a778d6b4..27518d84 100644 --- a/client/src/core-components/__tests__/form-test.js +++ b/client/src/core-components/__tests__/form-test.js @@ -1,15 +1,11 @@ // MOCKS const ValidationFactoryMock = require('lib-app/__mocks__/validations/validation-factory-mock'); const FormField = ReactMock(); -const {EditorState} = require('draft-js'); -const draftJsExportHTML = { - stateToHTML: stub().returns('HTML_CODE') -}; +const RichTextEditor = require('react-rte-browserify'); // COMPONENT const Form = requireUnit('core-components/form', { 'lib-app/validations/validations-factory': ValidationFactoryMock, - 'draft-js-export-html': draftJsExportHTML, 'core-components/form-field': FormField }); @@ -176,19 +172,6 @@ describe('Form component', function () { expect(form.props.onSubmit).to.have.been.calledWith(form.state.form); }); - it('should tranform EditorState to HTML usign draft-js-export-html library', function () { - draftJsExportHTML.stateToHTML.reset(); - form.state.form.first = EditorState.createEmpty(); - - TestUtils.Simulate.submit(ReactDOM.findDOMNode(form)); - expect(draftJsExportHTML.stateToHTML).to.have.been.calledWith(form.state.form.first.getCurrentContent()); - expect(form.props.onSubmit).to.have.been.calledWith({ - first: 'HTML_CODE', - second: 'value2', - third: 'value3' - }); - }); - it('should validate all fields and not call onSubmit if there are errors', function () { ValidationFactoryMock.validators.defaultValidatorMock.performValidation = stub().returns('MOCK_ERROR'); ValidationFactoryMock.validators.customValidatorMock.performValidation = stub().returns('MOCK_ERROR_2'); @@ -203,6 +186,19 @@ describe('Form component', function () { expect(form.props.onSubmit).to.not.have.been.called; }); + it('should tranform RichTextEditor value to HTML', function () { + form.state.form.first = RichTextEditor.createEmptyValue(); + form.state.form.first.toString = stub().returns('HTML_CODE'); + + TestUtils.Simulate.submit(ReactDOM.findDOMNode(form)); + expect(form.state.form.first.toString).to.have.been.called; + expect(form.props.onSubmit).to.have.been.calledWith({ + first: 'HTML_CODE', + second: 'value2', + third: 'value3' + }); + }); + it('should focus the first field with error', function () { ValidationFactoryMock.validators.defaultValidatorMock.performValidation = stub().returns('MOCK_ERROR'); ValidationFactoryMock.validators.customValidatorMock.performValidation = stub().returns('MOCK_ERROR_2'); diff --git a/client/src/core-components/form-field.js b/client/src/core-components/form-field.js index 98b9dd35..2e2e7efb 100644 --- a/client/src/core-components/form-field.js +++ b/client/src/core-components/form-field.js @@ -1,5 +1,5 @@ import React from 'react'; -import {EditorState} from 'draft-js'; +import RichTextEditor from 'react-rte-browserify'; import classNames from 'classnames'; import _ from 'lodash'; @@ -36,7 +36,7 @@ class FormField extends React.Component { return false; } else if (field === 'textarea') { - return EditorState.createEmpty(); + return RichTextEditor.createEmptyValue(); } else if (field === 'select') { return 0; diff --git a/client/src/core-components/form.js b/client/src/core-components/form.js index 8de7cbd8..32e5935f 100644 --- a/client/src/core-components/form.js +++ b/client/src/core-components/form.js @@ -1,8 +1,7 @@ import React from 'react'; import _ from 'lodash'; import classNames from 'classnames'; -import {EditorState} from 'draft-js'; -import {stateToHTML} from 'draft-js-export-html'; +import RichTextEditor from 'react-rte-browserify'; import {reactDFS, renderChildrenWithProps} from 'lib-core/react-dfs'; import ValidationFactory from 'lib-app/validations/validations-factory'; @@ -158,8 +157,8 @@ class Form extends React.Component { event.preventDefault(); const form = _.mapValues(this.state.form, (field) => { - if (field instanceof EditorState) { - return stateToHTML(field.getCurrentContent()); + if (field instanceof RichTextEditor.EditorValue) { + return field.toString('html'); } else { return field; } diff --git a/client/src/core-components/text-editor.js b/client/src/core-components/text-editor.js index 9c203463..d1787913 100644 --- a/client/src/core-components/text-editor.js +++ b/client/src/core-components/text-editor.js @@ -1,9 +1,6 @@ import React from 'react'; -import ReactDOM from 'react-dom'; import classNames from 'classnames'; -import _ from 'lodash'; -import {Editor, EditorState, RichUtils} from 'draft-js'; -import Button from 'core-components/button'; +import RichTextEditor from 'react-rte-browserify'; class TextEditor extends React.Component { static propTypes = { @@ -12,52 +9,19 @@ class TextEditor extends React.Component { value: React.PropTypes.object }; - constructor(props) { - super(props); - - this.state = { - editorState: EditorState.createEmpty(), - focused: false - }; - } + state = { + value: RichTextEditor.createEmptyValue(), + focused: false + }; render() { return (
- {this.renderEditOptions()} -
event.preventDefault()}> - event.stopPropagation()}> - - -
+
); } - renderEditOptions() { - const onBoldClick = (event) => { - event.preventDefault(); - this.onEditorChange(RichUtils.toggleInlineStyle(this.state.editorState, 'BOLD')); - }; - const onItalicsClick = (event) => { - event.preventDefault(); - this.onEditorChange(RichUtils.toggleInlineStyle(this.state.editorState, 'ITALIC')); - }; - const onUnderlineClick = (event) => { - event.preventDefault(); - this.onEditorChange(RichUtils.toggleInlineStyle(this.state.editorState, 'UNDERLINE')); - }; - - - return ( -
-
- ) - } - getClass() { let classes = { 'text-editor': true, @@ -72,7 +36,8 @@ class TextEditor extends React.Component { getEditorProps() { return { - editorState: this.props.value || this.state.editorState, + className: 'text-editor__editor', + value: this.state.value, ref: 'editor', onChange: this.onEditorChange.bind(this), onFocus: this.onEditorFocus.bind(this), @@ -80,15 +45,11 @@ class TextEditor extends React.Component { }; } - onEditorChange(editorState) { - this.setState({editorState}); + onEditorChange(value) { + this.setState({value}); if (this.props.onChange) { - this.props.onChange({ - target: { - value: editorState - } - }); + this.props.onChange({target: {value}}); } } @@ -110,7 +71,7 @@ class TextEditor extends React.Component { focus() { if (this.refs.editor) { - this.refs.editor.focus(); + this.refs.editor._focus(); } } } diff --git a/client/src/core-components/text-editor.scss b/client/src/core-components/text-editor.scss index f54f43c2..e1d65935 100644 --- a/client/src/core-components/text-editor.scss +++ b/client/src/core-components/text-editor.scss @@ -2,27 +2,12 @@ .text-editor { - &__editor { - background-color: white; + .text-editor__editor { border: 1px solid $grey; border-radius: 3px; - padding: 8px; - width: 100%; - height: 200px; - text-align: left; - overflow: auto; - &:hover { - border-color: $medium-grey; - } - } - - &__options { - text-align: left; - margin-bottom: 5px; - - .button { - margin-right: 3px; + .DraftEditor-root { + height: 200px; } } diff --git a/client/src/data/fixtures/ticket-fixtures.js b/client/src/data/fixtures/ticket-fixtures.js index 16d169cd..b76fc34d 100644 --- a/client/src/data/fixtures/ticket-fixtures.js +++ b/client/src/data/fixtures/ticket-fixtures.js @@ -21,5 +21,15 @@ module.exports = [ return response; } + }, + { + path: '/ticket/comment', + time: 1000, + response: function () { + return { + status: 'success', + data: {} + }; + } } ]; \ No newline at end of file diff --git a/client/src/lib-app/validations/length-validator.js b/client/src/lib-app/validations/length-validator.js index 3951c31e..82c277b9 100644 --- a/client/src/lib-app/validations/length-validator.js +++ b/client/src/lib-app/validations/length-validator.js @@ -1,4 +1,4 @@ -import {EditorState} from 'draft-js'; +import RichTextEditor from 'react-rte-browserify'; import Validator from 'lib-app/validations/validator'; @@ -11,8 +11,8 @@ class LengthValidator extends Validator { } validate(value, form) { - if (value instanceof EditorState) { - value = value.getCurrentContent().getPlainText(); + if (value instanceof RichTextEditor.EditorValue) { + value = value.getEditorState().getCurrentContent().getPlainText(); } if (value.length < this.minlength) return this.getError(this.errorKey); diff --git a/client/src/lib-app/validations/validator.js b/client/src/lib-app/validations/validator.js index b02ab078..b253bc18 100644 --- a/client/src/lib-app/validations/validator.js +++ b/client/src/lib-app/validations/validator.js @@ -1,4 +1,4 @@ -import {EditorState} from 'draft-js'; +import RichTextEditor from 'react-rte-browserify'; import i18n from 'lib-app/i18n'; @@ -20,8 +20,8 @@ class Validator { } validate(value, form) { - if (value instanceof EditorState) { - value = value.getCurrentContent().getPlainText() + if (value instanceof RichTextEditor.EditorValue) { + value = value.getEditorState().getPlainText() } if (value.length === 0) return this.getError('ERROR_EMPTY');