diff --git a/src/components/AccountSettingsDashboard/components/ProjectUnwatchCell.tsx b/src/components/AccountSettingsDashboard/components/ProjectUnwatchCell.tsx index c3759da52f..be54400bf7 100644 --- a/src/components/AccountSettingsDashboard/components/ProjectUnwatchCell.tsx +++ b/src/components/AccountSettingsDashboard/components/ProjectUnwatchCell.tsx @@ -1,9 +1,9 @@ import { useProjectHandleText } from 'hooks/useProjectHandleText' import { useProjectMetadata } from 'hooks/useProjectMetadata' import Link from 'next/link' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { useMemo } from 'react' import { twMerge } from 'tailwind-merge' -import { v2v3ProjectRoute } from 'utils/routes' import { useProjectUnwatchCellData } from '../hooks/useProjectUnwatchCellData' import { UnwatchButton } from './UnwatchButton' diff --git a/src/components/Create/components/pages/ProjectDetails/ProjectDetailsPage.tsx b/src/components/Create/components/pages/ProjectDetails/ProjectDetailsPage.tsx index ee3d20a30d..707b5b4ebe 100644 --- a/src/components/Create/components/pages/ProjectDetails/ProjectDetailsPage.tsx +++ b/src/components/Create/components/pages/ProjectDetails/ProjectDetailsPage.tsx @@ -9,7 +9,6 @@ import FormattedNumberInput from 'components/inputs/FormattedNumberInput' import { FormImageUploader } from 'components/inputs/FormImageUploader' import { JuiceTextArea } from 'components/inputs/JuiceTextArea' import { JuiceInput } from 'components/inputs/JuiceTextInput' -import PrefixedInput from 'components/inputs/PrefixedInput' import { RichEditor } from 'components/RichEditor' import { CREATE_FLOW } from 'constants/fathomEvents' import { constants } from 'ethers' @@ -133,7 +132,7 @@ export const ProjectDetailsPage: React.FC< - + @@ -277,3 +276,39 @@ const AmountInput = ({ ) } + +// Exists just to solve an issue where a user might paste a twitter url instead of just the handle +export const TwitterHandleInputWrapper = ({ + value, + onChange, +}: { + value?: string + onChange?: (val: string) => void +}) => { + const [_value, _setValue] = useState(value ?? '') + const setValue = onChange ?? _setValue + value = value ?? _value + + const onInputChange = useCallback( + (value: string | undefined) => { + const httpOrHttpsRegex = /^(http|https):\/\// + if (value?.length && value.match(httpOrHttpsRegex)) { + const handle = value.split('/').pop() + if (handle) { + setValue(handle) + return + } + } + setValue(value ?? '') + }, + [setValue], + ) + + return ( + onInputChange(e.target.value)} + prefix="@" + /> + ) +} diff --git a/src/components/Create/components/pages/ReviewDeploy/ReviewDeployPage.tsx b/src/components/Create/components/pages/ReviewDeploy/ReviewDeployPage.tsx index c7132a21d9..f4a1e81c33 100644 --- a/src/components/Create/components/pages/ReviewDeploy/ReviewDeployPage.tsx +++ b/src/components/Create/components/pages/ReviewDeploy/ReviewDeployPage.tsx @@ -16,7 +16,7 @@ import { useDispatch } from 'react-redux' import { useAppSelector } from 'redux/hooks/useAppSelector' import { useSetCreateFurthestPageReached } from 'redux/hooks/useEditingCreateFurthestPageReached' import { editingV2ProjectActions } from 'redux/slices/editingV2Project' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { CreateBadge } from '../../CreateBadge' import { CreateCollapse } from '../../CreateCollapse/CreateCollapse' import { Wizard } from '../../Wizard/Wizard' diff --git a/src/components/Home/FaqList/QAs.tsx b/src/components/Home/FaqList/QAs.tsx index 1651d32c2e..bf2680663f 100644 --- a/src/components/Home/FaqList/QAs.tsx +++ b/src/components/Home/FaqList/QAs.tsx @@ -2,7 +2,7 @@ import { Trans } from '@lingui/macro' import ExternalLink from 'components/ExternalLink' import Link from 'next/link' import { ReactNode } from 'react' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' const JB_FEE = 2.5 diff --git a/src/components/Home/HomepageProjectCard.tsx b/src/components/Home/HomepageProjectCard.tsx index 75d7e9ec23..641175d84d 100644 --- a/src/components/Home/HomepageProjectCard.tsx +++ b/src/components/Home/HomepageProjectCard.tsx @@ -6,7 +6,7 @@ import ETHAmount from 'components/currency/ETHAmount' import { PV_V2 } from 'constants/pv' import { useProjectMetadata } from 'hooks/useProjectMetadata' import { SubgraphQueryProject } from 'models/subgraphProjects' -import { v2v3ProjectRoute } from 'utils/routes' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' function Statistic({ name, diff --git a/src/components/Home/JuicyPicksSection/SpotlightProjectCard.tsx b/src/components/Home/JuicyPicksSection/SpotlightProjectCard.tsx index 5070664e54..84efcf289e 100644 --- a/src/components/Home/JuicyPicksSection/SpotlightProjectCard.tsx +++ b/src/components/Home/JuicyPicksSection/SpotlightProjectCard.tsx @@ -13,9 +13,9 @@ import { Project } from 'generated/graphql' import { useProjectMetadata } from 'hooks/useProjectMetadata' import { useProjectTrendingPercentageIncrease } from 'hooks/useProjectTrendingPercentageIncrease' import Link from 'next/link' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { twJoin } from 'tailwind-merge' import { ipfsUriToGatewayUrl } from 'utils/ipfs' -import { v2v3ProjectRoute } from 'utils/routes' function Statistic({ name, diff --git a/src/components/PayoutsTable/SwitchToUnlimitedModal.tsx b/src/components/PayoutsTable/SwitchToUnlimitedModal.tsx index c01782ee70..4d3af63535 100644 --- a/src/components/PayoutsTable/SwitchToUnlimitedModal.tsx +++ b/src/components/PayoutsTable/SwitchToUnlimitedModal.tsx @@ -1,7 +1,7 @@ import { Trans } from '@lingui/macro' import { Modal } from 'antd' import { ExternalLinkWithIcon } from 'components/ExternalLinkWithIcon' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' export function SwitchToUnlimitedModal({ open, diff --git a/src/components/Project/ProjectHeader/EditProjectHandleButton.tsx b/src/components/Project/ProjectHeader/EditProjectHandleButton.tsx index 1aab19889e..4cb86dd029 100644 --- a/src/components/Project/ProjectHeader/EditProjectHandleButton.tsx +++ b/src/components/Project/ProjectHeader/EditProjectHandleButton.tsx @@ -4,8 +4,8 @@ import { Button, Tooltip } from 'antd' import { ProjectMetadataContext } from 'contexts/ProjectMetadataContext' import Link from 'next/link' import { V2V3ProjectContext } from 'packages/v2v3/contexts/Project/V2V3ProjectContext' +import { settingsPagePath } from 'packages/v2v3/utils/routes' import { useContext } from 'react' -import { settingsPagePath } from 'utils/routes' export function EditProjectHandleButton() { const { projectId } = useContext(ProjectMetadataContext) diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/AdvancedDropdown.tsx b/src/components/Project/ProjectSettings/AdvancedDropdown.tsx similarity index 100% rename from src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/AdvancedDropdown.tsx rename to src/components/Project/ProjectSettings/AdvancedDropdown.tsx diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/EditCycleFormSection.tsx b/src/components/Project/ProjectSettings/EditCycleFormSection.tsx similarity index 100% rename from src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/EditCycleFormSection.tsx rename to src/components/Project/ProjectSettings/EditCycleFormSection.tsx diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/EditCycleHeader.tsx b/src/components/Project/ProjectSettings/EditCycleHeader.tsx similarity index 100% rename from src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/EditCycleHeader.tsx rename to src/components/Project/ProjectSettings/EditCycleHeader.tsx diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectDetailsSettingsPage/ProjectDetailsForm.tsx b/src/components/Project/ProjectSettings/ProjectDetailsForm.tsx similarity index 100% rename from src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectDetailsSettingsPage/ProjectDetailsForm.tsx rename to src/components/Project/ProjectSettings/ProjectDetailsForm.tsx diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx index ba76b1d585..259bfda4d9 100644 --- a/src/components/ProjectCard.tsx +++ b/src/components/ProjectCard.tsx @@ -6,11 +6,11 @@ import { useProjectHandleText } from 'hooks/useProjectHandleText' import Link from 'next/link' import { isHardArchived } from 'utils/archived' import { formatDate } from 'utils/format/formatDate' -import { v2v3ProjectRoute } from 'utils/routes' import { useProjectMetadata } from 'hooks/useProjectMetadata' import { useSubtitle } from 'hooks/useSubtitle' import { SubgraphQueryProject } from 'models/subgraphProjects' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { ArchivedBadge } from './ArchivedBadge' import Loading from './Loading' import ProjectLogo from './ProjectLogo' diff --git a/src/components/Projects/TrendingProjectCard.tsx b/src/components/Projects/TrendingProjectCard.tsx index a650d0c239..58e5624dbe 100644 --- a/src/components/Projects/TrendingProjectCard.tsx +++ b/src/components/Projects/TrendingProjectCard.tsx @@ -9,7 +9,7 @@ import { useProjectMetadata } from 'hooks/useProjectMetadata' import { useProjectTrendingPercentageIncrease } from 'hooks/useProjectTrendingPercentageIncrease' import { DBProject } from 'models/dbProject' import Link from 'next/link' -import { v2v3ProjectRoute } from 'utils/routes' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { TRENDING_WINDOW_DAYS } from './RankingExplanation' export default function TrendingProjectCard({ diff --git a/src/components/QuickProjectSearch/QuickProjectSearchModal.tsx b/src/components/QuickProjectSearch/QuickProjectSearchModal.tsx index 75edaa4504..fe0c702054 100644 --- a/src/components/QuickProjectSearch/QuickProjectSearchModal.tsx +++ b/src/components/QuickProjectSearch/QuickProjectSearchModal.tsx @@ -16,9 +16,9 @@ import { useDBProjectsQuery } from 'hooks/useDBProjects' import { useRouter } from 'next/router' import V1ProjectHandle from 'packages/v1/components/shared/V1ProjectHandle' import V2V3ProjectHandleLink from 'packages/v2v3/components/shared/V2V3ProjectHandleLink' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import React, { useCallback, useContext, useEffect, useState } from 'react' import { twMerge } from 'tailwind-merge' -import { v2v3ProjectRoute } from 'utils/routes' import { QuickProjectSearchContext } from './QuickProjectSearchContext' const INPUT_ID = 'quickProjectSearch' diff --git a/src/components/WalletContributionCard.tsx b/src/components/WalletContributionCard.tsx index ae1b37c4d0..ab32fb69f6 100644 --- a/src/components/WalletContributionCard.tsx +++ b/src/components/WalletContributionCard.tsx @@ -4,9 +4,9 @@ import { PV_V2 } from 'constants/pv' import { WalletContributionsQuery } from 'generated/graphql' import { useProjectMetadata } from 'hooks/useProjectMetadata' import Link from 'next/link' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { isHardArchived } from 'utils/archived' import { formatDate } from 'utils/format/formatDate' -import { v2v3ProjectRoute } from 'utils/routes' import { ArchivedBadge } from './ArchivedBadge' import ETHAmount from './currency/ETHAmount' diff --git a/src/components/buttons/ErrorNotificationButtons.tsx b/src/components/buttons/ErrorNotificationButtons.tsx index ee33f1a7fc..e4ffae3a33 100644 --- a/src/components/buttons/ErrorNotificationButtons.tsx +++ b/src/components/buttons/ErrorNotificationButtons.tsx @@ -2,7 +2,7 @@ import { WarningOutlined } from '@ant-design/icons' import { Trans } from '@lingui/macro' import { Button } from 'antd' import { LanguageProvider } from 'contexts/Language/LanguageProvider' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import ExternalLink from '../ExternalLink' const resetSite = () => { diff --git a/src/components/formItems/ProjectTwitter.tsx b/src/components/formItems/ProjectTwitter.tsx index 6a513859e2..5230ee6147 100644 --- a/src/components/formItems/ProjectTwitter.tsx +++ b/src/components/formItems/ProjectTwitter.tsx @@ -1,6 +1,7 @@ import { t } from '@lingui/macro' -import { Form, Input } from 'antd' +import { Form } from 'antd' +import { TwitterHandleInputWrapper } from 'components/Create/components/pages/ProjectDetails/ProjectDetailsPage' import { FormItemExt } from './formItemExt' export default function ProjectTwitter({ @@ -14,12 +15,7 @@ export default function ProjectTwitter({ label={hideLabel ? undefined : t`Twitter handle`} {...formItemProps} > - + ) } diff --git a/src/components/inputs/ReconfigurationStrategy/CustomStrategyInput.tsx b/src/components/inputs/ReconfigurationStrategy/CustomStrategyInput.tsx index 55b294d9b9..fbb8e13593 100644 --- a/src/components/inputs/ReconfigurationStrategy/CustomStrategyInput.tsx +++ b/src/components/inputs/ReconfigurationStrategy/CustomStrategyInput.tsx @@ -7,7 +7,7 @@ import { useWallet } from 'hooks/Wallet' import { FormItemInput } from 'models/formItemInput' import { NetworkName } from 'models/networkName' import { MouseEventHandler } from 'react' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' export const CustomStrategyInput: React.FC< React.PropsWithChildren< diff --git a/src/components/modals/LegalNoticeModal.tsx b/src/components/modals/LegalNoticeModal.tsx index 211b75e501..206cc28864 100644 --- a/src/components/modals/LegalNoticeModal.tsx +++ b/src/components/modals/LegalNoticeModal.tsx @@ -1,7 +1,7 @@ import { t } from '@lingui/macro' import { Modal, ModalProps } from 'antd' import ExternalLink from 'components/ExternalLink' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' export function LegalNoticeModal(props: ModalProps) { return ( diff --git a/src/components/strings.tsx b/src/components/strings.tsx index ba6a63167b..36d781c32f 100644 --- a/src/components/strings.tsx +++ b/src/components/strings.tsx @@ -44,7 +44,8 @@ export const LOCKED_PAYOUT_EXPLANATION = ( import ExternalLink from 'components/ExternalLink' import Link from 'next/link' -import { helpPagePath, v2v3ProjectRoute } from 'utils/routes' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' +import { helpPagePath } from 'utils/helpPagePath' export const DISTRIBUTION_LIMIT_EXPLANATION = ( diff --git a/src/packages/v1/components/V1Project/V1ProjectHeader/ProjectHeader.tsx b/src/packages/v1/components/V1Project/V1ProjectHeader/ProjectHeader.tsx index ab59b6d399..c872287a24 100644 --- a/src/packages/v1/components/V1Project/V1ProjectHeader/ProjectHeader.tsx +++ b/src/packages/v1/components/V1Project/V1ProjectHeader/ProjectHeader.tsx @@ -10,10 +10,10 @@ import { ProjectTagsList } from 'components/ProjectTags/ProjectTagsList' import { ProjectMetadataContext } from 'contexts/ProjectMetadataContext' import { useGnosisSafe } from 'hooks/safe/useGnosisSafe' import { ContractVersionSelect } from 'packages/v2v3/components/V2V3Project/V2V3ProjectHeaderActions/ContractVersionSelect' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { useContext } from 'react' import { twMerge } from 'tailwind-merge' import { ipfsUriToGatewayUrl } from 'utils/ipfs' -import { v2v3ProjectRoute } from 'utils/routes' import SocialLinks from './SocialLinks' function ProjectSubheading({ diff --git a/src/packages/v1/components/shared/forms/BudgetForm.tsx b/src/packages/v1/components/shared/forms/BudgetForm.tsx index d2f7bb1ee9..98ae72f9fe 100644 --- a/src/packages/v1/components/shared/forms/BudgetForm.tsx +++ b/src/packages/v1/components/shared/forms/BudgetForm.tsx @@ -19,7 +19,7 @@ import { useAppDispatch } from 'redux/hooks/useAppDispatch' import { useEditingV1FundingCycleSelector } from 'redux/hooks/useAppSelector' import { editingProjectActions } from 'redux/slices/editingProject' import { fromWad } from 'utils/format/formatNumber' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { CYCLE_EXPLANATION, diff --git a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/PayProjectModal/PayProjectModal.tsx b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/PayProjectModal/PayProjectModal.tsx index 53e4a0124c..466aede953 100644 --- a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/PayProjectModal/PayProjectModal.tsx +++ b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/PayRedeemCard/PayProjectModal/PayProjectModal.tsx @@ -5,7 +5,7 @@ import { JuiceModal } from 'components/modals/JuiceModal' import { Formik } from 'formik' import Image from "next/legacy/image" import { twMerge } from 'tailwind-merge' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { MessageSection } from './components/MessageSection' import { ReceiveSection } from './components/ReceiveSection' import { diff --git a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/SuccessPayView/SuccessPayView.tsx b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/SuccessPayView/SuccessPayView.tsx index 4d3bd5a3eb..6d99be376b 100644 --- a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/SuccessPayView/SuccessPayView.tsx +++ b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/SuccessPayView/SuccessPayView.tsx @@ -4,7 +4,7 @@ import { Button } from 'antd' import { SubscribeButton } from 'components/buttons/SubscribeButton/SubscribeButton' import dynamic from 'next/dynamic' import Link from 'next/link' -import { v2v3ProjectRoute } from 'utils/routes' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { SuccessNftItem } from './components/SuccessNftItem' import { SuccessPayCard } from './components/SuccessPayCard' import { SuccessTokensItem } from './components/SuccessTokensItem' diff --git a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/V2V3ProjectHeader.tsx b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/V2V3ProjectHeader.tsx index 6cd2a4d221..dca6c7b878 100644 --- a/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/V2V3ProjectHeader.tsx +++ b/src/packages/v2v3/components/V2V3Project/ProjectDashboard/components/V2V3ProjectHeader.tsx @@ -18,8 +18,8 @@ import { useV2V3ProjectHeader } from 'packages/v2v3/components/V2V3Project/Proje import V2V3ProjectHandleLink from 'packages/v2v3/components/shared/V2V3ProjectHandleLink' import { useV2V3WalletHasPermission } from 'packages/v2v3/hooks/contractReader/useV2V3WalletHasPermission' import { V2V3OperatorPermission } from 'packages/v2v3/models/v2v3Permissions' +import { settingsPagePath, v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { twMerge } from 'tailwind-merge' -import { settingsPagePath, v2v3ProjectRoute } from 'utils/routes' import { SocialLink } from '../hooks/useAboutPanel' export const V2V3ProjectHeader = ({ className }: { className?: string }) => { diff --git a/src/packages/v2v3/components/V2V3Project/V2V3FundingCycleSection/FundingCycleDetails/DataSourceListItems/index.tsx b/src/packages/v2v3/components/V2V3Project/V2V3FundingCycleSection/FundingCycleDetails/DataSourceListItems/index.tsx index c3129c05d7..fa2ee206eb 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3FundingCycleSection/FundingCycleDetails/DataSourceListItems/index.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3FundingCycleSection/FundingCycleDetails/DataSourceListItems/index.tsx @@ -15,7 +15,7 @@ import { JB721DelegateContractsContext } from 'packages/v2v3/contexts/NftRewards import { V2V3FundingCycleMetadata } from 'packages/v2v3/models/fundingCycle' import { useContext } from 'react' import { formatBoolean } from 'utils/format/formatBoolean' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { FundingCycleListItem } from '../FundingCycleListItem' function DataSourceAddressValue({ address }: { address: string | undefined }) { diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectContractsDashboard/V2V3ProjectContractsDashboard.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectContractsDashboard/V2V3ProjectContractsDashboard.tsx index e44681ec0c..bab80c47d7 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectContractsDashboard/V2V3ProjectContractsDashboard.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectContractsDashboard/V2V3ProjectContractsDashboard.tsx @@ -15,8 +15,8 @@ import { SUPPORTED_PAYMENT_TERMINALS, V2V3ContractName, } from 'packages/v2v3/models/contracts' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { useContext } from 'react' -import { v2v3ProjectRoute } from 'utils/routes' import { V2V3ProjectHeaderActions } from '../V2V3ProjectHeaderActions/V2V3ProjectHeaderActions' /** diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectHeaderActions/V2V3ProjectHeaderActions.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectHeaderActions/V2V3ProjectHeaderActions.tsx index f7f20216fd..24d5312268 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectHeaderActions/V2V3ProjectHeaderActions.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectHeaderActions/V2V3ProjectHeaderActions.tsx @@ -11,8 +11,8 @@ import { V2V3ProjectToolsDrawer } from 'packages/v2v3/components/V2V3Project/V2V import { V2V3ProjectContext } from 'packages/v2v3/contexts/Project/V2V3ProjectContext' import { useV2V3WalletHasPermission } from 'packages/v2v3/hooks/contractReader/useV2V3WalletHasPermission' import { V2V3OperatorPermission } from 'packages/v2v3/models/v2v3Permissions' +import { settingsPagePath } from 'packages/v2v3/utils/routes' import { useContext, useState } from 'react' -import { settingsPagePath } from 'utils/routes' export function V2V3ProjectHeaderActions() { const wallet = useWallet() diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/ProjectSettingsLayout.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/ProjectSettingsLayout.tsx index bf6994a242..4fb78b79f7 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/ProjectSettingsLayout.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/ProjectSettingsLayout.tsx @@ -3,8 +3,8 @@ import { Trans } from '@lingui/macro' import { ProjectMetadataContext } from 'contexts/ProjectMetadataContext' import Link from 'next/link' import { V2V3ProjectContext } from 'packages/v2v3/contexts/Project/V2V3ProjectContext' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { useContext } from 'react' -import { v2v3ProjectRoute } from 'utils/routes' export const ProjectSettingsLayout: React.FC = ({ children, diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/TransactionSuccessModal.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/TransactionSuccessModal.tsx index 8c0b06e5aa..2e4e819e0a 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/TransactionSuccessModal.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/TransactionSuccessModal.tsx @@ -4,8 +4,8 @@ import { Button, Modal } from 'antd' import { ProjectMetadataContext } from 'contexts/ProjectMetadataContext' import Link from 'next/link' import { V2V3ProjectContext } from 'packages/v2v3/contexts/Project/V2V3ProjectContext' +import { settingsPagePath, v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { ReactNode, useContext } from 'react' -import { settingsPagePath, v2v3ProjectRoute } from 'utils/routes' export function TransactionSuccessModal({ open, diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/hooks/useSettingsPagePath.ts b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/hooks/useSettingsPagePath.ts index 86a62f5de9..75ce7c13aa 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/hooks/useSettingsPagePath.ts +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/hooks/useSettingsPagePath.ts @@ -1,7 +1,7 @@ import { ProjectMetadataContext } from 'contexts/ProjectMetadataContext' import { V2V3ProjectContext } from 'packages/v2v3/contexts/Project/V2V3ProjectContext' +import { settingsPagePath } from 'packages/v2v3/utils/routes' import { useContext } from 'react' -import { settingsPagePath } from 'utils/routes' import { V2V3SettingsPageKey } from '../ProjectSettingsDashboard' export function useSettingsPagePath(key?: V2V3SettingsPageKey) { diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/DetailsSection/DetailsSection.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/DetailsSection/DetailsSection.tsx index 4941fec10b..afe2125b65 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/DetailsSection/DetailsSection.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/DetailsSection/DetailsSection.tsx @@ -1,6 +1,6 @@ import { Trans } from '@lingui/macro' +import { EditCycleHeader } from 'components/Project/ProjectSettings/EditCycleHeader' import { CYCLE_EXPLANATION } from 'components/strings' -import { EditCycleHeader } from '../EditCycleHeader' import CycleDeadlineDropdown from './CycleDeadlineDropdown' import { DetailsSectionAdvanced } from './DetailsSectionAdvanced' import { DurationFields } from './DurationFields' diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/DetailsSection/DetailsSectionAdvanced.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/DetailsSection/DetailsSectionAdvanced.tsx index 51be8a0aa3..c3a865bc23 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/DetailsSection/DetailsSectionAdvanced.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/DetailsSection/DetailsSectionAdvanced.tsx @@ -1,5 +1,6 @@ import { Trans } from '@lingui/macro' import { Form } from 'antd' +import { AdvancedDropdown } from 'components/Project/ProjectSettings/AdvancedDropdown' import TooltipLabel from 'components/TooltipLabel' import { JuiceSwitch } from 'components/inputs/JuiceSwitch' import { @@ -8,7 +9,6 @@ import { TERMINAL_CONFIG_EXPLANATION, TERMINAL_MIGRATION_EXPLANATION, } from 'components/strings' -import { AdvancedDropdown } from '../AdvancedDropdown' export function DetailsSectionAdvanced() { return ( diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/EditCyclePage.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/EditCyclePage.tsx index 3b4e67276e..74075e44c3 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/EditCyclePage.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/EditCyclePage.tsx @@ -2,15 +2,16 @@ import { Trans } from '@lingui/macro' import { Button, Form, Tooltip } from 'antd' import { ExternalLinkWithIcon } from 'components/ExternalLinkWithIcon' import Loading from 'components/Loading' +import EditCycleFormSection from 'components/Project/ProjectSettings/EditCycleFormSection' import { ProjectMetadataContext } from 'contexts/ProjectMetadataContext' import Link from 'next/link' import { useRouter } from 'next/router' import { V2V3ProjectContext } from 'packages/v2v3/contexts/Project/V2V3ProjectContext' +import { settingsPagePath } from 'packages/v2v3/utils/routes' import { useContext, useEffect, useRef, useState } from 'react' -import { helpPagePath, settingsPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { DetailsSection } from './DetailsSection' import { useEditCycleFormContext } from './EditCycleFormContext' -import EditCycleFormSection from './EditCycleFormSection' import { PayoutsSection } from './PayoutsSection/PayoutsSection' import { ReviewConfirmModal } from './ReviewConfirmModal' import { TokensSection } from './TokensSection' diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/PayoutsSection/PayoutsSection.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/PayoutsSection/PayoutsSection.tsx index 2815f10631..ebac1f6221 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/PayoutsSection/PayoutsSection.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/PayoutsSection/PayoutsSection.tsx @@ -2,10 +2,10 @@ import { Trans } from '@lingui/macro' import { Form } from 'antd' import { useWatch } from 'antd/lib/form/Form' import { JuiceSwitch } from 'components/inputs/JuiceSwitch' +import { AdvancedDropdown } from 'components/Project/ProjectSettings/AdvancedDropdown' import { CurrencyName } from 'constants/currency' import { PayoutsTable } from 'packages/v2v3/components/shared/PayoutsTable/PayoutsTable' import { Split } from 'packages/v2v3/models/splits' -import { AdvancedDropdown } from '../AdvancedDropdown' import { useEditCycleFormContext } from '../EditCycleFormContext' export function PayoutsSection() { diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/IssuanceRateReductionField.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/IssuanceRateReductionField.tsx index 9110cfd87b..b7347298ab 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/IssuanceRateReductionField.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/IssuanceRateReductionField.tsx @@ -3,7 +3,7 @@ import { ExternalLinkWithIcon } from 'components/ExternalLinkWithIcon' import { JuiceSwitch } from 'components/inputs/JuiceSwitch' import NumberSlider from 'components/inputs/NumberSlider' import { useState } from 'react' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { useEditCycleFormContext } from '../EditCycleFormContext' import { zeroPercentDisabledNoticed } from './RedemptionRateField' diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/RedemptionRateField.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/RedemptionRateField.tsx index 4fbd5367e2..d0fbb6f64c 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/RedemptionRateField.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/RedemptionRateField.tsx @@ -5,7 +5,7 @@ import { TokenRedemptionRateGraph } from 'components/TokenRedemptionRateGraph/To import { JuiceSwitch } from 'components/inputs/JuiceSwitch' import NumberSlider from 'components/inputs/NumberSlider' import { useState } from 'react' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { useEditCycleFormContext } from '../EditCycleFormContext' export const zeroPercentDisabledNoticed = ( diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/ReservedTokensField.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/ReservedTokensField.tsx index a430826b70..a8d0312a8a 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/ReservedTokensField.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/ReservedTokensField.tsx @@ -4,13 +4,13 @@ import { ExternalLinkWithIcon } from 'components/ExternalLinkWithIcon' import { FormItems } from 'components/formItems' import { ItemNoInput } from 'components/formItems/ItemNoInput' import { JuiceSwitch } from 'components/inputs/JuiceSwitch' +import { AdvancedDropdown } from 'components/Project/ProjectSettings/AdvancedDropdown' import { Split } from 'packages/v2v3/models/splits' import { SPLITS_TOTAL_PERCENT } from 'packages/v2v3/utils/math' import { totalSplitsPercent } from 'packages/v2v3/utils/v2v3Splits' import { useState } from 'react' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { V2V3EditReservedTokens } from '../../ReservedTokensSettingsPage/V2V3EditReservedTokens' -import { AdvancedDropdown } from '../AdvancedDropdown' import { useEditCycleFormContext } from '../EditCycleFormContext' import { zeroPercentDisabledNoticed } from './RedemptionRateField' diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/TokensSection.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/TokensSection.tsx index ee6f2329d6..4e961c6e62 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/TokensSection.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/TokensSection.tsx @@ -1,5 +1,5 @@ import { Trans } from '@lingui/macro' -import { EditCycleHeader } from '../EditCycleHeader' +import { EditCycleHeader } from 'components/Project/ProjectSettings/EditCycleHeader' import { MintRateField } from './MintRateField' import { TokensSectionAdvanced } from './TokensSectionAdvanced' diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/TokensSectionAdvanced.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/TokensSectionAdvanced.tsx index 80afa59cae..742ed459f1 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/TokensSectionAdvanced.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/EditCyclePage/TokensSection/TokensSectionAdvanced.tsx @@ -1,7 +1,7 @@ import { Trans } from '@lingui/macro' import { Form } from 'antd' import { JuiceSwitch } from 'components/inputs/JuiceSwitch' -import { AdvancedDropdown } from '../AdvancedDropdown' +import { AdvancedDropdown } from 'components/Project/ProjectSettings/AdvancedDropdown' import { IssuanceRateReductionField } from './IssuanceRateReductionField' import { RedemptionRateField } from './RedemptionRateField' import { ReservedTokensField } from './ReservedTokensField' diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/PayoutsSettingsPage/V2V3EditPayouts.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/PayoutsSettingsPage/V2V3EditPayouts.tsx index d7d2c8b16f..0e9740d223 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/PayoutsSettingsPage/V2V3EditPayouts.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/PayoutsSettingsPage/V2V3EditPayouts.tsx @@ -19,11 +19,11 @@ import { PayoutCard } from 'packages/v2v3/components/shared/PayoutCard/PayoutCar import { V2V3CurrencyOption } from 'packages/v2v3/models/currencyOption' import { parseV2SplitsCsv } from 'packages/v2v3/utils/csv' import { isInfiniteDistributionLimit } from 'packages/v2v3/utils/fundingCycle' +import { settingsPagePath } from 'packages/v2v3/utils/routes' import { allocationToSplit, splitToAllocation } from 'packages/v2v3/utils/splitToAllocation' import { twMerge } from 'tailwind-merge' import { formatFundingTarget } from 'utils/format/formatFundingTarget' import { formatPercent } from 'utils/format/formatPercent' -import { settingsPagePath } from 'utils/routes' export const V2V3EditPayouts = ({ editingSplits, diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProcessHeldFeesPage/ProcessHeldFeesPage.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProcessHeldFeesPage/ProcessHeldFeesPage.tsx index ba62b3b41b..595c836628 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProcessHeldFeesPage/ProcessHeldFeesPage.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProcessHeldFeesPage/ProcessHeldFeesPage.tsx @@ -7,9 +7,10 @@ import { useHeldFeesOf } from 'packages/v2v3/hooks/contractReader/useHeldFeesOf' import { useV2V3WalletHasPermission } from 'packages/v2v3/hooks/contractReader/useV2V3WalletHasPermission' import { useProcessHeldFeesTx } from 'packages/v2v3/hooks/transactor/useProcessHeldFeesTx' import { V2V3OperatorPermission } from 'packages/v2v3/models/v2v3Permissions' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { useState } from 'react' +import { helpPagePath } from 'utils/helpPagePath' import { emitErrorNotification } from 'utils/notifications' -import { helpPagePath, v2v3ProjectRoute } from 'utils/routes' export function ProcessHeldFeesPage() { const [processingHeldFees, setProcessingHeldFees] = useState() diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectDetailsSettingsPage/ProjectDetailsSettingsPage.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectDetailsSettingsPage/ProjectDetailsSettingsPage.tsx index e7536cdaad..d0c8527a2a 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectDetailsSettingsPage/ProjectDetailsSettingsPage.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectDetailsSettingsPage/ProjectDetailsSettingsPage.tsx @@ -1,13 +1,11 @@ import { useForm } from 'antd/lib/form/Form' +import { ProjectDetailsForm, ProjectDetailsFormFields } from 'components/Project/ProjectSettings/ProjectDetailsForm' import { PROJECT_PAY_CHARACTER_LIMIT } from 'constants/numbers' import { PV_V2 } from 'constants/pv' import { ProjectMetadataContext } from 'contexts/ProjectMetadataContext' import { uploadProjectMetadata } from 'lib/api/ipfs' import { revalidateProject } from 'lib/api/nextjs' -import { - ProjectDetailsForm, - ProjectDetailsFormFields, -} from 'packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectDetailsSettingsPage/ProjectDetailsForm' + import { useEditProjectDetailsTx } from 'packages/v2v3/hooks/transactor/useEditProjectDetailsTx' import { useCallback, useContext, useEffect, useState } from 'react' import { withoutHttps } from 'utils/http' diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectHandleSettingsPage.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectHandleSettingsPage.tsx index 4640da9e83..cd2921db8d 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectHandleSettingsPage.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectSettings/pages/ProjectHandleSettingsPage.tsx @@ -14,8 +14,8 @@ import useProjectENSName from 'packages/v2v3/hooks/contractReader/useProjectENSN import { useProjectHandleENSTextRecord } from 'packages/v2v3/hooks/contractReader/useProjectHandleENSTextRecord' import { useEditV2V3ProjectHandleTx } from 'packages/v2v3/hooks/transactor/useEditV2V3ProjectHandleTx' import { useSetENSTextRecordForHandleTx } from 'packages/v2v3/hooks/transactor/useSetENSTextRecordForHandleTx' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { useCallback, useContext, useEffect, useState } from 'react' -import { v2v3ProjectRoute } from 'utils/routes' export function ProjectHandleSettingsPage() { const { handle } = useContext(V2V3ProjectContext) diff --git a/src/packages/v2v3/components/V2V3Project/V2V3ProjectToolsDrawer/V2V3ProjectToolsDrawer.tsx b/src/packages/v2v3/components/V2V3Project/V2V3ProjectToolsDrawer/V2V3ProjectToolsDrawer.tsx index 843dce8a41..8cff805718 100644 --- a/src/packages/v2v3/components/V2V3Project/V2V3ProjectToolsDrawer/V2V3ProjectToolsDrawer.tsx +++ b/src/packages/v2v3/components/V2V3Project/V2V3ProjectToolsDrawer/V2V3ProjectToolsDrawer.tsx @@ -12,12 +12,9 @@ import Link from 'next/link' import { V2V3ProjectContext } from 'packages/v2v3/contexts/Project/V2V3ProjectContext' import { useAddToBalanceTx } from 'packages/v2v3/hooks/transactor/AddToBalanceTx' import { useDeployProjectPayerTx } from 'packages/v2v3/hooks/transactor/useDeployProjectPayerTx' -import { - ETHPayoutSplitGroup, - ReservedTokensSplitGroup, -} from 'packages/v2v3/models/splits' +import { ETHPayoutSplitGroup, ReservedTokensSplitGroup } from 'packages/v2v3/models/splits' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { useContext } from 'react' -import { v2v3ProjectRoute } from 'utils/routes' import { ExportSplitsButton } from './ExportSplitsButton' import { PaymentAddressSection } from './PaymentAddressSection/PaymentAddressSection' diff --git a/src/packages/v2v3/components/shared/FeeTooltipLabel.tsx b/src/packages/v2v3/components/shared/FeeTooltipLabel.tsx index 56134f3b71..ca0ddc9dfa 100644 --- a/src/packages/v2v3/components/shared/FeeTooltipLabel.tsx +++ b/src/packages/v2v3/components/shared/FeeTooltipLabel.tsx @@ -8,7 +8,7 @@ import { V2V3CurrencyOption } from 'packages/v2v3/models/currencyOption' import { V2V3_CURRENCY_ETH } from 'packages/v2v3/utils/currency' import { amountSubFee, formatFee } from 'packages/v2v3/utils/math' import { formatWad } from 'utils/format/formatNumber' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' export const FeeTooltipLabel = ({ currency, diff --git a/src/packages/v2v3/components/shared/PayoutsTable/ConvertAmountsModal.tsx b/src/packages/v2v3/components/shared/PayoutsTable/ConvertAmountsModal.tsx index 6f1eb9f189..8fad5cbda0 100644 --- a/src/packages/v2v3/components/shared/PayoutsTable/ConvertAmountsModal.tsx +++ b/src/packages/v2v3/components/shared/PayoutsTable/ConvertAmountsModal.tsx @@ -27,7 +27,7 @@ import { } from 'redux/hooks/useEditingDistributionLimit' import { parseWad } from 'utils/format/formatNumber' import { formatPercent } from 'utils/format/formatPercent' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' export const ConvertAmountsModal = ({ open, diff --git a/src/packages/v2v3/components/shared/PayoutsTable/HeaderRows.tsx b/src/packages/v2v3/components/shared/PayoutsTable/HeaderRows.tsx index 4b3e50e921..4cf7f34c2a 100644 --- a/src/packages/v2v3/components/shared/PayoutsTable/HeaderRows.tsx +++ b/src/packages/v2v3/components/shared/PayoutsTable/HeaderRows.tsx @@ -8,7 +8,7 @@ import { AddEditAllocationModalEntity, } from 'packages/v2v3/components/shared/Allocation/AddEditAllocationModal' import { useState } from 'react' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { usePayoutsTableContext } from './context/PayoutsTableContext' import { usePayoutsTable } from './hooks/usePayoutsTable' import { PayoutTableSettings } from './PayoutTableSettings' diff --git a/src/packages/v2v3/components/shared/PayoutsTable/PayoutsTableBody.tsx b/src/packages/v2v3/components/shared/PayoutsTable/PayoutsTableBody.tsx index d9a80f6916..367c92ad48 100644 --- a/src/packages/v2v3/components/shared/PayoutsTable/PayoutsTableBody.tsx +++ b/src/packages/v2v3/components/shared/PayoutsTable/PayoutsTableBody.tsx @@ -59,9 +59,9 @@ export function PayoutsTableBody() { Address or ID - - - + {hasDistributionLimit ? + + : Percent} ) : null} {payoutSplits.map((payoutSplit, index) => ( diff --git a/src/packages/v2v3/components/shared/PayoutsTable/hooks/usePayoutsTable.tsx b/src/packages/v2v3/components/shared/PayoutsTable/hooks/usePayoutsTable.tsx index 801b4ddacb..b326897e3f 100644 --- a/src/packages/v2v3/components/shared/PayoutsTable/hooks/usePayoutsTable.tsx +++ b/src/packages/v2v3/components/shared/PayoutsTable/hooks/usePayoutsTable.tsx @@ -18,6 +18,7 @@ import { derivePayoutAmount, ensureSplitsSumTo100Percent, getNewDistributionLimit, + roundSplitPercents, } from 'packages/v2v3/utils/distributions' import { MAX_DISTRIBUTION_LIMIT, @@ -136,7 +137,7 @@ export const usePayoutsTable = () => { function _setPayoutSplits(splits: Split[]) { if (distributionLimitIsInfinite) { - setPayoutSplits?.(splits) + setPayoutSplits?.(roundSplitPercents( {splits })) } else { setPayoutSplits?.(ensureSplitsSumTo100Percent({ splits })) } diff --git a/src/packages/v2v3/components/shared/V2V3ProjectHandleLink.tsx b/src/packages/v2v3/components/shared/V2V3ProjectHandleLink.tsx index e21c0bd40f..916fbcf2fb 100644 --- a/src/packages/v2v3/components/shared/V2V3ProjectHandleLink.tsx +++ b/src/packages/v2v3/components/shared/V2V3ProjectHandleLink.tsx @@ -4,9 +4,9 @@ import ProjectLogo from 'components/ProjectLogo' import { PV_V2 } from 'constants/pv' import { useProjectHandleText } from 'hooks/useProjectHandleText' import Link from 'next/link' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { useMemo } from 'react' import { twMerge } from 'tailwind-merge' -import { v2v3ProjectRoute } from 'utils/routes' /** * Renders a link to a v2v3 project that displays its handle, or fallback text if handle is missing. diff --git a/src/packages/v2v3/components/shared/V2V3ProjectLink.tsx b/src/packages/v2v3/components/shared/V2V3ProjectLink.tsx index 4b1f767aa5..634caebe3a 100644 --- a/src/packages/v2v3/components/shared/V2V3ProjectLink.tsx +++ b/src/packages/v2v3/components/shared/V2V3ProjectLink.tsx @@ -1,8 +1,8 @@ import { Trans } from '@lingui/macro' import { AllocatorBadge } from 'components/AllocatorBadge' import Link from 'next/link' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { twMerge } from 'tailwind-merge' -import { v2v3ProjectRoute } from 'utils/routes' /** * Different from V2V3ProjectHandleLink in that it doesn't use the handle. This can be used outside of V2V3ContractsContext and V2V3ProjectContext. diff --git a/src/packages/v2v3/utils/distributions.ts b/src/packages/v2v3/utils/distributions.ts index f39a1168ec..84485de4f2 100644 --- a/src/packages/v2v3/utils/distributions.ts +++ b/src/packages/v2v3/utils/distributions.ts @@ -147,6 +147,15 @@ export function ensureSplitsSumTo100Percent({ return adjustedSplits } +export function roundSplitPercents({ splits }: { splits: Split[]}) { + return splits.map((split) => { + return { + ...split, + percent: Math.round(split.percent), + } + }) +} + /** * Adjusts exist split percents to stay the same amount when distribution limit is changed * @param splits {Split[]} - list of current splits to have their percents adjusted @@ -174,6 +183,7 @@ export function adjustedSplitPercents({ amount: currentAmount, distributionLimit: parseFloat(newDistributionLimit), }) + const adjustedSplit = { beneficiary: split.beneficiary, percent: newPercent, diff --git a/src/utils/routes.ts b/src/packages/v2v3/utils/routes.ts similarity index 82% rename from src/utils/routes.ts rename to src/packages/v2v3/utils/routes.ts index 69da8323bc..e6a0713a05 100644 --- a/src/utils/routes.ts +++ b/src/packages/v2v3/utils/routes.ts @@ -2,8 +2,6 @@ import { BigNumber, BigNumberish } from 'ethers' import { V2V3SettingsPageKey } from 'packages/v2v3/components/V2V3Project/V2V3ProjectSettings/ProjectSettingsDashboard' import qs from 'qs' -const HELP_PAGE_HOSTNAME = 'https://docs.juicebox.money' - export const v2v3ProjectRoute = ({ projectId, handle, @@ -20,10 +18,6 @@ export const v2v3ProjectRoute = ({ return `${route}${query ? `?${qs.stringify(query)}` : ''}` } -export function helpPagePath(path: string): string { - return new URL(path, HELP_PAGE_HOSTNAME).toString() -} - export const settingsPagePath = ( settingsPage?: V2V3SettingsPageKey, { diff --git a/src/packages/v4/components/FeeTooltipLabel.tsx b/src/packages/v4/components/FeeTooltipLabel.tsx index 317edc5d1f..f83ed38b6a 100644 --- a/src/packages/v4/components/FeeTooltipLabel.tsx +++ b/src/packages/v4/components/FeeTooltipLabel.tsx @@ -5,7 +5,7 @@ import CurrencySymbol from 'components/currency/CurrencySymbol' import { Ether } from 'juice-sdk-core' import { NativeTokenValue } from 'juice-sdk-react' import { formatWad } from 'utils/format/formatNumber' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { V4CurrencyOption } from '../models/v4CurrencyOption' import { V4_CURRENCY_ETH } from '../utils/currency' import { amountSubFee } from '../utils/math' diff --git a/src/packages/v4/components/PayoutsTable/ConvertAmountsModal.tsx b/src/packages/v4/components/PayoutsTable/ConvertAmountsModal.tsx index f2247cff25..53a9afecb8 100644 --- a/src/packages/v4/components/PayoutsTable/ConvertAmountsModal.tsx +++ b/src/packages/v4/components/PayoutsTable/ConvertAmountsModal.tsx @@ -5,7 +5,7 @@ import EthereumAddress from 'components/EthereumAddress' import { ExternalLinkWithIcon } from 'components/ExternalLinkWithIcon' import FormattedNumberInput from 'components/inputs/FormattedNumberInput' import { Parenthesis } from 'components/Parenthesis' -import { JBSplit as Split, SPLITS_TOTAL_PERCENT } from 'juice-sdk-core' +import { JBSplit as Split } from 'juice-sdk-core' import { V4CurrencyOption } from 'packages/v4/models/v4CurrencyOption' import { V4_CURRENCY_ETH, V4_CURRENCY_USD } from 'packages/v4/utils/currency' @@ -23,7 +23,7 @@ import { } from 'redux/hooks/useEditingDistributionLimit' import { parseWad } from 'utils/format/formatNumber' import { formatPercent } from 'utils/format/formatPercent' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import V4ProjectHandleLink from '../V4ProjectHandleLink' export const ConvertAmountsModal = ({ @@ -46,7 +46,7 @@ export const ConvertAmountsModal = ({ const totalPayoutsPercent = useMemo( () => splits - .map(s => (s.percent.toFloat() / SPLITS_TOTAL_PERCENT) * 100) + .map(s => s.percent.toFloat() * 100) .reduce((acc, curr) => acc + curr, 0), [splits], ) diff --git a/src/packages/v4/components/PayoutsTable/HeaderRows.tsx b/src/packages/v4/components/PayoutsTable/HeaderRows.tsx index 9706befc4f..e11b47ecb7 100644 --- a/src/packages/v4/components/PayoutsTable/HeaderRows.tsx +++ b/src/packages/v4/components/PayoutsTable/HeaderRows.tsx @@ -1,10 +1,10 @@ -import { PlusCircleIcon } from '@heroicons/react/24/outline' +import { PlusIcon } from '@heroicons/react/24/outline' import { Trans } from '@lingui/macro' import { Button } from 'antd' import { ExternalLinkWithIcon } from 'components/ExternalLinkWithIcon' import { PayoutsTableCell } from 'components/PayoutsTable/PayoutsTableCell' import { useState } from 'react' -import { helpPagePath } from 'utils/routes' +import { helpPagePath } from 'utils/helpPagePath' import { AddEditAllocationModal, AddEditAllocationModalEntity, @@ -62,7 +62,8 @@ export function HeaderRows() { + + ) : null} + {/* */} + + {/* */} + + + ) +} diff --git a/src/packages/v4/views/V4ProjectSettings/EditCyclePage/PayoutsSection.tsx b/src/packages/v4/views/V4ProjectSettings/EditCyclePage/PayoutsSection.tsx new file mode 100644 index 0000000000..d15732309e --- /dev/null +++ b/src/packages/v4/views/V4ProjectSettings/EditCyclePage/PayoutsSection.tsx @@ -0,0 +1,54 @@ +import { Trans } from '@lingui/macro' +import { Form } from 'antd' +import { useWatch } from 'antd/lib/form/Form' +import { JuiceSwitch } from 'components/inputs/JuiceSwitch' +import { AdvancedDropdown } from 'components/Project/ProjectSettings/AdvancedDropdown' +import { CurrencyName } from 'constants/currency' +import { JBSplit } from 'juice-sdk-core' +import { PayoutsTable } from 'packages/v4/components/PayoutsTable/PayoutsTable' +import { useEditCycleFormContext } from './EditCycleFormContext' + +export function PayoutsSection() { + const { editCycleForm } = useEditCycleFormContext() + const payoutSplits = useWatch('payoutSplits', editCycleForm) ?? [] + const currency = useWatch('payoutLimitCurrency', editCycleForm) ?? 'ETH' + const payoutLimit = useWatch('payoutLimit', editCycleForm) + + const setPayoutSplits = (payoutSplits: JBSplit[]) => + editCycleForm?.setFieldsValue({ payoutSplits }) + + const setCurrency = (currency: CurrencyName) => + editCycleForm?.setFieldsValue({ + payoutLimitCurrency: currency, + }) + + const setPayoutLimit = (payoutLimit: number | undefined) => + editCycleForm?.setFieldsValue({ payoutLimit }) + + return ( +
+ + + {/* "Enable unlimited payouts" switch? */} + + Hold fees in project} + description={ + + Fees are held in the project instead of being processed + automatically. + + } + /> + + +
+ ) +} diff --git a/src/packages/v4/views/V4ProjectSettings/EditCyclePage/hooks/useEditCycleFormHasError.tsx b/src/packages/v4/views/V4ProjectSettings/EditCyclePage/hooks/useEditCycleFormHasError.tsx new file mode 100644 index 0000000000..764645c9b2 --- /dev/null +++ b/src/packages/v4/views/V4ProjectSettings/EditCyclePage/hooks/useEditCycleFormHasError.tsx @@ -0,0 +1,33 @@ +import { Trans } from '@lingui/macro' +import { useWatch } from 'antd/lib/form/Form' +import { SPLITS_TOTAL_PERCENT } from 'juice-sdk-core' +import { totalSplitsPercent } from 'packages/v4/utils/v4Splits' +import { useEditCycleFormContext } from '../EditCycleFormContext' + +export function useEditCycleFormHasError() { + const { editCycleForm } = useEditCycleFormContext() + + const payoutSplits = useWatch('payoutSplits', editCycleForm) ?? [] + const reservedSplits = useWatch('reservedTokensSplits', editCycleForm) ?? [] + + const payoutSplitsPercentExceedsMax = + totalSplitsPercent(payoutSplits) > SPLITS_TOTAL_PERCENT + const reservedSplitsPercentExceedsMax = + totalSplitsPercent(reservedSplits) > SPLITS_TOTAL_PERCENT + + let error: JSX.Element | undefined + + if (payoutSplitsPercentExceedsMax && reservedSplitsPercentExceedsMax) { + error = ( + Payout and reserved token recipients cannot exceed 100% + ) + } else if (payoutSplitsPercentExceedsMax) { + error = Payouts cannot exceed 100% + } else if (reservedSplitsPercentExceedsMax) { + error = Reserved token recipients cannot exceed 100% + } + + return { + error, + } +} diff --git a/src/packages/v4/views/V4ProjectSettings/EditCyclePage/hooks/useLoadEditCycleData.tsx b/src/packages/v4/views/V4ProjectSettings/EditCyclePage/hooks/useLoadEditCycleData.tsx new file mode 100644 index 0000000000..d33170692e --- /dev/null +++ b/src/packages/v4/views/V4ProjectSettings/EditCyclePage/hooks/useLoadEditCycleData.tsx @@ -0,0 +1,97 @@ +import { Form } from 'antd' +import { useEffect, useState } from 'react' +import { + deriveDurationOption, + deriveDurationUnit, + secondsToOtherUnit, +} from 'utils/format/formatTime' + +import { useJBRuleset, useJBRulesetMetadata } from 'juice-sdk-react' +import { useJBUpcomingRuleset } from 'packages/v4/hooks/useJBUpcomingRuleset' +import { usePayoutLimit } from 'packages/v4/hooks/usePayoutLimit' +import { useV4CurrentPayoutSplits } from 'packages/v4/hooks/useV4PayoutSplits' +import { useV4ReservedSplits } from 'packages/v4/hooks/useV4ReservedSplits' +import { V4CurrencyName } from 'packages/v4/utils/currency' +import { EditCycleFormFields } from '../EditCycleFormFields' + +/** Loads project FC data directly into an AntD form instance */ +export const useLoadEditCycleData = () => { + const [initialFormData, setInitialFormData] = useState< + EditCycleFormFields | undefined + >(undefined) + + const { data: ruleset } = useJBRuleset() + const { data: rulesetMetadata } = useJBRulesetMetadata() + const { + ruleset: upcomingRuleset, + } = useJBUpcomingRuleset() + + const { splits: reservedTokensSplits } = useV4ReservedSplits() + const { splits: payoutSplits } = useV4CurrentPayoutSplits() + const { data: payoutLimit } = usePayoutLimit() + + const [editCycleForm] = Form.useForm() + + useEffect(() => { + if ( + ruleset && + rulesetMetadata + ) { + const duration = Number(ruleset.duration) + + const issuanceRate = upcomingRuleset?.weight.toFloat() ?? 0 + const reservedPercent = rulesetMetadata.reservedPercent.formatPercentage() + // : DefaultTokenSettings.reservedTokensPercentage + + const decayPercent = ruleset.decayPercent.formatPercentage() + // : DefaultTokenSettings.discountRate + + const redemptionRate = rulesetMetadata.redemptionRate.formatPercentage() + // : DefaultTokenSettings.redemptionRate + + const allowOwnerMinting = rulesetMetadata.allowOwnerMinting + // : DefaultTokenSettings.tokenMinting + + const tokenTransfers = !rulesetMetadata.pauseCreditTransfers + // : DefaultTokenSettings.pauseTransfers + + const formData: EditCycleFormFields = { + duration: secondsToOtherUnit({ + duration, + unit: deriveDurationUnit(duration), + }), + durationUnit: deriveDurationOption(duration), + approvalHook: ruleset.approvalHook, + allowSetTerminals: + rulesetMetadata.allowSetTerminals, + allowSetController: + rulesetMetadata.allowSetController, + allowTerminalMigration: + rulesetMetadata.allowTerminalMigration, + pausePay: rulesetMetadata.pausePay, + payoutSplits, + payoutLimit: payoutLimit ? Number(payoutLimit.amount) : undefined, // TODO: format + payoutLimitCurrency: V4CurrencyName(payoutLimit?.currency) ?? 'ETH', + holdFees: rulesetMetadata?.holdFees, + issuanceRate, + reservedPercent, + reservedTokensSplits, + decayPercent, + redemptionRate, + allowOwnerMinting, + tokenTransfers, + // nftRewards: currentProjectData.nftRewards, + // useDataSourceForRedeem: + // rulesetMetadata.useDataSourceForRedeem, + memo: '', + } + setInitialFormData(formData) + editCycleForm.setFieldsValue(formData) + } + }, [ruleset, rulesetMetadata]) + + return { + initialFormData, + editCycleForm, + } +} diff --git a/src/packages/v4/views/V4ProjectSettings/ProjectDetailsSettingsPage/ProjectDetailsSettingsPage.tsx b/src/packages/v4/views/V4ProjectSettings/ProjectDetailsSettingsPage/ProjectDetailsSettingsPage.tsx new file mode 100644 index 0000000000..7adeacfc05 --- /dev/null +++ b/src/packages/v4/views/V4ProjectSettings/ProjectDetailsSettingsPage/ProjectDetailsSettingsPage.tsx @@ -0,0 +1,145 @@ +import { useForm } from 'antd/lib/form/Form' +import { ProjectDetailsForm, ProjectDetailsFormFields } from 'components/Project/ProjectSettings/ProjectDetailsForm' +import { PROJECT_PAY_CHARACTER_LIMIT } from 'constants/numbers' +import { PV_V2 } from 'constants/pv' +import { ProjectMetadataContext } from 'contexts/ProjectMetadataContext' +import { uploadProjectMetadata } from 'lib/api/ipfs' +import { revalidateProject } from 'lib/api/nextjs' + +import { useEditProjectDetailsTx } from 'packages/v2v3/hooks/transactor/useEditProjectDetailsTx' +import { useCallback, useContext, useEffect, useState } from 'react' +import { withoutHttps } from 'utils/http' +import { emitInfoNotification } from 'utils/notifications' + +export function ProjectDetailsSettingsPage() { + const { projectId } = useContext(ProjectMetadataContext) + const { projectMetadata, refetchProjectMetadata } = useContext( + ProjectMetadataContext, + ) + + const [loadingSaveChanges, setLoadingSaveChanges] = useState() + const [projectForm] = useForm() + + const editV2ProjectDetailsTx = useEditProjectDetailsTx() // v4Todo: V4 tx + + const onProjectFormSaved = useCallback(async () => { + setLoadingSaveChanges(true) + + const fields = projectForm.getFieldsValue(true) + + const uploadedMetadata = await uploadProjectMetadata({ + ...projectMetadata, + name: fields.name, + description: fields.description, + projectTagline: fields.projectTagline, + projectRequiredOFACCheck: fields.projectRequiredOFACCheck, + logoUri: fields.logoUri, + coverImageUri: fields.coverImageUri, + infoUri: fields.infoUri, + twitter: fields.twitter, + discord: fields.discord, + telegram: fields.telegram, + payButton: fields.payButton.substring(0, PROJECT_PAY_CHARACTER_LIMIT), // Enforce limit + payDisclosure: fields.payDisclosure, + tags: fields.tags, + }) + + if (!uploadedMetadata.Hash) { + setLoadingSaveChanges(false) + return + } + + const txSuccess = await editV2ProjectDetailsTx( + { + cid: uploadedMetadata.Hash, + }, + { + onConfirmed: async () => { + setLoadingSaveChanges(false) + + emitInfoNotification('Project details saved', { + description: 'Your project details have been saved.', + }) + + if (projectId) { + await revalidateProject({ + pv: PV_V2, + projectId: String(projectId), + }) + } + refetchProjectMetadata() + }, + onError: () => { + setLoadingSaveChanges(false) + }, + onCancelled: () => { + setLoadingSaveChanges(false) + }, + }, + ) + + if (!txSuccess) { + setLoadingSaveChanges(false) + } + }, [ + editV2ProjectDetailsTx, + projectForm, + projectId, + refetchProjectMetadata, + projectMetadata, + ]) + + const resetProjectForm = useCallback(() => { + const infoUri = withoutHttps(projectMetadata?.infoUri ?? '') + const discord = withoutHttps(projectMetadata?.discord ?? '') + const telegram = withoutHttps(projectMetadata?.telegram ?? '') + projectForm.setFieldsValue({ + name: projectMetadata?.name ?? '', + infoUri, + logoUri: projectMetadata?.logoUri ?? '', + coverImageUri: projectMetadata?.coverImageUri ?? '', + description: projectMetadata?.description ?? '', + projectTagline: projectMetadata?.projectTagline ?? '', + projectRequiredOFACCheck: + projectMetadata?.projectRequiredOFACCheck ?? false, + twitter: projectMetadata?.twitter ?? '', + discord, + telegram, + payButton: projectMetadata?.payButton ?? '', + payDisclosure: projectMetadata?.payDisclosure ?? '', + tags: projectMetadata?.tags ?? [], + }) + }, [ + projectForm, + projectMetadata?.name, + projectMetadata?.infoUri, + projectMetadata?.logoUri, + projectMetadata?.coverImageUri, + projectMetadata?.description, + projectMetadata?.projectTagline, + projectMetadata?.projectRequiredOFACCheck, + projectMetadata?.twitter, + projectMetadata?.discord, + projectMetadata?.telegram, + projectMetadata?.payButton, + projectMetadata?.payDisclosure, + projectMetadata?.tags, + ]) + + // initially fill form with any existing redux state + useEffect(() => { + // Bug with antd - required to make sure form is reset after initial render + setTimeout(() => { + resetProjectForm() + }, 0) + }, [resetProjectForm]) + + return ( + + ) +} diff --git a/src/packages/v4/views/V4ProjectSettings/ProjectSettingsContent.tsx b/src/packages/v4/views/V4ProjectSettings/ProjectSettingsContent.tsx new file mode 100644 index 0000000000..71dc282669 --- /dev/null +++ b/src/packages/v4/views/V4ProjectSettings/ProjectSettingsContent.tsx @@ -0,0 +1,120 @@ +import { ChevronRightIcon } from '@heroicons/react/20/solid' +import { ArrowLeftIcon } from '@heroicons/react/24/outline' +import { Trans, t } from '@lingui/macro' +import { Button, Layout } from 'antd' +import Link from 'next/link' +import { V2V3ProjectContext } from 'packages/v2v3/contexts/Project/V2V3ProjectContext' +import { useContext, useMemo } from 'react' +import { twJoin } from 'tailwind-merge' +import { isZeroAddress } from 'utils/address' +import { EditCyclePage } from './EditCyclePage/EditCyclePage' +import { useSettingsPagePath } from './hooks/useSettingsPagePath' +import { ProjectDetailsSettingsPage } from './ProjectDetailsSettingsPage/ProjectDetailsSettingsPage' +import { SettingsPageKey } from './ProjectSettingsDashboard' +import { ProjectSettingsLayout } from './ProjectSettingsLayout' + +const SettingsPageComponents: { + [k in SettingsPageKey]: () => JSX.Element | null +} = { + general: ProjectDetailsSettingsPage, + handle: () => null, //ProjectHandleSettingsPage, + cycle: EditCyclePage, + // nfts: () => null, //EditNftsPage, + payouts: () => null, //PayoutsSettingsPage, + reservedtokens: () => null, //ReservedTokensSettingsPage, + transferownership: () => null, //TransferOwnershipSettingsPage, + archiveproject: () => null, //ArchiveProjectSettingsPage, + heldfees: () => null, //ProcessHeldFeesPage, + createerc20: () => null, //CreateErc20TokenSettingsPage, +} + +const V4SettingsPageKeyTitleMap = ( + hasExistingNfts: boolean, +): { + [k in SettingsPageKey]: string +} => ({ + general: t`General`, + handle: t`Project handle`, + cycle: t`Cycle configuration`, + payouts: t`Payouts`, + reservedtokens: t`Reserved token recipients`, + // nfts: hasExistingNfts ? t`Edit NFT collection` : t`Launch New NFT Collection`, + transferownership: t`Transfer ownership`, + archiveproject: t`Archive project`, + heldfees: t`Process held fees`, + createerc20: t`Create ERC-20 token`, +}) + +function Breadcrumbs({ + pageTitle, + settingsPageKey, + className, +}: { + pageTitle: string + settingsPageKey: SettingsPageKey + className: string +}) { + return ( +
    +
  • + + Manage + +
  • + + + +
  • + + {pageTitle} + +
  • +
+ ) +} + +export function ProjectSettingsContent({ + settingsPageKey, +}: { + settingsPageKey: SettingsPageKey +}) { + const { fundingCycleMetadata } = useContext(V2V3ProjectContext) + const hasExistingNfts = !isZeroAddress(fundingCycleMetadata?.dataSource) + + const ActiveSettingsPage = useMemo( + () => SettingsPageComponents[settingsPageKey], + [settingsPageKey], + ) + + const pageTitle = + V4SettingsPageKeyTitleMap(hasExistingNfts)[settingsPageKey] + + return ( + + + + + + +

+ {pageTitle} +

+ + + + +
+ ) +} diff --git a/src/packages/v4/views/V4ProjectSettings/ProjectSettingsDashboard.tsx b/src/packages/v4/views/V4ProjectSettings/ProjectSettingsDashboard.tsx new file mode 100644 index 0000000000..da2c5c8d41 --- /dev/null +++ b/src/packages/v4/views/V4ProjectSettings/ProjectSettingsDashboard.tsx @@ -0,0 +1,207 @@ +import { Trans } from '@lingui/macro' +import { Button } from 'antd' +import EthereumAddress from 'components/EthereumAddress' +import Loading from 'components/Loading' +import { NativeTokenValue, useJBContractContext, useJBProjectMetadataContext } from 'juice-sdk-react' +import Link from 'next/link' +import { useV4BalanceOfNativeTerminal } from 'packages/v4/hooks/useV4BalanceOfNativeTerminal' +import useProjectOwnerOf from 'packages/v4/hooks/useV4ProjectOwnerOf' +import { useV4WalletHasPermission } from 'packages/v4/hooks/useV4WalletHasPermission' +import { V4OperatorPermission } from 'packages/v4/models/v4Permissions' +import { useV4DistributableAmount } from '../V4ProjectDashboard/V4ProjectTabs/V4CyclesPayoutsPanel/hooks/useV4DistributableAmount' +import { ProjectSettingsLayout } from './ProjectSettingsLayout' +import { useSettingsPagePath } from './hooks/useSettingsPagePath' + +export type SettingsPageKey = + | 'general' + | 'handle' + | 'cycle' + // | 'nfts' + | 'payouts' + | 'reservedtokens' + | 'transferownership' + | 'archiveproject' + | 'heldfees' + | 'createerc20' + +function SettingsCard({ children }: { children: React.ReactNode }) { + return ( +
+ {children} +
+ ) +} + +function SettingsGroupCard({ + title, + subtitle, + children, +}: { + title: string | JSX.Element + subtitle: string | JSX.Element + children: React.ReactNode +}) { + return ( + +
{title}
+
{subtitle}
+ {children} +
+ ) +} + +export function ProjectSettingsDashboard() { + const { data: projectOwnerAddress } = useProjectOwnerOf() + const { data: balance, isLoading: loading } = useV4BalanceOfNativeTerminal() + + const { projectId } = useJBContractContext() + const { metadata } = useJBProjectMetadataContext() + + const { distributableAmount } = useV4DistributableAmount() + const projectHasErc20Token = false // @v4TODO + const hasIssueTicketsPermission = useV4WalletHasPermission( + V4OperatorPermission.MINT_TOKENS, + ) + + const projectMetadata = metadata?.data + + const canCreateErc20Token = !projectHasErc20Token && hasIssueTicketsPermission + + const erc20Path = useSettingsPagePath('createerc20') + + return ( + +
+ + {projectMetadata ? ( +
+
+
+
+ {projectMetadata.name} +
+
+ <>Project #{projectId.toString()} +
+
+ + + + Owned by: + + +
+
+
+ Project balance +
+
+ +
+
+
+ ) : ( + + )} +
+ + +
+
+
+ Available payout +
+
+ {!loading ? ( + + ) : ( + + )} +
+
+ + + +
+
+
+ +
+

+ Project settings +

+ +
+ General} + subtitle={Update basic project details} + > +
    +
  • + + Basic details + +
  • + {/*
  • + + Project handle + +
  • */} +
+
+ + Cycle configuration} + subtitle={ + Make changes to your cycle settings and rules + } + > + + Edit next cycle + + + Tools} + subtitle={Extended functionality for project owners} + > +
    + {canCreateErc20Token && ( +
  • + + Create ERC-20 Token + +
  • + )} +
  • + + Process held fees + +
  • +
+
+ Manage} + subtitle={Manage your project's state and ownership} + > +
    +
  • + + Transfer ownership + +
  • +
  • + + Archive + +
  • +
+
+
+
+
+ ) +} diff --git a/src/packages/v4/views/V4ProjectSettings/ProjectSettingsLayout.tsx b/src/packages/v4/views/V4ProjectSettings/ProjectSettingsLayout.tsx new file mode 100644 index 0000000000..8ed7317947 --- /dev/null +++ b/src/packages/v4/views/V4ProjectSettings/ProjectSettingsLayout.tsx @@ -0,0 +1,35 @@ +import { Cog6ToothIcon, XMarkIcon } from '@heroicons/react/24/solid' +import { Trans } from '@lingui/macro' +import { useJBContractContext } from 'juice-sdk-react' +import Link from 'next/link' +import { v4ProjectRoute } from 'packages/v4/utils/routes' +import { useChainId } from 'wagmi' + +export const ProjectSettingsLayout: React.FC = ({ + children, +}) => { + const { projectId } = useJBContractContext() + const chainId = useChainId() + + return ( + <> +
+
+

+ + Manage project +

+ + + + +
+
+ +
{children}
+ + ) +} diff --git a/src/packages/v4/views/V4ProjectSettings/hooks/useSettingsPagePath.ts b/src/packages/v4/views/V4ProjectSettings/hooks/useSettingsPagePath.ts new file mode 100644 index 0000000000..01e84b44b7 --- /dev/null +++ b/src/packages/v4/views/V4ProjectSettings/hooks/useSettingsPagePath.ts @@ -0,0 +1,11 @@ +import { useJBContractContext } from 'juice-sdk-react' +import { settingsPagePath } from 'packages/v4/utils/routes' +import { useChainId } from 'wagmi' +import { SettingsPageKey } from '../ProjectSettingsDashboard' + +export function useSettingsPagePath(key?: SettingsPageKey) { + const { projectId } = useJBContractContext() + const chainId = useChainId() + + return settingsPagePath({ projectId: Number(projectId), chainId }, key, ) +} diff --git a/src/pages/v2/p/[projectId]/safe/index.tsx b/src/pages/v2/p/[projectId]/safe/index.tsx index 7eb75594a9..82a6f23c87 100644 --- a/src/pages/v2/p/[projectId]/safe/index.tsx +++ b/src/pages/v2/p/[projectId]/safe/index.tsx @@ -5,9 +5,9 @@ import { TransactionProvider } from 'contexts/Transaction/TransactionProvider' import { useRouter } from 'next/router' import { V2V3ProjectContext } from 'packages/v2v3/contexts/Project/V2V3ProjectContext' import { V2V3ProjectPageProvider } from 'packages/v2v3/contexts/V2V3ProjectPageProvider' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' import { useContext } from 'react' import globalGetServerSideProps from 'utils/next-server/globalGetServerSideProps' -import { v2v3ProjectRoute } from 'utils/routes' function V2V3ProjectSafeDashboard() { const { handle, projectOwnerAddress } = useContext(V2V3ProjectContext) diff --git a/src/pages/v4/[chainName]/p/[projectId]/settings/[settingsPage].tsx b/src/pages/v4/[chainName]/p/[projectId]/settings/[settingsPage].tsx new file mode 100644 index 0000000000..2921a2f462 --- /dev/null +++ b/src/pages/v4/[chainName]/p/[projectId]/settings/[settingsPage].tsx @@ -0,0 +1,22 @@ +import { useRouter } from 'next/router' +import { V4SettingsProvider } from 'packages/v4/contexts/V4SettingsProvider' +import { ProjectSettingsContent } from 'packages/v4/views/V4ProjectSettings/ProjectSettingsContent' +import { SettingsPageKey } from 'packages/v4/views/V4ProjectSettings/ProjectSettingsDashboard' +import globalGetServerSideProps from 'utils/next-server/globalGetServerSideProps' + +export default function V4CycleSettingsPage() { + const router = useRouter() + + const { settingsPage } = router.query + if (!settingsPage) return null + + return ( + + + + ) +} + +export const getServerSideProps = globalGetServerSideProps diff --git a/src/pages/v4/[chainName]/p/[projectId]/settings/index.tsx b/src/pages/v4/[chainName]/p/[projectId]/settings/index.tsx new file mode 100644 index 0000000000..527f24677f --- /dev/null +++ b/src/pages/v4/[chainName]/p/[projectId]/settings/index.tsx @@ -0,0 +1,13 @@ +import { V4SettingsProvider } from 'packages/v4/contexts/V4SettingsProvider' +import { ProjectSettingsDashboard } from 'packages/v4/views/V4ProjectSettings/ProjectSettingsDashboard' +import globalGetServerSideProps from 'utils/next-server/globalGetServerSideProps' + +export default function V4ProjectSettingsPage() { + return ( + + + + ) +} + +export const getServerSideProps = globalGetServerSideProps diff --git a/src/utils/helpPagePath.ts b/src/utils/helpPagePath.ts new file mode 100644 index 0000000000..75224bc717 --- /dev/null +++ b/src/utils/helpPagePath.ts @@ -0,0 +1,5 @@ +const HELP_PAGE_HOSTNAME = 'https://docs.juicebox.money' + +export function helpPagePath(path: string): string { + return new URL(path, HELP_PAGE_HOSTNAME).toString() +} diff --git a/src/utils/sgDbProjects.ts b/src/utils/sgDbProjects.ts index 324a499df3..d696e65d0f 100644 --- a/src/utils/sgDbProjects.ts +++ b/src/utils/sgDbProjects.ts @@ -228,8 +228,6 @@ export function formatSgProjectsForUpdate({ return propertiesToUpdate.length }) - // console.log('asdf', { changedSubgraphProjects }) - return { subgraphProjects, updatedProperties,