Skip to content

Commit

Permalink
Merge branch 'feature/per-page' of github.com:payloadcms/payload
Browse files Browse the repository at this point in the history
  • Loading branch information
jmikrut committed Oct 12, 2021
2 parents d0259ce + 6807637 commit ef4f284
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 15 deletions.
48 changes: 48 additions & 0 deletions src/admin/components/elements/PerPage/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@import '../../../scss/styles.scss';

.per-page {
display: flex;
margin-bottom: $baseline;
margin-right: 0;
margin-left: auto;

button {
padding: base(.25) 0;
line-height: base(1);
background: transparent;
border: 0;
font-weight: 600;
cursor: pointer;

&:hover {
text-decoration: underline;
}

&:active,
&:focus {
outline: none;
}
}

span {
color: $color-gray;
}

ul {
list-style: none;
padding: 0;
text-align: left;
margin: 0;

li {
text-decoration: none;
}

a {
color: $color-gray;
&:visited, &:link, &:active {
text-decoration: none;
}
}
}
}
61 changes: 61 additions & 0 deletions src/admin/components/elements/PerPage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useEffect, useState, useCallback } from 'react';
import qs from 'qs';

import { Link } from 'react-router-dom';
import { useConfig } from '@payloadcms/config-provider';
import { usePreferences } from '../../utilities/Preferences';
import { useSearchParams } from '../../utilities/SearchParams';
import Popup from '../Popup';
import Chevron from '../../icons/Chevron';

import './index.scss';

const baseClass = 'per-page';
type Props = {
setLimit: (limit: number) => void;
limit: number;
}

const PerPage: React.FC<Props> = ({ setLimit }) => {
const { admin: { pagination: { options } } } = useConfig();

return (
<div className={baseClass}>
<Popup
horizontalAlign="center"
button={(
<div>
Per Page:
<Chevron />
</div>
)}
backgroundColor="#333333"
render={({ close }) => (
<div>
<ul>
{options.map((limitNumber, i) => (
<li
className={`${baseClass}-item`}
key={i}
>
<button
type="button"
onClick={() => {
close();
setLimit(limitNumber);
}}
>
{limitNumber}
</button>
</li>
))}
;
</ul>
</div>
)}
/>
</div>
);
};

export default PerPage;
23 changes: 20 additions & 3 deletions src/admin/components/elements/Popup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const Popup: React.FC<Props> = (props) => {
horizontalAlign = 'left',
initActive = false,
onToggleOpen,
backgroundColor,
padding,
} = props;

const buttonRef = useRef(null);
Expand Down Expand Up @@ -98,7 +100,9 @@ const Popup: React.FC<Props> = (props) => {
].filter(Boolean).join(' ');

return (
<div className={classes}>
<div
className={classes}
>
<div
ref={buttonRef}
className={`${baseClass}__wrapper`}
Expand Down Expand Up @@ -133,9 +137,22 @@ const Popup: React.FC<Props> = (props) => {
<div
className={`${baseClass}__content`}
ref={contentRef}
style={{
backgroundColor,
}}

>
<div className={`${baseClass}__wrap`}>
<div className={`${baseClass}__scroll`}>
<div
className={`${baseClass}__wrap`}
// TODO: color ::after with bg color
>

<div
className={`${baseClass}__scroll`}
style={{
padding,
}}
>
{render && render({ close: () => setActive(false) })}
{children && children}
</div>
Expand Down
4 changes: 4 additions & 0 deletions src/admin/components/elements/Popup/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { CSSProperties } from 'react';

export type Props = {
className?: string
render?: (any) => void,
Expand All @@ -10,4 +12,6 @@ export type Props = {
showOnHover?: boolean,
initActive?: boolean,
onToggleOpen?: () => void,
backgroundColor?: CSSProperties['backgroundColor'],
padding?: CSSProperties['padding'],
}
8 changes: 8 additions & 0 deletions src/admin/components/views/collections/List/Default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Props } from './types';

import './index.scss';
import ViewDescription from '../../../elements/ViewDescription';
import PerPage from '../../../elements/PerPage';

const baseClass = 'collection-list';

Expand All @@ -34,6 +35,8 @@ const DefaultList: React.FC<Props> = (props) => {
newDocumentURL,
setListControls,
setSort,
limit,
setLimit,
columns,
hasCreatePermission,
} = props;
Expand Down Expand Up @@ -114,6 +117,7 @@ const DefaultList: React.FC<Props> = (props) => {
</div>
)}
<div className={`${baseClass}__page-controls`}>

<Paginator
limit={data.limit}
totalPages={data.totalPages}
Expand All @@ -124,6 +128,10 @@ const DefaultList: React.FC<Props> = (props) => {
nextPage={data.nextPage}
numberOfNeighbors={1}
/>
<PerPage
limit={limit}
setLimit={setLimit}
/>
{data?.totalDocs > 0 && (
<div className={`${baseClass}__page-info`}>
{(data.page * data.limit) - (data.limit - 1)}
Expand Down
37 changes: 25 additions & 12 deletions src/admin/components/views/collections/List/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const ListView: React.FC<ListIndexProps> = (props) => {
},
} = props;

const { serverURL, routes: { api, admin } } = useConfig();
const { serverURL, routes: { api, admin }, admin: { pagination: { defaultLimit } } } = useConfig();
const { permissions } = useAuth();
const location = useLocation();
const { setStepNav } = useStepNav();
Expand All @@ -41,6 +41,7 @@ const ListView: React.FC<ListIndexProps> = (props) => {
const [listControls, setListControls] = useState<ListControls>({});
const [columns, setColumns] = useState([]);
const [sort, setSort] = useState(null);
const [limit, setLimit] = useState(defaultLimit);

const collectionPermissions = permissions?.collections?.[slug];
const hasCreatePermission = collectionPermissions?.create?.permission;
Expand All @@ -54,19 +55,29 @@ const ListView: React.FC<ListIndexProps> = (props) => {
const { columns: listControlsColumns } = listControls;

useEffect(() => {
const params = {
depth: 1,
page: undefined,
sort: undefined,
where: undefined,
};
const perPagePrefKey = `${collection.slug}-per-page`;

if (page) params.page = page;
if (sort) params.sort = sort;
if (listControls?.where) params.where = listControls.where;
(async () => {
const currentLimit = await getPreference<number>(perPagePrefKey) || defaultLimit;
setLimit(currentLimit);

const params = {
depth: 1,
page: undefined,
sort: undefined,
where: undefined,
limit,
};

setParams(params);
}, [setParams, page, sort, listControls]);
if (page) params.page = page;
if (sort) params.sort = sort;
if (limit && limit !== defaultLimit) params.limit = limit;
if (listControls?.where) params.where = listControls.where;

console.log(params);
setParams(params);
})();
}, [setParams, page, sort, listControls, collection, defaultLimit, getPreference, limit]);

useEffect(() => {
setStepNav([
Expand Down Expand Up @@ -96,6 +107,8 @@ const ListView: React.FC<ListIndexProps> = (props) => {
listControls,
data,
columns,
setLimit,
limit,
}}
/>
);
Expand Down
2 changes: 2 additions & 0 deletions src/admin/components/views/collections/List/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export type Props = {
setSort: (sort: string) => void
columns: Column[]
hasCreatePermission: boolean
setLimit: (limit: number) => void
limit: number
}

export type ListIndexProps = {
Expand Down
80 changes: 80 additions & 0 deletions src/config/generateTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* eslint-disable no-nested-ternary */
/* eslint-disable no-use-before-define */
import { compile } from 'json-schema-to-typescript';
// import fse from 'fs-extra';
import { CollectionConfig, SanitizedCollectionConfig } from '../collections/config/types';
import { SanitizedConfig } from './types';

export function generateTypes(sanitizedConfig: SanitizedConfig): void {
console.log('compiling ts types');
const jsonSchema = configToJsonSchema(sanitizedConfig.collections);

compile(jsonSchema, 'Config', {
bannerComment: '// auto-generated by payload',
unreachableDefinitions: true,
}).then((compiled) => {
// fse.writeFileSync('generated-types.ts', compiled);
console.log('compiled', compiled);
});
}

function collectionToJsonSchema(
collection: CollectionConfig,
slugToLabel: Record<string, string>,
): any {
return {
title: collection.labels.singular,
type: 'object',
properties: Object.fromEntries(
collection.fields.map((field) => {
const type = field.type === 'number'
? { type: 'integer' }
: field.type === 'relationship'
? {
$ref: `#/definitions/${slugToLabel[field.relationTo as string]}`,
}
: { type: 'string' };
const enum_ = field.type === 'select' ? { enum: field.options } : {};
const default_ = field.defaultValue ? { default: field.defaultValue } : {};

return [
field.name,
{
...type,
...enum_,
...default_,
},
];
}),
),
required: collection.fields
.filter((field) => field.required === true)
.map((field) => field.name),
additionalProperties: false,
};
}

function configToJsonSchema(collections: SanitizedCollectionConfig[]): any {
const slugToLabel = Object.fromEntries(
collections.map((collection) => [
collection.slug,
collection.labels.singular,
]),
);
return {
definitions: Object.fromEntries(
collections.map((collection) => [
collection.labels.singular,
collectionToJsonSchema(collection, slugToLabel),
]),
),
additionalProperties: false,
};
}

// const result = await compile(jsonSchema, 'Config', {
// bannerComment: '// auto-generated by payload',
// unreachableDefinitions: true,
// });

// await fse.writeFile('generated-types.ts', result);
5 changes: 5 additions & 0 deletions src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export default joi.object({
Logo: component,
}),
}),
pagination: joi.object()
.keys({
defaultLimit: joi.number(),
options: joi.array().items(joi.number()),
}),
webpack: joi.func(),
}),
defaultDepth: joi.number()
Expand Down
4 changes: 4 additions & 0 deletions src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ export type Config = {
Dashboard?: React.ComponentType
}
}
pagination?: {
defaultLimit?: number;
options?: number[];
}
webpack?: (config: Configuration) => Configuration;
};
collections?: CollectionConfig[];
Expand Down

0 comments on commit ef4f284

Please sign in to comment.