Skip to content

Commit

Permalink
Token Manager + Finance: edit label from a table’s context menu (arag…
Browse files Browse the repository at this point in the history
  • Loading branch information
delfipolito authored and bpierre committed May 16, 2019
1 parent 525f3c0 commit 8b2e4db
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 128 deletions.
39 changes: 37 additions & 2 deletions apps/finance/app/src/components/IdentityManager/IdentityManager.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { useCallback, useContext, useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import { Subject } from 'rxjs'

Expand All @@ -9,6 +9,41 @@ const IdentityContext = React.createContext({
Promise.reject(Error('Please set resolve using IdentityProvider')),
})

function useIdentity(address) {
const [name, setName] = useState(null)
const { resolve, updates$, showLocalIdentityModal } = useContext(
IdentityContext
)

const handleNameChange = useCallback(metadata => {
setName(metadata ? metadata.name : null)
}, [])

const handleShowLocalIdentityModal = useCallback(
address => {
// Emit an event whenever the modal is closed (when the promise resolves)
return showLocalIdentityModal(address)
.then(() => updates$.next(address))
.catch(e => null)
},
[showLocalIdentityModal, updates$]
)

useEffect(() => {
resolve(address).then(handleNameChange)

const subscription = updates$.subscribe(updatedAddress => {
if (updatedAddress.toLowerCase() === address.toLowerCase()) {
// Resolve and update state when the identity have been updated
resolve(address).then(handleNameChange)
}
})
return () => subscription.unsubscribe()
}, [address, handleNameChange, updates$])

return [name, handleShowLocalIdentityModal]
}

const IdentityProvider = ({
onResolve,
onShowLocalIdentityModal,
Expand All @@ -33,4 +68,4 @@ IdentityProvider.propTypes = {

const IdentityConsumer = IdentityContext.Consumer

export { IdentityProvider, IdentityConsumer, IdentityContext }
export { IdentityConsumer, IdentityContext, IdentityProvider, useIdentity }
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { Badge, IdentityBadge, font } from '@aragon/ui'
import { IdentityContext } from '../IdentityManager/IdentityManager'

function useIdentity(address) {
const [name, setName] = React.useState(null)
const { resolve, updates$, showLocalIdentityModal } = React.useContext(
IdentityContext
)

const handleNameChange = metadata => {
setName(metadata ? metadata.name : null)
}

const handleShowLocalIdentityModal = address => {
// Emit an event whenever the modal is closed (when the promise resolves)
return showLocalIdentityModal(address)
.then(() => updates$.next(address))
.catch(e => null)
}

React.useEffect(() => {
resolve(address).then(handleNameChange)

const subscription = updates$.subscribe(updatedAddress => {
if (updatedAddress.toLowerCase() === address.toLowerCase()) {
// Resolve and update state when the identity have been updated
resolve(address).then(handleNameChange)
}
})
return () => subscription.unsubscribe()
}, [address])

return [name, handleShowLocalIdentityModal]
}
import { useIdentity } from '../IdentityManager/IdentityManager'

const LocalIdentityBadge = ({ entity, ...props }) => {
const [label, showLocalIdentityModal] = useIdentity(entity)
Expand Down
62 changes: 33 additions & 29 deletions apps/finance/app/src/components/TransferRow.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { useCallback } from 'react'
import styled from 'styled-components'
import { format } from 'date-fns'
import { useNetwork } from '@aragon/api-react'
Expand All @@ -12,47 +12,45 @@ import {
} from '@aragon/ui'
import { formatTokenAmount } from '../lib/utils'
import IconTokens from './icons/IconTokens'
import IconLabel from './icons/IconLabel'
import LocalIdentityBadge from './LocalIdentityBadge/LocalIdentityBadge'
import { useIdentity } from './IdentityManager/IdentityManager'

class TransferRow extends React.PureComponent {
handleViewTransaction = () => {
const TransferRow = React.memo(
({ network, transaction, token, smallViewMode }) => {
const {
network,
transaction: { transactionHash },
} = this.props
window.open(
blockExplorerUrl('transaction', transactionHash, {
networkType: network.type,
}),
'_blank'
)
}
date,
entity,
isIncoming,
numData: { amount },
reference,
transactionHash,
} = transaction

render() {
const {
network,
token,
smallViewMode,
transaction: {
date,
entity,
isIncoming,
numData: { amount },
reference,
transactionHash,
},
} = this.props
const handleViewTransaction = useCallback(() => {
window.open(
blockExplorerUrl('transaction', transactionHash, {
networkType: network.type,
}),
'_blank'
)
}, [transactionHash, network])

const [label, showLocalIdentityModal] = useIdentity(entity)
const handleEditLabel = useCallback(() => showLocalIdentityModal(entity))

const txUrl = blockExplorerUrl('transaction', transactionHash, {
networkType: network.type,
})

const formattedAmount = formatTokenAmount(
amount,
isIncoming,
token.decimals,
true,
{ rounding: 5 }
)

const formattedDate = format(date, "yyyy-MM-dd'T'HH:mm:ss.SSSxxx")

if (smallViewMode) {
Expand Down Expand Up @@ -115,18 +113,24 @@ class TransferRow extends React.PureComponent {
<div css="position: relative">
{txUrl && (
<ContextMenu>
<ContextMenuItem onClick={this.handleViewTransaction}>
<ContextMenuItem onClick={handleViewTransaction}>
<IconTokens />
<div css="margin-left: 15px">View Transaction</div>
</ContextMenuItem>
<ContextMenuItem onClick={handleEditLabel}>
<IconLabel />
<div css="margin-left: 15px">
{label ? 'Edit' : 'Add'} custom label
</div>
</ContextMenuItem>
</ContextMenu>
)}
</div>
</NoWrapCell>
</TableRow>
)
}
}
)

const StyledTableCell = styled(TableCell)`
max-width: 0;
Expand Down
14 changes: 14 additions & 0 deletions apps/finance/app/src/components/icons/IconLabel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'

const Label = props => (
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" {...props}>
<path
d="M11.5404 19.0354L11.5758 19.0707L11.6111 19.0354C14.0854 16.5604 16.5604 14.0854 19.0354 11.6111L19.0708 11.5757L19.0353 11.5403L8.42655 0.96459L8.41191 0.95H8.39125H1H0.95V1V8.42125V8.44196L0.96464 8.4566L11.5404 19.0354ZM6.84037 4.11766L6.84036 4.11764C6.08883 3.36612 4.86917 3.36612 4.11764 4.11764C3.36612 4.86917 3.36612 6.08883 4.11764 6.84036L4.11766 6.84037C4.86918 7.59113 6.08882 7.59113 6.84034 6.84037L6.84037 6.84034C7.59113 6.08882 7.59113 4.86918 6.84037 4.11766ZM6.23868 6.23861L6.23861 6.23868C5.81941 6.65859 5.1386 6.65864 4.71861 6.23864C4.29941 5.81945 4.29935 5.13861 4.71861 4.71861C5.13861 4.29935 5.81945 4.29941 6.23864 4.71861C6.65864 5.1386 6.65859 5.81941 6.23868 6.23861ZM8.06084 1.8C11.3299 5.05861 14.5989 8.31721 17.868 11.5766L11.5758 17.8688L1.8 8.09004V1.8H8.06084Z"
fill="#000"
stroke="#8B9396"
strokeWidth="0.1"
/>
</svg>
)

export default Label
72 changes: 42 additions & 30 deletions apps/token-manager/app/src/components/HolderRow.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { useCallback } from 'react'
import styled from 'styled-components'
import {
ContextMenu,
Expand All @@ -9,42 +9,40 @@ import {
TableRow,
theme,
} from '@aragon/ui'
import IconLabel from './IconLabel'
import { useNetwork } from '@aragon/api-react'
import LocalIdentityBadge from './LocalIdentityBadge/LocalIdentityBadge'
import { formatBalance } from '../utils'
import You from './You'
import { useIdentity } from './IdentityManager/IdentityManager'

class HolderRow extends React.Component {
static defaultProps = {
address: '',
balance: 0,
groupMode: false,
onAssignTokens: () => {},
onRemoveTokens: () => {},
}
handleAssignTokens = () => {
const { address, onAssignTokens } = this.props
onAssignTokens(address)
}
handleRemoveTokens = () => {
const { address, onRemoveTokens } = this.props
onRemoveTokens(address)
}
render() {
const {
address,
balance,
groupMode,
isCurrentUser,
maxAccountTokens,
network,
tokenDecimalsBase,
compact,
} = this.props
const HolderRow = React.memo(
({
address,
balance,
groupMode,
isCurrentUser,
maxAccountTokens,
network,
tokenDecimalsBase,
compact,
onAssignTokens,
onRemoveTokens,
}) => {
const handleAssignTokens = useCallback(() => {
onAssignTokens(address)
}, [address, onAssignTokens])

const handleRemoveTokens = useCallback(() => {
onRemoveTokens(address)
}, [address, onRemoveTokens])

const singleToken = balance.eq(tokenDecimalsBase)
const canAssign = balance.lt(maxAccountTokens)

const [label, showLocalIdentityModal] = useIdentity(address)
const handleEditLabel = useCallback(() => showLocalIdentityModal(address))

return (
<TableRow>
<FirstTableCell css="padding-right: 0">
Expand All @@ -65,14 +63,14 @@ class HolderRow extends React.Component {
<TableCell align="right" css="padding-left: 0">
<ContextMenu>
{canAssign && (
<ContextMenuItem onClick={this.handleAssignTokens}>
<ContextMenuItem onClick={handleAssignTokens}>
<IconWrapper>
<IconAdd />
</IconWrapper>
<ActionLabel>Add tokens</ActionLabel>
</ContextMenuItem>
)}
<ContextMenuItem onClick={this.handleRemoveTokens}>
<ContextMenuItem onClick={handleRemoveTokens}>
<IconWrapper>
<IconRemove />
</IconWrapper>
Expand All @@ -81,11 +79,25 @@ class HolderRow extends React.Component {
{singleToken ? '' : 's'}
</ActionLabel>
</ContextMenuItem>
<ContextMenuItem onClick={handleEditLabel}>
<IconWrapper>
<IconLabel />
</IconWrapper>
<ActionLabel>{label ? 'Edit' : 'Add'} custom label</ActionLabel>
</ContextMenuItem>
</ContextMenu>
</TableCell>
</TableRow>
)
}
)

HolderRow.defaultProps = {
address: '',
balance: 0,
groupMode: false,
onAssignTokens: () => {},
onRemoveTokens: () => {},
}

const FirstTableCell = styled(TableCell)`
Expand Down
14 changes: 14 additions & 0 deletions apps/token-manager/app/src/components/IconLabel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'

const Label = props => (
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" {...props}>
<path
d="M11.5404 19.0354L11.5758 19.0707L11.6111 19.0354C14.0854 16.5604 16.5604 14.0854 19.0354 11.6111L19.0708 11.5757L19.0353 11.5403L8.42655 0.96459L8.41191 0.95H8.39125H1H0.95V1V8.42125V8.44196L0.96464 8.4566L11.5404 19.0354ZM6.84037 4.11766L6.84036 4.11764C6.08883 3.36612 4.86917 3.36612 4.11764 4.11764C3.36612 4.86917 3.36612 6.08883 4.11764 6.84036L4.11766 6.84037C4.86918 7.59113 6.08882 7.59113 6.84034 6.84037L6.84037 6.84034C7.59113 6.08882 7.59113 4.86918 6.84037 4.11766ZM6.23868 6.23861L6.23861 6.23868C5.81941 6.65859 5.1386 6.65864 4.71861 6.23864C4.29941 5.81945 4.29935 5.13861 4.71861 4.71861C5.13861 4.29935 5.81945 4.29941 6.23864 4.71861C6.65864 5.1386 6.65859 5.81941 6.23868 6.23861ZM8.06084 1.8C11.3299 5.05861 14.5989 8.31721 17.868 11.5766L11.5758 17.8688L1.8 8.09004V1.8H8.06084Z"
fill="#99A0A2"
stroke="#8B9396"
strokeWidth="0.1"
/>
</svg>
)

export default Label
Loading

0 comments on commit 8b2e4db

Please sign in to comment.