Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.

Commit fdb4c6b

Browse files
authored
Merge pull request #848 from roiLeo/fix/component/series
fix(series): volume & days
2 parents d12be61 + 00cee94 commit fdb4c6b

File tree

7 files changed

+159
-64
lines changed

7 files changed

+159
-64
lines changed

src/components/landing/Series.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<template>
22
<div class="container mb-1">
33
<section>
4-
<h1 class="title is-2">Top Collection</h1>
5-
<p class="subtitle is-size-5">The top NFTs on RMRK, ranked by score, volume, floor price and other statistics.</p>
4+
<h1 class="title is-2">{{ $t('series.title') }}</h1>
5+
<p class="subtitle is-size-5">{{ $t('series.subtitle') }}</p>
66

77
<SeriesTable />
88
</section>

src/components/rmrk/Gallery/Search/query.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Row } from '@/components/spotlight/types'
2-
import { RowSeries } from '@/components/series/types'
2+
import { RowSeries, SortType } from '@/components/series/types'
33
import { Query, Aggregator } from 'mingo'
44
import { Collection as Aggregation } from 'mingo/core'
55
import { NFTWithMeta } from '../../service/scheme'
@@ -80,7 +80,7 @@ export const spotlightAggregation = (): Aggregator => {
8080
return new Aggregator(agg)
8181
}
8282

83-
export const seriesAggregation = (limit = 10): Aggregator => {
83+
export const seriesAggregation = (limit = 10, sort: SortType): Aggregator => {
8484
const agg: Aggregation = [
8585
{
8686
$group: {
@@ -94,17 +94,20 @@ export const seriesAggregation = (limit = 10): Aggregator => {
9494
averagePrice: { $avg: '$averagePrice' },
9595
floorPrice: { $sum: '$floorPrice' },
9696
count: { $sum: '$count' },
97-
// owned: { $sum: '$currentOwner' },
9897
rank: { $sum: '$rank' },
9998
volume: { $sum: '$volume' },
99+
dailyVolume: { $sum: '$dailyVolume' },
100100
weeklyVolume: { $sum: '$weeklyVolume' },
101101
monthlyVolume: { $sum: '$monthlyVolume' },
102+
dailyrangeVolume: { $sum: '$dailyrangeVolume' },
103+
weeklyrangeVolume: { $sum: '$weeklyrangeVolume' },
104+
monthlyrangeVolume: { $sum: '$monthlyrangeVolume' },
102105
name: { $first: '$name' },
103-
metadata: { $first: '$metadata' },
106+
metadata: { $first: '$metadata' }
104107
}
105108
},
106109
{
107-
$sort: { rank: -1 },
110+
$sort: { [sort['field']]: sort['value'] }
108111
},
109112
{
110113
$limit: limit
@@ -147,8 +150,8 @@ export const spotlightAggQuery = (nfts: Row[]) => {
147150
return query.run(nfts)
148151
}
149152

150-
export const seriesAggQuery = (limit: number, nfts: RowSeries[]) => {
151-
const query = seriesAggregation(limit)
153+
export const seriesAggQuery = (limit: number, sort: SortType, nfts: RowSeries[]) => {
154+
const query = seriesAggregation(limit, sort)
152155
return query.run(nfts)
153156
}
154157

src/components/series/SeriesTable.vue

Lines changed: 107 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,37 @@
11
<template>
22
<div>
3-
<b-field position="is-right">
4-
<b-radio-button
5-
v-model="nbRows"
6-
native-value="10"
7-
type="is-outlined"
8-
>10</b-radio-button>
9-
10-
<b-radio-button
11-
v-model="nbRows"
12-
native-value="50"
13-
type="is-outlined"
14-
>50</b-radio-button>
15-
16-
<b-radio-button
17-
v-model="nbRows"
18-
native-value="100"
19-
type="is-outlined"
20-
>100</b-radio-button>
3+
<b-field grouped>
4+
<b-field position="is-left" expanded>
5+
<b-radio-button
6+
v-model="nbDays"
7+
native-value="24"
8+
type="is-outlined"
9+
>24h</b-radio-button>
10+
11+
<b-radio-button
12+
v-model="nbDays"
13+
native-value="7"
14+
type="is-outlined"
15+
>7d</b-radio-button>
16+
17+
<b-radio-button
18+
v-model="nbDays"
19+
native-value="30"
20+
type="is-outlined"
21+
>30d</b-radio-button>
22+
</b-field>
23+
24+
<b-field class="has-text-right" expanded>
25+
<b-select v-model="nbRows">
26+
<option value="10">10</option>
27+
<option value="20">20</option>
28+
<option value="50">50</option>
29+
<option value="100">100</option>
30+
</b-select>
31+
</b-field>
2132
</b-field>
2233

23-
<b-table :data="data" hoverable>
34+
<b-table :data="data" backend-sorting @sort="onSort" hoverable>
2435
<b-table-column
2536
cell-class="is-vcentered"
2637
field="id"
@@ -73,78 +84,88 @@
7384
</b-table-column>
7485

7586
<b-table-column
76-
field="rank"
77-
:label="$t('spotlight.score')"
87+
field="volume"
88+
:label="$t('series.volume')"
7889
v-slot="props"
7990
sortable
8091
numeric
8192
cell-class="is-vcentered"
8293
>
83-
<template v-if="!isLoading">{{
84-
Math.ceil(props.row.rank)
85-
}}</template>
94+
<template v-if="!isLoading">
95+
<Money :value="props.row.volume" inline />
96+
</template>
8697
<b-skeleton :active="isLoading"> </b-skeleton>
8798
</b-table-column>
8899

89100
<b-table-column
90-
field="volume"
91-
label="Volume"
101+
field="dailyVolume"
102+
label="24h %"
92103
v-slot="props"
93104
sortable
94105
numeric
95106
cell-class="is-vcentered"
107+
:visible="nbDays === '24'"
96108
>
97109
<template v-if="!isLoading">
98-
<Money :value="props.row.volume" inline />
110+
<div
111+
v-html="
112+
displayVolumePercent(
113+
props.row.dailyVolume,
114+
props.row.dailyrangeVolume
115+
)
116+
"
117+
></div>
99118
</template>
100119
<b-skeleton :active="isLoading"> </b-skeleton>
101120
</b-table-column>
102121

103-
<!-- <b-table-column
122+
<b-table-column
104123
field="weeklyVolume"
105124
label="7d %"
106125
v-slot="props"
107126
sortable
108127
numeric
109128
cell-class="is-vcentered"
129+
:visible="nbDays === '7'"
110130
>
111131
<template v-if="!isLoading">
112132
<div
113133
v-html="
114134
displayVolumePercent(
115135
props.row.weeklyVolume,
116-
props.row.volume
136+
props.row.weeklyrangeVolume
117137
)
118138
"
119139
></div>
120140
</template>
121141
<b-skeleton :active="isLoading"> </b-skeleton>
122-
</b-table-column> -->
142+
</b-table-column>
123143

124-
<!-- <b-table-column
144+
<b-table-column
125145
field="monthlyVolume"
126146
label="30d %"
127147
v-slot="props"
128148
sortable
129149
numeric
130150
cell-class="is-vcentered"
151+
:visible="nbDays === '30'"
131152
>
132153
<template v-if="!isLoading">
133154
<div
134155
v-html="
135156
displayVolumePercent(
136157
props.row.monthlyVolume,
137-
props.row.volume
158+
props.row.monthlyrangeVolume
138159
)
139160
"
140161
></div>
141162
</template>
142163
<b-skeleton :active="isLoading"> </b-skeleton>
143-
</b-table-column> -->
164+
</b-table-column>
144165

145166
<b-table-column
146167
field="floorPrice"
147-
label="Floor price"
168+
:label="$t('series.floorprice')"
148169
v-slot="props"
149170
sortable
150171
numeric
@@ -157,32 +178,32 @@
157178
</b-table-column>
158179

159180
<b-table-column
160-
field="sold"
161-
label="Collected"
181+
field="uniqueCollectors"
182+
:label="$t('series.owners')"
162183
v-slot="props"
163184
sortable
164185
numeric
165186
cell-class="is-vcentered"
166187
>
167-
<template v-if="!isLoading">{{ props.row.sold }}</template>
188+
<template v-if="!isLoading">{{ props.row.uniqueCollectors }}</template>
168189
<b-skeleton :active="isLoading"> </b-skeleton>
169190
</b-table-column>
170191

171192
<b-table-column
172-
field="uniqueCollectors"
173-
label="Owners"
193+
field="sold"
194+
:label="$t('series.collected')"
174195
v-slot="props"
175196
sortable
176197
numeric
177198
cell-class="is-vcentered"
178199
>
179-
<template v-if="!isLoading">{{ props.row.uniqueCollectors }}</template>
200+
<template v-if="!isLoading">{{ props.row.sold }}</template>
180201
<b-skeleton :active="isLoading"> </b-skeleton>
181202
</b-table-column>
182203

183204
<b-table-column
184205
field="total"
185-
label="Assets"
206+
:label="$t('series.assets')"
186207
v-slot="props"
187208
sortable
188209
numeric
@@ -192,6 +213,20 @@
192213
<b-skeleton :active="isLoading"> </b-skeleton>
193214
</b-table-column>
194215

216+
<b-table-column
217+
field="rank"
218+
:label="$t('spotlight.score')"
219+
v-slot="props"
220+
sortable
221+
numeric
222+
cell-class="is-vcentered"
223+
>
224+
<template v-if="!isLoading">{{
225+
Math.ceil(props.row.rank)
226+
}}</template>
227+
<b-skeleton :active="isLoading"> </b-skeleton>
228+
</b-table-column>
229+
195230
<template #empty>
196231
<div v-if="!isLoading" class="has-text-centered">
197232
{{ $t('spotlight.empty') }}
@@ -204,7 +239,7 @@
204239

205240
<script lang="ts" >
206241
import { Component, Vue, Watch } from 'vue-property-decorator'
207-
import { Column, RowSeries } from './types'
242+
import { Column, RowSeries, SortType } from './types'
208243
import { columns, nftFn } from './utils'
209244
import collectionSeriesList from '@/queries/collectionSeriesList.graphql'
210245
import { seriesAggQuery } from '../rmrk/Gallery/Search/query'
@@ -221,23 +256,28 @@ const components = {
221256
}
222257
223258
@Component({ components })
224-
export default class SeriesTable extends Vue{
259+
export default class SeriesTable extends Vue {
225260
protected data: RowSeries[] = []
226261
protected columns: Column[] = columns
227262
protected usersWithIdentity: RowSeries[] = []
263+
protected nbDays = '7'
228264
protected nbRows = '10'
229-
public isLoading = false;
265+
protected sortBy: SortType = { field: 'volume', value: -1 }
266+
public isLoading = false
230267
231268
public meta: NFTMetadata = emptyObject<NFTMetadata>()
232269
233270
async created() {
234271
exist(this.$route.query.rows, (val) => {
235272
this.nbRows = val
236273
})
274+
exist(this.$route.query.period, (val) => {
275+
this.nbDays = val
276+
})
237277
await this.fetchCollectionsSeries(Number(this.nbRows))
238278
}
239279
240-
public async fetchCollectionsSeries(limit = 10) {
280+
public async fetchCollectionsSeries(limit = 10, sort: SortType = this.sortBy) {
241281
this.isLoading = true
242282
const collections = await this.$apollo.query({
243283
query: collectionSeriesList,
@@ -252,6 +292,7 @@ export default class SeriesTable extends Vue{
252292
253293
this.data = seriesAggQuery(
254294
limit,
295+
sort,
255296
collectionEntities?.nodes?.map(nftFn)
256297
) as RowSeries[]
257298
@@ -269,15 +310,28 @@ export default class SeriesTable extends Vue{
269310
this.isLoading = false
270311
}
271312
313+
public onSort(field: string, order: string) {
314+
let sort: SortType = { field: field, value: order === 'desc' ? -1 : 1 }
315+
this.fetchCollectionsSeries(Number(this.nbRows), sort)
316+
}
317+
272318
@Watch('nbRows')
273319
public onTopRowsChange(value: string) {
274320
this.$router.replace({
275321
name: String(this.$route.name),
276-
query: { rows: value },
277-
})
322+
query: { ...this.$route.query, rows: value },
323+
}).catch((e) => console.warn(e))
278324
this.fetchCollectionsSeries(Number(value))
279325
}
280326
327+
@Watch('nbDays')
328+
public onTopDaysChange(value: string) {
329+
this.$router.replace({
330+
name: String(this.$route.name),
331+
query: { ...this.$route.query, period: value },
332+
}).catch((e) => console.warn(e))
333+
}
334+
281335
public async fetchMetadataImage(metadata: any) {
282336
const m = await get(metadata)
283337
const meta = m ? m : await fetchCollectionMetadata({ metadata } as Collection)
@@ -287,15 +341,15 @@ export default class SeriesTable extends Vue{
287341
return sanitizeIpfsUrl(meta.image || '')
288342
}
289343
290-
public displayVolumePercent(firstVolume: number, volumeTotal: number) {
291-
const vol = (firstVolume / volumeTotal) * 100
292-
if (vol === 0) {
344+
public displayVolumePercent(priceNow: number, priceAgo: number) {
345+
const vol = ((priceNow - priceAgo) / priceAgo) * 100
346+
if (vol === 0 || !parseFloat(String(vol)) || !isFinite(vol)) {
293347
return '---'
294348
}
295-
const volumePercent = Math.ceil(vol * 100) / 100
296-
return volumePercent
349+
const volumePercent = Math.round(vol * 100) / 100
350+
return volumePercent > 0
297351
? `<div style="color: #41b883"> +${volumePercent}%</div>`
298-
: `<div class="has-text-danger"> -${volumePercent}%</div>`
352+
: `<div class="has-text-danger"> ${volumePercent}%</div>`
299353
}
300354
}
301355
</script>

0 commit comments

Comments
 (0)