Skip to content

Commit

Permalink
Cursor pagination actions and UI
Browse files Browse the repository at this point in the history
Make spinner appear while pages are requested

Fix pagination alignment
  • Loading branch information
Benaiah committed May 7, 2018
1 parent a784a25 commit dcf6df7
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 11 deletions.
40 changes: 40 additions & 0 deletions src/actions/entries.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,46 @@ export function loadEntries(collection, page = 0) {
};
}

function traverseCursor(backend, cursor, action) {
if (!cursor) {
throw new Error("No cursor exists");
}
if (!validateCursor(cursor)) {
throw new invalidCursorError(cursor);
}
if (!cursor.actions.includes(action)) {
throw new Error(`The current cursor does not support the pagination action "${ action }".`);
}
return backend.traverseCursor(cursor, action);
}

export function traverseCollectionCursor(collection, action) {
return async (dispatch, getState) => {
if (collection.get("isFetching")) {
return;
}
const state = getState();
const backend = currentBackend(state.config);
try {
const cursor = state.cursors.get(collectionEntriesCursorKey(collection.get('name')));
dispatch(entriesLoading(collection));
const { entries, cursor: newCursor } = await traverseCursor(backend, cursor, action);

// Pass null for the old pagination argument - this will
// eventually be removed.
return dispatch(entriesLoaded(collection, entries, null, newCursor));
} catch (err) {
console.error(err);
dispatch(notifSend({
message: `Failed to persist entry: ${ err }`,
kind: 'danger',
dismissAfter: 8000,
}));
return Promise.reject(dispatch(entriesFailed(collection, err)));
}
}
}

export function createEmptyDraft(collection) {
return (dispatch) => {
const dataFields = {};
Expand Down
14 changes: 9 additions & 5 deletions src/components/Collection/Entries/Entries.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@ const Entries = ({
page,
onPaginate,
isFetching,
viewStyle
viewStyle,
cursorActions,
cursorMeta,
}) => {
const loadingMessages = [
'Loading Entries',
'Caching Entries',
'This might take several minutes',
];

if (isFetching) {
return <Loader active>{loadingMessages}</Loader>;
}

if (entries) {
return (
<EntryListing
Expand All @@ -28,14 +34,12 @@ const Entries = ({
page={page}
onPaginate={onPaginate}
viewStyle={viewStyle}
cursorActions={cursorActions}
cursorMeta={cursorMeta}
/>
);
}

if (isFetching) {
return <Loader active>{loadingMessages}</Loader>;
}

return <div className="nc-collectionPage-noEntries">No Entries</div>;
}

Expand Down
26 changes: 23 additions & 3 deletions src/components/Collection/Entries/EntriesCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import { loadEntries as actionLoadEntries } from 'Actions/entries';
import pick from 'lodash/pick';
import {
loadEntries as actionLoadEntries,
traverseCollectionCursor as actionTraverseCollectionCursor,
} from 'Actions/entries';
import { selectEntries } from 'Reducers';
import { collectionEntriesCursorKey } from 'Reducers/cursors';
import Entries from './Entries';

class EntriesCollection extends React.Component {
Expand Down Expand Up @@ -35,8 +40,17 @@ class EntriesCollection extends React.Component {
loadEntries(collection, page);
}

cursorHandler = action => () => {
const { collection, traverseCollectionCursor } = this.props;
traverseCollectionCursor(collection, action);
};

getCursorActionFunctions = (cursor, handler) => cursor && cursor.actions
? cursor.actions.reduce((acc, action) => ({ ...acc, [action]: handler(action) }), {})
: {};

render () {
const { collection, entries, publicFolder, page, isFetching, viewStyle } = this.props;
const { collection, entries, publicFolder, page, isFetching, viewStyle, cursor } = this.props;

return (
<Entries
Expand All @@ -48,6 +62,8 @@ class EntriesCollection extends React.Component {
isFetching={isFetching}
collectionName={collection.get('label')}
viewStyle={viewStyle}
cursorActions={this.getCursorActionFunctions(cursor, this.cursorHandler)}
cursorMeta={cursor && cursor.meta}
/>
);
}
Expand All @@ -62,11 +78,15 @@ function mapStateToProps(state, ownProps) {
const entries = selectEntries(state, collection.get('name'));
const isFetching = state.entries.getIn(['pages', collection.get('name'), 'isFetching'], false);

return { publicFolder, collection, page, entries, isFetching, viewStyle };
const rawCursor = state.cursors.get(collectionEntriesCursorKey(collection.get('name')));
const cursor = rawCursor && pick(rawCursor, ["meta", "actions"]);

return { publicFolder, collection, page, entries, isFetching, viewStyle, cursor };
}

const mapDispatchToProps = {
loadEntries: actionLoadEntries,
traverseCollectionCursor: actionTraverseCollectionCursor,
};

export default connect(mapStateToProps, mapDispatchToProps)(EntriesCollection);
33 changes: 33 additions & 0 deletions src/components/Collection/Entries/EntryListing.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,36 @@
.nc-entryListing-cardsList {
margin-left: -12px;
}

.nc-entryListing-pagination {
display: flex;
justify-content: space-between;
flex-basis: var(--topCardWidth);
align-items: center;
margin-left: 12px;
}

.nc-entryListing-paginationElement {
flex-grow: 1;
flex-basis: 0;
}

.nc-entryListing-paginationElement {
text-align: left;
flex-grow: 1;
flex-basis: 0;
}

.nc-entryListing-paginationMeta {
text-align: center;
}

.nc-entryListing-paginationButton {
@apply(--button);
@apply(--buttonDefault);
@apply(--buttonGray);
}

.nc-entryListing-paginationElementRight {
text-align: right;
}
31 changes: 28 additions & 3 deletions src/components/Collection/Entries/EntryListing.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,14 @@ export default class EntryListing extends React.Component {
};

render() {
const { collections, entries, publicFolder } = this.props;
const { collections, entries, publicFolder, cursorActions, cursorMeta } = this.props;
const { first, next, last, prev } = (cursorActions || {});
const { index: rawIndex, pageCount: rawPageCount } = (cursorMeta || {});
const index = rawIndex + 1;
const pageCount = rawPageCount + 1;
const pageString = index
? `Page ${ index }${ pageCount ? ` of ${ pageCount }` : "" }`
: "";

return (
<div>
Expand All @@ -63,8 +70,26 @@ export default class EntryListing extends React.Component {
? this.renderCardsForSingleCollection()
: this.renderCardsForMultipleCollections()
}
<Waypoint onEnter={this.handleLoadMore} />
</div>
{cursorActions && Object.keys(cursorActions).length > 0
? <div className="nc-entryListing-pagination">
<div className="nc-entryListing-paginationElement">
{first ? <button className="nc-entryListing-paginationButton" onClick={first}>{"<<<"}</button> : ""}
</div>
<div className="nc-entryListing-paginationElement">
{prev ? <button className="nc-entryListing-paginationButton" onClick={prev}>{"<"}</button> : ""}
</div>
<div className="nc-entryListing-paginationElement nc-entryListing-paginationMeta">
{pageString}
</div>
<div className="nc-entryListing-paginationElement nc-entryListing-paginationElementRight">
{next ? <button className="nc-entryListing-paginationButton" onClick={next}>{">"}</button> : ""}
</div>
<div className="nc-entryListing-paginationElement nc-entryListing-paginationElementRight">
{last ? <button className="nc-entryListing-paginationButton" onClick={last}>{">>>"}</button> : ""}
</div>
</div>
: ""}
</div>
</div>
);
}
Expand Down

0 comments on commit dcf6df7

Please sign in to comment.