Use consistent Display Name sorting code throughout the webapp #5159 (#5213)

* Use consistent Display Name sorting code throughout the webapp #5159

* fixed broken sorting of teams and channels
Этот коммит содержится в:
Saturnino Abril
2017-02-01 08:57:16 +09:00
коммит произвёл enahum
родитель 9369cab56c
Коммит 9ba968ce33
11 изменённых файлов: 51 добавлений и 90 удалений

Просмотреть файл

@@ -570,7 +570,7 @@ export function redirectUserToDefaultTeam() {
} }
if (myTeams.length > 0) { if (myTeams.length > 0) {
myTeams = myTeams.sort((a, b) => a.display_name.localeCompare(b.display_name)); myTeams = myTeams.sort(Utils.sortTeamsByDisplayName);
teamId = myTeams[0].id; teamId = myTeams[0].id;
} }
} }

Просмотреть файл

@@ -6,6 +6,7 @@ import ReactDOM from 'react-dom';
import TeamStore from 'stores/team_store.jsx'; import TeamStore from 'stores/team_store.jsx';
import Constants from 'utils/constants.jsx'; import Constants from 'utils/constants.jsx';
import {sortTeamsByDisplayName} from 'utils/utils.jsx';
import * as GlobalActions from 'actions/global_actions.jsx'; import * as GlobalActions from 'actions/global_actions.jsx';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
@@ -64,9 +65,7 @@ export default class AdminNavbarDropdown extends React.Component {
} }
// Sort teams alphabetically with display_name // Sort teams alphabetically with display_name
teamsArray.sort((teamA, teamB) => teamsArray = teamsArray.sort(sortTeamsByDisplayName);
teamA.display_name.localeCompare(teamB.display_name)
);
for (const team of teamsArray) { for (const team of teamsArray) {
teams.push( teams.push(

Просмотреть файл

@@ -114,19 +114,6 @@ export default class AdminSidebar extends React.Component {
document.title = Utils.localizeMessage('sidebar_right_menu.console', 'System Console') + ' - ' + currentSiteName; document.title = Utils.localizeMessage('sidebar_right_menu.console', 'System Console') + ' - ' + currentSiteName;
} }
sortTeams(a, b) {
const teamA = a.display_name.toLowerCase();
const teamB = b.display_name.toLowerCase();
if (teamA < teamB) {
return -1;
}
if (teamA > teamB) {
return 1;
}
return 0;
}
renderAddTeamButton() { renderAddTeamButton() {
const addTeamTooltip = ( const addTeamTooltip = (
<Tooltip id='add-team-tooltip'> <Tooltip id='add-team-tooltip'>
@@ -159,7 +146,7 @@ export default class AdminSidebar extends React.Component {
renderTeams() { renderTeams() {
const teams = []; const teams = [];
const teamsArray = []; let teamsArray = [];
Reflect.ownKeys(this.state.selectedTeams).forEach((key) => { Reflect.ownKeys(this.state.selectedTeams).forEach((key) => {
if (this.state.teams[key]) { if (this.state.teams[key]) {
@@ -167,7 +154,7 @@ export default class AdminSidebar extends React.Component {
} }
}); });
teamsArray.sort(this.sortTeams); teamsArray = teamsArray.sort(Utils.sortTeamsByDisplayName);
for (let i = 0; i < teamsArray.length; i++) { for (let i = 0; i < teamsArray.length; i++) {
const team = teamsArray[i]; const team = teamsArray[i];

Просмотреть файл

@@ -3,18 +3,17 @@
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import React from 'react'; import React from 'react';
import {sortTeamsByDisplayName} from 'utils/utils.jsx';
export default class SelectTeamModal extends React.Component { export default class SelectTeamModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.doSubmit = this.doSubmit.bind(this); this.doSubmit = this.doSubmit.bind(this);
this.doCancel = this.doCancel.bind(this); this.doCancel = this.doCancel.bind(this);
this.compare = this.compare.bind(this);
} }
doSubmit(e) { doSubmit(e) {
@@ -25,24 +24,19 @@ export default class SelectTeamModal extends React.Component {
this.props.onModalDismissed(); this.props.onModalDismissed();
} }
compare(a, b) {
return a.display_name.localeCompare(b.display_name);
}
render() { render() {
if (this.props.teams == null) { if (this.props.teams == null) {
return <div/>; return <div/>;
} }
const options = []; const options = [];
const teamsArray = []; let teamsArray = [];
Reflect.ownKeys(this.props.teams).forEach((key) => { Reflect.ownKeys(this.props.teams).forEach((key) => {
teamsArray.push(this.props.teams[key]); teamsArray.push(this.props.teams[key]);
}); });
teamsArray.sort(this.compare); teamsArray = teamsArray.sort(sortTeamsByDisplayName);
for (let i = 0; i < teamsArray.length; i++) { for (let i = 0; i < teamsArray.length; i++) {
const team = teamsArray[i]; const team = teamsArray[i];
options.push( options.push(

Просмотреть файл

@@ -6,6 +6,7 @@ import React from 'react';
import Constants from 'utils/constants.jsx'; import Constants from 'utils/constants.jsx';
import ChannelStore from 'stores/channel_store.jsx'; import ChannelStore from 'stores/channel_store.jsx';
import * as Utils from 'utils/utils.jsx'; import * as Utils from 'utils/utils.jsx';
import {sortChannelsByDisplayName} from 'utils/channel_utils.jsx';
import * as AsyncClient from 'utils/async_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx';
export default class ChannelSelect extends React.Component { export default class ChannelSelect extends React.Component {
@@ -32,12 +33,11 @@ export default class ChannelSelect extends React.Component {
this.handleChannelChange = this.handleChannelChange.bind(this); this.handleChannelChange = this.handleChannelChange.bind(this);
this.filterChannels = this.filterChannels.bind(this); this.filterChannels = this.filterChannels.bind(this);
this.compareByDisplayName = this.compareByDisplayName.bind(this);
AsyncClient.getMoreChannels(true); AsyncClient.getMoreChannels(true);
this.state = { this.state = {
channels: ChannelStore.getAll().filter(this.filterChannels).sort(this.compareByDisplayName) channels: ChannelStore.getAll().filter(this.filterChannels).sort(sortChannelsByDisplayName)
}; };
} }
@@ -52,7 +52,7 @@ export default class ChannelSelect extends React.Component {
handleChannelChange() { handleChannelChange() {
this.setState({ this.setState({
channels: ChannelStore.getAll().concat(ChannelStore.getMoreAll()). channels: ChannelStore.getAll().concat(ChannelStore.getMoreAll()).
filter(this.filterChannels).sort(this.compareByDisplayName) filter(this.filterChannels).sort(sortChannelsByDisplayName)
}); });
} }
@@ -64,10 +64,6 @@ export default class ChannelSelect extends React.Component {
return false; return false;
} }
compareByDisplayName(channelA, channelB) {
return channelA.display_name.localeCompare(channelB.display_name);
}
render() { render() {
const options = [ const options = [
<option <option

Просмотреть файл

@@ -10,6 +10,7 @@ import ChannelStore from 'stores/channel_store.jsx';
import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
import {Constants, ActionTypes} from 'utils/constants.jsx'; import {Constants, ActionTypes} from 'utils/constants.jsx';
import {sortChannelsByDisplayName} from 'utils/channel_utils.jsx';
import React from 'react'; import React from 'react';
@@ -51,7 +52,7 @@ export default class SearchChannelProvider extends Provider {
const publicChannels = data; const publicChannels = data;
const localChannels = ChannelStore.getAll(); const localChannels = ChannelStore.getAll();
const privateChannels = []; let privateChannels = [];
for (const id of Object.keys(localChannels)) { for (const id of Object.keys(localChannels)) {
const channel = localChannels[id]; const channel = localChannels[id];
@@ -60,15 +61,15 @@ export default class SearchChannelProvider extends Provider {
} }
} }
const filteredPublicChannels = []; let filteredPublicChannels = [];
publicChannels.forEach((item) => { publicChannels.forEach((item) => {
if (item.name.startsWith(channelPrefix)) { if (item.name.startsWith(channelPrefix)) {
filteredPublicChannels.push(item); filteredPublicChannels.push(item);
} }
}); });
privateChannels.sort((a, b) => a.name.localeCompare(b.name)); privateChannels = privateChannels.sort(sortChannelsByDisplayName);
filteredPublicChannels.sort((a, b) => a.name.localeCompare(b.name)); filteredPublicChannels = filteredPublicChannels.sort(sortChannelsByDisplayName);
const channels = filteredPublicChannels.concat(privateChannels); const channels = filteredPublicChannels.concat(privateChannels);
const channelNames = channels.map((channel) => channel.name); const channelNames = channels.map((channel) => channel.name);

Просмотреть файл

@@ -12,6 +12,7 @@ import Client from 'client/web_client.jsx';
import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
import {Constants, ActionTypes} from 'utils/constants.jsx'; import {Constants, ActionTypes} from 'utils/constants.jsx';
import * as Utils from 'utils/utils.jsx'; import * as Utils from 'utils/utils.jsx';
import {sortChannelsByDisplayName} from 'utils/channel_utils.jsx';
import React from 'react'; import React from 'react';
@@ -105,19 +106,9 @@ export default class SwitchChannelProvider extends Provider {
userMap[user.id] = user; userMap[user.id] = user;
} }
channels.sort((a, b) => { const channelNames = channels.
if (a.display_name === b.display_name) { sort(sortChannelsByDisplayName).
if (a.type !== Constants.DM_CHANNEL && b.type === Constants.DM_CHANNEL) { map((channel) => channel.name);
return -1;
} else if (a.type === Constants.DM_CHANNEL && b.type !== Constants.DM_CHANNEL) {
return 1;
}
return a.name.localeCompare(b.name);
}
return a.display_name.localeCompare(b.display_name);
});
const channelNames = channels.map((channel) => channel.name);
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS, type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,

Просмотреть файл

@@ -118,21 +118,21 @@ export default class TeamSidebar extends React.Component {
} }
const teams = myTeams. const teams = myTeams.
sort((a, b) => a.display_name.localeCompare(b.display_name)). sort(Utils.sortTeamsByDisplayName).
map((team) => { map((team) => {
return ( return (
<TeamButton <TeamButton
key={'switch_team_' + team.name} key={'switch_team_' + team.name}
url={`/${team.name}`} url={`/${team.name}`}
tip={team.display_name} tip={team.display_name}
active={team.id === this.state.currentTeamId} active={team.id === this.state.currentTeamId}
isMobile={this.state.isMobile} isMobile={this.state.isMobile}
displayName={team.display_name} displayName={team.display_name}
unread={team.unread} unread={team.unread}
mentions={team.mentions} mentions={team.mentions}
/> />
); );
}); });
if (moreTeams) { if (moreTeams) {
teams.push( teams.push(

Просмотреть файл

@@ -204,10 +204,10 @@ class ChannelStoreClass extends EventEmitter {
} }
if (!Utils) { if (!Utils) {
Utils = require('utils/utils.jsx'); //eslint-disable-line global-require Utils = require('utils/channel_utils.jsx'); //eslint-disable-line global-require
} }
channels.sort(Utils.sortByDisplayName); channels = channels.sort(Utils.sortChannelsByDisplayName);
this.storeChannels(channels); this.storeChannels(channels);
} }
@@ -286,10 +286,10 @@ class ChannelStoreClass extends EventEmitter {
const teamChannels = this.moreChannels[teamId] || {}; const teamChannels = this.moreChannels[teamId] || {};
if (!Utils) { if (!Utils) {
Utils = require('utils/utils.jsx'); //eslint-disable-line global-require Utils = require('utils/channel_utils.jsx'); //eslint-disable-line global-require
} }
return Object.keys(teamChannels).map((cid) => teamChannels[cid]).sort(Utils.sortByDisplayName); return Object.keys(teamChannels).map((cid) => teamChannels[cid]).sort(Utils.sortChannelsByDisplayName);
} }
storeStats(stats) { storeStats(stats) {

Просмотреть файл

@@ -23,8 +23,11 @@ import LocalizationStore from 'stores/localization_store.jsx';
export function buildDisplayableChannelList(persistentChannels) { export function buildDisplayableChannelList(persistentChannels) {
const missingDMChannels = createMissingDirectChannels(persistentChannels); const missingDMChannels = createMissingDirectChannels(persistentChannels);
const channels = persistentChannels.concat(missingDMChannels).map(completeDirectChannelInfo).filter(isNotDeletedChannel); const channels = persistentChannels.
channels.sort(sortChannelsByDisplayName); concat(missingDMChannels).
map(completeDirectChannelInfo).
filter(isNotDeletedChannel).
sort(sortChannelsByDisplayName);
const favoriteChannels = channels.filter(isFavoriteChannel); const favoriteChannels = channels.filter(isFavoriteChannel);
const notFavoriteChannels = channels.filter(not(isFavoriteChannel)); const notFavoriteChannels = channels.filter(not(isFavoriteChannel));

Просмотреть файл

@@ -1093,25 +1093,15 @@ export function windowHeight() {
return $(window).height(); return $(window).height();
} }
// Use when sorting multiple channels or teams by their `display_name` field // Use when sorting multiple teams by their `display_name` field
export function sortByDisplayName(a, b) { export function sortTeamsByDisplayName(a, b) {
let aDisplayName = ''; const locale = LocalizationStore.getLocale();
let bDisplayName = '';
if (a && a.display_name) { if (a.display_name !== b.display_name) {
aDisplayName = a.display_name.toLowerCase(); return a.display_name.localeCompare(b.display_name, locale, {numeric: true});
}
if (b && b.display_name) {
bDisplayName = b.display_name.toLowerCase();
} }
if (aDisplayName < bDisplayName) { return a.name.localeCompare(b.name, locale, {numeric: true});
return -1;
}
if (aDisplayName > bDisplayName) {
return 1;
}
return 0;
} }
export function getChannelTerm(channelType) { export function getChannelTerm(channelType) {