make table translatable
This commit is contained in:
parent
88eb65ff65
commit
b51b33d7b6
|
@ -1,4 +1,6 @@
|
|||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TABLE } from '@config/namespaces';
|
||||
import isObjKey from '@utils/isObjKey';
|
||||
import { Action, Column, OrderDirection } from './types';
|
||||
|
||||
|
@ -7,6 +9,7 @@ import {
|
|||
TableBody,
|
||||
TableProps,
|
||||
TableBodyProps,
|
||||
TableContainer,
|
||||
} from '@material-ui/core';
|
||||
import TableHead from './TableHead';
|
||||
import TableRow from './TableRow';
|
||||
|
@ -32,6 +35,7 @@ export interface Props<T> {
|
|||
tableBodyProps?: TableBodyProps;
|
||||
footerProps?: TableFooterProps;
|
||||
hideFooter?: boolean;
|
||||
size?: 'medium' | 'small';
|
||||
}
|
||||
|
||||
function Table<T extends object>({
|
||||
|
@ -48,46 +52,58 @@ function Table<T extends object>({
|
|||
tableProps = {},
|
||||
hideFooter = false,
|
||||
footerProps,
|
||||
size,
|
||||
}: Props<T>) {
|
||||
const { t } = useTranslation(TABLE);
|
||||
return (
|
||||
<MUITable {...tableProps}>
|
||||
<TableHead
|
||||
columns={columns}
|
||||
selection={selection}
|
||||
orderBy={orderBy}
|
||||
orderDirection={orderDirection}
|
||||
onRequestSort={onRequestSort}
|
||||
allSelected={false}
|
||||
/>
|
||||
<TableBody {...tableBodyProps}>
|
||||
{loading ? (
|
||||
<TableLoading />
|
||||
) : data.length > 0 ? (
|
||||
data.map((item, index) => {
|
||||
return (
|
||||
<TableRow
|
||||
key={
|
||||
isObjKey(item, idFieldName) ? item[idFieldName] + '' : index
|
||||
}
|
||||
row={item}
|
||||
actions={actions}
|
||||
selected={false}
|
||||
selection={selection}
|
||||
columns={columns}
|
||||
/>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<TableEmpty />
|
||||
)}
|
||||
</TableBody>
|
||||
{!hideFooter && (
|
||||
<TableFooter
|
||||
count={footerProps?.count ?? data.length}
|
||||
{...footerProps}
|
||||
<TableContainer>
|
||||
<MUITable size={size} {...tableProps}>
|
||||
<TableHead
|
||||
columns={columns}
|
||||
selection={selection}
|
||||
orderBy={orderBy}
|
||||
orderDirection={orderDirection}
|
||||
onRequestSort={onRequestSort}
|
||||
allSelected={false}
|
||||
size={size}
|
||||
/>
|
||||
)}
|
||||
</MUITable>
|
||||
<TableBody {...tableBodyProps}>
|
||||
{loading ? (
|
||||
<TableLoading
|
||||
columns={columns}
|
||||
size={size}
|
||||
rowsPerPage={footerProps?.rowsPerPage ?? 50}
|
||||
/>
|
||||
) : data.length > 0 ? (
|
||||
data.map((item, index) => {
|
||||
return (
|
||||
<TableRow
|
||||
key={
|
||||
isObjKey(item, idFieldName) ? item[idFieldName] + '' : index
|
||||
}
|
||||
row={item}
|
||||
actions={actions}
|
||||
selected={false}
|
||||
selection={selection}
|
||||
columns={columns}
|
||||
size={size}
|
||||
/>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<TableEmpty t={t} />
|
||||
)}
|
||||
</TableBody>
|
||||
{!hideFooter && (
|
||||
<TableFooter
|
||||
t={t}
|
||||
count={footerProps?.count ?? data.length}
|
||||
size={size}
|
||||
{...footerProps}
|
||||
/>
|
||||
)}
|
||||
</MUITable>
|
||||
</TableContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import React from 'react';
|
||||
import { TFunction } from 'i18next';
|
||||
|
||||
import { TableRow, TableCell, Typography } from '@material-ui/core';
|
||||
|
||||
function TableEmpty() {
|
||||
export interface Props {
|
||||
t: TFunction;
|
||||
}
|
||||
|
||||
function TableEmpty({ t }: Props) {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell colSpan={100}>
|
||||
<Typography align="center">No records to display</Typography>
|
||||
<Typography align="center">{t('emptyDataSourceMessage')}</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import { TFunction } from 'i18next';
|
||||
|
||||
import {
|
||||
TablePagination,
|
||||
|
@ -24,7 +25,8 @@ function TableFooter({
|
|||
rowsPerPageOptions = [25, 50, 100],
|
||||
rowsPerPage = 50,
|
||||
size = 'small',
|
||||
}: Props) {
|
||||
t,
|
||||
}: Props & { t: TFunction }) {
|
||||
const handlePageChange = (
|
||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||
page: number
|
||||
|
@ -53,6 +55,10 @@ function TableFooter({
|
|||
rowsPerPageOptions={rowsPerPageOptions}
|
||||
size={size}
|
||||
colSpan={100}
|
||||
labelDisplayedRows={payload => t('labelDisplayedRows', payload)}
|
||||
labelRowsPerPage={t('labelRowsPerPage')}
|
||||
nextIconButtonText={t('next')}
|
||||
backIconButtonText={t('prev')}
|
||||
/>
|
||||
</TableRow>
|
||||
</MUITableFooter>
|
||||
|
|
|
@ -17,6 +17,7 @@ export interface Props {
|
|||
allSelected: boolean;
|
||||
orderDirection: OrderDirection;
|
||||
orderBy: string;
|
||||
size?: 'small' | 'medium';
|
||||
onRequestSort?: (
|
||||
property: string,
|
||||
orderDirection: OrderDirection
|
||||
|
@ -31,6 +32,7 @@ function TableHead({
|
|||
selection = false,
|
||||
allSelected = false,
|
||||
onRequestSort,
|
||||
size = 'medium',
|
||||
}: Props) {
|
||||
const createSortHandler = (property: string) => () => {
|
||||
if (onRequestSort) {
|
||||
|
@ -52,13 +54,14 @@ function TableHead({
|
|||
<MUITableHead>
|
||||
<TableRow>
|
||||
{selection && (
|
||||
<TableCell padding="checkbox">
|
||||
<TableCell size={size} padding="checkbox">
|
||||
<Checkbox checked={allSelected} onClick={handleSelectAll} />
|
||||
</TableCell>
|
||||
)}
|
||||
{columns.map(col => {
|
||||
return (
|
||||
<TableCell
|
||||
size={size}
|
||||
key={col.field}
|
||||
padding={col.disablePadding ? 'none' : 'default'}
|
||||
align={col.align ? col.align : 'left'}
|
||||
|
|
|
@ -1,21 +1,30 @@
|
|||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { Column } from './types';
|
||||
|
||||
import { TableRow, CircularProgress, Box, TableCell } from '@material-ui/core';
|
||||
import { TableRow, TableCell } from '@material-ui/core';
|
||||
import { Skeleton } from '@material-ui/lab';
|
||||
|
||||
function TableLoading() {
|
||||
export interface Props {
|
||||
rowsPerPage: number;
|
||||
columns: Column[];
|
||||
size?: 'small' | 'medium';
|
||||
}
|
||||
|
||||
function TableLoading({ rowsPerPage, columns, size = 'medium' }: Props) {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell colSpan={100}>
|
||||
<Box
|
||||
paddingY={2}
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<CircularProgress size={200} />
|
||||
</Box>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<Fragment>
|
||||
{new Array(rowsPerPage).fill(0).map((_, index) => {
|
||||
return (
|
||||
<TableRow key={index}>
|
||||
{columns.map(col => (
|
||||
<TableCell size={size} key={col.label}>
|
||||
<Skeleton variant="text" />
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ export type Props<T> = {
|
|||
row: T;
|
||||
selection: boolean;
|
||||
selected: boolean;
|
||||
size?: 'small' | 'medium';
|
||||
onSelect?: (row: T) => void;
|
||||
};
|
||||
|
||||
|
@ -21,6 +22,7 @@ function EnhancedTableRow<T extends object>({
|
|||
selection = false,
|
||||
selected = false,
|
||||
onSelect,
|
||||
size = 'medium',
|
||||
}: Props<T>) {
|
||||
const handleSelect = () => {
|
||||
if (onSelect) {
|
||||
|
@ -44,7 +46,7 @@ function EnhancedTableRow<T extends object>({
|
|||
return (
|
||||
<TableRow>
|
||||
{selection && (
|
||||
<TableCell padding="checkbox">
|
||||
<TableCell size={size} padding="checkbox">
|
||||
<Checkbox checked={selected} onClick={handleSelect} />
|
||||
</TableCell>
|
||||
)}
|
||||
|
@ -52,6 +54,7 @@ function EnhancedTableRow<T extends object>({
|
|||
const val = get(row, col.field, '');
|
||||
return (
|
||||
<TableCell
|
||||
size={size}
|
||||
key={col.field}
|
||||
padding={col.disablePadding ? 'none' : 'default'}
|
||||
align={col.align ? col.align : 'left'}
|
||||
|
@ -65,7 +68,7 @@ function EnhancedTableRow<T extends object>({
|
|||
);
|
||||
})}
|
||||
{actions.length > 0 && (
|
||||
<TableCell>
|
||||
<TableCell size={size}>
|
||||
{actions.map((action, index) =>
|
||||
action.tooltip ? (
|
||||
<Tooltip key={index} title={action.tooltip}>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export const COMMON = 'common';
|
||||
export const TABLE = 'table';
|
||||
export const INDEX_PAGE = 'index-page';
|
||||
export const NOT_FOUND_PAGE = 'not-found-page';
|
||||
export const SERVER_PAGE = {
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
import React from 'react';
|
||||
import useServer from '../../libs/ServerContext/useServer';
|
||||
|
||||
import { Container } from '@material-ui/core';
|
||||
import { Container, Grid } from '@material-ui/core';
|
||||
import PageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import RecentlyDeletedPlayers from './components/RecentlyDeletedPlayers/RecentlyDeletedPlayers';
|
||||
import RecentlyDeletedTribes from './components/RecentlyDeletedTribes/RecentlyDeletedTribes';
|
||||
|
||||
function IndexPage() {
|
||||
const { key } = useServer();
|
||||
return (
|
||||
<PageLayout>
|
||||
<Container>
|
||||
<RecentlyDeletedPlayers server={key} />
|
||||
<Grid container spacing={1}>
|
||||
<Grid item xs={6}>
|
||||
<RecentlyDeletedPlayers server={key} />
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<RecentlyDeletedTribes server={key} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
</PageLayout>
|
||||
);
|
||||
|
|
|
@ -34,13 +34,15 @@ function RecentlyDeletedPlayers({ server }: Props) {
|
|||
return (
|
||||
<Paper>
|
||||
<Toolbar>
|
||||
<Typography variant="h4">Test?</Typography>
|
||||
<Typography variant="h4">Recently deleted players</Typography>
|
||||
</Toolbar>
|
||||
<Table
|
||||
columns={COLUMNS}
|
||||
loading={loading}
|
||||
data={players}
|
||||
footerProps={{ rowsPerPage: LIMIT }}
|
||||
size="small"
|
||||
hideFooter
|
||||
footerProps={{ rowsPerPage: LIMIT, rowsPerPageOptions: [LIMIT] }}
|
||||
/>
|
||||
</Paper>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import React from 'react';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { RECENTLY_DELETED_TRIBES } from './queries';
|
||||
import { COLUMNS, LIMIT } from './constants';
|
||||
import { PlayersQueryVariables } from '@libs/graphql/types';
|
||||
import { TribeList } from './types';
|
||||
|
||||
import { Paper, Toolbar, Typography } from '@material-ui/core';
|
||||
import Table from '@common/Table/Table';
|
||||
|
||||
export interface Props {
|
||||
server: string;
|
||||
}
|
||||
|
||||
function RecentlyDeletedPlayers({ server }: Props) {
|
||||
const { loading: loadingPlayers, data } = useQuery<
|
||||
TribeList,
|
||||
PlayersQueryVariables
|
||||
>(RECENTLY_DELETED_TRIBES, {
|
||||
fetchPolicy: 'cache-and-network',
|
||||
variables: {
|
||||
filter: {
|
||||
limit: LIMIT,
|
||||
sort: 'deletedAt DESC',
|
||||
deletedAtGT: new Date(0),
|
||||
},
|
||||
server,
|
||||
},
|
||||
});
|
||||
const tribes = data?.tribes?.items ?? [];
|
||||
const loading = loadingPlayers && tribes.length === 0;
|
||||
|
||||
console.log(tribes, loading);
|
||||
return (
|
||||
<Paper>
|
||||
<Toolbar>
|
||||
<Typography variant="h4">Recently deleted tribes</Typography>
|
||||
</Toolbar>
|
||||
<Table
|
||||
columns={COLUMNS}
|
||||
loading={loading}
|
||||
data={tribes}
|
||||
size="small"
|
||||
hideFooter
|
||||
footerProps={{ rowsPerPage: LIMIT, rowsPerPageOptions: [LIMIT] }}
|
||||
/>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
export default RecentlyDeletedPlayers;
|
|
@ -0,0 +1,24 @@
|
|||
import { Column } from '@common/Table/types';
|
||||
|
||||
export const COLUMNS: Column[] = [
|
||||
{
|
||||
field: 'name',
|
||||
label: 'recentlyDeletedPlayers.columns.name',
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
field: 'mostPoints',
|
||||
label: 'recentlyDeletedPlayers.columns.mostPoints',
|
||||
sortable: false,
|
||||
valueFormatter: (param: string | number | boolean) =>
|
||||
(param as number).toLocaleString(),
|
||||
},
|
||||
{
|
||||
field: 'deletedAt',
|
||||
label: 'recentlyDeletedPlayers.columns.deletedAt',
|
||||
sortable: false,
|
||||
type: 'datetime',
|
||||
},
|
||||
];
|
||||
|
||||
export const LIMIT = 5;
|
|
@ -0,0 +1,14 @@
|
|||
import { gql } from '@apollo/client';
|
||||
|
||||
export const RECENTLY_DELETED_TRIBES = gql`
|
||||
query tribes($server: String!, $filter: TribeFilter) {
|
||||
tribes(server: $server, filter: $filter) {
|
||||
items {
|
||||
id
|
||||
name
|
||||
mostPoints
|
||||
deletedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -0,0 +1,12 @@
|
|||
import { List } from '@libs/graphql/types';
|
||||
|
||||
export type Tribe = {
|
||||
id: number;
|
||||
name: string;
|
||||
mostPoints: number;
|
||||
deletedAt: string | Date;
|
||||
};
|
||||
|
||||
export type TribeList = {
|
||||
tribes?: List<Tribe[]>;
|
||||
};
|
|
@ -3,11 +3,13 @@ import common from './common';
|
|||
import indexPage from './index-page';
|
||||
import notFoundPage from './not-found-page';
|
||||
import serverPage from './server-page';
|
||||
import table from './table';
|
||||
|
||||
const translations = {
|
||||
[NAMESPACES.COMMON]: common,
|
||||
[NAMESPACES.INDEX_PAGE]: indexPage,
|
||||
[NAMESPACES.NOT_FOUND_PAGE]: notFoundPage,
|
||||
[NAMESPACES.TABLE]: table,
|
||||
...serverPage,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const translations = {
|
||||
emptyDataSourceMessage: 'No records to display',
|
||||
labelDisplayedRows: '{from}-{to} of {count}',
|
||||
labelDisplayedRows: '{{from}}-{{to}} of {{count}}',
|
||||
labelRowsPerPage: 'Rows per page:',
|
||||
firstTooltip: 'First Page',
|
||||
previousTooltip: 'Previous Page',
|
||||
nextTooltip: 'Next Page',
|
||||
lastTooltip: 'Last Page',
|
||||
first: 'First page',
|
||||
last: 'Last page',
|
||||
next: 'Next page',
|
||||
previous: 'Previous page',
|
||||
};
|
||||
|
||||
export default translations;
|
||||
|
|
|
@ -3,11 +3,13 @@ import common from './common';
|
|||
import indexPage from './index-page';
|
||||
import notFoundPage from './not-found-page';
|
||||
import serverPage from './server-page';
|
||||
import table from './table';
|
||||
|
||||
const translations = {
|
||||
[NAMESPACES.COMMON]: common,
|
||||
[NAMESPACES.INDEX_PAGE]: indexPage,
|
||||
[NAMESPACES.NOT_FOUND_PAGE]: notFoundPage,
|
||||
[NAMESPACES.TABLE]: table,
|
||||
...serverPage,
|
||||
};
|
||||
|
||||
|
|
11
src/libs/i18n/pl/table.ts
Normal file
11
src/libs/i18n/pl/table.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
const translations = {
|
||||
emptyDataSourceMessage: 'Brak danych do wyświetlenia',
|
||||
labelDisplayedRows: '{{from}}-{{to}} z {{count}}',
|
||||
labelRowsPerPage: 'Wierszy na stronę:',
|
||||
first: 'Pierwsza strona',
|
||||
last: 'Ostatnia strona',
|
||||
next: 'Następna strona',
|
||||
previous: 'Poprzednia strona',
|
||||
};
|
||||
|
||||
export default translations;
|
|
@ -23,6 +23,13 @@ const createTheme = (): Theme => {
|
|||
color: 'default',
|
||||
},
|
||||
},
|
||||
overrides: {
|
||||
MuiTableContainer: {
|
||||
root: {
|
||||
overflow: 'auto',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
Reference in New Issue
Block a user