feat: move pagination to dedicated component (#760)

Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#760
Reviewed-by: konrad <k@knt.li>
Co-authored-by: dpschen <dpschen@noreply.kolaente.de>
Co-committed-by: dpschen <dpschen@noreply.kolaente.de>
This commit is contained in:
dpschen 2021-09-21 19:03:38 +00:00 committed by konrad
parent 2ff0976da6
commit 7719ef1bef
6 changed files with 138 additions and 134 deletions

View File

@ -0,0 +1,125 @@
<template>
<nav
aria-label="pagination"
class="pagination is-centered p-4"
role="navigation"
v-if="totalPages > 1"
>
<router-link
:disabled="currentPage === 1"
:to="getRouteForPagination(currentPage - 1)"
class="pagination-previous"
tag="button">
{{ $t('misc.previous') }}
</router-link>
<router-link
:disabled="currentPage === totalPages"
:to="getRouteForPagination(currentPage + 1)"
class="pagination-next"
tag="button">
{{ $t('misc.next') }}
</router-link>
<ul class="pagination-list">
<template v-for="(p, i) in pages">
<li :key="'page' + i" v-if="p.isEllipsis">
<span class="pagination-ellipsis">&hellip;</span>
</li>
<li :key="'page' + i" v-else>
<router-link
:aria-label="'Goto page ' + p.number"
:class="{ 'is-current': p.number === currentPage }"
:to="getRouteForPagination(p.number)"
class="pagination-link"
>
{{ p.number }}
</router-link>
</li>
</template>
</ul>
</nav>
</template>
<script>
function createPagination(totalPages, currentPage) {
const pages = []
for (let i = 0; i < totalPages; i++) {
// Show ellipsis instead of all pages
if (
i > 0 && // Always at least the first page
(i + 1) < totalPages && // And the last page
(
// And the current with current + 1 and current - 1
(i + 1) > currentPage + 1 ||
(i + 1) < currentPage - 1
)
) {
// Only add an ellipsis if the last page isn't already one
if (pages[i - 1] && !pages[i - 1].isEllipsis) {
pages.push({
number: 0,
isEllipsis: true,
})
}
continue
}
pages.push({
number: i + 1,
isEllipsis: false,
})
}
return pages
}
function getRouteForPagination(page = 1, type = 'list') {
return {
name: 'list.' + type,
params: {
type: type,
},
query: {
page: page,
},
}
}
export default {
name: 'Pagination',
props: {
totalPages: {
type: Number,
required: true,
},
currentPage: {
type: Number,
required: true,
},
},
computed: {
pages() {
return createPagination(this.totalPages, this.currentPage)
},
},
methods: {
getRouteForPagination,
},
}
</script>
<style lang="scss" scoped>
.pagination {
padding-bottom: 1rem;
.pagination-previous,
.pagination-next {
&:not(:disabled):hover {
background: $scheme-main;
cursor: pointer;
}
}
}
</style>

View File

@ -12,50 +12,6 @@ const DEFAULT_PARAMS = {
filter_concat: 'and',
}
function createPagination(totalPages, currentPage) {
const pages = []
for (let i = 0; i < totalPages; i++) {
// Show ellipsis instead of all pages
if (
i > 0 && // Always at least the first page
(i + 1) < totalPages && // And the last page
(
// And the current with current + 1 and current - 1
(i + 1) > currentPage + 1 ||
(i + 1) < currentPage - 1
)
) {
// Only add an ellipsis if the last page isn't already one
if (pages[i - 1] && !pages[i - 1].isEllipsis) {
pages.push({
number: 0,
isEllipsis: true,
})
}
continue
}
pages.push({
number: i + 1,
isEllipsis: false,
})
}
return pages
}
export function getRouteForPagination(page = 1, type = 'list') {
return {
name: 'list.' + type,
params: {
type: type,
},
query: {
page: page,
},
}
}
/**
* This mixin provides a base set of methods and properties to get tasks on a list.
*/
@ -84,11 +40,6 @@ export default {
},
'$route.path': 'loadTasksOnSavedFilter',
},
computed: {
pages() {
return createPagination(this.taskCollectionService.totalPages, this.currentPage)
},
},
methods: {
loadTasks(
page,
@ -213,6 +164,5 @@ export default {
this.error(e)
})
},
getRouteForPagination,
},
}

View File

@ -5,6 +5,7 @@
background-attachment: fixed;
min-height: 100vh;
// FIXME: move to pagination component
.pagination-link:not(.is-current) {
background: $light-background;
}

View File

@ -116,18 +116,6 @@ button.table {
}
}
.pagination {
padding-bottom: 1rem;
.pagination-previous,
.pagination-next {
&:not(:disabled):hover {
background: $button-background-color;
cursor: pointer;
}
}
}
.is-max-width-desktop {
width: 100%;
max-width: $desktop;

View File

@ -121,44 +121,10 @@
</card>
</div>
<nav
aria-label="pagination"
class="pagination is-centered p-4"
role="navigation"
v-if="taskCollectionService.totalPages > 1"
>
<router-link
:disabled="currentPage === 1"
:to="getRouteForPagination(currentPage - 1)"
class="pagination-previous"
tag="button">
{{ $t('misc.previous') }}
</router-link>
<router-link
:disabled="currentPage === taskCollectionService.totalPages"
:to="getRouteForPagination(currentPage + 1)"
class="pagination-next"
tag="button">
{{ $t('misc.next') }}
</router-link>
<ul class="pagination-list">
<template v-for="(p, i) in pages">
<li :key="'page' + i" v-if="p.isEllipsis">
<span class="pagination-ellipsis">&hellip;</span>
</li>
<li :key="'page' + i" v-else>
<router-link
:aria-label="'Goto page ' + p.number"
:class="{ 'is-current': p.number === currentPage }"
:to="getRouteForPagination(p.number)"
class="pagination-link"
>
{{ p.number }}
</router-link>
</li>
</template>
</ul>
</nav>
<Pagination
:total-pages="taskCollectionService.totalPages"
:current-page="currentPage"
/>
</card>
<!-- This router view is used to show the task popup while keeping the kanban board itself -->
@ -182,6 +148,7 @@ import FilterPopup from '@/components/list/partials/filter-popup.vue'
import {HAS_TASKS} from '@/store/mutation-types'
import Nothing from '@/components/misc/nothing.vue'
import createTask from '@/components/tasks/mixins/createTask'
import Pagination from '@/components/misc/pagination.vue'
import {mapState} from 'vuex'
import draggable from 'vuedraggable'
@ -214,6 +181,7 @@ export default {
EditTask,
AddTask,
draggable,
Pagination,
},
created() {
this.taskService = new TaskService()

View File

@ -172,40 +172,10 @@
</table>
</div>
<nav
aria-label="pagination"
class="pagination is-centered p-4"
role="navigation"
v-if="taskCollectionService.totalPages > 1">
<router-link
:disabled="currentPage === 1"
:to="getRouteForPagination(currentPage - 1, 'table')"
class="pagination-previous"
tag="button">
{{ $t('misc.previous') }}
</router-link>
<router-link
:disabled="currentPage === taskCollectionService.totalPages"
:to="getRouteForPagination(currentPage + 1, 'table')"
class="pagination-next"
tag="button">
{{ $t('misc.next') }}
</router-link>
<ul class="pagination-list">
<template v-for="(p, i) in pages">
<li :key="'page'+i" v-if="p.isEllipsis"><span class="pagination-ellipsis">&hellip;</span></li>
<li :key="'page'+i" v-else>
<router-link
:aria-label="'Goto page ' + p.number"
:class="{'is-current': p.number === currentPage}"
:to="getRouteForPagination(p.number, 'table')"
class="pagination-link">
{{ p.number }}
</router-link>
</li>
</template>
</ul>
</nav>
<Pagination
:total-pages="taskCollectionService.totalPages"
:current-page="currentPage"
/>
</card>
<!-- This router view is used to show the task popup while keeping the table view itself -->
@ -226,6 +196,7 @@ import Fancycheckbox from '../../../components/input/fancycheckbox'
import Sort from '../../../components/tasks/partials/sort'
import {saveListView} from '@/helpers/saveListView'
import FilterPopup from '@/components/list/partials/filter-popup.vue'
import Pagination from '@/components/misc/pagination.vue'
export default {
name: 'Table',
@ -237,6 +208,7 @@ export default {
Labels,
PriorityLabel,
User,
Pagination,
},
mixins: [
taskList,