mirror of https://github.com/zulip/zulip.git
input_pill: Remove display_value in favor of module-specific values.
This commit is part of a bigger project to remove custom logic in the input_pill module. This commit move us away from a world where we have a `display_value` that's used as identifying information for a pill as well as for what we display to the user. Now individual widgets can configure how they come up with a display value based on the data of that type of pill. Note: The change in the stream pill test for setting subscribers for denmark is fixing an issue that wasn't discoverable before. There always should have been three subscribers.
This commit is contained in:
parent
7dfb928277
commit
6e47d851ec
|
@ -23,6 +23,7 @@ var pills = input_pill.create({
|
||||||
$container: $pill_container,
|
$container: $pill_container,
|
||||||
create_item_from_text: user_pill.create_item_from_email,
|
create_item_from_text: user_pill.create_item_from_email,
|
||||||
get_text_from_item: user_pill.get_email_from_item,
|
get_text_from_item: user_pill.get_email_from_item,
|
||||||
|
get_display_value_from_item: user_pill.get_display_value_from_item,
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -30,8 +31,7 @@ You can look at `web/src/user_pill.ts` to see how the above
|
||||||
methods are implemented. Essentially you just need to convert
|
methods are implemented. Essentially you just need to convert
|
||||||
from raw data (like an email) to structured data (like an object
|
from raw data (like an email) to structured data (like an object
|
||||||
with display_value, email, and user_id for a user), and vice
|
with display_value, email, and user_id for a user), and vice
|
||||||
versa. The most important field to supply is `display_value`.
|
versa.
|
||||||
For user pills `pill_item.display_value === user.full_name`.
|
|
||||||
|
|
||||||
## Typeahead
|
## Typeahead
|
||||||
|
|
||||||
|
|
|
@ -66,10 +66,20 @@ function set_up_pill_typeahead({
|
||||||
pill_typeahead.set_up_combined($pill_container.find(".input"), pill_widget, opts);
|
pill_typeahead.set_up_combined($pill_container.find(".input"), pill_widget, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_display_value_from_item(item: InputPillItem<CombinedPill>): string {
|
||||||
|
if (item.type === "user_group") {
|
||||||
|
return user_group_pill.display_pill(user_groups.get_user_group_from_id(item.group_id));
|
||||||
|
} else if (item.type === "stream") {
|
||||||
|
return stream_pill.get_display_value_from_item(item);
|
||||||
|
}
|
||||||
|
assert(item.type === "user");
|
||||||
|
return user_pill.get_display_value_from_item(item);
|
||||||
|
}
|
||||||
|
|
||||||
function generate_pill_html(item: InputPillItem<CombinedPill>): string {
|
function generate_pill_html(item: InputPillItem<CombinedPill>): string {
|
||||||
if (item.type === "user_group") {
|
if (item.type === "user_group") {
|
||||||
return render_input_pill({
|
return render_input_pill({
|
||||||
display_value: item.display_value,
|
display_value: get_display_value_from_item(item),
|
||||||
group_id: item.group_id,
|
group_id: item.group_id,
|
||||||
});
|
});
|
||||||
} else if (item.type === "user") {
|
} else if (item.type === "user") {
|
||||||
|
@ -79,6 +89,7 @@ function generate_pill_html(item: InputPillItem<CombinedPill>): string {
|
||||||
return render_input_pill({
|
return render_input_pill({
|
||||||
...item,
|
...item,
|
||||||
has_stream: true,
|
has_stream: true,
|
||||||
|
display_value: get_display_value_from_item(item),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +104,7 @@ export function create({
|
||||||
$container: $pill_container,
|
$container: $pill_container,
|
||||||
create_item_from_text,
|
create_item_from_text,
|
||||||
get_text_from_item,
|
get_text_from_item,
|
||||||
|
get_display_value_from_item,
|
||||||
generate_pill_html,
|
generate_pill_html,
|
||||||
});
|
});
|
||||||
function get_users(): User[] {
|
function get_users(): User[] {
|
||||||
|
@ -138,6 +150,7 @@ export function create_without_add_button({
|
||||||
$container: $pill_container,
|
$container: $pill_container,
|
||||||
create_item_from_text,
|
create_item_from_text,
|
||||||
get_text_from_item,
|
get_text_from_item,
|
||||||
|
get_display_value_from_item,
|
||||||
generate_pill_html,
|
generate_pill_html,
|
||||||
});
|
});
|
||||||
function get_users(): User[] {
|
function get_users(): User[] {
|
||||||
|
|
|
@ -22,6 +22,7 @@ export function initialize_pill(): UserPillWidget {
|
||||||
pill_config,
|
pill_config,
|
||||||
create_item_from_text: user_pill.create_item_from_email,
|
create_item_from_text: user_pill.create_item_from_email,
|
||||||
get_text_from_item: user_pill.get_email_from_item,
|
get_text_from_item: user_pill.get_email_from_item,
|
||||||
|
get_display_value_from_item: user_pill.get_display_value_from_item,
|
||||||
generate_pill_html: (item: InputPillItem<UserPill>) =>
|
generate_pill_html: (item: InputPillItem<UserPill>) =>
|
||||||
user_pill.generate_pill_html(item, true),
|
user_pill.generate_pill_html(item, true),
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,7 +24,6 @@ export function create_item_from_email(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "email",
|
type: "email",
|
||||||
display_value: email,
|
|
||||||
email,
|
email,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -52,6 +51,7 @@ export function create_pills(
|
||||||
pill_config,
|
pill_config,
|
||||||
create_item_from_text: create_item_from_email,
|
create_item_from_text: create_item_from_email,
|
||||||
get_text_from_item: get_email_from_item,
|
get_text_from_item: get_email_from_item,
|
||||||
|
get_display_value_from_item: get_email_from_item,
|
||||||
});
|
});
|
||||||
return pill_container;
|
return pill_container;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,7 @@ import * as ui_util from "./ui_util";
|
||||||
// See https://zulip.readthedocs.io/en/latest/subsystems/input-pills.html
|
// See https://zulip.readthedocs.io/en/latest/subsystems/input-pills.html
|
||||||
|
|
||||||
export type InputPillItem<ItemType> = {
|
export type InputPillItem<ItemType> = {
|
||||||
display_value: string;
|
|
||||||
type: string;
|
type: string;
|
||||||
// Used for search pills
|
|
||||||
operator?: string;
|
|
||||||
} & ItemType;
|
} & ItemType;
|
||||||
|
|
||||||
export type InputPillConfig = {
|
export type InputPillConfig = {
|
||||||
|
@ -34,6 +31,7 @@ type InputPillCreateOptions<ItemType> = {
|
||||||
pill_config?: InputPillConfig | undefined,
|
pill_config?: InputPillConfig | undefined,
|
||||||
) => InputPillItem<ItemType> | undefined;
|
) => InputPillItem<ItemType> | undefined;
|
||||||
get_text_from_item: (item: InputPillItem<ItemType>) => string;
|
get_text_from_item: (item: InputPillItem<ItemType>) => string;
|
||||||
|
get_display_value_from_item: (item: InputPillItem<ItemType>) => string;
|
||||||
generate_pill_html?: (item: InputPillItem<ItemType>) => string;
|
generate_pill_html?: (item: InputPillItem<ItemType>) => string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,6 +48,7 @@ type InputPillStore<ItemType> = {
|
||||||
$input: JQuery;
|
$input: JQuery;
|
||||||
create_item_from_text: InputPillCreateOptions<ItemType>["create_item_from_text"];
|
create_item_from_text: InputPillCreateOptions<ItemType>["create_item_from_text"];
|
||||||
get_text_from_item: InputPillCreateOptions<ItemType>["get_text_from_item"];
|
get_text_from_item: InputPillCreateOptions<ItemType>["get_text_from_item"];
|
||||||
|
get_display_value_from_item: InputPillCreateOptions<ItemType>["get_display_value_from_item"];
|
||||||
generate_pill_html: InputPillCreateOptions<ItemType>["generate_pill_html"];
|
generate_pill_html: InputPillCreateOptions<ItemType>["generate_pill_html"];
|
||||||
onPillCreate?: () => void;
|
onPillCreate?: () => void;
|
||||||
onPillRemove?: (pill: InputPill<ItemType>, trigger: RemovePillTrigger) => void;
|
onPillRemove?: (pill: InputPill<ItemType>, trigger: RemovePillTrigger) => void;
|
||||||
|
@ -58,10 +57,6 @@ type InputPillStore<ItemType> = {
|
||||||
convert_to_pill_on_enter: boolean;
|
convert_to_pill_on_enter: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type InputPillRenderingDetails = {
|
|
||||||
display_value: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
// These are the functions that are exposed to other modules.
|
// These are the functions that are exposed to other modules.
|
||||||
export type InputPillContainer<ItemType> = {
|
export type InputPillContainer<ItemType> = {
|
||||||
appendValue: (text: string) => void;
|
appendValue: (text: string) => void;
|
||||||
|
@ -95,6 +90,7 @@ export function create<ItemType>(
|
||||||
$input: opts.$container.find(".input").expectOne(),
|
$input: opts.$container.find(".input").expectOne(),
|
||||||
create_item_from_text: opts.create_item_from_text,
|
create_item_from_text: opts.create_item_from_text,
|
||||||
get_text_from_item: opts.get_text_from_item,
|
get_text_from_item: opts.get_text_from_item,
|
||||||
|
get_display_value_from_item: opts.get_display_value_from_item,
|
||||||
split_text_on_comma: opts.split_text_on_comma ?? true,
|
split_text_on_comma: opts.split_text_on_comma ?? true,
|
||||||
convert_to_pill_on_enter: opts.convert_to_pill_on_enter ?? true,
|
convert_to_pill_on_enter: opts.convert_to_pill_on_enter ?? true,
|
||||||
generate_pill_html: opts.generate_pill_html,
|
generate_pill_html: opts.generate_pill_html,
|
||||||
|
@ -134,7 +130,7 @@ export function create<ItemType>(
|
||||||
const existing_items = funcs.items();
|
const existing_items = funcs.items();
|
||||||
const item = store.create_item_from_text(text, existing_items, store.pill_config);
|
const item = store.create_item_from_text(text, existing_items, store.pill_config);
|
||||||
|
|
||||||
if (!item?.display_value) {
|
if (!item) {
|
||||||
store.$input.addClass("shake");
|
store.$input.addClass("shake");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -145,11 +141,6 @@ export function create<ItemType>(
|
||||||
// This is generally called by typeahead logic, where we have all
|
// This is generally called by typeahead logic, where we have all
|
||||||
// the data we need (as opposed to, say, just a user-typed email).
|
// the data we need (as opposed to, say, just a user-typed email).
|
||||||
appendValidatedData(item: InputPillItem<ItemType>) {
|
appendValidatedData(item: InputPillItem<ItemType>) {
|
||||||
if (!item.display_value) {
|
|
||||||
blueslip.error("no display_value returned");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!item.type) {
|
if (!item.type) {
|
||||||
blueslip.error("no type defined for the item");
|
blueslip.error("no type defined for the item");
|
||||||
return;
|
return;
|
||||||
|
@ -158,10 +149,9 @@ export function create<ItemType>(
|
||||||
if (store.generate_pill_html !== undefined) {
|
if (store.generate_pill_html !== undefined) {
|
||||||
pill_html = store.generate_pill_html(item);
|
pill_html = store.generate_pill_html(item);
|
||||||
} else {
|
} else {
|
||||||
const opts: InputPillRenderingDetails = {
|
pill_html = render_input_pill({
|
||||||
display_value: item.display_value,
|
display_value: store.get_display_value_from_item(item),
|
||||||
};
|
});
|
||||||
pill_html = render_input_pill(opts);
|
|
||||||
}
|
}
|
||||||
const payload: InputPill<ItemType> = {
|
const payload: InputPill<ItemType> = {
|
||||||
item,
|
item,
|
||||||
|
@ -258,13 +248,6 @@ export function create<ItemType>(
|
||||||
}
|
}
|
||||||
assert(user_idx !== undefined);
|
assert(user_idx !== undefined);
|
||||||
user_pill_container.users.splice(user_idx, 1);
|
user_pill_container.users.splice(user_idx, 1);
|
||||||
const sign = user_pill_container.negated ? "-" : "";
|
|
||||||
const search_string =
|
|
||||||
sign +
|
|
||||||
user_pill_container.operator +
|
|
||||||
":" +
|
|
||||||
user_pill_container.users.map((user) => user.email).join(",");
|
|
||||||
user_pill_container.display_value = search_string;
|
|
||||||
|
|
||||||
// Remove the user pill from the DOM.
|
// Remove the user pill from the DOM.
|
||||||
const $user_pill = $(store.pills[container_idx]!.$element.children(".pill")[user_idx]!);
|
const $user_pill = $(store.pills[container_idx]!.$element.children(".pill")[user_idx]!);
|
||||||
|
|
|
@ -346,6 +346,7 @@ function open_invite_user_modal(e: JQuery.ClickEvent<Document, undefined>): void
|
||||||
$container: $pill_container,
|
$container: $pill_container,
|
||||||
create_item_from_text: email_pill.create_item_from_email,
|
create_item_from_text: email_pill.create_item_from_email,
|
||||||
get_text_from_item: email_pill.get_email_from_item,
|
get_text_from_item: email_pill.get_email_from_item,
|
||||||
|
get_display_value_from_item: email_pill.get_email_from_item,
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#invite-user-modal .dialog_submit_button").prop("disabled", true);
|
$("#invite-user-modal .dialog_submit_button").prop("disabled", true);
|
||||||
|
|
|
@ -55,8 +55,9 @@ export function create($stream_pill_container: JQuery): stream_pill.StreamPillWi
|
||||||
render_input_pill({
|
render_input_pill({
|
||||||
...item,
|
...item,
|
||||||
has_stream: true,
|
has_stream: true,
|
||||||
display_value: stream_pill.get_display_string_from_item(item),
|
display_value: stream_pill.get_display_value_from_item(item),
|
||||||
}),
|
}),
|
||||||
|
get_display_value_from_item: stream_pill.get_display_value_from_item,
|
||||||
});
|
});
|
||||||
add_default_stream_pills(pill_widget);
|
add_default_stream_pills(pill_widget);
|
||||||
set_up_pill_typeahead({pill_widget, $pill_container: $stream_pill_container});
|
set_up_pill_typeahead({pill_widget, $pill_container: $stream_pill_container});
|
||||||
|
|
|
@ -16,11 +16,6 @@ import type {UserStatusEmojiInfo} from "./user_status";
|
||||||
export type SearchUserPill = {
|
export type SearchUserPill = {
|
||||||
type: "search_user";
|
type: "search_user";
|
||||||
operator: string;
|
operator: string;
|
||||||
// TODO: It would be nice if we just call this `search_string` instead of
|
|
||||||
// `display_value`, because we don't actually display this value for user
|
|
||||||
// pills, but `display_value` is needed to hook into the generic input pill
|
|
||||||
// logic and it would be a decent amount of work to change that.
|
|
||||||
display_value: string;
|
|
||||||
negated: boolean;
|
negated: boolean;
|
||||||
users: {
|
users: {
|
||||||
display_value: string;
|
display_value: string;
|
||||||
|
@ -36,7 +31,6 @@ export type SearchUserPill = {
|
||||||
type SearchPill =
|
type SearchPill =
|
||||||
| {
|
| {
|
||||||
type: "search";
|
type: "search";
|
||||||
display_value: string;
|
|
||||||
operator: string;
|
operator: string;
|
||||||
operand: string;
|
operand: string;
|
||||||
negated: boolean | undefined;
|
negated: boolean | undefined;
|
||||||
|
@ -54,7 +48,6 @@ export function create_item_from_search_string(search_string: string): SearchPil
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
display_value: search_string,
|
|
||||||
type: "search",
|
type: "search",
|
||||||
operator: search_term.operator,
|
operator: search_term.operator,
|
||||||
operand: search_term.operand,
|
operand: search_term.operand,
|
||||||
|
@ -83,6 +76,7 @@ export function create_pills($pill_container: JQuery): SearchPillWidget {
|
||||||
display_value,
|
display_value,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
get_display_value_from_item: get_search_string_from_item,
|
||||||
});
|
});
|
||||||
// We don't automatically create pills on paste. When the user
|
// We don't automatically create pills on paste. When the user
|
||||||
// presses enter, we validate the input then.
|
// presses enter, we validate the input then.
|
||||||
|
@ -96,12 +90,9 @@ function append_user_pill(
|
||||||
operator: string,
|
operator: string,
|
||||||
negated: boolean,
|
negated: boolean,
|
||||||
): void {
|
): void {
|
||||||
const sign = negated ? "-" : "";
|
|
||||||
const search_string = sign + operator + ":" + users.map((user) => user.email).join(",");
|
|
||||||
const pill_data: SearchUserPill = {
|
const pill_data: SearchUserPill = {
|
||||||
type: "search_user",
|
type: "search_user",
|
||||||
operator,
|
operator,
|
||||||
display_value: search_string,
|
|
||||||
negated,
|
negated,
|
||||||
users: users.map((user) => ({
|
users: users.map((user) => ({
|
||||||
display_value: user.full_name,
|
display_value: user.full_name,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import assert from "minimalistic-assert";
|
||||||
|
|
||||||
import {$t} from "./i18n";
|
import {$t} from "./i18n";
|
||||||
import type {InputPillContainer, InputPillItem} from "./input_pill";
|
import type {InputPillContainer, InputPillItem} from "./input_pill";
|
||||||
import * as peer_data from "./peer_data";
|
import * as peer_data from "./peer_data";
|
||||||
|
@ -8,6 +10,7 @@ import type {CombinedPillContainer, CombinedPillItem} from "./typeahead_helper";
|
||||||
export type StreamPill = {
|
export type StreamPill = {
|
||||||
type: "stream";
|
type: "stream";
|
||||||
stream: StreamSubscription;
|
stream: StreamSubscription;
|
||||||
|
show_subscriber_count: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type StreamPillWidget = InputPillContainer<StreamPill>;
|
export type StreamPillWidget = InputPillContainer<StreamPill>;
|
||||||
|
@ -55,14 +58,9 @@ export function create_item_from_stream_name(
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let display_value = sub.name;
|
|
||||||
if (show_subscriber_count) {
|
|
||||||
display_value = format_stream_name_and_subscriber_count(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "stream",
|
type: "stream",
|
||||||
display_value,
|
show_subscriber_count,
|
||||||
stream: sub,
|
stream: sub,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -82,18 +80,23 @@ export function get_user_ids(pill_widget: StreamPillWidget | CombinedPillContain
|
||||||
return user_ids;
|
return user_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function get_display_value_from_item(item: StreamPill): string {
|
||||||
|
const stream = stream_data.get_sub_by_id(item.stream.stream_id);
|
||||||
|
assert(stream !== undefined);
|
||||||
|
if (item.show_subscriber_count) {
|
||||||
|
return format_stream_name_and_subscriber_count(stream);
|
||||||
|
}
|
||||||
|
return stream.name;
|
||||||
|
}
|
||||||
|
|
||||||
export function append_stream(
|
export function append_stream(
|
||||||
stream: StreamSubscription,
|
stream: StreamSubscription,
|
||||||
pill_widget: StreamPillWidget | CombinedPillContainer,
|
pill_widget: StreamPillWidget | CombinedPillContainer,
|
||||||
show_subscriber_count = true,
|
show_subscriber_count = true,
|
||||||
): void {
|
): void {
|
||||||
let display_value = stream.name;
|
|
||||||
if (show_subscriber_count) {
|
|
||||||
display_value = format_stream_name_and_subscriber_count(stream);
|
|
||||||
}
|
|
||||||
pill_widget.appendValidatedData({
|
pill_widget.appendValidatedData({
|
||||||
type: "stream",
|
type: "stream",
|
||||||
display_value,
|
show_subscriber_count,
|
||||||
stream,
|
stream,
|
||||||
});
|
});
|
||||||
pill_widget.clear_text();
|
pill_widget.clear_text();
|
||||||
|
|
|
@ -18,7 +18,7 @@ export type UserGroupPillData = UserGroup & {
|
||||||
is_silent?: boolean;
|
is_silent?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function display_pill(group: UserGroup): string {
|
export function display_pill(group: UserGroup): string {
|
||||||
const group_members = get_group_members(group);
|
const group_members = get_group_members(group);
|
||||||
return $t_html(
|
return $t_html(
|
||||||
{defaultMessage: "{group_name}: {group_size, plural, one {# user} other {# users}}"},
|
{defaultMessage: "{group_name}: {group_size, plural, one {# user} other {# users}}"},
|
||||||
|
@ -42,7 +42,6 @@ export function create_item_from_group_name(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "user_group",
|
type: "user_group",
|
||||||
display_value: display_pill(group),
|
|
||||||
group_id: group.id,
|
group_id: group.id,
|
||||||
group_name: group.name,
|
group_name: group.name,
|
||||||
};
|
};
|
||||||
|
@ -76,7 +75,6 @@ function get_group_members(user_group: UserGroup): number[] {
|
||||||
export function append_user_group(group: UserGroup, pill_widget: CombinedPillContainer): void {
|
export function append_user_group(group: UserGroup, pill_widget: CombinedPillContainer): void {
|
||||||
pill_widget.appendValidatedData({
|
pill_widget.appendValidatedData({
|
||||||
type: "user_group",
|
type: "user_group",
|
||||||
display_value: display_pill(group),
|
|
||||||
group_id: group.id,
|
group_id: group.id,
|
||||||
group_name: group.name,
|
group_name: group.name,
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,6 +17,7 @@ export type UserPill = {
|
||||||
type: "user";
|
type: "user";
|
||||||
user_id?: number;
|
user_id?: number;
|
||||||
email: string;
|
email: string;
|
||||||
|
full_name: string | undefined;
|
||||||
img_src?: string;
|
img_src?: string;
|
||||||
deactivated?: boolean;
|
deactivated?: boolean;
|
||||||
status_emoji_info?: (EmojiRenderingDetails & {emoji_alt_code?: boolean}) | undefined; // TODO: Move this in user_status.js
|
status_emoji_info?: (EmojiRenderingDetails & {emoji_alt_code?: boolean}) | undefined; // TODO: Move this in user_status.js
|
||||||
|
@ -46,7 +47,7 @@ export function create_item_from_email(
|
||||||
// is the email itself.
|
// is the email itself.
|
||||||
return {
|
return {
|
||||||
type: "user",
|
type: "user",
|
||||||
display_value: email,
|
full_name: undefined,
|
||||||
email,
|
email,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -67,11 +68,9 @@ export function create_item_from_email(
|
||||||
|
|
||||||
const status_emoji_info = user_status.get_status_emoji(user.user_id);
|
const status_emoji_info = user_status.get_status_emoji(user.user_id);
|
||||||
|
|
||||||
// We must supply display_value for the widget to work. Everything
|
|
||||||
// else is for our own use in callbacks.
|
|
||||||
const item: InputPillItem<UserPill> = {
|
const item: InputPillItem<UserPill> = {
|
||||||
type: "user",
|
type: "user",
|
||||||
display_value: user.full_name,
|
full_name: user.full_name,
|
||||||
user_id: user.user_id,
|
user_id: user.user_id,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
img_src: avatar_url,
|
img_src: avatar_url,
|
||||||
|
@ -108,7 +107,7 @@ export function append_person(opts: {
|
||||||
|
|
||||||
const pill_data: InputPillItem<UserPill> = {
|
const pill_data: InputPillItem<UserPill> = {
|
||||||
type: "user",
|
type: "user",
|
||||||
display_value: person.full_name,
|
full_name: person.full_name,
|
||||||
user_id: person.user_id,
|
user_id: person.user_id,
|
||||||
email: person.email,
|
email: person.email,
|
||||||
img_src: avatar_url,
|
img_src: avatar_url,
|
||||||
|
@ -166,6 +165,10 @@ export function append_user(user: User, pills: UserPillWidget | CombinedPillCont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function get_display_value_from_item(item: UserPill): string {
|
||||||
|
return item.full_name ?? item.email;
|
||||||
|
}
|
||||||
|
|
||||||
export function generate_pill_html(
|
export function generate_pill_html(
|
||||||
item: InputPillItem<UserPill>,
|
item: InputPillItem<UserPill>,
|
||||||
show_user_status_emoji = false,
|
show_user_status_emoji = false,
|
||||||
|
@ -179,7 +182,7 @@ export function generate_pill_html(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return render_input_pill({
|
return render_input_pill({
|
||||||
display_value: item.display_value,
|
display_value: get_display_value_from_item(item),
|
||||||
has_image: item.img_src !== undefined,
|
has_image: item.img_src !== undefined,
|
||||||
deactivated: item.deactivated,
|
deactivated: item.deactivated,
|
||||||
should_add_guest_user_indicator: item.should_add_guest_user_indicator,
|
should_add_guest_user_indicator: item.should_add_guest_user_indicator,
|
||||||
|
@ -199,6 +202,7 @@ export function create_pills(
|
||||||
pill_config,
|
pill_config,
|
||||||
create_item_from_text: create_item_from_email,
|
create_item_from_text: create_item_from_email,
|
||||||
get_text_from_item: get_email_from_item,
|
get_text_from_item: get_email_from_item,
|
||||||
|
get_display_value_from_item,
|
||||||
generate_pill_html,
|
generate_pill_html,
|
||||||
});
|
});
|
||||||
return pills;
|
return pills;
|
||||||
|
|
|
@ -114,7 +114,7 @@ run_test("pills", ({override, override_rewire}) => {
|
||||||
assert.ok(get_by_email_called);
|
assert.ok(get_by_email_called);
|
||||||
assert.equal(typeof res, "object");
|
assert.equal(typeof res, "object");
|
||||||
assert.equal(res.user_id, iago.user_id);
|
assert.equal(res.user_id, iago.user_id);
|
||||||
assert.equal(res.display_value, iago.full_name);
|
assert.equal(res.full_name, iago.full_name);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(function test_deactivated_pill() {
|
(function test_deactivated_pill() {
|
||||||
|
@ -124,7 +124,7 @@ run_test("pills", ({override, override_rewire}) => {
|
||||||
assert.ok(get_by_email_called);
|
assert.ok(get_by_email_called);
|
||||||
assert.equal(typeof res, "object");
|
assert.equal(typeof res, "object");
|
||||||
assert.equal(res.user_id, iago.user_id);
|
assert.equal(res.user_id, iago.user_id);
|
||||||
assert.equal(res.display_value, iago.full_name);
|
assert.equal(res.full_name, iago.full_name);
|
||||||
assert.ok(res.deactivated);
|
assert.ok(res.deactivated);
|
||||||
people.add_active_user(iago);
|
people.add_active_user(iago);
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -50,6 +50,7 @@ const typeahead_helper = zrequire("typeahead_helper");
|
||||||
const muted_users = zrequire("muted_users");
|
const muted_users = zrequire("muted_users");
|
||||||
const people = zrequire("people");
|
const people = zrequire("people");
|
||||||
const user_groups = zrequire("user_groups");
|
const user_groups = zrequire("user_groups");
|
||||||
|
const user_pill = zrequire("user_pill");
|
||||||
const stream_data = zrequire("stream_data");
|
const stream_data = zrequire("stream_data");
|
||||||
const stream_list_sort = zrequire("stream_list_sort");
|
const stream_list_sort = zrequire("stream_list_sort");
|
||||||
const compose_pm_pill = zrequire("compose_pm_pill");
|
const compose_pm_pill = zrequire("compose_pm_pill");
|
||||||
|
@ -846,7 +847,7 @@ test("initialize", ({override, override_rewire, mock_template}) => {
|
||||||
onPillCreate() {},
|
onPillCreate() {},
|
||||||
onPillRemove() {},
|
onPillRemove() {},
|
||||||
appendValidatedData(item) {
|
appendValidatedData(item) {
|
||||||
appended_names.push(item.display_value);
|
appended_names.push(user_pill.get_display_value_from_item(item));
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
compose_pm_pill.initialize({
|
compose_pm_pill.initialize({
|
||||||
|
|
|
@ -42,12 +42,13 @@ run_test("basics", ({mock_template}) => {
|
||||||
$container,
|
$container,
|
||||||
create_item_from_text: noop,
|
create_item_from_text: noop,
|
||||||
get_text_from_item: noop,
|
get_text_from_item: noop,
|
||||||
|
get_display_value_from_item: (item) => item.language,
|
||||||
});
|
});
|
||||||
|
|
||||||
// type for a pill can be any string but it needs to be
|
// type for a pill can be any string but it needs to be
|
||||||
// defined while creating any pill.
|
// defined while creating any pill.
|
||||||
const item = {
|
const item = {
|
||||||
display_value: "JavaScript",
|
language: "JavaScript",
|
||||||
type: "language",
|
type: "language",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,19 +69,19 @@ run_test("basics", ({mock_template}) => {
|
||||||
function set_up() {
|
function set_up() {
|
||||||
const items = {
|
const items = {
|
||||||
blue: {
|
blue: {
|
||||||
display_value: "BLUE",
|
color_name: "BLUE",
|
||||||
description: "color of the sky",
|
description: "color of the sky",
|
||||||
type: "color",
|
type: "color",
|
||||||
},
|
},
|
||||||
|
|
||||||
red: {
|
red: {
|
||||||
display_value: "RED",
|
color_name: "RED",
|
||||||
type: "color",
|
type: "color",
|
||||||
description: "color of stop signs",
|
description: "color of stop signs",
|
||||||
},
|
},
|
||||||
|
|
||||||
yellow: {
|
yellow: {
|
||||||
display_value: "YELLOW",
|
color_name: "YELLOW",
|
||||||
type: "color",
|
type: "color",
|
||||||
description: "color of bananas",
|
description: "color of bananas",
|
||||||
},
|
},
|
||||||
|
@ -99,7 +100,8 @@ function set_up() {
|
||||||
const config = {
|
const config = {
|
||||||
$container,
|
$container,
|
||||||
create_item_from_text,
|
create_item_from_text,
|
||||||
get_text_from_item: (item) => item.display_value,
|
get_text_from_item: (item) => item.color_name,
|
||||||
|
get_display_value_from_item: (item) => item.color_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -403,7 +405,7 @@ run_test("insert_remove", ({mock_template}) => {
|
||||||
|
|
||||||
const pills = widget._get_pills_for_testing();
|
const pills = widget._get_pills_for_testing();
|
||||||
for (const pill of pills) {
|
for (const pill of pills) {
|
||||||
pill.$element.remove = set_colored_removed_func(pill.item.display_value);
|
pill.$element.remove = set_colored_removed_func(pill.item.color_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
let key_handler = $container.get_on_handler("keydown", ".input");
|
let key_handler = $container.get_on_handler("keydown", ".input");
|
||||||
|
@ -527,12 +529,8 @@ run_test("misc things", () => {
|
||||||
assert.ok(shake_class_removed);
|
assert.ok(shake_class_removed);
|
||||||
|
|
||||||
// bad data
|
// bad data
|
||||||
blueslip.expect("error", "no display_value returned");
|
|
||||||
widget.appendValidatedData("this-has-no-item-attribute");
|
|
||||||
|
|
||||||
blueslip.expect("error", "no type defined for the item");
|
blueslip.expect("error", "no type defined for the item");
|
||||||
widget.appendValidatedData({
|
widget.appendValidatedData({
|
||||||
display_value: "This item has no type.",
|
|
||||||
language: "js",
|
language: "js",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -566,8 +564,9 @@ run_test("appendValue/clear", ({mock_template}) => {
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
$container,
|
$container,
|
||||||
create_item_from_text: (s) => ({type: "color", display_value: s}),
|
create_item_from_text: (s) => ({type: "color", color_name: s}),
|
||||||
get_text_from_item: /* istanbul ignore next */ (s) => s.display_value,
|
get_text_from_item: /* istanbul ignore next */ (s) => s.color_name,
|
||||||
|
get_display_value_from_item: (s) => s.color_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
$pill_input.before = noop;
|
$pill_input.before = noop;
|
||||||
|
@ -587,7 +586,7 @@ run_test("appendValue/clear", ({mock_template}) => {
|
||||||
const removed_colors = [];
|
const removed_colors = [];
|
||||||
for (const pill of pills) {
|
for (const pill of pills) {
|
||||||
pill.$element.remove = () => {
|
pill.$element.remove = () => {
|
||||||
removed_colors.push(pill.item.display_value);
|
removed_colors.push(pill.item.color_name);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,10 +137,7 @@ run_test("set_up_user", ({mock_template, override, override_rewire}) => {
|
||||||
sort_recipients_called = true;
|
sort_recipients_called = true;
|
||||||
return users;
|
return users;
|
||||||
});
|
});
|
||||||
mock_template("input_pill.hbs", true, (data, html) => {
|
mock_template("input_pill.hbs", true, (_data, html) => html);
|
||||||
assert.equal(typeof data.display_value, "string");
|
|
||||||
return html;
|
|
||||||
});
|
|
||||||
let input_pill_typeahead_called = false;
|
let input_pill_typeahead_called = false;
|
||||||
const $fake_input = $.create(".input");
|
const $fake_input = $.create(".input");
|
||||||
$fake_input.before = noop;
|
$fake_input.before = noop;
|
||||||
|
@ -152,6 +149,7 @@ run_test("set_up_user", ({mock_template, override, override_rewire}) => {
|
||||||
$container,
|
$container,
|
||||||
create_item_from_text: noop,
|
create_item_from_text: noop,
|
||||||
get_text_from_item: noop,
|
get_text_from_item: noop,
|
||||||
|
get_display_value_from_item: noop,
|
||||||
});
|
});
|
||||||
|
|
||||||
let update_func_called = false;
|
let update_func_called = false;
|
||||||
|
@ -228,10 +226,7 @@ run_test("set_up_stream", ({mock_template, override, override_rewire}) => {
|
||||||
sort_streams_called = true;
|
sort_streams_called = true;
|
||||||
return streams;
|
return streams;
|
||||||
});
|
});
|
||||||
mock_template("input_pill.hbs", true, (data, html) => {
|
mock_template("input_pill.hbs", true, (_data, html) => html);
|
||||||
assert.equal(typeof data.display_value, "string");
|
|
||||||
return html;
|
|
||||||
});
|
|
||||||
let input_pill_typeahead_called = false;
|
let input_pill_typeahead_called = false;
|
||||||
const $fake_input = $.create(".input");
|
const $fake_input = $.create(".input");
|
||||||
$fake_input.before = noop;
|
$fake_input.before = noop;
|
||||||
|
@ -243,6 +238,7 @@ run_test("set_up_stream", ({mock_template, override, override_rewire}) => {
|
||||||
$container,
|
$container,
|
||||||
create_item_from_text: noop,
|
create_item_from_text: noop,
|
||||||
get_text_from_item: noop,
|
get_text_from_item: noop,
|
||||||
|
get_display_value_from_item: noop,
|
||||||
});
|
});
|
||||||
|
|
||||||
let update_func_called = false;
|
let update_func_called = false;
|
||||||
|
@ -315,10 +311,7 @@ run_test("set_up_stream", ({mock_template, override, override_rewire}) => {
|
||||||
|
|
||||||
run_test("set_up_combined", ({mock_template, override, override_rewire}) => {
|
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) => html);
|
||||||
assert.equal(typeof data.display_value, "string");
|
|
||||||
return html;
|
|
||||||
});
|
|
||||||
let input_pill_typeahead_called = false;
|
let input_pill_typeahead_called = false;
|
||||||
const $fake_input = $.create(".input");
|
const $fake_input = $.create(".input");
|
||||||
$fake_input.before = noop;
|
$fake_input.before = noop;
|
||||||
|
@ -330,6 +323,7 @@ run_test("set_up_combined", ({mock_template, override, override_rewire}) => {
|
||||||
$container,
|
$container,
|
||||||
create_item_from_text: noop,
|
create_item_from_text: noop,
|
||||||
get_text_from_item: noop,
|
get_text_from_item: noop,
|
||||||
|
get_display_value_from_item: noop,
|
||||||
});
|
});
|
||||||
|
|
||||||
let update_func_called = false;
|
let update_func_called = false;
|
||||||
|
|
|
@ -28,18 +28,18 @@ const germany = {
|
||||||
invite_only: true,
|
invite_only: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
peer_data.set_subscribers(denmark.stream_id, [1, 2, 3, 77]);
|
peer_data.set_subscribers(denmark.stream_id, [1, 2, 77]);
|
||||||
peer_data.set_subscribers(sweden.stream_id, [1, 2, 3, 4, 5]);
|
peer_data.set_subscribers(sweden.stream_id, [1, 2, 3, 4, 5]);
|
||||||
|
|
||||||
const denmark_pill = {
|
const denmark_pill = {
|
||||||
type: "stream",
|
type: "stream",
|
||||||
display_value: "Denmark: 3 users",
|
|
||||||
stream: denmark,
|
stream: denmark,
|
||||||
|
show_subscriber_count: true,
|
||||||
};
|
};
|
||||||
const sweden_pill = {
|
const sweden_pill = {
|
||||||
type: "stream",
|
type: "stream",
|
||||||
display_value: "translated: Sweden: 5 users",
|
|
||||||
stream: sweden,
|
stream: sweden,
|
||||||
|
show_subscriber_count: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const subs = [denmark, sweden, germany];
|
const subs = [denmark, sweden, germany];
|
||||||
|
@ -82,6 +82,19 @@ run_test("create_item", () => {
|
||||||
test_create_item("#germany", [], undefined, true, stream_data.get_invite_stream_data);
|
test_create_item("#germany", [], undefined, true, stream_data.get_invite_stream_data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
run_test("display_value", () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
stream_pill.get_display_value_from_item(denmark_pill),
|
||||||
|
"translated: Denmark: 3 users",
|
||||||
|
);
|
||||||
|
assert.deepEqual(
|
||||||
|
stream_pill.get_display_value_from_item(sweden_pill),
|
||||||
|
"translated: Sweden: 5 users",
|
||||||
|
);
|
||||||
|
sweden_pill.show_subscriber_count = false;
|
||||||
|
assert.deepEqual(stream_pill.get_display_value_from_item(sweden_pill), "Sweden");
|
||||||
|
});
|
||||||
|
|
||||||
run_test("get_stream_id", () => {
|
run_test("get_stream_id", () => {
|
||||||
assert.equal(stream_pill.get_stream_name_from_item(denmark_pill), denmark.name);
|
assert.equal(stream_pill.get_stream_name_from_item(denmark_pill), denmark.name);
|
||||||
});
|
});
|
||||||
|
|
|
@ -68,13 +68,11 @@ const admins_pill = {
|
||||||
group_id: admins.id,
|
group_id: admins.id,
|
||||||
group_name: admins.name,
|
group_name: admins.name,
|
||||||
type: "user_group",
|
type: "user_group",
|
||||||
display_value: "translated HTML: " + admins.name + ": " + admins.members.length + " users",
|
|
||||||
};
|
};
|
||||||
const testers_pill = {
|
const testers_pill = {
|
||||||
group_id: testers.id,
|
group_id: testers.id,
|
||||||
group_name: testers.name,
|
group_name: testers.name,
|
||||||
type: "user_group",
|
type: "user_group",
|
||||||
display_value: "translated HTML: " + testers.name + ": " + testers.members.length + " users",
|
|
||||||
};
|
};
|
||||||
const everyone_pill = {
|
const everyone_pill = {
|
||||||
group_id: everyone.id,
|
group_id: everyone.id,
|
||||||
|
@ -83,7 +81,6 @@ const everyone_pill = {
|
||||||
// While we can programmatically set the user count below,
|
// While we can programmatically set the user count below,
|
||||||
// calculating it would almost mimic the entire display function
|
// calculating it would almost mimic the entire display function
|
||||||
// here, reducing the usefulness of the test.
|
// here, reducing the usefulness of the test.
|
||||||
display_value: "translated HTML: translated: Everyone: 5 users",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const groups = [admins, testers, everyone];
|
const groups = [admins, testers, everyone];
|
||||||
|
@ -104,6 +101,21 @@ run_test("create_item", () => {
|
||||||
test_create_item("role:everyone", [], everyone_pill);
|
test_create_item("role:everyone", [], everyone_pill);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
run_test("display_value", () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
user_group_pill.display_pill(admins),
|
||||||
|
"translated HTML: " + admins.name + ": " + admins.members.length + " users",
|
||||||
|
);
|
||||||
|
assert.deepEqual(
|
||||||
|
user_group_pill.display_pill(testers),
|
||||||
|
"translated HTML: " + testers.name + ": " + testers.members.length + " users",
|
||||||
|
);
|
||||||
|
assert.deepEqual(
|
||||||
|
user_group_pill.display_pill(everyone),
|
||||||
|
"translated HTML: translated: Everyone: 5 users",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
run_test("get_stream_id", () => {
|
run_test("get_stream_id", () => {
|
||||||
assert.equal(user_group_pill.get_group_name_from_item(admins_pill), admins.name);
|
assert.equal(user_group_pill.get_group_name_from_item(admins_pill), admins.name);
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,13 +27,13 @@ const isaac = {
|
||||||
const bogus_item = {
|
const bogus_item = {
|
||||||
email: "bogus@example.com",
|
email: "bogus@example.com",
|
||||||
type: "user",
|
type: "user",
|
||||||
display_value: "bogus@example.com",
|
full_name: undefined,
|
||||||
// status_emoji_info: undefined,
|
// status_emoji_info: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const isaac_item = {
|
const isaac_item = {
|
||||||
email: "isaac@example.com",
|
email: "isaac@example.com",
|
||||||
display_value: "Isaac Newton",
|
full_name: "Isaac Newton",
|
||||||
type: "user",
|
type: "user",
|
||||||
user_id: isaac.user_id,
|
user_id: isaac.user_id,
|
||||||
deactivated: false,
|
deactivated: false,
|
||||||
|
@ -46,7 +46,7 @@ const inaccessible_user_id = 103;
|
||||||
|
|
||||||
const inaccessible_user_item = {
|
const inaccessible_user_item = {
|
||||||
email: "user103@example.com",
|
email: "user103@example.com",
|
||||||
display_value: "translated: Unknown user",
|
full_name: "translated: Unknown user",
|
||||||
type: "user",
|
type: "user",
|
||||||
user_id: inaccessible_user_id,
|
user_id: inaccessible_user_id,
|
||||||
deactivated: false,
|
deactivated: false,
|
||||||
|
@ -108,7 +108,7 @@ test("append", () => {
|
||||||
function fake_append(opts) {
|
function fake_append(opts) {
|
||||||
appended = true;
|
appended = true;
|
||||||
assert.equal(opts.email, isaac.email);
|
assert.equal(opts.email, isaac.email);
|
||||||
assert.equal(opts.display_value, isaac.full_name);
|
assert.equal(opts.full_name, isaac.full_name);
|
||||||
assert.equal(opts.user_id, isaac.user_id);
|
assert.equal(opts.user_id, isaac.user_id);
|
||||||
assert.equal(opts.img_src, isaac_item.img_src);
|
assert.equal(opts.img_src, isaac_item.img_src);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue