3
3
<div class =" columns is-centered" >
4
4
<div class =" column is-half has-text-centered" >
5
5
<div class =" container image is-128x128 mb-2" >
6
- <b-image
7
- v-if =" !isLoading"
6
+ <BasicImage
8
7
:src =" image"
9
8
:alt =" name"
10
- ratio =" 1by1"
11
9
rounded
12
- ></b-image >
10
+ customClass =" collection__image"
11
+ />
13
12
</div >
14
13
<h1 class =" title is-2" >
15
- {{ name }}
14
+ <template v-if =" ! isLoading " >
15
+ {{ name }}
16
+ </template >
17
+ <b-skeleton :active =" isLoading" size =" is-medium" ></b-skeleton >
16
18
</h1 >
17
19
</div >
18
20
</div >
19
21
20
22
<div class =" columns is-align-items-center" >
21
23
<div class =" column" >
22
- <div class =" label" >
23
- {{ $t('creator') }}
24
- </div >
25
- <div class =" subtitle is-size-6" >
26
- <ProfileLink :address =" issuer" :inline =" true" :showTwitter =" true" />
27
- </div >
28
- </div >
29
- <div class =" column" v-if =" owner" >
30
- <div class =" label" >
31
- {{ $t('owner') }}
32
- </div >
33
- <div class =" subtitle is-size-6" >
34
- <ProfileLink :address =" owner" :inline =" true" :showTwitter =" true" />
24
+ <div v-if =" !isLoading" >
25
+ <div class =" label" >
26
+ {{ $t('creator') }}
27
+ </div >
28
+ <div v-if =" issuer" class =" subtitle is-size-6" >
29
+ <ProfileLink :address =" issuer" inline showTwitter />
30
+ </div >
35
31
</div >
32
+ <b-skeleton :active =" isLoading" width =" 40%" size =" is-small" ></b-skeleton >
33
+ <b-skeleton :active =" isLoading" width =" 60%" size =" is-small" ></b-skeleton >
36
34
</div >
35
+
37
36
<div class =" column is-6-tablet is-7-desktop is-8-widescreen" >
38
37
<CollectionActivity :nfts =" stats" />
39
38
</div >
39
+
40
40
<div class =" column has-text-right" >
41
41
<Sharing v-if =" sharingVisible"
42
42
class =" mb-2"
47
47
</div >
48
48
</div >
49
49
50
- <b-tabs v-model =" activeTab" position =" is-centered" >
51
- <b-tab-item label =" Collection" >
52
- <div class =" columns is-centered" >
53
- <div class =" column is-8 has-text-centered" >
54
- <CollapseWrapper
55
- visible =" collapse.collection.description.show"
56
- hidden =" collapse.collection.description.hide"
57
- >
58
- <VueMarkdown :source =" description" />
59
- </CollapseWrapper >
60
- </div >
61
- </div >
50
+ <div class =" columns is-centered" >
51
+ <div class =" column is-8 has-text-centered" >
52
+ <CollapseWrapper
53
+ visible =" collapse.collection.description.show"
54
+ hidden =" collapse.collection.description.hide"
55
+ >
56
+ <VueMarkdown :source =" description" />
57
+ </CollapseWrapper >
58
+ </div >
59
+ </div >
62
60
61
+ <b-tabs position =" is-centered" v-model =" activeTab" >
62
+ <b-tab-item label =" Collection" value =" collection" >
63
63
<Search v-bind.sync =" searchQuery" >
64
64
<Layout class =" mr-5" />
65
65
<b-field >
66
66
<Pagination hasMagicBtn simple replace preserveScroll :total =" total" v-model =" currentValue" :per-page =" first" />
67
67
</b-field >
68
68
</Search >
69
69
70
- <GalleryCardList :items =" collection.nfts" : horizontalLayout= " true " />
70
+ <GalleryCardList :items =" collection.nfts" horizontalLayout />
71
71
72
72
<Pagination
73
73
class =" py-5"
78
78
:per-page =" first"
79
79
/>
80
80
</b-tab-item >
81
- <b-tab-item label =" Activity" >
82
- <CollectionPriceChart v-if = " activeTab === 1 " :priceData =" priceData" />
81
+ <b-tab-item label =" Activity" value = " activity " >
82
+ <CollectionPriceChart :priceData =" priceData" />
83
83
</b-tab-item >
84
84
</b-tabs >
85
85
</section >
86
86
</template >
87
87
88
88
<script lang="ts" >
89
89
import { emptyObject } from ' @/utils/empty'
90
- import { Component , mixins } from ' nuxt-property-decorator'
90
+ import { Component , mixins , Watch } from ' nuxt-property-decorator'
91
91
import { CollectionWithMeta , Interaction } from ' ../service/scheme'
92
92
import {
93
93
sanitizeIpfsUrl , fetchCollectionMetadata , sortByTimeStamp , onlyEvents , onlyPriceEvents ,
94
94
eventTimestamp , soldNFTPrice , collectionFloorPriceList , PriceDataType , onlyBuyEvents
95
95
} from ' ../utils'
96
96
import isShareMode from ' @/utils/isShareMode'
97
+ import shouldUpdate from ' @/utils/shouldUpdate'
97
98
import collectionById from ' @/queries/collectionById.graphql'
98
99
import nftListByCollection from ' @/queries/nftListByCollection.graphql'
99
100
import { CollectionMetadata } from ' ../types'
100
101
import { NFT } from ' @/components/rmrk/service/scheme'
102
+ import { exist } from ' @/components/rmrk/Gallery/Search/exist'
101
103
import { SearchQuery } from ' ./Search/types'
102
104
import ChainMixin from ' @/utils/mixins/chainMixin'
103
105
@@ -112,6 +114,7 @@ const components = {
112
114
DonationButton : () => import (' @/components/transfer/DonationButton.vue' ),
113
115
Layout : () => import (' @/components/rmrk/Gallery/Layout.vue' ),
114
116
CollectionPriceChart : () => import (' @/components/rmrk/Gallery/CollectionPriceChart.vue' ),
117
+ BasicImage : () => import (' @/components/shared/view/BasicImage.vue' ),
115
118
CollapseWrapper : () => import (' @/components/shared/collapse/CollapseWrapper.vue' ),
116
119
}
117
120
@Component <CollectionItem >({
@@ -139,27 +142,30 @@ export default class CollectionItem extends mixins(
139
142
) {
140
143
private id = ' ' ;
141
144
private collection: CollectionWithMeta = emptyObject <CollectionWithMeta >();
142
- private isLoading = false ;
143
145
public meta: CollectionMetadata = emptyObject <CollectionMetadata >();
144
146
private searchQuery: SearchQuery = {
145
147
search: ' ' ,
146
148
type: ' ' ,
147
149
sortBy: ' BLOCK_NUMBER_DESC' ,
148
150
listed: false ,
149
151
};
150
- private activeTab = 0 ;
152
+ public activeTab = ' collection ' ;
151
153
private currentValue = 1 ;
152
154
private first = 15 ;
153
- private total = 0 ;
155
+ protected total = 0 ;
154
156
protected stats: NFT [] = [];
155
157
protected priceData: any = [];
156
158
159
+ get isLoading(): boolean {
160
+ return this .$apollo .queries .collection .loading
161
+ }
162
+
157
163
get offset(): number {
158
164
return this .currentValue * this .first - this .first
159
165
}
160
166
161
- get image(): string {
162
- return this .meta .image || ' '
167
+ get image(): string | undefined {
168
+ return this .meta .image
163
169
}
164
170
165
171
get description(): string {
@@ -178,10 +184,6 @@ export default class CollectionItem extends mixins(
178
184
return this .collection .issuer || ' '
179
185
}
180
186
181
- get owner(): string {
182
- return this .collection .issuer === (this .collection as any ).currentOwner ? ' ' : (this .collection as any ).currentOwner
183
- }
184
-
185
187
get sharingVisible(): boolean {
186
188
return ! isShareMode
187
189
}
@@ -205,10 +207,12 @@ export default class CollectionItem extends mixins(
205
207
}
206
208
207
209
public created(): void {
208
- this .isLoading = true
209
210
this .checkId ()
211
+ this .checkActiveTab ()
212
+ this .loadStats ()
210
213
this .$apollo .addSmartQuery (' collection' , {
211
214
query: collectionById ,
215
+ loadingKey: ' isLoading' ,
212
216
variables : () => {
213
217
return {
214
218
id: this .id ,
@@ -225,11 +229,9 @@ export default class CollectionItem extends mixins(
225
229
result: this .handleResult ,
226
230
})
227
231
228
- this .loadStats ()
229
- this .isLoading = false
230
232
}
231
233
232
- public async loadStats(): Promise < void > {
234
+ public loadStats(): void {
233
235
const nftStatsP = this .$apollo .query ({
234
236
query: nftListByCollection ,
235
237
variables: {
@@ -244,29 +246,27 @@ export default class CollectionItem extends mixins(
244
246
}
245
247
246
248
public loadPriceData(): void {
247
-
248
249
this .priceData = []
249
250
250
- const events : Interaction [][] = this .stats ?.map (onlyEvents ) || []
251
- const priceEvents : Interaction [][] = events .map (this .priceEvents ) || []
251
+ const events: Interaction [][] = this .stats ?.map (onlyEvents ) || []
252
+ const priceEvents: Interaction [][] = events .map (this .priceEvents ) || []
252
253
253
- const overTime : string [] = priceEvents .flat ().sort (sortByTimeStamp ).map (eventTimestamp )
254
+ const overTime: string [] = priceEvents .flat ().sort (sortByTimeStamp ).map (eventTimestamp )
254
255
255
- const floorPriceData : PriceDataType [] = overTime .map (collectionFloorPriceList (priceEvents , this .decimals ))
256
+ const floorPriceData: PriceDataType [] = overTime .map (collectionFloorPriceList (priceEvents , this .decimals ))
256
257
257
258
const buyEvents = events .map (onlyBuyEvents )?.flat ().sort (sortByTimeStamp )
258
- const soldPriceData : PriceDataType [] = buyEvents ?.map (soldNFTPrice (this .decimals ))
259
+ const soldPriceData: PriceDataType [] = buyEvents ?.map (soldNFTPrice (this .decimals ))
259
260
260
261
this .priceData = [floorPriceData , soldPriceData ]
261
262
}
262
263
263
264
public async handleResult({data }: any ): Promise <void > {
264
265
this .total = data .collectionEntity .nfts .totalCount
265
- this .fetchMetadata ()
266
+ await this .fetchMetadata ()
266
267
}
267
268
268
269
public async fetchMetadata(): Promise <void > {
269
- console .log (this .collection [' metadata' ], ! this .meta [' image' ])
270
270
if (this .collection [' metadata' ] && ! this .meta [' image' ]) {
271
271
const meta = await fetchCollectionMetadata (this .collection )
272
272
this .meta = {
@@ -282,12 +282,34 @@ export default class CollectionItem extends mixins(
282
282
}
283
283
}
284
284
285
+ public checkActiveTab(): void {
286
+ exist (this .$route .query .tab , (val ) => {
287
+ this .activeTab = val
288
+ })
289
+ }
290
+
291
+ @Watch (' activeTab' )
292
+ protected onTabChange(val : string , oldVal : string ): void {
293
+ if (shouldUpdate (val , oldVal )) {
294
+ this .$router .replace ({
295
+ name: String (this .$route .name ),
296
+ query: { tab: val },
297
+ })
298
+ }
299
+ }
300
+
285
301
get iframeSettings(): Record <string , unknown > {
286
302
return { width: ' 100%' , height: ' 100vh' }
287
303
}
288
304
289
- protected priceEvents(nftEvents : Interaction []) : Interaction [] {
305
+ protected priceEvents(nftEvents : Interaction []): Interaction [] {
290
306
return nftEvents .filter (onlyPriceEvents )
291
307
}
292
308
}
293
309
</script >
310
+
311
+ <style >
312
+ .collection__image img {
313
+ color : transparent ;
314
+ }
315
+ </style >
0 commit comments