Pagination working

pull/52/head
Piero Toffanin 2016-11-26 10:27:54 -05:00
rodzic 511f5b8680
commit ec74ab6def
7 zmienionych plików z 100 dodań i 28 usunięć

Wyświetl plik

@ -48,7 +48,7 @@ class Dashboard extends React.Component {
ref={(domNode) => { this.projectDialog = domNode; }}
/>
<ProjectList
source="/api/projects/?ordering=-created_at&page=1"
source="/api/projects/?ordering=-created_at&page=#{PAGE}"
ref={(domNode) => { this.projectList = domNode; }} />
</div>
);

Wyświetl plik

@ -60,7 +60,8 @@ class EditProjectDialog extends React.Component {
}
componentWillUnmount(){
$(this.modal).off('hidden.bs.modal hidden.bs.modal');
$(this.modal).off('hidden.bs.modal hidden.bs.modal')
.modal('hide');
}
componentDidUpdate(){

Wyświetl plik

@ -2,7 +2,7 @@ import React from 'react';
import '../css/Map.scss';
import 'leaflet/dist/leaflet.css';
import Leaflet from 'leaflet';
import async from 'async/dist/async';
import async from 'async';
import 'leaflet-measure/dist/leaflet-measure.css';
import 'leaflet-measure/dist/leaflet-measure';
import '../vendor/leaflet/L.Control.MousePosition.css';

Wyświetl plik

@ -1,28 +1,80 @@
import React from 'react';
import update from 'react-addons-update';
/*abstract*/ class Paginated extends React.Component{
constructor(){
super();
}
setupPagination(itemsPerPage, totalItems){
updatePagination(itemsPerPage, totalItems){
let currentPage = 1;
const totalPages = this.totalPages(itemsPerPage, totalItems);
if (this.state.pagination && this.state.pagination.currentPage !== undefined){
currentPage = this.state.pagination.currentPage;
}
if (currentPage > totalPages) currentPage = totalPages;
this.setState({pagination: {
itemsPerPage: itemsPerPage,
totalItems: totalItems,
currentPage: currentPage
switchingPages: false,
itemsPerPage: itemsPerPage,
totalItems: totalItems,
currentPage: currentPage
}
});
this.handlePageChange = this.handlePageChange.bind(this);
}
getPaginatedUrl(base, page){
totalPages(itemsPerPage, totalItems){
return Math.ceil(totalItems / itemsPerPage);
}
getPaginatedUrl(base){
const page = this.state.pagination && this.state.pagination.currentPage !== undefined
? this.state.pagination.currentPage
: 1;
return base.replace(/#\{PAGE\}/g, page);
}
setPaginationState(props, done){
this.setState(update(this.state, {
pagination: {
$merge: props
}
}), done);
}
handlePageChange(pageNum){
return (e) => {
// Update current page, once rendering is completed, raise
// on page changed event
this.setPaginationState({
currentPage: pageNum,
switchingPages: true
}, () => {
if (this.onPageChanged) this.onPageChanged(pageNum);
});
}
}
handlePageItemsNumChange(delta, needsRefreshCallback){
const pagesBefore = this.totalPages(this.state.pagination.itemsPerPage, this.state.pagination.totalItems),
pagesAfter = this.totalPages(this.state.pagination.itemsPerPage, this.state.pagination.totalItems + delta);
let currentPage = this.state.pagination.currentPage;
if (currentPage > pagesAfter) currentPage = pagesAfter;
this.setPaginationState({
totalItems: this.state.pagination.totalItems + delta,
currentPage: currentPage
}, () => {
if (pagesBefore !== pagesAfter) needsRefreshCallback(pagesAfter);
});
}
render(){
throw new Error("Override me");
}

Wyświetl plik

@ -14,7 +14,7 @@ class Paginator extends React.Component {
<div className={this.props.className}>
<ul className="pagination pagination-sm">
<li className={currentPage === 1 ? "disabled" : ""}>
<a href="#">
<a href="javascript:void(0);" onClick={this.props.handlePageChange(1)}>
<span>&laquo;</span>
</a>
</li>
@ -22,10 +22,10 @@ class Paginator extends React.Component {
return (<li
key={page + 1}
className={currentPage === (page + 1) ? "active" : ""}
><a href="#">{page + 1}</a></li>);
><a href="javascript:void(0);" onClick={this.props.handlePageChange(page + 1)}>{page + 1}</a></li>);
})}
<li className={currentPage === numPages ? "disabled" : ""}>
<a href="#">
<a href="javascript:void(0);" onClick={this.props.handlePageChange(numPages)}>
<span>&raquo;</span>
</a>
</li>

Wyświetl plik

@ -1,9 +1,11 @@
import React from 'react';
import $ from 'jquery';
import '../css/ProjectList.scss';
import ProjectListItem from './ProjectListItem';
import Paginated from './Paginated';
import Paginator from './Paginator';
import ErrorMessage from './ErrorMessage';
class ProjectList extends Paginated {
constructor(){
@ -11,10 +13,13 @@ class ProjectList extends Paginated {
this.state = {
loading: true,
refreshing: false,
error: "",
projects: null
projects: []
}
this.PROJECTS_PER_PAGE = 10;
this.handleDelete = this.handleDelete.bind(this);
}
@ -23,15 +28,17 @@ class ProjectList extends Paginated {
}
refresh(){
this.setState({refreshing: true});
// Load projects from API
this.serverRequest =
$.getJSON(this.props.source, json => {
$.getJSON(this.getPaginatedUrl(this.props.source), json => {
if (json.results){
this.setState({
projects: json.results,
loading: false
});
this.setupPagination(10, json.count);
this.updatePagination(this.PROJECTS_PER_PAGE, json.count);
}else{
this.setState({
error: `Invalid JSON response: ${JSON.stringify(json)}`,
@ -44,8 +51,14 @@ class ProjectList extends Paginated {
error: `Could not load projects list: ${textStatus}`,
loading: false
});
})
.always(() => {
this.setState({refreshing: false});
});
}
onPageChanged(pageNum){
this.refresh();
}
componentWillUnmount(){
@ -55,25 +68,25 @@ class ProjectList extends Paginated {
handleDelete(projectId){
let projects = this.state.projects.filter(p => p.id !== projectId);
this.setState({projects: projects});
this.handlePageItemsNumChange(-1, () => {
this.refresh();
});
}
render() {
if (this.state.loading){
return (<div>Loading projects... <i className="fa fa-refresh fa-spin fa-fw"></i></div>);
}
else if (this.state.projects){
return (
<Paginator className="text-right" {...this.state.pagination}>
<ul className="list-group">
{this.state.projects.map(p => (
<ProjectListItem key={p.id} data={p} onDelete={this.handleDelete} />
))}
</ul>
</Paginator>);
}else if (this.state.error){
return (<div>An error occurred: {this.state.error}</div>);
return (<div className="project-list">Loading projects... <i className="fa fa-refresh fa-spin fa-fw"></i></div>);
}else{
return (<div></div>); // should never happen
return (<div className="project-list">
<ErrorMessage bind={[this, 'error']} />
<Paginator className="text-right" {...this.state.pagination} handlePageChange={this.handlePageChange.bind(this)}>
<ul className={"list-group project-list " + (this.state.refreshing ? "refreshing" : "")}>
{this.state.projects.map(p => (
<ProjectListItem key={p.id} data={p} onDelete={this.handleDelete} />
))}
</ul>
</Paginator>
</div>);
}
}
}

Wyświetl plik

@ -0,0 +1,6 @@
.project-list{
ul.project-list.refreshing{
opacity: 0.5;
pointer-events: none;
}
}