Ivan - Create Ticket Form - Fix TextEditor issues [skip ci]

This commit is contained in:
ivan 2016-08-18 17:49:52 -03:00
parent 99e9392c45
commit 9813dd0ebd
10 changed files with 68 additions and 17 deletions

View File

@ -56,6 +56,7 @@
"app-module-path": "^1.0.3", "app-module-path": "^1.0.3",
"classnames": "^2.1.3", "classnames": "^2.1.3",
"draft-js": "^0.8.1", "draft-js": "^0.8.1",
"draft-js-export-html": "^0.4.0",
"jquery": "^2.1.4", "jquery": "^2.1.4",
"keycode": "^2.1.4", "keycode": "^2.1.4",
"localStorage": "^1.0.3", "localStorage": "^1.0.3",

View File

@ -23,7 +23,8 @@ class CreateTicketForm extends React.Component {
{content: 'Department3'} {content: 'Department3'}
]} /> ]} />
<Input label="Title" name="title" required /> <Input label="Title" name="title" required />
<TextArea label="Content" name="content" required /> <TextArea label="Content" name="content" required validation="TEXT_AREA" />
<SubmitButton>Sumibtea ameo</SubmitButton>
</Form> </Form>
</div> </div>
); );

View File

@ -50,6 +50,7 @@ class Button extends React.Component {
props.className = this.getClass(); props.className = this.getClass();
delete props.route; delete props.route;
delete props.iconName;
delete props.type; delete props.type;
return props; return props;

View File

@ -1,17 +1,20 @@
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 {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';
import Input from 'core-components/input'; import Input from 'core-components/input';
import Checkbox from 'core-components/checkbox'; import Checkbox from 'core-components/checkbox';
//import TextArea from 'core-components/text-area'; import TextArea from 'core-components/text-area';
const validFieldTypes = [ const validFieldTypes = [
Input, Input,
CheckBox TextArea,
Checkbox
]; ];
class Form extends React.Component { class Form extends React.Component {
@ -151,9 +154,9 @@ class Form extends React.Component {
else if (child.type === Checkbox) { else if (child.type === Checkbox) {
form[child.props.name] = child.props.checked || false; form[child.props.name] = child.props.checked || false;
} }
// else if (child.type === TextArea) { else if (child.type === TextArea) {
// DO SOMETHING form[child.props.name] = child.props.value || EditorState.createEmpty();
// } }
if (child.props.required) { if (child.props.required) {
validations[child.props.name] = ValidationFactory.getValidator(child.props.validation || 'DEFAULT'); validations[child.props.name] = ValidationFactory.getValidator(child.props.validation || 'DEFAULT');
@ -170,10 +173,18 @@ class Form extends React.Component {
handleSubmit(event) { handleSubmit(event) {
event.preventDefault(); event.preventDefault();
const form = _.mapValues(this.state.form, (field) => {
if (field instanceof EditorState) {
return stateToHTML(field.getCurrentContent());
} else {
return field;
}
});
if (this.hasFormErrors()) { if (this.hasFormErrors()) {
this.updateErrors(this.getAllFieldErrors(), this.focusFirstErrorField.bind(this)); this.updateErrors(this.getAllFieldErrors(), this.focusFirstErrorField.bind(this));
} else if (this.props.onSubmit) { } else if (this.props.onSubmit) {
this.props.onSubmit(this.state.form); this.props.onSubmit(form);
} }
} }

View File

@ -11,7 +11,7 @@ class TextArea extends React.Component {
}; };
static propTypes = { static propTypes = {
value: React.PropTypes.string, value: React.PropTypes.object,
validation: React.PropTypes.string, validation: React.PropTypes.string,
onChange: React.PropTypes.func, onChange: React.PropTypes.func,
required: React.PropTypes.bool, required: React.PropTypes.bool,
@ -45,6 +45,9 @@ class TextArea extends React.Component {
props.className = 'text-area__input'; props.className = 'text-area__input';
props.ref = 'nativeTextArea'; props.ref = 'nativeTextArea';
props.disabled = this.context.loading; props.disabled = this.context.loading;
props.value = this.props.value;
props.onChange = this.props.onChange;
props.errored = !!this.props.error;
delete props.required; delete props.required;
delete props.validation; delete props.validation;

View File

@ -7,7 +7,9 @@ import Button from 'core-components/button';
class TextEditor extends React.Component { class TextEditor extends React.Component {
static propTypes = { static propTypes = {
error: React.PropTypes.bool errored: React.PropTypes.bool,
onChange: React.PropTypes.func,
value: React.PropTypes.object
}; };
constructor(props) { constructor(props) {
@ -23,8 +25,10 @@ class TextEditor extends React.Component {
return ( return (
<div className={this.getClass()}> <div className={this.getClass()}>
{this.renderEditOptions()} {this.renderEditOptions()}
<div className="text-editor__editor" onClick={this.focus.bind(this)}> <div className="text-editor__editor" onClick={this.focus.bind(this)} onMouseDown={(event) => event.preventDefault()}>
<Editor {...this.getEditorProps()} /> <span onMouseDown={(event) => event.stopPropagation()}>
<Editor {...this.getEditorProps()} />
</span>
</div> </div>
</div> </div>
); );
@ -37,7 +41,7 @@ class TextEditor extends React.Component {
}; };
const onItalicsClick = (event) => { const onItalicsClick = (event) => {
event.preventDefault(); event.preventDefault();
this.onEditorChange(RichUtils.toggleInlineStyle(this.state.editorState, 'ITALICS')); this.onEditorChange(RichUtils.toggleInlineStyle(this.state.editorState, 'ITALIC'));
}; };
const onUnderlineClick = (event) => { const onUnderlineClick = (event) => {
event.preventDefault(); event.preventDefault();
@ -68,7 +72,7 @@ class TextEditor extends React.Component {
getEditorProps() { getEditorProps() {
return { return {
editorState: this.state.editorState, editorState: this.props.value || this.state.editorState,
ref: 'editor', ref: 'editor',
onChange: this.onEditorChange.bind(this), onChange: this.onEditorChange.bind(this),
onFocus: this.onEditorFocus.bind(this), onFocus: this.onEditorFocus.bind(this),
@ -78,14 +82,30 @@ class TextEditor extends React.Component {
onEditorChange(editorState) { onEditorChange(editorState) {
this.setState({editorState}); this.setState({editorState});
if (this.props.onChange) {
this.props.onChange({
target: {
value: editorState
}
});
}
} }
onEditorFocus() { onEditorFocus(event) {
this.setState({focused: true}); this.setState({focused: true});
if(this.props.onFocus) {
this.props.onFocus(event)
}
} }
onBlur() { onBlur(event) {
this.setState({focused: false}); this.setState({focused: false});
if(this.props.onBlur) {
this.props.onBlur(event)
}
} }
focus() { focus() {

View File

@ -21,6 +21,7 @@ export default {
'ERROR_PASSWORD': 'Invalid password', 'ERROR_PASSWORD': 'Invalid password',
'ERROR_NAME': 'Invalid name', 'ERROR_NAME': 'Invalid name',
'ERROR_EMAIL': 'Invalid email', 'ERROR_EMAIL': 'Invalid email',
'ERROR_CONTENT_SHORT': 'Content too short',
'PASSWORD_NOT_MATCH': 'Password does not match', 'PASSWORD_NOT_MATCH': 'Password does not match',
'INVALID_RECOVER': 'Invalid recover data', 'INVALID_RECOVER': 'Invalid recover data',

View File

@ -1,3 +1,5 @@
import {EditorState} from 'draft-js';
import Validator from 'lib-app/validations/validator'; import Validator from 'lib-app/validations/validator';
class LengthValidator extends Validator { class LengthValidator extends Validator {
@ -9,6 +11,10 @@ class LengthValidator extends Validator {
} }
validate(value, form) { validate(value, form) {
if (value instanceof EditorState) {
value = value.getCurrentContent().getPlainText();
}
if (value.length < this.minlength) return this.getError(this.errorKey); if (value.length < this.minlength) return this.getError(this.errorKey);
} }
} }

View File

@ -8,6 +8,7 @@ let validators = {
'DEFAULT': new Validator(), 'DEFAULT': new Validator(),
'NAME': new AlphaNumericValidator('ERROR_NAME', new LengthValidator(2, 'ERROR_NAME')), 'NAME': new AlphaNumericValidator('ERROR_NAME', new LengthValidator(2, 'ERROR_NAME')),
'EMAIL': new EmailValidator(), 'EMAIL': new EmailValidator(),
'TEXT_AREA': new LengthValidator(10, 'ERROR_CONTENT_SHORT'),
'PASSWORD': new LengthValidator(6, 'ERROR_PASSWORD'), 'PASSWORD': new LengthValidator(6, 'ERROR_PASSWORD'),
'REPEAT_PASSWORD': new RepeatPasswordValidator() 'REPEAT_PASSWORD': new RepeatPasswordValidator()
}; };

View File

@ -1,4 +1,6 @@
const i18n = require('lib-app/i18n'); import {EditorState} from 'draft-js';
import i18n from 'lib-app/i18n';
class Validator { class Validator {
constructor(validator = null) { constructor(validator = null) {
@ -18,7 +20,11 @@ class Validator {
} }
validate(value, form) { validate(value, form) {
if (!value.length) return this.getError('ERROR_EMPTY'); if (value instanceof EditorState) {
value = value.getCurrentContent().getPlainText()
}
if (value.length === 0) return this.getError('ERROR_EMPTY');
} }
getError(errorKey) { getError(errorKey) {