Skip to content

Commit

Permalink
settings: network preferences (#238)
Browse files Browse the repository at this point in the history
* box

* change polling

* stats

* stats

* eth node and active jurors

* svg optimization

* network folder

* network preferences

* onClose

* remove old network json

* http regex

* usePreferences hook

* Preferences from Global error screen

* Pr comments about usePrefereces

* remove preferences from global error

* ipfs endpoint

* reload on clear settings

* typo
  • Loading branch information
rperez89 authored Apr 8, 2020
1 parent a466e39 commit 160a3eb
Show file tree
Hide file tree
Showing 21 changed files with 758 additions and 50 deletions.
1 change: 1 addition & 0 deletions src/assets/global-preferences-network.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion src/components/Dashboard/CourtStats.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ function TokenStats({ stat, theme }) {

function AnjUsdValue(amount) {
const usdValue = useANJBalanceToUsd(amount)

return usdValue
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/Errors/GlobalErrorScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ function GlobalErrorScreen({ children }) {
<img
css={`
position: absolute;
top: 16px;
left: 16px;
top: ${2 * GU}px;
left: ${2 * GU}px;
`}
src={logo}
/>
Expand Down
172 changes: 172 additions & 0 deletions src/components/GlobalPreferences/GlobalPreferences.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import React, { useCallback, useEffect, useRef, useState } from 'react'
import {
ButtonIcon,
GU,
Header,
IconClose,
Layout,
Tabs,
springs,
useTheme,
useViewport,
} from '@aragon/ui'
import { Transition, animated } from 'react-spring/renderprops'
import { useEsc } from '../../hooks/useKeyboardArrows'
import Network from './Network/Network'

const SECTIONS = new Map([['network', 'Network']])
const PATHS = Array.from(SECTIONS.keys())
const VALUES = Array.from(SECTIONS.values())

const NETWORK_INDEX = 0

const AnimatedDiv = animated.div

function GlobalPreferences({ compact, onClose, onNavigation, sectionIndex }) {
useEsc(onClose)

const container = useRef()
useEffect(() => {
if (container.current) {
container.current.focus()
}
}, [])

return (
<div ref={container} tabIndex="0" css="outline: 0">
<Layout css="z-index: 2">
<Close compact={compact} onClick={onClose} />
<Header
primary="Global preferences"
css={`
padding-top: ${!compact ? 10 * GU : 0}px;
`}
/>
<React.Fragment>
<Tabs
items={VALUES}
onChange={onNavigation}
selected={sectionIndex}
/>

<main>{sectionIndex === NETWORK_INDEX && <Network />}</main>
</React.Fragment>
</Layout>
</div>
)
}

function useGlobalPreferences({ path = '', onScreenChange }) {
const [sectionIndex, setSectionIndex] = useState(null)
const handleNavigation = useCallback(
index => {
onScreenChange(PATHS[index]) // TODO - Test if this is working with the email preferences
},
[onScreenChange]
)

useEffect(() => {
if (!path) {
setSectionIndex(null)
return
}
const index = PATHS.findIndex(item => path.startsWith(item))

setSectionIndex(index === -1 ? null : index)
}, [path, sectionIndex])

return { sectionIndex, handleNavigation }
}

function Close({ compact, onClick }) {
const theme = useTheme()
return (
<div
css={`
position: absolute;
right: 0;
padding-top: ${2.5 * GU}px;
padding-right: ${3 * GU}px;
${compact &&
`
padding-top: ${2 * GU}px;
padding-right: ${1.5 * GU}px;
`}
`}
>
<ButtonIcon onClick={onClick} label="Close">
<IconClose
css={`
color: ${theme.surfaceIcon};
`}
/>
</ButtonIcon>
</div>
)
}

function AnimatedGlobalPreferences({ path, onScreenChange, onClose }) {
const { sectionIndex, handleNavigation } = useGlobalPreferences({
path,
onScreenChange,
})

const { below } = useViewport()
const compact = below('medium')
const theme = useTheme()

return (
<Transition
native
items={sectionIndex !== null}
from={{ opacity: 0, enterProgress: 0, blocking: false }}
enter={{ opacity: 1, enterProgress: 1, blocking: true }}
leave={{ opacity: 0, enterProgress: 1, blocking: false }}
config={springs.smooth}
>
{show =>
show &&
/* eslint-disable react/prop-types */
// z-index 1 on mobile keeps the menu above this preferences modal
(({ opacity, enterProgress, blocking }) => (
<AnimatedDiv
style={{
zIndex: 1,
pointerEvents: blocking ? 'auto' : 'none',
opacity,
transform: enterProgress.interpolate(
v => `
translate3d(0, ${(1 - v) * 10}px, 0)
scale3d(${1 - (1 - v) * 0.03}, ${1 - (1 - v) * 0.03}, 1)
`
),
}}
css={`
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: auto;
min-width: ${45 * GU}px;
padding-bottom: ${compact ? 2 : 0 * GU}px;
border-top: 2px solid ${theme.accent};
background: ${theme.surface};
`}
>
<GlobalPreferences
onClose={onClose}
compact={compact}
sectionIndex={sectionIndex}
onNavigation={handleNavigation}
/>
</AnimatedDiv>
))
/* eslint-enable react/prop-types */
}
</Transition>
)
}

export default React.memo(AnimatedGlobalPreferences)
148 changes: 148 additions & 0 deletions src/components/GlobalPreferences/GlobalPreferencesButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React, { useRef, useState, useCallback } from 'react'
import {
ButtonBase,
ButtonIcon,
GU,
IconSettings,
Popover,
RADIUS,
textStyle,
useTheme,
useViewport,
} from '@aragon/ui'

import iconNetwork from '../../assets/global-preferences-network.svg'

function GlobalPreferencesButton({ onOpen }) {
const theme = useTheme()
const { below } = useViewport()

const [opened, setOpened] = useState(false)
const containerRef = useRef()

const handleToggle = useCallback(() => setOpened(opened => !opened), [])
const handleClose = useCallback(() => setOpened(false), [])
const handleItemClick = useCallback(
path => () => {
setOpened(false)
onOpen(path)
},
[onOpen]
)

return (
<React.Fragment>
<div ref={containerRef}>
<ButtonIcon
element="div"
onClick={handleToggle}
css={`
width: ${4.25 * GU}px;
height: 100%;
border-radius: 0;
`}
label="Global preferences"
>
<IconSettings
css={`
color: ${theme.hint};
`}
/>
</ButtonIcon>
</div>
<Popover
closeOnOpenerFocus
placement="bottom-end"
onClose={handleClose}
visible={opened}
opener={containerRef.current}
>
<ul
css={`
/* Use 20px as the padding setting for popper is 10px */
width: ${below('medium') ? `calc(100vw - 20px)` : `${42 * GU}px`};
padding: 0;
margin: 0;
list-style: none;
background: ${theme.surface};
color: ${theme.content};
border-radius: ${RADIUS}px;
`}
>
<li
css={`
display: flex;
align-items: center;
height: ${4 * GU}px;
padding-left: ${2 * GU}px;
border-bottom: 1px solid ${theme.border};
${textStyle('label2')}
color: ${theme.surfaceContentSecondary};
`}
>
Global preferences
</li>
<Item
onClick={handleItemClick('network')}
icon={iconNetwork}
label="Network"
/>
</ul>
</Popover>
</React.Fragment>
)
}

function Item({ icon, label, onClick }) {
const theme = useTheme()

return (
<li
css={`
& + & {
border-top: 1px solid ${theme.border};
}
`}
>
<ButtonBase
onClick={onClick}
label={label}
css={`
width: 100%;
height: ${7 * GU}px;
border-radius: 0;
`}
>
<div
css={`
display: flex;
width: 100%;
height: 100%;
padding: ${2 * GU}px;
justify-content: left;
align-items: center;
&:active,
&:focus {
background: ${theme.surfacePressed};
}
`}
>
{icon && <img src={icon} alt="" />}
<div
css={`
flex-grow: 1;
display: flex;
align-items: center;
margin-left: ${icon ? 1 * GU : 0}px;
`}
>
{label}
</div>
</div>
</ButtonBase>
</li>
)
}

export default React.memo(GlobalPreferencesButton)
Loading

1 comment on commit 160a3eb

@vercel
Copy link

@vercel vercel bot commented on 160a3eb Apr 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.