Commit 216ae536 authored by Coung Ngo's avatar Coung Ngo Committed by Scott Hampton

Fix member autocomplete sort order

The @ autocomplete sort did not maintain participant
priority due to different browsers calling Array `sort`
methods slightly differently. Here we use lodash's
`sortBy` function which is a stable sort, and has the
added benefit of simplifying our logic
parent bf6c493c
import $ from 'jquery'; import $ from 'jquery';
import '~/lib/utils/jquery_at_who'; import '~/lib/utils/jquery_at_who';
import { escape, template } from 'lodash'; import { escape, sortBy, template } from 'lodash';
import * as Emoji from '~/emoji'; import * as Emoji from '~/emoji';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { s__, __, sprintf } from '~/locale'; import { s__, __, sprintf } from '~/locale';
...@@ -325,25 +325,7 @@ class GfmAutoComplete { ...@@ -325,25 +325,7 @@ class GfmAutoComplete {
return items; return items;
} }
const lowercaseQuery = query.toLowerCase(); return GfmAutoComplete.Members.sort(query, items);
const members = items.slice();
const { nameOrUsernameStartsWith, nameOrUsernameIncludes } = GfmAutoComplete.Members;
return members.sort((a, b) => {
if (nameOrUsernameStartsWith(a, lowercaseQuery)) {
return -1;
}
if (nameOrUsernameStartsWith(b, lowercaseQuery)) {
return 1;
}
if (nameOrUsernameIncludes(a, lowercaseQuery)) {
return -1;
}
if (nameOrUsernameIncludes(b, lowercaseQuery)) {
return 1;
}
return 0;
});
}, },
}, },
}); });
...@@ -837,6 +819,15 @@ GfmAutoComplete.Members = { ...@@ -837,6 +819,15 @@ GfmAutoComplete.Members = {
// `member.search` is a name:username string like `MargeSimpson msimpson` // `member.search` is a name:username string like `MargeSimpson msimpson`
return member.search.toLowerCase().includes(query); return member.search.toLowerCase().includes(query);
}, },
sort(query, members) {
const lowercaseQuery = query.toLowerCase();
const { nameOrUsernameStartsWith, nameOrUsernameIncludes } = GfmAutoComplete.Members;
return sortBy(members, [
(member) => (nameOrUsernameStartsWith(member, lowercaseQuery) ? -1 : 0),
(member) => (nameOrUsernameIncludes(member, lowercaseQuery) ? -1 : 0),
]);
},
}; };
GfmAutoComplete.Labels = { GfmAutoComplete.Labels = {
templateFunction(color, title) { templateFunction(color, title) {
......
---
title: Fix member autocomplete sort order
merge_request: 58652
author:
type: fixed
...@@ -665,6 +665,41 @@ describe('GfmAutoComplete', () => { ...@@ -665,6 +665,41 @@ describe('GfmAutoComplete', () => {
expect(GfmAutoComplete.Members.nameOrUsernameIncludes(member, query)).toBe(result); expect(GfmAutoComplete.Members.nameOrUsernameIncludes(member, query)).toBe(result);
}); });
}); });
describe('sorter', () => {
const query = 'c';
const items = [
{ search: 'DougHackett elayne.krieger' },
{ search: 'BerylHuel cherie.block' },
{ search: 'ErlindaMayert nicolle' },
{ search: 'Administrator root' },
{ search: 'PhoebeSchaden salina' },
{ search: 'CatherinTerry tommy.will' },
{ search: 'AntoineLedner ammie' },
{ search: 'KinaCummings robena' },
{ search: 'CharlsieHarber xzbdulia' },
];
const expected = [
// Members whose name/username starts with `c` are grouped first
{ search: 'BerylHuel cherie.block' },
{ search: 'CatherinTerry tommy.will' },
{ search: 'CharlsieHarber xzbdulia' },
// Members whose name/username contains `c` are grouped second
{ search: 'DougHackett elayne.krieger' },
{ search: 'ErlindaMayert nicolle' },
{ search: 'PhoebeSchaden salina' },
{ search: 'KinaCummings robena' },
// Remaining members are grouped last
{ search: 'Administrator root' },
{ search: 'AntoineLedner ammie' },
];
it('sorts by match with start of name/username, then match with any part of name/username, and maintains sort order', () => {
expect(GfmAutoComplete.Members.sort(query, items)).toMatchObject(expected);
});
});
}); });
}); });
......
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