2020-05-03 06:22:49 +01:00
|
|
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
|
|
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
|
|
|
import { injectIntl, defineMessages } from 'react-intl'
|
|
|
|
import isObject from 'lodash.isobject'
|
|
|
|
import {
|
|
|
|
setupListEditor,
|
|
|
|
resetListEditor,
|
|
|
|
removeFromListEditor,
|
|
|
|
addToListEditor,
|
|
|
|
fetchListSuggestions,
|
|
|
|
clearListSuggestions,
|
|
|
|
changeListSuggestions,
|
|
|
|
} from '../actions/lists'
|
|
|
|
import { openModal } from '../actions/modal'
|
|
|
|
import {
|
|
|
|
MODAL_LIST_EDITOR,
|
|
|
|
MODAL_LIST_DELETE,
|
|
|
|
} from '../constants'
|
|
|
|
import Account from '../components/account'
|
|
|
|
import Button from '../components/button'
|
|
|
|
import Divider from '../components/divider'
|
|
|
|
import Input from '../components/input'
|
|
|
|
import TabBar from '../components/tab_bar'
|
|
|
|
import Text from '../components/text'
|
|
|
|
|
|
|
|
const messages = defineMessages({
|
|
|
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
|
|
|
save: { id: 'lists.new.save_title', defaultMessage: 'Save Title' },
|
|
|
|
changeTitle: { id: 'lists.edit.submit', defaultMessage: 'Change title' },
|
|
|
|
addToList: { id: 'lists.account.add', defaultMessage: 'Add to list' },
|
|
|
|
removeFromList: { id: 'lists.account.remove', defaultMessage: 'Remove from list' },
|
|
|
|
editList: { id: 'lists.edit', defaultMessage: 'Edit list' },
|
|
|
|
editListTitle: { id: 'lists.new.edit_title_placeholder', defaultMessage: 'Edit list title' },
|
|
|
|
remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' },
|
|
|
|
add: { id: 'lists.account.add', defaultMessage: 'Add to list' },
|
|
|
|
search: { id: 'lists.search', defaultMessage: 'Search people...' },
|
|
|
|
searchMembers: { id: 'lists.search_members', defaultMessage: 'Search members...' },
|
|
|
|
searchTitle: { id: 'tabs_bar.search', defaultMessage: 'Search' },
|
|
|
|
})
|
|
|
|
|
|
|
|
const mapStateToProps = (state, { params, id }) => {
|
|
|
|
const listId = isObject(params) ? params['id'] : id
|
|
|
|
|
|
|
|
return {
|
|
|
|
listId,
|
|
|
|
list: state.getIn(['lists', listId]),
|
|
|
|
title: state.getIn(['listEditor', 'title']),
|
|
|
|
disabled: !state.getIn(['listEditor', 'isChanged']),
|
|
|
|
accountIds: state.getIn(['listEditor', 'accounts', 'items']),
|
|
|
|
searchAccountIds: state.getIn(['listEditor', 'suggestions', 'items']),
|
|
|
|
searchSuggestionsValue: state.getIn(['listEditor', 'suggestions', 'value']),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const mapDispatchToProps = (dispatch) => ({
|
|
|
|
|
|
|
|
onDeleteList(list) {
|
|
|
|
dispatch(openModal(MODAL_LIST_DELETE, { list }))
|
|
|
|
},
|
|
|
|
|
|
|
|
onChangeTitle(value) {
|
|
|
|
dispatch(changeListEditorTitle(value))
|
|
|
|
},
|
|
|
|
|
|
|
|
onUpdateList() {
|
|
|
|
dispatch(submitListEditor(false))
|
|
|
|
},
|
|
|
|
|
|
|
|
onInitialize(listId) {
|
|
|
|
dispatch(setupListEditor(listId))
|
|
|
|
},
|
|
|
|
|
|
|
|
onReset() {
|
|
|
|
dispatch(resetListEditor())
|
|
|
|
},
|
|
|
|
|
|
|
|
onRemoveAccountFromList(accountId) {
|
|
|
|
dispatch(removeFromListEditor(accountId))
|
|
|
|
},
|
|
|
|
|
|
|
|
onAddAccountToList(accountId) {
|
|
|
|
dispatch(addToListEditor(accountId))
|
|
|
|
},
|
|
|
|
|
|
|
|
onSubmitSearchSuggestions(value) {
|
|
|
|
dispatch(fetchListSuggestions(value))
|
|
|
|
},
|
|
|
|
|
|
|
|
onClearSearchSuggestions() {
|
|
|
|
dispatch(clearListSuggestions())
|
|
|
|
},
|
|
|
|
|
|
|
|
onChangeSuggestions(value) {
|
|
|
|
dispatch(changeListSuggestions(value))
|
|
|
|
},
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
export default
|
|
|
|
@connect(mapStateToProps, mapDispatchToProps)
|
|
|
|
@injectIntl
|
|
|
|
class ListEdit extends ImmutablePureComponent {
|
|
|
|
|
|
|
|
static propTypes = {
|
|
|
|
list: ImmutablePropTypes.map,
|
|
|
|
title: PropTypes.string,
|
|
|
|
listId: PropTypes.string.isRequired,
|
|
|
|
onClose: PropTypes.func.isRequired,
|
|
|
|
intl: PropTypes.object.isRequired,
|
|
|
|
onInitialize: PropTypes.func.isRequired,
|
|
|
|
onReset: PropTypes.func.isRequired,
|
|
|
|
searchSuggestionsValue: PropTypes.string.isRequired,
|
|
|
|
accountIds: ImmutablePropTypes.list.isRequired,
|
|
|
|
searchAccountIds: ImmutablePropTypes.list.isRequired,
|
|
|
|
onRemoveAccountFromList: PropTypes.func.isRequired,
|
|
|
|
onAddAccountToList: PropTypes.func.isRequired,
|
|
|
|
onChangeSuggestions: PropTypes.func.isRequired,
|
|
|
|
onClearSearchSuggestions: PropTypes.func.isRequired,
|
|
|
|
onSubmitSearchSuggestions: PropTypes.func.isRequired,
|
|
|
|
onDeleteList: PropTypes.func.isRequired,
|
|
|
|
tab: PropTypes.string,
|
|
|
|
}
|
|
|
|
|
|
|
|
state = {
|
|
|
|
activeTab: this.props.tab || 'members'
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
const { onInitialize, listId } = this.props
|
|
|
|
if (listId) {
|
|
|
|
onInitialize(listId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidUpdate(prevProps) {
|
|
|
|
if (this.props.listId !== prevProps.listId) {
|
|
|
|
this.props.onInitialize(this.props.listId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
this.props.onReset()
|
|
|
|
}
|
|
|
|
|
|
|
|
handleChangeTab = (tab) => {
|
|
|
|
this.setState({ activeTab: tab })
|
|
|
|
}
|
|
|
|
|
|
|
|
onClickClose = () => {
|
|
|
|
this.props.onClose(MODAL_LIST_EDITOR)
|
|
|
|
}
|
|
|
|
|
|
|
|
handleOnDeleteList = () => {
|
|
|
|
this.props.onDeleteList(this.props.list)
|
|
|
|
}
|
|
|
|
|
|
|
|
handleAddOrRemoveFromList = (accountId) => {
|
|
|
|
if (this.props.accountIds.includes(accountId)) {
|
|
|
|
this.props.onRemoveAccountFromList(accountId)
|
|
|
|
} else {
|
|
|
|
this.props.onAddAccountToList(accountId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handleSearchSuggestionsChange = (value) => {
|
|
|
|
this.props.onChangeSuggestions(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
handleSearchSuggestionsKeyUp = (e) => {
|
|
|
|
if (e.keyCode === 13) {
|
|
|
|
this.props.onSubmitSearchSuggestions(this.props.searchSuggestionsValue)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handleSearchSuggestionsSubmit = () => {
|
|
|
|
this.props.onSubmitSearchSuggestions(this.props.searchSuggestionsValue)
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const {
|
|
|
|
title,
|
|
|
|
accountIds,
|
|
|
|
searchAccountIds,
|
|
|
|
intl,
|
|
|
|
searchSuggestionsValue,
|
|
|
|
} = this.props
|
|
|
|
const { activeTab } = this.state
|
|
|
|
|
|
|
|
// : todo : save new list title
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
<div className={[_s.default, _s.borderTop1PX, _s.borderColorSecondary].join(' ')}>
|
|
|
|
<div className={[_s.default, _s.z4, _s.bgPrimary, _s.px15, _s.top0, _s.posSticky, _s.borderBottom1PX, _s.borderColorSecondary,].join(' ')}>
|
|
|
|
<TabBar
|
|
|
|
tabs={[
|
|
|
|
{
|
|
|
|
title: 'Members list',
|
|
|
|
onClick: () => this.handleChangeTab('members'),
|
|
|
|
active: activeTab === 'members',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: 'Add new',
|
|
|
|
onClick: () => this.handleChangeTab('add-new'),
|
|
|
|
active: activeTab === 'add-new',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: 'Settings',
|
|
|
|
onClick: () => this.handleChangeTab('settings'),
|
|
|
|
active: activeTab === 'settings',
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{
|
|
|
|
activeTab === 'members' &&
|
|
|
|
<div className={[_s.default, _s.mb10, _s.py10].join(' ')}>
|
|
|
|
<div className={[_s.default, _s.pb10, _s.pt5].join(' ')}>
|
|
|
|
<div className={[_s.default].join(' ')}>
|
|
|
|
<Text weight='bold' size='small' color='secondary' className={[_s.default, _s.px15, _s.mt5, _s.mb15].join(' ')}>
|
|
|
|
Total members ({accountIds.size})
|
|
|
|
</Text>
|
|
|
|
{
|
|
|
|
accountIds &&
|
|
|
|
accountIds.map((accountId) => (
|
|
|
|
<Account
|
|
|
|
compact
|
|
|
|
key={`remove-from-list-${accountId}`}
|
|
|
|
id={accountId}
|
|
|
|
onActionClick={() => this.handleAddOrRemoveFromList(accountId)}
|
2020-05-07 06:55:24 +01:00
|
|
|
actionIcon='subtract'
|
2020-05-03 06:22:49 +01:00
|
|
|
/>
|
|
|
|
))
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
activeTab === 'settings' &&
|
|
|
|
<div className={[_s.default, _s.mb10, _s.pb10, _s.px15].join(' ')}>
|
|
|
|
<div className={[_s.default, _s.py15].join(' ')}>
|
|
|
|
<Input
|
|
|
|
title={intl.formatMessage(messages.editListTitle)}
|
|
|
|
placeholder='My new list title...'
|
|
|
|
value={title}
|
|
|
|
// onChange={onChange}
|
|
|
|
// onSubmit={onSubmit}
|
|
|
|
// disabled={disabled}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<Divider />
|
|
|
|
<div className={_s.mb10}>
|
|
|
|
<Button
|
|
|
|
onClick={this.handleOnDeleteList}
|
|
|
|
backgroundColor='danger'
|
|
|
|
>
|
|
|
|
Delete List
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
<Text size='extraSmall' color='secondary'>
|
|
|
|
Once you delete a list you cannot retrieve it.
|
|
|
|
</Text>
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
activeTab === 'add-new' &&
|
|
|
|
<div className={[_s.default, _s.mb10, _s.py10].join(' ')}>
|
|
|
|
<div className={[_s.default, _s.px15].join(' ')}>
|
|
|
|
<Input
|
|
|
|
placeholder={intl.formatMessage(messages.search)}
|
|
|
|
value={searchSuggestionsValue}
|
|
|
|
onChange={this.handleSearchSuggestionsChange}
|
|
|
|
onKeyUp={this.handleSearchSuggestionsKeyUp}
|
|
|
|
handleSubmit={this.handleSearchSuggestionsSubmit}
|
|
|
|
title={intl.formatMessage(messages.searchTitle)}
|
|
|
|
prependIcon='search'
|
|
|
|
hideLabel
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={[_s.default, _s.pt10].join(' ')}>
|
|
|
|
<div className={[_s.default].join(' ')}>
|
|
|
|
<Text weight='bold' size='small' color='secondary' className={[_s.default, _s.px15, _s.mt5, _s.mb15].join(' ')}>
|
|
|
|
Search results ({searchAccountIds.size})
|
|
|
|
</Text>
|
|
|
|
{
|
|
|
|
searchAccountIds &&
|
|
|
|
searchAccountIds.map((accountId) => {
|
|
|
|
if (accountIds.includes(accountId)) return null
|
|
|
|
return (
|
|
|
|
<Account
|
|
|
|
key={`add-to-list-${accountId}`}
|
|
|
|
id={accountId}
|
|
|
|
compact
|
|
|
|
onActionClick={() => this.handleAddOrRemoveFromList(accountId)}
|
|
|
|
actionIcon='add'
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|