Convert channel_members and channel_invite modals to react boostrap to fix performance issues
Этот коммит содержится в:
@@ -1,20 +1,23 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
const NavbarSearchBox = require('./search_bar.jsx');
|
||||
const MessageWrapper = require('./message_wrapper.jsx');
|
||||
const PopoverListMembers = require('./popover_list_members.jsx');
|
||||
const EditChannelPurposeModal = require('./edit_channel_purpose_modal.jsx');
|
||||
const ChannelInviteModal = require('./channel_invite_modal.jsx');
|
||||
const ChannelMembersModal = require('./channel_members_modal.jsx');
|
||||
|
||||
const ChannelStore = require('../stores/channel_store.jsx');
|
||||
const UserStore = require('../stores/user_store.jsx');
|
||||
const SearchStore = require('../stores/search_store.jsx');
|
||||
const PreferenceStore = require('../stores/preference_store.jsx');
|
||||
const NavbarSearchBox = require('./search_bar.jsx');
|
||||
const AsyncClient = require('../utils/async_client.jsx');
|
||||
const Client = require('../utils/client.jsx');
|
||||
const TextFormatting = require('../utils/text_formatting.jsx');
|
||||
const Utils = require('../utils/utils.jsx');
|
||||
const MessageWrapper = require('./message_wrapper.jsx');
|
||||
const PopoverListMembers = require('./popover_list_members.jsx');
|
||||
const EditChannelPurposeModal = require('./edit_channel_purpose_modal.jsx');
|
||||
|
||||
const AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||
const Utils = require('../utils/utils.jsx');
|
||||
const TextFormatting = require('../utils/text_formatting.jsx');
|
||||
const AsyncClient = require('../utils/async_client.jsx');
|
||||
const Client = require('../utils/client.jsx');
|
||||
const Constants = require('../utils/constants.jsx');
|
||||
const ActionTypes = Constants.ActionTypes;
|
||||
|
||||
@@ -31,6 +34,8 @@ export default class ChannelHeader extends React.Component {
|
||||
|
||||
const state = this.getStateFromStores();
|
||||
state.showEditChannelPurposeModal = false;
|
||||
state.showInviteModal = false;
|
||||
state.showMembersModal = false;
|
||||
this.state = state;
|
||||
}
|
||||
getStateFromStores() {
|
||||
@@ -86,7 +91,7 @@ export default class ChannelHeader extends React.Component {
|
||||
|
||||
let terms = '';
|
||||
if (user.notify_props && user.notify_props.mention_keys) {
|
||||
let termKeys = UserStore.getCurrentMentionKeys();
|
||||
const termKeys = UserStore.getCurrentMentionKeys();
|
||||
if (user.notify_props.all === 'true' && termKeys.indexOf('@all') !== -1) {
|
||||
termKeys.splice(termKeys.indexOf('@all'), 1);
|
||||
}
|
||||
@@ -146,7 +151,7 @@ export default class ChannelHeader extends React.Component {
|
||||
channelTerm = 'Group';
|
||||
}
|
||||
|
||||
let dropdownContents = [];
|
||||
const dropdownContents = [];
|
||||
if (isDirect) {
|
||||
dropdownContents.push(
|
||||
<li
|
||||
@@ -162,7 +167,7 @@ export default class ChannelHeader extends React.Component {
|
||||
data-title={channel.display_name}
|
||||
data-channelid={channel.id}
|
||||
>
|
||||
Set Channel Header...
|
||||
{'Set Channel Header...'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -179,7 +184,7 @@ export default class ChannelHeader extends React.Component {
|
||||
data-channelid={channel.id}
|
||||
href='#'
|
||||
>
|
||||
View Info
|
||||
{'View Info'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -192,11 +197,10 @@ export default class ChannelHeader extends React.Component {
|
||||
>
|
||||
<a
|
||||
role='menuitem'
|
||||
data-toggle='modal'
|
||||
data-target='#channel_invite'
|
||||
href='#'
|
||||
onClick={() => this.setState({showInviteModal: true})}
|
||||
>
|
||||
Add Members
|
||||
{'Add Members'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -209,11 +213,10 @@ export default class ChannelHeader extends React.Component {
|
||||
>
|
||||
<a
|
||||
role='menuitem'
|
||||
data-toggle='modal'
|
||||
data-target='#channel_members'
|
||||
href='#'
|
||||
onClick={() => this.setState({showMembersModal: true})}
|
||||
>
|
||||
Manage Members
|
||||
{'Manage Members'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -234,7 +237,7 @@ export default class ChannelHeader extends React.Component {
|
||||
data-title={channel.display_name}
|
||||
data-channelid={channel.id}
|
||||
>
|
||||
Set {channelTerm} Header...
|
||||
{'Set '}{channelTerm}{' Header...'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -248,7 +251,7 @@ export default class ChannelHeader extends React.Component {
|
||||
href='#'
|
||||
onClick={() => this.setState({showEditChannelPurposeModal: true})}
|
||||
>
|
||||
Set {channelTerm} Purpose...
|
||||
{'Set '}{channelTerm}{' Purpose...'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -265,7 +268,7 @@ export default class ChannelHeader extends React.Component {
|
||||
data-title={channel.display_name}
|
||||
data-channelid={channel.id}
|
||||
>
|
||||
Notification Preferences
|
||||
{'Notification Preferences'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -286,7 +289,7 @@ export default class ChannelHeader extends React.Component {
|
||||
data-name={channel.name}
|
||||
data-channelid={channel.id}
|
||||
>
|
||||
Rename {channelTerm}...
|
||||
{'Rename '}{channelTerm}{'...'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -303,7 +306,7 @@ export default class ChannelHeader extends React.Component {
|
||||
data-title={channel.display_name}
|
||||
data-channelid={channel.id}
|
||||
>
|
||||
Delete {channelTerm}...
|
||||
{'Delete '}{channelTerm}{'...'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -319,7 +322,7 @@ export default class ChannelHeader extends React.Component {
|
||||
href='#'
|
||||
onClick={this.handleLeave}
|
||||
>
|
||||
Leave {channelTerm}
|
||||
{'Leave '}{channelTerm}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -397,7 +400,7 @@ export default class ChannelHeader extends React.Component {
|
||||
href='#'
|
||||
onClick={this.searchMentions}
|
||||
>
|
||||
Recent Mentions
|
||||
{'Recent Mentions'}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -411,6 +414,14 @@ export default class ChannelHeader extends React.Component {
|
||||
onModalDismissed={() => this.setState({showEditChannelPurposeModal: false})}
|
||||
channel={channel}
|
||||
/>
|
||||
<ChannelInviteModal
|
||||
show={this.state.showInviteModal}
|
||||
onModalDismissed={() => this.setState({showInviteModal: false})}
|
||||
/>
|
||||
<ChannelMembersModal
|
||||
show={this.state.showMembersModal}
|
||||
onModalDismissed={() => this.setState({showMembersModal: false})}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
var ChannelStore = require('../stores/channel_store.jsx');
|
||||
var MemberList = require('./member_list.jsx');
|
||||
var LoadingScreen = require('./loading_screen.jsx');
|
||||
var utils = require('../utils/utils.jsx');
|
||||
var client = require('../utils/client.jsx');
|
||||
var AsyncClient = require('../utils/async_client.jsx');
|
||||
const MemberList = require('./member_list.jsx');
|
||||
const LoadingScreen = require('./loading_screen.jsx');
|
||||
|
||||
const UserStore = require('../stores/user_store.jsx');
|
||||
const ChannelStore = require('../stores/channel_store.jsx');
|
||||
|
||||
const Utils = require('../utils/utils.jsx');
|
||||
const Client = require('../utils/client.jsx');
|
||||
const AsyncClient = require('../utils/async_client.jsx');
|
||||
|
||||
const Modal = ReactBootstrap.Modal;
|
||||
|
||||
export default class ChannelInviteModal extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.componentDidMount = this.componentDidMount.bind(this);
|
||||
this.componentWillUnmount = this.componentWillUnmount.bind(this);
|
||||
this.onShow = this.onShow.bind(this);
|
||||
this.onHide = this.onHide.bind(this);
|
||||
this.onListenerChange = this.onListenerChange.bind(this);
|
||||
this.handleInvite = this.handleInvite.bind(this);
|
||||
|
||||
this.isShown = false;
|
||||
this.state = this.getStateFromStores();
|
||||
}
|
||||
getStateFromStores() {
|
||||
@@ -39,7 +38,7 @@ export default class ChannelInviteModal extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
nonmembers.sort(function sortByUsername(a, b) {
|
||||
nonmembers.sort((a, b) => {
|
||||
return a.username.localeCompare(b.username);
|
||||
});
|
||||
|
||||
@@ -49,35 +48,27 @@ export default class ChannelInviteModal extends React.Component {
|
||||
}
|
||||
|
||||
return {
|
||||
nonmembers: nonmembers,
|
||||
memberIds: memberIds,
|
||||
channelName: channelName,
|
||||
loading: loading
|
||||
nonmembers,
|
||||
memberIds,
|
||||
channelName,
|
||||
loading
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
$(ReactDOM.findDOMNode(this)).on('hidden.bs.modal', this.onHide);
|
||||
$(ReactDOM.findDOMNode(this)).on('show.bs.modal', this.onShow);
|
||||
|
||||
ChannelStore.addExtraInfoChangeListener(this.onListenerChange);
|
||||
ChannelStore.addChangeListener(this.onListenerChange);
|
||||
UserStore.addChangeListener(this.onListenerChange);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
ChannelStore.removeExtraInfoChangeListener(this.onListenerChange);
|
||||
ChannelStore.removeChangeListener(this.onListenerChange);
|
||||
UserStore.removeChangeListener(this.onListenerChange);
|
||||
}
|
||||
onShow() {
|
||||
this.isShown = true;
|
||||
this.onListenerChange();
|
||||
}
|
||||
onHide() {
|
||||
this.isShown = false;
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!this.props.show && nextProps.show) {
|
||||
ChannelStore.addExtraInfoChangeListener(this.onListenerChange);
|
||||
ChannelStore.addChangeListener(this.onListenerChange);
|
||||
UserStore.addChangeListener(this.onListenerChange);
|
||||
this.onListenerChange();
|
||||
} else if (this.props.show && !nextProps.show) {
|
||||
ChannelStore.removeExtraInfoChangeListener(this.onListenerChange);
|
||||
ChannelStore.removeChangeListener(this.onListenerChange);
|
||||
UserStore.removeChangeListener(this.onListenerChange);
|
||||
}
|
||||
}
|
||||
onListenerChange() {
|
||||
var newState = this.getStateFromStores();
|
||||
if (!utils.areStatesEqual(this.state, newState) && this.isShown) {
|
||||
if (!Utils.areStatesEqual(this.state, newState)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
}
|
||||
@@ -90,8 +81,8 @@ export default class ChannelInviteModal extends React.Component {
|
||||
var data = {};
|
||||
data.user_id = userId;
|
||||
|
||||
client.addChannelMember(ChannelStore.getCurrentId(), data,
|
||||
function sucess() {
|
||||
Client.addChannelMember(ChannelStore.getCurrentId(), data,
|
||||
() => {
|
||||
var nonmembers = this.state.nonmembers;
|
||||
var memberIds = this.state.memberIds;
|
||||
|
||||
@@ -103,13 +94,12 @@ export default class ChannelInviteModal extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({inviteError: null, memberIds: memberIds, nonmembers: nonmembers});
|
||||
this.setState({inviteError: null, memberIds, nonmembers});
|
||||
AsyncClient.getChannelExtraInfo(true);
|
||||
}.bind(this),
|
||||
|
||||
function error(err) {
|
||||
},
|
||||
(err) => {
|
||||
this.setState({inviteError: err.message});
|
||||
}.bind(this)
|
||||
}
|
||||
);
|
||||
}
|
||||
render() {
|
||||
@@ -121,7 +111,7 @@ export default class ChannelInviteModal extends React.Component {
|
||||
var currentMember = ChannelStore.getCurrentMember();
|
||||
var isAdmin = false;
|
||||
if (currentMember) {
|
||||
isAdmin = utils.isAdmin(currentMember.roles) || utils.isAdmin(UserStore.getCurrentUser().roles);
|
||||
isAdmin = Utils.isAdmin(currentMember.roles) || Utils.isAdmin(UserStore.getCurrentUser().roles);
|
||||
}
|
||||
|
||||
var content;
|
||||
@@ -138,43 +128,32 @@ export default class ChannelInviteModal extends React.Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className='modal fade more-modal'
|
||||
id='channel_invite'
|
||||
tabIndex='-1'
|
||||
role='dialog'
|
||||
aria-hidden='true'
|
||||
<Modal
|
||||
show={this.props.show}
|
||||
onHide={this.props.onModalDismissed}
|
||||
>
|
||||
<div
|
||||
className='modal-dialog'
|
||||
role='document'
|
||||
>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button
|
||||
type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
aria-label='Close'
|
||||
>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
<h4 className='modal-title'>Add New Members to <span className='name'>{this.state.channelName}</span></h4>
|
||||
</div>
|
||||
<div className='modal-body'>
|
||||
<Modal.Header closeButton={true}>
|
||||
<Modal.Title>{'Add New Members to '}<span className='name'>{this.state.channelName}</span></Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{inviteError}
|
||||
{content}
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
data-dismiss='modal'
|
||||
>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
onClick={this.props.onModalDismissed}
|
||||
>
|
||||
{'Close'}
|
||||
</button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ChannelInviteModal.propTypes = {
|
||||
show: React.PropTypes.bool.isRequired,
|
||||
onModalDismissed: React.PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
const UserStore = require('../stores/user_store.jsx');
|
||||
const ChannelStore = require('../stores/channel_store.jsx');
|
||||
const AsyncClient = require('../utils/async_client.jsx');
|
||||
const MemberList = require('./member_list.jsx');
|
||||
const Client = require('../utils/client.jsx');
|
||||
const Utils = require('../utils/utils.jsx');
|
||||
|
||||
export default class ChannelMembers extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.getStateFromStores = this.getStateFromStores.bind(this);
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.handleRemove = this.handleRemove.bind(this);
|
||||
this.onHide = this.onHide.bind(this);
|
||||
this.onShow = this.onShow.bind(this);
|
||||
|
||||
this.state = this.getStateFromStores();
|
||||
}
|
||||
getStateFromStores() {
|
||||
const users = UserStore.getActiveOnlyProfiles();
|
||||
let memberList = ChannelStore.getCurrentExtraInfo().members;
|
||||
|
||||
let nonmemberList = [];
|
||||
for (let id in users) {
|
||||
if (users.hasOwnProperty(id)) {
|
||||
let found = false;
|
||||
for (let i = 0; i < memberList.length; i++) {
|
||||
if (memberList[i].id === id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
nonmemberList.push(users[id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function compareByUsername(a, b) {
|
||||
if (a.username < b.username) {
|
||||
return -1;
|
||||
} else if (a.username > b.username) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
memberList.sort(compareByUsername);
|
||||
nonmemberList.sort(compareByUsername);
|
||||
|
||||
const channel = ChannelStore.getCurrent();
|
||||
let channelName = '';
|
||||
if (channel) {
|
||||
channelName = channel.display_name;
|
||||
}
|
||||
|
||||
return {
|
||||
nonmemberList: nonmemberList,
|
||||
memberList: memberList,
|
||||
channelName: channelName
|
||||
};
|
||||
}
|
||||
onHide() {
|
||||
this.setState({renderMembers: false});
|
||||
}
|
||||
onShow() {
|
||||
this.setState({renderMembers: true});
|
||||
}
|
||||
componentDidMount() {
|
||||
ChannelStore.addExtraInfoChangeListener(this.onChange);
|
||||
ChannelStore.addChangeListener(this.onChange);
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
|
||||
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
ChannelStore.removeExtraInfoChangeListener(this.onChange);
|
||||
ChannelStore.removeChangeListener(this.onChange);
|
||||
}
|
||||
onChange() {
|
||||
const newState = this.getStateFromStores();
|
||||
if (!Utils.areStatesEqual(this.state, newState)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
}
|
||||
handleRemove(userId) {
|
||||
// Make sure the user is a member of the channel
|
||||
let memberList = this.state.memberList;
|
||||
let found = false;
|
||||
for (let i = 0; i < memberList.length; i++) {
|
||||
if (memberList[i].id === userId) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
|
||||
let data = {};
|
||||
data.user_id = userId;
|
||||
|
||||
Client.removeChannelMember(ChannelStore.getCurrentId(), data,
|
||||
function handleRemoveSuccess() {
|
||||
let oldMember;
|
||||
for (let i = 0; i < memberList.length; i++) {
|
||||
if (userId === memberList[i].id) {
|
||||
oldMember = memberList[i];
|
||||
memberList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let nonmemberList = this.state.nonmemberList;
|
||||
if (oldMember) {
|
||||
nonmemberList.push(oldMember);
|
||||
}
|
||||
|
||||
this.setState({memberList: memberList, nonmemberList: nonmemberList});
|
||||
AsyncClient.getChannelExtraInfo(true);
|
||||
}.bind(this),
|
||||
function handleRemoveError(err) {
|
||||
this.setState({inviteError: err.message});
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const currentMember = ChannelStore.getCurrentMember();
|
||||
let isAdmin = false;
|
||||
if (currentMember) {
|
||||
isAdmin = Utils.isAdmin(currentMember.roles) || Utils.isAdmin(UserStore.getCurrentUser().roles);
|
||||
}
|
||||
|
||||
var memberList = null;
|
||||
if (this.state.renderMembers) {
|
||||
memberList = (
|
||||
<MemberList
|
||||
memberList={this.state.memberList}
|
||||
isAdmin={isAdmin}
|
||||
handleRemove={this.handleRemove}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className='modal fade more-modal'
|
||||
ref='modal'
|
||||
id='channel_members'
|
||||
tabIndex='-1'
|
||||
role='dialog'
|
||||
aria-hidden='true'
|
||||
>
|
||||
<div className='modal-dialog'>
|
||||
<div className='modal-content'>
|
||||
<div className='modal-header'>
|
||||
<button
|
||||
type='button'
|
||||
className='close'
|
||||
data-dismiss='modal'
|
||||
aria-label='Close'
|
||||
>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
<h4 className='modal-title'><span className='name'>{this.state.channelName}</span> Members</h4>
|
||||
<a
|
||||
className='btn btn-md btn-primary'
|
||||
data-toggle='modal'
|
||||
data-target='#channel_invite'
|
||||
>
|
||||
<i className='glyphicon glyphicon-envelope'/> Add New Members
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
ref='modalBody'
|
||||
className='modal-body'
|
||||
>
|
||||
{memberList}
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
data-dismiss='modal'
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
193
web/react/components/channel_members_modal.jsx
Обычный файл
193
web/react/components/channel_members_modal.jsx
Обычный файл
@@ -0,0 +1,193 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
const MemberList = require('./member_list.jsx');
|
||||
const ChannelInviteModal = require('./channel_invite_modal.jsx');
|
||||
|
||||
const UserStore = require('../stores/user_store.jsx');
|
||||
const ChannelStore = require('../stores/channel_store.jsx');
|
||||
|
||||
const AsyncClient = require('../utils/async_client.jsx');
|
||||
const Client = require('../utils/client.jsx');
|
||||
const Utils = require('../utils/utils.jsx');
|
||||
|
||||
const Modal = ReactBootstrap.Modal;
|
||||
|
||||
export default class ChannelMembersModal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.getStateFromStores = this.getStateFromStores.bind(this);
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.handleRemove = this.handleRemove.bind(this);
|
||||
|
||||
const state = this.getStateFromStores();
|
||||
state.showInviteModal = false;
|
||||
this.state = state;
|
||||
}
|
||||
getStateFromStores() {
|
||||
const users = UserStore.getActiveOnlyProfiles();
|
||||
const memberList = ChannelStore.getCurrentExtraInfo().members;
|
||||
|
||||
const nonmemberList = [];
|
||||
for (const id in users) {
|
||||
if (users.hasOwnProperty(id)) {
|
||||
let found = false;
|
||||
for (let i = 0; i < memberList.length; i++) {
|
||||
if (memberList[i].id === id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
nonmemberList.push(users[id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function compareByUsername(a, b) {
|
||||
if (a.username < b.username) {
|
||||
return -1;
|
||||
} else if (a.username > b.username) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
memberList.sort(compareByUsername);
|
||||
nonmemberList.sort(compareByUsername);
|
||||
|
||||
const channel = ChannelStore.getCurrent();
|
||||
let channelName = '';
|
||||
if (channel) {
|
||||
channelName = channel.display_name;
|
||||
}
|
||||
|
||||
return {
|
||||
nonmemberList,
|
||||
memberList,
|
||||
channelName
|
||||
};
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!this.props.show && nextProps.show) {
|
||||
ChannelStore.addExtraInfoChangeListener(this.onChange);
|
||||
ChannelStore.addChangeListener(this.onChange);
|
||||
} else if (this.props.show && !nextProps.show) {
|
||||
ChannelStore.removeExtraInfoChangeListener(this.onChange);
|
||||
ChannelStore.removeChangeListener(this.onChange);
|
||||
}
|
||||
}
|
||||
onChange() {
|
||||
const newState = this.getStateFromStores();
|
||||
if (!Utils.areStatesEqual(this.state, newState)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
}
|
||||
handleRemove(userId) {
|
||||
// Make sure the user is a member of the channel
|
||||
const memberList = this.state.memberList;
|
||||
let found = false;
|
||||
for (let i = 0; i < memberList.length; i++) {
|
||||
if (memberList[i].id === userId) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = {};
|
||||
data.user_id = userId;
|
||||
|
||||
Client.removeChannelMember(ChannelStore.getCurrentId(), data,
|
||||
() => {
|
||||
let oldMember;
|
||||
for (let i = 0; i < memberList.length; i++) {
|
||||
if (userId === memberList[i].id) {
|
||||
oldMember = memberList[i];
|
||||
memberList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const nonmemberList = this.state.nonmemberList;
|
||||
if (oldMember) {
|
||||
nonmemberList.push(oldMember);
|
||||
}
|
||||
|
||||
this.setState({memberList, nonmemberList});
|
||||
AsyncClient.getChannelExtraInfo(true);
|
||||
},
|
||||
(err) => {
|
||||
this.setState({inviteError: err.message});
|
||||
}
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const currentMember = ChannelStore.getCurrentMember();
|
||||
let isAdmin = false;
|
||||
if (currentMember) {
|
||||
isAdmin = Utils.isAdmin(currentMember.roles) || Utils.isAdmin(UserStore.getCurrentUser().roles);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
show={this.props.show}
|
||||
onHide={this.props.onModalDismissed}
|
||||
>
|
||||
<Modal.Header closeButton={true}>
|
||||
<Modal.Title><span className='name'>{this.state.channelName}</span>{' Members'}</Modal.Title>
|
||||
<a
|
||||
className='btn btn-md btn-primary'
|
||||
href='#'
|
||||
onClick={() => {
|
||||
this.setState({showInviteModal: true});
|
||||
this.props.onModalDismissed();
|
||||
}}
|
||||
>
|
||||
<i className='glyphicon glyphicon-envelope'/>{' Add New Members'}
|
||||
</a>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<div className='col-sm-12'>
|
||||
<div className='team-member-list'>
|
||||
<MemberList
|
||||
memberList={this.state.memberList}
|
||||
isAdmin={isAdmin}
|
||||
handleRemove={this.handleRemove}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-default'
|
||||
onClick={this.props.onModalDismissed}
|
||||
>
|
||||
{'Close'}
|
||||
</button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
<ChannelInviteModal
|
||||
show={this.state.showInviteModal}
|
||||
onModalDismissed={() => this.setState({showInviteModal: false})}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ChannelMembersModal.defaultProps = {
|
||||
show: false
|
||||
};
|
||||
|
||||
ChannelMembersModal.propTypes = {
|
||||
show: React.PropTypes.bool.isRequired,
|
||||
onModalDismissed: React.PropTypes.func.isRequired
|
||||
};
|
||||
@@ -1,22 +1,26 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
var Client = require('../utils/client.jsx');
|
||||
var AsyncClient = require('../utils/async_client.jsx');
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
var ChannelStore = require('../stores/channel_store.jsx');
|
||||
var TeamStore = require('../stores/team_store.jsx');
|
||||
var MessageWrapper = require('./message_wrapper.jsx');
|
||||
var NotifyCounts = require('./notify_counts.jsx');
|
||||
const EditChannelPurposeModal = require('./edit_channel_purpose_modal.jsx');
|
||||
const MessageWrapper = require('./message_wrapper.jsx');
|
||||
const NotifyCounts = require('./notify_counts.jsx');
|
||||
const ChannelMembersModal = require('./channel_members_modal.jsx');
|
||||
const ChannelInviteModal = require('./channel_invite_modal.jsx');
|
||||
|
||||
const UserStore = require('../stores/user_store.jsx');
|
||||
const ChannelStore = require('../stores/channel_store.jsx');
|
||||
const TeamStore = require('../stores/team_store.jsx');
|
||||
|
||||
const Client = require('../utils/client.jsx');
|
||||
const AsyncClient = require('../utils/async_client.jsx');
|
||||
const Utils = require('../utils/utils.jsx');
|
||||
|
||||
var Constants = require('../utils/constants.jsx');
|
||||
var ActionTypes = Constants.ActionTypes;
|
||||
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||
const Constants = require('../utils/constants.jsx');
|
||||
const ActionTypes = Constants.ActionTypes;
|
||||
const AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||
|
||||
var Popover = ReactBootstrap.Popover;
|
||||
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
|
||||
const Popover = ReactBootstrap.Popover;
|
||||
const OverlayTrigger = ReactBootstrap.OverlayTrigger;
|
||||
|
||||
export default class Navbar extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -29,6 +33,8 @@ export default class Navbar extends React.Component {
|
||||
|
||||
const state = this.getStateFromStores();
|
||||
state.showEditChannelPurposeModal = false;
|
||||
state.showMembersModal = false;
|
||||
state.showInviteModal = false;
|
||||
this.state = state;
|
||||
}
|
||||
getStateFromStores() {
|
||||
@@ -45,17 +51,18 @@ export default class Navbar extends React.Component {
|
||||
}
|
||||
componentWillUnmount() {
|
||||
ChannelStore.removeChangeListener(this.onChange);
|
||||
ChannelStore.removeExtraInfoChangeListener(this.onChange);
|
||||
}
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
handleLeave() {
|
||||
Client.leaveChannel(this.state.channel.id,
|
||||
function success() {
|
||||
() => {
|
||||
AsyncClient.getChannels(true);
|
||||
window.location.href = TeamStore.getCurrentTeamUrl() + '/channels/town-square';
|
||||
},
|
||||
function error(err) {
|
||||
(err) => {
|
||||
AsyncClient.dispatchError(err, 'handleLeave');
|
||||
}
|
||||
);
|
||||
@@ -104,7 +111,7 @@ export default class Navbar extends React.Component {
|
||||
data-channelid={channel.id}
|
||||
href='#'
|
||||
>
|
||||
View Info
|
||||
{'View Info'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -120,7 +127,7 @@ export default class Navbar extends React.Component {
|
||||
data-title={channel.display_name}
|
||||
data-channelid={channel.id}
|
||||
>
|
||||
Set Channel Header...
|
||||
{'Set Channel Header...'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -145,11 +152,10 @@ export default class Navbar extends React.Component {
|
||||
<li role='presentation'>
|
||||
<a
|
||||
role='menuitem'
|
||||
data-toggle='modal'
|
||||
data-target='#channel_invite'
|
||||
href='#'
|
||||
onClick={() => this.setState({showInviteModal: false})}
|
||||
>
|
||||
Add Members
|
||||
{'Add Members'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -161,7 +167,7 @@ export default class Navbar extends React.Component {
|
||||
href='#'
|
||||
onClick={this.handleLeave}
|
||||
>
|
||||
Leave Channel
|
||||
{'Leave Channel'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -175,11 +181,10 @@ export default class Navbar extends React.Component {
|
||||
<li role='presentation'>
|
||||
<a
|
||||
role='menuitem'
|
||||
data-toggle='modal'
|
||||
data-target='#channel_members'
|
||||
href='#'
|
||||
onClick={() => this.setState({showMembersModal: true})}
|
||||
>
|
||||
Manage Members
|
||||
{'Manage Members'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -195,7 +200,7 @@ export default class Navbar extends React.Component {
|
||||
data-name={channel.name}
|
||||
data-channelid={channel.id}
|
||||
>
|
||||
Rename Channel...
|
||||
{'Rename Channel...'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -210,7 +215,7 @@ export default class Navbar extends React.Component {
|
||||
data-title={channel.display_name}
|
||||
data-channelid={channel.id}
|
||||
>
|
||||
Delete Channel...
|
||||
{'Delete Channel...'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -228,7 +233,7 @@ export default class Navbar extends React.Component {
|
||||
data-title={channel.display_name}
|
||||
data-channelid={channel.id}
|
||||
>
|
||||
Notification Preferences
|
||||
{'Notification Preferences'}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -299,7 +304,7 @@ export default class Navbar extends React.Component {
|
||||
data-toggle='collapse'
|
||||
data-target='#navbar-collapse-1'
|
||||
>
|
||||
<span className='sr-only'>Toggle sidebar</span>
|
||||
<span className='sr-only'>{'Toggle sidebar'}</span>
|
||||
<span className='icon-bar'></span>
|
||||
<span className='icon-bar'></span>
|
||||
<span className='icon-bar'></span>
|
||||
@@ -315,7 +320,7 @@ export default class Navbar extends React.Component {
|
||||
data-target='#sidebar-nav'
|
||||
onClick={this.toggleLeftSidebar}
|
||||
>
|
||||
<span className='sr-only'>Toggle sidebar</span>
|
||||
<span className='sr-only'>{'Toggle sidebar'}</span>
|
||||
<span className='icon-bar'></span>
|
||||
<span className='icon-bar'></span>
|
||||
<span className='icon-bar'></span>
|
||||
@@ -426,6 +431,14 @@ export default class Navbar extends React.Component {
|
||||
onModalDismissed={() => this.setState({showEditChannelPurposeModal: false})}
|
||||
channel={channel}
|
||||
/>
|
||||
<ChannelMembersModal
|
||||
show={this.state.showMembersModal}
|
||||
onModalDismissed={() => this.setState({showMembersModal: false})}
|
||||
/>
|
||||
<ChannelInviteModal
|
||||
show={this.state.showInviteModal}
|
||||
onModalDismissed={() => this.setState({showInviteModal: false})}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@ var PostDeletedModal = require('../components/post_deleted_modal.jsx');
|
||||
var ChannelNotificationsModal = require('../components/channel_notifications.jsx');
|
||||
var UserSettingsModal = require('../components/user_settings/user_settings_modal.jsx');
|
||||
var TeamSettingsModal = require('../components/team_settings_modal.jsx');
|
||||
var ChannelMembersModal = require('../components/channel_members.jsx');
|
||||
var ChannelInviteModal = require('../components/channel_invite_modal.jsx');
|
||||
var TeamMembersModal = require('../components/team_members.jsx');
|
||||
var ChannelInfoModal = require('../components/channel_info_modal.jsx');
|
||||
var AccessHistoryModal = require('../components/access_history_modal.jsx');
|
||||
@@ -127,16 +125,6 @@ function setupChannelPage(props) {
|
||||
document.getElementById('channel_notifications_modal')
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<ChannelMembersModal />,
|
||||
document.getElementById('channel_members_modal')
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<ChannelInviteModal />,
|
||||
document.getElementById('channel_invite_modal')
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<ChannelInfoModal />,
|
||||
document.getElementById('channel_info_modal')
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
<div id="new_channel_modal"></div>
|
||||
<div id="post_deleted_modal"></div>
|
||||
<div id="channel_notifications_modal"></div>
|
||||
<div id="channel_members_modal"></div>
|
||||
<div id="channel_invite_modal"></div>
|
||||
<div id="team_members_modal"></div>
|
||||
<div id="direct_channel_modal"></div>
|
||||
<div id="channel_info_modal"></div>
|
||||
|
||||
Ссылка в новой задаче
Block a user