diff --git a/components/rmrk/Gallery/CollectionItem.vue b/components/rmrk/Gallery/CollectionItem.vue
index 87d83d72f7..dc3ed5e002 100644
--- a/components/rmrk/Gallery/CollectionItem.vue
+++ b/components/rmrk/Gallery/CollectionItem.vue
@@ -106,6 +106,7 @@
:events="eventsOfNftCollection"
:openOnDefault="isHistoryOpen"
hideCollapse
+ displayItem
@setPriceChartData="setPriceChartData" />
diff --git a/components/rmrk/Gallery/Gallery.vue b/components/rmrk/Gallery/Gallery.vue
index 2c96d024c4..697b7d847e 100644
--- a/components/rmrk/Gallery/Gallery.vue
+++ b/components/rmrk/Gallery/Gallery.vue
@@ -262,7 +262,6 @@ export default class Gallery extends mixins(
offset: (page - 1) * this.first,
},
})
- console.log(result.data)
await this.handleResult(result, loadDirection)
this.isFetchingData = false
return true
diff --git a/components/rmrk/Gallery/GalleryItem.vue b/components/rmrk/Gallery/GalleryItem.vue
index c48e396e80..e6603220a7 100644
--- a/components/rmrk/Gallery/GalleryItem.vue
+++ b/components/rmrk/Gallery/GalleryItem.vue
@@ -144,12 +144,15 @@ import { sanitizeIpfsUrl, getSanitizer } from '../utils'
import { processMedia } from '@/utils/gallery/media'
import { emptyObject } from '@/utils/empty'
import { notificationTypes, showNotification } from '@/utils/notification'
+import { generateNftImage } from '@/utils/seoImageGenerator'
+import { formatBalanceEmptyOnZero } from '@/utils/format/balance'
import isShareMode from '@/utils/isShareMode'
import nftById from '@/queries/nftById.graphql'
import nftByIdMini from '@/queries/nftByIdMinimal.graphql'
import nftListIdsByCollection from '@/queries/nftIdListByCollection.graphql'
import nftByIdMinimal from '@/queries/rmrk/subsquid/nftByIdMinimal.graphql'
+
import { fetchNFTMetadata } from '../utils'
import { get, set } from 'idb-keyval'
import { exist } from './Search/exist'
@@ -159,6 +162,21 @@ import { Debounce } from 'vue-debounce-decorator'
import AvailableActions from './AvailableActions.vue'
@Component({
+ name: 'GalleryItem',
+ head() {
+ const metaData = {
+ mime: this.mimeType,
+ title: this.pageTitle,
+ description: this.meta.description,
+ url: this.$route.path,
+ image: this.image,
+ video: this.meta.animation_url,
+ }
+ return {
+ title: this.pageTitle,
+ meta: [...this.$seoMeta(metaData)],
+ }
+ },
components: {
Auth: () => import('@/components/shared/Auth.vue'),
AvailableActions,
@@ -201,6 +219,19 @@ export default class GalleryItem extends mixins(PrefixMixin) {
return `${this.$route.params.id}${this.$route.hash || ''}`
}
+ get pageTitle(): string {
+ return `${this.nft.name || ''}`
+ }
+
+ get image(): string {
+ return generateNftImage(
+ this.nft.name,
+ formatBalanceEmptyOnZero(this.nft.price as string),
+ this.meta.image as string,
+ this.mimeType
+ )
+ }
+
async fetch() {
try {
const {
diff --git a/components/rmrk/Gallery/History.vue b/components/rmrk/Gallery/History.vue
index d9c2e9db34..a570b6ea3c 100644
--- a/components/rmrk/Gallery/History.vue
+++ b/components/rmrk/Gallery/History.vue
@@ -47,7 +47,7 @@
{{ getEventDisplayName(props.row.Type) }}
- {{ props.row.Item.name }}
+ {{ props.row.Item.name || props.row.Item.id }}
({
name: 'GalleryItemPage',
- components: {
- GalleryItem,
- },
- head() {
- const title = this.currentlyViewedItem.title
- const metaData = {
- title,
- type: 'profile',
- description: this.currentlyViewedItem.description,
- url: this.$route.path,
- image: this.image,
- }
- return {
- title,
- meta: [
- ...this.$seoMeta(metaData),
- {
- hid: 'og:author',
- property: 'og:author',
- content: this.currentlyViewedItem.author,
- },
- ],
- }
- },
+ components,
})
-export default class GalleryItemPage extends Vue {
- get currentlyViewedItem() {
- return this.$store.getters['history/getCurrentlyViewedItem']
- }
-
- get image(): string {
- return generateNftImage(
- this.currentlyViewedItem.name,
- formatBalanceEmptyOnZero(this.currentlyViewedItem.price),
- this.currentlyViewedItem.image,
- this.currentlyViewedItem.mimeType
- )
- }
-}
+export default class GalleryItemPage extends Vue {}
diff --git a/plugins/seoMetaGenerator.ts b/plugins/seoMetaGenerator.ts
index bdbb3de01d..55f895c7dd 100644
--- a/plugins/seoMetaGenerator.ts
+++ b/plugins/seoMetaGenerator.ts
@@ -1,4 +1,5 @@
-import type { MetaInfo } from 'vue-meta'
+import { MediaType } from '~/components/rmrk/types'
+import { resolveMedia } from '~/utils/gallery/media'
declare module 'vue/types/vue' {
// this.$seoMeta inside Vue components
@@ -7,21 +8,52 @@ declare module 'vue/types/vue' {
}
}
-type MetaProperties = {
+interface MetaProperties {
type?: string
url?: string
title?: string
description?: string
image?: string
+ author?: string
+ video?: string
+ mime?: string
+}
+
+interface MetaTag {
+ hid?: string
+ name?: string
+ property?: string
+ content?: string
}
export default function ({ app }, inject): void {
- const seoMeta = (meta: MetaProperties): MetaInfo['meta'] => {
+ const getMetaType = (mediaType: MediaType | string | undefined): string => {
+ switch (mediaType) {
+ case MediaType.VIDEO:
+ return 'video:other'
+ case MediaType.AUDIO:
+ return 'music:song'
+ case MediaType.IMAGE:
+ case MediaType.JSON:
+ case MediaType.OBJECT:
+ default:
+ return 'website'
+ }
+ }
+
+ const seoMeta = (meta: MetaProperties): MetaTag[] => {
const baseUrl: string = app.$config.baseUrl
const title = 'KodaDot - Kusama NFT Market Explorer'
const description = 'Creating Carbonless NFTs on Kusama'
const image = `${baseUrl}/kodadot_card_root.png`
- return [
+ const type = resolveMedia(meta?.mime)
+
+ const seoTags: MetaTag[] = [
+ {
+ hid: 'title',
+ name: 'title',
+ content: meta?.title ? `${meta.title} | ${title}` : title,
+ },
{
hid: 'description',
name: 'description',
@@ -30,7 +62,7 @@ export default function ({ app }, inject): void {
{
hid: 'og:type',
property: 'og:type',
- content: meta?.type || 'website',
+ content: getMetaType(type),
},
{
hid: 'og:url',
@@ -40,7 +72,7 @@ export default function ({ app }, inject): void {
{
hid: 'og:title',
property: 'og:title',
- content: meta?.title || title,
+ content: meta?.title ? `${meta.title} | ${title}` : title,
},
{
hid: 'og:description',
@@ -73,6 +105,66 @@ export default function ({ app }, inject): void {
content: meta?.image || image,
},
]
+
+ if (type === MediaType.IMAGE) {
+ const imageMetaTags: MetaTag[] = [
+ {
+ hid: 'og:image:type',
+ property: 'og:image:type',
+ content: meta?.mime,
+ },
+ ]
+ seoTags.push(...imageMetaTags)
+ }
+
+ if (type === MediaType.VIDEO) {
+ const videoMetaTags: MetaTag[] = [
+ {
+ hid: 'og:video',
+ property: 'og:video',
+ content: meta?.video,
+ },
+ {
+ hid: 'og:video:width',
+ property: 'og:video:width',
+ content: '1280',
+ },
+ {
+ hid: 'og:video:height',
+ property: 'og:video:height',
+ content: '720',
+ },
+ {
+ hid: 'og:video:type',
+ property: 'og:video:type',
+ content: meta?.mime,
+ },
+ {
+ hid: 'twitter:player:width',
+ property: 'twitter:player:width',
+ content: '1280',
+ },
+ {
+ hid: 'twitter:player:height',
+ property: 'twitter:player:height',
+ content: '720',
+ },
+ {
+ hid: 'twitter:card',
+ property: 'twitter:card',
+ content: 'player',
+ },
+ {
+ hid: 'twitter:player',
+ name: 'twitter:player',
+ content: meta?.video,
+ },
+ ]
+ seoTags.push(...videoMetaTags)
+ }
+
+ // only return non null, not undefined, not empty string
+ return seoTags.filter((tag: MetaTag) => tag && tag.content !== '')
}
inject('seoMeta', seoMeta)
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cabb3fb331..0fbd3539d1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: 5.4
+lockfileVersion: 5.3
specifiers:
'@babel/core': ^7.18.2
@@ -391,7 +391,7 @@ packages:
resolution: {integrity: sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/types': 7.17.10
+ '@babel/types': 7.18.4
'@jridgewell/gen-mapping': 0.1.1
jsesc: 2.5.2
dev: false
@@ -1547,8 +1547,8 @@ packages:
'@babel/generator': 7.18.2
'@babel/helper-function-name': 7.17.9
'@babel/helper-split-export-declaration': 7.16.7
- '@babel/parser': 7.12.16
- '@babel/types': 7.12.13
+ '@babel/parser': 7.18.4
+ '@babel/types': 7.18.4
debug: 4.3.4
globals: 11.12.0
lodash: 4.17.21
@@ -2725,7 +2725,7 @@ packages:
'@netlify/functions': 1.0.0
'@nuxt/devalue': 2.0.0
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-27470397.9ebea90_g5rf3icusfse4b63pimitbrmgu
- '@nuxt/ui-templates': /@nuxt/ui-templates-edge/0.1.1-27576930.52eaf32
+ '@nuxt/ui-templates': /@nuxt/ui-templates-edge/0.1.1-27597075.ecafcef
'@rollup/plugin-alias': 3.1.9_rollup@2.75.6
'@rollup/plugin-commonjs': 21.1.0_rollup@2.75.6
'@rollup/plugin-inject': 4.0.4_rollup@2.75.6
@@ -2948,8 +2948,8 @@ packages:
- webpack
dev: true
- /@nuxt/ui-templates-edge/0.1.1-27576930.52eaf32:
- resolution: {integrity: sha512-eB+HyQUdSGbHdZ+f/pqvvyjvRtFzI4qxU8WGmnRz8nJ9tSIL+ox/RzTDXUiakjfNay7smtMx6txDAKPyq+FC0Q==}
+ /@nuxt/ui-templates-edge/0.1.1-27597075.ecafcef:
+ resolution: {integrity: sha512-3+Bu2PT+L7+ZZ6IPl+ib8G0S3UB32PzMs5+zjuqjAjqO3Zsq0Lnw0CfY7TlQVyWA6BQqd8Eq9AORMAEe94PGGA==}
dev: true
/@nuxt/utils-edge/2.16.0-27358576.777a4b7f:
@@ -17312,7 +17312,7 @@ packages:
dev: false
/yallist/2.1.2:
- resolution: {integrity: sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=}
+ resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==}
/yallist/3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
diff --git a/queries/subsquid/general/userStatsByAccount.graphql b/queries/subsquid/general/userStatsByAccount.graphql
index 9f4b289eb6..f7a021717b 100644
--- a/queries/subsquid/general/userStatsByAccount.graphql
+++ b/queries/subsquid/general/userStatsByAccount.graphql
@@ -9,13 +9,17 @@ query userStatsByAccount($account: String!) {
}
created: nftEntitiesConnection(
orderBy: blockNumber_DESC
- where: { issuer_eq: $account }
+ where: { issuer_eq: $account, burned_eq: false }
) {
totalCount
}
collected: nftEntitiesConnection(
orderBy: blockNumber_DESC
- where: { issuer_not_eq: $account, currentOwner_eq: $account }
+ where: {
+ issuer_not_eq: $account
+ currentOwner_eq: $account
+ burned_eq: false
+ }
) {
totalCount
edges {
@@ -37,7 +41,11 @@ query userStatsByAccount($account: String!) {
sold: nftEntitiesConnection(
orderBy: blockNumber_DESC
- where: { issuer_eq: $account, currentOwner_not_eq: $account }
+ where: {
+ issuer_eq: $account
+ currentOwner_not_eq: $account
+ burned_eq: false
+ }
) {
totalCount
}
diff --git a/queries/userStatsByAccount.graphql b/queries/userStatsByAccount.graphql
index d9065d7c5c..ae622bf40c 100644
--- a/queries/userStatsByAccount.graphql
+++ b/queries/userStatsByAccount.graphql
@@ -10,7 +10,9 @@ query userStatsByAccount($account: String!) {
}
}
- created: nFTEntities(filter: { issuer: { equalTo: $account } }) {
+ created: nFTEntities(
+ filter: { issuer: { equalTo: $account }, burned: { distinctFrom: true } }
+ ) {
totalCount
}
@@ -18,6 +20,7 @@ query userStatsByAccount($account: String!) {
filter: {
issuer: { notEqualTo: $account }
currentOwner: { equalTo: $account }
+ burned: { distinctFrom: true }
}
orderBy: BLOCK_NUMBER_DESC
first: 1
@@ -34,6 +37,7 @@ query userStatsByAccount($account: String!) {
filter: {
issuer: { equalTo: $account }
currentOwner: { notEqualTo: $account }
+ burned: { distinctFrom: true }
}
) {
totalCount
diff --git a/store/index.ts b/store/index.ts
index 2c0e35a7fd..9d6784d5ca 100644
--- a/store/index.ts
+++ b/store/index.ts
@@ -3,6 +3,11 @@ import Connector from '@kodadot1/sub-api'
import correctFormat from '@/utils/ss58Format'
import { GetterTree, MutationTree, Store } from 'vuex'
+type VuexAction = {
+ type: string
+ payload: string
+}
+
const apiPlugin = (store: Store): void => {
const { getInstance: Api } = Connector
@@ -44,7 +49,16 @@ const apiPlugin = (store: Store): void => {
console.log('[API] disconnected')
})
}
+const myPlugin = (store: Store): void => {
+ const { getInstance: Api } = Connector
+ store.subscribeAction(({ type, payload }: VuexAction) => {
+ if (type === 'setApiUrl' && payload) {
+ store.commit('setLoading', true)
+ Api().connect(payload)
+ }
+ })
+}
export const state = () => ({
loading: false,
keyringLoaded: false,
@@ -84,4 +98,4 @@ export const getters: GetterTree = {
},
}
-export const plugins = [apiPlugin]
+export const plugins = [apiPlugin, myPlugin]