revises APIError import structure, updates Localizer and StepNav
This commit is contained in:
@@ -24,6 +24,13 @@ module.exports = {
|
||||
"aspects": ["invalidHref", "preferButton"]
|
||||
}],
|
||||
"jsx-a11y/click-events-have-key-events": 0,
|
||||
"jsx-a11y/label-has-for": [2, {
|
||||
"components": ["Label"],
|
||||
"required": {
|
||||
"every": ["id"]
|
||||
},
|
||||
"allowChildren": false
|
||||
}],
|
||||
"react/no-array-index-key": 0,
|
||||
"max-len": 0,
|
||||
"react/no-danger": 0,
|
||||
|
||||
@@ -8,6 +8,7 @@ module.exports = {
|
||||
},
|
||||
useAsTitle: 'email',
|
||||
useAsUsername: 'email',
|
||||
passwordIndex: 1,
|
||||
policies: {
|
||||
create: (req, res, next) => {
|
||||
return next();
|
||||
|
||||
@@ -21,18 +21,20 @@ const requests = {
|
||||
post: (url, body) =>
|
||||
fetch(`${url}`, {
|
||||
method: 'post',
|
||||
body,
|
||||
body: JSON.stringify(body),
|
||||
headers: {
|
||||
...setJWT()
|
||||
...setJWT(),
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}),
|
||||
|
||||
put: (url, body) =>
|
||||
fetch(`${url}`, {
|
||||
method: 'put',
|
||||
body,
|
||||
body: JSON.stringify(body),
|
||||
headers: {
|
||||
...setJWT()
|
||||
...setJWT(),
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, Fragment } from 'react';
|
||||
import Cookies from 'universal-cookie';
|
||||
import {
|
||||
Route, Switch, withRouter, Redirect,
|
||||
@@ -56,67 +56,71 @@ const Routes = () => {
|
||||
if (cookies.get('token')) {
|
||||
return (
|
||||
<DefaultTemplate>
|
||||
<Route
|
||||
path={`${match.url}/media-library`}
|
||||
component={MediaLibrary}
|
||||
/>
|
||||
<Route
|
||||
path={`${match.url}/create-user`}
|
||||
component={CreateUser}
|
||||
/>
|
||||
<Route
|
||||
path={`${match.url}/`}
|
||||
exact
|
||||
component={Dashboard}
|
||||
/>
|
||||
<Switch>
|
||||
<Route
|
||||
path={`${match.url}/media-library`}
|
||||
component={MediaLibrary}
|
||||
/>
|
||||
<Route
|
||||
path={`${match.url}/create-user`}
|
||||
component={CreateUser}
|
||||
/>
|
||||
<Route
|
||||
path={`${match.url}/`}
|
||||
exact
|
||||
component={Dashboard}
|
||||
/>
|
||||
|
||||
{config.collections.map((collection) => {
|
||||
const components = collection.components ? collection.components : {};
|
||||
return (
|
||||
<Switch key={collection.slug}>
|
||||
<Route
|
||||
path={`${match.url}/collections/${collection.slug}/create`}
|
||||
exact
|
||||
render={(routeProps) => {
|
||||
return (
|
||||
<Edit
|
||||
{...routeProps}
|
||||
collection={collection}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{config.collections.map((collection) => {
|
||||
const components = collection.components ? collection.components : {};
|
||||
return (
|
||||
<Fragment key={collection.slug}>
|
||||
<Route
|
||||
path={`${match.url}/collections/${collection.slug}/create`}
|
||||
exact
|
||||
render={(routeProps) => {
|
||||
return (
|
||||
<Edit
|
||||
{...routeProps}
|
||||
collection={collection}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path={`${match.url}/collections/${collection.slug}/:id`}
|
||||
exact
|
||||
render={(routeProps) => {
|
||||
return (
|
||||
<Edit
|
||||
{...routeProps}
|
||||
collection={collection}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
path={`${match.url}/collections/${collection.slug}/:id`}
|
||||
exact
|
||||
render={(routeProps) => {
|
||||
return (
|
||||
<Edit
|
||||
{...routeProps}
|
||||
collection={collection}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path={`${match.url}/collections/${collection.slug}`}
|
||||
exact
|
||||
render={(routeProps) => {
|
||||
const ListComponent = components.List ? components.List : List;
|
||||
return (
|
||||
<ListComponent
|
||||
{...routeProps}
|
||||
collection={collection}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
||||
</Switch>
|
||||
);
|
||||
})}
|
||||
<Route
|
||||
path={`${match.url}/collections/${collection.slug}`}
|
||||
exact
|
||||
render={(routeProps) => {
|
||||
const ListComponent = components.List ? components.List : List;
|
||||
return (
|
||||
<ListComponent
|
||||
{...routeProps}
|
||||
collection={collection}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
<Route>
|
||||
<h1>Not Found</h1>
|
||||
</Route>
|
||||
</Switch>
|
||||
</DefaultTemplate>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ const Form = (props) => {
|
||||
|
||||
setProcessing(true);
|
||||
|
||||
console.log(data);
|
||||
|
||||
// Make the API call from the action
|
||||
api.requests[method.toLowerCase()](action, data).then(
|
||||
(res) => {
|
||||
|
||||
@@ -1,117 +1,163 @@
|
||||
import React, { Component } from 'react';
|
||||
import FormContext from '../../Form/Context'
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import FormContext from '../../Form/Context';
|
||||
import Tooltip from '../../../modules/Tooltip';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const fieldType = (PassedComponent, type, validate, errors) => {
|
||||
const baseClass = 'field-type';
|
||||
|
||||
class FieldType extends Component {
|
||||
const asFieldType = (PassedComponent, type, validate, errors) => {
|
||||
const FieldType = (props) => {
|
||||
const formContext = useContext(FormContext);
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const {
|
||||
name,
|
||||
id,
|
||||
value,
|
||||
required,
|
||||
initialValue,
|
||||
valueOverride,
|
||||
onChange,
|
||||
} = props;
|
||||
|
||||
this.state = {
|
||||
init: false
|
||||
};
|
||||
}
|
||||
|
||||
sendField(value) {
|
||||
this.props.context.setValue({
|
||||
name: this.props.name,
|
||||
value: value,
|
||||
valid: this.props.required && validate
|
||||
? validate(value || '', this.props.type)
|
||||
: true
|
||||
const sendField = (valueToSend) => {
|
||||
formContext.setValue({
|
||||
name,
|
||||
value: valueToSend,
|
||||
valid: required && validate
|
||||
? validate(valueToSend || '', type)
|
||||
: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
let value = this.props.value ? this.props.value : '';
|
||||
value = this.props.initialValue ? this.props.initialValue : value;
|
||||
value = this.props.valueOverride ? this.props.valueOverride : value;
|
||||
this.sendField(value);
|
||||
useEffect(() => {
|
||||
let valueToInitialize = value;
|
||||
if (initialValue) valueToInitialize = initialValue;
|
||||
if (valueOverride) valueToInitialize = valueOverride;
|
||||
sendField(valueToInitialize);
|
||||
}, []);
|
||||
|
||||
this.setState({
|
||||
init: true
|
||||
});
|
||||
}
|
||||
useEffect(() => {
|
||||
sendField(valueOverride);
|
||||
}, [valueOverride]);
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.valueOverride !== this.props.valueOverride) {
|
||||
this.sendField(this.props.valueOverride);
|
||||
}
|
||||
useEffect(() => {
|
||||
sendField(initialValue);
|
||||
}, [initialValue]);
|
||||
|
||||
if (prevProps.initialValue !== this.props.initialValue) {
|
||||
this.sendField(this.props.initialValue);
|
||||
}
|
||||
}
|
||||
const classList = [baseClass, type];
|
||||
const valid = formContext.fields[name] ? formContext.fields[name].valid : true;
|
||||
const showError = valid === false && formContext.submitted;
|
||||
|
||||
render() {
|
||||
const valid = this.props.context.fields[this.props.name]
|
||||
? this.props.context.fields[this.props.name].valid
|
||||
: true;
|
||||
if (showError) classList.push('error');
|
||||
|
||||
const showError = valid === false && this.props.context.submitted;
|
||||
let valueToRender = formContext.fields[name] ? formContext.fields[name].value : '';
|
||||
|
||||
let className = `field-type ${type}${showError ? ' error' : ''}`;
|
||||
// If valueOverride present, field is being controlled by state outside form
|
||||
valueToRender = valueOverride || value;
|
||||
|
||||
let value = this.props.context.fields[this.props.name] ? this.props.context.fields[this.props.name].value : '';
|
||||
const classes = classList.filter(Boolean).join(' ');
|
||||
|
||||
// If valueOverride present, field is being controlled by state outside form
|
||||
value = this.props.valueOverride ? this.props.valueOverride : value;
|
||||
|
||||
return (
|
||||
<PassedComponent {...this.props}
|
||||
className={className}
|
||||
value={value}
|
||||
label={<Label {...this.props} />}
|
||||
error={<Error showError={showError} type={this.props.type} />}
|
||||
onChange={e => {
|
||||
this.sendField(e.target.value);
|
||||
this.props.onChange && this.props.onChange(e);
|
||||
}} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Label = props => {
|
||||
if (props.label) {
|
||||
return (
|
||||
<label htmlFor={props.id ? props.id : props.name}>
|
||||
{props.label}
|
||||
{props.required &&
|
||||
<span className="required">*</span>
|
||||
}
|
||||
</label>
|
||||
)
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const Error = props => {
|
||||
if (props.showError) {
|
||||
return (
|
||||
<Tooltip className="error-message">
|
||||
{props.error && errors[props.error]}
|
||||
|
||||
{!props.error && errors}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const FieldTypeWithContext = props => {
|
||||
return (
|
||||
<FormContext.Consumer>
|
||||
{context => <FieldType {...props} context={context} />}
|
||||
</FormContext.Consumer>
|
||||
<PassedComponent
|
||||
{...props}
|
||||
className={classes}
|
||||
value={valueToRender}
|
||||
label={(
|
||||
<Label
|
||||
htmlFor={id || name}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
error={(
|
||||
<Error
|
||||
showError={showError}
|
||||
type={type}
|
||||
/>
|
||||
)}
|
||||
onChange={(e) => {
|
||||
sendField(e.target.value);
|
||||
if (onChange && typeof onChange === 'function') onChange(e);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return FieldTypeWithContext;
|
||||
}
|
||||
FieldType.defaultProps = {
|
||||
value: '',
|
||||
required: false,
|
||||
initialValue: '',
|
||||
valueOverride: '',
|
||||
onChange: null,
|
||||
id: '',
|
||||
};
|
||||
|
||||
export default fieldType;
|
||||
FieldType.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.string,
|
||||
required: PropTypes.bool,
|
||||
type: PropTypes.string.isRequired,
|
||||
initialValue: PropTypes.string,
|
||||
valueOverride: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
id: PropTypes.string,
|
||||
};
|
||||
|
||||
const Label = (props) => {
|
||||
const {
|
||||
label, required, htmlFor,
|
||||
} = props;
|
||||
|
||||
if (label) {
|
||||
return (
|
||||
<label htmlFor={htmlFor}>
|
||||
{label}
|
||||
{required
|
||||
&& <span className="required">*</span>
|
||||
}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
Label.defaultProps = {
|
||||
required: false,
|
||||
};
|
||||
|
||||
Label.propTypes = {
|
||||
label: PropTypes.string.isRequired,
|
||||
htmlFor: PropTypes.string.isRequired,
|
||||
required: PropTypes.bool,
|
||||
};
|
||||
|
||||
const Error = (props) => {
|
||||
const { error, showError } = props;
|
||||
|
||||
if (showError) {
|
||||
return (
|
||||
<Tooltip className="error-message">
|
||||
{error && errors[error]}
|
||||
{!error && errors}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
Error.defaultProps = {
|
||||
showError: false,
|
||||
};
|
||||
|
||||
Error.propTypes = {
|
||||
error: PropTypes.string.isRequired,
|
||||
showError: PropTypes.bool,
|
||||
};
|
||||
|
||||
return FieldType;
|
||||
};
|
||||
|
||||
export default asFieldType;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Sidebar from '../Sidebar';
|
||||
import StepNav from '../../modules/StepNav';
|
||||
import StepNav, { StepNavProvider } from '../../modules/StepNav';
|
||||
import Localizer from '../../modules/Localizer';
|
||||
|
||||
import './index.scss';
|
||||
@@ -9,15 +10,24 @@ const DefaultTemplate = ({ children }) => {
|
||||
return (
|
||||
<div className="default-template">
|
||||
<div className="wrap">
|
||||
<Sidebar />
|
||||
<div className="eyebrow">
|
||||
<StepNav />
|
||||
<Localizer />
|
||||
</div>
|
||||
{children}
|
||||
<StepNavProvider>
|
||||
<Sidebar />
|
||||
<div className="eyebrow">
|
||||
<StepNav />
|
||||
<Localizer />
|
||||
</div>
|
||||
{children}
|
||||
</StepNavProvider>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
DefaultTemplate.propTypes = {
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
PropTypes.node,
|
||||
]).isRequired,
|
||||
};
|
||||
|
||||
export default DefaultTemplate;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { withRouter, NavLink, Link } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import { useLocation, NavLink, Link } from 'react-router-dom';
|
||||
import config from 'payload-config';
|
||||
|
||||
import Arrow from '../../graphics/Arrow';
|
||||
@@ -8,11 +7,7 @@ import Icon from '../../graphics/Icon';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const mapState = state => ({
|
||||
config: state.common.config,
|
||||
});
|
||||
|
||||
const Sidebar = (props) => {
|
||||
const Sidebar = () => {
|
||||
const {
|
||||
collections,
|
||||
globals,
|
||||
@@ -21,6 +16,8 @@ const Sidebar = (props) => {
|
||||
},
|
||||
} = config;
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
return (
|
||||
<aside className="sidebar">
|
||||
<Link to="/">
|
||||
@@ -37,7 +34,7 @@ const Sidebar = (props) => {
|
||||
</NavLink>
|
||||
{collections && Object.keys(collections).map((key, i) => {
|
||||
const href = `${admin}/collections/${collections[key].slug}`;
|
||||
const classes = props.location.pathname.indexOf(href) > -1
|
||||
const classes = location.pathname.indexOf(href) > -1
|
||||
? 'active'
|
||||
: undefined;
|
||||
|
||||
@@ -57,7 +54,7 @@ const Sidebar = (props) => {
|
||||
<nav>
|
||||
{globals && globals.map((global, i) => {
|
||||
const href = `${admin}/globals/${global.slug}`;
|
||||
const classes = props.location.pathname.indexOf(href) > -1
|
||||
const classes = location.pathname.indexOf(href) > -1
|
||||
? 'active'
|
||||
: undefined;
|
||||
|
||||
@@ -77,4 +74,4 @@ const Sidebar = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withRouter(connect(mapState)(Sidebar));
|
||||
export default Sidebar;
|
||||
|
||||
@@ -1,66 +1,64 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Link, withRouter } from 'react-router-dom';
|
||||
import Arrow from '../../graphics/Arrow';
|
||||
import React, { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import config from 'payload-config';
|
||||
import qs from 'qs';
|
||||
import { useLocale } from '../../utilities/Locale';
|
||||
import { useSearchParams } from '../../utilities/SearchParams';
|
||||
import Arrow from '../../graphics/Arrow';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const mapState = state => ({
|
||||
config: state.common.config,
|
||||
locale: state.common.locale,
|
||||
searchParams: state.common.searchParams
|
||||
})
|
||||
const baseClass = 'localizer';
|
||||
|
||||
class Localizer extends Component {
|
||||
const Localizer = () => {
|
||||
const [active, setActive] = useState(false);
|
||||
const activeLocale = useLocale();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const { locales } = config.localization ? config.localization : { locales: [] };
|
||||
|
||||
this.state = {
|
||||
active: false
|
||||
}
|
||||
}
|
||||
if (locales.length <= 1) return null;
|
||||
|
||||
toggleActive = () =>
|
||||
this.setState({ active: !this.state.active })
|
||||
const classes = [
|
||||
baseClass,
|
||||
active && `${baseClass}--active`,
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
render() {
|
||||
let locales = [];
|
||||
return (
|
||||
<div className={classes}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActive(!active)}
|
||||
className={`${baseClass}__current`}
|
||||
>
|
||||
<Arrow />
|
||||
{activeLocale}
|
||||
</button>
|
||||
<ul>
|
||||
{locales.map((locale, i) => {
|
||||
if (activeLocale === locale) return null;
|
||||
|
||||
if (this.props.config && this.props.config.localization) locales = this.props.config.localization.locales;
|
||||
const newParams = {
|
||||
...searchParams,
|
||||
locale,
|
||||
};
|
||||
|
||||
if (locales.length <= 1) return null;
|
||||
const search = qs.stringify(newParams);
|
||||
|
||||
return (
|
||||
<div className={`localizer${this.state.active ? ' active' : ''}`}>
|
||||
<button onClick={this.toggleActive} className="current-locale">
|
||||
<Arrow />{this.props.locale}
|
||||
</button>
|
||||
<ul>
|
||||
{locales.map((locale, i) => {
|
||||
return (
|
||||
<li key={i}>
|
||||
<Link
|
||||
to={{ search }}
|
||||
onClick={() => setActive(false)}
|
||||
>
|
||||
{locale}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
if (locale === this.props.locale) return null;
|
||||
|
||||
const newParams = {
|
||||
...this.props.searchParams,
|
||||
locale
|
||||
};
|
||||
|
||||
const search = qs.stringify(newParams);
|
||||
|
||||
return (
|
||||
<li key={i}>
|
||||
<Link to={{ search }} onClick={this.toggleActive}>
|
||||
{locale}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(connect(mapState)(Localizer));
|
||||
export default Localizer;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.localizer {
|
||||
position: relative;
|
||||
|
||||
.current-locale {
|
||||
&__current {
|
||||
@extend %uppercase-label;
|
||||
@extend %btn-reset;
|
||||
display: flex;
|
||||
@@ -43,7 +43,7 @@
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&.active {
|
||||
&--active {
|
||||
svg {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
@@ -72,8 +72,7 @@ const StatusList = () => {
|
||||
|
||||
export {
|
||||
StatusListProvider,
|
||||
StatusList,
|
||||
useStatusList,
|
||||
};
|
||||
|
||||
export default Context;
|
||||
export default StatusList;
|
||||
|
||||
@@ -1,36 +1,74 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import React, { useState, createContext, useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link } from 'react-router-dom';
|
||||
import Arrow from '../../graphics/Arrow';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
nav: state.common.stepNav
|
||||
});
|
||||
const Context = createContext({});
|
||||
|
||||
class StepNav extends Component {
|
||||
render() {
|
||||
const dashboardLabel = <span>Dashboard</span>;
|
||||
const StepNavProvider = ({ children }) => {
|
||||
const [nav, setNav] = useState([]);
|
||||
|
||||
return (
|
||||
<nav className="step-nav">
|
||||
{this.props.nav.length > 0
|
||||
? <Link to="/">{dashboardLabel}<Arrow /></Link>
|
||||
: dashboardLabel
|
||||
}
|
||||
{this.props.nav.map((item, i) => {
|
||||
const StepLabel = <span key={i}>{item.label}</span>;
|
||||
return (
|
||||
<Context.Provider value={{
|
||||
nav,
|
||||
setNav,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Context.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const Step = this.props.nav.length === i + 1
|
||||
? StepLabel
|
||||
: <Link to={item.url} key={i}>{StepLabel}<Arrow /></Link>;
|
||||
StepNavProvider.propTypes = {
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
PropTypes.node,
|
||||
]).isRequired,
|
||||
};
|
||||
|
||||
return Step;
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
}
|
||||
const useStepNav = () => useContext(Context);
|
||||
|
||||
export default connect(mapStateToProps)(StepNav);
|
||||
const StepNav = () => {
|
||||
const dashboardLabel = <span>Dashboard</span>;
|
||||
const { nav } = useStepNav();
|
||||
|
||||
return (
|
||||
<nav className="step-nav">
|
||||
{nav.length > 0
|
||||
? (
|
||||
<Link to="/">
|
||||
{dashboardLabel}
|
||||
<Arrow />
|
||||
</Link>
|
||||
)
|
||||
: dashboardLabel
|
||||
}
|
||||
{nav.map((item, i) => {
|
||||
const StepLabel = <span key={i}>{item.label}</span>;
|
||||
|
||||
const Step = nav.length === i + 1
|
||||
? StepLabel
|
||||
: (
|
||||
<Link
|
||||
to={item.url}
|
||||
key={i}
|
||||
>
|
||||
{StepLabel}
|
||||
<Arrow />
|
||||
</Link>
|
||||
);
|
||||
|
||||
return Step;
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export {
|
||||
StepNavProvider,
|
||||
useStepNav,
|
||||
};
|
||||
|
||||
export default StepNav;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import config from 'payload-config';
|
||||
import PropTypes from 'prop-types';
|
||||
import searchParamsContext from '../SearchParams';
|
||||
import { useSearchParams } from '../SearchParams';
|
||||
|
||||
const Context = createContext({});
|
||||
|
||||
export const LocaleProvider = ({ children }) => {
|
||||
const searchParams = useContext(searchParamsContext);
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
let activeLocale = null;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { createContext } from 'react';
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import qs from 'qs';
|
||||
@@ -27,4 +27,4 @@ SearchParamsProvider.propTypes = {
|
||||
]).isRequired,
|
||||
};
|
||||
|
||||
export default Context;
|
||||
export const useSearchParams = () => useContext(Context);
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
set: nav => dispatch({ type: 'SET_STEP_NAV', payload: nav })
|
||||
});
|
||||
|
||||
class SetStepNav extends Component {
|
||||
componentDidMount() {
|
||||
this.props.set(this.props.nav);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.nav !== this.props.nav) {
|
||||
this.props.set(this.props.nav);
|
||||
}
|
||||
}
|
||||
|
||||
render() { return null; }
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)(SetStepNav);
|
||||
@@ -14,9 +14,23 @@ const handleAjaxResponse = (res) => {
|
||||
cookies.set('token', res.token, { path: '/' });
|
||||
};
|
||||
|
||||
const passwordField = {
|
||||
name: 'password',
|
||||
label: 'Password',
|
||||
type: 'password',
|
||||
};
|
||||
|
||||
const baseClass = 'create-first-user';
|
||||
|
||||
const CreateFirstUser = () => {
|
||||
const fields = [...config.user.fields];
|
||||
|
||||
if (config.user.passwordIndex) {
|
||||
fields.splice(config.user.passwordIndex, 0, passwordField);
|
||||
} else {
|
||||
fields.push(passwordField);
|
||||
}
|
||||
|
||||
return (
|
||||
<ContentBlock className={baseClass}>
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
@@ -25,9 +39,9 @@ const CreateFirstUser = () => {
|
||||
<Form
|
||||
handleAjaxResponse={handleAjaxResponse}
|
||||
method="POST"
|
||||
action="/first-user"
|
||||
action="/first-register"
|
||||
>
|
||||
<RenderFields fields={config.user.fields} />
|
||||
<RenderFields fields={fields} />
|
||||
<FormSubmit>Create</FormSubmit>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@ class ExtendableError extends Error {
|
||||
* Class representing an API error.
|
||||
* @extends ExtendableError
|
||||
*/
|
||||
export class APIError extends ExtendableError {
|
||||
class APIError extends ExtendableError {
|
||||
/**
|
||||
* Creates an API error.
|
||||
* @param {string} message - Error message.
|
||||
@@ -30,3 +30,5 @@ export class APIError extends ExtendableError {
|
||||
super(message, status, isPublic);
|
||||
}
|
||||
}
|
||||
|
||||
export default APIError;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { APIError } from './APIError';
|
||||
import APIError from './APIError';
|
||||
|
||||
export class DuplicateCollection extends APIError {
|
||||
constructor(config) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { APIError } from './APIError';
|
||||
import APIError from './APIError';
|
||||
|
||||
export class DuplicateGlobal extends APIError {
|
||||
constructor(config) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { APIError } from './APIError';
|
||||
import APIError from './APIError';
|
||||
|
||||
export class MissingCollectionLabel extends APIError {
|
||||
constructor(config) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { APIError } from './APIError';
|
||||
import APIError from './APIError';
|
||||
|
||||
export class MissingGlobalLabel extends APIError {
|
||||
constructor(config) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import httpStatus from 'http-status';
|
||||
import { APIError } from './APIError';
|
||||
import APIError from './APIError';
|
||||
|
||||
export class NotFound extends APIError {
|
||||
constructor() {
|
||||
|
||||
Reference in New Issue
Block a user