97 lines
2.4 KiB
Vue
97 lines
2.4 KiB
Vue
<template>
|
|
<div class="pagination-bar" v-if="totalPages > 1 || showPerPage">
|
|
<div class="pagination-info">
|
|
<select
|
|
v-if="showPerPage"
|
|
:value="perPage"
|
|
class="perpage-select"
|
|
@change="$emit('update:perPage', Number($event.target.value))"
|
|
>
|
|
<option v-for="opt in perPageOptions" :key="opt" :value="opt">
|
|
{{ opt }} per page
|
|
</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="pagination" v-if="totalPages > 1">
|
|
<button :disabled="page === 1" @click="$emit('update:page', page - 1)">
|
|
Prev
|
|
</button>
|
|
|
|
<button
|
|
v-for="p in visiblePages"
|
|
:key="p"
|
|
:class="{ active: p === page, ellipsis: p === '...' }"
|
|
:disabled="p === '...'"
|
|
@click="p !== '...' && $emit('update:page', p)"
|
|
>
|
|
{{ p }}
|
|
</button>
|
|
|
|
<button :disabled="page === totalPages" @click="$emit('update:page', page + 1)">
|
|
Next
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
|
|
const props = defineProps({
|
|
page: { type: Number, required: true },
|
|
totalPages: { type: Number, required: true },
|
|
perPage: { type: Number, default: 20 },
|
|
showPerPage: { type: Boolean, default: true }
|
|
})
|
|
|
|
defineEmits(['update:page', 'update:perPage'])
|
|
|
|
// A page size the caller actually uses must be selectable, or the control renders
|
|
// blank: NetworkDevicesList defaults to 25, which was in no option, so
|
|
// :value="25" matched nothing and the box showed empty - the operator could not
|
|
// see the current page size at all. Any size the component is handed is folded
|
|
// in rather than silently dropped.
|
|
const BASE_PER_PAGE_OPTIONS = [10, 20, 50, 100]
|
|
|
|
const perPageOptions = computed(() => {
|
|
const current = Number(props.perPage)
|
|
if (!current || BASE_PER_PAGE_OPTIONS.includes(current)) {
|
|
return BASE_PER_PAGE_OPTIONS
|
|
}
|
|
return [...BASE_PER_PAGE_OPTIONS, current].sort((a, b) => a - b)
|
|
})
|
|
|
|
const visiblePages = computed(() => {
|
|
const total = props.totalPages
|
|
const current = props.page
|
|
const pages = []
|
|
|
|
if (total <= 7) {
|
|
for (let i = 1; i <= total; i++) pages.push(i)
|
|
return pages
|
|
}
|
|
|
|
pages.push(1)
|
|
|
|
if (current > 3) {
|
|
pages.push('...')
|
|
}
|
|
|
|
const start = Math.max(2, current - 1)
|
|
const end = Math.min(total - 1, current + 1)
|
|
|
|
for (let i = start; i <= end; i++) {
|
|
pages.push(i)
|
|
}
|
|
|
|
if (current < total - 2) {
|
|
pages.push('...')
|
|
}
|
|
|
|
pages.push(total)
|
|
|
|
return pages
|
|
})
|
|
</script>
|