improves pattern for custom List component

This commit is contained in:
James
2020-05-19 18:55:04 -04:00
parent f0d5178cf2
commit 2c0954bb1b
6 changed files with 149 additions and 26 deletions

View File

@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import {
Route, Switch, withRouter, Redirect,
} from 'react-router-dom';
import DefaultList from './views/collections/List';
import List from './views/collections/List';
import { useUser } from './data/User';
import DefaultTemplate from './templates/Default';
import Dashboard from './views/Dashboard';
@@ -14,7 +14,6 @@ import CreateFirstUser from './views/CreateFirstUser';
import Edit from './views/collections/Edit';
import EditGlobal from './views/Global';
import { requests } from '../api';
import customComponents from './customComponents';
import ResetPassword from './views/ResetPassword';
import Unauthorized from './views/Unauthorized';
import Account from './views/Account';
@@ -94,7 +93,6 @@ const Routes = () => {
path={`${match.url}/collections/${collection.slug}`}
exact
render={(routeProps) => {
const List = customComponents[collection.slug]?.views?.List || DefaultList;
return (
<List
{...routeProps}

View File

@@ -2,6 +2,7 @@ import React from 'react';
import { NavLink, Link } from 'react-router-dom';
import { useUser } from '../../data/User';
import Chevron from '../../icons/Chevron';
import LogOut from '../../icons/LogOut';
import Icon from '../../graphics/Icon';
import Account from '../../graphics/Account';
import Localizer from '../Localizer';
@@ -74,14 +75,17 @@ const Sidebar = () => {
</nav>
<div className={`${baseClass}__controls`}>
<Localizer />
<Link to={`${admin}/account`}>
<Link
to={`${admin}/account`}
className={`${baseClass}__account`}
>
<Account />
</Link>
<Link
to={`${admin}/logout`}
className="log-out"
className={`${baseClass}__log-out`}
>
Log out
<LogOut />
</Link>
</div>
</div>

View File

@@ -35,6 +35,14 @@
}
}
&__log-out {
&:hover {
g {
transform: translateX(- #{base(.125)});
}
}
}
a {
padding: base(.125) 0;
display: flex;

View File

@@ -0,0 +1,36 @@
import React from 'react';
const LogOut = () => {
return (
<svg
width="25"
height="25"
viewBox="0 0 25 25"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10 5H18V19H10"
stroke="#333333"
strokeWidth="2"
/>
<g>
<path
d="M8 8.5L4.46447 12.0355L8 15.5711"
stroke="#333333"
strokeWidth="2"
/>
<line
x1="5"
y1="12"
x2="13"
y2="12"
stroke="#333333"
strokeWidth="2"
/>
</g>
</svg>
);
};
export default LogOut;

View File

@@ -0,0 +1,37 @@
import React from 'react';
const Menu = () => {
return (
<svg
width="25"
height="25"
viewBox="0 0 25 25"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect
x="3.5"
y="4.5"
width="18"
height="2"
fill="#333333"
/>
<rect
x="3.5"
y="11.5"
width="18"
height="2"
fill="#333333"
/>
<rect
x="3.5"
y="18.5"
width="18"
height="2"
fill="#333333"
/>
</svg>
);
};
export default Menu;

View File

@@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
import { Link, useLocation } from 'react-router-dom';
import queryString from 'qs';
import PropTypes from 'prop-types';
import customComponents from '../../../customComponents';
import { useStepNav } from '../../../elements/StepNav';
import usePayloadAPI from '../../../../hooks/usePayloadAPI';
import Paginator from '../../../elements/Paginator';
@@ -10,26 +11,8 @@ import './index.scss';
const { serverURL, routes: { api, admin } } = PAYLOAD_CONFIG;
const ListView = (props) => {
const { collection } = props;
const location = useLocation();
const { setStepNav } = useStepNav();
const { page } = queryString.parse(location.search, { ignoreQueryPrefix: true });
const apiURL = [
`${serverURL}${api}/${collection.slug}`,
page && `?page=${page}&`,
].filter(Boolean).join('');
const [{ data }] = usePayloadAPI(apiURL);
useEffect(() => {
setStepNav([
{
label: collection.labels.plural,
},
]);
}, [setStepNav, collection.labels.plural]);
const DefaultList = (props) => {
const { collection, data } = props;
return (
<div className="collection-list">
@@ -61,6 +44,63 @@ const ListView = (props) => {
);
};
DefaultList.defaultProps = {
data: undefined,
};
DefaultList.propTypes = {
collection: PropTypes.shape({
labels: PropTypes.shape({
plural: PropTypes.string,
}),
slug: PropTypes.string,
}).isRequired,
data: PropTypes.shape({
docs: PropTypes.arrayOf(
PropTypes.shape({}),
),
totalDocs: PropTypes.number,
prevPage: PropTypes.number,
nextPage: PropTypes.number,
hasNextPage: PropTypes.bool,
hasPrevPage: PropTypes.bool,
limit: PropTypes.number,
page: PropTypes.number,
totalPages: PropTypes.number,
}),
};
const ListView = (props) => {
const { collection } = props;
const location = useLocation();
const { setStepNav } = useStepNav();
const { page } = queryString.parse(location.search, { ignoreQueryPrefix: true });
const apiURL = [
`${serverURL}${api}/${collection.slug}`,
page && `?page=${page}&`,
].filter(Boolean).join('');
const [{ data }] = usePayloadAPI(apiURL);
useEffect(() => {
setStepNav([
{
label: collection.labels.plural,
},
]);
}, [setStepNav, collection.labels.plural]);
const List = customComponents?.[collection.slug]?.views?.List || DefaultList;
return (
<List
data={data}
collection={collection}
/>
);
};
ListView.propTypes = {
collection: PropTypes.shape({
labels: PropTypes.shape({