Skip to content
Snippets Groups Projects
Commit 337bbd58 authored by Paul Kaplan's avatar Paul Kaplan
Browse files

Add basic "show more" pagination for the backpack

parent fc1e1cce
No related branches found
No related tags found
No related merge requests found
......@@ -76,3 +76,16 @@
.backpack-item img {
mix-blend-mode: multiply; /* Make white transparent for thumnbnails */
}
.more {
background: $motion-primary;
color: $ui-white;
border: none;
outline: none;
font-weight: bold;
border-radius: 0.5rem;
font-size: 0.85rem;
padding: 0.5rem;
margin: 0.5rem;
cursor: pointer;
}
......@@ -25,10 +25,12 @@ const Backpack = ({
error,
expanded,
loading,
showMore,
onToggle,
onDelete,
onMouseEnter,
onMouseLeave
onMouseLeave,
onMore
}) => (
<div className={styles.backpackContainer}>
<div
......@@ -98,6 +100,18 @@ const Backpack = ({
onDeleteButtonClick={onDelete}
/>
))}
{showMore && (
<button
className={styles.more}
onClick={onMore}
>
<FormattedMessage
defaultMessage="More"
description="Load more from backpack"
id="gui.backpack.more"
/>
</button>
)}
</div>
) : (
<div className={styles.statusMessage}>
......@@ -129,6 +143,7 @@ Backpack.propTypes = {
expanded: PropTypes.bool,
loading: PropTypes.bool,
onDelete: PropTypes.func,
onMore: PropTypes.func,
onMouseEnter: PropTypes.func,
onMouseLeave: PropTypes.func,
onToggle: PropTypes.func
......@@ -140,6 +155,8 @@ Backpack.defaultProps = {
dragOver: false,
expanded: false,
loading: false,
showMore: false,
onMore: null,
onToggle: null
};
......
......@@ -29,11 +29,12 @@ class Backpack extends React.Component {
'handleToggle',
'handleDelete',
'getBackpackAssetURL',
'refreshContents',
'getContents',
'handleMouseEnter',
'handleMouseLeave',
'handleBlockDragEnd',
'handleBlockDragUpdate'
'handleBlockDragUpdate',
'handleMore'
]);
this.state = {
// While the DroppableHOC manages drop interactions for asset tiles,
......@@ -42,8 +43,8 @@ class Backpack extends React.Component {
blockDragOutsideWorkspace: false,
blockDragOverBackpack: false,
error: false,
offset: 0,
itemsPerPage: 20,
moreToLoad: false,
loading: false,
expanded: false,
contents: []
......@@ -72,12 +73,12 @@ class Backpack extends React.Component {
}
handleToggle () {
const newState = !this.state.expanded;
this.setState({expanded: newState, offset: 0}, () => {
this.setState({expanded: newState, contents: []}, () => {
// Emit resize on window to get blocks to resize
window.dispatchEvent(new Event('resize'));
});
if (newState) {
this.refreshContents();
this.getContents();
}
}
handleDrop (dragInfo) {
......@@ -107,33 +108,57 @@ class Backpack extends React.Component {
username: this.props.username,
...payload
}))
.then(this.refreshContents);
.then(item => {
this.setState({
loading: false,
contents: [item].concat(this.state.contents)
});
})
.catch(() => {
this.setState({error: true, loading: false});
});
});
}
handleDelete (id) {
deleteBackpackObject({
host: this.props.host,
token: this.props.token,
username: this.props.username,
id: id
}).then(this.refreshContents);
}
refreshContents () {
if (this.props.token && this.props.username) {
this.setState({loading: true, error: false});
getBackpackContents({
this.setState({loading: true}, () => {
deleteBackpackObject({
host: this.props.host,
token: this.props.token,
username: this.props.username,
offset: this.state.offset,
limit: this.state.itemsPerPage
id: id
})
.then(contents => {
this.setState({contents, loading: false});
.then(() => {
this.setState({
loading: false,
contents: this.state.contents.filter(o => o.id !== id)
});
})
.catch(() => {
this.setState({error: true, loading: false});
});
});
}
getContents () {
if (this.props.token && this.props.username) {
this.setState({loading: true, error: false}, () => {
getBackpackContents({
host: this.props.host,
token: this.props.token,
username: this.props.username,
offset: this.state.contents.length,
limit: this.state.itemsPerPage
})
.then(contents => {
this.setState({
contents: this.state.contents.concat(contents),
moreToLoad: contents.length === this.state.itemsPerPage,
loading: false
});
})
.catch(() => {
this.setState({error: true, loading: false});
});
});
}
}
handleBlockDragUpdate (isOutsideWorkspace) {
......@@ -168,6 +193,9 @@ class Backpack extends React.Component {
blockDragOutsideWorkspace: false
});
}
handleMore () {
this.getContents();
}
render () {
return (
<DroppableBackpack
......@@ -176,8 +204,10 @@ class Backpack extends React.Component {
error={this.state.error}
expanded={this.state.expanded}
loading={this.state.loading}
showMore={this.state.moreToLoad}
onDelete={this.handleDelete}
onDrop={this.handleDrop}
onMore={this.handleMore}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onToggle={this.props.host ? this.handleToggle : null}
......
......@@ -4,6 +4,14 @@ import soundPayload from './backpack/sound-payload';
import spritePayload from './backpack/sprite-payload';
import codePayload from './backpack/code-payload';
// Add a new property for the full thumbnail url, which includes the host.
// Also include a full body url for loading sprite zips
// TODO retreiving the images through storage would allow us to remove this.
const includeFullUrls = (item, host) => Object.assign({}, item, {
thumbnailUrl: `${host}/${item.thumbnail}`,
bodyUrl: `${host}/${item.body}`
});
const getBackpackContents = ({
host,
username,
......@@ -20,15 +28,7 @@ const getBackpackContents = ({
if (error || response.statusCode !== 200) {
return reject();
}
// Add a new property for the full thumbnail url, which includes the host.
// Also include a full body url for loading sprite zips
// TODO retreiving the images through storage would allow us to remove this.
return resolve(response.body.map(item => (
Object.assign({}, item, {
thumbnailUrl: `${host}/${item.thumbnail}`,
bodyUrl: `${host}/${item.body}`
})
)));
return resolve(response.body.map(item => includeFullUrls(item, host)));
});
});
......@@ -51,7 +51,7 @@ const saveBackpackObject = ({
if (error || response.statusCode !== 200) {
return reject();
}
return resolve(response.body);
return resolve(includeFullUrls(response.body, host));
});
});
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment