diff options
Diffstat (limited to 'web/react/components')
20 files changed, 278 insertions, 105 deletions
diff --git a/web/react/components/admin_console/email_settings.jsx b/web/react/components/admin_console/email_settings.jsx index 3b5ad2a1a..762a4ab26 100644 --- a/web/react/components/admin_console/email_settings.jsx +++ b/web/react/components/admin_console/email_settings.jsx @@ -288,7 +288,7 @@ export default class EmailSettings extends React.Component { className='control-label col-sm-4' htmlFor='feedbackName' > - {'Feedback Name:'} + {'Notification Display Name:'} </label> <div className='col-sm-8'> <input @@ -310,7 +310,7 @@ export default class EmailSettings extends React.Component { className='control-label col-sm-4' htmlFor='feedbackEmail' > - {'Feedback Email:'} + {'Notification Email Address:'} </label> <div className='col-sm-8'> <input diff --git a/web/react/components/admin_console/gitlab_settings.jsx b/web/react/components/admin_console/gitlab_settings.jsx index eaea15b8f..759892ad3 100644 --- a/web/react/components/admin_console/gitlab_settings.jsx +++ b/web/react/components/admin_console/gitlab_settings.jsx @@ -40,7 +40,6 @@ export default class GitLabSettings extends React.Component { config.GitLabSettings.Enable = React.findDOMNode(this.refs.Enable).checked; config.GitLabSettings.Secret = React.findDOMNode(this.refs.Secret).value.trim(); config.GitLabSettings.Id = React.findDOMNode(this.refs.Id).value.trim(); - config.GitLabSettings.Scope = React.findDOMNode(this.refs.Scope).value.trim(); config.GitLabSettings.AuthEndpoint = React.findDOMNode(this.refs.AuthEndpoint).value.trim(); config.GitLabSettings.TokenEndpoint = React.findDOMNode(this.refs.TokenEndpoint).value.trim(); config.GitLabSettings.UserApiEndpoint = React.findDOMNode(this.refs.UserApiEndpoint).value.trim(); @@ -121,28 +120,6 @@ export default class GitLabSettings extends React.Component { <div className='form-group'> <label className='control-label col-sm-4' - htmlFor='Secret' - > - {'Secret:'} - </label> - <div className='col-sm-8'> - <input - type='text' - className='form-control' - id='Secret' - ref='Secret' - placeholder='Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"' - defaultValue={this.props.config.GitLabSettings.Secret} - onChange={this.handleChange} - disabled={!this.state.Enable} - /> - <p className='help-text'>{'Obtain this value via the instructions above for logging into GitLab.'}</p> - </div> - </div> - - <div className='form-group'> - <label - className='control-label col-sm-4' htmlFor='Id' > {'Id:'} @@ -165,22 +142,22 @@ export default class GitLabSettings extends React.Component { <div className='form-group'> <label className='control-label col-sm-4' - htmlFor='Scope' + htmlFor='Secret' > - {'Scope:'} + {'Secret:'} </label> <div className='col-sm-8'> <input type='text' className='form-control' - id='Scope' - ref='Scope' - placeholder='Not currently used by GitLab. Please leave blank' - defaultValue={this.props.config.GitLabSettings.Scope} + id='Secret' + ref='Secret' + placeholder='Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"' + defaultValue={this.props.config.GitLabSettings.Secret} onChange={this.handleChange} disabled={!this.state.Enable} /> - <p className='help-text'>{'This field is not yet used by GitLab OAuth. Other OAuth providers may use this field to specify the scope of account data from OAuth provider that is sent to Mattermost.'}</p> + <p className='help-text'>{'Obtain this value via the instructions above for logging into GitLab.'}</p> </div> </div> @@ -202,7 +179,7 @@ export default class GitLabSettings extends React.Component { onChange={this.handleChange} disabled={!this.state.Enable} /> - <p className='help-text'>{'Enter <your-gitlab-url>/oauth/authorize (example http://localhost:3000/oauth/authorize).'}</p> + <p className='help-text'>{'Enter <your-gitlab-url>/oauth/authorize (example http://localhost:3000/oauth/authorize). Make sure you use HTTP or HTTPS in your URLs as appropriate.'}</p> </div> </div> @@ -224,7 +201,7 @@ export default class GitLabSettings extends React.Component { onChange={this.handleChange} disabled={!this.state.Enable} /> - <p className='help-text'>{'Enter <your-gitlab-url>/oauth/token.'}</p> + <p className='help-text'>{'Enter <your-gitlab-url>/oauth/token. Make sure you use HTTP or HTTPS in your URLs as appropriate.'}</p> </div> </div> @@ -246,7 +223,7 @@ export default class GitLabSettings extends React.Component { onChange={this.handleChange} disabled={!this.state.Enable} /> - <p className='help-text'>{'Enter <your-gitlab-url>/api/v3/user.'}</p> + <p className='help-text'>{'Enter <your-gitlab-url>/api/v3/user. Make sure you use HTTP or HTTPS in your URLs as appropriate.'}</p> </div> </div> @@ -272,6 +249,30 @@ export default class GitLabSettings extends React.Component { } } + +//config.GitLabSettings.Scope = React.findDOMNode(this.refs.Scope).value.trim(); +// <div className='form-group'> +// <label +// className='control-label col-sm-4' +// htmlFor='Scope' +// > +// {'Scope:'} +// </label> +// <div className='col-sm-8'> +// <input +// type='text' +// className='form-control' +// id='Scope' +// ref='Scope' +// placeholder='Not currently used by GitLab. Please leave blank' +// defaultValue={this.props.config.GitLabSettings.Scope} +// onChange={this.handleChange} +// disabled={!this.state.Allow} +// /> +// <p className='help-text'>{'This field is not yet used by GitLab OAuth. Other OAuth providers may use this field to specify the scope of account data from OAuth provider that is sent to Mattermost.'}</p> +// </div> +// </div> + GitLabSettings.propTypes = { config: React.PropTypes.object }; diff --git a/web/react/components/command_list.jsx b/web/react/components/command_list.jsx index 63bd57c2a..fea7085b7 100644 --- a/web/react/components/command_list.jsx +++ b/web/react/components/command_list.jsx @@ -96,4 +96,4 @@ CommandList.defaultProps = { CommandList.propTypes = { addCommand: React.PropTypes.func, channelId: React.PropTypes.string -};
\ No newline at end of file +}; diff --git a/web/react/components/more_direct_channels.jsx b/web/react/components/more_direct_channels.jsx index b7bce9b34..54d77c358 100644 --- a/web/react/components/more_direct_channels.jsx +++ b/web/react/components/more_direct_channels.jsx @@ -43,7 +43,7 @@ export default class MoreDirectChannels extends React.Component { handleClick = function clickHandler(e) { e.preventDefault(); - utils.switchChannel(channel, channel.teammate_username); + utils.switchChannel(channel); $(React.findDOMNode(self.refs.modal)).modal('hide'); }; } else { diff --git a/web/react/components/navbar_dropdown.jsx b/web/react/components/navbar_dropdown.jsx index 4c01d2c43..57a78a0d4 100644 --- a/web/react/components/navbar_dropdown.jsx +++ b/web/react/components/navbar_dropdown.jsx @@ -62,7 +62,7 @@ export default class NavbarDropdown extends React.Component { if (currentUser != null) { isAdmin = Utils.isAdmin(currentUser.roles); - isSystemAdmin = Utils.isInRole(currentUser.roles, 'system_admin'); + isSystemAdmin = Utils.isSystemAdmin(currentUser.roles); inviteLink = ( <li> diff --git a/web/react/components/popover_list_members.jsx b/web/react/components/popover_list_members.jsx index a2ca8b00f..95a88c3d6 100644 --- a/web/react/components/popover_list_members.jsx +++ b/web/react/components/popover_list_members.jsx @@ -1,6 +1,8 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. +var UserStore = require('../stores/user_store.jsx'); + export default class PopoverListMembers extends React.Component { componentDidMount() { const originalLeave = $.fn.popover.Constructor.prototype.leave; @@ -32,22 +34,28 @@ export default class PopoverListMembers extends React.Component { } render() { let popoverHtml = ''; + let count = 0; + let countText = '-'; const members = this.props.members; - let count; - if (members.length > 20) { - count = '20+'; - } else { - count = members.length || '-'; - } + const teamMembers = UserStore.getProfilesUsernameMap(); - if (members) { + if (members && teamMembers) { members.sort(function compareByLocal(a, b) { return a.username.localeCompare(b.username); }); members.forEach(function addMemberElement(m) { - popoverHtml += `<div class='text--nowrap'>${m.username}</div>`; + if (teamMembers[m.username] && teamMembers[m.username].delete_at <= 0) { + popoverHtml += `<div class='text--nowrap'>${m.username}</div>`; + count++; + } }); + + if (count > 20) { + countText = '20+'; + } else if (count > 0) { + countText = count.toString(); + } } return ( @@ -63,7 +71,7 @@ export default class PopoverListMembers extends React.Component { data-toggle='tooltip' title='View Channel Members' > - {count} + {countText} <span className='fa fa-user' aria-hidden='true' diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index 6e98e4aba..48b268700 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -12,7 +12,10 @@ export default class PostBody extends React.Component { constructor(props) { super(props); + this.receivedYoutubeData = false; + this.parseEmojis = this.parseEmojis.bind(this); + this.createYoutubeEmbed = this.createYoutubeEmbed.bind(this); const linkData = Utils.extractLinks(this.props.post.message); this.state = {links: linkData.links, message: linkData.text}; @@ -50,6 +53,123 @@ export default class PostBody extends React.Component { this.setState({links: linkData.links, message: linkData.text}); } + handleYoutubeTime(link) { + const timeRegex = /[\\?&]t=([0-9hms]+)/; + + const time = link.trim().match(timeRegex); + if (!time || !time[1]) { + return ''; + } + + const hours = time[1].match(/([0-9]+)h/); + const minutes = time[1].match(/([0-9]+)m/); + const seconds = time[1].match(/([0-9]+)s/); + + let ticks = 0; + + if (hours && hours[1]) { + ticks += parseInt(hours[1], 10) * 3600; + } + + if (minutes && minutes[1]) { + ticks += parseInt(minutes[1], 10) * 60; + } + + if (seconds && seconds[1]) { + ticks += parseInt(seconds[1], 10); + } + + return '&start=' + ticks.toString(); + } + + createYoutubeEmbed(link) { + const ytRegex = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|watch\?(?:[a-zA-Z-_]+=[a-zA-Z0-9-_]+&)+v=)([^#\&\?]*).*/; + + const match = link.trim().match(ytRegex); + if (!match || match[1].length !== 11) { + return null; + } + + const youtubeId = match[1]; + const time = this.handleYoutubeTime(link); + + function onClick(e) { + var div = $(e.target).closest('.video-thumbnail__container')[0]; + var iframe = document.createElement('iframe'); + iframe.setAttribute('src', + 'https://www.youtube.com/embed/' + + div.id + + '?autoplay=1&autohide=1&border=0&wmode=opaque&fs=1&enablejsapi=1' + + time); + iframe.setAttribute('width', '480px'); + iframe.setAttribute('height', '360px'); + iframe.setAttribute('type', 'text/html'); + iframe.setAttribute('frameborder', '0'); + iframe.setAttribute('allowfullscreen', 'allowfullscreen'); + + div.parentNode.replaceChild(iframe, div); + } + + function success(data) { + if (!data.items.length || !data.items[0].snippet) { + return null; + } + var metadata = data.items[0].snippet; + this.receivedYoutubeData = true; + this.setState({youtubeUploader: metadata.channelTitle, youtubeTitle: metadata.title}); + } + + if (global.window.config.GoogleDeveloperKey && !this.receivedYoutubeData) { + $.ajax({ + async: true, + url: 'https://www.googleapis.com/youtube/v3/videos', + type: 'GET', + data: {part: 'snippet', id: youtubeId, key: global.window.config.GoogleDeveloperKey}, + success + }); + } + + let header = 'Youtube'; + if (this.state.youtubeTitle) { + header = header + ' - '; + } + + let uploader = this.state.youtubeUploader; + if (!uploader) { + uploader = 'unknown'; + } + + return ( + <div className='post-comment'> + <h4> + <span className='video-type'>{header}</span> + <span className='video-title'><a href={link}>{this.state.youtubeTitle}</a></span> + </h4> + <h4 className='video-uploader'>{uploader}</h4> + <div + className='video-div embed-responsive-item' + id={youtubeId} + onClick={onClick} + > + <div className='embed-responsive embed-responsive-4by3 video-div__placeholder'> + <div + id={youtubeId} + className='video-thumbnail__container' + > + <img + className='video-thumbnail' + src={'https://i.ytimg.com/vi/' + youtubeId + '/hqdefault.jpg'} + /> + <div className='block'> + <span className='play-button'><span/></span> + </div> + </div> + </div> + </div> + </div> + ); + } + render() { const post = this.props.post; const filenames = this.props.post.filenames; @@ -133,7 +253,7 @@ export default class PostBody extends React.Component { let embed; if (filenames.length === 0 && this.state.links) { - embed = Utils.getEmbed(this.state.links[0]); + embed = this.createYoutubeEmbed(this.state.links[0]); } let fileAttachmentHolder = ''; diff --git a/web/react/components/post_info.jsx b/web/react/components/post_info.jsx index 824e7ef39..82e746dc0 100644 --- a/web/react/components/post_info.jsx +++ b/web/react/components/post_info.jsx @@ -150,7 +150,7 @@ export default class PostInfo extends React.Component { var dropdown = this.createDropdown(); - let tooltip = <Tooltip>{utils.displayDate(post.create_at)} at ${utils.displayTime(post.create_at)}</Tooltip>; + let tooltip = <Tooltip id={post.id + 'tooltip'}>{utils.displayDate(post.create_at)} at ${utils.displayTime(post.create_at)}</Tooltip>; return ( <ul className='post-header post-info'> diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index 3e1e075bb..a31967257 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -128,6 +128,15 @@ export default class PostList extends React.Component { this.userHasSeenNew = true; } this.isUserScroll = true; + + $('.top-visible-post').removeClass('top-visible-post'); + + $(React.findDOMNode(this.refs.postlistcontent)).children().each(function select() { + if ($(this).position().top + $(this).height() / 2 > 0) { + $(this).addClass('top-visible-post'); + return false; + } + }); }); $('.post-list__content div .post').removeClass('post--last'); @@ -665,7 +674,10 @@ export default class PostList extends React.Component { className={'post-list-holder-by-time ' + activeClass} > <div className='post-list__table'> - <div className='post-list__content'> + <div + ref='postlistcontent' + className='post-list__content' + > {moreMessages} {postCtls} </div> diff --git a/web/react/components/rename_channel_modal.jsx b/web/react/components/rename_channel_modal.jsx index 37958b649..9d514c741 100644 --- a/web/react/components/rename_channel_modal.jsx +++ b/web/react/components/rename_channel_modal.jsx @@ -78,7 +78,6 @@ export default class RenameChannelModal extends React.Component { $(React.findDOMNode(this.refs.modal)).modal('hide'); AsyncClient.getChannel(channel.id); - Utils.updateTabTitle(channel.display_name); Utils.updateAddressBar(channel.name); React.findDOMNode(this.refs.displayName).value = ''; diff --git a/web/react/components/search_results_item.jsx b/web/react/components/search_results_item.jsx index 32b521560..bdefdbee8 100644 --- a/web/react/components/search_results_item.jsx +++ b/web/react/components/search_results_item.jsx @@ -47,13 +47,8 @@ export default class SearchResultsItem extends React.Component { ); var postChannel = ChannelStore.get(this.props.post.channel_id); - var teammate = ''; - if (postChannel.type === 'D') { - teammate = utils.getDirectTeammate(this.props.post.channel_id).username; - } - - utils.switchChannel(postChannel, teammate); + utils.switchChannel(postChannel); } render() { diff --git a/web/react/components/setting_upload.jsx b/web/react/components/setting_upload.jsx index fad27b355..ccb26cc58 100644 --- a/web/react/components/setting_upload.jsx +++ b/web/react/components/setting_upload.jsx @@ -7,11 +7,11 @@ export default class SettingsUpload extends React.Component { this.doFileSelect = this.doFileSelect.bind(this); this.doSubmit = this.doSubmit.bind(this); - this.onFileSelect = this.onFileSelect.bind(this); this.state = { clientError: this.props.clientError, - serverError: this.props.serverError + serverError: this.props.serverError, + filename: '' }; } @@ -24,9 +24,14 @@ export default class SettingsUpload extends React.Component { doFileSelect(e) { e.preventDefault(); + var filename = $(e.target).val(); + if (filename.substring(3, 11) === 'fakepath') { + filename = filename.substring(12); + } this.setState({ clientError: '', - serverError: '' + serverError: '', + filename }); } @@ -40,28 +45,28 @@ export default class SettingsUpload extends React.Component { } } - onFileSelect(e) { - var filename = $(e.target).val(); - if (filename.substring(3, 11) === 'fakepath') { - filename = filename.substring(12); - } - $(e.target).closest('li').find('.file-status').addClass('hide'); - $(e.target).closest('li').find('.file-name').removeClass('hide').html(filename); - } - render() { - var clientError = null; + let clientError = null; if (this.state.clientError) { clientError = ( <div className='file-status'>{this.state.clientError}</div> ); } - var serverError = null; + let serverError = null; if (this.state.serverError) { serverError = ( <div className='file-status'>{this.state.serverError}</div> ); } + let fileNameText = null; + let submitButtonClass = 'btn btn-sm btn-primary disabled'; + if (this.state.filename) { + fileNameText = ( + <div className='file-status file-name'>{this.state.filename}</div> + ); + submitButtonClass = 'btn btn-sm btn-primary'; + } + return ( <ul className='section-max'> <li className='col-sm-12 section-title'>{this.props.title}</li> @@ -70,21 +75,21 @@ export default class SettingsUpload extends React.Component { <ul className='setting-list'> <li className='setting-list-item'> <span className='btn btn-sm btn-primary btn-file sel-btn'> - Select file + {'Select file'} <input ref='uploadinput' accept={this.props.fileTypesAccepted} type='file' - onChange={this.onFileSelect} + onChange={this.doFileSelect} /> </span> <a - className={'btn btn-sm btn-primary'} + className={submitButtonClass} onClick={this.doSubmit} > - Import + {'Import'} </a> - <div className='file-status file-name hide'></div> + {fileNameText} {serverError} {clientError} </li> @@ -102,4 +107,4 @@ SettingsUpload.propTypes = { clientError: React.PropTypes.string, serverError: React.PropTypes.string, helpText: React.PropTypes.object -}; +};
\ No newline at end of file diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index 14664ed4d..6033f200f 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -268,14 +268,19 @@ export default class Sidebar extends React.Component { } } updateTitle() { - var channel = ChannelStore.getCurrent(); + const channel = ChannelStore.getCurrent(); if (channel) { + let currentSiteName = ''; + if (global.window.config.SiteName != null) { + currentSiteName = global.window.config.SiteName; + } + + let currentChannelName = channel.display_name; if (channel.type === 'D') { - var teammateUsername = Utils.getDirectTeammate(channel.id).username; - document.title = teammateUsername + ' ' + document.title.substring(document.title.lastIndexOf('-')); - } else { - document.title = channel.display_name + ' ' + document.title.substring(document.title.lastIndexOf('-')); + currentChannelName = Utils.getDirectTeammate(channel.id).username; } + + document.title = currentChannelName + ' - ' + this.props.teamDisplayName + ' ' + currentSiteName; } } onScroll() { diff --git a/web/react/components/sidebar_right.jsx b/web/react/components/sidebar_right.jsx index 913715154..708cd04cb 100644 --- a/web/react/components/sidebar_right.jsx +++ b/web/react/components/sidebar_right.jsx @@ -14,9 +14,10 @@ export default class SidebarRight extends React.Component { constructor(props) { super(props); + this.plScrolledToBottom = true; + this.onSelectedChange = this.onSelectedChange.bind(this); this.onSearchChange = this.onSearchChange.bind(this); - this.resize = this.resize.bind(this); this.state = getStateFromStores(); } @@ -28,6 +29,14 @@ export default class SidebarRight extends React.Component { PostStore.removeSearchChangeListener(this.onSearchChange); PostStore.removeSelectedPostChangeListener(this.onSelectedChange); } + componentDidUpdate() { + if (!this.plScrolledToBottom) { + $('.top-visible-post')[0].scrollIntoView(); + } else { + var postHolder = $('.post-list-holder-by-time').not('.inactive'); + postHolder.scrollTop(postHolder[0].scrollHeight); + } + } onSelectedChange(fromSearch) { var newState = getStateFromStores(fromSearch); newState.from_search = fromSearch; @@ -41,15 +50,15 @@ export default class SidebarRight extends React.Component { this.setState(newState); } } - resize() { - var postHolder = $('.post-list-holder-by-time'); - postHolder[0].scrollTop = postHolder[0].scrollHeight - 224; - } render() { + var postHolder = $('.post-list-holder-by-time').not('.inactive'); + const position = postHolder.scrollTop() + postHolder.height() + 14; + const bottom = postHolder[0].scrollHeight; + this.plScrolledToBottom = position >= bottom; + if (!(this.state.search_visible || this.state.post_right_visible)) { $('.inner__wrap').removeClass('move--left').removeClass('move--right'); $('.sidebar--right').removeClass('move--left'); - this.resize(); return ( <div></div> ); @@ -59,8 +68,8 @@ export default class SidebarRight extends React.Component { $('.sidebar--left').removeClass('move--right'); $('.sidebar--right').addClass('move--left'); $('.sidebar--right').prepend('<div class="sidebar__overlay"></div>'); - this.resize(); - setTimeout(function overlayTimer() { + + setTimeout(() => { $('.sidebar__overlay').fadeOut('200', function fadeOverlay() { $(this).remove(); }); diff --git a/web/react/components/sidebar_right_menu.jsx b/web/react/components/sidebar_right_menu.jsx index f1341d9d7..2df2c8ffd 100644 --- a/web/react/components/sidebar_right_menu.jsx +++ b/web/react/components/sidebar_right_menu.jsx @@ -26,11 +26,14 @@ export default class SidebarRightMenu extends React.Component { var inviteLink = ''; var teamSettingsLink = ''; var manageLink = ''; + var consoleLink = ''; var currentUser = UserStore.getCurrentUser(); var isAdmin = false; + var isSystemAdmin = false; if (currentUser != null) { isAdmin = utils.isAdmin(currentUser.roles); + isSystemAdmin = utils.isSystemAdmin(currentUser.roles); inviteLink = ( <li> @@ -77,6 +80,17 @@ export default class SidebarRightMenu extends React.Component { ); } + if (isSystemAdmin) { + consoleLink = ( + <li> + <a + href='/admin_console' + > + <i className='glyphicon glyphicon-wrench'></i>System Console</a> + </li> + ); + } + var siteName = ''; if (global.window.config.SiteName != null) { siteName = global.window.config.SiteName; @@ -107,6 +121,7 @@ export default class SidebarRightMenu extends React.Component { {inviteLink} {teamLink} {manageLink} + {consoleLink} <li> <a href='#' diff --git a/web/react/components/team_signup_url_page.jsx b/web/react/components/team_signup_url_page.jsx index 1b722d611..a3f89a217 100644 --- a/web/react/components/team_signup_url_page.jsx +++ b/web/react/components/team_signup_url_page.jsx @@ -35,8 +35,8 @@ export default class TeamSignupUrlPage extends React.Component { if (cleanedName !== name || !urlRegex.test(name)) { this.setState({nameError: "Use only lower case letters, numbers and dashes. Must start with a letter and can't end in a dash."}); return; - } else if (cleanedName.length <= 3 || cleanedName.length > 15) { - this.setState({nameError: 'Name must be 4 or more characters up to a maximum of 15'}); + } else if (cleanedName.length <= 2 || cleanedName.length > 15) { + this.setState({nameError: 'Name must be 3 or more characters up to a maximum of 15'}); return; } diff --git a/web/react/components/team_signup_with_sso.jsx b/web/react/components/team_signup_with_sso.jsx index a4972dd8d..14f281f7a 100644 --- a/web/react/components/team_signup_with_sso.jsx +++ b/web/react/components/team_signup_with_sso.jsx @@ -23,12 +23,14 @@ export default class SSOSignUpPage extends React.Component { team.display_name = this.state.name; - if (team.display_name.length <= 3) { + if (!team.display_name) { + state.nameError = 'Please enter a team name'; + this.setState(state); return; } - if (!team.display_name) { - state.nameError = 'Please enter a team name'; + if (team.display_name.length <= 2) { + state.nameError = 'Name must be 3 or more characters up to a maximum of 15'; this.setState(state); return; } @@ -68,7 +70,7 @@ export default class SSOSignUpPage extends React.Component { } var disabled = false; - if (this.state.name.length <= 3) { + if (this.state.name.length <= 2) { disabled = true; } diff --git a/web/react/components/user_settings/import_theme_modal.jsx b/web/react/components/user_settings/import_theme_modal.jsx index 48be83afe..0f5cb59f5 100644 --- a/web/react/components/user_settings/import_theme_modal.jsx +++ b/web/react/components/user_settings/import_theme_modal.jsx @@ -140,7 +140,7 @@ export default class ImportThemeModal extends React.Component { > <Modal.Body> <p> - {'To import a theme, go to a Slack team and look for “”Preferences” -> Sidebar Theme”. Open the custom theme option, copy the theme color values and paste them here:'} + {'To import a theme, go to a Slack team and look for “Preferences -> Sidebar Theme”. Open the custom theme option, copy the theme color values and paste them here:'} </p> <div className='form-group less'> <div className='col-sm-9'> diff --git a/web/react/components/user_settings/manage_incoming_hooks.jsx b/web/react/components/user_settings/manage_incoming_hooks.jsx index 1bbfbd162..fa2e2e5e4 100644 --- a/web/react/components/user_settings/manage_incoming_hooks.jsx +++ b/web/react/components/user_settings/manage_incoming_hooks.jsx @@ -21,7 +21,7 @@ export default class ManageIncomingHooks extends React.Component { this.getHooks(); } addNewHook() { - let hook = {}; //eslint-disable-line prefer-const + const hook = {}; hook.channel_id = this.state.channelId; Client.addIncomingHook( @@ -40,13 +40,13 @@ export default class ManageIncomingHooks extends React.Component { ); } removeHook(id) { - let data = {}; //eslint-disable-line prefer-const + const data = {}; data.id = id; Client.deleteIncomingHook( data, () => { - let hooks = this.state.hooks; //eslint-disable-line prefer-const + const hooks = this.state.hooks; let index = -1; for (let i = 0; i < hooks.length; i++) { if (hooks[i].id === id) { @@ -69,7 +69,7 @@ export default class ManageIncomingHooks extends React.Component { getHooks() { Client.listIncomingHooks( (data) => { - let state = this.state; //eslint-disable-line prefer-const + const state = this.state; if (data) { state.hooks = data; @@ -93,9 +93,11 @@ export default class ManageIncomingHooks extends React.Component { } const channels = ChannelStore.getAll(); - let options = []; //eslint-disable-line prefer-const + const options = []; channels.forEach((channel) => { - options.push(<option value={channel.id}>{channel.name}</option>); + if (channel.type !== Constants.DM_CHANNEL) { + options.push(<option value={channel.id}>{channel.name}</option>); + } }); let disableButton = ''; @@ -103,7 +105,7 @@ export default class ManageIncomingHooks extends React.Component { disableButton = ' disable'; } - let hooks = []; //eslint-disable-line prefer-const + const hooks = []; this.state.hooks.forEach((hook) => { const c = ChannelStore.get(hook.channel_id); hooks.push( diff --git a/web/react/components/user_settings/user_settings_notifications.jsx b/web/react/components/user_settings/user_settings_notifications.jsx index ba14f019f..42c65ef5d 100644 --- a/web/react/components/user_settings/user_settings_notifications.jsx +++ b/web/react/components/user_settings/user_settings_notifications.jsx @@ -420,7 +420,7 @@ export default class NotificationsTab extends React.Component { </label> <br/> </div> - <div><br/>{'Email notifications are sent for mentions and direct messages after you have been away from ' + global.window.config.SiteName + ' for 5 minutes.'}</div> + <div><br/>{'Email notifications are sent for mentions and direct messages after you’ve been offline for more than 60 seconds or away from ' + global.window.config.SiteName + ' for more than 5 minutes.'}</div> </div> ); |