Skip to content

Commit

Permalink
Merge pull request #1149 from thunderstore-io/pagination-improvements
Browse files Browse the repository at this point in the history
Improve pagination support for large page counts
  • Loading branch information
MythicManiac authored Jan 6, 2024
2 parents 6f4d92d + dd4583f commit cee0f0f
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 10 deletions.
58 changes: 58 additions & 0 deletions src/components/navigation/PaginationButtons.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
import { truncatePagination } from "../../utils/Pagination";
@Component({})
export default class PaginationButtons extends Vue {
@Prop({ required: true })
private currentPage!: number;
@Prop({ required: true })
private pageCount!: number;
@Prop({ required: true })
private contextSize!: number;
@Prop({ required: true })
private onClick!: (pageIndex: number) => void;
@Watch("currentPage")
@Watch("pageCount")
@Watch("contextSize")
visibleButtons() {
return truncatePagination({
currentPage: this.currentPage,
pageCount: this.pageCount,
contextSize: this.contextSize,
});
}
}
</script>

<template>
<nav class="pagination">
<ul class="pagination-list">
<li
v-for="button in visibleButtons()"
:key="`pagination-${button.index}`"
>
<a
:class="[
'pagination-link',
'flex-centered',
{'is-current': button.index === currentPage}
]"
@click="onClick(button.index)"
>{{button.title}}</a>
</li>
</ul>
</nav>
</template>

<style scoped lang="scss">
.flex-centered {
display: flex;
align-items: center;
justify-content: center;
}
</style>
19 changes: 9 additions & 10 deletions src/components/views/OnlineModView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,12 @@
</p>
</div>
<br/>
<div class="pagination">
<div class="smaller-font">
<a v-for="index in getPaginationSize()" :key="`pagination-${index}`"
:class="['pagination-link', {'is-current': index === pageNumber}]"
@click="updatePageNumber(index)">
{{index}}
</a>
</div>
</div>
<PaginationButtons
:current-page="pageNumber"
:page-count="getPaginationSize()"
:context-size="3"
:on-click="updatePageNumber"
/>
</div>
</template>

Expand All @@ -84,15 +81,17 @@ import OnlineModListProvider from '../../providers/components/loaders/OnlineModL
import ArrayUtils from '../../utils/ArrayUtils';
import debounce from 'lodash.debounce';
import SearchUtils from '../../utils/SearchUtils';
import PaginationButtons from "../navigation/PaginationButtons.vue";
@Component({
components: {
OnlineModList: OnlineModListProvider.provider,
PaginationButtons,
}
})
export default class OnlineModView extends Vue {
readonly pageSize = 140;
readonly pageSize = 40;
pagedThunderstoreModList: ThunderstoreMod[] = [];
pageNumber = 1;
searchableThunderstoreModList: ThunderstoreMod[] = [];
Expand Down
54 changes: 54 additions & 0 deletions src/utils/Pagination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

export type PaginationButton = {
index: number;
title: string;
}

export function truncatePagination(props: {
currentPage: number,
pageCount: number,
contextSize: number,
}): PaginationButton[] {
const result = [];

if (props.currentPage - props.contextSize > 1) {
result.push({
index: 1,
title: "1"
});
}
if (props.currentPage - props.contextSize - 1 > 1) {
result.push({
index: props.currentPage - props.contextSize - 1,
title: "...",
});
}

for (
let i = props.currentPage - props.contextSize;
i <= props.currentPage + props.contextSize;
i++
) {
if (i > 0 && i <= props.pageCount) {
result.push({
index: i,
title: i.toString(),
});
}
}

if (props.currentPage + props.contextSize + 1 < props.pageCount) {
result.push({
index: props.currentPage + props.contextSize + 1,
title: "...",
});
}
if (props.currentPage + props.contextSize < props.pageCount) {
result.push({
index: props.pageCount,
title: props.pageCount.toString(),
});
}

return result;
}

0 comments on commit cee0f0f

Please sign in to comment.