From a3ffa47efaea2f07f8bcbdcce8fa6dd28d5b79c5 Mon Sep 17 00:00:00 2001 From: aeolian <94939382+aeolianeth@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:34:07 +1000 Subject: [PATCH 1/5] feat: NEXT_PUBLIC_V4_ENABLED --- .example.env | 2 ++ src/lib/api/supabase/projects/api.ts | 20 ++++++++++++-------- src/pages/api/projects/trending.ts | 8 +++++--- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/.example.env b/.example.env index ca2d6f22bf..8f1a8414d8 100644 --- a/.example.env +++ b/.example.env @@ -62,3 +62,5 @@ DB_PROJECTS_WEBHOOK_URL= # Discord Webhook URL for /contact page. CONTACT_WEBHOOK_URL= + +NEXT_PUBLIC_V4_ENABLED=false \ No newline at end of file diff --git a/src/lib/api/supabase/projects/api.ts b/src/lib/api/supabase/projects/api.ts index 76b6193894..af682f74d6 100644 --- a/src/lib/api/supabase/projects/api.ts +++ b/src/lib/api/supabase/projects/api.ts @@ -50,14 +50,18 @@ export async function queryAllSGProjectsForServer() { chainId: readNetwork.chainId, } }) as unknown as Json>[] - const _resSepoliaV4 = resSepoliaV4.map(p => { - return { - ...p, - id: getSubgraphIdForProject(PV_V4, p.projectId), // Patch in the subgraph ID for V4 projects (to be consitent with legacy subgraph) - pv: PV_V4, // Patch in the PV for V4 projects, - chainId: sepolia.id, - } - }) as unknown as Json>[] + const _resSepoliaV4 = process.env.NEXT_PUBLIC_V4_ENABLED + ? (resSepoliaV4.map(p => { + return { + ...p, + id: getSubgraphIdForProject(PV_V4, p.projectId), // Patch in the subgraph ID for V4 projects (to be consitent with legacy subgraph) + pv: PV_V4, // Patch in the PV for V4 projects, + chainId: sepolia.id, + } + }) as unknown as Json< + Pick + >[]) + : [] return [..._res, ..._resSepoliaV4].map(formatSGProjectForDB) } diff --git a/src/pages/api/projects/trending.ts b/src/pages/api/projects/trending.ts index e4c122e1c0..095a215f3d 100644 --- a/src/pages/api/projects/trending.ts +++ b/src/pages/api/projects/trending.ts @@ -63,9 +63,11 @@ const handler: NextApiHandler = async (req, res) => { const projects = [ ...projectsRes.data.projects, - ...v4SepoliaProjectsRes.data.projects.map(p => { - return { ...p, chainId: sepolia.id, pv: PV_V4 } - }), + ...(process.env.NEXT_PUBLIC_V4_ENABLED + ? v4SepoliaProjectsRes.data.projects.map(p => { + return { ...p, chainId: sepolia.id, pv: PV_V4 } + }) + : []), ] try { From 9071739edc0d196180ce9f9a357a706c6ed63882 Mon Sep 17 00:00:00 2001 From: aeolian <94939382+aeolianeth@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:53:37 +1000 Subject: [PATCH 2/5] Add pay notice to About panel (#4516) --- src/locales/messages.pot | 3 +++ .../components/AboutPanel/AboutPanel.tsx | 26 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/locales/messages.pot b/src/locales/messages.pot index 59a1d53d17..42b56b7b73 100644 --- a/src/locales/messages.pot +++ b/src/locales/messages.pot @@ -3275,6 +3275,9 @@ msgstr "" msgid "Available payout" msgstr "" +msgid "Notice from {name}" +msgstr "" + msgid "Big ups to the Ethereum community for crafting the infrastructure and economy to make Juicebox possible." msgstr "" diff --git a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/AboutPanel/AboutPanel.tsx b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/AboutPanel/AboutPanel.tsx index 890ea0bbe4..8e81f3dadc 100644 --- a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/AboutPanel/AboutPanel.tsx +++ b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/AboutPanel/AboutPanel.tsx @@ -1,10 +1,18 @@ -import { t } from '@lingui/macro' +import { EnvelopeIcon } from '@heroicons/react/24/outline' +import { t, Trans } from '@lingui/macro' +import { Callout } from 'components/Callout/Callout' import { EmptyScreen } from 'components/Project/ProjectTabs/EmptyScreen' import { RichPreview } from 'components/RichPreview/RichPreview' +import { useProjectMetadataContext } from 'contexts/ProjectMetadataContext' import { useAboutPanel } from 'packages/v2v3/components/V2V3Project/ProjectDashboard/hooks/useAboutPanel' export const AboutPanel = () => { const { description } = useAboutPanel() + const { projectMetadata } = useProjectMetadataContext() + + const payDisclosure = projectMetadata?.payDisclosure + const name = projectMetadata?.name + return (
@@ -15,6 +23,22 @@ export const AboutPanel = () => { )} + {/* provide an anchorpoint */} + + {name && payDisclosure && ( + } + > + <> +
+ Notice from {name} +
+

{payDisclosure}

+ +
+ )}
) From 8f12477cc17a34cf6ed17e5297571c7461c55352 Mon Sep 17 00:00:00 2001 From: aeolian <94939382+aeolianeth@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:58:05 +1000 Subject: [PATCH 3/5] feat: countdown to first cycle --- .../CyclesPayoutsTab/CountdownCallout.tsx | 24 +++++++++++++++++++ src/locales/messages.pot | 3 +++ .../CyclesPayoutsPanel/CyclesPayoutsPanel.tsx | 19 ++++++++------- .../components/CurrentUpcomingSubPanel.tsx | 10 ++++++-- .../hooks/useCurrentUpcomingSubPanel.ts | 4 ++++ 5 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 src/components/Project/ProjectTabs/CyclesPayoutsTab/CountdownCallout.tsx diff --git a/src/components/Project/ProjectTabs/CyclesPayoutsTab/CountdownCallout.tsx b/src/components/Project/ProjectTabs/CyclesPayoutsTab/CountdownCallout.tsx new file mode 100644 index 0000000000..86cd8186b7 --- /dev/null +++ b/src/components/Project/ProjectTabs/CyclesPayoutsTab/CountdownCallout.tsx @@ -0,0 +1,24 @@ +import { ClockIcon } from '@heroicons/react/24/outline' +import { Trans } from '@lingui/macro' +import { useCountdownClock } from 'components/Project/hooks/useCountdownClock' +import { twMerge } from 'tailwind-merge' + +export function CountdownCallout({ + cycleStart, +}: { + cycleStart: number | undefined +}) { + const { remainingTimeText } = useCountdownClock(cycleStart) + + return ( +
+ + Starts in {remainingTimeText} +
+ ) +} diff --git a/src/locales/messages.pot b/src/locales/messages.pot index 42b56b7b73..6c75493759 100644 --- a/src/locales/messages.pot +++ b/src/locales/messages.pot @@ -3989,6 +3989,9 @@ msgstr "" msgid "tokens per ETH paid" msgstr "" +msgid "Starts in {remainingTimeText}" +msgstr "" + msgid "Congratulations!" msgstr "" diff --git a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/CyclesPayoutsPanel.tsx b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/CyclesPayoutsPanel.tsx index 151bd44d91..cc61a2cf40 100644 --- a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/CyclesPayoutsPanel.tsx +++ b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/CyclesPayoutsPanel.tsx @@ -1,7 +1,7 @@ import { Tab } from '@headlessui/react' import { t } from '@lingui/macro' import { CyclesTab } from 'components/Project/ProjectTabs/CyclesPayoutsTab/CyclesTab' -import { useMemo } from 'react' +import { useProjectContext } from '../../hooks/useProjectContext' import { CurrentUpcomingSubPanel } from './components/CurrentUpcomingSubPanel' import { HistorySubPanel } from './components/HistorySubPanel' @@ -11,14 +11,15 @@ type CyclesSubPanel = { } export const CyclesPayoutsPanel = () => { - const tabs: CyclesSubPanel[] = useMemo( - () => [ - { id: 'current', name: t`Current` }, - { id: 'upcoming', name: t`Upcoming` }, - { id: 'history', name: t`History` }, - ], - [], - ) + const { fundingCycle } = useProjectContext() + + const tabs: CyclesSubPanel[] = [ + // Don't show the current tab if there is no current cycle + fundingCycle?.number.gt(0) && { id: 'current', name: t`Current` }, + { id: 'upcoming', name: t`Upcoming` }, + { id: 'history', name: t`History` }, + ].filter(Boolean) as CyclesSubPanel[] + return (
diff --git a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/components/CurrentUpcomingSubPanel.tsx b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/components/CurrentUpcomingSubPanel.tsx index 367f158bd4..67803def08 100644 --- a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/components/CurrentUpcomingSubPanel.tsx +++ b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/components/CurrentUpcomingSubPanel.tsx @@ -1,5 +1,6 @@ import { InformationCircleIcon } from '@heroicons/react/24/outline' import { Trans, t } from '@lingui/macro' +import { CountdownCallout } from 'components/Project/ProjectTabs/CyclesPayoutsTab/CountdownCallout' import { currentCycleRemainingLengthTooltip } from 'components/Project/ProjectTabs/CyclesPayoutsTab/CyclesPanelTooltips' import { UpcomingCycleChangesCallout } from 'components/Project/ProjectTabs/CyclesPayoutsTab/UpcomingCycleChangesCallout' import { TitleDescriptionDisplayCard } from 'components/Project/ProjectTabs/TitleDescriptionDisplayCard' @@ -104,8 +105,13 @@ export const CurrentUpcomingSubPanel = ({ return (
- {id === 'upcoming' && ( - + )} + {id === 'upcoming' && info.cycleNumber && info.cycleNumber > 1 && ( + { return upcomingFundingCycle?.duration?.isZero() ?? true }, [fundingCycle?.duration, type, upcomingFundingCycle?.duration]) + const start = + type === 'current' ? fundingCycle?.start : upcomingFundingCycle?.start + const upcomingCycleLength = useMemo(() => { if (!upcomingFundingCycle) return if (cycleUnlocked) return '-' @@ -82,6 +85,7 @@ export const useCurrentUpcomingSubPanel = (type: 'current' | 'upcoming') => { cycleLength: upcomingCycleLength, cycleUnlocked, currentCycleUnlocked, + start, hasPendingConfiguration: /** * If a cycle is unlocked, it may have a pending change. From ca5b82f18a26787753fd1e40c874d5c2b3fdfc5b Mon Sep 17 00:00:00 2001 From: aeolian <94939382+aeolianeth@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:46:10 +1000 Subject: [PATCH 4/5] fix: cycle tabs loading weirdness --- .../components/CyclesPayoutsPanel/CyclesPayoutsPanel.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/CyclesPayoutsPanel.tsx b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/CyclesPayoutsPanel.tsx index cc61a2cf40..2a6ef9209e 100644 --- a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/CyclesPayoutsPanel.tsx +++ b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/CyclesPayoutsPanel/CyclesPayoutsPanel.tsx @@ -13,12 +13,12 @@ type CyclesSubPanel = { export const CyclesPayoutsPanel = () => { const { fundingCycle } = useProjectContext() - const tabs: CyclesSubPanel[] = [ + const tabs: CyclesSubPanel[] = fundingCycle ? [ // Don't show the current tab if there is no current cycle - fundingCycle?.number.gt(0) && { id: 'current', name: t`Current` }, + fundingCycle.number.gt(0) && { id: 'current', name: t`Current` }, { id: 'upcoming', name: t`Upcoming` }, { id: 'history', name: t`History` }, - ].filter(Boolean) as CyclesSubPanel[] + ].filter(Boolean) as CyclesSubPanel[] : [] return ( From e6141ee5c67a7dc2b97d3a61334d048a4e1abeee Mon Sep 17 00:00:00 2001 From: aeolian <94939382+aeolianeth@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:10:17 +1000 Subject: [PATCH 5/5] feat: disable pay in cycle=0 --- src/locales/messages.pot | 12 +++- .../FirstCycleCountdownCallout.tsx | 30 ++++++++++ .../PayRedeemCard/PayRedeemCard.tsx | 55 +++++++++++++------ 3 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/FirstCycleCountdownCallout.tsx diff --git a/src/locales/messages.pot b/src/locales/messages.pot index 6c75493759..9ab838e6a6 100644 --- a/src/locales/messages.pot +++ b/src/locales/messages.pot @@ -554,9 +554,6 @@ msgstr "" msgid "If locked, this payout can't be edited or removed until the lock expires or the cycle is edited." msgstr "" -msgid "Project isn't currently issuing tokens, but is issuing NFTs" -msgstr "" - msgid "I understand" msgstr "" @@ -2411,6 +2408,9 @@ msgstr "" msgid "Export a list of this cycle's reserved token recipients to CSV." msgstr "" +msgid "Payments open in {remainingTimeText}" +msgstr "" + msgid "Redeem" msgstr "" @@ -2873,6 +2873,9 @@ msgstr "" msgid "Collection details" msgstr "" +msgid "{0} isn't currently issuing tokens" +msgstr "" + msgid "Token ticker is required" msgstr "" @@ -4007,6 +4010,9 @@ msgstr "" msgid "Amount (ETH)" msgstr "" +msgid "{0} is currently only issuing NFTs" +msgstr "" + msgid "You haven't created any projects yet!" msgstr "" diff --git a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/FirstCycleCountdownCallout.tsx b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/FirstCycleCountdownCallout.tsx new file mode 100644 index 0000000000..3089ba99e5 --- /dev/null +++ b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/FirstCycleCountdownCallout.tsx @@ -0,0 +1,30 @@ +import { ClockIcon } from '@heroicons/react/24/outline' +import { Trans } from '@lingui/macro' +import { useCountdownClock } from 'components/Project/hooks/useCountdownClock' +import { useProjectMetadataContext } from 'contexts/ProjectMetadataContext' +import { useProjectUpcomingFundingCycle } from 'packages/v2v3/hooks/contractReader/useProjectUpcomingFundingCycle' +import { twMerge } from 'tailwind-merge' + +export function FirstCycleCountdownCallout() { + const { projectId } = useProjectMetadataContext() + + // inefficient extra call, but meh + const fc = useProjectUpcomingFundingCycle({ projectId }) + const start = fc?.data?.[0]?.start?.toNumber() + const { remainingTimeText } = useCountdownClock(start) + + if (!start) { + return null + } + return ( +
+ + Payments open in {remainingTimeText} +
+ ) +} diff --git a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/PayRedeemCard.tsx b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/PayRedeemCard.tsx index 934eab322e..c89ea7576b 100644 --- a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/PayRedeemCard.tsx +++ b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/PayRedeemCard.tsx @@ -55,6 +55,7 @@ import { projectCartActions } from '../../redux/projectCartSlice' import { ClaimErc20Callout } from '../ClaimErc20Callout' import { EthPerTokenAccordion } from '../EthPerTokenAccordion' import { ProjectCartNftReward } from '../ReduxProjectCartProvider' +import { FirstCycleCountdownCallout } from './FirstCycleCountdownCallout' import { PayProjectModal } from './PayProjectModal/PayProjectModal' const MAX_AMOUNT = BigInt(Number.MAX_SAFE_INTEGER) @@ -75,6 +76,7 @@ type PayRedeemCardProps = { export const PayRedeemCard: React.FC = ({ className }) => { const project = useProjectContext() + const metadata = useProjectMetadataContext() const state = useProjectSelector(state => state.payRedeem.cardState) const dispatch = useProjectDispatch() // TODO: We should probably break out tokens panel hook into reusable module @@ -119,6 +121,9 @@ export const PayRedeemCard: React.FC = ({ className }) => { } const noticeText = useMemo(() => { + if (project.fundingCycle?.number?.isZero()) { + return + } const showPayerIssuance = !payerIssuanceRate.enabled && !payerIssuanceRate.loading if (!showPayerIssuance) { @@ -127,13 +132,20 @@ export const PayRedeemCard: React.FC = ({ className }) => { const showNfts = hasNfts && !hasNftsLoading if (showNfts) { - return t`Project isn't currently issuing tokens, but is issuing NFTs` + return t`${metadata.projectMetadata?.name} is currently only issuing NFTs` } - return t`Project isn't currently issuing tokens` - }, [payerIssuanceRate, hasNfts, hasNftsLoading]) + return t`${metadata.projectMetadata?.name} isn't currently issuing tokens` + }, [ + payerIssuanceRate, + hasNfts, + hasNftsLoading, + metadata, + project.fundingCycle, + ]) const redeemDisabled = + project.fundingCycle?.number?.isZero() || project.fundingCycleMetadata?.redemptionRate.eq(0) || isInfiniteDistributionLimit(project.distributionLimit) @@ -183,15 +195,17 @@ export const PayRedeemCard: React.FC = ({ className }) => { - {!payerIssuanceRate.enabled && !payerIssuanceRate.loading && ( - } - > - {noticeText} - - )} + {!payerIssuanceRate.enabled && + !payerIssuanceRate.loading && + noticeText && ( + } + > + {noticeText} + + )} @@ -443,7 +457,7 @@ const PayConfiguration: React.FC = ({ payerIssuanceRate, }) => { const { payDisabled, message } = usePayProjectDisabled() - const { tokenSymbol } = useProjectContext() + const { tokenSymbol, fundingCycle } = useProjectContext() const chosenNftRewards = useProjectSelector( state => state.projectCart.chosenNftRewards, ) @@ -516,13 +530,22 @@ const PayConfiguration: React.FC = ({ insufficientBalance || cartPayAmount === 0 || !cartPayAmount || - payDisabled + payDisabled || + fundingCycle?.number?.isZero() ) - }, [cartPayAmount, insufficientBalance, payDisabled, walletConnected]) + }, [ + cartPayAmount, + insufficientBalance, + payDisabled, + walletConnected, + fundingCycle, + ]) return (
-
+ {fundingCycle?.number?.isZero() && } + +