feat: page load on no network

This commit is contained in:
Alisa | Side.one 2023-05-14 16:26:18 +08:00
parent d18639204c
commit e5ad564826
19 changed files with 214 additions and 246 deletions

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import VueApexCharts from 'vue3-apexcharts';
import ApexCharts from 'vue3-apexcharts';
import { useTheme } from 'vuetify';
import { hexToRgb } from '@/plugins/vuetify/@layouts/utils';
import { computed, type PropType } from 'vue';
@ -141,7 +141,7 @@ const chartConfig = computed(() => {
<div class="text-sm text-gray-500 dark:text-gray-400">
{{ `Updated at ${format.toDay(props.commission?.update_time, 'short')}` }}
</div>
<VueApexCharts type="donut" :options="chartConfig" :series="series" />
<ApexCharts type="donut" :options="chartConfig" :series="series" />
<div>
<div class="flex items-center justify-center flex-wrap gap-x-3">
<div class="flex items-center gap-x-2">

View File

@ -1,5 +1,5 @@
<script lang="ts" setup>
import VueApexCharts from 'vue3-apexcharts';
import ApexCharts from 'vue3-apexcharts';
import { useTheme } from 'vuetify';
import { getDonutChartConfig } from './apexChartConfig';
@ -13,7 +13,7 @@ const expenseRationChartConfig = computed(() =>
</script>
<template>
<VueApexCharts
<ApexCharts
type="donut"
height="410"
:options="expenseRationChartConfig"

View File

@ -1,17 +1,14 @@
<script lang="ts" setup>
import VueApexCharts from 'vue3-apexcharts';
import ApexCharts from 'vue3-apexcharts';
import { useTheme } from 'vuetify';
import {
getAreaChartSplineConfig,
getMarketPriceChartConfig,
} from './apexChartConfig';
import { getMarketPriceChartConfig } from './apexChartConfig';
import { useIndexModule } from '@/modules/[chain]/indexStore';
import { computed, ref } from '@vue/reactivity';
const store = useIndexModule();
const vuetifyTheme = useTheme();
const chartConfig = computed(() => {
const labels = store.marketData.prices.map((x) => x[0]);
const labels = store.marketData.prices.map((item: any) => item[0]);
return getMarketPriceChartConfig(vuetifyTheme.current.value, labels);
});
const kind = ref('price');
@ -21,8 +18,8 @@ const series = computed(() => {
name: 'Price',
data:
kind.value === 'price'
? store.marketData.prices.map((x) => x[1])
: store.marketData.total_volumes.map((x) => x[1]),
? store.marketData.prices.map((item: any) => item[1])
: store.marketData.total_volumes.map((item: any) => item[1]),
},
];
});
@ -49,7 +46,7 @@ function changeChart(type: string) {
Volume
</a>
</div>
<VueApexCharts
<ApexCharts
type="area"
height="230"
:options="chartConfig"

View File

@ -21,10 +21,10 @@ const items = computed(() => [
<template>
<div class="d-flex flex-rows align-center">
<span class="text-h5 mr-3">{{ moduleName }}</span>
<Icon icon="mdi-dots-vertical"/>
<Icon icon="mdi-dots-vertical" />
<VBreadcrumbs :items="items">
<template v-slot:divider>
<Icon icon="mdi-chevron-right"/>
<Icon icon="mdi-chevron-right" />
</template>
</VBreadcrumbs>
</div>

View File

@ -147,15 +147,15 @@ loadAccount(props.address);
<!-- list-->
<div class="">
<!--balances -->
<div class="flex items-center px-4 mb-2" v-for="(balanceItem, index) in balances" :key="index">
<div
class="flex items-center px-4 mb-2"
v-for="(balanceItem, index) in balances"
:key="index"
>
<div
class="w-9 h-9 rounded overflow-hidden flex items-center justify-center relative mr-4"
>
<Icon
icon="mdi-account-cash"
class="text-info"
size="20"
/>
<Icon icon="mdi-account-cash" class="text-info" size="20" />
<div
class="absolute top-0 bottom-0 left-0 right-0 bg-info opacity-20"
></div>
@ -176,15 +176,15 @@ loadAccount(props.address);
</div>
</div>
<!--delegations -->
<div class="flex items-center px-4 mb-2" v-for="(delegationItem, index) in delegations" :key="index">
<div
class="flex items-center px-4 mb-2"
v-for="(delegationItem, index) in delegations"
:key="index"
>
<div
class="w-9 h-9 rounded overflow-hidden flex items-center justify-center relative mr-4"
>
<Icon
icon="mdi-user-clock"
class="text-warning"
size="20"
/>
<Icon icon="mdi-user-clock" class="text-warning" size="20" />
<div
class="absolute top-0 bottom-0 left-0 right-0 bg-warning opacity-20"
></div>
@ -201,11 +201,20 @@ loadAccount(props.address);
<span
class="inset-x-0 inset-y-0 opacity-10 absolute bg-primary text-sm"
></span>
{{ format.calculatePercent(delegationItem?.balance?.amount, totalAmount) }}
{{
format.calculatePercent(
delegationItem?.balance?.amount,
totalAmount
)
}}
</div>
</div>
<!-- rewards.total -->
<div class="flex items-center px-4 mb-2" v-for="(rewardItem, index) in rewards.total" :key="index">
<div
class="flex items-center px-4 mb-2"
v-for="(rewardItem, index) in rewards.total"
:key="index"
>
<div
class="w-9 h-9 rounded overflow-hidden flex items-center justify-center relative mr-4"
>
@ -450,12 +459,12 @@ loadAccount(props.address);
</td>
<td>
{{ format.messages(v.tx.body.messages) }}
<VIcon
<Icon
v-if="v.code === 0"
icon="mdi-check"
color="success"
></VIcon>
<VIcon v-else icon="mdi-multiply" color="error"></VIcon>
class="text-success text-lg"
/>
<Icon v-else icon="mdi-multiply" class="text-error text-lg" />
</td>
<td>{{ format.toDay(v.timestamp, 'from') }}</td>
</tr>
@ -470,10 +479,5 @@ loadAccount(props.address);
<DynamicComponent :value="account" />
</div>
</div>
<div v-else>Account does not exists on chain</div>
<div v-else class="text-no text-sm">Account does not exists on chain</div>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 5px;
}
</style>

View File

@ -55,13 +55,13 @@ export const useBlockModule = defineStore('blockModule', {
});
},
async fetchLatest() {
this.latest = await this.blockchain.rpc.getBaseBlockLatest();
this.latest = await this.blockchain.rpc?.getBaseBlockLatest();
if (this.recents.length >= 50) this.recents.shift();
this.recents.push(this.latest);
return this.latest;
},
async fetchBlock(height: string) {
this.current = await this.blockchain.rpc.getBaseBlockAt(height);
this.current = await this.blockchain.rpc?.getBaseBlockAt(height);
return this.current;
},
},

View File

@ -7,7 +7,7 @@ const store = useGovStore();
onMounted(() => {
store.fetchProposals('2').then((x) => {
if (x.proposals.length === 0) {
if (x?.proposals?.length === 0) {
tab.value = '3';
store.fetchProposals('3');
}

View File

@ -142,14 +142,14 @@ export const useIndexModule = defineStore('module-index', {
title: 'Height',
color: 'primary',
icon: 'mdi-pound',
stats: String(base.latest.block?.header?.height || 0),
stats: String(base?.latest?.block?.header?.height || 0),
change: 0,
},
{
title: 'Validators',
color: 'error',
icon: 'mdi-human-queue',
stats: String(base.latest.block?.last_commit?.signatures.length || 0),
stats: String(base?.latest?.block?.last_commit?.signatures.length || 0),
change: 0,
},
{
@ -198,9 +198,9 @@ export const useIndexModule = defineStore('module-index', {
useDistributionStore()
.fetchCommunityPool()
.then((x) => {
this.communityPool = x.pool
.filter((t) => t.denom.length < 10)
.map((t) => ({
this.communityPool = x?.pool
?.filter((t) => t.denom.length < 10)
?.map((t) => ({
amount: String(parseInt(t.amount)),
denom: t.denom,
}));

View File

@ -49,7 +49,7 @@ const messages = computed(() => {
<tr>
<td>Status</td>
<td>
<VChip color="primary">oioio</VChip>
<div class="badge badge-primary badge-sm">oioio</div>
<div
class="text-xs truncate relative py-2 px-4 rounded-full w-fit mr-2"
:class="`text-${

View File

@ -1,52 +1,27 @@
<script setup lang="ts">
import misc404 from '@images/pages/404.png';
import miscObj from '@images/pages/misc-404-object.png';
import miscMaskDark from '@images/pages/misc-mask-dark.png';
import miscMaskLight from '@images/pages/misc-mask-light.png';
import { useGenerateImageVariant } from '@/plugins/vuetify/@core/composable/useGenerateImageVariant';
const miscThemeMask = useGenerateImageVariant(miscMaskLight, miscMaskDark);
</script>
<template>
<div class="misc-wrapper">
<ErrorHeader
error-code="404"
error-title="Page Not Found ⚠️"
error-description="We couldn't find the page you are looking for."
/>
<div class="pt-10">
<div class="text-center">
<div class="text-8xl font-semibold text-main">404</div>
<div class="text-xl font-bold my-2">Page Not Found</div>
<div class="text-base">
We couldn't find the page you are looking for.
</div>
</div>
<!-- 👉 Image -->
<div class="misc-avatar w-100 text-center">
<VImg
:src="misc404"
alt="Coming Soon"
:height="$vuetify.display.xs ? 400 : 500"
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"
/>
<RouterLink to="/" class="btn no-underline btn-primary mt-4">
Back to Home
</RouterLink>
<img :src="misc404" alt="Coming Soon" class="mx-auto h-[400px] mt-10" />
</div>
</div>
</template>
<style lang="scss">
@use '@core/scss/template/pages/misc.scss';
</style>
<route lang="yaml">
meta:
layout: blank

View File

@ -1,17 +0,0 @@
<template>
<div>
<VCard title="Create Awesome 🙌">
<VCardText>This is your second page.</VCardText>
<VCardText>
Chocolate sesame snaps pie carrot cake pastry pie lollipop muffin.
Carrot cake dragée chupa chups jujubes. Macaroon liquorice cookie wafer
tart marzipan bonbon. Gingerbread jelly-o dragée chocolate.
</VCardText>
</VCard>
</div>
</template>
<route lang="yaml">
meta:
layout: blank
bgColor: yellow
</route>

View File

@ -33,11 +33,11 @@ export const useBaseStore = defineStore('baseStore', {
return useBlockchain();
},
txsInRecents() {
const txs = [] as { height: string, hash: string; tx: DecodedTxRaw }[];
const txs = [] as { height: string; hash: string; tx: DecodedTxRaw }[];
this.recents.forEach((b) =>
b.block?.data?.txs.forEach((tx: string) => {
if (tx) {
const raw = fromBase64(tx)
const raw = fromBase64(tx);
try {
txs.push({
height: b.block.header.height,
@ -45,7 +45,7 @@ export const useBaseStore = defineStore('baseStore', {
tx: decodeTxRaw(raw),
});
} catch (e) {
console.error(e)
console.error(e);
}
}
})
@ -61,18 +61,22 @@ export const useBaseStore = defineStore('baseStore', {
this.recents = [];
},
async fetchLatest() {
this.latest = await this.blockchain.rpc.getBaseBlockLatest();
this.latest = await this.blockchain.rpc?.getBaseBlockLatest();
if (
!this.earlest ||
this.earlest.block?.header?.chain_id !=
this.latest.block?.header?.chain_id
this.earlest?.block?.header?.chain_id !=
this.latest?.block?.header?.chain_id
) {
//reset earlest and recents
this.earlest = this.latest;
this.recents = [];
}
//check if the block exists in recents
if(this.recents.findIndex(x => x.block_id.hash === this.latest.block_id.hash) === -1 ) {
if (
this.recents.findIndex(
(x) => x?.block_id?.hash === this.latest?.block_id?.hash
) === -1
) {
if (this.recents.length >= 50) {
this.recents.pop();
}
@ -87,7 +91,7 @@ export const useBaseStore = defineStore('baseStore', {
async fetchLatestValidators(offset = 0) {
return this.blockchain.rpc.getBaseValidatorsetLatest(offset);
},
async fetchBlock(height?: number|string) {
async fetchBlock(height?: number | string) {
return this.blockchain.rpc.getBaseBlockAt(String(height));
},
async fetchAbciInfo() {

View File

@ -12,7 +12,7 @@ export const useDistributionStore = defineStore('distributionStore', {
},
actions: {
async fetchCommunityPool() {
return this.blockchain.rpc.getDistributionCommunityPool();
return this.blockchain.rpc?.getDistributionCommunityPool();
},
},
});

View File

@ -54,8 +54,8 @@ export const useFormatter = defineStore('formatter', {
return useBankStore();
},
dashboard() {
return useDashboard()
}
return useDashboard();
},
},
actions: {
async fetchDenomTrace(denom: string) {
@ -69,30 +69,31 @@ export const useFormatter = defineStore('formatter', {
return trace;
},
priceInfo(denom: string) {
const id = this.dashboard.coingecko[denom]?.coinId
const prices = this.dashboard.prices[id]
return prices
const id = this.dashboard.coingecko[denom]?.coinId;
const prices = this.dashboard.prices[id];
return prices;
},
price(denom: string, currency = "usd") {
price(denom: string, currency = 'usd') {
const info = this.priceInfo(denom);
return info? info[currency]||0 : 0
return info ? info[currency] || 0 : 0;
},
priceChanges(denom: string, currency="usd"): number {
priceChanges(denom: string, currency = 'usd'): number {
const info = this.priceInfo(denom);
return info? info[`${currency}_24h_change`]||0 : 0
return info ? info[`${currency}_24h_change`] || 0 : 0;
},
showChanges(v: number) {
return numeral(v).format("+0,0.[00]")
return numeral(v).format('+0,0.[00]');
},
tokenValue(token: Coin) {
// find the symbol,
const symbol = this.dashboard.coingecko[token.denom]?.symbol || ""
const symbol = this.dashboard.coingecko[token.denom]?.symbol || '';
// convert denomation to to symbol
const exponent = this.dashboard.coingecko[symbol.toLowerCase()]?.exponent || 0
const exponent =
this.dashboard.coingecko[symbol.toLowerCase()]?.exponent || 0;
// cacualte amount of symbol
const amount = Number(token.amount) / (10 ** exponent)
const value = amount * this.price(token.denom)
return numeral(value).format('0,0.[00]')
const amount = Number(token.amount) / 10 ** exponent;
const value = amount * this.price(token.denom);
return numeral(value).format('0,0.[00]');
},
formatTokenAmount(token: { denom: string; amount: string }) {
return this.formatToken(token, false);
@ -105,7 +106,7 @@ export const useFormatter = defineStore('formatter', {
withDenom = true,
fmt = '0.0a'
): string {
if (token && token.amount) {
if (token && token.amount && token?.denom) {
let amount = Number(token.amount);
let denom = token.denom;
@ -211,11 +212,11 @@ export const useFormatter = defineStore('formatter', {
}
return dayjs(time).format('YYYY-MM-DD HH:mm:ss');
},
messages(msgs: { '@type'?: string, typeUrl?: string }[]) {
messages(msgs: { '@type'?: string; typeUrl?: string }[]) {
if (msgs) {
const sum: Record<string, number> = msgs
.map((msg) => {
const msgType = msg['@type'] || msg.typeUrl || 'unknown'
const msgType = msg['@type'] || msg.typeUrl || 'unknown';
return msgType
.substring(msgType.lastIndexOf('.') + 1)
.replace('Msg', '');

View File

@ -29,10 +29,10 @@ export const useGovStore = defineStore('govStore', {
if (!this.loading[status]) {
this.loading[status] = LoadingStatus.Loading;
const proposals = reactive(
await this.blockchain.rpc.getGovProposals(status)
await this.blockchain.rpc?.getGovProposals(status)
);
if (status === '2') {
proposals.proposals.forEach(async (x1) => {
proposals?.proposals?.forEach(async (x1) => {
await this.fetchTally(x1.proposal_id).then((res) => {
x1.final_tally_result = res?.tally;
});

View File

@ -17,14 +17,16 @@ export const useMintStore = defineStore('mintStore', {
this.fetchInflation();
},
async fetchInflation() {
this.blockchain.rpc
.getMintInflation()
.then((x) => {
this.inflation = x.inflation;
})
.catch(() => {
try {
const res = await this.blockchain?.rpc?.getMintInflation().catch(() => {
this.inflation = '0';
});
if (res) {
this.inflation = res.inflation;
}
} catch (e) {
console.log(e);
}
},
},
});

View File

@ -203,19 +203,19 @@ export const useParamStore = defineStore('paramstore', {
console.log('handleAbciInfo', this.nodeVersion.items);
},
async getBaseTendermintBlockLatest() {
return await this.blockchain.rpc.getBaseBlockLatest();
return await this.blockchain.rpc?.getBaseBlockLatest();
},
async getMintParam() {
return await this.blockchain.rpc.getMintParam();
return await this.blockchain.rpc?.getMintParam();
},
async getStakingParams() {
return await this.blockchain.rpc.getStakingParams();
return await this.blockchain.rpc?.getStakingParams();
},
async getStakingPool() {
return await this.blockchain.rpc.getStakingPool();
return await this.blockchain.rpc?.getStakingPool();
},
async getBankTotal(denom: string) {
return await this.blockchain.rpc.getBankSupplyByDenom(denom);
return await this.blockchain.rpc?.getBankSupplyByDenom(denom);
// if (compareVersions(this.config.sdk_version, '0.46.2') > 0) {
// return this.get(`/cosmos/bank/v1beta1/supply/by_denom?denom=${denom}`).then(data => commonProcess(data).amount)
// }
@ -225,22 +225,22 @@ export const useParamStore = defineStore('paramstore', {
// return this.get(`/cosmos/bank/v1beta1/supply/${denom}`).then(data => commonProcess(data).amount)
},
async getSlashingParams() {
return await this.blockchain.rpc.getSlashingParams();
return await this.blockchain.rpc?.getSlashingParams();
},
async getDistributionParams() {
return await this.blockchain.rpc.getDistributionParams();
return await this.blockchain.rpc?.getDistributionParams();
},
async getGovParamsVoting() {
return await this.blockchain.rpc.getGovParamsVoting();
return await this.blockchain.rpc?.getGovParamsVoting();
},
async getGovParamsDeposit() {
return await this.blockchain.rpc.getGovParamsDeposit();
return await this.blockchain.rpc?.getGovParamsDeposit();
},
async getGovParamsTally() {
return await this.blockchain.rpc.getGovParamsTally();
return await this.blockchain.rpc?.getGovParamsTally();
},
async fetchAbciInfo() {
return this.blockchain.rpc.getBaseNodeInfo();
return this.blockchain.rpc?.getBaseNodeInfo();
},
},
});

View File

@ -47,14 +47,16 @@ export const useStakingStore = defineStore('stakingStore', {
);
},
async fetchParams() {
const response = await this.blockchain.rpc.getStakingParams();
if (response.params) this.params = response.params;
const response = await this.blockchain.rpc?.getStakingParams();
if (response?.params) this.params = response.params;
return this.params;
},
async fetchPool() {
const response = await this.blockchain.rpc.getStakingPool();
const response = await this.blockchain.rpc?.getStakingPool();
if (response) {
response.pool.bonded_tokens;
this.pool = response.pool;
}
},
async fetchAcitveValdiators() {
return this.fetchValidators('BOND_STATUS_BONDED');
@ -69,13 +71,13 @@ export const useStakingStore = defineStore('stakingStore', {
validatorAddr: string,
delegatorAddr: string
) {
return await this.blockchain.rpc.getStakingValidatorsDelegationsDelegator(
return await this.blockchain.rpc?.getStakingValidatorsDelegationsDelegator(
validatorAddr,
delegatorAddr
);
},
async fetchValidators(status: string) {
return this.blockchain.rpc.getStakingValidators(status).then((res) => {
return this.blockchain.rpc?.getStakingValidators(status).then((res) => {
const vals = res.validators.sort(
(a, b) => Number(b.delegator_shares) - Number(a.delegator_shares)
);