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

Centrifuge App: Prime overview page #1659

Merged
merged 12 commits into from
Oct 30, 2023
Merged
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
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v16
v18
1 change: 1 addition & 0 deletions centrifuge-app/src/assets/images/aave-token-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 121 additions & 2 deletions centrifuge-app/src/components/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
import { Grid, IconChevronDown, IconChevronUp, Shelf, Stack, Text } from '@centrifuge/fabric'
import {
Box,
Checkbox,
Divider,
Grid,
IconChevronDown,
IconChevronUp,
IconFilter,
Menu,
Popover,
Shelf,
Stack,
Text,
Tooltip,
} from '@centrifuge/fabric'
import css from '@styled-system/css'
import BN from 'bn.js'
import * as React from 'react'
import { Link, LinkProps } from 'react-router-dom'
import styled from 'styled-components'
import { useElementScrollSize } from '../utils/useElementScrollSize'
import { FiltersState } from '../utils/useFilters'
import { FilterButton } from './FilterButton'
import { QuickAction } from './QuickAction'

type GroupedProps = {
groupIndex?: number
Expand Down Expand Up @@ -254,8 +271,110 @@ export function SortableTableHeader({
)
}

export function FilterableTableHeader({
filterKey: key,
label,
options,
filters,
tooltip,
}: {
filterKey: string
label: string
options: string[] | Record<string, string>
filters: FiltersState
tooltip?: string
}) {
const optionKeys = Array.isArray(options) ? options : Object.keys(options)
const form = React.useRef<HTMLFormElement>(null)

function handleChange() {
if (!form.current) return
const formData = new FormData(form.current)
const entries = formData.getAll(key) as string[]
filters.setFilter(key, entries)
}

function deselectAll() {
filters.setFilter(key, [])
}

function selectAll() {
filters.setFilter(key, optionKeys)
}
const state = filters.getState()
const selectedOptions = state[key] as Set<string> | undefined

return (
<Box position="relative">
<Popover
placement="bottom left"
renderTrigger={(props, ref, state) => {
return (
<Box ref={ref}>
{tooltip ? (
<Tooltip body={tooltip} {...props} style={{ display: 'block' }}>
<FilterButton forwardedAs="span" variant="body3">
{label}
<IconFilter color={selectedOptions?.size ? 'textSelected' : 'currentColor'} size="1em" />
</FilterButton>
</Tooltip>
) : (
<FilterButton forwardedAs="button" type="button" variant="body3" {...props}>
{label}
<IconFilter color={selectedOptions?.size ? 'textSelected' : 'currentColor'} size="1em" />
</FilterButton>
)}
</Box>
)
}}
renderContent={(props, ref) => (
<Box {...props} ref={ref}>
<Menu width={300}>
<Stack as="form" ref={form} p={[2, 3]} gap={2}>
<Stack as="fieldset" borderWidth={0} gap={2}>
<Box as="legend" className="visually-hidden">
Filter {label} by:
</Box>
{optionKeys.map((option, index) => {
const label = Array.isArray(options) ? option : options[option]
const checked = filters.hasFilter(key, option)

return (
<Checkbox
key={index}
name={key}
value={option}
onChange={handleChange}
checked={checked}
label={label}
extendedClickArea
/>
)
})}
</Stack>

<Divider borderColor="textPrimary" />

{selectedOptions?.size === optionKeys.length ? (
<QuickAction variant="body1" forwardedAs="button" type="button" onClick={() => deselectAll()}>
Deselect all
</QuickAction>
) : (
<QuickAction variant="body1" forwardedAs="button" type="button" onClick={() => selectAll()}>
Select all
</QuickAction>
)}
</Stack>
</Menu>
</Box>
)}
/>
</Box>
)
}

const StyledHeader = styled(Shelf)`
color: ${({ theme }) => theme.colors.textSecondary};
color: ${({ theme }) => theme.colors.textPrimary};
cursor: pointer;
appearance: none;
border: none;
Expand Down
6 changes: 6 additions & 0 deletions centrifuge-app/src/components/DebugFlags/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export type Key =
| 'showPodAccountCreation'
| 'convertEvmAddress'
| 'showPortfolio'
| 'showPrime'
| 'poolCreationType'

export const flagsConfig: Record<Key, DebugFlagConfig> = {
Expand Down Expand Up @@ -121,6 +122,11 @@ export const flagsConfig: Record<Key, DebugFlagConfig> = {
default: false,
alwaysShow: true,
},
showPrime: {
type: 'checkbox',
default: false,
alwaysShow: true,
},
poolCreationType: {
type: 'select',
default: config.poolCreationType || 'immediate',
Expand Down
2 changes: 1 addition & 1 deletion centrifuge-app/src/components/LayoutBase/BasePadding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type BaseSectionProps = BoxProps & {

export function BasePadding({ children, ...boxProps }: BaseSectionProps) {
return (
<Stack pt={3} pb={4} px={[2, 2, 3, 3, 5]} {...boxProps}>
<Stack pt={4} pb={4} px={[2, 2, 3, 3, 5]} {...boxProps}>
{children}
</Stack>
)
Expand Down
43 changes: 43 additions & 0 deletions centrifuge-app/src/components/LayoutBase/LayoutSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Box, BoxProps, Shelf, Stack, Text } from '@centrifuge/fabric'
import * as React from 'react'
import { BasePadding } from './BasePadding'

type Props = {
title?: React.ReactNode
titleAddition?: React.ReactNode
subtitle?: string
headerRight?: React.ReactNode
children: React.ReactNode
} & BoxProps

export function LayoutSection({ title, titleAddition, subtitle, headerRight, children, ...boxProps }: Props) {
return (
<BasePadding as="section" gap={2} {...boxProps}>
{(title || titleAddition || subtitle || headerRight) && (
<Shelf justifyContent="space-between" as="header">
<Stack>
{(title || titleAddition) && (
<Shelf gap={1} alignItems="baseline">
{title && (
<Text as="h2" variant="heading2">
{title}
</Text>
)}
<Text variant="body2" color="textSecondary">
{titleAddition}
</Text>
</Shelf>
)}
{subtitle && (
<Text variant="body2" as="small" color="textSecondary">
{subtitle}
</Text>
)}
</Stack>
<Box ml="auto">{headerRight}</Box>
</Shelf>
)}
{children}
</BasePadding>
)
}
9 changes: 8 additions & 1 deletion centrifuge-app/src/components/Menu/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Box,
IconGlobe,
IconInvestments,
IconNft,
IconPieChart,
Expand All @@ -23,7 +24,7 @@ export function Menu() {
const pools = usePoolsThatAnyConnectedAddressHasPermissionsFor() || []
const isLarge = useIsAboveBreakpoint('L')
const address = useAddress('substrate')
const { showPortfolio } = useDebugFlags()
const { showPortfolio, showPrime } = useDebugFlags()

return (
<Shelf
Expand Down Expand Up @@ -53,6 +54,12 @@ export function Menu() {
Portfolio
</PageLink>
)}
{showPrime && (
<PageLink to="/prime" stacked={!isLarge}>
<IconGlobe />
Prime
</PageLink>
)}

{(pools.length > 0 || config.poolCreationType === 'immediate') && (
<IssuerMenu defaultOpen={isLarge} stacked={!isLarge}>
Expand Down
8 changes: 8 additions & 0 deletions centrifuge-app/src/components/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ const PoolDetailPage = React.lazy(() => import('../pages/Pool'))
const PortfolioPage = React.lazy(() => import('../pages/Portfolio'))
const TransactionsPage = React.lazy(() => import('../pages/Portfolio/Transactions'))
const TokenOverviewPage = React.lazy(() => import('../pages/Tokens'))
const PrimePage = React.lazy(() => import('../pages/Prime'))
const PrimeDetailPage = React.lazy(() => import('../pages/Prime/Detail'))

function Routes() {
return (
Expand Down Expand Up @@ -218,6 +220,12 @@ function Routes() {
<Route path="/portfolio">
<PortfolioPage />
</Route>
<Route path="/prime/:dao">
<PrimeDetailPage />
</Route>
<Route path="/prime">
<PrimePage />
</Route>
<Route path="/disclaimer">
<InvestmentDisclaimerPage />
</Route>
Expand Down
4 changes: 2 additions & 2 deletions centrifuge-app/src/components/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ export const buttonActionStyles = css`
background-color: transparent;
border-radius: ${({ theme }) => theme.radii.tooltip}px;

&:hover,
&:focus-visible {
outline: ${({ theme }) => `2px solid ${theme.colors.textSelected}`};
outline-offset: 4px;
color: ${({ theme }) => theme.colors.textInteractiveHover};
}
`
1 change: 0 additions & 1 deletion centrifuge-app/src/pages/IssuerCreatePool/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ function CreatePoolForm() {
) => {
const [transferToMultisig, aoProxy, adminProxy, , , , , , { adminMultisig }] = args
const multisigAddr = adminMultisig && createKeyMulti(adminMultisig.signers, adminMultisig.threshold)
console.log('adminMultisig', multisigAddr)
const poolArgs = args.slice(2) as any
return combineLatest([
cent.getApi(),
Expand Down
15 changes: 15 additions & 0 deletions centrifuge-app/src/pages/Prime/Detail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useParams } from 'react-router'
import { LayoutBase } from '../../components/LayoutBase'

export default function PrimeDetailPage() {
return (
<LayoutBase>
<PrimeDetail />
</LayoutBase>
)
}

function PrimeDetail() {
const { dao } = useParams<{ dao: string }>()
return <div>Prime detail, {dao}</div>
}
Loading
Loading