forked from cerc-io/cosmos-explorer
feature: governance list
This commit is contained in:
parent
dec4b82f75
commit
581a3b0e33
@ -7,56 +7,55 @@ import type { PropType } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
proposals: { type: Object as PropType<PaginatedProposals> },
|
||||
})
|
||||
});
|
||||
// const list = computed(()=> proposl)
|
||||
const format = useFormatter()
|
||||
const staking = useStakingStore()
|
||||
const chain = useBlockchain()
|
||||
const format = useFormatter();
|
||||
const staking = useStakingStore();
|
||||
const chain = useBlockchain();
|
||||
function showType(v: string) {
|
||||
if (v) {
|
||||
return v.substring(v.lastIndexOf('.')+1)
|
||||
return v.substring(v.lastIndexOf('.') + 1);
|
||||
}
|
||||
return v
|
||||
return v;
|
||||
}
|
||||
|
||||
const statusMap: Record<string, string> = {
|
||||
PROPOSAL_STATUS_VOTING_PERIOD: 'VOTING',
|
||||
PROPOSAL_STATUS_PASSED: 'PASSED',
|
||||
PROPOSAL_STATUS_REJECTED: 'REJECTED',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<VExpansionPanels variant="accordion">
|
||||
<VExpansionPanel v-for="(x, i) in proposals?.proposals">
|
||||
<VExpansionPanelTitle disable-icon-rotate>
|
||||
<VChip label color="primary" class="mr-2">{{x.proposal_id}}</VChip>
|
||||
<div class="w-100"><VChip label>{{ showType(x.content['@type']) }}</VChip> {{ x.content?.title }}
|
||||
<div class="d-flex mt-1">
|
||||
<small class="text-secondary me-auto"> {{ format.toDay(x.voting_end_time, 'from') }}</small>
|
||||
<ProposalProcess style="width:300px;" :pool="staking.pool" :tally="x.final_tally_result"></ProposalProcess>
|
||||
<span></span>
|
||||
<div class="bg-[#28334e] rounded text-sm">
|
||||
<RouterLink
|
||||
:to="`/${chain.chainName}/gov/${item?.proposal_id}`"
|
||||
v-for="(item, index) in proposals?.proposals"
|
||||
:key="index"
|
||||
class="py-4 px-4 hover:bg-[#353f5a] block rounded cursor-pointer"
|
||||
>
|
||||
<div class="grid grid-cols-6 md:grid-cols-11 flex-1">
|
||||
<div class="text-white mb-3">#{{ item?.proposal_id }}</div>
|
||||
|
||||
<div class="col-span-5 md:pr-10 text-white truncate">
|
||||
{{ item?.content?.title }}
|
||||
</div>
|
||||
|
||||
<div class="col-span-3 mb-3 truncate">
|
||||
<div class="bg-gray-600 text-gray-300 inline-block rounded-full px-2 py-[1px] text-xs">
|
||||
{{ showType(item.content['@type']) }}
|
||||
</div>
|
||||
</div>
|
||||
<template #actions>
|
||||
<VIcon
|
||||
v-if="x.status === 'PROPOSAL_STATUS_PASSED'"
|
||||
icon="mdi-check"
|
||||
color="success"
|
||||
class="ml-2"
|
||||
/>
|
||||
<VIcon
|
||||
v-if="x.status === 'PROPOSAL_STATUS_REJECTED'"
|
||||
icon="mdi-multiply"
|
||||
color="error"
|
||||
class="ml-2"
|
||||
/>
|
||||
</template>
|
||||
</VExpansionPanelTitle>
|
||||
<VExpansionPanelText>
|
||||
<VCard class="card-box">
|
||||
<VCardText>
|
||||
<MdEditor :model-value="format.multiLine(x.content?.description)" previewOnly></MdEditor>
|
||||
</VCardText>
|
||||
<div class="text-center w-100 my-2">
|
||||
<VBtn :to="`/${chain.chainName}/gov/${x.proposal_id}`" color="primary" variant="flat" size="small">Detail</VBtn>
|
||||
<VBtn color="primary" variant="flat" class="ml-2" size="small">Vote</VBtn>
|
||||
</div>
|
||||
</VCard>
|
||||
</VExpansionPanelText>
|
||||
</VExpansionPanel>
|
||||
</VExpansionPanels>
|
||||
|
||||
<div class="text-yes flex items-center mb-3">
|
||||
<div class="w-1 h-1 bg-yes rounded-full mr-2"></div>
|
||||
<div class="text-xs">{{ statusMap?.[item?.status] || item?.status }}</div>
|
||||
</div>
|
||||
|
||||
<div class="truncate mb-3 col-span-2 md:col-span-1 text-right md:flex md:justify-start">
|
||||
{{ format.toDay(item.voting_end_time, 'from') }}
|
||||
</div>
|
||||
</div>
|
||||
<ProposalProcess :pool="staking.pool" :tally="item.final_tally_result"></ProposalProcess>
|
||||
</RouterLink>
|
||||
</div>
|
||||
</template>
|
@ -2,8 +2,7 @@
|
||||
import { useFormatter } from '@/stores';
|
||||
import type { Tally } from '@/types';
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { ref, type PropType } from 'vue';
|
||||
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
tally: { type: Object as PropType<Tally> },
|
||||
@ -13,41 +12,26 @@ const props = defineProps({
|
||||
bonded_tokens: string;
|
||||
}>,
|
||||
},
|
||||
})
|
||||
const total = computed(() => props.pool?.bonded_tokens)
|
||||
const format = useFormatter()
|
||||
const yes = computed(() => (format.calculatePercent(props.tally?.yes, total.value)))
|
||||
const no = computed(() => ref(format.calculatePercent(props.tally?.no, total.value)))
|
||||
const abstain = computed(() => (format.calculatePercent(props.tally?.abstain, total.value)))
|
||||
const veto = computed(() => (format.calculatePercent(props.tally?.no_with_veto, total.value)))
|
||||
|
||||
});
|
||||
const total = computed(() => props.pool?.bonded_tokens);
|
||||
const format = useFormatter();
|
||||
const yes = computed(() => format.calculatePercent(props.tally?.yes, total.value));
|
||||
const no = computed(() => format.calculatePercent(props.tally?.no, total.value));
|
||||
const abstain = computed(() => format.calculatePercent(props.tally?.abstain, total.value));
|
||||
const veto = computed(() => format.calculatePercent(props.tally?.no_with_veto, total.value));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-success" :style="`width: ${yes}`"> {{ yes }}</div>
|
||||
<div class="progress-bar bg-error" :style="`width: ${no}`">{{ no }} </div>
|
||||
<div class="progress-bar " :style="`width: ${veto}; background-color: #B71C1C;`"> {{ veto }} </div>
|
||||
<div class="progress-bar bg-secondary" :style="`width: ${abstain}`"> </div>
|
||||
<div class="progress rounded-full h-1 text-xs">
|
||||
<div class="h-1 bg-yes" :style="`width: ${yes}`"></div>
|
||||
<div class="h-1 bg-no" :style="`width: ${no}`"></div>
|
||||
<div class="h-1" :style="`width: ${veto}; background-color: #B71C1C;`"></div>
|
||||
<div class="h-1 bg-secondary" :style="`width: ${abstain}`"></div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.progress {
|
||||
height: 0.8rem;
|
||||
overflow: hidden;
|
||||
background-color: rgba(128, 128, 128, 0.178);
|
||||
}
|
||||
.progress-bar {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
}
|
||||
.progress :first-child {
|
||||
border-radius: 0px !important;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
}
|
||||
.progress :last-child {
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
</style>
|
@ -1,41 +1,42 @@
|
||||
<script lang="ts" setup>
|
||||
import { useThemeConfig } from '@/plugins/vuetify/@core/composable/useThemeConfig'
|
||||
import { useThemeConfig } from '@/plugins/vuetify/@core/composable/useThemeConfig';
|
||||
|
||||
// Components
|
||||
import Footer from '@/layouts/components/Footer.vue'
|
||||
import NavbarThemeSwitcher from '@/layouts/components/NavbarThemeSwitcher.vue'
|
||||
import UserProfile from '@/layouts/components/ChainProfile.vue'
|
||||
import Footer from '@/layouts/components/Footer.vue';
|
||||
import NavbarThemeSwitcher from '@/layouts/components/NavbarThemeSwitcher.vue';
|
||||
import UserProfile from '@/layouts/components/ChainProfile.vue';
|
||||
|
||||
import { useDashboard } from '@/stores/useDashboard'
|
||||
import { useDashboard } from '@/stores/useDashboard';
|
||||
|
||||
// @layouts plugin
|
||||
import { VerticalNavLayout } from '@layouts'
|
||||
import NavBarI18n from './NavBarI18n.vue'
|
||||
import NavSearchBar from './NavSearchBar.vue'
|
||||
import NavBarNotifications from './NavBarNotifications.vue'
|
||||
import TheCustomizer from '@/plugins/vuetify/@core/components/TheCustomizer.vue'
|
||||
import Breadcrumbs from './Breadcrumbs.vue'
|
||||
import { useBlockchain } from '@/stores'
|
||||
import { VerticalNavLayout } from '@layouts';
|
||||
import NavBarI18n from './NavBarI18n.vue';
|
||||
import NavSearchBar from './NavSearchBar.vue';
|
||||
import NavBarNotifications from './NavBarNotifications.vue';
|
||||
import TheCustomizer from '@/plugins/vuetify/@core/components/TheCustomizer.vue';
|
||||
import Breadcrumbs from './Breadcrumbs.vue';
|
||||
import { useBlockchain } from '@/stores';
|
||||
|
||||
const { appRouteTransition, isLessThanOverlayNavBreakpoint, isVerticalNavCollapsed } = useThemeConfig()
|
||||
const { width: windowWidth } = useWindowSize()
|
||||
const { appRouteTransition, isLessThanOverlayNavBreakpoint, isVerticalNavCollapsed } =
|
||||
useThemeConfig();
|
||||
const { width: windowWidth } = useWindowSize();
|
||||
|
||||
// ℹ️ Provide animation name for vertical nav collapse icon.
|
||||
const verticalNavHeaderActionAnimationName = ref<null | 'rotate-180' | 'rotate-back-180'>(null)
|
||||
const verticalNavHeaderActionAnimationName = ref<null | 'rotate-180' | 'rotate-back-180'>(null);
|
||||
|
||||
watch(isVerticalNavCollapsed, val => {
|
||||
verticalNavHeaderActionAnimationName.value = val ? 'rotate-180' : 'rotate-back-180'
|
||||
})
|
||||
verticalNavHeaderActionAnimationName.value = val ? 'rotate-180' : 'rotate-back-180';
|
||||
});
|
||||
|
||||
const dashboard = useDashboard()
|
||||
dashboard.initial()
|
||||
const blockchain = useBlockchain()
|
||||
const dashboard = useDashboard();
|
||||
dashboard.initial();
|
||||
const blockchain = useBlockchain();
|
||||
// blockchain.initial()
|
||||
blockchain.$subscribe((m, s) => {
|
||||
if (!Array.isArray(m.events) && m.events.key === 'chainName') {
|
||||
blockchain.initial()
|
||||
blockchain.initial();
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -43,8 +44,11 @@ blockchain.$subscribe((m, s) => {
|
||||
<!-- 👉 navbar -->
|
||||
<template #navbar="{ toggleVerticalOverlayNavActive }">
|
||||
<div class="d-flex h-100 align-center">
|
||||
<IconBtn v-if="isLessThanOverlayNavBreakpoint(windowWidth)" class="ms-n3"
|
||||
@click="toggleVerticalOverlayNavActive(true)">
|
||||
<IconBtn
|
||||
v-if="isLessThanOverlayNavBreakpoint(windowWidth)"
|
||||
class="ms-n3"
|
||||
@click="toggleVerticalOverlayNavActive(true)"
|
||||
>
|
||||
<VIcon icon="mdi-menu" />
|
||||
</IconBtn>
|
||||
|
||||
@ -52,9 +56,9 @@ blockchain.$subscribe((m, s) => {
|
||||
|
||||
<VSpacer />
|
||||
<!-- <NavSearchBar />-->
|
||||
<NavBarNotifications />
|
||||
<NavBarI18n />
|
||||
<NavbarThemeSwitcher />
|
||||
<NavBarNotifications class="hidden md:inline-block" />
|
||||
<NavBarI18n class="hidden md:inline-block" />
|
||||
<NavbarThemeSwitcher class="hidden md:inline-block" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -5,7 +5,13 @@ module.exports = {
|
||||
"./src/**/*.{vue,js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
extend: {
|
||||
colors: {
|
||||
main: '#5973fe',
|
||||
yes: '#3fb68b',
|
||||
no: '#ff5353',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user