|
@@ -65,80 +65,111 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
<script lang="ts">
|
|
|
|
|
+ import { defineComponent } from 'vue';
|
|
|
|
|
+
|
|
|
import HueIcon from './HueIcon.vue';
|
|
import HueIcon from './HueIcon.vue';
|
|
|
import DropdownMenu from './dropdown/DropdownMenu.vue';
|
|
import DropdownMenu from './dropdown/DropdownMenu.vue';
|
|
|
import DropdownMenuButton from './dropdown/DropdownMenuButton.vue';
|
|
import DropdownMenuButton from './dropdown/DropdownMenuButton.vue';
|
|
|
- import Vue from 'vue';
|
|
|
|
|
- import Component from 'vue-class-component';
|
|
|
|
|
- import { Prop, Watch } from 'vue-property-decorator';
|
|
|
|
|
|
|
|
|
|
const DEFAULT_LIMIT = 25;
|
|
const DEFAULT_LIMIT = 25;
|
|
|
const PRESET_LIMITS = [DEFAULT_LIMIT, 50, 100];
|
|
const PRESET_LIMITS = [DEFAULT_LIMIT, 50, 100];
|
|
|
|
|
|
|
|
- @Component({
|
|
|
|
|
- components: { HueIcon, DropdownMenu, DropdownMenuButton }
|
|
|
|
|
- })
|
|
|
|
|
- export default class Paginator extends Vue {
|
|
|
|
|
- @Prop({ required: true })
|
|
|
|
|
- totalEntries!: number;
|
|
|
|
|
|
|
+ export default defineComponent({
|
|
|
|
|
+ components: {
|
|
|
|
|
+ HueIcon,
|
|
|
|
|
+ DropdownMenu,
|
|
|
|
|
+ DropdownMenuButton
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ props: {
|
|
|
|
|
+ totalEntries: {
|
|
|
|
|
+ type: Number,
|
|
|
|
|
+ required: true
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ emits: ['page-changed'],
|
|
|
|
|
+
|
|
|
|
|
+ setup(): {
|
|
|
|
|
+ presetLimits: number[];
|
|
|
|
|
+ } {
|
|
|
|
|
+ return {
|
|
|
|
|
+ presetLimits: PRESET_LIMITS
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ data(): {
|
|
|
|
|
+ currentPage: number;
|
|
|
|
|
+ limit: number;
|
|
|
|
|
+ } {
|
|
|
|
|
+ return {
|
|
|
|
|
+ currentPage: 1,
|
|
|
|
|
+ limit: DEFAULT_LIMIT
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ offset(): number {
|
|
|
|
|
+ return (this.currentPage - 1) * this.limit;
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ lastDisplayedIndex(): number {
|
|
|
|
|
+ return Math.min(this.offset + this.limit, this.totalEntries - 1);
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ totalPages(): number {
|
|
|
|
|
+ return Math.ceil(this.totalEntries / this.limit) || 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
|
|
|
- currentPage = 1;
|
|
|
|
|
- limit = DEFAULT_LIMIT;
|
|
|
|
|
- presetLimits = PRESET_LIMITS;
|
|
|
|
|
|
|
+ watch: {
|
|
|
|
|
+ currentPage(): void {
|
|
|
|
|
+ this.notifyPageChanged();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
|
|
|
mounted(): void {
|
|
mounted(): void {
|
|
|
this.notifyPageChanged();
|
|
this.notifyPageChanged();
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- get offset(): number {
|
|
|
|
|
- return (this.currentPage - 1) * this.limit;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- get lastDisplayedIndex(): number {
|
|
|
|
|
- return Math.min(this.offset + this.limit, this.totalEntries - 1);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- get totalPages(): number {
|
|
|
|
|
- return Math.ceil(this.totalEntries / this.limit) || 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Watch('currentPage')
|
|
|
|
|
- notifyPageChanged(): void {
|
|
|
|
|
- this.$emit('page-changed', {
|
|
|
|
|
- offset: this.offset,
|
|
|
|
|
- limit: this.limit
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- gotoFirstPage(): void {
|
|
|
|
|
- this.currentPage = 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- gotoPreviousPage(): void {
|
|
|
|
|
- this.currentPage = Math.max(this.currentPage - 1, 1);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- gotoNextPage(): void {
|
|
|
|
|
- this.currentPage = Math.min(this.currentPage + 1, this.totalPages);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- gotoLastPage(): void {
|
|
|
|
|
- this.currentPage = this.totalPages;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setLimit(limit: number): void {
|
|
|
|
|
- if (limit === this.limit) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- const factor = limit / this.limit;
|
|
|
|
|
- this.limit = limit;
|
|
|
|
|
- const lastCurrentPage = this.currentPage;
|
|
|
|
|
- this.currentPage = Math.floor((this.currentPage - 1) / factor) + 1;
|
|
|
|
|
- if (lastCurrentPage === this.currentPage) {
|
|
|
|
|
- this.notifyPageChanged(); // this.limit isn't watched
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ notifyPageChanged(): void {
|
|
|
|
|
+ this.$emit('page-changed', {
|
|
|
|
|
+ offset: this.offset,
|
|
|
|
|
+ limit: this.limit
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ gotoFirstPage(): void {
|
|
|
|
|
+ this.currentPage = 1;
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ gotoPreviousPage(): void {
|
|
|
|
|
+ this.currentPage = Math.max(this.currentPage - 1, 1);
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ gotoNextPage(): void {
|
|
|
|
|
+ this.currentPage = Math.min(this.currentPage + 1, this.totalPages);
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ gotoLastPage(): void {
|
|
|
|
|
+ this.currentPage = this.totalPages;
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ setLimit(limit: number): void {
|
|
|
|
|
+ if (limit === this.limit) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const factor = limit / this.limit;
|
|
|
|
|
+ this.limit = limit;
|
|
|
|
|
+ const lastCurrentPage = this.currentPage;
|
|
|
|
|
+ this.currentPage = Math.floor((this.currentPage - 1) / factor) + 1;
|
|
|
|
|
+ if (lastCurrentPage === this.currentPage) {
|
|
|
|
|
+ this.notifyPageChanged(); // this.limit isn't watched
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ });
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|