MM-24895 fetch roles if needed and add team member to the store when joining a new team (#4436)

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
Mattermost Build 2020-06-18 03:20:25 +02:00 committed by GitHub
parent dc0133bf01
commit 5c54186c8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 51 additions and 56 deletions

View file

@ -386,18 +386,18 @@ describe('Actions.Teams', () => {
nock(Client4.getTeamRoute(TestHelper.basicTeam.id)).
post('/members').
reply(201, {user_id: user1.id, team_id: TestHelper.basicTeam.id});
const {data: member1} = await Actions.addUserToTeam(TestHelper.basicTeam.id, user1.id)(store.dispatch, store.getState);
const {data: member1} = await store.dispatch(Actions.addUserToTeam(TestHelper.basicTeam.id, user1.id));
nock(Client4.getTeamRoute(TestHelper.basicTeam.id)).
post('/members').
reply(201, {user_id: user2.id, team_id: TestHelper.basicTeam.id});
const {data: member2} = await Actions.addUserToTeam(TestHelper.basicTeam.id, user2.id)(store.dispatch, store.getState);
const {data: member2} = await store.dispatch(Actions.addUserToTeam(TestHelper.basicTeam.id, user2.id));
nock(Client4.getBaseRoute()).
get(`/teams/${TestHelper.basicTeam.id}/members`).
query(true).
reply(200, [member1, member2, TestHelper.basicTeamMember]);
await Actions.getTeamMembers(TestHelper.basicTeam.id)(store.dispatch, store.getState);
await store.dispatch(Actions.getTeamMembers(TestHelper.basicTeam.id));
const membersInTeam = store.getState().entities.teams.membersInTeam;
assert.ok(membersInTeam[TestHelper.basicTeam.id]);

View file

@ -2,13 +2,12 @@
// See LICENSE.txt for license information.
import {Client4} from '@mm-redux/client';
import {General} from '../constants';
import {ChannelTypes, TeamTypes, UserTypes} from '@mm-redux/action_types';
import {ChannelTypes, RoleTypes, TeamTypes, UserTypes} from '@mm-redux/action_types';
import EventEmitter from '@mm-redux/utils/event_emitter';
import {isCompatibleWithJoinViewTeamPermissions} from '@mm-redux/selectors/entities/general';
import {getRoles} from '@mm-redux/selectors/entities/roles_helpers';
import {getCurrentTeamId} from '@mm-redux/selectors/entities/teams';
import {getCurrentUserId} from '@mm-redux/selectors/entities/users';
import {GetStateFunc, DispatchFunc, ActionFunc, ActionResult, batchActions, Action} from '@mm-redux/types/actions';
@ -417,16 +416,43 @@ export function addUserToTeam(teamId: string, userId: string): ActionFunc {
return {error};
}
dispatch(batchActions([
{
type: UserTypes.RECEIVED_PROFILE_IN_TEAM,
data: {id: teamId, user_id: userId},
},
{
type: TeamTypes.RECEIVED_MEMBER_IN_TEAM,
data: member,
},
]));
const actions: Array<Action> = [{
type: UserTypes.RECEIVED_PROFILE_IN_TEAM,
data: {id: teamId, user_id: userId},
}, {
type: TeamTypes.RECEIVED_MY_TEAM_MEMBER,
data: member,
}, {
type: TeamTypes.RECEIVED_MEMBER_IN_TEAM,
data: member,
}];
if (member.roles) {
const state = getState();
const currentRoles = getRoles(state);
const rolesToLoad = new Set<string>();
for (const role of member.roles?.split(' ')) {
if (!currentRoles[role] && role.trim() !== '') {
rolesToLoad.add(role);
}
}
if (rolesToLoad.size > 0) {
try {
const roles = await Client4.getRolesByNames(Array.from(rolesToLoad));
if (roles.length) {
actions.push({
type: RoleTypes.RECEIVED_ROLES,
data: roles,
});
}
} catch {
// do nothing
}
}
}
dispatch(batchActions(actions, 'BATCH_ADD_USER_TO_TEAM'));
return {data: member};
};

View file

@ -280,18 +280,18 @@ function profilesNotInTeam(state: RelationOneToMany<Team, UserProfile> = {}, act
function profilesWithoutTeam(state: Set<string> = new Set(), action: GenericAction) {
switch (action.type) {
case UserTypes.RECEIVED_PROFILE_WITHOUT_TEAM: {
const nextSet = new Set(state);
const nextSet = new Set(Array.from(state));
Object.values(action.data).forEach((id: string) => nextSet.add(id));
return nextSet;
}
case UserTypes.RECEIVED_PROFILES_LIST_WITHOUT_TEAM: {
const nextSet = new Set(state);
const nextSet = new Set(Array.from(state));
action.data.forEach((user: UserProfile) => nextSet.add(user.id));
return nextSet;
}
case UserTypes.PROFILE_NO_LONGER_VISIBLE:
case UserTypes.RECEIVED_PROFILE_IN_TEAM: {
const nextSet = new Set(state);
const nextSet = new Set(Array.from(state));
nextSet.delete(action.data.id);
return nextSet;
}

View file

@ -4,7 +4,7 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {getTeams, addUserToTeam, joinTeam} from '@mm-redux/actions/teams';
import {getTeams, addUserToTeam} from '@mm-redux/actions/teams';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {getJoinableTeams} from '@mm-redux/selectors/entities/teams';
import {getCurrentUser} from '@mm-redux/selectors/entities/users';
@ -24,7 +24,6 @@ function mapStateToProps(state) {
currentUserId: currentUser && currentUser.id,
currentUserIsGuest,
isLandscape: isLandscape(state),
serverVersion: state.entities.general.serverVersion,
teamsRequest: state.requests.teams.getTeams,
teams: getJoinableTeams(state),
theme: getTheme(state),
@ -36,7 +35,6 @@ function mapDispatchToProps(dispatch) {
actions: bindActionCreators({
getTeams,
handleTeamChange,
joinTeam,
addUserToTeam,
logout,
}, dispatch),

View file

@ -14,7 +14,6 @@ import {Navigation} from 'react-native-navigation';
import {RequestStatus} from '@mm-redux/constants';
import EventEmitter from '@mm-redux/utils/event_emitter';
import {isMinimumServerVersion} from '@mm-redux/utils/helpers';
import FormattedText from 'app/components/formatted_text';
import Loading from 'app/components/loading';
@ -35,7 +34,6 @@ export default class SelectTeam extends PureComponent {
actions: PropTypes.shape({
getTeams: PropTypes.func.isRequired,
handleTeamChange: PropTypes.func.isRequired,
joinTeam: PropTypes.func.isRequired,
addUserToTeam: PropTypes.func.isRequired,
logout: PropTypes.func.isRequired,
}).isRequired,
@ -47,7 +45,6 @@ export default class SelectTeam extends PureComponent {
theme: PropTypes.object,
teamsRequest: PropTypes.object.isRequired,
isLandscape: PropTypes.bool.isRequired,
serverVersion: PropTypes.string,
};
static defaultProps = {
@ -128,23 +125,15 @@ export default class SelectTeam extends PureComponent {
onSelectTeam = async (team) => {
this.setState({joining: true});
const {userWithoutTeams, currentUserId, serverVersion} = this.props;
const {userWithoutTeams, currentUserId} = this.props;
const {
joinTeam,
addUserToTeam,
handleTeamChange,
} = this.props.actions;
let error;
if (isMinimumServerVersion(serverVersion, 5, 18)) {
const result = await addUserToTeam(team.id, currentUserId);
error = result.error;
} else {
const result = await joinTeam(team.invite_id, team.id);
error = result.error;
}
if (error) {
Alert.alert(error.message);
const result = await addUserToTeam(team.id, currentUserId);
if (result.error) {
Alert.alert(result.error.message);
this.setState({joining: false});
return;
}

View file

@ -28,7 +28,6 @@ describe('SelectTeam', () => {
getTeams,
handleTeamChange: jest.fn(),
addUserToTeam: jest.fn(),
joinTeam: jest.fn(),
logout: jest.fn(),
};
@ -104,10 +103,9 @@ describe('SelectTeam', () => {
expect(wrapper.getElement()).toMatchSnapshot();
});
test('should call joinTeam versions prior to 5.18', async () => {
test('should call addUserToTeam', async () => {
const props = {
...baseProps,
serverVersion: '5.17',
};
const wrapper = shallow(
@ -115,22 +113,6 @@ describe('SelectTeam', () => {
);
wrapper.instance().onSelectTeam({id: 'test_id', invite_id: 'test_invite_id'});
expect(props.actions.joinTeam).toBeCalledWith('test_invite_id', 'test_id');
expect(props.actions.addUserToTeam).not.toBeCalled();
});
test('should call joinTeam versions posterior to 5.18', async () => {
const props = {
...baseProps,
serverVersion: '5.18',
};
const wrapper = shallow(
<SelectTeam {...props}/>,
);
wrapper.instance().onSelectTeam({id: 'test_id', invite_id: 'test_invite_id'});
expect(props.actions.joinTeam).not.toBeCalled();
expect(props.actions.addUserToTeam).toBeCalledWith('test_id', 'fakeid');
});
});