diff --git a/app/client/rest/posts.ts b/app/client/rest/posts.ts
index b18966aae..864400e7f 100644
--- a/app/client/rest/posts.ts
+++ b/app/client/rest/posts.ts
@@ -250,8 +250,13 @@ const ClientPosts = (superclass: any) => class extends superclass {
searchPostsWithParams = async (teamId: string, params: any) => {
analytics.trackAPI('api_posts_search', {team_id: teamId});
+ let route = `${this.getPostsRoute()}/search`;
+ if (teamId) {
+ route = `${this.getTeamRoute(teamId)}/posts/search`;
+ }
+
return this.doFetch(
- `${this.getTeamRoute(teamId)}/posts/search`,
+ route,
{method: 'post', body: JSON.stringify(params)},
);
};
diff --git a/app/mm-redux/actions/search.ts b/app/mm-redux/actions/search.ts
index ecf905c01..912250d64 100644
--- a/app/mm-redux/actions/search.ts
+++ b/app/mm-redux/actions/search.ts
@@ -114,13 +114,12 @@ export function getFlaggedPosts(): ActionFunc {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
const state = getState();
const userId = getCurrentUserId(state);
- const teamId = getCurrentTeamId(state);
dispatch({type: SearchTypes.SEARCH_FLAGGED_POSTS_REQUEST});
let posts;
try {
- posts = await Client4.getFlaggedPosts(userId, '', teamId);
+ posts = await Client4.getFlaggedPosts(userId);
await Promise.all([getProfilesAndStatusesForPosts(posts.posts, dispatch, getState) as any, dispatch(getMissingChannelsFromPosts(posts.posts)) as any]);
} catch (error) {
@@ -202,7 +201,6 @@ export function clearPinnedPosts(channelId: string): ActionFunc {
export function getRecentMentions(): ActionFunc {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
const state = getState();
- const teamId = getCurrentTeamId(state);
let posts;
try {
@@ -213,7 +211,7 @@ export function getRecentMentions(): ActionFunc {
const terms = termKeys.map(({key}) => key).join(' ').trim() + ' ';
analytics.trackAPI('api_posts_search_mention');
- posts = await Client4.searchPosts(teamId, terms, true);
+ posts = await Client4.searchPosts('', terms, true);
const profilesAndStatuses = getProfilesAndStatusesForPosts(posts.posts, dispatch, getState);
const missingChannels = dispatch(getMissingChannelsFromPosts(posts.posts));
diff --git a/app/screens/search/channel_display_name/__snapshots__/channel_display_name.test.js.snap b/app/screens/search/channel_display_name/__snapshots__/channel_display_name.test.js.snap
new file mode 100644
index 000000000..d83018d11
--- /dev/null
+++ b/app/screens/search/channel_display_name/__snapshots__/channel_display_name.test.js.snap
@@ -0,0 +1,83 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`SearchResultPost should match snapshot when no team is provided 1`] = `
+
+
+ channel
+
+
+`;
+
+exports[`SearchResultPost should match snapshot when team is provided 1`] = `
+
+
+ channel
+
+
+
+
+ team
+
+
+
+`;
diff --git a/app/screens/search/channel_display_name/channel_display_name.js b/app/screens/search/channel_display_name/channel_display_name.js
index 6841ec1e5..d01a3d530 100644
--- a/app/screens/search/channel_display_name/channel_display_name.js
+++ b/app/screens/search/channel_display_name/channel_display_name.js
@@ -3,7 +3,7 @@
import PropTypes from 'prop-types';
import React, {PureComponent} from 'react';
-import {Text} from 'react-native';
+import {Platform, Text, View} from 'react-native';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@@ -11,14 +11,29 @@ export default class ChannelDisplayName extends PureComponent {
static propTypes = {
displayName: PropTypes.string,
theme: PropTypes.object.isRequired,
+ teamName: PropTypes.string,
};
render() {
- const {displayName, theme} = this.props;
+ const {displayName, theme, teamName} = this.props;
const styles = getStyleFromTheme(theme);
return (
- {displayName}
+
+ {displayName}
+ {Boolean(teamName) &&
+ <>
+
+ {teamName}
+ >
+ }
+
);
}
}
@@ -29,8 +44,28 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
color: changeOpacity(theme.centerChannelColor, 0.8),
fontSize: 14,
fontWeight: '600',
+ flexShrink: 1,
+ },
+ teamName: {
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ fontSize: 12,
+ fontWeight: '400',
+ flexShrink: 2,
+ },
+ separator: {
+ borderStyle: 'solid',
+ borderLeftColor: changeOpacity(theme.centerChannelColor, 0.2),
+ borderLeftWidth: 1,
+ height: 16,
+ marginRight: 8,
+ marginLeft: 8,
+ alignSelf: Platform.select({ios: 'stretch'}),
+ },
+ container: {
+ flexDirection: 'row',
marginTop: 5,
paddingHorizontal: 16,
+ alignItems: 'baseline',
},
};
});
diff --git a/app/screens/search/channel_display_name/channel_display_name.test.js b/app/screens/search/channel_display_name/channel_display_name.test.js
new file mode 100644
index 000000000..5f577923f
--- /dev/null
+++ b/app/screens/search/channel_display_name/channel_display_name.test.js
@@ -0,0 +1,33 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {shallow} from 'enzyme';
+import React from 'react';
+
+import {Preferences} from '@mm-redux/constants';
+
+import ChannelDisplayName from './channel_display_name';
+
+describe('SearchResultPost', () => {
+ const baseProps = {
+ displayName: 'channel',
+ teamName: '',
+ theme: Preferences.THEMES.denim,
+ };
+
+ test('should match snapshot when no team is provided', async () => {
+ const wrapper = shallow();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+
+ test('should match snapshot when team is provided', async () => {
+ const props = {
+ ...baseProps,
+ teamName: 'team',
+ };
+ const wrapper = shallow();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
diff --git a/app/screens/search/channel_display_name/index.js b/app/screens/search/channel_display_name/index.js
index 9bdf012d3..6e8452bed 100644
--- a/app/screens/search/channel_display_name/index.js
+++ b/app/screens/search/channel_display_name/index.js
@@ -3,21 +3,33 @@
import {connect} from 'react-redux';
+import {General} from '@mm-redux/constants';
import {makeGetChannel} from '@mm-redux/selectors/entities/channels';
import {getPost} from '@mm-redux/selectors/entities/posts';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
+import {getTeam, getTeamMemberships} from '@mm-redux/selectors/entities/teams';
import ChannelDisplayName from './channel_display_name';
-function makeMapStateToProps() {
+// Exported for testing
+export function makeMapStateToProps() {
const getChannel = makeGetChannel();
return (state, ownProps) => {
const post = getPost(state, ownProps.postId);
const channel = post ? getChannel(state, {id: post.channel_id}) : null;
+ let teamName = '';
+ if (channel) {
+ const isDMorGM = channel.type === General.DM_CHANNEL || channel.type === General.GM_CHANNEL;
+ const memberships = getTeamMemberships(state);
+ if (!isDMorGM && memberships && Object.values(memberships).length > 1) {
+ teamName = getTeam(state, channel.team_id)?.display_name;
+ }
+ }
return {
displayName: channel ? channel.display_name : '',
theme: getTheme(state),
+ teamName,
};
};
}
diff --git a/app/screens/search/channel_display_name/index.test.js b/app/screens/search/channel_display_name/index.test.js
new file mode 100644
index 000000000..dc1e8c7ba
--- /dev/null
+++ b/app/screens/search/channel_display_name/index.test.js
@@ -0,0 +1,202 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {General} from '@mm-redux/constants';
+
+import {makeMapStateToProps} from './index';
+
+describe('components/SearchResultsItem/WithStore', () => {
+ const team = {
+ id: 'team_id',
+ display_name: 'team display name',
+ name: 'team_name',
+ };
+
+ const otherTeam = {
+ id: 'other_team_id',
+ display_name: 'other team display name',
+ name: 'other_team_name',
+ };
+
+ const currentUserID = 'other';
+ const user = {
+ id: 'user_id',
+ username: 'username',
+ is_bot: false,
+ };
+ const channel = {
+ id: 'channel_id_open',
+ type: General.OPEN_CHANNEL,
+ team_id: team.id,
+ name: 'open channel',
+ display_name: 'open channel',
+ };
+
+ const dmChannel = {
+ id: 'channel_id_dm',
+ type: General.DM_CHANNEL,
+ name: `${currentUserID}__${user.id}`,
+ display_name: `${currentUserID}__${user.id}`,
+ };
+
+ const post = {
+ channel_id: channel.id,
+ create_at: 1502715365009,
+ delete_at: 0,
+ edit_at: 1502715372443,
+ id: 'id',
+ is_pinned: false,
+ message: 'post message',
+ original_id: '',
+ pending_post_id: '',
+ props: {},
+ root_id: '',
+ type: '',
+ update_at: 1502715372443,
+ user_id: 'user_id',
+ reply_count: 0,
+ };
+
+ const defaultState = {
+ entities: {
+ general: {
+ config: {
+ EnablePostUsernameOverride: 'true',
+ },
+ license: {},
+ },
+ users: {
+ profiles: {
+ [user.id]: user,
+ },
+ currentUserId: currentUserID,
+ statuses: {},
+ profilesInChannel: {},
+ },
+ channels: {
+ channels: {
+ [channel.id]: channel,
+ [dmChannel.id]: dmChannel,
+ },
+ },
+ teams: {
+ myMembers: {
+ [team.id]: {},
+ },
+ teams: {
+ [team.id]: team,
+ [otherTeam.id]: otherTeam,
+ },
+ currentTeamId: team.id,
+ },
+ posts: {
+ posts: {
+ [post.id]: post,
+ },
+ postsInThread: {},
+ },
+ preferences: {
+ myPreferences: {
+ hasOwnProperty: () => true,
+ },
+ },
+ },
+ };
+
+ const defaultProps = {
+ postId: post.id,
+ };
+
+ const mstp = makeMapStateToProps();
+
+ test('should not show team name if user only belongs to one team', () => {
+ const newProps = mstp(defaultState, defaultProps);
+ expect(newProps.teamName).toBe('');
+ });
+
+ test('should show team name for open and private channels when user belongs to more than one team', () => {
+ let state = {
+ ...defaultState,
+ entities: {
+ ...defaultState.entities,
+ teams: {
+ ...defaultState.entities.teams,
+ myMembers: {
+ ...defaultState.entities.teams.myMembers,
+ [otherTeam.id]: {},
+ },
+ },
+ },
+ };
+ let newProps = mstp(state, defaultProps);
+ expect(newProps.teamName).toBe(team.display_name);
+
+ state = {
+ ...state,
+ entities: {
+ ...state.entities,
+ channels: {
+ ...state.entities.channels,
+ channels: {
+ ...state.entities.channels.channels,
+ [channel.id]: {
+ ...channel,
+ type: General.PRIVATE_CHANNEL,
+ },
+ },
+ },
+ },
+ };
+
+ newProps = mstp(state, defaultProps);
+ expect(newProps.teamName).toBe(team.display_name);
+ });
+
+ test('should not show team name for dm and group channels when user belongs to more than one team', () => {
+ let state = {
+ ...defaultState,
+ entities: {
+ ...defaultState.entities,
+ teams: {
+ ...defaultState.entities.teams,
+ myMembers: {
+ ...defaultState.entities.teams.myMembers,
+ [otherTeam.id]: {},
+ },
+ },
+ posts: {
+ ...defaultState.entities.posts,
+ posts: {
+ ...defaultState.entities.posts.posts,
+ [post.id]: {
+ ...defaultState.entities.posts.posts[post.id],
+ channel_id: dmChannel.id,
+ },
+ },
+ },
+ },
+ };
+
+ let newProps = mstp(state, defaultProps);
+ expect(newProps.teamName).toBe('');
+
+ state = {
+ ...state,
+ entities: {
+ ...state.entities,
+ channels: {
+ ...state.entities.channels,
+ channels: {
+ ...state.entities.channels.channels,
+ [dmChannel.id]: {
+ ...dmChannel,
+ type: General.GM_CHANNEL,
+ },
+ },
+ },
+ },
+ };
+ newProps = mstp(state, defaultProps);
+ expect(newProps.teamName).toBe('');
+ });
+});