diff --git a/apps/finance/app/src/components/DateRange/DateRangeInput.js b/apps/finance/app/src/components/DateRange/DateRangeInput.js index a68bdd9b36..e3cd588ecd 100644 --- a/apps/finance/app/src/components/DateRange/DateRangeInput.js +++ b/apps/finance/app/src/components/DateRange/DateRangeInput.js @@ -174,7 +174,6 @@ const StyledDatePickersContainer = styled.div` display: flex; flex-direction: row; align-items: baseline; - left: -250px; ` )} ` diff --git a/apps/finance/app/src/components/DownloadButton.js b/apps/finance/app/src/components/DownloadButton.js new file mode 100644 index 0000000000..9e6e644421 --- /dev/null +++ b/apps/finance/app/src/components/DownloadButton.js @@ -0,0 +1,21 @@ +import React from 'react' +import { ButtonIcon } from '@aragon/ui' +import IconDownload from './IconDownload' + +const Download = ({ url, filename, ...props }) => ( + + + +) + +export default Download diff --git a/apps/finance/app/src/components/Download.js b/apps/finance/app/src/components/IconDownload.js similarity index 89% rename from apps/finance/app/src/components/Download.js rename to apps/finance/app/src/components/IconDownload.js index f2d524b898..2b4dfdfba8 100644 --- a/apps/finance/app/src/components/Download.js +++ b/apps/finance/app/src/components/IconDownload.js @@ -1,20 +1,4 @@ import React from 'react' -import { ButtonIcon } from '@aragon/ui' - -const Download = props => ( - - - -) const IconDownload = props => ( ( ) -export default Download +export default IconDownload diff --git a/apps/finance/app/src/components/Transfers.js b/apps/finance/app/src/components/Transfers.js index a8905d1664..c3565ee120 100644 --- a/apps/finance/app/src/components/Transfers.js +++ b/apps/finance/app/src/components/Transfers.js @@ -1,43 +1,39 @@ import React from 'react' import styled from 'styled-components' -import { Spring, animated } from 'react-spring' import { compareDesc, - addDays, - addMonths, - getMonth, - getYear, - format, - startOfDay, endOfDay, + format, isWithinInterval, + startOfDay, + subDays, } from 'date-fns' import { Button, Table, TableHeader, TableRow, - DropDown, - theme, - breakpoint, Viewport, - springs, + theme, } from '@aragon/ui' import * as TransferTypes from '../transfer-types' import { addressesEqual, toChecksumAddress } from '../lib/web3-utils' +import { formatTokenAmount } from '../lib/utils' import TransferRow from './TransferRow' import ToggleFiltersButton from './ToggleFiltersButton' -import DateRange from './DateRange/DateRangeInput' -import { formatTokenAmount } from '../lib/utils' -import Download from './Download' +import TransfersFilters from './TransfersFilters' const TRANSFER_TYPES = [ TransferTypes.All, TransferTypes.Incoming, TransferTypes.Outgoing, ] -const TRANSFER_TYPES_STRING = TRANSFER_TYPES.map(TransferTypes.convertToString) const TRANSFERS_PER_PAGE = 10 +const TRANSFER_TYPES_STRING = TRANSFER_TYPES.map(TransferTypes.convertToString) + +const DEFAULT_DAYS_SELECTED = 90 + +const formatDate = date => format(date, 'dd/MM/yy') const reduceTokenDetails = (details, { address, decimals, symbol }) => { details[toChecksumAddress(address)] = { @@ -47,17 +43,11 @@ const reduceTokenDetails = (details, { address, decimals, symbol }) => { return details } -const getCurrentMonthRange = () => { - const now = Date.now() - const month = getMonth(now) - const year = getYear(now) - const start = new Date(year, month, 1) - const end = addDays(addMonths(start, 1), -1) - return { start, end } -} - const initialState = { - selectedDateRange: getCurrentMonthRange(), + selectedDateRange: { + start: subDays(new Date(), DEFAULT_DAYS_SELECTED), + end: new Date(), + }, selectedToken: 0, selectedTransferType: 0, displayedTransfers: TRANSFERS_PER_PAGE, @@ -66,7 +56,7 @@ const initialState = { class Transfers extends React.PureComponent { state = { ...initialState, - filtersOpened: !this.props.autohide, + filtersOpened: !this.props.compactMode, } handleToggleFiltersClick = () => { @@ -114,9 +104,8 @@ class Transfers extends React.PureComponent { true, { rounding: 5 } ) - return `${format( - date, - 'dd/MM/yy' + return `${formatDate( + date )},${entity},${reference},${`${formattedAmount} ${symbol}`}` } ) @@ -128,7 +117,7 @@ class Transfers extends React.PureComponent { const { selectedDateRange } = this.state const start = format(selectedDateRange.start, 'yyyy-MM-dd') const end = format(selectedDateRange.end, 'yyyy-MM-dd') - return `Finance_(${start}_to_${end}).csv` + return `transfers_${start}_to_${end}.csv` } showMoreTransfers = () => { this.setState(prevState => ({ @@ -166,7 +155,7 @@ class Transfers extends React.PureComponent { selectedToken, selectedTransferType, } = this.state - const { transactions, tokens, autohide } = this.props + const { compactMode, tokens, transactions } = this.props const filteredTransfers = this.getFilteredTransfers({ tokens, transactions, @@ -179,253 +168,113 @@ class Transfers extends React.PureComponent { const filtersActive = selectedToken !== 0 || selectedTransferType !== 0 return ( - - {({ below, above }) => ( -
-
- - <span>Transfers </span> - <span> - {below('medium') && ( - <ToggleFiltersButton - title="Toggle Filters" - onClick={this.handleToggleFiltersClick} - /> - )} - </span> - - - {({ progress }) => ( - - v === 1 ? 'unset' : 'hidden' - ), - height: progress.interpolate(v => - below('medium') ? `${180 * v}px` : 'auto' - ), - }} - > - - - - - - - - - - - - - - - - - - - - - - - )} - -
- {filteredTransfers.length === 0 ? ( - -

- No transfers found.{' '} - {filtersActive && ( - - Reset filters - - )} -

-
- ) : ( -
- - - - - - - - ) - } - > - {filteredTransfers - .sort(({ date: dateLeft }, { date: dateRight }) => - // Sort by date descending - compareDesc(dateLeft, dateRight) - ) - .slice(0, displayedTransfers) - .map(transfer => ( - - ))} - - {displayedTransfers < filteredTransfers.length && ( -
- -
- )} -
+
+
+ + <span>Transfers </span> + <span> + {compactMode && ( + <ToggleFiltersButton + title="Toggle Filters" + onClick={this.handleToggleFiltersClick} + css="margin-right: -5px" + /> + )} + </span> + + +
+ {filteredTransfers.length === 0 ? ( + +

+ No transfers match your filter and period ( + {formatDate(selectedDateRange.start)} to{' '} + {formatDate(selectedDateRange.end)}) selection.{' '} + {filtersActive && ( + + Clear filters + + )} +

+
+ ) : ( +
+ + + + + + + + ) + } + css={` + color: ${theme.textPrimary}; + margin-bottom: 20px; + `} + > + {filteredTransfers + .sort(({ date: dateLeft }, { date: dateRight }) => + // Sort by date descending + compareDesc(dateLeft, dateRight) + ) + .slice(0, displayedTransfers) + .map(transfer => ( + + ))} +
+ {displayedTransfers < filteredTransfers.length && ( +
+ +
)} -
+ )} - +
) } } -const WrapDateRange = styled.div` - display: inline-block; - box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.03); -` - -const StyledDownload = styled(Button.Anchor)` - display: flex; - align-items: center; - justify-content: center; - padding: 0; - background: #fff; - box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.03); -` - const Header = styled.div` - margin-bottom: 10px; - - ${breakpoint( - 'medium', - ` - display: flex; - justify-content: space-between; - align-items: baseline; - flex-wrap: wrap; - ` - )}; -` - -const Filters = styled(animated.div)` - margin: 0 20px 10px 20px; - - ${breakpoint( - 'medium', - ` - margin: 0; - display: inline-flex; - align-items: baseline; - justify-content: space-between; - flex-wrap: wrap; - margin-right: 0; - margin-left: auto; - ` - )}; -` - -const FilterLabel = styled.label` - ${breakpoint( - 'medium', - ` - display: flex; - flex-wrap: nowrap; - align-items: center; - white-space: nowrap; - margin-right: 16px; - ` - )}; -` - -const FiltersWrap = styled.div` display: flex; - align-items: flex-end; - justify-content: unset; - margin-top: 16px; - - ${FilterLabel}:first-child { - margin-right: 16px; - } - - ${breakpoint( - 'medium', - ` - display: inline-flex; - align-items: flex-start; - justify-content: space-between; - - ${FilterLabel}:last-child { - margin-right: 0; - } - ` - )} + justify-content: space-between; + align-items: baseline; + flex-wrap: wrap; + margin-bottom: 10px; ` const Title = styled.h1` - margin: 20px 20px 10px 20px; - font-weight: 600; display: flex; justify-content: space-between; - - ${breakpoint( - 'medium', - ` - margin: 30px 30px 20px 0; - ` - )}; -` - -const Label = styled.span` - display: block; - margin-right: 15px; - font-variant: small-caps; - text-transform: lowercase; - color: ${theme.textSecondary}; + align-items: center; + width: 100%; font-weight: 600; - - ${breakpoint( - 'medium', - ` - display: inline; - ` - )}; + margin: ${p => (p.compactMode ? '20px 20px 10px 20px' : '30px 30px 20px 0')}; ` - const NoTransfers = styled.div` display: flex; align-items: center; @@ -433,7 +282,9 @@ const NoTransfers = styled.div` min-height: 200px; background: ${theme.contentBackground}; border: 1px solid ${theme.contentBorder}; - border-radius: 3px; + border-radius: ${p => (p.compactMode ? '0' : '3px')}; + margin-bottom: ${p => (p.compactMode ? '20px' : '0')}; + padding: 20px; a { text-decoration: underline; color: ${theme.accent}; @@ -441,47 +292,15 @@ const NoTransfers = styled.div` } ` -const FixedTable = styled(Table)` - color: rgba(0, 0, 0, 0.75); - margin-bottom: 20px; - - ${breakpoint( - 'medium', - ` - margin-bottom: 0; - ` - )}; -` - -const DateHeader = styled(TableHeader)` - width: 12%; -` -const SourceRecipientHeader = styled(TableHeader)` - width: 40%; -` -const ReferenceHeader = styled(TableHeader)` - width: 100%; -` -const AmountHeader = styled(TableHeader)` - width: 0; -` - const Footer = styled.div` - margin-bottom: 30px; + margin-bottom: ${p => (p.compactMode ? '30px' : '0')}; display: flex; justify-content: center; margin-top: 30px; - - ${breakpoint( - 'medium', - ` - margin-bottom: 0; - ` - )}; ` export default props => ( - {({ below }) => } + {({ below }) => } ) diff --git a/apps/finance/app/src/components/TransfersFilters.js b/apps/finance/app/src/components/TransfersFilters.js new file mode 100644 index 0000000000..4a34aadf1e --- /dev/null +++ b/apps/finance/app/src/components/TransfersFilters.js @@ -0,0 +1,174 @@ +import React from 'react' +import styled, { css } from 'styled-components' +import { DropDown, springs, theme, unselectable } from '@aragon/ui' +import { Spring, animated } from 'react-spring' +import DownloadButton from './DownloadButton' +import DateRange from './DateRange/DateRangeInput' + +const TransfersFilters = ({ + compactMode, + opened, + dateRangeFilter, + onDateRangeChange, + onTokenChange, + symbols, + tokenFilter, + transferTypes, + transferTypeFilter, + onTransferTypeChange, + downloadFileName, + downloadUrl, +}) => ( + + {({ progress, height }) => ( + (v === 1 ? 'unset' : 'hidden')), + height, + }} + > + +
+
+ + + Period + + + + + + + + Token + + + + Type + + + +
+
+ + Export + + +
+
+
+
+ )} +
+) + +const WrapDateRange = styled.div` + display: inline-block; + box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.03); +` + +const Filter = styled.label`` + +const FilterLabel = styled.span` + display: block; + margin-right: 8px; + font-variant: small-caps; + text-transform: lowercase; + color: ${theme.textSecondary}; + font-weight: 600; + ${unselectable}; +` + +const Filters = styled.div` + margin: 0 20px 10px 20px; + padding-bottom: 16px; + ${Filter} { + margin-right: 16px; + } + ${p => + p.compact + ? '' + : css` + width: 100%; + margin: 0; + justify-content: space-between; + margin-left: 0; + margin-right: 0; + + /* Easier than passing compactMode to every Filter & FilterLabel */ + ${Filter} { + display: flex; + flex-wrap: nowrap; + align-items: center; + white-space: nowrap; + } + ${FilterLabel} { + display: inline; + } + `}; +` + +const FiltersGroup = styled.div` + display: ${p => (p.compact ? 'flex' : 'inline-flex')}; + align-items: flex-start; + justify-content: ${p => (p.compact ? 'unset' : 'space-between')}; + & + & { + margin-top: ${p => (p.compact ? '16px' : '0')}; + } +` + +const DownloadLabel = styled(FilterLabel)`` + +const Download = styled(Filter).attrs({ as: 'div' })` + && { + display: flex; + flex-direction: ${p => (p.compact ? 'column' : 'row')}; + align-items: ${p => (p.compact ? 'flex-end' : 'center')}; + margin-top: ${p => (p.compact ? '78px' : '0')}; + margin-right: 0; + } + ${DownloadLabel} { + margin-right: ${p => (p.compact ? '0' : '4px')}; + } +` + +export default TransfersFilters