Fix merge conflicts

This commit is contained in:
Elliot DeNolf
2018-09-27 12:00:58 -04:00
13 changed files with 270 additions and 207 deletions

View File

@@ -24,6 +24,7 @@ class Button extends Component {
this.buttonProps = {
className: classes,
onClick: this.props.onClick,
disabled: this.props.disabled,
...this.props
};
}

View File

@@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { Tooltip } from 'payload/components';
import { Tooltip, FormContext } from 'payload/components';
import './index.css';
@@ -12,21 +12,26 @@ class Input extends Component {
email: 'Please enter a valid email'
};
this.state = {
init: false
};
this.validate = this.validate.bind(this);
this.sendField = this.sendField.bind(this);
}
validate() {
validate(value) {
let emailTest = /\S+@\S+\.\S+/;
switch (this.props.type) {
case 'text':
return this.el.value.length > 0;
return value.length > 0;
case 'password':
return this.el.value.length > 0;
return value.length > 0;
case 'email':
return emailTest.test(this.el.value);
return emailTest.test(value);
case 'hidden':
return true;
@@ -36,18 +41,40 @@ class Input extends Component {
}
}
componentDidUpdate() {
if (this.props.autoFocus) {
this.el.focus();
}
sendField(value) {
return {
name: this.props.name,
value: value,
valid: this.props.required
? this.validate(value)
: true
};
}
componentDidMount() {
this.props.context.setValue(
this.sendField(
this.props.value ? this.props.value : ''
)
);
this.setState({
init: true
})
}
render() {
const valid = this.props.context.fields[this.props.name]
? this.props.context.fields[this.props.name].valid
: true;
const Required = this.props.required
? () => <span className="required">*</span>
: () => null;
const Error = this.props.valid === false
const Error = valid === false && this.props.context.submitted
? () => <Tooltip className="error-message">{this.errors[this.props.type]}</Tooltip>
: () => null;
@@ -60,23 +87,37 @@ class Input extends Component {
? className
: `${className} error`;
const initialValue = this.props.value ? this.props.value : '';
return (
<div className={className} style={this.props.style}>
<Error />
<Label />
<input
ref={el => { this.el = el; } }
value={
this.props.context.fields[this.props.name]
? this.props.context.fields[this.props.name].value
: initialValue
}
onChange={
(e) => {
this.props.context.setValue(this.sendField(e.target.value))
}
}
disabled={this.props.disabled}
placeholder={this.props.placeholder}
onChange={this.props.change}
onFocus={this.props.onFocus}
type={this.props.type}
id={this.props.id ? this.props.id : this.props.name}
name={this.props.name}
value={this.props.value} />
name={this.props.name} />
</div>
);
}
}
export default Input;
export default props => {
return (
<FormContext.Consumer>
{context => <Input {...props} context={context} />}
</FormContext.Consumer>
);
};

View File

@@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { Tooltip } from 'payload/components';
import { FormContext, Tooltip } from 'payload/components';
import './index.css';
@@ -11,24 +11,56 @@ class Textarea extends Component {
text: 'Please fill in the field'
};
this.state = {
init: false
};
this.validate = this.validate.bind(this);
this.sendField = this.sendField.bind(this);
}
validate() {
validate(value) {
switch (this.props.type) {
case 'honeypot':
return this.el.value.length === 0;
return value.length === 0;
default:
return this.el.value.length > 0;
return value.length > 0;
}
}
sendField(value) {
return {
name: this.props.name,
value: value,
valid: this.props.required
? this.validate(value)
: true
}
}
componentDidMount() {
this.props.context.setValue(
this.sendField(
this.props.value ? this.props.value : ''
)
);
this.setState({
init: true
})
}
render() {
const valid = this.props.context.fields[this.props.name]
? this.props.context.fields[this.props.name].valid
: true;
const Required = this.props.required
? () => <span className="required">*</span>
: () => null;
const Error = this.props.valid === false
const Error = valid === false && this.props.context.submitted
? () => <Tooltip className="error-message">{this.errors.text}</Tooltip>
: () => null;
@@ -49,23 +81,38 @@ class Textarea extends Component {
className = 'interact';
}
const initialValue = this.props.value ? this.props.value : '';
return (
<div className={className} style={style}>
<Error />
<Label />
<textarea
ref={el => { this.el = el; } }
onBlur={this.validate}
onFocus={this.props.onFocus}
onChange={this.props.change}
value={
this.props.context.fields[this.props.name]
? this.props.context.fields[this.props.name].value
: initialValue
}
onChange={
(e) => {
this.props.context.setValue(this.sendField(e.target.value))
}
}
disabled={this.props.disabled}
placeholder={this.props.placeholder}
type={this.props.type}
id={this.props.id ? this.props.id : this.props.name}
name={this.props.name}
rows={this.props.rows ? this.props.rows : '5'}
value={this.props.value}>
name={this.props.name}>
</textarea>
</div>
);
}
}
export default Textarea;
export default props => {
return (
<FormContext.Consumer>
{context => <Textarea {...props} context={context} />}
</FormContext.Consumer>
);
};

View File

@@ -1,70 +1,51 @@
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import React, { Component, createContext } from 'react';
import { ajax } from 'payload';
import './index.css';
export const FormContext = createContext({});
class Form extends Component {
constructor(props) {
super(props);
this.state = {
fields: this.buildFields(),
fields: {},
status: undefined,
submitted: false,
processing: false
};
// Fill from renderChildren
this.childRefs = {};
this.buildFields = this.buildFields.bind(this);
this.handleChange = this.handleChange.bind(this);
this.submit = this.submit.bind(this);
this.renderChildren = this.renderChildren.bind(this);
this.setValue = this.setValue.bind(this);
}
buildFields() {
let fields = {};
React.Children.map(this.props.children, (child) => {
if (child.props.name) {
fields[child.props.name] = {
value: child.props.value ? child.props.value : '',
required: child.props.required
};
setValue(field) {
this.setState(prevState => ({
...prevState,
fields: {
...prevState.fields,
[field.name]: {
value: field.value,
valid: field.valid
}
}
});
return fields;
}
handleChange(e) {
let newState = { ...this.state };
newState.fields[e.target.name].value = e.target.value;
this.setState(newState);
}));
}
submit(e) {
let isValid = true;
let newState = { ...this.state };
Object.keys(this.childRefs).forEach((field) => {
if (this.childRefs[field].props.required) {
let current = this.childRefs[field];
let validated = current.validate();
newState.fields[field].valid = validated;
if (!validated) {
isValid = false;
}
}
this.setState({
submitted: true
});
// Update validated fields
this.setState(newState);
let isValid = true;
Object.keys(this.state.fields).forEach((field) => {
if (!this.state.fields[field].valid) {
isValid = false;
}
});
// If not valid, prevent submission
if (!isValid) {
@@ -76,7 +57,7 @@ class Form extends Component {
this.props.onSubmit(this.state.fields);
// If form is AJAX, fetch data
} else if (this.props.ajax) {
} else if (this.props.ajax !== false) {
e.preventDefault();
let data = {};
@@ -118,52 +99,10 @@ class Form extends Component {
);
}
if (this.props.clearAfterSubmit && isValid) {
// Loop through fields - if not valid, set to invalid, rerender with error
Object.keys(this.state.fields).forEach((field) => {
newState.fields[field].value = '';
});
}
// If valid and not AJAX submit as usual
return;
}
renderChildren() {
let children = React.Children.map(this.props.children, (child) => {
if (child.props.name) {
// Initialize validation as true - only show error class if error after blur
let valid = true;
// If a valid value has been passed from field, set valid equal to that
if (typeof this.state.fields[child.props.name].valid !== 'undefined') {
valid = this.state.fields[child.props.name].valid;
}
return React.cloneElement(child, {
ref: (el) => {
this.childRefs[child.props.name] = el;
},
change: this.handleChange,
validate: this.validate,
valid: valid,
value: this.state.fields[child.props.name].value
});
}
if (child.props.type === 'submit') {
return React.cloneElement(child, {
disabled: this.state.processing || child.props.disabled === 'disabled' ? 'disabled' : false,
children: this.state.processing ? 'Processing...' : child.props.children
});
}
return child;
});
return children;
}
render() {
let Status = () => {
return null;
@@ -186,10 +125,17 @@ class Form extends Component {
action={this.props.action}
className={this.props.className}>
<Status />
{this.renderChildren()}
<FormContext.Provider value={{
setValue: this.setValue.bind(this),
fields: this.state.fields,
processing: this.state.processing,
submitted: this.state.submitted
}}>
{this.props.children}
</FormContext.Provider>
</form>
);
}
}
export default withRouter(Form);
export default Form;

View File

@@ -0,0 +1,21 @@
import React, { Component } from 'react';
import { FormContext, Button } from 'payload/components';
class FormSubmit extends Component {
render() {
return (
<Button disabled={this.props.context.processing ? 'disabled' : ''}>
{this.props.children}
</Button>
);
}
}
export default props => {
return (
<FormContext.Consumer>
{context => <FormSubmit {...props} context={context} />}
</FormContext.Consumer>
);
};

View File

@@ -1,10 +1,12 @@
import React, { Component } from 'react';
import { Input } from 'payload/components';
import { Form, Input } from 'payload/components';
class Filter extends Component {
render() {
return (
<Input data-fillable placeholder="Search" type="text" id="keywords" />
<Form>
<Input placeholder="Search" type="text" name="keywords" />
</Form>
);
}
}

View File

@@ -5,7 +5,8 @@
.tooltip {
@extend %uppercase-label;
background-color: $green;
position: absolute;
position: absolute;
z-index: 2;
top: - rem(.5);
left: 50%;
transform: translateX(-50%);