Ivan - Add form form custom responses [skip ci]
This commit is contained in:
parent
23ccc17a85
commit
d75ad2e165
|
@ -4,7 +4,7 @@ import classNames from 'classnames';
|
|||
import { connect } from 'react-redux'
|
||||
import { browserHistory } from 'react-router';
|
||||
|
||||
import ModalContainer from 'app/modal-container';
|
||||
import ModalContainer from 'app-components/modal-container';
|
||||
|
||||
class App extends React.Component {
|
||||
static contextTypes = {
|
||||
|
|
|
@ -1,18 +1,33 @@
|
|||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import {connect} from 'react-redux';
|
||||
import RichTextEditor from 'react-rte-browserify';
|
||||
|
||||
import i18n from 'lib-app/i18n';
|
||||
import AdminDataActions from 'actions/admin-data-actions';
|
||||
|
||||
import ModalContainer from 'app-components/modal-container';
|
||||
import AreYouSure from 'app-components/are-you-sure';
|
||||
|
||||
import Icon from 'core-components/icon';
|
||||
import Header from 'core-components/header';
|
||||
import Listing from 'core-components/listing';
|
||||
import Loading from 'core-components/loading';
|
||||
import Form from 'core-components/form';
|
||||
import FormField from 'core-components/form-field';
|
||||
import SubmitButton from 'core-components/submit-button';
|
||||
|
||||
class AdminPanelCustomResponses extends React.Component {
|
||||
static defaultProps = {
|
||||
items: []
|
||||
};
|
||||
|
||||
state = {
|
||||
selectedIndex: -1,
|
||||
edited: false,
|
||||
errors: {},
|
||||
form: {}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.loaded) {
|
||||
|
@ -36,7 +51,11 @@ class AdminPanelCustomResponses extends React.Component {
|
|||
<Listing {...this.getListingProps()}/>
|
||||
</div>
|
||||
<div className="col-md-9">
|
||||
Custom response form
|
||||
<Form {...this.getFormProps()}>
|
||||
<FormField label={i18n('TITLE')} name="title" validation="TITLE" required fieldProps={{size: 'large'}}/>
|
||||
<FormField label={i18n('CONTENT')} name="content" validation="TEXT_AREA" required field="textarea" />
|
||||
<SubmitButton>{i18n('SAVE')}</SubmitButton>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -52,12 +71,24 @@ class AdminPanelCustomResponses extends React.Component {
|
|||
|
||||
getListingProps() {
|
||||
return {
|
||||
title: 'Custom Responses',
|
||||
title: i18n('CUSTOM_RESPONSES'),
|
||||
items: this.getItems(),
|
||||
enableAddNew: true
|
||||
selectedIndex: this.state.selectedIndex,
|
||||
enableAddNew: true,
|
||||
onChange: this.onItemChange.bind(this),
|
||||
onAddClick: this.onItemChange.bind(this, -1)
|
||||
};
|
||||
}
|
||||
|
||||
getFormProps() {
|
||||
return {
|
||||
values: this.state.form,
|
||||
errors: this.state.errors,
|
||||
onChange: (form) => {this.setState({form, edited: true})},
|
||||
onValidateErrors: (errors) => {this.setState({errors})}
|
||||
}
|
||||
}
|
||||
|
||||
getItems() {
|
||||
return this.props.items.map((item) => {
|
||||
return {
|
||||
|
@ -72,6 +103,30 @@ class AdminPanelCustomResponses extends React.Component {
|
|||
};
|
||||
});
|
||||
}
|
||||
|
||||
onItemChange(index) {
|
||||
if(this.state.edited) {
|
||||
ModalContainer.openModal(
|
||||
<AreYouSure description={i18n('WILL_LOSE_CHANGES')} onYes={this.updateForm.bind(this, index)} />
|
||||
);
|
||||
} else {
|
||||
this.updateForm(index);
|
||||
}
|
||||
}
|
||||
|
||||
updateForm(index) {
|
||||
let form = _.clone(this.state.form);
|
||||
|
||||
form.title = (this.props.items[index] && this.props.items[index].name) || '';
|
||||
form.content = RichTextEditor.createValueFromString((this.props.items[index] && this.props.items[index].content) || '', 'html');
|
||||
|
||||
this.setState({
|
||||
selectedIndex: index,
|
||||
edited: false,
|
||||
form: form,
|
||||
errors: {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default connect((store) => {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
const React = require('react');
|
||||
const DocumentTitle = require('react-document-title');
|
||||
|
||||
const ModalContainer = require('app/modal-container');
|
||||
const ModalContainer = require('app-components/modal-container');
|
||||
const AreYouSure = require('app-components/are-you-sure');
|
||||
|
||||
const Button = require('core-components/button');
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import React from 'react';
|
||||
|
||||
import API from 'lib-app/api-call';
|
||||
import i18n from 'lib-app/i18n';
|
||||
|
||||
import ModalContainer from 'app-components/modal-container';
|
||||
import AreYouSure from 'app-components/are-you-sure';
|
||||
|
||||
import Header from 'core-components/header';
|
||||
import Form from 'core-components/form';
|
||||
import FormField from 'core-components/form-field';
|
||||
import SubmitButton from 'core-components/submit-button';
|
||||
import ModalContainer from 'app/modal-container';
|
||||
import AreYouSure from 'app-components/are-you-sure';
|
||||
import Message from 'core-components/message';
|
||||
import i18n from 'lib-app/i18n';
|
||||
|
||||
class DashboardEditProfilePage extends React.Component {
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ class Form extends React.Component {
|
|||
loading: React.PropTypes.bool,
|
||||
errors: React.PropTypes.object,
|
||||
onValidateErrors: React.PropTypes.func,
|
||||
onChange: React.PropTypes.func,
|
||||
values: React.PropTypes.object,
|
||||
onSubmit: React.PropTypes.func
|
||||
};
|
||||
|
||||
|
@ -58,6 +60,8 @@ class Form extends React.Component {
|
|||
delete props.errors;
|
||||
delete props.loading;
|
||||
delete props.onValidateErrors;
|
||||
delete props.values;
|
||||
delete props.onChange;
|
||||
|
||||
return props;
|
||||
}
|
||||
|
@ -80,7 +84,7 @@ class Form extends React.Component {
|
|||
|
||||
additionalProps = {
|
||||
ref: fieldName,
|
||||
value: this.state.form[fieldName] || props.value,
|
||||
value: this.getFormValue()[fieldName],
|
||||
error: this.getFieldError(fieldName),
|
||||
onChange: this.handleFieldChange.bind(this, fieldName),
|
||||
onBlur: this.validateField.bind(this, fieldName)
|
||||
|
@ -111,8 +115,8 @@ class Form extends React.Component {
|
|||
}
|
||||
|
||||
getAllFieldErrors() {
|
||||
let form = this.state.form;
|
||||
let fields = Object.keys(this.state.form);
|
||||
let form = this.getFormValue();
|
||||
let fields = Object.keys(form);
|
||||
let errors = {};
|
||||
|
||||
_.each(fields, (fieldName) => {
|
||||
|
@ -122,7 +126,7 @@ class Form extends React.Component {
|
|||
return errors;
|
||||
}
|
||||
|
||||
getErrorsWithValidatedField(fieldName, form = this.state.form, errors = this.state.errors) {
|
||||
getErrorsWithValidatedField(fieldName, form = this.getFormValue(), errors = this.state.errors) {
|
||||
let newErrors = _.clone(errors);
|
||||
|
||||
if (this.state.validations[fieldName]) {
|
||||
|
@ -156,7 +160,7 @@ class Form extends React.Component {
|
|||
handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const form = _.mapValues(this.state.form, (field) => {
|
||||
const form = _.mapValues(this.getFormValue(), (field) => {
|
||||
if (field instanceof RichTextEditor.EditorValue) {
|
||||
return field.toString('html');
|
||||
} else {
|
||||
|
@ -172,13 +176,18 @@ class Form extends React.Component {
|
|||
}
|
||||
|
||||
handleFieldChange(fieldName, event) {
|
||||
let form = _.clone(this.state.form);
|
||||
let form = _.clone(this.getFormValue());
|
||||
|
||||
form[fieldName] = event.target.value;
|
||||
|
||||
this.setState({
|
||||
form: form
|
||||
});
|
||||
|
||||
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(form);
|
||||
}
|
||||
}
|
||||
|
||||
isValidField(node) {
|
||||
|
@ -203,6 +212,10 @@ class Form extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
getFormValue() {
|
||||
return this.props.values || this.state.form;
|
||||
}
|
||||
|
||||
focusFirstErrorField() {
|
||||
let firstErrorField = this.getFirstErrorField();
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class Listing extends React.Component {
|
|||
renderAddButton() {
|
||||
return (
|
||||
<div className="listing__add">
|
||||
<Button type="secondary" size="auto" className="listing__add-button">
|
||||
<Button type="secondary" size="auto" className="listing__add-button" onClick={this.props.onAddClick}>
|
||||
<Icon name="plus-circle"/> {this.props.addNewText}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -37,7 +37,7 @@ class TextEditor extends React.Component {
|
|||
getEditorProps() {
|
||||
return {
|
||||
className: 'text-editor__editor',
|
||||
value: this.state.value,
|
||||
value: this.props.value || this.state.value,
|
||||
ref: 'editor',
|
||||
onChange: this.onEditorChange.bind(this),
|
||||
onFocus: this.onEditorFocus.bind(this),
|
||||
|
|
|
@ -17,7 +17,7 @@ const languages = {
|
|||
};
|
||||
|
||||
const i18nData = function (key, lang) {
|
||||
return languages[lang][key];
|
||||
return (languages[lang] && languages[lang][key]) || key;
|
||||
};
|
||||
|
||||
export default i18nData
|
||||
|
|
|
@ -55,7 +55,8 @@ export default {
|
|||
'MEDIUM': 'Medium',
|
||||
'LOW': 'Low',
|
||||
'TITLE': 'Title',
|
||||
|
||||
'CONTENT': 'Content',
|
||||
|
||||
//VIEW DESCRIPTIONS
|
||||
'CREATE_TICKET_DESCRIPTION': 'This is a form for creating tickets. Fill the form and send us your issues/doubts/suggestions. Our support system will answer it as soon as possible.',
|
||||
'TICKET_LIST_DESCRIPTION': 'Here you can find a list of all tickets you have sent to our support team.',
|
||||
|
@ -86,5 +87,6 @@ export default {
|
|||
'ARE_YOU_SURE': 'Are you sure?',
|
||||
'EMAIL_CHANGED': 'Email has been changed successfully',
|
||||
'PASSWORD_CHANGED': 'Password has been changed successfully',
|
||||
'OLD_PASSWORD_INCORRECT': 'Old password is incorrect'
|
||||
'OLD_PASSWORD_INCORRECT': 'Old password is incorrect',
|
||||
'WILL_LOSE_CHANGES': 'You haven\'t save. Your changes will be lost.'
|
||||
};
|
|
@ -8,7 +8,7 @@ class AlphaNumericValidator extends Validator {
|
|||
}
|
||||
|
||||
validate(value, form) {
|
||||
let alphaMatch = /^[-\sa-zA-Z.]+$/;
|
||||
let alphaMatch = /^[ A-Za-z0-9_@./#&+-]*$/;
|
||||
|
||||
if (!alphaMatch.test(value)) return this.getError(this.errorKey);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue