// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import ReactDOM from 'react-dom'; import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; import {cleanUpUrlable, getShortenedURL} from 'utils/url.jsx'; import TeamStore from 'stores/team_store.jsx'; import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl'; import {updateChannel} from 'actions/channel_actions.jsx'; import {Modal, Tooltip, OverlayTrigger} from 'react-bootstrap'; const holders = defineMessages({ required: { id: 'rename_channel.required', defaultMessage: 'This field is required' }, maxLength: { id: 'rename_channel.maxLength', defaultMessage: 'This field must be less than 22 characters' }, lowercase: { id: 'rename_channel.lowercase', defaultMessage: 'Must be lowercase alphanumeric characters' }, url: { id: 'rename_channel.url', defaultMessage: 'URL' }, defaultError: { id: 'rename_channel.defaultError', defaultMessage: ' - Cannot be changed for the default channel' }, displayNameHolder: { id: 'rename_channel.displayNameHolder', defaultMessage: 'Enter display name' }, handleHolder: { id: 'rename_channel.handleHolder', defaultMessage: 'lowercase alphanumeric characters' } }); import React from 'react'; export class RenameChannelModal extends React.Component { constructor(props) { super(props); this.handleShow = this.handleShow.bind(this); this.handleHide = this.handleHide.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.handleCancel = this.handleCancel.bind(this); this.onNameChange = this.onNameChange.bind(this); this.onDisplayNameChange = this.onDisplayNameChange.bind(this); this.state = { displayName: props.channel.display_name, channelName: props.channel.name, serverError: '', nameError: '', displayNameError: '', 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) { e.preventDefault(); const channel = Object.assign({}, this.props.channel); const oldName = channel.name; const oldDisplayName = channel.display_name; const state = {serverError: ''}; const {formatMessage} = this.props.intl; channel.display_name = this.state.displayName.trim(); if (!channel.display_name) { state.displayNameError = formatMessage(holders.required); state.invalid = true; } else if (channel.display_name.length > 22) { state.displayNameError = formatMessage(holders.maxLength); state.invalid = true; } else { state.displayNameError = ''; } channel.name = this.state.channelName.trim(); if (!channel.name) { state.nameError = formatMessage(holders.required); state.invalid = true; } else if (channel.name.length > 22) { state.nameError = formatMessage(holders.maxLength); state.invalid = true; } else { const cleanedName = cleanUpUrlable(channel.name); if (cleanedName === channel.name) { state.nameError = ''; } else { state.nameError = formatMessage(holders.lowercase); state.invalid = true; } } this.setState(state); if (state.invalid || (oldName === channel.name && oldDisplayName === channel.display_name)) { return; } updateChannel(channel, () => { this.handleHide(); }, (err) => { this.setState({ serverError: err.message, invalid: true }); } ); } handleCancel(e) { this.setState({ displayName: this.props.channel.display_name, channelName: this.props.channel.name }); this.handleHide(e); } onNameChange() { this.setState({channelName: ReactDOM.findDOMNode(this.refs.channelName).value}); } onDisplayNameChange() { this.setState({displayName: ReactDOM.findDOMNode(this.refs.displayName).value}); } render() { let displayNameError = null; let displayNameClass = 'form-group'; if (this.state.displayNameError) { displayNameError = ; displayNameClass += ' has-error'; } let nameError = null; let nameClass = 'form-group'; if (this.state.nameError) { nameError = ; nameClass += ' has-error'; } let serverError = null; if (this.state.serverError) { serverError =
; } const {formatMessage} = this.props.intl; let urlInputLabel = formatMessage(holders.url); const handleInputClass = 'form-control'; let readOnlyHandleInput = false; if (this.state.channelName === Constants.DEFAULT_CHANNEL) { urlInputLabel += formatMessage(holders.defaultError); readOnlyHandleInput = true; } const fullUrl = TeamStore.getCurrentTeamUrl() + '/channels'; const shortUrl = getShortenedURL(fullUrl, 35); const urlTooltip = ( {fullUrl} ); return (
{displayNameError}
{shortUrl}
{nameError}
{serverError}
); } } RenameChannelModal.propTypes = { intl: intlShape.isRequired, show: React.PropTypes.bool.isRequired, onHide: React.PropTypes.func.isRequired, channel: React.PropTypes.object.isRequired }; export default injectIntl(RenameChannelModal);