diff --git a/app/static/app/css/main.scss b/app/static/app/css/main.scss index 471c5abb..261342fe 100644 --- a/app/static/app/css/main.scss +++ b/app/static/app/css/main.scss @@ -94,6 +94,40 @@ ul#side-menu.nav{ z-index: 999999; } +.pagination{ + margin: 0; + + li>a{ + color: black; + border: 1px solid #ecf0f1; + background-color: #fff; + &:hover, &:focus{ + background-color: #798d8f; + } + } + .disabled > a{ + background-color: #fff; + border: 1px solid #f4f9f5; + &:hover, &:focus{ + background-color: #fff; + border: 1px solid #f4f9f5; + } + } + .active > a{ + background-color: #798d8f; + &:hover, &:focus{ + background-color: #798d8f; + } + } + + &.pagination-sm{ + a{ + padding-top: 2px; + padding-bottom: 2px; + } + } +} + table.table-first-col-bold{ td:first-child{ font-weight: bold; diff --git a/app/static/app/js/Dashboard.jsx b/app/static/app/js/Dashboard.jsx index 29a09368..ce124628 100644 --- a/app/static/app/js/Dashboard.jsx +++ b/app/static/app/js/Dashboard.jsx @@ -42,12 +42,13 @@ class Dashboard extends React.Component { Add Project + { this.projectDialog = domNode; }} /> { this.projectList = domNode; }} /> ); diff --git a/app/static/app/js/components/Paginated.jsx b/app/static/app/js/components/Paginated.jsx new file mode 100644 index 00000000..e0a7ab12 --- /dev/null +++ b/app/static/app/js/components/Paginated.jsx @@ -0,0 +1,33 @@ +import React from 'react'; + +/*abstract*/ class Paginated extends React.Component{ + constructor(){ + super(); + } + + // Should be called after parent state is set + setupPagination(itemsPerPage, totalItems){ + let currentPage = 1; + if (this.state.pagination && this.state.pagination.currentPage !== undefined){ + currentPage = this.state.pagination.currentPage; + } + + this.setState({pagination: { + itemsPerPage: itemsPerPage, + totalItems: totalItems, + currentPage: currentPage + } + }); + } + + getPaginatedUrl(base, page){ + return base.replace(/#\{PAGE\}/g, page); + } + + render(){ + throw new Error("Override me"); + } +} + +export default Paginated; + diff --git a/app/static/app/js/components/Paginator.jsx b/app/static/app/js/components/Paginator.jsx new file mode 100644 index 00000000..a878c30f --- /dev/null +++ b/app/static/app/js/components/Paginator.jsx @@ -0,0 +1,45 @@ +import React from 'react'; +import $ from 'jquery'; + +class Paginator extends React.Component { + render() { + const { itemsPerPage, totalItems, currentPage } = this.props; + let paginator = null; + + if (itemsPerPage && itemsPerPage && totalItems > itemsPerPage){ + const numPages = Math.ceil(totalItems / itemsPerPage), + pages = [...Array(numPages).keys()]; // [0, 1, 2, ...numPages] + + paginator = ( +
+ +
+ ); + } + + return (
+ {paginator} + {this.props.children} + {paginator} +
); + } +} + +export default Paginator; diff --git a/app/static/app/js/components/ProjectList.jsx b/app/static/app/js/components/ProjectList.jsx index 46d0ec30..99c1cdb3 100644 --- a/app/static/app/js/components/ProjectList.jsx +++ b/app/static/app/js/components/ProjectList.jsx @@ -2,8 +2,10 @@ import React from 'react'; import $ from 'jquery'; import ProjectListItem from './ProjectListItem'; +import Paginated from './Paginated'; +import Paginator from './Paginator'; -class ProjectList extends React.Component { +class ProjectList extends Paginated { constructor(){ super(); @@ -29,6 +31,7 @@ class ProjectList extends React.Component { projects: json.results, loading: false }); + this.setupPagination(10, json.count); }else{ this.setState({ error: `Invalid JSON response: ${JSON.stringify(json)}`, @@ -59,11 +62,14 @@ class ProjectList extends React.Component { return (
Loading projects...
); } else if (this.state.projects){ - return ( + ); }else if (this.state.error){ return (
An error occurred: {this.state.error}
); }else{ diff --git a/app/static/app/js/css/Dashboard.scss b/app/static/app/js/css/Dashboard.scss index fc7ce3d5..3cbba099 100644 --- a/app/static/app/js/css/Dashboard.scss +++ b/app/static/app/js/css/Dashboard.scss @@ -14,7 +14,7 @@ } } - .add-button{ + .add-button, .list-group{ margin-bottom: 8px; } } \ No newline at end of file