Skip to content

Commit

Permalink
Merge branch 'crt' into feature/buy-sell-amm
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/atlas/src/joystream-lib/extrinsics.ts
  • Loading branch information
WRadoslaw committed Nov 13, 2023
2 parents 7a31511 + 9d76afc commit fcd4e82
Show file tree
Hide file tree
Showing 36 changed files with 558 additions and 131 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/atlas/src/api/queries/fragments.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ fragment FullCreatorToken on CreatorToken {
...BasicCreatorToken
annualCreatorRewardPermill
description
revenueShareRatioPermill
ammCurves {
id
finalized
Expand Down
9 changes: 7 additions & 2 deletions packages/atlas/src/components/ActionBar/ActionBar.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ export const ActionBarContainer = styled.div<ActionBarContainerProps>`
grid-template:
'primary-text badge' auto
'secondary-button primary-button' auto / auto 1fr;
'secondary-button primary-button' auto
'teriary-button teriary-button' auto / auto 1fr;
${media.sm} {
grid-template: 'primary-text badge secondary-button primary-button' auto / 1fr max-content max-content max-content;
grid-template: 'primary-text badge teriary-button secondary-button primary-button' auto / 1fr max-content max-content max-content max-content;
}
${media.md} {
Expand All @@ -47,6 +48,10 @@ export const StyledInformation = styled(Information)`
margin-left: ${sizes(1)};
`

export const TertiaryButton = styled(Button)`
grid-area: teriary-button;
`

export const SecondaryButton = styled(Button)`
grid-area: secondary-button;
`
Expand Down
14 changes: 14 additions & 0 deletions packages/atlas/src/components/ActionBar/ActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
PrimaryButtonContainer,
SecondaryButton,
StyledInformation,
TertiaryButton,
} from './ActionBar.styles'

export type ActionDialogButtonProps = {
Expand All @@ -36,6 +37,7 @@ export type ActionBarProps = {
primaryButton: ActionDialogButtonProps
primaryButtonTooltip?: Omit<TooltipProps, 'reference'>
secondaryButton?: ActionDialogButtonProps
tertiaryButton?: ActionDialogButtonProps
isActive?: boolean
skipFeeCheck?: boolean
className?: string
Expand All @@ -52,6 +54,7 @@ export const ActionBar = forwardRef<HTMLDivElement, ActionBarProps>(
primaryButton,
primaryButtonTooltip,
secondaryButton,
tertiaryButton,
infoBadge,
skipFeeCheck,
isNoneCrypto,
Expand Down Expand Up @@ -82,6 +85,17 @@ export const ActionBar = forwardRef<HTMLDivElement, ActionBarProps>(
<StyledInformation multiline placement="top-end" {...infoBadge.tooltip} />
</DraftsBadgeContainer>
) : null}
<CSSTransition
in={!!tertiaryButton}
timeout={parseInt(transitions.timings.sharp)}
classNames={transitions.names.fade}
mountOnEnter
unmountOnExit
>
<TertiaryButton {...tertiaryButton} variant="tertiary" size={smMatch ? 'large' : 'medium'}>
{tertiaryButton?.text}
</TertiaryButton>
</CSSTransition>
<CSSTransition
in={!!secondaryButton}
timeout={parseInt(transitions.timings.sharp)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export const HeaderContainer = styled.div`
svg {
cursor: pointer;
margin-right: ${sizes(4)};
}
${media.md} {
Expand Down
114 changes: 107 additions & 7 deletions packages/atlas/src/components/CrtPreviewLayout/CrtPreviewLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import { ReactElement } from 'react'
import { ReactElement, useMemo } from 'react'
import { useNavigate } from 'react-router'

import { useGetCreatorTokenHoldersQuery } from '@/api/queries/__generated__/creatorTokens.generated'
import { FullCreatorTokenFragment } from '@/api/queries/__generated__/fragments.generated'
import { SvgActionChevronL, SvgActionNewTab } from '@/assets/icons'
import { JoyTokenIcon } from '@/components/JoyTokenIcon'
import { OutputPill } from '@/components/OutputPill'
import { Text } from '@/components/Text'
import { Button } from '@/components/_buttons/Button'
import { CrtBasicInfoWidget } from '@/components/_crt/CrtBasicInfoWidget'
import { CrtStatusWidget } from '@/components/_crt/CrtStatusWidget'
import { HoldersWidget } from '@/components/_crt/HoldersWidget'
import { SkeletonLoader } from '@/components/_loaders/SkeletonLoader'
import { absoluteRoutes } from '@/config/routes'
import { useMediaMatch } from '@/hooks/useMediaMatch'
import { useConfirmationModal } from '@/providers/confirmationModal'
import { useUser } from '@/providers/user/user.hooks'
import { permillToPercentage } from '@/utils/number'

import {
FirstColumn,
Expand All @@ -18,34 +31,121 @@ import {
type CrtPreviewViewProps = {
mode: 'edit' | 'preview'
tokenDetails?: ReactElement
token: FullCreatorTokenFragment
isDirty?: boolean
}

export const getTokenDetails = (token: FullCreatorTokenFragment) => {
const details = []
if (token.totalSupply)
details.push({
caption: 'TOTAL REV.',
content: +token.totalSupply,
icon: <JoyTokenIcon size={16} variant="silver" />,
tooltipText: 'Lorem ipsum',
})

if (token.revenueShareRatioPermill)
details.push({
caption: 'REV. SHARE',
content: `${permillToPercentage(token.revenueShareRatioPermill)}%`,
tooltipText: 'Lorem ipsum',
})

if (token.annualCreatorRewardPermill)
details.push({
caption: 'AN. REWARD',
content: `${permillToPercentage(token.annualCreatorRewardPermill)}%`,
tooltipText: 'Lorem ipsum',
})
return details
}

export const CrtPreviewLayout = ({
tokenDetails = <Placeholder height={1000}>Token details</Placeholder>,
mode,
token,
isDirty,
}: CrtPreviewViewProps) => {
const lgMatch = useMediaMatch('lg')
const navigate = useNavigate()
const [openConfirmationModal, closeModal] = useConfirmationModal()
const { memberId } = useUser()
const { data } = useGetCreatorTokenHoldersQuery({
variables: {
where: {
token: {
id_eq: token.id,
},
member: {
id_eq: memberId,
},
},
},
})

const basicDetails = useMemo(() => getTokenDetails(token), [token])

return (
<Wrapper>
<HeaderContainer>
<SvgActionChevronL />
<Button to={absoluteRoutes.studio.crtDashboard()} icon={<SvgActionChevronL />} variant="tertiary" />
<HeaderInnerContainer>
<Text variant="h400" as="p">
Token page preview
</Text>
<OutputPill handle={mode === 'edit' ? 'Edit mode' : 'Preview mode'} />
</HeaderInnerContainer>
{lgMatch && (
<HeaderButton variant="tertiary" icon={<SvgActionNewTab />} iconPlacement="right">
<HeaderButton
variant="tertiary"
icon={<SvgActionNewTab />}
iconPlacement="right"
onClick={() => {
if (isDirty) {
openConfirmationModal({
title: 'You have unpublished changes',
description: 'You need to publish your changes to see them reflected on the token page.',
primaryButton: {
variant: 'warning',
text: 'Confirm and leave',
onClick: () => {
closeModal()
navigate(absoluteRoutes.viewer.channel(token.channel?.channel.id, { tab: 'Token' }))
},
},
secondaryButton: {
text: 'Stay',
onClick: () => closeModal(),
},
})
return
}
navigate(absoluteRoutes.viewer.channel(token.channel?.channel.id, { tab: 'Token' }))
}}
>
See your token
</HeaderButton>
)}
</HeaderContainer>
<FirstColumn>{tokenDetails}</FirstColumn>
<SecondColumn>
{/* these components are the same for each mode */}
<Placeholder height={192}>Token details</Placeholder>
<Placeholder height={248}>Token status</Placeholder>
<Placeholder height={368}>Token holders</Placeholder>
<CrtBasicInfoWidget details={basicDetails} name={token.symbol ?? 'N/A'} />
{/* todo all props below creationDate are incorrect and should be calucated on orion side */}
<CrtStatusWidget
name={token.symbol ?? 'N/A'}
creationDate={new Date(token.createdAt)}
supply={+(token.totalSupply ?? 0)}
marketCap={token.annualCreatorRewardPermill}
revenue={token.annualCreatorRewardPermill}
revenueShare={token.annualCreatorRewardPermill}
transactionVolume={token.annualCreatorRewardPermill}
/>
{data ? (
<HoldersWidget totalSupply={+token.totalSupply} holders={data.tokenAccounts} ownerId={memberId ?? ''} />
) : (
<SkeletonLoader width="100%" height={300} />
)}
</SecondColumn>
</Wrapper>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const CREATOR_TOKEN_INITIAL_DATA: CreateTokenForm = {
name: '',
isOpen: true,
revenueShare: 50,
creatorReward: 50,
creatorReward: 10,
creatorIssueAmount: undefined,
assuranceType: 'safe',
cliff: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,11 @@ Recommended values — Channel: 80%, Holders:20%. "
}}
description="Define your own reward for managing the tokens. 10% means that if you have 10000k of tokens exist and this amount does not change, an additional 1k tokens will get minted and added to your wallet gradually over the course of 1 year."
>
<Controller name="creatorReward" control={control} render={({ field }) => <RatioSlider {...field} />} />
<Controller
name="creatorReward"
control={control}
render={({ field }) => <RatioSlider {...field} max={30} step={2} />}
/>
</FormField>
</CrtFormWrapper>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useApolloClient } from '@apollo/client'
import { keyframes } from '@emotion/react'
import styled from '@emotion/styled'
import { useNavigate } from 'react-router-dom'
Expand All @@ -17,6 +18,8 @@ export type CreateTokenSuccessModalProps = {
}
export const CreateTokenSuccessModal = ({ tokenName, show }: CreateTokenSuccessModalProps) => {
const navigate = useNavigate()
const client = useApolloClient()

return (
<DialogModal
show={show}
Expand All @@ -29,7 +32,11 @@ export const CreateTokenSuccessModal = ({ tokenName, show }: CreateTokenSuccessM
variant="secondary"
icon={<SvgActionNewTab />}
iconPlacement="right"
onClick={() => navigate(absoluteRoutes.studio.crtDashboard())} // todo add correct route
onClick={() => {
client.refetchQueries({ include: 'active' }).then(() => {
navigate(absoluteRoutes.studio.crtDashboard())
})
}}
>
View your token page
</TextButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ export type CrtBasicInfoWidgetProps = {
icon?: ReactNode
tooltipText?: string
}[]
flow?: 'column' | 'row'
}

export const CrtBasicInfoWidget = ({ name, details, titleColor }: CrtBasicInfoWidgetProps) => {
export const CrtBasicInfoWidget = ({ name, details, titleColor, flow = 'row' }: CrtBasicInfoWidgetProps) => {
const [titleRef, setTitleRef] = useState<HTMLSpanElement | null>(null)
const smMatch = useMediaMatch('sm')
return (
Expand All @@ -27,7 +28,7 @@ export const CrtBasicInfoWidget = ({ name, details, titleColor }: CrtBasicInfoWi
titleVariant="h700"
titleColor={titleColor ?? 'colorTextStrong'}
customNode={
<FlexBox gap={5}>
<FlexBox flow={flow} gap={5}>
<Tooltip reference={titleRef} text="Token name" placement="top-start" />
{details.map((detail, idx) => (
<DetailsContent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import styled from '@emotion/styled'
import BN from 'bn.js'
import { useMemo } from 'react'

import { FlexBox } from '@/components/FlexBox'
Expand All @@ -15,8 +16,9 @@ const COLUMNS: TableProps['columns'] = [

type CrtHolder = {
memberId: string
total: number
vested: number
total: number | BN
vested: number | BN
allocation: number
}

export type CrtHoldersTableProps = {
Expand Down Expand Up @@ -45,9 +47,9 @@ export const CrtHoldersTable = ({ isLoading, data, className, ownerId }: CrtHold
total: (
<RightAlignedCell>
<FlexBox alignItems="center" gap={1}>
<NumberFormat format="short" value={row.vested} as="p" variant="t200-strong" />
<NumberFormat format="short" value={row.total} as="p" variant="t200-strong" />
<Text variant="t200" as="p" color="colorText">
(20%)
({row.allocation}%)
</Text>
</FlexBox>
</RightAlignedCell>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const CrtStatusWidget: FC<CrtStatusWidgetProps> = ({
status,
}) => {
const drawer = useRef<HTMLDivElement>(null)
const [isExpanded, expand] = useState(true)
const [isExpanded, expand] = useState(false)
const smMatch = useMediaMatch('sm')

const ticker = `$${name}`
Expand Down
Loading

0 comments on commit fcd4e82

Please sign in to comment.