2022-12-26 13:17:09 +00:00
|
|
|
/* eslint-disable eslint-comments/disable-enable-pair */
|
|
|
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
|
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
|
|
|
|
|
|
import { useMetadataAttributesState } from 'components/forms/MetadataAttributes.hooks'
|
|
|
|
import { useEffect, useMemo, useState } from 'react'
|
|
|
|
|
|
|
|
import { TextInput } from './forms/FormInput'
|
|
|
|
import { useInputState } from './forms/FormInput.hooks'
|
|
|
|
import { MetadataAttributes } from './forms/MetadataAttributes'
|
|
|
|
|
|
|
|
export interface MetadataInputProps {
|
|
|
|
selectedAssetFile: File
|
|
|
|
selectedMetadataFile: File
|
|
|
|
updateMetadataToUpload: (metadataFile: File) => void
|
2023-08-17 11:20:37 +00:00
|
|
|
onChange?: (metadata: any) => void
|
|
|
|
importedMetadata?: any
|
2022-12-26 13:17:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const MetadataInput = (props: MetadataInputProps) => {
|
|
|
|
const emptyMetadataFile = new File(
|
|
|
|
[JSON.stringify({})],
|
|
|
|
`${props.selectedAssetFile?.name.substring(0, props.selectedAssetFile?.name.lastIndexOf('.'))}.json`,
|
|
|
|
{ type: 'application/json' },
|
|
|
|
)
|
|
|
|
|
|
|
|
const [metadata, setMetadata] = useState<any>(null)
|
|
|
|
|
|
|
|
const nameState = useInputState({
|
|
|
|
id: 'name',
|
|
|
|
name: 'name',
|
|
|
|
title: 'Name',
|
|
|
|
placeholder: 'Token name',
|
|
|
|
})
|
|
|
|
|
|
|
|
const descriptionState = useInputState({
|
|
|
|
id: 'description',
|
|
|
|
name: 'description',
|
|
|
|
title: 'Description',
|
|
|
|
placeholder: 'Token description',
|
|
|
|
})
|
|
|
|
|
|
|
|
const externalUrlState = useInputState({
|
|
|
|
id: 'externalUrl',
|
|
|
|
name: 'externalUrl',
|
|
|
|
title: 'External URL',
|
|
|
|
placeholder: 'https://',
|
|
|
|
})
|
|
|
|
|
|
|
|
const youtubeUrlState = useInputState({
|
|
|
|
id: 'youtubeUrl',
|
|
|
|
name: 'youtubeUrl',
|
|
|
|
title: 'Youtube URL',
|
|
|
|
placeholder: 'https://',
|
|
|
|
})
|
|
|
|
|
|
|
|
const attributesState = useMetadataAttributesState()
|
|
|
|
|
|
|
|
let parsedMetadata: any
|
|
|
|
const parseMetadata = async (metadataFile: File) => {
|
|
|
|
console.log(metadataFile.size)
|
|
|
|
console.log(`Parsing metadataFile...`)
|
|
|
|
if (metadataFile) {
|
|
|
|
attributesState.reset()
|
|
|
|
try {
|
|
|
|
parsedMetadata = JSON.parse(await metadataFile.text())
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
console.log('Parsed metadata: ', parsedMetadata)
|
|
|
|
|
|
|
|
if (!parsedMetadata.attributes || parsedMetadata.attributes?.length === 0) {
|
|
|
|
attributesState.reset()
|
|
|
|
attributesState.add({
|
|
|
|
trait_type: '',
|
|
|
|
value: '',
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
attributesState.reset()
|
|
|
|
for (let i = 0; i < parsedMetadata.attributes?.length; i++) {
|
|
|
|
attributesState.add({
|
|
|
|
trait_type: parsedMetadata.attributes[i].trait_type,
|
|
|
|
value: parsedMetadata.attributes[i].value,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!parsedMetadata.name) {
|
|
|
|
nameState.onChange('')
|
|
|
|
} else {
|
|
|
|
nameState.onChange(parsedMetadata.name)
|
|
|
|
}
|
|
|
|
if (!parsedMetadata.description) {
|
|
|
|
descriptionState.onChange('')
|
|
|
|
} else {
|
|
|
|
descriptionState.onChange(parsedMetadata.description)
|
|
|
|
}
|
|
|
|
if (!parsedMetadata.external_url) {
|
|
|
|
externalUrlState.onChange('')
|
|
|
|
} else {
|
|
|
|
externalUrlState.onChange(parsedMetadata.external_url)
|
|
|
|
}
|
|
|
|
if (!parsedMetadata.youtube_url) {
|
|
|
|
youtubeUrlState.onChange('')
|
|
|
|
} else {
|
|
|
|
youtubeUrlState.onChange(parsedMetadata.youtube_url)
|
|
|
|
}
|
|
|
|
setMetadata(parsedMetadata)
|
|
|
|
} else {
|
|
|
|
attributesState.reset()
|
|
|
|
nameState.onChange('')
|
|
|
|
descriptionState.onChange('')
|
|
|
|
externalUrlState.onChange('')
|
|
|
|
youtubeUrlState.onChange('')
|
|
|
|
attributesState.add({
|
|
|
|
trait_type: '',
|
|
|
|
value: '',
|
|
|
|
})
|
|
|
|
setMetadata(null)
|
|
|
|
props.updateMetadataToUpload(emptyMetadataFile)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const generateUpdatedMetadata = () => {
|
|
|
|
metadata.attributes = Object.values(attributesState)[1]
|
|
|
|
metadata.attributes = metadata.attributes.filter((attribute: { trait_type: string }) => attribute.trait_type !== '')
|
|
|
|
|
|
|
|
if (metadata.attributes.length === 0) delete metadata.attributes
|
|
|
|
if (nameState.value === '') delete metadata.name
|
|
|
|
else metadata.name = nameState.value
|
|
|
|
if (descriptionState.value === '') delete metadata.description
|
2023-09-26 05:46:01 +00:00
|
|
|
else metadata.description = descriptionState.value.replaceAll('\\n', '\n')
|
2022-12-26 13:17:09 +00:00
|
|
|
if (externalUrlState.value === '') delete metadata.external_url
|
|
|
|
else metadata.external_url = externalUrlState.value
|
|
|
|
if (youtubeUrlState.value === '') delete metadata.youtube_url
|
|
|
|
else metadata.youtube_url = youtubeUrlState.value
|
|
|
|
|
|
|
|
const metadataFileBlob = new Blob([JSON.stringify(metadata)], {
|
|
|
|
type: 'application/json',
|
|
|
|
})
|
|
|
|
|
|
|
|
const editedMetadataFile = new File(
|
|
|
|
[metadataFileBlob],
|
|
|
|
props.selectedMetadataFile?.name
|
|
|
|
? props.selectedMetadataFile?.name
|
|
|
|
: `${props.selectedAssetFile?.name.substring(0, props.selectedAssetFile?.name.lastIndexOf('.'))}.json`,
|
|
|
|
{ type: 'application/json' },
|
|
|
|
)
|
|
|
|
props.updateMetadataToUpload(editedMetadataFile)
|
|
|
|
//console.log(editedMetadataFile)
|
|
|
|
//console.log(`${props.assetFile?.name.substring(0, props.assetFile?.name.lastIndexOf('.'))}.json`)
|
|
|
|
}
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
console.log(props.selectedMetadataFile?.name)
|
2023-08-17 11:20:37 +00:00
|
|
|
if (props.selectedMetadataFile) {
|
|
|
|
void parseMetadata(props.selectedMetadataFile)
|
|
|
|
} else if (!props.importedMetadata) {
|
|
|
|
void parseMetadata(emptyMetadataFile)
|
|
|
|
}
|
2023-08-21 09:07:11 +00:00
|
|
|
}, [props.selectedMetadataFile?.name, props.importedMetadata])
|
2022-12-26 13:17:09 +00:00
|
|
|
|
|
|
|
const nameStateMemo = useMemo(() => nameState, [nameState.value])
|
|
|
|
const descriptionStateMemo = useMemo(() => descriptionState, [descriptionState.value])
|
|
|
|
const externalUrlStateMemo = useMemo(() => externalUrlState, [externalUrlState.value])
|
|
|
|
const youtubeUrlStateMemo = useMemo(() => youtubeUrlState, [youtubeUrlState.value])
|
|
|
|
const attributesStateMemo = useMemo(() => attributesState, [attributesState.entries])
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
console.log('Update metadata')
|
2023-08-17 11:20:37 +00:00
|
|
|
if (metadata) {
|
|
|
|
generateUpdatedMetadata()
|
|
|
|
if (props.onChange) props.onChange(metadata)
|
|
|
|
}
|
2022-12-26 13:17:09 +00:00
|
|
|
console.log(metadata)
|
|
|
|
}, [
|
|
|
|
nameStateMemo.value,
|
|
|
|
descriptionStateMemo.value,
|
|
|
|
externalUrlStateMemo.value,
|
|
|
|
youtubeUrlStateMemo.value,
|
|
|
|
attributesStateMemo.entries,
|
|
|
|
])
|
|
|
|
|
2023-08-17 11:20:37 +00:00
|
|
|
useEffect(() => {
|
|
|
|
if (props.importedMetadata) {
|
2023-08-21 09:07:11 +00:00
|
|
|
void parseMetadata(emptyMetadataFile).then(() => {
|
|
|
|
console.log('Imported metadata: ', props.importedMetadata)
|
|
|
|
nameState.onChange(props.importedMetadata.name || '')
|
|
|
|
descriptionState.onChange(props.importedMetadata.description || '')
|
|
|
|
externalUrlState.onChange(props.importedMetadata.external_url || '')
|
|
|
|
youtubeUrlState.onChange(props.importedMetadata.youtube_url || '')
|
|
|
|
if (props.importedMetadata?.attributes && props.importedMetadata?.attributes?.length > 0) {
|
|
|
|
attributesState.reset()
|
|
|
|
props.importedMetadata?.attributes?.forEach((attribute: { trait_type: string; value: string }) => {
|
|
|
|
attributesState.add({
|
|
|
|
trait_type: attribute.trait_type,
|
|
|
|
value: attribute.value,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
attributesState.reset()
|
2023-08-17 11:20:37 +00:00
|
|
|
attributesState.add({
|
2023-08-21 09:07:11 +00:00
|
|
|
trait_type: '',
|
|
|
|
value: '',
|
2023-08-17 11:20:37 +00:00
|
|
|
})
|
2023-08-21 09:07:11 +00:00
|
|
|
}
|
|
|
|
})
|
2023-08-17 11:20:37 +00:00
|
|
|
}
|
|
|
|
}, [props.importedMetadata])
|
|
|
|
|
2022-12-26 13:17:09 +00:00
|
|
|
return (
|
|
|
|
<div>
|
2023-06-15 13:13:08 +00:00
|
|
|
<div className="grid grid-cols-2 mt-4 mr-4 ml-8 w-full max-w-6xl max-h-full no-scrollbar">
|
2022-12-26 13:17:09 +00:00
|
|
|
<div className="mr-4">
|
2023-06-15 13:13:08 +00:00
|
|
|
<div className="mb-7 text-xl font-bold underline underline-offset-4">NFT Metadata</div>
|
2022-12-26 13:17:09 +00:00
|
|
|
<TextInput {...nameState} />
|
|
|
|
<TextInput className="mt-2" {...descriptionState} />
|
|
|
|
<TextInput className="mt-2" {...externalUrlState} />
|
|
|
|
<TextInput className="mt-2" {...youtubeUrlState} />
|
|
|
|
</div>
|
|
|
|
<div className="mt-6">
|
|
|
|
<MetadataAttributes
|
|
|
|
attributes={attributesState.entries}
|
|
|
|
onAdd={attributesState.add}
|
|
|
|
onChange={attributesState.update}
|
|
|
|
onRemove={attributesState.remove}
|
|
|
|
title="Attributes"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|