fix: add a link to switch the locale conditionally (#1776)
* add a link to switch the locale conditionally * make it smaller * add the locale labels * language labels from the internet * fix the heart in the claim popup * undo the conditional change * remove todo * updated Chinese locale name to office-365 language ids * added missing <Trans> Co-authored-by: Justin Domingue <judo@uniswap.org>
This commit is contained in:
parent
5125cbb1a3
commit
a7a1607faa
@ -1,7 +1,8 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import React, { useCallback, useEffect } from 'react'
|
||||
import ReactGA from 'react-ga'
|
||||
import { X } from 'react-feather'
|
||||
import { Heart, X } from 'react-feather'
|
||||
import styled, { keyframes } from 'styled-components'
|
||||
import tokenLogo from '../../assets/images/token-logo.png'
|
||||
import { ButtonPrimary } from '../../components/Button'
|
||||
@ -104,18 +105,20 @@ export default function ClaimPopup() {
|
||||
<span role="img" aria-label="party">
|
||||
🎉
|
||||
</span>{' '}
|
||||
UNI has arrived{' '}
|
||||
<Trans>UNI has arrived</Trans>{' '}
|
||||
<span role="img" aria-label="party">
|
||||
🎉
|
||||
</span>
|
||||
</TYPE.white>
|
||||
<TYPE.subHeader style={{ paddingTop: '0.5rem', textAlign: 'center' }} color="white">
|
||||
{`Thanks for being part of the Uniswap community <3`}
|
||||
<Trans>
|
||||
Thanks for being part of the Uniswap community <Heart size={12} />
|
||||
</Trans>
|
||||
</TYPE.subHeader>
|
||||
</AutoColumn>
|
||||
<AutoColumn style={{ zIndex: 10 }} justify="center">
|
||||
<ButtonPrimary padding="8px" borderRadius="8px" width={'fit-content'} onClick={handleToggleSelfClaimModal}>
|
||||
Claim your UNI tokens
|
||||
<Trans>Claim your UNI tokens</Trans>
|
||||
</ButtonPrimary>
|
||||
</AutoColumn>
|
||||
</StyledClaimPopup>
|
||||
|
47
src/components/SwitchLocaleLink/index.tsx
Normal file
47
src/components/SwitchLocaleLink/index.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useLocation } from 'react-router'
|
||||
import styled from 'styled-components/macro'
|
||||
import { DEFAULT_LOCALE, LOCALE_LABEL, SupportedLocale } from '../../constants/locales'
|
||||
import { navigatorLocale, useActiveLocale } from '../../hooks/useActiveLocale'
|
||||
import useParsedQueryString from '../../hooks/useParsedQueryString'
|
||||
import { StyledInternalLink, TYPE } from '../../theme'
|
||||
import { stringify } from 'qs'
|
||||
|
||||
const Container = styled(TYPE.small)`
|
||||
opacity: 0.6;
|
||||
:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
margin-top: 1rem !important;
|
||||
`
|
||||
|
||||
export function SwitchLocaleLink() {
|
||||
const activeLocale = useActiveLocale()
|
||||
const browserLocale = useMemo(() => navigatorLocale(), [])
|
||||
const location = useLocation()
|
||||
const qs = useParsedQueryString()
|
||||
|
||||
if (browserLocale && (browserLocale !== DEFAULT_LOCALE || activeLocale !== DEFAULT_LOCALE)) {
|
||||
let targetLocale: SupportedLocale
|
||||
if (activeLocale === browserLocale) {
|
||||
targetLocale = DEFAULT_LOCALE
|
||||
} else {
|
||||
targetLocale = browserLocale
|
||||
}
|
||||
|
||||
const target = {
|
||||
...location,
|
||||
search: stringify({ ...qs, lng: targetLocale }),
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Trans>
|
||||
Uniswap available in: {<StyledInternalLink to={target}>{LOCALE_LABEL[targetLocale]}</StyledInternalLink>}
|
||||
</Trans>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
@ -35,7 +35,36 @@ export type SupportedLocale = typeof SUPPORTED_LOCALES[number]
|
||||
|
||||
export const DEFAULT_LOCALE: SupportedLocale = 'en-US'
|
||||
|
||||
// todo: fill this back out
|
||||
export const LOCALE_LABEL: { [locale in SupportedLocale]?: string } = {
|
||||
export const LOCALE_LABEL: { [locale in SupportedLocale]: string } = {
|
||||
'af-ZA': 'Afrikaans',
|
||||
'ar-SA': 'العربية',
|
||||
'ca-ES': 'Català',
|
||||
'cs-CZ': 'čeština',
|
||||
'da-DK': 'dansk',
|
||||
'de-DE': 'Deutsche',
|
||||
'el-GR': 'ελληνικά',
|
||||
'en-US': 'English',
|
||||
'es-ES': 'Español',
|
||||
'fi-FI': 'Suomalainen',
|
||||
'fr-FR': 'français',
|
||||
'he-IL': 'עִברִית',
|
||||
'hu-HU': 'Magyar',
|
||||
'id-ID': 'bahasa Indonesia',
|
||||
'it-IT': 'Italiano',
|
||||
'ja-JP': '日本語',
|
||||
'ko-KR': '한국어',
|
||||
'nl-NL': 'Nederlands',
|
||||
'no-NO': 'norsk',
|
||||
'pl-PL': 'Polskie',
|
||||
'pt-BR': 'português',
|
||||
'pt-PT': 'português',
|
||||
'ro-RO': 'Română',
|
||||
'ru-RU': 'русский',
|
||||
'sr-SP': 'Српски',
|
||||
'sv-SE': 'svenska',
|
||||
'tr-TR': 'Türkçe',
|
||||
'uk-UA': 'Український',
|
||||
'vi-VN': 'Tiếng Việt',
|
||||
'zh-CN': '中文 ( 中国 )',
|
||||
'zh-TW': '中文 ( 台灣 )',
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ function parseLocale(maybeSupportedLocale: string): SupportedLocale | undefined
|
||||
/**
|
||||
* Returns the supported locale read from the user agent (navigator)
|
||||
*/
|
||||
function navigatorLocale(): SupportedLocale | undefined {
|
||||
export function navigatorLocale(): SupportedLocale | undefined {
|
||||
if (!navigator.language) return undefined
|
||||
|
||||
const [language, region] = navigator.language.split('-')
|
||||
|
@ -13,6 +13,7 @@ import { Link } from 'react-router-dom'
|
||||
import { useWalletModalToggle } from 'state/application/hooks'
|
||||
import styled, { ThemeContext } from 'styled-components'
|
||||
import { HideSmall, TYPE } from 'theme'
|
||||
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
|
||||
import { LoadingRows } from './styleds'
|
||||
import Toggle from 'components/Toggle'
|
||||
import { useUserHideClosedPositions } from 'state/user/hooks'
|
||||
@ -295,6 +296,7 @@ export default function Pool() {
|
||||
</AutoColumn>
|
||||
</AutoColumn>
|
||||
</PageWrapper>
|
||||
<SwitchLocaleLink />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { Currency, CurrencyAmount, Token, TradeType } from '@uniswap/sdk-core'
|
||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
@ -6,7 +7,7 @@ import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter
|
||||
import { MouseoverTooltip, MouseoverTooltipContent } from 'components/Tooltip'
|
||||
import JSBI from 'jsbi'
|
||||
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
||||
import { ArrowDown, CheckCircle, HelpCircle, Info, ArrowLeft } from 'react-feather'
|
||||
import { ArrowDown, ArrowLeft, CheckCircle, HelpCircle, Info } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
import { Link, RouteComponentProps } from 'react-router-dom'
|
||||
import { Text } from 'rebass'
|
||||
@ -26,8 +27,8 @@ import ConfirmSwapModal from '../../components/swap/ConfirmSwapModal'
|
||||
import { ArrowWrapper, BottomGrouping, Dots, SwapCallbackError, Wrapper } from '../../components/swap/styleds'
|
||||
import SwapHeader from '../../components/swap/SwapHeader'
|
||||
import TradePrice from '../../components/swap/TradePrice'
|
||||
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
|
||||
import TokenWarningModal from '../../components/TokenWarningModal'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useAllTokens, useCurrency } from '../../hooks/Tokens'
|
||||
import { ApprovalState, useApproveCallbackFromTrade } from '../../hooks/useApproveCallback'
|
||||
import { V3TradeState } from '../../hooks/useBestV3Trade'
|
||||
@ -39,6 +40,7 @@ import { useSwapCallback } from '../../hooks/useSwapCallback'
|
||||
import useToggledVersion, { Version } from '../../hooks/useToggledVersion'
|
||||
import { useUSDCValue } from '../../hooks/useUSDCPrice'
|
||||
import useWrapCallback, { WrapType } from '../../hooks/useWrapCallback'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||
import { Field } from '../../state/swap/actions'
|
||||
import {
|
||||
@ -55,7 +57,6 @@ import { isTradeBetter } from '../../utils/isTradeBetter'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
import { warningSeverity } from '../../utils/prices'
|
||||
import AppBody from '../AppBody'
|
||||
import { Trans } from '@lingui/macro'
|
||||
|
||||
const StyledInfo = styled(Info)`
|
||||
opacity: 0.4;
|
||||
@ -658,6 +659,7 @@ export default function Swap({ history }: RouteComponentProps) {
|
||||
</AutoColumn>
|
||||
</Wrapper>
|
||||
</AppBody>
|
||||
<SwitchLocaleLink />
|
||||
{!swapIsUnsupported ? null : (
|
||||
<UnsupportedCurrencyFooter show={swapIsUnsupported} currencies={[currencies.INPUT, currencies.OUTPUT]} />
|
||||
)}
|
||||
|
@ -14,6 +14,7 @@ import { GreyCard } from '../../components/Card'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import { CardSection, DataCard } from '../../components/earn/styled'
|
||||
import { RowBetween, RowFixed } from '../../components/Row'
|
||||
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
|
||||
import DelegateModal from '../../components/vote/DelegateModal'
|
||||
import VoteModal from '../../components/vote/VoteModal'
|
||||
import {
|
||||
@ -199,161 +200,164 @@ export default function VotePage({
|
||||
}
|
||||
|
||||
return (
|
||||
<PageWrapper gap="lg" justify="center">
|
||||
<VoteModal isOpen={showVoteModal} onDismiss={toggleVoteModal} proposalId={proposalData?.id} support={support} />
|
||||
<DelegateModal isOpen={showDelegateModal} onDismiss={toggleDelegateModal} title={<Trans>Unlock Votes</Trans>} />
|
||||
<ProposalInfo gap="lg" justify="start">
|
||||
<RowBetween style={{ width: '100%' }}>
|
||||
<ArrowWrapper to="/vote">
|
||||
<Trans>
|
||||
<ArrowLeft size={20} /> All Proposals
|
||||
</Trans>
|
||||
</ArrowWrapper>
|
||||
{proposalData && (
|
||||
<ProposalStatus status={proposalData.status}>{ProposalState[proposalData.status]}</ProposalStatus>
|
||||
)}
|
||||
</RowBetween>
|
||||
<AutoColumn gap="10px" style={{ width: '100%' }}>
|
||||
<TYPE.largeHeader style={{ marginBottom: '.5rem' }}>{proposalData?.title}</TYPE.largeHeader>
|
||||
<RowBetween>
|
||||
<TYPE.main>
|
||||
{endDate && endDate < now ? (
|
||||
<Trans>Voting ended {endDate && endDate.toLocaleString(DateTime.DATETIME_FULL)}</Trans>
|
||||
) : proposalData ? (
|
||||
<Trans>Voting ends approximately {endDate && endDate.toLocaleString(DateTime.DATETIME_FULL)}</Trans>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</TYPE.main>
|
||||
<>
|
||||
<PageWrapper gap="lg" justify="center">
|
||||
<VoteModal isOpen={showVoteModal} onDismiss={toggleVoteModal} proposalId={proposalData?.id} support={support} />
|
||||
<DelegateModal isOpen={showDelegateModal} onDismiss={toggleDelegateModal} title={<Trans>Unlock Votes</Trans>} />
|
||||
<ProposalInfo gap="lg" justify="start">
|
||||
<RowBetween style={{ width: '100%' }}>
|
||||
<ArrowWrapper to="/vote">
|
||||
<Trans>
|
||||
<ArrowLeft size={20} /> All Proposals
|
||||
</Trans>
|
||||
</ArrowWrapper>
|
||||
{proposalData && (
|
||||
<ProposalStatus status={proposalData.status}>{ProposalState[proposalData.status]}</ProposalStatus>
|
||||
)}
|
||||
</RowBetween>
|
||||
{proposalData && proposalData.status === ProposalState.Active && !showVotingButtons && (
|
||||
<GreyCard>
|
||||
<TYPE.black>
|
||||
<Trans>
|
||||
Only UNI votes that were self delegated or delegated to another address before block{' '}
|
||||
{proposalData.startBlock} are eligible for voting.{' '}
|
||||
</Trans>
|
||||
{showLinkForUnlock && (
|
||||
<span>
|
||||
<Trans>
|
||||
<StyledInternalLink to="/vote">Unlock voting</StyledInternalLink> to prepare for the next
|
||||
proposal.
|
||||
</Trans>
|
||||
</span>
|
||||
<AutoColumn gap="10px" style={{ width: '100%' }}>
|
||||
<TYPE.largeHeader style={{ marginBottom: '.5rem' }}>{proposalData?.title}</TYPE.largeHeader>
|
||||
<RowBetween>
|
||||
<TYPE.main>
|
||||
{endDate && endDate < now ? (
|
||||
<Trans>Voting ended {endDate && endDate.toLocaleString(DateTime.DATETIME_FULL)}</Trans>
|
||||
) : proposalData ? (
|
||||
<Trans>Voting ends approximately {endDate && endDate.toLocaleString(DateTime.DATETIME_FULL)}</Trans>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</TYPE.black>
|
||||
</GreyCard>
|
||||
)}
|
||||
</AutoColumn>
|
||||
{showVotingButtons ? (
|
||||
<RowFixed style={{ width: '100%', gap: '12px' }}>
|
||||
<ButtonPrimary
|
||||
padding="8px"
|
||||
borderRadius="8px"
|
||||
onClick={() => {
|
||||
setSupport(true)
|
||||
toggleVoteModal()
|
||||
}}
|
||||
>
|
||||
Vote For
|
||||
</ButtonPrimary>
|
||||
<ButtonPrimary
|
||||
padding="8px"
|
||||
borderRadius="8px"
|
||||
onClick={() => {
|
||||
setSupport(false)
|
||||
toggleVoteModal()
|
||||
}}
|
||||
>
|
||||
<Trans>Vote Against</Trans>
|
||||
</ButtonPrimary>
|
||||
</RowFixed>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<CardWrapper>
|
||||
<StyledDataCard>
|
||||
<CardSection>
|
||||
<AutoColumn gap="md">
|
||||
<WrapSmall>
|
||||
</TYPE.main>
|
||||
</RowBetween>
|
||||
{proposalData && proposalData.status === ProposalState.Active && !showVotingButtons && (
|
||||
<GreyCard>
|
||||
<TYPE.black>
|
||||
<Trans>
|
||||
<TYPE.black fontWeight={600}>
|
||||
<Trans>For</Trans>
|
||||
</TYPE.black>
|
||||
<TYPE.black fontWeight={600}>
|
||||
{' '}
|
||||
{proposalData?.forCount.toLocaleString(undefined, { maximumFractionDigits: 0 })}
|
||||
</TYPE.black>
|
||||
Only UNI votes that were self delegated or delegated to another address before block{' '}
|
||||
{proposalData.startBlock} are eligible for voting.{' '}
|
||||
</Trans>
|
||||
</WrapSmall>
|
||||
</AutoColumn>
|
||||
<ProgressWrapper>
|
||||
<Progress status={'for'} percentageString={forPercentage} />
|
||||
</ProgressWrapper>
|
||||
</CardSection>
|
||||
</StyledDataCard>
|
||||
<StyledDataCard>
|
||||
<CardSection>
|
||||
<AutoColumn gap="md">
|
||||
<WrapSmall>
|
||||
<TYPE.black fontWeight={600}>
|
||||
<Trans>Against</Trans>
|
||||
</TYPE.black>
|
||||
<TYPE.black fontWeight={600}>
|
||||
{proposalData?.againstCount.toLocaleString(undefined, { maximumFractionDigits: 0 })}
|
||||
</TYPE.black>
|
||||
</WrapSmall>
|
||||
</AutoColumn>
|
||||
<ProgressWrapper>
|
||||
<Progress status={'against'} percentageString={againstPercentage} />
|
||||
</ProgressWrapper>
|
||||
</CardSection>
|
||||
</StyledDataCard>
|
||||
</CardWrapper>
|
||||
<AutoColumn gap="md">
|
||||
<TYPE.mediumHeader fontWeight={600}>
|
||||
<Trans>Details</Trans>
|
||||
</TYPE.mediumHeader>
|
||||
{proposalData?.details?.map((d, i) => {
|
||||
return (
|
||||
<DetailText key={i}>
|
||||
{i + 1}: {linkIfAddress(d.target)}.{d.functionSig}(
|
||||
{d.callData.split(',').map((content, i) => {
|
||||
return (
|
||||
<span key={i}>
|
||||
{linkIfAddress(content)}
|
||||
{d.callData.split(',').length - 1 === i ? '' : ','}
|
||||
{showLinkForUnlock && (
|
||||
<span>
|
||||
<Trans>
|
||||
<StyledInternalLink to="/vote">Unlock voting</StyledInternalLink> to prepare for the next
|
||||
proposal.
|
||||
</Trans>
|
||||
</span>
|
||||
)}
|
||||
</TYPE.black>
|
||||
</GreyCard>
|
||||
)}
|
||||
</AutoColumn>
|
||||
{showVotingButtons ? (
|
||||
<RowFixed style={{ width: '100%', gap: '12px' }}>
|
||||
<ButtonPrimary
|
||||
padding="8px"
|
||||
borderRadius="8px"
|
||||
onClick={() => {
|
||||
setSupport(true)
|
||||
toggleVoteModal()
|
||||
}}
|
||||
>
|
||||
<Trans>Vote For</Trans>
|
||||
</ButtonPrimary>
|
||||
<ButtonPrimary
|
||||
padding="8px"
|
||||
borderRadius="8px"
|
||||
onClick={() => {
|
||||
setSupport(false)
|
||||
toggleVoteModal()
|
||||
}}
|
||||
>
|
||||
<Trans>Vote Against</Trans>
|
||||
</ButtonPrimary>
|
||||
</RowFixed>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<CardWrapper>
|
||||
<StyledDataCard>
|
||||
<CardSection>
|
||||
<AutoColumn gap="md">
|
||||
<WrapSmall>
|
||||
<Trans>
|
||||
<TYPE.black fontWeight={600}>
|
||||
<Trans>For</Trans>
|
||||
</TYPE.black>
|
||||
<TYPE.black fontWeight={600}>
|
||||
{' '}
|
||||
{proposalData?.forCount.toLocaleString(undefined, { maximumFractionDigits: 0 })}
|
||||
</TYPE.black>
|
||||
</Trans>
|
||||
</WrapSmall>
|
||||
</AutoColumn>
|
||||
<ProgressWrapper>
|
||||
<Progress status={'for'} percentageString={forPercentage} />
|
||||
</ProgressWrapper>
|
||||
</CardSection>
|
||||
</StyledDataCard>
|
||||
<StyledDataCard>
|
||||
<CardSection>
|
||||
<AutoColumn gap="md">
|
||||
<WrapSmall>
|
||||
<TYPE.black fontWeight={600}>
|
||||
<Trans>Against</Trans>
|
||||
</TYPE.black>
|
||||
<TYPE.black fontWeight={600}>
|
||||
{proposalData?.againstCount.toLocaleString(undefined, { maximumFractionDigits: 0 })}
|
||||
</TYPE.black>
|
||||
</WrapSmall>
|
||||
</AutoColumn>
|
||||
<ProgressWrapper>
|
||||
<Progress status={'against'} percentageString={againstPercentage} />
|
||||
</ProgressWrapper>
|
||||
</CardSection>
|
||||
</StyledDataCard>
|
||||
</CardWrapper>
|
||||
<AutoColumn gap="md">
|
||||
<TYPE.mediumHeader fontWeight={600}>
|
||||
<Trans>Details</Trans>
|
||||
</TYPE.mediumHeader>
|
||||
{proposalData?.details?.map((d, i) => {
|
||||
return (
|
||||
<DetailText key={i}>
|
||||
{i + 1}: {linkIfAddress(d.target)}.{d.functionSig}(
|
||||
{d.callData.split(',').map((content, i) => {
|
||||
return (
|
||||
<span key={i}>
|
||||
{linkIfAddress(content)}
|
||||
{d.callData.split(',').length - 1 === i ? '' : ','}
|
||||
</span>
|
||||
)
|
||||
})}
|
||||
)
|
||||
})}
|
||||
)
|
||||
</DetailText>
|
||||
)
|
||||
})}
|
||||
</AutoColumn>
|
||||
<AutoColumn gap="md">
|
||||
<TYPE.mediumHeader fontWeight={600}>
|
||||
<Trans>Description</Trans>
|
||||
</TYPE.mediumHeader>
|
||||
<MarkDownWrapper>
|
||||
<ReactMarkdown source={proposalData?.description} />
|
||||
</MarkDownWrapper>
|
||||
</AutoColumn>
|
||||
<AutoColumn gap="md">
|
||||
<TYPE.mediumHeader fontWeight={600}>
|
||||
<Trans>Proposer</Trans>
|
||||
</TYPE.mediumHeader>
|
||||
<ProposerAddressLink
|
||||
href={
|
||||
proposalData?.proposer && chainId
|
||||
? getExplorerLink(chainId, proposalData?.proposer, ExplorerDataType.ADDRESS)
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<ReactMarkdown source={proposalData?.proposer} />
|
||||
</ProposerAddressLink>
|
||||
</AutoColumn>
|
||||
</ProposalInfo>
|
||||
</PageWrapper>
|
||||
</DetailText>
|
||||
)
|
||||
})}
|
||||
</AutoColumn>
|
||||
<AutoColumn gap="md">
|
||||
<TYPE.mediumHeader fontWeight={600}>
|
||||
<Trans>Description</Trans>
|
||||
</TYPE.mediumHeader>
|
||||
<MarkDownWrapper>
|
||||
<ReactMarkdown source={proposalData?.description} />
|
||||
</MarkDownWrapper>
|
||||
</AutoColumn>
|
||||
<AutoColumn gap="md">
|
||||
<TYPE.mediumHeader fontWeight={600}>
|
||||
<Trans>Proposer</Trans>
|
||||
</TYPE.mediumHeader>
|
||||
<ProposerAddressLink
|
||||
href={
|
||||
proposalData?.proposer && chainId
|
||||
? getExplorerLink(chainId, proposalData?.proposer, ExplorerDataType.ADDRESS)
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<ReactMarkdown source={proposalData?.proposer} />
|
||||
</ProposerAddressLink>
|
||||
</AutoColumn>
|
||||
</ProposalInfo>
|
||||
</PageWrapper>
|
||||
<SwitchLocaleLink />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import styled from 'styled-components/macro'
|
||||
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
|
||||
import { UNI } from '../../constants/tokens'
|
||||
import { ExternalLink, TYPE } from '../../theme'
|
||||
import { RowBetween, RowFixed } from '../../components/Row'
|
||||
@ -135,130 +136,133 @@ export default function Vote() {
|
||||
)
|
||||
|
||||
return (
|
||||
<PageWrapper gap="lg" justify="center">
|
||||
<DelegateModal
|
||||
isOpen={showDelegateModal}
|
||||
onDismiss={toggleDelegateModal}
|
||||
title={showUnlockVoting ? <Trans>Unlock Votes</Trans> : <Trans>Update Delegation</Trans>}
|
||||
/>
|
||||
<TopSection gap="md">
|
||||
<VoteCard>
|
||||
<CardBGImage />
|
||||
<CardNoise />
|
||||
<CardSection>
|
||||
<AutoColumn gap="md">
|
||||
<RowBetween>
|
||||
<TYPE.white fontWeight={600}>
|
||||
<Trans>Uniswap Governance</Trans>
|
||||
</TYPE.white>
|
||||
</RowBetween>
|
||||
<RowBetween>
|
||||
<TYPE.white fontSize={14}>
|
||||
<Trans>
|
||||
UNI tokens represent voting shares in Uniswap governance. You can vote on each proposal yourself or
|
||||
delegate your votes to a third party.
|
||||
</Trans>
|
||||
</TYPE.white>
|
||||
</RowBetween>
|
||||
<ExternalLink
|
||||
style={{ color: 'white', textDecoration: 'underline' }}
|
||||
href="https://uniswap.org/blog/uni"
|
||||
target="_blank"
|
||||
<>
|
||||
<PageWrapper gap="lg" justify="center">
|
||||
<DelegateModal
|
||||
isOpen={showDelegateModal}
|
||||
onDismiss={toggleDelegateModal}
|
||||
title={showUnlockVoting ? <Trans>Unlock Votes</Trans> : <Trans>Update Delegation</Trans>}
|
||||
/>
|
||||
<TopSection gap="md">
|
||||
<VoteCard>
|
||||
<CardBGImage />
|
||||
<CardNoise />
|
||||
<CardSection>
|
||||
<AutoColumn gap="md">
|
||||
<RowBetween>
|
||||
<TYPE.white fontWeight={600}>
|
||||
<Trans>Uniswap Governance</Trans>
|
||||
</TYPE.white>
|
||||
</RowBetween>
|
||||
<RowBetween>
|
||||
<TYPE.white fontSize={14}>
|
||||
<Trans>
|
||||
UNI tokens represent voting shares in Uniswap governance. You can vote on each proposal yourself
|
||||
or delegate your votes to a third party.
|
||||
</Trans>
|
||||
</TYPE.white>
|
||||
</RowBetween>
|
||||
<ExternalLink
|
||||
style={{ color: 'white', textDecoration: 'underline' }}
|
||||
href="https://uniswap.org/blog/uni"
|
||||
target="_blank"
|
||||
>
|
||||
<TYPE.white fontSize={14}>
|
||||
<Trans>Read more about Uniswap governance</Trans>
|
||||
</TYPE.white>
|
||||
</ExternalLink>
|
||||
</AutoColumn>
|
||||
</CardSection>
|
||||
<CardBGImage />
|
||||
<CardNoise />
|
||||
</VoteCard>
|
||||
</TopSection>
|
||||
<TopSection gap="2px">
|
||||
<WrapSmall>
|
||||
<TYPE.mediumHeader style={{ margin: '0.5rem 0.5rem 0.5rem 0', flexShrink: 0 }}>
|
||||
<Trans>Proposals</Trans>
|
||||
</TYPE.mediumHeader>
|
||||
{(!allProposals || allProposals.length === 0) && !availableVotes && <Loader />}
|
||||
{showUnlockVoting ? (
|
||||
<ButtonPrimary
|
||||
style={{ width: 'fit-content' }}
|
||||
padding="8px"
|
||||
borderRadius="8px"
|
||||
onClick={toggleDelegateModal}
|
||||
>
|
||||
<TYPE.white fontSize={14}>
|
||||
<Trans>Read more about Uniswap governance</Trans>
|
||||
</TYPE.white>
|
||||
</ExternalLink>
|
||||
</AutoColumn>
|
||||
</CardSection>
|
||||
<CardBGImage />
|
||||
<CardNoise />
|
||||
</VoteCard>
|
||||
</TopSection>
|
||||
<TopSection gap="2px">
|
||||
<WrapSmall>
|
||||
<TYPE.mediumHeader style={{ margin: '0.5rem 0.5rem 0.5rem 0', flexShrink: 0 }}>
|
||||
<Trans>Proposals</Trans>
|
||||
</TYPE.mediumHeader>
|
||||
{(!allProposals || allProposals.length === 0) && !availableVotes && <Loader />}
|
||||
{showUnlockVoting ? (
|
||||
<ButtonPrimary
|
||||
style={{ width: 'fit-content' }}
|
||||
padding="8px"
|
||||
borderRadius="8px"
|
||||
onClick={toggleDelegateModal}
|
||||
>
|
||||
<Trans>Unlock Voting</Trans>
|
||||
</ButtonPrimary>
|
||||
) : availableVotes && JSBI.notEqual(JSBI.BigInt(0), availableVotes?.quotient) ? (
|
||||
<TYPE.body fontWeight={500} mr="6px">
|
||||
<Trans>
|
||||
<FormattedCurrencyAmount currencyAmount={availableVotes} /> Votes
|
||||
</Trans>
|
||||
</TYPE.body>
|
||||
) : uniBalance &&
|
||||
userDelegatee &&
|
||||
userDelegatee !== ZERO_ADDRESS &&
|
||||
JSBI.notEqual(JSBI.BigInt(0), uniBalance?.quotient) ? (
|
||||
<TYPE.body fontWeight={500} mr="6px">
|
||||
<Trans>
|
||||
<FormattedCurrencyAmount currencyAmount={uniBalance} /> Votes
|
||||
</Trans>
|
||||
</TYPE.body>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</WrapSmall>
|
||||
{!showUnlockVoting && (
|
||||
<RowBetween>
|
||||
<div />
|
||||
{userDelegatee && userDelegatee !== ZERO_ADDRESS ? (
|
||||
<RowFixed>
|
||||
<TYPE.body fontWeight={500} mr="4px">
|
||||
<Trans>Delegated to:</Trans>
|
||||
</TYPE.body>
|
||||
<AddressButton>
|
||||
<StyledExternalLink
|
||||
href={getExplorerLink(1, userDelegatee, ExplorerDataType.ADDRESS)}
|
||||
style={{ margin: '0 4px' }}
|
||||
>
|
||||
{userDelegatee === account ? <Trans>Self</Trans> : shortenAddress(userDelegatee)}
|
||||
</StyledExternalLink>
|
||||
<TextButton onClick={toggleDelegateModal} style={{ marginLeft: '4px' }}>
|
||||
<Trans>(edit)</Trans>
|
||||
</TextButton>
|
||||
</AddressButton>
|
||||
</RowFixed>
|
||||
<Trans>Unlock Voting</Trans>
|
||||
</ButtonPrimary>
|
||||
) : availableVotes && JSBI.notEqual(JSBI.BigInt(0), availableVotes?.quotient) ? (
|
||||
<TYPE.body fontWeight={500} mr="6px">
|
||||
<Trans>
|
||||
<FormattedCurrencyAmount currencyAmount={availableVotes} /> Votes
|
||||
</Trans>
|
||||
</TYPE.body>
|
||||
) : uniBalance &&
|
||||
userDelegatee &&
|
||||
userDelegatee !== ZERO_ADDRESS &&
|
||||
JSBI.notEqual(JSBI.BigInt(0), uniBalance?.quotient) ? (
|
||||
<TYPE.body fontWeight={500} mr="6px">
|
||||
<Trans>
|
||||
<FormattedCurrencyAmount currencyAmount={uniBalance} /> Votes
|
||||
</Trans>
|
||||
</TYPE.body>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</RowBetween>
|
||||
)}
|
||||
{allProposals?.length === 0 && (
|
||||
<EmptyProposals>
|
||||
<TYPE.body style={{ marginBottom: '8px' }}>
|
||||
<Trans>No proposals found.</Trans>
|
||||
</TYPE.body>
|
||||
<TYPE.subHeader>
|
||||
<i>
|
||||
<Trans>Proposals submitted by community members will appear here.</Trans>
|
||||
</i>
|
||||
</TYPE.subHeader>
|
||||
</EmptyProposals>
|
||||
)}
|
||||
{allProposals?.map((p: ProposalData, i) => {
|
||||
return (
|
||||
<Proposal as={Link} to={'/vote/' + p.id} key={i}>
|
||||
<ProposalNumber>{p.id}</ProposalNumber>
|
||||
<ProposalTitle>{p.title}</ProposalTitle>
|
||||
<ProposalStatus status={p.status}>{ProposalState[p.status]}</ProposalStatus>
|
||||
</Proposal>
|
||||
)
|
||||
})}
|
||||
</TopSection>
|
||||
<TYPE.subHeader color="text3">
|
||||
<Trans>A minimum threshold of 1% of the total UNI supply is required to submit proposals</Trans>
|
||||
</TYPE.subHeader>
|
||||
</PageWrapper>
|
||||
</WrapSmall>
|
||||
{!showUnlockVoting && (
|
||||
<RowBetween>
|
||||
<div />
|
||||
{userDelegatee && userDelegatee !== ZERO_ADDRESS ? (
|
||||
<RowFixed>
|
||||
<TYPE.body fontWeight={500} mr="4px">
|
||||
<Trans>Delegated to:</Trans>
|
||||
</TYPE.body>
|
||||
<AddressButton>
|
||||
<StyledExternalLink
|
||||
href={getExplorerLink(1, userDelegatee, ExplorerDataType.ADDRESS)}
|
||||
style={{ margin: '0 4px' }}
|
||||
>
|
||||
{userDelegatee === account ? <Trans>Self</Trans> : shortenAddress(userDelegatee)}
|
||||
</StyledExternalLink>
|
||||
<TextButton onClick={toggleDelegateModal} style={{ marginLeft: '4px' }}>
|
||||
<Trans>(edit)</Trans>
|
||||
</TextButton>
|
||||
</AddressButton>
|
||||
</RowFixed>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</RowBetween>
|
||||
)}
|
||||
{allProposals?.length === 0 && (
|
||||
<EmptyProposals>
|
||||
<TYPE.body style={{ marginBottom: '8px' }}>
|
||||
<Trans>No proposals found.</Trans>
|
||||
</TYPE.body>
|
||||
<TYPE.subHeader>
|
||||
<i>
|
||||
<Trans>Proposals submitted by community members will appear here.</Trans>
|
||||
</i>
|
||||
</TYPE.subHeader>
|
||||
</EmptyProposals>
|
||||
)}
|
||||
{allProposals?.map((p: ProposalData, i) => {
|
||||
return (
|
||||
<Proposal as={Link} to={'/vote/' + p.id} key={i}>
|
||||
<ProposalNumber>{p.id}</ProposalNumber>
|
||||
<ProposalTitle>{p.title}</ProposalTitle>
|
||||
<ProposalStatus status={p.status}>{ProposalState[p.status]}</ProposalStatus>
|
||||
</Proposal>
|
||||
)
|
||||
})}
|
||||
</TopSection>
|
||||
<TYPE.subHeader color="text3">
|
||||
<Trans>A minimum threshold of 1% of the total UNI supply is required to submit proposals</Trans>
|
||||
</TYPE.subHeader>
|
||||
</PageWrapper>
|
||||
<SwitchLocaleLink />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user