From ebbf6c522d592afe1483d684d3a67170b5e81ca5 Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Mon, 28 Oct 2024 17:09:38 +0500
Subject: [PATCH 01/45] add(collectinos): init new edit collection modal
---
components/collection/CustomizeModal.vue | 93 ---------
components/collection/EditModal.vue | 197 ++++++++++++++++++
.../HeroButtonCustomizeCollection.vue | 37 ----
.../collection/HeroButtonEditCollection.vue | 31 +++
components/collection/HeroButtons.vue | 7 +-
components/collection/edit/OverrideFile.vue | 36 ++++
components/collection/edit/Section.vue | 15 ++
locales/en.json | 19 +-
8 files changed, 299 insertions(+), 136 deletions(-)
delete mode 100644 components/collection/CustomizeModal.vue
create mode 100644 components/collection/EditModal.vue
delete mode 100644 components/collection/HeroButtonCustomizeCollection.vue
create mode 100644 components/collection/HeroButtonEditCollection.vue
create mode 100644 components/collection/edit/OverrideFile.vue
create mode 100644 components/collection/edit/Section.vue
diff --git a/components/collection/CustomizeModal.vue b/components/collection/CustomizeModal.vue
deleted file mode 100644
index 1c548b10b0..0000000000
--- a/components/collection/CustomizeModal.vue
+++ /dev/null
@@ -1,93 +0,0 @@
-
-
-
-
- {{ 'Customize Collection' }}
-
-
- This will update the Maximum items in your collection
-
-
-
-
-
-
-
-
-
-
- {{ $t('Update') }}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/components/collection/EditModal.vue b/components/collection/EditModal.vue
new file mode 100644
index 0000000000..6a1124d5f4
--- /dev/null
+++ b/components/collection/EditModal.vue
@@ -0,0 +1,197 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/collection/HeroButtonCustomizeCollection.vue b/components/collection/HeroButtonCustomizeCollection.vue
deleted file mode 100644
index c26659cda3..0000000000
--- a/components/collection/HeroButtonCustomizeCollection.vue
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
- {{ $i18n.t('moreActions.customize') }}
-
-
-
-
-
-
diff --git a/components/collection/HeroButtonEditCollection.vue b/components/collection/HeroButtonEditCollection.vue
new file mode 100644
index 0000000000..f12ca4b596
--- /dev/null
+++ b/components/collection/HeroButtonEditCollection.vue
@@ -0,0 +1,31 @@
+
+
+ {{ $t('moreActions.editCollection') }}
+
+
+
+
+
+
diff --git a/components/collection/HeroButtons.vue b/components/collection/HeroButtons.vue
index f18837957d..551a905bd4 100644
--- a/components/collection/HeroButtons.vue
+++ b/components/collection/HeroButtons.vue
@@ -97,9 +97,8 @@
-
@@ -172,8 +171,6 @@ const { collection } = useCollectionMinimal({
collectionId,
})
const collectionIssuer = computed(() => collection.value?.displayCreator)
-const collectionNftCount = computed(() => collection.value?.nftCount)
-const collectionMaxCount = computed(() => collection.value?.max)
const { twitter } = useIdentity({
address: collectionIssuer,
diff --git a/components/collection/edit/OverrideFile.vue b/components/collection/edit/OverrideFile.vue
new file mode 100644
index 0000000000..b81f54821b
--- /dev/null
+++ b/components/collection/edit/OverrideFile.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/collection/edit/Section.vue b/components/collection/edit/Section.vue
new file mode 100644
index 0000000000..c15973d30a
--- /dev/null
+++ b/components/collection/edit/Section.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/locales/en.json b/locales/en.json
index 61277caac1..ab47bf492f 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -377,6 +377,23 @@
"youSuccessfullyClaimedNft": "You successfully minted {0} NFT",
"yourWalletNeeds": "Your wallet needs a minimum of {0} to claim this drop."
},
+ "edit": {
+ "collection": {
+ "banner": {
+ "hint": "1440 x 560 size recommended",
+ "message": "Represents your collection on its page and on collection card",
+ "title": "Banner"
+ },
+ "drop": "Don't click, just drop!",
+ "image": {
+ "hint": "300 x 300 size recommended",
+ "message": "Visible on collection card and view",
+ "title": "Logo"
+ },
+ "saveChanges": "Save Changes",
+ "title": "Edit Collection"
+ }
+ },
"email": "Email",
"error": "Error",
"errors": {
@@ -1421,11 +1438,11 @@
"mintingSettings": "Minting Settings",
"moreActions": {
"addNfts": "Add NFTs",
- "customize": "Customize",
"deleteCollection": "Delete Collection",
"deleteNfts": "Delete NFTs",
"deletingNfts": "Deleting NFTs",
"download": "Download",
+ "editCollection": "Edit Collection",
"reportCollection": "Report Collection"
},
"multipleNFTS": "Multiple NFT's",
From b90b894b343ef9f7f20bf83fe36d5ec07b580892 Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Tue, 29 Oct 2024 16:22:56 +0500
Subject: [PATCH 02/45] add(collection): edit collection transaction
---
components/collection/EditModal.vue | 77 +++++++++----
.../collection/HeroButtonEditCollection.vue | 4 +-
.../mintCollection/constructMeta.ts | 2 +-
.../mintToken/constructDirectoryMeta.ts | 2 +-
.../transaction/mintToken/constructMeta.ts | 2 +-
.../transactionSetCollectionMaxSupply.ts | 108 ++++++++++++++----
composables/transaction/types.ts | 21 +++-
composables/transaction/utils.ts | 4 +-
composables/useTransaction.ts | 14 ++-
locales/en.json | 9 +-
services/nftStorage.ts | 2 +-
11 files changed, 178 insertions(+), 67 deletions(-)
diff --git a/components/collection/EditModal.vue b/components/collection/EditModal.vue
index 6a1124d5f4..ac616d5099 100644
--- a/components/collection/EditModal.vue
+++ b/components/collection/EditModal.vue
@@ -1,4 +1,11 @@
+
+
-
+
imageUrl = undefined"
+ @clear="() => {
+ image = undefined
+ imageUrl = undefined
+ }"
@select="value => image = value"
/>
@@ -52,7 +62,7 @@
/>
-
+
{{ $t('edit.collection.banner.message') }}
@@ -71,7 +81,10 @@
bannerUrl = undefined"
+ @clear="() => {
+ banner = undefined
+ bannerUrl = undefined
+ }"
@select="value => banner = value"
/>
@@ -100,9 +113,19 @@
required
>
+
+
{{ $t('mint.unlimited') }}
+
+
@@ -129,17 +152,19 @@
diff --git a/components/collection/HeroButtonEditCollection.vue b/components/collection/HeroButtonEditCollection.vue
index f12ca4b596..1d10bc2f0c 100644
--- a/components/collection/HeroButtonEditCollection.vue
+++ b/components/collection/HeroButtonEditCollection.vue
@@ -9,7 +9,6 @@
v-model="isModalActive"
:collection="collectinoMetadata"
:min="collection.nftCount"
- @submit="isModalActive = false"
/>
@@ -24,7 +23,10 @@ const props = defineProps<{
const isModalActive = ref(false)
const collectinoMetadata = computed
(() => ({
+ name: props.collection.meta.name,
+ description: props.collection.meta.description,
image: props.collection.meta.image,
+ imageType: props.collection.meta.type,
banner: props.collection.meta.banner,
max: props.collection.max,
}))
diff --git a/composables/transaction/mintCollection/constructMeta.ts b/composables/transaction/mintCollection/constructMeta.ts
index 4ee348d965..5cc97610a7 100644
--- a/composables/transaction/mintCollection/constructMeta.ts
+++ b/composables/transaction/mintCollection/constructMeta.ts
@@ -21,7 +21,7 @@ export async function constructMeta(item: ActionMintCollection) {
undefined,
type,
)
- const metaHash = await pinJson(meta, imageHash)
+ const metaHash = await pinJson(meta)
if (file) {
$consola.log('[UPLOADING FILE]')
diff --git a/composables/transaction/mintToken/constructDirectoryMeta.ts b/composables/transaction/mintToken/constructDirectoryMeta.ts
index 6d69222334..14294045a8 100644
--- a/composables/transaction/mintToken/constructDirectoryMeta.ts
+++ b/composables/transaction/mintToken/constructDirectoryMeta.ts
@@ -80,7 +80,7 @@ const batchFiles = (files: File[], maxBatchSize: number): File[][] => {
return batches
}
-const uploadMediaFiles = async (files: File[]): Promise => {
+export const uploadMediaFiles = async (files: File[]): Promise => {
const MAX_BATCH_SIZE = 100 * 1024 * 1024 // 100 MB in bytes
const serialFiles = mapToSerial(files)
const fileBatches = batchFiles(serialFiles, MAX_BATCH_SIZE)
diff --git a/composables/transaction/mintToken/constructMeta.ts b/composables/transaction/mintToken/constructMeta.ts
index 01c047e8f7..d3684630fe 100644
--- a/composables/transaction/mintToken/constructMeta.ts
+++ b/composables/transaction/mintToken/constructMeta.ts
@@ -57,7 +57,7 @@ export async function constructMeta(
file.type,
)
- const metaHash = await pinJson(meta, imageHash)
+ const metaHash = await pinJson(meta)
preheatFileFromIPFS(fileHash)
uploadDirectWhenMultiple(
[file, secondFile],
diff --git a/composables/transaction/transactionSetCollectionMaxSupply.ts b/composables/transaction/transactionSetCollectionMaxSupply.ts
index 983b959d40..5966ec4e9b 100644
--- a/composables/transaction/transactionSetCollectionMaxSupply.ts
+++ b/composables/transaction/transactionSetCollectionMaxSupply.ts
@@ -1,28 +1,86 @@
-import type { ActionSetCollectionMaxSupply, ExecuteTransactionParams } from './types'
-
-export function execSetCollectionMaxSupply(
- params: ActionSetCollectionMaxSupply,
- api,
- executeTransaction: ({
- cb,
- arg,
- successMessage,
- errorMessage,
- }: ExecuteTransactionParams) => void,
-) {
- const collectionId = params.collectionId.toString()
- const maxSupply = params.max.toString()
-
- try {
- // item.urlPrefix === 'ahr'
- if (params.urlPrefix === 'ahk' || params.urlPrefix === 'ahp') {
- executeTransaction({
- cb: api.tx.nfts.setCollectionMaxSupply,
- arg: [collectionId, maxSupply],
- })
- }
+import { createMetadata, unSanitizeIpfsUrl } from '@kodadot1/minimark/utils'
+import { uploadMediaFiles } from './mintToken/constructDirectoryMeta'
+import type { ActionUpdateCollection, UpdateCollectionParams } from './types'
+import { pinFileToIPFS, pinJson } from '@/services/nftStorage'
+
+const constructMeta = async (item: ActionUpdateCollection) => {
+ const { name, description, image, banner, imageType } = item.collection
+
+ const mediaFiles = [] as File[]
+ const isImageFile = image instanceof File
+ const isBannerFile = banner instanceof File
+
+ let type = imageType
+
+ if (isImageFile) {
+ mediaFiles.push(image)
+ type = getImageTypeSafe(image)
+ }
+
+ if (isBannerFile) {
+ mediaFiles.push(banner)
+ }
+
+ const ipfs = { image: '', banner: '' }
+
+ if (isImageFile && isBannerFile) {
+ const [image, banner] = await uploadMediaFiles(mediaFiles)
+ ipfs.image = image
+ ipfs.banner = banner
+ }
+ else if (isImageFile) {
+ ipfs.image = await pinFileToIPFS(image)
+ ipfs.banner = banner as string
+ }
+ else if (isBannerFile) {
+ ipfs.image = image as string
+ ipfs.banner = await pinFileToIPFS(banner)
+ }
+ else {
+ ipfs.image = image as string
+ ipfs.banner = banner as string
}
- catch (error) {
- warningMessage(error)
+
+ const attributes = []
+
+ const meta = createMetadata(
+ name,
+ description,
+ ipfs.image,
+ undefined,
+ attributes,
+ undefined,
+ type,
+ )
+
+ const metaHash = await pinJson(meta)
+
+ return unSanitizeIpfsUrl(metaHash)
+}
+
+async function execUpdateCollectionStatmine({ item, api, executeTransaction, isLoading, status }: UpdateCollectionParams) {
+ isLoading.value = true
+ status.value = 'loader.ipfs'
+
+ const metadata = await constructMeta(item)
+
+ const collectionId = item.collectionId.toString()
+
+ const args = [
+ api.tx.nfts.setCollectionMetadata(collectionId, metadata),
+ api.tx.nfts.setCollectionMaxSupply(collectionId, item.collection.max),
+ ]
+
+ executeTransaction({
+ cb: api.tx.utility.batchAll,
+ arg: [args],
+ successMessage: item.successMessage,
+ errorMessage: item.errorMessage,
+ })
+}
+
+export async function execUpdateCollection({ item, ...params }: UpdateCollectionParams) {
+ if (item.urlPrefix === 'ahk' || item.urlPrefix === 'ahp') {
+ return execUpdateCollectionStatmine({ item, ...params })
}
}
diff --git a/composables/transaction/types.ts b/composables/transaction/types.ts
index a5ce780e3f..5a9ec51854 100644
--- a/composables/transaction/types.ts
+++ b/composables/transaction/types.ts
@@ -241,7 +241,7 @@ export interface ActionMintCollection {
export enum Collections {
DELETE = 'delete',
- SET_MAX_SUPPLY = 'setCollectionMaxSupply',
+ UPDATE_COLLECTION = 'updateCollection',
}
export type ActionsInteractions = Interaction | ShoppingActions | Collections
@@ -267,11 +267,22 @@ export interface ActionBurnMultipleNFTs {
errorMessage?: string
}
-export interface ActionSetCollectionMaxSupply {
- interaction: Collections.SET_MAX_SUPPLY
+type UpdateCollectionStatemine = {
+ name: string
+ description: string
+ image: File | string
+ imageType?: string
+ banner?: File | string | null
+ max?: number
+}
+
+export type UpdateCollectionParams = BaseUnionMintParams & { api: ApiPromise }
+
+export interface ActionUpdateCollection {
+ interaction: Collections.UPDATE_COLLECTION
collectionId: string
+ collection: UpdateCollectionStatemine
urlPrefix: string
- max: number
successMessage?: string | ((blockNumber: string) => string)
errorMessage?: string
}
@@ -288,5 +299,5 @@ export type Actions =
| ActionMintCollection
| ActionDeleteCollection
| ActionBurnMultipleNFTs
- | ActionSetCollectionMaxSupply
+ | ActionUpdateCollection
| ActionMintDrop
diff --git a/composables/transaction/utils.ts b/composables/transaction/utils.ts
index c645cd1040..ed78d9fe55 100644
--- a/composables/transaction/utils.ts
+++ b/composables/transaction/utils.ts
@@ -17,7 +17,7 @@ import type {
ActionMintToken,
ActionOffer,
ActionSend,
- ActionSetCollectionMaxSupply,
+ ActionUpdateCollection,
ActionWithdrawOffer,
Actions } from '../transaction/types'
import { getPercentSupportFee } from '@/utils/support'
@@ -57,7 +57,7 @@ export function isActionValid(action: Actions): boolean {
Boolean(action.collection),
[Collections.DELETE]: (action: ActionDeleteCollection) =>
Boolean(action.collectionId),
- [Collections.SET_MAX_SUPPLY]: (action: ActionSetCollectionMaxSupply) =>
+ [Collections.UPDATE_COLLECTION]: (action: ActionUpdateCollection) =>
Boolean(action.collectionId),
[NFTs.BURN_MULTIPLE]: (action: ActionBurnMultipleNFTs) =>
hasContent(action.nftIds),
diff --git a/composables/useTransaction.ts b/composables/useTransaction.ts
index fc4240c76d..a6e656c66d 100644
--- a/composables/useTransaction.ts
+++ b/composables/useTransaction.ts
@@ -15,7 +15,7 @@ import { execAcceptOfferTx } from './transaction/transactionOfferAccept'
import { execMakingOfferTx } from './transaction/transactionOffer'
import { execMintToken } from './transaction/transactionMintToken'
import { execMintCollection } from './transaction/transactionMintCollection'
-import { execSetCollectionMaxSupply } from './transaction/transactionSetCollectionMaxSupply'
+import { execUpdateCollection } from './transaction/transactionSetCollectionMaxSupply'
import type {
ActionAcceptOffer,
ActionBurnMultipleNFTs,
@@ -28,7 +28,7 @@ import type {
ActionMintDrop,
ActionMintToken,
ActionSend,
- ActionSetCollectionMaxSupply,
+ ActionUpdateCollection,
ActionWithdrawOffer,
Actions,
ExecuteEvmTransactionParams,
@@ -253,12 +253,14 @@ export const executeAction = ({
api as ApiPromise,
executeTransaction,
),
- [Collections.SET_MAX_SUPPLY]: () =>
- execSetCollectionMaxSupply(
- item as ActionSetCollectionMaxSupply,
+ [Collections.UPDATE_COLLECTION]: () =>
+ execUpdateCollection({
+ item: item as ActionUpdateCollection,
api,
executeTransaction,
- ),
+ isLoading,
+ status,
+ }),
[NFTs.BURN_MULTIPLE]: () =>
execBurnMultiple(
item as ActionBurnMultipleNFTs,
diff --git a/locales/en.json b/locales/en.json
index ab47bf492f..d128cdde35 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -381,15 +381,16 @@
"collection": {
"banner": {
"hint": "1440 x 560 size recommended",
- "message": "Represents your collection on its page and on collection card",
- "title": "Banner"
+ "label": "Banner",
+ "message": "Represents your collection on its page and on collection card"
},
"drop": "Don't click, just drop!",
"image": {
"hint": "300 x 300 size recommended",
- "message": "Visible on collection card and view",
- "title": "Logo"
+ "label": "Logo",
+ "message": "Visible on collection card and view"
},
+ "modal": "Editing Collection",
"saveChanges": "Save Changes",
"title": "Edit Collection"
}
diff --git a/services/nftStorage.ts b/services/nftStorage.ts
index 34786b016c..4ad7aac791 100644
--- a/services/nftStorage.ts
+++ b/services/nftStorage.ts
@@ -27,7 +27,7 @@ type StorageApiResponse = {
}
}
-export const pinJson = async (object: Metadata, _name: string) => {
+export const pinJson = async (object: Metadata) => {
const { value } = await nftStorageApi('/pinJson', {
method: 'POST',
body: object,
From c7d369c30c0377e0c8b3d2ec9b59f9462834ced1 Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Wed, 30 Oct 2024 08:53:16 +0500
Subject: [PATCH 03/45] add(transactionUpdateCollection.ts): collection banner
in metadata
---
components/collection/EditModal.vue | 6 ++-
...pply.ts => transactionUpdateCollection.ts} | 42 +++++++++----------
composables/useTransaction.ts | 2 +-
locales/en.json | 1 +
4 files changed, 27 insertions(+), 24 deletions(-)
rename composables/transaction/{transactionSetCollectionMaxSupply.ts => transactionUpdateCollection.ts} (73%)
diff --git a/components/collection/EditModal.vue b/components/collection/EditModal.vue
index ac616d5099..2ab8eb4800 100644
--- a/components/collection/EditModal.vue
+++ b/components/collection/EditModal.vue
@@ -179,6 +179,7 @@ const imageUrl = ref()
const bannerUrl = ref()
const unlimited = ref(true)
+const { $i18n } = useNuxtApp()
const { transaction, status, isLoading } = useTransaction()
const { urlPrefix } = usePrefix()
const route = useRoute()
@@ -186,7 +187,7 @@ const route = useRoute()
const min = computed(() => props.min || 1)
const max = ref(props.collection?.max)
-const disabled = computed(() => !image.value && !banner.value && props.collection?.max === max.value)
+const disabled = computed(() => !image.value && !banner.value && props.collection?.max === max.value && bannerUrl.value)
const editCollection = async () => {
if (!props.collection) {
@@ -203,10 +204,11 @@ const editCollection = async () => {
description: props.collection.description,
image: image.value || props.collection.image,
imageType: props.collection.imageType,
- banner: banner.value || props.collection.banner,
+ banner: bannerUrl.value ? banner.value || props.collection.banner : undefined,
max: max.value,
},
urlPrefix: urlPrefix.value,
+ successMessage: $i18n.t('edit.collection.success'),
})
}
diff --git a/composables/transaction/transactionSetCollectionMaxSupply.ts b/composables/transaction/transactionUpdateCollection.ts
similarity index 73%
rename from composables/transaction/transactionSetCollectionMaxSupply.ts
rename to composables/transaction/transactionUpdateCollection.ts
index 5966ec4e9b..24ab87a3c3 100644
--- a/composables/transaction/transactionSetCollectionMaxSupply.ts
+++ b/composables/transaction/transactionUpdateCollection.ts
@@ -3,34 +3,24 @@ import { uploadMediaFiles } from './mintToken/constructDirectoryMeta'
import type { ActionUpdateCollection, UpdateCollectionParams } from './types'
import { pinFileToIPFS, pinJson } from '@/services/nftStorage'
-const constructMeta = async (item: ActionUpdateCollection) => {
- const { name, description, image, banner, imageType } = item.collection
-
- const mediaFiles = [] as File[]
+const getIpfsMedia = async ({ collection: { image, banner, imageType } }: ActionUpdateCollection) => {
const isImageFile = image instanceof File
const isBannerFile = banner instanceof File
let type = imageType
- if (isImageFile) {
- mediaFiles.push(image)
- type = getImageTypeSafe(image)
- }
-
- if (isBannerFile) {
- mediaFiles.push(banner)
- }
-
- const ipfs = { image: '', banner: '' }
+ const ipfs: { image: string, banner?: string } = { image: '', banner: '' }
if (isImageFile && isBannerFile) {
- const [image, banner] = await uploadMediaFiles(mediaFiles)
- ipfs.image = image
- ipfs.banner = banner
+ const mediaFiles = await uploadMediaFiles([image, banner])
+ ipfs.image = mediaFiles[0]
+ ipfs.banner = mediaFiles[1]
+ type = getImageTypeSafe(image)
}
else if (isImageFile) {
ipfs.image = await pinFileToIPFS(image)
- ipfs.banner = banner as string
+ ipfs.banner = banner as string | undefined
+ type = getImageTypeSafe(image)
}
else if (isBannerFile) {
ipfs.image = image as string
@@ -38,22 +28,32 @@ const constructMeta = async (item: ActionUpdateCollection) => {
}
else {
ipfs.image = image as string
- ipfs.banner = banner as string
+ ipfs.banner = banner as string | undefined
+ }
+
+ return {
+ ...ipfs,
+ type,
}
+}
+
+const constructMeta = async (item: ActionUpdateCollection) => {
+ const { name, description } = item.collection
+ const { image, banner, type } = await getIpfsMedia(item)
const attributes = []
const meta = createMetadata(
name,
description,
- ipfs.image,
+ image,
undefined,
attributes,
undefined,
type,
)
- const metaHash = await pinJson(meta)
+ const metaHash = await pinJson({ ...meta, banner } as any)
return unSanitizeIpfsUrl(metaHash)
}
diff --git a/composables/useTransaction.ts b/composables/useTransaction.ts
index a6e656c66d..710daa5ca6 100644
--- a/composables/useTransaction.ts
+++ b/composables/useTransaction.ts
@@ -15,7 +15,7 @@ import { execAcceptOfferTx } from './transaction/transactionOfferAccept'
import { execMakingOfferTx } from './transaction/transactionOffer'
import { execMintToken } from './transaction/transactionMintToken'
import { execMintCollection } from './transaction/transactionMintCollection'
-import { execUpdateCollection } from './transaction/transactionSetCollectionMaxSupply'
+import { execUpdateCollection } from './transaction/transactionUpdateCollection'
import type {
ActionAcceptOffer,
ActionBurnMultipleNFTs,
diff --git a/locales/en.json b/locales/en.json
index d128cdde35..db3d987960 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -392,6 +392,7 @@
},
"modal": "Editing Collection",
"saveChanges": "Save Changes",
+ "success": "Successfully edited collection",
"title": "Edit Collection"
}
},
From 193601f79e2535a2c2f8d69c49ae3d0f4ef682c8 Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Wed, 30 Oct 2024 09:03:27 +0500
Subject: [PATCH 04/45] ref(transactionUpdateCollection.ts): one liner
---
composables/transaction/transactionUpdateCollection.ts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/composables/transaction/transactionUpdateCollection.ts b/composables/transaction/transactionUpdateCollection.ts
index 24ab87a3c3..7afebf5a01 100644
--- a/composables/transaction/transactionUpdateCollection.ts
+++ b/composables/transaction/transactionUpdateCollection.ts
@@ -12,9 +12,7 @@ const getIpfsMedia = async ({ collection: { image, banner, imageType } }: Action
const ipfs: { image: string, banner?: string } = { image: '', banner: '' }
if (isImageFile && isBannerFile) {
- const mediaFiles = await uploadMediaFiles([image, banner])
- ipfs.image = mediaFiles[0]
- ipfs.banner = mediaFiles[1]
+ [ipfs.image, ipfs.banner] = await uploadMediaFiles([image, banner])
type = getImageTypeSafe(image)
}
else if (isImageFile) {
From 3d9ec0c053f2e2fc712476f26e7bbc1abb76cc54 Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Wed, 30 Oct 2024 09:07:18 +0500
Subject: [PATCH 05/45] fix(useTransaction.ts): api param type
---
composables/useTransaction.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/composables/useTransaction.ts b/composables/useTransaction.ts
index 710daa5ca6..2397689a50 100644
--- a/composables/useTransaction.ts
+++ b/composables/useTransaction.ts
@@ -256,7 +256,7 @@ export const executeAction = ({
[Collections.UPDATE_COLLECTION]: () =>
execUpdateCollection({
item: item as ActionUpdateCollection,
- api,
+ api: api as ApiPromise,
executeTransaction,
isLoading,
status,
From 57c820acabb1b4c2f085b8573519ef29864ef5ef Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Wed, 30 Oct 2024 10:42:48 +0500
Subject: [PATCH 06/45] fix(EditModal.vue): disabled computed
---
components/collection/EditModal.vue | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/components/collection/EditModal.vue b/components/collection/EditModal.vue
index 2ab8eb4800..2ebf7ae4a8 100644
--- a/components/collection/EditModal.vue
+++ b/components/collection/EditModal.vue
@@ -187,7 +187,13 @@ const route = useRoute()
const min = computed(() => props.min || 1)
const max = ref(props.collection?.max)
-const disabled = computed(() => !image.value && !banner.value && props.collection?.max === max.value && bannerUrl.value)
+const disabled = computed(() => {
+ const hasImage = imageUrl.value
+ const hasBannerChanged = (!bannerUrl.value && Boolean(props.collection?.banner)) || Boolean(banner.value)
+ const hasMaxChanged = max.value !== props.collection?.max
+
+ return !hasImage || (!hasBannerChanged && !hasMaxChanged)
+})
const editCollection = async () => {
if (!props.collection) {
From b1d22cf062efcbfa2d8f4c99454cbf498620ffe4 Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Wed, 30 Oct 2024 14:54:06 +0500
Subject: [PATCH 07/45] add(HeroButtonEditCollection.vue): refresh page on
collection data indexed
---
components/collection/EditModal.vue | 39 +++++-------------
.../collection/HeroButtonEditCollection.vue | 40 +++++++++++++++++++
components/collection/HeroButtons.vue | 3 +-
.../collection/utils/useCollectionDetails.ts | 4 +-
composables/transaction/types.ts | 4 +-
composables/useSubscriptionGraphql.ts | 8 +++-
6 files changed, 63 insertions(+), 35 deletions(-)
diff --git a/components/collection/EditModal.vue b/components/collection/EditModal.vue
index 2ebf7ae4a8..2e57f2d817 100644
--- a/components/collection/EditModal.vue
+++ b/components/collection/EditModal.vue
@@ -1,11 +1,4 @@
-
-
import { NeoButton, NeoField, NeoInput, NeoModal, NeoSwitch } from '@kodadot1/brick'
-import { Collections } from '@/composables/transaction/types'
import ModalBody from '@/components/shared/modals/ModalBody.vue'
+import type { UpdateCollection } from '@/composables/transaction/types'
export type CollectionEditMetadata = {
name: string
@@ -165,6 +158,7 @@ export type CollectionEditMetadata = {
max?: number
}
+const emit = defineEmits(['submit'])
const props = defineProps<{
modelValue: boolean
collection?: CollectionEditMetadata
@@ -179,11 +173,6 @@ const imageUrl = ref()
const bannerUrl = ref()
const unlimited = ref(true)
-const { $i18n } = useNuxtApp()
-const { transaction, status, isLoading } = useTransaction()
-const { urlPrefix } = usePrefix()
-const route = useRoute()
-
const min = computed(() => props.min || 1)
const max = ref(props.collection?.max)
@@ -200,22 +189,14 @@ const editCollection = async () => {
return
}
- isModalActive.value = false
-
- await transaction({
- interaction: Collections.UPDATE_COLLECTION,
- collectionId: route.params.id.toString(),
- collection: {
- name: props.collection.name,
- description: props.collection.description,
- image: image.value || props.collection.image,
- imageType: props.collection.imageType,
- banner: bannerUrl.value ? banner.value || props.collection.banner : undefined,
- max: max.value,
- },
- urlPrefix: urlPrefix.value,
- successMessage: $i18n.t('edit.collection.success'),
- })
+ emit('submit', {
+ name: props.collection.name,
+ description: props.collection.description,
+ image: image.value || props.collection.image,
+ imageType: props.collection.imageType,
+ banner: bannerUrl.value ? banner.value || props.collection.banner : undefined,
+ max: max.value,
+ } as UpdateCollection)
}
watch(isModalActive, (value) => {
diff --git a/components/collection/HeroButtonEditCollection.vue b/components/collection/HeroButtonEditCollection.vue
index 1d10bc2f0c..da7f90f5ed 100644
--- a/components/collection/HeroButtonEditCollection.vue
+++ b/components/collection/HeroButtonEditCollection.vue
@@ -5,21 +5,36 @@
{{ $t('moreActions.editCollection') }}
+
+
diff --git a/components/collection/HeroButtons.vue b/components/collection/HeroButtons.vue
index 551a905bd4..8b33c51884 100644
--- a/components/collection/HeroButtons.vue
+++ b/components/collection/HeroButtons.vue
@@ -99,6 +99,7 @@
@@ -167,7 +168,7 @@ const shareCollectionToFarcaster = () => {
)
}
-const { collection } = useCollectionMinimal({
+const { collection, refetch } = useCollectionMinimal({
collectionId,
})
const collectionIssuer = computed(() => collection.value?.displayCreator)
diff --git a/components/collection/utils/useCollectionDetails.ts b/components/collection/utils/useCollectionDetails.ts
index cf4f48b931..abea520bd2 100644
--- a/components/collection/utils/useCollectionDetails.ts
+++ b/components/collection/utils/useCollectionDetails.ts
@@ -113,7 +113,7 @@ export const useCollectionMinimal = ({
id: collectionId.value,
}))
- const { data } = useQuery({
+ const { data, refetch } = useQuery({
queryKey: ['collection-minimal', isAssetHub, collectionId],
queryFn: async () =>
collectionId.value
@@ -127,7 +127,7 @@ export const useCollectionMinimal = ({
: null,
})
- const { drop: collectionDrop, isPending: isDropPending, refetch } = useCollectionDrop(collectionId)
+ const { drop: collectionDrop, isPending: isDropPending } = useCollectionDrop(collectionId)
watch([data, isDropPending],
async ([data, dropPending]) => {
diff --git a/composables/transaction/types.ts b/composables/transaction/types.ts
index 5a9ec51854..ed7679715f 100644
--- a/composables/transaction/types.ts
+++ b/composables/transaction/types.ts
@@ -276,12 +276,14 @@ type UpdateCollectionStatemine = {
max?: number
}
+export type UpdateCollection = UpdateCollectionStatemine
+
export type UpdateCollectionParams = BaseUnionMintParams & { api: ApiPromise }
export interface ActionUpdateCollection {
interaction: Collections.UPDATE_COLLECTION
collectionId: string
- collection: UpdateCollectionStatemine
+ collection: UpdateCollection
urlPrefix: string
successMessage?: string | ((blockNumber: string) => string)
errorMessage?: string
diff --git a/composables/useSubscriptionGraphql.ts b/composables/useSubscriptionGraphql.ts
index 116270f392..d5931defe4 100644
--- a/composables/useSubscriptionGraphql.ts
+++ b/composables/useSubscriptionGraphql.ts
@@ -8,6 +8,7 @@ export default function ({
onError,
pollingInterval = 6000,
disabled,
+ immediate = true,
}: {
clientName?: string
query: string
@@ -15,6 +16,7 @@ export default function ({
onError?: (error) => void
pollingInterval?: number
disabled?: ComputedRef
+ immediate?: boolean
}) {
const { client: prefixClient } = usePrefix()
const { $consola } = useNuxtApp()
@@ -46,8 +48,10 @@ export default function ({
const newResult = response.data as any
if (!isEqual(newResult, lastQueryResult)) {
- $consola.log(`[Graphql Subscription] New changes: ${JSON.stringify(newResult)}`)
- onChange({ data: newResult })
+ if (!lastQueryResult ? immediate : true) {
+ $consola.log(`[Graphql Subscription] New changes: ${JSON.stringify(newResult)}`)
+ onChange({ data: newResult })
+ }
lastQueryResult = newResult
}
}
From cecd40330b361fe7e9568d1139bc9c2d05c782ad Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Wed, 30 Oct 2024 14:58:03 +0500
Subject: [PATCH 08/45] fix(EditModal.vue): collection max overriden on image
upload
---
components/collection/EditModal.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/collection/EditModal.vue b/components/collection/EditModal.vue
index 2e57f2d817..025eece664 100644
--- a/components/collection/EditModal.vue
+++ b/components/collection/EditModal.vue
@@ -218,6 +218,6 @@ watch([image, banner, unlimited], ([image, banner, unlimited]) => {
bannerUrl.value = URL.createObjectURL(banner)
}
- max.value = unlimited ? undefined : props.collection?.max
+ max.value = unlimited ? undefined : max.value || props.collection?.max
})
From 8ec7cbc2c7badaf51ce0581cdca126615c43a9b7 Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Wed, 30 Oct 2024 18:40:22 +0500
Subject: [PATCH 09/45] add(HeroButtons.vue): refresh collection metadata
---
.../collection/HeroButtonRefreshMetadata.vue | 22 +++++++++++++++++++
components/collection/HeroButtons.vue | 1 +
.../GalleryItemMoreActionBtn.vue | 2 +-
locales/en.json | 2 ++
services/oda.ts | 6 +++++
5 files changed, 32 insertions(+), 1 deletion(-)
create mode 100644 components/collection/HeroButtonRefreshMetadata.vue
diff --git a/components/collection/HeroButtonRefreshMetadata.vue b/components/collection/HeroButtonRefreshMetadata.vue
new file mode 100644
index 0000000000..dd4300b688
--- /dev/null
+++ b/components/collection/HeroButtonRefreshMetadata.vue
@@ -0,0 +1,22 @@
+
+
+ {{ $t('moreActions.refereshCollectionMetdata') }}
+
+
+
+
diff --git a/components/collection/HeroButtons.vue b/components/collection/HeroButtons.vue
index 8b33c51884..fb0fa4c508 100644
--- a/components/collection/HeroButtons.vue
+++ b/components/collection/HeroButtons.vue
@@ -102,6 +102,7 @@
@refetch="refetch"
/>
+
{{ $i18n.t('moreActions.reportCollection') }}
diff --git a/components/gallery/GalleryItemButton/GalleryItemMoreActionBtn.vue b/components/gallery/GalleryItemButton/GalleryItemMoreActionBtn.vue
index 4304e0f845..8eec658257 100644
--- a/components/gallery/GalleryItemButton/GalleryItemMoreActionBtn.vue
+++ b/components/gallery/GalleryItemButton/GalleryItemMoreActionBtn.vue
@@ -188,7 +188,7 @@ const unlist = () => {
const refreshMetadata = async () => {
if (props.nft?.collection?.id && props.nft?.sn) {
- toast('Refreshing metadata. Check back in a minute...')
+ toast($i18n.t('toast.refreshMetdata'))
await refreshOdaTokenMetadata(urlPrefix.value, props.nft.collection.id, props.nft.sn)
}
}
diff --git a/locales/en.json b/locales/en.json
index db3d987960..c52ca2daf0 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -1445,6 +1445,7 @@
"deletingNfts": "Deleting NFTs",
"download": "Download",
"editCollection": "Edit Collection",
+ "refereshCollectionMetdata": "Refresh Metadata",
"reportCollection": "Report Collection"
},
"multipleNFTS": "Multiple NFT's",
@@ -1892,6 +1893,7 @@
"downloadImage": "Downloading image",
"downloadOnMobile": "To download the image, copy the URL from the address bar and open it in your browser. The page will open in 2 seconds.",
"paymentLinkCopy": "Payment link copied to clipboard",
+ "refreshMetdata": "Refreshing metadata. Check back in a minute...",
"unsupportedOperation": "Unsupported action",
"uploadFileSizeLimit": "The uploaded file exceeds the {0}MB size limit.",
"urlCopy": "URL copied to clipboard ✓"
diff --git a/services/oda.ts b/services/oda.ts
index c07d14db82..62da733c44 100644
--- a/services/oda.ts
+++ b/services/oda.ts
@@ -52,6 +52,12 @@ export const refreshOdaTokenMetadata = (chain: Prefix, address: string, tokenId:
})
}
+export const refreshOdaCollectionTokensMetadata = (chain: Prefix, address: string) => {
+ return api(`/v1/${chain}/collection/${address}/tokens`, {
+ method: 'DELETE',
+ })
+}
+
type OdaMimeType = {
mime_type: string
}
From fea45277ddebb6fef537ac11cc2f7f053c746fc2 Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Thu, 31 Oct 2024 08:02:17 +0500
Subject: [PATCH 10/45] add(EditModal.vue): into translation keys
---
components/collection/EditModal.vue | 8 ++++----
locales/en.json | 4 ++++
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/components/collection/EditModal.vue b/components/collection/EditModal.vue
index 025eece664..5bf8872a65 100644
--- a/components/collection/EditModal.vue
+++ b/components/collection/EditModal.vue
@@ -69,7 +69,7 @@
class="h-[167px] border border-border-color object-cover"
>
-
+
{{ $t('edit.collection.banner.hint') }}
@@ -93,7 +93,7 @@
:label="$t('edit.collection.drop')"
/>
-
+
{{ $t('edit.collection.banner.hint') }}
@@ -101,7 +101,7 @@
@@ -124,7 +124,7 @@
/>
- This will update the Maximum items in your collection
+ {{ $t('edit.collection.max.hint') }}
diff --git a/locales/en.json b/locales/en.json
index c52ca2daf0..66493b8a33 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -390,6 +390,10 @@
"label": "Logo",
"message": "Visible on collection card and view"
},
+ "max": {
+ "hit": "This will update the Maximum items in your collection",
+ "label": "Maximum NFTs in collection"
+ },
"modal": "Editing Collection",
"saveChanges": "Save Changes",
"success": "Successfully edited collection",
From 5b5f8803b242dbc4769e6b30b6ba01e449c52cce Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Thu, 31 Oct 2024 09:35:24 +0500
Subject: [PATCH 11/45] add(EditModal.vue): capitalize text
---
components/collection/EditModal.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/collection/EditModal.vue b/components/collection/EditModal.vue
index 5bf8872a65..e6d139bbae 100644
--- a/components/collection/EditModal.vue
+++ b/components/collection/EditModal.vue
@@ -56,7 +56,7 @@
-
+
{{ $t('edit.collection.banner.message') }}
From dd0d332927e9b794efff8d804076b5d2ed98b6f7 Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Fri, 1 Nov 2024 17:57:43 +0500
Subject: [PATCH 12/45] add(GalleryItem): set collection metadata
---
components/common/EditNftModal.vue | 171 ++++++++++++++++++
.../GalleryItemEditNftButton.vue | 57 ++++++
.../GalleryItemMoreActionBtn.vue | 2 +
.../transaction/transactionSetNftMetadata.ts | 53 ++++++
composables/transaction/types.ts | 18 +-
composables/transaction/utils.ts | 3 +
composables/useTransaction.ts | 10 +
locales/en.json | 3 +-
8 files changed, 315 insertions(+), 2 deletions(-)
create mode 100644 components/common/EditNftModal.vue
create mode 100644 components/gallery/GalleryItemButton/GalleryItemEditNftButton.vue
create mode 100644 composables/transaction/transactionSetNftMetadata.ts
diff --git a/components/common/EditNftModal.vue b/components/common/EditNftModal.vue
new file mode 100644
index 0000000000..753a4d345d
--- /dev/null
+++ b/components/common/EditNftModal.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+7
diff --git a/components/gallery/GalleryItemButton/GalleryItemEditNftButton.vue b/components/gallery/GalleryItemButton/GalleryItemEditNftButton.vue
new file mode 100644
index 0000000000..f15d83f4e3
--- /dev/null
+++ b/components/gallery/GalleryItemButton/GalleryItemEditNftButton.vue
@@ -0,0 +1,57 @@
+
+
+ Edit
+
+
+
+
+
+
+
+
diff --git a/components/gallery/GalleryItemButton/GalleryItemMoreActionBtn.vue b/components/gallery/GalleryItemButton/GalleryItemMoreActionBtn.vue
index 8eec658257..d9b944c21e 100644
--- a/components/gallery/GalleryItemButton/GalleryItemMoreActionBtn.vue
+++ b/components/gallery/GalleryItemButton/GalleryItemMoreActionBtn.vue
@@ -48,6 +48,7 @@
Delist
+
Report
@@ -63,6 +64,7 @@
import { NeoButton, NeoDropdown, NeoDropdownItem } from '@kodadot1/brick'
import { Interaction } from '@kodadot1/minimark/v1'
import { useQuery } from '@tanstack/vue-query'
+import GalleryItemEditNftButton from './GalleryItemEditNftButton.vue'
import { downloadImage } from '@/utils/download'
import { sanitizeIpfsUrl, toOriginalContentUrl } from '@/utils/ipfs'
import { isMobileDevice } from '@/utils/extension'
diff --git a/composables/transaction/transactionSetNftMetadata.ts b/composables/transaction/transactionSetNftMetadata.ts
new file mode 100644
index 0000000000..6f758e5a25
--- /dev/null
+++ b/composables/transaction/transactionSetNftMetadata.ts
@@ -0,0 +1,53 @@
+import { unSanitizeIpfsUrl } from '@kodadot1/minimark/utils'
+import { type Metadata } from '@kodadot1/minimark/common'
+import type { SetNftMetadataParams, ActionSetNftMetadata } from './types'
+import { pinJson, rateLimitedPinFileToIPFS } from '@/services/nftStorage'
+
+const constructMeta = async (item: ActionSetNftMetadata) => {
+ const { name, description, attributes, image } = item.metadata
+
+ let imageHash: string | undefined
+ let type: string | undefined
+
+ if (image instanceof File) {
+ imageHash = unSanitizeIpfsUrl(await rateLimitedPinFileToIPFS(image))
+ type = getImageTypeSafe(image)
+ }
+ else {
+ imageHash = image
+ type = item.metadata.type
+ }
+
+ const meta = {
+ ...item.metadata,
+ name,
+ description,
+ image: imageHash,
+ attributes,
+ type,
+ } as Metadata
+
+ const metaHash = await pinJson(meta)
+
+ return unSanitizeIpfsUrl(metaHash)
+}
+
+async function execSetNftMetadataStatmine({ item, api, executeTransaction, isLoading, status }: SetNftMetadataParams) {
+ isLoading.value = true
+ status.value = 'loader.ipfs'
+
+ const metadata = await constructMeta(item)
+
+ executeTransaction({
+ cb: api.tx.nfts.setMetadata,
+ arg: [item.collectionId, item.nftSn, metadata],
+ successMessage: item.successMessage,
+ errorMessage: item.errorMessage,
+ })
+}
+
+export async function execSetNftMetadata({ item, ...params }: SetNftMetadataParams) {
+ if (item.urlPrefix === 'ahk' || item.urlPrefix === 'ahp') {
+ return execSetNftMetadataStatmine({ item, ...params })
+ }
+}
diff --git a/composables/transaction/types.ts b/composables/transaction/types.ts
index ed7679715f..ceea971c4f 100644
--- a/composables/transaction/types.ts
+++ b/composables/transaction/types.ts
@@ -1,4 +1,4 @@
-import type { Attribute } from '@kodadot1/minimark/common'
+import type { Attribute, Metadata } from '@kodadot1/minimark/common'
import type { Interaction } from '@kodadot1/minimark/v1'
import type { ApiPromise } from '@polkadot/api'
import type { Prefix } from '@kodadot1/static'
@@ -257,6 +257,7 @@ export interface ActionDeleteCollection {
export enum NFTs {
BURN_MULTIPLE = 'burnMultiple',
MINT_DROP = 'mintDrop',
+ SET_METADATA = 'setMetadata',
}
export interface ActionBurnMultipleNFTs {
@@ -267,6 +268,20 @@ export interface ActionBurnMultipleNFTs {
errorMessage?: string
}
+export type ActionMetadataSetMetadata = Metadata & { image: File | string }
+
+export interface ActionSetNftMetadata {
+ interaction: NFTs.SET_METADATA
+ urlPrefix: string
+ nftSn: string
+ collectionId: string
+ metadata: ActionMetadataSetMetadata
+ successMessage?: string
+ errorMessage?: string
+}
+
+export type SetNftMetadataParams = BaseUnionMintParams & { api: ApiPromise }
+
type UpdateCollectionStatemine = {
name: string
description: string
@@ -302,4 +317,5 @@ export type Actions =
| ActionDeleteCollection
| ActionBurnMultipleNFTs
| ActionUpdateCollection
+ | ActionSetNftMetadata
| ActionMintDrop
diff --git a/composables/transaction/utils.ts b/composables/transaction/utils.ts
index ed78d9fe55..0f4d7af233 100644
--- a/composables/transaction/utils.ts
+++ b/composables/transaction/utils.ts
@@ -19,6 +19,7 @@ import type {
ActionSend,
ActionUpdateCollection,
ActionWithdrawOffer,
+ ActionSetNftMetadata,
Actions } from '../transaction/types'
import { getPercentSupportFee } from '@/utils/support'
@@ -61,6 +62,8 @@ export function isActionValid(action: Actions): boolean {
Boolean(action.collectionId),
[NFTs.BURN_MULTIPLE]: (action: ActionBurnMultipleNFTs) =>
hasContent(action.nftIds),
+ [NFTs.SET_METADATA]: (action: ActionSetNftMetadata) =>
+ hasContent(action.nftSn),
[NFTs.MINT_DROP]: (action: ActionMintDrop) =>
hasContent(action.collectionId),
}
diff --git a/composables/useTransaction.ts b/composables/useTransaction.ts
index 2397689a50..40a99f9c40 100644
--- a/composables/useTransaction.ts
+++ b/composables/useTransaction.ts
@@ -16,6 +16,7 @@ import { execMakingOfferTx } from './transaction/transactionOffer'
import { execMintToken } from './transaction/transactionMintToken'
import { execMintCollection } from './transaction/transactionMintCollection'
import { execUpdateCollection } from './transaction/transactionUpdateCollection'
+import { execSetNftMetadata } from './transaction/transactionSetNftMetadata'
import type {
ActionAcceptOffer,
ActionBurnMultipleNFTs,
@@ -29,6 +30,7 @@ import type {
ActionMintToken,
ActionSend,
ActionUpdateCollection,
+ ActionSetNftMetadata,
ActionWithdrawOffer,
Actions,
ExecuteEvmTransactionParams,
@@ -267,6 +269,14 @@ export const executeAction = ({
api as ApiPromise,
executeTransaction,
),
+ [NFTs.SET_METADATA]: () =>
+ execSetNftMetadata({
+ item: item as ActionSetNftMetadata,
+ api: api as ApiPromise,
+ executeTransaction,
+ isLoading,
+ status,
+ }),
[NFTs.MINT_DROP]: () =>
execMintDrop({
item: item as ActionMintDrop,
diff --git a/locales/en.json b/locales/en.json
index 66493b8a33..a175cd0f93 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -398,7 +398,8 @@
"saveChanges": "Save Changes",
"success": "Successfully edited collection",
"title": "Edit Collection"
- }
+ },
+ "nft": { "title": "Edit NFT" }
},
"email": "Email",
"error": "Error",
From 0991b286e306a5059ce3623ad5b69a872911ba2a Mon Sep 17 00:00:00 2001
From: hassnian <44554284+hassnian@users.noreply.github.com>
Date: Sat, 2 Nov 2024 11:54:37 +0500
Subject: [PATCH 13/45] fix(EditNftModal.vue): disabled computed and attributes
updating
---
components/common/EditNftModal.vue | 13 ++++++++++---
components/rmrk/Create/CustomAttributeInput.vue | 13 +++++--------
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/components/common/EditNftModal.vue b/components/common/EditNftModal.vue
index 753a4d345d..7da704f96b 100644
--- a/components/common/EditNftModal.vue
+++ b/components/common/EditNftModal.vue
@@ -132,9 +132,16 @@ const imageUrl = ref()
const attributes = ref([])
const disabled = computed(() => {
- const hasImage = imageUrl.value
+ const hasImage = Boolean(imageUrl.value)
+ const isNameFilled = Boolean(name.value)
- return !hasImage
+ const nameChanged = props.metadata?.name !== name.value
+ const descriptionChanged = props.metadata?.description !== description.value
+ const imageChanged = Boolean(image.value)
+ const attributesChanged = JSON.stringify(attributes.value) !== JSON.stringify(props.metadata?.attributes || [])
+
+ return !hasImage || !isNameFilled
+ || (!nameChanged && !descriptionChanged && !imageChanged && !attributesChanged)
})
const editCollection = async () => {
@@ -159,7 +166,7 @@ watch(isModalActive, (value) => {
image.value = undefined
name.value = props.metadata?.name
description.value = props.metadata?.description
- attributes.value = props.metadata?.attributes || [] as Attribute[]
+ attributes.value = JSON.parse(JSON.stringify(props.metadata?.attributes || []))
}
})
diff --git a/components/rmrk/Create/CustomAttributeInput.vue b/components/rmrk/Create/CustomAttributeInput.vue
index 11eac07341..ffa707c40c 100644
--- a/components/rmrk/Create/CustomAttributeInput.vue
+++ b/components/rmrk/Create/CustomAttributeInput.vue
@@ -36,6 +36,7 @@ import AttributeInput from './AttributeInput.vue'
const props = withDefaults(
defineProps<{
+ modelValue?: Attribute[]
max: number
visible?: string
hidden?: string
@@ -44,11 +45,12 @@ const props = withDefaults(
max: 0,
visible: 'collapse.collection.attributes.show',
hidden: 'collapse.collection.attributes.hide',
+ modelValue: () => [],
},
)
-const emit = defineEmits(['update:modelValue'])
-const attributes = ref([])
+const attributes = useVModel(props, 'modelValue')
+
const disabled = computed(
() => props.max > 0 && attributes.value.length === props.max,
)
@@ -61,13 +63,8 @@ const addAttribute = () => {
})
}
}
-const removeAttribute = (index: number) => attributes.value.splice(index, 1)
-const handleInput = (attributes: Attribute[]) =>
- emit('update:modelValue', attributes)
-watch(attributes.value, () => {
- handleInput(attributes.value)
-})
+const removeAttribute = (index: number) => attributes.value.splice(index, 1)