From 3621734ededdd9a8dfa92aa21e40cb1ef04d4d51 Mon Sep 17 00:00:00 2001 From: Johnny D Date: Tue, 12 Sep 2023 15:25:11 +1000 Subject: [PATCH 1/9] Improve launch NFT collection tx UI --- .../RewardsList/AddEditRewardModal.tsx | 7 ++- ...sModal.tsx => TransactionSuccessModal.tsx} | 16 +++---- .../ReviewConfirmModal/ReviewConfirmModal.tsx | 17 ++++++- .../LaunchNftCollection/EnableNftsModal.tsx | 3 -- .../UploadAndLaunchNftsButton.tsx | 44 +++++++++++++++---- .../hooks/useReconfigureFundingCycle.ts | 19 +++++++- src/locales/messages.pot | 6 +++ 7 files changed, 84 insertions(+), 28 deletions(-) rename src/components/v2v3/V2V3Project/V2V3ProjectSettings/{pages/NewEditCyclePage/ReviewConfirmModal/EditCycleSuccessModal.tsx => TransactionSuccessModal.tsx} (80%) diff --git a/src/components/Create/components/RewardsList/AddEditRewardModal.tsx b/src/components/Create/components/RewardsList/AddEditRewardModal.tsx index 9070bedd72..743dd0b64b 100644 --- a/src/components/Create/components/RewardsList/AddEditRewardModal.tsx +++ b/src/components/Create/components/RewardsList/AddEditRewardModal.tsx @@ -41,7 +41,12 @@ interface AddEditRewardModalFormProps { externalUrl?: string | undefined } -const NFT_FILE_UPLOAD_EXTRA = t`Images will be cropped to a 1:1 square in thumbnail previews on the Juicebox app.` +const NFT_FILE_UPLOAD_EXTRA = ( + + Images will be cropped to a 1:1 square in thumbnail previews on the Juicebox + app. + +) const MAX_NFT_FILE_SIZE_MB = 100 // This assumes an existing NFT ID (from the contracts) will never be >= 1000000 diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditCyclePage/ReviewConfirmModal/EditCycleSuccessModal.tsx b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/TransactionSuccessModal.tsx similarity index 80% rename from src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditCyclePage/ReviewConfirmModal/EditCycleSuccessModal.tsx rename to src/components/v2v3/V2V3Project/V2V3ProjectSettings/TransactionSuccessModal.tsx index be82f46cb7..697e312cac 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditCyclePage/ReviewConfirmModal/EditCycleSuccessModal.tsx +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/TransactionSuccessModal.tsx @@ -4,15 +4,17 @@ import { Button, Modal } from 'antd' import { ProjectMetadataContext } from 'contexts/shared/ProjectMetadataContext' import { V2V3ProjectContext } from 'contexts/v2v3/Project/V2V3ProjectContext' import Link from 'next/link' -import { useContext } from 'react' +import { ReactNode, useContext } from 'react' import { settingsPagePath, v2v3ProjectRoute } from 'utils/routes' -export function EditCycleSuccessModal({ +export function TransactionSuccessModal({ open, onClose, + content, }: { open: boolean onClose: VoidFunction + content: ReactNode }) { const { projectId } = useContext(ProjectMetadataContext) const { handle } = useContext(V2V3ProjectContext) @@ -35,15 +37,7 @@ export function EditCycleSuccessModal({ >
{checkIconWithBackground} -
- Your updated cycle has been deployed -
-
- - Changes will take effect in your next cycle as long as it starts - after your edit deadline. - -
+ {content}
+ <> + + + setSuccessModalOpen(false)} + content={ + <> +
+ Your new NFTs have been deployed +
+
+ + New NFTs will be available in your next cycle as long as it + starts after your edit deadline. + +
+ + } + /> + ) } diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle.ts index d1ced0c89a..8c098da370 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle.ts +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle.ts @@ -60,6 +60,7 @@ export const useReconfigureFundingCycle = ({ const [reconfigureTxLoading, setReconfigureTxLoading] = useState(false) + const [txPending, setTxPending] = useState(false) const reconfigureV2V3FundingCycleTx = useReconfigureV2V3FundingCycleTx() const reconfigureV2V3FundingCycleWithNftsTx = @@ -120,6 +121,9 @@ export const useReconfigureFundingCycle = ({ } const txOpts = { + onDone() { + setTxPending(true) + }, async onConfirmed() { if (projectId) { await revalidateProject({ @@ -128,14 +132,20 @@ export const useReconfigureFundingCycle = ({ }) } setReconfigureTxLoading(false) + setTxPending(false) if (onComplete) { onComplete() } else { reloadWindow() } }, + onCancelled() { + setTxPending(false) + }, + onError() { + setTxPending(false) + }, } - let txSuccessful: boolean if (launchedNewNfts && editingNftRewards?.rewardTiers) { txSuccessful = await reconfigureV2V3FundingCycleWithNftsTx( @@ -154,6 +164,7 @@ export const useReconfigureFundingCycle = ({ if (!txSuccessful) { setReconfigureTxLoading(false) + setTxPending(false) } }, [ @@ -169,5 +180,9 @@ export const useReconfigureFundingCycle = ({ ], ) - return { reconfigureLoading: reconfigureTxLoading, reconfigureFundingCycle } + return { + reconfigureLoading: reconfigureTxLoading, + reconfigureFundingCycle, + txPending, + } } diff --git a/src/locales/messages.pot b/src/locales/messages.pot index 60d8f2429a..e0a8889dfb 100644 --- a/src/locales/messages.pot +++ b/src/locales/messages.pot @@ -782,6 +782,9 @@ msgstr "" msgid "Receive ERC-20 tokens" msgstr "" +msgid "New NFTs will be available in your next cycle as long as it starts after your edit deadline." +msgstr "" + msgid "Confirm" msgstr "" @@ -4424,6 +4427,9 @@ msgstr "" msgid "Add recipient" msgstr "" +msgid "Your new NFTs have been deployed" +msgstr "" + msgid "Your balance" msgstr "" From 2b5e79dc7f367954c751cce8b92b70dc5588501d Mon Sep 17 00:00:00 2001 From: Johnny D Date: Wed, 13 Sep 2023 20:56:58 +1000 Subject: [PATCH 2/9] [PREVIEW] Better organise settings and create flow instances of the NFT form and related components --- src/components/Create/Create.tsx | 4 +- .../pages/NftRewards/NftRewardsPage.tsx | 27 ++++ .../pages/NftRewards/hooks/index.ts | 2 +- ...Form.ts => useCreateFlowNftRewardsForm.ts} | 16 +-- .../components/pages/NftRewards/index.ts | 2 +- .../RewardsReview/RewardsReview.tsx | 2 +- .../AddNftCollectionForm.tsx | 50 +++---- .../NftAdvancedFormItems.tsx | 0 .../NftPaymentSuccessFormItems.tsx | 0 .../NftRewards/AddNftCollectionForm/index.ts | 1 + .../RewardImage/RewardImage.tsx | 0 .../RewardImage/index.ts | 0 .../RewardsList/AddEditRewardModal.tsx | 4 +- .../RewardsList/RewardItem.tsx | 0 .../RewardsList/RewardItemButton.tsx | 0 .../RewardsList/RewardsList.tsx | 0 .../RewardsList/hooks/index.ts | 0 .../RewardsList/hooks/useRewards.ts | 0 .../RewardsList/index.ts | 0 src/components/inputs/UploadNoStyle.tsx | 2 +- .../hooks/useUpdateCurrentCollection.ts | 2 +- .../LaunchNftsCollection.tsx | 47 ++++++- .../UploadAndLaunchNftsButton.tsx | 122 ++---------------- .../hooks/useSettingsLaunchNftsForm.ts | 117 +++++++++++++++++ .../EditNftsPostPaySection.tsx | 2 +- .../UpdateNftsPage/EditNftsSection.tsx | 2 +- .../AddNftsSection/AddNftsSection.tsx | 2 +- 27 files changed, 242 insertions(+), 162 deletions(-) create mode 100644 src/components/Create/components/pages/NftRewards/NftRewardsPage.tsx rename src/components/Create/components/pages/NftRewards/hooks/{useNftRewardsForm.ts => useCreateFlowNftRewardsForm.ts} (94%) rename src/components/{Create/components/pages/NftRewards => NftRewards/AddNftCollectionForm}/AddNftCollectionForm.tsx (85%) rename src/components/{Create/components/pages/NftRewards => NftRewards/AddNftCollectionForm}/NftAdvancedFormItems.tsx (100%) rename src/components/{Create/components/pages/NftRewards => NftRewards/AddNftCollectionForm}/NftPaymentSuccessFormItems.tsx (100%) create mode 100644 src/components/NftRewards/AddNftCollectionForm/index.ts rename src/components/{Create/components => NftRewards}/RewardImage/RewardImage.tsx (100%) rename src/components/{Create/components => NftRewards}/RewardImage/index.ts (100%) rename src/components/{Create/components => NftRewards}/RewardsList/AddEditRewardModal.tsx (98%) rename src/components/{Create/components => NftRewards}/RewardsList/RewardItem.tsx (100%) rename src/components/{Create/components => NftRewards}/RewardsList/RewardItemButton.tsx (100%) rename src/components/{Create/components => NftRewards}/RewardsList/RewardsList.tsx (100%) rename src/components/{Create/components => NftRewards}/RewardsList/hooks/index.ts (100%) rename src/components/{Create/components => NftRewards}/RewardsList/hooks/useRewards.ts (100%) rename src/components/{Create/components => NftRewards}/RewardsList/index.ts (100%) create mode 100644 src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/hooks/useSettingsLaunchNftsForm.ts diff --git a/src/components/Create/Create.tsx b/src/components/Create/Create.tsx index b778396280..1741f23c2c 100644 --- a/src/components/Create/Create.tsx +++ b/src/components/Create/Create.tsx @@ -12,8 +12,8 @@ import { NetworkName } from 'models/networkName' import Link from 'next/link' import { useRouter } from 'next/router' import { - AddNftCollectionForm, FundingCyclesPage, + NftRewardsPage, ProjectDetailsPage, ProjectTokenPage, ReconfigurationRulesPage, @@ -124,7 +124,7 @@ export function Create() { Reward your supporters with custom NFTs. } > - + } + onFinish={() => { + goToNextPage?.() + trackFathomGoal(CREATE_FLOW.NFT_NEXT_CTA) + }} + /> + ) +} diff --git a/src/components/Create/components/pages/NftRewards/hooks/index.ts b/src/components/Create/components/pages/NftRewards/hooks/index.ts index 1dcc1c7bce..37bd0f823b 100644 --- a/src/components/Create/components/pages/NftRewards/hooks/index.ts +++ b/src/components/Create/components/pages/NftRewards/hooks/index.ts @@ -1 +1 @@ -export * from './useNftRewardsForm' +export * from './useCreateFlowNftRewardsForm' diff --git a/src/components/Create/components/pages/NftRewards/hooks/useNftRewardsForm.ts b/src/components/Create/components/pages/NftRewards/hooks/useCreateFlowNftRewardsForm.ts similarity index 94% rename from src/components/Create/components/pages/NftRewards/hooks/useNftRewardsForm.ts rename to src/components/Create/components/pages/NftRewards/hooks/useCreateFlowNftRewardsForm.ts index 26cdf48f31..fec7d5b4c8 100644 --- a/src/components/Create/components/pages/NftRewards/hooks/useNftRewardsForm.ts +++ b/src/components/Create/components/pages/NftRewards/hooks/useCreateFlowNftRewardsForm.ts @@ -1,4 +1,5 @@ import { Form } from 'antd' +import { NftRewardsFormProps } from 'components/NftRewards/AddNftCollectionForm' import { JB721GovernanceType, NftRewardTier } from 'models/nftRewards' import { useEffect, useMemo } from 'react' import { useAppDispatch } from 'redux/hooks/useAppDispatch' @@ -11,20 +12,7 @@ import { } from 'utils/nftRewards' import { useFormDispatchWatch } from '../../hooks' -type NftRewardsFormProps = Partial<{ - rewards: NftRewardTier[] - collectionName?: string - collectionSymbol?: string - collectionDescription?: string - postPayMessage?: string - postPayButtonText?: string - postPayButtonLink?: string - onChainGovernance: JB721GovernanceType - useDataSourceForRedeem: boolean - preventOverspending: boolean -}> - -export const useNftRewardsForm = () => { +export const useCreateFlowNftRewardsForm = () => { const [form] = Form.useForm() const { collectionMetadata, diff --git a/src/components/Create/components/pages/NftRewards/index.ts b/src/components/Create/components/pages/NftRewards/index.ts index b915789057..5f5f642e3c 100644 --- a/src/components/Create/components/pages/NftRewards/index.ts +++ b/src/components/Create/components/pages/NftRewards/index.ts @@ -1 +1 @@ -export * from './AddNftCollectionForm' +export * from './NftRewardsPage' diff --git a/src/components/Create/components/pages/ReviewDeploy/components/RewardsReview/RewardsReview.tsx b/src/components/Create/components/pages/ReviewDeploy/components/RewardsReview/RewardsReview.tsx index fbd87faea0..c4da2e5f59 100644 --- a/src/components/Create/components/pages/ReviewDeploy/components/RewardsReview/RewardsReview.tsx +++ b/src/components/Create/components/pages/ReviewDeploy/components/RewardsReview/RewardsReview.tsx @@ -1,5 +1,5 @@ import { t } from '@lingui/macro' -import { RewardsList } from 'components/Create/components/RewardsList' +import { RewardsList } from 'components/NftRewards/RewardsList' import { JB721GovernanceType, NftRewardTier } from 'models/nftRewards' import { useCallback, useMemo } from 'react' import { useAppDispatch } from 'redux/hooks/useAppDispatch' diff --git a/src/components/Create/components/pages/NftRewards/AddNftCollectionForm.tsx b/src/components/NftRewards/AddNftCollectionForm/AddNftCollectionForm.tsx similarity index 85% rename from src/components/Create/components/pages/NftRewards/AddNftCollectionForm.tsx rename to src/components/NftRewards/AddNftCollectionForm/AddNftCollectionForm.tsx index 1072a651c6..8d36c7f874 100644 --- a/src/components/Create/components/pages/NftRewards/AddNftCollectionForm.tsx +++ b/src/components/NftRewards/AddNftCollectionForm/AddNftCollectionForm.tsx @@ -1,37 +1,46 @@ import { RightOutlined } from '@ant-design/icons' import { Trans, t } from '@lingui/macro' -import { Form, Radio } from 'antd' +import { Form, FormInstance, Radio } from 'antd' import { useLockPageRulesWrapper } from 'components/Create/hooks/useLockPageRulesWrapper' import ExternalLink from 'components/ExternalLink' import TooltipLabel from 'components/TooltipLabel' import { JuiceInput } from 'components/inputs/JuiceTextInput' import { RadioItem } from 'components/inputs/RadioItem' -import { CREATE_FLOW } from 'constants/fathomEvents' -import { trackFathomGoal } from 'lib/fathom' -import { JB721GovernanceType } from 'models/nftRewards' -import { useContext } from 'react' -import { useSetCreateFurthestPageReached } from 'redux/hooks/useEditingCreateFurthestPageReached' +import { JB721GovernanceType, NftRewardTier } from 'models/nftRewards' import { inputMustExistRule } from 'utils/antdRules' import { helpPagePath } from 'utils/routes' -import { CreateBadge } from '../../CreateBadge' -import { CreateCollapse } from '../../CreateCollapse' -import { OptionalHeader } from '../../OptionalHeader' -import { RewardsList } from '../../RewardsList' -import { Wizard } from '../../Wizard' -import { PageContext } from '../../Wizard/contexts/PageContext' +import { CreateBadge } from '../../Create/components/CreateBadge' +import { CreateCollapse } from '../../Create/components/CreateCollapse' +import { OptionalHeader } from '../../Create/components/OptionalHeader' +import { RewardsList } from '../RewardsList' import { NftAdvancedFormItems } from './NftAdvancedFormItems' import { NftPaymentSuccessFormItems } from './NftPaymentSuccessFormItems' -import { useNftRewardsForm } from './hooks' + +export type NftRewardsFormProps = Partial<{ + rewards: NftRewardTier[] + collectionName?: string + collectionSymbol?: string + collectionDescription?: string + postPayMessage?: string + postPayButtonText?: string + postPayButtonLink?: string + onChainGovernance: JB721GovernanceType + useDataSourceForRedeem: boolean + preventOverspending: boolean +}> export const AddNftCollectionForm = ({ + form, + initialValues, okButton, + onFinish, }: { - okButton?: React.ReactNode + form: FormInstance + initialValues?: NftRewardsFormProps + okButton: React.ReactNode + onFinish?: VoidFunction }) => { - useSetCreateFurthestPageReached('nftRewards') - const { form, initialValues } = useNftRewardsForm() const lockPageRulesWrapper = useLockPageRulesWrapper() - const { goToNextPage } = useContext(PageContext) const hasNfts = !!Form.useWatch('rewards', form)?.length @@ -43,10 +52,7 @@ export const AddNftCollectionForm = ({ name="fundingCycles" colon={false} layout="vertical" - onFinish={() => { - goToNextPage?.() - trackFathomGoal(CREATE_FLOW.NFT_NEXT_CTA) - }} + onFinish={onFinish} scrollToFirstError >
@@ -171,7 +177,7 @@ export const AddNftCollectionForm = ({
)}
- {okButton ?? } + {okButton}
diff --git a/src/components/Create/components/pages/NftRewards/NftAdvancedFormItems.tsx b/src/components/NftRewards/AddNftCollectionForm/NftAdvancedFormItems.tsx similarity index 100% rename from src/components/Create/components/pages/NftRewards/NftAdvancedFormItems.tsx rename to src/components/NftRewards/AddNftCollectionForm/NftAdvancedFormItems.tsx diff --git a/src/components/Create/components/pages/NftRewards/NftPaymentSuccessFormItems.tsx b/src/components/NftRewards/AddNftCollectionForm/NftPaymentSuccessFormItems.tsx similarity index 100% rename from src/components/Create/components/pages/NftRewards/NftPaymentSuccessFormItems.tsx rename to src/components/NftRewards/AddNftCollectionForm/NftPaymentSuccessFormItems.tsx diff --git a/src/components/NftRewards/AddNftCollectionForm/index.ts b/src/components/NftRewards/AddNftCollectionForm/index.ts new file mode 100644 index 0000000000..b915789057 --- /dev/null +++ b/src/components/NftRewards/AddNftCollectionForm/index.ts @@ -0,0 +1 @@ +export * from './AddNftCollectionForm' diff --git a/src/components/Create/components/RewardImage/RewardImage.tsx b/src/components/NftRewards/RewardImage/RewardImage.tsx similarity index 100% rename from src/components/Create/components/RewardImage/RewardImage.tsx rename to src/components/NftRewards/RewardImage/RewardImage.tsx diff --git a/src/components/Create/components/RewardImage/index.ts b/src/components/NftRewards/RewardImage/index.ts similarity index 100% rename from src/components/Create/components/RewardImage/index.ts rename to src/components/NftRewards/RewardImage/index.ts diff --git a/src/components/Create/components/RewardsList/AddEditRewardModal.tsx b/src/components/NftRewards/RewardsList/AddEditRewardModal.tsx similarity index 98% rename from src/components/Create/components/RewardsList/AddEditRewardModal.tsx rename to src/components/NftRewards/RewardsList/AddEditRewardModal.tsx index 743dd0b64b..008cae951b 100644 --- a/src/components/Create/components/RewardsList/AddEditRewardModal.tsx +++ b/src/components/NftRewards/RewardsList/AddEditRewardModal.tsx @@ -26,8 +26,8 @@ import { } from 'utils/antdRules' import { withHttps } from 'utils/externalLink' import { ipfsGatewayUrl } from 'utils/ipfs' -import { CreateCollapse } from '../CreateCollapse' -import { OptionalHeader } from '../OptionalHeader' +import { CreateCollapse } from '../../Create/components/CreateCollapse' +import { OptionalHeader } from '../../Create/components/OptionalHeader' interface AddEditRewardModalFormProps { fileUrl: string diff --git a/src/components/Create/components/RewardsList/RewardItem.tsx b/src/components/NftRewards/RewardsList/RewardItem.tsx similarity index 100% rename from src/components/Create/components/RewardsList/RewardItem.tsx rename to src/components/NftRewards/RewardsList/RewardItem.tsx diff --git a/src/components/Create/components/RewardsList/RewardItemButton.tsx b/src/components/NftRewards/RewardsList/RewardItemButton.tsx similarity index 100% rename from src/components/Create/components/RewardsList/RewardItemButton.tsx rename to src/components/NftRewards/RewardsList/RewardItemButton.tsx diff --git a/src/components/Create/components/RewardsList/RewardsList.tsx b/src/components/NftRewards/RewardsList/RewardsList.tsx similarity index 100% rename from src/components/Create/components/RewardsList/RewardsList.tsx rename to src/components/NftRewards/RewardsList/RewardsList.tsx diff --git a/src/components/Create/components/RewardsList/hooks/index.ts b/src/components/NftRewards/RewardsList/hooks/index.ts similarity index 100% rename from src/components/Create/components/RewardsList/hooks/index.ts rename to src/components/NftRewards/RewardsList/hooks/index.ts diff --git a/src/components/Create/components/RewardsList/hooks/useRewards.ts b/src/components/NftRewards/RewardsList/hooks/useRewards.ts similarity index 100% rename from src/components/Create/components/RewardsList/hooks/useRewards.ts rename to src/components/NftRewards/RewardsList/hooks/useRewards.ts diff --git a/src/components/Create/components/RewardsList/index.ts b/src/components/NftRewards/RewardsList/index.ts similarity index 100% rename from src/components/Create/components/RewardsList/index.ts rename to src/components/NftRewards/RewardsList/index.ts diff --git a/src/components/inputs/UploadNoStyle.tsx b/src/components/inputs/UploadNoStyle.tsx index 4e60618bb4..c4f45019cb 100644 --- a/src/components/inputs/UploadNoStyle.tsx +++ b/src/components/inputs/UploadNoStyle.tsx @@ -2,9 +2,9 @@ import { CloseCircleFilled, UploadOutlined } from '@ant-design/icons' import { Trans, t } from '@lingui/macro' import { Progress, Upload, UploadProps } from 'antd' import { RcFile } from 'antd/lib/upload' -import { RewardImage } from 'components/Create/components/RewardImage' import { JuiceVideoPreview } from 'components/JuiceVideo/JuiceVideoPreview' import Loading from 'components/Loading' +import { RewardImage } from 'components/NftRewards/RewardImage' import { CreateButton } from 'components/buttons/CreateButton' import { useContentType } from 'hooks/useContentType' import { FormItemInput } from 'models/formItemInput' diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/EditNftsPage/hooks/useUpdateCurrentCollection.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/EditNftsPage/hooks/useUpdateCurrentCollection.ts index 42c2bba8ea..97bc941949 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/EditNftsPage/hooks/useUpdateCurrentCollection.ts +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/EditNftsPage/hooks/useUpdateCurrentCollection.ts @@ -1,5 +1,5 @@ import { t } from '@lingui/macro' -import { NEW_NFT_ID_LOWER_LIMIT } from 'components/Create/components/RewardsList/AddEditRewardModal' +import { NEW_NFT_ID_LOWER_LIMIT } from 'components/NftRewards/RewardsList/AddEditRewardModal' import { JB721DelegateContractsContext } from 'contexts/NftRewards/JB721DelegateContracts/JB721DelegateContractsContext' import { useAdjustTiersTx } from 'hooks/JB721Delegate/transactor/useAdjustTiersTx' import { NftRewardTier } from 'models/nftRewards' diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/LaunchNftsCollection.tsx b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/LaunchNftsCollection.tsx index ca5c19c30e..cfcf1b9fee 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/LaunchNftsCollection.tsx +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/LaunchNftsCollection.tsx @@ -1,10 +1,49 @@ -import { AddNftCollectionForm } from 'components/Create/components' +import { Trans } from '@lingui/macro' +import { AddNftCollectionForm } from 'components/NftRewards/AddNftCollectionForm' +import TransactionModal from 'components/modals/TransactionModal' +import { TransactionSuccessModal } from '../../../TransactionSuccessModal' import { UploadAndLaunchNftsButton } from './UploadAndLaunchNftsButton' +import { useSettingsLaunchNftsForm } from './hooks/useSettingsLaunchNftsForm' export function LaunchNftsPage() { + const { + form, + launchCollection, + launchButtonLoading, + launchTxPending, + successModalOpen, + setSuccessModalOpen, + } = useSettingsLaunchNftsForm() return ( - } - /> + <> + launchCollection} + loading={launchButtonLoading} + /> + } + /> + + setSuccessModalOpen(false)} + content={ + <> +
+ Your new NFTs have been deployed +
+
+ + New NFTs will be available in your next cycle as long as it + starts after your edit deadline. + +
+ + } + /> + ) } diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/UploadAndLaunchNftsButton.tsx b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/UploadAndLaunchNftsButton.tsx index deefc155f7..059d9c32b1 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/UploadAndLaunchNftsButton.tsx +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/UploadAndLaunchNftsButton.tsx @@ -1,121 +1,23 @@ import { Trans } from '@lingui/macro' import { Button } from 'antd' -import TransactionModal from 'components/modals/TransactionModal' -import { useState } from 'react' -import { useAppSelector } from 'redux/hooks/useAppSelector' -import { pinNftCollectionMetadata, pinNftRewards } from 'utils/nftRewards' -import { TransactionSuccessModal } from '../../../TransactionSuccessModal' -import { - EditingFundingCycleConfig, - useEditingFundingCycleConfig, -} from '../../ReconfigureFundingCycleSettingsPage/hooks/useEditingFundingCycleConfig' -import { useReconfigureFundingCycle } from '../../ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle' export function UploadAndLaunchNftsButton({ className, + onClick, + loading, }: { className?: string + onClick?: VoidFunction + loading: boolean }) { - const [ipfsUploading, setIpfsUploading] = useState(false) - const [successModalOpen, setSuccessModalOpen] = useState(false) - - const { - projectMetadata: { logoUri }, - } = useAppSelector(state => state.editingV2Project) - - const editingFundingCycleConfig = useEditingFundingCycleConfig() - const { reconfigureLoading, reconfigureFundingCycle, txPending } = - useReconfigureFundingCycle({ - editingFundingCycleConfig, - memo: 'First NFT collection', - launchedNewNfts: true, - onComplete: () => setSuccessModalOpen(true), - }) - - const buttonLoading = ipfsUploading || reconfigureLoading - - const { - editingPayoutGroupedSplits, - editingReservedTokensGroupedSplits, - editingFundingCycleMetadata, - editingFundingCycleData, - editingFundAccessConstraints, - editingNftRewards, - editingMustStartAtOrAfter, - } = editingFundingCycleConfig - - const uploadNftsToIpfs = async () => { - setIpfsUploading(true) - const newRewardTiers = - editingFundingCycleConfig.editingNftRewards?.rewardTiers - const collectionName = - editingFundingCycleConfig.editingNftRewards?.collectionMetadata.name ?? '' - const collectionDescription = - editingFundingCycleConfig.editingNftRewards?.collectionMetadata - .description ?? '' - const collectionLogoUri = logoUri ?? '' - const collectionInfoUri = - editingFundingCycleConfig.editingNftRewards?.collectionMetadata.uri ?? '' - - const [rewardTiersCIDs, nftCollectionMetadataUri] = await Promise.all([ - newRewardTiers ? pinNftRewards(newRewardTiers) : [], - pinNftCollectionMetadata({ - collectionName, - collectionDescription, - collectionLogoUri, - collectionInfoUri, - }), - ]) - const latestEditingData: EditingFundingCycleConfig = { - editingPayoutGroupedSplits, - editingReservedTokensGroupedSplits, - editingFundingCycleMetadata, - editingFundingCycleData, - editingFundAccessConstraints, - editingNftRewards: editingNftRewards - ? { - ...editingNftRewards, - collectionMetadata: { - ...editingNftRewards.collectionMetadata, - uri: nftCollectionMetadataUri, - }, - CIDs: rewardTiersCIDs, - } - : undefined, - editingMustStartAtOrAfter, - } - reconfigureFundingCycle(latestEditingData) - setIpfsUploading(false) - } - return ( - <> - - - setSuccessModalOpen(false)} - content={ - <> -
- Your new NFTs have been deployed -
-
- - New NFTs will be available in your next cycle as long as it - starts after your edit deadline. - -
- - } - /> - + ) } diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/hooks/useSettingsLaunchNftsForm.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/hooks/useSettingsLaunchNftsForm.ts new file mode 100644 index 0000000000..f707a398c9 --- /dev/null +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/hooks/useSettingsLaunchNftsForm.ts @@ -0,0 +1,117 @@ +import { useForm } from 'antd/lib/form/Form' +import { NftRewardsFormProps } from 'components/NftRewards/AddNftCollectionForm' +import { JB721GovernanceType } from 'models/nftRewards' +import { useState } from 'react' +import { useAppSelector } from 'redux/hooks/useAppSelector' +import { DEFAULT_NFT_FLAGS } from 'redux/slices/editingV2Project' +import { + defaultNftCollectionDescription, + defaultNftCollectionName, + pinNftCollectionMetadata, + pinNftRewards, +} from 'utils/nftRewards' +import { + EditingFundingCycleConfig, + useEditingFundingCycleConfig, +} from '../../../ReconfigureFundingCycleSettingsPage/hooks/useEditingFundingCycleConfig' +import { useReconfigureFundingCycle } from '../../../ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle' + +export const useSettingsLaunchNftsForm = () => { + const [form] = useForm() + + const [ipfsUploading, setIpfsUploading] = useState(false) + const [successModalOpen, setSuccessModalOpen] = useState(false) + + const { + projectMetadata: { logoUri, name: projectName }, + } = useAppSelector(state => state.editingV2Project) + + const editingFundingCycleConfig = useEditingFundingCycleConfig() + const { + reconfigureLoading, + reconfigureFundingCycle, + txPending: launchTxPending, + } = useReconfigureFundingCycle({ + editingFundingCycleConfig, + memo: 'First NFT collection', + launchedNewNfts: true, + onComplete: () => setSuccessModalOpen(true), + }) + + const launchButtonLoading = ipfsUploading || reconfigureLoading + + const { + editingPayoutGroupedSplits, + editingReservedTokensGroupedSplits, + editingFundingCycleMetadata, + editingFundingCycleData, + editingFundAccessConstraints, + editingMustStartAtOrAfter, + } = editingFundingCycleConfig + + const launchCollection = async () => { + setIpfsUploading(true) + const formValues = form.getFieldsValue(true) as NftRewardsFormProps + const newRewardTiers = formValues.rewards + const collectionName = + formValues.collectionName ?? defaultNftCollectionName(projectName) + const collectionDescription = + formValues.collectionDescription ?? + defaultNftCollectionDescription(projectName) + const collectionLogoUri = logoUri ?? '' + const collectionInfoUri = '' + + const [rewardTiersCIDs, nftCollectionMetadataUri] = await Promise.all([ + newRewardTiers ? pinNftRewards(newRewardTiers) : [], + pinNftCollectionMetadata({ + collectionName, + collectionDescription, + collectionLogoUri, + collectionInfoUri, + }), + ]) + + const latestEditingData: EditingFundingCycleConfig = { + editingPayoutGroupedSplits, + editingReservedTokensGroupedSplits, + editingFundingCycleMetadata, + editingFundingCycleData, + editingFundAccessConstraints, + editingNftRewards: { + rewardTiers: newRewardTiers, + collectionMetadata: { + uri: nftCollectionMetadataUri, + symbol: formValues.collectionSymbol, + name: collectionName, + description: collectionDescription, + }, + CIDs: rewardTiersCIDs, + postPayModal: { + ctaText: formValues.postPayButtonText, + ctaLink: formValues.postPayButtonLink, + content: formValues.postPayMessage, + }, + flags: { + ...DEFAULT_NFT_FLAGS, + preventOverspending: + formValues.preventOverspending ?? + DEFAULT_NFT_FLAGS.preventOverspending, + }, + governanceType: + formValues.onChainGovernance ?? JB721GovernanceType.NONE, + }, + editingMustStartAtOrAfter, + } + reconfigureFundingCycle(latestEditingData) + setIpfsUploading(false) + } + + return { + form, + launchButtonLoading, + launchCollection, + successModalOpen, + setSuccessModalOpen, + launchTxPending, + } +} diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/UpdateNftsPage/EditNftsPostPaySection/EditNftsPostPaySection.tsx b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/UpdateNftsPage/EditNftsPostPaySection/EditNftsPostPaySection.tsx index 0e89354040..db60de9fd8 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/UpdateNftsPage/EditNftsPostPaySection/EditNftsPostPaySection.tsx +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/UpdateNftsPage/EditNftsPostPaySection/EditNftsPostPaySection.tsx @@ -1,6 +1,6 @@ import { Trans } from '@lingui/macro' import { Button, Form } from 'antd' -import { NftPaymentSuccessFormItems } from 'components/Create/components/pages/NftRewards/NftPaymentSuccessFormItems' +import { NftPaymentSuccessFormItems } from 'components/NftRewards/AddNftCollectionForm/NftPaymentSuccessFormItems' import { PV_V2 } from 'constants/pv' import { ProjectMetadataContext } from 'contexts/shared/ProjectMetadataContext' import { useEditProjectDetailsTx } from 'hooks/v2v3/transactor/useEditProjectDetailsTx' diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/UpdateNftsPage/EditNftsSection.tsx b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/UpdateNftsPage/EditNftsSection.tsx index 200aa44f15..d19edaa178 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/UpdateNftsPage/EditNftsSection.tsx +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/UpdateNftsPage/EditNftsSection.tsx @@ -1,8 +1,8 @@ import { t, Trans } from '@lingui/macro' import { Button, Empty } from 'antd' import { Callout } from 'components/Callout' -import { RewardsList } from 'components/Create/components/RewardsList' import Loading from 'components/Loading' +import { RewardsList } from 'components/NftRewards/RewardsList' import { useUpdateCurrentCollection } from 'components/v2v3/V2V3Project/V2V3ProjectSettings/pages/EditNftsPage/hooks/useUpdateCurrentCollection' import { useHasNftRewards } from 'hooks/JB721Delegate/useHasNftRewards' diff --git a/src/components/v2v3/shared/FundingCycleConfigurationDrawers/NftDrawer/AddNftsSection/AddNftsSection.tsx b/src/components/v2v3/shared/FundingCycleConfigurationDrawers/NftDrawer/AddNftsSection/AddNftsSection.tsx index f5bdc5f746..67ea0e08f9 100644 --- a/src/components/v2v3/shared/FundingCycleConfigurationDrawers/NftDrawer/AddNftsSection/AddNftsSection.tsx +++ b/src/components/v2v3/shared/FundingCycleConfigurationDrawers/NftDrawer/AddNftsSection/AddNftsSection.tsx @@ -1,6 +1,6 @@ import { t, Trans } from '@lingui/macro' import { Button, Empty, Form } from 'antd' -import { RewardsList } from 'components/Create/components/RewardsList' +import { RewardsList } from 'components/NftRewards/RewardsList' import { useCallback, useState } from 'react' import { emitErrorNotification } from 'utils/notifications' From b613d22f17659a54c48fcea0cc8fdfba2251a99d Mon Sep 17 00:00:00 2001 From: Johnny D Date: Wed, 13 Sep 2023 22:41:46 +1000 Subject: [PATCH 3/9] [PREVIEW] --- .../LaunchNftCollection/LaunchNftsCollection.tsx | 2 +- .../LaunchNftCollection/UploadAndLaunchNftsButton.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/LaunchNftsCollection.tsx b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/LaunchNftsCollection.tsx index cfcf1b9fee..b297ebd09c 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/LaunchNftsCollection.tsx +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/LaunchNftsCollection.tsx @@ -21,7 +21,7 @@ export function LaunchNftsPage() { okButton={ launchCollection} + onClick={launchCollection} loading={launchButtonLoading} /> } diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/UploadAndLaunchNftsButton.tsx b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/UploadAndLaunchNftsButton.tsx index 059d9c32b1..cd23e2c1a1 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/UploadAndLaunchNftsButton.tsx +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/UploadAndLaunchNftsButton.tsx @@ -7,7 +7,7 @@ export function UploadAndLaunchNftsButton({ loading, }: { className?: string - onClick?: VoidFunction + onClick: VoidFunction loading: boolean }) { return ( From 2882754b5b93a33f731a491f5826a6d4d5ba134b Mon Sep 17 00:00:00 2001 From: Johnny D Date: Thu, 14 Sep 2023 20:26:40 +1000 Subject: [PATCH 4/9] [PREVIEW] Fix edge-case settings bug where launch nft txs/edit cycle txs canoverride eachother --- .../hooks/useConflictingLaunchEditCycleTx.tsx | 60 +++++++++++++++++ .../hooks/useConflictingNftSettingsTx.ts | 64 +++++++++++++++++++ .../hooks/useReconfigureFundingCycle.ts | 29 ++++++++- .../useProjectQueuedFundingCycle.ts | 13 +++- 4 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useConflictingLaunchEditCycleTx.tsx create mode 100644 src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useConflictingNftSettingsTx.ts diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useConflictingLaunchEditCycleTx.tsx b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useConflictingLaunchEditCycleTx.tsx new file mode 100644 index 0000000000..37d29a16a6 --- /dev/null +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useConflictingLaunchEditCycleTx.tsx @@ -0,0 +1,60 @@ +import { ProjectMetadataContext } from 'contexts/shared/ProjectMetadataContext' +import useProjectQueuedFundingCycle from 'hooks/v2v3/contractReader/useProjectQueuedFundingCycle' +import { ReconfigureFundingCycleTxParams } from 'hooks/v2v3/transactor/useReconfigureV2V3FundingCycleTx' +import { useContext } from 'react' + +/** + * This hook is necessary to run before cycle-related tx's in NFT settings (`/settings/nfts`): + * e.g. launch nfts, edit useDataSourceForRedemption + * + * @hasConflictingEditCycleTx + * - Determines if there is a conflicting `reconfigureFundingCyclesOf` tx + * called from the edit cycle page of the settings (`/settings/cycle`) + * - Since the launch Nfts Tx can only be called once, we can assume that + * if ANY queued cycle exists, we merge all its attributes minus the NFT specific ones + * + * @mergeAlreadyQueuedEditCycleTx + * - If there is a conflicting prior tx ( @hasConflictingEditCycleTx ), it merges all of the + * already queued data from that tx, minus the NFT specific ones we want to change from the /nfts tx + * + */ +export const useConflictingEditCycleTx = () => { + const { projectId } = useContext(ProjectMetadataContext) + const { data: queuedCycle } = useProjectQueuedFundingCycle({ projectId }) + + if (!queuedCycle) + return { + hasConflictingEditCycleTx: false, + mergeAlreadyQueuedEditCycleTx: (data: ReconfigureFundingCycleTxParams) => + data, + } + + const queuedCycleData = queuedCycle[0] + const queuedCycleMetadata = queuedCycle[1] + + const mergeAlreadyQueuedEditCycleTx = ( + nftTxData: ReconfigureFundingCycleTxParams, + ) => { + const data = nftTxData + data.fundingCycleMetadata = { + ...queuedCycleMetadata, + useDataSourceForPay: nftTxData.fundingCycleMetadata.useDataSourceForPay, + useDataSourceForRedeem: + nftTxData.fundingCycleMetadata.useDataSourceForRedeem, + dataSource: nftTxData.fundingCycleMetadata.dataSource, + } + data.fundingCycleData = { + ...queuedCycleData, + } + + // fundAccessConstraints?!?: + // https://discord.com/channels/939317843059679252/1080714793595441182/1151822556907712593 + + return data + } + + return { + hasConflictingEditCycleTx: true, + mergeAlreadyQueuedEditCycleTx, + } +} diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useConflictingNftSettingsTx.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useConflictingNftSettingsTx.ts new file mode 100644 index 0000000000..8d753d4de9 --- /dev/null +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useConflictingNftSettingsTx.ts @@ -0,0 +1,64 @@ +import { ProjectMetadataContext } from 'contexts/shared/ProjectMetadataContext' +import { V2V3ProjectContext } from 'contexts/v2v3/Project/V2V3ProjectContext' +import useProjectQueuedFundingCycle from 'hooks/v2v3/contractReader/useProjectQueuedFundingCycle' +import { ReconfigureFundingCycleTxParams } from 'hooks/v2v3/transactor/useReconfigureV2V3FundingCycleTx' +import { useContext } from 'react' + +/** + * This hook is necessary to run before edit cycle tx's (`/settings/cycle`): + * @hasConflictingNftTx + * - Determines if there is a conflicting `reconfigureFundingCyclesOf` tx + * called from the NFT page of the settings (`/settings/nft`) + * + * @mergeAlreadyQueuedNftTx + * - If there is a conflicting prior tx ( @hasConflictingNftTx ), it merges the attributes + * handled by the NFT tx into given data from an edit cycle tx + * + */ +export const useConflictingNftSettingsTx = () => { + const { projectId } = useContext(ProjectMetadataContext) + const { fundingCycleMetadata } = useContext(V2V3ProjectContext) + const { data: queuedCycle } = useProjectQueuedFundingCycle({ projectId }) + + if (!queuedCycle || !fundingCycleMetadata) + return { + hasConflictingNftTx: false, + mergeAlreadyQueuedNftTx: (data: ReconfigureFundingCycleTxParams) => data, + } + + const queuedFcMetadata = queuedCycle[1] + + // Check if the queued cycle has any NFT specific diff's compared to the current cycle + const useDataSourceForPayHasDiff = + queuedFcMetadata.useDataSourceForPay !== + fundingCycleMetadata.useDataSourceForPay + const useDataSourceForRedeemHasDiff = + queuedFcMetadata.useDataSourceForRedeem !== + fundingCycleMetadata.useDataSourceForRedeem + const useDataSourceHasDiff = + queuedFcMetadata.dataSource !== fundingCycleMetadata.dataSource + + const hasConflictingNftTx = + useDataSourceForPayHasDiff || + useDataSourceForRedeemHasDiff || + useDataSourceHasDiff + + const mergeAlreadyQueuedNftTx = ( + editCycleTxData: ReconfigureFundingCycleTxParams, + ) => { + const data = editCycleTxData + data.fundingCycleMetadata = { + ...editCycleTxData.fundingCycleMetadata, + useDataSourceForPay: queuedFcMetadata.useDataSourceForPay, + useDataSourceForRedeem: queuedFcMetadata.useDataSourceForRedeem, + dataSource: queuedFcMetadata.dataSource, + } + + return data + } + + return { + hasConflictingNftTx, + mergeAlreadyQueuedNftTx, + } +} diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle.ts index 8c098da370..52d20d0cc5 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle.ts +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle.ts @@ -14,6 +14,8 @@ import { fromWad } from 'utils/format/formatNumber' import { NFT_FUNDING_CYCLE_METADATA_OVERRIDES } from 'utils/nftFundingCycleMetadataOverrides' import { WEIGHT_UNCHANGED, WEIGHT_ZERO } from 'utils/v2v3/fundingCycle' import { reloadWindow } from 'utils/windowUtils' +import { useConflictingEditCycleTx } from './useConflictingLaunchEditCycleTx' +import { useConflictingNftSettingsTx } from './useConflictingNftSettingsTx' import { EditingFundingCycleConfig } from './useEditingFundingCycleConfig' /** @@ -41,6 +43,11 @@ const getWeightArgument = ({ return newFundingCycleWeight } +/** + * This hook is used in two places: + * 1. Edit cycle form + * 2. NFT page - edit dataSource-related attributes of the cycle + */ export const useReconfigureFundingCycle = ({ editingFundingCycleConfig, memo, @@ -66,6 +73,12 @@ export const useReconfigureFundingCycle = ({ const reconfigureV2V3FundingCycleWithNftsTx = useReconfigureV2V3FundingCycleWithNftsTx() + const { hasConflictingNftTx, mergeAlreadyQueuedNftTx } = + useConflictingNftSettingsTx() + + const { hasConflictingEditCycleTx, mergeAlreadyQueuedEditCycleTx } = + useConflictingEditCycleTx() + // If given a latestEditingData, will use that. Else, will use redux store const reconfigureFundingCycle = useCallback( async (latestEditingData?: EditingFundingCycleConfig) => { @@ -105,7 +118,7 @@ export const useReconfigureFundingCycle = ({ newFundingCycleWeight: editingFundingCycleData.weight, }) - const reconfigureFundingCycleData: ReconfigureFundingCycleTxParams = { + let reconfigureFundingCycleData: ReconfigureFundingCycleTxParams = { fundingCycleData: { ...editingFundingCycleData, weight, @@ -120,6 +133,16 @@ export const useReconfigureFundingCycle = ({ mustStartAtOrAfter: editingMustStartAtOrAfter, } + if (hasConflictingNftTx) { + reconfigureFundingCycleData = mergeAlreadyQueuedNftTx( + reconfigureFundingCycleData, + ) + } else if (hasConflictingEditCycleTx) { + reconfigureFundingCycleData = mergeAlreadyQueuedEditCycleTx( + reconfigureFundingCycleData, + ) + } + const txOpts = { onDone() { setTxPending(true) @@ -177,6 +200,10 @@ export const useReconfigureFundingCycle = ({ memo, onComplete, projectId, + hasConflictingEditCycleTx, + hasConflictingNftTx, + mergeAlreadyQueuedEditCycleTx, + mergeAlreadyQueuedNftTx, ], ) diff --git a/src/hooks/v2v3/contractReader/useProjectQueuedFundingCycle.ts b/src/hooks/v2v3/contractReader/useProjectQueuedFundingCycle.ts index e45332475f..f1d6475bdc 100644 --- a/src/hooks/v2v3/contractReader/useProjectQueuedFundingCycle.ts +++ b/src/hooks/v2v3/contractReader/useProjectQueuedFundingCycle.ts @@ -1,3 +1,4 @@ +import { BigNumber } from '@ethersproject/bignumber' import { V2V3ProjectContractsContext } from 'contexts/v2v3/ProjectContracts/V2V3ProjectContractsContext' import { V2V3FundingCycle, @@ -13,9 +14,19 @@ export default function useProjectQueuedFundingCycle({ }) { const { contracts } = useContext(V2V3ProjectContractsContext) - return useV2ContractReader<[V2V3FundingCycle, V2V3FundingCycleMetadata]>({ + const { data, loading } = useV2ContractReader< + [V2V3FundingCycle, V2V3FundingCycleMetadata] + >({ contract: contracts.JBController, functionName: 'queuedFundingCycleOf', args: projectId ? [projectId] : null, }) + + if (data && data[0].start.eq(BigNumber.from(0))) { + return { data: undefined, loading: false } + } + return { + data, + loading, + } } From c46606e0339a273a716faf4deef0e6f97b9171ec Mon Sep 17 00:00:00 2001 From: Johnny D Date: Tue, 3 Oct 2023 16:38:13 +1000 Subject: [PATCH 5/9] [PREVIEW] i18n --- .../hooks/useResolveEditCycleConflicts.ts | 17 ++++++----------- .../hooks/useSettingsLaunchNftsForm.ts | 10 +++++----- src/locales/messages.pot | 3 --- tailwind.config.js | 10 +++++----- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts index e59d2f73aa..69de0f7847 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts @@ -9,8 +9,10 @@ import { import { useContext } from 'react' /** - * Determines if there's an NFT conflict between the current and queued funding cycle metadata. - * A conflict arises if there are differences in the NFT related attributes. + * Determines if a "Launch NFTs" (NftDeployer.reconfigureFundingCycleOf) has been called + * in the same cycle as an "Edit cycle" (reconfigureFundingCycleOf) tx. If so, need to pass + * the new delegate and other NFT related attributes into the subsequent "Edit cycle" tx so + * they are not overriden and lost. * * @param {V2V3FundingCycleMetadata} currentFcMetadata - The current funding cycle metadata. * @param {V2V3FundingCycleMetadata} queuedFcMetadata - The queued funding cycle metadata. @@ -48,13 +50,6 @@ export const useResolveEditCycleConflicts = () => { const queuedFcData: V2V3FundingCycleData = queuedCycle[0] const queuedFcMetadata: V2V3FundingCycleMetadata = queuedCycle[1] - /** - * Resolves any potential conflicts in the reconfiguration of funding cycles. - * It merges the given data with the data from a queued cycle, taking into account any NFT specific conflicts. - * - * @param {ReconfigureFundingCycleTxParams} data - The data for reconfiguring the funding cycle. - * @returns {ReconfigureFundingCycleTxParams} - The modified data after resolving conflicts. - */ return (data: ReconfigureFundingCycleTxParams) => { if (hasNftConflict(fundingCycleMetadata, queuedFcMetadata)) { return { @@ -70,12 +65,12 @@ export const useResolveEditCycleConflicts = () => { return { ...data, fundingCycleMetadata: { - ...queuedFcMetadata, ...data.fundingCycleMetadata, + ...queuedFcMetadata, }, fundingCycleData: { - ...queuedFcData, ...data.fundingCycleData, + ...queuedFcData, }, } } diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/hooks/useSettingsLaunchNftsForm.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/hooks/useSettingsLaunchNftsForm.ts index f707a398c9..5a655f56cc 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/hooks/useSettingsLaunchNftsForm.ts +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/pages/NewEditNftsPage/LaunchNftCollection/hooks/useSettingsLaunchNftsForm.ts @@ -1,5 +1,10 @@ import { useForm } from 'antd/lib/form/Form' import { NftRewardsFormProps } from 'components/NftRewards/AddNftCollectionForm' +import { + EditingFundingCycleConfig, + useEditingFundingCycleConfig, +} from 'components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useEditingFundingCycleConfig' +import { useReconfigureFundingCycle } from 'components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useReconfigureFundingCycle' import { JB721GovernanceType } from 'models/nftRewards' import { useState } from 'react' import { useAppSelector } from 'redux/hooks/useAppSelector' @@ -10,11 +15,6 @@ import { pinNftCollectionMetadata, pinNftRewards, } from 'utils/nftRewards' -import { - EditingFundingCycleConfig, - useEditingFundingCycleConfig, -} from '../../../ReconfigureFundingCycleSettingsPage/hooks/useEditingFundingCycleConfig' -import { useReconfigureFundingCycle } from '../../../ReconfigureFundingCycleSettingsPage/hooks/useReconfigureFundingCycle' export const useSettingsLaunchNftsForm = () => { const [form] = useForm() diff --git a/src/locales/messages.pot b/src/locales/messages.pot index 99eb9d7a7f..3365c50b8c 100644 --- a/src/locales/messages.pot +++ b/src/locales/messages.pot @@ -752,9 +752,6 @@ msgstr "" msgid "New NFTs will be available in your next cycle as long as it starts after your edit deadline." msgstr "" -msgid "New NFTs will be available in your next cycle as long as it starts after your edit deadline." -msgstr "" - msgid "Confirm" msgstr "" diff --git a/tailwind.config.js b/tailwind.config.js index 9e0cd9d494..c88a910ca5 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,6 +1,6 @@ -/** @type {import('tailwindcss').Config} */ const defaultTheme = require('tailwindcss/defaultTheme') +/** @type {import('tailwindcss').Config} */ module.exports = { content: [ './src/pages/**/*.{js,ts,jsx,tsx}', @@ -43,12 +43,12 @@ module.exports = { }, keyframes: { rise: { - '0%': { transform: 'translate(-50%, 100%)', opacity: 0 }, - '100%': { transform: 'translate(0%, 0%)', opacity: 1 }, + '0%': { transform: 'translate(-50%, 100%)', opacity: '0' }, + '100%': { transform: 'translate(0%, 0%)', opacity: '1' }, }, set: { - '0%': { transform: 'translate(0%, 0%)', opacity: 1 }, - '100%': { transform: 'translate(50%, 100%)', opacity: 0 }, + '0%': { transform: 'translate(0%, 0%)', opacity: '1' }, + '100%': { transform: 'translate(50%, 100%)', opacity: '0' }, }, }, animation: { From da3c86d4acde061a1059757bc0efd72360aee084 Mon Sep 17 00:00:00 2001 From: Tom Quirk <12551741+tomquirk@users.noreply.github.com> Date: Thu, 2 Nov 2023 08:25:55 +1000 Subject: [PATCH 6/9] rm some trans --- .../announcements/ExampleFeatureAnnouncement.tsx | 13 ++++--------- src/locales/messages.pot | 12 ------------ 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/components/announcements/ExampleFeatureAnnouncement.tsx b/src/components/announcements/ExampleFeatureAnnouncement.tsx index bd47294d6f..85edc878f7 100644 --- a/src/components/announcements/ExampleFeatureAnnouncement.tsx +++ b/src/components/announcements/ExampleFeatureAnnouncement.tsx @@ -1,4 +1,3 @@ -import { Trans, t } from '@lingui/macro' import { JuiceModalProps } from 'components/modals/JuiceModal' import { NewFeatureAnnouncement } from './NewFeatureAnnouncement' @@ -11,17 +10,13 @@ export const ExampleFeatureAnnouncement = ( return ( -

- This is an example feature announcement. -

-

- Use me as a base! -

+

This is an example feature announcement.

+

Use me as a base!

) } diff --git a/src/locales/messages.pot b/src/locales/messages.pot index 5f0e08e274..5fc4aaae06 100644 --- a/src/locales/messages.pot +++ b/src/locales/messages.pot @@ -713,9 +713,6 @@ msgstr "" msgid "Project token" msgstr "" -msgid "Got it" -msgstr "" - msgid "Setup new NFTs for {projectTitle}" msgstr "" @@ -743,9 +740,6 @@ msgstr "" msgid "Tokens to burn" msgstr "" -msgid "Use me as a base!" -msgstr "" - msgid "New NFTs will be available in your next cycle as long as it starts after your edit deadline." msgstr "" @@ -1334,9 +1328,6 @@ msgstr "" msgid "Juicebox is as versatile as you are, build anything from an NFT project to a boutique crypto lawfirm and everything in between." msgstr "" -msgid "This is an example feature announcement." -msgstr "" - msgid "Button link" msgstr "" @@ -3914,9 +3905,6 @@ msgstr "" msgid "Owner tools" msgstr "" -msgid "Example Feature" -msgstr "" - msgid "<0>Juicebox is a programmable crypto fundraising platform for web3. It helps people fund, operate, and scale their projects transparently using Ethereum, which is a type of programmable cryptocurrency.<1>Juicebox is funded and owned by its community." msgstr "" From 1b3c1285faf6963661cfc3e669581c157096d93e Mon Sep 17 00:00:00 2001 From: Tom Quirk <12551741+tomquirk@users.noreply.github.com> Date: Thu, 2 Nov 2023 08:28:29 +1000 Subject: [PATCH 7/9] note --- .../hooks/useReconfigureFundingCycle.ts | 44 ++++++++----------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useReconfigureFundingCycle.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useReconfigureFundingCycle.ts index e87ad77b46..253e96888b 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useReconfigureFundingCycle.ts +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useReconfigureFundingCycle.ts @@ -43,7 +43,9 @@ const getWeightArgument = ({ } /** - * This hook is used in two places: + * Return a function to initiate a transaction to reconfigure a project's funding cycle. + * + * @dev Used in two places: * 1. Edit cycle form * 2. NFT page - edit dataSource-related attributes of the cycle */ @@ -71,13 +73,6 @@ export const useReconfigureFundingCycle = ({ const reconfigureV2V3FundingCycleTx = useReconfigureV2V3FundingCycleTx() const reconfigureV2V3FundingCycleWithNftsTx = useReconfigureV2V3FundingCycleWithNftsTx() - - // const { hasConflictingNftTx, mergeAlreadyQueuedNftTx } = - // useConflictingNftSettingsTx() - - // const { hasConflictingEditCycleTx, mergeAlreadyQueuedEditCycleTx } = - // useConflictingEditCycleTx() - const resolveEditCycleConflicts = useResolveEditCycleConflicts() // If given a latestEditingData, will use that. Else, will use redux store @@ -119,24 +114,21 @@ export const useReconfigureFundingCycle = ({ newFundingCycleWeight: editingFundingCycleData.weight, }) - let reconfigureFundingCycleData: ReconfigureFundingCycleTxParams = { - fundingCycleData: { - ...editingFundingCycleData, - weight, - }, - fundingCycleMetadata, - fundAccessConstraints: editingFundAccessConstraints, - groupedSplits: [ - editingPayoutGroupedSplits, - editingReservedTokensGroupedSplits, - ], - memo, - mustStartAtOrAfter: editingMustStartAtOrAfter, - } - - reconfigureFundingCycleData = resolveEditCycleConflicts( - reconfigureFundingCycleData, - ) + const reconfigureFundingCycleData: ReconfigureFundingCycleTxParams = + resolveEditCycleConflicts({ + fundingCycleData: { + ...editingFundingCycleData, + weight, + }, + fundingCycleMetadata, + fundAccessConstraints: editingFundAccessConstraints, + groupedSplits: [ + editingPayoutGroupedSplits, + editingReservedTokensGroupedSplits, + ], + memo, + mustStartAtOrAfter: editingMustStartAtOrAfter, + }) const txOpts = { onDone() { From 48ebd32810304788abfcb9e7b493e3502884749d Mon Sep 17 00:00:00 2001 From: Tom Quirk <12551741+tomquirk@users.noreply.github.com> Date: Thu, 2 Nov 2023 08:35:58 +1000 Subject: [PATCH 8/9] some more comments --- .../hooks/useResolveEditCycleConflicts.ts | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts index 69de0f7847..c907f1c576 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts @@ -10,9 +10,10 @@ import { useContext } from 'react' /** * Determines if a "Launch NFTs" (NftDeployer.reconfigureFundingCycleOf) has been called - * in the same cycle as an "Edit cycle" (reconfigureFundingCycleOf) tx. If so, need to pass - * the new delegate and other NFT related attributes into the subsequent "Edit cycle" tx so - * they are not overriden and lost. + * in the same cycle as an "Edit cycle" (reconfigureFundingCycleOf) tx. + * + * If so, we need to pass the new delegate and other NFT-related data into the subsequent + * "Edit cycle" tx so they are not overriden and lost. * * @param {V2V3FundingCycleMetadata} currentFcMetadata - The current funding cycle metadata. * @param {V2V3FundingCycleMetadata} queuedFcMetadata - The queued funding cycle metadata. @@ -22,6 +23,7 @@ function hasNftConflict( currentFcMetadata: V2V3FundingCycleMetadata, queuedFcMetadata: V2V3FundingCycleMetadata, ): boolean { + // if the queued cycle's NFT data has any changes to the current cycle, return true. const useDataSourceForPayHasDiff = queuedFcMetadata.useDataSourceForPay !== currentFcMetadata.useDataSourceForPay @@ -38,11 +40,17 @@ function hasNftConflict( ) } +/** + * + * @returns + */ export const useResolveEditCycleConflicts = () => { const { projectId } = useContext(ProjectMetadataContext) const { fundingCycleMetadata } = useContext(V2V3ProjectContext) + const { data: queuedCycle } = useProjectQueuedFundingCycle({ projectId }) + // if (!queuedCycle || !fundingCycleMetadata) { return (data: ReconfigureFundingCycleTxParams) => data } @@ -51,6 +59,7 @@ export const useResolveEditCycleConflicts = () => { const queuedFcMetadata: V2V3FundingCycleMetadata = queuedCycle[1] return (data: ReconfigureFundingCycleTxParams) => { + // if the queued cycle's NFT data has changed, inject the queued NFT data. if (hasNftConflict(fundingCycleMetadata, queuedFcMetadata)) { return { ...data, @@ -61,18 +70,18 @@ export const useResolveEditCycleConflicts = () => { dataSource: queuedFcMetadata.dataSource, }, } - } else { - return { - ...data, - fundingCycleMetadata: { - ...data.fundingCycleMetadata, - ...queuedFcMetadata, - }, - fundingCycleData: { - ...data.fundingCycleData, - ...queuedFcData, - }, - } + } + + return { + ...data, + fundingCycleMetadata: { + ...data.fundingCycleMetadata, + ...queuedFcMetadata, + }, + fundingCycleData: { + ...data.fundingCycleData, + ...queuedFcData, + }, } } } From bfffab454f739585f70c37e49aa63b0fc3607fd1 Mon Sep 17 00:00:00 2001 From: "johnnyD.eth@protonmail.com" Date: Thu, 2 Nov 2023 09:54:51 +0800 Subject: [PATCH 9/9] [PREVIEW] Add better comments to useResolveEditCycleConflicts() --- .../useFormatConfigurationCyclesSection.tsx | 123 ++++++++++++++++++ .../hooks/useReconfigureFundingCycle.ts | 1 + .../hooks/useResolveEditCycleConflicts.ts | 35 ++--- 3 files changed, 144 insertions(+), 15 deletions(-) create mode 100644 src/components/v2v3/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/hooks/useConfigurationPanel/useFormatConfigurationCyclesSection.tsx diff --git a/src/components/v2v3/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/hooks/useConfigurationPanel/useFormatConfigurationCyclesSection.tsx b/src/components/v2v3/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/hooks/useConfigurationPanel/useFormatConfigurationCyclesSection.tsx new file mode 100644 index 0000000000..c8e30ca441 --- /dev/null +++ b/src/components/v2v3/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/hooks/useConfigurationPanel/useFormatConfigurationCyclesSection.tsx @@ -0,0 +1,123 @@ +import { t } from '@lingui/macro' +import { AmountInCurrency } from 'components/currency/AmountInCurrency' +import { timeSecondsToDateString } from 'components/v2v3/V2V3Project/ProjectDashboard/utils/timeSecondsToDateString' +import { BigNumber } from 'ethers' +import { V2V3CurrencyOption } from 'models/v2v3/currencyOption' +import { V2V3FundingCycle } from 'models/v2v3/fundingCycle' +import { useMemo } from 'react' +import { fromWad } from 'utils/format/formatNumber' +import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' +import { getBallotStrategyByAddress } from 'utils/v2v3/ballotStrategies' +import { V2V3CurrencyName } from 'utils/v2v3/currency' +import { MAX_DISTRIBUTION_LIMIT } from 'utils/v2v3/math' +import { ConfigurationPanelDatum } from '../../components/ConfigurationPanel' +import { pairToDatum } from '../../utils/pairToDatum' + +export const useFormatConfigurationCyclesSection = ({ + fundingCycle, + upcomingFundingCycle, + distributionLimitAmountCurrency, + upcomingDistributionLimitAmountCurrency, +}: { + fundingCycle: V2V3FundingCycle | undefined + upcomingFundingCycle?: V2V3FundingCycle | null + distributionLimitAmountCurrency: + | { + distributionLimit: BigNumber | undefined + currency: BigNumber | undefined + } + | undefined + upcomingDistributionLimitAmountCurrency?: { + distributionLimit: BigNumber | undefined + currency: BigNumber | undefined + } | null +}) => { + const durationDatum: ConfigurationPanelDatum = useMemo(() => { + const formatDuration = (duration: BigNumber | undefined) => { + if (duration === undefined) return undefined + if (duration.eq(0)) return t`Not set` + return timeSecondsToDateString(duration.toNumber(), 'short', 'lower') + } + const currentDuration = formatDuration(fundingCycle?.duration) + if (upcomingFundingCycle === null) { + return pairToDatum(t`Duration`, currentDuration, null) + } + const upcomingDuration = formatDuration(upcomingFundingCycle?.duration) + + return pairToDatum(t`Duration`, currentDuration, upcomingDuration) + }, [fundingCycle?.duration, upcomingFundingCycle]) + + const payoutsDatum: ConfigurationPanelDatum = useMemo(() => { + const formatCurrency = (currency: BigNumber | undefined) => { + if (currency === undefined) return undefined + return currency.toNumber() as V2V3CurrencyOption + } + const formatAmountWad = ( + amountWad: BigNumber | undefined, + currency: V2V3CurrencyOption | undefined, + ) => { + if (amountWad === undefined) return undefined + if (amountWad.eq(MAX_DISTRIBUTION_LIMIT)) return t`Unlimited` + if (amountWad.eq(0)) return t`Zero (no payouts)` + return formatCurrencyAmount({ + amount: Number(fromWad(amountWad)), + currency, + }) + } + const { distributionLimit, currency } = + distributionLimitAmountCurrency ?? {} + // const currentPayout = formatAmountWad( + // distributionLimit, + // formatCurrency(currency), + // ) + const currentPayout = ( + + ) + + if (upcomingDistributionLimitAmountCurrency === null) { + return pairToDatum(t`Payouts`, currentPayout, null) + } + + const upcomingDistributionLimit = + upcomingDistributionLimitAmountCurrency?.distributionLimit !== undefined + ? upcomingDistributionLimitAmountCurrency.distributionLimit + : undefined + const upcomingDistributionLimitCurrency = + upcomingDistributionLimitAmountCurrency?.currency !== undefined + ? upcomingDistributionLimitAmountCurrency.currency + : undefined + const upcomingPayout = formatAmountWad( + upcomingDistributionLimit, + formatCurrency(upcomingDistributionLimitCurrency), + ) + + return pairToDatum(t`Payouts`, currentPayout, upcomingPayout) + }, [distributionLimitAmountCurrency, upcomingDistributionLimitAmountCurrency]) + + const editDeadlineDatum: ConfigurationPanelDatum = useMemo(() => { + const currentBallotStrategy = fundingCycle?.ballot + ? getBallotStrategyByAddress(fundingCycle.ballot) + : undefined + const current = currentBallotStrategy?.name + if (upcomingFundingCycle === null) { + return pairToDatum(t`Edit deadline`, current, null) + } + + const upcomingBallotStrategy = upcomingFundingCycle?.ballot + ? getBallotStrategyByAddress(upcomingFundingCycle.ballot) + : undefined + const upcoming = upcomingBallotStrategy?.name + return pairToDatum(t`Edit deadline`, current, upcoming) + }, [fundingCycle?.ballot, upcomingFundingCycle]) + + return useMemo(() => { + return { + duration: durationDatum, + payouts: payoutsDatum, + editDeadline: editDeadlineDatum, + } + }, [durationDatum, editDeadlineDatum, payoutsDatum]) +} diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useReconfigureFundingCycle.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useReconfigureFundingCycle.ts index 253e96888b..67c6ac097c 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useReconfigureFundingCycle.ts +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useReconfigureFundingCycle.ts @@ -128,6 +128,7 @@ export const useReconfigureFundingCycle = ({ ], memo, mustStartAtOrAfter: editingMustStartAtOrAfter, + launchedNewNfts, }) const txOpts = { diff --git a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts index c907f1c576..bdc2ce476e 100644 --- a/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts +++ b/src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts @@ -50,7 +50,7 @@ export const useResolveEditCycleConflicts = () => { const { data: queuedCycle } = useProjectQueuedFundingCycle({ projectId }) - // + // If no queued cycle, no resolving needs to be done. Return current data if (!queuedCycle || !fundingCycleMetadata) { return (data: ReconfigureFundingCycleTxParams) => data } @@ -58,8 +58,10 @@ export const useResolveEditCycleConflicts = () => { const queuedFcData: V2V3FundingCycleData = queuedCycle[0] const queuedFcMetadata: V2V3FundingCycleMetadata = queuedCycle[1] - return (data: ReconfigureFundingCycleTxParams) => { - // if the queued cycle's NFT data has changed, inject the queued NFT data. + return ( + data: ReconfigureFundingCycleTxParams & { launchedNewNfts?: boolean }, + ) => { + // Calling from "Edit cycle" and an NFT tx has be called same cycle: pass that previously queued NFT data into this "Edit cycle" tx if (hasNftConflict(fundingCycleMetadata, queuedFcMetadata)) { return { ...data, @@ -71,17 +73,20 @@ export const useResolveEditCycleConflicts = () => { }, } } - - return { - ...data, - fundingCycleMetadata: { - ...data.fundingCycleMetadata, - ...queuedFcMetadata, - }, - fundingCycleData: { - ...data.fundingCycleData, - ...queuedFcData, - }, - } + // Calling from "Launch NFTs" and an "Edit cycle" tx has be called same cycle: pass that previously queued data into this "Launch NFTs" tx + if (data.launchedNewNfts) { + return { + ...data, + fundingCycleMetadata: { + ...data.fundingCycleMetadata, + ...queuedFcMetadata, + }, + fundingCycleData: { + ...data.fundingCycleData, + ...queuedFcData, + }, + } + // Calling "Edit cycle" when a previously "Edit cycle" tx exists: ignore the old tx data, return the new one + } else return data } }