begins repeater, extracts Section into own component
This commit is contained in:
@@ -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';
|
||||
|
||||
30
src/components/field-types/Email/index.js
Normal file
30
src/components/field-types/Email/index.js
Normal 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);
|
||||
16
src/components/field-types/Email/index.scss
Normal file
16
src/components/field-types/Email/index.scss
Normal 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%);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
7
src/components/field-types/HiddenInput/index.js
Normal file
7
src/components/field-types/HiddenInput/index.js
Normal 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');
|
||||
@@ -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);
|
||||
|
||||
33
src/components/field-types/Password/index.js
Normal file
33
src/components/field-types/Password/index.js
Normal 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);
|
||||
16
src/components/field-types/Password/index.scss
Normal file
16
src/components/field-types/Password/index.scss
Normal 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%);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/components/field-types/Repeater/index.js
Normal file
19
src/components/field-types/Repeater/index.js
Normal 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;
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,4 +6,8 @@ form {
|
||||
> * {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
> .btn {
|
||||
@include gutter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
9
src/components/forms/Submit/index.scss
Normal file
9
src/components/forms/Submit/index.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
@import '~payload/scss/styles';
|
||||
|
||||
form > .form-submit {
|
||||
@include gutter;
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
20
src/components/layout/Section/index.js
Normal file
20
src/components/layout/Section/index.js
Normal 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;
|
||||
@@ -1,6 +1,6 @@
|
||||
@import '~payload/scss/styles';
|
||||
|
||||
.field-group {
|
||||
section.section {
|
||||
@extend %shadow;
|
||||
margin: rem(1) rem(.5);
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
.controls {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
|
||||
.btn {
|
||||
margin-top: 0;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
22
src/lib/helpers/convertData.js
Normal file
22
src/lib/helpers/convertData.js
Normal 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;
|
||||
}, {});
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user