Merge pull request #365 from alisaweb3/v3-single

Parameters Page: data docking, perfect page content, mobile adaptation
This commit is contained in:
ping 2023-04-28 08:40:08 +08:00 committed by GitHub
commit 016f022e27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 187 additions and 107 deletions

View File

@ -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"
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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
}

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1,12 @@
<template>
<VCard>
UPTIME
</VCard>
</template>
<route>
{
meta: {
i18n: 'uptime'
}
}
</route>

View File

@ -4,7 +4,8 @@
"blocks": "区块和交易",
"staking": "质押生息",
"governance": "社区治理",
"parameters": "参数"
"parameters": "参数",
"uptime": "状态"
},
"index": {
"slogan": "Ping Dashboard 是一个区块链浏览器,也是一个网页钱包,还有更多 ... 🛠",

View File

@ -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 ... 🛠",

View File

@ -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()

View File

@ -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"