Files
mostlymatter/webapp/components/multiselect/multiselect_list.jsx
Joram Wilander 3a91d4e5e4 PLT-3077 Add group messaging (#5489)
* Implement server changes for group messaging

* Majority of client-side implementation

* Some server updates

* Added new React multiselect component

* Fix style issues

* Add custom renderer for options

* Fix model test

* Update ENTER functionality for multiselect control

* Remove buttons from multiselect UI control

* Updating group messaging UI (#5524)

* Move filter controls up a component level

* Scroll with arrow keys

* Updating mobile layout for multiselect (#5534)

* Fix race condition when backspacing quickly

* Hidden or new GMs show up for regular messages

* Add overriding of number remaining text

* Add UI filtering for team if config setting set

* Add icon to channel switcher and class prop to status icon

* Minor updates per feedback

* Improving group messaging UI (#5563)

* UX changes per feedback

* Update email for group messages

* UI fixes for group messaging (#5587)

* Fix missing localization string

* Add maximum users message when adding members to GM

* Fix input clearing on Android

* Updating group messaging UI (#5603)

* Updating UI for group messaging (#5604)
2017-03-02 17:48:56 -05:00

170 строки
4.7 KiB
JavaScript

// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {cmdOrCtrlPressed} from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
const KeyCodes = Constants.KeyCodes;
import React from 'react';
import {FormattedMessage} from 'react-intl';
export default class MultiSelectList extends React.Component {
constructor(props) {
super(props);
this.defaultOptionRenderer = this.defaultOptionRenderer.bind(this);
this.handleArrowPress = this.handleArrowPress.bind(this);
this.setSelected = this.setSelected.bind(this);
this.toSelect = -1;
this.state = {
selected: -1
};
}
componentDidMount() {
document.addEventListener('keydown', this.handleArrowPress);
}
componentWillUnmount() {
document.removeEventListener('keydown', this.handleArrowPress);
}
componentWillReceiveProps(nextProps) {
this.setState({selected: this.toSelect});
const options = nextProps.options;
if (options && options.length > 0 && this.toSelect >= 0) {
this.props.onSelect(options[this.toSelect]);
}
}
componentDidUpdate() {
if (this.refs.list && this.refs.selected) {
const elemTop = this.refs.selected.getBoundingClientRect().top;
const elemBottom = this.refs.selected.getBoundingClientRect().bottom;
const listTop = this.refs.list.getBoundingClientRect().top;
const listBottom = this.refs.list.getBoundingClientRect().bottom;
if (elemBottom > listBottom) {
this.refs.selected.scrollIntoView(false);
} else if (elemTop < listTop) {
this.refs.selected.scrollIntoView(true);
}
}
}
setSelected(selected) {
this.toSelect = selected;
}
handleArrowPress(e) {
if (cmdOrCtrlPressed(e) && e.shiftKey) {
return;
}
const options = this.props.options;
if (options.length === 0) {
return;
}
let selected;
switch (e.keyCode) {
case KeyCodes.DOWN:
if (this.state.selected === -1) {
selected = 0;
break;
}
selected = Math.min(this.state.selected + 1, options.length - 1);
break;
case KeyCodes.UP:
if (this.state.selected === -1) {
selected = 0;
break;
}
selected = Math.max(this.state.selected - 1, 0);
break;
default:
return;
}
e.preventDefault();
this.setState({selected});
this.props.onSelect(options[selected]);
}
defaultOptionRenderer(option, isSelected, onAdd) {
var rowSelected = '';
if (isSelected) {
rowSelected = 'more-modal__row--selected';
}
return (
<div
ref={isSelected ? 'selected' : option.value}
className={rowSelected}
key={'multiselectoption' + option.value}
onClick={() => onAdd(option)}
>
{option.label}
</div>
);
}
render() {
const options = this.props.options;
if (options == null || options.length === 0) {
return (
<div
key='no-users-found'
className='no-channel-message'
>
<p className='primary-message'>
<FormattedMessage
id='multiselect.list.notFound'
defaultMessage='No items found'
/>
</p>
</div>
);
}
let renderer;
if (this.props.optionRenderer) {
renderer = this.props.optionRenderer;
} else {
renderer = this.defaultOptionRenderer;
}
const optionControls = options.map((o, i) => renderer(o, this.state.selected === i, this.props.onAdd));
return (
<div className='more-modal__list'>
<div
ref='list'
>
{optionControls}
</div>
</div>
);
}
}
MultiSelectList.defaultProps = {
options: [],
perPage: 50,
onAction: () => null
};
MultiSelectList.propTypes = {
options: React.PropTypes.arrayOf(React.PropTypes.object),
optionRenderer: React.PropTypes.func,
page: React.PropTypes.number,
perPage: React.PropTypes.number,
onPageChange: React.PropTypes.func,
onAdd: React.PropTypes.func,
onSelect: React.PropTypes.func
};