* 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
Этот коммит содержится в:
Joram Wilander
2017-04-25 11:46:02 -04:00
коммит произвёл Christopher Speller
родитель cc07c00507
Коммит 6c4c706313
57 изменённых файлов: 1148 добавлений и 1454 удалений

Просмотреть файл

@@ -5,21 +5,12 @@ import Client from 'client/web_client.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
import {browserHistory} from 'react-router/es6';
export function revokeSession(altId, success, error) {
Client.revokeSession(altId,
() => {
AsyncClient.getSessions();
if (success) {
success();
}
},
(err) => {
if (error) {
error(err);
}
}
);
}
// Redux actions
import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
import {getUser} from 'mattermost-redux/actions/users';
export function saveConfig(config, success, error) {
Client.saveConfig(
@@ -57,7 +48,7 @@ export function adminResetMfa(userId, success, error) {
Client.adminResetMfa(
userId,
() => {
AsyncClient.getUser(userId);
getUser(userId)(dispatch, getState);
if (success) {
success();

Просмотреть файл

@@ -10,6 +10,12 @@ import Client from 'client/web_client.jsx';
import {ActionTypes} from 'utils/constants.jsx';
// Redux actions
import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
import {getProfilesByIds} from 'mattermost-redux/actions/users';
export function loadEmoji(getProfiles = true) {
Client.listEmoji(
(data) => {
@@ -42,5 +48,5 @@ function loadProfilesForEmoji(emojiList) {
return;
}
AsyncClient.getProfilesByIds(list);
getProfilesByIds(list)(dispatch, getState);
}

Просмотреть файл

@@ -9,7 +9,6 @@ import UserStore from 'stores/user_store.jsx';
import BrowserStore from 'stores/browser_store.jsx';
import ErrorStore from 'stores/error_store.jsx';
import TeamStore from 'stores/team_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import SearchStore from 'stores/search_store.jsx';
import {handleNewPost, loadPosts, loadPostsBefore, loadPostsAfter} from 'actions/post_actions.jsx';
@@ -32,6 +31,12 @@ import en from 'i18n/en.json';
import * as I18n from 'i18n/i18n.jsx';
import {browserHistory} from 'react-router/es6';
// Redux actions
import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
import {ChannelTypes} from 'mattermost-redux/action_types';
export function emitChannelClickEvent(channel) {
function userVisitedFakeChannel(chan, success, fail) {
const otherUserId = Utils.getUserIdFromChannelName(chan);
@@ -77,6 +82,11 @@ export function emitChannelClickEvent(channel) {
channelMember,
prev: oldChannelId
});
dispatch({
type: ChannelTypes.SELECT_CHANNEL,
data: chan.id
}, getState);
}
if (channel.fake) {
@@ -94,85 +104,6 @@ export function emitChannelClickEvent(channel) {
}
}
export function emitInitialLoad(callback) {
Client.getInitialLoad(
(data) => {
global.window.mm_config = data.client_cfg;
global.window.mm_license = data.license_cfg;
if (global.window && global.window.analytics) {
global.window.analytics.identify(global.window.mm_config.DiagnosticId, {}, {
context: {
ip: '0.0.0.0'
},
page: {
path: '',
referrer: '',
search: '',
title: '',
url: ''
},
anonymousId: '00000000000000000000000000'
});
}
UserStore.setNoAccounts(data.no_accounts);
if (data.user && data.user.id) {
global.window.mm_user = data.user;
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_ME,
me: data.user
});
}
if (data.preferences) {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_PREFERENCES,
preferences: data.preferences
});
}
if (data.teams) {
var teams = {};
data.teams.forEach((team) => {
teams[team.id] = team;
});
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_ALL_TEAMS,
teams
});
}
if (data.team_members) {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_MY_TEAM_MEMBERS,
team_members: data.team_members
});
}
if (data.direct_profiles) {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_DIRECT_PROFILES,
profiles: data.direct_profiles
});
}
if (callback) {
callback();
}
},
(err) => {
AsyncClient.dispatchError(err, 'getInitialLoad');
if (callback) {
callback();
}
}
);
}
export function doFocusPost(channelId, postId, data) {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_FOCUSED_POST,
@@ -536,12 +467,11 @@ export function emitUserLoggedOutEvent(redirectTo = '/', shouldSignalLogout = tr
export function clientLogout(redirectTo = '/') {
BrowserStore.clear();
ErrorStore.clearLastError();
PreferenceStore.clear();
UserStore.clear();
TeamStore.clear();
ChannelStore.clear();
stopPeriodicStatusUpdates();
WebsocketActions.close();
localStorage.removeItem('currentUserId');
window.location.href = redirectTo;
}

Просмотреть файл

@@ -11,6 +11,12 @@ import Client from 'client/web_client.jsx';
import {ActionTypes} from 'utils/constants.jsx';
// Redux actions
import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
import {getProfilesByIds} from 'mattermost-redux/actions/users';
export function loadIncomingHooks() {
Client.listIncomingHooks(
(data) => {
@@ -42,7 +48,7 @@ function loadProfilesForIncomingHooks(hooks) {
return;
}
AsyncClient.getProfilesByIds(list);
getProfilesByIds(list)(dispatch, getState);
}
export function loadOutgoingHooks() {
@@ -76,7 +82,7 @@ function loadProfilesForOutgoingHooks(hooks) {
return;
}
AsyncClient.getProfilesByIds(list);
getProfilesByIds(list)(dispatch, getState);
}
export function loadTeamCommands() {
@@ -110,5 +116,5 @@ function loadProfilesForCommands(commands) {
return;
}
AsyncClient.getProfilesByIds(list);
getProfilesByIds(list)(dispatch, getState);
}

Просмотреть файл

@@ -20,6 +20,12 @@ import Constants from 'utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
const Preferences = Constants.Preferences;
// Redux actions
import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
import {getProfilesByIds} from 'mattermost-redux/actions/users';
export function handleNewPost(post, msg) {
let websocketMessageProps = {};
if (msg) {
@@ -310,7 +316,7 @@ export function loadProfilesForPosts(posts) {
return;
}
AsyncClient.getProfilesByIds(list);
getProfilesByIds(list)(dispatch, getState);
}
export function addReaction(channelId, postId, emojiName) {

Просмотреть файл

@@ -1,16 +1,19 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
import ChannelStore from 'stores/channel_store.jsx';
import PostStore from 'stores/post_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import UserStore from 'stores/user_store.jsx';
import Client from 'client/web_client.jsx';
import {Preferences, Constants} from 'utils/constants.jsx';
import {ActionTypes, Preferences, Constants} from 'utils/constants.jsx';
// Redux actions
import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
import {getStatusesByIds} from 'mattermost-redux/actions/users';
export function loadStatusesForChannel(channelId = ChannelStore.getCurrentId()) {
const postList = PostStore.getVisiblePosts(channelId);
@@ -108,15 +111,7 @@ export function loadStatusesByIds(userIds) {
return;
}
Client.getStatusesByIds(
userIds,
(data) => {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_STATUSES,
statuses: data
});
}
);
getStatusesByIds(userIds)(dispatch, getState);
}
let intervalId = '';

Просмотреть файл

@@ -13,6 +13,13 @@ import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
import {browserHistory} from 'react-router/es6';
// Redux actions
import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
import {getUser} from 'mattermost-redux/actions/users';
export function checkIfTeamExists(teamName, onSuccess, onError) {
Client.findTeamByName(teamName, onSuccess, onError);
}
@@ -62,7 +69,7 @@ export function removeUserFromTeam(teamId, userId, success, error) {
TeamStore.removeMemberInTeam(teamId, userId);
UserStore.removeProfileFromTeam(teamId, userId);
UserStore.emitInTeamChange();
AsyncClient.getUser(userId);
getUser(userId)(dispatch, getState);
AsyncClient.getTeamStats(teamId);
if (success) {

Просмотреть файл

@@ -19,6 +19,79 @@ import Client from 'client/web_client.jsx';
import {Constants, ActionTypes, Preferences} from 'utils/constants.jsx';
import {browserHistory} from 'react-router/es6';
// Redux actions
import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
import {
getProfiles,
getProfilesInChannel,
getProfilesInTeam,
getProfilesWithoutTeam,
getProfilesByIds,
getMe,
searchProfiles,
autocompleteUsers as autocompleteRedux,
updateMe,
updateUserMfa,
checkMfa as checkMfaRedux,
updateUserPassword,
createUser,
login,
loadMe as loadMeRedux
} from 'mattermost-redux/actions/users';
import {getClientConfig, getLicenseConfig} from 'mattermost-redux/actions/general';
export function loadMe(callback) {
loadMeRedux()(dispatch, getState).then(
() => {
localStorage.setItem('currentUserId', UserStore.getCurrentId());
if (callback) {
callback();
}
}
);
}
export function loadMeAndConfig(callback) {
loadMe(() => {
getClientConfig()(store.dispatch, store.getState).then(
(config) => {
global.window.mm_config = config;
if (global.window && global.window.analytics) {
global.window.analytics.identify(global.window.mm_config.DiagnosticId, {}, {
context: {
ip: '0.0.0.0'
},
page: {
path: '',
referrer: '',
search: '',
title: '',
url: ''
},
anonymousId: '00000000000000000000000000'
});
}
getLicenseConfig()(store.dispatch, store.getState).then(
(license) => { // eslint-disable-line max-nested-callbacks
global.window.mm_license = license;
if (callback) {
callback();
}
}
);
}
);
});
}
export function switchFromLdapToEmail(email, password, token, ldapPassword, onSuccess, onError) {
Client.ldapToEmail(
email,
@@ -38,80 +111,30 @@ export function switchFromLdapToEmail(email, password, token, ldapPassword, onSu
);
}
export function loadProfilesAndTeamMembers(offset, limit, teamId = TeamStore.getCurrentId(), success, error) {
Client.getProfilesInTeam(
teamId,
offset,
limit,
export function loadProfilesAndTeamMembers(page, perPage, teamId = TeamStore.getCurrentId(), success) {
getProfilesInTeam(teamId, page, perPage)(dispatch, getState).then(
(data) => {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_PROFILES_IN_TEAM,
profiles: data,
team_id: teamId,
offset,
count: Object.keys(data).length
});
loadTeamMembersForProfilesMap(data, teamId, success, error);
loadStatusesForProfilesMap(data);
},
(err) => {
AsyncClient.dispatchError(err, 'getProfilesInTeam');
loadTeamMembersForProfilesList(data, teamId, success);
loadStatusesForProfilesList(data);
}
);
}
export function loadProfilesAndTeamMembersAndChannelMembers(offset, limit, teamId = TeamStore.getCurrentId(), channelId = ChannelStore.getCurrentId(), success, error) {
Client.getProfilesInChannel(
channelId,
offset,
limit,
export function loadProfilesAndTeamMembersAndChannelMembers(page, perPage, teamId = TeamStore.getCurrentId(), channelId = ChannelStore.getCurrentId(), success, error) {
getProfilesInChannel(channelId, page, perPage)(dispatch, getState).then(
(data) => {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_PROFILES_IN_CHANNEL,
profiles: data,
channel_id: channelId,
offset,
count: Object.keys(data).length
});
loadTeamMembersForProfilesMap(
loadTeamMembersForProfilesList(
data,
teamId,
() => {
loadChannelMembersForProfilesMap(data, channelId, success, error);
loadStatusesForProfilesMap(data);
});
},
(err) => {
AsyncClient.dispatchError(err, 'getProfilesInChannel');
loadChannelMembersForProfilesList(data, channelId, success, error);
loadStatusesForProfilesList(data);
}
);
}
);
}
export function loadTeamMembersForProfilesMap(profiles, teamId = TeamStore.getCurrentId(), success, error) {
const membersToLoad = {};
for (const pid in profiles) {
if (!profiles.hasOwnProperty(pid)) {
continue;
}
if (!TeamStore.hasActiveMemberInTeam(teamId, pid)) {
membersToLoad[pid] = true;
}
}
const list = Object.keys(membersToLoad);
if (list.length === 0) {
if (success) {
success({});
}
return;
}
loadTeamMembersForProfiles(list, teamId, success, error);
}
export function loadTeamMembersForProfilesList(profiles, teamId = TeamStore.getCurrentId(), success, error) {
const membersToLoad = {};
for (let i = 0; i < profiles.length; i++) {
@@ -133,24 +156,13 @@ export function loadTeamMembersForProfilesList(profiles, teamId = TeamStore.getC
loadTeamMembersForProfiles(list, teamId, success, error);
}
export function loadProfilesWithoutTeam(page, perPage, success, error) {
Client.getProfilesWithoutTeam(
page,
perPage,
export function loadProfilesWithoutTeam(page, perPage, success) {
getProfilesWithoutTeam(page, perPage)(dispatch, getState).then(
(data) => {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_PROFILES_WITHOUT_TEAM,
profiles: data,
page
});
loadStatusesForProfilesMap(data);
},
(err) => {
AsyncClient.dispatchError(err, 'getProfilesWithoutTeam');
if (error) {
error(err);
if (success) {
success(data);
}
}
);
@@ -248,9 +260,9 @@ function populateDMChannelsWithProfiles(userIds) {
}
}
function populateChannelWithProfiles(channelId, userIds) {
for (let i = 0; i < userIds.length; i++) {
UserStore.saveUserIdInChannel(channelId, userIds[i]);
function populateChannelWithProfiles(channelId, users) {
for (let i = 0; i < users.length; i++) {
UserStore.saveUserIdInChannel(channelId, users[i].id);
}
UserStore.emitInChannelChange();
}
@@ -360,17 +372,9 @@ export function loadProfilesForGM() {
});
}
Client.getProfilesInChannel(
channel.id,
0,
Constants.MAX_USERS_IN_GM,
getProfilesInChannel(channel.id, 0, Constants.MAX_USERS_IN_GM)(dispatch, getState).then(
(data) => {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_PROFILES,
profiles: data
});
populateChannelWithProfiles(channel.id, Object.keys(data));
populateChannelWithProfiles(channel.id, data);
}
);
}
@@ -420,20 +424,10 @@ export function loadProfilesForDM() {
}
if (profilesToLoad.length > 0) {
Client.getProfilesByIds(
profilesToLoad,
(data) => {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_PROFILES,
profiles: data
});
// Use membersToLoad so we get all the DM profiles even if they were already loaded
getProfilesByIds(profilesToLoad)(dispatch, getState).then(
() => {
populateDMChannelsWithProfiles(profileIds);
},
(err) => {
AsyncClient.dispatchError(err, 'getProfilesByIds');
}
);
} else {
populateDMChannelsWithProfiles(profileIds);
@@ -491,119 +485,70 @@ function onThemeSaved(teamId, theme, onSuccess) {
onSuccess();
}
export function searchUsers(term, teamId = TeamStore.getCurrentId(), options = {}, success, error) {
Client.searchUsers(
term,
teamId,
options,
export function searchUsers(term, teamId = TeamStore.getCurrentId(), options = {}, success) {
searchProfiles(term, {team_id: teamId, ...options})(dispatch, getState).then(
(data) => {
loadStatusesForProfilesList(data);
if (success) {
success(data);
}
},
(err) => {
AsyncClient.dispatchError(err, 'searchUsers');
if (error) {
error(err);
}
}
);
}
export function searchUsersNotInTeam(term, teamId = TeamStore.getCurrentId(), options = {}, success, error) {
Client.searchUsersNotInTeam(
term,
teamId,
options,
export function searchUsersNotInTeam(term, teamId = TeamStore.getCurrentId(), options = {}, success) {
searchProfiles(term, {not_in_team_id: teamId, ...options})(dispatch, getState).then(
(data) => {
loadStatusesForProfilesList(data);
if (success) {
success(data);
}
},
(err) => {
AsyncClient.dispatchError(err, 'searchUsersNotInTeam');
}
);
}
if (error) {
error(err);
export function autocompleteUsersInChannel(username, channelId, success) {
const channel = ChannelStore.get(channelId);
const teamId = channel ? channel.team_id : TeamStore.getCurrentId();
autocompleteRedux(username, teamId, channelId)(dispatch, getState).then(
(data) => {
if (success) {
success(data);
}
}
);
}
export function autocompleteUsersInChannel(username, channelId, success, error) {
Client.autocompleteUsersInChannel(
username,
channelId,
export function autocompleteUsersInTeam(username, success) {
autocompleteRedux(username, TeamStore.getCurrentId())(dispatch, getState).then(
(data) => {
if (success) {
success(data);
}
},
(err) => {
AsyncClient.dispatchError(err, 'autocompleteUsersInChannel');
if (error) {
error(err);
}
}
);
}
export function autocompleteUsersInTeam(username, success, error) {
Client.autocompleteUsersInTeam(
username,
export function autocompleteUsers(username, success) {
autocompleteRedux(username)(dispatch, getState).then(
(data) => {
if (success) {
success(data);
}
},
(err) => {
AsyncClient.dispatchError(err, 'autocompleteUsersInTeam');
if (error) {
error(err);
}
}
);
}
export function autocompleteUsers(username, success, error) {
Client.autocompleteUsers(
username,
export function updateUser(user, type, success, error) {
updateMe(user)(dispatch, getState).then(
(data) => {
if (success) {
if (data && success) {
success(data);
}
},
(err) => {
AsyncClient.dispatchError(err, 'autocompleteUsers');
if (error) {
error(err);
}
}
);
}
export function updateUser(username, type, success, error) {
Client.updateUser(
username,
type,
(data) => {
if (success) {
success(data);
}
},
(err) => {
if (error) {
error(err);
} else {
AsyncClient.dispatchError(err, 'updateUser');
} else if (data == null && error) {
const serverError = getState().requests.users.updateUser.error;
error({id: serverError.server_error_id, ...serverError});
}
}
);
@@ -626,74 +571,55 @@ export function generateMfaSecret(success, error) {
);
}
export function updateUserNotifyProps(data, success, error) {
Client.updateUserNotifyProps(
data,
() => {
AsyncClient.getMe();
if (success) {
success();
}
},
(err) => {
if (error) {
error(err);
}
}
export function updateUserNotifyProps(props, success, error) {
updateMe({notify_props: props})(dispatch, getState).then(
(data) => {
if (data && success) {
success(data);
} else if (data == null && error) {
const serverError = getState().requests.users.updateMe.error;
error({id: serverError.server_error_id, ...serverError});
}
}
);
}
export function updateUserRoles(userId, newRoles, success, error) {
Client.updateUserRoles(
userId,
newRoles,
() => {
AsyncClient.getUser(
userId,
success,
error
);
},
error
updateUserRoles(userId, newRoles)(dispatch, getState).then(
(data) => {
if (data && success) {
success(data);
} else if (data == null && error) {
const serverError = getState().requests.users.updateUser.error;
error({id: serverError.server_error_id, ...serverError});
}
}
);
}
export function activateMfa(code, success, error) {
Client.updateMfa(
code,
true,
() => {
AsyncClient.getMe();
if (success) {
success();
updateUserMfa(UserStore.getCurrentId(), true, code)(dispatch, getState).then(
(data) => {
if (data && success) {
success(data);
} else if (data == null && error) {
const serverError = getState().requests.users.updateUser.error;
error({id: serverError.server_error_id, ...serverError});
}
},
(err) => {
if (error) {
error(err);
}
}
);
}
export function deactivateMfa(success, error) {
Client.updateMfa(
'',
false,
() => {
AsyncClient.getMe();
if (success) {
success();
updateUserMfa(UserStore.getCurrentId(), false)(dispatch, getState).then(
(data) => {
if (data && success) {
success(data);
} else if (data == null && error) {
const serverError = getState().requests.users.updateUser.error;
error({id: serverError.server_error_id, ...serverError});
}
},
(err) => {
if (error) {
error(err);
}
}
);
}
@@ -703,16 +629,13 @@ export function checkMfa(loginId, success, error) {
return;
}
Client.checkMfa(
loginId,
checkMfaRedux(loginId)(dispatch, getState).then(
(data) => {
if (success) {
success(data && data.mfa_required === 'true');
}
},
(err) => {
if (error) {
error(err);
if (data && success) {
success(data);
} else if (data == null && error) {
const serverError = getState().requests.users.checkMfa.error;
error({id: serverError.server_error_id, ...serverError});
}
}
);
@@ -735,15 +658,13 @@ export function updateActive(userId, active, success, error) {
}
export function updatePassword(userId, currentPassword, newPassword, success, error) {
Client.updatePassword(userId, currentPassword, newPassword,
() => {
if (success) {
success();
}
},
(err) => {
if (error) {
error(err);
updateUserPassword(userId, currentPassword, newPassword)(dispatch, getState).then(
(data) => {
if (data && success) {
success(data);
} else if (data == null && error) {
const serverError = getState().requests.users.updateUser.error;
error({id: serverError.server_error_id, ...serverError});
}
}
);
@@ -820,37 +741,27 @@ export function loginById(userId, password, mfaToken, success, error) {
}
export function createUserWithInvite(user, data, emailHash, inviteId, success, error) {
Client.createUserWithInvite(
user,
data,
emailHash,
inviteId,
(response) => {
if (success) {
success(response);
}
},
(err) => {
if (error) {
error(err);
createUser(user, data, emailHash, inviteId)(dispatch, getState).then(
(resp) => {
if (resp && success) {
success(resp);
} else if (resp == null && error) {
const serverError = getState().requests.users.create.error;
error({id: serverError.server_error_id, ...serverError});
}
}
);
}
export function webLogin(loginId, password, token, success, error) {
Client.webLogin(
loginId,
password,
token,
() => {
if (success) {
login(loginId, password, token)(dispatch, getState).then(
(ok) => {
if (ok && success) {
localStorage.setItem('currentUserId', UserStore.getCurrentId());
success();
}
},
(err) => {
if (error) {
error(err);
} else if (!ok && error) {
const serverError = getState().requests.users.login.error;
error({id: serverError.server_error_id, ...serverError});
}
}
);
@@ -907,7 +818,7 @@ export function uploadProfileImage(userPicture, success, error) {
Client.uploadProfileImage(
userPicture,
() => {
AsyncClient.getMe();
getMe()(dispatch, getState);
if (success) {
success();
}
@@ -920,38 +831,24 @@ export function uploadProfileImage(userPicture, success, error) {
);
}
export function loadProfiles(offset = UserStore.getPagingOffset(), limit = Constants.PROFILE_CHUNK_SIZE, success, error) {
Client.getProfiles(
offset,
limit,
export function loadProfiles(page, perPage, success) {
getProfiles(page, perPage)(dispatch, getState).then(
(data) => {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_PROFILES,
profiles: data
});
if (success) {
success(data);
}
},
(err) => {
AsyncClient.dispatchError(err, 'getProfiles');
if (error) {
error(err);
}
}
);
}
export function getMissingProfiles(ids, success, error) {
export function getMissingProfiles(ids) {
const missingIds = ids.filter((id) => !UserStore.hasProfile(id));
if (missingIds.length === 0) {
return;
}
AsyncClient.getProfilesByIds(missingIds, success, error);
getProfilesByIds(missingIds)(dispatch, getState);
}
export function loadMyTeamMembers() {

Просмотреть файл

@@ -338,7 +338,6 @@ function handleUserUpdatedEvent(msg) {
const user = msg.data.user;
if (UserStore.getCurrentId() !== user.id) {
UserStore.saveProfile(user);
UserStore.emitChange(user.id);
}
}