begins repeater, extracts Section into own component

This commit is contained in:
James
2018-12-09 19:32:53 -07:00
parent 302bcd5757
commit 9c5dfa2db0
23 changed files with 277 additions and 70 deletions

View File

@@ -10,8 +10,12 @@ export { default as withEditData } from './components/data/edit';
// Field Types
export { default as fieldType } from './components/field-types/fieldType';
export { default as Group } from './components/field-types/Group';
export { default as Repeater } from './components/field-types/Repeater';
export { default as Input } from './components/field-types/Input';
export { default as Email } from './components/field-types/Email';
export { default as Password } from './components/field-types/Password';
export { default as Textarea } from './components/field-types/Textarea';
export { default as HiddenInput } from './components/field-types/HiddenInput';
// Forms
export { default as Form, FormContext } from './components/forms/Form';
@@ -29,6 +33,7 @@ export { default as Sticky } from './components/layout/Sticky';
export { default as Sidebar } from './components/layout/Sidebar';
export { default as ContentBlock } from './components/layout/ContentBlock';
export { default as Table } from './components/layout/Table';
export { default as Section } from './components/layout/Section';
// Modules
export { default as Status } from './components/modules/Status';

View File

@@ -0,0 +1,30 @@
import React from 'react';
import { fieldType } from 'payload/components';
import './index.scss';
const error = 'Please enter a valid email';
const validate = value => /\S+@\S+\.\S+/.test(value);
const Email = props => {
return (
<div className={props.className} style={{
...props.style,
width: props.width ? `${props.width}%` : null
}}>
{props.error}
{props.label}
<input
value={props.value}
onChange={props.onChange}
disabled={props.disabled}
placeholder={props.placeholder}
type="email"
id={props.id ? props.id : props.name}
name={props.name} />
</div>
);
}
export default fieldType(Email, 'email', validate, error);

View File

@@ -0,0 +1,16 @@
@import '~payload/scss/styles';
.field-type.email {
margin-bottom: rem(.5);
position: relative;
input {
@include formInput;
}
&.error {
input {
background-color: lighten($error, 20%);
}
}
}

View File

@@ -1,19 +1,11 @@
import React from 'react';
import './index.scss';
import { Section } from 'payload/components';
const Group = props => {
return (
<section className="field-group">
{props.heading &&
<header>
<h2>{props.heading}</h2>
</header>
}
<div className="content">
{props.children}
</div>
</section>
<Section heading={props.label} className="field-group">
{props.children}
</Section>
);
};

View File

@@ -0,0 +1,7 @@
import React from 'react';
import { fieldType } from 'payload/components';
const HiddenInput = props => <input type="hidden" value={props.value}
onChange={props.onChange} id={props.id ? props.id : props.name} name={props.name} />;
export default fieldType(HiddenInput, 'hiddenInput');

View File

@@ -3,32 +3,9 @@ import { fieldType } from 'payload/components';
import './index.scss';
const errors = {
text: 'Please fill in the field',
email: 'Please enter a valid email',
password: 'Please enter a password'
};
const error = 'Please fill in the field';
const validate = (value, type) => {
let emailTest = /\S+@\S+\.\S+/;
switch (type) {
case 'text':
return value.length > 0;
case 'password':
return value.length > 0;
case 'email':
return emailTest.test(value);
case 'hidden':
return true;
default:
return false;
}
}
const validate = value => value.length > 0;
const Input = props => {
return (
@@ -43,11 +20,11 @@ const Input = props => {
onChange={props.onChange}
disabled={props.disabled}
placeholder={props.placeholder}
type={props.type}
type="text"
id={props.id ? props.id : props.name}
name={props.name} />
</div>
);
}
export default fieldType(Input, 'input', validate, errors);
export default fieldType(Input, 'input', validate, error);

View File

@@ -0,0 +1,33 @@
import React from 'react';
import { fieldType } from 'payload/components';
import './index.scss';
const errors = {
password: 'Please enter a password',
confirm: 'Please ensure that both passwords match'
};
const validate = value => value.length > 0;
const Password = props => {
return (
<div className={props.className} style={{
...props.style,
width: props.width ? `${props.width}%` : null
}}>
{props.error}
{props.label}
<input
value={props.value}
onChange={props.onChange}
disabled={props.disabled}
placeholder={props.placeholder}
type="password"
id={props.id ? props.id : props.name}
name={props.name} />
</div>
);
}
export default fieldType(Password, 'password', validate, errors);

View File

@@ -0,0 +1,16 @@
@import '~payload/scss/styles';
.field-type.password {
margin-bottom: rem(.5);
position: relative;
input {
@include formInput;
}
&.error {
input {
background-color: lighten($error, 20%);
}
}
}

View File

@@ -0,0 +1,19 @@
import React, { Component } from 'react';
import { Section } from 'payload/components';
class Repeater extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="field-repeater">
<Section heading={this.props.label}>
</Section>
</div>
)
}
}
export default Repeater;

View File

@@ -3,7 +3,7 @@ import { FormContext, Tooltip } from 'payload/components';
import './index.scss';
const fieldType = (PassedComponent, slug, validate, errors) => {
const fieldType = (PassedComponent, type, validate, errors) => {
class FieldType extends Component {
@@ -19,7 +19,7 @@ const fieldType = (PassedComponent, slug, validate, errors) => {
this.props.context.setValue({
name: this.props.name,
value: value,
valid: this.props.required
valid: this.props.required && validate
? validate(value, this.props.type)
: true
});
@@ -52,7 +52,7 @@ const fieldType = (PassedComponent, slug, validate, errors) => {
const showError = valid === false && this.props.context.submitted;
let className = `field-type ${slug}${showError ? ' error' : ''}`;
let className = `field-type ${type}${showError ? ' error' : ''}`;
let value = this.props.context.fields[this.props.name] ? this.props.context.fields[this.props.name].value : '';
@@ -92,9 +92,9 @@ const fieldType = (PassedComponent, slug, validate, errors) => {
if (props.showError) {
return (
<Tooltip className="error-message">
{props.type && errors[props.type]}
{props.error && errors[props.error]}
{!props.type && errors}
{!props.error && errors}
</Tooltip>
)
}

View File

@@ -6,4 +6,8 @@ form {
> * {
width: 100%;
}
> .btn {
@include gutter;
}
}

View File

@@ -1,17 +1,21 @@
import React, { Component } from 'react';
import { FormContext, Button } from 'payload/components';
import './index.scss';
class FormSubmit extends Component {
render() {
return (
<Button disabled={this.props.context.processing ? 'disabled' : ''}>
{this.props.children}
</Button>
<div className="form-submit">
<Button disabled={this.props.context.processing ? 'disabled' : ''}>
{this.props.children}
</Button>
</div>
);
}
}
export default props => {
const ContextFormSubmit = props => {
return (
<FormContext.Consumer>
{context => <FormSubmit {...props} context={context} />}
@@ -19,3 +23,5 @@ export default props => {
);
};
export default ContextFormSubmit;

View File

@@ -0,0 +1,9 @@
@import '~payload/scss/styles';
form > .form-submit {
@include gutter;
.btn {
width: 100%;
}
}

View File

@@ -0,0 +1,20 @@
import React from 'react';
import './index.scss';
const Section = props => {
return (
<section className={`section${props.className ? ` ${props.className}` : ''}`}>
{props.heading &&
<header>
<h2>{props.heading}</h2>
</header>
}
<div className="content">
{props.children}
</div>
</section>
)
}
export default Section;

View File

@@ -1,6 +1,6 @@
@import '~payload/scss/styles';
.field-group {
section.section {
@extend %shadow;
margin: rem(1) rem(.5);

View File

@@ -5,7 +5,7 @@ class Filter extends Component {
render() {
return (
<Form className="filter">
<Input placeholder="Search" type="text" name="keywords" />
<Input placeholder="Search" name="keywords" />
</Form>
);
}

View File

@@ -13,6 +13,7 @@
.controls {
flex-shrink: 0;
display: flex;
.btn {
margin-top: 0;

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { ContentBlock, Form, Input, FormSubmit, SetStepNav } from 'payload/components';
import { ContentBlock, Form, Email, Password, FormSubmit, SetStepNav } from 'payload/components';
import './index.scss';
@@ -16,8 +16,8 @@ const CreateUser = () => {
<Form
method="POST"
action="http://localhost:3000/users">
<Input type="email" label="Email Address" name="email" required />
<Input type="password" label="Password" name="password" required />
<Email label="Email Address" name="email" required />
<Password error="password" label="Password" name="password" required />
<FormSubmit>Create</FormSubmit>
</Form>
</ContentBlock>

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { ContentBlock, Form, Input, FormSubmit } from 'payload/components';
import { ContentBlock, Form, Email, Password, FormSubmit } from 'payload/components';
import './index.scss';
@@ -21,8 +21,8 @@ const Login = props => {
<Form
method="POST"
action="http://localhost:3000/login">
<Input type="email" label="Email Address" name="email" required />
<Input type="password" label="Password" name="password" required />
<Email label="Email Address" name="email" required />
<Password error="password" label="Password" name="password" required />
<FormSubmit>Login</FormSubmit>
</Form>
<Link to="/">To Dashboard</Link>

View File

@@ -0,0 +1,22 @@
export const convertArrayToObject = (arr, key) => {
return arr.reduce((obj, item) => {
if (key) {
obj[item[key]] = item;
return obj;
}
obj[item] = {};
return obj;
}, {});
}
export const convertObjectToArray = arr => {
return Object.values(arr);
}
export const convertArrayToHash = (arr, key) => {
return arr.reduce((obj, item, i) => {
obj[item[key]] = i;
return obj;
}, {});
}

View File

@@ -1,2 +1,3 @@
export { default as toKebabCase } from './lib/helpers/toKebabCase';
export { default as getPropSubset } from './lib/helpers/getPropSubset';
export { convertArrayToHash, convertArrayToObject, convertObjectToArray } from './lib/helpers/convertData';