From f487bb4014fd238b1ddadc50ca44cfef31100c09 Mon Sep 17 00:00:00 2001 From: enahum Date: Thu, 8 Dec 2016 13:36:07 -0300 Subject: [PATCH] Remove pagination for profiles in the store (#105) --- src/actions/channels.js | 6 ++- src/actions/users.js | 11 ++---- src/reducers/entities/helpers.js | 52 ++++++++++++-------------- src/reducers/entities/users.js | 63 +++++++++++--------------------- test/actions/channels.test.js | 18 ++++++--- test/actions/users.test.js | 45 +++++++++++------------ 6 files changed, 88 insertions(+), 107 deletions(-) diff --git a/src/actions/channels.js b/src/actions/channels.js index c86e234ce..4d481021a 100644 --- a/src/actions/channels.js +++ b/src/actions/channels.js @@ -426,7 +426,8 @@ export function addChannelMember(teamId, channelId, userId) { dispatch(batchActions([ { type: UsersTypes.RECEIVED_PROFILE_IN_CHANNEL, - user_id: userId + data: {user_id: userId}, + id: channelId }, { type: ChannelTypes.ADD_CHANNEL_MEMBER_SUCCESS @@ -448,7 +449,8 @@ export function removeChannelMember(teamId, channelId, userId) { dispatch(batchActions([ { type: UsersTypes.RECEIVED_PROFILE_NOT_IN_CHANNEL, - user_id: userId + data: {user_id: userId}, + id: channelId }, { type: ChannelTypes.REMOVE_CHANNEL_MEMBER_SUCCESS diff --git a/src/actions/users.js b/src/actions/users.js index e9eb76612..0a66ba3ec 100644 --- a/src/actions/users.js +++ b/src/actions/users.js @@ -88,8 +88,7 @@ export function getProfilesInTeam(teamId, offset, limit = Constants.PROFILE_CHUN { type: UsersTypes.RECEIVED_PROFILES_IN_TEAM, data: profiles, - offset, - count: Object.keys(profiles).length + id: teamId }, { type: UsersTypes.RECEIVED_PROFILES, @@ -115,8 +114,7 @@ export function getProfilesInChannel(teamId, channelId, offset, limit = Constant { type: UsersTypes.RECEIVED_PROFILES_IN_CHANNEL, data: profiles, - offset, - count: Object.keys(profiles).length + id: channelId }, { type: UsersTypes.RECEIVED_PROFILES, @@ -137,13 +135,12 @@ export function getProfilesNotInChannel(teamId, channelId, offset, limit = Const return async (dispatch, getState) => { try { dispatch({type: UsersTypes.PROFILES_NOT_IN_CHANNEL_REQUEST}, getState); - const profiles = await Client.getProfilesInChannel(teamId, channelId, offset, limit); + const profiles = await Client.getProfilesNotInChannel(teamId, channelId, offset, limit); dispatch(batchActions([ { type: UsersTypes.RECEIVED_PROFILES_NOT_IN_CHANNEL, data: profiles, - offset, - count: Object.keys(profiles).length + id: channelId }, { type: UsersTypes.RECEIVED_PROFILES, diff --git a/src/reducers/entities/helpers.js b/src/reducers/entities/helpers.js index 506faadab..994b36263 100644 --- a/src/reducers/entities/helpers.js +++ b/src/reducers/entities/helpers.js @@ -1,14 +1,6 @@ // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -export function initialPagingState() { - return { - items: new Set(), - offset: 0, - count: 0 - }; -} - function isPostListNull(pl) { if (!pl) { return true; @@ -105,32 +97,34 @@ export function addPosts(state, action) { } export function profilesToSet(state, action) { - const nextState = {...state}; - if (action.offset != null && action.count != null) { - nextState.offset = action.offset + action.count; - nextState.count += action.count; - } - - nextState.items = new Set(state.items); + const id = action.id; + const nextSet = new Set(state[id]); Object.keys(action.data).forEach((key) => { - nextState.items.add(key); + nextSet.add(key); }); - return nextState; + return { + ...state, + [id]: nextSet + }; } -export function addProfileToSet(state, profileId) { - const nextState = {...state}; - nextState.items = new Set(state.items); - nextState.items.add(profileId); - - return nextState; +export function addProfileToSet(state, action) { + const id = action.id; + const nextSet = new Set(state[id]); + nextSet.add(action.data.user_id); + return { + ...state, + [id]: nextSet + }; } -export function removeProfileFromSet(state, profileId) { - const nextState = {...state}; - nextState.items = new Set(state.items); - nextState.items.delete(profileId); - - return nextState; +export function removeProfileFromSet(state, action) { + const id = action.id; + const nextSet = new Set(state[id]); + nextSet.delete(action.data.user_id); + return { + ...state, + [id]: nextSet + }; } diff --git a/src/reducers/entities/users.js b/src/reducers/entities/users.js index 1508a349f..40d5197ad 100644 --- a/src/reducers/entities/users.js +++ b/src/reducers/entities/users.js @@ -3,7 +3,7 @@ import {combineReducers} from 'redux'; import {UsersTypes} from 'constants'; -import {initialPagingState, profilesToSet, addProfileToSet, removeProfileFromSet} from './helpers'; +import {profilesToSet, addProfileToSet, removeProfileFromSet} from './helpers'; function currentId(state = '', action) { switch (action.type) { @@ -83,84 +83,70 @@ function myAudits(state = [], action) { } } -function profiles(state = {items: {}, offset: 0, count: 0}, action) { - const nextState = {...state}; - +function profiles(state = {}, action) { switch (action.type) { case UsersTypes.RECEIVED_ME: { - const id = action.data.id; - nextState.items = { - ...nextState.items, - [id]: { - ...nextState.items[id], - ...action.data - } + return { + ...state, + [action.data.id]: {...action.data} }; - - return nextState; } case UsersTypes.RECEIVED_PROFILES: - if (action.offset != null && action.count != null) { - nextState.offset = action.offset + action.count; - nextState.count += action.count; - } - nextState.items = Object.assign({}, nextState.items, action.data); - - return nextState; + return Object.assign({}, state, action.data); case UsersTypes.LOGOUT_SUCCESS: - return {items: {}, offset: 0, count: 0}; + return {}; default: return state; } } -function profilesInTeam(state = initialPagingState(), action) { +function profilesInTeam(state = {}, action) { switch (action.type) { case UsersTypes.RECEIVED_PROFILES_IN_TEAM: return profilesToSet(state, action); case UsersTypes.LOGOUT_SUCCESS: - return initialPagingState(); + return {}; default: return state; } } -function profilesInChannel(state = initialPagingState(), action) { +function profilesInChannel(state = {}, action) { switch (action.type) { case UsersTypes.RECEIVED_PROFILE_IN_CHANNEL: - return addProfileToSet(state, action.user_id); + return addProfileToSet(state, action); case UsersTypes.RECEIVED_PROFILES_IN_CHANNEL: return profilesToSet(state, action); case UsersTypes.RECEIVED_PROFILE_NOT_IN_CHANNEL: - return removeProfileFromSet(state, action.user_id); + return removeProfileFromSet(state, action); case UsersTypes.LOGOUT_SUCCESS: - return initialPagingState(); + return {}; default: return state; } } -function profilesNotInChannel(state = initialPagingState(), action) { +function profilesNotInChannel(state = {}, action) { switch (action.type) { case UsersTypes.RECEIVED_PROFILE_NOT_IN_CHANNEL: - return addProfileToSet(state, action.user_id); + return addProfileToSet(state, action); case UsersTypes.RECEIVED_PROFILES_NOT_IN_CHANNEL: return profilesToSet(state, action); case UsersTypes.RECEIVED_PROFILE_IN_CHANNEL: - return removeProfileFromSet(state, action.user_id); + return removeProfileFromSet(state, action); case UsersTypes.LOGOUT_SUCCESS: - return initialPagingState(); + return {}; default: return state; @@ -170,8 +156,7 @@ function profilesNotInChannel(state = initialPagingState(), action) { function statuses(state = {}, action) { switch (action.type) { case UsersTypes.RECEIVED_STATUSES: { - const nextState = {...state}; - return Object.assign({}, nextState, action.data); + return Object.assign({}, state, action.data); } case UsersTypes.LOGOUT_SUCCESS: return {}; @@ -195,20 +180,16 @@ export default combineReducers({ // array with the user's audits myAudits, - // object containing items, count and offset where items is an object where every key is a user id - // and has an object with the users details + // object where every key is a user id and has an object with the users details profiles, - // object containing items, count and offset where items is an object where every key is a user id - // and has a Set with the users id that are members of the team + // object where every key is a user id and has a Set with the users id that are members of the team profilesInTeam, - // object containing items, count and offset where items is an object where every key is a user id - // and has a Set with the users id that are members of the channel + // object where every key is a user id and has a Set with the users id that are members of the channel profilesInChannel, - // object containing items, count and offset where items is an object where every key is a user id - // and has a Set with the users id that are members of the channel + // object where every key is a user id and has a Set with the users id that are members of the channel profilesNotInChannel, // object where every key is the user id and has a value with the current status of each user diff --git a/test/actions/channels.test.js b/test/actions/channels.test.js index 4bef58f55..502b96852 100644 --- a/test/actions/channels.test.js +++ b/test/actions/channels.test.js @@ -70,7 +70,7 @@ describe('Actions.Channels', () => { const membersCount = Object.keys(members).length; assert.ok(channels); assert.ok(members); - assert.ok(profiles.items[user.id]); + assert.ok(profiles[user.id]); assert.ok(Object.keys(preferences).length); assert.ok(channels[Object.keys(members)[0]]); assert.ok(members[Object.keys(channels)[0]]); @@ -440,8 +440,12 @@ describe('Actions.Channels', () => { const addRequest = store.getState().requests.channels.addChannelMember; if (addRequest.status === RequestStatus.SUCCESS) { - assert.ok(profilesInChannel.items.has(user.id)); - assert.ifError(profilesNotInChannel.items.has(user.id)); + const channel = profilesInChannel[TestHelper.basicChannel.id]; + const notChannel = profilesNotInChannel[TestHelper.basicChannel.id]; + assert.ok(channel); + assert.ok(notChannel); + assert.ok(channel.has(user.id)); + assert.ifError(notChannel.has(user.id)); done(); } else if (addRequest.status === RequestStatus.FAILURE) { done(new Error(JSON.stringify(addRequest.error))); @@ -472,8 +476,12 @@ describe('Actions.Channels', () => { const removeRequest = store.getState().requests.channels.removeChannelMember; if (removeRequest.status === RequestStatus.SUCCESS) { - assert.ok(profilesNotInChannel.items.has(user.id)); - assert.ifError(profilesInChannel.items.has(user.id)); + const channel = profilesInChannel[TestHelper.basicChannel.id]; + const notChannel = profilesNotInChannel[TestHelper.basicChannel.id]; + assert.ok(channel); + assert.ok(notChannel); + assert.ok(notChannel.has(user.id)); + assert.ifError(channel.has(user.id)); done(); } else if (removeRequest.status === RequestStatus.FAILURE) { done(new Error(JSON.stringify(removeRequest.error))); diff --git a/test/actions/users.test.js b/test/actions/users.test.js index 93dafff87..a7b4641f5 100644 --- a/test/actions/users.test.js +++ b/test/actions/users.test.js @@ -30,7 +30,7 @@ describe('Actions.Users', () => { } else { assert.ok(currentUserId); assert.ok(profiles); - assert.ok(profiles.items[currentUserId]); + assert.ok(profiles[currentUserId]); assert.ok(Object.keys(preferences).length); // TODO: uncomment when PLT-4167 is merged @@ -75,10 +75,10 @@ describe('Actions.Users', () => { assert.deepStrictEqual(users.myPreferences, {}, 'user preferences not empty'); assert.deepStrictEqual(users.mySessions, [], 'user sessions not empty'); assert.deepStrictEqual(users.myAudits, [], 'user audits not empty'); - assert.deepStrictEqual(users.profiles, {items: {}, offset: 0, count: 0}, 'user profiles not empty'); - assert.deepStrictEqual(users.profilesInTeam, {items: new Set(), offset: 0, count: 0}, 'users profiles in team not empty'); - assert.deepStrictEqual(users.profilesInChannel, {items: new Set(), offset: 0, count: 0}, 'users profiles in channel not empty'); - assert.deepStrictEqual(users.profilesNotInChannel, {items: new Set(), offset: 0, count: 0}, 'users profiles NOT in channel not empty'); + assert.deepStrictEqual(users.profiles, {}, 'user profiles not empty'); + assert.deepStrictEqual(users.profilesInTeam, {}, 'users profiles in team not empty'); + assert.deepStrictEqual(users.profilesInChannel, {}, 'users profiles in channel not empty'); + assert.deepStrictEqual(users.profilesNotInChannel, {}, 'users profiles NOT in channel not empty'); assert.deepStrictEqual(users.statuses, {}, 'users statuses not empty'); assert.strictEqual(loginView.loginId, '', 'login id not empty'); assert.strictEqual(loginView.password, '', 'password not empty'); @@ -123,9 +123,7 @@ describe('Actions.Users', () => { if (profilesRequest.error) { done(new Error(JSON.stringify(profilesRequest.error))); } else { - assert.strictEqual(profiles.offset, 0, 'offset should be 0'); - assert.strictEqual(profiles.count, 0, 'count should be 0'); - assert.ok(profiles.items[user.id]); + assert.ok(profiles[user.id]); done(); } @@ -149,11 +147,10 @@ describe('Actions.Users', () => { if (profilesRequest.error) { done(new Error(JSON.stringify(profilesRequest.error))); } else { - assert.ok(profilesInTeam.offset > 0, 'offset should be > 0'); - assert.ok(profilesInTeam.count > 0, 'count should be > 0'); - assert.equal(profilesInTeam.count, profilesInTeam.items.size, 'count should be equal to the amount of profiles'); - assert.ok(profilesInTeam.items.has(TestHelper.basicUser.id)); - assert.equal(Object.keys(profiles.items).length, profilesInTeam.count, 'profiles != profiles in team'); + const team = profilesInTeam[TestHelper.basicTeam.id]; + assert.ok(team); + assert.ok(team.has(TestHelper.basicUser.id)); + assert.equal(Object.keys(profiles).length, team.size, 'profiles != profiles in team'); done(); } @@ -177,11 +174,9 @@ describe('Actions.Users', () => { if (profilesRequest.error) { done(new Error(JSON.stringify(profilesRequest.error))); } else { - assert.ok(profilesInChannel.offset > 0, 'offset should be > 0'); - assert.ok(profilesInChannel.count > 0, 'count should be > 0'); - assert.equal(profilesInChannel.count, profilesInChannel.items.size, 'count should be equal to the amount of profiles'); - assert.ok(profilesInChannel.items.has(TestHelper.basicUser.id)); - assert.equal(Object.keys(profiles.items).length, profilesInChannel.count, 'profiles != profiles in channel'); + const channel = profilesInChannel[TestHelper.basicChannel.id]; + assert.ok(channel.has(TestHelper.basicUser.id)); + assert.equal(Object.keys(profiles).length, channel.size, 'profiles != profiles in channel'); done(); } @@ -195,6 +190,12 @@ describe('Actions.Users', () => { it('getProfilesNotInChannel', (done) => { TestHelper.initBasic(Client).then(async () => { const store = configureStore(); + const user = await TestHelper.basicClient.createUserWithInvite( + TestHelper.fakeUser(), + null, + null, + TestHelper.basicTeam.invite_id + ); store.subscribe(() => { const profilesRequest = store.getState().requests.users.getProfilesNotInChannel; @@ -205,11 +206,9 @@ describe('Actions.Users', () => { if (profilesRequest.error) { done(new Error(JSON.stringify(profilesRequest.error))); } else { - assert.ok(profilesNotInChannel.offset > 0, 'offset should be > 0'); - assert.ok(profilesNotInChannel.count > 0, 'count should be > 0'); - assert.equal(profilesNotInChannel.count, profilesNotInChannel.items.size, 'count should be equal to the amount of profiles'); - assert.ok(profilesNotInChannel.items.has(TestHelper.basicUser.id)); - assert.equal(Object.keys(profiles.items).length, profilesNotInChannel.count, 'profiles != profiles in channel'); + const channel = profilesNotInChannel[TestHelper.basicChannel.id]; + assert.ok(channel.has(user.id)); + assert.equal(Object.keys(profiles).length, channel.size, 'profiles != profiles in channel'); done(); }