diff --git a/package.json b/package.json index 8f87ec52f0..bf62a0f43b 100644 --- a/package.json +++ b/package.json @@ -57,13 +57,12 @@ "passport-local": "^1.0.0", "passport-local-mongoose": "^5.0.1", "postcss-preset-env": "6.0.6", + "prop-types": "^15.7.2", "qs": "^6.9.0", "react": "^16.9.0", "react-document-meta": "^3.0.0-beta.2", "react-dom": "^16.9.0", - "react-redux": "^5.0.7", - "react-router-dom": "^4.3.1", - "redux": "^4.0.4", + "react-router-dom": "^5.1.2", "sharp": "^0.22.1", "universal-cookie": "^3.1.0", "url-loader": "^1.0.1", diff --git a/src/client/components/controls/Button/index.scss b/src/client/components/controls/Button/index.scss index 9a2880bb59..7921741ba4 100644 --- a/src/client/components/controls/Button/index.scss +++ b/src/client/components/controls/Button/index.scss @@ -4,11 +4,11 @@ @extend %uppercase-label; background-color: $primary; border: 1px solid $primary; - padding: rem(.5) rem(.75); - line-height: rem(.5); + padding: base(.5) base(.75); + line-height: base(.5); border-radius: $radius-sm; - margin-top: rem(1); - margin-bottom: rem(1); + margin-top: base(1); + margin-bottom: base(1); cursor: pointer; &.btn-secondary { @@ -33,9 +33,9 @@ } &.btn-small { - padding: rem(0) rem(.25) rem(.04); + padding: base(0) base(.25) base(.04); border-radius: 3px; - font-size: rem(.3); + font-size: base(.3); } &.btn-text { @@ -55,12 +55,12 @@ padding: 0; border-radius: 0; border: 0; - width: rem(1.5); - height: rem(1.5); + width: base(1.5); + height: base(1.5); svg { - width: rem(.75); - height: rem(.75); + width: base(.75); + height: base(.75); } &:hover { diff --git a/src/client/components/field-types/Email/index.scss b/src/client/components/field-types/Email/index.scss index 4d654e28d7..b130bba66a 100644 --- a/src/client/components/field-types/Email/index.scss +++ b/src/client/components/field-types/Email/index.scss @@ -1,7 +1,7 @@ @import '~payload/client/scss/styles'; .field-type.email { - margin-bottom: rem(.5); + margin-bottom: base(.5); position: relative; input { diff --git a/src/client/components/field-types/HiddenInput/index.js b/src/client/components/field-types/HiddenInput/index.js index ff06231ed4..0e54a356ed 100644 --- a/src/client/components/field-types/HiddenInput/index.js +++ b/src/client/components/field-types/HiddenInput/index.js @@ -1,7 +1,14 @@ import React from 'react'; import fieldType from '../fieldType'; -const HiddenInput = props => ; +const HiddenInput = props => ( + +); export default fieldType(HiddenInput, 'hiddenInput'); diff --git a/src/client/components/field-types/Input/index.scss b/src/client/components/field-types/Input/index.scss index 8da9091ea3..30bf5c599f 100644 --- a/src/client/components/field-types/Input/index.scss +++ b/src/client/components/field-types/Input/index.scss @@ -1,7 +1,7 @@ @import '~payload/client/scss/styles'; .field-type.input { - margin-bottom: rem(.5); + margin-bottom: base(.5); position: relative; input { diff --git a/src/client/components/field-types/Password/index.scss b/src/client/components/field-types/Password/index.scss index 3e5e6a5219..491a197723 100644 --- a/src/client/components/field-types/Password/index.scss +++ b/src/client/components/field-types/Password/index.scss @@ -1,7 +1,7 @@ @import '~payload/client/scss/styles'; .field-type.password { - margin-bottom: rem(.5); + margin-bottom: base(.5); position: relative; input { diff --git a/src/client/components/field-types/Textarea/index.scss b/src/client/components/field-types/Textarea/index.scss index c4660b137f..b26e327dcc 100644 --- a/src/client/components/field-types/Textarea/index.scss +++ b/src/client/components/field-types/Textarea/index.scss @@ -1,12 +1,12 @@ @import '~payload/client/scss/styles'; .field-type.textarea { - margin-bottom: rem(.5); + margin-bottom: base(.5); position: relative; textarea { @include formInput(); - min-height: rem(3); + min-height: base(3); } &.error { diff --git a/src/client/components/field-types/fieldType/index.js b/src/client/components/field-types/fieldType/index.js index 7e56a09108..32c1f91574 100644 --- a/src/client/components/field-types/fieldType/index.js +++ b/src/client/components/field-types/fieldType/index.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { FormContext } from '../../forms/Form' +import FormContext from '../../forms/Form/Context' import './index.scss'; diff --git a/src/client/components/field-types/fieldType/index.scss b/src/client/components/field-types/fieldType/index.scss index 0a5e2d8f23..197514f9e9 100644 --- a/src/client/components/field-types/fieldType/index.scss +++ b/src/client/components/field-types/fieldType/index.scss @@ -2,7 +2,7 @@ .field-type { @include gutter; - margin-bottom: rem(.5); + margin-bottom: base(.5); position: relative; width: 100%; @@ -11,14 +11,14 @@ .required { color: $error; - margin-left: rem(.25); + margin-left: base(.25); margin-right: auto; } } .tooltip { left: auto; - right: rem(.5); + right: base(.5); transform: none; background-color: $error; @@ -28,6 +28,6 @@ } @include small-break { - margin-bottom: rem(.5); + margin-bottom: base(.5); } } diff --git a/src/client/components/forms/Form/Context.js b/src/client/components/forms/Form/Context.js new file mode 100644 index 0000000000..7c0127fbd6 --- /dev/null +++ b/src/client/components/forms/Form/Context.js @@ -0,0 +1,3 @@ +import { createContext } from 'react'; + +export default createContext({}); diff --git a/src/client/components/forms/Form/index.js b/src/client/components/forms/Form/index.js index 6b389af555..bd9a853aec 100644 --- a/src/client/components/forms/Form/index.js +++ b/src/client/components/forms/Form/index.js @@ -1,55 +1,50 @@ -import React, { Component, createContext } from 'react'; -import { withRouter } from 'react-router-dom'; -import { connect } from 'react-redux'; +import React, { useState } from 'react'; +import { useHistory } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import FormContext from './Context'; +import { useLocale } from '../../utilities/Locale'; +import { useStatusList } from '../../modules/Status'; import HiddenInput from '../../field-types/HiddenInput'; import api from '../../../api'; import './index.scss'; -export const FormContext = createContext({}); +const Form = (props) => { + const [fields, setFields] = useState({}); + const [submitted, setSubmitted] = useState(false); + const [processing, setProcessing] = useState(false); + const history = useHistory(); + const locale = useLocale(); + const { addStatus } = useStatusList(); -const mapState = state => ({ - searchParams: state.common.searchParams -}) + const { + onSubmit, + ajax, + method, + action, + handleAjaxResponse, + children, + className, + redirect, + } = props; -const mapDispatch = dispatch => ({ - addStatus: status => dispatch({ type: 'ADD_STATUS', payload: status }) -}) - -class Form extends Component { - constructor(props) { - super(props); - - this.state = { - fields: {}, - status: null, - submitted: false, - processing: false - }; - } - - setValue = field => { - this.setState(prevState => ({ - ...prevState, - fields: { - ...prevState.fields, - [field.name]: { - value: field.value, - valid: field.valid - } - } - })); - } - - submit = e => { - this.setState({ - submitted: true + const setValue = (field) => { + setFields({ + ...fields, + [field.name]: { + value: field.value, + valid: field.valid, + }, }); + }; + + const submit = (e) => { + setSubmitted(true); let isValid = true; - Object.keys(this.state.fields).forEach((field) => { - if (!this.state.fields[field].valid) { + Object.keys(fields).forEach((field) => { + if (!fields[field].valid) { isValid = false; } }); @@ -59,80 +54,100 @@ class Form extends Component { e.preventDefault(); // If submit handler comes through via props, run that - } else if (this.props.onSubmit) { + } else if (onSubmit) { e.preventDefault(); - this.props.onSubmit(this.state.fields); + onSubmit(fields); // If form is AJAX, fetch data - } else if (this.props.ajax !== false) { + } else if (ajax !== false) { e.preventDefault(); - let data = {}; + const data = {}; // Clean up data passed from field state - Object.keys(this.state.fields).forEach((field) => { - data[field] = this.state.fields[field].value; + Object.keys(fields).forEach((field) => { + data[field] = fields[field].value; }); - this.setState({ - processing: true - }); + setProcessing(true); // Make the API call from the action - api.requests[this.props.method.toLowerCase()](this.props.action, data).then( - res => { - + api.requests[method.toLowerCase()](action, data).then( + (res) => { // If prop handleAjaxResponse is passed, pass it the response - this.props.handleAjaxResponse && this.props.handleAjaxResponse(res); + if (handleAjaxResponse && typeof handleAjaxResponse === 'function') handleAjaxResponse(res); // Provide form data to the redirected page - if (this.props.redirect) { - this.props.history.push(this.props.redirect, data); + if (redirect) { + history.push(redirect, data); } else { - this.setState({ processing: false }); - this.props.addStatus({ + setProcessing(false); + addStatus({ message: res.message, - type: 'success' - }) + type: 'success', + }); } }, - error => { + (error) => { console.log(error); - this.setState({ processing: false }); - this.props.addStatus({ + setProcessing(false); + addStatus({ message: error.message, - type: 'error' - }) - } + type: 'error', + }); + }, ); } // If valid and not AJAX submit as usual - return; - } + }; - render() { + return ( +
+ + + {children} + +
+ ); +}; - return ( -
- - - {this.props.children} - -
- ); - } -} +Form.defaultProps = { + redirect: '', + onSubmit: null, + ajax: true, + method: 'POST', + action: '', + handleAjaxResponse: false, + className: '', +}; -export default withRouter(connect(mapState, mapDispatch)(Form)); +Form.propTypes = { + onSubmit: PropTypes.func, + ajax: PropTypes.bool, + method: PropTypes.oneOf(['post', 'POST', 'get', 'GET', 'put', 'PUT', 'delete', 'DELETE']), + action: PropTypes.string, + handleAjaxResponse: PropTypes.func, + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]).isRequired, + className: PropTypes.string, + redirect: PropTypes.string, +}; + +export default Form; diff --git a/src/client/components/graphics/Arrow/index.js b/src/client/components/forms/Submit/graphics/Arrow/index.js similarity index 100% rename from src/client/components/graphics/Arrow/index.js rename to src/client/components/forms/Submit/graphics/Arrow/index.js diff --git a/src/client/components/graphics/Close/index.js b/src/client/components/forms/Submit/graphics/Close/index.js similarity index 100% rename from src/client/components/graphics/Close/index.js rename to src/client/components/forms/Submit/graphics/Close/index.js diff --git a/src/client/components/graphics/Icon/index.js b/src/client/components/forms/Submit/graphics/Icon/index.js similarity index 100% rename from src/client/components/graphics/Icon/index.js rename to src/client/components/forms/Submit/graphics/Icon/index.js diff --git a/src/client/components/graphics/Logo/index.js b/src/client/components/forms/Submit/graphics/Logo/index.js similarity index 100% rename from src/client/components/graphics/Logo/index.js rename to src/client/components/forms/Submit/graphics/Logo/index.js diff --git a/src/client/components/graphics/PayloadIcon/icon.svg b/src/client/components/forms/Submit/graphics/PayloadIcon/icon.svg similarity index 100% rename from src/client/components/graphics/PayloadIcon/icon.svg rename to src/client/components/forms/Submit/graphics/PayloadIcon/icon.svg diff --git a/src/client/components/graphics/PayloadIcon/index.js b/src/client/components/forms/Submit/graphics/PayloadIcon/index.js similarity index 100% rename from src/client/components/graphics/PayloadIcon/index.js rename to src/client/components/forms/Submit/graphics/PayloadIcon/index.js diff --git a/src/client/components/graphics/PayloadIcon/index.scss b/src/client/components/forms/Submit/graphics/PayloadIcon/index.scss similarity index 100% rename from src/client/components/graphics/PayloadIcon/index.scss rename to src/client/components/forms/Submit/graphics/PayloadIcon/index.scss diff --git a/src/client/components/graphics/PayloadLogo/index.js b/src/client/components/forms/Submit/graphics/PayloadLogo/index.js similarity index 100% rename from src/client/components/graphics/PayloadLogo/index.js rename to src/client/components/forms/Submit/graphics/PayloadLogo/index.js diff --git a/src/client/components/graphics/PayloadLogo/index.scss b/src/client/components/forms/Submit/graphics/PayloadLogo/index.scss similarity index 100% rename from src/client/components/graphics/PayloadLogo/index.scss rename to src/client/components/forms/Submit/graphics/PayloadLogo/index.scss diff --git a/src/client/components/forms/Submit/index.js b/src/client/components/forms/Submit/index.js index 1ba8fe9666..97e2d35e3e 100644 --- a/src/client/components/forms/Submit/index.js +++ b/src/client/components/forms/Submit/index.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { FormContext } from '../Form'; +import FormContext from '../Form/Context'; import Button from '../../controls/Button'; import './index.scss'; @@ -16,13 +16,17 @@ class FormSubmit extends Component { } } -const ContextFormSubmit = props => { +const ContextFormSubmit = (props) => { return ( - {context => } + {context => ( + + )} ); }; export default ContextFormSubmit; - diff --git a/src/client/components/index.js b/src/client/components/index.js index 9f0cdcdc3c..1eabec662f 100644 --- a/src/client/components/index.js +++ b/src/client/components/index.js @@ -1,29 +1,24 @@ -import React, { Fragment } from 'react'; +import React from 'react'; import { render } from 'react-dom'; import { BrowserRouter as Router } from 'react-router-dom'; -import { Provider } from 'react-redux'; +import { SearchParamsProvider } from './utilities/SearchParams'; +import { LocaleProvider } from './utilities/Locale'; +import { StatusListProvider } from './modules/Status'; import Routes from './Routes'; -import store from '../store'; -import MeasureWindow from './utilities/MeasureWindow'; -import MeasureScroll from './utilities/MeasureScroll'; -import SetLocale from './utilities/SetLocale'; -import SetSearchParams from './utilities/SetSearchParams'; import '../scss/app.scss'; const Index = () => { return ( - - - - - - - - - - - + + + + + + + + + ); }; diff --git a/src/client/components/layout/DefaultTemplate/index.scss b/src/client/components/layout/DefaultTemplate/index.scss index 2b3638e80d..764f68889a 100644 --- a/src/client/components/layout/DefaultTemplate/index.scss +++ b/src/client/components/layout/DefaultTemplate/index.scss @@ -2,7 +2,7 @@ .default-template { @include default-template-width; - padding-top: rem(1); + padding-top: base(1); .eyebrow { @include m; diff --git a/src/client/components/layout/Section/index.scss b/src/client/components/layout/Section/index.scss index 1d2c97dd2e..b28449fa88 100644 --- a/src/client/components/layout/Section/index.scss +++ b/src/client/components/layout/Section/index.scss @@ -2,7 +2,7 @@ section.section { @extend %shadow; - margin: rem(1) rem(.5); + margin: base(1) base(.5); header, .content { diff --git a/src/client/components/layout/Sidebar/index.scss b/src/client/components/layout/Sidebar/index.scss index 704b97ad59..d169881aac 100644 --- a/src/client/components/layout/Sidebar/index.scss +++ b/src/client/components/layout/Sidebar/index.scss @@ -4,11 +4,11 @@ position: fixed; top: 0; left: 0; - width: rem(6); - padding: rem(1); + width: base(6); + padding: base(1); .icon-wrap { - margin: 0 0 rem(.5); + margin: 0 0 base(.5); > * { height: $base; @@ -21,26 +21,26 @@ } nav { - margin: rem(.25) 0 $base; + margin: base(.25) 0 $base; a { position: relative; display: flex; - padding: rem(.33) 0; + padding: base(.33) 0; border-bottom: 0; svg { opacity: 0; position: absolute; top: 50%; - left: - rem(.5); + left: - base(.5); transform: translateY(-50%); - width: rem(.3); - height: rem(.3); + width: base(.3); + height: base(.3); } &.active { - padding-left: rem(.6); + padding-left: base(.6); svg { opacity: 1; diff --git a/src/client/components/layout/Sticky/index.scss b/src/client/components/layout/Sticky/index.scss index b268e648b2..64a5c19dbc 100644 --- a/src/client/components/layout/Sticky/index.scss +++ b/src/client/components/layout/Sticky/index.scss @@ -2,8 +2,8 @@ .sticky { z-index: 10; - padding-top: rem(.75); - padding-bottom: rem(.75); + padding-top: base(.75); + padding-bottom: base(.75); width: 100%; position: sticky; top: 0; diff --git a/src/client/components/layout/Table/index.scss b/src/client/components/layout/Table/index.scss index 500dde4bb6..0ed114ffd9 100644 --- a/src/client/components/layout/Table/index.scss +++ b/src/client/components/layout/Table/index.scss @@ -11,7 +11,7 @@ table { } td, th { - padding: rem(.5); + padding: base(.5); } tbody { diff --git a/src/client/components/modules/HeadingButton/index.scss b/src/client/components/modules/HeadingButton/index.scss index c81de26f31..3bf0b2043c 100644 --- a/src/client/components/modules/HeadingButton/index.scss +++ b/src/client/components/modules/HeadingButton/index.scss @@ -10,6 +10,6 @@ } h1 { - margin: 0 rem(.5) 0 0; + margin: 0 base(.5) 0 0; } } diff --git a/src/client/components/modules/Localizer/index.scss b/src/client/components/modules/Localizer/index.scss index 90fb4ba9ef..0fef47a7b4 100644 --- a/src/client/components/modules/Localizer/index.scss +++ b/src/client/components/modules/Localizer/index.scss @@ -17,9 +17,9 @@ svg { transform: rotate(90deg); - width: rem(.25); - height: rem(.25); - margin-right: rem(.375); + width: base(.25); + height: base(.25); + margin-right: base(.375); } &:hover { diff --git a/src/client/components/modules/Status/index.js b/src/client/components/modules/Status/index.js index 73dbc09537..119a0e1e03 100644 --- a/src/client/components/modules/Status/index.js +++ b/src/client/components/modules/Status/index.js @@ -1,40 +1,79 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { Close } from 'payload/components'; +import React, { useState, createContext, useContext } from 'react'; +import PropTypes from 'prop-types'; +import Close from '../../forms/Submit/graphics/Close'; import './index.scss'; -const mapState = state => ({ - status: state.common.status -}) +const Context = createContext({}); -const mapDispatch = dispatch => ({ - addStatus: status => dispatch({ type: 'ADD_STATUS', payload: status }), - removeStatus: i => dispatch({ type: 'REMOVE_STATUS', payload: i }) -}) +const StatusListProvider = ({ children }) => { + const [statusList, setStatus] = useState([]); -const Status = props => { - if (props.status.length > 0) { + return ( + { + const newStatusList = [...statusList]; + newStatusList.splice(i, 1); + setStatus(newStatusList); + }, + addStatus: status => [ + ...statusList, + status, + ], + }} + > + {children} + + ); +}; + +StatusListProvider.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]).isRequired, +}; + +const useStatusList = () => useContext(Context); + +const StatusList = () => { + const { statusList, removeStatus } = useStatusList(); + + if (statusList.length > 0) { return ( - ) + ); } return null; -} +}; -export default connect(mapState, mapDispatch)(Status); +export { + StatusListProvider, + StatusList, + useStatusList, +}; + +export default Context; diff --git a/src/client/components/modules/Status/index.scss b/src/client/components/modules/Status/index.scss index 10421e8878..0b6cea231c 100644 --- a/src/client/components/modules/Status/index.scss +++ b/src/client/components/modules/Status/index.scss @@ -12,8 +12,8 @@ color: $black; font-weight: bold; border-radius: $radius-sm; - padding: rem(.5); - margin-bottom: rem(.5); + padding: base(.5); + margin-bottom: base(.5); display: flex; justify-content: space-between; } @@ -24,8 +24,8 @@ svg { @include color-svg($black); - width: rem(.35); - height: rem(.35); + width: base(.35); + height: base(.35); } &:hover { diff --git a/src/client/components/modules/StepNav/index.scss b/src/client/components/modules/StepNav/index.scss index 915991009c..35e73020e1 100644 --- a/src/client/components/modules/StepNav/index.scss +++ b/src/client/components/modules/StepNav/index.scss @@ -8,15 +8,15 @@ } a { - margin-right: rem(.35); + margin-right: base(.35); border: 0; display: flex; align-items: center; svg { - margin-left: rem(.35); - width: rem(.25); - height: rem(.25); + margin-left: base(.35); + width: base(.25); + height: base(.25); } label { diff --git a/src/client/components/modules/StickyHeader/index.scss b/src/client/components/modules/StickyHeader/index.scss index 01ab1505ab..d49942ef54 100644 --- a/src/client/components/modules/StickyHeader/index.scss +++ b/src/client/components/modules/StickyHeader/index.scss @@ -12,7 +12,7 @@ .content { flex-grow: 1; min-width: 0; - padding-right: rem(1); + padding-right: base(1); } .controls { @@ -25,7 +25,7 @@ } > *:last-child { - margin-left: rem(1); + margin-left: base(1); } } @@ -35,8 +35,8 @@ position: absolute; z-index: -1; top: 0; - right: - rem(1); + right: - base(1); bottom: 0; - left: - rem(1); + left: - base(1); } } diff --git a/src/client/components/modules/Tooltip/index.scss b/src/client/components/modules/Tooltip/index.scss index 4362669214..5627486d26 100644 --- a/src/client/components/modules/Tooltip/index.scss +++ b/src/client/components/modules/Tooltip/index.scss @@ -8,14 +8,14 @@ top: 0; left: 50%; transform: translateX(-50%); - padding: 0 rem(.4); + padding: 0 base(.4); color: $black; - line-height: rem(.8); + line-height: base(.8); span { position: absolute; transform: translateX(-50%); - top: rem(.7); + top: base(.7); left: 50%; height: 0; width: 0; diff --git a/src/client/components/modules/UploadMedia/index.scss b/src/client/components/modules/UploadMedia/index.scss index b1a2c98447..9cb35d7af6 100644 --- a/src/client/components/modules/UploadMedia/index.scss +++ b/src/client/components/modules/UploadMedia/index.scss @@ -1,7 +1,7 @@ @import '~payload/client/scss/styles'; .upload-media { - padding: rem(1); + padding: base(1); display: flex; align-items: center; flex-direction: column; @@ -17,6 +17,6 @@ } .btn { - margin: rem(.125) 0 0; + margin: base(.125) 0 0; } } diff --git a/src/client/components/utilities/Locale/index.js b/src/client/components/utilities/Locale/index.js new file mode 100644 index 0000000000..4fac354b5c --- /dev/null +++ b/src/client/components/utilities/Locale/index.js @@ -0,0 +1,37 @@ +import React, { createContext, useContext } from 'react'; +import config from 'payload-config'; +import PropTypes from 'prop-types'; +import searchParamsContext from '../SearchParams'; + +const Context = createContext({}); + +export const LocaleProvider = ({ children }) => { + const searchParams = useContext(searchParamsContext); + + let activeLocale = null; + + if (config.localization) { + if (searchParams.locale && config.localization.locales.indexOf(searchParams.locale) > -1) { + activeLocale = searchParams.locale; + } else { + activeLocale = (config.localization.defaultLocale); + } + } + + return ( + + {children} + + ); +}; + +export const useLocale = () => useContext(Context); + +LocaleProvider.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]).isRequired, +}; + +export default Context; diff --git a/src/client/components/utilities/MeasureScroll/index.js b/src/client/components/utilities/MeasureScroll/index.js deleted file mode 100644 index e805fa84aa..0000000000 --- a/src/client/components/utilities/MeasureScroll/index.js +++ /dev/null @@ -1,58 +0,0 @@ -import { Component } from 'react'; -import { connect } from 'react-redux'; - -const mapStateToProps = state => ({ - scrollPercentage: state.common.scrollPercentage, - scrollPos: state.common.scrollPos -}); - -const mapDispatchToProps = dispatch => ({ - updateScroll: (pos) => dispatch({ type: 'UPDATE_SCROLL', payload: pos }), - updateScrollPercentage : (percentage) => dispatch({ type: 'UPDATE_SCROLL_PERCENTAGE', payload: percentage }) -}); - -class MeasureScroll extends Component { - constructor(props) { - super(props); - - if ('scrollRestoration' in window.history) { - window.history.scrollRestoration = 'manual'; - } - - // Throttle scroll event - let ticking = false; - let latestKnownScrollY = 0; - let scrollPercentage = 0; - - this.updateScroll = () => { - ticking = false; - this.props.updateScroll(latestKnownScrollY); - this.props.updateScrollPercentage(scrollPercentage); - }; - - this.onScroll = () => { - const roundedPercent = 100; - const roundedDecimal = 2; - latestKnownScrollY = window.pageYOffset; - scrollPercentage = (latestKnownScrollY / (document.body.scrollHeight - window.innerHeight) * roundedPercent).toFixed(roundedDecimal); - this.requestTick(); - }; - - this.requestTick = () => { - if (!ticking) { - requestAnimationFrame(this.updateScroll); - } - ticking = true; - }; - } - - componentDidMount() { - window.addEventListener('scroll', this.onScroll, false); - } - - render() { - return null; - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(MeasureScroll); diff --git a/src/client/components/utilities/MeasureWindow/index.js b/src/client/components/utilities/MeasureWindow/index.js deleted file mode 100644 index ebff883259..0000000000 --- a/src/client/components/utilities/MeasureWindow/index.js +++ /dev/null @@ -1,55 +0,0 @@ -import { Component } from 'react'; -import { connect } from 'react-redux'; - -const mapStateToProps = state => ({ - windowWidth: state.common.windowWidth, - windowHeight: state.common.windowHeight -}); - -const mapDispatchToProps = dispatch => ({ - setWindowSize: (size) => dispatch({ type: 'SET_WINDOW_SIZE', payload: size }), -}); - -class MeasureWindow extends Component { - constructor() { - super(); - this.setSize = this.setSize.bind(this); - this.onResize = this.onResize.bind(this); - } - - setSize() { - this.props.setWindowSize({ - width: window.innerWidth, - height: window.innerHeight - }); - } - - onResize() { - // Only resize on screens larger than mobile - // To avoid toolbars hiding and orientation change - const mobileWidth = 450; - - if (window.innerWidth > mobileWidth) { - this.setSize(); - } - } - - componentDidMount() { - window.addEventListener('resize', this.onResize); - - window.addEventListener('orientationchange', () => { - const delay = 500; - setTimeout(() => { - this.setSize(); - }, delay); - }); - - this.setSize(); - } - - render() { - return false; - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(MeasureWindow); diff --git a/src/client/components/utilities/SearchParams/index.js b/src/client/components/utilities/SearchParams/index.js new file mode 100644 index 0000000000..4ccdc7ed54 --- /dev/null +++ b/src/client/components/utilities/SearchParams/index.js @@ -0,0 +1,30 @@ +import React, { createContext } from 'react'; +import { useLocation } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import qs from 'qs'; + +const Context = createContext({}); + +export const SearchParamsProvider = ({ children }) => { + const location = useLocation(); + + const params = qs.parse( + location.search, + { ignoreQueryPrefix: true }, + ); + + return ( + + {children} + + ); +}; + +SearchParamsProvider.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]).isRequired, +}; + +export default Context; diff --git a/src/client/components/utilities/SetLocale/index.js b/src/client/components/utilities/SetLocale/index.js deleted file mode 100644 index bb8c947145..0000000000 --- a/src/client/components/utilities/SetLocale/index.js +++ /dev/null @@ -1,51 +0,0 @@ -import { Component } from 'react'; -import { connect } from 'react-redux'; - -const mapState = state => ({ - config: state.common.config, - searchParams: state.common.searchParams -}) - -const mapDispatch = dispatch => ({ - setLocale: locale => dispatch({ type: 'SET_LOCALE', payload: locale }) -}) - -class SetLocale extends Component { - - constructor() { - super(); - - this.state = { - init: false - } - } - - setLocale = () => { - const { searchParams, config, setLocale } = this.props; - - if (searchParams && config.localization) { - if (searchParams.locale && config.localization.locales.indexOf(searchParams.locale) > -1) { - setLocale(searchParams.locale); - } else if (!this.state.init) { - setLocale(config.localization.defaultLocale); - this.setState({ init: true }); - } - } - } - - componentDidMount() { - this.setLocale(); - } - - componentDidUpdate(prevProps) { - if (prevProps.searchParams !== this.props.searchParams || prevProps.config !== this.props.config) { - this.setLocale(); - } - } - - render() { - return null; - } -} - -export default connect(mapState, mapDispatch)(SetLocale); diff --git a/src/client/components/utilities/SetSearchParams/index.js b/src/client/components/utilities/SetSearchParams/index.js deleted file mode 100644 index 023d49a4bb..0000000000 --- a/src/client/components/utilities/SetSearchParams/index.js +++ /dev/null @@ -1,36 +0,0 @@ -import { Component } from 'react' -import { connect } from 'react-redux'; -import { withRouter } from 'react-router-dom'; -import qs from 'qs'; - -const mapDispatch = dispatch => ({ - setParams: params => dispatch({ type: 'SET_SEARCH_PARAMS', payload: params }) -}) - -class SetSearchParams extends Component { - - setParams = () => { - const params = qs.parse( - this.props.location.search, - { ignoreQueryPrefix: true } - ); - - this.props.setParams(params ? params : {}); - } - - componentDidMount() { - this.setParams(); - } - - componentDidUpdate(prevProps) { - if (prevProps.location !== this.props.location) { - this.setParams(); - } - } - - render() { - return null; - } -} - -export default withRouter(connect(null, mapDispatch)(SetSearchParams)); diff --git a/src/client/components/views/Login/index.js b/src/client/components/views/Login/index.js index 3df8ec9fe0..967d89928e 100644 --- a/src/client/components/views/Login/index.js +++ b/src/client/components/views/Login/index.js @@ -1,6 +1,5 @@ import React from 'react'; import Cookies from 'universal-cookie'; -import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; import ContentBlock from '../../layout/ContentBlock'; import Form from '../../forms/Form'; @@ -10,25 +9,17 @@ import FormSubmit from '../../forms/Submit'; import './index.scss'; -const mapStateToProps = state => ({ - windowHeight: state.common.windowHeight, -}); - const cookies = new Cookies(); const handleAjaxResponse = (res) => { cookies.set('token', res.token, { path: '/' }); }; -const Login = (props) => { - const Logo = props.logo; - const minHeight = props.windowHeight; - +const Login = () => { return (
{ ); }; -export default connect(mapStateToProps)(Login); +export default Login; diff --git a/src/client/components/views/Login/index.scss b/src/client/components/views/Login/index.scss index 3d7a22eba0..d3dc5bec42 100644 --- a/src/client/components/views/Login/index.scss +++ b/src/client/components/views/Login/index.scss @@ -1,13 +1,13 @@ -@import '~payload/client/scss/styles'; +@import '../../../scss/styles'; .login { display: flex; align-items: center; flex-wrap: wrap; + min-height: 100vh; .logo-wrap { - display: block; - margin: 0 auto rem(1); + margin: 0 auto base(1); max-width: 200px; svg { diff --git a/src/client/reducers/common.js b/src/client/reducers/common.js deleted file mode 100644 index fcd8d446ef..0000000000 --- a/src/client/reducers/common.js +++ /dev/null @@ -1,95 +0,0 @@ -const defaultState = { - scrollPos: 0, - windowWidth: 1400, - windowHeight: 900, - viewWidth: false, - viewHeight: false, - stepNav: [], - locale: null, - config: { - collections: {}, - localization: { - locales: [] - }, - routes: {}, - }, - searchParams: {}, - status: [] -}; - -export default (state = defaultState, action) => { - switch (action.type) { - - case 'UPDATE_SCROLL': - - return { - ...state, - scrollPos: action.payload - }; - - case 'SET_WINDOW_SIZE': - - return { - ...state, - windowWidth: action.payload.width, - windowHeight: action.payload.height - }; - - case 'SET_VIEW_SIZE': - - return { - ...state, - viewWidth: action.payload.width, - viewHeight: action.payload.height - }; - - case 'SET_STEP_NAV': - - return { - ...state, - stepNav: action.payload - }; - - case 'LOAD_CONFIG': - - return { - ...state, - config: action.payload - }; - - case 'SET_LOCALE': - return { - ...state, - locale: action.payload - } - - case 'SET_SEARCH_PARAMS': - return { - ...state, - searchParams: action.payload - } - - case 'ADD_STATUS': - return { - ...state, - status: [ - action.payload, - ...state.status - ] - }; - - case 'REMOVE_STATUS': { - const newStatus = [...state.status]; - newStatus.splice(action.payload, 1); - return { - ...state, - status: newStatus - }; - } - - default: - // - } - - return state; -}; diff --git a/src/client/scss/app.scss b/src/client/scss/app.scss index 2400230324..36a8415110 100644 --- a/src/client/scss/app.scss +++ b/src/client/scss/app.scss @@ -24,17 +24,17 @@ body { html { font-size: $body; - line-height: rem(1); + line-height: base(1); font-size: 20px; @include mid-break { font-size: 18px; - line-height: rem(1); + line-height: base(1); } @include small-break { font-size: 16px; - line-height: rem(.8) + line-height: base(.8) } } @@ -75,7 +75,7 @@ h5 { } p { - margin: 0 0 rem(.5); + margin: 0 0 base(.5); } ul { diff --git a/src/client/scss/form.scss b/src/client/scss/form.scss index 92f4de01a4..53624e5cac 100644 --- a/src/client/scss/form.scss +++ b/src/client/scss/form.scss @@ -10,10 +10,10 @@ background: white; color: $black; border-radius: 0; - font-size: rem(.55); - height: rem(1.75); - line-height: rem(1.75); - padding: 0 rem(.75); + font-size: base(.55); + height: base(1.75); + line-height: base(1.75); + padding: 0 base(.75); -webkit-appearance: none; &::-webkit-input-placeholder { /* Chrome/Opera/Safari */ @@ -43,6 +43,6 @@ } @include small-break { - margin-bottom: rem(.5); + margin-bottom: base(.5); } } diff --git a/src/client/scss/grid.scss b/src/client/scss/grid.scss index a1b453f756..5338262a24 100644 --- a/src/client/scss/grid.scss +++ b/src/client/scss/grid.scss @@ -5,7 +5,7 @@ ///////////////////////////// // Gutter -$gutter : rem(.5); +$gutter : base(.5); ///////////////////////////// // ROWS diff --git a/src/client/scss/structure.scss b/src/client/scss/structure.scss index 5c1fc1c1c5..a21b615951 100644 --- a/src/client/scss/structure.scss +++ b/src/client/scss/structure.scss @@ -8,8 +8,8 @@ @mixin default-template-width { padding-left: $base; padding-right: $base; - margin-left: rem(6); - width: calc(100% - #{rem(6)}); + margin-left: base(6); + width: calc(100% - #{base(6)}); .wrap { max-width: $content-width; @@ -25,19 +25,19 @@ padding: $base; @include mid-break { - padding: rem(.75); + padding: base(.75); } @include small-break { - padding: rem(.5); + padding: base(.5); } } @mixin pad-x2 { - padding: rem(2) rem(2) rem(1); + padding: base(2) base(2) base(1); @include mid-break { - padding: rem(1) rem(1) 0; + padding: base(1) base(1) 0; } } @@ -49,12 +49,12 @@ padding-top: $base; @include mid-break { - padding-top: rem(.5); + padding-top: base(.5); } } @mixin pad-vert-x2 { - padding-top: rem(2); + padding-top: base(2); padding-bottom: $base; @include mid-break { @@ -64,21 +64,21 @@ } @mixin pad-vert-x3 { - padding-top: rem(3); - padding-bottom: rem(2); + padding-top: base(3); + padding-bottom: base(2); @include mid-break { - padding-top: rem(2); + padding-top: base(2); padding-bottom: $base; } } @mixin pad-vert-x4 { - padding-top: rem(4); - padding-bottom: rem(3); + padding-top: base(4); + padding-bottom: base(3); @include mid-break { - padding-top: rem(2); + padding-top: base(2); padding-bottom: $base; } } @@ -91,42 +91,42 @@ margin-bottom: $base; @include small-break { - margin-bottom: rem(.75); + margin-bottom: base(.75); } } @mixin m-x2 { - margin-bottom: rem(2); + margin-bottom: base(2); @include mid-break { margin-bottom: $base; } @include small-break { - margin-bottom: rem(.75); + margin-bottom: base(.75); } } @mixin m-x3 { - margin-bottom: rem(3); + margin-bottom: base(3); @include mid-break { - margin-bottom: rem(2); + margin-bottom: base(2); } @include small-break { - margin-bottom: rem(1); + margin-bottom: base(1); } } @mixin m-x4 { - margin-bottom: rem(4); + margin-bottom: base(4); @include mid-break { - margin-bottom: rem(3); + margin-bottom: base(3); } @include small-break { - margin-bottom: rem(2); + margin-bottom: base(2); } } diff --git a/src/client/scss/type.scss b/src/client/scss/type.scss index 933a159f94..7df365a2a2 100644 --- a/src/client/scss/type.scss +++ b/src/client/scss/type.scss @@ -12,63 +12,63 @@ } %jumbo { - font-size: rem(2.5); + font-size: base(2.5); line-height: 1; - margin: 0 0 rem(2); + margin: 0 0 base(2); } %h1 { - margin: 0 0 rem(1); - font-size: rem(1); - line-height: rem(1); + margin: 0 0 base(1); + font-size: base(1); + line-height: base(1); @include small-break { - letter-spacing: rem(0); - font-size: rem(1.25); - line-height: rem(1.25); + letter-spacing: base(0); + font-size: base(1.25); + line-height: base(1.25); } } %h2 { - margin: 0 0 rem(1); - font-size: rem(.7); - line-height: rem(.75); + margin: 0 0 base(1); + font-size: base(.7); + line-height: base(.75); letter-spacing: 0; @include small-break { - font-size: rem(.85); - line-height: rem(.85); + font-size: base(.85); + line-height: base(.85); } } %h3 { - margin: 0 0 rem(1); - font-size: rem(1); + margin: 0 0 base(1); + font-size: base(1); line-height: 1.25; font-weight: 500; @include small-break { - font-size: rem(.65); - line-height: rem(.75); + font-size: base(.65); + line-height: base(.75); } } %h4 { margin: 0 0 $base; - font-size: rem(.75); + font-size: base(.75); line-height: 1.5; } %h5 { margin: 0; - font-size: rem(.5); + font-size: base(.5); line-height: 1.5; font-weight: 700; } %small { margin: 0; - font-size: rem(.4); + font-size: base(.4); line-height: 1.5; } @@ -78,35 +78,35 @@ %uppercase-label { text-transform: uppercase; - letter-spacing: rem(.1); - font-size: rem(.3); + letter-spacing: base(.1); + font-size: base(.3); font-family: $font-label; -webkit-font-smoothing: auto; @include mid-break { - font-size: rem(.31); - letter-spacing: rem(.05); + font-size: base(.31); + letter-spacing: base(.05); } } %large-body { - font-size: rem(.6); - line-height: rem(1); - letter-spacing: rem(.02); + font-size: base(.6); + line-height: base(1); + letter-spacing: base(.02); @include mid-break { - font-size: rem(.7); - line-height: rem(1); + font-size: base(.7); + line-height: base(1); } @include small-break { - font-size: rem(.55); - line-height: rem(.75); + font-size: base(.55); + line-height: base(.75); } } %code { - font-size: rem(.4); + font-size: base(.4); color: $gray; span { diff --git a/src/client/scss/vars.scss b/src/client/scss/vars.scss index a3c16101a3..3fb7a3fce4 100644 --- a/src/client/scss/vars.scss +++ b/src/client/scss/vars.scss @@ -18,7 +18,7 @@ $body : 18px; $base-px : 36px; $base : ($base-px / $body) + rem; // This computes to 36px in rem -@function rem($multiplier) { +@function base($multiplier) { @return ($base-px / $body) * $multiplier + rem; } diff --git a/src/client/store.js b/src/client/store.js deleted file mode 100644 index f3180b08c3..0000000000 --- a/src/client/store.js +++ /dev/null @@ -1,10 +0,0 @@ -import { createStore, combineReducers } from 'redux'; -import common from './reducers/common'; - -const reducer = combineReducers({ - common -}); - -const store = createStore(reducer); - -export default store;