Browse Source

Merge pull request #114 from meriadec/master

Create dropdown component and use it in TopBar and Dashboard
master
Loëck Vézien 7 years ago
committed by GitHub
parent
commit
5b9e0ec489
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 58
      src/components/DashboardPage/index.js
  2. 29
      src/components/SettingsPage/Display.js
  3. 10
      src/components/SettingsPage/index.js
  4. 10
      src/components/TopBar.js
  5. 101
      src/components/base/DropDown/index.js
  6. 6
      static/i18n/en/translation.yml
  7. 6
      static/i18n/fr/translation.yml

58
src/components/DashboardPage/index.js

@ -13,32 +13,44 @@ import sortBy from 'lodash/sortBy'
import takeRight from 'lodash/takeRight' import takeRight from 'lodash/takeRight'
import type { MapStateToProps } from 'react-redux' import type { MapStateToProps } from 'react-redux'
import type { Accounts } from 'types/common' import type { Accounts, T } from 'types/common'
import { space } from 'styles/theme' import { space } from 'styles/theme'
import { getVisibleAccounts } from 'reducers/accounts' import { getVisibleAccounts } from 'reducers/accounts'
import { getOrderAccounts } from 'reducers/settings'
import { updateOrderAccounts } from 'actions/accounts'
import { saveSettings } from 'actions/settings'
import { AreaChart } from 'components/base/Chart' import { AreaChart } from 'components/base/Chart'
import Box, { Card } from 'components/base/Box' import Box, { Card } from 'components/base/Box'
import Pills from 'components/base/Pills' import Pills from 'components/base/Pills'
import Text from 'components/base/Text' import Text from 'components/base/Text'
import TransactionsList from 'components/TransactionsList' import TransactionsList from 'components/TransactionsList'
import DropDown from 'components/base/DropDown'
import AccountCard from './AccountCard' import AccountCard from './AccountCard'
import BalanceInfos from './BalanceInfos' import BalanceInfos from './BalanceInfos'
const mapStateToProps: MapStateToProps<*, *, *> = state => ({ const mapStateToProps: MapStateToProps<*, *, *> = state => ({
accounts: getVisibleAccounts(state), accounts: getVisibleAccounts(state),
orderAccounts: getOrderAccounts(state),
}) })
const mapDispatchToProps = { const mapDispatchToProps = {
push, push,
updateOrderAccounts,
saveSettings,
} }
type Props = { type Props = {
accounts: Accounts, accounts: Accounts,
push: Function, push: Function,
t: T,
updateOrderAccounts: Function,
saveSettings: Function,
orderAccounts: string,
} }
type State = { type State = {
@ -108,6 +120,12 @@ class DashboardPage extends PureComponent<Props, State> {
return chunk(listAccounts, ACCOUNTS_BY_LINE) return chunk(listAccounts, ACCOUNTS_BY_LINE)
} }
setAccountOrder = order => {
const { updateOrderAccounts, saveSettings } = this.props
updateOrderAccounts(order)
saveSettings({ orderAccounts: order })
}
generateFakeDatas() { generateFakeDatas() {
const { accounts } = this.props const { accounts } = this.props
return accounts.map(() => [...Array(25).keys()].map(v => generateFakeData(v + 1))) return accounts.map(() => [...Array(25).keys()].map(v => generateFakeData(v + 1)))
@ -136,11 +154,26 @@ class DashboardPage extends PureComponent<Props, State> {
_timeout = undefined _timeout = undefined
render() { render() {
const { push, accounts } = this.props const { push, accounts, t, orderAccounts } = this.props
const { selectedTime, fakeDatas } = this.state const { selectedTime, fakeDatas } = this.state
const totalAccounts = accounts.length const totalAccounts = accounts.length
const sortItems = [
{
key: 'name',
label: t('orderAccounts.name'),
},
{
key: 'balance',
label: t('orderAccounts.balance'),
},
{
key: 'type',
label: t('orderAccounts.type'),
},
]
return ( return (
<Box flow={7}> <Box flow={7}>
<Box horizontal align="flex-end"> <Box horizontal align="flex-end">
@ -195,9 +228,24 @@ class DashboardPage extends PureComponent<Props, State> {
</Box> </Box>
</Card> </Card>
<Box flow={4}> <Box flow={4}>
<Text color="dark" ff="Museo Sans" fontSize={6}> <Box horizontal align="flex-end">
{'Accounts'} <Text color="dark" ff="Museo Sans" fontSize={6}>
</Text> {'Accounts'}
</Text>
<Box ml="auto" horizontal flow={1}>
<Text ff="Open Sans|SemiBold" fontSize={4}>
{'Sort by'}
</Text>
<DropDown
onChange={item => this.setAccountOrder(item.key)}
items={sortItems}
ff="Open Sans|SemiBold"
fontSize={4}
>
<Text color="dark">{t(`orderAccounts.${orderAccounts}`)}</Text>
</DropDown>
</Box>
</Box>
<Box flow={5}> <Box flow={5}>
{this.getAccountsChunk().map((accountsByLine, i) => ( {this.getAccountsChunk().map((accountsByLine, i) => (
<Box <Box

29
src/components/SettingsPage/Display.js

@ -17,6 +17,7 @@ type Props = {
settings: SettingsDisplay, settings: SettingsDisplay,
onSaveSettings: Function, onSaveSettings: Function,
} }
type State = { type State = {
inputValue: InputValue, inputValue: InputValue,
} }
@ -25,7 +26,7 @@ class TabProfile extends PureComponent<Props, State> {
state = { state = {
inputValue: { inputValue: {
language: this.props.settings.language, language: this.props.settings.language,
orderAccounts: this.props.settings.orderAccounts, orderAccounts: '',
}, },
} }
@ -43,20 +44,6 @@ class TabProfile extends PureComponent<Props, State> {
name: t('language.fr'), name: t('language.fr'),
}, },
], ],
orderAccounts: [
{
key: 'name',
name: t('orderAccounts.name'),
},
{
key: 'balance',
name: t('orderAccounts.balance'),
},
{
key: 'type',
name: t('orderAccounts.type'),
},
],
} }
} }
@ -83,10 +70,9 @@ class TabProfile extends PureComponent<Props, State> {
const { t } = this.props const { t } = this.props
const { inputValue } = this.state const { inputValue } = this.state
const { languages, orderAccounts } = this.getDatas() const { languages } = this.getDatas()
const currentLanguage = languages.find(l => l.key === inputValue.language) const currentLanguage = languages.find(l => l.key === inputValue.language)
const currentOrderAccounts = orderAccounts.find(l => l.key === inputValue.orderAccounts)
return ( return (
<form onSubmit={this.handleSubmit}> <form onSubmit={this.handleSubmit}>
@ -100,15 +86,6 @@ class TabProfile extends PureComponent<Props, State> {
items={languages} items={languages}
/> />
</Box> </Box>
<Box flow={1}>
<Label>{t('settings.display.orderAccounts')}</Label>
<Select
onChange={item => this.handleChangeInput('orderAccounts')(item.key)}
renderSelected={item => item && item.name}
value={currentOrderAccounts}
items={orderAccounts}
/>
</Box>
<Box horizontal justify="flex-end"> <Box horizontal justify="flex-end">
<Button primary type="submit"> <Button primary type="submit">
Save Save

10
src/components/SettingsPage/index.js

@ -8,9 +8,7 @@ import { translate } from 'react-i18next'
import type { MapStateToProps } from 'react-redux' import type { MapStateToProps } from 'react-redux'
import type { Settings, T } from 'types/common' import type { Settings, T } from 'types/common'
import type { SaveSettings } from 'actions/settings' import type { SaveSettings } from 'actions/settings'
import type { UpdateOrderAccounts } from 'actions/accounts'
import { updateOrderAccounts } from 'actions/accounts'
import { saveSettings } from 'actions/settings' import { saveSettings } from 'actions/settings'
import Box from 'components/base/Box' import Box from 'components/base/Box'
@ -26,7 +24,6 @@ const mapStateToProps: MapStateToProps<*, *, *> = state => ({
const mapDispatchToProps = { const mapDispatchToProps = {
saveSettings, saveSettings,
updateOrderAccounts,
} }
type Props = { type Props = {
@ -34,7 +31,6 @@ type Props = {
saveSettings: SaveSettings, saveSettings: SaveSettings,
settings: Settings, settings: Settings,
t: T, t: T,
updateOrderAccounts: UpdateOrderAccounts,
} }
type State = { type State = {
@ -49,16 +45,12 @@ class SettingsPage extends PureComponent<Props, State> {
handleChangeTab = (tab: number) => this.setState({ tab }) handleChangeTab = (tab: number) => this.setState({ tab })
handleSaveSettings = newSettings => { handleSaveSettings = newSettings => {
const { saveSettings, i18n, settings, updateOrderAccounts } = this.props const { saveSettings, i18n, settings } = this.props
if (newSettings.language !== settings.language) { if (newSettings.language !== settings.language) {
i18n.changeLanguage(newSettings.language) i18n.changeLanguage(newSettings.language)
} }
if (newSettings.orderAccounts !== settings.orderAccounts) {
updateOrderAccounts(newSettings.orderAccounts)
}
saveSettings(newSettings) saveSettings(newSettings)
} }

10
src/components/TopBar.js

@ -15,6 +15,7 @@ import { hasPassword } from 'reducers/settings'
import IconDevices from 'icons/Devices' import IconDevices from 'icons/Devices'
import IconActivity from 'icons/Activity' import IconActivity from 'icons/Activity'
import DropDown from 'components/base/DropDown'
import Box from 'components/base/Box' import Box from 'components/base/Box'
import GlobalSearch from 'components/GlobalSearch' import GlobalSearch from 'components/GlobalSearch'
@ -23,7 +24,6 @@ const Container = styled(Box).attrs({
})` })`
height: ${p => p.theme.sizes.topBarHeight}px; height: ${p => p.theme.sizes.topBarHeight}px;
position: absolute; position: absolute;
overflow: hidden;
left: 0; left: 0;
right: 0; right: 0;
top: 0; top: 0;
@ -142,9 +142,13 @@ class TopBar extends PureComponent<Props, State> {
</Box> </Box>
</Box> </Box>
<Box horizontal noShrink> <Box horizontal noShrink>
<Box justify="center" px={4} ff="Open Sans|SemiBold" fontSize={4}> <DropDown
items={[{ key: 'empty', label: 'Nothing here yet' }]}
ff="Open Sans|SemiBold"
fontSize={4}
>
{'Khalil Benihoud'} {'Khalil Benihoud'}
</Box> </DropDown>
</Box> </Box>
</Inner> </Inner>
</Container> </Container>

101
src/components/base/DropDown/index.js

@ -0,0 +1,101 @@
// @flow
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import noop from 'lodash/noop'
import Downshift from 'downshift'
import Box from 'components/base/Box'
type ItemType = {
key: string,
label: any,
}
type Props = {
children: any,
items: Array<ItemType>,
value?: ItemType | null,
onChange?: ItemType => void,
}
const Trigger = styled(Box)`
outline: none;
cursor: pointer;
`
const Drop = styled(Box).attrs({
bg: 'white',
boxShadow: 0,
})`
position: absolute;
top: 100%;
right: 0;
`
const Item = styled(Box).attrs({
py: 2,
px: 4,
bg: p => (p.isHighlighted ? 'pearl' : ''),
})`
white-space: nowrap;
`
function itemToString(item) {
return item ? item.label : ''
}
class DropDown extends PureComponent<Props> {
static defaultProps = {
value: null,
onChange: noop,
}
renderItems = (items: Array<ItemType>, selectedItem: ItemType, downshiftProps: Object) => {
const { getItemProps, highlightedIndex } = downshiftProps
return (
<Drop>
{items.map((item, i) => (
<Item isHighlighted={highlightedIndex === i} key={item.key} {...getItemProps({ item })}>
{item.label}
</Item>
))}
</Drop>
)
}
render() {
const { children, items, value, onChange, ...props } = this.props
return (
<Downshift
onChange={onChange}
itemToString={itemToString}
selectedItem={value}
render={({
getButtonProps,
getRootProps,
isOpen,
openMenu,
selectedItem,
...downshiftProps
}) => (
<Box
{...getRootProps({ refKey: 'innerRef' })}
horizontal
align="center"
relative
{...props}
>
<Trigger {...getButtonProps()} tabIndex={0}>
{children}
</Trigger>
{isOpen && this.renderItems(items, selectedItem, downshiftProps)}
</Box>
)}
/>
)
}
}
export default DropDown

6
static/i18n/en/translation.yml

@ -9,9 +9,9 @@ language:
fr: French fr: French
orderAccounts: orderAccounts:
name: By name name: Name
balance: By balance balance: Balance
type: By type type: Type
sidebar: sidebar:
menu: Menu menu: Menu

6
static/i18n/fr/translation.yml

@ -9,9 +9,9 @@ language:
fr: Français fr: Français
orderAccounts: orderAccounts:
name: Par nom name: Nom
balance: Par solde balance: Solde
type: Par type type: Type
sidebar: sidebar:
menu: Menu menu: Menu

Loading…
Cancel
Save