mirror of https://github.com/zulip/zulip.git
pill_typeahead: Separate user-only typeahead to specialized function.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
512f4d1476
commit
e6bfaed782
|
@ -56,7 +56,7 @@ function set_up_pill_typeahead({
|
||||||
user_group: true,
|
user_group: true,
|
||||||
user: true,
|
user: true,
|
||||||
};
|
};
|
||||||
pill_typeahead.set_up($pill_container.find(".input"), pill_widget, opts);
|
pill_typeahead.set_up_combined($pill_container.find(".input"), pill_widget, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function create({
|
export function create({
|
||||||
|
|
|
@ -117,15 +117,14 @@ export function initialize_custom_user_type_fields(
|
||||||
const update_func = () => pill_update_handler(field, pills);
|
const update_func = () => pill_update_handler(field, pills);
|
||||||
const opts = {
|
const opts = {
|
||||||
update_func,
|
update_func,
|
||||||
user: true,
|
|
||||||
exclude_bots: true,
|
exclude_bots: true,
|
||||||
};
|
};
|
||||||
pill_typeahead.set_up($input, pills, opts);
|
pill_typeahead.set_up_user($input, pills, opts);
|
||||||
pills.onPillRemove(() => {
|
pills.onPillRemove(() => {
|
||||||
pill_update_handler(field, pills);
|
pill_update_handler(field, pills);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
pill_typeahead.set_up($input, pills, {user: true, exclude_bots: true});
|
pill_typeahead.set_up_user($input, pills, {exclude_bots: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
user_pills.set(field.id, pills);
|
user_pills.set(field.id, pills);
|
||||||
|
|
|
@ -12,7 +12,7 @@ import type {CombinedPillContainer} from "./typeahead_helper";
|
||||||
import * as user_group_pill from "./user_group_pill";
|
import * as user_group_pill from "./user_group_pill";
|
||||||
import type {UserGroupPillData} from "./user_group_pill";
|
import type {UserGroupPillData} from "./user_group_pill";
|
||||||
import * as user_pill from "./user_pill";
|
import * as user_pill from "./user_pill";
|
||||||
import type {UserPillData} from "./user_pill";
|
import type {UserPillData, UserPillWidget} from "./user_pill";
|
||||||
|
|
||||||
function person_matcher(query: string, item: UserPillData): boolean {
|
function person_matcher(query: string, item: UserPillData): boolean {
|
||||||
return (
|
return (
|
||||||
|
@ -27,7 +27,52 @@ function group_matcher(query: string, item: UserGroupPillData): boolean {
|
||||||
|
|
||||||
type TypeaheadItem = UserGroupPillData | StreamPillData | UserPillData;
|
type TypeaheadItem = UserGroupPillData | StreamPillData | UserPillData;
|
||||||
|
|
||||||
export function set_up(
|
export function set_up_user(
|
||||||
|
$input: JQuery,
|
||||||
|
pills: UserPillWidget,
|
||||||
|
opts: {
|
||||||
|
exclude_bots?: boolean;
|
||||||
|
update_func?: () => void;
|
||||||
|
},
|
||||||
|
): void {
|
||||||
|
const exclude_bots = opts.exclude_bots;
|
||||||
|
const bootstrap_typeahead_input: TypeaheadInputElement = {
|
||||||
|
$element: $input,
|
||||||
|
type: "contenteditable",
|
||||||
|
};
|
||||||
|
new Typeahead(bootstrap_typeahead_input, {
|
||||||
|
items: 5,
|
||||||
|
dropup: true,
|
||||||
|
source(_query: string): UserPillData[] {
|
||||||
|
return user_pill.typeahead_source(pills, exclude_bots);
|
||||||
|
},
|
||||||
|
highlighter_html(item: UserPillData, _query: string): string {
|
||||||
|
return typeahead_helper.render_person(item);
|
||||||
|
},
|
||||||
|
matcher(item: UserPillData, query: string): boolean {
|
||||||
|
query = query.toLowerCase();
|
||||||
|
query = query.replaceAll("\u00A0", " ");
|
||||||
|
return person_matcher(query, item);
|
||||||
|
},
|
||||||
|
sorter(matches: UserPillData[], query: string): UserPillData[] {
|
||||||
|
const users = matches.filter((match) => people.is_known_user_id(match.user.user_id));
|
||||||
|
return typeahead_helper.sort_recipients({users, query}).map((item) => {
|
||||||
|
assert(item.type === "user");
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
updater(item: UserPillData, _query: string): undefined {
|
||||||
|
if (people.is_known_user_id(item.user.user_id)) {
|
||||||
|
user_pill.append_user(item.user, pills);
|
||||||
|
}
|
||||||
|
$input.trigger("focus");
|
||||||
|
opts.update_func?.();
|
||||||
|
},
|
||||||
|
stopAdvance: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function set_up_combined(
|
||||||
$input: JQuery,
|
$input: JQuery,
|
||||||
pills: CombinedPillContainer,
|
pills: CombinedPillContainer,
|
||||||
opts: {
|
opts: {
|
||||||
|
|
|
@ -132,7 +132,7 @@ export function has_unconverted_data(pill_widget: UserPillWidget): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function typeahead_source(
|
export function typeahead_source(
|
||||||
pill_widget: CombinedPillContainer,
|
pill_widget: UserPillWidget | CombinedPillContainer,
|
||||||
exclude_bots?: boolean,
|
exclude_bots?: boolean,
|
||||||
): UserPillData[] {
|
): UserPillData[] {
|
||||||
const users = exclude_bots ? people.get_realm_active_human_users() : people.get_realm_users();
|
const users = exclude_bots ? people.get_realm_active_human_users() : people.get_realm_users();
|
||||||
|
@ -148,7 +148,7 @@ export function filter_taken_users(
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function append_user(user: User, pills: CombinedPillContainer): void {
|
export function append_user(user: User, pills: UserPillWidget | CombinedPillContainer): void {
|
||||||
if (user) {
|
if (user) {
|
||||||
append_person({
|
append_person({
|
||||||
pill_widget: pills,
|
pill_widget: pills,
|
||||||
|
|
|
@ -33,8 +33,9 @@ function override_typeahead_helper(override_rewire) {
|
||||||
override_rewire(typeahead_helper, "sort_streams", () => {
|
override_rewire(typeahead_helper, "sort_streams", () => {
|
||||||
sort_streams_called = true;
|
sort_streams_called = true;
|
||||||
});
|
});
|
||||||
override_rewire(typeahead_helper, "sort_recipients", () => {
|
override_rewire(typeahead_helper, "sort_recipients", ({users}) => {
|
||||||
sort_recipients_called = true;
|
sort_recipients_called = true;
|
||||||
|
return users;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +131,100 @@ for (const sub of subs) {
|
||||||
stream_data.add_sub(sub);
|
stream_data.add_sub(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
run_test("set_up", ({mock_template, override, override_rewire}) => {
|
run_test("set_up_user", ({mock_template, override, override_rewire}) => {
|
||||||
|
override_rewire(typeahead_helper, "render_person", () => $fake_rendered_person);
|
||||||
|
override_rewire(typeahead_helper, "sort_recipients", ({users}) => {
|
||||||
|
sort_recipients_called = true;
|
||||||
|
return users;
|
||||||
|
});
|
||||||
|
mock_template("input_pill.hbs", true, (data, html) => {
|
||||||
|
assert.equal(typeof data.display_value, "string");
|
||||||
|
assert.equal(typeof data.has_image, "boolean");
|
||||||
|
return html;
|
||||||
|
});
|
||||||
|
let input_pill_typeahead_called = false;
|
||||||
|
const $fake_input = $.create(".input");
|
||||||
|
$fake_input.before = noop;
|
||||||
|
|
||||||
|
const $container = $.create(".pill-container");
|
||||||
|
$container.find = () => $fake_input;
|
||||||
|
|
||||||
|
const $pill_widget = input_pill.create({
|
||||||
|
$container,
|
||||||
|
create_item_from_text: noop,
|
||||||
|
get_text_from_item: noop,
|
||||||
|
});
|
||||||
|
|
||||||
|
let update_func_called = false;
|
||||||
|
function update_func() {
|
||||||
|
update_func_called = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
override(bootstrap_typeahead, "Typeahead", (input_element, config) => {
|
||||||
|
assert.equal(input_element.$element, $fake_input);
|
||||||
|
assert.equal(config.items, 5);
|
||||||
|
assert.ok(config.dropup);
|
||||||
|
assert.ok(config.stopAdvance);
|
||||||
|
|
||||||
|
assert.equal(typeof config.source, "function");
|
||||||
|
assert.equal(typeof config.highlighter_html, "function");
|
||||||
|
assert.equal(typeof config.matcher, "function");
|
||||||
|
assert.equal(typeof config.sorter, "function");
|
||||||
|
assert.equal(typeof config.updater, "function");
|
||||||
|
|
||||||
|
// test queries
|
||||||
|
const person_query = "me";
|
||||||
|
|
||||||
|
(function test_highlighter() {
|
||||||
|
assert.equal(config.highlighter_html(me_item, person_query), $fake_rendered_person);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function test_matcher() {
|
||||||
|
let result;
|
||||||
|
result = config.matcher(me_item, person_query);
|
||||||
|
assert.ok(result);
|
||||||
|
result = config.matcher(jill_item, person_query);
|
||||||
|
assert.ok(!result);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function test_sorter() {
|
||||||
|
sort_recipients_called = false;
|
||||||
|
config.sorter([me_item], person_query);
|
||||||
|
assert.ok(sort_recipients_called);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function test_source() {
|
||||||
|
let expected_result = [];
|
||||||
|
let actual_result = [];
|
||||||
|
const result = config.source(person_query);
|
||||||
|
actual_result = result.map((item) => item.user_id);
|
||||||
|
expected_result = [...expected_result, ...person_items];
|
||||||
|
expected_result = expected_result.map((item) => item.user_id);
|
||||||
|
assert.deepEqual(actual_result, expected_result);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function test_updater() {
|
||||||
|
function number_of_pills() {
|
||||||
|
const pills = $pill_widget.items();
|
||||||
|
return pills.length;
|
||||||
|
}
|
||||||
|
assert.equal(number_of_pills(), 0);
|
||||||
|
config.updater(me_item, person_query);
|
||||||
|
assert.equal(number_of_pills(), 1);
|
||||||
|
|
||||||
|
assert.ok(update_func_called);
|
||||||
|
})();
|
||||||
|
|
||||||
|
// input_pill_typeahead_called is set true if
|
||||||
|
// no exception occurs in pill_typeahead.set_up_user.
|
||||||
|
input_pill_typeahead_called = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
pill_typeahead.set_up_user($fake_input, $pill_widget, {update_func});
|
||||||
|
assert.ok(input_pill_typeahead_called);
|
||||||
|
});
|
||||||
|
|
||||||
|
run_test("set_up_combined", ({mock_template, override, override_rewire}) => {
|
||||||
override_typeahead_helper(override_rewire);
|
override_typeahead_helper(override_rewire);
|
||||||
mock_template("input_pill.hbs", true, (data, html) => {
|
mock_template("input_pill.hbs", true, (data, html) => {
|
||||||
assert.equal(typeof data.display_value, "string");
|
assert.equal(typeof data.display_value, "string");
|
||||||
|
@ -328,12 +422,12 @@ run_test("set_up", ({mock_template, override, override_rewire}) => {
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// input_pill_typeahead_called is set true if
|
// input_pill_typeahead_called is set true if
|
||||||
// no exception occurs in pill_typeahead.set_up.
|
// no exception occurs in pill_typeahead.set_up_combined.
|
||||||
input_pill_typeahead_called = true;
|
input_pill_typeahead_called = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
function test_pill_typeahead(opts) {
|
function test_pill_typeahead(opts) {
|
||||||
pill_typeahead.set_up($fake_input, $pill_widget, opts);
|
pill_typeahead.set_up_combined($fake_input, $pill_widget, opts);
|
||||||
assert.ok(input_pill_typeahead_called);
|
assert.ok(input_pill_typeahead_called);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,6 +459,6 @@ run_test("set_up", ({mock_template, override, override_rewire}) => {
|
||||||
opts = {};
|
opts = {};
|
||||||
input_pill_typeahead_called = false;
|
input_pill_typeahead_called = false;
|
||||||
blueslip.expect("error", "Unspecified possible item types");
|
blueslip.expect("error", "Unspecified possible item types");
|
||||||
pill_typeahead.set_up($fake_input, $pill_widget, {});
|
pill_typeahead.set_up_combined($fake_input, $pill_widget, {});
|
||||||
assert.ok(!input_pill_typeahead_called);
|
assert.ok(!input_pill_typeahead_called);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue