diff --git a/demo/Page/Page.controller.js b/demo/Page/Page.controller.js index 3d6c368f73..965b6bdec6 100644 --- a/demo/Page/Page.controller.js +++ b/demo/Page/Page.controller.js @@ -1,7 +1,5 @@ -import config from './Page.config'; import Page from './Page.model'; import httpStatus from 'http-status'; -import toKebabCase from '../../src/lib/helpers/toKebabCase'; const pageController = { query(req, res) { diff --git a/package-lock.json b/package-lock.json index 3dd8e797fc..ba01c30c6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1822,6 +1822,32 @@ } } }, + "babel-eslint": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.1.tgz", + "integrity": "sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "^1.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, "babel-generator": { "version": "6.26.1", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", diff --git a/package.json b/package.json index a3c721e6a7..3477a00c86 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@babel/preset-react": "^7.0.0", "@babel/register": "^7.0.0", "autoprefixer": "^9.0.1", + "babel-eslint": "^10.0.1", "babel-loader": "^8.0.4", "circular-dependency-plugin": "^5.0.2", "css-loader": "^1.0.0", diff --git a/src/components.js b/src/components.js index 08b691a994..df42c04a9a 100644 --- a/src/components.js +++ b/src/components.js @@ -8,6 +8,7 @@ export { default as withArchiveData } from './components/data/archive'; 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 Input } from './components/field-types/Input'; export { default as Textarea } from './components/field-types/Textarea'; diff --git a/src/components/field-types/Input/index.js b/src/components/field-types/Input/index.js index 005df1aa1f..4ecd9f22ea 100644 --- a/src/components/field-types/Input/index.js +++ b/src/components/field-types/Input/index.js @@ -1,140 +1,50 @@ -import React, { Component } from 'react'; -import { Tooltip, FormContext } from 'payload/components'; +import React from 'react'; +import { fieldType } from 'payload/components'; import './index.scss'; -class Input extends Component { - constructor() { - super(); +const errors = { + text: 'Please fill in the field', + email: 'Please enter a valid email', + password: 'Please enter a password' +}; - this.errors = { - text: 'Please fill in the field', - email: 'Please enter a valid email', - password: 'Please enter a password' - }; +const validate = (value, type) => { + let emailTest = /\S+@\S+\.\S+/; - this.state = { - init: false - }; + switch (type) { + case 'text': + return value.length > 0; - this.validate = this.validate.bind(this); - this.sendField = this.sendField.bind(this); - } + case 'password': + return value.length > 0; - validate(value) { - let emailTest = /\S+@\S+\.\S+/; + case 'email': + return emailTest.test(value); - switch (this.props.type) { - case 'text': - return value.length > 0; + case 'hidden': + return true; - case 'password': - return value.length > 0; - - case 'email': - return emailTest.test(value); - - case 'hidden': - return true; - - default: - return false; - } - } - - sendField(value) { - this.props.context.setValue({ - name: this.props.name, - value: value, - valid: this.props.required - ? this.validate(value) - : true - }) - } - - componentDidMount() { - this.sendField( - this.props.value ? this.props.value : '' - ); - - this.setState({ - init: true - }); - } - - componentDidUpdate(prevProps) { - if (prevProps.valueOverride !== this.props.valueOverride) { - this.sendField(this.props.valueOverride); - } - - if (prevProps.initialValue !== this.props.initialValue) { - this.sendField(this.props.initialValue); - } - } - - render() { - - const valid = this.props.context.fields[this.props.name] - ? this.props.context.fields[this.props.name].valid - : true; - - const showError = valid === false && this.props.context.submitted; - - const Required = this.props.required - ? () => * - : () => null; - - const Error = showError - ? () => {this.errors[this.props.type]} - : () => null; - - const Label = this.props.label - ? () => - : () => null; - - let className = `interact ${this.props.type}`; - className = !showError ? className : `${className} error`; - - const initialValue = this.props.initialValue - ? this.props.initialValue - : ''; - - const contextValue = (this.props.context.fields[this.props.name] && this.props.context.fields[this.props.name].value) - ? this.props.context.fields[this.props.name].value - : initialValue; - - const value = this.props.valueOverride - ? this.props.valueOverride - : contextValue; - - return ( -
- -
- ); + default: + return false; } } -const ContextInput = props => { +const Input = props => { return ( - - {context => } - +
+ {props.error} + {props.label} + +
); -}; +} -export default ContextInput; +export default fieldType(Input, 'input', validate, errors); diff --git a/src/components/field-types/Input/index.scss b/src/components/field-types/Input/index.scss index 6dbca9ac7d..7da51e7358 100644 --- a/src/components/field-types/Input/index.scss +++ b/src/components/field-types/Input/index.scss @@ -1,8 +1,6 @@ @import '~payload/scss/styles'; -.interact.text, -.interact.email, -.interact.password { +.field-type.input { margin-bottom: rem(.5); position: relative; diff --git a/src/components/field-types/Textarea/index.js b/src/components/field-types/Textarea/index.js index 464b1f17bf..6e242a07f7 100644 --- a/src/components/field-types/Textarea/index.js +++ b/src/components/field-types/Textarea/index.js @@ -1,136 +1,30 @@ -import React, { Component } from 'react'; -import { FormContext, Tooltip } from 'payload/components'; +import React from 'react'; +import { fieldType } from 'payload/components'; import './index.scss'; -class Textarea extends Component { - constructor() { - super(); - - this.errors = { - text: 'Please fill in the field' - }; - - this.state = { - init: false - }; - - this.validate = this.validate.bind(this); - this.sendField = this.sendField.bind(this); - } - - validate(value) { - switch (this.props.type) { - case 'honeypot': - return value.length === 0; - default: - return value.length > 0; - } - } - - sendField(value) { - this.props.context.setValue({ - name: this.props.name, - value: value, - valid: this.props.required - ? this.validate(value) - : true - }); - } - - componentDidMount() { - this.sendField( - this.props.value ? this.props.value : '' - ) - - this.setState({ - init: true - }); - } - - componentDidUpdate(prevProps) { - if (prevProps.valueOverride !== this.props.valueOverride) { - this.sendField(this.props.valueOverride); - } - - if (prevProps.initialValue !== this.props.initialValue) { - this.sendField(this.props.initialValue); - } - } - - render() { - const valid = this.props.context.fields[this.props.name] - ? this.props.context.fields[this.props.name].valid - : true; - - const showError = valid === false && this.props.context.submitted; - - const Required = this.props.required - ? () => * - : () => null; - - let Error = showError - ? () => {this.errors.text} - : () => null; - - const Label = this.props.label - ? () => - : () => null; - - let className = 'interact textarea'; - className = !showError ? className : `${className} error`; - - let style = this.props.style - ? this.props.style - : null; - - if (this.props.type === 'honeypot') { - style = { position: 'fixed', left: '10000px', top: '-100px' }; - Error = () => null; - className = 'interact'; - } - - const initialValue = this.props.initialValue - ? this.props.initialValue - : ''; - - const contextValue = (this.props.context.fields[this.props.name] && this.props.context.fields[this.props.name].value) - ? this.props.context.fields[this.props.name].value - : initialValue; - - const value = this.props.valueOverride - ? this.props.valueOverride - : contextValue; - - return ( -
- -
- ); - } -} - -const ContextTextarea = props => { - return ( - - {context => + + ); +} + +export default fieldType(Textarea, 'textarea', validate, errors); diff --git a/src/components/field-types/Textarea/index.scss b/src/components/field-types/Textarea/index.scss index 89a969ed81..460a4f51d6 100644 --- a/src/components/field-types/Textarea/index.scss +++ b/src/components/field-types/Textarea/index.scss @@ -1,6 +1,6 @@ @import '~payload/scss/styles'; -.interact.textarea { +.field-type.textarea { margin-bottom: rem(.5); position: relative; diff --git a/src/components/field-types/fieldType/index.js b/src/components/field-types/fieldType/index.js new file mode 100644 index 0000000000..78e7159e8f --- /dev/null +++ b/src/components/field-types/fieldType/index.js @@ -0,0 +1,120 @@ +import React, { Component } from 'react'; +import { FormContext, Tooltip } from 'payload/components'; + +const fieldType = (PassedComponent, slug, validate, errors) => { + + class FieldType extends Component { + + constructor(props) { + super(props); + + this.state = { + init: false + }; + } + + sendField(value) { + this.props.context.setValue({ + name: this.props.name, + value: value, + valid: this.props.required + ? validate(value, this.props.type) + : true + }); + } + + componentDidMount() { + this.sendField( + this.props.value ? this.props.value : '' + ) + + this.setState({ + init: true + }); + } + + componentDidUpdate(prevProps) { + if (prevProps.valueOverride !== this.props.valueOverride) { + this.sendField(this.props.valueOverride); + } + + if (prevProps.initialValue !== this.props.initialValue) { + this.sendField(this.props.initialValue); + } + } + + render() { + const valid = this.props.context.fields[this.props.name] + ? this.props.context.fields[this.props.name].valid + : true; + + const showError = valid === false && this.props.context.submitted; + + let className = `field-type ${slug}${showError ? ' error' : ''}`; + + const initialValue = this.props.initialValue + ? this.props.initialValue + : ''; + + const contextValue = (this.props.context.fields[this.props.name] && this.props.context.fields[this.props.name].value) + ? this.props.context.fields[this.props.name].value + : initialValue; + + const value = this.props.valueOverride + ? this.props.valueOverride + : contextValue; + + return ( + { + this.sendField(e.target.value); + this.props.onChange && this.props.onChange(e); + }} + Label={