summaryrefslogtreecommitdiffstats
path: root/webapp/components
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2017-04-25 11:46:02 -0400
committerChristopher Speller <crspeller@gmail.com>2017-04-25 11:46:02 -0400
commit6c4c706313eb765eb00c639f381646be74f27b69 (patch)
tree6068feaa9668dcd74601730ac1a5abfb366402b1 /webapp/components
parentcc07c005074348de87854f1c953a549e8772fa03 (diff)
downloadchat-6c4c706313eb765eb00c639f381646be74f27b69.tar.gz
chat-6c4c706313eb765eb00c639f381646be74f27b69.tar.bz2
chat-6c4c706313eb765eb00c639f381646be74f27b69.zip
Start moving webapp to Redux (#6140)
* Start moving webapp to Redux * Fix localforage import * Updates per feedback * Feedback udpates and a few fixes * Minor updates * Fix statuses, config not loading properly, getMe sanitizing too much * Fix preferences * Fix user autocomplete * Fix sessions and audits * Fix error handling for all redux actions * Use new directory structure for components and containers * Refresh immediately on logout instead of after timeout * Add fetch polyfill
Diffstat (limited to 'webapp/components')
-rw-r--r--webapp/components/access_history_modal/access_history_modal.jsx (renamed from webapp/components/access_history_modal.jsx)18
-rw-r--r--webapp/components/access_history_modal/index.js24
-rw-r--r--webapp/components/activity_log_modal/activity_log_modal.jsx (renamed from webapp/components/activity_log_modal.jsx)29
-rw-r--r--webapp/components/activity_log_modal/index.js25
-rw-r--r--webapp/components/add_users_to_team/add_users_to_team.jsx (renamed from webapp/components/add_users_to_team.jsx)69
-rw-r--r--webapp/components/add_users_to_team/index.js24
-rw-r--r--webapp/components/admin_console/system_users/system_users.jsx87
-rw-r--r--webapp/components/channel_header.jsx4
-rw-r--r--webapp/components/channel_invite_modal/channel_invite_modal.jsx (renamed from webapp/components/channel_invite_modal.jsx)61
-rw-r--r--webapp/components/channel_invite_modal/index.js24
-rw-r--r--webapp/components/login/login_controller.jsx22
-rw-r--r--webapp/components/member_list_channel.jsx47
-rw-r--r--webapp/components/member_list_team.jsx30
-rw-r--r--webapp/components/more_direct_channels/index.js25
-rw-r--r--webapp/components/more_direct_channels/more_direct_channels.jsx (renamed from webapp/components/more_direct_channels.jsx)77
-rw-r--r--webapp/components/navbar.jsx2
-rw-r--r--webapp/components/popover_list_members/index.js24
-rw-r--r--webapp/components/popover_list_members/popover_list_members.jsx (renamed from webapp/components/popover_list_members.jsx)23
-rw-r--r--webapp/components/root.jsx1
-rw-r--r--webapp/components/sidebar.jsx2
-rw-r--r--webapp/components/sidebar_header_dropdown.jsx2
-rw-r--r--webapp/components/sidebar_right_menu.jsx2
-rw-r--r--webapp/components/signup/components/signup_email.jsx6
-rw-r--r--webapp/components/signup/components/signup_ldap.jsx4
-rw-r--r--webapp/components/signup/signup_controller.jsx3
-rw-r--r--webapp/components/suggestion/at_mention_provider.jsx8
-rw-r--r--webapp/components/suggestion/search_user_provider.jsx2
-rw-r--r--webapp/components/suggestion/switch_channel_provider.jsx4
-rw-r--r--webapp/components/team_members_dropdown/index.js24
-rw-r--r--webapp/components/team_members_dropdown/team_members_dropdown.jsx (renamed from webapp/components/team_members_dropdown.jsx)21
-rw-r--r--webapp/components/user_settings/user_settings.jsx4
-rw-r--r--webapp/components/user_settings/user_settings_general/index.js24
-rw-r--r--webapp/components/user_settings/user_settings_general/user_settings_general.jsx (renamed from webapp/components/user_settings/user_settings_general.jsx)32
-rw-r--r--webapp/components/user_settings/user_settings_security/index.js24
-rw-r--r--webapp/components/user_settings/user_settings_security/user_settings_security.jsx (renamed from webapp/components/user_settings/user_settings_security.jsx)35
35 files changed, 476 insertions, 337 deletions
diff --git a/webapp/components/access_history_modal.jsx b/webapp/components/access_history_modal/access_history_modal.jsx
index 25c7ef380..da03fdb5b 100644
--- a/webapp/components/access_history_modal.jsx
+++ b/webapp/components/access_history_modal/access_history_modal.jsx
@@ -1,12 +1,11 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import LoadingScreen from './loading_screen.jsx';
-import AuditTable from './audit_table.jsx';
+import LoadingScreen from 'components/loading_screen.jsx';
+import AuditTable from 'components/audit_table.jsx';
import UserStore from 'stores/user_store.jsx';
-import * as AsyncClient from 'utils/async_client.jsx';
import * as Utils from 'utils/utils.jsx';
import $ from 'jquery';
@@ -16,6 +15,13 @@ import {Modal} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
export default class AccessHistoryModal extends React.Component {
+ static propTypes = {
+ onHide: React.PropTypes.func.isRequired,
+ actions: React.PropTypes.shape({
+ getUserAudits: React.PropTypes.func.isRequired
+ }).isRequired
+ }
+
constructor(props) {
super(props);
@@ -37,7 +43,7 @@ export default class AccessHistoryModal extends React.Component {
}
onShow() {
- AsyncClient.getAudits();
+ this.props.actions.getUserAudits(UserStore.getCurrentId(), 0, 200);
if (!Utils.isMobile()) {
$('.modal-body').perfectScrollbar();
}
@@ -100,7 +106,3 @@ export default class AccessHistoryModal extends React.Component {
);
}
}
-
-AccessHistoryModal.propTypes = {
- onHide: React.PropTypes.func.isRequired
-};
diff --git a/webapp/components/access_history_modal/index.js b/webapp/components/access_history_modal/index.js
new file mode 100644
index 000000000..4842ca730
--- /dev/null
+++ b/webapp/components/access_history_modal/index.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {bindActionCreators} from 'redux';
+import {getUserAudits} from 'mattermost-redux/actions/users';
+
+import AccessHistoryModal from './access_history_modal.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ getUserAudits
+ }, dispatch)
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(AccessHistoryModal);
diff --git a/webapp/components/activity_log_modal.jsx b/webapp/components/activity_log_modal/activity_log_modal.jsx
index 8890a1d19..c94909754 100644
--- a/webapp/components/activity_log_modal.jsx
+++ b/webapp/components/activity_log_modal/activity_log_modal.jsx
@@ -1,11 +1,10 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import LoadingScreen from './loading_screen.jsx';
+import LoadingScreen from 'components/loading_screen.jsx';
import UserStore from 'stores/user_store.jsx';
-import * as AsyncClient from 'utils/async_client.jsx';
import * as Utils from 'utils/utils.jsx';
import $ from 'jquery';
@@ -13,9 +12,15 @@ import React from 'react';
import {Modal} from 'react-bootstrap';
import {FormattedMessage, FormattedTime, FormattedDate} from 'react-intl';
-import {revokeSession} from 'actions/admin_actions.jsx';
-
export default class ActivityLogModal extends React.Component {
+ static propTypes = {
+ onHide: React.PropTypes.func.isRequired,
+ actions: React.PropTypes.shape({
+ getSessions: React.PropTypes.func.isRequired,
+ revokeSession: React.PropTypes.func.isRequired
+ }).isRequired
+ }
+
constructor(props) {
super(props);
@@ -35,7 +40,6 @@ export default class ActivityLogModal extends React.Component {
getStateFromStores() {
return {
sessions: UserStore.getSessions(),
- serverError: null,
clientError: null
};
}
@@ -47,18 +51,11 @@ export default class ActivityLogModal extends React.Component {
setTimeout(() => {
modalContent.removeClass('animation--highlight');
}, 1500);
- revokeSession(altId,
- null,
- (err) => {
- const state = this.getStateFromStores();
- state.serverError = err;
- this.setState(state);
- }
- );
+ this.props.actions.revokeSession(UserStore.getCurrentId(), altId);
}
onShow() {
- AsyncClient.getSessions();
+ this.props.actions.getSessions(UserStore.getCurrentId());
if (!Utils.isMobile()) {
$('.modal-body').perfectScrollbar();
}
@@ -302,7 +299,3 @@ export default class ActivityLogModal extends React.Component {
);
}
}
-
-ActivityLogModal.propTypes = {
- onHide: React.PropTypes.func.isRequired
-};
diff --git a/webapp/components/activity_log_modal/index.js b/webapp/components/activity_log_modal/index.js
new file mode 100644
index 000000000..1c4890c65
--- /dev/null
+++ b/webapp/components/activity_log_modal/index.js
@@ -0,0 +1,25 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {bindActionCreators} from 'redux';
+import {revokeSession, getSessions} from 'mattermost-redux/actions/users';
+
+import ActivityLogModal from './activity_log_modal.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ getSessions,
+ revokeSession
+ }, dispatch)
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ActivityLogModal);
diff --git a/webapp/components/add_users_to_team.jsx b/webapp/components/add_users_to_team/add_users_to_team.jsx
index f0936c0d7..ae6fd8c4e 100644
--- a/webapp/components/add_users_to_team.jsx
+++ b/webapp/components/add_users_to_team/add_users_to_team.jsx
@@ -10,7 +10,6 @@ import {searchUsersNotInTeam} from 'actions/user_actions.jsx';
import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
-import * as AsyncClient from 'utils/async_client.jsx';
import Constants from 'utils/constants.jsx';
import {displayUsernameForUser} from 'utils/utils.jsx';
import Client from 'client/web_client.jsx';
@@ -20,10 +19,20 @@ import {Modal} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import {browserHistory} from 'react-router/es6';
+import store from 'stores/redux_store.jsx';
+import {searchProfilesNotInCurrentTeam} from 'mattermost-redux/selectors/entities/users';
+
const USERS_PER_PAGE = 50;
const MAX_SELECTABLE_VALUES = 20;
export default class AddUsersToTeam extends React.Component {
+ static propTypes = {
+ onModalDismissed: React.PropTypes.func,
+ actions: React.PropTypes.shape({
+ getProfilesNotInTeam: React.PropTypes.func.isRequired
+ }).isRequired
+ }
+
constructor(props) {
super(props);
@@ -34,11 +43,12 @@ export default class AddUsersToTeam extends React.Component {
this.onChange = this.onChange.bind(this);
this.search = this.search.bind(this);
this.addValue = this.addValue.bind(this);
+ this.handlePageChange = this.handlePageChange.bind(this);
this.searchTimeoutId = 0;
this.state = {
- users: null,
+ users: Object.assign([], UserStore.getProfileListNotInTeam(TeamStore.getCurrentId(), true)),
values: [],
show: true,
search: false
@@ -50,7 +60,7 @@ export default class AddUsersToTeam extends React.Component {
UserStore.addNotInTeamChangeListener(this.onChange);
UserStore.addStatusesChangeListener(this.onChange);
- AsyncClient.getProfilesNotInTeam(TeamStore.getCurrentId(), 0, USERS_PER_PAGE * 2);
+ this.props.actions.getProfilesNotInTeam(TeamStore.getCurrentId(), 0, USERS_PER_PAGE * 2);
}
componentWillUnmount() {
@@ -97,13 +107,14 @@ export default class AddUsersToTeam extends React.Component {
this.setState({values});
}
- onChange(force) {
- if (this.state.search && !force) {
- return;
+ onChange() {
+ let users;
+ if (this.term) {
+ users = Object.assign([], searchProfilesNotInCurrentTeam(store.getState(), this.term, true));
+ } else {
+ users = Object.assign([], UserStore.getProfileListNotInTeam(TeamStore.getCurrentId(), true));
}
- const users = Object.assign([], UserStore.getProfileListNotInTeam(TeamStore.getCurrentId(), true));
-
for (let i = 0; i < users.length; i++) {
const user = Object.assign({}, users[i]);
user.value = user.id;
@@ -118,53 +129,25 @@ export default class AddUsersToTeam extends React.Component {
handlePageChange(page, prevPage) {
if (page > prevPage) {
- AsyncClient.getProfilesNotInTeam((page + 1) * USERS_PER_PAGE, USERS_PER_PAGE);
+ this.props.actions.getProfilesNotInTeam(TeamStore.getCurrentId(), page + 1, USERS_PER_PAGE);
}
}
search(term) {
clearTimeout(this.searchTimeoutId);
+ this.term = term;
if (term === '') {
- this.onChange(true);
- this.setState({search: false});
- this.searchTimeoutId = '';
+ this.onChange();
return;
}
- const teamId = TeamStore.getCurrentId();
-
- const searchTimeoutId = setTimeout(
+ this.searchTimeoutId = setTimeout(
() => {
- searchUsersNotInTeam(
- term,
- teamId,
- {},
- (users) => {
- if (searchTimeoutId !== this.searchTimeoutId) {
- return;
- }
-
- let indexToDelete = -1;
- for (let i = 0; i < users.length; i++) {
- if (users[i].id === UserStore.getCurrentId()) {
- indexToDelete = i;
- }
- users[i].value = users[i].id;
- users[i].label = '@' + users[i].username;
- }
-
- if (indexToDelete !== -1) {
- users.splice(indexToDelete, 1);
- }
- this.setState({search: true, users});
- }
- );
+ searchUsersNotInTeam(term, TeamStore.getCurrentId(), {});
},
Constants.SEARCH_TIMEOUT_MILLISECONDS
);
-
- this.searchTimeoutId = searchTimeoutId;
}
handleDelete(values) {
@@ -272,7 +255,3 @@ export default class AddUsersToTeam extends React.Component {
);
}
}
-
-AddUsersToTeam.propTypes = {
- onModalDismissed: React.PropTypes.func
-};
diff --git a/webapp/components/add_users_to_team/index.js b/webapp/components/add_users_to_team/index.js
new file mode 100644
index 000000000..d38aeb4e5
--- /dev/null
+++ b/webapp/components/add_users_to_team/index.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {bindActionCreators} from 'redux';
+import {getProfilesNotInTeam} from 'mattermost-redux/actions/users';
+
+import AddUsersToTeam from './add_users_to_team.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ getProfilesNotInTeam
+ }, dispatch)
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(AddUsersToTeam);
diff --git a/webapp/components/admin_console/system_users/system_users.jsx b/webapp/components/admin_console/system_users/system_users.jsx
index 0b967dead..7bc4b81ed 100644
--- a/webapp/components/admin_console/system_users/system_users.jsx
+++ b/webapp/components/admin_console/system_users/system_users.jsx
@@ -23,6 +23,9 @@ import * as Utils from 'utils/utils.jsx';
import SystemUsersList from './system_users_list.jsx';
+import store from 'stores/redux_store.jsx';
+import {searchProfiles, searchProfilesInTeam} from 'mattermost-redux/selectors/entities/users';
+
const ALL_USERS = '';
const NO_TEAM = 'no_team';
@@ -120,25 +123,18 @@ export default class SystemUsers extends React.Component {
updateUsersFromStore(teamId = this.state.teamId, term = this.state.term) {
if (term) {
- if (teamId === this.state.teamId) {
- // Search results aren't in the store, so manually update the users in them
- const users = [...this.state.users];
-
- for (let i = 0; i < users.length; i++) {
- const user = users[i];
-
- if (UserStore.hasProfile(user.id)) {
- users[i] = UserStore.getProfile(user.id);
- }
- }
-
- this.setState({
- users
- });
+ let users;
+ if (teamId) {
+ users = searchProfilesInTeam(store.getState(), teamId, term);
} else {
- this.doSearch(teamId, term, true);
+ users = searchProfiles(store.getState(), term);
}
+ if (users.length === 0 && UserStore.hasProfile(term)) {
+ users = [UserStore.getProfile(term)];
+ }
+
+ this.setState({users});
return;
}
@@ -179,11 +175,11 @@ export default class SystemUsers extends React.Component {
// Paging isn't supported while searching
if (this.state.teamId === ALL_USERS) {
- loadProfiles((page + 1) * USERS_PER_PAGE, USERS_PER_PAGE, this.loadComplete);
+ loadProfiles(page, USERS_PER_PAGE, this.loadComplete);
} else if (this.state.teamId === NO_TEAM) {
loadProfilesWithoutTeam(page + 1, USERS_PER_PAGE, this.loadComplete);
} else {
- loadProfilesAndTeamMembers((page + 1) * USERS_PER_PAGE, USERS_PER_PAGE, this.state.teamId, this.loadComplete);
+ loadProfilesAndTeamMembers(page + 1, USERS_PER_PAGE, this.state.teamId, this.loadComplete);
}
}
@@ -204,11 +200,9 @@ export default class SystemUsers extends React.Component {
doSearch(teamId, term, now = false) {
clearTimeout(this.searchTimeoutId);
+ this.term = term;
- this.setState({
- loading: true,
- users: []
- });
+ this.setState({loading: true});
const options = {
[UserSearchOptions.ALLOW_INACTIVE]: true
@@ -217,74 +211,45 @@ export default class SystemUsers extends React.Component {
options[UserSearchOptions.WITHOUT_TEAM] = true;
}
- const searchTimeoutId = setTimeout(
+ this.searchTimeoutId = setTimeout(
() => {
searchUsers(
term,
teamId,
options,
(users) => {
- if (searchTimeoutId !== this.searchTimeoutId) {
- return;
- }
-
- if (users.length > 0) {
- this.setState({
- loading: false,
- users
- });
- } else if (term.length === USER_ID_LENGTH) {
+ if (users.length === 0 && term.length === USER_ID_LENGTH) {
// This term didn't match any users name, but it does look like it might be a user's ID
- this.getUserById(term, searchTimeoutId);
+ this.getUserById(term);
} else {
- this.setState({
- loading: false
- });
+ this.setState({loading: false});
}
},
() => {
- this.setState({
- loading: false
- });
+ this.setState({loading: false});
}
);
},
now ? 0 : Constants.SEARCH_TIMEOUT_MILLISECONDS
);
-
- this.searchTimeoutId = searchTimeoutId;
}
- getUserById(id, searchTimeoutId) {
+ getUserById(id) {
if (UserStore.hasProfile(id)) {
- this.setState({
- loading: false,
- users: [UserStore.getProfile(id)]
- });
-
+ this.setState({loading: false});
return;
}
getUser(
id,
- (user) => {
- if (searchTimeoutId !== this.searchTimeoutId) {
- return;
- }
-
+ () => {
this.setState({
- loading: false,
- users: [user]
+ loading: false
});
},
() => {
- if (searchTimeoutId !== this.searchTimeoutId) {
- return;
- }
-
this.setState({
- loading: false,
- users: []
+ loading: false
});
}
);
diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx
index 5ebe1b745..82864d48c 100644
--- a/webapp/components/channel_header.jsx
+++ b/webapp/components/channel_header.jsx
@@ -5,11 +5,11 @@ import $ from 'jquery';
import 'bootstrap';
import NavbarSearchBox from './search_bar.jsx';
import MessageWrapper from './message_wrapper.jsx';
-import PopoverListMembers from './popover_list_members.jsx';
+import PopoverListMembers from 'components/popover_list_members';
import EditChannelHeaderModal from './edit_channel_header_modal.jsx';
import EditChannelPurposeModal from './edit_channel_purpose_modal.jsx';
import ChannelInfoModal from './channel_info_modal.jsx';
-import ChannelInviteModal from './channel_invite_modal.jsx';
+import ChannelInviteModal from 'components/channel_invite_modal';
import ChannelMembersModal from './channel_members_modal.jsx';
import ChannelNotificationsModal from './channel_notifications_modal.jsx';
import DeleteChannelModal from './delete_channel_modal.jsx';
diff --git a/webapp/components/channel_invite_modal.jsx b/webapp/components/channel_invite_modal/channel_invite_modal.jsx
index d41948a2b..847af16f6 100644
--- a/webapp/components/channel_invite_modal.jsx
+++ b/webapp/components/channel_invite_modal/channel_invite_modal.jsx
@@ -1,9 +1,9 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import ChannelInviteButton from './channel_invite_button.jsx';
+import ChannelInviteButton from 'components/channel_invite_button.jsx';
import SearchableUserList from 'components/searchable_user_list/searchable_user_list_container.jsx';
-import LoadingScreen from './loading_screen.jsx';
+import LoadingScreen from 'components/loading_screen.jsx';
import ChannelStore from 'stores/channel_store.jsx';
import UserStore from 'stores/user_store.jsx';
@@ -19,9 +19,20 @@ import React from 'react';
import {Modal} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
+import store from 'stores/redux_store.jsx';
+import {searchProfilesNotInCurrentChannel} from 'mattermost-redux/selectors/entities/users';
+
const USERS_PER_PAGE = 50;
export default class ChannelInviteModal extends React.Component {
+ static propTypes = {
+ onHide: React.PropTypes.func.isRequired,
+ channel: React.PropTypes.object.isRequired,
+ actions: React.PropTypes.shape({
+ getProfilesNotInChannel: React.PropTypes.func.isRequired
+ }).isRequired
+ }
+
constructor(props) {
super(props);
@@ -39,10 +50,9 @@ export default class ChannelInviteModal extends React.Component {
const teamStats = TeamStore.getCurrentStats();
this.state = {
- users: null,
+ users: UserStore.getProfileListNotInChannel(props.channel.id, true),
total: teamStats.active_member_count - channelStats.member_count,
show: true,
- search: false,
statusChange: false
};
}
@@ -53,7 +63,7 @@ export default class ChannelInviteModal extends React.Component {
UserStore.addNotInChannelChangeListener(this.onChange);
UserStore.addStatusesChangeListener(this.onStatusChange);
- AsyncClient.getProfilesNotInChannel(this.props.channel.id, 0);
+ this.props.actions.getProfilesNotInChannel(TeamStore.getCurrentId(), this.props.channel.id, 0);
AsyncClient.getTeamStats(TeamStore.getCurrentId());
}
@@ -64,17 +74,19 @@ export default class ChannelInviteModal extends React.Component {
UserStore.removeStatusesChangeListener(this.onStatusChange);
}
- onChange(force) {
- if (this.state.search && !force) {
- this.search(this.term);
- return;
+ onChange() {
+ let users;
+ if (this.term) {
+ users = searchProfilesNotInCurrentChannel(store.getState(), this.term, true);
+ } else {
+ users = UserStore.getProfileListNotInChannel(this.props.channel.id, true);
}
const channelStats = ChannelStore.getStats(this.props.channel.id);
const teamStats = TeamStore.getCurrentStats();
this.setState({
- users: UserStore.getProfileListNotInChannel(this.props.channel.id, true),
+ users,
total: teamStats.active_member_count - channelStats.member_count
});
}
@@ -103,40 +115,24 @@ export default class ChannelInviteModal extends React.Component {
}
nextPage(page) {
- AsyncClient.getProfilesNotInChannel(this.props.channel.id, (page + 1) * USERS_PER_PAGE, USERS_PER_PAGE);
+ this.props.actions.getProfilesNotInChannel(TeamStore.getCurrentId(), this.props.channel.id, (page + 1) * USERS_PER_PAGE, USERS_PER_PAGE);
}
search(term) {
clearTimeout(this.searchTimeoutId);
-
this.term = term;
if (term === '') {
- this.onChange(true);
- this.setState({search: false});
- this.searchTimeoutId = '';
+ this.onChange();
return;
}
- const searchTimeoutId = setTimeout(
+ this.searchTimeoutId = setTimeout(
() => {
- searchUsers(
- term,
- TeamStore.getCurrentId(),
- {not_in_channel_id: this.props.channel.id},
- (users) => {
- if (searchTimeoutId !== this.searchTimeoutId) {
- return;
- }
-
- this.setState({search: true, users});
- }
- );
+ searchUsers(term, TeamStore.getCurrentId(), {not_in_channel_id: this.props.channel.id});
},
Constants.SEARCH_TIMEOUT_MILLISECONDS
);
-
- this.searchTimeoutId = searchTimeoutId;
}
render() {
@@ -190,8 +186,3 @@ export default class ChannelInviteModal extends React.Component {
);
}
}
-
-ChannelInviteModal.propTypes = {
- onHide: React.PropTypes.func.isRequired,
- channel: React.PropTypes.object.isRequired
-};
diff --git a/webapp/components/channel_invite_modal/index.js b/webapp/components/channel_invite_modal/index.js
new file mode 100644
index 000000000..c8bdb54f5
--- /dev/null
+++ b/webapp/components/channel_invite_modal/index.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {bindActionCreators} from 'redux';
+import {getProfilesNotInChannel} from 'mattermost-redux/actions/users';
+
+import ChannelInviteModal from './channel_invite_modal.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ getProfilesNotInChannel
+ }, dispatch)
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ChannelInviteModal);
diff --git a/webapp/components/login/login_controller.jsx b/webapp/components/login/login_controller.jsx
index 482135a5e..34fdc536c 100644
--- a/webapp/components/login/login_controller.jsx
+++ b/webapp/components/login/login_controller.jsx
@@ -209,19 +209,15 @@ export default class LoginController extends React.Component {
}
finishSignin(team) {
- GlobalActions.emitInitialLoad(
- () => {
- const query = this.props.location.query;
- GlobalActions.loadDefaultLocale();
- if (query.redirect_to) {
- browserHistory.push(query.redirect_to);
- } else if (team) {
- browserHistory.push(`/${team.name}`);
- } else {
- GlobalActions.redirectUserToDefaultTeam();
- }
- }
- );
+ const query = this.props.location.query;
+ GlobalActions.loadDefaultLocale();
+ if (query.redirect_to) {
+ browserHistory.push(query.redirect_to);
+ } else if (team) {
+ browserHistory.push(`/${team.name}`);
+ } else {
+ GlobalActions.redirectUserToDefaultTeam();
+ }
}
handleLoginIdChange(e) {
diff --git a/webapp/components/member_list_channel.jsx b/webapp/components/member_list_channel.jsx
index e9eef9fb8..df000c132 100644
--- a/webapp/components/member_list_channel.jsx
+++ b/webapp/components/member_list_channel.jsx
@@ -17,6 +17,9 @@ import * as UserAgent from 'utils/user_agent.jsx';
import React from 'react';
+import store from 'stores/redux_store.jsx';
+import {searchProfilesInCurrentChannel} from 'mattermost-redux/selectors/entities/users';
+
const USERS_PER_PAGE = 50;
export default class MemberListChannel extends React.Component {
@@ -29,6 +32,7 @@ export default class MemberListChannel extends React.Component {
this.loadComplete = this.loadComplete.bind(this);
this.searchTimeoutId = 0;
+ this.term = '';
const stats = ChannelStore.getCurrentStats();
@@ -37,8 +41,6 @@ export default class MemberListChannel extends React.Component {
teamMembers: Object.assign({}, TeamStore.getMembersInTeam()),
channelMembers: Object.assign({}, ChannelStore.getMembersInChannel()),
total: stats.member_count,
- search: false,
- term: '',
loading: true
};
}
@@ -66,16 +68,16 @@ export default class MemberListChannel extends React.Component {
this.setState({loading: false});
}
- onChange(force) {
- if (this.state.search && !force) {
- return;
- } else if (this.state.search) {
- this.search(this.state.term);
- return;
+ onChange() {
+ let users;
+ if (this.term) {
+ users = searchProfilesInCurrentChannel(store.getState(), this.term);
+ } else {
+ users = UserStore.getProfileListInChannel();
}
this.setState({
- users: UserStore.getProfileListInChannel(),
+ users,
teamMembers: Object.assign({}, TeamStore.getMembersInTeam()),
channelMembers: Object.assign({}, ChannelStore.getMembersInChannel())
});
@@ -87,43 +89,30 @@ export default class MemberListChannel extends React.Component {
}
nextPage(page) {
- loadProfilesAndTeamMembersAndChannelMembers((page + 1) * USERS_PER_PAGE, USERS_PER_PAGE);
+ loadProfilesAndTeamMembersAndChannelMembers(page + 1, USERS_PER_PAGE);
}
search(term) {
clearTimeout(this.searchTimeoutId);
+ this.term = term;
if (term === '') {
- this.setState({
- search: false,
- term,
- users: UserStore.getProfileListInChannel(),
- teamMembers: Object.assign([], TeamStore.getMembersInTeam()),
- channelMembers: Object.assign([], ChannelStore.getMembersInChannel())
- });
+ this.setState({loading: false});
this.searchTimeoutId = '';
+ this.onChange();
return;
}
const searchTimeoutId = setTimeout(
() => {
- searchUsers(
- term,
- TeamStore.getCurrentId(),
- {},
+ searchUsers(term, TeamStore.getCurrentId(), {},
(users) => {
if (searchTimeoutId !== this.searchTimeoutId) {
return;
}
- this.setState({
- loading: true,
- search: true,
- users,
- term,
- teamMembers: Object.assign([], TeamStore.getMembersInTeam()),
- channelMembers: Object.assign([], ChannelStore.getMembersInChannel())
- });
+ this.setState({loading: true});
+
loadTeamMembersAndChannelMembersForProfilesList(users, TeamStore.getCurrentId(), ChannelStore.getCurrentId(), this.loadComplete);
}
);
diff --git a/webapp/components/member_list_team.jsx b/webapp/components/member_list_team.jsx
index 0aa1e6e57..212536dc8 100644
--- a/webapp/components/member_list_team.jsx
+++ b/webapp/components/member_list_team.jsx
@@ -2,7 +2,7 @@
// See License.txt for license information.
import SearchableUserList from 'components/searchable_user_list/searchable_user_list_container.jsx';
-import TeamMembersDropdown from 'components/team_members_dropdown.jsx';
+import TeamMembersDropdown from 'components/team_members_dropdown';
import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
@@ -16,6 +16,9 @@ import * as UserAgent from 'utils/user_agent.jsx';
import React from 'react';
+import store from 'stores/redux_store.jsx';
+import {searchProfilesInCurrentTeam} from 'mattermost-redux/selectors/entities/users';
+
const USERS_PER_PAGE = 50;
export default class MemberListTeam extends React.Component {
@@ -29,6 +32,7 @@ export default class MemberListTeam extends React.Component {
this.loadComplete = this.loadComplete.bind(this);
this.searchTimeoutId = 0;
+ this.term = '';
const stats = TeamStore.getCurrentStats();
@@ -36,8 +40,6 @@ export default class MemberListTeam extends React.Component {
users: UserStore.getProfileListInTeam(),
teamMembers: Object.assign([], TeamStore.getMembersInTeam()),
total: stats.total_member_count,
- search: false,
- term: '',
loading: true
};
}
@@ -67,15 +69,15 @@ export default class MemberListTeam extends React.Component {
this.onChange(true);
}
- onChange(force) {
- if (this.state.search && !force) {
- return;
- } else if (this.state.search) {
- this.search(this.state.term);
- return;
+ onChange() {
+ let users;
+ if (this.term) {
+ users = searchProfilesInCurrentTeam(store.getState(), this.term);
+ } else {
+ users = UserStore.getProfileListInTeam();
}
- this.setState({users: UserStore.getProfileListInTeam(), teamMembers: Object.assign([], TeamStore.getMembersInTeam())});
+ this.setState({users, teamMembers: Object.assign([], TeamStore.getMembersInTeam())});
}
onStatsChange() {
@@ -84,15 +86,17 @@ export default class MemberListTeam extends React.Component {
}
nextPage(page) {
- loadProfilesAndTeamMembers((page + 1) * USERS_PER_PAGE, USERS_PER_PAGE);
+ loadProfilesAndTeamMembers(page, USERS_PER_PAGE);
}
search(term) {
clearTimeout(this.searchTimeoutId);
+ this.term = term;
if (term === '') {
- this.setState({search: false, term, users: UserStore.getProfileListInTeam(), teamMembers: Object.assign([], TeamStore.getMembersInTeam())});
+ this.setState({loading: false});
this.searchTimeoutId = '';
+ this.onChange();
return;
}
@@ -106,7 +110,7 @@ export default class MemberListTeam extends React.Component {
if (searchTimeoutId !== this.searchTimeoutId) {
return;
}
- this.setState({loading: true, search: true, users, term, teamMembers: Object.assign([], TeamStore.getMembersInTeam())});
+ this.setState({loading: true});
loadTeamMembersForProfilesList(users, TeamStore.getCurrentId(), this.loadComplete);
}
);
diff --git a/webapp/components/more_direct_channels/index.js b/webapp/components/more_direct_channels/index.js
new file mode 100644
index 000000000..a56f45886
--- /dev/null
+++ b/webapp/components/more_direct_channels/index.js
@@ -0,0 +1,25 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {bindActionCreators} from 'redux';
+import {getProfiles, getProfilesInTeam} from 'mattermost-redux/actions/users';
+
+import MoreDirectChannels from './more_direct_channels.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ getProfiles,
+ getProfilesInTeam
+ }, dispatch)
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(MoreDirectChannels);
diff --git a/webapp/components/more_direct_channels.jsx b/webapp/components/more_direct_channels/more_direct_channels.jsx
index c8a0d22ee..50e2c4e48 100644
--- a/webapp/components/more_direct_channels.jsx
+++ b/webapp/components/more_direct_channels/more_direct_channels.jsx
@@ -10,7 +10,6 @@ import {openDirectChannelToUser, openGroupChannelToUsers} from 'actions/channel_
import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
-import * as AsyncClient from 'utils/async_client.jsx';
import Constants from 'utils/constants.jsx';
import {displayUsernameForUser} from 'utils/utils.jsx';
import Client from 'client/web_client.jsx';
@@ -20,10 +19,22 @@ import {Modal} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import {browserHistory} from 'react-router/es6';
+import store from 'stores/redux_store.jsx';
+import {searchProfiles, searchProfilesInCurrentTeam} from 'mattermost-redux/selectors/entities/users';
+
const USERS_PER_PAGE = 50;
const MAX_SELECTABLE_VALUES = Constants.MAX_USERS_IN_GM - 1;
export default class MoreDirectChannels extends React.Component {
+ static propTypes = {
+ startingUsers: React.PropTypes.arrayOf(React.PropTypes.object),
+ onModalDismissed: React.PropTypes.func,
+ actions: React.PropTypes.shape({
+ getProfiles: React.PropTypes.func.isRequired,
+ getProfilesInTeam: React.PropTypes.func.isRequired
+ }).isRequired
+ }
+
constructor(props) {
super(props);
@@ -36,6 +47,7 @@ export default class MoreDirectChannels extends React.Component {
this.addValue = this.addValue.bind(this);
this.searchTimeoutId = 0;
+ this.term = '';
this.listType = global.window.mm_config.RestrictDirectMessage;
const values = [];
@@ -63,9 +75,9 @@ export default class MoreDirectChannels extends React.Component {
UserStore.addStatusesChangeListener(this.onChange);
if (this.listType === 'any') {
- AsyncClient.getProfiles(0, USERS_PER_PAGE * 2);
+ this.props.actions.getProfiles(0, USERS_PER_PAGE * 2);
} else {
- AsyncClient.getProfilesInTeam(TeamStore.getCurrentId(), 0, USERS_PER_PAGE * 2);
+ this.props.actions.getProfilesInTeam(TeamStore.getCurrentId(), 0, USERS_PER_PAGE * 2);
}
}
@@ -134,13 +146,15 @@ export default class MoreDirectChannels extends React.Component {
this.setState({values});
}
- onChange(force) {
- if (this.state.search && !force) {
- return;
- }
-
+ onChange() {
let users;
- if (this.listType === 'any') {
+ if (this.term) {
+ if (this.listType === 'any') {
+ users = Object.assign([], searchProfiles(store.getState(), this.term, true));
+ } else {
+ users = Object.assign([], searchProfilesInCurrentTeam(store.getState(), this.term, true));
+ }
+ } else if (this.listType === 'any') {
users = Object.assign([], UserStore.getProfileList(true));
} else {
users = Object.assign([], UserStore.getProfileListInTeam(TeamStore.getCurrentId(), true));
@@ -160,17 +174,20 @@ export default class MoreDirectChannels extends React.Component {
handlePageChange(page, prevPage) {
if (page > prevPage) {
- AsyncClient.getProfiles((page + 1) * USERS_PER_PAGE, USERS_PER_PAGE);
+ if (this.listType === 'any') {
+ this.props.actions.getProfiles(page + 1, USERS_PER_PAGE);
+ } else {
+ this.props.actions.getProfilesInTeam(page + 1, USERS_PER_PAGE);
+ }
}
}
search(term) {
clearTimeout(this.searchTimeoutId);
+ this.term = term;
if (term === '') {
- this.onChange(true);
- this.setState({search: false});
- this.searchTimeoutId = '';
+ this.onChange();
return;
}
@@ -181,37 +198,12 @@ export default class MoreDirectChannels extends React.Component {
teamId = TeamStore.getCurrentId();
}
- const searchTimeoutId = setTimeout(
+ this.searchTimeoutId = setTimeout(
() => {
- searchUsers(
- term,
- teamId,
- {},
- (users) => {
- if (searchTimeoutId !== this.searchTimeoutId) {
- return;
- }
-
- let indexToDelete = -1;
- for (let i = 0; i < users.length; i++) {
- if (users[i].id === UserStore.getCurrentId()) {
- indexToDelete = i;
- }
- users[i].value = users[i].id;
- users[i].label = '@' + users[i].username;
- }
-
- if (indexToDelete !== -1) {
- users.splice(indexToDelete, 1);
- }
- this.setState({search: true, users});
- }
- );
+ searchUsers(term, teamId);
},
Constants.SEARCH_TIMEOUT_MILLISECONDS
);
-
- this.searchTimeoutId = searchTimeoutId;
}
handleDelete(values) {
@@ -334,8 +326,3 @@ export default class MoreDirectChannels extends React.Component {
);
}
}
-
-MoreDirectChannels.propTypes = {
- startingUsers: React.PropTypes.arrayOf(React.PropTypes.object),
- onModalDismissed: React.PropTypes.func
-};
diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx
index 22d2b8ae4..33df0b423 100644
--- a/webapp/components/navbar.jsx
+++ b/webapp/components/navbar.jsx
@@ -7,7 +7,7 @@ import EditChannelPurposeModal from './edit_channel_purpose_modal.jsx';
import MessageWrapper from './message_wrapper.jsx';
import NotifyCounts from './notify_counts.jsx';
import ChannelInfoModal from './channel_info_modal.jsx';
-import ChannelInviteModal from './channel_invite_modal.jsx';
+import ChannelInviteModal from 'components/channel_invite_modal';
import ChannelMembersModal from './channel_members_modal.jsx';
import ChannelNotificationsModal from './channel_notifications_modal.jsx';
import DeleteChannelModal from './delete_channel_modal.jsx';
diff --git a/webapp/components/popover_list_members/index.js b/webapp/components/popover_list_members/index.js
new file mode 100644
index 000000000..3e9087e0d
--- /dev/null
+++ b/webapp/components/popover_list_members/index.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {bindActionCreators} from 'redux';
+import {getProfilesInChannel} from 'mattermost-redux/actions/users';
+
+import PopoverListMembers from './popover_list_members.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ getProfilesInChannel
+ }, dispatch)
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(PopoverListMembers);
diff --git a/webapp/components/popover_list_members.jsx b/webapp/components/popover_list_members/popover_list_members.jsx
index 3af53cb70..e435126ff 100644
--- a/webapp/components/popover_list_members.jsx
+++ b/webapp/components/popover_list_members/popover_list_members.jsx
@@ -7,13 +7,12 @@ import TeamStore from 'stores/team_store.jsx';
import UserStore from 'stores/user_store.jsx';
import ChannelStore from 'stores/channel_store.jsx';
-import TeamMembersModal from './team_members_modal.jsx';
-import ChannelMembersModal from './channel_members_modal.jsx';
-import ChannelInviteModal from './channel_invite_modal.jsx';
+import TeamMembersModal from 'components/team_members_modal.jsx';
+import ChannelMembersModal from 'components/channel_members_modal.jsx';
+import ChannelInviteModal from 'components/channel_invite_modal';
import {openDirectChannelToUser} from 'actions/channel_actions.jsx';
-import * as AsyncClient from 'utils/async_client.jsx';
import Client from 'client/web_client.jsx';
import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
@@ -26,6 +25,15 @@ import {FormattedMessage} from 'react-intl';
import {browserHistory} from 'react-router/es6';
export default class PopoverListMembers extends React.Component {
+ static propTypes = {
+ channel: React.PropTypes.object.isRequired,
+ members: React.PropTypes.array.isRequired,
+ memberCount: React.PropTypes.number,
+ actions: React.PropTypes.shape({
+ getProfilesInChannel: React.PropTypes.func.isRequired
+ }).isRequired
+ }
+
constructor(props) {
super(props);
@@ -239,7 +247,7 @@ export default class PopoverListMembers extends React.Component {
ref='member_popover_target'
onClick={(e) => {
this.setState({popoverTarget: e.target, showPopover: !this.state.showPopover});
- AsyncClient.getProfilesInChannel(this.props.channel.id, 0);
+ this.props.actions.getProfilesInChannel(this.props.channel.id, 0);
}}
>
{countText}
@@ -272,8 +280,3 @@ export default class PopoverListMembers extends React.Component {
}
}
-PopoverListMembers.propTypes = {
- channel: React.PropTypes.object.isRequired,
- members: React.PropTypes.array.isRequired,
- memberCount: React.PropTypes.number
-};
diff --git a/webapp/components/root.jsx b/webapp/components/root.jsx
index b49b4d509..6907e84e4 100644
--- a/webapp/components/root.jsx
+++ b/webapp/components/root.jsx
@@ -136,6 +136,7 @@ export default class Root extends React.Component {
);
}
}
+
Root.defaultProps = {
};
diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx
index 72dcac992..8667802cc 100644
--- a/webapp/components/sidebar.jsx
+++ b/webapp/components/sidebar.jsx
@@ -4,7 +4,7 @@
import $ from 'jquery';
import ReactDOM from 'react-dom';
import NewChannelFlow from './new_channel_flow.jsx';
-import MoreDirectChannels from './more_direct_channels.jsx';
+import MoreDirectChannels from 'components/more_direct_channels';
import MoreChannels from 'components/more_channels.jsx';
import SidebarHeader from './sidebar_header.jsx';
import UnreadChannelIndicator from './unread_channel_indicator.jsx';
diff --git a/webapp/components/sidebar_header_dropdown.jsx b/webapp/components/sidebar_header_dropdown.jsx
index 728017b27..256019b64 100644
--- a/webapp/components/sidebar_header_dropdown.jsx
+++ b/webapp/components/sidebar_header_dropdown.jsx
@@ -14,7 +14,7 @@ import AboutBuildModal from './about_build_modal.jsx';
import SidebarHeaderDropdownButton from './sidebar_header_dropdown_button.jsx';
import TeamMembersModal from './team_members_modal.jsx';
import UserSettingsModal from './user_settings/user_settings_modal.jsx';
-import AddUsersToTeam from './add_users_to_team.jsx';
+import AddUsersToTeam from 'components/add_users_to_team';
import {Constants, WebrtcActionTypes} from 'utils/constants.jsx';
diff --git a/webapp/components/sidebar_right_menu.jsx b/webapp/components/sidebar_right_menu.jsx
index 784f06eac..aac7d58cc 100644
--- a/webapp/components/sidebar_right_menu.jsx
+++ b/webapp/components/sidebar_right_menu.jsx
@@ -6,7 +6,7 @@ import TeamMembersModal from './team_members_modal.jsx';
import ToggleModalButton from './toggle_modal_button.jsx';
import UserSettingsModal from './user_settings/user_settings_modal.jsx';
import AboutBuildModal from './about_build_modal.jsx';
-import AddUsersToTeam from './add_users_to_team.jsx';
+import AddUsersToTeam from 'components/add_users_to_team';
import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
diff --git a/webapp/components/signup/components/signup_email.jsx b/webapp/components/signup/components/signup_email.jsx
index c33fb45e0..976b0648b 100644
--- a/webapp/components/signup/components/signup_email.jsx
+++ b/webapp/components/signup/components/signup_email.jsx
@@ -8,7 +8,7 @@ import {trackEvent} from 'actions/diagnostics_actions.jsx';
import BrowserStore from 'stores/browser_store.jsx';
import {getInviteInfo} from 'actions/team_actions.jsx';
-import {loginById, createUserWithInvite} from 'actions/user_actions.jsx';
+import {loadMe, loginById, createUserWithInvite} from 'actions/user_actions.jsx';
import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
@@ -108,7 +108,7 @@ export default class SignupEmail extends React.Component {
}
finishSignup() {
- GlobalActions.emitInitialLoad(
+ loadMe(
() => {
const query = this.props.location.query;
GlobalActions.loadDefaultLocale();
@@ -132,7 +132,7 @@ export default class SignupEmail extends React.Component {
BrowserStore.setGlobalItem(this.state.hash, JSON.stringify({usedBefore: true}));
}
- GlobalActions.emitInitialLoad(
+ loadMe(
() => {
const query = this.props.location.query;
if (query.redirect_to) {
diff --git a/webapp/components/signup/components/signup_ldap.jsx b/webapp/components/signup/components/signup_ldap.jsx
index 80fac3ecc..a101c248f 100644
--- a/webapp/components/signup/components/signup_ldap.jsx
+++ b/webapp/components/signup/components/signup_ldap.jsx
@@ -5,7 +5,7 @@ import FormError from 'components/form_error.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
import {addUserToTeamFromInvite} from 'actions/team_actions.jsx';
-import {webLoginByLdap} from 'actions/user_actions.jsx';
+import {loadMe, webLoginByLdap} from 'actions/user_actions.jsx';
import {trackEvent} from 'actions/diagnostics_actions.jsx';
import * as Utils from 'utils/utils.jsx';
@@ -97,7 +97,7 @@ export default class SignupLdap extends React.Component {
}
finishSignup() {
- GlobalActions.emitInitialLoad(
+ loadMe(
() => {
const query = this.props.location.query;
GlobalActions.loadDefaultLocale();
diff --git a/webapp/components/signup/signup_controller.jsx b/webapp/components/signup/signup_controller.jsx
index 701fe1d30..0c969e5ed 100644
--- a/webapp/components/signup/signup_controller.jsx
+++ b/webapp/components/signup/signup_controller.jsx
@@ -13,6 +13,7 @@ import * as AsyncClient from 'utils/async_client.jsx';
import Client from 'client/web_client.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
import {addUserToTeamFromInvite, getInviteInfo} from 'actions/team_actions.jsx';
+import {loadMe} from 'actions/user_actions.jsx';
import logoImage from 'images/logo.png';
import ErrorBar from 'components/error_bar.jsx';
@@ -74,7 +75,7 @@ export default class SignupController extends React.Component {
hash,
inviteId,
(team) => {
- GlobalActions.emitInitialLoad(
+ loadMe(
() => {
browserHistory.push('/' + team.name + '/channels/town-square');
}
diff --git a/webapp/components/suggestion/at_mention_provider.jsx b/webapp/components/suggestion/at_mention_provider.jsx
index ddf9d46e7..4d55e9db6 100644
--- a/webapp/components/suggestion/at_mention_provider.jsx
+++ b/webapp/components/suggestion/at_mention_provider.jsx
@@ -127,14 +127,14 @@ export default class AtMentionProvider extends Provider {
return;
}
- const members = data.in_channel;
+ const members = Object.assign([], data.users);
for (const id of Object.keys(members)) {
- members[id].type = Constants.MENTION_MEMBERS;
+ members[id] = {...members[id], type: Constants.MENTION_MEMBERS};
}
- const nonmembers = data.out_of_channel;
+ const nonmembers = data.out_of_channel || [];
for (const id of Object.keys(nonmembers)) {
- nonmembers[id].type = Constants.MENTION_NONMEMBERS;
+ nonmembers[id] = {...nonmembers[id], type: Constants.MENTION_NONMEMBERS};
}
let specialMentions = [];
diff --git a/webapp/components/suggestion/search_user_provider.jsx b/webapp/components/suggestion/search_user_provider.jsx
index 6fcc7f7e9..d55f35c87 100644
--- a/webapp/components/suggestion/search_user_provider.jsx
+++ b/webapp/components/suggestion/search_user_provider.jsx
@@ -72,7 +72,7 @@ export default class SearchUserProvider extends Provider {
return;
}
- const users = data.in_team;
+ const users = Object.assign([], data.users);
const mentions = users.map((user) => user.username);
AppDispatcher.handleServerAction({
diff --git a/webapp/components/suggestion/switch_channel_provider.jsx b/webapp/components/suggestion/switch_channel_provider.jsx
index 3d295951c..67cda61ea 100644
--- a/webapp/components/suggestion/switch_channel_provider.jsx
+++ b/webapp/components/suggestion/switch_channel_provider.jsx
@@ -67,7 +67,9 @@ export default class SwitchChannelProvider extends Provider {
autocompleteUsers(
channelPrefix,
- (users) => {
+ (data) => {
+ const users = Object.assign([], data.users);
+
if (this.shouldCancelDispatch(channelPrefix)) {
return;
}
diff --git a/webapp/components/team_members_dropdown/index.js b/webapp/components/team_members_dropdown/index.js
new file mode 100644
index 000000000..54e002a6e
--- /dev/null
+++ b/webapp/components/team_members_dropdown/index.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {bindActionCreators} from 'redux';
+import {getUser} from 'mattermost-redux/actions/users';
+
+import TeamMembersDropdown from './team_members_dropdown.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ getUser
+ }, dispatch)
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(TeamMembersDropdown);
diff --git a/webapp/components/team_members_dropdown.jsx b/webapp/components/team_members_dropdown/team_members_dropdown.jsx
index 7c2b763c3..704a60dae 100644
--- a/webapp/components/team_members_dropdown.jsx
+++ b/webapp/components/team_members_dropdown/team_members_dropdown.jsx
@@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import ConfirmModal from './confirm_modal.jsx';
+import ConfirmModal from 'components/confirm_modal.jsx';
import TeamStore from 'stores/team_store.jsx';
import UserStore from 'stores/user_store.jsx';
@@ -18,6 +18,14 @@ import {FormattedMessage} from 'react-intl';
import {browserHistory} from 'react-router/es6';
export default class TeamMembersDropdown extends React.Component {
+ static propTypes = {
+ user: React.PropTypes.object.isRequired,
+ teamMember: React.PropTypes.object.isRequired,
+ actions: React.PropTypes.shape({
+ getUser: React.PropTypes.func.isRequired
+ }).isRequired
+ }
+
constructor(props) {
super(props);
@@ -48,7 +56,7 @@ export default class TeamMembersDropdown extends React.Component {
this.props.user.id,
'team_user',
() => {
- AsyncClient.getUser(this.props.user.id);
+ this.props.actions.getUser(this.props.user.id);
if (this.props.user.id === me.id) {
loadMyTeamMembers();
@@ -110,7 +118,7 @@ export default class TeamMembersDropdown extends React.Component {
this.props.user.id,
'team_user team_admin',
() => {
- AsyncClient.getUser(this.props.user.id);
+ this.props.actions.getUser(this.props.user.id);
},
(err) => {
this.setState({serverError: err.message});
@@ -145,7 +153,7 @@ export default class TeamMembersDropdown extends React.Component {
this.props.user.id,
this.state.newRole,
() => {
- AsyncClient.getUser(this.props.user.id);
+ this.props.actions.getUser(this.props.user.id);
const teamUrl = TeamStore.getCurrentTeamUrl();
if (teamUrl) {
@@ -385,8 +393,3 @@ export default class TeamMembersDropdown extends React.Component {
);
}
}
-
-TeamMembersDropdown.propTypes = {
- user: React.PropTypes.object.isRequired,
- teamMember: React.PropTypes.object.isRequired
-};
diff --git a/webapp/components/user_settings/user_settings.jsx b/webapp/components/user_settings/user_settings.jsx
index d9d5423fe..b01274b32 100644
--- a/webapp/components/user_settings/user_settings.jsx
+++ b/webapp/components/user_settings/user_settings.jsx
@@ -4,8 +4,8 @@
import UserStore from 'stores/user_store.jsx';
import * as utils from 'utils/utils.jsx';
import NotificationsTab from './user_settings_notifications.jsx';
-import SecurityTab from './user_settings_security.jsx';
-import GeneralTab from './user_settings_general.jsx';
+import SecurityTab from './user_settings_security';
+import GeneralTab from './user_settings_general';
import DisplayTab from './user_settings_display.jsx';
import AdvancedTab from './user_settings_advanced.jsx';
diff --git a/webapp/components/user_settings/user_settings_general/index.js b/webapp/components/user_settings/user_settings_general/index.js
new file mode 100644
index 000000000..90fd58bf2
--- /dev/null
+++ b/webapp/components/user_settings/user_settings_general/index.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {bindActionCreators} from 'redux';
+import {getMe} from 'mattermost-redux/actions/users';
+
+import UserSettingsGeneralTab from './user_settings_general.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ getMe
+ }, dispatch)
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(UserSettingsGeneralTab);
diff --git a/webapp/components/user_settings/user_settings_general.jsx b/webapp/components/user_settings/user_settings_general/user_settings_general.jsx
index ce4349519..79132d929 100644
--- a/webapp/components/user_settings/user_settings_general.jsx
+++ b/webapp/components/user_settings/user_settings_general/user_settings_general.jsx
@@ -2,16 +2,15 @@
// See License.txt for license information.
import $ from 'jquery';
-import SettingItemMin from '../setting_item_min.jsx';
-import SettingItemMax from '../setting_item_max.jsx';
-import SettingPicture from '../setting_picture.jsx';
+import SettingItemMin from 'components/setting_item_min.jsx';
+import SettingItemMax from 'components/setting_item_max.jsx';
+import SettingPicture from 'components/setting_picture.jsx';
import UserStore from 'stores/user_store.jsx';
import ErrorStore from 'stores/error_store.jsx';
import Client from 'client/web_client.jsx';
import Constants from 'utils/constants.jsx';
-import * as AsyncClient from 'utils/async_client.jsx';
import * as Utils from 'utils/utils.jsx';
import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage, FormattedDate} from 'react-intl';
@@ -80,6 +79,19 @@ const holders = defineMessages({
import React from 'react';
class UserSettingsGeneralTab extends React.Component {
+ static propTypes = {
+ intl: intlShape.isRequired,
+ user: React.PropTypes.object.isRequired,
+ updateSection: React.PropTypes.func.isRequired,
+ updateTab: React.PropTypes.func.isRequired,
+ activeSection: React.PropTypes.string.isRequired,
+ closeModal: React.PropTypes.func.isRequired,
+ collapseModal: React.PropTypes.func.isRequired,
+ actions: React.PropTypes.shape({
+ getMe: React.PropTypes.func.isRequired
+ }).isRequired
+ }
+
constructor(props) {
super(props);
this.submitActive = false;
@@ -205,7 +217,7 @@ class UserSettingsGeneralTab extends React.Component {
updateUser(user, type,
() => {
this.updateSection('');
- AsyncClient.getMe();
+ this.props.actions.getMe();
const verificationEnabled = global.window.mm_config.SendEmailNotifications === 'true' && global.window.mm_config.RequireEmailVerification === 'true' && emailUpdated;
if (verificationEnabled) {
@@ -1194,14 +1206,4 @@ class UserSettingsGeneralTab extends React.Component {
}
}
-UserSettingsGeneralTab.propTypes = {
- intl: intlShape.isRequired,
- user: React.PropTypes.object.isRequired,
- updateSection: React.PropTypes.func.isRequired,
- updateTab: React.PropTypes.func.isRequired,
- activeSection: React.PropTypes.string.isRequired,
- closeModal: React.PropTypes.func.isRequired,
- collapseModal: React.PropTypes.func.isRequired
-};
-
export default injectIntl(UserSettingsGeneralTab);
diff --git a/webapp/components/user_settings/user_settings_security/index.js b/webapp/components/user_settings/user_settings_security/index.js
new file mode 100644
index 000000000..cdbabd055
--- /dev/null
+++ b/webapp/components/user_settings/user_settings_security/index.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import {connect} from 'react-redux';
+import {bindActionCreators} from 'redux';
+import {getMe} from 'mattermost-redux/actions/users';
+
+import SecurityTab from './user_settings_security.jsx';
+
+function mapStateToProps(state, ownProps) {
+ return {
+ ...ownProps
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ actions: bindActionCreators({
+ getMe
+ }, dispatch)
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(SecurityTab);
diff --git a/webapp/components/user_settings/user_settings_security.jsx b/webapp/components/user_settings/user_settings_security/user_settings_security.jsx
index ead579c19..d4a372454 100644
--- a/webapp/components/user_settings/user_settings_security.jsx
+++ b/webapp/components/user_settings/user_settings_security/user_settings_security.jsx
@@ -1,15 +1,14 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import SettingItemMin from '../setting_item_min.jsx';
-import SettingItemMax from '../setting_item_max.jsx';
-import AccessHistoryModal from '../access_history_modal.jsx';
-import ActivityLogModal from '../activity_log_modal.jsx';
-import ToggleModalButton from '../toggle_modal_button.jsx';
+import SettingItemMin from 'components/setting_item_min.jsx';
+import SettingItemMax from 'components/setting_item_max.jsx';
+import AccessHistoryModal from 'components/access_history_modal';
+import ActivityLogModal from 'components/activity_log_modal';
+import ToggleModalButton from 'components/toggle_modal_button.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
-import * as AsyncClient from 'utils/async_client.jsx';
import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
@@ -23,6 +22,19 @@ import {browserHistory, Link} from 'react-router/es6';
import icon50 from 'images/icon50x50.png';
export default class SecurityTab extends React.Component {
+ static propTypes = {
+ user: React.PropTypes.object,
+ activeSection: React.PropTypes.string,
+ updateSection: React.PropTypes.func,
+ updateTab: React.PropTypes.func,
+ closeModal: React.PropTypes.func.isRequired,
+ collapseModal: React.PropTypes.func.isRequired,
+ setEnforceFocus: React.PropTypes.func.isRequired,
+ actions: React.PropTypes.shape({
+ getMe: React.PropTypes.func.isRequired
+ }).isRequired
+ }
+
constructor(props) {
super(props);
@@ -98,7 +110,7 @@ export default class SecurityTab extends React.Component {
newPassword,
() => {
this.props.updateSection('');
- AsyncClient.getMe();
+ this.props.actions.getMe();
this.setState(this.getDefaultState());
},
(err) => {
@@ -1022,12 +1034,3 @@ SecurityTab.defaultProps = {
user: {},
activeSection: ''
};
-SecurityTab.propTypes = {
- user: React.PropTypes.object,
- activeSection: React.PropTypes.string,
- updateSection: React.PropTypes.func,
- updateTab: React.PropTypes.func,
- closeModal: React.PropTypes.func.isRequired,
- collapseModal: React.PropTypes.func.isRequired,
- setEnforceFocus: React.PropTypes.func.isRequired
-};