Commit 2973d518 authored by Saturnino Abril's avatar Saturnino Abril Committed by Derrick Anderson

[PLT-8494] Filter out teams that are deleted and without display_name, then sort… (#611)

* filter out teams that are deleted and without display_name, then sort by their `display_name` field

* handle `delete_team` websocket event

* eliminate usage of TeamStore
parent ad3dd8f0
......@@ -24,7 +24,7 @@ import WebSocketClient from 'client/web_websocket_client.jsx';
import {ActionTypes, Constants, ErrorPageTypes, PostTypes} from 'utils/constants.jsx';
import EventTypes from 'utils/event_types.jsx';
import {sortTeamsByDisplayName} from 'utils/team_utils.jsx';
import {filterAndSortTeamsByDisplayName} from 'utils/team_utils.jsx';
import * as Utils from 'utils/utils.jsx';
import en from 'i18n/en.json';
import * as I18n from 'i18n/i18n.jsx';
......@@ -485,8 +485,10 @@ export async function redirectUserToDefaultTeam() {
}
if (myTeams.length > 0) {
myTeams = myTeams.sort(sortTeamsByDisplayName);
teamId = myTeams[0].id;
myTeams = filterAndSortTeamsByDisplayName(myTeams);
if (myTeams && myTeams[0]) {
teamId = myTeams[0].id;
}
}
}
......
......@@ -11,6 +11,7 @@ import * as TeamActions from 'mattermost-redux/actions/teams';
import {getMe} from 'mattermost-redux/actions/users';
import {Client4} from 'mattermost-redux/client';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import {getMyTeams} from 'mattermost-redux/selectors/entities/teams';
import {browserHistory} from 'utils/browser_history';
import {loadChannelsForCurrentUser} from 'actions/channel_actions.jsx';
......@@ -158,6 +159,10 @@ function handleEvent(msg) {
handleUpdateTeamEvent(msg);
break;
case SocketEvents.DELETE_TEAM:
handleDeleteTeamEvent(msg);
break;
case SocketEvents.ADDED_TO_TEAM:
handleTeamAddedEvent(msg);
break;
......@@ -350,6 +355,60 @@ function handleUpdateTeamEvent(msg) {
TeamStore.updateTeam(msg.data.team);
}
function handleDeleteTeamEvent(msg) {
const deletedTeam = JSON.parse(msg.data.team);
const state = store.getState();
const {teams} = state.entities.teams;
if (
deletedTeam &&
teams &&
teams[deletedTeam.id] &&
teams[deletedTeam.id].delete_at === 0
) {
const {currentUserId} = state.entities.users;
const {currentTeamId, myMembers} = state.entities.teams;
const teamMembers = Object.values(myMembers);
const teamMember = teamMembers.find((m) => m.user_id === currentUserId && m.team_id === currentTeamId);
let newTeamId = '';
if (
deletedTeam &&
teamMember &&
deletedTeam.id === teamMember.team_id
) {
const myTeams = {};
getMyTeams(state).forEach((t) => {
myTeams[t.id] = t;
});
for (let i = 0; i < teamMembers.length; i++) {
const memberTeamId = teamMembers[i].team_id;
if (
myTeams &&
myTeams[memberTeamId] &&
myTeams[memberTeamId].delete_at === 0 &&
deletedTeam.id !== memberTeamId
) {
newTeamId = memberTeamId;
break;
}
}
}
dispatch(batchActions([
{type: TeamTypes.RECEIVED_TEAM_DELETED, data: {id: deletedTeam.id}},
{type: TeamTypes.UPDATED_TEAM, data: deletedTeam}
]));
if (newTeamId) {
dispatch({type: TeamTypes.SELECT_TEAM, data: newTeamId});
browserHistory.push(`${TeamStore.getCurrentTeamUrl()}/channels/${Constants.DEFAULT_CHANNEL}`);
} else {
browserHistory.push('/');
}
}
}
function handleUpdateMemberRoleEvent(msg) {
const member = JSON.parse(msg.data.member);
TeamStore.updateMyRoles(member);
......
......@@ -10,7 +10,8 @@ import {Link} from 'react-router-dom';
import * as GlobalActions from 'actions/global_actions.jsx';
import TeamStore from 'stores/team_store.jsx';
import {sortTeamsByDisplayName} from 'utils/team_utils.jsx';
import {filterAndSortTeamsByDisplayName} from 'utils/team_utils.jsx';
import * as Utils from 'utils/utils.jsx';
import {Constants} from 'utils/constants.jsx';
import AboutBuildModal from 'components/about_build_modal';
......@@ -101,8 +102,7 @@ export default class AdminNavbarDropdown extends React.Component {
}
}
// Sort teams alphabetically with display_name
teamsArray = teamsArray.sort(sortTeamsByDisplayName);
teamsArray = filterAndSortTeamsByDisplayName(teamsArray);
for (const team of teamsArray) {
teams.push(
......
......@@ -8,7 +8,8 @@ import {FormattedMessage} from 'react-intl';
import {Client4} from 'mattermost-redux/client';
import * as TeamActions from 'actions/team_actions.jsx';
import {sortTeamsByDisplayName} from 'utils/team_utils.jsx';
import {filterAndSortTeamsByDisplayName} from 'utils/team_utils.jsx';
import * as Utils from 'utils/utils.jsx';
import LoadingScreen from 'components/loading_screen.jsx';
......@@ -57,7 +58,7 @@ export default class ManageTeamsModal extends React.Component {
loadTeamsAndTeamMembers = (user = this.props.user) => {
TeamActions.getTeamsForUser(user.id, (teams) => {
this.setState({
teams: teams.sort(sortTeamsByDisplayName)
teams: filterAndSortTeamsByDisplayName(teams)
});
});
......
......@@ -210,13 +210,15 @@ export default class NeedsTeam extends React.Component {
toLastChannel = () => {
let channelName = Constants.DEFAULT_CHANNEL;
const team = TeamStore.getByName(this.props.match.params.team);
if (team) {
if (team && team.id) {
const channelId = BrowserStore.getGlobalItem(team.id);
const channel = ChannelStore.getChannelById(channelId);
if (channel) {
channelName = channel.name;
}
}
return `${this.props.match.url}/channels/${channelName}`;
}
......
......@@ -8,7 +8,8 @@ import {FormattedMessage} from 'react-intl';
import TeamStore from 'stores/team_store.jsx';
import UserStore from 'stores/user_store.jsx';
import {sortTeamsByDisplayName} from 'utils/team_utils.jsx';
import {filterAndSortTeamsByDisplayName} from 'utils/team_utils.jsx';
import * as Utils from 'utils/utils.jsx';
import TeamButton from './components/team_button.jsx';
......@@ -126,8 +127,7 @@ export default class TeamSidebar extends React.Component {
}
}
const teams = myTeams.
sort(sortTeamsByDisplayName).
const teams = filterAndSortTeamsByDisplayName(myTeams).
map((team) => {
return (
<TeamButton
......
// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as TeamUtils from 'utils/team_utils.jsx';
describe('TeamUtils.filterAndSortTeamsByDisplayName', function() {
const teamA = {id: 'team_id_a', name: 'team-a', display_name: 'Team A', delete_at: 0};
const teamB = {id: 'team_id_b', name: 'team-b', display_name: 'Team A', delete_at: 0};
const teamC = {id: 'team_id_c', name: 'team-c', display_name: 'Team C', delete_at: null};
const teamD = {id: 'team_id_d', name: 'team-d', display_name: 'Team D'};
const teamE = {id: 'team_id_e', name: 'team-e', display_name: 'Team E', delete_at: 1};
const teamF = {id: 'team_id_i', name: 'team-f', display_name: null};
const teamG = null;
test('should return correct sorted teams', function() {
for (const data of [
{teams: [teamG], result: []},
{teams: [teamF, teamG], result: []},
{teams: [teamA, teamB, teamC, teamD, teamE], result: [teamA, teamB, teamC, teamD]},
{teams: [teamE, teamD, teamC, teamB, teamA], result: [teamA, teamB, teamC, teamD]},
{teams: [teamA, teamB, teamC, teamD, teamE, teamF, teamG], result: [teamA, teamB, teamC, teamD]},
{teams: [teamG, teamF, teamE, teamD, teamC, teamB, teamA], result: [teamA, teamB, teamC, teamD]}
]) {
expect(TeamUtils.filterAndSortTeamsByDisplayName(data.teams)).toEqual(data.result);
}
});
});
......@@ -302,6 +302,7 @@ export const SocketEvents = {
JOIN_TEAM: 'join_team',
LEAVE_TEAM: 'leave_team',
UPDATE_TEAM: 'update_team',
DELETE_TEAM: 'delete_team',
USER_ADDED: 'user_added',
USER_REMOVED: 'user_removed',
USER_UPDATED: 'user_updated',
......
......@@ -3,20 +3,8 @@
import LocalizationStore from 'stores/localization_store.jsx';
export function convertTeamMapToList(teamMap) {
const teams = [];
for (const id in teamMap) {
if (teamMap.hasOwnProperty(id)) {
teams.push(teamMap[id]);
}
}
return teams.sort(sortTeamsByDisplayName);
}
// Use when sorting multiple teams by their `display_name` field
export function sortTeamsByDisplayName(a, b) {
function sortTeamsByDisplayName(a, b) {
const locale = LocalizationStore.getLocale();
if (a.display_name !== b.display_name) {
......@@ -25,3 +13,16 @@ export function sortTeamsByDisplayName(a, b) {
return a.name.localeCompare(b.name, locale, {numeric: true});
}
// Use to filter out teams that are deleted and without display_name, then sort by their `display_name` field
export function filterAndSortTeamsByDisplayName(teams = []) {
if (!teams) {
return [];
}
return teams.
filter((team) => {
return team && !team.delete_at > 0 && team.display_name != null;
}).
sort(sortTeamsByDisplayName);
}
......@@ -59,10 +59,12 @@ export function cmdOrCtrlPressed(e, allowAlt = false) {
}
export function isInRole(roles, inRole) {
var parts = roles.split(' ');
for (var i = 0; i < parts.length; i++) {
if (parts[i] === inRole) {
return true;
if (roles) {
var parts = roles.split(' ');
for (var i = 0; i < parts.length; i++) {
if (parts[i] === inRole) {
return true;
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment