diff --git a/app/server/static/components/annotation.pug b/app/server/static/components/annotation.pug index 3e7e965a..28044eee 100644 --- a/app/server/static/components/annotation.pug +++ b/app/server/static/components/annotation.pug @@ -53,7 +53,7 @@ div.columns(v-cloak="") | Completed div.main.pt0.pb0.pr20.pl20 - span About {{ count }} results + span About {{ count }} results (page {{ paginationPage }} of {{ paginationPages }}) div.main.sidebar-scrollable a.item( @@ -141,22 +141,41 @@ div.columns(v-cloak="") preview(v-bind:url="documentMetadata.documentSourceUrl") div.level.mt30 - a.button.level-left( - v-shortkey="{ prev1: ['ctrl', 'p'], prev2: ['arrowup'], prev3: ['arrowleft'] }" - v-on:click="prevPage" - v-on:shortkey="prevPage" - ) - span.icon - i.fas.fa-chevron-left - span Prev - - span.button.level-center.is-static {{ offset + pageNumber + 1 }} / {{ count }} - - a.button.level-right( - v-shortkey="{ next1: ['ctrl', 'n'], next2: ['arrowdown'], next3: ['arrowright'] }" - v-on:click="nextPage" - v-on:shortkey="nextPage" - ) - span Next - span.icon - i.fas.fa-chevron-right + div.level-left + div.buttons + a.button( + v-shortkey="{ prev1: ['shift', 'ctrl', 'p'], prev2: ['shift', 'arrowup'], prev3: ['shift', 'arrowleft'] }" + v-on:click="prevPagination" + v-on:shortkey="prevPagination" + ) + span.icon.tooltip(data-tooltip="Previous page") + i.fas.fa-arrow-left + + a.button( + v-shortkey="{ prev1: ['ctrl', 'p'], prev2: ['arrowup'], prev3: ['arrowleft'] }" + v-on:click="prevPage" + v-on:shortkey="prevPage" + ) + span.icon.tooltip(data-tooltip="Previous document") + i.fas.fa-chevron-left + + div.level-center + span.button.is-static {{ offset + pageNumber + 1 }} / {{ count }} + + div.level-right + div.buttons + a.button( + v-shortkey="{ next1: ['ctrl', 'n'], next2: ['arrowdown'], next3: ['arrowright'] }" + v-on:click="nextPage" + v-on:shortkey="nextPage" + ) + span.icon.tooltip(data-tooltip="Next document") + i.fas.fa-chevron-right + + a.button( + v-shortkey="{ next1: ['shift', 'ctrl', 'n'], next2: ['shift', 'arrowdown'], next3: ['shift', 'arrowright'] }" + v-on:click="nextPagination" + v-on:shortkey="nextPagination" + ) + span.icon.tooltip(data-tooltip="Next page") + i.fas.fa-arrow-right diff --git a/app/server/static/components/annotationMixin.js b/app/server/static/components/annotationMixin.js index ee68723d..7a9975a4 100644 --- a/app/server/static/components/annotationMixin.js +++ b/app/server/static/components/annotationMixin.js @@ -13,6 +13,19 @@ const getOffsetFromUrl = (url) => { return parseInt(offsetMatch[1], 10); }; +const removeHost = (url) => { + if (!url) { + return url; + } + + const hostMatch = url.match(/^https?:\/\/[^/]*\/(.*)$/); + if (hostMatch == null) { + return url; + } + + return `${window.location.origin}/${hostMatch[1]}`; +}; + const storeOffsetInUrl = (offset) => { let href = window.location.href; @@ -36,6 +49,28 @@ const storeOffsetInUrl = (offset) => { window.location.href = href; }; +const getLimitFromUrl = (url, prevLimit) => { + try { + const limitMatch = url.match(/[?#].*limit=(\d+)/); + + return parseInt(limitMatch[1], 10); + } catch (err) { + return prevLimit; + } +}; + +const getSidebarTotal = (count, limit) => ( + count !== 0 && limit !== 0 + ? Math.ceil(count / limit) + : 0 +); + +const getSidebarPage = (offset, limit) => ( + limit !== 0 + ? Math.ceil(offset / limit) + 1 + : 0 +); + export default { components: { VueJsonPretty, Preview }, @@ -53,6 +88,9 @@ export default { offset: getOffsetFromUrl(window.location.href), picked: 'all', count: 0, + prevLimit: 0, + paginationPages: 0, + paginationPage: 0, isSuperuser: false, isMetadataActive: false, isAnnotationGuidelineActive: false, @@ -97,14 +135,44 @@ export default { } }, + async nextPagination() { + if (this.next) { + this.url = this.next; + await this.search(); + this.pageNumber = 0; + } else { + this.pageNumber = this.docs.length - 1; + } + this.resetScrollbar(); + }, + + async prevPagination() { + if (this.prev) { + this.url = this.prev; + await this.search(); + this.pageNumber = this.docs.length - this.limit; + } else { + this.pageNumber = 0; + } + this.resetScrollbar(); + }, + async search() { await HTTP.get(this.url).then((response) => { this.docs = response.data.results; - this.next = response.data.next; - this.prev = response.data.previous; + this.next = removeHost(response.data.next); + this.prev = removeHost(response.data.previous); this.count = response.data.count; this.annotations = this.docs.map(doc => doc.annotations); this.offset = getOffsetFromUrl(this.url); + this.prevLimit = this.limit; + if (this.next || this.prevLimit) { + this.limit = getLimitFromUrl(this.next, this.prevLimit); + } else { + this.limit = this.count; + } + this.paginationPages = getSidebarTotal(this.count, this.limit); + this.paginationPage = getSidebarPage(this.offset, this.limit); }); },