Skip to content

Commit

Permalink
MM-33439: Fetch invited users independently (#486)
Browse files Browse the repository at this point in the history
* Fetch invited users independently

* Use getProfilesByIds

* Add a comment clarifying the filter(u => u) idiom

* Make useEffect do one thing: get the list of users
  • Loading branch information
agarciamontoro committed Mar 4, 2021
1 parent 580e3e0 commit 3a37483
Showing 1 changed file with 39 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, {FC, useState, useEffect} from 'react';
import {useDispatch, useSelector} from 'react-redux';

import ReactSelect, {GroupType, ControlProps, OptionsType, MenuListComponentProps} from 'react-select';

Expand All @@ -7,6 +8,9 @@ import {Scrollbars} from 'react-custom-scrollbars';
import styled from 'styled-components';
import {ActionFunc} from 'mattermost-redux/types/actions';
import {UserProfile} from 'mattermost-redux/types/users';
import {GlobalState} from 'mattermost-redux/types/store';
import {getUser} from 'mattermost-redux/selectors/entities/users';
import {getProfilesByIds} from 'mattermost-redux/actions/users';

import Profile from 'src/components/profile/profile';

Expand All @@ -20,11 +24,14 @@ interface Props {
}

const InviteUsersSelector: FC<Props> = (props: Props) => {
// When there are no users invited, options is UserProfile[], a plain list. When there is at least one user invited,
// options contains two groups: the first with invited members, the second with non invited members. This is needed
// because groups are rendered in the selector list only when there is at least one user invited.
const [options, setOptions] = useState<UserProfile[] | GroupType<UserProfile>[]>([]);
const dispatch = useDispatch();
const [searchTerm, setSearchTerm] = useState('');
const invitedUsers = useSelector<GlobalState, UserProfile[]>((state: GlobalState) => props.userIds.map((id) => getUser(state, id)));
const [searchedUsers, setSearchedUsers] = useState<UserProfile[]>([]);

useEffect(() => {
dispatch(getProfilesByIds(props.userIds));
}, [props.userIds]);

// Update the options whenever the passed user IDs or the search term are updated
useEffect(() => {
Expand All @@ -38,34 +45,40 @@ const InviteUsersSelector: FC<Props> = (props: Props) => {

//@ts-ignore
profiles.then(({data}: { data: UserProfile[] }) => {
const invitedProfiles: UserProfile[] = [];
const nonInvitedProfiles: UserProfile[] = [];

data.forEach((profile: UserProfile) => {
if (props.userIds.includes(profile.id)) {
invitedProfiles.push(profile);
} else {
nonInvitedProfiles.push(profile);
}
});

if (invitedProfiles.length === 0) {
setOptions(nonInvitedProfiles);
} else {
setOptions([
{label: 'INVITED MEMBERS', options: invitedProfiles},
{label: 'NON INVITED MEMBERS', options: nonInvitedProfiles},
]);
}
}).catch(() => {
// eslint-disable-next-line no-console
console.error('Error searching user profiles in custom attribute settings dropdown.');
setSearchedUsers(data);
});
};

updateOptions(searchTerm);
}, [props.userIds, searchTerm]);

let invitedProfiles: UserProfile[] = [];
let nonInvitedProfiles: UserProfile[] = [];

if (searchTerm.trim().length === 0) {
// Filter out all the undefined users, which will cast to false in the filter predicate
invitedProfiles = invitedUsers.filter((user) => user);
nonInvitedProfiles = searchedUsers.filter(
(profile: UserProfile) => !props.userIds.includes(profile.id),
);
} else {
searchedUsers.forEach((profile: UserProfile) => {
if (props.userIds.includes(profile.id)) {
invitedProfiles.push(profile);
} else {
nonInvitedProfiles.push(profile);
}
});
}

let options: UserProfile[] | GroupType<UserProfile>[] = nonInvitedProfiles;
if (invitedProfiles.length !== 0) {
options = [
{label: 'INVITED MEMBERS', options: invitedProfiles},
{label: 'NON INVITED MEMBERS', options: nonInvitedProfiles},
];
}

let badgeContent = '';
const numInvitedMembers = props.userIds.length;
if (numInvitedMembers > 0) {
Expand Down

0 comments on commit 3a37483

Please sign in to comment.