add pagination

This commit is contained in:
liangping 2023-05-21 13:41:57 +08:00
parent 5b897002a5
commit 0a4d8bad06
8 changed files with 98 additions and 19 deletions

View File

@ -0,0 +1,42 @@
<script lang="ts" setup>
import TwoFactorAuthDialog from '@/plugins/vuetify/@core/components/TwoFactorAuthDialog.vue';
import { PageRequest } from '@/types';
import type { PropType } from 'vue';
import { computed } from 'vue';
const props = defineProps({
total: { type: Number },
limit: { type: Number },
current: { type: Number, default: 1},
load: { type: Function, required: true },
});
const showSize = 3
const pages = computed(() => {
const pages: {color: string, page: number}[] = []
if(props.total && props.limit && props.total > props.limit) {
let page = 0
while(true) {
page += 1
if( page * props.limit > props.total ) break
if( page > showSize && page < (props.total / props.limit - showSize + 1)) {
if(!(page >= props.current - 1 && page <= props.current + 1)){
continue
}
}
pages.push({
color: page === props.current? 'btn-primary': '',
page: page,
})
}
}
return pages
})
</script>
<template>
<div class="my-5 text-center">
<div v-if="total && limit" class="btn-group">
<button v-for="{page, color} in pages" class="btn btn-md" :class="color" @click="load(page)">{{ page }}</button>
</div>
</div>
</template>

View File

@ -54,7 +54,7 @@ const proposalInfo = ref();
#{{ item?.proposal_id }}</label #{{ item?.proposal_id }}</label
> >
</td> </td>
<td class="w-[35%]"> <td class="w-full">
<div> <div>
<RouterLink <RouterLink
:to="`/${chain.chainName}/gov/${item?.proposal_id}`" :to="`/${chain.chainName}/gov/${item?.proposal_id}`"
@ -69,13 +69,13 @@ const proposalInfo = ref();
</div> </div>
</div> </div>
</td> </td>
<td class="w-[25%]"> <td class="w-60">
<ProposalProcess <ProposalProcess
:pool="staking.pool" :pool="staking.pool"
:tally="item.final_tally_result" :tally="item.final_tally_result"
></ProposalProcess> ></ProposalProcess>
</td> </td>
<td> <td class="w-36">
<div class="pl-4"> <div class="pl-4">
<div <div
class="flex items-center" class="flex items-center"
@ -228,8 +228,8 @@ const proposalInfo = ref();
</div> </div>
<input type="checkbox" id="proposal-detail-modal" class="modal-toggle" /> <input type="checkbox" id="proposal-detail-modal" class="modal-toggle" />
<label for="proposal-detail-modal" class="modal sm:!modal-middle"> <label for="proposal-detail-modal" class="modal">
<label class="modal-box relative" for=""> <label class="modal-box w-11/12 max-w-5xl" for="">
<label <label
for="proposal-detail-modal" for="proposal-detail-modal"
class="btn btn-sm btn-circle absolute right-2 top-2" class="btn btn-sm btn-circle absolute right-2 top-2"

View File

@ -95,7 +95,7 @@ const showDiscord = window.location.host.search("ping.pub") > -1
</div> </div>
<div <div
v-if="item?.badgeContent" v-if="item?.badgeContent"
class="mr-6 badge badge-sm rounded-none" :class="item?.badgeClass" class="mr-6 badge badge-sm" :class="item?.badgeClass"
> >
{{ item?.badgeContent }} {{ item?.badgeContent }}
</div> </div>

View File

@ -8,6 +8,7 @@ import {
type Registry, type Registry,
type AbstractRegistry, type AbstractRegistry,
} from './registry'; } from './registry';
import { PageRequest } from '@/types';
export class BaseRestClient<R extends AbstractRegistry> { export class BaseRestClient<R extends AbstractRegistry> {
endpoint: string; endpoint: string;
@ -98,10 +99,11 @@ export class CosmosRestClient extends BaseRestClient<RequestRegistry> {
async getGovParamsTally() { async getGovParamsTally() {
return this.request(this.registry.gov_params_tally, {}); return this.request(this.registry.gov_params_tally, {});
} }
async getGovProposals(status: string, limit = 20) { async getGovProposals(status: string, page?: PageRequest) {
const query = if(!page) page = new PageRequest()
'?proposal_status={status}&pagination.limit={limit}&pagination.reverse=true&pagination.key='; page.reverse = true
return this.request(this.registry.gov_proposals, { status, limit }, query); const query =`?proposal_status={status}&${page.toQueryString()}`;
return this.request(this.registry.gov_proposals, { status }, query);
} }
async getGovProposal(proposal_id: string) { async getGovProposal(proposal_id: string) {
return this.request(this.registry.gov_proposals_proposal_id, { return this.request(this.registry.gov_proposals_proposal_id, {

View File

@ -42,7 +42,7 @@ import type {
Validator, Validator,
} from '@/types/staking'; } from '@/types/staking';
import type { PaginatedTxs, Tx, TxResponse } from '@/types/tx'; import type { PaginatedTxs, Tx, TxResponse } from '@/types/tx';
import semver from 'semver'
export interface Request<T> { export interface Request<T> {
url: string; url: string;
adapter: (source: any) => T; adapter: (source: any) => T;

View File

@ -2,8 +2,13 @@
import { useGovStore } from '@/stores'; import { useGovStore } from '@/stores';
import ProposalListItem from '@/components/ProposalListItem.vue'; import ProposalListItem from '@/components/ProposalListItem.vue';
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import PaginationBar from '@/components/PaginationBar.vue';
import { PageRequest } from '@/types';
const tab = ref('2'); const tab = ref('2');
const store = useGovStore(); const store = useGovStore();
const pageNo = ref({} as Record<string, number>)
const pageRequest = ref(new PageRequest())
onMounted(() => { onMounted(() => {
store.fetchProposals('2').then((x) => { store.fetchProposals('2').then((x) => {
@ -11,17 +16,25 @@ onMounted(() => {
tab.value = '3'; tab.value = '3';
store.fetchProposals('3'); store.fetchProposals('3');
} }
store.fetchProposals('3');
store.fetchProposals('4');
}); });
}); });
const changeTab = (val: '2' | '3' | '4') => { const changeTab = (val: '2' | '3' | '4') => {
tab.value = val; tab.value = val;
store.fetchProposals(val);
}; };
function page(p: number) {
pageNo.value[tab.value] = p
pageRequest.value.setPage(p)
store.fetchProposals(tab.value, pageRequest.value)
}
</script> </script>
<template> <template>
<div> <div>
<div class="tabs tabs-boxed bg-transparent mb-4"> <div class="tabs tabs-boxed bg-transparent mb-4 text-center">
<a <a
class="tab text-gray-400 uppercase" class="tab text-gray-400 uppercase"
:class="{ 'tab-active': tab === '2' }" :class="{ 'tab-active': tab === '2' }"
@ -42,6 +55,7 @@ const changeTab = (val: '2' | '3' | '4') => {
> >
</div> </div>
<ProposalListItem :proposals="store?.proposals[tab]"/> <ProposalListItem :proposals="store?.proposals[tab]"/>
<PaginationBar :total="store?.proposals[tab]?.pagination?.total" :limit="pageRequest.limit" :current="pageNo[tab]" :load="page"/>
</div> </div>
</template> </template>
<route> <route>

View File

@ -32,10 +32,10 @@ export const useGovStore = defineStore('govStore', {
this.fetchProposals("2"); this.fetchProposals("2");
}, },
async fetchProposals(status: string, pagination?: PageRequest) { async fetchProposals(status: string, pagination?: PageRequest) {
if (!this.loading[status]) { //if (!this.loading[status]) {
this.loading[status] = LoadingStatus.Loading; this.loading[status] = LoadingStatus.Loading;
const proposals = reactive( const proposals = reactive(
await this.blockchain.rpc?.getGovProposals(status) await this.blockchain.rpc?.getGovProposals(status, pagination)
); );
if (status === '2') { if (status === '2') {
proposals?.proposals?.forEach((item) => { proposals?.proposals?.forEach((item) => {
@ -44,7 +44,7 @@ export const useGovStore = defineStore('govStore', {
}); });
if (this.walletstore.currentAddress) { if (this.walletstore.currentAddress) {
try { try {
this.fetchProposalVotesVoter(item.proposal_id,this.walletstore.currentAddress).then((res) => { this.fetchProposalVotesVoter(item.proposal_id, this.walletstore.currentAddress).then((res) => {
item.voterStatus = res?.vote?.option || 'No With Veto' item.voterStatus = res?.vote?.option || 'No With Veto'
}); });
} catch (error) { } catch (error) {
@ -58,7 +58,7 @@ export const useGovStore = defineStore('govStore', {
this.loading[status] = LoadingStatus.Loaded; this.loading[status] = LoadingStatus.Loaded;
this.proposals[status] = proposals; this.proposals[status] = proposals;
} //}
return this.proposals[status]; return this.proposals[status];
}, },
async fetchParams() { async fetchParams() {

View File

@ -15,7 +15,28 @@ export interface Pagination {
} }
export class PageRequest { export class PageRequest {
limit?: number; key?: string;
limit: number;
offset?: number;
count_total: boolean;
reverse?: boolean;
constructor() {
this.limit = 20
this.count_total = true
}
toQueryString() {
const query = []
if(this.key) query.push(`pagination.key=${this.key}`)
if(this.limit) query.push(`pagination.limit=${this.limit}`)
if(this.offset) query.push(`pagination.offset=${this.offset}`)
if(this.count_total) query.push(`pagination.count_total=${this.count_total}`)
if(this.reverse) query.push(`pagination.reverse=${this.reverse}`)
return query.join('&')
}
setPage(page: number) {
if(page >= 1) this.offset = (page - 1) * this.limit
}
} }
export interface PaginatedResponse { export interface PaginatedResponse {