simplify the Table component, the UsersPage shows some basic data

This commit is contained in:
Dawid Wysokiński 2021-03-11 20:29:56 +01:00
parent 987a7b46f6
commit 970d962ca5
10 changed files with 100 additions and 44 deletions

View File

@ -6,7 +6,6 @@ import {
Table as MUITable,
TableBody,
TableProps as MUITableProps,
TableBodyProps,
TableContainer,
} from '@material-ui/core';
import TableHead from './TableHead';
@ -23,18 +22,15 @@ export interface TableProps<T> {
orderDirection?: OrderDirection;
selection?: boolean;
idFieldName?: string;
getRowKey?: (row: T, index: number) => string | number | null | undefined;
onRequestSort?: (
orderBy: string,
orderDirection: OrderDirection
) => void | Promise<void>;
onSelect?: (rows: T[]) => void;
loading?: boolean;
tableProps?: MUITableProps;
tableBodyProps?: TableBodyProps;
footerProps?: TableFooterProps;
hideFooter?: boolean;
size?: 'medium' | 'small';
size?: MUITableProps['size'];
selected?: T[];
}
@ -48,19 +44,12 @@ function Table<T>({
selection = false,
loading = false,
actions = [],
tableBodyProps = {},
tableProps = {},
hideFooter = false,
footerProps = {},
size,
selected,
onSelect,
getRowKey,
}: TableProps<T>) {
const headColumns =
actions.length > 0
? [...columns, { field: 'action', label: 'Akcje' }]
: columns;
const preparedFooterProps = {
page: 0,
rowsPerPage: validateRowsPerPage(
@ -86,11 +75,12 @@ function Table<T>({
return (
<TableContainer>
<MUITable size={size} {...tableProps}>
<MUITable size={size}>
<TableHead
columns={headColumns}
columns={columns}
selection={selection}
orderBy={orderBy}
hasActions={actions.length > 0}
orderDirection={orderDirection}
onRequestSort={onRequestSort}
size={size}
@ -101,10 +91,9 @@ function Table<T>({
}}
allSelected={selected?.length === data.length}
/>
<TableBody {...tableBodyProps}>
<TableBody>
{loading ? (
<TableLoading
columns={headColumns}
size={size}
rowsPerPage={preparedFooterProps.rowsPerPage}
/>
@ -113,11 +102,7 @@ function Table<T>({
return (
<TableRow
key={
getRowKey
? getRowKey(item, index)
: isObjKey(item, idFieldName)
? item[idFieldName] + ''
: index
isObjKey(item, idFieldName) ? item[idFieldName] + '' : index
}
index={index}
row={item}

View File

@ -4,6 +4,7 @@ import {
TablePagination,
TableRow,
TableFooter as MUITableFooter,
TablePaginationProps as MUITablePaginationProps,
} from '@material-ui/core';
export interface TableFooterProps {
@ -12,8 +13,8 @@ export interface TableFooterProps {
onChangePage?: (page: number) => void;
rowsPerPage?: number;
onChangeRowsPerPage?: (limit: number) => void;
rowsPerPageOptions?: Array<number | { value: number; label: string }>;
size?: 'small' | 'medium';
rowsPerPageOptions?: MUITablePaginationProps['rowsPerPageOptions'];
size?: MUITablePaginationProps['size'];
}
export const ROWS_PER_PAGE_DEFAULT = 25;

View File

@ -22,6 +22,7 @@ export interface TableHeadProps {
property: string,
orderDirection: OrderDirection
) => void | Promise<void>;
hasActions: boolean;
}
function TableHead({
@ -33,6 +34,7 @@ function TableHead({
allSelected = false,
onRequestSort,
size = 'medium',
hasActions = false,
}: TableHeadProps) {
const createSortHandler = (property: string) => () => {
if (onRequestSort) {
@ -85,6 +87,7 @@ function TableHead({
</TableCell>
);
})}
{hasActions && <TableCell size={size}>Akcje</TableCell>}
</TableRow>
</MUITableHead>
);

View File

@ -1,30 +1,22 @@
import React, { Fragment } from 'react';
import { Column } from './types';
import { TableRow, TableCell } from '@material-ui/core';
import { Skeleton } from '@material-ui/lab';
export interface TableLoadingProps {
rowsPerPage: number;
columns: Column[];
size?: 'small' | 'medium';
}
function TableLoading({
rowsPerPage,
columns,
size = 'medium',
}: TableLoadingProps) {
function TableLoading({ rowsPerPage, size = 'medium' }: TableLoadingProps) {
return (
<Fragment>
{new Array(rowsPerPage).fill(0).map((_, index) => {
return (
<TableRow key={index}>
{columns.map(col => (
<TableCell size={size} key={col.field}>
<Skeleton variant="text" />
</TableCell>
))}
<TableCell size={size} colSpan={100}>
<Skeleton variant="text" />
</TableCell>
</TableRow>
);
})}

View File

@ -1,13 +1,12 @@
import {
ROWS_PER_PAGE_DEFAULT,
ROWS_PER_PAGE_OPTIONS_DEFAULT,
TableFooterProps,
} from './TableFooter';
export const validateRowsPerPage = (
rowsPerPage: number | null = ROWS_PER_PAGE_DEFAULT,
rowsPerPageOptions: Array<
number | { value: number; label: string }
> = ROWS_PER_PAGE_OPTIONS_DEFAULT
rowsPerPageOptions: TableFooterProps['rowsPerPageOptions'] = ROWS_PER_PAGE_OPTIONS_DEFAULT
) => {
const opt =
rowsPerPageOptions.find(opt =>

View File

@ -2,20 +2,52 @@ import useUsers from './UsersPage.useUsers';
import { NumberParam, useQueryParams, withDefault } from 'use-query-params';
import SortParam, { decodeSort } from 'libs/serialize-query-params/SortParam';
import { validateRowsPerPage } from 'common/Table/helpers';
import { DEFAULT_SORT, COLUMNS } from './constants';
const DEFAULT_SORT = decodeSort('id DESC');
import { Container, Paper } from '@material-ui/core';
import Table from 'common/Table/Table';
const UsersPage = () => {
const [{ page, sort, ...rest }, setQuery] = useQueryParams({
const [{ page, sort, ...rest }, setQueryParams] = useQueryParams({
limit: NumberParam,
page: withDefault(NumberParam, 0),
sort: withDefault(SortParam, DEFAULT_SORT),
});
const limit = validateRowsPerPage(rest.limit);
const data = useUsers(page, limit, sort.toString());
console.log(data);
const { users, total, loading } = useUsers(page, limit, sort.toString());
console.log(users);
return <div>UsersPage</div>;
return (
<Container>
<Paper>
<Table
selection
columns={COLUMNS}
data={users}
loading={loading}
orderBy={sort.orderBy}
orderDirection={sort.orderDirection}
onRequestSort={(orderBy, orderDirection) => {
setQueryParams({
page: 0,
sort: decodeSort(orderBy + ' ' + orderDirection),
});
}}
footerProps={{
count: total,
page,
onChangePage: page => {
setQueryParams({ page });
},
onChangeRowsPerPage: limit => {
setQueryParams({ page: 0, limit });
},
rowsPerPage: limit,
}}
/>
</Paper>
</Container>
);
};
export default UsersPage;

View File

@ -18,7 +18,7 @@ const useUsers = (page: number, limit: number, sort: string) => {
return {
users: data?.users.items ?? [],
get loading() {
return this.users.length === 0 || loading;
return this.users.length === 0 && loading;
},
total: data?.users.total ?? 0,
};

View File

@ -0,0 +1,39 @@
import { decodeSort } from 'libs/serialize-query-params/SortParam';
import { formatRole } from './utils';
import { Column } from 'common/Table/types';
import { User } from 'libs/graphql/types';
export const DEFAULT_SORT = decodeSort('id DESC');
export const COLUMNS: Column<User>[] = [
{
field: 'id',
sortable: true,
label: 'ID',
},
{
field: 'displayName',
sortable: true,
label: 'Użytkownik',
valueFormatter: v => {
return `${v.displayName} (${v.email})`;
},
},
{
field: 'role',
sortable: false,
label: 'Rola',
valueFormatter: v => formatRole(v.role),
},
{
field: 'activated',
sortable: false,
label: 'Aktywowany',
valueFormatter: v => (v.activated ? 'Tak' : 'Nie'),
},
{
field: 'createdAt',
sortable: true,
label: 'Data utworzenia',
type: 'datetime',
},
];

View File

@ -15,6 +15,7 @@ export const QUERY_USERS = gql`
displayName
email
role
createdAt
}
}
}

View File

@ -0,0 +1,4 @@
import { Role } from '../../libs/graphql/types';
export const formatRole = (r: Role): string =>
r === Role.Admin ? 'Admin' : 'Użytkownik';