list_widget: Add functionality to display empty list message.

This commit introduces a function in list_widget.js that allows
displaying a message when the list is empty using the `data-empty`
dataset. The function checks the container type to determine the
appropriate wrapper for the message and appends it to the container
body.

Fixes a part of #23072.
This commit is contained in:
Hemant Umre 2023-08-24 22:37:11 +05:30 committed by Tim Abbott
parent 2cbf65b1f2
commit 5eb784a652
9 changed files with 84 additions and 2 deletions

View File

@ -1,6 +1,9 @@
import $ from "jquery"; import $ from "jquery";
import assert from "minimalistic-assert"; import assert from "minimalistic-assert";
import render_empty_list_widget_for_list from "../templates/empty_list_widget_for_list.hbs";
import render_empty_list_widget_for_table from "../templates/empty_list_widget_for_table.hbs";
import * as blueslip from "./blueslip"; import * as blueslip from "./blueslip";
import * as scroll_util from "./scroll_util"; import * as scroll_util from "./scroll_util";
@ -177,6 +180,44 @@ function is_scroll_position_for_render(scroll_container: HTMLElement): boolean {
); );
} }
function get_column_count_for_table($table: JQuery): number {
let column_count = 0;
const $thead = $table.find("thead");
if ($thead.length) {
column_count = $thead.find("tr").children().length;
}
return column_count;
}
export function render_empty_list_message_if_needed($container: JQuery): void {
const empty_list_message = $container.data("empty");
if (!empty_list_message || $container.children().length) {
return;
}
let empty_list_widget;
if ($container.is("table, tbody")) {
let $table = $container;
if ($container.is("tbody")) {
$table = $container.closest("table");
}
const column_count = get_column_count_for_table($table);
empty_list_widget = render_empty_list_widget_for_table({
empty_list_message,
column_count,
});
} else {
empty_list_widget = render_empty_list_widget_for_list({
empty_list_message,
});
}
$container.append(empty_list_widget);
}
// @params // @params
// $container: jQuery object to append to. // $container: jQuery object to append to.
// list: The list of items to progressively append. // list: The list of items to progressively append.
@ -249,6 +290,7 @@ export function create<Key = unknown, Item = Key>(
// Stop once the offset reaches the length of the original list. // Stop once the offset reaches the length of the original list.
if (meta.offset >= meta.filtered_list.length) { if (meta.offset >= meta.filtered_list.length) {
render_empty_list_message_if_needed($container);
return; return;
} }

View File

@ -201,11 +201,19 @@ function render_user_stream_list(streams, user) {
modifier_html(item) { modifier_html(item) {
return format_user_stream_list_item_html(item, user); return format_user_stream_list_item_html(item, user);
}, },
callback_after_render() {
$container.parent().removeClass("empty-list");
},
filter: { filter: {
$element: $("#user-profile-streams-tab .stream-search"), $element: $("#user-profile-streams-tab .stream-search"),
predicate(item, value) { predicate(item, value) {
return item && item.name.toLocaleLowerCase().includes(value); return item && item.name.toLocaleLowerCase().includes(value);
}, },
onupdate() {
if ($container.find("#empty-table-message").length) {
$container.parent().addClass("empty-list");
}
},
}, },
$simplebar_container: $("#user-profile-modal .modal__body"), $simplebar_container: $("#user-profile-modal .modal__body"),
}); });
@ -218,6 +226,9 @@ function render_user_group_list(groups, user) {
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, get_item: ListWidget.default_get_item,
callback_after_render() {
$container.parent().removeClass("empty-list");
},
modifier_html(item) { modifier_html(item) {
return format_user_group_list_item_html(item); return format_user_group_list_item_html(item);
}, },

View File

@ -1163,6 +1163,15 @@ div.overlay {
} }
} }
#empty-list-message,
#empty-table-message {
background-color: inherit;
color: var(--color-text-default);
font-size: 1.5em;
padding: 3em 1em;
text-align: center;
}
.filter_text_input { .filter_text_input {
padding: 4px 6px; padding: 4px 6px;
color: hsl(0deg 0% 33%); color: hsl(0deg 0% 33%);

View File

@ -673,6 +673,14 @@ ul {
} }
} }
} }
.empty-list {
border: none;
#empty-table-message {
padding: 3em 1em;
}
}
} }
@media (width < $md_min) { @media (width < $md_min) {

View File

@ -61,6 +61,11 @@
position: absolute; position: absolute;
} }
#empty-table-message {
background-color: var(--color-background);
padding: 3em 1em;
}
.fa-check-square-o, .fa-check-square-o,
.fa-square-o { .fa-square-o {
padding: 0 2px; padding: 0 2px;

View File

@ -0,0 +1 @@
<li id="empty-list-message">{{empty_list_message}}</li>

View File

@ -0,0 +1,5 @@
<tr>
<td id="empty-table-message" colspan="{{column_count}}">
{{empty_list_message}}
</td>
</tr>

View File

@ -109,13 +109,13 @@
<i class="fa fa-remove" aria-hidden="true"></i> <i class="fa fa-remove" aria-hidden="true"></i>
</button> </button>
</div> </div>
<div class="subscription-stream-list"> <div class="subscription-stream-list empty-list">
<table class="user-stream-list" data-empty="{{t 'No stream subscriptions.'}}"></table> <table class="user-stream-list" data-empty="{{t 'No stream subscriptions.'}}"></table>
</div> </div>
</div> </div>
<div class="tabcontent" id="user-profile-groups-tab"> <div class="tabcontent" id="user-profile-groups-tab">
<div class="subscription-group-list"> <div class="subscription-group-list empty-list">
<table class="user-group-list" data-empty="{{t 'No user group subscriptions.'}}"></table> <table class="user-group-list" data-empty="{{t 'No user group subscriptions.'}}"></table>
</div> </div>
</div> </div>

View File

@ -46,6 +46,7 @@ const ListWidget = zrequire("list_widget");
function make_container() { function make_container() {
const $container = {}; const $container = {};
$container.empty = () => {}; $container.empty = () => {};
$container.data = () => {};
// Make our append function just set a field we can // Make our append function just set a field we can
// check in our tests. // check in our tests.