From 38c8f2dcd1d96c4e06fa3cb11fb13fd06afce727 Mon Sep 17 00:00:00 2001 From: Robbie Antenesse Date: Wed, 21 Feb 2018 23:14:39 -0700 Subject: [PATCH] Add pagination to hopefully quell fears of storing too much in memory. --- src/components/MainDisplay.jsx | 16 ++++++++ src/components/structure/Pagination.jsx | 51 +++++++++++++++++++++++++ src/index.jsx | 29 ++++++++++++-- 3 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 src/components/structure/Pagination.jsx diff --git a/src/components/MainDisplay.jsx b/src/components/MainDisplay.jsx index c4b253c..984fb35 100644 --- a/src/components/MainDisplay.jsx +++ b/src/components/MainDisplay.jsx @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import { LeftColumn } from './structure/LeftColumn'; import { RightColumn } from './structure/RightColumn'; +import { Pagination } from './structure/Pagination'; import { WordForm } from './management/WordForm'; import { DictionaryDetails } from './display/DictionaryDetails'; @@ -17,6 +18,10 @@ export class MainDisplay extends Component { dictionaryInfo: PropTypes.object.isRequired, wordsToDisplay: PropTypes.array.isRequired, wordsAreFiltered: PropTypes.bool, + currentPage: PropTypes.number, + itemsPerPage: PropTypes.number, + stats: PropTypes.object.isRequired, + setPage: PropTypes.func.isRequired, updateDisplay: PropTypes.func.isRequired, updater: PropTypes.object.isRequired, }, props, 'prop', 'MainDisplay'); @@ -52,6 +57,10 @@ export class MainDisplay extends Component { dictionaryInfo, wordsToDisplay, wordsAreFiltered, + currentPage, + itemsPerPage, + stats, + setPage, updateDisplay, updater, } = this.props; @@ -100,6 +109,13 @@ export class MainDisplay extends Component { words={ wordsToDisplay } adsEveryXWords={ 10 } updateDisplay={ updateDisplay } /> + + group.name === 'Total').value : null} + setPage={ setPage } /> diff --git a/src/components/structure/Pagination.jsx b/src/components/structure/Pagination.jsx new file mode 100644 index 0000000..f3446e8 --- /dev/null +++ b/src/components/structure/Pagination.jsx @@ -0,0 +1,51 @@ +import Inferno from 'inferno'; +import PropTypes from 'prop-types'; + +export const Pagination = (props) => { + PropTypes.checkPropTypes({ + currentPage: PropTypes.number.isRequired, + itemsPerPage: PropTypes.number.isRequired, + totalWords: PropTypes.number, + setPage: PropTypes.func.isRequired, + }, props, 'prop', 'Pagination'); + + const { currentPage, itemsPerPage, totalWords, setPage } = props; + + if (totalWords === null) { + return
; + } + + const lastPage = Math.floor(totalWords / itemsPerPage); + const nextPage = currentPage + 1 > lastPage ? lastPage : currentPage + 1; + const prevPage = currentPage - 1 < 0 ? 0 : currentPage - 1; + + const changePage = (page) => { + if (page !== currentPage && page <= lastPage && page >= 0) { + setPage(page); + } + } + + return ( + + ); +} diff --git a/src/index.jsx b/src/index.jsx index 9ce2da7..94ab883 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -36,6 +36,8 @@ class App extends Component { alphabeticalOrder: dictionary.alphabeticalOrder, displayedWords: [], + currentPage: 0, + itemsPerPage: 30, searchConfig: { searchingIn: 'name', searchMethod: SEARCH_METHOD.contains, @@ -90,9 +92,12 @@ class App extends Component { } updateDisplayedWords (callback = () => {}) { + const {currentPage, itemsPerPage} = this.state; dictionary.wordsPromise.then(words => { - const { searchConfig, partsOfSpeech } = this.state; + const { searchConfig, partsOfSpeech, currentPage, itemsPerPage } = this.state; const partsOfSpeechForFilter = [...partsOfSpeech, 'Uncategorized']; + const pageStart = currentPage * itemsPerPage; + const pageEnd = pageStart + itemsPerPage; let displayedWords; if (this.isUsingFilter) { const { @@ -104,7 +109,10 @@ class App extends Component { filteredPartsOfSpeech } = searchConfig; - displayedWords = words.filter((word) => { + displayedWords = words.filter((word, index) => { + if (index < pageStart || index >= pageEnd) { + return false; + } const wordPartOfSpeech = word.partOfSpeech === '' ? 'Uncategorized' : word.partOfSpeech; if (!filteredPartsOfSpeech.includes(wordPartOfSpeech)) { return false; @@ -161,7 +169,12 @@ class App extends Component { } }); } else { - displayedWords = words; + displayedWords = words.filter((word, index) => { + if (index < pageStart || index >= pageEnd) { + return false; + } + return true; + }); } this.setState({ @@ -177,6 +190,12 @@ class App extends Component { }, () => this.updateDisplayedWords()); } + setPage (newPage) { + this.setState({ + currentPage: newPage, + }, () => this.updateDisplayedWords()); + } + render () { return (
@@ -190,6 +209,10 @@ class App extends Component { dictionaryInfo={ this.dictionaryInfo } wordsToDisplay={ this.state.displayedWords } wordsAreFiltered={ this.isUsingFilter } + currentPage={ this.state.currentPage } + itemsPerPage={ this.state.itemsPerPage } + stats={ this.state.stats } + setPage={ this.setPage.bind(this) } updateDisplay={ this.updateDisplayedWords.bind(this) } updater={ this.updater } />