settings: Update the 'Muted topics' setting.

This commit updates the existing 'Muted topics'
settings UI to add support for other visibility
policies.

Changes:
Settings sidebar:
1. Rename 'Muted topics' to 'Topics'.
2. Change icon.
Main panel:
3. Rename 'Muted topics' header to 'Topic settings'.
Topics table:
4. Rename 'Date muted' to 'Date updated'.
5. Update the search bar placeholder text to 'Filter topics'.
6. Drop the 'Actions' column.
7. Add a status column with a dropdown set of options.
(Muted, Unmuted, Default for stream)

Fixes #25081.
This commit is contained in:
Prakhar Pratyush 2023-04-14 21:43:13 +05:30 committed by Tim Abbott
parent e87f2ff408
commit c526543498
10 changed files with 87 additions and 45 deletions

BIN
web/shared/icons/topic.svg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

View File

@ -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,

View File

@ -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"}),
},
};

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -1,17 +1,25 @@
<div id="muted-topic-settings" class="settings-section" data-name="muted-topics">
<div id="user-topic-settings" class="settings-section" data-name="topics">
<p>
{{#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. <z-link>Learn more.</z-link>
{{#*inline "z-link"}}<a href="/help/mute-a-topic" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
<div class="settings_panel_list_header">
<h3>{{t "Muted topics"}}</h3>
<input id="muted_topics_search" class="search" type="text" placeholder="{{t 'Filter muted topics' }}" aria-label="{{t 'Filter muted topics' }}"/>
<h3>{{t "Topic settings"}}</h3>
<input id="user_topics_search" class="search" type="text" placeholder="{{t 'Filter topics' }}" aria-label="{{t 'Filter topics' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar>
<table class="table table-condensed table-striped wrapped-table">
<thead class="table-sticky-headers">
<th data-sort="alphabetic" data-sort-prop="stream">{{t "Stream" }}</th>
<th data-sort="alphabetic" data-sort-prop="topic">{{t "Topic" }}</th>
<th data-sort="numeric" data-sort-prop="date_muted" class="topic_date_updated">{{t "Date muted" }}</th>
<th class="actions">{{t "Actions" }}</th>
<th data-sort="numeric" data-sort-prop="visibility_policy">{{t "Status" }}</th>
<th data-sort="numeric" data-sort-prop="date_updated" class="active topic_date_updated">{{t "Date updated" }}</th>
</thead>
<tbody id="muted_topics_table" class="required-text" data-empty="{{t 'You have not muted any topics yet.'}}"></tbody>
<tbody id="user_topics_table" class="required-text" data-empty="{{t 'You have not configured any topics yet.'}}"></tbody>
</table>
</div>
</div>

View File

@ -44,9 +44,9 @@
<div class="text">{{t "Uploaded files" }}</div>
</li>
{{/if}}
<li tabindex="0" data-section="muted-topics">
<i class="icon zulip-icon zulip-icon-mute" aria-hidden="true"></i>
<div class="text">{{t "Muted topics" }}</div>
<li tabindex="0" data-section="topics">
<i class="icon zulip-icon zulip-icon-topic" aria-hidden="true"></i>
<div class="text">{{t "Topics" }}</div>
</li>
<li tabindex="0" data-section="muted-users">
<i class="icon fa fa-eye-slash" aria-hidden="true"></i>

View File

@ -1,10 +1,14 @@
{{#with user_topic}}
<tr data-stream-id="{{stream_id}}" data-stream="{{stream}}" data-topic="{{topic}}" data-date-updated="{{date_updated_str}}">
<tr data-stream-id="{{stream_id}}" data-stream="{{stream}}" data-topic="{{topic}}" data-date-updated="{{date_updated_str}}" data-visibility-policy="{{visibility_policy}}">
<td>{{stream}}</td>
<td>{{topic}}</td>
<td class="topic_date_updated">{{date_updated_str}}</td>
<td class="actions">
<span><a class="settings-unmute-topic">{{t "Unmute" }}</a></span>
<td>
<select class="settings_user_topic_visibility_policy prop-element list_select bootstrap-focus-style" data-setting-widget-type="number">
{{#each ../user_topic_visibility_policy_values}}
<option value='{{this.code}}' {{#if (eq this.code ../visibility_policy)}}selected{{/if}}>{{this.description}}</option>
{{/each}}
</select>
</td>
<td class="topic_date_updated">{{date_updated_str}}</td>
</tr>
{{/with}}

View File

@ -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);
});