Merge branch 'release-3.5'
Этот коммит содержится в:
@@ -81,6 +81,7 @@ export default class AdminTeamMembersDropdown extends React.Component {
|
||||
this.props.teamMember.team_id,
|
||||
this.props.user.id,
|
||||
() => {
|
||||
AsyncClient.getTeamStats(this.props.teamMember.team_id);
|
||||
UserStore.removeProfileFromTeam(this.props.teamMember.team_id, this.props.user.id);
|
||||
UserStore.emitInTeamChange();
|
||||
},
|
||||
|
||||
@@ -105,7 +105,7 @@ export default class LoggedIn extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// Initalize websocket
|
||||
// Initialize websocket
|
||||
WebSocketActions.initialize();
|
||||
|
||||
// Listen for user
|
||||
|
||||
@@ -32,6 +32,7 @@ export default class MemberListTeam extends React.Component {
|
||||
teamMembers: Object.assign([], TeamStore.getMembersInTeam()),
|
||||
total: stats.total_member_count,
|
||||
search: false,
|
||||
term: '',
|
||||
loading: true
|
||||
};
|
||||
}
|
||||
@@ -39,7 +40,7 @@ export default class MemberListTeam extends React.Component {
|
||||
componentDidMount() {
|
||||
UserStore.addInTeamChangeListener(this.onChange);
|
||||
UserStore.addStatusesChangeListener(this.onChange);
|
||||
TeamStore.addChangeListener(this.onChange);
|
||||
TeamStore.addChangeListener(this.onChange.bind(null, true));
|
||||
TeamStore.addStatsChangeListener(this.onStatsChange);
|
||||
|
||||
loadProfilesAndTeamMembers(0, Constants.PROFILE_CHUNK_SIZE, TeamStore.getCurrentId(), this.loadComplete);
|
||||
@@ -60,6 +61,9 @@ export default class MemberListTeam extends React.Component {
|
||||
onChange(force) {
|
||||
if (this.state.search && !force) {
|
||||
return;
|
||||
} else if (this.state.search) {
|
||||
this.search(this.state.term);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({users: UserStore.getProfileListInTeam(), teamMembers: Object.assign([], TeamStore.getMembersInTeam())});
|
||||
@@ -76,8 +80,7 @@ export default class MemberListTeam extends React.Component {
|
||||
|
||||
search(term) {
|
||||
if (term === '') {
|
||||
this.onChange(true);
|
||||
this.setState({search: false});
|
||||
this.setState({search: false, term, users: UserStore.getProfileListInTeam(), teamMembers: Object.assign([], TeamStore.getMembersInTeam())});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -86,7 +89,7 @@ export default class MemberListTeam extends React.Component {
|
||||
TeamStore.getCurrentId(),
|
||||
{},
|
||||
(users) => {
|
||||
this.setState({loading: true, search: true, users});
|
||||
this.setState({loading: true, search: true, users, term, teamMembers: Object.assign([], TeamStore.getMembersInTeam())});
|
||||
loadTeamMembersForProfilesList(users, TeamStore.getCurrentId(), this.loadComplete);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -38,6 +38,7 @@ export default class MoreDirectChannels extends React.Component {
|
||||
users: null,
|
||||
loadingDMChannel: -1,
|
||||
listType: 'team',
|
||||
show: true,
|
||||
search: false
|
||||
};
|
||||
}
|
||||
@@ -60,15 +61,17 @@ export default class MoreDirectChannels extends React.Component {
|
||||
}
|
||||
|
||||
handleHide() {
|
||||
if (this.props.onModalDismissed) {
|
||||
this.props.onModalDismissed();
|
||||
}
|
||||
this.setState({show: false});
|
||||
}
|
||||
|
||||
handleExit() {
|
||||
if (this.exitToDirectChannel) {
|
||||
browserHistory.push(this.exitToDirectChannel);
|
||||
}
|
||||
|
||||
if (this.props.onModalDismissed) {
|
||||
this.props.onModalDismissed();
|
||||
}
|
||||
}
|
||||
|
||||
handleShowDirectChannel(teammate, e) {
|
||||
@@ -220,7 +223,7 @@ export default class MoreDirectChannels extends React.Component {
|
||||
return (
|
||||
<Modal
|
||||
dialogClassName='more-modal more-direct-channels'
|
||||
show={this.props.show}
|
||||
show={this.state.show}
|
||||
onHide={this.handleHide}
|
||||
onExited={this.handleExit}
|
||||
>
|
||||
@@ -262,6 +265,5 @@ export default class MoreDirectChannels extends React.Component {
|
||||
}
|
||||
|
||||
MoreDirectChannels.propTypes = {
|
||||
show: React.PropTypes.bool.isRequired,
|
||||
onModalDismissed: React.PropTypes.func
|
||||
};
|
||||
|
||||
@@ -546,6 +546,12 @@ export default class Navbar extends React.Component {
|
||||
{deleteChannelOption}
|
||||
{leaveChannelOption}
|
||||
{toggleFavoriteOption}
|
||||
<div
|
||||
className='close visible-xs-block'
|
||||
onClick={() => this.refs.headerOverlay.hide()}
|
||||
>
|
||||
{'×'}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -671,7 +677,7 @@ export default class Navbar extends React.Component {
|
||||
options={{singleline: true, mentionHighlight: false}}
|
||||
/>
|
||||
<div
|
||||
className='close__icon visible-xs-block'
|
||||
className='close visible-xs-block'
|
||||
onClick={() => this.refs.headerOverlay.hide()}
|
||||
>
|
||||
{'×'}
|
||||
@@ -721,7 +727,7 @@ export default class Navbar extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className='close__icon visible-xs-block'
|
||||
className='close visible-xs-block'
|
||||
onClick={() => this.refs.headerOverlay.hide()}
|
||||
>
|
||||
{'×'}
|
||||
|
||||
@@ -81,7 +81,6 @@ export default class NeedsTeam extends React.Component {
|
||||
if (tutorialStep <= TutorialSteps.INTRO_SCREENS) {
|
||||
browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/tutorial');
|
||||
}
|
||||
stopPeriodicStatusUpdates();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -132,6 +131,7 @@ export default class NeedsTeam extends React.Component {
|
||||
if (UserAgent.isIosSafari()) {
|
||||
iNoBounce.disable();
|
||||
}
|
||||
stopPeriodicStatusUpdates();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -264,6 +264,7 @@ export default class PostList extends React.Component {
|
||||
|
||||
let commentCount = 0;
|
||||
let isCommentMention = false;
|
||||
let shouldHighlightThreads = false;
|
||||
let commentRootId;
|
||||
if (parentPost) {
|
||||
commentRootId = post.root_id;
|
||||
@@ -271,9 +272,14 @@ export default class PostList extends React.Component {
|
||||
commentRootId = post.id;
|
||||
}
|
||||
|
||||
for (const postId in posts) {
|
||||
if (posts[postId].root_id === commentRootId) {
|
||||
commentCount += 1;
|
||||
if (commentRootId) {
|
||||
for (const postId in posts) {
|
||||
if (posts[postId].root_id === commentRootId) {
|
||||
commentCount += 1;
|
||||
if (posts[postId].user_id === userId) {
|
||||
shouldHighlightThreads = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +287,7 @@ export default class PostList extends React.Component {
|
||||
const commentsNotifyLevel = this.props.currentUser.notify_props.comments || 'never';
|
||||
const notCurrentUser = post.user_id !== userId || (post.props && post.props.from_webhook);
|
||||
if (notCurrentUser) {
|
||||
if (commentsNotifyLevel === 'any') {
|
||||
if (commentsNotifyLevel === 'any' && (posts[commentRootId].user_id === userId || shouldHighlightThreads)) {
|
||||
isCommentMention = true;
|
||||
} else if (commentsNotifyLevel === 'root' && posts[commentRootId].user_id === userId) {
|
||||
isCommentMention = true;
|
||||
|
||||
@@ -13,6 +13,7 @@ import SearchSuggestionList from './suggestion/search_suggestion_list.jsx';
|
||||
import SearchUserProvider from './suggestion/search_user_provider.jsx';
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
import Constants from 'utils/constants.jsx';
|
||||
import {loadProfilesForPosts} from 'actions/post_actions.jsx';
|
||||
|
||||
import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
|
||||
|
||||
@@ -129,6 +130,8 @@ export default class SearchBar extends React.Component {
|
||||
results: data,
|
||||
is_mention_search: isMentionSearch
|
||||
});
|
||||
|
||||
loadProfilesForPosts(data.posts);
|
||||
},
|
||||
(err) => {
|
||||
this.setState({isSearching: false});
|
||||
|
||||
@@ -19,7 +19,6 @@ import * as AsyncClient from 'utils/async_client.jsx';
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
import * as ChannelUtils from 'utils/channel_utils.jsx';
|
||||
import * as ChannelActions from 'actions/channel_actions.jsx';
|
||||
import {loadProfilesAndTeamMembersForDMSidebar} from 'actions/user_actions.jsx';
|
||||
|
||||
import Constants from 'utils/constants.jsx';
|
||||
|
||||
@@ -125,9 +124,6 @@ export default class Sidebar extends React.Component {
|
||||
|
||||
document.addEventListener('keydown', this.navigateChannelShortcut);
|
||||
document.addEventListener('keydown', this.navigateUnreadChannelShortcut);
|
||||
|
||||
loadProfilesAndTeamMembersForDMSidebar();
|
||||
AsyncClient.getMyChannelMembers();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// See License.txt for license information.
|
||||
|
||||
import $ from 'jquery';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Constants from 'utils/constants.jsx';
|
||||
import * as GlobalActions from 'actions/global_actions.jsx';
|
||||
@@ -37,6 +36,13 @@ export default class SuggestionBox extends React.Component {
|
||||
SuggestionStore.addPretextChangedListener(this.suggestionId, this.handlePretextChanged);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// Clear any suggestions when the SuggestionBox is cleared
|
||||
if (nextProps.value === '' && this.props.value !== nextProps.value) {
|
||||
GlobalActions.emitClearSuggestions(this.suggestionId);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
SuggestionStore.removeCompleteWordListener(this.suggestionId, this.handleCompleteWord);
|
||||
SuggestionStore.removePretextChangedListener(this.suggestionId, this.handlePretextChanged);
|
||||
@@ -64,7 +70,7 @@ export default class SuggestionBox extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
const container = $(ReactDOM.findDOMNode(this));
|
||||
const container = $(this.refs.container);
|
||||
|
||||
if (!(container.is(e.target) || container.has(e.target).length > 0)) {
|
||||
// We can't just use blur for this because it fires and hides the children before
|
||||
@@ -198,7 +204,7 @@ export default class SuggestionBox extends React.Component {
|
||||
const SuggestionListComponent = listComponent;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div ref='container'>
|
||||
{textbox}
|
||||
<SuggestionListComponent
|
||||
suggestionId={this.suggestionId}
|
||||
@@ -239,6 +245,5 @@ SuggestionBox.propTypes = {
|
||||
|
||||
// explicitly name any input event handlers we override and need to manually call
|
||||
onChange: React.PropTypes.func,
|
||||
onBlur: React.PropTypes.func,
|
||||
onKeyDown: React.PropTypes.func
|
||||
};
|
||||
|
||||
@@ -928,8 +928,9 @@ export default class SecurityTab extends React.Component {
|
||||
numMethods = config.EnableLdap === 'true' ? numMethods + 1 : numMethods;
|
||||
numMethods = config.EnableSaml === 'true' ? numMethods + 1 : numMethods;
|
||||
|
||||
// If there are other sign-in methods and either email is enabled or the user's account is email, then allow switching
|
||||
let signInSection;
|
||||
if (config.EnableSignUpWithEmail === 'true' && numMethods > 0) {
|
||||
if ((config.EnableSignUpWithEmail === 'true' || user.auth_service === '') && numMethods > 0) {
|
||||
signInSection = this.createSignInSection();
|
||||
}
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user