mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Change ordering of at-mention suggestions (#3698)
List members in the current channel first.
This commit is contained in:
committed by
Joram Wilander
parent
bb0b895bad
commit
d6da7d1220
@@ -8,6 +8,7 @@ import ChannelStore from 'stores/channel_store.jsx';
|
||||
import UserStore from 'stores/user_store.jsx';
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
import Client from 'client/web_client.jsx';
|
||||
import Constants from 'utils/constants.jsx';
|
||||
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
import Suggestion from './suggestion.jsx';
|
||||
@@ -98,61 +99,92 @@ class AtMentionSuggestion extends Suggestion {
|
||||
}
|
||||
}
|
||||
|
||||
function filterUsersByPrefix(users, prefix, limit) {
|
||||
const filtered = [];
|
||||
|
||||
for (const id of Object.keys(users)) {
|
||||
if (filtered.length >= limit) {
|
||||
break;
|
||||
}
|
||||
|
||||
const user = users[id];
|
||||
|
||||
if (user.delete_at > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (user.username.startsWith(prefix) ||
|
||||
(user.first_name && user.first_name.toLowerCase().startsWith(prefix)) ||
|
||||
(user.last_name && user.last_name.toLowerCase().startsWith(prefix)) ||
|
||||
(user.nickname && user.nickname.toLowerCase().startsWith(prefix))) {
|
||||
filtered.push(user);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
export default class AtMentionProvider {
|
||||
handlePretextChanged(suggestionId, pretext) {
|
||||
const captured = (/@([a-z0-9\-\._]*)$/i).exec(pretext.toLowerCase());
|
||||
if (captured) {
|
||||
const prefix = captured[1];
|
||||
|
||||
// Group users into members and nonmembers of the channel.
|
||||
const users = UserStore.getActiveOnlyProfiles(true);
|
||||
|
||||
const filtered = [];
|
||||
|
||||
for (const id of Object.keys(users)) {
|
||||
const user = users[id];
|
||||
|
||||
if (user.delete_at > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (user.username.startsWith(prefix) ||
|
||||
(user.first_name && user.first_name.toLowerCase().startsWith(prefix)) ||
|
||||
(user.last_name && user.last_name.toLowerCase().startsWith(prefix)) ||
|
||||
(user.nickname && user.nickname.toLowerCase().startsWith(prefix))) {
|
||||
filtered.push(user);
|
||||
}
|
||||
|
||||
if (filtered.length >= MaxUserSuggestions) {
|
||||
break;
|
||||
const channelMembers = {};
|
||||
const extra = ChannelStore.getCurrentExtraInfo();
|
||||
for (let i = 0; i < extra.members.length; i++) {
|
||||
const id = extra.members[i].id;
|
||||
if (users[id]) {
|
||||
channelMembers[id] = users[id];
|
||||
Reflect.deleteProperty(users, id);
|
||||
}
|
||||
}
|
||||
const channelNonmembers = users;
|
||||
|
||||
// Filter users by prefix.
|
||||
const filteredMembers = filterUsersByPrefix(
|
||||
channelMembers, prefix, MaxUserSuggestions);
|
||||
const filteredNonmembers = filterUsersByPrefix(
|
||||
channelNonmembers, prefix, MaxUserSuggestions - filteredMembers.length);
|
||||
let filteredSpecialMentions = [];
|
||||
if (!pretext.startsWith('/msg')) {
|
||||
// add dummy users to represent the @channel and @all special mentions when not using the /msg command
|
||||
if ('channel'.startsWith(prefix)) {
|
||||
filtered.push({username: 'channel'});
|
||||
}
|
||||
if ('all'.startsWith(prefix)) {
|
||||
filtered.push({username: 'all'});
|
||||
}
|
||||
if ('here'.startsWith(prefix)) {
|
||||
filtered.push({username: 'here'});
|
||||
}
|
||||
filteredSpecialMentions = ['here', 'channel', 'all'].filter((item) => {
|
||||
return item.startsWith(prefix);
|
||||
}).map((name) => {
|
||||
return {username: name};
|
||||
});
|
||||
}
|
||||
|
||||
filtered.sort((a, b) => {
|
||||
const aPrefix = a.username.startsWith(prefix);
|
||||
const bPrefix = b.username.startsWith(prefix);
|
||||
// Sort users by username.
|
||||
[filteredMembers, filteredNonmembers].forEach((items) => {
|
||||
items.sort((a, b) => {
|
||||
const aPrefix = a.username.startsWith(prefix);
|
||||
const bPrefix = b.username.startsWith(prefix);
|
||||
|
||||
if (aPrefix === bPrefix) {
|
||||
return a.username.localeCompare(b.username);
|
||||
} else if (aPrefix) {
|
||||
return -1;
|
||||
}
|
||||
if (aPrefix === bPrefix) {
|
||||
return a.username.localeCompare(b.username);
|
||||
} else if (aPrefix) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
});
|
||||
});
|
||||
|
||||
filteredMembers.forEach((item) => {
|
||||
item.type = Constants.MENTION_MEMBERS;
|
||||
});
|
||||
filteredNonmembers.forEach((item) => {
|
||||
item.type = Constants.MENTION_NONMEMBERS;
|
||||
});
|
||||
filteredSpecialMentions.forEach((item) => {
|
||||
item.type = Constants.MENTION_SPECIAL;
|
||||
});
|
||||
|
||||
const filtered = filteredMembers.concat(filteredSpecialMentions).concat(filteredNonmembers);
|
||||
|
||||
const mentions = filtered.map((user) => '@' + user.username);
|
||||
|
||||
SuggestionStore.addSuggestions(suggestionId, mentions, filtered, AtMentionSuggestion, captured[0]);
|
||||
|
||||
@@ -5,6 +5,7 @@ import $ from 'jquery';
|
||||
import ReactDOM from 'react-dom';
|
||||
import * as GlobalActions from 'actions/global_actions.jsx';
|
||||
import SuggestionStore from 'stores/suggestion_store.jsx';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@@ -92,19 +93,39 @@ export default class SuggestionList extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
renderDivider(type) {
|
||||
return (
|
||||
<div
|
||||
key={type + '-divider'}
|
||||
className='suggestion-list__divider'
|
||||
>
|
||||
<span>
|
||||
<FormattedMessage id={'suggestion.' + type}/>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.items.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const items = [];
|
||||
let lastType;
|
||||
for (let i = 0; i < this.state.items.length; i++) {
|
||||
const item = this.state.items[i];
|
||||
const term = this.state.terms[i];
|
||||
const isSelection = term === this.state.selection;
|
||||
|
||||
// ReactComponent names need to be upper case when used in JSX
|
||||
const Component = this.state.components[i];
|
||||
|
||||
if (item.type !== lastType) {
|
||||
items.push(this.renderDivider(item.type));
|
||||
lastType = item.type;
|
||||
}
|
||||
|
||||
items.push(
|
||||
<Component
|
||||
key={term}
|
||||
|
||||
@@ -1538,6 +1538,9 @@
|
||||
"suggestion.mention.all": "Notifies everyone in the channel, use in {townsquare} to notify the whole team",
|
||||
"suggestion.mention.channel": "Notifies everyone in the channel",
|
||||
"suggestion.mention.here": "Notifies everyone in the channel and online",
|
||||
"suggestion.mention.members": "Channel Members",
|
||||
"suggestion.mention.nonmembers": "Not in Channel",
|
||||
"suggestion.mention.special": "Special Mentions",
|
||||
"suggestion.search.private": "Private Groups",
|
||||
"suggestion.search.public": "Public Channels",
|
||||
"team_export_tab.download": "download",
|
||||
|
||||
@@ -44,3 +44,33 @@
|
||||
.suggestion-list--bottom {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.suggestion-list__divider {
|
||||
line-height: 21px;
|
||||
margin: 5px 0px 0px 5px;
|
||||
position: relative;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
> span {
|
||||
color: rgba(51,51,51,0.7);
|
||||
background: #f2f4f8;
|
||||
display: inline-block;
|
||||
padding-right: 10px;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
&:before {
|
||||
@include opacity(.2);
|
||||
background: $dark-gray;
|
||||
content: '';
|
||||
height: 1px;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -797,7 +797,10 @@ export const Constants = {
|
||||
LICENSE_GRACE_PERIOD: 1000 * 60 * 60 * 24 * 15, // 15 days
|
||||
PERMISSIONS_ALL: 'all',
|
||||
PERMISSIONS_TEAM_ADMIN: 'team_admin',
|
||||
PERMISSIONS_SYSTEM_ADMIN: 'system_admin'
|
||||
PERMISSIONS_SYSTEM_ADMIN: 'system_admin',
|
||||
MENTION_MEMBERS: 'mention.members',
|
||||
MENTION_NONMEMBERS: 'mention.nonmembers',
|
||||
MENTION_SPECIAL: 'mention.special'
|
||||
};
|
||||
|
||||
export default Constants;
|
||||
|
||||
Reference in New Issue
Block a user