Merge pull request #2210 from hmhealey/plt1258

PLT-1258 Ported RenameChannelModal to React-Bootstrap
Этот коммит содержится в:
Christopher Speller
2016-02-22 15:03:04 -05:00
родитель bc69f2aae0 5ddd227985
Коммит 12fd1ddc95
4 изменённых файлов: 207 добавлений и 159 удалений

Просмотреть файл

@@ -11,6 +11,7 @@ import ChannelInviteModal from './channel_invite_modal.jsx';
import ChannelMembersModal from './channel_members_modal.jsx'; import ChannelMembersModal from './channel_members_modal.jsx';
import ChannelNotificationsModal from './channel_notifications_modal.jsx'; import ChannelNotificationsModal from './channel_notifications_modal.jsx';
import DeleteChannelModal from './delete_channel_modal.jsx'; import DeleteChannelModal from './delete_channel_modal.jsx';
import RenameChannelModal from './rename_channel_modal.jsx';
import ToggleModalButton from './toggle_modal_button.jsx'; import ToggleModalButton from './toggle_modal_button.jsx';
import ChannelStore from '../stores/channel_store.jsx'; import ChannelStore from '../stores/channel_store.jsx';
@@ -39,10 +40,13 @@ export default class ChannelHeader extends React.Component {
this.onListenerChange = this.onListenerChange.bind(this); this.onListenerChange = this.onListenerChange.bind(this);
this.handleLeave = this.handleLeave.bind(this); this.handleLeave = this.handleLeave.bind(this);
this.searchMentions = this.searchMentions.bind(this); this.searchMentions = this.searchMentions.bind(this);
this.showRenameChannelModal = this.showRenameChannelModal.bind(this);
this.hideRenameChannelModal = this.hideRenameChannelModal.bind(this);
const state = this.getStateFromStores(); const state = this.getStateFromStores();
state.showEditChannelPurposeModal = false; state.showEditChannelPurposeModal = false;
state.showMembersModal = false; state.showMembersModal = false;
state.showRenameChannelModal = false;
this.state = state; this.state = state;
} }
getStateFromStores() { getStateFromStores() {
@@ -120,6 +124,18 @@ export default class ChannelHeader extends React.Component {
is_mention_search: true is_mention_search: true
}); });
} }
showRenameChannelModal(e) {
e.preventDefault();
this.setState({
showRenameChannelModal: true
});
}
hideRenameChannelModal() {
this.setState({
showRenameChannelModal: false
});
}
render() { render() {
if (this.state.channel === null) { if (this.state.channel === null) {
return null; return null;
@@ -326,11 +342,7 @@ export default class ChannelHeader extends React.Component {
<a <a
role='menuitem' role='menuitem'
href='#' href='#'
data-toggle='modal' onClick={this.showRenameChannelModal}
data-target='#rename_channel'
data-display={channel.display_name}
data-name={channel.name}
data-channelid={channel.id}
> >
<FormattedMessage <FormattedMessage
id='channel_header.rename' id='channel_header.rename'
@@ -470,6 +482,11 @@ export default class ChannelHeader extends React.Component {
onModalDismissed={() => this.setState({showMembersModal: false})} onModalDismissed={() => this.setState({showMembersModal: false})}
channel={channel} channel={channel}
/> />
<RenameChannelModal
show={this.state.showRenameChannelModal}
onHide={this.hideRenameChannelModal}
channel={channel}
/>
</div> </div>
); );
} }

Просмотреть файл

@@ -5,11 +5,11 @@ import EditChannelHeaderModal from './edit_channel_header_modal.jsx';
import EditChannelPurposeModal from './edit_channel_purpose_modal.jsx'; import EditChannelPurposeModal from './edit_channel_purpose_modal.jsx';
import MessageWrapper from './message_wrapper.jsx'; import MessageWrapper from './message_wrapper.jsx';
import NotifyCounts from './notify_counts.jsx'; import NotifyCounts from './notify_counts.jsx';
import ChannelMembersModal from './channel_members_modal.jsx';
import ChannelInfoModal from './channel_info_modal.jsx'; import ChannelInfoModal from './channel_info_modal.jsx';
import ChannelInviteModal from './channel_invite_modal.jsx'; import ChannelInviteModal from './channel_invite_modal.jsx';
import ChannelNotificationsModal from './channel_notifications_modal.jsx'; import ChannelNotificationsModal from './channel_notifications_modal.jsx';
import DeleteChannelModal from './delete_channel_modal.jsx'; import DeleteChannelModal from './delete_channel_modal.jsx';
import RenameChannelModal from './rename_channel_modal.jsx';
import ToggleModalButton from './toggle_modal_button.jsx'; import ToggleModalButton from './toggle_modal_button.jsx';
import UserStore from '../stores/user_store.jsx'; import UserStore from '../stores/user_store.jsx';
@@ -39,6 +39,8 @@ export default class Navbar extends React.Component {
this.showSearch = this.showSearch.bind(this); this.showSearch = this.showSearch.bind(this);
this.showEditChannelHeaderModal = this.showEditChannelHeaderModal.bind(this); this.showEditChannelHeaderModal = this.showEditChannelHeaderModal.bind(this);
this.showRenameChannelModal = this.showRenameChannelModal.bind(this);
this.hideRenameChannelModal = this.hideRenameChannelModal.bind(this);
this.createCollapseButtons = this.createCollapseButtons.bind(this); this.createCollapseButtons = this.createCollapseButtons.bind(this);
this.createDropdown = this.createDropdown.bind(this); this.createDropdown = this.createDropdown.bind(this);
@@ -47,6 +49,7 @@ export default class Navbar extends React.Component {
state.showEditChannelPurposeModal = false; state.showEditChannelPurposeModal = false;
state.showEditChannelHeaderModal = false; state.showEditChannelHeaderModal = false;
state.showMembersModal = false; state.showMembersModal = false;
state.showRenameChannelModal = false;
this.state = state; this.state = state;
} }
getStateFromStores() { getStateFromStores() {
@@ -128,6 +131,18 @@ export default class Navbar extends React.Component {
showEditChannelHeaderModal: true showEditChannelHeaderModal: true
}); });
} }
showRenameChannelModal(e) {
e.preventDefault();
this.setState({
showRenameChannelModal: true
});
}
hideRenameChannelModal() {
this.setState({
showRenameChannelModal: false
});
}
createDropdown(channel, channelTitle, isAdmin, isDirect, popoverContent) { createDropdown(channel, channelTitle, isAdmin, isDirect, popoverContent) {
if (channel) { if (channel) {
var viewInfoOption = ( var viewInfoOption = (
@@ -253,11 +268,7 @@ export default class Navbar extends React.Component {
<a <a
role='menuitem' role='menuitem'
href='#' href='#'
data-toggle='modal' onClick={this.showRenameChannelModal}
data-target='#rename_channel'
data-display={channel.display_name}
data-name={channel.name}
data-channelid={channel.id}
> >
<FormattedMessage <FormattedMessage
id='navbar.rename' id='navbar.rename'
@@ -410,6 +421,7 @@ export default class Navbar extends React.Component {
var editChannelHeaderModal = null; var editChannelHeaderModal = null;
var editChannelPurposeModal = null; var editChannelPurposeModal = null;
let renameChannelModal = null;
if (channel) { if (channel) {
popoverContent = ( popoverContent = (
@@ -492,6 +504,14 @@ export default class Navbar extends React.Component {
channel={channel} channel={channel}
/> />
); );
renameChannelModal = (
<RenameChannelModal
show={this.state.showRenameChannelModal}
onHide={this.hideRenameChannelModal}
channel={channel}
/>
);
} }
var collapseButtons = this.createCollapseButtons(currentId); var collapseButtons = this.createCollapseButtons(currentId);
@@ -524,11 +544,7 @@ export default class Navbar extends React.Component {
</nav> </nav>
{editChannelHeaderModal} {editChannelHeaderModal}
{editChannelPurposeModal} {editChannelPurposeModal}
<ChannelMembersModal {renameChannelModal}
show={this.state.showMembersModal}
onModalDismissed={() => this.setState({showMembersModal: false})}
channel={{channel}}
/>
</div> </div>
); );
} }

Просмотреть файл

@@ -4,11 +4,12 @@
import * as Utils from '../utils/utils.jsx'; import * as Utils from '../utils/utils.jsx';
import * as Client from '../utils/client.jsx'; import * as Client from '../utils/client.jsx';
import * as AsyncClient from '../utils/async_client.jsx'; import * as AsyncClient from '../utils/async_client.jsx';
import ChannelStore from '../stores/channel_store.jsx';
import Constants from '../utils/constants.jsx'; import Constants from '../utils/constants.jsx';
import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl'; import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
const Modal = ReactBootstrap.Modal;
const holders = defineMessages({ const holders = defineMessages({
required: { required: {
id: 'rename_channel.required', id: 'rename_channel.required',
@@ -44,33 +45,81 @@ export default class RenameChannelModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.handleShow = this.handleShow.bind(this);
this.handleHide = this.handleHide.bind(this);
this.handleSubmit = this.handleSubmit.bind(this); this.handleSubmit = this.handleSubmit.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.onNameChange = this.onNameChange.bind(this); this.onNameChange = this.onNameChange.bind(this);
this.onDisplayNameChange = this.onDisplayNameChange.bind(this); this.onDisplayNameChange = this.onDisplayNameChange.bind(this);
this.displayNameKeyUp = this.displayNameKeyUp.bind(this); this.displayNameKeyUp = this.displayNameKeyUp.bind(this);
this.handleClose = this.handleClose.bind(this);
this.handleShow = this.handleShow.bind(this);
this.handleShown = this.handleShown.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = { this.state = {
displayName: '', displayName: props.channel.display_name,
channelName: '', channelName: props.channel.name,
channelId: '',
serverError: '', serverError: '',
nameError: '', nameError: '',
displayNameError: '', displayNameError: '',
invalid: false invalid: false
}; };
} }
componentWillReceiveProps(nextProps) {
if (!Utils.areObjectsEqual(nextProps.channel, this.props.channel)) {
this.setState({
displayName: nextProps.channel.display_name,
channelName: nextProps.channel.name
});
}
}
shouldComponentUpdate(nextProps, nextState) {
if (!nextProps.show && !this.props.show) {
return false;
}
if (!Utils.areObjectsEqual(nextState, this.state)) {
return true;
}
if (!Utils.areObjectsEqual(nextProps, this.props)) {
return true;
}
return false;
}
componentDidUpdate(prevProps) {
if (!prevProps.show && this.props.show) {
this.handleShow();
}
}
handleShow() {
const textbox = ReactDOM.findDOMNode(this.refs.displayName);
textbox.focus();
Utils.placeCaretAtEnd(textbox);
}
handleHide(e) {
if (e) {
e.preventDefault();
}
this.props.onHide();
this.setState({
serverError: '',
nameError: '',
displayNameError: '',
invalid: false
});
}
handleSubmit(e) { handleSubmit(e) {
e.preventDefault(); e.preventDefault();
if (this.state.channelId.length !== 26) { const channel = Object.assign({}, this.props.channel);
return;
}
const channel = ChannelStore.get(this.state.channelId);
const oldName = channel.name; const oldName = channel.name;
const oldDisplayName = channel.displayName; const oldDisplayName = channel.displayName;
const state = {serverError: ''}; const state = {serverError: ''};
@@ -110,29 +159,40 @@ export default class RenameChannelModal extends React.Component {
return; return;
} }
Client.updateChannel(channel, Client.updateChannel(
channel,
() => { () => {
$(ReactDOM.findDOMNode(this.refs.modal)).modal('hide');
AsyncClient.getChannel(channel.id); AsyncClient.getChannel(channel.id);
Utils.updateAddressBar(channel.name); Utils.updateAddressBar(channel.name);
ReactDOM.findDOMNode(this.refs.displayName).value = ''; this.handleHide();
ReactDOM.findDOMNode(this.refs.channelName).value = '';
}, },
(err) => { (err) => {
state.serverError = err.message; this.setState({
state.invalid = true; serverError: err.message,
this.setState(state); invalid: true
});
} }
); );
} }
handleCancel(e) {
this.setState({
displayName: this.props.channel.display_name,
channelName: this.props.channel.name
});
this.handleHide(e);
}
onNameChange() { onNameChange() {
this.setState({channelName: ReactDOM.findDOMNode(this.refs.channelName).value}); this.setState({channelName: ReactDOM.findDOMNode(this.refs.channelName).value});
} }
onDisplayNameChange() { onDisplayNameChange() {
this.setState({displayName: ReactDOM.findDOMNode(this.refs.displayName).value}); this.setState({displayName: ReactDOM.findDOMNode(this.refs.displayName).value});
} }
displayNameKeyUp() { displayNameKeyUp() {
if (this.state.channelName !== Constants.DEFAULT_CHANNEL) { if (this.state.channelName !== Constants.DEFAULT_CHANNEL) {
const displayName = ReactDOM.findDOMNode(this.refs.displayName).value.trim(); const displayName = ReactDOM.findDOMNode(this.refs.displayName).value.trim();
@@ -141,32 +201,7 @@ export default class RenameChannelModal extends React.Component {
this.setState({channelName: channelName}); this.setState({channelName: channelName});
} }
} }
handleClose() {
this.setState({
displayName: '',
channelName: '',
channelId: '',
serverError: '',
nameError: '',
displayNameError: '',
invalid: false
});
}
handleShow(e) {
const button = $(e.relatedTarget);
this.setState({displayName: button.attr('data-display'), channelName: button.attr('data-name'), channelId: button.attr('data-channelid')});
}
handleShown() {
$('#rename_channel #display_name').focus();
}
componentDidMount() {
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.handleShow);
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.handleClose);
$(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', this.handleShown);
}
componentWillUnmount() {
$(ReactDOM.findDOMNode(this.refs.modal)).off('hidden.bs.modal', this.handleClose);
}
render() { render() {
let displayNameError = null; let displayNameError = null;
let displayNameClass = 'form-group'; let displayNameClass = 'form-group';
@@ -199,107 +234,89 @@ export default class RenameChannelModal extends React.Component {
} }
return ( return (
<div <Modal
className='modal fade' show={this.props.show}
ref='modal' onHide={this.handleCancel}
id='rename_channel'
tabIndex='-1'
role='dialog'
aria-hidden='true'
> >
<div className='modal-dialog'> <Modal.Header closeButton={true}>
<div className='modal-content'> <Modal.Title>
<div className='modal-header'> <FormattedMessage
<button id='rename_channel.title'
type='button' defaultMessage='Rename Channel'
className='close' />
data-dismiss='modal' </Modal.Title>
> </Modal.Header>
<span aria-hidden='true'>{'×'}</span> <form role='form'>
<span className='sr-only'> <Modal.Body>
<FormattedMessage <div className={displayNameClass}>
id='rename_channel.close' <label className='control-label'>
defaultMessage='Close' <FormattedMessage
/> id='rename_channel.displayName'
</span> defaultMessage='Display Name'
</button> />
<h4 className='modal-title'> </label>
<FormattedMessage <input
id='rename_channel.title' onKeyUp={this.displayNameKeyUp}
defaultMessage='Rename Channel' onChange={this.onDisplayNameChange}
type='text'
ref='displayName'
id='display_name'
className='form-control'
placeholder={formatMessage(holders.displayNameHolder)}
value={this.state.displayName}
maxLength='64'
/> />
</h4> {displayNameError}
</div> </div>
<form role='form'> <div className={nameClass}>
<div className='modal-body'> <label className='control-label'>{handleInputLabel}</label>
<div className={displayNameClass}> <input
<label className='control-label'> onChange={this.onNameChange}
<FormattedMessage type='text'
id='rename_channel.displayName' className={handleInputClass}
defaultMessage='Display Name' ref='channelName'
/> placeholder={formatMessage(holders.handleHolder)}
</label> value={this.state.channelName}
<input maxLength='64'
onKeyUp={this.displayNameKeyUp} readOnly={readOnlyHandleInput}
onChange={this.onDisplayNameChange} />
type='text' {nameError}
ref='displayName' </div>
id='display_name' {serverError}
className='form-control' </Modal.Body>
placeholder={formatMessage(holders.displayNameHolder)} <Modal.Footer>
value={this.state.displayName} <button
maxLength='64' type='button'
/> className='btn btn-default'
{displayNameError} onClick={this.handleCancel}
</div> >
<div className={nameClass}> <FormattedMessage
<label className='control-label'>{handleInputLabel}</label> id='rename_channel.cancel'
<input defaultMessage='Cancel'
onChange={this.onNameChange} />
type='text' </button>
className={handleInputClass} <button
ref='channelName' onClick={this.handleSubmit}
placeholder={formatMessage(holders.handleHolder)} type='submit'
value={this.state.channelName} className='btn btn-primary'
maxLength='64' >
readOnly={readOnlyHandleInput} <FormattedMessage
/> id='rename_channel.save'
{nameError} defaultMessage='Save'
</div> />
{serverError} </button>
</div> </Modal.Footer>
<div className='modal-footer'> </form>
<button </Modal>
type='button'
className='btn btn-default'
data-dismiss='modal'
>
<FormattedMessage
id='rename_channel.cancel'
defaultMessage='Cancel'
/>
</button>
<button
onClick={this.handleSubmit}
type='submit'
className='btn btn-primary'
>
<FormattedMessage
id='rename_channel.save'
defaultMessage='Save'
/>
</button>
</div>
</form>
</div>
</div>
</div>
); );
} }
} }
RenameChannelModal.propTypes = { RenameChannelModal.propTypes = {
intl: intlShape.isRequired intl: intlShape.isRequired,
show: React.PropTypes.bool.isRequired,
onHide: React.PropTypes.func.isRequired,
channel: React.PropTypes.object.isRequired
}; };
export default injectIntl(RenameChannelModal); export default injectIntl(RenameChannelModal);

Просмотреть файл

@@ -8,7 +8,6 @@ import * as Client from '../utils/client.jsx';
import GetPostLinkModal from '../components/get_post_link_modal.jsx'; import GetPostLinkModal from '../components/get_post_link_modal.jsx';
import GetTeamInviteLinkModal from '../components/get_team_invite_link_modal.jsx'; import GetTeamInviteLinkModal from '../components/get_team_invite_link_modal.jsx';
import RenameChannelModal from '../components/rename_channel_modal.jsx';
import EditPostModal from '../components/edit_post_modal.jsx'; import EditPostModal from '../components/edit_post_modal.jsx';
import DeletePostModal from '../components/delete_post_modal.jsx'; import DeletePostModal from '../components/delete_post_modal.jsx';
import MoreChannelsModal from '../components/more_channels.jsx'; import MoreChannelsModal from '../components/more_channels.jsx';
@@ -73,7 +72,6 @@ class Root extends React.Component {
<InviteMemberModal/> <InviteMemberModal/>
<ImportThemeModal/> <ImportThemeModal/>
<TeamSettingsModal/> <TeamSettingsModal/>
<RenameChannelModal/>
<MoreChannelsModal/> <MoreChannelsModal/>
<EditPostModal/> <EditPostModal/>
<DeletePostModal/> <DeletePostModal/>