diff --git a/js/src/forum/components/DiscussionList.js b/js/src/forum/components/DiscussionList.js index 0e7ec4f99..4f14e5cc7 100644 --- a/js/src/forum/components/DiscussionList.js +++ b/js/src/forum/components/DiscussionList.js @@ -4,6 +4,13 @@ import Button from '../../common/components/Button'; import LoadingIndicator from '../../common/components/LoadingIndicator'; import Placeholder from '../../common/components/Placeholder'; +/** + * How many discussions do we show / load per page? + * + * @type {number} + */ +const DISCUSSIONS_PER_PAGE = 20; + /** * The `DiscussionList` component displays a list of discussions. * @@ -15,11 +22,11 @@ import Placeholder from '../../common/components/Placeholder'; export default class DiscussionList extends Component { init() { /** - * Whether or not discussion results are loading. + * Whether or not discussion results are loading for the next page. * * @type {Boolean} */ - this.loading = true; + this.loadingNext = true; /** * Whether or not discussion results are loading for the previous page. @@ -28,13 +35,6 @@ export default class DiscussionList extends Component { */ this.loadingPrev = false; - /** - * Whether or not there are previous results that can be loaded - * - * @type {boolean} - */ - this.previousResults = false; - /** * Whether or not there are more results that can be loaded. * @@ -63,19 +63,12 @@ export default class DiscussionList extends Component { */ this.lastLoadedPage = this.page; - /** - * Discussions per page - * - * @type {number} - */ - this.offsetBy = 20; - /** * Number of discussions to offset for pagination * * @type {number} */ - this.offset = (this.page - 1) * this.offsetBy; + this.offset = (this.page - 1) * DISCUSSIONS_PER_PAGE; /** * The discussions in the discussion list. @@ -97,7 +90,7 @@ export default class DiscussionList extends Component { view() { const params = this.props.params; - if (this.discussions.length === 0 && !this.loading) { + if (this.discussions.length === 0 && !this.loadingNext) { const text = app.translator.trans('core.forum.discussion_list.empty_text'); return
{Placeholder.component({ text })}
; } @@ -106,7 +99,7 @@ export default class DiscussionList extends Component {
{this.loadingPrev ? LoadingIndicator.component() - : this.firstLoadedPage !== 1 &&
{this.getLoadButton(false)}
} + : this.firstLoadedPage !== 1 &&
{this.getLoadPrevButton()}
} -
{this.loading ? LoadingIndicator.component() : this.moreResults && this.getLoadButton()}
+
+ {this.loadingNext ? LoadingIndicator.component() : this.moreResults && this.getLoadNextButton()} +
); } @@ -169,7 +164,7 @@ export default class DiscussionList extends Component { */ refresh(clear = true) { if (clear) { - this.loading = true; + this.loadingNext = true; this.discussions = []; } @@ -179,7 +174,7 @@ export default class DiscussionList extends Component { this.parseResults(results); }, () => { - this.loading = false; + this.loadingNext = false; m.redraw(); } ); @@ -206,29 +201,36 @@ export default class DiscussionList extends Component { } /** - * Load the next page of discussion results. + * Load the previous page of discussion results. * - * @param isNext the page to load is the next page, false for previous page * @public */ - load(isNext = true) { - if (isNext) { - this.loading = true; - this.page = ++this.lastLoadedPage; - } else if (this.firstLoadedPage !== 1) { + loadPrev() { + if (this.firstLoadedPage !== 1) { this.loadingPrev = true; this.page = --this.firstLoadedPage; this.addResultsToBeginning = true; } - this.loadResults((this.offset = (this.page - 1) * this.offsetBy)).then(this.parseResults.bind(this)); + this.loadResults((this.offset = (this.page - 1) * DISCUSSIONS_PER_PAGE)).then(this.parseResults.bind(this)); + } + + /** + * Load the next page of discussion results. + * + * @public + */ + loadNext() { + this.loadingNext = true; + this.page = ++this.lastLoadedPage; + + this.loadResults((this.offset = (this.page - 1) * DISCUSSIONS_PER_PAGE)).then(this.parseResults.bind(this)); } /** * Parse results and append them to the discussion list. * * @param {Discussion[]} results - * @return {Discussion[]} */ parseResults(results) { // If the results need to be added to the beginning of the discussion list @@ -240,31 +242,35 @@ export default class DiscussionList extends Component { [].push.apply(this.discussions, results); } - this.loading = false; + this.loadingNext = false; this.loadingPrev = false; - this.previousResults = !!results.payload.links.prev; this.moreResults = !!results.payload.links.next; - // Construct a URL to this discussion with the updated page, then - // replace it into the window's history and our own history stack. m.lazyRedraw(); + this.updateUrl(); + } - // Update page parameter in URL - // not supported in IE - if (typeof window.URL === 'function') { - const query = m.route.parseQueryString(document.location.search); + /** + * Update the "page" parameter in the URL shown to the user. + * + * Constructs a URL to this discussion with the updated page, then + * replaces it into the window's history and our own history stack. + */ + updateUrl() { + // Bail out if the browser does not support updating the URL. + if (typeof window.URL !== 'function') return; - if (this.page !== 1) query.page = this.page; - else delete query.page; + const query = m.route.parseQueryString(document.location.search); + query.page = this.page; - const url = new URL(document.location.href); - - url.search = m.route.buildQueryString(query); - - window.history.replaceState(null, document.title, url); + if (this.page === 1) { + delete query.page; } - return results; + const url = new URL(document.location.href); + url.search = m.route.buildQueryString(query); + + window.history.replaceState(null, '', url.toString()); } /** @@ -292,15 +298,28 @@ export default class DiscussionList extends Component { } /** - * Get the "Load More" or "Load Previous" page buttons + * Get the "Load Previous" page button. * - * @param isNext + * @return {Button} */ - getLoadButton(isNext = true) { + getLoadPrevButton() { return Button.component({ - children: app.translator.trans(`core.forum.discussion_list.load_${isNext ? 'more' : 'prev'}_button`), + children: app.translator.trans(`core.forum.discussion_list.load_prev_button`), className: 'Button', - onclick: this.load.bind(this, isNext), + onclick: this.loadPrev.bind(this), + }); + } + + /** + * Get the "Load More" page button. + * + * @return {Button} + */ + getLoadNextButton() { + return Button.component({ + children: app.translator.trans(`core.forum.discussion_list.load_more_button`), + className: 'Button', + onclick: this.loadNext.bind(this), }); } } diff --git a/less/forum/DiscussionList.less b/less/forum/DiscussionList.less index 2e2f1453a..f6a0d768d 100644 --- a/less/forum/DiscussionList.less +++ b/less/forum/DiscussionList.less @@ -7,7 +7,7 @@ list-style-type: none; position: relative; } -.DiscussionList-loadMore, .DiscussionList-loadPrev { +.DiscussionList-loadMore { text-align: center; margin-top: 10px; }