RN-270 "Jump to conversation" filtering (#755)

* RN-270 "Jump to conversation" filtering

* Review Feedback

* Change reduce filter for member details

* Remove duplicate email push
This commit is contained in:
Chris Duarte
2017-07-24 05:11:52 -07:00
committed by Harrison Healey
parent a5f10c7137
commit b6274da38a
3 changed files with 115 additions and 19 deletions

View File

@@ -35,14 +35,13 @@ class FilteredList extends Component {
currentUserId: PropTypes.string,
currentChannel: PropTypes.object,
groupChannels: PropTypes.array,
groupChannelMemberDetails: PropTypes.object,
intl: intlShape.isRequired,
teammateNameDisplay: PropTypes.string,
onSelectChannel: PropTypes.func.isRequired,
otherChannels: PropTypes.array,
profiles: PropTypes.oneOfType(
PropTypes.object,
PropTypes.array
),
profiles: PropTypes.object,
teamProfiles: PropTypes.object,
searchOrder: PropTypes.array.isRequired,
pastDirectMessages: PropTypes.array,
restrictDms: PropTypes.bool.isRequired,
@@ -86,6 +85,11 @@ class FilteredList extends Component {
clearTimeout(this.searchTimeoutId);
this.searchTimeoutId = setTimeout(() => {
// Android has a fatal error if we send a blank term
if (!term) {
return;
}
searchProfiles(term);
searchChannels(currentTeam.id, term);
}, General.SEARCH_TIMEOUT_MILLISECONDS);
@@ -123,7 +127,17 @@ class FilteredList extends Component {
const text = term.toLowerCase();
return channels.filter((c) => {
return c.display_name.toLowerCase().includes(text);
const fieldsToCheck = ['display_name', 'username', 'email', 'full_name', 'nickname'];
let match = false;
for (const field of fieldsToCheck) {
if (c.hasOwnProperty(field) && c[field].toLowerCase().includes(text)) {
match = true;
break;
}
}
return match;
});
};
@@ -162,7 +176,7 @@ class FilteredList extends Component {
}
buildCurrentDMSForSearch = (props, term) => {
const {channels, teammateNameDisplay, profiles, statuses, pastDirectMessages} = props;
const {channels, teammateNameDisplay, profiles, statuses, pastDirectMessages, groupChannelMemberDetails} = props;
const {favoriteChannels} = channels;
const favoriteDms = favoriteChannels.filter((c) => {
@@ -170,11 +184,13 @@ class FilteredList extends Component {
});
const directChannelUsers = [];
const groupChannels = [];
let groupChannels = [];
channels.directAndGroupChannels.forEach((c) => {
if (c.type === General.DM_CHANNEL) {
directChannelUsers.push(profiles[c.teammate_id]);
if (profiles.hasOwnProperty(c.teammate_id)) {
directChannelUsers.push(profiles[c.teammate_id]);
}
} else {
groupChannels.push(c);
}
@@ -193,7 +209,16 @@ class FilteredList extends Component {
email: u.email,
name: displayName,
type: General.DM_CHANNEL,
fake: true
fake: true,
nickname: u.nickname,
fullname: `${u.first_name} ${u.last_name}`
};
});
groupChannels = groupChannels.map((channel) => {
return {
...channel,
...groupChannelMemberDetails[channel.id]
};
});
@@ -201,7 +226,7 @@ class FilteredList extends Component {
}
buildMembersForSearch = (props, term) => {
const {channels, currentUserId, teammateNameDisplay, profiles, statuses, pastDirectMessages} = props;
const {channels, currentUserId, teammateNameDisplay, profiles, teamProfiles, statuses, pastDirectMessages, restrictDms} = props;
const {favoriteChannels, unreadChannels} = channels;
const favoriteAndUnreadDms = [...favoriteChannels, ...unreadChannels].filter((c) => {
@@ -210,7 +235,9 @@ class FilteredList extends Component {
const directAndGroupChannelMembers = [...channels.directAndGroupChannels, ...favoriteAndUnreadDms].filter((c) => c.type === General.DM_CHANNEL).map((c) => c.teammate_id);
const userNotInDirectOrGroupChannels = Object.values(profiles).filter((u) => directAndGroupChannelMembers.indexOf(u.id) === -1 && pastDirectMessages.indexOf(u.id) === -1 && u.id !== currentUserId);
const profilesToUse = restrictDms ? teamProfiles : profiles;
const userNotInDirectOrGroupChannels = Object.values(profilesToUse).filter((u) => directAndGroupChannelMembers.indexOf(u.id) === -1 && pastDirectMessages.indexOf(u.id) === -1 && u.id !== currentUserId);
const members = userNotInDirectOrGroupChannels.map((u) => {
const displayName = displayUsername(u, teammateNameDisplay);
@@ -219,9 +246,13 @@ class FilteredList extends Component {
id: u.id,
status: statuses[u.id],
display_name: displayName,
username: u.username,
email: u.email,
name: displayName,
type: General.DM_CHANNEL,
fake: true
fake: true,
nickname: u.nickname,
fullname: `${u.first_name} ${u.last_name}`
};
});

View File

@@ -11,7 +11,7 @@ import {makeGroupMessageVisibleIfNecessary} from 'mattermost-redux/actions/prefe
import {General} from 'mattermost-redux/constants';
import {getGroupChannels, getOtherChannels} from 'mattermost-redux/selectors/entities/channels';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {getProfilesInCurrentTeam, getUsers, getUserStatuses} from 'mattermost-redux/selectors/entities/users';
import {getCurrentUserId, getProfilesInCurrentTeam, getUsers, getUserIdsInChannels, getUserStatuses} from 'mattermost-redux/selectors/entities/users';
import {getDirectShowPreferences, getTeammateNameDisplaySetting} from 'mattermost-redux/selectors/entities/preferences';
import Config from 'assets/config';
@@ -25,15 +25,78 @@ const pastDirectMessages = createSelector(
(directChannelsFromPreferences) => directChannelsFromPreferences.filter((d) => d.value === 'false').map((d) => d.name)
);
const getTeamProfiles = createSelector(
getProfilesInCurrentTeam,
(members) => {
return members.reduce((memberProfiles, member) => {
memberProfiles[member.id] = member;
return memberProfiles;
}, {});
}
);
// Fill an object for each group channel with concatenated strings for username, email, fullname, and nickname
function getGroupDetails(currentUserId, userIdsInChannels, profiles, groupChannels) {
return groupChannels.reduce((groupMemberDetails, channel) => {
if (!userIdsInChannels.hasOwnProperty(channel.id)) {
return groupMemberDetails;
}
const members = Array.from(userIdsInChannels[channel.id]).reduce((memberDetails, member) => {
if (member === currentUserId) {
return memberDetails;
}
const details = {...memberDetails};
const profile = profiles[member];
details.username.push(profile.username);
if (profile.email) {
details.email.push(profile.email);
}
if (profile.nickname) {
details.nickname.push(profile.nickname);
}
if (profile.fullname) {
details.fullname.push(`${profile.first_name} ${profile.last_name}`);
}
return details;
}, {
email: [],
fullname: [],
nickname: [],
username: []
});
groupMemberDetails[channel.id] = {
email: members.email.join(','),
fullname: members.fullname.join(','),
nickname: members.nickname.join(','),
username: members.username.join(',')
};
return groupMemberDetails;
}, {});
}
const getGroupChannelMemberDetails = createSelector(
getCurrentUserId,
getUserIdsInChannels,
getUsers,
getGroupChannels,
getGroupDetails
);
function mapStateToProps(state, ownProps) {
const {currentUserId} = state.entities.users;
let profiles;
const profiles = getUsers(state);
let teamProfiles = {};
const restrictDms = getConfig(state).RestrictDirectMessage !== General.RESTRICT_DIRECT_MESSAGE_ANY;
if (restrictDms) {
profiles = getProfilesInCurrentTeam(state);
} else {
profiles = getUsers(state);
teamProfiles = getTeamProfiles(state);
}
const searchOrder = Config.DrawerSearchOrder ? Config.DrawerSearchOrder : DEFAULT_SEARCH_ORDER;
@@ -42,7 +105,9 @@ function mapStateToProps(state, ownProps) {
currentUserId,
otherChannels: getOtherChannels(state),
groupChannels: getGroupChannels(state),
groupChannelMemberDetails: getGroupChannelMemberDetails(state),
profiles,
teamProfiles,
teammateNameDisplay: getTeammateNameDisplaySetting(state),
statuses: getUserStatuses(state),
searchOrder,

View File

@@ -6,7 +6,7 @@ import {bindActionCreators} from 'redux';
import {addReaction, getReactionsForPost, removeReaction} from 'mattermost-redux/actions/posts';
import {makeGetReactionsForPost} from 'mattermost-redux/selectors/entities/posts';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import {getTheme} from 'app/selectors/preferences';
@@ -15,7 +15,7 @@ import Reactions from './reactions';
function makeMapStateToProps() {
const getReactionsForPostSelector = makeGetReactionsForPost();
return function mapStateToProps(state, ownProps) {
const currentUserId = getCurrentUser(state);
const currentUserId = getCurrentUserId(state);
const reactionsForPost = getReactionsForPostSelector(state, ownProps.postId);
const highlightedReactions = [];