-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFR] Display a skeleton instead of empty datagrid when loading #2706
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Reducer } from 'redux'; | ||
import { CRUD_GET_LIST_SUCCESS } from '../../../../actions/dataActions'; | ||
|
||
type State = boolean; | ||
|
||
/** | ||
* This resource reducer is false until the list loads successfully | ||
*/ | ||
const loadedOnce: Reducer<State> = (previousState = false, { type }) => { | ||
// early return | ||
if (previousState === true) { | ||
return previousState; | ||
} | ||
if (type === CRUD_GET_LIST_SUCCESS) { | ||
return true; | ||
} | ||
return previousState; | ||
}; | ||
|
||
export default loadedOnce; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import React from 'react'; | ||
import Table from '@material-ui/core/Table'; | ||
import TableCell from '@material-ui/core/TableCell'; | ||
import TableHead from '@material-ui/core/TableHead'; | ||
import TableRow from '@material-ui/core/TableRow'; | ||
import TableBody from '@material-ui/core/TableBody'; | ||
import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; | ||
import IconButton from '@material-ui/core/IconButton'; | ||
import Checkbox from '@material-ui/core/Checkbox'; | ||
import classnames from 'classnames'; | ||
import { withStyles } from '@material-ui/core/styles'; | ||
|
||
const RawPlaceholder = ({ classes }) => ( | ||
<div className={classes.root}> </div> | ||
); | ||
|
||
const styles = theme => ({ | ||
root: { | ||
backgroundColor: theme.palette.grey[300], | ||
display: 'flex', | ||
}, | ||
}); | ||
|
||
const Placeholder = withStyles(styles)(RawPlaceholder); | ||
|
||
const times = (nbChildren, fn) => | ||
Array.from({ length: nbChildren }, (_, key) => fn(key)); | ||
|
||
export default ({ | ||
classes, | ||
className, | ||
expand, | ||
hasBulkActions, | ||
nbChildren, | ||
nbFakeLines = 5, | ||
}) => ( | ||
<Table className={classnames(classes.table, className)}> | ||
<TableHead> | ||
<TableRow className={classes.row}> | ||
{expand && <TableCell className={classes.expandHeader} />} | ||
{hasBulkActions && ( | ||
<TableCell | ||
padding="none" | ||
className={classes.expandIconCell} | ||
> | ||
<Checkbox | ||
className="select-all" | ||
color="primary" | ||
checked={false} | ||
/> | ||
</TableCell> | ||
)} | ||
{times(nbChildren, key => ( | ||
<TableCell | ||
padding="none" | ||
variant="head" | ||
className={classes.headerCell} | ||
key={key} | ||
> | ||
<Placeholder /> | ||
</TableCell> | ||
))} | ||
</TableRow> | ||
</TableHead> | ||
<TableBody> | ||
{times(nbFakeLines, key1 => ( | ||
<TableRow key={key1} style={{ opacity: 1 / (key1 + 1) }}> | ||
{expand && ( | ||
<TableCell | ||
padding="none" | ||
className={classes.expandIconCell} | ||
> | ||
<IconButton | ||
className={classes.expandIcon} | ||
component="div" | ||
aria-hidden="true" | ||
role="expand" | ||
> | ||
<ExpandMoreIcon /> | ||
</IconButton> | ||
</TableCell> | ||
)} | ||
{hasBulkActions && ( | ||
<TableCell | ||
padding="none" | ||
className={classes.expandIconCell} | ||
> | ||
<Checkbox | ||
className="select-all" | ||
color="primary" | ||
checked={false} | ||
/> | ||
</TableCell> | ||
)} | ||
{times(nbChildren, key2 => ( | ||
<TableCell | ||
padding="none" | ||
className={classes.rowCell} | ||
key={key2} | ||
> | ||
<Placeholder /> | ||
</TableCell> | ||
))} | ||
</TableRow> | ||
))} | ||
</TableBody> | ||
</Table> | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,6 +62,7 @@ const sanitizeRestProps = ({ | |
history, | ||
ids, | ||
isLoading, | ||
loadedOnce, | ||
locale, | ||
location, | ||
match, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import React, { cloneElement, Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import classnames from 'classnames'; | ||
import LinearProgress from '@material-ui/core/LinearProgress'; | ||
import { withStyles } from '@material-ui/core/styles'; | ||
import { linkToRecord } from 'ra-core'; | ||
|
||
|
@@ -13,7 +14,7 @@ const styles = { | |
// useful to prevent click bubbling in a datagrid with rowClick | ||
const stopPropagation = e => e.stopPropagation(); | ||
|
||
const sanitizeRestProps = ({ currentSort, setSort, isLoading, ...props }) => | ||
const sanitizeRestProps = ({ currentSort, setSort, loadedOnce, ...props }) => | ||
props; | ||
|
||
/** | ||
|
@@ -59,13 +60,18 @@ export class SingleFieldList extends Component { | |
className, | ||
ids, | ||
data, | ||
loadedOnce, | ||
resource, | ||
basePath, | ||
children, | ||
linkType, | ||
...rest | ||
} = this.props; | ||
|
||
if (loadedOnce === false) { | ||
return <LinearProgress />; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not faking multiple lines here too ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SingleFieldList can contain anything (usually in-line Besides, I just added the |
||
} | ||
|
||
return ( | ||
<div | ||
className={classnames(classes.root, className)} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be considered a BC break, but it was never documented, so I'm confident it should not break much.