Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cloudflare] New Demo Mode #2668

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,5 @@ VITE_APP_SITE_URL="https://app.dev.decentdao.org"
# WalletConnect Cloud Project ID
VITE_APP_WALLET_CONNECT_PROJECT_ID=""

# FEATURE FLAGS (Must equal "ON")
VITE_APP_FLAG_DEVELOPMENT_MODE=""
VITE_APP_FLAG_DEMO_MODE=""

# Use legacy Netlify balances backend
VITE_APP_USE_LEGACY_BACKEND=""
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { WarningCircle } from '@phosphor-icons/react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { isDevMode } from '../../../constants/common';
import { getModeStatus } from '../../../hooks/utils/modes';
import { useDaoInfoStore } from '../../../store/daoInfo/useDaoInfoStore';
import { FractalModuleType, ICreationStepProps, VotingStrategyType } from '../../../types';
import { BigIntInput } from '../../ui/forms/BigIntInput';
Expand Down Expand Up @@ -78,8 +78,9 @@ export function AzoriusGovernance(props: ICreationStepProps) {

useStepRedirect({ values });

const [votingPeriodDays, setVotingPeriodDays] = useState(isDevMode() ? 0.0021 : 7);
const [timelockPeriodDays, setTimelockPeriodDays] = useState(isDevMode() ? 0 : 1);
const isDevMode = getModeStatus('DEV');
const [votingPeriodDays, setVotingPeriodDays] = useState(isDevMode ? 0.0021 : 7);
const [timelockPeriodDays, setTimelockPeriodDays] = useState(isDevMode ? 0 : 1);
const [executionPeriodDays, setExecutionPeriodDays] = useState(2);

useEffect(() => {
Expand Down
9 changes: 6 additions & 3 deletions src/components/Roles/RolePaymentDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { Address, getAddress, Hex } from 'viem';
import { useAccount, usePublicClient } from 'wagmi';
import { DETAILS_BOX_SHADOW, isDemoMode } from '../../constants/common';
import { DETAILS_BOX_SHADOW } from '../../constants/common';
import { DAO_ROUTES } from '../../constants/routes';
import { getModeStatus } from '../../hooks/utils/modes';
import { useNetworkConfigStore } from '../../providers/NetworkConfig/useNetworkConfigStore';
import { useDaoInfoStore } from '../../store/daoInfo/useDaoInfoStore';
import { useRolesStore } from '../../store/roles/useRolesStore';
Expand Down Expand Up @@ -145,6 +146,8 @@ export function RolePaymentDetails({
const { refreshWithdrawableAmount } = useRolesStore();
const navigate = useNavigate();
const publicClient = usePublicClient();
const isDemoMode = getModeStatus('DEMO');

const canWithdraw = useMemo(() => {
if (
connectedAccount &&
Expand All @@ -153,8 +156,8 @@ export function RolePaymentDetails({
) {
return true;
}
return isDemoMode();
}, [connectedAccount, payment.recipient, showWithdraw, roleHatWearerAddress]);
return isDemoMode;
}, [connectedAccount, payment.recipient, showWithdraw, roleHatWearerAddress, isDemoMode]);

const assignedTerm = useMemo(() => {
return roleTerms.find(term => term.termEndDate.getTime() === payment.endDate.getTime());
Expand Down
25 changes: 2 additions & 23 deletions src/components/Roles/forms/RoleFormPaymentStream.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Alert, Box, Button, Flex, FormControl, Icon, Show, Text } from '@chakra-ui/react';
import { ArrowRight, Info, Trash } from '@phosphor-icons/react';
import { addDays, addMinutes } from 'date-fns';
import { addDays } from 'date-fns';
import { Field, FieldProps, FormikErrors, useFormikContext } from 'formik';
import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { DETAILS_BOX_SHADOW, isDevMode } from '../../../constants/common';
import { DETAILS_BOX_SHADOW } from '../../../constants/common';
import { useRolesStore } from '../../../store/roles/useRolesStore';
import { RoleFormValues, RoleHatFormValue } from '../../../types/roles';
import { DatePicker } from '../../ui/forms/DatePicker';
Expand Down Expand Up @@ -215,27 +215,6 @@ export function RoleFormPaymentStream({ formIndex }: { formIndex: number }) {
{t('save')}
</Button>
)}
{isDevMode() && !canBeCancelled && (
<Button
onClick={() => {
if (payment === undefined) {
return;
}
const nowDate = new Date();
setFieldValue(`roleEditing.payments.${formIndex}`, {
...payment,
amount: {
value: '100',
bigintValue: 100000000000000000000n,
},
startDate: addMinutes(nowDate, 1),
endDate: addMinutes(nowDate, 10),
});
}}
>
Ze stream ends in 10!
</Button>
)}
{canBeCancelled && (
<Show above="md">
<Button
Expand Down
4 changes: 3 additions & 1 deletion src/components/ui/page/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, ComponentWithAs, Flex, Icon as ChakraIcon, IconProps } from '@chakra-ui/react';
import { Box, Icon as ChakraIcon, ComponentWithAs, Flex, IconProps } from '@chakra-ui/react';
import { DiscordLogo, Icon, TelegramLogo, XLogo } from '@phosphor-icons/react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
Expand All @@ -10,6 +10,7 @@ import {
URL_TWITTER,
URL_WARPCAST,
} from '../../../constants/url';
import { ModeButtons } from '../../../hooks/utils/modes';
import ExternalLink from '../links/ExternalLink';

function NavigationIconLink(props: {
Expand Down Expand Up @@ -94,6 +95,7 @@ export function Footer() {
DisplayIcon={DiscordLogo}
/>
</Flex>
<ModeButtons />
</Flex>
);
}
4 changes: 4 additions & 0 deletions src/components/ui/page/Global/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
FavoritesCacheValue,
} from '../../../../hooks/utils/cache/cacheDefaults';
import { setValue } from '../../../../hooks/utils/cache/useLocalStorage';
import { useInitializeModes } from '../../../../hooks/utils/modes';
import { getSafeName } from '../../../../hooks/utils/useGetSafeName';
import {
getNetworkConfig,
Expand Down Expand Up @@ -91,6 +92,9 @@ const useUpdateFavoritesCache = (onFavoritesUpdated: () => void) => {
export function Global() {
useUserTracking();

// Initialize all modes from URL parameters
useInitializeModes();

// Trigger a re-render when favorite names are updated
const [favoritesUpdatedTrigger, setFavoritesUpdatedTrigger] = useState(0);
useUpdateFavoritesCache(() => setFavoritesUpdatedTrigger(prev => prev + 1));
Expand Down
19 changes: 0 additions & 19 deletions src/constants/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,6 @@ export const SIDEBAR_WIDTH = '4.25rem';

export const MAX_CONTENT_WIDTH = '80rem';

const features = {
developmentMode: 'DEVELOPMENT_MODE',
demoMode: 'DEMO_MODE',
} as const;

type FeatureFlag = (typeof features)[keyof typeof features];

export const isFeatureEnabled = (feature: FeatureFlag) => {
const featureStatus = import.meta.env[`VITE_APP_FLAG_${feature}`];
if (featureStatus === 'ON') {
return true;
} else {
return false;
}
};

export const isDevMode = () => isFeatureEnabled(features.developmentMode);
export const isDemoMode = () => isFeatureEnabled(features.demoMode);

/**
* @dev DO NOT CHANGE THE SALT
* @note This SALT is used to generate the account address for the Hats Smart Account
Expand Down
97 changes: 97 additions & 0 deletions src/hooks/utils/modes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Button, Icon as ChakraIcon } from '@chakra-ui/react';
import { X } from '@phosphor-icons/react';
import { useCallback } from 'react';
import { useSearchParams } from 'react-router-dom';

export const MODE_QUERY_PARAMS = {
DEMO: 'demo_mode',
DEV: 'dev_mode',
} as const;

export const MODE_VALUES = {
ON: 'on',
OFF: 'off',
} as const;

type ModeTypesKeys = keyof typeof MODE_QUERY_PARAMS;
type ModeValueTypes = typeof MODE_VALUES;
type ModeValueTypesKeys = keyof ModeValueTypes;

function getModeStorageKey(modeType: ModeTypesKeys) {
return `decent_${MODE_QUERY_PARAMS[modeType]}`;
}

export function useInitializeModes() {
const [searchParams] = useSearchParams();

(Object.keys(MODE_QUERY_PARAMS) as Array<ModeTypesKeys>).forEach(modeType => {
const MODE_QUERY_PARAM = MODE_QUERY_PARAMS[modeType];
const MODE_STORAGE_KEY = getModeStorageKey(modeType);
const rawValue = searchParams.get(MODE_QUERY_PARAM)?.toLowerCase();

if (rawValue === MODE_VALUES.ON) {
localStorage.setItem(MODE_STORAGE_KEY, MODE_VALUES.ON);
} else if (rawValue === MODE_VALUES.OFF) {
localStorage.setItem(MODE_STORAGE_KEY, MODE_VALUES.OFF);
}
});
}

export function getModeStatus(modeType: ModeTypesKeys): boolean {
try {
const MODE_STORAGE_KEY = getModeStorageKey(modeType);
return localStorage.getItem(MODE_STORAGE_KEY) === MODE_VALUES.ON;
} catch {
return false;
}
}

function useToggleMode() {
const [searchParams] = useSearchParams();

return useCallback(
(modeType: ModeTypesKeys, modeValue: ModeValueTypes[ModeValueTypesKeys]) => {
const newParams = new URLSearchParams(searchParams);
newParams.set(MODE_QUERY_PARAMS[modeType], modeValue);
window.location.href = `${window.location.pathname}?${newParams.toString()}`;
},
[searchParams],
);
}

function ModeToggleButton({ modeType }: { modeType: ModeTypesKeys }) {
const handleToggleMode = useToggleMode();

return (
<Button
size="sm"
variant="secondary"
onClick={() => handleToggleMode(modeType, MODE_VALUES.OFF)}
pr="0.3rem"
>
{modeType}
<ChakraIcon
as={X}
boxSize="16px"
position="relative"
/>
</Button>
);
}

export function ModeButtons() {
DarksightKellar marked this conversation as resolved.
Show resolved Hide resolved
const modes = Object.keys(MODE_QUERY_PARAMS) as Array<ModeTypesKeys>;

return (
<>
{modes
.filter(modeType => getModeStatus(modeType))
.map(modeType => (
<ModeToggleButton
key={modeType}
modeType={modeType}
/>
))}
</>
);
}
8 changes: 5 additions & 3 deletions src/hooks/utils/useCanUserSubmitProposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { abis } from '@fractal-framework/fractal-contracts';
import { useCallback, useEffect, useState } from 'react';
import { Address, getContract } from 'viem';
import { useAccount, usePublicClient } from 'wagmi';
import { isDemoMode } from '../../constants/common';
import { useFractal } from '../../providers/App/AppProvider';
import { useSafeAPI } from '../../providers/App/hooks/useSafeAPI';
import { useDaoInfoStore } from '../../store/daoInfo/useDaoInfoStore';
import { GovernanceType } from '../../types';
import { getModeStatus } from './modes';
import useVotingStrategiesAddresses from './useVotingStrategiesAddresses';

export function useCanUserCreateProposal() {
Expand All @@ -27,6 +27,8 @@ export function useCanUserCreateProposal() {

const { getVotingStrategies } = useVotingStrategiesAddresses();

const isDemoMode = getModeStatus('DEMO');

/**
* Performs a check whether user has access rights to create proposal for DAO
* @param {string} safeAddress - parameter to verify that user can create proposal for this specific DAO.
Expand Down Expand Up @@ -117,13 +119,13 @@ export function useCanUserCreateProposal() {

useEffect(() => {
const loadCanUserCreateProposal = async () => {
const newCanCreateProposal = isDemoMode() || (await getCanUserCreateProposal());
const newCanCreateProposal = isDemoMode || (await getCanUserCreateProposal());
if (newCanCreateProposal !== canUserCreateProposal) {
setCanUserCreateProposal(newCanCreateProposal);
}
};
loadCanUserCreateProposal();
}, [getCanUserCreateProposal, canUserCreateProposal]);
}, [getCanUserCreateProposal, canUserCreateProposal, isDemoMode]);

return { canUserCreateProposal, getCanUserCreateProposal };
}
Loading