settings: Add sorting feature for list of alert words.

This changes the method of rendering list of alert words in DOM,
earlier it was rendered using 'for' loop over the array of alert_words
which is now changed to render using ListWidget, which gets a array
of objects from get_word_list() in alert_words.js.

The use of ListWidget helps to define a parent_container and $container
in table-body of alert-words-table using which we can now apply sorting over
alert words with the help of handle_sort() function in list_widget.js

Changed the method of adding alert_word_settings_item row in table body
through {{#with}} loop because of rendering through ListWidget, which was done
earlier using for loop over each alert-word in while rendering the list.

this commit also mocks template of render_alert_word_item
while mocking ListWidget.create() function in render_alert_words_ui().
and checks that ListWidget.create() is not called when variable `loaded`
is set as false.

Fixes #21142.
This commit is contained in:
jai2201
2022-02-21 22:53:21 +05:30
committed by Tim Abbott
parent 27b985e868
commit 5e49ddf4e1
8 changed files with 62 additions and 43 deletions

View File

@@ -15,28 +15,34 @@ const alert_words_ui = zrequire("alert_words_ui");
alert_words.initialize({
alert_words: ["foo", "bar"],
});
const noop = () => {};
run_test("render_alert_words_ui", ({mock_template}) => {
const word_list = $("#alert_words_list");
const appended = [];
word_list.append = (rendered) => {
appended.push(rendered);
};
const alert_word_items = $.create("alert_word_items");
word_list.set_find_results(".alert-word-item", alert_word_items);
alert_word_items.remove = () => {};
mock_template("settings/alert_word_settings_item.hbs", false, (args) => "stub-" + args.word);
const new_alert_word = $("#create_alert_word_name");
assert.ok(!new_alert_word.is_focused());
let list_widget_create_called = false;
alert_words_ui.reset();
assert.ok(!$("#create_alert_word_name").is_focused());
const ListWidget = mock_esm("../../static/js/list_widget", {
modifier: noop,
create: (container, words, opts) => {
const alert_words = [];
ListWidget.modifier = opts.modifier;
for (const word of words) {
alert_words.push(opts.modifier(word));
}
list_widget_create_called = true;
return alert_words;
},
});
mock_template("settings/alert_word_settings_item.hbs", false, (args) => {
assert.ok(["foo", "bar"].includes(args.alert_word.word));
});
assert.equal(alert_words_ui.loaded, false);
alert_words_ui.render_alert_words_ui();
assert.deepEqual(appended, ["stub-bar", "stub-foo"]);
assert.ok(new_alert_word.is_focused());
assert.equal(list_widget_create_called, false);
alert_words_ui.set_up_alert_words();
assert.equal(alert_words_ui.loaded, true);
assert.equal(list_widget_create_called, true);
assert.ok($("#create_alert_word_name").is_focused());
});
run_test("add_alert_word", ({override_rewire}) => {
@@ -124,7 +130,7 @@ run_test("remove_alert_word", ({override_rewire}) => {
override_rewire(alert_words_ui, "render_alert_words_ui", () => {});
alert_words_ui.set_up_alert_words();
const word_list = $("#alert_words_list");
const word_list = $("#alert-words-table");
const remove_func = word_list.get_on_handler("click", ".remove-alert-word");
const remove_alert_word = $(".remove-alert-word");

View File

@@ -130,7 +130,7 @@ run_test("alert_words", ({override}) => {
const event = event_fixtures.alert_words;
dispatch(event);
assert.deepEqual(alert_words.get_word_list(), ["fire", "lunch"]);
assert.deepEqual(alert_words.get_word_list(), [{word: "fire"}, {word: "lunch"}]);
assert.ok(alert_words.has_alert_word("fire"));
assert.ok(alert_words.has_alert_word("lunch"));
});

View File

@@ -11,12 +11,13 @@ export function set_words(words) {
}
export function get_word_list() {
// People usually only have a couple alert
// words, so it's cheap to be defensive
// here and give a copy of the list to
// our caller (in case they want to sort it
// or something).
return [...my_alert_words];
// Returns a array of objects
// (with each alert_word as value and 'word' as key to the object.)
const words = [];
for (const word of my_alert_words) {
words.push({word});
}
return words;
}
export function has_alert_word(word) {

View File

@@ -5,20 +5,26 @@ import render_alert_word_settings_item from "../templates/settings/alert_word_se
import * as alert_words from "./alert_words";
import * as channel from "./channel";
import {$t} from "./i18n";
import * as ListWidget from "./list_widget";
export let loaded = false;
export function render_alert_words_ui() {
if (!loaded) {
return;
}
const words = alert_words.get_word_list();
words.sort();
const word_list = $("#alert_words_list");
const word_list = $("#alert-words-table");
word_list.find(".alert-word-item").remove();
for (const alert_word of words) {
const rendered_alert_word = render_alert_word_settings_item({
word: alert_word,
ListWidget.create(word_list, words, {
name: "alert-words-list",
modifier(alert_word) {
return render_alert_word_settings_item({alert_word});
},
parent_container: $("#alert-word-settings"),
simplebar_container: $("#alert-word-settings .progressive-table-wrapper"),
});
word_list.append(rendered_alert_word);
}
// Focus new alert word name text box.
$("#create_alert_word_name").trigger("focus");
@@ -83,7 +89,7 @@ function remove_alert_word(alert_word) {
export function set_up_alert_words() {
// The settings page must be rendered before this function gets called.
loaded = true;
render_alert_words_ui();
$("#create_alert_word_form").on("click", "#create_alert_word_button", () => {
@@ -91,7 +97,7 @@ export function set_up_alert_words() {
add_alert_word(word);
});
$("#alert_words_list").on("click", ".remove-alert-word", (event) => {
$("#alert-words-table").on("click", ".remove-alert-word", (event) => {
const word = $(event.currentTarget).parents("tr").find(".value").text().trim();
remove_alert_word(word);
});
@@ -111,3 +117,7 @@ export function set_up_alert_words() {
alert.hide();
});
}
export function reset() {
loaded = false;
}

View File

@@ -115,5 +115,6 @@ export function reset_sections() {
settings_user_groups.reset();
settings_muted_topics.reset();
settings_muted_users.reset();
alert_words_ui.reset();
// settings_users doesn't need a reset()
}

View File

@@ -978,7 +978,7 @@ input[type="checkbox"] {
}
}
#alert_words_list {
#alert-words-table {
margin: 0;
li {
@@ -997,7 +997,7 @@ input[type="checkbox"] {
}
}
#alert_words_list,
#alert-words-table,
#attachments_list {
.edit-attachment-buttons {
position: absolute;

View File

@@ -30,10 +30,10 @@
<div class="progressive-table-wrapper" data-simplebar>
<table class="table table-condensed table-striped wrapped-table">
<thead>
<th class="active">{{t "Word" }}</th>
<th data-sort="alphabetic" data-sort-prop="word">{{t "Word" }}</th>
<th>{{t "Actions" }}</th>
</thead>
<tbody id="alert_words_list" class="alert_words_list required-text thick"
<tbody id="alert-words-table" class="alert-words-table required-text thick"
data-empty="{{t 'There are no current alert words.' }}"></tbody>
</table>
</div>

View File

@@ -1,5 +1,5 @@
{{! Alert word in the settings page that can be removed }}
{{#with alert_word}}
<tr class="alert-word-item" data-word='{{word}}'>
<td>
<div class="alert_word_listing">
@@ -12,3 +12,4 @@
</button>
</td>
</tr>
{{/with}}