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 (
+
+ );
+};
- return (
-
- );
- }
-}
+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 (
- {props.status.map((status, i) => {
+ {statusList.map((status, i) => {
return (
- -
+
-
{status.message}
-
- )
+ );
})}
- )
+ );
}
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 (