forked from cerc-io/cosmos-explorer
Merge pull request #365 from alisaweb3/v3-single
Parameters Page: data docking, perfect page content, mobile adaptation
This commit is contained in:
commit
016f022e27
@ -76,7 +76,7 @@
|
||||
"unplugin-auto-import": "^0.13.0",
|
||||
"unplugin-vue-components": "^0.23.0",
|
||||
"unplugin-vue-define-options": "1.1.4",
|
||||
"vite": "^4.3.1",
|
||||
"vite": "^4.3.3",
|
||||
"vite-plugin-pages": "^0.28.0",
|
||||
"vue-tsc": "^1.0.12"
|
||||
}
|
||||
|
@ -1,22 +1,28 @@
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue';
|
||||
const props = defineProps({
|
||||
cardItem: {
|
||||
type: Object as PropType<{title: string;items: Array<any>;}>,
|
||||
},
|
||||
})
|
||||
|
||||
cardItem: {
|
||||
type: Object as PropType<{ title: string; items: Array<any> }>,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="bg-card px-4 pt-3 pb-4 rounded-sm mt-6"
|
||||
v-if="props.cardItem?.items && props.cardItem?.items?.length > 0">
|
||||
<div class="text-base mb-3 text-main">{{ props.cardItem?.title }}</div>
|
||||
<div class="grid grid-cols-5 gap-4">
|
||||
<div v-for="(item,index) of props.cardItem?.items" :key="index" class="rounded-sm bg-active px-4 py-2">
|
||||
<div class="text-xs mb-2 text-secondary">{{ item?.subtitle }}</div>
|
||||
<div class="text-base text-main">{{ item?.value }}</div>
|
||||
<!-- {{ item }} -->
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bg-card px-4 pt-3 pb-4 rounded mt-5"
|
||||
v-if="props.cardItem?.items && props.cardItem?.items?.length > 0"
|
||||
>
|
||||
<div class="text-base mb-3 text-main">{{ props.cardItem?.title }}</div>
|
||||
<div
|
||||
class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 2xl:grid-cols-6 gap-4"
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) of props.cardItem?.items"
|
||||
:key="index"
|
||||
class="rounded-sm bg-active px-4 py-2"
|
||||
>
|
||||
<div class="text-xs mb-2 text-secondary">{{ item?.subtitle }}</div>
|
||||
<div class="text-base text-main">{{ Array.isArray(item?.value) ? (item?.value[0] && item?.value[0].amount)|| '-':`${Number(item?.value)}` === 'NaN' ? item?.value : Number(item?.value)}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,26 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue';
|
||||
const props = defineProps({
|
||||
tableItem: {
|
||||
type: Object as PropType<{title: string;items: Object;}>,
|
||||
},
|
||||
})
|
||||
|
||||
function formatTitle (name: string){
|
||||
return String(name).replaceAll('_', ' ')
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="bg-card px-4 pt-3 pb-4 rounded-sm mt-6">
|
||||
<div class="text-base mb-3 text-main">{{ props.tableItem?.title }}</div>
|
||||
<div class="">
|
||||
<div class="d-flex flex-nowrap" v-for="(item,index ) of props.tableItem?.items" :key="index">
|
||||
<div class="mr-6">{{ formatTitle(item?.subtitle) }}</div>
|
||||
<div class="flex-1" >{{ item?.value }}</div>
|
||||
<div>{{typeof(item?.value )}}</div>
|
||||
<!-- {{ item }} -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
@ -3,7 +3,11 @@ import { computed } from '@vue/reactivity';
|
||||
import DynamicComponent from './DynamicComponent.vue';
|
||||
|
||||
const props = defineProps({
|
||||
value: { type: Array<Object>},
|
||||
value: { type: null as any },
|
||||
thead: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
const header = computed(() => {
|
||||
@ -15,16 +19,20 @@ const header = computed(() => {
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<VTable v-if="header.length > 0" density="compact" height="300px" fixed-header>
|
||||
<thead>
|
||||
<VTable v-if="header.length > 0" density="compact" height="300px" fixed-header hover>
|
||||
<thead v-if="thead">
|
||||
<tr>
|
||||
<th v-for="k in header" class="text-left text-capitalize">{{ k }}</th>
|
||||
<th v-for="(item, index) in header" :key="index" class="text-left text-capitalize">{{ item }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="v in props.value">
|
||||
<td v-for="k in header"> <DynamicComponent :value="v[k]" /></td>
|
||||
<tr v-for="(item, index) in value" :key="index">
|
||||
<td v-for="(el, key) in header" :key="key"> <DynamicComponent :value="item[el]" /></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</VTable>
|
||||
|
||||
<div v-else class="h-[300px]">
|
||||
|
||||
</div>
|
||||
</template>
|
@ -46,3 +46,65 @@ export function numberWithCommas(x: any) {
|
||||
return parts.join('.')
|
||||
}
|
||||
|
||||
export function tokenFormatter(tokens:any, denoms = {}, decimal = 2) {
|
||||
if (Array.isArray(tokens)) {
|
||||
return tokens.map(t => formatToken(t, denoms, decimal)).join(', ')
|
||||
}
|
||||
return formatToken(tokens, denoms, 2)
|
||||
}
|
||||
export function formatToken(token:any, IBCDenom = {}, decimals = 2, withDenom = true) {
|
||||
if (token) {
|
||||
const denom = IBCDenom[token.denom] || token.denom
|
||||
if (withDenom) {
|
||||
return `${formatTokenAmount(token.amount, decimals, denom)} ${formatTokenDenom(denom)}`
|
||||
}
|
||||
return formatTokenAmount(token.amount, decimals, denom)
|
||||
}
|
||||
return token
|
||||
}
|
||||
export function formatTokenDenom(tokenDenom:any) {
|
||||
if (tokenDenom && tokenDenom.code === undefined) {
|
||||
let denom = tokenDenom.denom_trace ? tokenDenom.denom_trace.base_denom : tokenDenom
|
||||
const chains = getLocalChains()
|
||||
const selected = localStorage.getItem('selected_chain')
|
||||
const selChain = chains[selected]
|
||||
const nativeAsset = selChain.assets.find(a => (a.base === denom))
|
||||
if (nativeAsset) {
|
||||
denom = nativeAsset.symbol
|
||||
} else {
|
||||
const config = Object.values(chains)
|
||||
config.forEach(x => {
|
||||
if (x.assets) {
|
||||
const asset = x.assets.find(a => (a.base === denom))
|
||||
if (asset) denom = asset.symbol
|
||||
}
|
||||
})
|
||||
}
|
||||
return denom.length > 10 ? `${denom.substring(0, 7).toUpperCase()}..${denom.substring(denom.length - 3)}` : denom.toUpperCase()
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
export function isToken(value: string) {
|
||||
let is = false
|
||||
if (Array.isArray(value)) {
|
||||
is = value.findIndex(x => Object.keys(x).includes('denom')) > -1
|
||||
} else {
|
||||
is = Object.keys(value).includes('denom')
|
||||
}
|
||||
return is
|
||||
}
|
||||
export function isStringArray(value: any) {
|
||||
let is = false
|
||||
if (Array.isArray(value)) {
|
||||
is = value.findIndex(x => typeof x === 'string') > -1
|
||||
}
|
||||
return is
|
||||
}
|
||||
|
||||
export function isHexAddress(v: any) {
|
||||
// const re = /^[A-Z\d]{40}$/
|
||||
// return re.test(v)
|
||||
return v.length === 28
|
||||
}
|
||||
|
||||
|
@ -1,36 +1,35 @@
|
||||
<script lang="ts" setup>
|
||||
import { useGovStore } from '@/stores';
|
||||
import ProposalListItem from '@/components/ProposalListItem.vue';
|
||||
import { ref, onMounted } from 'vue'
|
||||
const tab = ref("")
|
||||
const store = useGovStore()
|
||||
|
||||
onMounted(()=>{
|
||||
store.fetchProposals('2')
|
||||
})
|
||||
import { ref, onMounted } from 'vue';
|
||||
const tab = ref('');
|
||||
const store = useGovStore();
|
||||
|
||||
onMounted(() => {
|
||||
store.fetchProposals('2');
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<VTabs v-model="tab">
|
||||
<VTab value="2">Voting</VTab>
|
||||
<VTab value="3" @click="store.fetchProposals('3')">Passed</VTab>
|
||||
<VTab value="4" @click="store.fetchProposals('4')">Rejected</VTab>
|
||||
</VTabs>
|
||||
<VWindow v-model="tab" class="mt-5">
|
||||
<VWindowItem value="2">
|
||||
<ProposalListItem :proposals="store?.proposals['2']"/>
|
||||
</VWindowItem>
|
||||
<div>
|
||||
<VTabs v-model="tab" class="v-tabs-pill">
|
||||
<VTab value="2">Voting</VTab>
|
||||
<VTab value="3" @click="store.fetchProposals('3')">Passed</VTab>
|
||||
<VTab value="4" @click="store.fetchProposals('4')">Rejected</VTab>
|
||||
</VTabs>
|
||||
<VWindow v-model="tab" class="mt-5">
|
||||
<VWindowItem value="2">
|
||||
<ProposalListItem :proposals="store?.proposals['2']" />
|
||||
</VWindowItem>
|
||||
|
||||
<VWindowItem value="3">
|
||||
<ProposalListItem :proposals="store?.proposals['3']"/>
|
||||
</VWindowItem>
|
||||
<VWindowItem value="3">
|
||||
<ProposalListItem :proposals="store?.proposals['3']" />
|
||||
</VWindowItem>
|
||||
|
||||
<VWindowItem value="4">
|
||||
<ProposalListItem :proposals="store?.proposals['4']"/>
|
||||
</VWindowItem>
|
||||
</VWindow>
|
||||
</div>
|
||||
<VWindowItem value="4">
|
||||
<ProposalListItem :proposals="store?.proposals['4']" />
|
||||
</VWindowItem>
|
||||
</VWindow>
|
||||
</div>
|
||||
</template>
|
||||
<route>
|
||||
{
|
||||
@ -38,4 +37,4 @@ onMounted(()=>{
|
||||
i18n: 'governance'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
</route>
|
||||
|
@ -2,8 +2,7 @@
|
||||
import { useParamStore } from '@/stores';
|
||||
import { ref, onMounted } from 'vue'
|
||||
import CardParameter from '@/components/CardParameter.vue'
|
||||
import TableParameter from '@/components/TableParameter.vue'
|
||||
import { sort } from 'semver';
|
||||
import ArrayObjectElement from '@/components/dynamic/ArrayObjectElement.vue';
|
||||
const store = useParamStore()
|
||||
const chain = ref(store.chain)
|
||||
onMounted(() => {
|
||||
@ -13,17 +12,23 @@ onMounted(() => {
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<!-- Chain ID -->
|
||||
<div class="bg-card px-4 pt-3 pb-4 rounded-sm">
|
||||
<div class="text-base mb-3 text-main">{{ chain.title }}</div>
|
||||
<div class="grid grid-cols-5 gap-4">
|
||||
<div v-for="(item,index) of chain.items" :key="index" class="rounded-sm bg-active px-4 py-2">
|
||||
<div class="text-xs mb-2 text-secondary">{{ item.subtitle }}</div>
|
||||
<div class="text-base text-main">{{ item.value }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-hidden">
|
||||
<!-- Chain ID -->
|
||||
<div class="bg-card px-4 pt-3 pb-4 rounded">
|
||||
<div class="text-base mb-3 text-main">{{ chain.title }}</div>
|
||||
<div
|
||||
class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 2xl:grid-cols-6 gap-4"
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) of chain.items"
|
||||
:key="index"
|
||||
class="rounded-sm bg-active px-4 py-2"
|
||||
>
|
||||
<div class="text-xs mb-2 text-secondary">{{ item.subtitle }}</div>
|
||||
<div class="text-base text-main">{{ item.value }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- minting Parameters -->
|
||||
<CardParameter :cardItem="store.mint"/>
|
||||
<!-- Staking Parameters -->
|
||||
@ -35,16 +40,28 @@ onMounted(() => {
|
||||
<!-- Slashing Parameters -->
|
||||
<CardParameter :cardItem="store.slashing"/>
|
||||
<!-- Application Version -->
|
||||
<TableParameter :tableItem="store.appVersion"/>
|
||||
<div class="bg-card px-4 pt-3 pb-4 rounded-sm mt-6">
|
||||
<div class="text-base mb-3 text-main">{{ store.appVersion?.title }}</div>
|
||||
<ArrayObjectElement :value="store.appVersion?.items" :thead="false"/>
|
||||
</div>
|
||||
|
||||
<!-- Node Information -->
|
||||
<TableParameter :tableItem="store.nodeVersion"/>
|
||||
</div>
|
||||
|
||||
<div class="bg-card px-4 pt-3 pb-4ß rounded-sm mt-6">
|
||||
<div class="text-base mb-3 text-main">{{ store.nodeVersion?.title }}</div>
|
||||
<ArrayObjectElement :value="store.nodeVersion?.items" :thead="false"/>
|
||||
</div>
|
||||
|
||||
<!-- Application Version -->
|
||||
<!-- <TableParameter :tableItem="store.appVersion" /> -->
|
||||
<!-- Node Information -->
|
||||
<!-- <TableParameter :tableItem="store.nodeVersion" /> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<route>
|
||||
{
|
||||
meta: {
|
||||
meta: {
|
||||
i18n: 'parameters'
|
||||
}
|
||||
}
|
||||
}
|
||||
</route>
|
||||
</route>
|
||||
|
12
src/modules/[chain]/uptime/index.vue
Normal file
12
src/modules/[chain]/uptime/index.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<VCard>
|
||||
UPTIME
|
||||
</VCard>
|
||||
</template>
|
||||
<route>
|
||||
{
|
||||
meta: {
|
||||
i18n: 'uptime'
|
||||
}
|
||||
}
|
||||
</route>
|
@ -4,7 +4,8 @@
|
||||
"blocks": "区块和交易",
|
||||
"staking": "质押生息",
|
||||
"governance": "社区治理",
|
||||
"parameters": "参数"
|
||||
"parameters": "参数",
|
||||
"uptime": "状态"
|
||||
},
|
||||
"index": {
|
||||
"slogan": "Ping Dashboard 是一个区块链浏览器,也是一个网页钱包,还有更多 ... 🛠",
|
||||
|
@ -4,7 +4,8 @@
|
||||
"blocks": "Blocks&Transaction",
|
||||
"staking": "Staking",
|
||||
"governance": "Governance",
|
||||
"parameters": "Parameters"
|
||||
"parameters": "Parameters",
|
||||
"uptime": "Uptime"
|
||||
},
|
||||
"index": {
|
||||
"slogan": "Ping Dashboard is not just an explorer but also a wallet and more ... 🛠",
|
||||
|
@ -143,7 +143,7 @@ export const useParamStore = defineStore("paramstore", {
|
||||
value: value }))
|
||||
this.nodeVersion.items = Object.entries(res.default_node_info).map(([key, value]) => ({ subtitle:key,
|
||||
value: value }))
|
||||
console.log('handleAbciInfo', res)
|
||||
console.log('handleAbciInfo', this.nodeVersion.items)
|
||||
},
|
||||
async getBaseTendermintBlockLatest() {
|
||||
return await this.blockchain.rpc.getBaseBlockLatest()
|
||||
|
20
yarn.lock
20
yarn.lock
@ -6609,7 +6609,7 @@ postcss@^8.0.9, postcss@^8.4.23:
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
postcss@^8.1.10, postcss@^8.4.21:
|
||||
postcss@^8.1.10:
|
||||
version "8.4.21"
|
||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz"
|
||||
integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
|
||||
@ -6886,9 +6886,9 @@ rimraf@3.0.2, rimraf@^3.0.2:
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rollup@^3.20.2:
|
||||
rollup@^3.21.0:
|
||||
version "3.21.0"
|
||||
resolved "https://registry.npmjs.org/rollup/-/rollup-3.21.0.tgz"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.21.0.tgz#0a71517db56e150222670f88e5e7acfa4fede7c8"
|
||||
integrity sha512-ANPhVcyeHvYdQMUyCbczy33nbLzI7RzrBje4uvNiTDJGIMtlKoOStmympwr9OtS1LZxiDmE2wvxHyVhoLtf1KQ==
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
@ -7365,7 +7365,7 @@ symbol-observable@^2.0.3:
|
||||
|
||||
tailwindcss@^3.3.1:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.1.tgz#b6662fab6a9b704779e48d083a9fef5a81d2b81e"
|
||||
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.1.tgz#b6662fab6a9b704779e48d083a9fef5a81d2b81e"
|
||||
integrity sha512-Vkiouc41d4CEq0ujXl6oiGFQ7bA3WEhUZdTgXAhtKxSy49OmKs8rEfQmupsfF0IGW8fv2iQkp1EVUuapCFrZ9g==
|
||||
dependencies:
|
||||
arg "^5.0.2"
|
||||
@ -7749,14 +7749,14 @@ vite-plugin-vuetify@^1.0.2:
|
||||
debug "^4.3.3"
|
||||
upath "^2.0.1"
|
||||
|
||||
vite@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.npmjs.org/vite/-/vite-4.3.1.tgz"
|
||||
integrity sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==
|
||||
vite@^4.3.3:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-4.3.3.tgz#26adb4aa01439fc4546c480ea547674d87289396"
|
||||
integrity sha512-MwFlLBO4udZXd+VBcezo3u8mC77YQk+ik+fbc0GZWGgzfbPP+8Kf0fldhARqvSYmtIWoAJ5BXPClUbMTlqFxrA==
|
||||
dependencies:
|
||||
esbuild "^0.17.5"
|
||||
postcss "^8.4.21"
|
||||
rollup "^3.20.2"
|
||||
postcss "^8.4.23"
|
||||
rollup "^3.21.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user