diff --git a/web/shared/icons/topic.svg b/web/shared/icons/topic.svg new file mode 100644 index 0000000000..ce83e39260 --- /dev/null +++ b/web/shared/icons/topic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/muted_topics_ui.js b/web/src/muted_topics_ui.js index 17df67e461..4b5d04da9c 100644 --- a/web/src/muted_topics_ui.js +++ b/web/src/muted_topics_ui.js @@ -1,8 +1,6 @@ import * as message_lists from "./message_lists"; -import * as overlays from "./overlays"; import * as popover_menus from "./popover_menus"; import * as recent_topics_ui from "./recent_topics_ui"; -import * as settings_muted_topics from "./settings_muted_topics"; import * as stream_list from "./stream_list"; import * as sub_store from "./sub_store"; import * as unread_ui from "./unread_ui"; @@ -19,9 +17,6 @@ export function handle_topic_updates(user_topic_event) { if (message_lists.current !== message_lists.home) { message_lists.home.update_muting_and_rerender(); } - if (overlays.settings_open() && settings_muted_topics.loaded) { - settings_muted_topics.populate_list(); - } recent_topics_ui.update_topic_visibility_policy( user_topic_event.stream_id, user_topic_event.topic_name, diff --git a/web/src/settings_config.ts b/web/src/settings_config.ts index 79be7392ee..1f25171f22 100644 --- a/web/src/settings_config.ts +++ b/web/src/settings_config.ts @@ -867,3 +867,18 @@ export const system_user_groups_list = [ display_name: $t({defaultMessage: "Nobody"}), }, ]; + +export const user_topic_visibility_policy_values = { + muted: { + code: 1, + description: $t({defaultMessage: "Muted"}), + }, + unmuted: { + code: 2, + description: $t({defaultMessage: "Unmuted"}), + }, + inherit: { + code: 0, + description: $t({defaultMessage: "Default for stream"}), + }, +}; diff --git a/web/src/settings_muted_topics.js b/web/src/settings_muted_topics.js index e7c70440ac..60e5a440b6 100644 --- a/web/src/settings_muted_topics.js +++ b/web/src/settings_muted_topics.js @@ -3,22 +3,35 @@ import $ from "jquery"; import render_user_topic_ui_row from "../templates/user_topic_ui_row.hbs"; import * as ListWidget from "./list_widget"; +import * as settings_config from "./settings_config"; import * as ui from "./ui"; import * as user_topics from "./user_topics"; export let loaded = false; export function populate_list() { - const all_muted_topics = user_topics.get_user_topics_for_visibility_policy( - user_topics.all_visibility_policies.MUTED, - ); - const $muted_topics_table = $("#muted_topics_table"); - const $search_input = $("#muted_topics_search"); + const all_user_topics = []; + const visibility_policies = Object.values(user_topics.all_visibility_policies); + for (const visibility_policy of visibility_policies) { + /* For visibility_policy=INHERIT, 'get_user_topics_for_visibility_policy' returns + an empty list as we only maintain the record of topics having visibility_policy + other than INHERIT; INHERIT is used to remove topics from the record. */ + const user_topics_list = + user_topics.get_user_topics_for_visibility_policy(visibility_policy); + all_user_topics.push(...user_topics_list); + } + const $user_topics_table = $("#user_topics_table"); + const $search_input = $("#user_topics_search"); - ListWidget.create($muted_topics_table, all_muted_topics, { - name: "muted-topics-list", + ListWidget.create($user_topics_table, all_user_topics, { + name: "user-topics-list", modifier(user_topic) { - return render_user_topic_ui_row({user_topic}); + const context = { + user_topic, + user_topic_visibility_policy_values: + settings_config.user_topic_visibility_policy_values, + }; + return render_user_topic_ui_row(context); }, filter: { $element: $search_input, @@ -26,28 +39,28 @@ export function populate_list() { return item.topic.toLocaleLowerCase().includes(value); }, onupdate() { - ui.reset_scrollbar($muted_topics_table.closest(".progressive-table-wrapper")); + ui.reset_scrollbar($user_topics_table.closest(".progressive-table-wrapper")); }, }, - $parent_container: $("#muted-topic-settings"), - $simplebar_container: $("#muted-topic-settings .progressive-table-wrapper"), + init_sort: ["numeric", "date_updated"], + initially_descending_sort: true, + $parent_container: $("#user-topic-settings"), + $simplebar_container: $("#user-topic-settings .progressive-table-wrapper"), }); } export function set_up() { loaded = true; - $("body").on("click", ".settings-unmute-topic", function (e) { + + $("body").on("change", ".settings_user_topic_visibility_policy", function (e) { const $row = $(this).closest("tr"); const stream_id = Number.parseInt($row.attr("data-stream-id"), 10); const topic = $row.attr("data-topic"); + const visibility_policy = this.value; e.stopPropagation(); - user_topics.set_user_topic_visibility_policy( - stream_id, - topic, - user_topics.all_visibility_policies.INHERIT, - ); + user_topics.set_user_topic_visibility_policy(stream_id, topic, visibility_policy); }); populate_list(); diff --git a/web/src/settings_sections.js b/web/src/settings_sections.js index 23e71b5e1f..55b60af9b0 100644 --- a/web/src/settings_sections.js +++ b/web/src/settings_sections.js @@ -60,7 +60,7 @@ export function initialize() { load_func_dict.set("your-bots", settings_bots.set_up); load_func_dict.set("alert-words", alert_words_ui.set_up_alert_words); load_func_dict.set("uploaded-files", attachments_ui.set_up_attachments); - load_func_dict.set("muted-topics", settings_muted_topics.set_up); + load_func_dict.set("topics", settings_muted_topics.set_up); load_func_dict.set("muted-users", settings_muted_users.set_up); // org diff --git a/web/styles/settings.css b/web/styles/settings.css index 574ce1e239..cfad4d655b 100644 --- a/web/styles/settings.css +++ b/web/styles/settings.css @@ -367,7 +367,9 @@ td .button { } } -.settings_select { +/* list_select is similar to settings_select, but without the height styling. */ +.settings_select, +.list_select { padding: 4px 6px; color: hsl(0deg 0% 33%); border-radius: 4px; diff --git a/web/templates/settings/muted_topics_settings.hbs b/web/templates/settings/muted_topics_settings.hbs index b5d29fa994..e46c5a4af1 100644 --- a/web/templates/settings/muted_topics_settings.hbs +++ b/web/templates/settings/muted_topics_settings.hbs @@ -1,17 +1,25 @@ -
+
+

+ {{#tr}} + Zulip lets you mute topics and streams to avoid receiving notifications messages you are not interested in. + Muting a stream effectively mutes all topics in that stream. You can also manually mute a topic in an unmuted stream, + or unmute a topic in a muted stream. Learn more. + {{#*inline "z-link"}}{{> @partial-block}}{{/inline}} + {{/tr}} +

-

{{t "Muted topics"}}

- +

{{t "Topic settings"}}

+
- - + + - +
{{t "Stream" }} {{t "Topic" }}{{t "Date muted" }}{{t "Actions" }}{{t "Status" }}{{t "Date updated" }}
diff --git a/web/templates/settings_overlay.hbs b/web/templates/settings_overlay.hbs index 7b635a6605..87ad5c6c83 100644 --- a/web/templates/settings_overlay.hbs +++ b/web/templates/settings_overlay.hbs @@ -44,9 +44,9 @@
{{t "Uploaded files" }}
{{/if}} -
  • - -
    {{t "Muted topics" }}
    +
  • + +
    {{t "Topics" }}
  • diff --git a/web/templates/user_topic_ui_row.hbs b/web/templates/user_topic_ui_row.hbs index b3fce06cac..ae4e21749d 100644 --- a/web/templates/user_topic_ui_row.hbs +++ b/web/templates/user_topic_ui_row.hbs @@ -1,10 +1,14 @@ {{#with user_topic}} - + {{stream}} {{topic}} - {{date_updated_str}} - - {{t "Unmute" }} + + + {{date_updated_str}} {{/with}} diff --git a/web/tests/settings_muted_topics.test.js b/web/tests/settings_muted_topics.test.js index 89a958dfb3..63afb9cade 100644 --- a/web/tests/settings_muted_topics.test.js +++ b/web/tests/settings_muted_topics.test.js @@ -49,14 +49,17 @@ run_test("settings", ({override}) => { assert.equal(settings_muted_topics.loaded, true); assert.ok(populate_list_called); - const topic_click_handler = $("body").get_on_handler("click", ".settings-unmute-topic"); - assert.equal(typeof topic_click_handler, "function"); + const topic_change_handler = $("body").get_on_handler( + "change", + ".settings_user_topic_visibility_policy", + ); + assert.equal(typeof topic_change_handler, "function"); const event = { stopPropagation: noop, }; - const $topic_fake_this = $.create("fake.settings-unmute-topic"); + const $topic_fake_this = $.create("fake.settings_user_topic_visibility_policy"); const $topic_tr_html = $('tr[data-topic="js"]'); $topic_fake_this.closest = (opts) => { assert.equal(opts, "tr"); @@ -77,13 +80,15 @@ run_test("settings", ({override}) => { } }; - let unmute_topic_called = false; - user_topics.set_user_topic_visibility_policy = (stream_id, topic) => { + let user_topic_visibility_policy_changed = false; + user_topics.set_user_topic_visibility_policy = (stream_id, topic, visibility_policy) => { assert.equal(stream_id, frontend.stream_id); assert.equal(topic, "js"); - unmute_topic_called = true; + assert.equal(visibility_policy, user_topics.all_visibility_policies.UNMUTED); + user_topic_visibility_policy_changed = true; }; - topic_click_handler.call($topic_fake_this, event); - assert.ok(unmute_topic_called); + $topic_fake_this.value = user_topics.all_visibility_policies.UNMUTED; + topic_change_handler.call($topic_fake_this, event); + assert.ok(user_topic_visibility_policy_changed); assert.equal(topic_data_called, 2); });