input pill: Move user pill rendering code to user_pill.

This is part of a larger effort to refactor input_pill to
remove custom logic and move it into relevant modules.
This commit is contained in:
evykassirer
2024-07-29 15:22:57 -07:00
committed by Tim Abbott
parent aa0b150265
commit 2b7d14084b
5 changed files with 36 additions and 74 deletions

View File

@@ -1,17 +1,16 @@
import $ from "jquery";
import type {InputPillConfig} from "./input_pill";
import type {InputPillConfig, InputPillItem} from "./input_pill";
import * as input_pill from "./input_pill";
import type {User} from "./people";
import * as people from "./people";
import type {UserPillWidget} from "./user_pill";
import type {UserPill, UserPillWidget} from "./user_pill";
import * as user_pill from "./user_pill";
import * as util from "./util";
export let widget: UserPillWidget;
const pill_config: InputPillConfig = {
show_user_status_emoji: true,
exclude_inaccessible_users: true,
};
@@ -23,6 +22,8 @@ export function initialize_pill(): UserPillWidget {
pill_config,
create_item_from_text: user_pill.create_item_from_email,
get_text_from_item: user_pill.get_email_from_item,
generate_pill_html: (item: InputPillItem<UserPill>) =>
user_pill.generate_pill_html(item, true),
});
return pill;

View File

@@ -29,7 +29,6 @@ export type InputPillItem<ItemType> = {
} & ItemType;
export type InputPillConfig = {
show_user_status_emoji?: boolean;
exclude_inaccessible_users?: boolean;
};
@@ -70,13 +69,6 @@ type InputPillStore<ItemType> = {
type InputPillRenderingDetails = {
display_value: string;
has_image: boolean;
img_src?: string | undefined;
deactivated: boolean | undefined;
has_status?: boolean;
status_emoji_info?: (EmojiRenderingDetails & {emoji_alt_code?: boolean}) | undefined;
should_add_guest_user_indicator: boolean | undefined;
user_id?: number | undefined;
group_id?: number | undefined;
has_stream?: boolean;
stream?: StreamSubscription;
@@ -178,38 +170,18 @@ export function create<ItemType>(
if (store.generate_pill_html !== undefined) {
pill_html = store.generate_pill_html(item);
} else {
const has_image = item.img_src !== undefined;
const opts: InputPillRenderingDetails = {
display_value: item.display_value,
has_image,
deactivated: item.deactivated,
should_add_guest_user_indicator: item.should_add_guest_user_indicator,
};
if (item.user_id) {
opts.user_id = item.user_id;
}
if (item.group_id) {
opts.group_id = item.group_id;
}
if (has_image) {
opts.img_src = item.img_src;
}
if (item.type === "stream" && item.stream) {
opts.has_stream = true;
opts.stream = item.stream;
}
if (store.pill_config?.show_user_status_emoji === true) {
const has_status = item.status_emoji_info !== undefined;
if (has_status) {
opts.status_emoji_info = item.status_emoji_info;
}
opts.has_status = has_status;
}
pill_html = render_input_pill(opts);
}
const payload: InputPill<ItemType> = {

View File

@@ -1,3 +1,5 @@
import render_input_pill from "../templates/input_pill.hbs";
import * as blueslip from "./blueslip";
import type {InputPillConfig, InputPillContainer, InputPillItem} from "./input_pill";
import * as input_pill from "./input_pill";
@@ -159,6 +161,30 @@ export function append_user(user: User, pills: UserPillWidget | CombinedPillCont
}
}
export function generate_pill_html(
item: InputPillItem<UserPill>,
show_user_status_emoji = false,
): string {
let status_emoji_info;
let has_status;
if (show_user_status_emoji) {
has_status = item.status_emoji_info !== undefined;
if (has_status) {
status_emoji_info = item.status_emoji_info;
}
}
return render_input_pill({
display_value: item.display_value,
has_image: item.img_src !== undefined,
deactivated: item.deactivated,
should_add_guest_user_indicator: item.should_add_guest_user_indicator,
user_id: item.user_id,
img_src: item.img_src,
has_status,
status_emoji_info,
});
}
export function create_pills(
$pill_container: JQuery,
pill_config?: InputPillConfig | undefined,
@@ -168,6 +194,7 @@ export function create_pills(
pill_config,
create_item_from_text: create_item_from_email,
get_text_from_item: get_email_from_item,
generate_pill_html,
});
return pills;
}

View File

@@ -11,8 +11,6 @@ set_global("document", {});
class ClipboardEvent {}
set_global("ClipboardEvent", ClipboardEvent);
const example_img_link = "http://example.com/example.png";
mock_esm("../src/ui_util", {
place_caret_at_end: noop,
});
@@ -23,24 +21,10 @@ set_global("getSelection", () => ({
const input_pill = zrequire("input_pill");
function pill_html(value, img_src, status_emoji_info) {
const has_image = img_src !== undefined;
const has_status = status_emoji_info !== undefined;
function pill_html(value) {
const opts = {
display_value: value,
has_image,
has_status,
};
if (has_image) {
opts.img_src = img_src;
}
if (has_status) {
opts.status_emoji_info = status_emoji_info;
}
return require("../templates/input_pill.hbs")(opts);
}
@@ -58,24 +42,17 @@ run_test("basics", ({mock_template}) => {
$container,
create_item_from_text: noop,
get_text_from_item: noop,
pill_config: {
show_user_status_emoji: true,
},
});
const status_emoji_info = {emoji_code: "5"};
// type for a pill can be any string but it needs to be
// defined while creating any pill.
const item = {
display_value: "JavaScript",
language: "js",
type: "language",
img_src: example_img_link,
status_emoji_info,
};
let inserted_before;
const expected_html = pill_html("JavaScript", example_img_link, status_emoji_info);
const expected_html = pill_html("JavaScript");
$pill_input.before = ($elem) => {
inserted_before = true;
@@ -94,7 +71,6 @@ function set_up() {
display_value: "BLUE",
description: "color of the sky",
type: "color",
img_src: example_img_link,
},
red: {
@@ -172,10 +148,7 @@ run_test("copy from pill", ({mock_template}) => {
});
run_test("paste to input", ({mock_template}) => {
mock_template("input_pill.hbs", true, (data, html) => {
assert.equal(typeof data.has_image, "boolean");
return html;
});
mock_template("input_pill.hbs", true, (_data, html) => html);
const info = set_up();
const config = info.config;
@@ -219,10 +192,7 @@ run_test("paste to input", ({mock_template}) => {
});
run_test("arrows on pills", ({mock_template}) => {
mock_template("input_pill.hbs", true, (data, html) => {
assert.equal(typeof data.has_image, "boolean");
return html;
});
mock_template("input_pill.hbs", true, (_data, html) => html);
const info = set_up();
const config = info.config;
@@ -413,11 +383,7 @@ run_test("insert_remove", ({mock_template}) => {
assert.ok(created);
assert.ok(!removed);
assert.deepEqual(inserted_html, [
pill_html("BLUE", example_img_link),
pill_html("RED"),
pill_html("YELLOW"),
]);
assert.deepEqual(inserted_html, [pill_html("BLUE"), pill_html("RED"), pill_html("YELLOW")]);
assert.deepEqual(widget.items(), [items.blue, items.red, items.yellow]);
@@ -568,7 +534,6 @@ run_test("misc things", () => {
widget.appendValidatedData({
display_value: "This item has no type.",
language: "js",
img_src: example_img_link,
});
// click on container

View File

@@ -139,7 +139,6 @@ run_test("set_up_user", ({mock_template, override, override_rewire}) => {
});
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;
@@ -231,7 +230,6 @@ run_test("set_up_stream", ({mock_template, override, override_rewire}) => {
});
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;
@@ -319,7 +317,6 @@ run_test("set_up_combined", ({mock_template, override, override_rewire}) => {
override_typeahead_helper(override_rewire);
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;