Merge branch 'master' into OS-65-table-pagination

This commit is contained in:
ivan 2016-09-20 21:14:33 -03:00
commit 36a8e77d8b
10 changed files with 53 additions and 101 deletions

View File

@ -70,6 +70,7 @@
"react-redux": "^4.4.5", "react-redux": "^4.4.5",
"react-router": "^2.4.0", "react-router": "^2.4.0",
"react-router-redux": "^4.0.5", "react-router-redux": "^4.0.5",
"react-rte-browserify": "^0.5.0",
"redux": "^3.5.2", "redux": "^3.5.2",
"redux-promise-middleware": "^3.3.2" "redux-promise-middleware": "^3.3.2"
} }

View File

@ -3,7 +3,7 @@ const Checkbox = ReactMock();
const DropDown = ReactMock(); const DropDown = ReactMock();
const TextEditor = ReactMock(); const TextEditor = ReactMock();
const {EditorState} = require('draft-js'); const RichTextEditor = require('react-rte-browserify');
const FormField = requireUnit('core-components/form-field', { const FormField = requireUnit('core-components/form-field', {
'core-components/input': Input, 'core-components/input': Input,
@ -35,7 +35,7 @@ describe('FormField component', function () {
expect(FormField.getDefaultValue('input')).to.equal(''); expect(FormField.getDefaultValue('input')).to.equal('');
expect(FormField.getDefaultValue('checkbox')).to.equal(false); expect(FormField.getDefaultValue('checkbox')).to.equal(false);
expect(FormField.getDefaultValue('select')).to.equal(0); 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);
}); });
}); });

View File

@ -1,15 +1,11 @@
// MOCKS // MOCKS
const ValidationFactoryMock = require('lib-app/__mocks__/validations/validation-factory-mock'); const ValidationFactoryMock = require('lib-app/__mocks__/validations/validation-factory-mock');
const FormField = ReactMock(); const FormField = ReactMock();
const {EditorState} = require('draft-js'); const RichTextEditor = require('react-rte-browserify');
const draftJsExportHTML = {
stateToHTML: stub().returns('HTML_CODE')
};
// COMPONENT // COMPONENT
const Form = requireUnit('core-components/form', { const Form = requireUnit('core-components/form', {
'lib-app/validations/validations-factory': ValidationFactoryMock, 'lib-app/validations/validations-factory': ValidationFactoryMock,
'draft-js-export-html': draftJsExportHTML,
'core-components/form-field': FormField 'core-components/form-field': FormField
}); });
@ -176,19 +172,6 @@ describe('Form component', function () {
expect(form.props.onSubmit).to.have.been.calledWith(form.state.form); 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 () { it('should validate all fields and not call onSubmit if there are errors', function () {
ValidationFactoryMock.validators.defaultValidatorMock.performValidation = stub().returns('MOCK_ERROR'); ValidationFactoryMock.validators.defaultValidatorMock.performValidation = stub().returns('MOCK_ERROR');
ValidationFactoryMock.validators.customValidatorMock.performValidation = stub().returns('MOCK_ERROR_2'); 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; 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 () { it('should focus the first field with error', function () {
ValidationFactoryMock.validators.defaultValidatorMock.performValidation = stub().returns('MOCK_ERROR'); ValidationFactoryMock.validators.defaultValidatorMock.performValidation = stub().returns('MOCK_ERROR');
ValidationFactoryMock.validators.customValidatorMock.performValidation = stub().returns('MOCK_ERROR_2'); ValidationFactoryMock.validators.customValidatorMock.performValidation = stub().returns('MOCK_ERROR_2');

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import {EditorState} from 'draft-js'; import RichTextEditor from 'react-rte-browserify';
import classNames from 'classnames'; import classNames from 'classnames';
import _ from 'lodash'; import _ from 'lodash';
@ -36,7 +36,7 @@ class FormField extends React.Component {
return false; return false;
} }
else if (field === 'textarea') { else if (field === 'textarea') {
return EditorState.createEmpty(); return RichTextEditor.createEmptyValue();
} }
else if (field === 'select') { else if (field === 'select') {
return 0; return 0;

View File

@ -1,8 +1,7 @@
import React from 'react'; import React from 'react';
import _ from 'lodash'; import _ from 'lodash';
import classNames from 'classnames'; import classNames from 'classnames';
import {EditorState} from 'draft-js'; import RichTextEditor from 'react-rte-browserify';
import {stateToHTML} from 'draft-js-export-html';
import {reactDFS, renderChildrenWithProps} from 'lib-core/react-dfs'; import {reactDFS, renderChildrenWithProps} from 'lib-core/react-dfs';
import ValidationFactory from 'lib-app/validations/validations-factory'; import ValidationFactory from 'lib-app/validations/validations-factory';
@ -158,8 +157,8 @@ class Form extends React.Component {
event.preventDefault(); event.preventDefault();
const form = _.mapValues(this.state.form, (field) => { const form = _.mapValues(this.state.form, (field) => {
if (field instanceof EditorState) { if (field instanceof RichTextEditor.EditorValue) {
return stateToHTML(field.getCurrentContent()); return field.toString('html');
} else { } else {
return field; return field;
} }

View File

@ -1,9 +1,6 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames'; import classNames from 'classnames';
import _ from 'lodash'; import RichTextEditor from 'react-rte-browserify';
import {Editor, EditorState, RichUtils} from 'draft-js';
import Button from 'core-components/button';
class TextEditor extends React.Component { class TextEditor extends React.Component {
static propTypes = { static propTypes = {
@ -12,52 +9,19 @@ class TextEditor extends React.Component {
value: React.PropTypes.object value: React.PropTypes.object
}; };
constructor(props) { state = {
super(props); value: RichTextEditor.createEmptyValue(),
focused: false
this.state = { };
editorState: EditorState.createEmpty(),
focused: false
};
}
render() { render() {
return ( return (
<div className={this.getClass()}> <div className={this.getClass()}>
{this.renderEditOptions()} <RichTextEditor {...this.getEditorProps()} />
<div className="text-editor__editor" onClick={this.focus.bind(this)} onMouseDown={(event) => event.preventDefault()}>
<span onMouseDown={(event) => event.stopPropagation()}>
<Editor {...this.getEditorProps()} />
</span>
</div>
</div> </div>
); );
} }
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 (
<div className="text-editor__options">
<Button type="primary" size="auto" iconName="bold" onClick={onBoldClick.bind(this)} onMouseDown={(e) => {e.preventDefault()}} />
<Button type="primary" size="auto" iconName="italic" onClick={onItalicsClick.bind(this)} onMouseDown={(e) => {e.preventDefault()}} />
<Button type="primary" size="auto" iconName="underline" onClick={onUnderlineClick.bind(this)} onMouseDown={(e) => {e.preventDefault()}} />
</div>
)
}
getClass() { getClass() {
let classes = { let classes = {
'text-editor': true, 'text-editor': true,
@ -72,7 +36,8 @@ class TextEditor extends React.Component {
getEditorProps() { getEditorProps() {
return { return {
editorState: this.props.value || this.state.editorState, className: 'text-editor__editor',
value: this.state.value,
ref: 'editor', ref: 'editor',
onChange: this.onEditorChange.bind(this), onChange: this.onEditorChange.bind(this),
onFocus: this.onEditorFocus.bind(this), onFocus: this.onEditorFocus.bind(this),
@ -80,15 +45,11 @@ class TextEditor extends React.Component {
}; };
} }
onEditorChange(editorState) { onEditorChange(value) {
this.setState({editorState}); this.setState({value});
if (this.props.onChange) { if (this.props.onChange) {
this.props.onChange({ this.props.onChange({target: {value}});
target: {
value: editorState
}
});
} }
} }
@ -110,7 +71,7 @@ class TextEditor extends React.Component {
focus() { focus() {
if (this.refs.editor) { if (this.refs.editor) {
this.refs.editor.focus(); this.refs.editor._focus();
} }
} }
} }

View File

@ -2,27 +2,12 @@
.text-editor { .text-editor {
&__editor { .text-editor__editor {
background-color: white;
border: 1px solid $grey; border: 1px solid $grey;
border-radius: 3px; border-radius: 3px;
padding: 8px;
width: 100%;
height: 200px;
text-align: left;
overflow: auto;
&:hover { .DraftEditor-root {
border-color: $medium-grey; height: 200px;
}
}
&__options {
text-align: left;
margin-bottom: 5px;
.button {
margin-right: 3px;
} }
} }

View File

@ -21,5 +21,15 @@ module.exports = [
return response; return response;
} }
},
{
path: '/ticket/comment',
time: 1000,
response: function () {
return {
status: 'success',
data: {}
};
}
} }
]; ];

View File

@ -1,4 +1,4 @@
import {EditorState} from 'draft-js'; import RichTextEditor from 'react-rte-browserify';
import Validator from 'lib-app/validations/validator'; import Validator from 'lib-app/validations/validator';
@ -11,8 +11,8 @@ class LengthValidator extends Validator {
} }
validate(value, form) { validate(value, form) {
if (value instanceof EditorState) { if (value instanceof RichTextEditor.EditorValue) {
value = value.getCurrentContent().getPlainText(); value = value.getEditorState().getCurrentContent().getPlainText();
} }
if (value.length < this.minlength) return this.getError(this.errorKey); if (value.length < this.minlength) return this.getError(this.errorKey);

View File

@ -1,4 +1,4 @@
import {EditorState} from 'draft-js'; import RichTextEditor from 'react-rte-browserify';
import i18n from 'lib-app/i18n'; import i18n from 'lib-app/i18n';
@ -20,8 +20,8 @@ class Validator {
} }
validate(value, form) { validate(value, form) {
if (value instanceof EditorState) { if (value instanceof RichTextEditor.EditorValue) {
value = value.getCurrentContent().getPlainText() value = value.getEditorState().getPlainText()
} }
if (value.length === 0) return this.getError('ERROR_EMPTY'); if (value.length === 0) return this.getError('ERROR_EMPTY');