diff --git a/.env.example b/.env.example index 7e1aada..cdedc47 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -APP_VERSION=0.6.0 +APP_VERSION=0.6.1 NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS NEXT_PUBLIC_SG721_CODE_ID=2092 diff --git a/components/LogModal.tsx b/components/LogModal.tsx new file mode 100644 index 0000000..ae56680 --- /dev/null +++ b/components/LogModal.tsx @@ -0,0 +1,155 @@ +import { useLogStore } from 'contexts/log' +import { useRef, useState } from 'react' +import { FaCopy, FaEraser } from 'react-icons/fa' +import { copy } from 'utils/clipboard' + +import type { LogItem } from '../contexts/log' +import { removeLogItem, setLogItemList } from '../contexts/log' +import { Button } from './Button' +import { Tooltip } from './Tooltip' + +export interface LogModalProps { + tempLogItem?: LogItem +} +export const LogModal = (props: LogModalProps) => { + const logs = useLogStore() + const [isChecked, setIsChecked] = useState(false) + + const checkBoxRef = useRef(null) + + const handleCheckBox = () => { + checkBoxRef.current?.click() + } + + return ( +
+ + +
+ ) +} diff --git a/components/Sidebar.tsx b/components/Sidebar.tsx index cde52fc..a98685d 100644 --- a/components/Sidebar.tsx +++ b/components/Sidebar.tsx @@ -3,21 +3,36 @@ import clsx from 'clsx' import { Anchor } from 'components/Anchor' +import { setLogItemList, useLogStore } from 'contexts/log' import { useWallet } from 'contexts/wallet' import Link from 'next/link' import { useRouter } from 'next/router' +import { useEffect } from 'react' // import BrandText from 'public/brand/brand-text.svg' import { footerLinks, socialsLinks } from 'utils/links' import { BADGE_HUB_ADDRESS, BASE_FACTORY_ADDRESS, NETWORK } from '../utils/constants' import { Conditional } from './Conditional' import { IncomeDashboardDisclaimer } from './IncomeDashboardDisclaimer' +import { LogModal } from './LogModal' import { SidebarLayout } from './SidebarLayout' import { WalletLoader } from './WalletLoader' export const Sidebar = () => { const router = useRouter() const wallet = useWallet() + const logs = useLogStore() + + useEffect(() => { + if (logs.itemList.length === 0) return + console.log('Stringified log item list: ', JSON.stringify(logs.itemList)) + window.localStorage.setItem('logs', JSON.stringify(logs.itemList)) + }, [logs]) + + useEffect(() => { + console.log(window.localStorage.getItem('logs')) + setLogItemList(JSON.parse(window.localStorage.getItem('logs') || '[]')) + }, []) return ( @@ -25,7 +40,6 @@ export const Sidebar = () => { [e.preventDefault(), router.push('/brand')]}> Brand Text - {/* wallet button */} {/* main navigation routes */} @@ -205,9 +219,17 @@ export const Sidebar = () => { +
- + {logs.itemList.length > 0 && ( + + )} {/* Stargaze network status */}
Network: {wallet.network}
diff --git a/components/collections/creation/CollectionDetails.tsx b/components/collections/creation/CollectionDetails.tsx index 17dd8b7..629cbff 100644 --- a/components/collections/creation/CollectionDetails.tsx +++ b/components/collections/creation/CollectionDetails.tsx @@ -10,10 +10,12 @@ import { FormGroup } from 'components/FormGroup' import { useInputState } from 'components/forms/FormInput.hooks' import { InputDateTime } from 'components/InputDateTime' import { Tooltip } from 'components/Tooltip' +import { addLogItem } from 'contexts/log' import type { ChangeEvent } from 'react' import { useEffect, useRef, useState } from 'react' import { toast } from 'react-hot-toast' import { SG721_UPDATABLE_CODE_ID } from 'utils/constants' +import { uid } from 'utils/random' import { TextInput } from '../../forms/FormInput' import type { MinterType } from '../actions/Combobox' @@ -89,6 +91,7 @@ export const CollectionDetails = ({ onChange, uploadMethod, coverImageUrl, minte // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [ diff --git a/components/collections/creation/UploadDetails.tsx b/components/collections/creation/UploadDetails.tsx index d6ce63a..e6b0f4c 100644 --- a/components/collections/creation/UploadDetails.tsx +++ b/components/collections/creation/UploadDetails.tsx @@ -13,10 +13,12 @@ import { useInputState } from 'components/forms/FormInput.hooks' import { MetadataInput } from 'components/MetadataInput' import { MetadataModal } from 'components/MetadataModal' import { SingleAssetPreview } from 'components/SingleAssetPreview' +import { addLogItem } from 'contexts/log' import type { ChangeEvent } from 'react' import { useEffect, useRef, useState } from 'react' import { toast } from 'react-hot-toast' import type { UploadServiceType } from 'services/upload' +import { uid } from 'utils/random' import { naturalCompare } from 'utils/sort' import type { MinterType } from '../actions/Combobox' @@ -106,6 +108,12 @@ export const UploadDetails = ({ onChange, minterType, baseMinterAcquisitionMetho for (let i = 0; i < sortedFileNames.length; i++) { if (isNaN(Number(sortedFileNames[i])) || parseInt(sortedFileNames[i]) !== i + 1) { toast.error('The file names should be in numerical order starting from 1.') + addLogItem({ + id: uid(), + message: 'The file names should be in numerical order starting from 1.', + type: 'Error', + timestamp: new Date(), + }) //clear the input event.target.value = '' return @@ -152,6 +160,12 @@ export const UploadDetails = ({ onChange, minterType, baseMinterAcquisitionMetho for (let i = 0; i < sortedFileNames.length; i++) { if (isNaN(Number(sortedFileNames[i])) || parseInt(sortedFileNames[i]) !== i + 1) { toast.error('The file names should be in numerical order starting from 1.') + addLogItem({ + id: uid(), + message: 'The file names should be in numerical order starting from 1.', + type: 'Error', + timestamp: new Date(), + }) event.target.value = '' return } @@ -174,9 +188,10 @@ export const UploadDetails = ({ onChange, minterType, baseMinterAcquisitionMetho setMetadataFilesArray([]) return toast.error(`Invalid metadata file: ${metadataFile.name}`) } - } catch (error) { + } catch (error: any) { event.target.value = '' setMetadataFilesArray([]) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) return toast.error(`Invalid metadata file: ${metadataFile.name}`) } } @@ -237,6 +252,7 @@ export const UploadDetails = ({ onChange, minterType, baseMinterAcquisitionMetho onChange(data) } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) } }, [ assetFilesArray, diff --git a/contexts/log.ts b/contexts/log.ts new file mode 100644 index 0000000..cc91f5d --- /dev/null +++ b/contexts/log.ts @@ -0,0 +1,27 @@ +import create from 'zustand' + +export interface LogItem { + id: string + message: string + type?: string + timestamp?: Date + code?: number + source?: string + connectedWallet?: string +} + +export const useLogStore = create(() => ({ + itemList: [] as LogItem[], +})) + +export const setLogItemList = (list: LogItem[]) => { + useLogStore.setState({ itemList: list }) +} + +export const addLogItem = (item: LogItem) => { + useLogStore.setState((prev) => ({ itemList: [...prev.itemList, item] })) +} + +export const removeLogItem = (id: string) => { + useLogStore.setState((prev) => ({ itemList: prev.itemList.filter((item) => item.id !== id) })) +} diff --git a/package.json b/package.json index 867358b..3bdcb91 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stargaze-studio", - "version": "0.6.0", + "version": "0.6.1", "workspaces": [ "packages/*" ], diff --git a/pages/badges/create.tsx b/pages/badges/create.tsx index 8abd492..1c9f41e 100644 --- a/pages/badges/create.tsx +++ b/pages/badges/create.tsx @@ -22,6 +22,7 @@ import { TextInput } from 'components/forms/FormInput' import { useInputState } from 'components/forms/FormInput.hooks' import { Tooltip } from 'components/Tooltip' import { useContracts } from 'contexts/contracts' +import { addLogItem } from 'contexts/log' import { useWallet } from 'contexts/wallet' import type { Badge } from 'contracts/badgeHub' import type { DispatchExecuteArgs as BadgeHubDispatchExecuteArgs } from 'contracts/badgeHub/messages/execute' @@ -41,6 +42,7 @@ import { copy } from 'utils/clipboard' import { BADGE_HUB_ADDRESS, BLOCK_EXPLORER_URL, NETWORK } from 'utils/constants' import { withMetadata } from 'utils/layout' import { links } from 'utils/links' +import { uid } from 'utils/random' import { resolveAddress } from 'utils/resolveAddress' import { truncateMiddle } from 'utils/text' @@ -97,6 +99,7 @@ const BadgeCreationPage: NextPage = () => { }, 100) } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) setReadyToCreateBadge(false) } @@ -127,6 +130,7 @@ const BadgeCreationPage: NextPage = () => { return imageUploadDetails?.imageUrl as string } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setCreatingBadge(false) setUploading(false) throw new Error("Couldn't upload the image.") @@ -252,13 +256,15 @@ const BadgeCreationPage: NextPage = () => { }) .catch((error: { message: any }) => { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) setIsAddingKeysComplete(false) setCreatingBadge(false) }) } - } catch (err: any) { - toast.error(err.message, { style: { maxWidth: 'none' } }) + } catch (error: any) { + toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setCreatingBadge(false) setUploading(false) } @@ -296,6 +302,12 @@ const BadgeCreationPage: NextPage = () => { const url = new URL(badgeDetails.external_url) } catch (e: any) { throw new Error(`Invalid external url: Make sure to include the protocol (e.g. https://)`) + addLogItem({ + id: uid(), + message: 'Invalid external url: Make sure to include the protocol (e.g. https://)', + type: 'Error', + timestamp: new Date(), + }) } } } diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx index f0c1cc9..5d45845 100644 --- a/pages/collections/create.tsx +++ b/pages/collections/create.tsx @@ -29,6 +29,7 @@ import type { WhitelistDetailsDataProps } from 'components/collections/creation/ import { Conditional } from 'components/Conditional' import { LoadingModal } from 'components/LoadingModal' import { useContracts } from 'contexts/contracts' +import { addLogItem } from 'contexts/log' import { useWallet } from 'contexts/wallet' import type { DispatchExecuteArgs as BaseFactoryDispatchExecuteArgs } from 'contracts/baseFactory/messages/execute' import { dispatchExecute as baseFactoryDispatchExecute } from 'contracts/baseFactory/messages/execute' @@ -56,6 +57,7 @@ import { } from 'utils/constants' import { withMetadata } from 'utils/layout' import { links } from 'utils/links' +import { uid } from 'utils/random' import type { MinterType } from '../../components/collections/actions/Combobox' import type { UploadMethod } from '../../components/collections/creation/UploadDetails' @@ -127,19 +129,25 @@ const CollectionCreationPage: NextPage = () => { checkwalletBalance() setReadyToCreateVm(true) }) - .catch((err) => { - if (String(err.message).includes('Insufficient wallet balance')) - toast.error(`${err.message}`, { style: { maxWidth: 'none' } }) - else toast.error(`Error in Whitelist Configuration: ${err.message}`, { style: { maxWidth: 'none' } }) + .catch((error) => { + if (String(error.message).includes('Insufficient wallet balance')) { + toast.error(`${error.message}`, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) + } else { + toast.error(`Error in Whitelist Configuration: ${error.message}`, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) + } setReadyToCreateVm(false) }) }) - .catch((err) => { - toast.error(`Error in Royalty Details: ${err.message}`, { style: { maxWidth: 'none' } }) + .catch((error) => { + toast.error(`Error in Royalty Details: ${error.message}`, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setReadyToCreateVm(false) }) } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) setReadyToCreateVm(false) } @@ -157,17 +165,20 @@ const CollectionCreationPage: NextPage = () => { checkwalletBalance() setReadyToCreateBm(true) }) - .catch((err) => { - toast.error(`${err.message}`, { style: { maxWidth: 'none' } }) + .catch((error) => { + toast.error(`${error.message}`, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setReadyToCreateBm(false) }) }) - .catch((err) => { - toast.error(`Error in Royalty Configuration: ${err.message}`, { style: { maxWidth: 'none' } }) + .catch((error) => { + toast.error(`Error in Royalty Configuration: ${error.message}`, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setReadyToCreateBm(false) }) } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) } } @@ -180,12 +191,14 @@ const CollectionCreationPage: NextPage = () => { .then(() => { setReadyToUploadAndMint(true) }) - .catch((err) => { - toast.error(`${err.message}`, { style: { maxWidth: 'none' } }) + .catch((error) => { + toast.error(`${error.message}`, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setReadyToUploadAndMint(false) }) } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) } } @@ -245,6 +258,7 @@ const CollectionCreationPage: NextPage = () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' }, duration: 10000 }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setCreatingCollection(false) setUploading(false) } @@ -307,6 +321,7 @@ const CollectionCreationPage: NextPage = () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' }, duration: 10000 }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setCreatingCollection(false) setUploading(false) } @@ -367,6 +382,7 @@ const CollectionCreationPage: NextPage = () => { }) .catch((error) => { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) setCreatingCollection(false) setIsMintingComplete(false) @@ -388,6 +404,7 @@ const CollectionCreationPage: NextPage = () => { }) .catch((error) => { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) setCreatingCollection(false) }) @@ -396,6 +413,7 @@ const CollectionCreationPage: NextPage = () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setCreatingCollection(false) setUploading(false) } @@ -583,6 +601,7 @@ const CollectionCreationPage: NextPage = () => { ) .catch((error) => { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) setIsMintingComplete(false) setCreatingCollection(false) @@ -607,6 +626,7 @@ const CollectionCreationPage: NextPage = () => { ) .catch((error) => { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) setIsMintingComplete(false) setCreatingCollection(false) @@ -617,6 +637,7 @@ const CollectionCreationPage: NextPage = () => { }) .catch((error) => { toast.error(error.message, { style: { maxWidth: 'none' } }) + addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) setUploading(false) setCreatingCollection(false) })