Merge pull request #362 from alisaweb3/v3-single
Governance Data Improve
This commit is contained in:
commit
85f6e48c50
9
.prettierrc.json
Normal file
9
.prettierrc.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
|
"singleQuote": true,
|
||||||
|
"semi": true,
|
||||||
|
"endOfLine": "auto",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"TrailingCooma": true,
|
||||||
|
"arrowParens": "always"
|
||||||
|
}
|
@ -37,10 +37,7 @@ const veto = computed(() =>
|
|||||||
<div class="progress">
|
<div class="progress">
|
||||||
<div class="progress-bar bg-success" :style="`width: ${yes}`"></div>
|
<div class="progress-bar bg-success" :style="`width: ${yes}`"></div>
|
||||||
<div class="progress-bar bg-error" :style="`width: ${no}`"></div>
|
<div class="progress-bar bg-error" :style="`width: ${no}`"></div>
|
||||||
<div
|
<div class="progress-bar bg-[#B71C1C]" :style="`width: ${veto};`"></div>
|
||||||
class="progress-bar"
|
|
||||||
:style="`width: ${veto}; background-color: #B71C1C;`"
|
|
||||||
></div>
|
|
||||||
<div class="progress-bar bg-secondary" :style="`width: ${abstain}`"></div>
|
<div class="progress-bar bg-secondary" :style="`width: ${abstain}`"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,74 +1,87 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import TxsElement from '@/components/dynamic/TxsElement.vue';
|
import TxsElement from "@/components/dynamic/TxsElement.vue";
|
||||||
import { useBlockModule } from './block'
|
import { useBlockModule } from "./block";
|
||||||
import DynamicComponent from '@/components/dynamic/DynamicComponent.vue';
|
import DynamicComponent from "@/components/dynamic/DynamicComponent.vue";
|
||||||
import { computed } from '@vue/reactivity';
|
import { computed } from "@vue/reactivity";
|
||||||
import { toBase64, toHex } from '@cosmjs/encoding';
|
import { toBase64, toHex } from "@cosmjs/encoding";
|
||||||
import { useFormatter } from '@/stores';
|
import { useFormatter } from "@/stores";
|
||||||
const props = defineProps(["height", "chain"]);
|
const props = defineProps(["height", "chain"]);
|
||||||
|
|
||||||
const store = useBlockModule()
|
const store = useBlockModule();
|
||||||
store.fetchBlock(props.height)
|
store.fetchBlock(props.height);
|
||||||
const tab = ref('blocks')
|
const tab = ref("blocks");
|
||||||
|
|
||||||
const format = useFormatter()
|
const format = useFormatter();
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
<VCard>
|
||||||
<VCard>
|
<VCardTitle class="d-flex justify-space-between">
|
||||||
<VCardTitle class="d-flex justify-space-between">
|
<VTabs v-model="tab">
|
||||||
<VTabs v-model="tab">
|
<VTab value="blocks">Blocks</VTab>
|
||||||
<VTab value="blocks">Blocks</VTab>
|
<VTab value="transactions">Transactions</VTab>
|
||||||
<VTab value="transactions">Transactions</VTab>
|
</VTabs>
|
||||||
</VTabs>
|
</VCardTitle>
|
||||||
</VCardTitle>
|
<VWindow v-model="tab">
|
||||||
<VWindow v-model="tab">
|
<VWindowItem value="blocks">
|
||||||
<VWindowItem value="blocks">
|
<VTable>
|
||||||
<VTable>
|
<thead>
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<th>Height</th>
|
||||||
<th>Height</th><th>Hash</th><th>Proposor</th><th>Txs</th><th>Time</th>
|
<th>Hash</th>
|
||||||
</tr>
|
<th>Proposor</th>
|
||||||
</thead>
|
<th>Txs</th>
|
||||||
<tbody>
|
<th>Time</th>
|
||||||
<tr v-for="item in store.recents">
|
</tr>
|
||||||
<td><RouterLink :to="`/${props.chain}/block/${item.block?.header?.height}`">{{ item.block?.header?.height }}</RouterLink></td>
|
</thead>
|
||||||
<td>{{ toBase64(item.blockId?.hash) }}</td>
|
<tbody>
|
||||||
<td>{{ format.validator(item.block?.header?.proposerAddress) }}</td>
|
<tr v-for="item in store.recents">
|
||||||
<td>{{ item.block?.data?.txs.length }}</td>
|
<td>
|
||||||
<td>{{ format.toDay(item.block?.header?.time, 'from') }}</td>
|
<RouterLink
|
||||||
</tr>
|
:to="`/${props.chain}/block/${item.block?.header?.height}`"
|
||||||
</tbody>
|
>{{ item.block?.header?.height }}</RouterLink
|
||||||
</VTable>
|
>
|
||||||
</VWindowItem>
|
</td>
|
||||||
<VWindowItem value="transactions">
|
<td>{{ toBase64(item.blockId?.hash) }}</td>
|
||||||
<VTable>
|
<td>
|
||||||
<thead>
|
{{ format.validator(item.block?.header?.proposerAddress) }}
|
||||||
<tr>
|
</td>
|
||||||
<th>Hash</th><th>Messages</th><th>Fees</th>
|
<td>{{ item.block?.data?.txs.length }}</td>
|
||||||
</tr>
|
<td>{{ format.toDay(item.block?.header?.time, "from") }}</td>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</tbody>
|
||||||
<tr v-for="item in store.txsInRecents">
|
</VTable>
|
||||||
<td><RouterLink :to="`/${props.chain}/tx/${item.hash}`">{{ item.hash }}</RouterLink></td>
|
</VWindowItem>
|
||||||
<td>{{ format.messages(item.tx.body.messages) }}</td>
|
<VWindowItem value="transactions">
|
||||||
<td>{{ format.formatTokens(item.tx.authInfo.fee?.amount) }}</td>
|
<VTable>
|
||||||
</tr>
|
<thead>
|
||||||
</tbody>
|
<tr>
|
||||||
</VTable>
|
<th>Hash</th>
|
||||||
|
<th>Messages</th>
|
||||||
|
<th>Fees</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="item in store.txsInRecents">
|
||||||
|
<td>
|
||||||
|
<RouterLink :to="`/${props.chain}/tx/${item.hash}`">{{
|
||||||
|
item.hash
|
||||||
|
}}</RouterLink>
|
||||||
|
</td>
|
||||||
|
<td>{{ format.messages(item.tx.body.messages) }}</td>
|
||||||
|
<td>{{ format.formatTokens(item.tx.authInfo.fee?.amount) }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</VTable>
|
||||||
|
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<v-alert
|
<v-alert
|
||||||
type="info"
|
type="info"
|
||||||
text="Only show txs in recent blocks"
|
text="Only show txs in recent blocks"
|
||||||
variant="tonal"
|
variant="tonal"
|
||||||
></v-alert>
|
></v-alert>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
</VWindow>
|
</VWindow>
|
||||||
<VCardActions>
|
<VCardActions> </VCardActions>
|
||||||
|
</VCard>
|
||||||
</VCardActions>
|
</template>
|
||||||
</VCard>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
@ -1,40 +1,45 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import MdEditor from 'md-editor-v3';
|
import MdEditor from "md-editor-v3";
|
||||||
import PriceMarketChart from '@/components/charts/PriceMarketChart.vue'
|
import PriceMarketChart from "@/components/charts/PriceMarketChart.vue";
|
||||||
|
|
||||||
import { useBlockchain, useFormatter } from '@/stores';
|
import { useBlockchain, useFormatter } from "@/stores";
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from "vue";
|
||||||
import { useIndexModule } from './indexStore';
|
import { useIndexModule } from "./indexStore";
|
||||||
import { computed } from '@vue/reactivity';
|
import { computed } from "@vue/reactivity";
|
||||||
|
|
||||||
import CardStatisticsVertical from '@/components/CardStatisticsVertical.vue';
|
import CardStatisticsVertical from "@/components/CardStatisticsVertical.vue";
|
||||||
import ProposalProcess from '@/components/ProposalProcess.vue';
|
import ProposalProcess from "@/components/ProposalProcess.vue";
|
||||||
|
|
||||||
const blockchain = useBlockchain()
|
const blockchain = useBlockchain();
|
||||||
const store = useIndexModule()
|
const store = useIndexModule();
|
||||||
|
|
||||||
const coinInfo = computed(() => {
|
const coinInfo = computed(() => {
|
||||||
return store.coinInfo
|
return store.coinInfo;
|
||||||
})
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
store.loadDashboard()
|
store.loadDashboard();
|
||||||
})
|
});
|
||||||
|
|
||||||
const format = useFormatter()
|
const format = useFormatter();
|
||||||
const ticker = computed(() => store.coinInfo.tickers[store.tickerIndex])
|
const ticker = computed(() => store.coinInfo.tickers[store.tickerIndex]);
|
||||||
|
|
||||||
blockchain.$subscribe((m, s) => {
|
blockchain.$subscribe((m, s) => {
|
||||||
console.log('index:', m)
|
console.log("index:", m);
|
||||||
if(!Array.isArray(m.events) && ['chainName', 'endpoint'].includes(m.events.key)) {
|
if (
|
||||||
console.log(m.events.key)
|
!Array.isArray(m.events) &&
|
||||||
store.loadDashboard()
|
["chainName", "endpoint"].includes(m.events.key)
|
||||||
|
) {
|
||||||
|
console.log(m.events.key);
|
||||||
|
store.loadDashboard();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
function shortName(name: string, id: string) {
|
function shortName(name: string, id: string) {
|
||||||
return name.toLowerCase().startsWith('ibc/') || name.toLowerCase().startsWith('0x') ? id: name
|
return name.toLowerCase().startsWith("ibc/") ||
|
||||||
|
name.toLowerCase().startsWith("0x")
|
||||||
|
? id
|
||||||
|
: name;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -44,58 +49,97 @@ function shortName(name: string, id: string) {
|
|||||||
<VCol md="5">
|
<VCol md="5">
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<VCardTitle>
|
<VCardTitle>
|
||||||
{{ coinInfo.name }} (<span class="text-uppercase">{{ coinInfo.symbol }}</span>)
|
{{ coinInfo.name }} (<span class="text-uppercase">{{
|
||||||
|
coinInfo.symbol
|
||||||
|
}}</span
|
||||||
|
>)
|
||||||
</VCardTitle>
|
</VCardTitle>
|
||||||
<VCardSubtitle>
|
<VCardSubtitle>
|
||||||
Rank: <VChip color="error" size="x-small">#{{ coinInfo.market_cap_rank }}</VChip>
|
Rank:
|
||||||
|
<VChip color="error" size="x-small"
|
||||||
|
>#{{ coinInfo.market_cap_rank }}</VChip
|
||||||
|
>
|
||||||
</VCardSubtitle>
|
</VCardSubtitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider/>
|
<VDivider />
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<VBtn variant="text" size="small" :href="store.homepage" prependIcon="mdi-web">Website</VBtn>
|
<VBtn
|
||||||
<VBtn variant="text" size="small" :href="store.twitter" prependIcon="mdi-twitter">Twitter</VBtn>
|
variant="text"
|
||||||
<VBtn variant="text" size="small" :href="store.telegram" prependIcon="mdi-telegram">Telegram</VBtn>
|
size="small"
|
||||||
<VBtn variant="text" size="small" :href="store.github" prependIcon="mdi-github">Github</VBtn>
|
:href="store.homepage"
|
||||||
|
prependIcon="mdi-web"
|
||||||
|
>Website</VBtn
|
||||||
|
>
|
||||||
|
<VBtn
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
:href="store.twitter"
|
||||||
|
prependIcon="mdi-twitter"
|
||||||
|
>Twitter</VBtn
|
||||||
|
>
|
||||||
|
<VBtn
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
:href="store.telegram"
|
||||||
|
prependIcon="mdi-telegram"
|
||||||
|
>Telegram</VBtn
|
||||||
|
>
|
||||||
|
<VBtn
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
:href="store.github"
|
||||||
|
prependIcon="mdi-github"
|
||||||
|
>Github</VBtn
|
||||||
|
>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<!-- SECTION upgrade plan banner -->
|
<!-- SECTION upgrade plan banner -->
|
||||||
<div class="plan-upgrade-banner d-flex bg-light-secondary rounded align-center pa-3">
|
<div
|
||||||
<h3
|
class="plan-upgrade-banner d-flex bg-light-secondary rounded align-center pa-3"
|
||||||
class="plan-details me-3"
|
>
|
||||||
:class="store.priceColor"
|
<h3 class="plan-details me-3" :class="store.priceColor">
|
||||||
>
|
|
||||||
{{ store.priceChange }}<small>%</small>
|
{{ store.priceChange }}<small>%</small>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<VMenu open-on-hover>
|
<VMenu open-on-hover>
|
||||||
<template #activator="{ props }">
|
<template #activator="{ props }">
|
||||||
<div class="d-flex flex-column align-start" v-bind="props">
|
<div class="d-flex flex-column align-start" v-bind="props">
|
||||||
<h3 class="text-base font-weight-semibold">
|
<h3 class="text-base font-weight-semibold">
|
||||||
{{ ticker?.market?.name || ''}}
|
{{ ticker?.market?.name || "" }}
|
||||||
</h3>
|
</h3>
|
||||||
<span class="text-primary text-xs">{{ shortName(ticker?.base, ticker.coin_id) }}/{{ shortName(ticker?.target, ticker.target_coin_id) }}</span>
|
<span class="text-primary text-xs"
|
||||||
|
>{{ shortName(ticker?.base, ticker.coin_id) }}/{{
|
||||||
|
shortName(ticker?.target, ticker.target_coin_id)
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<VList style="max-height: 300px;">
|
<VList style="max-height: 300px">
|
||||||
<VListItem
|
<VListItem
|
||||||
v-for="(item, i) in store.coinInfo.tickers"
|
v-for="(item, i) in store.coinInfo.tickers"
|
||||||
:key="i"
|
:key="i"
|
||||||
rounded
|
rounded
|
||||||
@click="store.selectTicker(i)"
|
@click="store.selectTicker(i)"
|
||||||
>
|
>
|
||||||
<template #prepend>
|
<template #prepend> </template>
|
||||||
</template>
|
|
||||||
<!-- eslint-disable-next-line vue/no-v-text-v-html-on-component -->
|
<!-- eslint-disable-next-line vue/no-v-text-v-html-on-component -->
|
||||||
<VListItemTitle v-text="item.market.name" />
|
<VListItemTitle v-text="item.market.name" />
|
||||||
<VListItemSubtitle>{{ shortName(item?.base, item.coin_id) }}/{{ shortName(item?.target, item.target_coin_id) }}</VListItemSubtitle>
|
<VListItemSubtitle
|
||||||
|
>{{ shortName(item?.base, item.coin_id) }}/{{
|
||||||
|
shortName(item?.target, item.target_coin_id)
|
||||||
|
}}</VListItemSubtitle
|
||||||
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
<span class="ml-3" :class="`text-${store.tickerColor(item.trust_score)}`">{{ item.converted_last.usd }}</span>
|
<span
|
||||||
|
class="ml-3"
|
||||||
|
:class="`text-${store.tickerColor(item.trust_score)}`"
|
||||||
|
>{{ item.converted_last.usd }}</span
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
</VListItem>
|
</VListItem>
|
||||||
</VList>
|
</VList>
|
||||||
</VMenu>
|
</VMenu>
|
||||||
|
|
||||||
|
|
||||||
<VSpacer />
|
<VSpacer />
|
||||||
|
|
||||||
<div class="d-flex align-center">
|
<div class="d-flex align-center">
|
||||||
@ -107,14 +151,14 @@ function shortName(name: string, id: string) {
|
|||||||
</div>
|
</div>
|
||||||
<!-- !SECTION -->
|
<!-- !SECTION -->
|
||||||
<VSpacer />
|
<VSpacer />
|
||||||
<VBtn
|
<VBtn
|
||||||
block
|
block
|
||||||
:color="store.trustColor"
|
:color="store.trustColor"
|
||||||
class="mt-3"
|
class="mt-3"
|
||||||
:href="ticker.trade_url"
|
:href="ticker.trade_url"
|
||||||
>
|
>
|
||||||
Buy {{ coinInfo.symbol || '' }}
|
Buy {{ coinInfo.symbol || "" }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol md="7">
|
<VCol md="7">
|
||||||
@ -124,9 +168,16 @@ function shortName(name: string, id: string) {
|
|||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
<VDivider />
|
<VDivider />
|
||||||
<VCardText class="" style="max-height: 250px; overflow:auto;"><MdEditor :model-value="coinInfo.description?.en" previewOnly></MdEditor></VCardText>
|
<VCardText class="" style="max-height: 250px; overflow: auto"
|
||||||
|
><MdEditor
|
||||||
|
:model-value="coinInfo.description?.en"
|
||||||
|
previewOnly
|
||||||
|
></MdEditor
|
||||||
|
></VCardText>
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<VChip v-for="tag in coinInfo.categories" size="x-small" class="mr-2">{{ tag }}</VChip>
|
<VChip v-for="tag in coinInfo.categories" size="x-small" class="mr-2">{{
|
||||||
|
tag
|
||||||
|
}}</VChip>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|
||||||
@ -139,46 +190,56 @@ function shortName(name: string, id: string) {
|
|||||||
</VRow>
|
</VRow>
|
||||||
|
|
||||||
<VCard class="my-5">
|
<VCard class="my-5">
|
||||||
<VCardItem class="pb-0">
|
<VCardItem class="pb-0">
|
||||||
<VCardTitle>Active Proposals</VCardTitle>
|
<VCardTitle>Active Proposals</VCardTitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<VExpansionPanels variant="accordion">
|
<VExpansionPanels variant="accordion">
|
||||||
<VExpansionPanel v-for="(x, i) in store.proposals">
|
<VExpansionPanel v-for="(x, i) in store.proposals">
|
||||||
<VExpansionPanelTitle disable-icon-rotate>
|
<VExpansionPanelTitle disable-icon-rotate>
|
||||||
<VChip label color="primary" class="mr-2">{{x.proposalId}}</VChip>
|
<VChip label color="primary" class="mr-2">{{
|
||||||
<div class="w-100">{{ x.content?.title }}
|
x.proposalId
|
||||||
<div class="d-flex mt-1">
|
}}</VChip>
|
||||||
<small class="text-secondary me-auto"> {{ format.toDay(x.votingEndTime, 'from') }}</small>
|
<div class="w-100">
|
||||||
<ProposalProcess style="width:300px;" :pool="store.pool" :tally="store.tally[Number(x.proposalId)]"></ProposalProcess>
|
{{ x.content?.title }}
|
||||||
<span></span>
|
<div class="d-flex mt-1">
|
||||||
</div>
|
<small class="text-secondary me-auto">
|
||||||
</div>
|
{{ format.toDay(x.votingEndTime, "from") }}</small
|
||||||
<template #actions>
|
>
|
||||||
<VIcon
|
<ProposalProcess
|
||||||
icon="mdi-check"
|
style="width: 300px"
|
||||||
color="success"
|
:pool="store.pool"
|
||||||
class="ml-2"
|
:tally="store.tally[Number(x.proposalId)]"
|
||||||
/>
|
></ProposalProcess>
|
||||||
</template>
|
<span></span>
|
||||||
</VExpansionPanelTitle>
|
</div>
|
||||||
<VExpansionPanelText>
|
</div>
|
||||||
<VCard class="card-box">
|
<template #actions>
|
||||||
<VCardText>
|
<VIcon icon="mdi-check" color="success" class="ml-2" />
|
||||||
<MdEditor :model-value="x.content?.description" previewOnly></MdEditor>
|
</template>
|
||||||
</VCardText>
|
</VExpansionPanelTitle>
|
||||||
<div class="text-center w-100 my-2">
|
<VExpansionPanelText>
|
||||||
<VBtn color="primary" variant="flat">Vote</VBtn>
|
<VCard class="card-box">
|
||||||
</div>
|
<VCardText>
|
||||||
</VCard>
|
<MdEditor
|
||||||
</VExpansionPanelText>
|
:model-value="x.content?.description"
|
||||||
</VExpansionPanel>
|
previewOnly
|
||||||
</VExpansionPanels>
|
></MdEditor>
|
||||||
</VCardItem>
|
</VCardText>
|
||||||
<VCardText v-if="store.proposals.length === 0">No active proposals</VCardText>
|
<div class="text-center w-100 my-2">
|
||||||
|
<VBtn color="primary" variant="flat">Vote</VBtn>
|
||||||
|
</div>
|
||||||
|
</VCard>
|
||||||
|
</VExpansionPanelText>
|
||||||
|
</VExpansionPanel>
|
||||||
|
</VExpansionPanels>
|
||||||
|
</VCardItem>
|
||||||
|
<VCardText v-if="store.proposals.length === 0"
|
||||||
|
>No active proposals</VCardText
|
||||||
|
>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|
||||||
<VBtn block color='secondary' variant="outlined" class="mt-5">
|
<VBtn block color="secondary" variant="outlined" class="mt-5">
|
||||||
Connect Wallet
|
Connect Wallet
|
||||||
</VBtn>
|
</VBtn>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,29 +1,44 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import misc404 from '@images/pages/404.png'
|
import misc404 from "@images/pages/404.png";
|
||||||
|
|
||||||
import miscObj from '@images/pages/misc-404-object.png'
|
import miscObj from "@images/pages/misc-404-object.png";
|
||||||
import miscMaskDark from '@images/pages/misc-mask-dark.png'
|
import miscMaskDark from "@images/pages/misc-mask-dark.png";
|
||||||
import miscMaskLight from '@images/pages/misc-mask-light.png'
|
import miscMaskLight from "@images/pages/misc-mask-light.png";
|
||||||
|
|
||||||
import { useGenerateImageVariant } from '@/plugins/vuetify/@core/composable/useGenerateImageVariant'
|
import { useGenerateImageVariant } from "@/plugins/vuetify/@core/composable/useGenerateImageVariant";
|
||||||
|
|
||||||
const miscThemeMask = useGenerateImageVariant(miscMaskLight, miscMaskDark)
|
const miscThemeMask = useGenerateImageVariant(miscMaskLight, miscMaskDark);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="misc-wrapper">
|
<div class="misc-wrapper">
|
||||||
<ErrorHeader error-code="404" error-title="Page Not Found ⚠️"
|
<ErrorHeader
|
||||||
error-description="We couldn't find the page you are looking for." />
|
error-code="404"
|
||||||
|
error-title="Page Not Found ⚠️"
|
||||||
|
error-description="We couldn't find the page you are looking for."
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 👉 Image -->
|
<!-- 👉 Image -->
|
||||||
<div class="misc-avatar w-100 text-center">
|
<div class="misc-avatar w-100 text-center">
|
||||||
<VImg :src="misc404" alt="Coming Soon" :height="$vuetify.display.xs ? 400 : 500" class="my-sm-4" />
|
<VImg
|
||||||
<VBtn to="/" class="mt-10">
|
:src="misc404"
|
||||||
Back to Home
|
alt="Coming Soon"
|
||||||
</VBtn>
|
:height="$vuetify.display.xs ? 400 : 500"
|
||||||
<VImg :src="miscThemeMask" class="d-none d-md-block footer-coming-soon" cover />
|
class="my-sm-4"
|
||||||
|
/>
|
||||||
|
<VBtn to="/" class="mt-10"> Back to Home </VBtn>
|
||||||
|
<VImg
|
||||||
|
:src="miscThemeMask"
|
||||||
|
class="d-none d-md-block footer-coming-soon"
|
||||||
|
cover
|
||||||
|
/>
|
||||||
|
|
||||||
<VImg :src="miscObj" class="d-none d-md-block footer-coming-soon-obj" :max-width="174" height="158" />
|
<VImg
|
||||||
|
:src="miscObj"
|
||||||
|
class="d-none d-md-block footer-coming-soon-obj"
|
||||||
|
:max-width="174"
|
||||||
|
height="158"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"add_to_favorite": "Add to favorite"
|
"add_to_favorite": "Add to favorite"
|
||||||
},
|
},
|
||||||
"Ecosystem": "Ecosystem",
|
"Ecosystem": "Ecosystem",
|
||||||
"All Blockchains": "All Blockchain222",
|
"All Blockchains": "All Blockchain",
|
||||||
"Favorite": "Favorite"
|
"Favorite": "Favorite"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,38 +1,30 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string
|
title: string;
|
||||||
color?: string
|
color?: string;
|
||||||
icon: string
|
icon: string;
|
||||||
stats: string
|
stats: string;
|
||||||
change?: number
|
change?: number;
|
||||||
subtitle?: string
|
subtitle?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
color: 'primary',
|
color: 'primary',
|
||||||
})
|
});
|
||||||
|
|
||||||
const isPositive = controlledComputed(() => props.change, () => Math.sign(props.change||0) === 1)
|
const isPositive = controlledComputed(
|
||||||
|
() => props.change,
|
||||||
|
() => Math.sign(props.change || 0) === 1
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VCard>
|
<VCard class="h-full flex-col content-between">
|
||||||
<VCardText class="d-flex align-center justify-center">
|
<VCardText class="d-flex align-center justify-between">
|
||||||
<VAvatar
|
<VAvatar v-if="props.icon" rounded size="38" variant="tonal" :color="props.color">
|
||||||
v-if="props.icon"
|
<VIcon :icon="props.icon" size="24" />
|
||||||
rounded
|
|
||||||
size="38"
|
|
||||||
variant="tonal"
|
|
||||||
:color="props.color"
|
|
||||||
>
|
|
||||||
<VIcon
|
|
||||||
:icon="props.icon"
|
|
||||||
size="24"
|
|
||||||
/>
|
|
||||||
</VAvatar>
|
</VAvatar>
|
||||||
|
|
||||||
<VSpacer />
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="props.change"
|
v-if="props.change"
|
||||||
:class="isPositive ? 'text-success' : 'text-error'"
|
:class="isPositive ? 'text-success' : 'text-error'"
|
||||||
@ -44,7 +36,7 @@ const isPositive = controlledComputed(() => props.change, () => Math.sign(props.
|
|||||||
</div>
|
</div>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
|
|
||||||
<VCardText>
|
<VCardText class="d-flex flex-col">
|
||||||
<h6 class="text-h6 me-2 mt-2 mb-1">
|
<h6 class="text-h6 me-2 mt-2 mb-1">
|
||||||
{{ props.stats }}
|
{{ props.stats }}
|
||||||
</h6>
|
</h6>
|
||||||
@ -52,11 +44,7 @@ const isPositive = controlledComputed(() => props.change, () => Math.sign(props.
|
|||||||
{{ props.title }}
|
{{ props.title }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<VChip
|
<VChip v-if="props.subtitle" size="x-small" class="font-weight-medium">
|
||||||
v-if="props.subtitle"
|
|
||||||
size="x-small"
|
|
||||||
class="font-weight-medium"
|
|
||||||
>
|
|
||||||
<span class="text-truncate">{{ props.subtitle }}</span>
|
<span class="text-truncate">{{ props.subtitle }}</span>
|
||||||
</VChip>
|
</VChip>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import MdEditor from 'md-editor-v3';
|
|
||||||
import { useBlockchain, useFormatter, useStakingStore } from '@/stores';
|
import { useBlockchain, useFormatter, useStakingStore } from '@/stores';
|
||||||
import type { GovProposal, PaginatedProposals } from '@/types';
|
import type { PaginatedProposals } from '@/types';
|
||||||
import ProposalProcess from './ProposalProcess.vue';
|
import ProposalProcess from './ProposalProcess.vue';
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
|
|
||||||
const props = defineProps({
|
defineProps({
|
||||||
proposals: { type: Object as PropType<PaginatedProposals> },
|
proposals: { type: Object as PropType<PaginatedProposals> },
|
||||||
});
|
});
|
||||||
// const list = computed(()=> proposl)
|
|
||||||
const format = useFormatter();
|
const format = useFormatter();
|
||||||
const staking = useStakingStore();
|
const staking = useStakingStore();
|
||||||
const chain = useBlockchain();
|
const chain = useBlockchain();
|
||||||
@ -34,9 +33,11 @@ const statusMap: Record<string, string> = {
|
|||||||
class="py-4 px-4 hover:bg-gray-100 dark:hover:bg-[#353f5a] block rounded cursor-pointer"
|
class="py-4 px-4 hover:bg-gray-100 dark:hover:bg-[#353f5a] block rounded cursor-pointer"
|
||||||
>
|
>
|
||||||
<div class="grid grid-cols-6 md:grid-cols-11 flex-1">
|
<div class="grid grid-cols-6 md:grid-cols-11 flex-1">
|
||||||
<div class="text-textMain dark:text-white mb-3">#{{ item?.proposal_id }}</div>
|
<div class="text-main dark:text-white mb-3">
|
||||||
|
#{{ item?.proposal_id }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-span-5 md:pr-10 text-textMain dark:text-white truncate">
|
<div class="col-span-5 md:pr-10 text-main dark:text-white truncate">
|
||||||
{{ item?.content?.title }}
|
{{ item?.content?.title }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -48,9 +49,29 @@ const statusMap: Record<string, string> = {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-yes flex items-center mb-3">
|
<div
|
||||||
<div class="w-1 h-1 bg-yes rounded-full mr-2"></div>
|
class="flex items-center mb-3"
|
||||||
<div class="text-xs">{{ statusMap?.[item?.status] || item?.status }}</div>
|
:class="
|
||||||
|
statusMap?.[item?.status] === 'PASSED'
|
||||||
|
? 'text-yes'
|
||||||
|
: statusMap?.[item?.status] === 'REJECTED'
|
||||||
|
? 'text-no'
|
||||||
|
: 'text-info'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="w-1 h-1 rounded-full mr-2"
|
||||||
|
:class="
|
||||||
|
statusMap?.[item?.status] === 'PASSED'
|
||||||
|
? 'bg-yes'
|
||||||
|
: statusMap?.[item?.status] === 'REJECTED'
|
||||||
|
? 'bg-no'
|
||||||
|
: 'bg-info'
|
||||||
|
"
|
||||||
|
></div>
|
||||||
|
<div class="text-xs">
|
||||||
|
{{ statusMap?.[item?.status] || item?.status }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@ -59,7 +80,10 @@ const statusMap: Record<string, string> = {
|
|||||||
{{ format.toDay(item.voting_end_time, 'from') }}
|
{{ format.toDay(item.voting_end_time, 'from') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ProposalProcess :pool="staking.pool" :tally="item.final_tally_result"></ProposalProcess>
|
<ProposalProcess
|
||||||
|
:pool="staking.pool"
|
||||||
|
:tally="item.final_tally_result"
|
||||||
|
></ProposalProcess>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -17,15 +17,22 @@ import TheCustomizer from '@/plugins/vuetify/@core/components/TheCustomizer.vue'
|
|||||||
import Breadcrumbs from './Breadcrumbs.vue';
|
import Breadcrumbs from './Breadcrumbs.vue';
|
||||||
import { useBlockchain } from '@/stores';
|
import { useBlockchain } from '@/stores';
|
||||||
|
|
||||||
const { appRouteTransition, isLessThanOverlayNavBreakpoint, isVerticalNavCollapsed } =
|
const {
|
||||||
useThemeConfig();
|
appRouteTransition,
|
||||||
|
isLessThanOverlayNavBreakpoint,
|
||||||
|
isVerticalNavCollapsed,
|
||||||
|
} = useThemeConfig();
|
||||||
const { width: windowWidth } = useWindowSize();
|
const { width: windowWidth } = useWindowSize();
|
||||||
|
|
||||||
// ℹ️ Provide animation name for vertical nav collapse icon.
|
// ℹ️ 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 => {
|
watch(isVerticalNavCollapsed, (val) => {
|
||||||
verticalNavHeaderActionAnimationName.value = val ? 'rotate-180' : 'rotate-back-180';
|
verticalNavHeaderActionAnimationName.value = val
|
||||||
|
? 'rotate-180'
|
||||||
|
: 'rotate-back-180';
|
||||||
});
|
});
|
||||||
|
|
||||||
const dashboard = useDashboard();
|
const dashboard = useDashboard();
|
||||||
|
@ -1,66 +1,126 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { SearchHeader, SearchItem } from '@/@fake-db/types'
|
import type { SearchHeader, SearchItem } from '@/@fake-db/types';
|
||||||
import axios from 'axios'
|
import axios from 'axios';
|
||||||
import { useThemeConfig } from '@core/composable/useThemeConfig'
|
import { useThemeConfig } from '@core/composable/useThemeConfig';
|
||||||
|
|
||||||
interface Suggestion {
|
interface Suggestion {
|
||||||
icon: string
|
icon: string;
|
||||||
title: string
|
title: string;
|
||||||
url: object
|
url: object;
|
||||||
}
|
}
|
||||||
const { appContentLayoutNav } = useThemeConfig()
|
const { appContentLayoutNav } = useThemeConfig();
|
||||||
|
|
||||||
interface SuggestionGroup {
|
interface SuggestionGroup {
|
||||||
title: string
|
title: string;
|
||||||
content: Suggestion[]
|
content: Suggestion[];
|
||||||
}
|
}
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
})
|
});
|
||||||
|
|
||||||
// 👉 Is App Search Bar Visible
|
// 👉 Is App Search Bar Visible
|
||||||
const isAppSearchBarVisible = ref(false)
|
const isAppSearchBarVisible = ref(false);
|
||||||
|
|
||||||
// 👉 Default suggestions
|
// 👉 Default suggestions
|
||||||
const suggestionGroups: SuggestionGroup[] = [
|
const suggestionGroups: SuggestionGroup[] = [
|
||||||
{
|
{
|
||||||
title: 'Popular Searches',
|
title: 'Popular Searches',
|
||||||
content: [
|
content: [
|
||||||
{ icon: 'mdi-chart-donut', title: 'Analytics', url: { name: 'dashboards-analytics' } },
|
{
|
||||||
{ icon: 'mdi-chart-bubble', title: 'CRM', url: { name: 'dashboards-crm' } },
|
icon: 'mdi-chart-donut',
|
||||||
{ icon: 'mdi-file-outline', title: 'Invoice List', url: { name: 'apps-invoice-list' } },
|
title: 'Analytics',
|
||||||
{ icon: 'mdi-account-group-outline', title: 'User List', url: { name: 'apps-user-list' } },
|
url: { name: 'dashboards-analytics' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-chart-bubble',
|
||||||
|
title: 'CRM',
|
||||||
|
url: { name: 'dashboards-crm' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-file-outline',
|
||||||
|
title: 'Invoice List',
|
||||||
|
url: { name: 'apps-invoice-list' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-account-group-outline',
|
||||||
|
title: 'User List',
|
||||||
|
url: { name: 'apps-user-list' },
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Apps & Pages',
|
title: 'Apps & Pages',
|
||||||
content: [
|
content: [
|
||||||
{ icon: 'mdi-calendar', title: 'Calendar', url: { name: 'apps-calendar' } },
|
{
|
||||||
{ icon: 'mdi-file-plus-outline', title: 'Invoice Add', url: { name: 'apps-invoice-add' } },
|
icon: 'mdi-calendar',
|
||||||
{ icon: 'mdi-currency-usd', title: 'Pricing', url: { name: 'pages-pricing' } },
|
title: 'Calendar',
|
||||||
{ icon: 'mdi-account-cog-outline', title: 'Account Settings', url: { name: 'pages-account-settings-tab', params: { tab: 'account' } } },
|
url: { name: 'apps-calendar' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-file-plus-outline',
|
||||||
|
title: 'Invoice Add',
|
||||||
|
url: { name: 'apps-invoice-add' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-currency-usd',
|
||||||
|
title: 'Pricing',
|
||||||
|
url: { name: 'pages-pricing' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-account-cog-outline',
|
||||||
|
title: 'Account Settings',
|
||||||
|
url: { name: 'pages-account-settings-tab', params: { tab: 'account' } },
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'User Interface',
|
title: 'User Interface',
|
||||||
content: [
|
content: [
|
||||||
{ icon: 'mdi-alpha-a-box-outline', title: 'Typography', url: { name: 'pages-typography' } },
|
{
|
||||||
|
icon: 'mdi-alpha-a-box-outline',
|
||||||
|
title: 'Typography',
|
||||||
|
url: { name: 'pages-typography' },
|
||||||
|
},
|
||||||
{ icon: 'mdi-tab', title: 'Tabs', url: { name: 'components-tabs' } },
|
{ icon: 'mdi-tab', title: 'Tabs', url: { name: 'components-tabs' } },
|
||||||
{ icon: 'mdi-gesture-tap-button', title: 'Buttons', url: { name: 'components-button' } },
|
{
|
||||||
{ icon: 'mdi-keyboard-settings-outline', title: 'Statistics', url: { name: 'pages-cards-card-statistics' } },
|
icon: 'mdi-gesture-tap-button',
|
||||||
|
title: 'Buttons',
|
||||||
|
url: { name: 'components-button' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-keyboard-settings-outline',
|
||||||
|
title: 'Statistics',
|
||||||
|
url: { name: 'pages-cards-card-statistics' },
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Popular Searches',
|
title: 'Popular Searches',
|
||||||
content: [
|
content: [
|
||||||
{ icon: 'mdi-format-list-checkbox', title: 'Select', url: { name: 'forms-select' } },
|
{
|
||||||
{ icon: 'mdi-lastpass', title: 'Combobox', url: { name: 'forms-combobox' } },
|
icon: 'mdi-format-list-checkbox',
|
||||||
{ icon: 'mdi-calendar-range-outline', title: 'Date & Time Picker', url: { name: 'forms-date-time-picker' } },
|
title: 'Select',
|
||||||
{ icon: 'mdi-hexagram-outline', title: 'Rating', url: { name: 'forms-rating' } },
|
url: { name: 'forms-select' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-lastpass',
|
||||||
|
title: 'Combobox',
|
||||||
|
url: { name: 'forms-combobox' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-calendar-range-outline',
|
||||||
|
title: 'Date & Time Picker',
|
||||||
|
url: { name: 'forms-date-time-picker' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-hexagram-outline',
|
||||||
|
title: 'Rating',
|
||||||
|
url: { name: 'forms-rating' },
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
// 👉 No Data suggestion
|
// 👉 No Data suggestion
|
||||||
const noDataSuggestions: Suggestion[] = [
|
const noDataSuggestions: Suggestion[] = [
|
||||||
@ -79,32 +139,36 @@ const noDataSuggestions: Suggestion[] = [
|
|||||||
icon: 'mdi-cash',
|
icon: 'mdi-cash',
|
||||||
url: { name: 'pages-pricing' },
|
url: { name: 'pages-pricing' },
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
const searchQuery = ref('')
|
const searchQuery = ref('');
|
||||||
const searchResult = ref<(SearchItem | SearchHeader)[]>([])
|
const searchResult = ref<(SearchItem | SearchHeader)[]>([]);
|
||||||
const router = useRouter()
|
const router = useRouter();
|
||||||
|
|
||||||
// 👉 fetch search result API
|
// 👉 fetch search result API
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
axios.get('/app-bar/search', {
|
axios
|
||||||
params: {
|
.get('/app-bar/search', {
|
||||||
q: searchQuery.value,
|
params: {
|
||||||
},
|
q: searchQuery.value,
|
||||||
}).then(response => {
|
},
|
||||||
searchResult.value = response.data
|
})
|
||||||
})
|
.then((response) => {
|
||||||
})
|
searchResult.value = response.data;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// 👉 redirect the selected page
|
// 👉 redirect the selected page
|
||||||
const redirectToSuggestedOrSearchedPage = (selected: Suggestion) => {
|
const redirectToSuggestedOrSearchedPage = (selected: Suggestion) => {
|
||||||
router.push(selected.url)
|
router.push(selected.url);
|
||||||
|
|
||||||
isAppSearchBarVisible.value = false
|
isAppSearchBarVisible.value = false;
|
||||||
searchQuery.value = ''
|
searchQuery.value = '';
|
||||||
}
|
};
|
||||||
|
|
||||||
const LazyAppBarSearch = defineAsyncComponent(() => import('@core/components/AppBarSearch.vue'))
|
const LazyAppBarSearch = defineAsyncComponent(
|
||||||
|
() => import('@core/components/AppBarSearch.vue')
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -157,7 +221,7 @@ const LazyAppBarSearch = defineAsyncComponent(() => import('@core/components/App
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@use "@styles/variables/_vuetify.scss";
|
@use '@styles/variables/_vuetify.scss';
|
||||||
|
|
||||||
.meta-key {
|
.meta-key {
|
||||||
border: thin solid rgba(var(--v-border-color), var(--v-border-opacity));
|
border: thin solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useSkins } from '@core/composable/useSkins'
|
import { useSkins } from '@core/composable/useSkins';
|
||||||
import { useThemeConfig } from '@core/composable/useThemeConfig'
|
import { useThemeConfig } from '@core/composable/useThemeConfig';
|
||||||
|
|
||||||
const DefaultLayout = defineAsyncComponent(() => import('./components/DefaultLayout.vue'))
|
const DefaultLayout = defineAsyncComponent(
|
||||||
|
() => import('./components/DefaultLayout.vue')
|
||||||
|
);
|
||||||
|
|
||||||
const { layoutAttrs, injectSkinClasses } = useSkins()
|
const { layoutAttrs, injectSkinClasses } = useSkins();
|
||||||
|
|
||||||
injectSkinClasses()
|
injectSkinClasses();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -15,5 +17,5 @@ injectSkinClasses()
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
// As we are using `layouts` plugin we need its styles to be imported
|
// As we are using `layouts` plugin we need its styles to be imported
|
||||||
@use "@layouts/styles/default-layout";
|
@use '@layouts/styles/default-layout';
|
||||||
</style>
|
</style>
|
||||||
|
12
src/modules/[chain]/Parameters.vue
Normal file
12
src/modules/[chain]/Parameters.vue
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div class="text-main text-h5 mb-4">Parameters</div>
|
||||||
|
<div class="bg-card px-4 pt-3 pb-4 rounded-sm">
|
||||||
|
<div class="text-base mb-3 text-main">Minting Parameters</div>
|
||||||
|
<div class="grid grid-cols-5 gap-4">
|
||||||
|
<div v-for="item in 10" :key="item" class="rounded-sm bg-active px-4 py-2">
|
||||||
|
<div class="text-xs mb-2 text-secondary">Blocks Per Year</div>
|
||||||
|
<div class="text-base text-main">4,360,000</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -1,73 +1,86 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useBlockModule } from './block'
|
import { useBlockModule } from './block';
|
||||||
import { computed, ref } from '@vue/reactivity';
|
import { computed, ref } from '@vue/reactivity';
|
||||||
import { useFormatter } from '@/stores';
|
import { useFormatter } from '@/stores';
|
||||||
const props = defineProps(["height", "chain"]);
|
const props = defineProps(['height', 'chain']);
|
||||||
|
|
||||||
const store = useBlockModule()
|
const store = useBlockModule();
|
||||||
// store.fetchBlock(props.height)
|
// store.fetchBlock(props.height)
|
||||||
const tab = ref('blocks')
|
const tab = ref('blocks');
|
||||||
|
|
||||||
const format = useFormatter()
|
const format = useFormatter();
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
<VCard>
|
||||||
<VCard>
|
<VCardTitle class="d-flex justify-space-between">
|
||||||
<VCardTitle class="d-flex justify-space-between">
|
<VTabs v-model="tab">
|
||||||
<VTabs v-model="tab">
|
<VTab value="blocks">Blocks</VTab>
|
||||||
<VTab value="blocks">Blocks</VTab>
|
<VTab value="transactions">Transactions</VTab>
|
||||||
<VTab value="transactions">Transactions</VTab>
|
</VTabs>
|
||||||
</VTabs>
|
</VCardTitle>
|
||||||
</VCardTitle>
|
<VWindow v-model="tab">
|
||||||
<VWindow v-model="tab">
|
<VWindowItem value="blocks">
|
||||||
<VWindowItem value="blocks">
|
<VTable>
|
||||||
<VTable>
|
<thead>
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<th>Height</th>
|
||||||
<th>Height</th><th>Hash</th><th>Proposer</th><th>Txs</th><th>Time</th>
|
<th>Hash</th>
|
||||||
</tr>
|
<th>Proposer</th>
|
||||||
</thead>
|
<th>Txs</th>
|
||||||
<tbody>
|
<th>Time</th>
|
||||||
<tr v-for="item in store.recents">
|
</tr>
|
||||||
<td class="text-sm text-primary"><RouterLink :to="`/${props.chain}/block/${item.block?.header?.height}`">{{ item.block?.header?.height }}</RouterLink></td>
|
</thead>
|
||||||
<td>{{ item.block_id?.hash }}</td>
|
<tbody>
|
||||||
<td>{{ format.validator(item.block?.header?.proposer_address) }}</td>
|
<tr v-for="item in store.recents">
|
||||||
<td>{{ item.block?.data?.txs.length }}</td>
|
<td class="text-sm text-primary">
|
||||||
<td>{{ format.toDay(item.block?.header?.time, 'from') }}</td>
|
<RouterLink
|
||||||
</tr>
|
:to="`/${props.chain}/block/${item.block?.header?.height}`"
|
||||||
</tbody>
|
>{{ item.block?.header?.height }}</RouterLink
|
||||||
</VTable>
|
>
|
||||||
</VWindowItem>
|
</td>
|
||||||
<VWindowItem value="transactions">
|
<td>{{ item.block_id?.hash }}</td>
|
||||||
<VTable>
|
<td>
|
||||||
<thead>
|
{{ format.validator(item.block?.header?.proposer_address) }}
|
||||||
<tr>
|
</td>
|
||||||
<th>Hash</th><th>Messages</th><th>Fees</th>
|
<td>{{ item.block?.data?.txs.length }}</td>
|
||||||
</tr>
|
<td>{{ format.toDay(item.block?.header?.time, 'from') }}</td>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</tbody>
|
||||||
<tr v-for="item in store.txsInRecents">
|
</VTable>
|
||||||
<td><RouterLink :to="`/${props.chain}/tx/${item.hash}`">{{ item.hash }}</RouterLink></td>
|
</VWindowItem>
|
||||||
<td>{{ format.messages(item.tx.body.messages) }}</td>
|
<VWindowItem value="transactions">
|
||||||
<td>{{ format.formatTokens(item.tx.authInfo.fee?.amount) }}</td>
|
<VTable>
|
||||||
</tr>
|
<thead>
|
||||||
</tbody>
|
<tr>
|
||||||
</VTable>
|
<th>Hash</th>
|
||||||
|
<th>Messages</th>
|
||||||
|
<th>Fees</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="item in store.txsInRecents">
|
||||||
|
<td>
|
||||||
|
<RouterLink :to="`/${props.chain}/tx/${item.hash}`">{{
|
||||||
|
item.hash
|
||||||
|
}}</RouterLink>
|
||||||
|
</td>
|
||||||
|
<td>{{ format.messages(item.tx.body.messages) }}</td>
|
||||||
|
<td>{{ format.formatTokens(item.tx.authInfo.fee?.amount) }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</VTable>
|
||||||
|
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<v-alert
|
<v-alert
|
||||||
type="info"
|
type="info"
|
||||||
text="Only show txs in recent blocks"
|
text="Only show txs in recent blocks"
|
||||||
variant="tonal"
|
variant="tonal"
|
||||||
></v-alert>
|
></v-alert>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
</VWindow>
|
</VWindow>
|
||||||
<VCardActions>
|
<VCardActions> </VCardActions>
|
||||||
|
</VCard>
|
||||||
</VCardActions>
|
|
||||||
</VCard>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<route>
|
<route>
|
||||||
@ -76,4 +89,4 @@ const format = useFormatter()
|
|||||||
i18n: 'blocks'
|
i18n: 'blocks'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</route>
|
</route>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import ObjectElement from '@/components/dynamic/ObjectElement.vue';
|
import ObjectElement from '@/components/dynamic/ObjectElement.vue';
|
||||||
import { useBaseStore, useFormatter, useGovStore, useStakingStore } from '@/stores';
|
import { useBaseStore, useFormatter, useGovStore, useStakingStore } from '@/stores';
|
||||||
import type { GovProposal, GovVote, PaginabledAccounts, PaginatedProposalDeposit, PaginatedProposalVotes, Pagination } from '@/types';
|
import type { GovProposal, GovVote, PaginabledAccounts, PaginatedProposalDeposit, PaginatedProposalVotes, Pagination } from '@/types';
|
||||||
import { ref } from 'vue';
|
import { ref , reactive} from 'vue';
|
||||||
import Countdown from '@/components/Countdown.vue';
|
import Countdown from '@/components/Countdown.vue';
|
||||||
import { computed } from '@vue/reactivity';
|
import { computed } from '@vue/reactivity';
|
||||||
|
|
||||||
@ -12,7 +12,16 @@ const props = defineProps(["proposal_id", "chain"]);
|
|||||||
const proposal = ref({} as GovProposal)
|
const proposal = ref({} as GovProposal)
|
||||||
const format = useFormatter()
|
const format = useFormatter()
|
||||||
const store = useGovStore()
|
const store = useGovStore()
|
||||||
store.fetchProposal(props.proposal_id).then((x) => proposal.value = x.proposal)
|
store.fetchProposal(props.proposal_id).then((res) => {
|
||||||
|
const proposalDetail = reactive(res.proposal)
|
||||||
|
// when status under the voting, final_tally_result are no data, should request fetchTally
|
||||||
|
if (res.proposal?.status === 'PROPOSAL_STATUS_VOTING_PERIOD'){
|
||||||
|
store.fetchTally(props.proposal_id).then((tallRes)=>{
|
||||||
|
proposalDetail.final_tally_result = tallRes?.tally
|
||||||
|
})
|
||||||
|
}
|
||||||
|
proposal.value = proposalDetail
|
||||||
|
})
|
||||||
|
|
||||||
const color = computed(() => {
|
const color = computed(() => {
|
||||||
if (proposal.value.status==='PROPOSAL_STATUS_PASSED') {
|
if (proposal.value.status==='PROPOSAL_STATUS_PASSED') {
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
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'
|
||||||
const tab = ref("")
|
const tab = ref("")
|
||||||
const store = useGovStore()
|
const store = useGovStore()
|
||||||
store.fetchProposals("2")
|
|
||||||
|
onMounted(()=>{
|
||||||
|
store.fetchProposals('2')
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import MdEditor from 'md-editor-v3';
|
import MdEditor from 'md-editor-v3';
|
||||||
import PriceMarketChart from '@/components/charts/PriceMarketChart.vue'
|
import PriceMarketChart from '@/components/charts/PriceMarketChart.vue';
|
||||||
|
|
||||||
import { useBlockchain, useFormatter } from '@/stores';
|
import { useBlockchain, useFormatter } from '@/stores';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
@ -10,31 +10,30 @@ import { computed } from '@vue/reactivity';
|
|||||||
import CardStatisticsVertical from '@/components/CardStatisticsVertical.vue';
|
import CardStatisticsVertical from '@/components/CardStatisticsVertical.vue';
|
||||||
import ProposalListItem from '@/components/ProposalListItem.vue';
|
import ProposalListItem from '@/components/ProposalListItem.vue';
|
||||||
|
|
||||||
const blockchain = useBlockchain()
|
const blockchain = useBlockchain();
|
||||||
const store = useIndexModule()
|
const store = useIndexModule();
|
||||||
|
|
||||||
const coinInfo = computed(() => {
|
const coinInfo = computed(() => {
|
||||||
return store.coinInfo
|
return store.coinInfo;
|
||||||
})
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
store.loadDashboard()
|
store.loadDashboard();
|
||||||
})
|
});
|
||||||
|
|
||||||
const format = useFormatter()
|
const format = useFormatter();
|
||||||
const ticker = computed(() => store.coinInfo.tickers[store.tickerIndex])
|
const ticker = computed(() => store.coinInfo.tickers[store.tickerIndex]);
|
||||||
|
|
||||||
blockchain.$subscribe((m, s) => {
|
blockchain.$subscribe((m, s) => {
|
||||||
console.log('index:', m)
|
console.log('index:', m);
|
||||||
if(!Array.isArray(m.events) && ['chainName', 'endpoint'].includes(m.events.key)) {
|
if (!Array.isArray(m.events) && ['chainName', 'endpoint'].includes(m.events.key)) {
|
||||||
console.log(m.events.key)
|
console.log(m.events.key);
|
||||||
store.loadDashboard()
|
store.loadDashboard();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
function shortName(name: string, id: string) {
|
function shortName(name: string, id: string) {
|
||||||
return name.toLowerCase().startsWith('ibc/') || name.toLowerCase().startsWith('0x') ? id: name
|
return name.toLowerCase().startsWith('ibc/') || name.toLowerCase().startsWith('0x') ? id : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -44,58 +43,75 @@ function shortName(name: string, id: string) {
|
|||||||
<VCol md="5">
|
<VCol md="5">
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<VCardTitle>
|
<VCardTitle>
|
||||||
{{ coinInfo.name }} (<span class="text-uppercase">{{ coinInfo.symbol }}</span>)
|
{{ coinInfo.name }} (
|
||||||
|
<span class="text-uppercase">{{ coinInfo.symbol }}</span>
|
||||||
|
)
|
||||||
</VCardTitle>
|
</VCardTitle>
|
||||||
<VCardSubtitle>
|
<VCardSubtitle>
|
||||||
Rank: <VChip color="error" size="x-small">#{{ coinInfo.market_cap_rank }}</VChip>
|
Rank:
|
||||||
|
<VChip color="error" size="x-small">#{{ coinInfo.market_cap_rank }}</VChip>
|
||||||
</VCardSubtitle>
|
</VCardSubtitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider/>
|
<VDivider />
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<VBtn variant="text" size="small" :href="store.homepage" prependIcon="mdi-web">Website</VBtn>
|
<VBtn variant="text" size="small" :href="store.homepage" prependIcon="mdi-web">
|
||||||
<VBtn variant="text" size="small" :href="store.twitter" prependIcon="mdi-twitter">Twitter</VBtn>
|
Website
|
||||||
<VBtn variant="text" size="small" :href="store.telegram" prependIcon="mdi-telegram">Telegram</VBtn>
|
</VBtn>
|
||||||
<VBtn variant="text" size="small" :href="store.github" prependIcon="mdi-github">Github</VBtn>
|
<VBtn variant="text" size="small" :href="store.twitter" prependIcon="mdi-twitter">
|
||||||
|
Twitter
|
||||||
|
</VBtn>
|
||||||
|
<VBtn variant="text" size="small" :href="store.telegram" prependIcon="mdi-telegram">
|
||||||
|
Telegram
|
||||||
|
</VBtn>
|
||||||
|
<VBtn variant="text" size="small" :href="store.github" prependIcon="mdi-github">
|
||||||
|
Github
|
||||||
|
</VBtn>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<!-- SECTION upgrade plan banner -->
|
<!-- SECTION upgrade plan banner -->
|
||||||
<div class="plan-upgrade-banner d-flex bg-light-secondary rounded align-center pa-3">
|
<div class="plan-upgrade-banner d-flex bg-light-secondary rounded align-center pa-3">
|
||||||
<h3
|
<h3 class="plan-details me-3" :class="store.priceColor">
|
||||||
class="plan-details me-3"
|
{{ store.priceChange }}
|
||||||
:class="store.priceColor"
|
<small>%</small>
|
||||||
>
|
|
||||||
{{ store.priceChange }}<small>%</small>
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<VMenu open-on-hover>
|
<VMenu open-on-hover>
|
||||||
<template #activator="{ props }">
|
<template #activator="{ props }">
|
||||||
<div class="d-flex flex-column align-start" v-bind="props">
|
<div class="d-flex flex-column align-start" v-bind="props">
|
||||||
<h3 class="text-base font-weight-semibold">
|
<h3 class="text-base font-weight-semibold">
|
||||||
{{ ticker?.market?.name || ''}}
|
{{ ticker?.market?.name || '' }}
|
||||||
</h3>
|
</h3>
|
||||||
<span class="text-primary text-xs">{{ shortName(ticker?.base, ticker.coin_id) }}/{{ shortName(ticker?.target, ticker.target_coin_id) }}</span>
|
<span class="text-primary text-xs">
|
||||||
|
{{ shortName(ticker?.base, ticker.coin_id) }}/{{
|
||||||
|
shortName(ticker?.target, ticker.target_coin_id)
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<VList style="max-height: 300px;">
|
<VList style="max-height: 300px">
|
||||||
<VListItem
|
<VListItem
|
||||||
v-for="(item, i) in store.coinInfo.tickers"
|
v-for="(item, i) in store.coinInfo.tickers"
|
||||||
:key="i"
|
:key="i"
|
||||||
rounded
|
rounded
|
||||||
@click="store.selectTicker(i)"
|
@click="store.selectTicker(i)"
|
||||||
>
|
>
|
||||||
<template #prepend>
|
<template #prepend></template>
|
||||||
</template>
|
|
||||||
<!-- eslint-disable-next-line vue/no-v-text-v-html-on-component -->
|
<!-- eslint-disable-next-line vue/no-v-text-v-html-on-component -->
|
||||||
<VListItemTitle v-text="item.market.name" />
|
<VListItemTitle v-text="item.market.name" />
|
||||||
<VListItemSubtitle>{{ shortName(item?.base, item.coin_id) }}/{{ shortName(item?.target, item.target_coin_id) }}</VListItemSubtitle>
|
<VListItemSubtitle>
|
||||||
|
{{ shortName(item?.base, item.coin_id) }}/{{
|
||||||
|
shortName(item?.target, item.target_coin_id)
|
||||||
|
}}
|
||||||
|
</VListItemSubtitle>
|
||||||
<template #append>
|
<template #append>
|
||||||
<span class="ml-3" :class="`text-${store.tickerColor(item.trust_score)}`">{{ item.converted_last.usd }}</span>
|
<span class="ml-3" :class="`text-${store.tickerColor(item.trust_score)}`">
|
||||||
|
{{ item.converted_last.usd }}
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</VListItem>
|
</VListItem>
|
||||||
</VList>
|
</VList>
|
||||||
</VMenu>
|
</VMenu>
|
||||||
|
|
||||||
|
|
||||||
<VSpacer />
|
<VSpacer />
|
||||||
|
|
||||||
<div class="d-flex align-center">
|
<div class="d-flex align-center">
|
||||||
@ -107,14 +123,9 @@ function shortName(name: string, id: string) {
|
|||||||
</div>
|
</div>
|
||||||
<!-- !SECTION -->
|
<!-- !SECTION -->
|
||||||
<VSpacer />
|
<VSpacer />
|
||||||
<VBtn
|
<VBtn block :color="store.trustColor" class="mt-3" :href="ticker.trade_url">
|
||||||
block
|
Buy {{ coinInfo.symbol || '' }}
|
||||||
:color="store.trustColor"
|
</VBtn>
|
||||||
class="mt-3"
|
|
||||||
:href="ticker.trade_url"
|
|
||||||
>
|
|
||||||
Buy {{ coinInfo.symbol || '' }}
|
|
||||||
</VBtn>
|
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol md="7">
|
<VCol md="7">
|
||||||
@ -124,33 +135,31 @@ function shortName(name: string, id: string) {
|
|||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
<VDivider />
|
<VDivider />
|
||||||
<VCardText style="max-height: 250px; overflow:auto;"><MdEditor :model-value="coinInfo.description?.en" previewOnly></MdEditor></VCardText>
|
<VCardText style="max-height: 250px; overflow: auto">
|
||||||
|
<MdEditor :model-value="coinInfo.description?.en" previewOnly></MdEditor>
|
||||||
|
</VCardText>
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<VChip v-for="tag in coinInfo.categories" size="x-small" class="mr-2">{{ tag }}</VChip>
|
<VChip v-for="tag in coinInfo.categories" size="x-small" class="mr-2">{{ tag }}</VChip>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|
||||||
<VRow>
|
<div class="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-6">
|
||||||
<VCol v-for="item in store.stats" cols="12" sm="6" md="2">
|
<div v-for="item in store.stats">
|
||||||
<VCard>
|
<CardStatisticsVertical v-bind="item" />
|
||||||
<CardStatisticsVertical v-bind="item" />
|
</div>
|
||||||
</VCard>
|
</div>
|
||||||
</VCol>
|
|
||||||
</VRow>
|
|
||||||
|
|
||||||
<VCard class="my-5">
|
<VCard class="my-5">
|
||||||
<VCardItem class="pb-0">
|
<VCardItem class="pb-0">
|
||||||
<VCardTitle>Active Proposals</VCardTitle>
|
<VCardTitle>Active Proposals</VCardTitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<ProposalListItem :proposals="store.proposals"/>
|
<ProposalListItem :proposals="store.proposals" />
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VCardText v-if="store.proposals.length === 0">No active proposals</VCardText>
|
<VCardText v-if="store.proposals.length === 0">No active proposals</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|
||||||
<VBtn block color='secondary' variant="outlined" class="mt-5">
|
<VBtn block color="secondary" variant="outlined" class="mt-5">Connect Wallet</VBtn>
|
||||||
Connect Wallet
|
|
||||||
</VBtn>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"add_to_favorite": "Add to favorite"
|
"add_to_favorite": "Add to favorite"
|
||||||
},
|
},
|
||||||
"Ecosystem": "Ecosystem",
|
"Ecosystem": "Ecosystem",
|
||||||
"All Blockchains": "All Blockchain222",
|
"All Blockchains": "All Blockchain",
|
||||||
"Favorite": "Favorite"
|
"Favorite": "Favorite"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,6 @@ export const useFormatter = defineStore('formatter', {
|
|||||||
calculatePercent(input?: string|number, total?: string|number ) {
|
calculatePercent(input?: string|number, total?: string|number ) {
|
||||||
if(!input || !total) return '0'
|
if(!input || !total) return '0'
|
||||||
const percent = Number(input)/Number(total)
|
const percent = Number(input)/Number(total)
|
||||||
console.log(input, total, percent);
|
|
||||||
return numeral(percent>0.0001?percent: 0).format("0.[00]%")
|
return numeral(percent>0.0001?percent: 0).format("0.[00]%")
|
||||||
},
|
},
|
||||||
formatDecimalToPercent(decimal: string) {
|
formatDecimalToPercent(decimal: string) {
|
||||||
|
@ -2,6 +2,7 @@ import { defineStore } from "pinia";
|
|||||||
import { useBlockchain } from "./useBlockchain";
|
import { useBlockchain } from "./useBlockchain";
|
||||||
import type { PageRequest, PaginatedProposals } from "@/types";
|
import type { PageRequest, PaginatedProposals } from "@/types";
|
||||||
import { LoadingStatus } from "./useDashboard";
|
import { LoadingStatus } from "./useDashboard";
|
||||||
|
import {reactive} from 'vue'
|
||||||
|
|
||||||
export const useGovStore = defineStore('govStore', {
|
export const useGovStore = defineStore('govStore', {
|
||||||
state: () => {
|
state: () => {
|
||||||
@ -27,18 +28,16 @@ export const useGovStore = defineStore('govStore', {
|
|||||||
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 = await this.blockchain.rpc.getGovProposals(status)
|
const proposals = reactive(await this.blockchain.rpc.getGovProposals(status))
|
||||||
|
if(status === '2') {
|
||||||
|
proposals.proposals.forEach(async(x1) => {
|
||||||
|
await this.fetchTally(x1.proposal_id).then(res => {
|
||||||
|
x1.final_tally_result = res?.tally
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
this.loading[status] = LoadingStatus.Loaded
|
this.loading[status] = LoadingStatus.Loaded
|
||||||
this.proposals[status] = proposals
|
this.proposals[status] = proposals
|
||||||
|
|
||||||
if(status === '2') {
|
|
||||||
proposals.proposals.forEach(x1 => {
|
|
||||||
this.fetchTally(x1.proposal_id).then(t => {
|
|
||||||
x1.final_tally_result = t.tally
|
|
||||||
this.proposals[status] = proposals
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this.proposals[status]
|
return this.proposals[status]
|
||||||
},
|
},
|
||||||
@ -48,7 +47,7 @@ export const useGovStore = defineStore('govStore', {
|
|||||||
// })
|
// })
|
||||||
},
|
},
|
||||||
async fetchTally(proposalId: string) {
|
async fetchTally(proposalId: string) {
|
||||||
return this.blockchain.rpc.getGovProposalTally(proposalId)
|
return await this.blockchain.rpc.getGovProposalTally(proposalId)
|
||||||
},
|
},
|
||||||
async fetchProposal(proposalId: string) {
|
async fetchProposal(proposalId: string) {
|
||||||
return this.blockchain.rpc.getGovProposal(proposalId)
|
return this.blockchain.rpc.getGovProposal(proposalId)
|
||||||
@ -59,5 +58,6 @@ export const useGovStore = defineStore('govStore', {
|
|||||||
async fetchProposalVotes(proposalId: string, next_key?: string) {
|
async fetchProposalVotes(proposalId: string, next_key?: string) {
|
||||||
return this.blockchain.rpc.getGovProposalVotes(proposalId, next_key)
|
return this.blockchain.rpc.getGovProposalVotes(proposalId, next_key)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--text-main: #333;
|
||||||
|
--text-secondary: #4b525d;
|
||||||
|
--bg-card: #fff;
|
||||||
|
--bg-active: #fbfbfc;
|
||||||
|
--bg-hover: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark {
|
||||||
|
--text-main: #f7f7f7;
|
||||||
|
--text-secondary: #6f6e84;
|
||||||
|
--bg-card: #28334e;
|
||||||
|
--bg-active: #242b40;
|
||||||
|
--bg-hover: #303044;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -27,6 +27,10 @@ export interface GovProposal {
|
|||||||
"@type": string,
|
"@type": string,
|
||||||
"title": string,
|
"title": string,
|
||||||
"description": string,
|
"description": string,
|
||||||
|
"plan"?: {
|
||||||
|
'height'?: string | number,
|
||||||
|
'time'?: string | number,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"status": string,
|
"status": string,
|
||||||
"final_tally_result": {
|
"final_tally_result": {
|
||||||
|
@ -5,12 +5,15 @@ module.exports = {
|
|||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
main: '#5973fe',
|
|
||||||
yes: '#3fb68b',
|
yes: '#3fb68b',
|
||||||
no: '#ff5353',
|
no: '#ff5353',
|
||||||
info: '#00b2ff',
|
info: '#00b2ff',
|
||||||
textMain: '#333',
|
|
||||||
primary: '#666cff',
|
primary: '#666cff',
|
||||||
|
main: 'var(--text-main)',
|
||||||
|
secondary: 'var(--text-secondary)',
|
||||||
|
card: 'var(--bg-card)',
|
||||||
|
hover: 'var(--bg-hover)',
|
||||||
|
active: 'var(--bg-active)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user