mirror of https://github.com/zulip/zulip.git
list_widget: Make `get_item` option required and pass a default where needed.
This is a prep commit for moving towards typescript migration of this module. We should make `get_item` required on `list_widget` because its intended to be used with a set of keys and then hydrate the keys lazily. Also this will help us to avoid writing messy if-conditions while filtering and sorting and make our life much easier when we migrate to TypeScript. I added a `default_get_item` function which is just n identity function and also refactored some code to make use of default get item.
This commit is contained in:
parent
7176590eea
commit
3720fd5c76
|
@ -23,6 +23,7 @@ export function rerender_alert_words_ui() {
|
||||||
|
|
||||||
ListWidget.create($word_list, words, {
|
ListWidget.create($word_list, words, {
|
||||||
name: "alert-words-list",
|
name: "alert-words-list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(alert_word) {
|
modifier(alert_word) {
|
||||||
return render_alert_word_settings_item({alert_word});
|
return render_alert_word_settings_item({alert_word});
|
||||||
},
|
},
|
||||||
|
|
|
@ -94,6 +94,7 @@ function render_attachments_ui() {
|
||||||
|
|
||||||
ListWidget.create($uploaded_files_table, attachments, {
|
ListWidget.create($uploaded_files_table, attachments, {
|
||||||
name: "uploaded-files-list",
|
name: "uploaded-files-list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(attachment) {
|
modifier(attachment) {
|
||||||
return render_uploaded_files_list({attachment});
|
return render_uploaded_files_list({attachment});
|
||||||
},
|
},
|
||||||
|
|
|
@ -116,6 +116,7 @@ export class DropdownListWidget {
|
||||||
|
|
||||||
this.list_widget = ListWidget.create($dropdown_list_body, this.get_data(data), {
|
this.list_widget = ListWidget.create($dropdown_list_body, this.get_data(data), {
|
||||||
name: `${CSS.escape(this.widget_name)}_list`,
|
name: `${CSS.escape(this.widget_name)}_list`,
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
return render_dropdown_list({item});
|
return render_dropdown_list({item});
|
||||||
},
|
},
|
||||||
|
@ -414,6 +415,7 @@ export class MultiSelectDropdownListWidget extends DropdownListWidget {
|
||||||
|
|
||||||
this.list_widget = ListWidget.create($dropdown_list_body, data, {
|
this.list_widget = ListWidget.create($dropdown_list_body, data, {
|
||||||
name: `${CSS.escape(this.widget_name)}_list`,
|
name: `${CSS.escape(this.widget_name)}_list`,
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
return render_dropdown_list({item});
|
return render_dropdown_list({item});
|
||||||
},
|
},
|
||||||
|
|
|
@ -47,6 +47,7 @@ export function setup(tippy_props, get_options, item_click_callback, dropdown_pr
|
||||||
|
|
||||||
const list_widget = ListWidget.create($dropdown_list_body, get_options(), {
|
const list_widget = ListWidget.create($dropdown_list_body, get_options(), {
|
||||||
name: `${CSS.escape(tippy_props.target)}-list-widget`,
|
name: `${CSS.escape(tippy_props.target)}-list-widget`,
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
return render_dropdown_list({item});
|
return render_dropdown_list({item});
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,6 +24,10 @@ export function validate_opts(opts) {
|
||||||
blueslip.error("$simplebar_container is missing.");
|
blueslip.error("$simplebar_container is missing.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!opts.get_item) {
|
||||||
|
blueslip.error("get_item is missing.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,38 +40,28 @@ export function get_filtered_items(value, list, opts) {
|
||||||
const get_item = opts.get_item;
|
const get_item = opts.get_item;
|
||||||
|
|
||||||
if (!opts.filter) {
|
if (!opts.filter) {
|
||||||
if (get_item) {
|
return list.map((key) => get_item(key));
|
||||||
return list.map((key) => get_item(key));
|
|
||||||
}
|
|
||||||
return [...list];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.filter.filterer) {
|
if (opts.filter.filterer) {
|
||||||
if (get_item) {
|
return opts.filter.filterer(
|
||||||
return opts.filter.filterer(
|
list.map((key) => get_item(key)),
|
||||||
list.map((key) => get_item(key)),
|
value,
|
||||||
value,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
return opts.filter.filterer(list, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const predicate = (item) => opts.filter.predicate(item, value);
|
const predicate = (item) => opts.filter.predicate(item, value);
|
||||||
|
|
||||||
if (get_item) {
|
const result = [];
|
||||||
const result = [];
|
|
||||||
|
|
||||||
for (const key of list) {
|
for (const key of list) {
|
||||||
const item = get_item(key);
|
const item = get_item(key);
|
||||||
if (predicate(item)) {
|
if (predicate(item)) {
|
||||||
result.push(item);
|
result.push(item);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return list.filter((item) => predicate(item));
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function alphabetic_sort(prop) {
|
export function alphabetic_sort(prop) {
|
||||||
|
@ -262,9 +256,7 @@ export function create($container, list, opts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.get_item) {
|
item = opts.get_item(item);
|
||||||
item = opts.get_item(item);
|
|
||||||
}
|
|
||||||
const html = opts.modifier(item);
|
const html = opts.modifier(item);
|
||||||
if (typeof html !== "string") {
|
if (typeof html !== "string") {
|
||||||
blueslip.error("List item is not a string", {item: html});
|
blueslip.error("List item is not a string", {item: html});
|
||||||
|
@ -495,3 +487,5 @@ export function handle_sort($th, list) {
|
||||||
// and not if it is undefined.
|
// and not if it is undefined.
|
||||||
list.sort(sort_type, prop_name);
|
list.sort(sort_type, prop_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const default_get_item = (item) => item;
|
||||||
|
|
|
@ -843,6 +843,7 @@ export function complete_rerender() {
|
||||||
$container.empty();
|
$container.empty();
|
||||||
topics_widget = ListWidget.create($container, mapped_topic_values, {
|
topics_widget = ListWidget.create($container, mapped_topic_values, {
|
||||||
name: "recent_topics_table",
|
name: "recent_topics_table",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
$parent_container: $("#recent_topics_table"),
|
$parent_container: $("#recent_topics_table"),
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
return render_recent_topic_row(format_conversation(item));
|
return render_recent_topic_row(format_conversation(item));
|
||||||
|
|
|
@ -111,6 +111,7 @@ export function populate_emoji() {
|
||||||
const $emoji_table = $("#admin_emoji_table").expectOne();
|
const $emoji_table = $("#admin_emoji_table").expectOne();
|
||||||
ListWidget.create($emoji_table, Object.values(emoji_data), {
|
ListWidget.create($emoji_table, Object.values(emoji_data), {
|
||||||
name: "emoji_list",
|
name: "emoji_list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
if (item.deactivated !== true) {
|
if (item.deactivated !== true) {
|
||||||
return render_admin_emoji_list({
|
return render_admin_emoji_list({
|
||||||
|
|
|
@ -41,6 +41,7 @@ export function populate_exports_table(exports) {
|
||||||
const $exports_table = $("#admin_exports_table").expectOne();
|
const $exports_table = $("#admin_exports_table").expectOne();
|
||||||
ListWidget.create($exports_table, Object.values(exports), {
|
ListWidget.create($exports_table, Object.values(exports), {
|
||||||
name: "admin_exports_list",
|
name: "admin_exports_list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(data) {
|
modifier(data) {
|
||||||
let failed_timestamp = data.failed_timestamp;
|
let failed_timestamp = data.failed_timestamp;
|
||||||
let deleted_timestamp = data.deleted_timestamp;
|
let deleted_timestamp = data.deleted_timestamp;
|
||||||
|
|
|
@ -61,6 +61,7 @@ function populate_invites(invites_data) {
|
||||||
const $invites_table = $("#admin_invites_table").expectOne();
|
const $invites_table = $("#admin_invites_table").expectOne();
|
||||||
ListWidget.create($invites_table, invites_data.invites, {
|
ListWidget.create($invites_table, invites_data.invites, {
|
||||||
name: "admin_invites_list",
|
name: "admin_invites_list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
item.invited_absolute_time = timerender.absolute_time(item.invited * 1000);
|
item.invited_absolute_time = timerender.absolute_time(item.invited * 1000);
|
||||||
if (item.expiry_date !== null) {
|
if (item.expiry_date !== null) {
|
||||||
|
|
|
@ -136,6 +136,7 @@ export function populate_linkifiers(linkifiers_data) {
|
||||||
const $linkifiers_table = $("#admin_linkifiers_table").expectOne();
|
const $linkifiers_table = $("#admin_linkifiers_table").expectOne();
|
||||||
ListWidget.create($linkifiers_table, linkifiers_data, {
|
ListWidget.create($linkifiers_table, linkifiers_data, {
|
||||||
name: "linkifiers_list",
|
name: "linkifiers_list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(linkifier) {
|
modifier(linkifier) {
|
||||||
return render_admin_linkifier_list({
|
return render_admin_linkifier_list({
|
||||||
linkifier: {
|
linkifier: {
|
||||||
|
|
|
@ -21,6 +21,7 @@ export function populate_list() {
|
||||||
|
|
||||||
ListWidget.create($muted_users_table, all_muted_users, {
|
ListWidget.create($muted_users_table, all_muted_users, {
|
||||||
name: "muted-users-list",
|
name: "muted-users-list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(muted_user) {
|
modifier(muted_user) {
|
||||||
return render_muted_user_ui_row({muted_user});
|
return render_muted_user_ui_row({muted_user});
|
||||||
},
|
},
|
||||||
|
|
|
@ -35,6 +35,7 @@ export function populate_playgrounds(playgrounds_data) {
|
||||||
const $playgrounds_table = $("#admin_playgrounds_table").expectOne();
|
const $playgrounds_table = $("#admin_playgrounds_table").expectOne();
|
||||||
ListWidget.create($playgrounds_table, playgrounds_data, {
|
ListWidget.create($playgrounds_table, playgrounds_data, {
|
||||||
name: "playgrounds_list",
|
name: "playgrounds_list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(playground) {
|
modifier(playground) {
|
||||||
return render_admin_playground_list({
|
return render_admin_playground_list({
|
||||||
playground: {
|
playground: {
|
||||||
|
|
|
@ -108,6 +108,7 @@ export function build_default_stream_table() {
|
||||||
|
|
||||||
ListWidget.create($table, subs, {
|
ListWidget.create($table, subs, {
|
||||||
name: "default_streams_list",
|
name: "default_streams_list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
return render_admin_default_streams_list({
|
return render_admin_default_streams_list({
|
||||||
stream: item,
|
stream: item,
|
||||||
|
|
|
@ -25,6 +25,7 @@ export function populate_list() {
|
||||||
|
|
||||||
ListWidget.create($user_topics_table, all_user_topics, {
|
ListWidget.create($user_topics_table, all_user_topics, {
|
||||||
name: "user-topics-list",
|
name: "user-topics-list",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(user_topic) {
|
modifier(user_topic) {
|
||||||
const context = {
|
const context = {
|
||||||
user_topic,
|
user_topic,
|
||||||
|
|
|
@ -112,6 +112,7 @@ function make_list_widget({$parent_container, name, user_ids, user_can_remove_su
|
||||||
|
|
||||||
return ListWidget.create($list_container, users, {
|
return ListWidget.create($list_container, users, {
|
||||||
name,
|
name,
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
return format_member_list_elem(item, user_can_remove_subscribers);
|
return format_member_list_elem(item, user_can_remove_subscribers);
|
||||||
},
|
},
|
||||||
|
|
|
@ -66,6 +66,7 @@ function make_list_widget({$parent_container, name, user_ids}) {
|
||||||
|
|
||||||
return ListWidget.create($list_container, users, {
|
return ListWidget.create($list_container, users, {
|
||||||
name,
|
name,
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
$parent_container,
|
$parent_container,
|
||||||
sort_fields: {
|
sort_fields: {
|
||||||
email: settings_users.sort_email,
|
email: settings_users.sort_email,
|
||||||
|
|
|
@ -199,6 +199,7 @@ export function setup_page(callback) {
|
||||||
|
|
||||||
group_list_widget = ListWidget.create($container, user_groups_list, {
|
group_list_widget = ListWidget.create($container, user_groups_list, {
|
||||||
name: "user-groups-overlay",
|
name: "user-groups-overlay",
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
item.is_member = user_groups.is_direct_member_of(
|
item.is_member = user_groups.is_direct_member_of(
|
||||||
people.my_current_user_id(),
|
people.my_current_user_id(),
|
||||||
|
|
|
@ -83,6 +83,7 @@ function render_user_stream_list(streams, user) {
|
||||||
$container.empty();
|
$container.empty();
|
||||||
ListWidget.create($container, streams, {
|
ListWidget.create($container, streams, {
|
||||||
name: `user-${user.user_id}-stream-list`,
|
name: `user-${user.user_id}-stream-list`,
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
return format_user_stream_list_item(item, user);
|
return format_user_stream_list_item(item, user);
|
||||||
},
|
},
|
||||||
|
@ -102,6 +103,7 @@ function render_user_group_list(groups, user) {
|
||||||
$container.empty();
|
$container.empty();
|
||||||
ListWidget.create($container, groups, {
|
ListWidget.create($container, groups, {
|
||||||
name: `user-${user.user_id}-group-list`,
|
name: `user-${user.user_id}-group-list`,
|
||||||
|
get_item: ListWidget.default_get_item,
|
||||||
modifier(item) {
|
modifier(item) {
|
||||||
return format_user_group_list_item(item);
|
return format_user_group_list_item(item);
|
||||||
},
|
},
|
||||||
|
|
|
@ -157,6 +157,7 @@ run_test("scrolling", () => {
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
modifier: (item) => item,
|
modifier: (item) => item,
|
||||||
|
get_item: (item) => item,
|
||||||
$simplebar_container: $scroll_container,
|
$simplebar_container: $scroll_container,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -205,6 +206,7 @@ run_test("not_scrolling", () => {
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
modifier: (item) => item,
|
modifier: (item) => item,
|
||||||
|
get_item: (item) => item,
|
||||||
$simplebar_container: $scroll_container,
|
$simplebar_container: $scroll_container,
|
||||||
is_scroll_position_for_render: () => false,
|
is_scroll_position_for_render: () => false,
|
||||||
post_scroll__pre_render_callback,
|
post_scroll__pre_render_callback,
|
||||||
|
@ -243,6 +245,7 @@ run_test("filtering", () => {
|
||||||
predicate: (item, value) => item.includes(value),
|
predicate: (item, value) => item.includes(value),
|
||||||
},
|
},
|
||||||
modifier: (item) => div(item),
|
modifier: (item) => div(item),
|
||||||
|
get_item: (item) => item,
|
||||||
$simplebar_container: $scroll_container,
|
$simplebar_container: $scroll_container,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -288,6 +291,7 @@ run_test("no filtering", () => {
|
||||||
callback_after_render() {
|
callback_after_render() {
|
||||||
callback_called = true;
|
callback_called = true;
|
||||||
},
|
},
|
||||||
|
get_item: (item) => item,
|
||||||
};
|
};
|
||||||
const widget = ListWidget.create($container, ["apple", "banana"], opts);
|
const widget = ListWidget.create($container, ["apple", "banana"], opts);
|
||||||
widget.render();
|
widget.render();
|
||||||
|
@ -362,6 +366,7 @@ run_test("wire up filter element", () => {
|
||||||
$element: $filter_element,
|
$element: $filter_element,
|
||||||
},
|
},
|
||||||
modifier: (s) => "(" + s + ")",
|
modifier: (s) => "(" + s + ")",
|
||||||
|
get_item: (item) => item,
|
||||||
$simplebar_container: $scroll_container,
|
$simplebar_container: $scroll_container,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -392,6 +397,7 @@ run_test("sorting", () => {
|
||||||
name: "sorting-list",
|
name: "sorting-list",
|
||||||
$parent_container: $sort_container,
|
$parent_container: $sort_container,
|
||||||
modifier: (item) => div(item.name) + div(item.salary),
|
modifier: (item) => div(item.name) + div(item.salary),
|
||||||
|
get_item: (item) => item,
|
||||||
filter: {
|
filter: {
|
||||||
predicate: () => true,
|
predicate: () => true,
|
||||||
},
|
},
|
||||||
|
@ -492,6 +498,7 @@ run_test("custom sort", () => {
|
||||||
ListWidget.create($container, list, {
|
ListWidget.create($container, list, {
|
||||||
name: "custom-sort-list",
|
name: "custom-sort-list",
|
||||||
modifier: (n) => "(" + n.x + ", " + n.y + ")",
|
modifier: (n) => "(" + n.x + ", " + n.y + ")",
|
||||||
|
get_item: (item) => item,
|
||||||
sort_fields: {
|
sort_fields: {
|
||||||
product: sort_by_product,
|
product: sort_by_product,
|
||||||
x_value: sort_by_x,
|
x_value: sort_by_x,
|
||||||
|
@ -529,6 +536,7 @@ run_test("clear_event_handlers", () => {
|
||||||
name: "list-we-create-twice",
|
name: "list-we-create-twice",
|
||||||
$parent_container: $sort_container,
|
$parent_container: $sort_container,
|
||||||
modifier() {},
|
modifier() {},
|
||||||
|
get_item() {},
|
||||||
filter: {
|
filter: {
|
||||||
$element: $filter_element,
|
$element: $filter_element,
|
||||||
predicate: /* istanbul ignore next */ () => true,
|
predicate: /* istanbul ignore next */ () => true,
|
||||||
|
@ -578,6 +586,7 @@ run_test("errors", () => {
|
||||||
predicate: "wrong type",
|
predicate: "wrong type",
|
||||||
},
|
},
|
||||||
$simplebar_container: $scroll_container,
|
$simplebar_container: $scroll_container,
|
||||||
|
get_item() {},
|
||||||
});
|
});
|
||||||
blueslip.reset();
|
blueslip.reset();
|
||||||
|
|
||||||
|
@ -588,6 +597,7 @@ run_test("errors", () => {
|
||||||
predicate: /* istanbul ignore next */ () => true,
|
predicate: /* istanbul ignore next */ () => true,
|
||||||
},
|
},
|
||||||
$simplebar_container: $scroll_container,
|
$simplebar_container: $scroll_container,
|
||||||
|
get_item() {},
|
||||||
});
|
});
|
||||||
blueslip.reset();
|
blueslip.reset();
|
||||||
|
|
||||||
|
@ -595,6 +605,7 @@ run_test("errors", () => {
|
||||||
ListWidget.create($container, list, {
|
ListWidget.create($container, list, {
|
||||||
filter: {},
|
filter: {},
|
||||||
$simplebar_container: $scroll_container,
|
$simplebar_container: $scroll_container,
|
||||||
|
get_item() {},
|
||||||
});
|
});
|
||||||
blueslip.reset();
|
blueslip.reset();
|
||||||
|
|
||||||
|
@ -602,6 +613,7 @@ run_test("errors", () => {
|
||||||
ListWidget.create($container, list, {
|
ListWidget.create($container, list, {
|
||||||
modifier: () => 999,
|
modifier: () => 999,
|
||||||
$simplebar_container: $scroll_container,
|
$simplebar_container: $scroll_container,
|
||||||
|
get_item: (item) => item,
|
||||||
});
|
});
|
||||||
blueslip.reset();
|
blueslip.reset();
|
||||||
});
|
});
|
||||||
|
@ -638,6 +650,7 @@ run_test("replace_list_data w/filter update", () => {
|
||||||
ListWidget.create($container, list, {
|
ListWidget.create($container, list, {
|
||||||
name: "replace-list",
|
name: "replace-list",
|
||||||
modifier: (n) => "(" + n.toString() + ")",
|
modifier: (n) => "(" + n.toString() + ")",
|
||||||
|
get_item: (item) => item,
|
||||||
filter: {
|
filter: {
|
||||||
predicate: (n) => n % 2 === 0,
|
predicate: (n) => n % 2 === 0,
|
||||||
onupdate() {
|
onupdate() {
|
||||||
|
@ -873,6 +886,7 @@ run_test("Multiselect dropdown retain_selected_items", () => {
|
||||||
const widget = ListWidget.create($container, list, {
|
const widget = ListWidget.create($container, list, {
|
||||||
name: "replace-list",
|
name: "replace-list",
|
||||||
modifier: (item) => `<li data-value="${item.value}">${item.name}</li>\n`,
|
modifier: (item) => `<li data-value="${item.value}">${item.name}</li>\n`,
|
||||||
|
get_item: (item) => item,
|
||||||
multiselect: {
|
multiselect: {
|
||||||
selected_items: data,
|
selected_items: data,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue