Skip to content

Commit

Permalink
fix eslint
Browse files Browse the repository at this point in the history
  • Loading branch information
onmax committed Aug 20, 2024
1 parent 3872d16 commit ef4cdd6
Show file tree
Hide file tree
Showing 30 changed files with 430 additions and 374 deletions.
8 changes: 4 additions & 4 deletions app/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ const { data: health } = useFetch('/api/vts/health')
<header flex="~ gap-32 row items-center">
<NuxtLink to="/" flex>
<div aria-hidden i-nimiq:logos-nimiq-horizontal class="!ml-16 !h-24 !w-90" dark:i-nimiq:logos-nimiq-white-horizontal />
<span font-light text-16 tracking-0.75 ml-8>Validators</span>
<span top--6 relative h-max py-2 px-6 ml-6 nq-label text-orange bg="orange/10" rounded-2 text-9>{{ networkName }}</span>
<span ml-8 text-16 font-light tracking-0.75>Validators</span>
<span bg="orange/10" relative top--6 ml-6 h-max rounded-2 px-6 py-2 text-9 text-orange nq-label>{{ networkName }}</span>
</NuxtLink>
<NuxtLink v-if="validatorDetail" to="/" block w-max nq-arrow-back nq-ghost-btn>
Go back
</NuxtLink>
<div flex-auto />
<NuxtLink to="/vts/health" :class="{ 'bg-green/10 text-green': health?.isSynced, 'bg-red/10 text-red': !health?.isSynced}" px-12 py-4 rounded-full text-11 flex="~ items-center gap-6">
<div text-10 :class="health?.isSynced ? 'i-nimiq:check' : 'i-nimiq:alert'"/>
<NuxtLink to="/vts/health" :class="{ 'bg-green/10 text-green': health?.isSynced, 'bg-red/10 text-red': !health?.isSynced }" rounded-full px-12 py-4 text-11 flex="~ items-center gap-6">
<div text-10 :class="health?.isSynced ? 'i-nimiq:check' : 'i-nimiq:alert'" />
<span font-semibold>{{ health?.isSynced ? 'Synced' : 'Not Synced' }}</span>
</NuxtLink>
<NuxtLink to="https://github.com/onmax/nimiq-validators" i-nimiq:logos-github-mono target="_blank" />
Expand Down
7 changes: 4 additions & 3 deletions app/components/Copyable.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
const props = withDefaults(defineProps<{ content: string, enableClipboard?: boolean }>(),{enableClipboard: false})
const props = withDefaults(defineProps<{ content: string, enableClipboard?: boolean }>(), { enableClipboard: false })
const { copy, isSupported } = useClipboard()
Expand All @@ -12,8 +12,9 @@ function copyAddress() {

<template>
<p
text-neutral-800 text-12 font-semibold whitespace-nowrap lh-none tracking-wide p-4 rounded-4
:class="{ 'hover:cursor-pointer hover:bg-neutral-200': enableClipboard }" @click="copyAddress">
text-neutral-800 text-12 font-semibold whitespace-nowrap lh-none tracking-wide p-4 rounded-4
:class="{ 'hover:cursor-pointer hover:bg-neutral-200': enableClipboard }" @click="copyAddress"
>
<slot>
{{ content }}
</slot>
Expand Down
19 changes: 10 additions & 9 deletions app/components/Donut.client.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
<script setup lang="ts">
import { VisSingleContainer, VisDonut, VisTooltip } from '@unovis/vue'
import { VisDonut, VisSingleContainer, VisTooltip } from '@unovis/vue'
import { Donut } from '@unovis/ts'
import type { Validator } from '~~/server/api/vts/index.get';
import ScorePies from './ScorePies.vue';
import { render, toDisplayString } from 'vue'
import { render } from 'vue'
import ScorePies from './ScorePies.vue'
import type { Validator } from '~~/server/api/vts/index.get'
defineProps<{ data: Validator[] }>()
const isMounted = useMounted()
const props = defineProps<{ data: Validator[] }>()
// TOOD We should so balance disitrubtion not size score!!! -->
const value = (d: Validator) => d.size
const label = (d: Validator) => d.name || d.address
const colors = ['red','orange','blue','green','gold']
const colors = ['red', 'orange', 'blue', 'green', 'gold']
const color = (d: number, i: number) => `rgb(var(--nq-${colors[i % colors.length]}))`
function template(v: Validator) {
Expand All @@ -25,13 +26,13 @@ function template(v: Validator) {
<p text="11 neutral-900" m-0>${address}</p>
${div.innerHTML}
</div>
`
`
}
</script>

<template>
<VisSingleContainer :data :style="{ height: isMounted ? '100%' : 'auto' }" :margin="{ left: 20, right: 20 }">
<VisTooltip :triggers="{ [Donut.selectors.segment]: (item) => template(item.data) }" style="--vis-tooltip-padding: 0 0"/>
<VisTooltip :triggers="{ [Donut.selectors.segment]: (item) => template(item.data) }" style="--vis-tooltip-padding: 0 0" />
<VisDonut :value :label :arc-width="40" :color />
</VisSingleContainer>
</template>
Expand All @@ -40,4 +41,4 @@ function template(v: Validator) {
:root {
--vis-tooltip-padding: 0;
}
</style>
</style>
32 changes: 21 additions & 11 deletions app/components/ScorePie.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const strokeWidth = 10
const radius = center - strokeWidth / 2
function generateArcPath(score: number) {
if (score >= 0.999) score = 0.99 // TODO Improve this
if (score >= 0.999)
score = 0.99 // TODO Improve this
const startAngle = -Math.PI / 2 // start at the top of the circle
const endAngle = startAngle + score * 2 * Math.PI
Expand All @@ -23,30 +24,39 @@ function generateArcPath(score: number) {
}
const strokeColor = computed(() => {
if (!props.score || props.score < 0.6) return 'stroke-red'
if (props.score < 0.85) return 'stroke-gold'
if (!props.score || props.score < 0.6)
return 'stroke-red'
if (props.score < 0.85)
return 'stroke-gold'
return 'stroke-green'
})
</script>

<template>
<div grid="~ cols-1 rows-1 place-content-center *:row-span-full *:col-span-full">
<template v-if="score !== null">
<div font-bold size-full grid="~ place-content-center">{{ (score * 100).toFixed(0) }}</div>
<div font-bold size-full grid="~ place-content-center">
{{ (score * 100).toFixed(0) }}
</div>
<svg
bg-transparent :viewBox="`0 0 ${viewBoxSize} ${viewBoxSize}`" height="100%" width="100%"
preserveAspectRatio="xMidYMid slice">
bg-transparent :viewBox="`0 0 ${viewBoxSize} ${viewBoxSize}`" height="100%" width="100%"
preserveAspectRatio="xMidYMid slice"
>
<circle :r="radius" :cx="center" :cy="center" stroke-neutral-400 fill-none :stroke-width="strokeWidth" />
<path
:d="generateArcPath(score)" :class="strokeColor" fill-none :stroke-width="strokeWidth"
stroke-linecap="round" />
:d="generateArcPath(score)" :class="strokeColor" fill-none :stroke-width="strokeWidth"
stroke-linecap="round"
/>
</svg>
</template>
<template v-else>
<div font-bold size-full grid="~ place-content-center">NA</div>
<div font-bold size-full grid="~ place-content-center">
NA
</div>
<svg
bg-transparent :viewBox="`0 0 ${viewBoxSize} ${viewBoxSize}`" height="100%" width="100%"
preserveAspectRatio="xMidYMid slice">
bg-transparent :viewBox="`0 0 ${viewBoxSize} ${viewBoxSize}`" height="100%" width="100%"
preserveAspectRatio="xMidYMid slice"
>
<circle :r="radius" :cx="center" :cy="center" stroke-neutral-400 fill-none :stroke-width="strokeWidth" />
</svg>
</template>
Expand Down
2 changes: 1 addition & 1 deletion app/components/ScorePies.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import type { Validator } from '~~/server/api/validators/index.get';
import type { Validator } from '~~/server/api/validators/index.get'
defineProps<{ validator: Validator }>()
</script>
Expand Down
2 changes: 1 addition & 1 deletion app/components/Stat.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
<slot name="description" />
</span>
</div>
</template>
</template>
40 changes: 25 additions & 15 deletions app/components/ValidatorsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,45 @@ defineProps<{ validators: Validator[] }>()

<template>
<div
v-if="validators.length > 0" grid="~ gap-x-32" :style="`grid-template-columns: 56px max-content 1fr max-content`"
of-x-auto mx--32 px-32>
<div/>
<div nq-label font-bold text="11 neutral-700" py-2>Name</div>
<div nq-label font-bold text="11 neutral-700" py-2>Address</div>
<div nq-label font-bold text="11 neutral-700" py-2 text-center>Score</div>
v-if="validators.length > 0" grid="~ gap-x-32" style="grid-template-columns: 56px max-content 1fr max-content"
of-x-auto mx--32 px-32
>
<div />
<div nq-label font-bold text="11 neutral-700" py-2>
Name
</div>
<div nq-label font-bold text="11 neutral-700" py-2>
Address
</div>
<div nq-label font-bold text="11 neutral-700" py-2 text-center>
Score
</div>
<NuxtLink
v-for="validator in validators" :key="validator.address" :to="`/validator/${validator.address}`"
v-for="validator in validators" :key="validator.address" :to="`/validator/${validator.address}`"
border="t neutral-200" grid="~ rows-subgrid cols-subgrid col-span-full items-center"
bg="transparent even:neutral-50 hocus:neutral-200 hocus:even:neutral-300" transition-colors py-16>

bg="transparent even:neutral-50 hocus:neutral-200 hocus:even:neutral-300" transition-colors py-16
>
<NuxtImg
:src="validator.icon" :alt="validator.name!" size-32 mr--20 ml-20 object-contain
:style="{ 'view-transition-name': `logo-${validator.id}` }" />
:src="validator.icon" :alt="validator.name!" size-32 mr--20 ml-20 object-contain
:style="{ 'view-transition-name': `logo-${validator.id}` }"
/>

<div mr-24 flex="~ items-center gap-8">
<h2 text-14 op-90 lh-none font-light w-max :style="{ 'view-transition-name': `h-${validator.id}` }">
{{ validator.name }}
</h2>
<div
v-if="validator.tag === ValidatorTag.Nimiq" i-nimiq:icons-lg-verified-filled text="13 green/70"
title="Maintained by Nimiq" />
v-if="validator.tag === ValidatorTag.Nimiq" i-nimiq:icons-lg-verified-filled text="13 green/70"
title="Maintained by Nimiq"
/>
</div>

<Copyable :content="validator.address" :style="{ 'view-transition-name': `address-${validator.id}` }" />

<ScorePie
size-32 text-12 mx-auto :score="validator.total"
:style="{ 'view-transition-name': `score-${validator.id}` }" />
size-32 text-12 mx-auto :score="validator.total"
:style="{ 'view-transition-name': `score-${validator.id}` }"
/>
</NuxtLink>
</div>
<div v-else>
Expand Down
37 changes: 26 additions & 11 deletions app/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ const { data, status, error } = useFetch('/api/vts')
const validators = computed(() => data.value?.validators || [])
const averageScore = computed(() => {
if (!validators.value?.length) return 0
if (!validators.value?.length)
return 0
const scores = validators.value.map(validator => validator.total).filter(t => !!t) as number[]
const totalScore = scores?.reduce((acc, score) => acc + score, 0) || 0
return totalScore / validators.value.length
Expand All @@ -14,29 +15,43 @@ const averageScore = computed(() => {
<div v-if="status === 'pending'">
Loading...
</div>
<div v-if="status === 'error'">
<div v-else-if="status === 'error'">
There was an error: {{ JSON.stringify(error) }}
</div>

<div flex="~ col" pt-64 pb-128 v-if="status === 'success'">
<div v-else-if="status === 'success'" flex="~ col" pt-64 pb-128>
<div flex="~ wrap gap-96 justify-center" of-x-auto mx--32 px-32 pb-64>
<Stat text-green>
<template #value>{{ validators?.length }}</template>
<template #description>Validators</template>
<template #value>
{{ validators?.length }}
</template>
<template #description>
Validators
</template>
</Stat>
<Stat text-blue>
<template #value>{{data?.epochNumber}}</template>
<template #description>Epoch</template>
<template #value>
{{ data?.epochNumber }}
</template>
<template #description>
Epoch
</template>
</Stat>
<Stat text-red>
<template #value>{{ (averageScore * 100).toFixed(2) }}</template>
<template #description>Avg. score</template>
<template #value>
{{ (averageScore * 100).toFixed(2) }}
</template>
<template #description>
Avg. score
</template>
</Stat>
</div>

<ValidatorsTable :validators mt-96 />

<h2 text-center mt-128>Size distribution</h2>
<h2 text-center mt-128>
Size distribution
</h2>

<Donut :data="validators" mt-48 />
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/pages/validator/[address].vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const validator = computed(() => {
mx-auto mt-32 size-128 text-40 :score="validator.total"
:style="{ 'view-transition-name': `score-${validator.id}` }"
/>
<ScorePies :validator text-28 mt-64 />

<ScorePies :validator mt-64 text-28 />
<!-- <div self-stretch w-2 bg-neutral-300 mx-48 /> -->

<p mt-32 block max-w-700 text-neutral-900>
Expand Down
42 changes: 24 additions & 18 deletions app/pages/vts/health.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ const network = useRuntimeConfig().public.nimiqNetwork
<template>
<div class="nq-prose">
<div flex="~ items-center justify-between">
<h1 max-w-inherit my-32>Network <code px-4 rounded-6>{{ network }}</code></h1>
<NuxtLink to="/api/vts/health" target="_blank" nq-arrow nq-pill-tertiary text-12 op-80>
<h1 my-32 max-w-inherit>
Network <code rounded-6 px-4>{{ network }}</code>
</h1>
<NuxtLink to="/api/vts/health" target="_blank" text-12 op-80 nq-arrow nq-pill-tertiary>
API
</NuxtLink>
</NuxtLink>
</div>

<div v-if="status === 'pending'">
Expand All @@ -20,10 +22,14 @@ const network = useRuntimeConfig().public.nimiqNetwork
<p>Failed to fetch health data</p>
<pre>{{ error }}</pre>
</div>

<div v-else-if="status === 'success' && health" mt-12>
<p v-if="health.isSynced">The network is <span text-green font-bold>synced</span></p>
<p v-else>The network is <span text-red font-bold>not synced</span></p>
<p v-if="health.isSynced">
The network is <span text-green font-bold>synced</span>
</p>
<p v-else>
The network is <span text-red font-bold>not synced</span>
</p>

<p v-if="health.flags.length > 0">
{{ JSON.stringify(health.flags) }}
Expand All @@ -33,40 +39,41 @@ const network = useRuntimeConfig().public.nimiqNetwork
<p>
Range: [{{ health.range.fromEpoch }} - {{ health.range.toEpoch }}] ({{ health.range.epochCount }} epochs)
</p>
<p text-neutral-700 text-13 m-0>
<p m-0 text-13 text-neutral-700>
The range of blocks used to compute the score of the validators. We don't consider the first epoch as it is an speacial epoch.
</p>
</div>


<div mt-16>
<p>
Current Epoch: {{ health.currentEpoch }}
</p>
<p m-0>
Latest Fetched Epoch: {{ health.latestFetchedEpoch }}
</p>
<p text-neutral-700 text-13 m-0>
<p m-0 text-13 text-neutral-700>
We only use finished epochs to compute the score of the validators.
</p>
</div>

<template v-if="health.missingEpochs.length > 0">
<h3>Missing Epochs</h3>
<p v-for="epoch in health.missingEpochs" :key="epoch">{{ epoch }}</p>
<p v-for="epoch in health.missingEpochs" :key="epoch">
{{ epoch }}
</p>
</template>

<p mt-32>
{{ health.fetchedEpochs.length }} epochs fetched
</p>
<p text-11 m-0>
{{ health.fetchedEpochs.join(', ') }}
</p>
<p mt-32>
{{ health.fetchedEpochs.length }} epochs fetched
</p>
<p m-0 text-11>
{{ health.fetchedEpochs.join(', ') }}
</p>

<p mt-32>
{{ health.missingEpochs.length }} epochs missing
</p>
<p v-if="health.missingEpochs.length > 0" text-11 m-0>
<p v-if="health.missingEpochs.length > 0" m-0 text-11>
{{ health.missingEpochs.join(', ') }}
</p>

Expand All @@ -75,6 +82,5 @@ const network = useRuntimeConfig().public.nimiqNetwork
<pre px-2 font-12>{{ JSON.stringify(health, null, 2) }}</pre>
</details>
</div>

</div>
</template>
Loading

0 comments on commit ef4cdd6

Please sign in to comment.