summaryrefslogtreecommitdiffstats
path: root/webapp/stores
diff options
context:
space:
mode:
authorHarrison Healey <harrisonmhealey@gmail.com>2017-03-30 12:46:47 -0400
committerCorey Hulen <corey@hulen.com>2017-03-30 09:46:47 -0700
commit689cac535e45c47a4f603b236dc129dd456efcc9 (patch)
tree767ef80b310d6d073840bd5216da38c439f6e193 /webapp/stores
parent9a9729f22fea7275637eafb4046900c9f372ec56 (diff)
downloadchat-689cac535e45c47a4f603b236dc129dd456efcc9.tar.gz
chat-689cac535e45c47a4f603b236dc129dd456efcc9.tar.bz2
chat-689cac535e45c47a4f603b236dc129dd456efcc9.zip
PLT-2713/PLT-6028 Added System Users list to System Console (#5882)
* PLT-2713 Added ability for admins to list users not in any team * Updated style of unit test * Split SearchableUserList to give better control over its properties * Added users without any teams to the user store * Added ManageUsers page * Renamed ManageUsers to SystemUsers * Added ability to search by user id in SystemUsers page * Added SystemUsersDropdown * Removed unnecessary injectIntl * Created TeamUtils * Reduced scope of system console heading CSS * Added team filter to TeamAnalytics page * Updated admin console sidebar * Removed unnecessary TODO * Removed unused reference to deleted modal * Fixed system console sidebar not scrolling on first load * Fixed TeamAnalytics page not rendering on first load * Fixed chart.js throwing an error when switching between teams * Changed TeamAnalytics header to show the team's display name * Fixed appearance of TeamAnalytics and SystemUsers on small screen widths * Fixed placement of 'No users found' message * Fixed teams not appearing in SystemUsers on first load * Updated user count text for SystemUsers * Changed search by id fallback to trigger less often * Fixed SystemUsers list items not updating when searching * Fixed localization strings for SystemUsers page
Diffstat (limited to 'webapp/stores')
-rw-r--r--webapp/stores/admin_store.jsx14
-rw-r--r--webapp/stores/user_store.jsx130
2 files changed, 81 insertions, 63 deletions
diff --git a/webapp/stores/admin_store.jsx b/webapp/stores/admin_store.jsx
index 4a68ec14c..59c763575 100644
--- a/webapp/stores/admin_store.jsx
+++ b/webapp/stores/admin_store.jsx
@@ -4,8 +4,6 @@
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import EventEmitter from 'events';
-import BrowserStore from 'stores/browser_store.jsx';
-
import Constants from 'utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
@@ -138,18 +136,6 @@ class AdminStoreClass extends EventEmitter {
getTeam(id) {
return this.teams[id];
}
-
- getSelectedTeams() {
- const result = BrowserStore.getItem('selected_teams');
- if (!result) {
- return {};
- }
- return result;
- }
-
- saveSelectedTeams(teams) {
- BrowserStore.setItem('selected_teams', teams);
- }
}
var AdminStore = new AdminStoreClass();
diff --git a/webapp/stores/user_store.jsx b/webapp/stores/user_store.jsx
index 007d8a5a7..6f4acae0a 100644
--- a/webapp/stores/user_store.jsx
+++ b/webapp/stores/user_store.jsx
@@ -16,6 +16,7 @@ const UserStatuses = Constants.UserStatuses;
const CHANGE_EVENT_NOT_IN_CHANNEL = 'change_not_in_channel';
const CHANGE_EVENT_IN_CHANNEL = 'change_in_channel';
const CHANGE_EVENT_IN_TEAM = 'change_in_team';
+const CHANGE_EVENT_WITHOUT_TEAM = 'change_without_team';
const CHANGE_EVENT = 'change';
const CHANGE_EVENT_SESSIONS = 'change_sessions';
const CHANGE_EVENT_AUDITS = 'change_audits';
@@ -50,6 +51,9 @@ class UserStoreClass extends EventEmitter {
this.not_in_channel_offset = {};
this.not_in_channel_count = {};
+ // Lists of sorted IDs for users without a team
+ this.profiles_without_team = {};
+
this.statuses = {};
this.sessions = {};
this.audits = [];
@@ -105,6 +109,18 @@ class UserStoreClass extends EventEmitter {
this.removeListener(CHANGE_EVENT_NOT_IN_CHANNEL, callback);
}
+ emitWithoutTeamChange() {
+ this.emit(CHANGE_EVENT_WITHOUT_TEAM);
+ }
+
+ addWithoutTeamChangeListener(callback) {
+ this.on(CHANGE_EVENT_WITHOUT_TEAM, callback);
+ }
+
+ removeWithoutTeamChangeListener(callback) {
+ this.removeListener(CHANGE_EVENT_WITHOUT_TEAM, callback);
+ }
+
emitSessionsChange() {
this.emit(CHANGE_EVENT_SESSIONS);
}
@@ -189,8 +205,33 @@ class UserStoreClass extends EventEmitter {
return null;
}
+ getProfileListForIds(userIds, skipCurrent = false, skipInactive = false) {
+ const profiles = [];
+ const currentId = this.getCurrentId();
+
+ for (let i = 0; i < userIds.length; i++) {
+ const profile = this.getProfile(userIds[i]);
+
+ if (!profile) {
+ continue;
+ }
+
+ if (skipCurrent && profile.id === currentId) {
+ continue;
+ }
+
+ if (skipInactive && profile.delete_at > 0) {
+ continue;
+ }
+
+ profiles.push(profile);
+ }
+
+ return profiles;
+ }
+
hasProfile(userId) {
- return this.getProfile(userId) != null;
+ return this.getProfiles().hasOwnProperty(userId);
}
getProfileByUsername(username) {
@@ -248,7 +289,7 @@ class UserStoreClass extends EventEmitter {
return profiles;
}
- getProfileList(skipCurrent) {
+ getProfileList(skipCurrent = false, allowInactive = false) {
const profiles = [];
const currentId = this.getCurrentId();
@@ -260,7 +301,7 @@ class UserStoreClass extends EventEmitter {
continue;
}
- if (profile.delete_at === 0) {
+ if (allowInactive || profile.delete_at === 0) {
profiles.push(profile);
}
}
@@ -314,28 +355,8 @@ class UserStoreClass extends EventEmitter {
getProfileListInTeam(teamId = TeamStore.getCurrentId(), skipCurrent = false, skipInactive = false) {
const userIds = this.profiles_in_team[teamId] || [];
- const profiles = [];
- const currentId = this.getCurrentId();
-
- for (let i = 0; i < userIds.length; i++) {
- const profile = this.getProfile(userIds[i]);
-
- if (!profile) {
- continue;
- }
-
- if (skipCurrent && profile.id === currentId) {
- continue;
- }
-
- if (skipInactive && profile.delete_at > 0) {
- continue;
- }
-
- profiles.push(profile);
- }
- return profiles;
+ return this.getProfileListForIds(userIds, skipCurrent, skipInactive);
}
removeProfileFromTeam(teamId, userId) {
@@ -416,21 +437,8 @@ class UserStoreClass extends EventEmitter {
getProfileListInChannel(channelId = ChannelStore.getCurrentId(), skipCurrent = false) {
const userIds = this.profiles_in_channel[channelId] || [];
- const currentId = this.getCurrentId();
- const profiles = [];
-
- for (let i = 0; i < userIds.length; i++) {
- const profile = this.getProfile(userIds[i]);
- if (profile) {
- if (skipCurrent && profile.id === currentId) {
- continue;
- }
-
- profiles.push(profile);
- }
- }
- return profiles;
+ return this.getProfileListForIds(userIds, skipCurrent, false);
}
saveProfilesNotInChannel(channelId = ChannelStore.getCurrentId(), profiles) {
@@ -482,23 +490,43 @@ class UserStoreClass extends EventEmitter {
getProfileListNotInChannel(channelId = ChannelStore.getCurrentId(), skipInactive = false) {
const userIds = this.profiles_not_in_channel[channelId] || [];
- const profiles = [];
- for (let i = 0; i < userIds.length; i++) {
- const profile = this.getProfile(userIds[i]);
+ return this.getProfileListForIds(userIds, false, skipInactive);
+ }
- if (!profile) {
- continue;
- }
+ // Profiles without any teams
- if (skipInactive && profile.delete_at > 0) {
- continue;
+ saveProfilesWithoutTeam(profiles) {
+ const oldProfileList = this.profiles_without_team;
+ const oldProfileMap = {};
+ for (let i = 0; i < oldProfileList.length; i++) {
+ oldProfileMap[oldProfileList[i]] = this.getProfile(oldProfileList[i]);
+ }
+
+ const newProfileMap = Object.assign({}, oldProfileMap, profiles);
+ const newProfileList = Object.keys(newProfileMap);
+
+ newProfileList.sort((a, b) => {
+ const aProfile = newProfileMap[a];
+ const bProfile = newProfileMap[b];
+
+ if (aProfile.username < bProfile.username) {
+ return -1;
}
+ if (aProfile.username > bProfile.username) {
+ return 1;
+ }
+ return 0;
+ });
- profiles.push(profile);
- }
+ this.profiles_without_team = newProfileList;
+ this.saveProfiles(profiles);
+ }
- return profiles;
+ getProfileListWithoutTeam(skipCurrent = false, skipInactive = false) {
+ const userIds = this.profiles_without_team || [];
+
+ return this.getProfileListForIds(userIds, skipCurrent, skipInactive);
}
// Other
@@ -680,6 +708,10 @@ UserStore.dispatchToken = AppDispatcher.register((payload) => {
}
UserStore.emitNotInChannelChange();
break;
+ case ActionTypes.RECEIVED_PROFILES_WITHOUT_TEAM:
+ UserStore.saveProfilesWithoutTeam(action.profiles);
+ UserStore.emitWithoutTeamChange();
+ break;
case ActionTypes.RECEIVED_PROFILE:
UserStore.saveProfile(action.profile);
UserStore.emitChange();