Surface open edition collection configuration

This commit is contained in:
Serkan Reis 2023-07-25 22:26:29 +03:00
parent 8921938c6c
commit 2a38e79191
7 changed files with 128 additions and 8 deletions

View File

@ -28,6 +28,7 @@ interface CollectionDetailsProps {
uploadMethod: UploadMethod
coverImageUrl: string
metadataStorageMethod: MetadataStorageMethod
importedCollectionDetails?: CollectionDetailsDataProps
}
export interface CollectionDetailsDataProps {
@ -46,6 +47,7 @@ export const CollectionDetails = ({
uploadMethod,
metadataStorageMethod,
coverImageUrl,
importedCollectionDetails,
}: CollectionDetailsProps) => {
const [coverImage, setCoverImage] = useState<File | null>(null)
const [timestamp, setTimestamp] = useState<Date | undefined>()
@ -152,6 +154,23 @@ export const CollectionDetails = ({
}
}, [updatable])
useEffect(() => {
if (importedCollectionDetails) {
nameState.onChange(importedCollectionDetails.name)
descriptionState.onChange(importedCollectionDetails.description)
symbolState.onChange(importedCollectionDetails.symbol)
setCoverImage(importedCollectionDetails.imageFile[0] || null)
externalLinkState.onChange(importedCollectionDetails.externalLink || '')
setTimestamp(
importedCollectionDetails.startTradingTime
? new Date(parseInt(importedCollectionDetails.startTradingTime) / 1_000_000)
: undefined,
)
setExplicit(importedCollectionDetails.explicit)
setUpdatable(importedCollectionDetails.updatable)
}
}, [importedCollectionDetails])
const videoPreview = useMemo(() => {
if (uploadMethod === 'new' && coverImage) {
return (

View File

@ -20,6 +20,7 @@ export type UploadMethod = 'new' | 'existing'
interface ImageUploadDetailsProps {
onChange: (value: ImageUploadDetailsDataProps) => void
importedImageUploadDetails?: ImageUploadDetailsDataProps
}
export interface ImageUploadDetailsDataProps {
@ -33,7 +34,7 @@ export interface ImageUploadDetailsDataProps {
coverImageUrl?: string
}
export const ImageUploadDetails = ({ onChange }: ImageUploadDetailsProps) => {
export const ImageUploadDetails = ({ onChange, importedImageUploadDetails }: ImageUploadDetailsProps) => {
const [assetFile, setAssetFile] = useState<File>()
const [uploadMethod, setUploadMethod] = useState<UploadMethod>('new')
const [uploadService, setUploadService] = useState<UploadServiceType>('nft-storage')
@ -140,6 +141,18 @@ export const ImageUploadDetails = ({ onChange }: ImageUploadDetailsProps) => {
imageUrlState.onChange('')
}, [uploadMethod])
useEffect(() => {
if (importedImageUploadDetails) {
setUploadMethod(importedImageUploadDetails.uploadMethod)
setUploadService(importedImageUploadDetails.uploadService)
nftStorageApiKeyState.onChange(importedImageUploadDetails.nftStorageApiKey || '')
pinataApiKeyState.onChange(importedImageUploadDetails.pinataApiKey || '')
pinataSecretKeyState.onChange(importedImageUploadDetails.pinataSecretKey || '')
imageUrlState.onChange(importedImageUploadDetails.imageUrl || '')
coverImageUrlState.onChange(importedImageUploadDetails.coverImageUrl || '')
}
}, [importedImageUploadDetails])
const previewUrl = imageUrlState.value.toLowerCase().trim().startsWith('ipfs://')
? `https://ipfs-gw.stargaze-apis.com/ipfs/${imageUrlState.value.substring(7)}`
: imageUrlState.value

View File

@ -15,6 +15,7 @@ interface MintingDetailsProps {
onChange: (data: MintingDetailsDataProps) => void
uploadMethod: UploadMethod
minimumMintPrice: number
importedMintingDetails?: MintingDetailsDataProps
}
export interface MintingDetailsDataProps {
@ -25,7 +26,12 @@ export interface MintingDetailsDataProps {
paymentAddress?: string
}
export const MintingDetails = ({ onChange, uploadMethod, minimumMintPrice }: MintingDetailsProps) => {
export const MintingDetails = ({
onChange,
uploadMethod,
minimumMintPrice,
importedMintingDetails,
}: MintingDetailsProps) => {
const wallet = useWallet()
const [timestamp, setTimestamp] = useState<Date | undefined>()
@ -81,6 +87,17 @@ export const MintingDetails = ({ onChange, uploadMethod, minimumMintPrice }: Min
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [unitPriceState.value, perAddressLimitState.value, timestamp, endTimestamp, paymentAddressState.value])
useEffect(() => {
if (importedMintingDetails) {
unitPriceState.onChange(Number(importedMintingDetails.unitPrice))
perAddressLimitState.onChange(importedMintingDetails.perAddressLimit)
setTimestamp(new Date(Number(importedMintingDetails.startTime) / 1_000_000))
setEndTimestamp(new Date(Number(importedMintingDetails.endTime) / 1_000_000))
paymentAddressState.onChange(importedMintingDetails.paymentAddress ? importedMintingDetails.paymentAddress : '')
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [importedMintingDetails])
return (
<div className="border-l-[1px] border-gray-500 border-opacity-20">
<FormGroup subtitle="Information about your minting settings" title="Minting Details">

View File

@ -28,6 +28,7 @@ export type UploadMethod = 'new' | 'existing'
interface OffChainMetadataUploadDetailsProps {
onChange: (value: OffChainMetadataUploadDetailsDataProps) => void
metadataStorageMethod?: MetadataStorageMethod
importedOffChainMetadataUploadDetails?: OffChainMetadataUploadDetailsDataProps
}
export interface OffChainMetadataUploadDetailsDataProps {
@ -46,6 +47,7 @@ export interface OffChainMetadataUploadDetailsDataProps {
export const OffChainMetadataUploadDetails = ({
onChange,
metadataStorageMethod,
importedOffChainMetadataUploadDetails,
}: OffChainMetadataUploadDetailsProps) => {
const [assetFilesArray, setAssetFilesArray] = useState<File[]>([])
const [metadataFilesArray, setMetadataFilesArray] = useState<File[]>([])
@ -233,6 +235,19 @@ export const OffChainMetadataUploadDetails = ({
coverImageUrlState.onChange('')
}, [uploadMethod, metadataStorageMethod])
useEffect(() => {
if (importedOffChainMetadataUploadDetails) {
setUploadService(importedOffChainMetadataUploadDetails.uploadService)
nftStorageApiKeyState.onChange(importedOffChainMetadataUploadDetails.nftStorageApiKey || '')
pinataApiKeyState.onChange(importedOffChainMetadataUploadDetails.pinataApiKey || '')
pinataSecretKeyState.onChange(importedOffChainMetadataUploadDetails.pinataSecretKey || '')
setUploadMethod('existing')
tokenUriState.onChange(importedOffChainMetadataUploadDetails.tokenURI || '')
coverImageUrlState.onChange(importedOffChainMetadataUploadDetails.imageUrl || '')
setOpenEditionMinterMetadataFile(importedOffChainMetadataUploadDetails.openEditionMinterMetadataFile)
}
}, [importedOffChainMetadataUploadDetails])
return (
<div className="justify-items-start mb-3 rounded border-2 border-white/20 flex-column">
<div className="flex justify-center">

View File

@ -21,6 +21,7 @@ import type { UploadMethod } from './ImageUploadDetails'
interface OnChainMetadataInputDetailsProps {
onChange: (data: OnChainMetadataInputDetailsDataProps) => void
uploadMethod: UploadMethod | undefined
importedOnChainMetadataInputDetails?: OnChainMetadataInputDetailsDataProps
}
export interface OnChainMetadataInputDetailsDataProps {
@ -34,7 +35,11 @@ export interface OnChainMetadataInputDetailsDataProps {
youtube_url?: string
}
export const OnChainMetadataInputDetails = ({ onChange, uploadMethod }: OnChainMetadataInputDetailsProps) => {
export const OnChainMetadataInputDetails = ({
onChange,
uploadMethod,
importedOnChainMetadataInputDetails,
}: OnChainMetadataInputDetailsProps) => {
const wallet = useWallet()
const [timestamp, setTimestamp] = useState<Date | undefined>(undefined)
const [metadataFile, setMetadataFile] = useState<File>()
@ -196,6 +201,26 @@ export const OnChainMetadataInputDetails = ({ onChange, uploadMethod }: OnChainM
youtubeUrlState.value,
])
useEffect(() => {
if (importedOnChainMetadataInputDetails) {
nameState.onChange(importedOnChainMetadataInputDetails.name || '')
descriptionState.onChange(importedOnChainMetadataInputDetails.description || '')
externalUrlState.onChange(importedOnChainMetadataInputDetails.external_url || '')
youtubeUrlState.onChange(importedOnChainMetadataInputDetails.youtube_url || '')
animationUrlState.onChange(importedOnChainMetadataInputDetails.animation_url || '')
imageDataState.onChange(importedOnChainMetadataInputDetails.image_data || '')
if (importedOnChainMetadataInputDetails.attributes) {
attributesState.reset()
importedOnChainMetadataInputDetails.attributes.forEach((attr) => {
attributesState.add({
trait_type: attr.trait_type,
value: attr.value,
})
})
}
}
}, [importedOnChainMetadataInputDetails])
return (
<div className="py-3 px-8 rounded border-2 border-white/20">
<span className="ml-4 text-xl font-bold underline underline-offset-4">NFT Metadata</span>

View File

@ -54,6 +54,7 @@ export interface OpenEditionMinterDetailsDataProps {
onChainMetadataInputDetails?: OnChainMetadataInputDetailsDataProps
offChainMetadataUploadDetails?: OffChainMetadataUploadDetailsDataProps
mintingDetails?: MintingDetailsDataProps
metadataStorageMethod?: MetadataStorageMethod
}
interface OpenEditionMinterCreatorProps {
@ -64,7 +65,7 @@ interface OpenEditionMinterCreatorProps {
minimumMintPrice?: string
minimumUpdatableMintPrice?: string
minterType?: MinterType
importedOpenEditionMinterDetails?: OpenEditionMinterCreatorDataProps
importedOpenEditionMinterDetails?: OpenEditionMinterDetailsDataProps
}
export interface OpenEditionMinterCreatorDataProps {
@ -82,6 +83,7 @@ export const OpenEditionMinterCreator = ({
minimumMintPrice,
minimumUpdatableMintPrice,
minterType,
importedOpenEditionMinterDetails,
}: OpenEditionMinterCreatorProps) => {
const wallet = useWallet()
const { openEditionMinter: openEditionMinterContract, openEditionFactory: openEditionFactoryContract } =
@ -605,6 +607,7 @@ export const OpenEditionMinterCreator = ({
onChainMetadataInputDetails: onChainMetadataInputDetails ? onChainMetadataInputDetails : undefined,
offChainMetadataUploadDetails: offChainMetadataUploadDetails ? offChainMetadataUploadDetails : undefined,
mintingDetails: mintingDetails ? mintingDetails : undefined,
metadataStorageMethod,
}
onDetailsChange(data)
// eslint-disable-next-line react-hooks/exhaustive-deps
@ -617,6 +620,12 @@ export const OpenEditionMinterCreator = ({
mintingDetails,
])
useEffect(() => {
if (importedOpenEditionMinterDetails) {
setMetadataStorageMethod(importedOpenEditionMinterDetails.metadataStorageMethod as MetadataStorageMethod)
}
}, [importedOpenEditionMinterDetails])
return (
<div>
{/* TODO: Cancel once we're able to index on-chain metadata */}
@ -667,13 +676,20 @@ export const OpenEditionMinterCreator = ({
<div className={clsx('my-4 mx-10')}>
<Conditional test={metadataStorageMethod === 'off-chain'}>
<div>
<OffChainMetadataUploadDetails onChange={setOffChainMetadataUploadDetails} />
<OffChainMetadataUploadDetails
importedOffChainMetadataUploadDetails={importedOpenEditionMinterDetails?.offChainMetadataUploadDetails}
onChange={setOffChainMetadataUploadDetails}
/>
</div>
</Conditional>
<Conditional test={metadataStorageMethod === 'on-chain'}>
<div>
<ImageUploadDetails onChange={setImageUploadDetails} />
<ImageUploadDetails
importedImageUploadDetails={importedOpenEditionMinterDetails?.imageUploadDetails}
onChange={setImageUploadDetails}
/>
<OnChainMetadataInputDetails
importedOnChainMetadataInputDetails={importedOpenEditionMinterDetails?.onChainMetadataInputDetails}
onChange={setOnChainMetadataInputDetails}
uploadMethod={imageUploadDetails?.uploadMethod}
/>
@ -687,6 +703,7 @@ export const OpenEditionMinterCreator = ({
? (offChainMetadataUploadDetails?.imageUrl as string)
: (imageUploadDetails?.coverImageUrl as string)
}
importedCollectionDetails={importedOpenEditionMinterDetails?.collectionDetails}
metadataStorageMethod={metadataStorageMethod}
onChange={setCollectionDetails}
uploadMethod={
@ -696,6 +713,7 @@ export const OpenEditionMinterCreator = ({
}
/>
<MintingDetails
importedMintingDetails={importedOpenEditionMinterDetails?.mintingDetails}
minimumMintPrice={
collectionDetails?.updatable
? Number(minimumUpdatableMintPrice) / 1000000
@ -706,7 +724,10 @@ export const OpenEditionMinterCreator = ({
/>
</div>
<div className="my-6">
<RoyaltyDetails onChange={setRoyaltyDetails} />
<RoyaltyDetails
importedRoyaltyDetails={importedOpenEditionMinterDetails?.royaltyDetails}
onChange={setRoyaltyDetails}
/>
</div>
<div className="flex justify-end w-full">
<Button

View File

@ -9,6 +9,7 @@ import { NumberInput, TextInput } from '../forms/FormInput'
interface RoyaltyDetailsProps {
onChange: (data: RoyaltyDetailsDataProps) => void
importedRoyaltyDetails?: RoyaltyDetailsDataProps
}
export interface RoyaltyDetailsDataProps {
@ -19,7 +20,7 @@ export interface RoyaltyDetailsDataProps {
type RoyaltyState = 'none' | 'new'
export const RoyaltyDetails = ({ onChange }: RoyaltyDetailsProps) => {
export const RoyaltyDetails = ({ onChange, importedRoyaltyDetails }: RoyaltyDetailsProps) => {
const wallet = useWallet()
const [royaltyState, setRoyaltyState] = useState<RoyaltyState>('none')
@ -60,6 +61,15 @@ export const RoyaltyDetails = ({ onChange }: RoyaltyDetailsProps) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [royaltyState, royaltyPaymentAddressState.value, royaltyShareState.value])
useEffect(() => {
if (importedRoyaltyDetails) {
setRoyaltyState(importedRoyaltyDetails.royaltyType)
royaltyPaymentAddressState.onChange(importedRoyaltyDetails.paymentAddress)
royaltyShareState.onChange(importedRoyaltyDetails.share.toString())
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [importedRoyaltyDetails])
return (
<div className="py-3 px-8 mx-10 rounded border-2 border-white/20">
<div className="flex justify-center">