summaryrefslogtreecommitdiffstats
path: root/webapp/components
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/components')
-rw-r--r--webapp/components/admin_console/compliance_settings.jsx2
-rw-r--r--webapp/components/admin_console/service_settings.jsx5
-rw-r--r--webapp/components/admin_console/user_item.jsx2
-rw-r--r--webapp/components/analytics/team_analytics.jsx2
-rw-r--r--webapp/components/channel_header.jsx2
-rw-r--r--webapp/components/channel_view.jsx19
-rw-r--r--webapp/components/invite_member_modal.jsx18
-rw-r--r--webapp/components/logged_in.jsx23
-rw-r--r--webapp/components/msg_typing.jsx12
-rw-r--r--webapp/components/permalink_view.jsx25
-rw-r--r--webapp/components/popover_list_members.jsx9
-rw-r--r--webapp/components/post.jsx2
-rw-r--r--webapp/components/posts_view.jsx26
-rw-r--r--webapp/components/posts_view_container.jsx12
-rw-r--r--webapp/components/rhs_root_post.jsx2
-rw-r--r--webapp/components/search_results_item.jsx3
-rw-r--r--webapp/components/user_settings/user_settings_display.jsx2
-rw-r--r--webapp/components/user_settings/user_settings_security.jsx3
18 files changed, 76 insertions, 93 deletions
diff --git a/webapp/components/admin_console/compliance_settings.jsx b/webapp/components/admin_console/compliance_settings.jsx
index fb2ae26f9..206bb0faa 100644
--- a/webapp/components/admin_console/compliance_settings.jsx
+++ b/webapp/components/admin_console/compliance_settings.jsx
@@ -223,7 +223,7 @@ export default class ComplianceSettings extends React.Component {
</label>
<p className='help-text'>
<FormattedMessage
- id='admin.compliance.enableDesc'
+ id='admin.compliance.enableDailyDesc'
defaultMessage='When true, Mattermost will generate a daily compliance report.'
/>
</p>
diff --git a/webapp/components/admin_console/service_settings.jsx b/webapp/components/admin_console/service_settings.jsx
index 41ea5ea34..c72c97326 100644
--- a/webapp/components/admin_console/service_settings.jsx
+++ b/webapp/components/admin_console/service_settings.jsx
@@ -84,10 +84,13 @@ class ServiceSettings extends React.Component {
config.ServiceSettings.EnableDeveloper = ReactDOM.findDOMNode(this.refs.EnableDeveloper).checked;
config.ServiceSettings.EnableSecurityFixAlert = ReactDOM.findDOMNode(this.refs.EnableSecurityFixAlert).checked;
config.ServiceSettings.EnableInsecureOutgoingConnections = ReactDOM.findDOMNode(this.refs.EnableInsecureOutgoingConnections).checked;
- config.ServiceSettings.EnableMultifactorAuthentication = ReactDOM.findDOMNode(this.refs.EnableMultifactorAuthentication).checked;
config.ServiceSettings.EnableCommands = ReactDOM.findDOMNode(this.refs.EnableCommands).checked;
config.ServiceSettings.EnableOnlyAdminIntegrations = ReactDOM.findDOMNode(this.refs.EnableOnlyAdminIntegrations).checked;
+ if (this.refs.EnablMultifactorAuthentication) {
+ config.ServiceSettings.EnableMultifactorAuthentication = ReactDOM.findDOMNode(this.refs.EnableMultifactorAuthentication).checked;
+ }
+
//config.ServiceSettings.EnableOAuthServiceProvider = ReactDOM.findDOMNode(this.refs.EnableOAuthServiceProvider).checked;
var MaximumLoginAttempts = DefaultMaximumLoginAttempts;
diff --git a/webapp/components/admin_console/user_item.jsx b/webapp/components/admin_console/user_item.jsx
index 91f567d4d..c00050584 100644
--- a/webapp/components/admin_console/user_item.jsx
+++ b/webapp/components/admin_console/user_item.jsx
@@ -333,7 +333,7 @@ export default class UserItem extends React.Component {
<div>
<FormattedMessage
id='admin.user_item.confirmDemoteDescription'
- defaultMessage="If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you\'ll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command."
+ defaultMessage="If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you'll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command."
/>
<br/>
<br/>
diff --git a/webapp/components/analytics/team_analytics.jsx b/webapp/components/analytics/team_analytics.jsx
index efc965f24..9b4eb1f94 100644
--- a/webapp/components/analytics/team_analytics.jsx
+++ b/webapp/components/analytics/team_analytics.jsx
@@ -154,7 +154,7 @@ class TeamAnalytics extends React.Component {
<TableChart
title={
<FormattedMessage
- id='analytics.team.activeUsers'
+ id='analytics.team.recentUsers'
defaultMessage='Recent Active Users'
/>
}
diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx
index 6bb466c3e..482aabc01 100644
--- a/webapp/components/channel_header.jsx
+++ b/webapp/components/channel_header.jsx
@@ -216,9 +216,9 @@ export default class ChannelHeader extends React.Component {
if (!isDirect) {
popoverListMembers = (
<PopoverListMembers
+ channel={channel}
members={this.state.users}
memberCount={this.state.userCount}
- channelId={channel.id}
/>
);
}
diff --git a/webapp/components/channel_view.jsx b/webapp/components/channel_view.jsx
index 54d796ac1..4cca5aa98 100644
--- a/webapp/components/channel_view.jsx
+++ b/webapp/components/channel_view.jsx
@@ -8,7 +8,6 @@ import PostsViewContainer from 'components/posts_view_container.jsx';
import CreatePost from 'components/create_post.jsx';
import ChannelStore from 'stores/channel_store.jsx';
-import UserStore from 'stores/user_store.jsx';
export default class ChannelView extends React.Component {
constructor(props) {
@@ -23,14 +22,12 @@ export default class ChannelView extends React.Component {
getStateFromStores(props) {
const channel = ChannelStore.getByName(props.params.channel);
const channelId = channel ? channel.id : '';
- const profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
return {
- channelId,
- profiles
+ channelId
};
}
isStateValid() {
- return this.state.channelId !== '' && this.state.profiles;
+ return this.state.channelId !== '';
}
updateState() {
this.setState(this.getStateFromStores(this.props));
@@ -44,13 +41,6 @@ export default class ChannelView extends React.Component {
componentWillReceiveProps(nextProps) {
this.setState(this.getStateFromStores(nextProps));
}
- shouldComponentUpdate(nextProps, nextState) {
- if (nextState.channelId !== this.state.channelId) {
- return true;
- }
-
- return false;
- }
render() {
return (
<div
@@ -60,7 +50,7 @@ export default class ChannelView extends React.Component {
<ChannelHeader
channelId={this.state.channelId}
/>
- <PostsViewContainer profiles={this.state.profiles}/>
+ <PostsViewContainer profiles={this.props.profiles}/>
<div
className='post-create__container'
id='post-create'
@@ -75,5 +65,6 @@ ChannelView.defaultProps = {
};
ChannelView.propTypes = {
- params: React.PropTypes.object.isRequired
+ params: React.PropTypes.object.isRequired,
+ profiles: React.PropTypes.object
};
diff --git a/webapp/components/invite_member_modal.jsx b/webapp/components/invite_member_modal.jsx
index 1f8fd6133..81c3a9629 100644
--- a/webapp/components/invite_member_modal.jsx
+++ b/webapp/components/invite_member_modal.jsx
@@ -50,6 +50,7 @@ class InviteMemberModal extends React.Component {
constructor(props) {
super(props);
+ this.teamChange = this.teamChange.bind(this);
this.handleToggle = this.handleToggle.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleHide = this.handleHide.bind(this);
@@ -68,16 +69,27 @@ class InviteMemberModal extends React.Component {
emailEnabled: global.window.mm_config.SendEmailNotifications === 'true',
userCreationEnabled: global.window.mm_config.EnableUserCreation === 'true',
showConfirmModal: false,
- isSendingEmails: false
+ isSendingEmails: false,
+ teamType: null
};
}
+ teamChange() {
+ const team = TeamStore.getCurrent();
+ const teamType = team ? team.type : null;
+ this.setState({
+ teamType
+ });
+ }
+
componentDidMount() {
ModalStore.addModalListener(ActionTypes.TOGGLE_INVITE_MEMBER_MODAL, this.handleToggle);
+ TeamStore.addChangeListener(this.teamChange);
}
componentWillUnmount() {
ModalStore.removeModalListener(ActionTypes.TOGGLE_INVITE_MEMBER_MODAL, this.handleToggle);
+ TeamStore.removeChangeListener(this.teamChange);
}
handleToggle(value) {
@@ -224,7 +236,7 @@ class InviteMemberModal extends React.Component {
var currentUser = UserStore.getCurrentUser();
const {formatMessage} = this.props.intl;
- if (currentUser != null) {
+ if (currentUser != null && this.state.teamType != null) {
var inviteSections = [];
var inviteIds = this.state.inviteIds;
for (var i = 0; i < inviteIds.length; i++) {
@@ -398,7 +410,7 @@ class InviteMemberModal extends React.Component {
);
} else if (this.state.userCreationEnabled) {
var teamInviteLink = null;
- if (currentUser && TeamStore.getCurrent().type === 'O') {
+ if (currentUser && this.state.teamType === 'O') {
var link = (
<a
href='#'
diff --git a/webapp/components/logged_in.jsx b/webapp/components/logged_in.jsx
index f7a6be647..0c4571083 100644
--- a/webapp/components/logged_in.jsx
+++ b/webapp/components/logged_in.jsx
@@ -47,11 +47,12 @@ export default class LoggedIn extends React.Component {
this.onUserChanged = this.onUserChanged.bind(this);
this.state = {
- user: null
+ user: null,
+ profiles: null
};
}
isValidState() {
- return this.state.user != null;
+ return this.state.user != null && this.state.profiles != null;
}
onUserChanged() {
// Grab the current user
@@ -84,7 +85,13 @@ export default class LoggedIn extends React.Component {
browserHistory.push(Utils.getTeamURLFromAddressBar() + '/tutorial');
}
- this.setState({user});
+ // Get profiles
+ const profiles = UserStore.getProfiles();
+
+ this.setState({
+ user,
+ profiles
+ });
}
componentWillMount() {
// Emit view action
@@ -232,7 +239,10 @@ export default class LoggedIn extends React.Component {
</div>
</div>
<div className='row main'>
- {this.props.center}
+ {React.cloneElement(this.props.center, {
+ user: this.state.user,
+ profiles: this.state.profiles
+ })}
</div>
</div>
);
@@ -266,7 +276,10 @@ LoggedIn.defaultProps = {
};
LoggedIn.propTypes = {
- children: React.PropTypes.arrayOf(React.PropTypes.element),
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.arrayOf(React.PropTypes.element),
+ React.PropTypes.element
+ ]),
navbar: React.PropTypes.element,
sidebar: React.PropTypes.element,
center: React.PropTypes.element,
diff --git a/webapp/components/msg_typing.jsx b/webapp/components/msg_typing.jsx
index b2d414287..631eea78d 100644
--- a/webapp/components/msg_typing.jsx
+++ b/webapp/components/msg_typing.jsx
@@ -40,13 +40,15 @@ class MsgTyping extends React.Component {
}
updateTypingText(typingUsers) {
- if (!typingUsers) {
- return;
+ let text = '';
+ let users = {};
+ let numUsers = 0;
+ if (typingUsers) {
+ users = Object.keys(typingUsers);
+ numUsers = users.length;
}
- const users = Object.keys(typingUsers);
- let text = '';
- switch (users.length) {
+ switch (numUsers) {
case 0:
text = '';
break;
diff --git a/webapp/components/permalink_view.jsx b/webapp/components/permalink_view.jsx
index 2ebe52356..2c32d643d 100644
--- a/webapp/components/permalink_view.jsx
+++ b/webapp/components/permalink_view.jsx
@@ -7,7 +7,6 @@ import ChannelHeader from 'components/channel_header.jsx';
import PostFocusView from 'components/post_focus_view.jsx';
import ChannelStore from 'stores/channel_store.jsx';
-import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
import {Link} from 'react-router';
@@ -30,17 +29,15 @@ export default class PermalinkView extends React.Component {
const channelName = channel ? channel.name : '';
const team = TeamStore.getCurrent();
const teamName = team ? team.name : '';
- const profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
return {
channelId,
channelName,
- profiles,
teamName,
postId
};
}
isStateValid() {
- return this.state.channelId !== '' && this.state.profiles && this.state.teamName;
+ return this.state.channelId !== '' && this.state.teamName;
}
updateState() {
this.setState(this.getStateFromStores(this.props));
@@ -56,21 +53,6 @@ export default class PermalinkView extends React.Component {
componentWillReceiveProps(nextProps) {
this.setState(this.getStateFromStores(nextProps));
}
- shouldComponentUpdate(nextProps, nextState) {
- if (nextState.postId !== this.state.postId) {
- return true;
- }
-
- if (nextState.channelId !== this.state.channelId) {
- return true;
- }
-
- if (nextState.teamName !== this.state.teamName) {
- return true;
- }
-
- return false;
- }
render() {
if (!this.isStateValid()) {
return null;
@@ -83,7 +65,7 @@ export default class PermalinkView extends React.Component {
<ChannelHeader
channelId={this.state.channelId}
/>
- <PostFocusView profiles={this.state.profiles}/>
+ <PostFocusView profiles={this.props.profiles}/>
<div
id='archive-link-home'
>
@@ -106,5 +88,6 @@ PermalinkView.defaultProps = {
};
PermalinkView.propTypes = {
- params: React.PropTypes.object.isRequired
+ params: React.PropTypes.object.isRequired,
+ profiles: React.PropTypes.object
};
diff --git a/webapp/components/popover_list_members.jsx b/webapp/components/popover_list_members.jsx
index cd583e4c3..226a1889c 100644
--- a/webapp/components/popover_list_members.jsx
+++ b/webapp/components/popover_list_members.jsx
@@ -9,8 +9,6 @@ import * as Utils from 'utils/utils.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
import Constants from 'utils/constants.jsx';
-import ChannelStore from 'stores/channel_store.jsx';
-
import {FormattedMessage} from 'react-intl';
import React from 'react';
@@ -57,7 +55,6 @@ export default class PopoverListMembers extends React.Component {
const members = this.props.members;
const teamMembers = UserStore.getProfilesUsernameMap();
const currentUserId = UserStore.getCurrentId();
- const ch = ChannelStore.getCurrent();
if (members && teamMembers) {
members.sort((a, b) => {
@@ -69,7 +66,7 @@ export default class PopoverListMembers extends React.Component {
members.forEach((m, i) => {
let button = '';
- if (currentUserId !== m.id && ch.type !== 'D') {
+ if (currentUserId !== m.id && this.props.channel.type !== 'D') {
button = (
<a
href='#'
@@ -177,7 +174,7 @@ export default class PopoverListMembers extends React.Component {
}
PopoverListMembers.propTypes = {
+ channel: React.PropTypes.object.isRequired,
members: React.PropTypes.array.isRequired,
- memberCount: React.PropTypes.number,
- channelId: React.PropTypes.string.isRequired
+ memberCount: React.PropTypes.number
};
diff --git a/webapp/components/post.jsx b/webapp/components/post.jsx
index f2818188a..30c47ee22 100644
--- a/webapp/components/post.jsx
+++ b/webapp/components/post.jsx
@@ -188,6 +188,8 @@ export default class Post extends React.Component {
if (post.props && post.props.from_webhook && global.window.mm_config.EnablePostIconOverride === 'true') {
if (post.props.override_icon_url) {
src = post.props.override_icon_url;
+ } else {
+ src = Constants.DEFAULT_WEBHOOK_LOGO;
}
} else if (Utils.isSystemMessage(post)) {
src = Constants.SYSTEM_MESSAGE_PROFILE_IMAGE;
diff --git a/webapp/components/posts_view.jsx b/webapp/components/posts_view.jsx
index 647c7f086..ffe04daa1 100644
--- a/webapp/components/posts_view.jsx
+++ b/webapp/components/posts_view.jsx
@@ -173,24 +173,15 @@ export default class PostsView extends React.Component {
const postFromWebhook = Boolean(post.props && post.props.from_webhook);
const prevPostFromWebhook = Boolean(prevPost.props && prevPost.props.from_webhook);
const prevPostUserId = Utils.isSystemMessage(prevPost) ? '' : prevPost.user_id;
- let prevWebhookName = '';
- if (prevPost.props && prevPost.props.override_username) {
- prevWebhookName = prevPost.props.override_username;
- }
- let curWebhookName = '';
- if (post.props && post.props.override_username) {
- curWebhookName = post.props.override_username;
- }
// consider posts from the same user if:
// the previous post was made by the same user as the current post,
// the previous post was made within 5 minutes of the current post,
- // the previous post and current post are both from webhooks or both not,
- // the previous post and current post have the same webhook usernames
+ // the current post is not from a webhook
+ // the previous post is not from a webhook
if (prevPostUserId === postUserId &&
post.create_at - prevPost.create_at <= 1000 * 60 * 5 &&
- postFromWebhook === prevPostFromWebhook &&
- prevWebhookName === curWebhookName) {
+ !postFromWebhook && !prevPostFromWebhook) {
sameUser = true;
}
@@ -213,13 +204,11 @@ export default class PostsView extends React.Component {
// the previous post was made by the same user as the current post,
// the previous post is not a comment,
// the current post is not a comment,
- // the previous post and current post are both from webhooks or both not,
- // the previous post and current post have the same webhook usernames
+ // the current post is not from a webhook
if (prevPostUserId === postUserId &&
!prevPostIsComment &&
!postIsComment &&
- postFromWebhook === prevPostFromWebhook &&
- prevWebhookName === curWebhookName) {
+ !postFromWebhook) {
hideProfilePic = true;
}
}
@@ -319,7 +308,7 @@ export default class PostsView extends React.Component {
if (this.props.scrollType === PostsView.SCROLL_TYPE_BOTTOM) {
this.scrollToBottom();
} else if (this.props.scrollType === PostsView.SCROLL_TYPE_NEW_MESSAGE) {
- window.requestAnimationFrame(() => {
+ window.setTimeout(window.requestAnimationFrame(() => {
// If separator exists scroll to it. Otherwise scroll to bottom.
if (this.refs.newMessageSeparator) {
var objDiv = this.refs.postlist;
@@ -327,7 +316,7 @@ export default class PostsView extends React.Component {
} else if (this.refs.postlist) {
this.refs.postlist.scrollTop = this.refs.postlist.scrollHeight;
}
- });
+ }), 0);
} else if (this.props.scrollType === PostsView.SCROLL_TYPE_POST && this.props.scrollPostId) {
window.requestAnimationFrame(() => {
const postNode = ReactDOM.findDOMNode(this.refs[this.props.scrollPostId]);
@@ -385,6 +374,7 @@ export default class PostsView extends React.Component {
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
this.scrollStopAction.cancel();
+ PreferenceStore.removeChangeListener(this.updateState);
}
componentDidUpdate() {
if (this.props.postList != null) {
diff --git a/webapp/components/posts_view_container.jsx b/webapp/components/posts_view_container.jsx
index 7e334d4b0..a49c77f8d 100644
--- a/webapp/components/posts_view_container.jsx
+++ b/webapp/components/posts_view_container.jsx
@@ -8,7 +8,6 @@ import ChannelStore from 'stores/channel_store.jsx';
import PostStore from 'stores/post_store.jsx';
import UserStore from 'stores/user_store.jsx';
-import * as Utils from 'utils/utils.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
import Constants from 'utils/constants.jsx';
@@ -158,17 +157,6 @@ export default class PostsViewContainer extends React.Component {
this.setState({scrollType: PostsView.SCROLL_TYPE_FREE});
}
}
- shouldComponentUpdate(nextProps, nextState) {
- if (!Utils.areObjectsEqual(this.state, nextState)) {
- return true;
- }
-
- if (!Utils.areObjectsEqual(this.props, nextProps)) {
- return true;
- }
-
- return false;
- }
render() {
const postLists = this.state.postLists;
const channels = this.state.channels;
diff --git a/webapp/components/rhs_root_post.jsx b/webapp/components/rhs_root_post.jsx
index 26b392aa1..7a7c5f692 100644
--- a/webapp/components/rhs_root_post.jsx
+++ b/webapp/components/rhs_root_post.jsx
@@ -217,6 +217,8 @@ export default class RhsRootPost extends React.Component {
if (post.props && post.props.from_webhook && global.window.mm_config.EnablePostIconOverride === 'true') {
if (post.props.override_icon_url) {
src = post.props.override_icon_url;
+ } else {
+ src = Constants.DEFAULT_WEBHOOK_LOGO;
}
} else if (Utils.isSystemMessage(post)) {
src = Constants.SYSTEM_MESSAGE_PROFILE_IMAGE;
diff --git a/webapp/components/search_results_item.jsx b/webapp/components/search_results_item.jsx
index 219aa7093..75cbcb2a0 100644
--- a/webapp/components/search_results_item.jsx
+++ b/webapp/components/search_results_item.jsx
@@ -5,7 +5,6 @@ import UserStore from 'stores/user_store.jsx';
import UserProfile from './user_profile.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
import * as TextFormatting from 'utils/text_formatting.jsx';
-import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
@@ -88,7 +87,7 @@ export default class SearchResultsItem extends React.Component {
</li>
<li>
<Link
- to={Utils.getTeamURLFromAddressBar() + '/pl/' + this.props.post.id}
+ to={'/' + window.location.pathname.split('/')[1] + '/pl/' + this.props.post.id}
className='search-item__jump'
>
<FormattedMessage
diff --git a/webapp/components/user_settings/user_settings_display.jsx b/webapp/components/user_settings/user_settings_display.jsx
index d815bd371..d169e01b5 100644
--- a/webapp/components/user_settings/user_settings_display.jsx
+++ b/webapp/components/user_settings/user_settings_display.jsx
@@ -304,7 +304,7 @@ export default class UserSettingsDisplay extends React.Component {
describe = (
<FormattedMessage
id='user.settings.display.showUsername'
- defaultMessage='Show username (team default)'
+ defaultMessage='Show username (default)'
/>
);
} else if (this.state.nameFormat === 'full_name') {
diff --git a/webapp/components/user_settings/user_settings_security.jsx b/webapp/components/user_settings/user_settings_security.jsx
index e4044e6d0..ff5a898a9 100644
--- a/webapp/components/user_settings/user_settings_security.jsx
+++ b/webapp/components/user_settings/user_settings_security.jsx
@@ -1,6 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import $ from 'jquery';
import SettingItemMin from '../setting_item_min.jsx';
import SettingItemMax from '../setting_item_max.jsx';
import AccessHistoryModal from '../access_history_modal.jsx';
@@ -247,7 +248,7 @@ class SecurityTab extends React.Component {
extraInfo = (
<span>
<FormattedMessage
- id='user.settings.mfa.addHelp'
+ id='user.settings.mfa.addHelpQr'
defaultMessage='Please scan the QR code with the Google Authenticator app on your smartphone and fill in the token with one provided by the app.'
/>
</span>