diff options
Diffstat (limited to 'webapp/components')
-rw-r--r-- | webapp/components/admin_console/admin_team_members_dropdown.jsx | 4 | ||||
-rw-r--r-- | webapp/components/admin_console/policy_settings.jsx | 12 | ||||
-rw-r--r-- | webapp/components/admin_console/saml_settings.jsx | 4 | ||||
-rw-r--r-- | webapp/components/analytics/system_analytics.jsx | 314 | ||||
-rw-r--r-- | webapp/components/channel_members_modal.jsx | 4 | ||||
-rw-r--r-- | webapp/components/create_comment.jsx | 9 | ||||
-rw-r--r-- | webapp/components/create_post.jsx | 10 | ||||
-rw-r--r-- | webapp/components/mfa/components/setup.jsx | 2 | ||||
-rw-r--r-- | webapp/components/more_channels.jsx | 16 | ||||
-rw-r--r-- | webapp/components/more_direct_channels.jsx | 6 | ||||
-rw-r--r-- | webapp/components/notify_counts.jsx | 4 | ||||
-rw-r--r-- | webapp/components/post_view/components/post_body_additional_content.jsx | 2 | ||||
-rw-r--r-- | webapp/components/search_bar.jsx | 53 | ||||
-rw-r--r-- | webapp/components/searchable_channel_list.jsx | 6 | ||||
-rw-r--r-- | webapp/components/suggestion/suggestion_box.jsx | 5 | ||||
-rw-r--r-- | webapp/components/team_sidebar/components/team_button.jsx | 22 | ||||
-rw-r--r-- | webapp/components/team_sidebar/team_sidebar_controller.jsx | 14 |
17 files changed, 281 insertions, 206 deletions
diff --git a/webapp/components/admin_console/admin_team_members_dropdown.jsx b/webapp/components/admin_console/admin_team_members_dropdown.jsx index 0019dfbc0..ee9e53f6c 100644 --- a/webapp/components/admin_console/admin_team_members_dropdown.jsx +++ b/webapp/components/admin_console/admin_team_members_dropdown.jsx @@ -432,10 +432,6 @@ export default class AdminTeamMembersDropdown extends React.Component { ); } - if (global.window.mm_config.EnableSignInWithEmail !== 'true') { - passwordReset = null; - } - let makeDemoteModal = null; if (this.props.user.id === me.id) { const title = ( diff --git a/webapp/components/admin_console/policy_settings.jsx b/webapp/components/admin_console/policy_settings.jsx index 50b9d4033..0e224af73 100644 --- a/webapp/components/admin_console/policy_settings.jsx +++ b/webapp/components/admin_console/policy_settings.jsx @@ -146,7 +146,11 @@ export default class PolicySettings extends AdminSettings { defaultMessage='Set policy on who can delete public channels. Deleted channels can be recovered from the database using a {commandLineToolLink}.' values={{ commandLineToolLink: ( - <a href='https://docs.mattermost.com/administration/command-line-tools.html'> + <a + href='https://docs.mattermost.com/administration/command-line-tools.html' + target='_blank' + rel='noopener noreferrer' + > <FormattedMessage id='admin.general.policy.restrictPublicChannelDeletionCommandLineToolLink' defaultMessage='command line tool' @@ -222,7 +226,11 @@ export default class PolicySettings extends AdminSettings { defaultMessage='Set policy on who can delete private groups. Deleted groups can be recovered from the database using a {commandLineToolLink}.' values={{ commandLineToolLink: ( - <a href='https://docs.mattermost.com/administration/command-line-tools.html'> + <a + href='https://docs.mattermost.com/administration/command-line-tools.html' + target='_blank' + rel='noopener noreferrer' + > <FormattedMessage id='admin.general.policy.restrictPrivateChannelDeletionCommandLineToolLink' defaultMessage='command line tool' diff --git a/webapp/components/admin_console/saml_settings.jsx b/webapp/components/admin_console/saml_settings.jsx index 1391df0b6..ad7a82553 100644 --- a/webapp/components/admin_console/saml_settings.jsx +++ b/webapp/components/admin_console/saml_settings.jsx @@ -296,9 +296,9 @@ export default class SamlSettings extends AdminSettings { <SettingsGroup> <div className='banner'> <div className='banner__content'> - <FormattedMessage + <FormattedHTMLMessage id='admin.saml.bannerDesc' - defaultMessage='If a user attribute changes on the SAML server it will be updated the next time the user enters their credentials to log in to Mattermost. This includes if a user is made inactive or removed from a SAML Identity Provider. Remote logout with SAML servers is considered in a future release.' + defaultMessage='User attributes in SAML server, including user deactivation or removal, are updated in Mattermost during user login. Learn more at: <a href=\"https://docs.mattermost.com/deployment/sso-saml.html\">https://docs.mattermost.com/deployment/sso-saml.html</a>' /> </div> </div> diff --git a/webapp/components/analytics/system_analytics.jsx b/webapp/components/analytics/system_analytics.jsx index 244e1ff07..dd7b90260 100644 --- a/webapp/components/analytics/system_analytics.jsx +++ b/webapp/components/analytics/system_analytics.jsx @@ -80,69 +80,141 @@ class SystemAnalytics extends React.Component { render() { const stats = this.state.stats; + const isLicensed = global.window.mm_license.IsLicensed === 'true'; + const skippedIntensiveQueries = stats[StatTypes.TOTAL_POSTS] === -1; + const postCountsDay = formatPostsPerDayData(stats[StatTypes.POST_PER_DAY]); + const userCountsWithPostsDay = formatUsersWithPostsPerDayData(stats[StatTypes.USERS_WITH_POSTS_PER_DAY]); let banner; - if (stats[StatTypes.TOTAL_POSTS] === -1) { + let postCount; + let postTotalGraph; + let activeUserGraph; + if (skippedIntensiveQueries) { banner = ( - <Banner - description={ + <div className='banner'> + <div className='banner__content'> <FormattedHTMLMessage id='analytics.system.skippedIntensiveQueries' - defaultMessage="Some statistics have been omitted because they put too much load on the system to calculate. See <a href='https://docs.mattermost.com/administration/statistics.html' target='_blank'>https://docs.mattermost.com/administration/statistics.html</a> for more details." + defaultMessage="To maximize performance, some statistics are disabled. You can re-enable them in config.json. See: <a href='https://docs.mattermost.com/administration/statistics.html' target='_blank'>https://docs.mattermost.com/administration/statistics.html</a>" + /> + </div> + </div> + ); + } else { + postCount = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.totalPosts' + defaultMessage='Total Posts' /> } + icon='fa-comment' + count={stats[StatTypes.TOTAL_POSTS]} /> ); - } - let advancedCounts; - let advancedStats; - let advancedGraphs; - if (global.window.mm_license.IsLicensed === 'true') { - advancedCounts = ( + postTotalGraph = ( <div className='row'> - <StatisticCount - title={ - <FormattedMessage - id='analytics.system.totalSessions' - defaultMessage='Total Sessions' - /> - } - icon='fa-signal' - count={stats[StatTypes.TOTAL_SESSIONS]} - /> - <StatisticCount - title={ - <FormattedMessage - id='analytics.system.totalCommands' - defaultMessage='Total Commands' - /> - } - icon='fa-terminal' - count={stats[StatTypes.TOTAL_COMMANDS]} - /> - <StatisticCount + <LineChart title={ <FormattedMessage - id='analytics.system.totalIncomingWebhooks' - defaultMessage='Incoming Webhooks' + id='analytics.system.totalPosts' + defaultMessage='Total Posts' /> } - icon='fa-arrow-down' - count={stats[StatTypes.TOTAL_IHOOKS]} + data={postCountsDay} + options={{ + legend: { + display: false + } + }} + width='740' + height='225' /> - <StatisticCount + </div> + ); + + activeUserGraph = ( + <div className='row'> + <LineChart title={ <FormattedMessage - id='analytics.system.totalOutgoingWebhooks' - defaultMessage='Outgoing Webhooks' + id='analytics.system.activeUsers' + defaultMessage='Active Users With Posts' /> } - icon='fa-arrow-up' - count={stats[StatTypes.TOTAL_OHOOKS]} + data={userCountsWithPostsDay} + options={{ + legend: { + display: false + } + }} + width='740' + height='225' /> </div> ); + } + + let advancedStats; + let advancedGraphs; + let sessionCount; + let commandCount; + let incomingCount; + let outgoingCount; + if (global.window.mm_license.IsLicensed === 'true') { + sessionCount = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.totalSessions' + defaultMessage='Total Sessions' + /> + } + icon='fa-signal' + count={stats[StatTypes.TOTAL_SESSIONS]} + /> + ); + + commandCount = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.totalCommands' + defaultMessage='Total Commands' + /> + } + icon='fa-terminal' + count={stats[StatTypes.TOTAL_COMMANDS]} + /> + ); + + incomingCount = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.totalIncomingWebhooks' + defaultMessage='Incoming Webhooks' + /> + } + icon='fa-arrow-down' + count={stats[StatTypes.TOTAL_IHOOKS]} + /> + ); + + outgoingCount = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.totalOutgoingWebhooks' + defaultMessage='Outgoing Webhooks' + /> + } + icon='fa-arrow-up' + count={stats[StatTypes.TOTAL_OHOOKS]} + /> + ); advancedStats = ( <div className='row'> @@ -247,65 +319,89 @@ class SystemAnalytics extends React.Component { } } - const postCountsDay = formatPostsPerDayData(stats[StatTypes.POST_PER_DAY]); - const userCountsWithPostsDay = formatUsersWithPostsPerDayData(stats[StatTypes.USERS_WITH_POSTS_PER_DAY]); + const userCount = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.totalUsers' + defaultMessage='Total Users' + /> + } + icon='fa-user' + count={stats[StatTypes.TOTAL_USERS]} + /> + ); - let totalPostsCount; - let postTotalGraph; - let activeUserGraph; - if (stats[StatTypes.TOTAL_POSTS] !== -1) { - totalPostsCount = ( - <StatisticCount - title={ - <FormattedMessage - id='analytics.system.totalPosts' - defaultMessage='Total Posts' - /> - } - icon='fa-comment' - count={stats[StatTypes.TOTAL_POSTS]} - /> + const teamCount = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.totalTeams' + defaultMessage='Total Teams' + /> + } + icon='fa-users' + count={stats[StatTypes.TOTAL_TEAMS]} + /> + ); + + const channelCount = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.totalChannels' + defaultMessage='Total Channels' + /> + } + icon='fa-globe' + count={stats[StatTypes.TOTAL_PUBLIC_CHANNELS] + stats[StatTypes.TOTAL_PRIVATE_GROUPS]} + /> + ); + + let firstRow; + let secondRow; + if (isLicensed && skippedIntensiveQueries) { + firstRow = ( + <div className='row'> + {userCount} + {teamCount} + {channelCount} + {sessionCount} + </div> ); - postTotalGraph = ( + secondRow = ( <div className='row'> - <LineChart - title={ - <FormattedMessage - id='analytics.system.totalPosts' - defaultMessage='Total Posts' - /> - } - data={postCountsDay} - options={{ - legend: { - display: false - } - }} - width='740' - height='225' - /> + {commandCount} + {incomingCount} + {outgoingCount} + </div> + ); + } else if (isLicensed && !skippedIntensiveQueries) { + firstRow = ( + <div className='row'> + {userCount} + {teamCount} + {channelCount} + {postCount} </div> ); - activeUserGraph = ( + secondRow = ( <div className='row'> - <LineChart - title={ - <FormattedMessage - id='analytics.system.activeUsers' - defaultMessage='Active Users With Posts' - /> - } - data={userCountsWithPostsDay} - options={{ - legend: { - display: false - } - }} - width='740' - height='225' - /> + {sessionCount} + {commandCount} + {incomingCount} + {outgoingCount} + </div> + ); + } else if (!isLicensed) { + firstRow = ( + <div className='row'> + {userCount} + {teamCount} + {channelCount} + {postCount} </div> ); } @@ -319,40 +415,8 @@ class SystemAnalytics extends React.Component { /> </h3> {banner} - <div className='row'> - <StatisticCount - title={ - <FormattedMessage - id='analytics.system.totalUsers' - defaultMessage='Total Users' - /> - } - icon='fa-user' - count={stats[StatTypes.TOTAL_USERS]} - /> - <StatisticCount - title={ - <FormattedMessage - id='analytics.system.totalTeams' - defaultMessage='Total Teams' - /> - } - icon='fa-users' - count={stats[StatTypes.TOTAL_TEAMS]} - /> - {totalPostsCount} - <StatisticCount - title={ - <FormattedMessage - id='analytics.system.totalChannels' - defaultMessage='Total Channels' - /> - } - icon='fa-globe' - count={stats[StatTypes.TOTAL_PUBLIC_CHANNELS] + stats[StatTypes.TOTAL_PRIVATE_GROUPS]} - /> - </div> - {advancedCounts} + {firstRow} + {secondRow} {advancedStats} {advancedGraphs} {postTotalGraph} diff --git a/webapp/components/channel_members_modal.jsx b/webapp/components/channel_members_modal.jsx index 9f6a2a2eb..351efed96 100644 --- a/webapp/components/channel_members_modal.jsx +++ b/webapp/components/channel_members_modal.jsx @@ -168,7 +168,7 @@ export default class ChannelMembersModal extends React.Component { return ( <div> <Modal - dialogClassName='more-modal' + dialogClassName='more-modal more-modal--action' show={this.state.show} onHide={this.onHide} onExited={this.props.onModalDismissed} @@ -210,4 +210,4 @@ ChannelMembersModal.propTypes = { onModalDismissed: React.PropTypes.func.isRequired, showInviteModal: React.PropTypes.func.isRequired, channel: React.PropTypes.object.isRequired -}; +};
\ No newline at end of file diff --git a/webapp/components/create_comment.jsx b/webapp/components/create_comment.jsx index 09ec32b6b..0e9d2a41a 100644 --- a/webapp/components/create_comment.jsx +++ b/webapp/components/create_comment.jsx @@ -67,9 +67,10 @@ export default class CreateComment extends React.Component { fileInfos: draft.fileInfos, submitting: false, ctrlSend: PreferenceStore.getBool(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter'), - showPostDeletedModal: false, - lastBlurAt: 0 + showPostDeletedModal: false }; + + this.lastBlurAt = 0; } componentDidMount() { @@ -145,7 +146,7 @@ export default class CreateComment extends React.Component { }); const fasterThanHumanWillClick = 150; - const forceFocus = (Date.now() - this.state.lastBlurAt < fasterThanHumanWillClick); + const forceFocus = (Date.now() - this.lastBlurAt < fasterThanHumanWillClick); this.focusTextbox(forceFocus); } @@ -405,7 +406,7 @@ export default class CreateComment extends React.Component { } handleBlur() { - this.setState({lastBlurAt: Date.now()}); + this.lastBlurAt = Date.now(); } render() { diff --git a/webapp/components/create_post.jsx b/webapp/components/create_post.jsx index 13a8c729f..e1b2ca059 100644 --- a/webapp/components/create_post.jsx +++ b/webapp/components/create_post.jsx @@ -76,9 +76,10 @@ export default class CreatePost extends React.Component { ctrlSend: PreferenceStore.getBool(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter'), fullWidthTextBox: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT) === Preferences.CHANNEL_DISPLAY_MODE_FULL_SCREEN, showTutorialTip: false, - showPostDeletedModal: false, - lastBlurAt: 0 + showPostDeletedModal: false }; + + this.lastBlurAt = 0; } handlePostError(postError) { @@ -154,7 +155,8 @@ export default class CreatePost extends React.Component { this.setState({message: '', submitting: false, postError: null, fileInfos: [], serverError: null}); const fasterThanHumanWillClick = 150; - const forceFocus = (Date.now() - this.state.lastBlurAt < fasterThanHumanWillClick); + const forceFocus = (Date.now() - this.lastBlurAt < fasterThanHumanWillClick); + this.focusTextbox(forceFocus); } @@ -438,7 +440,7 @@ export default class CreatePost extends React.Component { } handleBlur() { - this.setState({lastBlurAt: Date.now()}); + this.lastBlurAt = Date.now(); } showPostDeletedModal() { diff --git a/webapp/components/mfa/components/setup.jsx b/webapp/components/mfa/components/setup.jsx index f7a287c15..a19e5d9fb 100644 --- a/webapp/components/mfa/components/setup.jsx +++ b/webapp/components/mfa/components/setup.jsx @@ -67,7 +67,7 @@ export default class Setup extends React.Component { } let mfaRequired; - if (global.window.mm_config.EnforceMultifactorAuthentication) { + if (global.window.mm_config.EnforceMultifactorAuthentication === 'true') { mfaRequired = ( <p> <FormattedHTMLMessage diff --git a/webapp/components/more_channels.jsx b/webapp/components/more_channels.jsx index 783aeff50..e4cff451d 100644 --- a/webapp/components/more_channels.jsx +++ b/webapp/components/more_channels.jsx @@ -9,7 +9,6 @@ import TeamStore from 'stores/team_store.jsx'; import Constants from 'utils/constants.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; -import * as ChannelUtils from 'utils/channel_utils.jsx'; import {joinChannel, searchMoreChannels} from 'actions/channel_actions.jsx'; import React from 'react'; @@ -152,14 +151,19 @@ export default class MoreChannels extends React.Component { const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser(); const isSystemAdmin = UserStore.isSystemAdminForCurrentUser(); - if (!ChannelUtils.showCreateOption(Constants.OPEN_CHANNEL, isAdmin, isSystemAdmin)) { - createNewChannelButton = null; - createChannelHelpText = null; + if (global.window.mm_license.IsLicensed === 'true') { + if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) { + createNewChannelButton = null; + createChannelHelpText = null; + } else if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) { + createNewChannelButton = null; + createChannelHelpText = null; + } } return ( <Modal - dialogClassName='more-modal more-public-channels' + dialogClassName='more-modal more-modal--action' show={this.state.show} onHide={this.handleHide} onExited={this.handleExit} @@ -192,4 +196,4 @@ export default class MoreChannels extends React.Component { MoreChannels.propTypes = { onModalDismissed: React.PropTypes.func, handleNewChannel: React.PropTypes.func -}; +};
\ No newline at end of file diff --git a/webapp/components/more_direct_channels.jsx b/webapp/components/more_direct_channels.jsx index 1b287b3b2..13ee50b4d 100644 --- a/webapp/components/more_direct_channels.jsx +++ b/webapp/components/more_direct_channels.jsx @@ -195,7 +195,9 @@ export default class MoreDirectChannels extends React.Component { render() { let teamToggle; + let memberClass = ''; if (global.window.mm_config.RestrictDirectMessage === 'any') { + memberClass = 'more-system-members'; teamToggle = ( <div className='member-select__container'> <select @@ -226,7 +228,7 @@ export default class MoreDirectChannels extends React.Component { return ( <Modal - dialogClassName='more-modal more-direct-channels' + dialogClassName={'more-modal more-direct-channels ' + memberClass} show={this.state.show} onHide={this.handleHide} onExited={this.handleExit} @@ -258,4 +260,4 @@ export default class MoreDirectChannels extends React.Component { MoreDirectChannels.propTypes = { onModalDismissed: React.PropTypes.func -}; +};
\ No newline at end of file diff --git a/webapp/components/notify_counts.jsx b/webapp/components/notify_counts.jsx index d49925780..55ede2d90 100644 --- a/webapp/components/notify_counts.jsx +++ b/webapp/components/notify_counts.jsx @@ -13,7 +13,7 @@ function getCountsStateFromStores() { teamMembers.forEach((member) => { if (member.team_id !== TeamStore.getCurrentId()) { - count += ((member.msg_count || 0) + (member.mention_count || 0)); + count += (member.mention_count || 0); } }); @@ -27,8 +27,6 @@ function getCountsStateFromStores() { count += channel.total_msg_count - channelMember.msg_count; } else if (channelMember.mention_count > 0) { count += channelMember.mention_count; - } else if (channelMember.notify_props.mark_unread !== 'mention' && channel.total_msg_count - channelMember.msg_count > 0) { - count += 1; } }); diff --git a/webapp/components/post_view/components/post_body_additional_content.jsx b/webapp/components/post_view/components/post_body_additional_content.jsx index 5cdbef050..a65b608d7 100644 --- a/webapp/components/post_view/components/post_body_additional_content.jsx +++ b/webapp/components/post_view/components/post_body_additional_content.jsx @@ -136,7 +136,7 @@ export default class PostBodyAdditionalContent extends React.Component { } generateStaticEmbed() { - if (this.props.post.type === Constants.POST_TYPE_ATTACHMENT) { + if (this.props.post.props && this.props.post.props.attachments) { return this.getSlackAttachment(); } diff --git a/webapp/components/search_bar.jsx b/webapp/components/search_bar.jsx index bea722243..a7e9bfcac 100644 --- a/webapp/components/search_bar.jsx +++ b/webapp/components/search_bar.jsx @@ -111,9 +111,8 @@ export default class SearchBar extends React.Component { } handleUserFocus() { - $('.search-bar__container').addClass('focused'); - this.setState({focused: true}); + $('.search-bar__container').addClass('focused'); } performSearch(terms, isMentionSearch) { @@ -193,19 +192,6 @@ export default class SearchBar extends React.Component { </Tooltip> ); - const searchPopover = ( - <Popover - id='searchbar-help-popup' - placement='bottom' - className={helpClass} - > - <FormattedHTMLMessage - id='search_bar.usage' - defaultMessage='<h4>Search Options</h4><ul><li><span>Use </span><b>"quotation marks"</b><span> to search for phrases</span></li><li><span>Use </span><b>from:</b><span> to find posts from specific users and </span><b>in:</b><span> to find posts in specific channels</span></li></ul>' - /> - </Popover> - ); - const flaggedTooltip = ( <Tooltip id='flaggedTooltip'> <FormattedMessage @@ -289,28 +275,29 @@ export default class SearchBar extends React.Component { autoComplete='off' > <span className='fa fa-search sidebar__search-icon'/> - <OverlayTrigger - delayShow={Constants.OVERLAY_TIME_DELAY_SMALL} + <SuggestionBox + ref='search' + className='form-control search-bar' + placeholder={Utils.localizeMessage('search_bar.search', 'Search')} + value={this.state.searchTerm} + onFocus={this.handleUserFocus} + onBlur={this.handleUserBlur} + onChange={this.handleChange} + listComponent={SearchSuggestionList} + providers={this.suggestionProviders} + type='search' + /> + {isSearching} + <Popover + id='searchbar-help-popup' placement='bottom' - overlay={searchPopover} - trigger='focus' - rootClose={true} className={helpClass} > - <SuggestionBox - ref='search' - className='form-control search-bar' - placeholder={Utils.localizeMessage('search_bar.search', 'Search')} - value={this.state.searchTerm} - onFocus={this.handleUserFocus} - onBlur={this.handleUserBlur} - onChange={this.handleChange} - listComponent={SearchSuggestionList} - providers={this.suggestionProviders} - type='search' + <FormattedHTMLMessage + id='search_bar.usage' + defaultMessage='<h4>Search Options</h4><ul><li><span>Use </span><b>"quotation marks"</b><span> to search for phrases</span></li><li><span>Use </span><b>from:</b><span> to find posts from specific users and </span><b>in:</b><span> to find posts in specific channels</span></li></ul>' /> - </OverlayTrigger> - {isSearching} + </Popover> </form> {mentionBtn} diff --git a/webapp/components/searchable_channel_list.jsx b/webapp/components/searchable_channel_list.jsx index afd113975..1bbaa3e57 100644 --- a/webapp/components/searchable_channel_list.jsx +++ b/webapp/components/searchable_channel_list.jsx @@ -180,7 +180,9 @@ export default class SearchableChannelList extends React.Component { ref='channelList' className='more-modal__list' > - {listContent} + <div> + {listContent} + </div> </div> <div className='filter-controls'> {previousButton} @@ -202,4 +204,4 @@ SearchableChannelList.propTypes = { search: React.PropTypes.func.isRequired, handleJoin: React.PropTypes.func.isRequired, noResultsText: React.PropTypes.object -}; +};
\ No newline at end of file diff --git a/webapp/components/suggestion/suggestion_box.jsx b/webapp/components/suggestion/suggestion_box.jsx index b3f9843c6..e9f7c3699 100644 --- a/webapp/components/suggestion/suggestion_box.jsx +++ b/webapp/components/suggestion/suggestion_box.jsx @@ -64,6 +64,10 @@ export default class SuggestionBox extends React.Component { // Delay this slightly so that we don't clear the suggestions before we run click handlers on SuggestionList GlobalActions.emitClearSuggestions(this.suggestionId); }, 100); + + if (this.props.onBlur) { + this.props.onBlur(); + } } handleChange(e) { @@ -272,6 +276,7 @@ SuggestionBox.propTypes = { renderDividers: React.PropTypes.bool, // explicitly name any input event handlers we override and need to manually call + onBlur: React.PropTypes.func, onChange: React.PropTypes.func, onKeyDown: React.PropTypes.func, onItemSelected: React.PropTypes.func diff --git a/webapp/components/team_sidebar/components/team_button.jsx b/webapp/components/team_sidebar/components/team_button.jsx index 203e1de00..2df21b20b 100644 --- a/webapp/components/team_sidebar/components/team_button.jsx +++ b/webapp/components/team_sidebar/components/team_button.jsx @@ -7,9 +7,6 @@ import React from 'react'; import {Link} from 'react-router/es6'; import {Tooltip, OverlayTrigger} from 'react-bootstrap'; -import {isMobile} from 'utils/utils.jsx'; -import {isMobileApp} from 'utils/user_agent.jsx'; - export default class TeamButton extends React.Component { constructor(props) { super(props); @@ -50,14 +47,21 @@ export default class TeamButton extends React.Component { </div> ); } - if (!isMobile() && !isMobileApp()) { + if (this.props.isMobile) { + btn = ( + <div className={'team-btn ' + btnClass}> + {badge} + {content} + </div> + ); + } else { btn = ( <OverlayTrigger delayShow={Constants.OVERLAY_TIME_DELAY} placement={this.props.placement} overlay={ <Tooltip id={`tooltip-${this.props.url}`}> - {this.props.displayName} + {this.props.tip} </Tooltip> } > @@ -67,13 +71,6 @@ export default class TeamButton extends React.Component { </div> </OverlayTrigger> ); - } else { - btn = ( - <div className={'team-btn ' + btnClass}> - {badge} - {content} - </div> - ); } return ( @@ -110,6 +107,7 @@ TeamButton.propTypes = { tip: React.PropTypes.node.isRequired, active: React.PropTypes.bool, disabled: React.PropTypes.bool, + isMobile: React.PropTypes.bool, unread: React.PropTypes.bool, mentions: React.PropTypes.number, placement: React.PropTypes.oneOf(['left', 'right', 'top', 'bottom']) diff --git a/webapp/components/team_sidebar/team_sidebar_controller.jsx b/webapp/components/team_sidebar/team_sidebar_controller.jsx index 24cd48d39..ac3a9f894 100644 --- a/webapp/components/team_sidebar/team_sidebar_controller.jsx +++ b/webapp/components/team_sidebar/team_sidebar_controller.jsx @@ -34,7 +34,8 @@ export default class TeamSidebar extends React.Component { teamListings: TeamStore.getTeamListings(), teamMembers, currentTeamId, - show: teamMembers && teamMembers.length > 1 + show: teamMembers && teamMembers.length > 1, + isMobile: Utils.isMobile() }; } @@ -53,12 +54,16 @@ export default class TeamSidebar extends React.Component { } componentDidUpdate(prevProps, prevState) { - $('.team-wrapper').perfectScrollbar(); + if (!this.state.isMobile) { + $('.team-wrapper').perfectScrollbar(); + } // reset the scrollbar upon switching teams if (this.state.currentTeam !== prevState.currentTeam) { this.refs.container.scrollTop = 0; - $('.team-wrapper').perfectScrollbar('update'); + if (!this.state.isMobile) { + $('.team-wrapper').perfectScrollbar('update'); + } } } @@ -121,6 +126,7 @@ export default class TeamSidebar extends React.Component { url={`/${team.name}`} tip={team.display_name} active={team.id === this.state.currentTeamId} + isMobile={this.state.isMobile} displayName={team.display_name} unread={team.unread} mentions={team.mentions} @@ -134,6 +140,7 @@ export default class TeamSidebar extends React.Component { btnClass='team-btn__add' key='more_teams' url='/select_team' + isMobile={this.state.isMobile} tip={ <FormattedMessage id='team_sidebar.join' @@ -149,6 +156,7 @@ export default class TeamSidebar extends React.Component { btnClass='team-btn__add' key='more_teams' url='/create_team' + isMobile={this.state.isMobile} tip={ <FormattedMessage id='navbar_dropdown.create' |